AgentFEM API Style¶
AgentFEM APIs should be readable by finite-element researchers and predictable for AI agents.
Naming¶
- Use nouns for assets:
Amplitude,LoadSet,ConstraintSet,TransientState. - Use verbs for actions:
assemble_vector,copy_function,solve_matrix_system. - Use explicit qualifiers when ambiguity matters:
DirichletConstraint,NeumannLoad,ViscousAbsorbingBoundary.
Inputs¶
- Prefer explicit function-space arguments named
V. - Use
measurefor UFL integration measures. - Use
test_functionandtrial_functionrather than single-letter names in public APIs. - Use
comm,model_rank, andgdimexplicitly for mesh import/read helpers. - Keep optional file-format dependencies lazy. Import packages such as
meshioand Gmsh only at the capability boundary, and raise an actionableOptionalDependencyErrornaming the relevant AgentFEM extra.
Outputs¶
- Return DOLFINx/PETSc objects when the function is a low-level operation.
- Return dataclasses for reusable FEM assets.
- Give reusable dataclasses a
summary()method when the object represents a finite-element concept that humans or agents may audit. - Give material-like dataclasses an
as_dict()method when constants and derived quantities are useful for logs or validation. - Use
to_ir()for a versioned scientific record. Do not userepr()as a persistent fallback for backend objects because it may contain memory addresses and no scientific semantics. - Validation failures intended for repair should carry a stable code and an
object path in a
ValidationIssue. - Avoid hidden global state.
Semantic Constructors¶
- Provide readable constructors for common concepts, such as
constraints.dirichlet(...),loads.neumann(...), andloads.body_load(...). - Provide application-level constructors when they reduce boilerplate, such as
constraints.fixed(...)for fixed-value Dirichlet conditions. - Field arithmetic should be eager and explicit for same-space field algebra:
field_a + scalar * field_breturns a numerical AgentFEM field, not a hidden symbolic solve. - Use
amplitudesfor reusable time histories and scale factors that can drive loads, constraints, sources, or prescribed data. - Hide backend scalar-type details inside concept constructors such as
loads.traction(...),loads.pressure(...),constraints.fixed(...),constraints.symmetry(...), and material-property loaders. - Application examples should not call
PETSc.ScalarTypedirectly. Usekernel.constants.scalar_value(...)in low-level helpers andamplitudes.Amplitudewithconstraints.time_dependent_component_dirichlet(...)for time-dependent boundary data. - For vector fields, application-level constraint constructors should make the
common case short:
constraints.fixed(displacement, on=left)fixes all displacement components, whilecomponents=0orcomponents=(0, 1)selects individual dofs. Engineering axis names ("x","y","z") are accepted wherever a public component selector is unambiguous. - Prefer
on=...for geometric targets in user-facing APIs. Keeplocation=...as a compatibility spelling for explicit region objects. - Provide model-level registration helpers such as
model.field(...),model.fix(...),model.symmetry(...),model.pressure(...), andmodel.traction(...)when they keep the workflow readable without hiding finite-element meaning. - Provide model-level operator helpers such as
model.stiffness(...),model.internal_force(...), andmodel.external_force(...)for daily application scripts. These helpers should delegate tooperatorsand preserve inspectable operator summaries. - Prefer the model-owned
model.step(...)procedure-dispatch entry point for beginner workflows. The step should expose its K/F system through summaries so it remains auditable rather than becoming a black box. - Every built-in Step provider must publish a
StepOptionContract. The contract is the single source for accepted and required keyword names, pre-assembly typo detection, CLI capability JSON, and future IDE/GUI forms. Third-party providers without a contract remain supported during 0.2.x, but a provider is not considered workflow-ready until it declares one. - Keep cross-cutting execution choices readable as ordinary
model.step(...)keywords. Normalize solver, output, history, progress, and checkpoint values into one immutableStepExecutionPolicyfor lifecycle metadata and tooling; do not make users construct a second configuration object for ordinary work. - Material/procedure-specific construction belongs in internal scientific
builders selected by
step_providers.py.Modelremains the stable registry and facade; compatibility builder methods must delegate rather than preserve another implementation of the same route. - Prefer
solve_result()as the common completion verb. An output product may be supplied tosolve_result(output=...)or declared once onmodel.step(..., output=...); provider constructors must not reinterpret it as a numerical solver option. - Provide operator-level constructors for engineering FEM notation, such as
operators.stiffness(...),operators.capacity_operator(...),operators.conduction_operator(...), andoperators.load_vector(...). - Provide contribution-combination helpers such as
operators.combine(...)for explicit operator algebra. The+operator may be convenient shorthand, but public examples should prefercombine(...)when names and summaries matter. - Give matrix, vector, residual, and scalar operators explicit roles and check
those roles against UFL form arity before assembly. Preserve the visible
relation
K_t = dR/duwhen UFL automatic differentiation linearizes a nonlinear residual. - Represent weak boundary-model residual terms with operator helpers such as
operators.boundary_model_vector(...)instead of writing UFL forms in application examples. - Keep explicit family constructors such as
operators.elastic_stiffness(...)available when ambiguity would be harmful. - Prefer problem-level constructors such as
problems.linear_static(K, F, study=..., unknown=..., constraints=...)andproblems.first_order_transient(capacity=C, stiffness=K, history=..., dt=...)when an example is intentionally teaching explicit operator notation. - Keep lower-level dataclasses available for advanced users who need direct control.
- Use concept names in errors and summaries: constraint, load, boundary model, constitutive law, operator, state, and diagnostic.
- Prefer a repair address such as
model.materials[1].regionand a specific hint over a generic execution error. - Parameter-study APIs must carry bounds, units, and deterministic case IDs.
Prefer a fresh
build(parameters)case factory over mutating one live backend model across samples. - Learning outputs must be declared with names, shapes, and units before a campaign runs. Do not infer a scientific schema only from the first returned NumPy array.
- A surrogate prediction API should report its source, uncertainty semantics, applicability decision, and fallback behavior. It must not silently extrapolate or describe residual scale as calibrated epistemic uncertainty.
- Use
learningas the public umbrella while retaining the exact terms surrogate, neural operator, neural-field solver, and learned constitutive model. Do not describe every neural computation as a surrogate or PINN. - A neural-field contract separates the physical coefficient of an energy or work term from its numerical loss-balancing weight. Loss tuning must never silently change the declared mechanics.
- Treat sampling, condition enforcement, inferred physical parameters, units, scaling, provider identity, and verification evidence as inspectable assets. Do not hide them in one optimizer dictionary.
- Add an executable neural-field route through a registered Step provider and
SimulationResult; do not register it as a matrix/form backend merely because it is implemented with PyTorch.
Error Messages¶
Raise errors that explain the modeling issue, not only the Python issue. For example, say that a normal vector is required for normal/tangential absorbing boundaries.
Model vocabulary and compatibility¶
Bundled application cases should begin with the physical factories
studies.static_solid(...), studies.steady_heat_transfer(...),
studies.transient_heat_transfer(...), studies.dynamic_solid(...), or
studies.creep_solid(...). Generic analysis-order factories remain available
for new physics and expert formulation work, but ordinary examples should not
repeat physics="solid_mechanics" or physics="heat_transfer" when the
physical factory already states it.
The canonical application language is returned by models.model_api("core").
It includes registration and engineering verbs such as field, material,
clamp, traction, step, and check. Operator construction, remote
coupling, machine records, and other deliberate escape hatches are disclosed
through models.model_api("advanced").
Historical add_* registration spellings and material/procedure-specific
*_step factories remain executable throughout 0.2.x, but
models.model_api("compatibility") identifies them so documentation, agents,
IDEs, and future GUIs do not present them as parallel beginner workflows. New
examples must use:
model.material(material)
step = model.step(target=unknown, output="results.xdmf")
result = step.solve_result()
models.model_api_contract() and agentfem capabilities --json expose the
lifecycle and preferred replacement for every discoverable Model method.
agentfem upgrade reports compatibility calls that deserve review. It does
not silently rewrite a scientific program: moving arguments from a
material-specific builder to model.step(...) may require a human or agent to
confirm the selected Study, procedure, material protocol, and solver policy.
Do not add another alias merely to save one word. A new public name must either express a distinct engineering concept or replace an older name through an explicit migration path.
The progressive module tiers, Model method tiers, CLI inventory, and
machine-facing workflow stages are declared once in _api_contract.py.
Runtime discovery, documentation generation, the Agent Skill, IDEs, and future
GUI clients must consume that contract rather than maintain parallel lists.