Mesh sizing, local refinement and convergence

Last changes: Documentation changelog

Problem statement

Refinement composes object bulk, interface, transition, perimeter, manual-hotspot and region-owned fields into one realized Gmsh field stack.

Governing equations

(1)\[\mathcal F=\mathcal F_{bulk}\cup\mathcal F_{interface}\cup\mathcal F_{transition}\cup\mathcal F_{perimeter}\cup\mathcal F_{hotspot}\cup\mathcal F_{region}.\]

Symbols and SI units

Token

Meaning

SI unit

\(\mathcal F\)

realized field stack

\(1\)

\(\mathcal F_{bulk}\)

object bulk fields

\(1\)

\(\mathcal F_{interface}\)

interface fields

\(1\)

Assumptions and validity

The union denotes ordered composition in _build_field_stack, not a physical superposition rule. Region order other than one is explicitly rejected in the shown source path.

Python API

Complete public signature and IR matrix

The following rows are the exhaustive public-signature contract for this page; each row mirrors one public_api.parameters entry in the source map.

Python

Type

Default

SI unit

Validation

Meaning

Backend support

ProblemIR

hmax

float | str | None

None

\(\mathrm{m}\)

compatibility alias; canonical maximum_element_size wins; numeric values must be positive and the only accepted string is exact auto

compatibility coarse-size spelling

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].maximum_element_size

hmin

float | None

None

\(\mathrm{m}\)

compatibility alias; canonical minimum_element_size wins; positive and no greater than numeric maximum

compatibility lower-clamp spelling

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].minimum_element_size

maximum_element_size

float | str | None

None

\(\mathrm{m}\)

positive finite float or exact auto

coarse size target

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].maximum_element_size

minimum_element_size

float | None

None

\(\mathrm{m}\)

positive and no greater than numeric maximum

lower size clamp

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].minimum_element_size

order

int | None

None

\(1\)

prismatic route restricts order to 1; other routes are backend-gated

FEM order request

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].order

calibrate_for

str | None

None

\(1\)

normalized to a supported calibration name

calibration family

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].calibrate_for

size_preset

str | None

None

\(1\)

normalized to coarse, normal, fine, finer, or extra_fine

preset family

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].size_preset

algorithm_2d

int | None

None

\(1\)

stored without an authoring-time range check

Gmsh 2-D algorithm

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].algorithm_2d

algorithm_3d

int | None

None

\(1\)

stored without an authoring-time range check

Gmsh 3-D algorithm

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].algorithm_3d

optimize

str | None

None

\(1\)

stored without an authoring-time vocabulary check

optimizer

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].optimize

optimize_iterations

int | None

None (effective state 1)

passes

stored without an authoring-time range check

optimizer passes

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].optimize_iterations

smoothing_steps

int | None

None (effective state 1)

passes

stored without an authoring-time range check

smoothing passes

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].smoothing_steps

size_factor

float | None

None (effective state 1.0)

\(1\)

stored without an authoring-time positivity check

preset multiplier

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].size_factor

size_from_curvature

int | None

None (effective state 0)

points per \(2\pi\)

stored without an authoring-time range check

curvature sampling

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].size_from_curvature

curvature_factor

float | None

None

\(1\)

coerced with float()

curvature refinement

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].curvature_factor

maximum_element_growth_rate

float | None

None

\(1\)

finite, positive and at most 2.5

neighboring-zone growth

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].maximum_element_growth_rate

growth_rate

float | None

None

\(1\)

compatibility alias; canonical maximum_element_growth_rate wins; finite, positive and at most 2.5

compatibility growth spelling

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].maximum_element_growth_rate

narrow_regions

int | None

None (effective state 0)

elements

non-Boolean integer at least 0

narrow-gap request

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].narrow_regions

narrow_region_resolution

float | None

None

\(1\)

coerced with float()

narrow-gap strength

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].narrow_region_resolution

interface_maximum_element_size

float | None

None

\(\mathrm{m}\)

positive

interface target

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].interface_hmax

interface_hmax

float | None

None

\(\mathrm{m}\)

compatibility alias; canonical interface_maximum_element_size wins; positive

compatibility interface-target spelling

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].interface_hmax

interface_thickness

float | None

None

