FDM periodic grids

Last changes: Documentation changelog

Physical problem

FdmPbc records periodic local topology and a separate demagnetization policy. truncated_images is finite translated-image magnetostatics, not an infinite periodic Green function.

Governing equations

(1)\[\mathbf H_d(\mathbf r_i)=\sum_{\mathbf n\in\mathcal I}\sum_j\mathcal N(\mathbf r_i-\mathbf r_j-\mathbf n\odot\mathbf L)\mathbf M_j .\]

Symbols and SI units

Symbol

Meaning

SI unit

\(\mathbf H_d\)

demagnetizing field

A m^-1

\(\mathbf r_i\)

target cell centre

m

\(\mathbf L\)

unit-cell period

m

\(\mathbf n\)

image index

1

\(\mathcal I\)

finite image set

1

\(\mathbf M_j\)

source magnetization

A m^-1

Assumptions and validity

axes is first iterated and every value is converted with bool(value); only then must the resulting tuple have length three. If image_counts is present, every value is first converted with int(value), then the resulting tuple must have length three and contain no negative value. Consequently numeric strings and truncatable floats can be accepted, while conversion itself may raise TypeError, ValueError, or OverflowError. The demagnetization string is normalized with strip().lower() before policy validation. Image counts remain valid only with truncated_images. FDM rejects periodic_airbox_k0, which is FEM-only. Converge image counts and cell size separately.

Python API

# %%
import fullmag as fm
nm = 1e-9
study = fm.study("periodic-grid")
study.engine("fdm")
study.fdm(default_cell=(2 * nm, 2 * nm, 5 * nm))
film = study.geometry(fm.Box(100 * nm, 40 * nm, 5 * nm), name="film")
film.Ms = 800.0e3
film.Aex = 13.0e-12
film.m = fm.texture.uniform(1.0, 0.0, 0.0)
study.pbc(x=True, y=True, z=False, demag="truncated_images", images=(4, 4, 0))
study.demag()
study.stages.add_relax(stage_id="equilibrium", dt=5.0e-13, max_steps=1)

Python

Type

Default

SI unit

Validation

Meaning

Backend support

ProblemIR

FdmPbc.axes

tuple[bool, bool, bool]

required

1

iterates input, applies bool(value), then requires length three

periodic flags

FDM CPU source-backed; GPU capability-gated; FEM separate contract

pbc.axes as periodic or open

FdmPbc.demag

str

open

1

applies strip().lower(), then requires open, truncated_images, or periodic_airbox_k0

normalized requested demag policy

FDM CPU open/truncated source-backed; GPU capability-gated; FEM differs

pbc.demag

FdmPbc.image_counts

tuple[int, int, int] | None

None

1

applies int(value), then requires length three and non-negative results; only truncated_images

finite image ranges; when omitted for active periodic truncated demag, resolves to 10 on periodic axes and 0 on open axes

FDM CPU source-backed; GPU capability-gated; FEM not applicable

pbc.image_counts

ProblemIR

StudyBuilder.pbc(...) applies the setting to the study and constructs FdmPbc; FdmPbc.to_ir() emits axis strings, the normalized policy, and optional image counts. FDM lowering rejects periodic_airbox_k0 rather than changing policy.

Round-trip and failure semantics

Requested intent preserves the coerced Boolean flags, normalized demagnetization policy, and integer counts, not necessarily the caller’s original Python value types. Resolved execution validates the runtime boundary and periodic workspace. With active demagnetization, at least one periodic axis, and truncated_images, omitted image_counts first supplies requested counts [10, 10, 10]; resolution keeps 10 on each periodic axis and sets every open axis to 0. The resolved number of translated-image terms is

\[N_{\mathrm{images}}=\prod_{\alpha\in\{x,y,z\}}(2n_\alpha+1),\]

where resolved open-axis counts are zero. Resolution rejects more than 1,000,000 image terms. Validation errors cover non-iterable inputs, failed bool()/int() conversion, wrong post-coercion lengths, negative converted counts, invalid policy, image-budget overflow, or workspace-budget overflow. Unsupported combinations, including FDM periodic_airbox_k0 and periodic demag without truncated_images, fail closed.

Discrete realization

