jaxdem.bonded_forces.plastic_perimeter_deformable_particle#

Implementation of the plastic perimeter deformable particle model.

Classes

PlasticPerimeterDeformableParticleModel(...)

Deformable particle model with perimeter-level plasticity.

class jaxdem.bonded_forces.plastic_perimeter_deformable_particle.PlasticPerimeterDeformableParticleModel(elements: Array | None, edges: Array | None, element_adjacency: Array | None, element_adjacency_edges: Array | None, elements_id: Array | None, edges_id: Array | None, initial_body_contents: Array | None, initial_element_measures: Array | None, initial_edge_lengths: Array | None, initial_bendings: Array | None, w_b: Array | None, em: Array | None, ec: Array | None, eb: Array | None, el: Array | None, gamma: Array | None, tau_s: Array | None)#

Bases: BondedForceModel

Deformable particle model with perimeter-level plasticity.

Elastic forces are identical to DeformableParticleModel (individual edge springs, measure, content, bending, and surface-tension terms are all preserved). The only difference is in the plastic update rule.

Instead of relaxing each edge rest length independently (as in PlasticDeformableParticleModel), the total reference perimeter of each body relaxes toward the current total perimeter, and the change is distributed back to individual edges by uniform rescaling:

\[\begin{split}P_{K,0}^{\text{new}} &= P_{K,0} + \frac{1}{\tau_{s,K}} (P_K - P_{K,0})\,dt \\ L_{e,0}^{\text{new}} &= L_{e,0}\;\frac{P_{K,0}^{\text{new}}}{P_{K,0}} \qquad \forall\, e \in K\end{split}\]

where \(P_K = \sum_{e \in K} L_e\) is the current perimeter, \(P_{K,0} = \sum_{e \in K} L_{e,0}\) the reference perimeter, \(\tau_{s,K}\) the per-body relaxation time, and \(dt\) the time step. Uniform rescaling preserves relative edge proportions within each body.

This model requires an edges_id mapping (shape (E,)) that assigns each edge to its owning body, analogous to elements_id for elements. When only a single body is present and edges_id is omitted, all edges are assumed to belong to body 0.

Shapes (see DeformableParticleModel for definitions of K, M, E, A):

  • edges_id: (E,)

  • tau_s: (K,)

elements: Array | None#

Array of vertex indices forming the boundary elements. Shape: (M, 3) for 3D (Triangles) or (M, 2) for 2D (Segments). Indices refer to the particle unique_id. Vertices correspond to State.pos.

edges: Array | None#

(E, 2). Each row contains the indices of the two vertices forming the edge. Note: In 2D, the set of edges often overlaps with the set of elements (segments).

Type:

Array of vertex indices forming the edges. Shape

element_adjacency: Array | None#

(A, 2). Each row contains the indices of the two elements sharing a connection.

Type:

Array of element adjacency pairs (for bending/dihedral angles). Shape

element_adjacency_edges: Array | None#

(A, 2). This can be independent from edges because we could have extra edge springs that do not correspond to the mesh connectivity.

Type:

Array of vertex IDs forming the shared edge for each adjacency. Shape

elements_id: Array | None#

(M,). elements_id[i] == k means element i belongs to body k.

Type:

Array of body IDs for each boundary element. Shape

edges_id: Array | None#

(E,). edges_id[e] == k means edge e belongs to body k. Required for perimeter-level plasticity.

Type:

Array of body IDs for each edge. Shape

initial_body_contents: Array | None#

(K,). Represents Volume in 3D or Area in 2D.

Type:

Array of reference (stress-free) bulk content for each body. Shape

initial_element_measures: Array | None#

(M,). Represents Area in 3D or Length in 2D.

Type:

Array of reference (stress-free) measures for each element. Shape

initial_edge_lengths: Array | None#

(E,).

Type:

Array of reference (stress-free) lengths for each unique edge. Shape

initial_bendings: Array | None#

(A,). Represents Dihedral Angle in 3D or Vertex Angle in 2D.

Type:

Array of reference (stress-free) bending angles for each adjacency. Shape

w_b: Array | None#

(A,). 3D: hinge_length0 / dual_length0 with dual_length0 between face centers. 2D: 1 / dual_length0 with dual_length0 = 0.5 * (L_left0 + L_right0).

Type:

Precomputed bending normalization coefficient per adjacency. Shape

em: Array | None#

(M,). (Controls Area stiffness in 3D; Length stiffness in 2D).

Type:

Measure elasticity coefficient for each element. Shape

ec: Array | None#

(K,). (Controls Volume stiffness in 3D; Area stiffness in 2D).

Type:

Content elasticity coefficient for each body. Shape

eb: Array | None#

(A,).

Type:

Bending elasticity coefficient for each hinge. Shape

el: Array | None#

(E,).

Type:

Edge length elasticity coefficient for each edge. Shape

gamma: Array | None#

(M,).

Type:

Surface/Line tension coefficient for each element. Shape

tau_s: Array | None#

(K,). Controls how fast the total reference perimeter of each body relaxes toward the current perimeter.

Type:

Plastic relaxation time for each body. Shape

classmethod Create(*, vertices: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None, elements: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None, edges: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None, element_adjacency: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None, element_adjacency_edges: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None, elements_id: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None, edges_id: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None, initial_body_contents: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None, initial_element_measures: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None, initial_edge_lengths: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None, initial_bendings: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None, em: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None, ec: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None, eb: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None, el: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None, gamma: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None, tau_s: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None, w_b: Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray | None = None) Self[source]#
static merge(model1: BondedForceModel, model2: BondedForceModel | Sequence[BondedForceModel]) BondedForceModel[source]#

Merge two or more bonded-force models into one.

Concatenates topology, reference, and coefficient arrays. Vertex indices and body IDs are shifted automatically so that references remain consistent. When one side carries a term that the other does not, missing coefficients are padded with 0 and missing reference values with 1.

Parameters:
Returns:

A new model containing all bodies from both sides.

Return type:

BondedForceModel

static add(model: BondedForceModel, **kwargs: Any) BondedForceModel[source]#

Create a new body from raw arrays and merge it into an existing model.

This is a convenience wrapper equivalent to calling the concrete Create constructor followed by merge().

Parameters:
  • model (BondedForceModel) – Existing model to extend.

  • **kwargs – Constructor arguments forwarded to the concrete Create method (e.g. vertices, elements, coefficients, …).

Returns:

The extended model.

Return type:

BondedForceModel

static compute_potential_energy_w_aux(pos: jax.Array, state: State, system: System) tuple[jax.Array, dict[str, jax.Array]][source]#
static compute_potential_energy(pos: jax.Array, state: State, system: System) jax.Array[source]#
static compute_forces(pos: jax.Array, state: State, system: System) tuple[jax.Array, jax.Array][source]#
property force_and_energy_fns: tuple[ForceFunction, EnergyFunction, bool][source]#

Build bonded force/energy callables consumed by the force manager.

Returns:

(force_fn, energy_fn, is_com_force) where:

  • force_fn computes bonded force and torque contributions.

  • energy_fn computes bonded potential-energy contributions.

  • is_com_force indicates where force is applied: True for center-of-mass application, False for contact-point application. This has no effect on spheres.

Return type:

Tuple[ForceFunction, EnergyFunction, bool]