\(\mathrm{m}\)

positive

interface-band thickness

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].interface_thickness

transition_distance

float | str | None

None

\(\mathrm{m}\) or symbol

non-negative numeric value or supported boundary symbol

interface transition span

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].transition_distance

transition_growth

float | None

None

\(1\)

positive

interface transition growth

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].transition_growth

edge_maximum_element_size

float | None

None

\(\mathrm{m}\)

positive

edge target

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].edge_hmax

edge_hmax

float | None

None

\(\mathrm{m}\)

compatibility alias; canonical edge_maximum_element_size wins; positive

compatibility edge-target spelling

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].edge_hmax

edge_thickness

float | None

None

\(\mathrm{m}\)

positive; perimeter validation also applies

edge-band width

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].edge_thickness

edge_transition_distance

float | str | None

None

\(\mathrm{m}\) or symbol

positive numeric value or supported boundary symbol

edge transition span

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].edge_transition_distance

corner_maximum_element_size

float | None

None

\(\mathrm{m}\)

positive

corner target

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].corner_hmax

corner_hmax

float | None

None

\(\mathrm{m}\)

compatibility alias; canonical corner_maximum_element_size wins; positive

compatibility corner-target spelling

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].corner_hmax

corner_extent

float | None

None

\(\mathrm{m}\)

positive; perimeter validation also applies

corner extent

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].corner_extent

corner_transition_distance

float | str | None

None

\(\mathrm{m}\) or symbol

positive numeric value or supported boundary symbol

corner transition span

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].corner_transition_distance

boundary_layer_count

int | None

None

layers

int() coercion and at least 1

boundary-layer count

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].boundary_layer_count

boundary_layer_thickness

float | None

None

\(\mathrm{m}\)

positive

boundary-layer thickness

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].boundary_layer_thickness

boundary_layer_stretching

float | None

None

\(1\)

positive

boundary-layer growth

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].boundary_layer_stretching

boundary_layer_target_surface_tags

Sequence[int] | None

None

\(1\)

normalized by _normalize_int_tags

target surfaces

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].boundary_layer_target_surface_tags

boundary_layer_target_curve_tags

Sequence[int] | None

None

\(1\)

normalized by _normalize_int_tags

target curves

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].boundary_layer_target_curve_tags

boundary_layer_target_surface_selectors

Sequence[Mapping] | None

None

\(1\)

normalized by _normalize_selector_list

semantic target surfaces

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].boundary_layer_target_surface_selectors

boundary_layer_target_curve_selectors

Sequence[Mapping] | None

None

\(1\)

normalized by _normalize_selector_list

semantic target curves

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].boundary_layer_target_curve_selectors

compute_quality

bool | None

None (effective state False)

\(1\)

no explicit Python type check

aggregate quality request

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].compute_quality

per_element_quality

bool | None

None (effective state False)

\(1\)

no explicit Python type check

per-element quality request

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].per_element_quality

kind

str

required

\(1\)

appended without authoring-time field validation

manual Gmsh field kind

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].size_fields[].kind

**params

Mapping[str, object]

{}

mixed

appended without authoring-time field validation

manual Gmsh field parameters

FEM CPU/GPU capability-gated

mesh_workflow.per_geometry[].size_fields[].params

This page’s public controls are normalized before _build_field_stack; the internal function is not a user callable. Use the documented mesh-policy/size-field API and inspect the resulting stack.

Python

Type

Default

SI unit

Validation and coercion

Meaning

Backend support

ProblemIR

maximum_element_size, hmax

`float

str

None`

None

m

numeric values are positive; the only accepted string is exact "auto"; canonical name wins

coarse target

minimum_element_size, hmin

`float

None`

None

m

positive and no greater than numeric maximum_element_size; canonical name wins

lower clamp

FEM CPU/GPU capability-gated

order

`int

None`

None

1

prismatic intent permits only 1; other orders are realized-backend decisions

FEM basis request

FEM CPU/GPU capability-gated

calibrate_for, size_preset

`str

None`

None

1

calibration is normalized; preset is normalized to coarse, normal, fine, finer, or extra_fine

preset selection

FEM CPU/GPU capability-gated

algorithm_2d, algorithm_3d, optimize

`int

str

None`

None

