GEOPY-2799: Implement MVI with PDE inversion#375
GEOPY-2799: Implement MVI with PDE inversion#375domfournier wants to merge 29 commits intodevelopfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces support for a new “magnetic vector pde” workflow (forward + inversion) and integrates it into joint inversion drivers/tests, alongside updates to rotated-regularization handling and related plumbing.
Changes:
- Added new
magnetic_vector_pdedriver package (forward/inversion/options) and new PDE UI JSON assets. - Updated joint drivers/tests to exercise MVI PDE in joint survey / cross-gradient contexts.
- Refactored rotated-regularization operator handling (degrees vs radians) and adjusted nested/simulation factory logic for remanence mapping.
Reviewed changes
Copilot reviewed 42 out of 42 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
simpeg_drivers/potential_fields/magnetic_vector_pde/* |
Adds PDE forward/inversion drivers and options for the new method. |
simpeg_drivers-assets/uijson/magnetic_vector_pde_*.ui.json |
Adds UI schemas for PDE forward/inversion runs. |
simpeg_drivers/components/models.py |
Extends vector-model logic to include PDE inversion type; adjusts gradient rotation handling. |
simpeg_drivers/components/factories/* |
Allows factories (survey/source/receiver/simulation/directives) to recognize “magnetic vector pde”. |
simpeg_drivers/joint/* |
Adjusts joint regularization/model handling to work with global mesh + PDE cases. |
simpeg_drivers/utils/regularization.py |
Updates rotated operator setup to accept degrees and convert internally. |
simpeg_drivers/utils/nested.py |
Ensures local tile mapping uses 3 components when remanence mapping is present. |
tests/run_tests/driver_mvi_pde_test.py |
Adds an integration-style test file for PDE forward+inversion. |
tests/run_tests/driver_joint_surveys_test.py |
Parametrizes joint surveys MVI test to include PDE driver/options. |
tests/run_tests/driver_joint_cross_gradient_test.py |
Adds a rotated-gradient joint cross-gradient test and tweaks inv run behavior. |
pyproject.toml + conda lock files |
Pins mira-simpeg and refreshes environment locks accordingly. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
simpeg_drivers-assets/uijson/magnetic_vector_pde_inversion.ui.json
Outdated
Show resolved
Hide resolved
# Conflicts: # environments/py-3.12-linux-64-dev.conda.lock.yml # environments/py-3.12-linux-64.conda.lock.yml # environments/py-3.12-win-64-dev.conda.lock.yml # environments/py-3.12-win-64.conda.lock.yml # environments/py-3.13-linux-64-dev.conda.lock.yml # environments/py-3.13-linux-64.conda.lock.yml # environments/py-3.13-win-64-dev.conda.lock.yml # environments/py-3.13-win-64.conda.lock.yml # environments/py-3.14-linux-64-dev.conda.lock.yml # environments/py-3.14-linux-64.conda.lock.yml # environments/py-3.14-win-64-dev.conda.lock.yml # environments/py-3.14-win-64.conda.lock.yml # py-3.12.conda-lock.yml # py-3.13.conda-lock.yml # py-3.14.conda-lock.yml
benk-mira
left a comment
There was a problem hiding this comment.
Some questions/comments in the review. Also.. I wasn't expecting a whole new driver/options/ui.json combo. 1. Is the old method worth keeping around? (Will people want to choose between them on a case-by-case basis?) 2. Could this be written as an option in the mvi ui.json to switch from pde/integral equation?
| regularizations = super().get_regularization() | ||
| reg_list, multipliers = self._overload_regularization(regularizations) | ||
| # Trick the drivers by swapping the inversion_mesh and models | ||
| # such that the regularization uses the global mesh |
There was a problem hiding this comment.
Yes, in big part. Also, because this new PDE Driver has a special regularization, we need to rely on each sub-inversion to generate their own reg. So the trick here is to collect all the models, interpolate onto the global mesh, then pass it back to the sub inversion to form their reg
| inducing_field_strength: float | FloatData | ||
| inducing_field_inclination: float | FloatData | ||
| inducing_field_declination: float | FloatData | ||
| models: VectorModelPDEOptions |
There was a problem hiding this comment.
Why no reference inclination/declination like in the regular mvi?
There was a problem hiding this comment.
Because we currently don't have mechanics to enforce direction in Cartesian space. This new PDE formalulation doesn't allow to switch to spherical, so we can't allow it, for now.
| if any( | ||
| k in inversion_type | ||
| for k in ["direct current", "induced polarization", "gravity", "magnetic"] | ||
| for k in ["direct current", "induced polarization", "gravity", "magnetic "] |
There was a problem hiding this comment.
why is the space needed? Seems like you could omit.. "magnetic scalar", "magnetic vector", and "magnetic vector pde" should all get captured without any confusion with "electromagnetic" as far as I can tell.
There was a problem hiding this comment.
I don't think so, no. Because we do k in inversion_type, then "magnetic" in "electromagnetics" is True, which would take all of the EM methods. The space prevents that.
domfournier
left a comment
There was a problem hiding this comment.
Fair point that there is a lot of overlap, but there is enough for us to keep both around, for now. Main difference is that the PDE can't do reference angles, and has a special VectorAmplitude reg.
I think it would be possible to do reference angles in Cartesian space, but I ll need more time to develop. For now it's just simpler to have a second.
| regularizations = super().get_regularization() | ||
| reg_list, multipliers = self._overload_regularization(regularizations) | ||
| # Trick the drivers by swapping the inversion_mesh and models | ||
| # such that the regularization uses the global mesh |
There was a problem hiding this comment.
Yes, in big part. Also, because this new PDE Driver has a special regularization, we need to rely on each sub-inversion to generate their own reg. So the trick here is to collect all the models, interpolate onto the global mesh, then pass it back to the sub inversion to form their reg
| inducing_field_strength: float | FloatData | ||
| inducing_field_inclination: float | FloatData | ||
| inducing_field_declination: float | FloatData | ||
| models: VectorModelPDEOptions |
There was a problem hiding this comment.
Because we currently don't have mechanics to enforce direction in Cartesian space. This new PDE formalulation doesn't allow to switch to spherical, so we can't allow it, for now.
| if any( | ||
| k in inversion_type | ||
| for k in ["direct current", "induced polarization", "gravity", "magnetic"] | ||
| for k in ["direct current", "induced polarization", "gravity", "magnetic "] |
There was a problem hiding this comment.
I don't think so, no. Because we do k in inversion_type, then "magnetic" in "electromagnetics" is True, which would take all of the EM methods. The space prevents that.
Co-authored-by: benk-mira <81254271+benk-mira@users.noreply.github.com>
GEOPY-2799 - Implement MVI with PDE inversion