--- title: Free-Tetrahedral API status: implemented doc_kind: reference audience: user owner: fullmag-public-docs --- (public-docs-python-api-meshing-fem-ferromagnet-free-tetrahedral)= # Free-Tetrahedral API (python-api-meshing-fem-ferromagnet-free-tetrahedral-python-api)= ## Python API The complete runnable example is in the numbered example section below; the exact callable fields and arguments are in the numbered API section. These values are copied from the current Python contract, not inferred from the UI. (python-api-meshing-fem-ferromagnet-free-tetrahedral-problem-statement)= (python-api-meshing-fem-ferromagnet-free-tetrahedral-governing-equations)= (python-api-meshing-fem-ferromagnet-free-tetrahedral-symbols-and-si-units)= ## Symbols and SI units All geometric lengths use $\mathrm{m}$; dimensionless selectors use $1$. (python-api-meshing-fem-ferromagnet-free-tetrahedral-assumptions-and-validity)= ## Assumptions and validity Authoring validation does not prove mesh generation or solver qualification; the realized report is authoritative. ## 1. What it is and when to use it `object.mesh(...)` is the default object meshing strategy: an unstructured tetrahedral mesh generated by Gmsh inside the object geometry, with no forced through-thickness topology. When to use it: - any magnetic object without special layering requirements, - complex-shaped geometries (imported STL/STEP, nanoflowers), - the first choice before reaching for specialized modes. When to pick something else: thin films with through-thickness control → {doc}`thin-film-tetrahedral`; exact prism layers → {doc}`swept-prism`; an external prebuilt mesh → {doc}`imported-mesh`. Impact on the simulation: `maximum_element_size` controls the accuracy/cost trade-off; refinement should respect the exchange length $l_{\mathrm{ex}}$ (section 2). ## 2. Physical and mathematical explanation This page introduces no equation of its own; it selects the discrete space for micromagnetic operators. The practical sizing rule follows from the exchange length: $$ l_{\mathrm{ex}} = \sqrt{\frac{2A}{\mu_0 M_s^2}}, $$ where $A$ — exchange stiffness ($\mathrm{J\,m^{-1}}$), $M_s$ — saturation magnetization ($\mathrm{A\,m^{-1}}$), $\mu_0$ — vacuum permeability ($\mathrm{H\,m^{-1}}$). For a correct domain-wall description, elements should not be significantly larger than $l_{\mathrm{ex}}$. | Symbol | Meaning | SI unit | |---|---|---| | $l_{\mathrm{ex}}$ | exchange length | $\mathrm{m}$ | | $A$ | exchange stiffness | $\mathrm{J\,m^{-1}}$ | | $M_s$ | saturation magnetization | $\mathrm{A\,m^{-1}}$ | | $\mu_0$ | vacuum permeability | $\mathrm{H\,m^{-1}}$ | ## 3. Example — complete Python script ```python # %% Free-tetrahedral object mesh import fullmag as fm nm = 1.0e-9 study = fm.study("free_tetrahedral_example") study.engine("fem") study.device("cpu", precision="double") study.mode("strict") study.universe(mode="manual", size=(800 * nm, 400 * nm, 300 * nm)) study.universe.mesh( minimum_element_size=8 * nm, maximum_element_size=80 * nm, maximum_element_growth_rate=1.5, grading="geometric", ) film = study.geometry(fm.Box(300 * nm, 100 * nm, 5 * nm), name="film") film.Ms = 800.0e3 # A/m film.Aex = 13.0e-12 # J/m film.alpha = 0.02 film.m = fm.texture.uniform(1.0, 0.0, 0.0) film.mesh( minimum_element_size=2.5 * nm, maximum_element_size=5 * nm, order=1, compute_quality=True, ) study.exchange() study.demag(model="airbox", variant="robin") study.build_domain_mesh() study.stages.add_relax(stage_id="equilibrium", tolT=1.0e-6) ``` ## 4. Exact API Signature: `object.mesh(**kwargs)` — `GeometryMeshHandle.__call__` (`packages/fullmag-py/src/fullmag/world.py`). The most common arguments: | Python | Type | Default | SI unit | Validation | Meaning | Backend support | ProblemIR | | --- | --- | --- | --- | --- | --- | --- | --- | | `maximum_element_size` / `hmax` | `float \| str \| None` | `None` (inherits study) | $\mathrm{m}$ | finite positive | maximum element size | FEM CPU/GPU; FDM not applicable to this mesh policy | `mesh_workflow` | | `minimum_element_size` / `hmin` | `float \| str \| None` | `None` | $\mathrm{m}$ | finite positive | minimum element size | FEM CPU/GPU; FDM not applicable to this mesh policy | `mesh_workflow` | | `order` | `int \| None` | `None` | $1$ | `>= 1` | element order | FEM CPU/GPU; FDM not applicable to this mesh policy | `mesh_workflow` | | `growth_rate` / `maximum_element_growth_rate` | `float \| None` | `None` | $1$ | positive | maximum size growth rate | FEM CPU/GPU; FDM not applicable to this mesh policy | `mesh_workflow` | | `curvature_factor`, `size_from_curvature` | `float \| int \| None` | `None` | $1$ | positive | curvature fitting | FEM CPU/GPU; FDM not applicable to this mesh policy | `mesh_workflow` | | `narrow_regions`, `narrow_region_resolution` | `int \| float \| None` | `None` | $1/\mathrm{m}$ | positive | narrow-region resolution | FEM CPU/GPU; FDM not applicable to this mesh policy | `mesh_workflow` | | `algorithm_2d`, `algorithm_3d` | `int \| None` | `None` | $1$ | Gmsh algorithm numbers | mesher algorithm selection | FEM CPU/GPU; FDM not applicable to this mesh policy | `mesh_workflow` | | `optimize`, `optimize_iterations` | `str \| int \| None` | `None` | $1$ | Gmsh optimizer name | mesh post-optimization | FEM CPU/GPU; FDM not applicable to this mesh policy | `mesh_workflow` | | `smoothing_steps` | `int \| None` | `None` | $1$ | non-negative | node smoothing | FEM CPU/GPU; FDM not applicable to this mesh policy | `mesh_workflow` | | `calibrate_for`, `size_preset`, `size_factor` | `str \| float \| None` | `None` | $1$ | preset names | calibrated size presets | FEM CPU/GPU; FDM not applicable to this mesh policy | `mesh_workflow` | | `source` | `str \| None` | `None` | $1$ | non-empty | import a prebuilt object mesh | FEM CPU/GPU; FDM not applicable to this mesh policy | `mesh_workflow` | | `compute_quality`, `per_element_quality` | `bool \| None` | `None` | $1$ | bool | quality statistics request | FEM CPU/GPU; FDM not applicable to this mesh policy | `mesh_workflow` | Advanced recipes (`PerObjectMeshRecipe`) additionally expose `mesh_strategy="free_tetrahedral"`, Gmsh algorithms, size fields (`size_field`), ordered operations, and boundary layers — see {doc}`boundary-layers` and the source index below. Failure behavior: non-positive sizes, `order < 1`, and contradictory aliases raise `ValueError` immediately, before any mesh is built. ProblemIR mapping: fields land in the canonical object recipe (`PerObjectMeshRecipe`) and then in the mesh workflow metadata. (python-api-meshing-fem-ferromagnet-free-tetrahedral-problem-ir)= ## ProblemIR The request lowers to the mesh-workflow or discretization subtree; requested intent remains distinct from the resolved mesh asset and provenance report. (python-api-meshing-fem-ferromagnet-free-tetrahedral-round-trip-and-failure-semantics)= ## Round-trip and failure semantics Requested intent is the Python policy; resolved execution is the realized mesh report. Validation errors identify the violated domain rule, and unsupported combinations fail explicitly without silent fallback. (python-api-meshing-fem-ferromagnet-free-tetrahedral-discrete-realization)= ## Discrete realization The backend consumes the realized Cartesian or finite-element asset, including topology, markers, quality, and provenance where available. ## 5. How to set it in Control Room ``` Model Explorer └── Objects └── └── Mesh → selection kind: object.mesh ``` The **Object Mesh Policy** inspector (`ObjectMeshPolicyPanel.tsx`): the *Element Size Parameters*, *Mesh Size Presets*, and *Backend Mesh Parameters* groups (Gmsh algorithms, optimizer, quality). **Apply Object Policy** writes the recipe; **Build Mesh** materializes it. Full description: {doc}`../../../../frontend/meshing/object-mesh`. ## 6. Backend support | Solver | Device | Status | Notes | |---|---|---|---| | FEM | CPU | implemented | Gmsh free-tet, full quality pipeline | | FEM | GPU | capability-gated | identical content-addressed mesh; coverage gated | | FDM | CPU/GPU | not applicable | use the FDM meshing API ({doc}`../../fdm/index`) | (python-api-meshing-fem-ferromagnet-free-tetrahedral-validation)= ## Validation Focused constructor, lowering, and mesh-report tests are the evidence boundary for this page. (python-api-meshing-fem-ferromagnet-free-tetrahedral-limitations)= ## 7. Limitations and known pitfalls - Tetrahedra do not guarantee through-thickness layers — for films with strong resolution anisotropy prefer {doc}`swept-prism`. - `maximum_element_size` is a target, not a local guarantee; realized extrema are in the build report. (python-api-meshing-fem-ferromagnet-free-tetrahedral-scientific-bibliography)= ## 8. Scientific bibliography 1. C. Geuzaine and J.-F. Remacle, “Gmsh,” *Int. J. Numer. Methods Eng.* **79**, 1309–1331 (2009). 2. A. Hubert and R. Schäfer, *Magnetic Domains*, Springer, 1998. (python-api-meshing-fem-ferromagnet-free-tetrahedral-implementation-mapping)= (python-api-meshing-fem-ferromagnet-free-tetrahedral-source-code-index)= ## 9. Source-code index | Claim | Path | Symbol | Evidence | |---|---|---|---| | `object.mesh(...)` facade | `packages/fullmag-py/src/fullmag/world.py` | `GeometryMeshHandle.__call__` / `configure` | signature and validation in code | | object recipe | `packages/fullmag-py/src/fullmag/model/discretization.py` | `PerObjectMeshRecipe` | validation tests | | size fields | `packages/fullmag-py/src/fullmag/world.py` | `GeometryMeshHandle.size_field` | method signature | ## Source-code index - Python contract source: `packages/fullmag-py/src/fullmag/model/discretization.py` and `packages/fullmag-py/src/fullmag/world.py`, where applicable. Backend realization is in the relevant `backends/fdm` or `backends/fem` lane named by the page. ### Source-map coverage | Claim | Path | Stable symbol | Responsibility | Evidence | |---|---|---|---|---| | Free-tetrahedral object policy and lowering. | `packages/fullmag-py/src/fullmag/model/discretization.py` | `class PerObjectMeshRecipe` | Free-tetrahedral object policy and lowering. | Source-map validator and focused API tests |