1

stored without an authoring-time range or vocabulary check

Gmsh algorithms and optimizer

optimize_iterations, smoothing_steps

`int

None`

None (stored defaults 1)

passes

direct public call stores values; recipe validation requires non-negative integral smoothing

optimization/smoothing passes

FEM CPU/GPU capability-gated

size_factor, size_from_curvature, curvature_factor

`float

int

None`

None (stored 1.0, 0, None)

1

curvature_factor uses float(); the first two are stored directly by this call

global and curvature sizing

maximum_element_growth_rate, growth_rate

`float

None`

None

1

finite, positive, and at most 2.5; canonical name wins

requested growth

FEM CPU/GPU capability-gated

narrow_regions, narrow_region_resolution

`int

float

None`

None (stored 0, None)

elements, 1

narrow_regions is non-Boolean integer >= 0; resolution uses float()

narrow-gap refinement

interface_maximum_element_size, interface_hmax, interface_thickness, transition_distance, transition_growth

`float

str

None`

None

m, 1

positive sizes/thickness/growth; transition_distance is non-negative float or normalized "airbox_boundary"; canonical size name wins

interface band

edge_maximum_element_size, edge_hmax, edge_thickness, edge_transition_distance

`float

str

None`

None

m

positive sizes/thickness; transition is positive float or normalized "airbox_boundary"; size and thickness must occur together

edge band

corner_maximum_element_size, corner_hmax, corner_extent, corner_transition_distance

`float

str

None`

None

m

positive size/extent; transition is positive float or normalized "airbox_boundary"; size and extent must occur together and corner size <= edge size

corner band

boundary_layer_count, boundary_layer_thickness, boundary_layer_stretching

`int

float

None`

None

layers, m, 1

count uses int() and is >= 1; thickness and stretching use float() then require positive

boundary layer

boundary_layer_target_surface_tags, boundary_layer_target_curve_tags

`Sequence[int]

None`

None

1

each element uses int() and must be > 0

numeric targets

FEM CPU/GPU capability-gated

boundary_layer_target_surface_selectors, boundary_layer_target_curve_selectors

`Sequence[Mapping]

None`

None

1

every item must be a mapping and is copied with dict(); semantic selector parsing belongs downstream

semantic targets

FEM CPU/GPU capability-gated

compute_quality, per_element_quality

`bool

None`

None (stored False)

1

no explicit type check in this public call

quality-report request

FEM CPU/GPU capability-gated

size_field(kind, **params)

str, Mapping[str, object]

required, {}

mixed

appends {"kind": kind, "params": dict(params)} without authoring-time field validation

manual Gmsh field

FEM CPU/GPU capability-gated

per_geometry[].size_fields[]

# %%
import fullmag as fm

# %%
study = fm.study("refinement_contract")
study.engine("fem")
study.device("cpu", precision="double")
study.mode("strict")
study.universe(
    mode="manual",
    size=(220.0e-9, 170.0e-9, 80.0e-9),
    center=(0.0, 0.0, 0.0),
    padding=(20.0e-9, 20.0e-9, 20.0e-9),
)
study.universe.mesh(
    maximum_element_size=12.0e-9,
    minimum_element_size=6.0e-9,
    maximum_element_growth_rate=1.3,
    grading="geometric",
)
film = study.geometry(fm.Box(size=(100e-9, 50e-9, 5e-9), name="film"), name="film")
film.Ms = 800.0e3
film.Aex = 13.0e-12
film.alpha = 0.02
film.m = fm.texture.uniform(1.0, 0.0, 0.0)
film.mesh(
    maximum_element_size=8.0e-9,
    minimum_element_size=3.0e-9,
    maximum_element_growth_rate=1.2,
    interface_maximum_element_size=4.0e-9,
    interface_thickness=8.0e-9,
    transition_distance="airbox_boundary",
    edge_maximum_element_size=3.0e-9,
    edge_thickness=10.0e-9,
    corner_maximum_element_size=2.0e-9,
    corner_extent=6.0e-9,
)
film.mesh.size_field("Ball", VIn=2.0e-9, VOut=8.0e-9, Radius=15.0e-9)
study.exchange()
study.demag(realization="poisson_robin")
study.build_domain_mesh()
study.stages.add_relax(stage_id="equilibrium", dt=5.0e-13, max_steps=1)

