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. - 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. - 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.
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.