Run¶
The run lifecycle: the driver, the content-addressed bundle it writes per solve, and the run and result readers.
femforge.run
¶
Run lifecycle: the content-addressed bundle a Driver writes per solve and a Run opens for reading.
Modules:
-
artifacts–The run side of the built-in artifacts: rebinding a cached mesh's groups, the bundle file policy, and rehydration.
-
bundle–Read and write the
runs/<run_id>/bundle: a content-addressed run directory holding the manifest, the typed result and the pinned geometry. -
convergence–Mesh convergence: re-run one configuration at increasing refinement, then Richardson-extrapolate the quantity of interest.
-
driver–The driver: assemble one run end-to-end (identity, reuse, mesh + sif + solve, parse, bundle, publish, retention); the generators (
Mesher,Sim) stay run-ignorant. -
electrical–Per-phase electrical quantities of a current-conduction run, from the electrode flux columns in
Result.rawandboundaries.yml. -
entities–Named bodies and boundaries of a run bundle, resolved to the mesh ids the VTU's
GeometryIdscell array uses. -
fields–Fluent numpy queries over a solved VTU's fields, keyed by body names, tags, and mesh ids.
-
inspect–The discoverable face of a run bundle:
Run(sim_dir)opens typed results, named entities, components, and the VTU field query. -
kinds–Run identity and the built-in artifact kinds: the STEP a geometry builds, the Elmer mesh a config meshes, and the bundle a run leaves.
-
magnetic–Per-component magnetic quantities of a magnetostatics run, joined from the SaveScalars columns in
Result.rawandcomponents.yml. -
manifest–Run provenance: the self-describing run manifest and the git version stamp.
-
parse–Parse Elmer outputs into a typed
Result: SaveScalars columns for the numbers, the solver log for status, residual and wall time. -
purge–Post-hoc retention over existing run bundles: one bundle or a whole runs directory, dry-run by default.
-
reap–Abandoned runs: the bundles left
runningwith no live claim on them, marked so and their claims broken. -
result–The typed outcome of a solve: Elmer outputs parsed into validated, pint-typed fields.
-
retention–Run retention: which classes of bundle files leave after a run, the policy that says so, and the engine that applies it.
-
stages–Pipeline stage vocabulary: the driver's stages in execution order, plus the timed event a run records per stage.
Classes:
-
BundlePolicy–Which bundle files a published run bundle carries.
-
MeshGroupsFile–groups.json: the group records and element count a mesh artifact carries beside ElmerGrid's files. -
MeshRebindError–A cached mesh cannot be bound to the current config's domain.
-
ConvergencePoint–One rung of the refinement ladder: the refinement level, the resulting quantity, and its relative change from the previous (coarser) rung.
-
RichardsonEstimate–Richardson extrapolation of a ladder's finest three rungs, assuming q(h) = q* + C·hᵖ.
-
Driver–Runs each config through the pipeline into a
runs/<run_id>/bundle and returns its typedResult. -
Bodies–Name-keyed collection of a run's bodies.
-
Body–One named body group of a run.
-
Boundaries–Name-keyed collection of a run's boundaries, with adjacency lookups powered by the
A__Bname convention. -
Boundary–One named boundary group of a run.
-
BoundaryKind–What a boundary group separates: two bodies, a body's external shell, or its trace on the 2D symmetry axis.
-
Entities–A bundle's named bodies and boundaries.
-
FieldMesh–A solved VTU as cell-space numpy arrays with named-body selection; open one via
loadorRun.mesh(). -
FieldQuery–One field array under an immutable cell mask: filters return refined copies, terminals return numpy values.
-
Run–One run bundle (
runs/<run_id>/) opened for reading. -
SifComponent–One sif Component block with its lumped force and torque.
-
MeshSpec–Everything that decides the Elmer mesh files and their group names, and nothing that only decides the solve.
-
RunSpec–The bundle kind's spec: the config a run solved.
-
RunManifest–The self-describing record of one run.
-
ReapedRun–One run
reap_runssettled. -
MeshStats–Per-run mesh size/quality summary, recorded in the manifest so a sweep can be audited for mesh consistency.
-
Result–The typed outcome of one solve.
-
BundleEntry–One file found in a bundle, with the retention class its name falls in.
-
Cleanup–When a file class leaves the bundle; definition order is escalation order.
-
CleanupRecord–One cleanup pass over a bundle: when, by whom, under which policy, and what left.
-
CleanupReport–The outcome of applying a plan: what left (or would have, in a dry run) and what could not be removed.
-
Preset–Named retention policies, from keep-everything to removing the run directory.
-
RetentionPolicy–One
Cleanuprule per bundle file class; the default keeps everything the run cannot re-fetch. -
Stage–The driver's pipeline stages, in execution order.
-
StageEvent–One stage's timing record: created at stage start, mutated with
finished_atwhen the stage completes.
Functions:
-
bundle_files–The bundle-relative posix paths
policypublishes fromsim_dir. -
rebind_groups–Rebuild a cached mesh's groups against this config's domain, matching materials by tag and
EntityTagobjects by selector; ids stay placeholders untilreconcile_ids. -
rehydrate_bundle–Fetch every store-sourced input the manifest names back into the bundle.
-
load_manifest–Read a bundle's
manifest.jsonback into a typedRunManifest— a delegate toRunManifest.load. -
load_result–Read a bundle's
result.jsonback into a typedResult— a delegate toResult.load. -
write_atomic–Replace
pathatomically: write a.tmpsibling, thenos.replace— a reader never sees a half-written file. -
write_bundle–Write
manifest.jsonandresult.jsonintosim_dir, pin the source STEP asgeometry.stepunless the run already holds one, and return the bundle. -
write_manifest–Atomically write (or overwrite)
manifest.jsoninsim_dir(created if needed) and return its path. -
convergence_ladder–Run
base_configat each refinement level and report the quantity of interest plus its relative change between rungs. -
richardson–Richardson-extrapolate the finest three rungs of a ladder whose
scalesare mesh-size multipliers (larger is coarser) paired withvalues. -
boundary_fluxes–Elmer bc index -> integrated conductive flux (A) from the SaveScalars columns in
Result.raw. -
electrode_currents–Boundary block name -> terminal current (A), joining the flux columns against the bc-index name map.
-
phase_currents–Phase index ("0", "1", ...) -> terminal current (A): the largest-magnitude current among each phase's named electrode currents.
-
read_boundary_names–The
boundaries.ymlmap the Sim writes (<bc index>: <boundary block name>), as a dict. -
resistance–R = ΔV / I for one phase; raises on a (numerically) zero current.
-
load_entities–Read a bundle's bodies/boundaries:
entities.jsonwhen present, elsemesh.namesenriched from the manifest config, else empty. -
write_entities–Write
entities.jsonmapping each group's reconciled mesh id to its named record; call afterreconcile_ids. -
select_array–Resolve a VTU array name for a solver variable: exact (nodal), then the elemental
"<name> e", then substring — VTU names come back lowercased. -
find_runs–The bundles under
runs_dirwhose metadata matches, newest first; this reads every manifest, so preferRunIndexover thousands of bundles. -
mesh_spec–The mesh artifact spec of
config(step_key_overridewhen the driver already resolved the geometry). -
step_digest–SHA-256 of a STEP with its
FILE_NAMEheader (the export timestamp) masked; of the path string when the file is absent, so pure-logic keys stay deterministic. -
component_forces–Component name -> lumped magnetic force (N, per radian in an axisymmetric run), joining the force triples against the
components.ymlmap. -
component_torques–Component name -> lumped magnetic torque (N*m about the authored origin/axis, per radian in an axisymmetric run), joining the torque triples against the
components.ymlmap. -
eddy_current_power–The total eddy current power (W, per radian in an axisymmetric run), or None when the run exported none (static solves have no eddy losses).
-
force_triples–Column stem -> per-component force Vec3 (N, per radian in an axisymmetric run) from the SaveScalars columns in
Result.raw. -
magnetic_field_energy–The total magnetic field energy (J, per radian in an axisymmetric run), or None when the run exported none.
-
read_component_names–The
components.ymlmap the Sim writes (<component id>: <Component name>) — the same flat format asboundaries.yml. -
cache_key–Full-run identity: every result-affecting input plus
RUN_PRODUCER_VERSION; never the code commit, the machine, or the run metadata. -
git_sha–The current commit, with
-dirtyappended when the working tree has uncommitted changes; None without git or outside a repository. -
mesh_key–The mesh artifact key of
config: invariant to materials' properties, conditions, physics, and metadata. -
step_key–The solve-frame geometry identity a run and its mesh key on: the STEP artifact key of
step_spec(config). -
parse_result–Parse a finished run directory into a typed
Result, revolving force and torque to full-revolution totals under anAxisymmetricframe. -
result_vtu–The run's newest ParaView output: the
.pvtumaster when the solve was partitioned, else the newest.vtu; None when there is none. -
reap_runs–Mark every bundle under
runs_dirleftrunningwith no live claim on it asabandoned, and break every claim that went silent. -
apply_cleanup–Remove every planned path; never raises, so a path that cannot be removed lands in
report.failed. -
bundle_inventory–Every file under a bundle with the retention class its name matches; a name no class claims is filed under
RunFile.RUN_DIR, the only rule that reaches it. -
plan_cleanup–Resolve
policyagainst one bundle into the sized paths each applying rule removes; refuses a symlinked or junctioned directory.
Attributes:
-
SolverFn–A solve step that fills
sim_dirwith Elmer outputs and reports the mesh it built; injecting one replaces the gmsh and Elmer pipeline. -
GEOMETRY_IDS_ARRAY–The Int cell array
ResultOutputSolver(Save Geometry Ids) writes: each cell's mesh id, bodies and boundaries alike. -
ELMER_MESH(ArtifactKind[MeshSpec]) –ElmerGrid's mesh files plus
groups.json; produced by the driver, which owns gmsh and ElmerGrid. -
RUN_BUNDLE(ArtifactKind[RunSpec]) –A finished run bundle, keyed by
cache_keyso its store key and itsrun_idagree. -
STEP(ArtifactKind[StepSpec]) –The solve-frame STEP of a parametric geometry or an authored file, keyed by its source (
HashExcludefields left out) and the frame. -
ManifestStatus–A manifest's lifecycle status:
"running"while the pipeline executes, then the terminalRunStatus, or"abandoned"when its claim went silent first. -
RunStatus–The terminal state of a solve: completed cleanly, failed to converge, or errored out.
SolverFn
module-attribute
¶
SolverFn = Callable[[SimulationConfig, Path], MeshStats]
A solve step that fills sim_dir with Elmer outputs and reports the mesh it built; injecting one replaces the gmsh and Elmer pipeline.
GEOMETRY_IDS_ARRAY
module-attribute
¶
The Int cell array ResultOutputSolver (Save Geometry Ids) writes: each cell's mesh id, bodies and boundaries alike.
ELMER_MESH
module-attribute
¶
ELMER_MESH: ArtifactKind[MeshSpec] = ArtifactKind(name=BuiltinKind.ELMER_MESH, spec_type=MeshSpec, producer_version=MESH_PRODUCER_VERSION, required_files=(BundleFile.MESH_HEADER, BundleFile.MESH_NODES, BundleFile.MESH_ELEMENTS, BundleFile.MESH_BOUNDARY, BundleFile.MESH_NAMES, BundleFile.GROUPS))
ElmerGrid's mesh files plus groups.json; produced by the driver, which owns gmsh and ElmerGrid.
RUN_BUNDLE
module-attribute
¶
RUN_BUNDLE: ArtifactKind[RunSpec] = ArtifactKind(name=BuiltinKind.RUN_BUNDLE, spec_type=RunSpec, producer_version=RUN_PRODUCER_VERSION, required_files=(BundleFile.MANIFEST, BundleFile.RESULT), key=lambda spec: cache_key(spec.config), in_place=True)
A finished run bundle, keyed by cache_key so its store key and its run_id agree.
STEP
module-attribute
¶
STEP: ArtifactKind[StepSpec] = ArtifactKind(name=BuiltinKind.STEP, spec_type=StepSpec, producer_version=STEP_PRODUCER_VERSION, required_files=(BundleFile.GEOMETRY_STEP,), produce=_build_step)
The solve-frame STEP of a parametric geometry or an authored file, keyed by its source (HashExclude fields left out) and the frame.
ManifestStatus
module-attribute
¶
A manifest's lifecycle status: "running" while the pipeline executes, then the terminal RunStatus, or "abandoned" when its claim went silent first.
RunStatus
module-attribute
¶
RunStatus = Literal['ok', 'diverged', 'error']
The terminal state of a solve: completed cleanly, failed to converge, or errored out.
BundlePolicy
¶
Bases: StrEnum
Which bundle files a published run bundle carries.
Attributes:
MeshGroupsFile
pydantic-model
¶
Bases: BaseModel
groups.json: the group records and element count a mesh artifact carries beside ElmerGrid's files.
Config:
use_attribute_docstrings:True
Fields:
boundaries
pydantic-field
¶
boundaries: list[BoundaryGroupRecord]
The boundary group records, in mesher order.
capture
classmethod
¶
capture(physical_groups: Iterable[_BodySource], boundary_groups: Iterable[_BoundarySource], element_count: int) -> MeshGroupsFile
Record the mesher's groups.
Parameters:
-
physical_groups(Iterable[_BodySource]) –The body groups, in mesher order.
-
boundary_groups(Iterable[_BoundarySource]) –The boundary groups, in mesher order.
-
element_count(int) –Elements of the body dimension in the mesh.
Source code in src/femforge/meshing/groups.py
load
classmethod
¶
load(sim_dir: str | Path) -> MeshGroupsFile
write
¶
Write groups.json into sim_dir and return its path.
Source code in src/femforge/meshing/groups.py
MeshRebindError
¶
Bases: ArtifactError
A cached mesh cannot be bound to the current config's domain.
ConvergencePoint
pydantic-model
¶
Bases: BaseModel
One rung of the refinement ladder: the refinement level, the resulting quantity, and its relative change from the previous (coarser) rung.
Config:
arbitrary_types_allowed:Trueuse_attribute_docstrings:True
Fields:
-
refinement(float) -
quantity(Quantity) -
delta_vs_previous(float | None)
RichardsonEstimate
pydantic-model
¶
Bases: BaseModel
Richardson extrapolation of a ladder's finest three rungs, assuming q(h) = q* + C·hᵖ.
Config:
use_attribute_docstrings:True
Fields:
Driver
¶
Driver(*, runs_dir: str | Path = 'runs', code_sha: str | None = None, solver: SolverFn | None = None, mpi_processes: int = 1, backend: ExecutionBackend | None = None, mesher: MeshBackend | None = None, docker: bool | None = None, docker_image: str | None = None, retention: RetentionPolicy | None = None, artifacts: ArtifactCache | None = None, reuse: bool = True, bundle_policy: BundlePolicy = FIELDS, telemetry: str | Path | None = None)
Runs each config through the pipeline into a runs/<run_id>/ bundle and returns its typed Result.
The config alone decides a run's identity: execution settings such as the backend, the mesher, the rank count, retention and telemetry never enter it.
Parameters:
-
runs_dir(str | Path, default:'runs') –The directory each run's bundle is written under.
-
code_sha(str | None, default:None) –The code version each manifest records; None reads it from git.
-
solver(SolverFn | None, default:None) –A replacement for the staged pipeline, for tests that run without gmsh or Elmer.
-
mpi_processes(int, default:1) –The ElmerSolver rank count; more than 1 needs a partitioned backend.
-
backend(ExecutionBackend | None, default:None) –Where ElmerGrid and ElmerSolver run; None picks Docker or native Elmer from
docker,docker_imageandmpi_processes. -
mesher(MeshBackend | None, default:None) –Where gmsh meshes each STEP; None meshes in this process, and a
WorkerMeshermeshes in a child process. -
docker(bool | None, default:None) –True runs Elmer in Docker and False runs it natively; it cannot be combined with
backend. -
docker_image(str | None, default:None) –An image tag to run Elmer in instead of femforge's own image; it cannot be combined with
backend. -
retention(RetentionPolicy | None, default:None) –What leaves each bundle after its evaluation;
evaluate(retention=...)overrides it for one call. -
artifacts(ArtifactCache | None, default:None) –The cache the STEP, mesh and bundle stages read from and publish to; None keeps runs store-free.
-
reuse(bool, default:True) –Whether to return a finished bundle with the same identity instead of solving again.
-
bundle_policy(BundlePolicy, default:FIELDS) –Which bundle files a publish carries, and so which files a reused bundle must still hold.
-
telemetry(str | Path | None, default:None) –The telemetry root for each run's index row and log records; None falls back to
FEMFORGE_TELEMETRY.
Methods:
-
evaluate–Return the finished bundle for
configwhen one is reusable, else mesh + sif + solve it under a claim on its -
run_index–The index this driver records into, or None when telemetry is off — which is also what keeps polars unimported.
-
publish–The
Stage.PUBLISHdefault: commit the filesbundle_policyselects, store-sourced inputs excluded, to the artifact cache under the run identity. -
cleanup–The
Stage.CLEANUPdefault: applypolicyagainst the run's terminal status and record what left on the manifest. -
on_stage_event–Default stage-event sink: record the event on the active run's manifest and persist it (override +
super()to add behavior). -
prepare_geometry–Materialize the solve-frame STEP into the run directory (from the artifact cache when one is configured) and repoint
state.configat it. -
pre_mesh–Hook before meshing (e.g. adjust
state.configor drop extra inputs intostate.sim_dir). -
mesh–Mesh with
mesherand convert with ElmerGrid, served from the artifact cache when one is configured, then bind the groups to this config. -
post_mesh–Hook between meshing and sim construction (e.g. amend the Elmer mesh files in
state.sim_dir). -
build_sim–Populate
state.sim: the typedSimfrom the config's resolved solver stack, MPI-adjusted when partitioned. -
configure_sim–Hook to edit the typed solver stack (
state.sim.config) before the sif is generated. Prefer authoring -
write_sif–Generate the sif object graph from the typed stack and write the sif into the run directory.
-
run_solver–Partition the mesh when the solve is parallel (a partitioned backend is checked at construction), then run ElmerSolver on
backend. -
mesh_stats–The built mesh's
MeshStats: the meshed element count plus the config's size settings.
Source code in src/femforge/run/driver.py
evaluate
¶
evaluate(config: SimulationConfig, *, retention: RetentionPolicy | None = None) -> Result
Return the finished bundle for config when one is reusable, else mesh + sif + solve it under a claim on its
run directory, parse the result, write and publish the bundle, then apply the retention policy.
The run directory is bundle_name(cache_key) — a memorable name derived from the content hash — so
re-evaluating identical inputs still targets the same bundle. retention overrides the driver's policy for this call.
Source code in src/femforge/run/driver.py
run_index
¶
run_index() -> RunIndex | None
The index this driver records into, or None when telemetry is off — which is also what keeps polars unimported.
Source code in src/femforge/run/driver.py
publish
¶
publish(manifest: RunManifest, sim_dir: Path, config: SimulationConfig, result: Result) -> ArtifactRef
The Stage.PUBLISH default: commit the files bundle_policy selects, store-sourced inputs excluded, to the artifact cache under the run identity.
The store keeps the manifest as it stands on disk at publish time.
Parameters:
-
manifest(RunManifest) –The run's manifest, which records the published reference.
-
sim_dir(Path) –The run directory the files come from.
-
config(SimulationConfig) –The config whose identity keys the published bundle.
-
result(Result) –The parsed result, whose Elmer version the store records.
Source code in src/femforge/run/driver.py
cleanup
¶
cleanup(manifest: RunManifest, sim_dir: Path, policy: RetentionPolicy) -> CleanupReport
The Stage.CLEANUP default: apply policy against the run's terminal status and record what left on the manifest.
Override it to push the bundle elsewhere first, then call super().
Parameters:
-
manifest(RunManifest) –The run's manifest, which records the cleanup.
-
sim_dir(Path) –The run directory to clean.
-
policy(RetentionPolicy) –The retention policy to apply.
Source code in src/femforge/run/driver.py
on_stage_event
¶
on_stage_event(event: StageEvent) -> None
Default stage-event sink: record the event on the active run's manifest and persist it (override + super() to add behavior).
Source code in src/femforge/run/driver.py
prepare_geometry
¶
Materialize the solve-frame STEP into the run directory (from the artifact cache when one is configured) and repoint state.config at it.
Source code in src/femforge/run/driver.py
pre_mesh
¶
mesh
¶
Mesh with mesher and convert with ElmerGrid, served from the artifact cache when one is configured, then bind the groups to this config.
Source code in src/femforge/run/driver.py
post_mesh
¶
build_sim
¶
Populate state.sim: the typed Sim from the config's resolved solver stack, MPI-adjusted when partitioned.
Source code in src/femforge/run/driver.py
configure_sim
¶
Hook to edit the typed solver stack (state.sim.config) before the sif is generated. Prefer authoring
config.physics.overrides instead — edits made here happen after the run identity is computed.
Source code in src/femforge/run/driver.py
write_sif
¶
Generate the sif object graph from the typed stack and write the sif into the run directory.
Source code in src/femforge/run/driver.py
run_solver
¶
Partition the mesh when the solve is parallel (a partitioned backend is checked at construction), then run ElmerSolver on backend.
Source code in src/femforge/run/driver.py
mesh_stats
¶
mesh_stats(state: SolveState) -> MeshStats
The built mesh's MeshStats: the meshed element count plus the config's size settings.
Source code in src/femforge/run/driver.py
Bodies
¶
Name-keyed collection of a run's bodies.
Methods:
-
get–The body by exact name, or None.
-
with_material–Every body whose material tag matches (case-insensitive).
-
with_tag–Every body whose selector tags carry
key=value.
Source code in src/femforge/run/entities.py
Body
dataclass
¶
Body(name: str, mesh_id: int, material: str | None = None, tags: Mapping[str, str] = dict[str, str]())
One named body group of a run.
Attributes:
-
name(str) –The body group's name, shared by the mesh, the sif and
entities.json. -
mesh_id(int) –The body's
GeometryIdsvalue in the VTU. -
material(str | None) –The material tag the body was grouped by; None when unknown.
-
tags(Mapping[str, str]) –The selector tags the body was grouped by, merged into one mapping.
Boundaries
¶
Name-keyed collection of a run's boundaries, with adjacency lookups powered by the A__B name convention.
Methods:
-
get–The boundary by exact name, or None.
-
between–The interface boundary between two bodies, whichever order the mesher named it.
-
external–The body's external shell boundary (
<BODY>__EXT). -
axis–The body's symmetry-axis boundary (
<BODY>__AXIS), or None when it has none. -
of_body–Every boundary bordering the body.
Source code in src/femforge/run/entities.py
get
¶
between
¶
The interface boundary between two bodies, whichever order the mesher named it.
Source code in src/femforge/run/entities.py
external
¶
axis
¶
The body's symmetry-axis boundary (<BODY>__AXIS), or None when it has none.
of_body
¶
Boundary
dataclass
¶
Boundary(name: str, mesh_id: int, bodies: tuple[str, ...], kind: BoundaryKind, sif_index: int | None = None)
One named boundary group of a run.
Attributes:
-
name(str) –The boundary group's name, such as
A__BorA__EXT. -
mesh_id(int) –The boundary's
GeometryIdsvalue in the VTU. -
bodies(tuple[str, ...]) –The names of the bodies the boundary borders.
-
kind(BoundaryKind) –What the boundary separates.
-
sif_index(int | None) –The boundary's Boundary Condition block number in the sif; None when no condition produced a block.
BoundaryKind
¶
Bases: StrEnum
What a boundary group separates: two bodies, a body's external shell, or its trace on the 2D symmetry axis.
Attributes:
Entities
dataclass
¶
Entities(bodies: Bodies, boundaries: Boundaries)
A bundle's named bodies and boundaries.
Attributes:
-
bodies(Bodies) –The named bodies.
-
boundaries(Boundaries) –The named boundaries.
FieldMesh
¶
FieldMesh(*, arrays: Mapping[str, FloatArray], measure: FloatArray, geometry_ids: IntArray | None = None, centers: FloatArray | None = None, bodies: Bodies | None = None, grid: UnstructuredGrid | None = None)
A solved VTU as cell-space numpy arrays with named-body selection; open one via load or Run.mesh().
Parameters:
-
arrays(Mapping[str, FloatArray]) –Field array name -> per-cell values.
-
measure(FloatArray) –Per-cell measure: volume in 3D, area in 2D.
-
geometry_ids(IntArray | None, default:None) –Per-cell
GeometryIdsmesh ids; None when the VTU carries none. -
centers(FloatArray | None, default:None) –Per-cell center coordinates; None disables position filters and revolved integrals.
-
bodies(Bodies | None, default:None) –The run's named bodies; None disables selection by body, material or tag.
-
grid(UnstructuredGrid | None, default:None) –The source pyvista grid; None disables extracting cells for plotting.
Methods:
-
load–Read the bundle's newest VTU (via
result_vtu), attaching body names from the bundle's sidecars when not given. -
from_grid–Extract every field array to cell space (nodal ones projected once), the cell measure, GeometryIds, and cell centers.
-
get–Start a query over one field array; all cells are selected until filtered (boundary overlay cells included).
-
extract_cells–The masked cells as a pyvista subgrid (for plotting); requires construction from a live grid.
Attributes:
-
array_names(list[str]) –Every available field array name.
Source code in src/femforge/run/fields.py
load
classmethod
¶
Read the bundle's newest VTU (via result_vtu), attaching body names from the bundle's sidecars when not given.
Source code in src/femforge/run/fields.py
from_grid
classmethod
¶
Extract every field array to cell space (nodal ones projected once), the cell measure, GeometryIds, and cell centers.
Source code in src/femforge/run/fields.py
get
¶
get(variable: ElmerVariable | str) -> FieldQuery
Start a query over one field array; all cells are selected until filtered (boundary overlay cells included).
Source code in src/femforge/run/fields.py
extract_cells
¶
The masked cells as a pyvista subgrid (for plotting); requires construction from a live grid.
Source code in src/femforge/run/fields.py
FieldQuery
¶
One field array under an immutable cell mask: filters return refined copies, terminals return numpy values.
Parameters:
-
mesh(FieldMesh) –The field mesh the array belongs to.
-
name(str) –The VTU array name.
-
values(FloatArray) –The array's per-cell values over the full grid.
-
mask(BoolArray) –One flag per cell of the full grid; True keeps the cell.
Methods:
-
where_body–Keep the named bodies' own cells (boundary overlay cells excluded).
-
where_material–Keep the cells of every body with this material tag (case-insensitive).
-
where_tag–Keep the cells of every body tagged
key=value. -
where_ids–Keep cells whose
GeometryIdsvalue is one ofids— raw mesh ids, so boundary cells are reachable too. -
where_mask–AND an arbitrary cell mask into the selection (one flag per cell of the full grid).
-
where_pos–Keep cells whose center lies inside the inclusive per-axis
(min, max)bounds. -
magnitude–A scalar query of per-cell |value|: the row norm of a vector field, the absolute value of a scalar one.
-
sum–Plain sum of the selected values: a float for scalars, a per-component vector otherwise.
-
max–Component-wise maximum over the selection; raises when nothing matched.
-
min–Component-wise minimum over the selection; raises when nothing matched.
-
mean–Measure-weighted mean over the selection (so cell size doesn't bias it; boundary overlay cells weigh 0).
-
integrate–∫ value · dV over the selection (in a 2D model: the plane-slice ∫ value · dA — see
integrate_revolvedfor the axisymmetric volume integral). -
integrate_revolved–∫ value · 2π·r dA over a 2D axisymmetric selection — the full-revolution volume integral, with r the radial (x) cell-center coordinate.
-
total_measure–The selection's total volume (3D) or area (2D).
-
cells–The selected cells as a pyvista subgrid, for plotting.
Attributes:
-
values(FloatArray) –The selected cells' values, in cell order.
-
measures(FloatArray) –The selected cells' measure (volume in 3D, area in 2D); boundary overlay cells measure 0.
-
cell_indices(IntArray) –The selected cells' indices into the full grid.
Source code in src/femforge/run/fields.py
measures
property
¶
The selected cells' measure (volume in 3D, area in 2D); boundary overlay cells measure 0.
where_body
¶
where_body(*bodies: Body | str) -> FieldQuery
Keep the named bodies' own cells (boundary overlay cells excluded).
Source code in src/femforge/run/fields.py
where_material
¶
where_material(tag: str) -> FieldQuery
Keep the cells of every body with this material tag (case-insensitive).
Source code in src/femforge/run/fields.py
where_tag
¶
where_tag(key: TagKey | str, value: str) -> FieldQuery
Keep the cells of every body tagged key=value.
Source code in src/femforge/run/fields.py
where_ids
¶
where_ids(ids: Iterable[int]) -> FieldQuery
Keep cells whose GeometryIds value is one of ids — raw mesh ids, so boundary cells are reachable too.
where_mask
¶
where_mask(mask: BoolArray) -> FieldQuery
AND an arbitrary cell mask into the selection (one flag per cell of the full grid).
Source code in src/femforge/run/fields.py
where_pos
¶
where_pos(x: Bounds | None = None, y: Bounds | None = None, z: Bounds | None = None) -> FieldQuery
Keep cells whose center lies inside the inclusive per-axis (min, max) bounds.
Parameters:
-
x(Bounds | None, default:None) –The
(min, max)bounds on x; None leaves x unbounded, and a None bound leaves its side open. -
y(Bounds | None, default:None) –The bounds on y, as for
x. -
z(Bounds | None, default:None) –The bounds on z, as for
x.
Source code in src/femforge/run/fields.py
magnitude
¶
magnitude() -> FieldQuery
A scalar query of per-cell |value|: the row norm of a vector field, the absolute value of a scalar one.
Source code in src/femforge/run/fields.py
sum
¶
sum() -> float | FloatArray
Plain sum of the selected values: a float for scalars, a per-component vector otherwise.
max
¶
max() -> float | FloatArray
Component-wise maximum over the selection; raises when nothing matched.
Source code in src/femforge/run/fields.py
min
¶
min() -> float | FloatArray
Component-wise minimum over the selection; raises when nothing matched.
Source code in src/femforge/run/fields.py
mean
¶
mean() -> float | FloatArray
Measure-weighted mean over the selection (so cell size doesn't bias it; boundary overlay cells weigh 0).
Source code in src/femforge/run/fields.py
integrate
¶
integrate() -> float | FloatArray
∫ value · dV over the selection (in a 2D model: the plane-slice ∫ value · dA — see integrate_revolved for the axisymmetric volume integral).
Source code in src/femforge/run/fields.py
integrate_revolved
¶
integrate_revolved() -> float | FloatArray
∫ value · 2π·r dA over a 2D axisymmetric selection — the full-revolution volume integral, with r the radial (x) cell-center coordinate.
Source code in src/femforge/run/fields.py
Run
¶
One run bundle (runs/<run_id>/) opened for reading.
Methods:
-
from_result–Open the bundle a Result was loaded from or written to (the driver and
Result.loadstamprun_dir). -
latest–The most recently created bundle under a runs directory (by manifest
created_at, then mtime). -
purged–The newest cleanup pass that removed
file_class(or the whole run directory), else None. -
mesh–The solved VTU as a fluent field query, body names attached (lazy pyvista import; cached per Run); names the retention pass when the VTU was purged.
Attributes:
-
meta(RunMeta) –The run's searchable metadata (description + tags), as recorded in the manifest's config.
-
result(Result) –The typed result:
result.jsonwhen written, else parsed fresh from the Elmer outputs in the bundle. -
manifest(RunManifest) –The run's provenance manifest.
-
cleanups(list[CleanupRecord]) –Every retention pass recorded on the manifest (empty when the manifest is missing or unreadable).
-
entities(Entities) –Named bodies and boundaries from the richest available source (entities.json, else enriched mesh.names).
-
bodies(Bodies) –The run's named bodies (
mesh_id== the VTU'sGeometryIdsvalues). -
boundaries(Boundaries) –The run's named boundaries, with
between/external/axislookups. -
components(list[SifComponent]) –Every sif Component with its lumped force/torque, joined from
components.ymland the result. -
component_forces(dict[str, VectorQuantity]) –Lumped magnetic force (N) per Component name.
-
component_torques(dict[str, VectorQuantity]) –Lumped magnetic torque (N·m) per Component name.
-
electrode_currents(dict[str, float]) –Terminal current (A) per named electrode boundary, from a conduction solve's flux columns.
-
phase_currents(dict[str, float]) –Terminal current (A) per phase index ("0", "1", ...), from the named electrode currents.
-
vtu_path(Path | None) –The run's ParaView output (the partitioned master when one exists), or None when the solve wrote none.
Source code in src/femforge/run/inspect.py
meta
property
¶
meta: RunMeta
The run's searchable metadata (description + tags), as recorded in the manifest's config.
result
cached
property
¶
result: Result
The typed result: result.json when written, else parsed fresh from the Elmer outputs in the bundle.
cleanups
property
¶
cleanups: list[CleanupRecord]
Every retention pass recorded on the manifest (empty when the manifest is missing or unreadable).
entities
cached
property
¶
entities: Entities
Named bodies and boundaries from the richest available source (entities.json, else enriched mesh.names).
boundaries
property
¶
boundaries: Boundaries
The run's named boundaries, with between/external/axis lookups.
components
cached
property
¶
components: list[SifComponent]
Every sif Component with its lumped force/torque, joined from components.yml and the result.
component_forces
property
¶
component_forces: dict[str, VectorQuantity]
Lumped magnetic force (N) per Component name.
component_torques
property
¶
component_torques: dict[str, VectorQuantity]
Lumped magnetic torque (N·m) per Component name.
electrode_currents
property
¶
Terminal current (A) per named electrode boundary, from a conduction solve's flux columns.
phase_currents
property
¶
Terminal current (A) per phase index ("0", "1", ...), from the named electrode currents.
vtu_path
property
¶
vtu_path: Path | None
The run's ParaView output (the partitioned master when one exists), or None when the solve wrote none.
from_result
classmethod
¶
Open the bundle a Result was loaded from or written to (the driver and Result.load stamp run_dir).
Source code in src/femforge/run/inspect.py
latest
classmethod
¶
The most recently created bundle under a runs directory (by manifest created_at, then mtime).
Source code in src/femforge/run/inspect.py
purged
¶
purged(file_class: RunFile) -> CleanupRecord | None
The newest cleanup pass that removed file_class (or the whole run directory), else None.
Source code in src/femforge/run/inspect.py
mesh
¶
mesh() -> FieldMesh
The solved VTU as a fluent field query, body names attached (lazy pyvista import; cached per Run); names the retention pass when the VTU was purged.
Source code in src/femforge/run/inspect.py
SifComponent
dataclass
¶
SifComponent(name: str, sif_index: int, force: VectorQuantity | None = None, torque: VectorQuantity | None = None)
One sif Component block with its lumped force and torque.
Attributes:
-
name(str) –The Component name, as
components.ymlrecords it. -
sif_index(int) –The Component block number in the sif.
-
force(VectorQuantity | None) –F⃗[N]: Lumped magnetic force on the Component; None when the solve exported none. -
torque(VectorQuantity | None) –M⃗[N·m]: Lumped magnetic torque on the Component; None when the solve exported none.
force
class-attribute
instance-attribute
¶
force: VectorQuantity | None = None
F⃗ [N]: Lumped magnetic force on the Component; None when the solve exported none.
torque
class-attribute
instance-attribute
¶
torque: VectorQuantity | None = None
M⃗ [N·m]: Lumped magnetic torque on the Component; None when the solve exported none.
MeshSpec
pydantic-model
¶
Bases: BaseModel
Everything that decides the Elmer mesh files and their group names, and nothing that only decides the solve.
Config:
use_attribute_docstrings:True
Fields:
-
step_key(str) -
model_dim(Literal[2, 3]) -
global_mesh_size(float) -
gmsh_options(GmshOptions) -
deterministic(bool) -
tags(list[TagSelectorSpec]) -
materials(list[str])
model_dim
pydantic-field
¶
model_dim: Literal[2, 3]
Body dimension of the STEP, from the frame: 2D cross-section or 3D solids.
gmsh_options
pydantic-field
¶
gmsh_options: GmshOptions
The gmsh knobs (thread count and terminal output are HashExclude and drop out).
deterministic
pydantic-field
¶
deterministic: bool
Whether meshing was pinned to one thread for reproducibility.
tags
pydantic-field
¶
tags: list[TagSelectorSpec]
The domain's tags in domain order (an unnamed body's group name concatenates tag names in that order).
RunSpec
pydantic-model
¶
Bases: BaseModel
The bundle kind's spec: the config a run solved.
Config:
arbitrary_types_allowed:Trueuse_attribute_docstrings:True
Fields:
RunManifest
pydantic-model
¶
Bases: BaseModel
The self-describing record of one run.
Config:
arbitrary_types_allowed:Trueuse_attribute_docstrings:True
Fields:
-
run_id(str) -
cache_key(str) -
created_at(datetime) -
git_sha(str | None) -
elmer_version(str | None) -
config(SimulationConfig) -
physics(Physics) -
physics_config(PhysicsConfig) -
mesh_key(str) -
mesh_name(str) -
mesh_stats(MeshStats | None) -
status(ManifestStatus) -
stage_history(list[StageEvent]) -
artifacts(list[ArtifactRef]) -
published(ArtifactRef | None) -
cleanups(list[CleanupRecord]) -
notes(str)
Validators:
-
_derive_mesh_name
run_id
pydantic-field
¶
run_id: str
The bundle directory name: <adjective>-<noun>-<hash8> derived from cache_key.
cache_key
pydantic-field
¶
cache_key: str
The full content hash of the result-affecting inputs; run_id is its derived name.
created_at
pydantic-field
¶
created_at: datetime
When this run was assembled (UTC). Provenance only — never feeds run_id.
git_sha
pydantic-field
¶
git_sha: str | None = None
Code version that produced the run (-dirty when uncommitted changes were present). Provenance only — never feeds run_id.
elmer_version
pydantic-field
¶
elmer_version: str | None = None
ElmerSolver version parsed from the log, if available.
config
pydantic-field
¶
config: SimulationConfig
The full typed input that drove both the mesh and the sif.
physics_config
pydantic-field
¶
physics_config: PhysicsConfig
The resolved solver stack the run solved with (preset or authored overrides).
mesh_key
pydantic-field
¶
mesh_key: str
The mesh artifact key (geometry, mesh settings, body grouping).
mesh_name
pydantic-field
¶
mesh_name: str = ''
The mesh artifact's store directory name; always derived from mesh_key, never read from input.
mesh_stats
pydantic-field
¶
mesh_stats: MeshStats | None = None
Mesh size/quality summary for consistency auditing.
status
pydantic-field
¶
status: ManifestStatus
Lifecycle status: "running" while the pipeline executes, then the terminal solve status (mirrors Result.status), or "abandoned" when its claim went silent first.
stage_history
pydantic-field
¶
stage_history: list[StageEvent]
Per-stage start/finish timeline, appended as the pipeline runs.
artifacts
pydantic-field
¶
artifacts: list[ArtifactRef]
Store-sourced inputs this run consumed (STEP, mesh): kind, key, origin, and the bundle files they materialized — enough to re-hydrate the directory and for retention to know what is re-fetchable.
published
pydantic-field
¶
published: ArtifactRef | None = None
The bundle's own store entry (kind run_bundle, key == cache_key, the files its policy included); None when never published.
cleanups
pydantic-field
¶
cleanups: list[CleanupRecord]
Every retention pass applied to this bundle (the driver's cleanup stage, then any post-hoc purge), oldest first.
current_stage
property
¶
current_stage: Stage | None
The stage currently running — the first event without a finish time — or None when idle/finished; a crashed stage stays current through cleanup.
cached_inputs
¶
Bundle-relative paths the artifact store can re-fetch, so retention may drop them freely.
load
classmethod
¶
Load a bundle's manifest.json (pass the bundle directory or the file itself).
Source code in src/femforge/run/manifest.py
build
classmethod
¶
build(config: SimulationConfig, *, status: ManifestStatus, run_id: str | None = None, mesh_stats: MeshStats | None = None, code_sha: str | None = None, elmer_version: str | None = None, created_at: datetime | None = None, notes: str = '') -> 'RunManifest'
Assemble the manifest of config: its cache_key and mesh_key, and the physics and solver stack the config solves.
Parameters:
-
config(SimulationConfig) –The run's full typed input.
-
status(ManifestStatus) –The manifest's lifecycle status.
-
run_id(str | None, default:None) –The bundle name to record verbatim; None derives it from the cache key.
-
mesh_stats(MeshStats | None, default:None) –The mesh size summary, when known.
-
code_sha(str | None, default:None) –The producing commit, stored as the manifest's
git_sha. -
elmer_version(str | None, default:None) –The ElmerSolver version, when known.
-
created_at(datetime | None, default:None) –When the run was assembled; None takes the current UTC time.
-
notes(str, default:'') –A free-form provenance note.
Source code in src/femforge/run/manifest.py
ReapedRun
dataclass
¶
ReapedRun(run_id: str, sim_dir: Path, owner: LockOwner | None, status: ManifestStatus | None)
One run reap_runs settled.
Attributes:
-
run_id(str) –The run's bundle name.
-
sim_dir(Path) –The run's bundle directory.
-
owner(LockOwner | None) –Who held the run's claim and when it last beat; None when nobody did.
-
status(ManifestStatus | None) –The status the run's bundle carries now; None without a readable manifest.
owner
instance-attribute
¶
owner: LockOwner | None
Who held the run's claim and when it last beat; None when nobody did.
status
instance-attribute
¶
status: ManifestStatus | None
The status the run's bundle carries now; None without a readable manifest.
MeshStats
pydantic-model
¶
Bases: BaseModel
Per-run mesh size/quality summary, recorded in the manifest so a sweep can be audited for mesh consistency.
Config:
use_attribute_docstrings:True
Fields:
Result
pydantic-model
¶
Bases: BaseModel
The typed outcome of one solve.
Quantities stay pint-typed; they are stripped to floats only at the analysis boundary (Study.to_dataframe).
Config:
arbitrary_types_allowed:Trueuse_attribute_docstrings:Trueextra:forbid
Fields:
-
status(RunStatus) -
run_id(str | None) -
run_dir(Path | None) -
force(Force | None) -
torque(Torque | None) -
flux_density_max(FluxDensity | None) -
temperature_max(Temperature | None) -
residual(float | None) -
wall_time(float | None) -
elmer_version(str | None) -
frame(Frame) -
component_forces(dict[str, Force]) -
component_torques(dict[str, Torque]) -
raw(dict[str, float])
run_id
pydantic-field
¶
run_id: str | None = None
The run's identity (== the manifest's run_id and the bundle directory name — the memorable name derived
from the cache key); the driver stamps it after parsing, so a bare parse (no run lifecycle) leaves it None.
run_dir
pydantic-field
¶
run_dir: Path | None = None
The bundle directory this result lives in, stamped by the driver and load_result; never serialized, and None once retention removed the directory.
force
pydantic-field
¶
F⃗ [N]: Net force on the moving array, as a vector pint quantity.
torque
pydantic-field
¶
M⃗ [N·m]: Net torque on the moving array, as a vector pint quantity.
flux_density_max
pydantic-field
¶
|B|_max [T]: Peak flux density magnitude in the domain.
temperature_max
pydantic-field
¶
T_max [K]: Peak temperature in the domain, from the thermal or coupled joule-heating solve — the max-current search observable.
residual
pydantic-field
¶
residual: float | None = None
Δ_rel [-]: Final linear/nonlinear relative change reported by the solver.
elmer_version
pydantic-field
¶
elmer_version: str | None = None
ElmerSolver version parsed from the log, if present.
frame
pydantic-field
¶
The run's solve frame. Every vector stays in solve coordinates; under Axisymmetric the typed force/torque fields
are full-revolution totals with the radial component zeroed (zero net by symmetry), while raw keeps Elmer's per-radian columns.
component_forces
pydantic-field
¶
F⃗ [N]: Lumped magnetic force on each force-carrying sif Component, keyed by its components.yml name.
component_torques
pydantic-field
¶
M⃗ [N·m]: Lumped magnetic torque (about the authored origin/axis) on each sif Component, keyed by its components.yml name.
raw
pydantic-field
¶
[?]: Escape hatch for un-modelled scalars the parser found but Result doesn't type yet, in whatever unit Elmer printed them.
load
classmethod
¶
Load a bundle's result.json (pass the bundle directory or the file itself), stamping run_dir with where it was read from.
Source code in src/femforge/run/result.py
axial_force
¶
F_ax [N]: Component body's force along the authored axis; an axisymmetric run defaults to its symmetry axis.
Source code in src/femforge/run/result.py
BundleEntry
dataclass
¶
One file found in a bundle, with the retention class its name falls in.
Attributes:
-
relative(str) –Bundle-relative posix path.
-
size(int) –File size in bytes.
-
file_class(RunFile) –The retention class the file's name falls in.
Cleanup
¶
Bases: StrEnum
When a file class leaves the bundle; definition order is escalation order.
Methods:
-
applies–Whether this rule removes its files for a run that ended in
status(ON_SUCCESSmeansokonly). -
escalate–The stricter of two rules.
Attributes:
-
NEVER–Keep the files.
-
ON_SUCCESS–Remove the files when the run ended
ok. -
ALWAYS–Remove the files whatever the run's status.
ON_SUCCESS
class-attribute
instance-attribute
¶
Remove the files when the run ended ok.
ALWAYS
class-attribute
instance-attribute
¶
Remove the files whatever the run's status.
applies
¶
applies(status: ManifestStatus) -> bool
Whether this rule removes its files for a run that ended in status (ON_SUCCESS means ok only).
Source code in src/femforge/run/retention.py
escalate
¶
CleanupRecord
pydantic-model
¶
Bases: BaseModel
One cleanup pass over a bundle: when, by whom, under which policy, and what left.
Config:
use_attribute_docstrings:True
Fields:
-
applied_at(datetime) -
trigger(CleanupTrigger) -
status(ManifestStatus) -
policy(RetentionPolicy) -
removed(list[RemovedFile])
status
pydantic-field
¶
status: ManifestStatus
The run status the ON_SUCCESS rules were resolved against.
removed
pydantic-field
¶
removed: list[RemovedFile]
Every path that left, with its class and the rule that removed it.
CleanupReport
dataclass
¶
CleanupReport(plan: CleanupPlan, removed: list[RemovedFile] = list(), failed: list[tuple[str, str]] = list(), dry_run: bool = False)
The outcome of applying a plan: what left (or would have, in a dry run) and what could not be removed.
Attributes:
-
plan(CleanupPlan) –The plan that was applied.
-
removed(list[RemovedFile]) –Every path that left, or would have in a dry run.
-
failed(list[tuple[str, str]]) –The
(path, error)pairs of the paths that could not be removed. -
dry_run(bool) –Whether the pass only reported, removing nothing.
-
bytes_freed(int) –Total bytes removed, or that a dry run would remove.
removed
class-attribute
instance-attribute
¶
Every path that left, or would have in a dry run.
failed
class-attribute
instance-attribute
¶
The (path, error) pairs of the paths that could not be removed.
Preset
¶
Bases: StrEnum
Named retention policies, from keep-everything to removing the run directory.
Attributes:
-
DEFAULT–Keep everything the run cannot re-fetch; drop store-sourced inputs.
-
KEEP_ALL–Keep everything, store-sourced inputs included.
-
LEAN–Drop the regenerable meshes after a successful run.
-
MINIMAL–Lean plus the field output after a successful run.
-
NUKE–Remove the run directory whatever happened.
DEFAULT
class-attribute
instance-attribute
¶
Keep everything the run cannot re-fetch; drop store-sourced inputs.
KEEP_ALL
class-attribute
instance-attribute
¶
Keep everything, store-sourced inputs included.
LEAN
class-attribute
instance-attribute
¶
Drop the regenerable meshes after a successful run.
MINIMAL
class-attribute
instance-attribute
¶
Lean plus the field output after a successful run.
RetentionPolicy
pydantic-model
¶
Bases: ConfigArea
One Cleanup rule per bundle file class; the default keeps everything the run cannot re-fetch.
Fields:
-
geometry(Cleanup) -
gmsh_mesh(Cleanup) -
elmer_mesh(Cleanup) -
partitioning(Cleanup) -
sif(Cleanup) -
fields(Cleanup) -
scalars(Cleanup) -
logs(Cleanup) -
sidecars(Cleanup) -
run_dir(Cleanup) -
cached_inputs(Cleanup)
geometry
pydantic-field
¶
The geometry.step copy pinned into the bundle.
gmsh_mesh
pydantic-field
¶
The gmsh .msh (only in the bundle for a parametric geometry).
elmer_mesh
pydantic-field
¶
ElmerGrid's mesh.header/nodes/elements/boundary.
partitioning
pydantic-field
¶
The partitioning.<n>/ directory and its log from a parallel solve.
fields
pydantic-field
¶
The VTU/PVTU field output, master and per-rank pieces together.
scalars
pydantic-field
¶
SaveScalars .dat exports and their .names sidecars.
logs
pydantic-field
¶
ElmerGrid/ElmerSolver logs, convergence.jsonl, run.log.
sidecars
pydantic-field
¶
entities.json, boundaries.yml, components.yml, mesh.names, entities.sif.
run_dir
pydantic-field
¶
The whole bundle, manifest included; when it applies nothing else matters.
cached_inputs
pydantic-field
¶
Escalation for files the artifact store can re-fetch (manifest.artifacts); the stricter of this and the class rule wins.
rules
¶
The (file class, rule) pairs, read off the Map() metadata.
Source code in src/femforge/run/retention.py
default
classmethod
¶
default() -> RetentionPolicy
keep_all
classmethod
¶
keep_all() -> RetentionPolicy
minimal
classmethod
¶
minimal() -> RetentionPolicy
Lean plus the field output: keep only what re-reading the numbers needs.
nuke
classmethod
¶
nuke() -> RetentionPolicy
Remove the run directory whatever happened (throwaway evaluations, bundles already pushed elsewhere).
Source code in src/femforge/run/retention.py
from_preset
classmethod
¶
from_preset(preset: Preset) -> RetentionPolicy
The policy a preset names.
Source code in src/femforge/run/retention.py
Stage
¶
Bases: StrEnum
The driver's pipeline stages, in execution order.
Attributes:
-
PREPARE_GEOMETRY–Build or fetch the solve-frame STEP.
-
PRE_MESH–A hook before meshing.
-
MESH–Mesh the STEP and convert it with ElmerGrid, or fetch the cached mesh.
-
POST_MESH–A hook between meshing and building the sim.
-
BUILD_SIM–Build the typed sim from the resolved solver stack.
-
CONFIGURE_SIM–A hook to edit the solver stack before the sif is written.
-
WRITE_SIF–Write the sif into the run directory.
-
RUN_SOLVER–Run ElmerSolver, partitioning the mesh first for a parallel solve.
-
MESH_STATS–Record the mesh size summary.
-
PUBLISH–Commit the bundle to the artifact cache.
-
CLEANUP–Apply the retention policy.
PREPARE_GEOMETRY
class-attribute
instance-attribute
¶
Build or fetch the solve-frame STEP.
MESH
class-attribute
instance-attribute
¶
Mesh the STEP and convert it with ElmerGrid, or fetch the cached mesh.
POST_MESH
class-attribute
instance-attribute
¶
A hook between meshing and building the sim.
BUILD_SIM
class-attribute
instance-attribute
¶
Build the typed sim from the resolved solver stack.
CONFIGURE_SIM
class-attribute
instance-attribute
¶
A hook to edit the solver stack before the sif is written.
WRITE_SIF
class-attribute
instance-attribute
¶
Write the sif into the run directory.
RUN_SOLVER
class-attribute
instance-attribute
¶
Run ElmerSolver, partitioning the mesh first for a parallel solve.
MESH_STATS
class-attribute
instance-attribute
¶
Record the mesh size summary.
PUBLISH
class-attribute
instance-attribute
¶
Commit the bundle to the artifact cache.
StageEvent
pydantic-model
¶
Bases: BaseModel
One stage's timing record: created at stage start, mutated with finished_at when the stage completes.
Config:
use_attribute_docstrings:True
Fields:
-
stage(Stage) -
started_at(datetime) -
finished_at(datetime | None)
bundle_files
¶
bundle_files(sim_dir: str | Path, policy: BundlePolicy, *, exclude: Iterable[str] = ()) -> list[str]
The bundle-relative posix paths policy publishes from sim_dir.
Parameters:
-
sim_dir(str | Path) –The run bundle directory.
-
policy(BundlePolicy) –Which bundle files to publish.
-
exclude(Iterable[str], default:()) –Bundle-relative paths to leave out, such as the store-sourced inputs.
Source code in src/femforge/run/artifacts.py
rebind_groups
¶
rebind_groups(groups: MeshGroupsFile, domain: DomainConfig) -> tuple[list[PhysicalGroup], list[BoundaryGroup]]
Rebuild a cached mesh's groups against this config's domain, matching materials by tag and EntityTag objects by selector; ids stay placeholders until reconcile_ids.
Source code in src/femforge/run/artifacts.py
rehydrate_bundle
¶
rehydrate_bundle(sim_dir: str | Path, cache: ArtifactCache) -> list[ArtifactHandle[StepSpec] | ArtifactHandle[MeshSpec]]
Fetch every store-sourced input the manifest names back into the bundle.
Source code in src/femforge/run/artifacts.py
load_manifest
¶
load_manifest(sim_dir: str | Path) -> RunManifest
Read a bundle's manifest.json back into a typed RunManifest — a delegate to RunManifest.load.
load_result
¶
Read a bundle's result.json back into a typed Result — a delegate to Result.load.
write_atomic
¶
Replace path atomically: write a .tmp sibling, then os.replace — a reader never sees a half-written file.
Source code in src/femforge/common/files.py
write_bundle
¶
write_bundle(sim_dir: str | Path, manifest: RunManifest, result: Result) -> Path
Write manifest.json and result.json into sim_dir, pin the source STEP as geometry.step unless the run already holds one, and return the bundle.
Parameters:
-
sim_dir(str | Path) –The run bundle directory, created when missing.
-
manifest(RunManifest) –The run's manifest.
-
result(Result) –The run's typed result.
Source code in src/femforge/run/bundle.py
write_manifest
¶
write_manifest(sim_dir: str | Path, manifest: RunManifest) -> Path
Atomically write (or overwrite) manifest.json in sim_dir (created if needed) and return its path.
Source code in src/femforge/run/bundle.py
convergence_ladder
¶
convergence_ladder(base_config: SimulationConfig, refinements: list[float], quantity_of: QuantityOf, evaluate: EvaluateFn) -> list[ConvergencePoint]
Run base_config at each refinement level and report the quantity of interest plus its relative change between rungs.
Parameters:
-
base_config(SimulationConfig) –The configuration to refine.
-
refinements(list[float]) –Factors that divide
global_mesh_size; a factor above 1 is finer than the base. -
quantity_of(QuantityOf) –Extracts the quantity of interest from a result.
-
evaluate(EvaluateFn) –Solves one configuration, such as a driver's
evaluate.
Source code in src/femforge/run/convergence.py
richardson
¶
richardson(scales: Sequence[float], values: Sequence[float]) -> RichardsonEstimate
Richardson-extrapolate the finest three rungs of a ladder whose scales are mesh-size multipliers (larger is coarser) paired with values.
Raises when fewer than three rungs are given, scales repeat, or the rung deltas are not shrinking.
Source code in src/femforge/run/convergence.py
boundary_fluxes
¶
Elmer bc index -> integrated conductive flux (A) from the SaveScalars columns in Result.raw.
Source code in src/femforge/run/electrical.py
electrode_currents
¶
Boundary block name -> terminal current (A), joining the flux columns against the bc-index name map.
Source code in src/femforge/run/electrical.py
phase_currents
¶
Phase index ("0", "1", ...) -> terminal current (A): the largest-magnitude current among each phase's named electrode currents.
Source code in src/femforge/run/electrical.py
read_boundary_names
¶
The boundaries.yml map the Sim writes (<bc index>: <boundary block name>), as a dict.
Source code in src/femforge/run/electrical.py
resistance
¶
R = ΔV / I for one phase; raises on a (numerically) zero current.
Source code in src/femforge/run/electrical.py
load_entities
¶
load_entities(sim_dir: str | Path, manifest: RunManifest | None = None) -> Entities
Read a bundle's bodies/boundaries: entities.json when present, else mesh.names enriched from the manifest config, else empty.
Source code in src/femforge/run/entities.py
write_entities
¶
write_entities(sim_dir: str | Path, physical_groups: Iterable[_BodyGroupLike], boundary_groups: Iterable[_BoundaryGroupLike]) -> Path
Write entities.json mapping each group's reconciled mesh id to its named record; call after reconcile_ids.
Parameters:
-
sim_dir(str | Path) –The run bundle directory.
-
physical_groups(Iterable[_BodyGroupLike]) –The body groups, carrying ElmerGrid's ids.
-
boundary_groups(Iterable[_BoundaryGroupLike]) –The boundary groups, carrying ElmerGrid's ids.
Source code in src/femforge/run/entities.py
select_array
¶
select_array(names: Iterable[str], variable: ElmerVariable | str) -> str
Resolve a VTU array name for a solver variable: exact (nodal), then the elemental "<name> e", then substring — VTU names come back lowercased.
Source code in src/femforge/run/fields.py
find_runs
¶
find_runs(runs_dir: str | Path, *, tags: Mapping[str, str] | None = None, text: str | None = None) -> list[Run]
The bundles under runs_dir whose metadata matches, newest first; this reads every manifest, so prefer RunIndex over thousands of bundles.
Parameters:
-
runs_dir(str | Path) –The runs directory to search; bundles with unreadable manifests are skipped.
-
tags(Mapping[str, str] | None, default:None) –Tag pairs a run's metadata must all carry; None matches any tags.
-
text(str | None, default:None) –Text to find, ignoring case, in the run name, description or notes; None matches any text.
Source code in src/femforge/run/inspect.py
mesh_spec
¶
mesh_spec(config: SimulationConfig, step_key_override: str | None = None) -> MeshSpec
The mesh artifact spec of config (step_key_override when the driver already resolved the geometry).
Source code in src/femforge/run/kinds.py
step_digest
¶
SHA-256 of a STEP with its FILE_NAME header (the export timestamp) masked; of the path string when the file is absent, so pure-logic keys stay deterministic.
Source code in src/femforge/run/kinds.py
component_forces
¶
component_forces(raw: Mapping[str, float], names_by_component: Mapping[int, str]) -> dict[str, Vec3]
Component name -> lumped magnetic force (N, per radian in an axisymmetric run), joining the force triples against the components.yml map.
Source code in src/femforge/run/magnetic.py
component_torques
¶
component_torques(raw: Mapping[str, float], names_by_component: Mapping[int, str]) -> dict[str, Vec3]
Component name -> lumped magnetic torque (N*m about the authored origin/axis, per radian in an axisymmetric run), joining the torque triples against the components.yml map.
Source code in src/femforge/run/magnetic.py
eddy_current_power
¶
The total eddy current power (W, per radian in an axisymmetric run), or None when the run exported none (static solves have no eddy losses).
Source code in src/femforge/run/magnetic.py
force_triples
¶
Column stem -> per-component force Vec3 (N, per radian in an axisymmetric run) from the SaveScalars columns in Result.raw.
magnetic_field_energy
¶
The total magnetic field energy (J, per radian in an axisymmetric run), or None when the run exported none.
Source code in src/femforge/run/magnetic.py
read_component_names
¶
The components.yml map the Sim writes (<component id>: <Component name>) — the same flat format as boundaries.yml.
cache_key
¶
cache_key(config: SimulationConfig) -> str
Full-run identity: every result-affecting input plus RUN_PRODUCER_VERSION; never the code commit, the machine, or the run metadata.
Source code in src/femforge/run/kinds.py
git_sha
¶
The current commit, with -dirty appended when the working tree has uncommitted changes; None without git or outside a repository.
Source code in src/femforge/run/manifest.py
mesh_key
¶
mesh_key(config: SimulationConfig) -> str
The mesh artifact key of config: invariant to materials' properties, conditions, physics, and metadata.
step_key
¶
step_key(config: SimulationConfig) -> str
The solve-frame geometry identity a run and its mesh key on: the STEP artifact key of step_spec(config).
parse_result
¶
Parse a finished run directory into a typed Result, revolving force and torque to full-revolution totals under an Axisymmetric frame.
frame=None reads the frame from the bundle's manifest, falling back to Solid for a directory without one.
Source code in src/femforge/run/parse.py
result_vtu
¶
The run's newest ParaView output: the .pvtu master when the solve was partitioned, else the newest .vtu; None when there is none.
Use it instead of a *.vtu glob, which also matches a partitioned run's per-rank pieces.
Source code in src/femforge/run/parse.py
reap_runs
¶
Mark every bundle under runs_dir left running with no live claim on it as abandoned, and break every claim that went silent.
Parameters:
-
runs_dir(str | Path) –The runs directory holding the bundles and their claims.
-
alive(Alive, default:pid_exists) –Whether a process id is alive on this host.
-
host(str, default:HOST) –This host's name; a claim held here by a process that is no longer alive counts as silent.
Source code in src/femforge/run/reap.py
apply_cleanup
¶
apply_cleanup(plan: CleanupPlan, *, dry_run: bool = False) -> CleanupReport
Remove every planned path; never raises, so a path that cannot be removed lands in report.failed.
A planned run directory is only reported (as "."); the caller removes it with remove_run_dir after its last manifest write.
Source code in src/femforge/run/retention.py
bundle_inventory
¶
bundle_inventory(sim_dir: str | Path) -> list[BundleEntry]
Every file under a bundle with the retention class its name matches; a name no class claims is filed under RunFile.RUN_DIR, the only rule that reaches it.
Source code in src/femforge/run/retention.py
plan_cleanup
¶
plan_cleanup(sim_dir: str | Path, policy: RetentionPolicy, *, status: ManifestStatus, cached: Iterable[str] = ()) -> CleanupPlan
Resolve policy against one bundle into the sized paths each applying rule removes; refuses a symlinked or junctioned directory.
Parameters:
-
sim_dir(str | Path) –The run bundle directory.
-
policy(RetentionPolicy) –The retention policy to resolve.
-
status(ManifestStatus) –The run status the
ON_SUCCESSrules resolve against. -
cached(Iterable[str], default:()) –Bundle-relative paths the store can re-fetch;
policy.cached_inputsescalates their rules.