jaxdem.bonded_forces.deformable_particle#
Implementation of the deformable particle model.
Functions
|
Unsigned angle between normals. |
|
|
|
|
|
Signed bending angles of the current configuration. |
|
Signed bending angle per element adjacency. |
Classes
|
Model for 2D and 3D deformable bodies built from surface meshes. |
- class jaxdem.bonded_forces.deformable_particle.DeformableParticleModel(elements: Array | None, edges: Array | None, element_adjacency: Array | None, element_adjacency_edges: Array | None, elements_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)#
Bases:
BondedForceModelModel for 2D and 3D deformable bodies built from surface meshes.
The mesh is triangular for 3D bodies and made of line segments for 2D bodies. The mesh does not need to be closed, but content-based forces fail on an open mesh. Order the vertices consistently (e.g., CCW) to define positive normals and bending angles.
The container stores the mesh connectivity (elements, edges, etc.) and the reference properties (initial measures, contents, lengths, angles) that the force computation needs.
The general form of the deformable particle potential energy per particle is:
\[\begin{split}E_K &= E_{K,measure} + E_{K,content} + E_{K,bending} + E_{K,edge} + E_{K,surface} \\ E_{K,measure} &= \sum_{m} \frac{em_m}{2{\mathcal{M}_{m,0}}} \left(\mathcal{M}_m - \mathcal{M}_{m,0}\right)^2 \\ E_{K,surface} &= \sum_{m} \gamma_m \mathcal{M}_m \\ E_{K,content} &= \frac{e_c}{2{\mathcal{C}_{K,0}}} \left(\mathcal{C}_K - \mathcal{C}_{K,0}\right)^2 \\ E_{K,bending} &= \frac{1}{2} \sum_{a} eb_a wb_{a} \left(\theta_a -\theta_{a,0}\right)^2 \\ E_{K,edge} &= \frac{1}{2} \sum_{e} el_e \left(L_e - L_{e,0}\right)^2\end{split}\]Definitions per Dimension:
3D: Measure ($mathcal{M}$) is Face Area. Content ($mathcal{C}$) is Volume. Elements are Triangles.
2D: Measure ($mathcal{M}$) is Segment Length. Content ($mathcal{C}$) is Enclosed Area. Elements are Segments.
The constructor precomputes the bending normalization from the reference configuration:
3D: \(w_b = l_0 / h_0\), where \(l_0\) is the initial shared-edge (hinge) length and \(h_0\) is the initial distance between adjacent face centroids.
2D: \(w_b = 1/h_0\), with \(h_0 = 0.5 (L_{\text{left},0}+L_{\text{right},0})\), where \(L_{\text{left},0}\) and \(L_{\text{right},0}\) are initial lengths of adjacent segments.
Shapes:
K: Number of deformable bodies. Vertices and connectivity (elements, edges, etc.) define each body.
M: Number of boundary elements (\(K \sum_K m_K\))
E: Number of unique edges (\(K \sum_K e_K\))
A: Number of element adjacencies (\(K \sum_K a_K\))
The model concatenates the mesh properties of all bodies along axis=0. Only the content term needs the body ID of each element: it sums the content contributions per body. elements_id maps each element to its body.
Coefficient broadcasting:
Createbroadcasts scalar coefficients to the matching geometric entities. em and gamma become shape (M,), eb becomes (A,), and el becomes (E,).ec is special: its shape is (K,), one value per body. K is the number of unique IDs in elements_id. elements_id[m] gives the body index that reads ec for element m.
- 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 index. 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
- 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 and length stiffness in 2D).
- Type:
Measure elasticity coefficient for each element. Shape
- ec: Array | None#
(K,). (Controls volume stiffness in 3D and 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
- classmethod Create(*, vertices: Array | ndarray | bool | number | bool | int | float | complex | None = None, elements: Array | ndarray | bool | number | bool | int | float | complex | None = None, edges: Array | ndarray | bool | number | bool | int | float | complex | None = None, element_adjacency: Array | ndarray | bool | number | bool | int | float | complex | None = None, element_adjacency_edges: Array | ndarray | bool | number | bool | int | float | complex | None = None, elements_id: Array | ndarray | bool | number | bool | int | float | complex | None = None, initial_body_contents: Array | ndarray | bool | number | bool | int | float | complex | None = None, initial_element_measures: Array | ndarray | bool | number | bool | int | float | complex | None = None, initial_edge_lengths: Array | ndarray | bool | number | bool | int | float | complex | None = None, initial_bendings: Array | ndarray | bool | number | bool | int | float | complex | None = None, em: Array | ndarray | bool | number | bool | int | float | complex | None = None, ec: Array | ndarray | bool | number | bool | int | float | complex | None = None, eb: Array | ndarray | bool | number | bool | int | float | complex | None = None, el: Array | ndarray | bool | number | bool | int | float | complex | None = None, gamma: Array | ndarray | bool | number | bool | int | float | complex | None = None, w_b: Array | ndarray | bool | number | bool | int | float | complex | None = None) Self[source]#
- static merge(model1: BondedForceModel, model2: BondedForceModel | Sequence[BondedForceModel]) BondedForceModel[source]#
Merge two or more bonded-force models into one.
The merge concatenates topology, reference, and coefficient arrays. It shifts vertex indices and body IDs automatically so references stay consistent. When one side has a term that the other does not, the merge pads missing coefficients with
0and missing reference values with1.- Parameters:
model1 (BondedForceModel) – Base model.
model2 (BondedForceModel or Sequence[BondedForceModel]) – Model(s) to merge into model1.
- Returns:
A new model containing all bodies from both sides.
- Return type:
- 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
Createconstructor followed bymerge().- Parameters:
model (BondedForceModel) – Existing model to extend.
**kwargs – Constructor arguments forwarded to the concrete
Createmethod (e.g.vertices,elements, coefficients, …).
- Returns:
The extended model.
- Return type:
- static compute_potential_energy_w_aux(pos: jax.Array, state: State, system: System) tuple[jax.Array, dict[str, jax.Array]][source]#
- update_reference_state(pos: jax.Array, state: State, system: System) DeformableParticleModel[source]#
Return a model with the plastically updated reference configuration.
This is a pure functional update: the update never mutates the model. The base (elastic) model has no plastic flow and returns
self. Plastic subclasses override this hook.
- property force_and_energy_fns: tuple[ForceFunction, EnergyFunction, bool][source]#
Build the bonded force/energy callables for the force manager.
- Returns:
(force_fn, energy_fn, is_com_force)where:force_fncomputes bonded force and torque contributions.energy_fncomputes bonded potential-energy contributions.is_com_forcetells where the force acts:Truefor the center of mass,Falsefor the contact point. It has no effect on spheres.
- Return type:
Tuple[ForceFunction, EnergyFunction, bool]
- jaxdem.bonded_forces.deformable_particle.angle_between_normals(n1: Array, n2: Array) Array[source]#
Unsigned angle between normals.
Warning
This loses the sign of the bending angle in 2D and 3D. For reference bendings consistent with the runtime energy, use
signed_bending_angles()instead.
- jaxdem.bonded_forces.deformable_particle.signed_bending_angles(element_normals: Array, element_adjacency: Array, hinge_vertices: Array | None, dim: int) Array[source]#
Signed bending angle per element adjacency.
This function is the single source of truth for the bending-angle sign convention. The energy, the reference-bending computation at
Createtime, and the plastic bending update all use it.- Parameters:
element_normals (jax.Array) – Unit normals per element. Shape
(M, dim).element_adjacency (jax.Array) – Adjacent element pairs. Shape
(A, 2).hinge_vertices (jax.Array or None) – Positions of the two shared-edge (hinge) vertices per adjacency, ordered as in
element_adjacency_edges. Shape(A, 2, 3). Required in 3D. Ignored in 2D.dim (int) – Spatial dimension (2 or 3).
- jaxdem.bonded_forces.deformable_particle.current_bending_angles(model: DeformableParticleModel, pos: jax.Array, state: State) jax.Array | None[source]#
Signed bending angles of the current configuration.
Runs the same element-normal and bending-angle pipeline as the energy (single source of truth:
signed_bending_angles()). ReturnsNonewhen the model lacks the required bending topology.