First FDM Simulation

Last changes: Documentation changelog

This page runs a small finite-difference relaxation: a soft ferromagnetic film with exchange and magnetostatic interactions relaxes from a uniform magnetization under its own effective field. The example follows the stage-first fm.study(...) workflow and never constructs a fm.Problem(...) snapshot.

What the example computes

A film of size \(160 \times 160 \times 24\ \mathrm{nm}\) is discretized on a regular FDM grid with \(4\ \mathrm{nm}\) cells. The magnetic body is \(80 \times 120 \times 8\ \mathrm{nm}\), so the resolved geometry sits inside the discretization universe. Exchange stiffness \(A_{\mathrm{ex}}\) and the magnetostatic field drive the magnetization toward a local minimum; the overdamped LLG relaxation stage stops when the requested torque/field tolerance or step budget is reached.

Author the study

import fullmag as fm

nm = 1.0e-9
study = fm.study("first_fdm_simulation")
study.engine("fdm")
study.device("cpu", precision="double")
study.mode("strict")

study.universe(
    mode="manual",
    size=(160 * nm, 160 * nm, 24 * nm),
    center=(0.0, 0.0, 0.0),
    padding=(0.0, 0.0, 0.0),
)
study.objects.mesh.defaults(cell_size=(4 * nm, 4 * nm, 4 * nm))

film = study.geometry(
    fm.Box(size=(80 * nm, 120 * nm, 8 * nm), name="film"),
    name="film",
)
film.Ms = 800.0e3
film.Aex = 13.0e-12
film.alpha = 0.1
film.m = fm.init.UniformMagnetization((1.0, 0.0, 0.0))

study.solver(fix_dt=5.0e-13, gamma=2.211e5)

study.stages.add_relax(
    stage_id="relax",
    algorithm="llg_overdamped",
    dt=5.0e-13,
    tolA=1.0e-4,
    max_steps=2000,
).tableautosave(
    every_steps=50,
    quantities=["step", "t", "dt", "mx", "my", "mz", "E_total"],
)

What each part does

  • fm.study("first_fdm_simulation") opens the study builder.

  • study.engine("fdm") selects the finite-difference backend; the finite-element alternative is study.engine("fem").

  • study.device("cpu", precision="double") requests CPU execution in double precision. This is a requested intent; the runtime records the resolved backend and device independently.

  • study.mode("strict") selects the strict execution mode, so validation rejects unsupported combinations instead of silently changing them.

  • study.universe(...) defines the discretization domain. mode="manual" means FullMag does not automatically grow the domain.

  • study.objects.mesh.defaults(cell_size=(...)) sets the FDM cell size for the object grid.

  • film.Ms, film.Aex and film.alpha set saturation magnetization \(\mathrm{A\,m^{-1}}\), exchange stiffness \(\mathrm{J\,m^{-1}}\) and the Gilbert damping parameter (\(1\), dimensionless).

  • Exchange and demagnetization are registered by default. film.Aex supplies the exchange stiffness; it is not an enable call. Use study.disable_exchange() or study.disable_demag() only for an intentional opt-out.

  • study.solver(fix_dt=..., gamma=...) sets the fixed solver timestep and the positive gyromagnetic ratio in \(\mathrm{m\,A^{-1}\,s^{-1}}\).

  • study.stages.add_relax(...) declares the ordered relaxation stage; its .tableautosave(...) records per-step scalars.

The relaxation uses an explicit fixed timestep. fix_dt=5.0e-13 defines the solver-level default, while the stage-level dt=5.0e-13 records the timestep requested for this relaxation stage.

Run headlessly

Save the block above as first_fdm_simulation.py and run it through the repository launcher:

just run-headless first_fdm_simulation.py

This builds the local runtime on first use, executes the stage, and writes per-stage scientific artifacts and the autosave table to the auto-derived output directory. For an interactive run with the Control Room use just fullmag build=True fdm cpu first_fdm_simulation.py.

Reading the result

The tableautosave quantities (mx, my, mz, E_total) are scalar observables: the spatially averaged magnetization components and the total energy respectively. They are the first evidence that the relaxation is progressing; per-cell field and magnetization snapshots are separate artifacts selected through stage outputs.

Limits of this example

This is an onboarding run, not an MD/qualification benchmark. It uses a small cell grid so it is practical to run; exchange and demagnetization validation regimes are documented on the canonical interaction pages. The FDM CPU lane shown here has scoped published evidence; do not infer executed CUDA parity from this snippet.

Control Room crosswalk

Use the authoring path stated in this guide, normally Model Explorer -> Objects followed by the relevant Geometry, Material, Physics, Mesh, or Stage panel. Any parameter shown in Python but not shown in that path is TODO: frontend support; do not describe it as configurable in the UI. See Control Room capability register.

Python/API crosswalk

The runnable Python example and exact argument contract are authoritative. If this guide is conceptual or does not contain a runnable example, it explicitly defers to the linked {doc}``/python-api/index page rather than duplicating an unverified signature.

Physics, limitations, and bibliography

Use the linked physics or numerical-methods page for governing equations and assumptions. This onboarding page does not add a new physical model. Bibliography: see the linked terminal API or physics page; no additional source is claimed here.

Source-code index

  • No new implementation symbol is introduced by this guide. The exact Python source symbol is owned by the linked terminal API page and the runnable example.