Simulation workflow¶
1. Choose output behavior¶
NmagConfig holds immutable choices for one simulation. Give each study a
dedicated output directory and choose deliberately how existing files are
handled:
from pathlib import Path
import nmag
results = Path("results")
results.mkdir(exist_ok=True)
config = nmag.NmagConfig(
output_directory=results,
output_policy="error",
accelerator="auto",
)
simulation = nmag.Simulation(name="sample", config=config)
The default "error" policy protects existing NDT and HDF5 files. "replace"
starts those files again, while "append" checks the existing NDT schema and
adds rows. Append does not restore physical state; use a restart file for that.
2. Prepare a mesh and materials¶
The simulation solver expects a 3D tetrahedral mesh whose cells carry integer region IDs. A material definition supplies saturation magnetization and the physics enabled for that region:
permalloy = nmag.MagMaterial(
name="Py",
Ms=nmag.SI(1e6, "A/m"),
exchange_coupling=nmag.SI(13e-12, "J/m"),
llg_damping=0.02,
)
simulation.load_mesh(
"sample.msh",
[("magnetic", permalloy)],
unit_length=nmag.SI(1e-9, "m"),
)
The material list is ordered by mesh region: entries map to the distinct mesh region IDs in ascending order. Region IDs do not need to be contiguous or start at 1, but Nmag still requires one material entry per mesh region. Region names then appear in field and output labels.
unit_length converts mesh coordinate units into metres. If a Gmsh file already
stores metres, use nmag.SI(1, "m").
3. Set the state and applied fields¶
Magnetization is a unit direction vector. Assign it uniformly, per node, or with a callable evaluated at physical positions in metres:
simulation.set_m([1.0, 0.0, 0.0])
# A position-dependent alternative:
# simulation.set_m(lambda position: [1, 0, 0] if position[0] < 0 else [0, 1, 0])
The applied field can be supplied as a vector plus a unit:
Pinning and Zhang-Li current density are optional:
simulation.set_pinning(lambda position: 0.0 if position[2] < 2e-9 else 1.0)
simulation.set_current_density([0.0, 0.0, 1e12], nmag.SI("A/m^2"))
A pin value of zero fixes the complete local magnetization derivative; one leaves it free.
4. Calculate, advance, or relax¶
Field access triggers the required calculation lazily:
For dynamics, either advance to a requested physical time or relax until the configured convergence test passes:
5. Save and inspect results¶
See fields, output, and restarts for selective output and safe continuation, and dynamics and relaxation before tuning an integrator.