Geometry, regions, materials and meshes¶
Last changes: Documentation changelog
Geometry and material declarations are the physical input to FullMag. They are authored once and then lowered to the selected FDM or FEM realization. The lowerer may choose different cells, elements, markers, quadrature locations, and boundary machinery, but it must preserve the authored object identity, region membership, material assignment, and mesh intent or reject the request.
This page is the physics-level map of the complete path:
geometry object -> magnetic object -> object-owned region -> material assignment -> mesh policy
-> ProblemIR -> FDM grid or FEM mesh -> interaction and solver realization
The Python terminal pages linked below are the authoritative reference for each constructor. This page explains how those contracts compose and records the physical assumptions and current limits.
Physical model¶
Let Omega be the magnetic domain and Omega_i its authored regions. A valid realization preserves
the intended membership relation:
The equation describes the resolved physical partition, not every intermediate authoring shape. Boolean operands may overlap by design, and object-owned region policies may overlap while they are being resolved. Such cases require explicit priority and conflict policy; insertion order is not a physical rule.
For a material parameter p, the object scalar is the default value and a scoped field is an
override evaluated only where its owning object and optional region have support. A resolved
operator consumes the material value at its own cells, nodes, elements, or quadrature points. The
Python field declaration does not by itself prove that a particular backend, interpolation rule,
precision, or device can materialize it.
Symbols and SI units¶
Symbol |
Meaning |
SI unit |
|---|---|---|
|
resolved magnetic domain |
|
|
authored magnetic region |
|
|
material parameter |
parameter-dependent |
Assumptions and validity¶
All dimensional values in this page are authored in SI units. Geometry lengths and coordinates are finite metres; positive dimensions and radii are required by the corresponding constructors. Material scalar values are validated by their source constructors, while unit strings on spatial fields are preserved metadata rather than a conversion request. Backend capability, asset loading, mesh conformity, and solver qualification remain separate checks.
Geometry operations¶
Boolean operations¶
The geometry mixin implements these operators:
Python expression |
Set operation |
Canonical IR kind |
|---|---|---|
|
difference |
|
|
union |
|
|
intersection |
|
The explicit constructors fm.Difference(base, tool), fm.Union(a, b), and
fm.Intersection(a, b) produce the same typed records. Operands remain nested in to_ir();
the operation is not silently converted to a triangulated mesh during authoring.
Translation¶
geometry.translate((dx, dy, dz)) creates a Translate record with the nested base geometry and
the by vector. It preserves any existing center or transform in the nested object. The vector is
finite and has three components; the derived name is stable unless Translate(..., name=...) is
used.
Imported geometry¶
# %%
# Import a source geometry with an explicit physical scale
import fullmag as fm
cad = fm.ImportedGeometry(
source="mesh.step",
scale=1.0,
units="mm",
name="cad_body",
volume="full",
)
record = cad.to_ir()
study = fm.study("imported_geometry")
body = study.geometry(cad, name="cad_body")
body.Ms = 800.0e3
body.Aex = 13.0e-12
study.stages.add_run(stage_id="inspect_import", until=1.0e-15)
units is normalized against the source scale table (m, cm, mm, um, nm, and supported
micro-metre spellings). A scalar scale is applied uniformly; a three-vector scale is applied per
axis. volume="full" is the default. volume="surface" is a preview-only authoring route in
the current problem lowering and must not be presented as a volumetric solver mesh.
Detailed constructor and failure semantics: Imported geometry.
Materials and units¶
fm.Material stores magnetic constitutive parameters in SI units only. The class implemented in
fullmag.model.structure validates positive Ms and A, non-negative alpha, finite anisotropy
and DMI constants, and three-component anisotropy directions when supplied.
Python field |
Meaning |
SI unit |
Lowered ProblemIR field |
|---|---|---|---|
|
saturation magnetization |
|
|
|
exchange stiffness |
|
|
|
Gilbert damping |
|
|
|
uniaxial anisotropy constants |
|
|
|
uniaxial axis or easy-plane normal |
|
|
|
cubic anisotropy constants |
|
|
|
cubic anisotropy axes |
|
|
|
interfacial DMI coefficient |
|
|
|
bulk DMI coefficient |
|
|
unit values on spatial fields are non-empty metadata. The current Python factories preserve that
metadata but do not convert it or check that it matches the selected parameter. Authors must pass
SI-valued numbers and use the unit string consistently.
Base material example¶
# %%
# Author a base SI material and inspect its typed record
import fullmag as fm
permalloy = fm.Material(
name="Py",
Ms=800.0e3,
A=13.0e-12,
alpha=0.02,
Ku1=0.0,
anisU=(0.0, 0.0, 1.0),
)
material_ir = permalloy.to_ir()
study = fm.study("base_material")
body = study.geometry(fm.Box(size=(100e-9, 20e-9, 5e-9)), name="film")
body.Ms = permalloy.Ms
body.Aex = permalloy.A
study.stages.add_run(stage_id="inspect_material", until=1.0e-15)
For the high-level object handle, the equivalent assignments are body.Ms, body.Aex,
body.alpha, body.Ku1, body.anisU, body.Kc1, body.Dind, and body.Dbulk. The handle
converts these values to the Material record during Problem lowering.
Regions, fields and interfaces¶
Region creation and local mesh policy¶
# %%
# Create one object-owned region and its local FEM mesh request
import fullmag as fm
nm = 1.0e-9
study = fm.study("geometry_materials_regions")
study.engine("fem")
study.device("cpu", precision="double")
study.mode("strict")
body = study.geometry(fm.Box(size=(200 * nm, 80 * nm, 5 * nm)), name="track")
body.Ms = 800.0e3
body.Aex = 13.0e-12
body.alpha = 0.02
core = body.add_region(
"core",
fm.Cylinder(radius=30 * nm, height=5 * nm),
priority=10,
)
core.material.Ms = fm.fields.constant(750.0e3, unit="A/m")
core.mesh(
maximum_element_size=2 * nm,
minimum_element_size=1 * nm,
transition_distance=5 * nm,
order=1,
)
study.stages.add_run(stage_id="inspect_region", until=1.0e-15)
ObjectRegion.mesh has exactly this signature:
mesh(*, maximum_element_size=None, minimum_element_size=None,
transition_distance=None, order=None)
Sizes are positive metres, transition_distance is non-negative, and
minimum_element_size <= maximum_element_size when both are supplied. The request is serialized
under the owning object region and is resolved together with the shared mesh.
Spatial material fields¶
MaterialParameterField provides four typed factories:
Factory |
Required arguments |
Meaning |
|---|---|---|
|
finite scalar or finite 3-vector |
uniform override |
|
finite base and 3-vector gradient |
affine spatial profile |
|
finite center/values and positive radius |
inside/outside radial profile |
|
non-empty asset, count >= 1, valid location and unit |
immutable asset reference |
For linear and radial, frame is exactly object or world. Object-frame coordinates follow
the object; world-frame coordinates remain fixed in the laboratory frame. Supported material
parameter names are Ms, Aex, Alpha, Ku1, Ku2, AnisotropyAxis, Kc1, Kc2, Kc3,
Dind, and Dbulk; ProblemIR normalizes them to lower-case canonical names.
# %%
# Apply a region-scoped analytic material field
import fullmag as fm
nm = 1.0e-9
study = fm.study("region_material_field")
study.engine("fem")
study.device("cpu", precision="double")
study.mode("strict")
body = study.geometry(fm.Box(size=(200 * nm, 80 * nm, 5 * nm)), name="track")
body.Ms = 800.0e3
body.Aex = 13.0e-12
body.alpha = 0.02
core = body.add_region(
"core",
fm.Cylinder(radius=30 * nm, height=5 * nm),
priority=10,
)
body.set_material_field(
"Ms",
fm.fields.linear(
base=760.0e3,
gradient=(0.0, 1.5e11, 0.0),
frame="object",
unit="A/m",
),
region=core,
assignment_id="track_core_ms_gradient",
priority=10,
conflict_policy="error",
)
study.stages.add_run(stage_id="inspect_field", until=1.0e-15)
body.set_material_field accepts parameter, value, and the keyword arguments
assignment_id=None, region=None, unit=None, priority=0, and conflict_policy="error".
region can be an ObjectRegion or its key. higher_priority_wins and
min_mesh_size_wins are the other declared conflict policies. Equal-priority overlap with
error fails closed; assignment order is not used as a tie-breaker.
sampled fields are currently authoring-only. The asset identity and sampling location survive in
ProblemIR, but the planner rejects materialization until the asset-loading and mesh-cardinality
contract is available. A legal Python object is therefore not evidence of sampled-field runtime
support.
Material transitions¶
region.material_transition(...) records an explicit interface policy:
material_transition(*, cells=None, width=None,
kind="mesh_relative", scope="boundary")
kind="mesh_relative" requires cells >= 1; kind="metric" requires positive width; and
kind="sharp" carries neither. scope is boundary, inside, or outside. This is an
authoring policy for Ms, Aex, or another supported parameter; it is not an automatic smoothing
pass and does not create an RKKY or inter-object coupling.
ProblemIR and realization¶
Problem.to_ir(...) is the canonical problem serialization boundary. The relevant output sections
are:
Authored concern |
ProblemIR section |
What remains visible |
|---|---|---|
primitive, boolean, transform, or import |
|
typed |
object-owned region |
|
owner, region ID, shape, frame, priority, mesh policy, overrides |
base material |
|
SI scalar values, axes, anisotropy and DMI fields |
spatial material assignment |
|
assignment ID, owner, region, field kind, frame, unit and conflict policy |
realized grid or mesh |
|
backend-specific assets only when asset building is requested |
Requested intent and resolved assets are separate. A changed geometry, region membership, mesh policy, imported source, or material-field definition invalidates dependent mesh and materialized field provenance. A change to magnetization alone does not change mesh identity.
Round-trip and failure semantics¶
Requested intent preserves typed geometry, region identity, field kind, units, frame, and conflict policy before execution. Resolved execution adds backend assets, mesh locations, interpolation, and provenance. Validation errors identify invalid authored values; unsupported combinations fail closed at construction, planning, or materialization rather than silently changing backend or device.
Discrete realization¶
FDM realization¶
FDM uses structured cells and active masks. Geometry defines cell ownership and region membership; material values are evaluated at the locations consumed by the stencil. FDM periodicity, demagnetizing boundary correction, per-magnet grids, and multilayer policies are separate contracts and must not be inferred from a successful primitive construction.
FEM realization¶
FEM uses a shared domain with typed element topology, material markers, and boundary markers. Object-region mesh policies participate in that shared domain. Thin-film swept layers, prism or tetrahedral topology, airbox extent, periodic pairs, and boundary layers are resolver-specific choices that require their own mesh report and convergence evidence.
The physics page therefore claims authoring and ProblemIR semantics only. It does not claim that every legal geometry/material combination is supported by every backend, device, precision, mesh topology, or Control Room path.
Complete composition example¶
# %%
# Compose geometry, regions, materials, fields, and an explicit FEM request
import fullmag as fm
nm = 1.0e-9
study = fm.study("perforated_film")
study.engine("fem")
study.device("cpu", precision="double")
study.mode("strict")
film_shape = fm.Box(size=(300 * nm, 100 * nm, 5 * nm), name="film_shape")
hole_shape = fm.Cylinder(radius=20 * nm, height=5 * nm).translate((80 * nm, 0.0, 0.0))
film = study.geometry(film_shape - hole_shape, name="film")
film.Ms = 800.0e3
film.Aex = 13.0e-12
film.alpha = 0.02
core = film.add_region(
"core",
fm.Ellipsoid(40 * nm, 20 * nm, 2 * nm),
frame="object",
priority=10,
realization_policy="inherit",
)
core.material.Ms = fm.fields.constant(760.0e3, unit="A/m")
core.material_transition(kind="mesh_relative", cells=2, scope="boundary")
core.mesh(maximum_element_size=3 * nm, minimum_element_size=1 * nm, order=1)
film.set_material_field(
"Ms",
fm.fields.radial(
center=(0.0, 0.0, 0.0),
radius=50 * nm,
inside=780.0e3,
outside=800.0e3,
frame="world",
unit="A/m",
),
assignment_id="film_world_radial_ms",
priority=1,
)
study.stages.add_run(stage_id="inspect_composition", until=1.0e-15)
This example creates one magnetic object, one nested CSG geometry, one object-owned region, one region override, one region mesh policy, one interface transition policy, and one object-scoped world-frame field. It does not claim a completed mesh or a solved field; those are produced only by the selected build and runtime workflow.
Control Room crosswalk¶
The intended path for scalar object parameters is Model Explorer -> Objects -> <object> -> Material;
region membership and local mesh controls are exposed only where the capability register marks them
as supported. Spatial fields, imported-CAD authoring, advanced boolean operations, and unqualified
mesh policies remain Python/ProblemIR-first unless a named Control Room transaction is implemented.
Backend or Python availability must not be interpreted as UI availability.
See Control Room capability register for the current support matrix.
Validation strategy and known limits¶
Construction and serialization tests are evidence for the typed authoring boundary. They do not prove mesh quality, solver convergence, CPU/GPU parity, or scientific validity. A backend qualification for this section must include at least:
geometry and source identity, including the imported scale and revision when applicable;
resolved region membership and material markers or FDM masks;
mesh/grid cardinality, topology, quality, boundary policy, and provenance;
material-field location, interpolation, conflict resolution, and precision;
interaction-specific observables and refinement or convergence evidence;
device and execution-mode evidence when CPU/GPU behavior is claimed.
The current page does not qualify adaptive refinement, arbitrary Python geometry callables, every boolean/import format, every periodic boundary combination, sampled material-field materialization, or every mixed FEM topology. Unsupported combinations must fail explicitly rather than silently fall back to another backend or device.
Known limits¶
The current public contract does not qualify adaptive refinement, arbitrary Python geometry callables, every boolean or import format, every periodic boundary combination, sampled material-field materialization, or every mixed FEM topology.
Terminal API pages¶
Bibliography¶
W. F. Brown Jr., Micromagnetics, Wiley, 1963.
A. Hubert and R. Schafer, Magnetic Domains, Springer, 1998.
P. G. Ciarlet, The Finite Element Method for Elliptic Problems, SIAM, 2002.
O. C. Zienkiewicz, R. L. Taylor, and J. Z. Zhu, The Finite Element Method: Its Basis and Fundamentals, 7th ed., Butterworth-Heinemann, 2013.
C. Geuzaine and J.-F. Remacle, “Gmsh: a three-dimensional finite element mesh generator,” International Journal for Numerical Methods in Engineering 79, 1309-1331 (2009), doi:10.1002/nme.2579.
Implementation mapping¶
The Python authoring classes build typed records first. Problem.to_ir collects those records, and
build_geometry_assets_for_request is the boundary where optional FDM/FEM geometry assets are
requested. Backend planners and runners own materialization, marker assignment, topology, and
device-specific support.
Source-code index¶
Claim or API |
Repository path |
Stable symbol |
Responsibility |
|---|---|---|---|
primitives, imports, booleans, transforms |
|
|
typed geometry and |
high-level geometry handle |
|
|
object creation and base material properties |
object regions and overrides |
|
|
region identity, material proxy, transitions, local mesh policy |
base material |
|
|
SI validation and material IR |
analytic and sampled fields |
|
|
field payload and scoped assignment |
full problem lowering |
|
|
ProblemIR and optional geometry assets |
shared-domain mesh policy |
|
|
mesh intent before backend realization |
Focused public API evidence includes the region-lowering, boolean-difference, centered-shape,
material-field, and ProblemIR tests in packages/fullmag-py/tests/test_api.py. These tests establish
source behavior; they are not a substitute for executed FDM/FEM qualification receipts.