Skip to content

Assembly

Assembly

Several models coupled by kinematic constraints.

Parts keep their own nodes, elements, materials and boundary conditions. The assembly stacks their degrees of freedom into one global vector, in the order the parts are given, and couples them with coupling(...): translations follow u_secondary = u_primary + theta_primary x (x_secondary - x_primary) and rotations follow theta_secondary = theta_primary. A primary without rotations leaves a pure translation link, which joins a coincident mechanical interface and holds two thermal meshes at one temperature.

Constraints are enforced by eliminating the secondary degrees of freedom, so the solved system stays symmetric and positive definite and needs no penalty parameter. The parts must share one physics and one spatial dimension.

A coupling is linearized about the reference configuration, so it never rotates.

Attributes:

  • parts

    The coupled models, in global degree-of-freedom order.

  • n_dofs

    Total number of degrees of freedom, before elimination.

__init__(parts)

Initialize an assembly from its parts.

Parameters:

  • parts (Sequence[Part]) –

    Models and points to couple. They must share one physics, either all mechanical or all thermal.

Raises:

  • ValueError

    If a part appears twice, or the parts mix physics or spatial dimensions.

coupling(secondary, mask, primary, primary_mask=None, dofs=None)

Couple nodes of a part to the nearest nodes of another part.

Each secondary node follows the rigid-body motion of the primary node closest to it: a single-node primary such as a reference point drives them all, a primary surface pairs a coincident interface node for node, and a solid's through-thickness nodes pair with the shell node whose rotation carries their offset.

Parameters:

  • secondary (Part) –

    Part whose degrees of freedom are eliminated.

  • mask (Tensor) –

    Boolean nodal mask with shape [n_nod] selecting the coupled nodes of secondary.

  • primary (Part) –

    Part driving the motion.

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

    Boolean nodal mask selecting the candidate nodes of primary. Defaults to all of them, which is the single node of a ReferencePoint.

  • dofs (Iterable[int] | None, default: None ) –

    Degrees of freedom of secondary to couple, as indices into its degrees of freedom per node. Defaults to all of them, so dofs=[2] couples only the displacement along z.

solve(increments=None, max_iter=10, rtol=1e-08, atol=1e-06, stol=1e-10, verbose=False, method=None, preconditioner=None, device=None, return_intermediate=False, aggregate_integration_points=True, differentiable_parameters=None)

Solve the constrained quasi-static problem by load increments.

Parameters:

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

    Load scale factors, typically [0, 1]. Unlike FEM.solve(...), an increment that does not converge is not subdivided, so a nonlinear problem needs its own increments.

  • max_iter (int, default: 10 ) –

    Maximum Newton iterations per increment.

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

  • verbose (bool, default: False ) –

    If True, reports solver configuration and progress.

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

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

    Explicit parameter(s) to differentiate through the implicit Newton solve.

Returns:

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

    Tuple of displacement, internal force, flux, gradient, and material state, each a list with one entry per part. A reference point contributes empty flux, gradient and state. A retained DOF carries what the constraints transmit into it, so its force is the reaction where it is constrained and the coupling load at a reference point, while an eliminated one carries the part's own internal force.

Raises:

  • ValueError

    If a constrained degree of freedom is eliminated.

plot(u=0.0, **kwargs)

Plot the assembly in 2D (matplotlib) or 3D (PyVista).

Dispatches to plot2d or plot3d based on the spatial dimension.

Parameters:

  • u (list[Tensor] | float, default: 0.0 ) –

    Nodal displacements per part, e.g. the u of solve(...). Defaults to 0.0 (undeformed).

  • **kwargs

    Forwarded to plot2d or plot3d, and from there to every part's own plot(...). A list is spread over the parts, inside a dict too, so node_property={"u": u} splits like u. bcs=True renders the boundary conditions of the parts and of the reference points alike.

ReferencePoint

A free node with rigid-body degrees of freedom and no stiffness.

Coupling nodes to it makes them follow its rigid-body motion, which is how a moment reaches a solid mesh whose nodes carry translations only. The position sets the dimension: three translations and three rotations in 3D, two and one in 2D.

Attributes:

  • nodes

    Position with shape [1, n_dim].

  • forces

    Applied forces and moments with shape [1, n_dofs].

  • displacements

    Prescribed displacements and rotations with shape [1, n_dofs].

  • constraints

    Boolean mask of constrained DOFs with shape [1, n_dofs].

__init__(position)

Initialize a reference point at position, of shape [2] or [3].

ReferencePointHeat

A free node with one temperature and no heat capacity.

Coupling nodes to it holds them at one common temperature, so a surface can be driven by a single heat source and its total heat flow read back.

Attributes:

  • nodes

    Position with shape [1, n_dim].

  • heat_flux

    Applied heat source with shape [1, 1].

  • temperatures

    Prescribed temperature with shape [1, 1].

  • constraints

    Boolean mask of constrained DOFs with shape [1, 1].

__init__(position)

Initialize a thermal reference point at position, of shape [2] or [3].