Choosing solvers#
Several simulations available in SimPEG need to numerically solve a partial
differential equations system (PDE), such as
Simulation3DNodal
(DC)
Simulation3DMagneticFluxDensity
(TDEM)
and
Simulation3DMagneticFluxDensity
(FDEM).
A numerical solver is needed to solve the PDEs.
SimPEG can make use of the solvers available in pymatsolver
, like
pymatsolver.Pardiso
, pymatsolver.Mumps
or
pymatsolver.SolverLU
.
The choice of an appropriate solver can affect the computation time required to
solve the PDE. Generally we recommend using direct solvers over iterative solvers
for SimPEG, but be aware that direct solvers have much larger memory requirements.
The Pardiso
solver wraps the oneMKL PARDISO
solver available for x86_64 CPUs.
The Mumps
solver wraps MUMPS, a fast solver available for
all CPU brands, including Apple silicon architecture.
The SolverLU
wraps SciPy’s scipy.sparse.linalg.splu()
. The
performance of this solver is not up to the level of Mumps
and Pardiso
.
Usage of the SolveLU
is recommended only when it’s not possible to use
other faster solvers.
The default solver#
We can use simpeg.utils.get_default_solver()
to obtain a reasonable default
solver available for our system:
import simpeg
import simpeg.electromagnetics.static.resistivity as dc
# Get default solver
solver = simpeg.utils.get_default_solver()
print(f"Solver: {solver}")
which would print out on an x86_64 cpu:
Solver: <class 'pymatsolver.direct.pardiso.Pardiso'>
We can then use this solver in a simulation:
# Define a simple mesh
h = [(1.0, 10)]
mesh = discretize.TensorMesh([h, h, h], origin="CCC")
# And a DC survey
receiver = dc.receivers.Dipole(locations_m=(-1, 0, 0), locations_n=(1, 0, 0))
source = dc.sources.Dipole(
receiver_list=[receiver], location_a=(-2, 0, 0), location_b=(2, 0, 0)
)
survey = dc.Survey([source])
# Use the default solver in the simulation
simulation = dc.Simulation3DNodal(mesh=mesh, survey=survey, solver=solver)
Note
The priority list used to choose a default solver is:
Pardiso
Mumps
SolverLU
Setting solvers manually#
Alternatively, we can manually set a solver. For example, if we want to use
Mumps
in our DC resistivity simulation, we can import
pymatsolver.Mumps
and pass it to our simulation:
import simpeg.electromagnetics.static.resistivity as dc
from pymatsolver import Mumps
# Manually set Mumps as our solver
simulation = dc.Simulation3DNodal(mesh=mesh, survey=survey, solver=Mumps)
Note
When sharing your notebook or script with a colleague, keep in mind that
your code might not work if Pardiso
is not available in their system.
For such scenarios, we recommend using the
simpeg.utils.get_default_solver()
function, that will always return
a suitable solver for the current system.
Ultimately, choosing the best solver is a mixture of the problem you are solving and your current system. Experiment with different solvers yourself to choose the best.