Solid mechanics¶
AgentFEM keeps the engineering model readable while allowing advanced constitutive and weak-form work to descend into the reusable finite-element layer.
Current routes¶
| Route | Present maturity | Typical use |
|---|---|---|
| Linear elasticity | Release workflow | Small-strain static solids and first models |
| Axisymmetric elasticity | Release workflow | Revolved solids using a readable 2D meridian and full 3D stress |
| Thermoelasticity | Engineering workflow | Temperature-driven stress after thermal analysis |
| Compressible Neo-Hookean | Engineering workflow | Finite-strain hyperelastic solids |
| Mooney--Rivlin | Experimental FEM workflow | Compressible 3D solids and incompressible plane-stress sheets |
| Mixed displacement-pressure Neo-Hookean | Experimental/engineering | Near-incompressible quadratic tetrahedral solids |
| Small-strain J2 plasticity | Engineering path | Stateful elastoplastic loading with consistent tangent |
| Finite-strain logarithmic J2 | Experimental public path | Strong-boundary solids with dead or current-configuration pressure loads, and regional 3D affine-periodic cells |
| Small-strain power-law creep | Engineering path | 3D or axisymmetric stateful creep with adaptive physical time |
Modeling sequence¶
- Select the physical study.
- Create or import the mesh and name physical regions.
- Declare the displacement field and material.
- Apply constraints, tractions, body forces, pressure, foundations, or distributed resultants.
- Select the solution step and incrementation policy.
- Request standard fields and histories.
- Accept the result only after the required verification policy passes.
Exact periodic linear systems¶
Rectangular small-strain cells can use the same public Step grammar with an exact distributed constraint:
periodicity = constraints.rectangular_periodic_mpc(displacement)
result = model.step(
target=displacement,
constraints=periodicity,
).solve_result()
The linear provider separates ordinary Dirichlet data from exact MPC
elimination before assembly and supports the same route in serial and MPI.
Only one exact-MPC provider may own a linear system. The solved field and
constraint-construction diagnostics are retained in the Result. After a
converged solve, the provider recovers the owned slave multipliers from the
full residual, publishes a nodal rectangular_periodic_mpc_reaction field,
checks the constraint gap, and contributes its physical resultant and virtual
work to the common balance ledger. The current relation is homogeneous, so
its capability contract declares exact zero constraint work rather than
inventing an endpoint coordinate; affine macroscopic loading and nonlinear
path work use typed accepted-path evidence from the affine-periodic provider.
Solver convergence alone is not used to invent any missing dual quantity.
Axisymmetric solids¶
Declare the formulation on the Study; do not manually insert cylindrical weights into an ordinary planar model:
study = studies.static_solid(dimension=2, assumption="axisymmetric")
model = models.create(study=study, mesh=meridian)
u = model.field(fields.displacement(meridian, degree=2))
model.material(constitutive.isotropic_elastic(young=E, poisson=nu))
model.pressure(p, on=inner_wall)
result = model.step(target=u).solve_result()
Coordinates and displacement are \((r,z)\); S and E are full
\((r,\theta,z)\) tensors. Pressure, traction, body loads, energy, and standard
projection automatically use \(2\pi r\). When calling a public result integral
directly, pass study=study to request the same physical measure. See the
axisymmetric thick-cylinder source.
If the meridian reaches r=0, register
constraints.axisymmetric_axis(u, on=axis); model validation warns when that
regularity declaration is absent.
Finite-strain J2 plasticity¶
The same material and model.step(...) vocabulary selects one compatible
equilibrium provider. Ordinary solids use strong Dirichlet or
remote-displacement constraints and may include body forces or natural loads
defined in the reference configuration:
material = model.material(
constitutive.finite_strain_j2_logarithmic(
young=210e3,
poisson=0.3,
yield_stress=250.0,
hardening_modulus=1e3,
)
)
model.fix(u, on=clamp, value=(0.0, 0.0, 0.0))
model.body_force((0.0, 0.0, -body_force), target=u)
step = model.step(
target=u,
material=material,
incrementation=steps.automatic(initial=0.1, maximum=0.2),
)
result = step.solve_result()
For a nonmonotone amplitudes.tabular(...) load path, its interior table
times are mandatory accepted stations in the normalized Step coordinate.
steps.fixed(...) must include each station (use steps.at(...) for a
nonuniform path); steps.automatic(...) lands on them before continuing.
The shared Step amplitude also drives a prescribed rigid tool. Output-frame
selection remains separate from these material-history stations. A custom
amplitude without declared table knots requires the user to resolve its
reversals in the increment path explicitly. A tabular asset copies its input
arrays and fingerprints its creation-time metadata, so mutating caller arrays
later cannot silently change a checkpointed path.
The ordinary finite-J2 Step also has a bounded experimental serial route for
registered, prescribed rigid contact pairs: analytical planes or spheres,
reviewed triangular surfaces, certified closed-convex triangular solids, and
explicitly reviewed closed nonconvex triangle solids in the later source
candidate. The latter requires an embedding attestation, rejects ambiguous
nearest features, and has a serial O(facets) winding-sign cost.
The contact residual and tangent enter the same Newton, line-search, accepted
State, work, and checkpoint lifecycle as the material. A certified convex
solid or a reviewed triangular tool on an active face-interior planar branch
can use the bounded penalty-Coulomb tangential law. For an open triangle
patch, active noncoplanar edges or vertices remain unsupported; the certified
closed-convex tool has a separate one-sided selected-feature branch. Curved
tool friction and distributed implicit friction remain unsupported. This is
experimental, not general frictional contact. Multiple named pairs and a
two-region J2 material map have serial regression evidence. Unsupported
geometry, material/contact composition, or MPI operation fails before solve;
do not infer general industrial-contact support from this route. See
examples/finite_j2_closed_convex_contact.py and
examples/finite_j2_hertz_contact.py for the supported shapes and the
remaining independent accuracy gap.
For a first- or second-order tetrahedral or hexahedral contact boundary, the
optional contact_quadrature_degree=5, 7, 9 or 11 selects a positive
Basix face rule: 7, 15, 19 or 28 points per triangle, or 3×3, 4×4, 5×5 or
6×6 points per quadrilateral.
The CG1 defaults remain three-point triangles and 2×2 quadrilaterals; a CG2
trace retains its degree-four default. It is a convergence-study control, not an accuracy
preset: higher contact integration did not monotonically improve a finite-
block Hertz screen. The benchmark separately reports the analytic pressure
sampled on the actual trace and a nominal pressure difference, because a
close total force can hide an inaccurate pressure distribution. The chosen
rule likewise changes sampled physical-edge contact on a reviewed reentrant
tool; mesh and penalty sensitivity remain mandatory before engineering use.
For such a tool, the result records sampled slave faces spanning multiple
nearest features. If any are observed without a certified feature-transition
integral, result.verify("engineering") and result.verify("release") fail
the corresponding runtime claim. "exploratory" still permits inspection;
zero observed mixed faces is not proof that the full contact boundary was
integrated accurately. Release verification therefore requires a certified
feature integral for every polyhedral pair, even when sampled mixed-face and
active-point counts are both zero: no sampled contact does not prove whole-face
separation. A passed runtime check still needs an
independent scientific reference before the result can be called verified.
Serial standard and periodic/MPC finite-J2 paths retain those sampled
feature observations across every accepted station and checkpoint, rather
than only the final output frame. A checkpoint written before this ledger
existed may resume, but its earlier feature history is explicitly incomplete;
it cannot acquire a clean engineering claim by replaying only the last part.
This path record is observational evidence, not a proof that a changing
nonconvex contact boundary was integrated consistently.
The rule is part of the checkpoint identity. Both the strong-boundary and
affine-periodic/MPC finite-J2 penalty-contact paths accept this explicit
control; restoring a checkpoint with a different rule is rejected before
changing the accepted state. Nodal normal augmentation and partitioned-face
integration use their own integration definitions and reject this Gauss-rule
override. Legacy plane contact also rejects it; no unsupported combination
silently falls back. Other weak boundary models and
formulations need their own reviewed lowering.
For the narrower experimental case of a frictionless, scalar-penalty analytical plane
against an affine CG1 tetrahedral slave boundary, the ordinary Step can select
contact_integration="planar_active_partition". It partitions each
sign-crossing triangle at the current trial zero-gap contour and uses positive
reference-area quadrature on its active part. This avoids a documented blind
spot where a small contact strip falls between all ordinary face points.
The same trial partition supplies residual and tangent, and the choice is
checkpoint-identified. It is not an automatic fix for curved or faceted tools,
sharp features, friction, higher-order/quad faces, or MPI. Exported point IDs
in this mode identify one accepted snapshot, not a stable material point across
increments. Use independent mesh/penalty/increment checks before interpreting
local contact pressure or plasticity as engineering results.
The separate experimental contact_integration="convex_feature_partition"
option addresses a certified closed-convex rigid tool when an affine CG1
tetrahedral slave triangle has at most four positive-area dominant support
planes. It partitions both the active area and the compressed feature switch;
the latter contributes a line term to the Newton tangent. A moving/rotating
tool, force--moment work, total J2-plus-contact Jacobian, affine-periodic MPC
reduction, and interrupted restart have bounded regressions. The option
requires frictionless scalar-penalty contact, the default three-point
reference triangle rule, and a single MPI rank. More than four dominant planes
or an undefined boundary-aligned feature switch rejects the trial; no normal is
smoothed or third feature discarded. Accepted contact-point IDs are local to
that snapshot. This does not apply to concave STL geometry, nonlinear
nearest-edge/vertex distance branches, frictional edge transitions, or
general hard contact. Its successful small tests are not a penalty- or
mesh-convergence certificate.
For a still narrower experimental subset of a reviewed closed, possibly
concave rigid solid, the ordinary serial finite-J2 Step can use
contact_integration="closed_planar_branch_partition". At every Newton trial,
it proves that every current affine P1 slave triangle projects wholly inside
one coplanar smooth master patch and that no other noncoplanar master feature can
become nearer anywhere on that face. Different slave faces may have different
certified planes; one face may not cross a master feature. Only then does it
reuse the exact active-plane reference-area partition on each face.
It can cross an internal coplanar triangulation seam, provided bounded
polygon subtraction proves complete patch coverage. It refuses a physical
sharp edge, competing vertex, uncovered patch, friction, higher-order
trace, unsupported quadrature, or geometry above its explicit proof budget;
it never substitutes a sampled normal. The bound is checked again after a
rigid translation or rotation and is checkpoint-identified. It is useful for
a small smooth patch of a larger complex tool, not general nonconvex
contact or an edge/point law. A separate whole-face signed-distance check can
certify zero contact at an accepted configuration; neither certificate proves
nonintersection between accepted stations. See the runnable
closed-tool smooth-face example.
When an ordinary serial finite-J2 Step has several named rigid pairs, supply
contact_integration={"closed_tool": "closed_planar_branch_partition",
"flat_tool": "planar_active_partition"} to select their already supported
rules independently. The mapping must name every pair exactly; adding a
tool cannot silently give it the default sampled rule. Its selected mode is
part of each pair's checkpoint identity. The affine-periodic J2 route does
also admit exact-name per-pair mode mappings for its otherwise supported
serial P1 rigid pairs. The total contact residual and tangent are reduced
through the same MPC transformation. A verified smooth branch on a reviewed
closed tool is still required at every trial; assigning that mode does not
turn a sharp edge into an admitted contact law.
The same whole-face proof can also be requested for a consistently oriented,
reviewed open triangulated tool with
contact_integration="reviewed_planar_branch_partition". This is a
one-sided oriented sheet, not a closed solid with inside/outside semantics.
The matching triangle BVH finds the current nearest facet; a complete
coplanar patch must cover each projected affine slave face, and every
noncoplanar facet must be proven farther over that entire face. A moving or
rotating sheet, a coplanar triangulation seam, total J2-plus-contact residual,
periodic MPC reduction and interrupted restart have serial regressions.
An uncovered rim or true master feature switch rejects the Newton trial;
the option does not provide edge/point contact, arbitrary STL admission,
friction or parallel implicit assembly. The earlier
closed_planar_branch_partition spelling remains available specifically
for reviewed closed solids. The same small example supports
--tool-kind open_sheet; its result and contact samples are exported to a
single named output directory unless --output is supplied.
For an analytical plane and first-order tetrahedral/hexahedral reference
geometry, initial_penetration_limit is checked at authoritative face
vertices, including when displacement uses CG2. A quadratic field does not
make the reference geometry quadratic. The check does not bound a later
deformed CG2 face, and curved reference geometry remains unsupported for
this vertex certificate. Whole-cell interpolation nodes and sampled Gauss
gaps are not substitutes for the selected face's geometry vertices.
For an affine P1 triangular slave against a reviewed closed convex tool,
initial_penetration_limit also uses a face-wise certificate. If one rigid
support plane dominates at every triangle vertex, its affine nodal minimum
bounds the whole face; mixed-feature faces retain the adaptive signed-distance
check. This admits near-touching planar patches without treating three
ordinary Gauss samples as a whole-face proof. That closed-solid signed-distance
argument does not apply to open sheets, higher-order geometry or the later
sliding path; the separate open-sheet bound below needs its own oriented
whole-face planar-branch proof.
The runnable, dimensionless feature-partition example exercises the ordinary installed-package workflow; it is a regression fixture, not an external forming benchmark.
An open reviewed sheet may also declare initial_penetration_limit only
with reviewed_planar_branch_partition on affine P1 triangular faces. The
same complete-coverage/nearest-branch proof is repeated at the reference
pose; its oriented plane gap is affine, so the worst penetration is bounded
at face vertices. A rim, competing feature or exhausted proof budget rejects
the model. Ordinary sampled gauss contact does not inherit this guarantee.
Bulk and contact integration are separate choices. For an ordinary CG2
hexahedral finite-J2 displacement field, model.step(...) selects bulk
quadrature_degree=4 by default; an explicit lower degree is rejected before
solving because it can leave displacement modes uncontrolled. This safeguard
does not establish mesh-independent contact accuracy or stability for every
material path.
Affine-periodic cells¶
constitutive.finite_strain_j2_logarithmic(...) is lowered by the ordinary
model.step(...) interface when a three-dimensional nonlinear-static model
contains compatible explicitly partitioned material regions and exactly one
AbaqusPeriodicConstraint. This provider prescribes the macroscopic
deformation gradient; it does not accept
body or natural loads. Serial execution uses exact affine reduction and MPI
execution uses the reviewed dolfinx_mpc reduction.
A proportional endpoint may be passed as deformation_gradient=F_end. For
unloading, reloading, or a change of loading direction, declare the physical
matrix history explicitly:
macro_path = constraints.deformation_gradient_path(
(0.0, 0.35, 0.65, 1.0),
(F_identity, F_loaded, F_unloaded, F_shear),
)
periodicity = constraints.abaqus_periodic_cell(
displacement,
nodes=nodes,
equations=equations,
anchor_node=anchor,
reference_nodes=references,
deformation_gradient_path=macro_path,
)
step = model.step(
target=displacement,
material=material,
constraints=periodicity,
incrementation=steps.automatic(initial=0.2, maximum=0.2),
)
The normalized step coordinate remains increasing while the physical deformation-gradient components may reverse. The path must start at the identity and preserve positive determinant throughout every linear segment. Every path knot is a mandatory accepted boundary: fixed incrementation that omits one fails before assembly, while automatic incrementation lands on it. The complete path enters the constraint fingerprint and checkpoint identity. Knots define the physical loading history; they are not, by themselves, a constitutive-integration convergence study. Refine the accepted increments between knots when plastic history accuracy matters.
Accepted increments retain provider-owned quadrature fields F, P, S,
MISES, SENER, ELENER, HARDENER, PDENER, FP, and PEEQ, with
separately named cell averages for visualization. For this material,
SENER = ELENER + HARDENER; it records recoverable elastic and hardening
storage, not accumulated plastic dissipation. The same accepted boundary can
be checkpointed and restored across a compatible MPI repartition. This route
remains experimental. The true spherical-void RVE has geometric pairing,
positive-J, Hill--Mandel, public-lifecycle, and two-rank execution evidence,
and now has a versioned fixed-stack Golden. That Golden freezes one
h/L=0.25 first-order mesh, two accepted increments, the runtime stack, and
the portable mesh identity. It detects software drift in the macroscopic
first-Piola stress, physical-weighted PEEQ distribution, and solid fraction;
it is not a mesh-converged RVE reference solution. A separate opt-in check
compares two and four increments and two successive mesh levels. Passing that
check establishes only the declared successive-refinement stability, not
formal asymptotic convergence or a GCI uncertainty estimate. The independent
Zhang et al. periodic-composite gate still fails rather than being promoted.
Experimental serial 3D P2/DG0 and 2D plane-strain Q2/DPC1 mixed affine routes
now solve an independent tension-positive MEAN_KIRCHHOFF_STRESS, assemble
all four mixed Newton blocks, and keep the condensed ELENER representation
separate from MIXED_POTENTIAL. Their
thin-3D tetrahedral diagnostic remains distinct from the now executable 2D
Q2/DPC1 interpolation. The direct Zhang driver now evaluates the geometry,
stress, primal/condensed energy channels and a Schur-condensed current-state
effective tangent. Its homogeneous analytical tangent check has passed, but
the published Table 5 comparison, load-path and formulation convergence,
cell-replication checks, distributed mixed MPC/restart, and a production
mixed-formulation conditioning study remain promotion gates. The local
finite-strain J2 return now uses an analytical spectral dP/dF by default and
retains a central-difference oracle for verification.