Parameters

The complete parameter matrix in the Python API section is the public mesh-authoring contract. Defaults, validation, ProblemIR lowering and capability-gated lanes are listed there and mirrored by the adjacent source map.

ProblemIR

Mesh-policy and size-field descriptors are normalized to per-geometry and region-owned records; the resulting field stack is resolved execution data, not a user-authored IR literal.

Round-trip and failure semantics

Requested intent is the policy descriptor. Resolved execution is the assembled field list. Validation errors include unsupported region order and malformed region data. Unsupported combinations are rejected or skipped with a progress warning; neither is silently represented as applied refinement.

Discrete realization

The cited owners build unstructured FEM fields. FDM CPU and GPU are not-applicable for this page contract; structured-grid refinement belongs to the linked FDM-grid page.

Implementation mapping

GeometryMeshHandle and surface_shell own public descriptors; _build_problem and Problem.to_ir preserve runtime_metadata.mesh_workflow.per_geometry; _build_field_stack composes realized Gmsh fields; the domain asset pipeline materializes the mesh; planner/runtime consume the artifact without proving convergence or GPU execution.

Validation

Inspect realized field records and local-size distributions, then establish observable convergence. No runtime/device evidence is added by this documentation change.

Limitations

The stack itself does not certify a requested physical resolution; convergence remains observable-specific.

Scientific bibliography

Geuzaine and Remacle, IJNME 79 (2009), doi:10.1002/nme.2579.

Contract source-code index

ID

Path

Symbol

Responsibility

Evidence

field_stack

packages/fullmag-py/src/fullmag/meshing/_size_field_plan.py

_build_field_stack

ordered refinement-field normalization

source-inspected

public_study

packages/fullmag-py/src/fullmag/world.py

study

public study entry point

source-inspected

mesh_authoring

packages/fullmag-py/src/fullmag/world.py

class GeometryMeshHandle

per-body mesh authoring

source-inspected

surface_shell

packages/fullmag-py/src/fullmag/meshing/mesh_controls.py

surface_shell

public refinement descriptor

source-inspected

problem_lowering

packages/fullmag-py/src/fullmag/world.py

_build_problem

builder-state lowering

source-inspected

problem_ir

packages/fullmag-py/src/fullmag/model/problem.py

class Problem

ProblemIR mesh-workflow serialization

source-inspected

domain_realization

packages/fullmag-py/src/fullmag/meshing/asset_pipeline.py

realize_fem_domain_mesh_asset_from_components_with_report

field-plan mesh realization

source-inspected

planner

crates/fullmag-plan/src/lib.rs

plan

ProblemIR planning and compatibility

source-inspected, runtime-unverified

runtime

crates/fullmag-runner/src/lib.rs

run_planned_problem

planned runtime dispatch

source-inspected, device-unverified

Last changes: 12:31 24.08.2026

Refinement should be driven by physical length scales and observable error. Fullmag combines calibrated presets, explicit min/max sizes, interface/edge/corner controls and structured size fields.

Implementation status

Named calibrations, presets, explicit size bounds, interface/edge/corner controls, manual boxes and semantic size fields are implemented. Adaptive solve–estimate–remesh loops are documented separately and must not be inferred from static authoring controls.

Scope and purpose

Use this page to choose element/cell sizes, construct local grading zones and design a convergence study. Refinement is not synonymous with globally decreasing hmax: it should target regions responsible for the dominant discretization error while preserving acceptable element quality and solver conditioning.

Scientific and numerical model

FDM scientific invariants (context only)

These criteria are contextual guidance for the separate FDM-grid page, not backend or implementation claims for this FEM refinement API.

An FDM grid stores the magnetization on a Cartesian lattice with cell dimensions \(\Delta x\), \(\Delta y\) and \(\Delta z\). Cell centers are

(2)\[\mathbf r_{ijk}=\mathbf r_0+ \left(i+\tfrac12,j+\tfrac12,k+\tfrac12\right) \odot(\Delta x,\Delta y,\Delta z).\]

The cell size simultaneously controls geometry voxelization, finite-difference exchange and the accuracy/cost of FFT demagnetization. It must therefore resolve the smallest magnetic length scale, the smallest geometric feature and the desired boundary accuracy. The exchange-length expression

