Skip to content

trusty.fem

FEM solid bodies.

ElementOrder

Bases: Enum

Linear class-attribute instance-attribute

Linear = 0

Quadratic class-attribute instance-attribute

Quadratic = 1

QuadraticSerendipity class-attribute instance-attribute

QuadraticSerendipity = 2

add_hex_solid

add_hex_solid(
    world: World,
    mesh: HexMesh,
    material: StableNeoHookean
    | Corotational
    | StableFung
    | NeohookeanBW
    | ARAP
    | QuadraticVolume,
    density: float,
    *,
    order: ElementOrder = ElementOrder.Linear,
    consistent_mass: bool = True,
    friction_mu: float = 0.0,
) -> int

Add a hex solid body running material (a constitutive model carrying the parameters it reads). order selects Q1 linear (default), Q2 Lagrange (Quadratic), or Q2 serendipity (QuadraticSerendipity); quadratic orders promote the linear mesh internally. consistent_mass (default True) runs a quadratic body on the consistent mass matrix; False falls back to HRZ-lumped mass. Linear bodies are lumped either way. friction_mu is the body's surface Coulomb coefficient (>= 0); 0 is frictionless.

add_tet_solid

add_tet_solid(
    world: World,
    mesh: TetMesh,
    material: StableNeoHookean
    | Corotational
    | StableFung
    | NeohookeanBW
    | ARAP
    | QuadraticVolume,
    density: float,
    *,
    order: ElementOrder = ElementOrder.Linear,
    consistent_mass: bool = True,
    friction_mu: float = 0.0,
) -> int

Add a tet solid body running material. order selects P1 linear (default) or P2 (Quadratic); P2 promotes the linear mesh internally. consistent_mass (default True) runs a P2 body on the consistent mass matrix; False falls back to HRZ-lumped mass. friction_mu is the body's surface Coulomb coefficient (>= 0); 0 is frictionless.

apply_affine_transform

apply_affine_transform(
    world: World,
    body: int,
    A: ndarray[float64, (3, 3)],
    t: tuple[float, float, float],
) -> None

Apply a general affine map p -> A p + t to a body's current positions, leaving its rest geometry alone: the body starts strained and relaxes toward its unchanged rest shape once stepped. To place a body instead, pass the mesh through transform_mesh before building it.

set_velocity

set_velocity(
    world: World, body: int, v: ndarray[float64, (N, 3)]
) -> None

Overwrite per-node velocities for a body. v must have shape (num_nodes, 3). Read when the simulator is built (the first step); each step publishes the end-of-step velocities back.

pin_face

pin_face(
    world: World,
    body: int,
    axis: int,
    coord: float,
    tol: float = 1e-06,
) -> None

read_mesh

read_mesh(world: World, body: int) -> HexMesh

read_tet_mesh

read_tet_mesh(world: World, body: int) -> TetMesh

Read back the current deformed mesh of a tet solid. Returns an empty TetMesh if body is a hex body.

read_positions

read_positions(
    world: World, body: int
) -> ndarray[float64, (N, 3)]

Read the current deformed node positions (num_nodes, 3) of any solid body, regardless of element family (linear or quadratic).

read_surface_triangles

read_surface_triangles(
    world: World, body: int
) -> ndarray[int32, (N, M)]

Boundary triangles (F, 3) indexed into read_positions. Quadratic bodies return the linear sub-triangle tessellation of the curved surface (corner/edge/center nodes) used for contact and rendering.

read_von_mises

read_von_mises(
    world: World,
    body: int,
    nodal: bool = True,
    unit_material: bool = False,
) -> ndarray[float64, (N,)]

Von Mises Cauchy stress (Pa) of a hex solid at the current deformation. nodal=True returns a superconvergent per-node field (length num_nodes); nodal=False returns raw per-element values (length num_hexes). unit_material=True evaluates with unit moduli (mu = lam = 1) everywhere -- a stiffness-independent strain measure, so a soft and a stiff region are comparable.

read_strain_energy_density

read_strain_energy_density(
    world: World,
    body: int,
    nodal: bool = True,
    unit_material: bool = False,
) -> ndarray[float64, (N,)]

Hyperelastic strain energy density (J/m^3 = Pa) of a hex solid at the current deformation -- unlike von Mises it includes the volumetric (pressure) term. nodal=True returns a superconvergent per-node field (length num_nodes); nodal=False returns raw per-element values (length num_hexes). See read_von_mises for unit_material.