Scientific agent reference¶
Read only for a relevant numerical implementation or scientific question. Ordinary installation, result viewing and routine execution use the short agent guide. Code paths below are relative to the repository root; this is a topic index, not a mandatory checklist.
Progressive Reading¶
- Mesh, domain, or region modeling: read the Mesh Region, Selector, and Region
Set concepts in
CONCEPTS.md. Prefer named regions and region sets over raw integer tags in user-facing workflows. Use low-levelMeshTagshelpers only when importing, validating, or teaching the tagging implementation. - Mesh or boundary tagging: read
docs/module_map.md, then usemesh.summarize_mesh,mesh.require_cell_tags, andmesh.require_facet_tags. Reviewed array archives usemesh.read_array_meshand an explicit ordering manifest; part exteriors usemesh.exterior_regions, not case-owned MeshTags construction. Preserve input-cell identity and independent coincident nodes. Seedocs/guide/array_mesh_inputs.md; a shared material interface is not an exterior surface and must not be silently turned into contact. - Abaqus migration: run
agentfem inspect-abaqus source.inp --jsonbefore conversion and readdocs/abaqus_migration.md. Preserve element formulation suffixes and report topology-only support; never substitute a native element formulation silently. - If
migration.jsonreports an eligible narrow native route, useagentfem lower-abaqus PROJECT --reviewed-by NAME --unit-system SYSTEMto createcase.native.pyandlowering.jsonwithout activation. Read both, then use--activate --forceonly when accepted. Never invent units or delete a blocking finding. Multiple constant isotropic materials are lowered only through exact, non-overlapping ELSET/Section coverage. Dependent material tables, partial or ambiguous Section coverage, non-unit 2D thickness, and Step/BC inheritance require a dedicated lowering route rather than a first-row or final-value approximation. - Study setup: use
studies.static_solid,studies.steady_heat_transfer,studies.transient_heat_transfer, orstudies.dynamic_solidfor common workflows. Use the general factories only when the common vocabulary does not fit.dynamic_solid(method=...)changes the procedure, not the physics. - Solution procedure: inspect
procedures.pywhen Standard/Explicit or a particular time integrator must be selected. Do not encode the algorithm by inventing a new physical analysis type. - Model audit: use
model.tree(),model.manifest(),model.summary(), andmodel.validate()when multiple fields, regions, loads, constraints, or steps must be inspected. Usemodel.check()to stop before execution on validation errors andmodel.write_ir(...)when a persistent scientific record is required. - Capability dispatch: inspect
models.step_capability(model)or runmodel.check()before solve. It queries the same provider predicates asmodel.step(...), including target-field shape and the material protocol needed by the default lowering; never work aroundAFM-STUDY-002by silently changing the Study. - Step failures: read
error.detailsin the local execution record forstep_optionsorstep_capabilityfailures. Use the recorded suggestions or rejection reasons to propose a targeted correction; syntax-onlycheckdoes not validate these physical inputs. Do not automatically rerun or change physics. - API discovery: begin with
agentfem.public_api("core")or thepublic_api.coresection ofagentfem capabilities workflow --json. Escalate to the advanced or expert layer only when the task requires it; the flatpublic_modulesinventory remains a compatibility contract. These generated views share one product contract; never reconstruct a competing vocabulary from one example or an old compatibility method. Use a relevant topic/material name for focused discovery. Scoped views omit unrelated sections, not capability limitations or verification gaps; use the complete record only when needed. For an uncertain parameter, useagentfem capabilities --api fields.displacement --json(ormodels.Model.step) to read the installed signature. Do not repeat discovery for every already-known call; provider options still use the Step contract. - Model registration: use
model.field(...),model.material(...),model.fix(...),model.traction(...),model.surface_force(...),model.distributing_coupling(...), andmodel.elastic_foundation(...)in application workflows when the assets should stay visible and auditable. - Application unknowns: use
fields.pybefore dropping tospaces.py. - Sequential thermal--mechanical handoff: use the same runtime mesh and an
explicit
stage.predefine(T_solid, T, method="interpolate"). Never copy coefficient arrays merely because their lengths match. Protect the configured Step's construction and solve withstage.field_transaction(displacement=u); seedocs/engineering_workflows.md. Physical times, when relevant, must be explicitly declared and equal. This does not imply cross-mesh transfer, unit conversion, live binding, or converged two-way coupling. - Function spaces: inspect
spaces.py; only inspectkernel/dofs.pyfor implementation-level dof work. - Essential boundary conditions: read
CONCEPTS.md, then useconstraints/. - Natural loads: read
CONCEPTS.md, then useloads.body_load,loads.neumann, orloads.boundary_load. - Constitutive laws: read
docs/nonlinear_materials.md, queryconstitutive.capabilities(), then useconstitutive/. Never turn a material-point law into a claimed FEM step without state/tangent/solver evidence. For a custom finite-strain history material, readdocs/history_material_workflow.mdandexamples/history_materialbefore creating a project Step provider. The bounded serial 3D/plane-strain route already owns quadrature, Newton, physical time, rollback/restart and unified multi-field output. Supply the localUserMaterialand its referencedP/dF, not a project Newton loop. Its exclusions are explicit; do not infer general plane stress, MPI, contact or arbitrary UMAT support. Prescribed uniform temperature is supplied bytemperature=as positive kelvin or a scalar linearhistories.temperatureover physical time; the Step freezes this input and owns accepted TEMP output. Do not infer spatial thermal histories, heat conduction or two-way coupling from this option. Usematerial_points=(results.material_point("site", cell=..., point=...),)for selected raw histories through this same Step.site.E_GLis total Green–Lagrange strain; do not treat it as infinitesimal or mechanical strain for life assessment. No project sampling loop or XML edits are needed. The limited plane-stress option requires a 2D plane-stress Study and explicitconstitutive.PlaneStressReduction(symmetry="reflection_symmetric"). The core solves thickness equilibrium, condenses the algorithmic tangent and preserves full 3D stress/history. Never truncate stiffness or infer a 3D material from a uniaxial fit. Forces are per unit reference thickness. For a reviewed strain-history VUMAT, readdocs/strain_history_runtime.md. Use the declared runtime instead of writing project-specific ctypes/Fortran bridges. Never declare unused thermal, time, length or energy channels without source review, or infer state layouts and step limits from another case.constitutive.chaboche(...)is an experimental three-dimensional global combined-hardening route with quadrature rollback/restart andALPHAoutput. Keep its external-definition evidence distinct from a calibrated structure-level stabilized-hysteresis validation. For composite solids and sections, readdocs/composite_materials_and_forming.md. Keep a material's constants, assignment orientation, and laminate placement separate. ADecoupledFabricSurfacehas an experimental finite-kinematics in-plane membrane provider throughstudies.static_membrane()andmodel.step(...). That provider consumes yarn tension and trellising shear and rejects nonzero bending stiffness. Objective director-shell measures are local foundations; do not present them as a shell element, contact, or forming simulation until those providers and their benchmarks exist.constitutive.finite_strain_j2_logarithmic(...)has experimental publicmodel.step(...)providers for ordinary strong boundaries/reference dead loads and for 3D affine-periodic cells with exactly oneAbaqusPeriodicConstraint. Both share one provider-owned quadrature transaction and accepted-state portable checkpoint. The ordinary serial provider also accepts independently named rigid pairs using a differentiableSmoothRigidSurface(built-in plane/sphere/cylinder or a conforming external implementation), or a triangulated tool with interior or coplanar-seam projection. Each prescribed tool pose needs a normalized 0-to-1 schedule driven by the shared Step amplitude; per-pair accepted force--moment work and all poses must rollback together. Open triangle patches reject active free/noncoplanar edges. Reviewed closed-solid tools and Coulomb friction have separate, geometry-dependent admission limits; use the current matrix indocs/guide/model_setup.md, not a blanket friction prohibition or an assumption that all sharp features are supported. The separate affine-periodic provider accepts named multiple rigid pairs and tested locally planar Coulomb combinations, with total-residual MPC reduction and a nonsymmetric linear-solver policy for friction. Reject follower loads and unrelated weak boundary models; ordinary strong constraints and affine MPC cannot be mixed in one Step. The J2 law owns its analytic discrete tangent, but that alone does not validate a contact geometry, mixed displacement--pressure/contact combination, external structure response, general energy closure or distributed implicit route. - Named materials: use
materials.define(...)when material identity, source, reuse, or separate mechanical/thermal roles matter. The Study selects the required physics role atmodel.material(...); it does not choose or rewrite the constitutive equation. Packagedload_definition(...)cards are reference-only unless their source and applicability establish otherwise. - Project materials:
materials.load("materials/active.py")explicitly loads reviewed, trusted Python code and records its content hash. Do not use it to inspect downloaded code. TOML may select an asset but is not a constitutive language; installed or private collections belong in extension packages. For reviewed multi-source Fortran providers useconstitutive.build_native_librariesrather than rewriting compiler/cache logic in a project. Keep source trust explicit. For supported serial transient delivery useproject.execute_steparound the ordinary Step, not a case-owned integration loop. Seedocs/project_execution.md. Project version constraints belong inproject.requires_agentfem, not private-module probes or commit IDs. - Absorbing or Robin-like terms: use
boundary_models/. - Assembly or lumped operators: inspect
assembly.py. - Time stepping: inspect
time/andproblems.py. For the serial response-Hex route usemass_scaling=FixedMassScaling(...)orInitialMassScaling(...)(reference estimate), orTargetIncrementMassScaling(...)instead of generating nodal arrays in a case. Target planning requires a reviewed bound provider and a mass budget. Never fill a missing contact/hourglass/damping contribution with zero merely to satisfy its coverage check. Never infer path stability from a single initial elastic tangent. An NPZ from another geometry is not a mass policy. - Time histories: define reusable assets in
amplitudes.py, register important histories withmodel.amplitude("name", history), and reference the name from loads or prescribed data. Static single-solve, nonlinear normalized step time, and transient physical time have distinct documented coordinates. Do not substitute the half-cosinesmooth_stepfor a quintic loading law: usequintic_stepand pass its physical-time amplitude to the rigid-motion schedule. Changing that history changes checkpoint identity. Attach histories to model loads, prescribed values, or supported boundary models. Transient procedures update registered histories automatically; use callbacks only for genuinely application-specific state. Type a custom callback withtime.input_update(...): RHS/output-only inputs may retain a prepared linear operator, while operator/state inputs require refresh. Linear heat and implicit dynamics enforce this distinction; nonlinear heat remains per-step assembled. For many related loading modes, useamplitudes.basis(...)andbasis.combine(...); preserve coefficient order, derivatives, endpoint audit, and the amplitude fingerprint. Do not represent a frozen campaign waveform only as an anonymous callable. - Solves: inspect
solvers.py. - Step incrementation: use
steps.automatic(...)by default orsteps.fixed(...)only when exact fixed subdivision is scientifically intended.max_incrementslimits accepted increments; Newtonmax_itlimits iterations in one attempt. - Global implicit creep has an additional physical-time accuracy decision:
The experimental
constitutive.CreepPlasticityMaterialcomposition uses the ordinarycreep_solidStudy andmodel.step, not a project-level sequential material loop. It jointly commits creep/plastic histories; its maximum inelastic increment checks both CEEQ and PEEQ. Limit this composition to serial homogeneous 3D small strain; contact, MPI and temperature-dependent plastic properties are not admitted. Seeexamples/thermal_cyclic_creep.creep_strain_error_tolerancebounds the endpoint creep-rate change times the attempted increment. Keep it distinct from Newton convergence andmaximum_inelastic_increment; all three may independently trigger atomic rollback and cutback. Result time units come from the modelUnitSystemand remain undeclared when no consistent-unit contract was supplied. For one-way thermal input,capture_history(...)records source Study, procedure, accepted-time role and content identity. Useassessments.sequential_energy_ledger(...)to keep heat and mechanical residuals separate. For engineering creep--fatigue from result histories, declareDwellIntervalobjects and pass a source-identified project rupture relation tocreep_fatigue_from_result(...); do not embed normative curves. For tabulated rupture data in different units, explicitly callcurve.in_units(stress_unit=..., time_unit=...); keep accepted histories unchanged. Conversion preserves provenance, not experimental applicability. For scalar strain-life instead, explicitly callassess_strain_historywith a calibratedCoffinMansonBasquinCurveand signed total mechanical strain. Never substitute accumulated PEEQ or sparse visualization frames. For a reviewed strain-amplitude applicability interval, use the curve'sfrom_strain_domainconstructor; do not widen observed cycle extrema merely to make an endpoint fit evaluate. This declares a different input domain, not a newly validated material model. The result can be passed toassessments.creep_fatigue; it is not a stiffness-damage law or a certified service-life prediction. For experimental lives/run-outs, useassessments.LifeObservationandlife_survival(seedocs/life_observations.md). Keep distinct test conditions separate; survival confidence limits are not individual-life prediction bounds. For a predetermined sample size/horizon with known binary outcomes, usefixed_horizon_reliability, including zero failures. It rejects early censoring; do not delete such specimens or select the horizon after inspecting outcomes. Usecreep_damage_from_result(..., quadrature_subdivisions=...)only for explicit quadrature refinement; source-gap checks still apply to recorded history, not interpolated points. Keep this separate from FE time refinement. - Multi-Step activation: use
model.stage(...)and pass its result asconfiguration=tomodel.step(...); keep asset inheritance separate from incrementation and nonlinear solver controls. - Hybrid solids: a known C3D10H source mesh requires
fields.displacement_pressure(...)andconstitutive.mixed_neo_hookean(...); do not route it through a displacement-only provider. - Analysis steps: prefer
model.step(...)when a model owns fields, materials, loads, and constraints. Pass aSolutionProcedureobject when the numerical route must be explicit or must override the Study preference; capability inspection and lowering consume that same object. Treat named legacy Step factories as expert/compatibility entrypoints. Useproblems.linear_staticorproblems.first_order_transientwhen a workflow intentionally starts from explicit K/C/F operators without model ownership. - Problem summaries: use
problems.FEMProblemwhen a workflow needs a broader structured audit record. - Scientific formulas: when a formula arrives from JSON, a benchmark,
experiment metadata, or agent-authored configuration, use
expressions.expression(...),expressions.as_ufl(...), orexpressions.interpolate(...). The language accepts coordinates, declared parameters, arithmetic, and reviewed mathematical functions; never replace it witheval, and do not silently reinterpret an invalid formula. Useas_uflfor symbolic weak-form physics andinterpolatefor known fields; the latter uses the same validated AST without a per-expression C++ JIT. - Results: read
docs/results_and_campaigns.md; usesolve_result()orsolve_result(output="results.xdmf")for the standard static/transient solve/output/result lifecycle. Useresults.SimulationResult, MPI-safe point/path probes, region integrals/averages, boundary resultants and field extrema inresults, then attach additional XDMF/CSV artifacts fromio. A model-owned case may instead declare a path inmodel.step(..., output="results.xdmf")and callsolve_result()once; do not send the same output request through custom case loops. Model-generated static elasticity produces projectedS/E/MISESautomatically;SENERis opt-in throughfield_variables. J2 and creep expose the same completed-result writer throughsolve_result(output=...); raw quadrature fields remain result evidence and explicit*_CELLfields are written for visualization. Useresults.small_strain_partition_fieldsfor reviewed regional projections andresults.reaction_resultant(..., on=..., component=...)only for named strong-constraint reactions. InspectSimulationResult.metadata["constraint_balance_contract"]before claiming global equilibrium: MPC, weak, contact, projection, or multiplier channels remain unavailable until their active provider supplies actual dual forces. For imported physical surfaces usemesh.tagged_boundary_region(...)for both strong and weak conditions, callmodel.audit_boundaries(strict=True), and useresults.region_measure(on=...)rather than application-owned UFL. Requestfield_extrema(..., location=True)when publishing a peak. Serialsolve_result(output=...)writes one Uniform Grid with mixed point/cell attributes; low-levelio.XDMFTimeSeriesretains DOLFINx multi-Grid semantics. Under MPI, open thefield_outputmetadata'srecommended_visualization_artifact(normally PVD), not the scientific multi-Grid XDMF; that route needs no Extract Block step. Never write VTK/XDMF connectivity or reorder element nodes in an application case. Usesolve_result(output=...), orio.ResultWriterfor a custom loop. Useresults.cell_field_from_valueswith explicit cell keys for external per-cell data. Equal array lengths do not establish matching field layouts. Keep reference geometry for Warp; do not apply Warp again to an already deformed presentation artifact. Never merge coincident physical nodes merely to remove duplicate visualization blocks: cracks/interfaces may require them. For field-learning data, create a fixedsurrogates.ObservationGridand calldatasets.fem_observation_sample; preserve its units, layout, and mask. For a direct solver or external benchmark contract, useresults.sample_rectilinear_grid(...); its physical-axisshape=(nx, ny, nz)is returned in array order(nz, ny, nx)and itsinsidemask must be retained for non-rectangular domains. For the pinned PDEAgent-Bench contract, useintegrations.pdeagent_bench.solve_case(...)and readdocs/pdeagent_bench.md; inspectSUPPORTED_FAMILIESrather than guessing capability from a case name. Do not read oracle-only mesh, FEM, solver, or manufactured-solution fields, dispatch on case IDs, or infer success from execution alone. Preserve the benchmark commit and failure taxonomy. For mixed flow, periodic MPC, or split fourth-order cases, report the resolved field pair, pressure reference, periodic method, and auxiliary boundary closure fromsolver_inforather than presenting them as implicit defaults. When observations and the FEM mesh use different axes or origins, pass an explicitsurrogates.AffineCoordinateMap; for publication maps convert the result todatasets.RectilinearObservationbefore comparison. Never infer a transpose, unit conversion, or reference/current transformation from a figure. Afracture.DynamicFractureEvidenceBundleis the portable handoff for one fracture condition, but its provenance seal is not a validation claim. Distinguish execution status fromresult.trust_level, apply a named quality policy for routine checks, and attach explicit scientific claims before describing a result as verified. - Result provenance: register every numerical/report artifact before
publishing, then use
agentfem verify ... --json. Treatverifiedhere as byte-integrity evidence only; scientific trust remains inSimulationResult.verification. - Runtime freeze: use
provenance.freeze_runtime(...)before a frozen or blind campaign andprovenance.require_runtime(...)before continuing it. A runtime match establishes execution compatibility, not scientific validity. - Scientific inputs: pass reusable mesh/source files as
Pathvalues and materials, loading bases, procedures, and observer plans throughCampaign(scientific_inputs=...). Review fingerprint coverage; an opaque input is an explicit incomplete identity, not permission to ignore it. - For a single run, attach the same assets with
result.add_scientific_inputs(...)before writing its manifest. Pass source files asPath, not filename strings, when byte identity matters. - Events: use
events.first_passage(...)for threshold timing. Preserve its bracket, localization method, and censoring state; for discontinuous damage or contact, refine the solve rather than presenting linear interpolation as an exact event time. - For long transient jobs, pass one
checkpointing.every(...)policy throughmodel.step(checkpoint=...); do not implement cadence in a case loop. Setkeep_lastfor bounded storage; do not delete checkpoint directories in application code. - For transient probes or scalar histories, pass reusable
results.probe_history(...)/results.history(...)requests tomodel.step(history=...),run(history=...), orsolve_result(history=...). Construction-time requests are consumed automatically by the common result lifecycle and retained with solver, output, progress, and checkpoint declarations in execution metadata. The callback receives the public Step and physical time. Keep the same named requests across restart; AgentFEM rejects a changed history schema instead of producing ragged data. - Restart: heat, Standard dynamics, and Explicit dynamics share
run(until_step=...),save_checkpoint(...),load_checkpoint(...), and resumedsolve_result(output=...). Treatoutput_scope="continuation_segment"as a partial field series even though the result retains full accepted-time and execution evidence. Do not change MPI size or mesh partition when loading the current partition-bound checkpoint. - Cohesive state portability: fixed-path cohesive transactions may instead use
interfaces.save_portable_cohesive_state(...)andinterfaces.load_portable_cohesive_state(...). Physical facet keys survive local order and MPI rank-count changes.create_dolfinx_split_mesh(..., comm=...)plus the unchangedfracture.mode_i_cohesive_force(...)factory provides the experimental sparse-payload MPI force path. When positive-side cell identities are known, preferinterfaces.split_conforming_cell_interface(...)to a hand-written facet list. Portable transient checkpoints also distinguish coincident independent nodes. Do not infer 3D imported surfaces or extreme-scale performance from this 2D owner-scheduled contract. - Cyclic cohesive equilibrium: use
fracture.FiniteStrainCohesiveEquilibrium(...)when a UFL finite-strain bulk residual and paired-facet interfaces should enter one native Newton solve. Supply the physical scalar load throughload_parameterorset_load; keep interface history commit/rollback under the owning Step. Strong-constraint reactions are supported through the residual reaction field, but do not reuse that definition for MPC, weak, contact or multiplier reactions. - Installed projects and external frontends: read
docs/getting_started.mdanddocs/agent_gui_integration.md. Keepcase.pyas modeling truth, useproject.current_run()for artifacts, publish aSimulationResult, and consume versioned JSON instead of scraping terminal prose. - Installed private extensions: run
agentfem extensions --jsonbefore accepting a project's[extensions].requiredlist. Treat every extension as trusted executable code; a missing package is not permission to install an unknown distribution. Keep private products in separate repositories and integrate them through the versioned extension API. - AF-IR and repair: inspect
ir/andvalidation.py. Treat AF-IR 0.1 as an experimental record, not as proof of backend-neutral executability. - API lifecycle: consult
models.model_api_contract()oragentfem capabilities workflow --jsonwhen a method's status is uncertain. Runagentfem upgradefor version migration or reported migration findings. Compatibility findings that require semantic review are guidance, not permission for blind textual replacement. - Backend work: inspect
backends/anddocs/air_architecture_roadmap.md. Preserve the full FEniCSx path and do not advertise a backend until its capabilities are independently tested. - Parameter campaigns and learned models: read
docs/ai_native_learning.md, then inspectcampaigns/,datasets/, andlearning/. Build a fresh model per case; retain units, output shapes, case IDs, validation data, and applicability behavior. Do not present a training residual or successful prediction call as independent scientific validation. Userequire_dataset(quality="engineering")for ordinary learning data and a release policy when every sample carries a scientific release contract. A user-owned neural-field model may enter throughmodel.step(target=spec, executor=...)without an official adapter, but it must returnSimulationResult; do not serialize the live callable into provenance or infer scientific validation from training loss. - Predefined fracture fields: construct reusable straight 2D cracks through
fracture.segment(...)andfracture.crack_set(...). Preserve stable crack/tip identity, orientation, and fingerprints through every provider. Never infer fracture mode from an input label, average the two sides of a discontinuous field into one nodal value, or report one SIF without its local convention and ring-sensitivity evidence. The first geometry contract deliberately rejects intersecting, touching, and curved cracks. Usefracture.infinite_plate_stress_intensity(...)as an analytical oracle andfracture.interaction_integral_report(...)for common LEFM normalization; usefracture.dolfinx_interaction_integral_report(...)to lower solved DOLFINx stress and displacement-gradient fields, and keep its MPI reduction and multiple-radius evidence intact. The executablebenchmarks.center_crack_mode_i_benchmark()is the first finite-element acceptance reference; its split-mesh generator is not a general mesher. do not apply the initial homogeneous straight-crack integral to curved, inhomogeneous, thermally strained, body-force, or traction-bearing crack-face cases without the required additional terms. - Neural energy integration: use
learning.IntegrationPlanto distinguish the optimization rule from explicitly independent validation and refinement rules. Attachintegration_consistency_check(...)evidence to the result. Loss reduction, held-out integration, refinement convergence, boundary checks, and physical balance are separate decisions. - Across-case execution: use
campaigns.local_processes(workers=...)only for independent cases. It deliberately usesspawn. Do not nest it inside a within-case MPI communicator; use deterministic plan shards for separate MPI jobs or schedulers. Build/evaluate callables must be importable and serializable, and each case must construct fresh mutable solver state. - Convergence certificates: use
convergence.audit(...)with one explicit refinement axis at a time, fixed values for every other varying parameter, and an observable-specific relative, absolute, or exact comparison. Missing, failed, ambiguous, or insufficient sequences remain inconclusive. - Response experiments: use
responses.finite_difference(...)when baseline and perturbation cases should share Campaign identity, cache, failures, and evidence. Keep the parameter perturbation mode and output quantities explicit. A failed perturbation makes the response report incomplete. - External meshes: inventory with
mesh.inspect_external_mesh(...)before choosing cell/facet types. Preserve conversion manifests and never describe mesh conversion as full Abaqus/ANSYS deck import. - Abaqus projects: run
agentfem inspect-abaqus ... --jsonbeforeagentfem migrate-abaqus .... The migration project must preserve the recursive source graph, Part/Instance scope, section/material assignments, source locations, and unresolved issue codes. A generated material candidate is reviewable data, not permission to execute it. Do not remove formulation suffixes, flatten same-named sets across scopes, or bypass the fail-closed guard before native operators and verification evidence are selected. Never invent a missing material property or silently omit a Step, load, boundary, interaction, or output listed underpending_assets. - Example workflows: inspect
examples/after readingWORKFLOW.md.
Agent Rules¶
- Do not mix constraints, loads, and boundary models.
- For contact, keep surface geometry, rigid-body kinematics, and enforcement law separate. Report tool work only from accepted generalized force--translation/moment--rotation stations, never from penalty energy.
- When a serial implicit rigid contact trace intersects strong prescribed displacement DOFs, lift the native contact tangent by the prescribed correction and keep constrained matrix rows/columns eliminated. The bounded finite-J2 source candidate exercises this on a symmetry-reduced indentation; it is not evidence for MPI implicit contact or non-smooth tool edges.
- The finite-J2 rigid-contact result reports final unsmoothed contact-point
diagnostics: active reference area, peak nominal penalty pressure and peak
penetration per named pair. Their location is reference-boundary quadrature, not nodes;
neither a peak alone nor a visually smoothed field proves contact accuracy.
For spatial comparisons use the accepted trace's
reference_positionsand declared measure, not current-coordinate bins that move with deformation.export_accepted_contact_pointspreserves reference positions when all providers supply them and explicitly reports absence for older providers. - For a large serial nonlinear contact model, inspect accepted increment phase timings before tuning. Direct LU can dominate at finer resolution; an explicitly chosen nonsymmetric Krylov/preconditioner policy may help, but accept it only after converged linear reasons and force, work, contact-area, penetration and state comparisons on the same model. Do not make a machine- or case-specific policy the global default.
- For explicit penalty contact, prefer the reviewed lumped-mass stability screen and preserve its contact-only scope. Add its spectral upper bound to the body/material spectral upper bound before converting the sum to a time increment; taking the minimum of separately derived time limits is not a valid composition. Apply any stricter caller ceiling afterward. Include both normal and tangential penalties plus Coulomb pressure coupling. Require a caller ceiling for curved-normal geometry until geometric stiffness has a reviewed bound; never infer stability from penetration or from a converged time history.
- For every explicit Procedure, represent body/material, cohesive, contact,
and future stiffness restrictions as named
time.ExplicitStabilityContributionobjects. Combine them once withtime.combine_explicit_stability; never take the minimum of independently derived time limits when their stiffness operators act simultaneously, and never apply a safety factor separately to every contribution. The bounded finite Hex8 provider may consume a material-ownedFirstPiolaTangentEnvelopeinstead of a caller frequency ceiling. It must cover all admissible material states/inputs in its stated stretch domain. Never invent an envelope from one initial tangent or equatedt="auto"with adaptive stepping. Native finite J2 still requires the caller ceiling. Its bounded finite-Hex contact candidate accepts one registered frictionless fixed/translating plane in serial or MPI with optional elastic bonding. Keep the reference-surface penalty meaning explicit; rotating/curved tools, multiple pairs and friction are not admitted. An equal-stiffness elastic reference bond can coexist on disjoint trace nodes; this is not debonding/contact switching. Useexamples/finite_hex_moving_plane.pyorexamples/finite_hex_bond_contact.py. - Treat a surface projection as evidence, not merely coordinates. Preserve its surface identity, method, admissible-side unit normal, signed-gap convention, validity, discrete entity identity, geometry fingerprint and local coordinates. Never turn a failed or ambiguous closest-point query into an active contact silently, and never reuse local coordinates with another geometry fingerprint.
- A
TriangulatedRigidSurfacecan validate and project reviewed 3D triangle geometry, and imported triangle tools are executable in the bounded Explicit route through the reviewed serial or routed distributed BVH. This does not imply CAD healing, deformable-master contact, an implicit linearization, or free rigid-body dynamics. triangle_surface_bvh(surface)accelerates a reviewed triangle surface while preserving its exact narrow phase and ambiguity semantics. Inspect its diagnostics when performance matters. For the MPI correctness reference, usepartition_triangle_surface(surface, comm)followed bydistributed_triangle_surface_bvh(partition, comm). That path owns only a facet shard per rank and reproduces the global projection contract, but uses all-gather communication; never describe it as scalable neighborhood search or executable general contact.routed_distributed_triangle_surface_bvh(partition, comm)uses two-stage rank-AABB routing and the all-gather implementation as its correctness oracle. Inspect avoided-message and queried-rank evidence. Its sparse route uses packed numericMPI_Alltoallvtransport; do not describe that bounded route as a general neighborhood-collective or extreme-scale contact search.RigidSphereSurfaceandRigidCylinderSurfaceprovide exact analytical projection. The sphere also represents a 2D circle; the cylinder is 3D and infinite by default. Its optionalaxial_intervaladmits finite lateral interior only; rim/end queries remain unsupported. Keep their interior/exterior admissible side explicit, preservesingular_projection, and do not claim that projection-only geometry is an executable contact law.- Do not hide the finite-element workflow inside overly broad abstractions.
- Do not make concrete geometry helpers, such as circle/disk/box predicates, the core modeling concept. Treat them as selectors used to build named regions. Regions are the stable interface for materials, loads, constraints, boundary models, output, and imported CAE mesh groups.
- Keep application-specific geometry, source definitions, and parameter choices outside the core platform.
- Validate imports, syntax, and a small runnable case after structural changes.
- Report structured validation codes and paths when they are available; do not replace them with an unaddressed generic error.
- When changing a public concept, update
CONCEPTS.md,WORKFLOW.md, and the relevant skill references. - Keep solve increments and result frames distinct. Use output
every="increment"orintervals=...; reserve “frame” for saved/read result states. - State whether a nonlinear capability is FEM-integrated, material-point verified, or a postprocessor. Use the benchmark registry as evidence.
- Never call one converged mesh a convergence study. Use coarse-to-fine
verification.ConvergenceStudyevidence and record a reference theory's applicability domain. - Do not silently extrapolate a learned model. Reject the request or invoke an explicit high-fidelity fallback and report which source produced the result.
Current Platform Focus¶
AgentFEM currently focuses on a dependable DOLFINx/PETSc path: linear elasticity, implicit and explicit linear structural dynamics, implicit heat transfer, sequential thermoelasticity, a bounded Neo-Hookean nonlinear solve, result/campaign/data flow, external mesh conversion, and deliberately staged path-dependent material tools. The first global J2 and Arrhenius power-law creep providers use regional quadrature materials. J2 MPI global equilibrium is public after partition-interface, cutback/rollback, cross-rank-count restart, and external thick-cylinder structural tests; distributed creep equilibrium retains its separate NAFEMS promotion gate. Their constitutive transactions and quadrature archives are MPI-safe and portable across rank counts. Product depth and external verification take priority over adding material names or backend abstractions.
For undamped linear structural modes, use
studies.modal_solid(...) followed by model.step(target=u, modes=...).
The SLEPc provider removes strongly constrained degrees of freedom and returns
frequencies, eigenpair residuals, orthogonality evidence, and deterministically
oriented singleton mode fields through SimulationResult. Repeated or
numerically clustered modes must be compared through their recorded invariant
subspace, not by matching individual vectors; reject a comparison when
selected_clusters_complete is false. Treat a mass-normalized mode shape as a
relative pattern, not as a dimensionless or physical displacement; use its
recorded Mode shape warp field for visualization.
For small-strain linear steady-state vibration, use
studies.harmonic_solid(...) and give model.step(...) explicit K, F,
and optional M, C, and K_loss operators. The lowering preserves them in
an inspectable operators.direct_harmonic_system(...). This provider-neutral
procedure is at engineering maturity for
supported strong constraints, one frequency or a bounded canonical sweep,
and one real spatial load with a common phase. Supply exactly one of
frequency in Hz or angular_frequency in rad/s. Results use the public
exp(+i*omega*t) convention and expose U_REAL, U_IMAG, U_AMPLITUDE,
U_PHASE, residual, cycle-energy, and load evidence. Sweep checkpoints are
portable scalar evidence ledgers, not full-field recovery. Complex modes,
prestressed small-on-large response, nonlinear harmonic balance, arbitrary
constraint families, arbitrary complex spatial loads, and
frequency-dependent operator families are not currently supported.
Use dynamics.spectrum(...), frequency_response(...), and
damping_from_free_decay(...) on arrays or scalar result histories.
constitutive.GeneralizedMaxwell remains the scalar material-point and
spectral asset. For global solid equilibrium, register
constitutive.IsotropicGeneralizedMaxwell, select
studies.viscoelastic_solid(dimension=3), and call
model.step(target=u, duration=..., steps=..., amplitude=...). Use
time_points=(0.0, ..., duration) instead of steps when known loading events
or separated relaxation scales require a nonuniform grid. For an automatically
resolved path, pass incrementation=steps.automatic(...) and optionally
time_error_tolerance=...; do not combine these controls. The error-controlled
route accepts the two-half-step endpoint, rolls back all nodal and quadrature
state after a rejected attempt, and records accepted/rejected increments. The
Step owns committed quadrature history, exact branch updates, standard
viscoelastic fields, energy evidence, and the declared portable serial/MPI
restart route. The generalized-Maxwell material-specific harmonic provider is
separate and remains experimental; do not infer its maturity from the
engineering generic harmonic procedure or the elastic NAFEMS Test 5H
comparison. Neither route implies finite strain or physical aging.
Learn from existing FEniCSx cases¶
Preserve the PDE, discretization, boundaries and solver when migrating working
code. Use operators.from_ufl to adopt integrated weak forms, then substitute
named operators when their semantics match. Do not invent a new wrapper for
every case or force unsupported physics into the closest named operator.
Use (M / dt).expression or (1.0 / dt) * M.expression; UFL Forms and UFL
integrands have different arithmetic. A history/load form has one argument,
not a matrix role; use from_ufl(..., role="vector") when needed. For a
nonlinear residual use role="residual", followed by operators.linearize.
Use mesh.from_arrays(cells=..., coordinates=..., coordinate_element=...,
comm=...) instead of guessing positional DOLFINx mesh arguments.
For constant, coordinate-dependent or explicitly updated time-dependent fields,
use expressions.interpolate(target, source, parameters=...); a bare constant
need not be wrapped in a DOLFINx Expression. Vector/tensor inputs accept lists
or NumPy arrays matching the target value shape. Interpolation is an assignment,
not a persistent time binding. See docs/guide/field_expression_inputs.md.
For high-order mixed-field boundary data, use spaces.independent_subspace(W, i)
and paired parent/independent dof location. Transfer output by interpolation;
never copy coefficient arrays between different numberings. See
docs/guide/high_order_mixed_fields.md.
For serial degree-one imported nodes, spaces.locate_input_nodes uses mesh input
identity and backend entity layouts; it is not a coordinate or source-label
lookup. Use interfaces.reference_trace_from_boundary(..., geometry="bilinear")
for explicitly supported warped Q1 boundary traces. Do not hand-write face
connectivity or collapse coincident nodes at a bonded interface.
For the bounded response-Hex route, use accepted_material_fields() for named
state arrays and accepted_contact_evidence(name=...) for accepted pair evidence.
Keep source-law SDV names in the provider, not the core. Observe only accepted
stations; custom history callbacks are pure observations, never material
updates. Their absence must not change the mechanical solution. Mass-preparation
diagnostics describe supplied reference bounds, not a whole-path stability
proof. Keep worker and reporting budgets separate from scientific controls.