Skip to content

Models

A FEM model combines a mesh (nodes and elements) with a material to form a solvable finite-element problem. All models share the same workflow:

  1. Create the model from nodes, elements, and a material. Several models can be combined as one system in an Assembly and coupled by kinematic constraints.
  2. Apply loads and boundary conditions by setting entries of the model attributes: forces and displacements for mechanics models (Truss, Planar, Shell, Solid), or heat_flux and temperatures for thermal models (TrussHeat, PlanarHeat, ShellHeat, SolidHeat). Prescribed values are activated by setting the corresponding entries of the boolean mask constraints to True. A distributed load, such as gravity or a pressure, becomes nodal values with the load integrators below.
  3. Solve with solve(), which returns the nodal solution, the internal nodal forces, and the flux, gradient, and material state at the elements.
  4. Postprocess the resulting tensors, e.g. with plot().

See Getting Started for a worked example.

All models inherit their construction and solution interface from the abstract base class FEM:

FEM

Bases: ABC

Abstract base class for all finite-element models.

A model is defined by nodal coordinates, an element connectivity, and a material. Loads and boundary conditions are set through attributes of the concrete model classes, and the quasi-static solution is computed with solve().

Attributes:

  • nodes

    Nodal coordinates with shape [n_nod, n_dim].

  • elements

    Element connectivity with shape [n_elem, nodes_per_element].

  • material (Material | None) –

    Vectorized material model (or None for laminate shells).

  • constraints (Tensor) –

    Boolean mask of constrained degrees of freedom with shape [n_nod, n_dof_per_node].

  • n_nod

    Number of nodes.

  • n_elem

    Number of elements.

  • n_dofs

    Total number of degrees of freedom.

__init__(nodes, elements, material)

Initialize a finite-element model.

Parameters:

  • nodes (Tensor) –

    Nodal coordinates with shape [n_nod, n_dim].

  • elements (Tensor) –

    Connectivity with shape [n_elem, n_nodes_per_element].

  • material (Material | None) –

    Material model. If not vectorized, it is vectorized over elements during initialization. May be None for shells that use a laminate section instead.

solve(increments=None, max_iter=10, rtol=1e-08, atol=1e-06, stol=1e-10, cutback_factor=0.5, growth_factor=1.1, max_cutbacks=10, verbose=False, method=None, preconditioner=None, device=None, return_intermediate=False, aggregate_integration_points=True, alpha=0.0, differentiable_parameters=None)

Solve the quasi-static finite-element problem by load increments.

Parameters:

  • increments (Tensor | None, default: None ) –

    Load scale factors, typically [0, 1]. They may rise and fall, so a load cycle is expressed as a sequence like [0, 1, 0]. Results are always returned at exactly these values. If a Newton solve does not converge, the increment is subdivided internally and retried, and the substep is grown again after each success.

  • max_iter (int, default: 10 ) –

    Maximum Newton iterations before an increment is cut back.

  • rtol (float, default: 1e-08 ) –

    Relative residual tolerance for Newton convergence.

  • atol (float, default: 1e-06 ) –

    Absolute residual tolerance for Newton convergence.

  • stol (float, default: 1e-10 ) –

    Tolerance used by iterative linear solvers.

  • cutback_factor (float, default: 0.5 ) –

    Factor applied to the substep size after a Newton solve failed to converge.

  • growth_factor (float, default: 1.1 ) –

    Factor applied to the substep size after a Newton solve converged, capped at the requested increment.

  • max_cutbacks (int, default: 10 ) –

    Number of successive cutbacks accepted within an increment before the solve is given up.

  • verbose (bool, default: False ) –

    If True, reports the solver configuration and a table of per-increment progress, updated in place inside notebooks.

  • method (Literal['direct', 'cg', 'bicgstab'] | None, default: None ) –

    Linear solver method, chosen by size and tangent symmetry when omitted.

  • preconditioner (Literal['amg', 'jacobi', 'none'] | None, default: None ) –

    Preconditioner for an iterative method, chosen by device and available backends when omitted.

  • device (str | None, default: None ) –

    Optional device hint for the linear solver backend.

  • return_intermediate (bool, default: False ) –

    If True, returns values for all increments.

  • aggregate_integration_points (bool, default: True ) –

    If True, averages flux, gradient, and state over integration points.

  • alpha (float, default: 0.0 ) –

    Damping factor for viscous stabilization. Dissipated energy is accumulated in self.stabilization_energy.

  • differentiable_parameters (Tensor | Iterable[Tensor] | None, default: None ) –

    Explicit parameter(s) to differentiate through implicit Newton/sparse solves. Accepts either a single tensor or an iterable of tensors.

Returns:

  • tuple[Tensor, Tensor, Tensor, Tensor, Tensor]

    Tuple of displacement, internal force, flux, gradient, and material state. If return_intermediate is True, each tensor includes an increment dimension as the leading axis.

integrate_field(field=None)

Integrate a nodal scalar field over each element.

The measure is that of the mesh and excludes volume_scale, so a planar model integrates over areas and a truss over lengths. Scaling to a volume is left to the caller, which keeps this constant where a thickness or a cross section is a design variable.

Parameters:

  • field (Tensor | None, default: None ) –

    Nodal scalar values with shape [n_nod]. If None, integrates a unit field and therefore returns the measure of each element.

Returns:

  • Tensor

    Per-element integral values with shape [n_elem].

Loads

A distributed load is integrated into consistent nodal loads, which are added to the forces of a mechanics model or the heat_flux of a thermal one:

model.forces += model.integrate_body_load([0.0, -rho * g])

Which integrators a model offers follows from the dimension of its elements:

Model Body Surface Line
Truss, TrussHeat
Planar, PlanarHeat
Shell, ShellHeat
Solid, SolidHeat

integrate_body_load(load)

Consistent nodal loads from a load per unit volume, e.g. gravity.

Parameters:

  • load (float | Tensor) –

    Load per unit volume as a float, with shape [k] if uniform, or with shape [n_elem, k] to vary it per element. k is the number of loaded degrees of freedom per node, i.e. n_dim for a force and 1 for a heat source.

Returns:

  • Tensor

    Nodal loads with shape [n_nod, k], to be added to forces or heat_flux.

integrate_surface_load(mask, load)

Consistent nodal loads from a load per unit area on a surface.

The surface is made up of the element faces whose nodes all lie in mask and that are on the boundary of the mesh.

Parameters:

  • mask (Tensor) –

    Boolean nodal mask with shape [n_nod] selecting the surface.

  • load (float | Tensor) –

    Load per unit area. A float is a pressure acting along the outward normal, while shape [k] or [n_face, k] is a traction in global coordinates.

Returns:

  • Tensor

    Nodal loads with shape [n_nod, k], to be added to forces or heat_flux.

A Shell element is its own surface, so Shell.integrate_surface_load(...) loads the elements in the mask rather than the boundary faces of the mesh.

integrate_line_load(mask, load)

Consistent nodal loads from a load per unit length on a line.

The line is made up of the element edges whose nodes all lie in mask and that are on the boundary of the mesh.

Parameters:

  • mask (Tensor) –

    Boolean nodal mask with shape [n_nod] selecting the line.

  • load (float | Tensor) –

    Load per unit length with shape [k] or [n_edge, k]. For a planar model a float is a pressure acting along the outward normal.

Returns:

  • Tensor

    Nodal loads with shape [n_nod, k], to be added to forces or heat_flux.