(3)\[\ell_{\mathrm{ex}}=\sqrt{\frac{2A}{\mu_0M_s^2}}\]

is a useful initial guide, but final values require a grid-refinement study. A one-cell film thickness is a thickness-averaged discretization; it cannot represent a nonuniform mode across the thickness.

FEM scientific invariants

A finite-element mesh is not only a visualization asset. It defines the trial/test spaces used by exchange, anisotropy, DMI, magnetostatic and dynamic operators. The following conditions are therefore part of the numerical contract:

  1. Every magnetic volume has an unambiguous region marker and every exterior-air volume has the canonical air role.

  2. Interfaces used by coupled operators are conforming, or an explicitly supported nonconforming coupling operator is selected. Fullmag’s ordinary shared-domain path expects conformity.

  3. Cell orientation is valid: the element mapping has a positive Jacobian at all required evaluation points. Inverted or collapsed cells are build failures, not warnings to ignore.

  4. Requested topology, polynomial order, layer count and mesh-size controls are compared with the realized mesh. A topology change is legal only when the build mode permits fallback and the report names the actual method and reason.

  5. Mesh convergence is assessed on physical observables—energy, average magnetization, switching field, eigenfrequency, linewidth or field error—not only on element count.

For exchange-dominated variation, a useful starting scale is the magnetostatic exchange length

(4)\[\ell_{\mathrm{ex}}=\sqrt{\frac{2A}{\mu_0M_s^2}}.\]

Using an element size below roughly one half of the smallest relevant magnetic length scale is a common initial choice, not a proof of convergence. Curved boundaries, surface charges, DMI, defects, interfaces and through-thickness modes can demand a smaller local size.

A generic size field is a spatial target \(h(\mathbf r)\). When several upper-bound fields are active, the mesher normally receives their minimum,

(5)\[h_{target}(\mathbf r)=\min_j h_j(\mathbf r),\]

followed by global lower/upper clamps and growth controls. This means overlapping refinement fields do not average; the finest request dominates. ObjectCoreRelaxation explicitly keeps a fine surface/edge shell while allowing a coarser interior. Distance-threshold fields interpolate from SizeMin near a selected entity to SizeMax over a specified distance.

Presets fill defaults. Explicit parameters and object-specific fields can override them. The effective configuration resource is therefore the only reliable record of the resolved values.

Selection guide

Use case

Recommended choice

Reason

Unknown problem / first mesh

calibrate_for + normal or fine

Provides a reproducible baseline before explicit convergence

Exchange/DMI texture localized in the bulk

local box or physics-driven field

Refine around the expected soliton/domain-wall region

Demag edge singularity / antidot

edge and corner refinement

Targets strong surface-charge gradients

Large 3-D body with smooth core

ObjectCoreRelaxation

Fine boundary shell, coarser interior

Magnet/air interface

interface shell + controlled transition

Protects field accuracy and conformity

Detailed refinement field guidance

Python / IR key

Unit

Default

Validation

Numerical effect

maximum_element_size

m

required for direct FEM generation

positive finite

coarse upper target; local size fields may request smaller elements

minimum_element_size

m

unset

positive and not greater than the maximum

lower size clamp for local refinement and curvature sizing

maximum_element_growth_rate

1

preset/backend dependent

positive

limits requested growth between neighboring size zones

calibrate_for

1

unset

named calibration family

selects physics-aware preset calibration

size_preset

1

unset

coarse, normal, fine, finer, or extra_fine after normalization

fills common size/growth/curvature controls before explicit overrides

size_factor

1

1

positive

multiplies preset-derived target sizes

curvature_factor

1

unset

positive when set

controls curvature-driven refinement; smaller values generally refine more

narrow_region_resolution

1

unset

positive when set

requests additional resolution in narrow geometric gaps/features

order

1

unset in GeometryMeshHandle

prismatic requests restrict it to 1; other routes are backend-gated

finite-element polynomial order request

algorithm_2d

Gmsh ID

6

supported Gmsh 2-D algorithm number

surface triangulation before volume meshing

algorithm_3d

Gmsh ID

1

supported Gmsh 3-D algorithm number

