SimPEG v0.25.0 Release Notes#
October 22nd, 2025
Updates#
New features#
New differential simulation for magnetic fields#
This release ships with a new and improved version of the magnetic differential
simulation
Simulation3DDifferential by
@johnweis0480.
This simulation computes the magnetic field on every cell of the mesh by
numerically solving the magnetostatic PDE. It accounts for
self-demagnetization effects, model both induced and remanent magnetizations,
and is faster and less memory intensive than the integral simulation for large
problems.
See simpeg/simpeg#1682 for more details.
Add utility function to shift electrodes to discrete topography#
A new simpeg.utils.shift_to_discrete_topography() function shifts
locations relative to discrete surface topography. When performing MT surveys,
we measure electric fields at the Earth’s surface.
Similar to DC/IP, the original measurement locations of the electric fields can
end up in air cells when we discretize surface topography. This function allows
the user to shift locations relative to discrete topography on Tensor and Tree
meshes.
For Airborne NSEM, they also allow the user to preserve the original flight
heights.
See simpeg/simpeg#1683 for more details.
Calculate B/H fields with a step-off waveform closed-loop wire source in TDEM#
We can now calculate the B and H fields using a closed-loop wire as source in the TDEM code with a step-off waveform. The simulation will first compute the vector potential using the Biot-Savart Law and then take the curl of it to get the initial \(\mathbf{B}\) field.
See simpeg/simpeg#1651 for more details.
Sensitivity matrix as a LinearOperator in gravity and magnetic equivalent layers#
Gravity and magnetic equivalent sources can now define the sensitivity
matrix J as a scipy.sparse.linalg.LinearOperator when
store_sensitivities="forward_only". This extends the behaviour previously
implemented in the integral gravity and magnetic simulations to the
equivalent layer classes.
See simpeg/simpeg#1674 and simpeg/simpeg#1676 for more details.
Choosing the default solver is easier now#
The get_default_solver() can now be imported directly from
simpeg.utils making it easier to use it.
Check out the new How to Guide on Choosing solvers for more information on how we can use this function.
Improved inversion printout#
The information table displayed during an inversion has been improved. Now, the zero-th iteration corresponds to the status of the inversion problem before any optimization steps, while subsequent iterations show information after each iteration but before directives are applied. The final iteration of the inversion is shown in the last row of the table. Additionally, some non-very-useful messages have been removed to produce a cleaner output.
See simpeg/simpeg#1626 for more details.
Standardized directives for saving outputs#
Directives that store and save inversion outputs have been
standardized and made more reliable. They now respect the output directory
chosen by the user, and output filenames follow a standardized
name-timestamp-iteration format to make it easier to sort and identify
files from different inversions.
See simpeg/simpeg#1657 for more details.
Updates to the Conjugate Gradient minimizers#
The conjugate gradient minimizers were updated to be consistent with the latest
versions of SciPy. They can now accept both relative and absolute tolerances
through the cg_rtol and cg_atol arguments, respectively.
The tolCG argument will be removed in the future, making cg_rtol and
cg_atol the preferred way to set tolerances in these minimizers.
See simpeg/simpeg#1656 for more details.
Documentation#
This release introduces a fresh new landing page for SimPEG docs, and a new How to Guide section in our SimPEG User Guide with pages on Choosing solvers and Locating mesh on survey area.
We also included a new page that clarifies Python and Numpy Version compatibility with SimPEG, and explain the criteria for dropping older versions of our dependencies.
We started removing the gravity, magnetic and DC tutorials from SimPEG’s docs, as part of our plan of moving all tutorials to our User Tutorials.
Now we can navigate our docs using our arrow keys in the keyboard (for those power users that don’t want to leave the keyboard) thanks to @prisae.
Finally, we improved and fixed a few things in the docs: mathematical expressions, added missing classes to the API reference, updated admonitions in docstrings, and more.
Bugfixes#
In this release we included a few bugfixes:
- Fixes sign error in 1D field calculation. by @jcapriot in simpeg/simpeg#1662 
- Fix beta cooling in - UpdateIRLSdirective by @jcapriot in simpeg/simpeg#1659
- Fix bug in phase for recursive 1d NSEM simulation by @dccowan in simpeg/simpeg#1679 
- Fix bug on - Impedance.evalwhen orientation is “xx” or “yy” by @dccowan in simpeg/simpeg#1692
- Fix magnetic dipole source for for HJ formulation by @lheagy in simpeg/simpeg#1575 
- Fix bug with duplicated current in - LineCurrent.Mejsby @santisoler in simpeg/simpeg#1718
Breaking changes#
We introduced a few breaking changes in SimPEG v0.25.0.
Dropped support for Python 3.10#
We dropped support for Python 3.10, inline with our Version compatibility schedule. So, remember to use Python 3.11 or higher when installing SimPEG v0.25.0. If you still need to use Python 3.10, please pin your SimPEG version to v0.24.0.
Modified how mappings are applied in regularizations#
We updated how mappings are applied in most of our regularization classes
(WeightedLeastSquares,
Smallness,
SmoothnessFirstOrder,
Sparse,
etc.). The mapping was applied, for example in the
Smallness regularization, to the difference
between the model and the reference_model:
where \(\mu()\) is the mapping.
Since SimPEG v0.25.0 the regularizations are applied to the difference between the mapped model and the mapped regularization model:
This impacts only non-linear mappings, since the two expressions are equivalent for linear ones.
Changed the output of get_indices_block()#
The get_indices_block() function previously
returned a tuple with just a single element: the array with cell indices that
correspond the given block. We standardized its output to be in agreement with
similar functions in the module. It now returns a single NumPy array with the
cell indices of the block.
If you were using this function as follows, where you used to extract the first element of the tuple:
ind = get_indices_block(p0, p1, mesh.cell_centers)[0]
You’ll need to update it to:
ind = get_indices_block(p0, p1, mesh.cell_centers)
An informative warning will be printed out every time the function is used to remind users of this new behaviour.
Removals#
We also removed several deprecated items marked for removal in previous releases, including:
- The - Data.index_dictionaryproperty. Use the new- get_slicemethod of- Survey(for example:- simpeg.potential_fields.gravity.Survey.get_slice()).
- The - gtg_diagonalproperty from gravity simulation.
- The - componentsproperty from gravity and magnetic surveys.
Contributors#
Contributors:
Pull Requests#
- Update docstring descriptions for gravity gradient component guv by @williamjsdavis in simpeg/simpeg#1665 
- Clean up Numba functions for potential field simulations by @santisoler in simpeg/simpeg#1663 
- Make directives submodules private by @santisoler in simpeg/simpeg#1667 
- Ensure misfit is purely real valued by @prisae in simpeg/simpeg#1524 
- Add key navigation to docs by @prisae in simpeg/simpeg#1668 
- Add missing map classes to the API reference by @santisoler in simpeg/simpeg#1672 
- Replace sklearn deprecated method for - validate_datafunction by @santisoler in simpeg/simpeg#1673
- Remove - BaseSurvey.counterproperty by @santisoler in simpeg/simpeg#1640
- Fixes sign error in 1D field calculation. by @jcapriot in simpeg/simpeg#1662 
- Allow use of - Jas- LinearOperatorin mag equivalent layers by @santisoler in simpeg/simpeg#1676
- Fix beta cooling in - UpdateIRLSdirective by @jcapriot in simpeg/simpeg#1659
- Allow use of - Jas- LinearOperatorin gravity equivalent layers by @santisoler in simpeg/simpeg#1674
- Improve admonitions in gravity simulation by @santisoler in simpeg/simpeg#1677 
- Have an option to take a step when the Linesearch breaks by @lheagy in simpeg/simpeg#1581 
- Fix bug in phase for recursive 1d NSEM simulation by @dccowan in simpeg/simpeg#1679 
- Use conda-forge as only channel in Azure pipelines by @santisoler in simpeg/simpeg#1688 
- Expose solver utility functions in - simpeg.utilsby @santisoler in simpeg/simpeg#1678
- Use logging while setting default solver in PDE simulations by @santisoler in simpeg/simpeg#1670 
- Use - Impedanceand- Tipperin examples and tests by @santisoler in simpeg/simpeg#1690
- Fix bug on - Impedance.evalwhen orientation is “xx” or “yy” by @dccowan in simpeg/simpeg#1692
- Remove deprecated objects missed in v0.24.0 by @jcapriot in simpeg/simpeg#1658 
- Update magnetic simulation using differential formulation by @johnweis0480 in simpeg/simpeg#1682 
- Standardize output directives and make them more reliable by @jcapriot in simpeg/simpeg#1657 
- Make tests error on implicit complex to real by @jcapriot in simpeg/simpeg#1696 
- Avoids calculating unused values for boundary conditions on DC 2D simulations by @jcapriot in simpeg/simpeg#1698 
- Add How to Guide page on how to choose a solver by @santisoler in simpeg/simpeg#1695 
- Make Logger a bit quieter when running pytest by @jcapriot in simpeg/simpeg#1697 
- CG Minimizer Updates by @jcapriot in simpeg/simpeg#1656 
- Add top level descriptions to missing to functions by @jcapriot in simpeg/simpeg#1702 
- Update meeting times in README.rst by @santisoler in simpeg/simpeg#1700 
- Add - _faceDivattribute to FDEM H- Fieldsby @lheagy in simpeg/simpeg#1346
- Improve landing page of docs by @santisoler in simpeg/simpeg#1701 
- Add How to Guide page on moving mesh to survey area by @santisoler in simpeg/simpeg#1699 
- Remove gravity and magnetic tutorials by @santisoler in simpeg/simpeg#1704 
- Minor fixes to docs of - UpdateSensitivityWeightsby @santisoler in simpeg/simpeg#1705
- Update iteration print out by @jcapriot in simpeg/simpeg#1626 
- Fix magnetic dipole source for for HJ formulation by @lheagy in simpeg/simpeg#1575 
- Drop support for Python 3.10 by @santisoler in simpeg/simpeg#1708 
- Add documentation page for version compatibility by @santisoler in simpeg/simpeg#1707 
- Remove DC resistivity tutorials by @santisoler in simpeg/simpeg#1710 
- Improve dipole source tests by @santisoler in simpeg/simpeg#1711 
- Update deprecated calls in examples, tutorials, and tests to inexact CG minimizers by @jcapriot in simpeg/simpeg#1703 
- Make - ComplexMap.derivto return a sparse diagonal matrix by @lheagy in simpeg/simpeg#1686
- Standardize signature of mappings’ - derivmethod by @YingHuuu in simpeg/simpeg#1407
- Update how mappings are applied in regularizations by @santisoler in simpeg/simpeg#1605 
- Simple fix for pymatsolver 0.4.0 by @jcapriot in simpeg/simpeg#1717 
- Fix bug with duplicated current in - LineCurrent.Mejsby @santisoler in simpeg/simpeg#1718
- Minor fixes to LaTeX equations in regularizations by @santisoler in simpeg/simpeg#1720 
- Fix return of - get_indices_blockby @santisoler in simpeg/simpeg#1713
- Remove deprecated bits marked for removal in v0.25.0 by @santisoler in simpeg/simpeg#1719 
- Add shift to discrete topography for NSEM by @dccowan in simpeg/simpeg#1683 
- Deprecate unused arguments in - drape_electrodes_on_topographyby @santisoler in simpeg/simpeg#1723
- Fix LaTeX equations in - Simulation3DDifferentialby @santisoler in simpeg/simpeg#1726
- Implement a closed loop as a TDEM source by @lheagy in simpeg/simpeg#1651 
- Allow for specifying ramp start and ramp end in - RampOffWaveformby @jcapriot in simpeg/simpeg#1714