resolve_demag_boundary owns the resolved boundary policy, axis-specific image counts, and 1,000,000-term budget. resolve_periodic_images owns execution padding and workspace accounting: a periodic axis uses padding N, an open axis uses 2N, and the estimate includes three real buffers plus twelve complex spectral buffers. A workspace estimate above 8 GiB is rejected before allocation. CPU compute_periodic_newell_kernel_spectra owns finite Newell image spectra, while the runner consumes and validates the resolved metadata.

Implementation mapping

StudyBuilder.pbc applies the public setting; FdmPbc owns normalization, schema, and lowering; resolve_demag_boundary owns resolved counts and the image-term budget; resolve_periodic_images owns padding and workspace accounting; the runner validates the resolved metadata; and CPU FFT owns periodic spectra.

Validation

Sweep image counts at fixed grid and cell size at fixed images; record field, energy, padding, precision, and kernel identity. Confirm FDM plus periodic_airbox_k0 rejects.

Limitations

Finite images require convergence and are not an Ewald implementation. The default of 10 images per periodic axis is a resolution default, not evidence of convergence. GPU remains capability-gated.

Scientific bibliography

Source-code index

Source

Stable symbol

Evidence

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

class StudyBuilder

public fdm(...) and pbc(...) application routes

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

class FdmPbc

policy validation and IR

crates/fullmag-ir/src/execution.rs

resolve_demag_boundary

default/resolved image counts and image-term budget

crates/fullmag-ir/src/execution.rs

resolve_periodic_images

periodic padding and workspace accounting

crates/fullmag-runner/src/fdm/mod.rs

resolve_fdm_demag_boundary_for_periodicity

runtime policy resolution

crates/fullmag-engine/src/fdm/cpu/fft.rs

compute_periodic_newell_kernel_spectra

CPU periodic spectra

Scope and purpose

This page defines the public contract for periodic FDM grids. It is an authoring and implementation reference: the Python example, the serialized ProblemIR description, the implementation mapping, and the adjacent source map are the source-backed contract. A capability marked partial or not evaluated is not presented as a production guarantee.

Scientific and numerical model

The mesh or grid is a discrete approximation of the continuous domain. For a Cartesian partition, each spacing satisfies Delta_i = L_i / N_i; for a geometry-dependent FEM mesh, the requested local target is bounded by the active bulk, interface, boundary, and topology constraints. In compact form, h_target(x) = min(h_bulk(x), h_interface(x), h_boundary(x)). Length quantities use SI metres (m); counts, orders, and topology labels are dimensionless.

The equations and assumptions in the earlier physical-problem and governing-equations sections state the model-specific specialization. This section does not introduce a conversion from FEM to FDM, a hidden topology conversion, or a silent CPU fallback.

Parameters

The exact callable and argument names are the ones shown in the ## Python API section above. For this page the parameter family is cell_size, periods, and periodic-axis controls. Use the documented defaults, validation rules, and ProblemIR lowering exactly as shown; do not replace a canonical argument with an unlisted alias. Numerical lengths must be supplied in metres, and invalid positive-length, count, order, periodicity, or topology constraints must fail closed rather than being silently repaired.

Control Room workflow

In Control Room, select the engine and mesh workflow, enter the same values as the Python authoring example, inspect the planned mesh or grid report, and only then submit the run. The UI is a projection of the public contract: a missing control is not evidence that the backend accepts the option, and a visible control is not evidence that a production lane is enabled. When the page or capability register marks a field partial or not evaluated, keep the workflow explicitly bounded to the implemented path.

Diagnostics and failure semantics

A valid request must preserve the declared geometry, units, element or cell topology, and backend lane. Reject non-finite or non-positive lengths, invalid counts and orders, incompatible periodic or shared-boundary data, and unsupported topology combinations at the owning validation layer. Reports should retain requested and resolved values, source identity, and any capability gate. No diagnostic may hide a failed mesh realization by substituting another discretization.

Where this is implemented

The existing implementation-mapping and source-code-index sections identify the exact public authoring, ProblemIR, planner, realization, and runtime owners for this topic. The adjacent .source-map.json file is the machine-readable source of truth for those paths, symbols, responsibilities, backend matrix, and reviewed revision. Claims in this page must be updated together with that map when an owner moves.