volume tetrahedralization algorithm

smoothing_steps

passes

1

non-negative integer

post-generation node smoothing

optimize

1

unset

Gmsh optimizer name

optional quality optimization; does not replace convergence checks

optimize_iterations

passes

1

positive integer

number of optimizer passes

compute_quality

1

omitted retains False in Python; Control Room may author True

no explicit Python type check

requests aggregate quality metrics

per_element_quality

1

omitted retains False in Python; Control Room may author True

no explicit Python type check

requests per-element quality arrays and scoped distributions

interface_maximum_element_size

m

unset

positive

near-interface target size

interface_thickness

m

unset

positive

distance over which interface sizing remains active

transition_distance

m or symbolic

unset

positive or airbox_boundary when supported

ramp length from fine interface to coarse far field

transition_growth

1

unset

positive

requested growth across the transition

edge_maximum_element_size

m

unset

positive

target along selected/recovered object edges

edge_thickness

m

unset

positive

width of the finest edge band

edge_transition_distance

m or symbolic

unset

positive or supported symbolic value

edge-to-far-field ramp

corner_maximum_element_size

m

unset

positive; no edge-target ordering check is performed here

target at corners

size_fields

mixed

[]

validated field descriptors

composable spatial target fields

Complete refinement authoring example

Complete Python example

import fullmag as fm

nm = 1.0e-9
study = fm.study("fem_local_refinement_reference")
study.engine("fem")
study.device("cpu", precision="double")
study.mode("strict")
study.universe(
    mode="manual",
    size=(800 * nm, 500 * nm, 260 * nm),
    center=(0.0, 0.0, 0.0),
    padding=(0.0, 0.0, 0.0),
)
study.universe.mesh(
    minimum_element_size=15 * nm,
    maximum_element_size=100 * nm,
    maximum_element_growth_rate=1.6,
    grading="geometric",
)

film = study.geometry(
    fm.Box(size=(600 * nm, 250 * nm, 10 * nm), name="film"),
    name="film",
)
film.mesh(
    mesh_strategy="free_tetrahedral",
    calibrate_for="general_physics",
    size_preset="fine",
    size_factor=1.0,
    minimum_element_size=3 * nm,
    maximum_element_size=10 * nm,
    maximum_element_growth_rate=1.35,
    order=1,
    compute_quality=True,
    per_element_quality=True,
)
film.mesh.size_field("Ball", VIn=3 * nm, VOut=10 * nm, Radius=30 * nm, XCenter=0.0, YCenter=0.0, ZCenter=0.0)
film.Ms = 800.0e3
film.Aex = 13.0e-12
film.alpha = 0.02
film.m = fm.texture.uniform(1.0, 1.0e-4, 0.0)

study.exchange()
study.demag(realization="poisson_robin")
study.build_domain_mesh()
study.stages.add_relax(
    stage_id="equilibrium",
    algorithm="llg_overdamped",
    dt=5.0e-13,
    tolA=1.0e-4,
    max_steps=20_000,
)

Control Room workflow

  1. In Explorer, select the magnetic object’s Mesh child (the object mesh-policy route).

  2. In Inspector → Object Mesh Policy, enable Use object policy when an object-specific override is required.

  3. Configure the relevant groups: Mesh Size Presets, Element Size Parameters, Thin-Film Sweep Strategy, Interface and Transition Refinement, Backend Mesh Parameters, Core Relaxation, Manual Size Field, and Edge and Corner Refinement.

  4. Select Apply Object Policy. This stores authoring intent and invalidates mesh resources whose revision no longer matches the model.

  5. Select Build Mesh. If the draft is dirty, the panel applies it first and dispatches the canonical mesh.build-selected command.

  6. Open the Quality and History tabs. Compare requested and realized values, then inspect the scoped size/quality distributions and the raw build report before running a solver.

The read-only effective values come from backend resources. They must not be reconstructed from the current form fields because presets, capability gates and backend normalization can change the resolved configuration.

Use Mesh Size Presets for the reproducible baseline. Use Element Size Parameters for explicit clamps and Gmsh controls. Configure Interface and Transition Refinement, Core Relaxation, Manual Size Field, or Edge and Corner Refinement only where the physics justifies them. The size histogram and scoped quality views should show the realized distribution; a filled form is not evidence that a field matched any entity.

Verification, quality and provenance

After every build, inspect the realized resource rather than assuming that the authored request was applied. The production check is:

  • geometry and mesh revisions match the current model;

  • requested and realized discretization/topology/order are recorded;

  • node, element and boundary-facet counts are nonzero for every required region;

  • region and boundary markers cover the complete topology;

  • inverted and degenerate element counts are zero;

  • interface diagnostics report no orphan, coincident, nonmanifold or unmatched facets;

  • local size distributions are consistent with the intended edge/interface/core grading;

  • any fallback or degradation has an explicit reason and an actual method;

  • a mesh-refinement sequence demonstrates convergence of the scientific observable.

MeshQualityReport exposes signed inverse condition number (SICN), gamma/radius quality, volume statistics and optional per-element arrays. The source constants gamma_min=0.08 and SICN p05=0.1 are implementation gates for named report paths; they are not universal physical acceptance thresholds for every element family or study.

Mesh-convergence protocol

A production result should include at least three discretizations. Refine only the parameter under study while holding geometry, material parameters, solver tolerances, initial state and output sampling fixed. Let \(Q_h\) denote the observable for characteristic size \(h\). Report

(6)\[\varepsilon_h=\frac{|Q_h-Q_{h/\rho}|}{\max(|Q_{h/\rho}|,Q_{\mathrm{scale}})}, \qquad \rho>1,\]

with a documented scale for observables that can cross zero. For dynamics, compare resonance frequency, linewidth and mode profile; for relaxation, compare total energy and texture; for demag, compare field/energy and verify that moving the outer boundary does not change the result beyond the chosen tolerance.

Diagnostics and failure semantics

  • A semantic selector resolving zero entities is an error or explicit no-op, never silent success.

  • Raw Gmsh tags are fragile across geometry rebuilds; prefer semantic selectors.

  • An aggressive size jump can create poor quality or solver-conditioning problems despite a locally fine mesh.

  • A preset name without effective numeric values is insufficient provenance.

  • Refine geometry and field sampling together for imported/curved boundaries; very small hmin cannot repair a defective surface asset.

  • A lower element count after adding refinement can indicate that another size field was replaced rather than combined; inspect the normalized field plan.

Where this is implemented

Responsibility

Repository source

Stable owner / symbol

Mesh-size presets and resolution

packages/fullmag-py/src/fullmag/meshing/_gmsh_types.py

MESH_SIZE_PRESETS, resolve_mesh_size_controls

Semantic field constructors

packages/fullmag-py/src/fullmag/meshing/mesh_controls.py

object_core_relaxation, edge_distance_threshold, interface_shell

Field-plan normalization

packages/fullmag-py/src/fullmag/meshing/_size_field_plan.py

size-field plan

Gmsh field application

packages/fullmag-py/src/fullmag/meshing/_gmsh_fields.py

_apply_mesh_options

Object policy UI

apps/control-room/src/modules/inspector/panels/ObjectMeshPolicyPanel.tsx

ObjectMeshPolicyPanel

Size-field preview resource

apps/control-room/src/kernel/resources/geometryLifecycleResources.ts

object mesh size-field resource

Implementation map reviewed against commit 5db00ccf0113b9756fec2d46feb36ade762b12c2 on 2026-08-24.

References

  • C. Geuzaine and J.-F. Remacle, “Gmsh: a three-dimensional finite element mesh generator with built-in pre- and post-processing facilities,” International Journal for Numerical Methods in Engineering 79 (2009), 1309–1331, doi:10.1002/nme.2579.

  • C. Abert, “Micromagnetics and spintronics: models and numerical methods,” European Physical Journal B 92, 120 (2019), doi:10.1140/epjb/e2019-90599-6.

  • Gmsh reference manual, mesh algorithms, size fields, extrusion and physical groups: gmsh.info/doc/texinfo.

Extended source notes

  • Python contract source: packages/fullmag-py/src/fullmag/model/discretization.py and packages/fullmag-py/src/fullmag/world.py, where applicable. Runtime realization is owned by the relevant backends/fdm or backends/fem implementation; the page must not claim a symbol not named in its implementation mapping.