Skip to content

liblaf.apple.energy ¤

Modules:

Classes:

ARAP ¤

Bases: Elastic

As-Rigid-As-Possible.

\[ \Psi = \frac{\mu}{2} \|F - R\|_F^2 = \frac{\mu}{2} (I_2 - 2 I_1 + 3) \]

Parameters:

  • id (str, default: <dynamic> ) –
  • actor (Actor) –
  • hess_diag_filter (bool, default: True ) –
  • hess_quad_filter (bool, default: True ) –

Methods:

Attributes:

actor class-attribute instance-attribute ¤

actor: Actor = data()

actors abstractmethod property ¤

hess_diag_filter class-attribute instance-attribute ¤

hess_diag_filter: bool = static(default=True, kw_only=True)

hess_quad_filter class-attribute instance-attribute ¤

hess_quad_filter: bool = static(default=True, kw_only=True)

id class-attribute instance-attribute ¤

id: str = static(
    default=Factory(uniq_id, takes_self=True), kw_only=True
)

mu property ¤

mu: Float[Array, ' c']

__pdoc__ ¤

__pdoc__(**kwargs) -> AbstractDoc

...

References
  1. wadler_lindig._definitions._pformat_dataclass()
Source code in src/liblaf/apple/energy/elastic/arap.py
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
$$
\Psi = \frac{\mu}{2} \|F - R\|_F^2 = \frac{\mu}{2} (I_2 - 2 I_1 + 3)
$$
"""

@property
def mu(self) -> Float[jax.Array, " c"]:
    return self.actor.cell_data["mu"]

@override
@utils.jit_method(inline=True)
def energy_density(
    self, field: sim.Field, /, params: sim.GlobalParams
) -> Float[jax.Array, "c q"]:
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)
    F: Float[jax.Array, "cq J J"] = region.squeeze_cq(F)
    Psi: Float[jax.Array, " cq"]
    (Psi,) = arap_energy_density_warp(F, self.mu)
    Psi: Float[jax.Array, "c q"] = region.unsqueeze_cq(Psi)
    return Psi

@override
@utils.jit_method(inline=True)
def first_piola_kirchhoff_stress(

__repr__ ¤

__repr__() -> str
Source code in src/liblaf/apple/energy/elastic/arap.py
43
44
) -> Float[jax.Array, "c q J J"]:
    region: sim.Region = field.region

energy_density ¤

energy_density(
    field: Field, /, params: GlobalParams
) -> Float[Array, "c q"]
Source code in src/liblaf/apple/energy/elastic/arap.py
26
27
28
29
30
31
32
33
34
35
36
37
@override
@utils.jit_method(inline=True)
def energy_density(
    self, field: sim.Field, /, params: sim.GlobalParams
) -> Float[jax.Array, "c q"]:
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)
    F: Float[jax.Array, "cq J J"] = region.squeeze_cq(F)
    Psi: Float[jax.Array, " cq"]
    (Psi,) = arap_energy_density_warp(F, self.mu)
    Psi: Float[jax.Array, "c q"] = region.unsqueeze_cq(Psi)
    return Psi

energy_density_hess_diag ¤

energy_density_hess_diag(
    field: Field, /, params: GlobalParams
) -> Float[Array, "c q a J"]
Source code in src/liblaf/apple/energy/elastic/arap.py
52
53
54
55
56
57
58
59
60
61
62
63
64
65
@override
@utils.jit_method(inline=True)
def energy_density_hess_diag(
    self, field: sim.Field, /, params: sim.GlobalParams
) -> Float[jax.Array, "c q a J"]:
    hess_diag: Float[jax.Array, "cells 4 3"]
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)
    F: Float[jax.Array, "cq J J"] = region.squeeze_cq(F)
    dhdX: Float[jax.Array, "cq a J"] = region.squeeze_cq(region.dhdX)
    hess_diag: Float[jax.Array, "cq a J"]
    (hess_diag,) = arap_energy_density_hess_diag_warp(F, self.mu, dhdX)
    hess_diag: Float[jax.Array, "c q a J"] = region.unsqueeze_cq(hess_diag)
    return hess_diag

energy_density_hess_quad ¤

energy_density_hess_quad(
    field: Field, p: Field, /, params: GlobalParams
) -> Float[Array, "c q"]
Source code in src/liblaf/apple/energy/elastic/arap.py
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
@override
@utils.jit_method(inline=True)
def energy_density_hess_quad(
    self, field: sim.Field, p: sim.Field, /, params: sim.GlobalParams
) -> Float[jax.Array, "c q"]:
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)
    F: Float[jax.Array, "cq J J"] = region.squeeze_cq(F)
    dhdX: Float[jax.Array, "cq a J"] = region.squeeze_cq(region.dhdX)
    hess_quad: Float[jax.Array, " cq"]
    (hess_quad,) = arap_energy_density_hess_quad_warp(
        F, region.scatter(p.values), self.mu, dhdX
    )
    hess_quad: Float[jax.Array, "c q"] = region.unsqueeze_cq(hess_quad)
    return hess_quad

energy_density_jac ¤

energy_density_jac(
    field: Field, /, params: GlobalParams
) -> Float[Array, "c q a J"]
Source code in src/liblaf/apple/energy/elastic/arap.py
118
119
120
121
122
123
124
125
126
@no_type_check
@utils.jax_kernel
def arap_energy_density_hess_quad_warp(
    F: wp.array(dtype=mat33),
    p: wp.array(dtype=mat43),
    mu: wp.array(dtype=float),
    dh_dX: wp.array(dtype=mat43),
    hess_quad: wp.array(dtype=float),
) -> None:

evolve ¤

evolve(**changes) -> Self
Source code in src/liblaf/apple/energy/elastic/arap.py
46
47
F: Float[jax.Array, "cq J J"] = region.squeeze_cq(F)
PK1: Float[jax.Array, "cq J J"]

first_piola_kirchhoff_stress ¤

first_piola_kirchhoff_stress(
    field: Field, /, params: GlobalParams
) -> Float[Array, "c q J J"]
Source code in src/liblaf/apple/energy/elastic/arap.py
39
40
41
42
43
44
45
46
47
48
49
50
@override
@utils.jit_method(inline=True)
def first_piola_kirchhoff_stress(
    self, field: sim.Field, /, params: sim.GlobalParams
) -> Float[jax.Array, "c q J J"]:
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)
    F: Float[jax.Array, "cq J J"] = region.squeeze_cq(F)
    PK1: Float[jax.Array, "cq J J"]
    (PK1,) = arap_first_piola_kirchhoff_stress_warp(F, self.mu)
    PK1: Float[jax.Array, "c q J J"] = region.unsqueeze_cq(PK1)
    return PK1

from_actor classmethod ¤

from_actor(
    actor: Actor,
    *,
    hess_diag_filter: bool = True,
    hess_quad_filter: bool = True,
) -> Self
Source code in src/liblaf/apple/energy/elastic/arap.py
16
17
18
19
20
21
22
23
24
25
26
27
$$
\Psi = \frac{\mu}{2} \|F - R\|_F^2 = \frac{\mu}{2} (I_2 - 2 I_1 + 3)
$$
"""

@property
def mu(self) -> Float[jax.Array, " c"]:
    return self.actor.cell_data["mu"]

@override
@utils.jit_method(inline=True)
def energy_density(

fun ¤

fun(
    x: ArrayDict, /, params: GlobalParams
) -> Float[Array, ""]
Source code in src/liblaf/apple/energy/elastic/arap.py
35
36
37
38
39
40
41
    (Psi,) = arap_energy_density_warp(F, self.mu)
    Psi: Float[jax.Array, "c q"] = region.unsqueeze_cq(Psi)
    return Psi

@override
@utils.jit_method(inline=True)
def first_piola_kirchhoff_stress(

fun_and_jac ¤

fun_and_jac(
    x: ArrayDict, /, params: GlobalParams
) -> tuple[Float[Array, ""], ArrayDict]
Source code in src/liblaf/apple/energy/elastic/arap.py
78
79
80
81
    F, region.scatter(p.values), self.mu, dhdX
)
hess_quad: Float[jax.Array, "c q"] = region.unsqueeze_cq(hess_quad)
return hess_quad

hess_diag ¤

hess_diag(
    x: ArrayDict, /, params: GlobalParams
) -> ArrayDict
Source code in src/liblaf/apple/energy/elastic/arap.py
61
62
63
64
65
66
67
68
69
    dhdX: Float[jax.Array, "cq a J"] = region.squeeze_cq(region.dhdX)
    hess_diag: Float[jax.Array, "cq a J"]
    (hess_diag,) = arap_energy_density_hess_diag_warp(F, self.mu, dhdX)
    hess_diag: Float[jax.Array, "c q a J"] = region.unsqueeze_cq(hess_diag)
    return hess_diag

@override
@utils.jit_method(inline=True)
def energy_density_hess_quad(

hess_quad ¤

hess_quad(
    x: ArrayDict, p: ArrayDict, /, params: GlobalParams
) -> Float[Array, ""]
Source code in src/liblaf/apple/energy/elastic/arap.py
71
72
73
74
75
76
) -> Float[jax.Array, "c q"]:
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)
    F: Float[jax.Array, "cq J J"] = region.squeeze_cq(F)
    dhdX: Float[jax.Array, "cq a J"] = region.squeeze_cq(region.dhdX)
    hess_quad: Float[jax.Array, " cq"]

hessp ¤

hessp(
    x: ArrayDict, p: ArrayDict, /, params: GlobalParams
) -> ArrayDict
Source code in src/liblaf/apple/energy/elastic/arap.py
54
55
56
57
58
59
def energy_density_hess_diag(
    self, field: sim.Field, /, params: sim.GlobalParams
) -> Float[jax.Array, "c q a J"]:
    hess_diag: Float[jax.Array, "cells 4 3"]
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)

jac ¤

jac(x: ArrayDict, /, params: GlobalParams) -> ArrayDict
Source code in src/liblaf/apple/energy/elastic/arap.py
43
44
45
46
47
48
49
50
51
52
) -> Float[jax.Array, "c q J J"]:
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)
    F: Float[jax.Array, "cq J J"] = region.squeeze_cq(F)
    PK1: Float[jax.Array, "cq J J"]
    (PK1,) = arap_first_piola_kirchhoff_stress_warp(F, self.mu)
    PK1: Float[jax.Array, "c q J J"] = region.unsqueeze_cq(PK1)
    return PK1

@override

jac_and_hess_diag ¤

jac_and_hess_diag(
    x: ArrayDict, /, params: GlobalParams
) -> tuple[ArrayDict, ArrayDict]
Source code in src/liblaf/apple/energy/elastic/arap.py
85
86
87
88
89
90
@utils.jax_kernel
def arap_energy_density_warp(
    F: wp.array(dtype=mat33), mu: wp.array(dtype=float), Psi: wp.array(dtype=float)
) -> None:
    tid = wp.tid()
    Psi[tid] = func.elastic.arap_energy_density(F=F[tid], mu=mu[tid])

make_field ¤

make_field(x: ArrayDict) -> Field
Source code in src/liblaf/apple/energy/elastic/arap.py
39
40
41
@override
@utils.jit_method(inline=True)
def first_piola_kirchhoff_stress(

pre_optim_iter ¤

pre_optim_iter(params: GlobalParams) -> Self
Source code in src/liblaf/apple/energy/elastic/arap.py
24
return self.actor.cell_data["mu"]

pre_time_step ¤

pre_time_step(params: GlobalParams) -> Self
Source code in src/liblaf/apple/energy/elastic/arap.py
21
@property

tree_at ¤

tree_at(
    where: Callable[[Self], Node | Sequence[Node]],
    replace: Any | Sequence[Any] = ...,
    replace_fn: Callable[[Node], Any] = ...,
    is_leaf: Callable[[Any], bool] | None = None,
) -> Self
Source code in src/liblaf/apple/energy/elastic/arap.py
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
    PK1: Float[jax.Array, "c q J J"] = region.unsqueeze_cq(PK1)
    return PK1

@override
@utils.jit_method(inline=True)
def energy_density_hess_diag(
    self, field: sim.Field, /, params: sim.GlobalParams
) -> Float[jax.Array, "c q a J"]:
    hess_diag: Float[jax.Array, "cells 4 3"]
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)
    F: Float[jax.Array, "cq J J"] = region.squeeze_cq(F)
    dhdX: Float[jax.Array, "cq a J"] = region.squeeze_cq(region.dhdX)
    hess_diag: Float[jax.Array, "cq a J"]
    (hess_diag,) = arap_energy_density_hess_diag_warp(F, self.mu, dhdX)

with_actors abstractmethod ¤

with_actors(actors: NodeContainer[Actor]) -> Self
Source code in src/liblaf/apple/energy/elastic/arap.py
27
28
29
@utils.jit_method(inline=True)
def energy_density(
    self, field: sim.Field, /, params: sim.GlobalParams

CollisionCandidatesVertFace ¤

Bases: PyTreeMixin

Parameters:

  • closest (Float[Array, 'points 3'], default: None ) –
  • collide (Bool[Array, points], default: None ) –
  • distance (Float[Array, points], default: None ) –
  • face_id (Integer[Array, points], default: None ) –
  • face_normal (Float[Array, 'points 3'], default: None ) –
  • uv (Float[Array, 'points 2'], default: None ) –

Methods:

Attributes:

  • closest (Float[Array, 'points 3']) –
  • collide (Bool[Array, ' points']) –
  • distance (Float[Array, ' points']) –
  • face_id (Integer[Array, ' points']) –
  • face_normal (Float[Array, 'points 3']) –
  • uv (Float[Array, 'points 2']) –

closest class-attribute instance-attribute ¤

closest: Float[Array, 'points 3'] = array(default=None)

collide class-attribute instance-attribute ¤

collide: Bool[Array, ' points'] = array(default=None)

distance class-attribute instance-attribute ¤

distance: Float[Array, ' points'] = array(default=None)

face_id class-attribute instance-attribute ¤

face_id: Integer[Array, ' points'] = array(default=None)

face_normal class-attribute instance-attribute ¤

face_normal: Float[Array, 'points 3'] = array(default=None)

uv class-attribute instance-attribute ¤

uv: Float[Array, 'points 2'] = array(default=None)

__pdoc__ ¤

__pdoc__(**kwargs) -> AbstractDoc

...

References
  1. wadler_lindig._definitions._pformat_dataclass()
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@struct.pytree
class CollisionCandidatesVertFace(struct.PyTreeMixin):
    closest: Float[Array, "points 3"] = struct.array(default=None)
    collide: Bool[Array, " points"] = struct.array(default=None)
    distance: Float[Array, " points"] = struct.array(default=None)
    face_id: Integer[Array, " points"] = struct.array(default=None)
    face_normal: Float[Array, "points 3"] = struct.array(default=None)
    uv: Float[Array, "points 2"] = struct.array(default=None)


@struct.pytree
class CollisionVertFace(sim.Energy):
    rigid: sim.Actor = struct.data(default=None)
    soft: sim.Actor = struct.data(default=None)

    stiffness: Float[Array, ""] = struct.array(default=1e5)
    rest_length: Float[Array, ""] = struct.array(default=1e-3)
    max_dist: Float[Array, ""] = struct.array(default=1e-2)
    epsilon: Float[Array, ""] = struct.array(default=1e-3)
    filter_hess_diag: bool = struct.static(default=True, kw_only=True)
    filter_hess_quad: bool = struct.static(default=True, kw_only=True)

    candidates: CollisionCandidatesVertFace = struct.data(
        factory=CollisionCandidatesVertFace

__repr__ ¤

__repr__() -> str
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
43
@classmethod

evolve ¤

evolve(**changes) -> Self
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
46
47
cls,
rigid: sim.Actor,

tree_at ¤

tree_at(
    where: Callable[[Self], Node | Sequence[Node]],
    replace: Any | Sequence[Any] = ...,
    replace_fn: Callable[[Node], Any] = ...,
    is_leaf: Callable[[Any], bool] | None = None,
) -> Self
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
    *,
    stiffness: float = 1e3,
    rest_length: float = 1e-3,
    max_dist: float | None = None,
    epsilon: float = 1e-3,
) -> Self:
    if max_dist is None:
        max_dist = 2.0 * rest_length
    return cls(
        rigid=rigid,
        soft=soft,
        stiffness=jnp.asarray(stiffness),
        rest_length=jnp.asarray(rest_length),
        max_dist=jnp.asarray(max_dist),
        epsilon=jnp.asarray(epsilon),

CollisionVertFace ¤

Bases: Energy

Parameters:

  • id (str, default: <dynamic> ) –
  • rigid (Actor, default: None ) –
  • soft (Actor, default: None ) –
  • stiffness (Float[Array, ''], default: 100000.0 ) –
  • rest_length (Float[Array, ''], default: 0.001 ) –
  • max_dist (Float[Array, ''], default: 0.01 ) –
  • epsilon (Float[Array, ''], default: 0.001 ) –
  • filter_hess_diag (bool, default: True ) –
  • filter_hess_quad (bool, default: True ) –
  • candidates (CollisionCandidatesVertFace, default: <dynamic> ) –

Methods:

Attributes:

actors property ¤

candidates class-attribute instance-attribute ¤

epsilon class-attribute instance-attribute ¤

epsilon: Float[Array, ''] = array(default=0.001)

filter_hess_diag class-attribute instance-attribute ¤

filter_hess_diag: bool = static(default=True, kw_only=True)

filter_hess_quad class-attribute instance-attribute ¤

filter_hess_quad: bool = static(default=True, kw_only=True)

id class-attribute instance-attribute ¤

id: str = static(
    default=Factory(uniq_id, takes_self=True), kw_only=True
)

max_dist class-attribute instance-attribute ¤

max_dist: Float[Array, ''] = array(default=0.01)

rest_length class-attribute instance-attribute ¤

rest_length: Float[Array, ''] = array(default=0.001)

rigid class-attribute instance-attribute ¤

rigid: Actor = data(default=None)

soft class-attribute instance-attribute ¤

soft: Actor = data(default=None)

stiffness class-attribute instance-attribute ¤

stiffness: Float[Array, ''] = array(default=100000.0)

__pdoc__ ¤

__pdoc__(**kwargs) -> AbstractDoc

...

References
  1. wadler_lindig._definitions._pformat_dataclass()
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@struct.pytree
class CollisionCandidatesVertFace(struct.PyTreeMixin):
    closest: Float[Array, "points 3"] = struct.array(default=None)
    collide: Bool[Array, " points"] = struct.array(default=None)
    distance: Float[Array, " points"] = struct.array(default=None)
    face_id: Integer[Array, " points"] = struct.array(default=None)
    face_normal: Float[Array, "points 3"] = struct.array(default=None)
    uv: Float[Array, "points 2"] = struct.array(default=None)


@struct.pytree
class CollisionVertFace(sim.Energy):
    rigid: sim.Actor = struct.data(default=None)
    soft: sim.Actor = struct.data(default=None)

    stiffness: Float[Array, ""] = struct.array(default=1e5)
    rest_length: Float[Array, ""] = struct.array(default=1e-3)
    max_dist: Float[Array, ""] = struct.array(default=1e-2)
    epsilon: Float[Array, ""] = struct.array(default=1e-3)
    filter_hess_diag: bool = struct.static(default=True, kw_only=True)
    filter_hess_quad: bool = struct.static(default=True, kw_only=True)

    candidates: CollisionCandidatesVertFace = struct.data(
        factory=CollisionCandidatesVertFace

__repr__ ¤

__repr__() -> str
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
43
@classmethod

collide ¤

Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
@utils.jit_method()
def collide(self) -> CollisionCandidatesVertFace:
    (
        closest,
        collide,
        distance,
        face_id,
        face_normal,
        uv,
    ) = collision_detect_vert_face_kernel(
        self.soft.positions,
        np.uint64(self.rigid.collision_mesh.id),
        self.rest_length.reshape((1,)),
        self.max_dist.reshape((1,)),
        self.epsilon.reshape((1,)),
        output_dims={
            "closest": (self.soft.n_points,),
            "collide": (self.soft.n_points,),
            "distance": (self.soft.n_points,),
            "face_id": (self.soft.n_points,),
            "face_normal": (self.soft.n_points,),
            "uv": (self.soft.n_points,),
        },
        launch_dims=(self.soft.n_points,),
    )
    return CollisionCandidatesVertFace(
        closest=closest,
        collide=collide,
        distance=distance,
        face_id=face_id,
        face_normal=face_normal,
        uv=uv,
    )

evolve ¤

evolve(**changes) -> Self
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
46
47
cls,
rigid: sim.Actor,

from_actors classmethod ¤

from_actors(
    rigid: Actor,
    soft: Actor,
    *,
    stiffness: float = 1000.0,
    rest_length: float = 0.001,
    max_dist: float | None = None,
    epsilon: float = 0.001,
) -> Self
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
@classmethod
def from_actors(
    cls,
    rigid: sim.Actor,
    soft: sim.Actor,
    *,
    stiffness: float = 1e3,
    rest_length: float = 1e-3,
    max_dist: float | None = None,
    epsilon: float = 1e-3,
) -> Self:
    if max_dist is None:
        max_dist = 2.0 * rest_length
    return cls(
        rigid=rigid,
        soft=soft,
        stiffness=jnp.asarray(stiffness),
        rest_length=jnp.asarray(rest_length),
        max_dist=jnp.asarray(max_dist),
        epsilon=jnp.asarray(epsilon),
    )

fun ¤

fun(
    x: ArrayDict, /, params: GlobalParams
) -> Float[Array, ""]
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
@override
@utils.jit_method(inline=True)
def fun(self, x: struct.ArrayDict, /, params: sim.GlobalParams) -> Float[Array, ""]:
    points: Float[Array, "points dim"] = self.soft.points + x[self.soft.id]
    energy: Float[Array, " points"]
    (energy,) = collision_energy_vert_face_fun_kernel(
        points,
        self.candidates.closest,
        self.candidates.collide,
        self.candidates.distance,
        self.rest_length.reshape((1,)),
        self.stiffness.reshape((1,)),
        output_dims={"energy": (1,)},
        launch_dims=(self.soft.n_points,),
    )
    return energy.sum()

fun_and_jac ¤

fun_and_jac(
    x: ArrayDict, /, params: GlobalParams
) -> tuple[Float[Array, ""], ArrayDict]
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
78
79
80
81
82
83
    # wl.pprint(candidates, short_arrays=False)
    return self.evolve(candidates=candidates)

@override
@utils.jit_method(inline=True)
def fun(self, x: struct.ArrayDict, /, params: sim.GlobalParams) -> Float[Array, ""]:

hess_diag ¤

hess_diag(
    x: ArrayDict, /, params: GlobalParams
) -> ArrayDict
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
@override
@utils.jit_method(inline=True)
def hess_diag(
    self, x: struct.ArrayDict, /, params: sim.GlobalParams
) -> struct.ArrayDict:
    points: Float[Array, "points dim"] = self.soft.points + x[self.soft.id]
    hess_diag: Float[Array, "points dim"]
    (hess_diag,) = collision_energy_vert_face_hess_diag_kernel(
        points,
        self.candidates.closest,
        self.candidates.collide,
        self.candidates.distance,
        self.rest_length.reshape((1,)),
        self.stiffness.reshape((1,)),
        output_dims={"hess_diag": (self.soft.n_points,)},
        launch_dims=(self.soft.n_points,),
    )
    if self.filter_hess_diag:
        hess_diag = jnp.clip(hess_diag, min=0.0)
    return struct.ArrayDict(
        {self.soft.id: hess_diag, self.rigid.id: jnp.zeros_like(x[self.rigid.id])}
    )

hess_quad ¤

hess_quad(
    x: ArrayDict, p: ArrayDict, /, params: GlobalParams
) -> Float[Array, ""]
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
@override
@utils.jit_method(inline=True)
def hess_quad(
    self, x: struct.ArrayDict, p: struct.ArrayDict, /, params: sim.GlobalParams
) -> Float[Array, ""]:
    points: Float[Array, "points dim"] = self.soft.points + x[self.soft.id]
    hess_quad: Float[Array, " points"]
    (hess_quad,) = collision_energy_vert_face_hess_quad_kernel(
        points,
        p[self.soft.id],
        self.candidates.closest,
        self.candidates.collide,
        self.candidates.distance,
        self.rest_length.reshape((1,)),
        self.stiffness.reshape((1,)),
        output_dims={"hess_quad": (self.soft.n_points,)},
        launch_dims=(self.soft.n_points,),
    )
    if self.filter_hess_quad:
        hess_quad = jnp.clip(hess_quad, min=0.0)
    return hess_quad.sum()

hessp ¤

hessp(
    x: ArrayDict, p: ArrayDict, /, params: GlobalParams
) -> ArrayDict
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
54
55
56
57
58
59
) -> Self:
    if max_dist is None:
        max_dist = 2.0 * rest_length
    return cls(
        rigid=rigid,
        soft=soft,

jac ¤

jac(x: ArrayDict, /, params: GlobalParams) -> ArrayDict
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
@override
@utils.jit_method(inline=True)
def jac(self, x: struct.ArrayDict, /, params: sim.GlobalParams) -> struct.ArrayDict:
    points: Float[Array, "points dim"] = self.soft.points + x[self.soft.id]
    jac_soft: Float[Array, " points dim"]
    (jac_soft,) = collision_energy_vert_face_jac_kernel(
        points,
        self.candidates.closest,
        self.candidates.collide,
        self.candidates.distance,
        self.rest_length.reshape((1,)),
        self.stiffness.reshape((1,)),
        output_dims={"jac": (self.soft.n_points,)},
        launch_dims=(self.soft.n_points,),
    )
    # jax.debug.print("CollisionVertFace.jac = {}", jac_soft)
    return struct.ArrayDict(
        {self.soft.id: jac_soft, self.rigid.id: jnp.zeros_like(x[self.rigid.id])}
    )

jac_and_hess_diag ¤

jac_and_hess_diag(
    x: ArrayDict, /, params: GlobalParams
) -> tuple[ArrayDict, ArrayDict]
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
85
86
87
88
89
90
energy: Float[Array, " points"]
(energy,) = collision_energy_vert_face_fun_kernel(
    points,
    self.candidates.closest,
    self.candidates.collide,
    self.candidates.distance,

pre_optim_iter ¤

pre_optim_iter(params: GlobalParams) -> Self
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
75
76
77
78
79
@override
def pre_optim_iter(self, params: sim.GlobalParams) -> Self:
    candidates: CollisionCandidatesVertFace = self.collide()
    # wl.pprint(candidates, short_arrays=False)
    return self.evolve(candidates=candidates)

pre_time_step ¤

pre_time_step(params: GlobalParams) -> Self
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
21
22
collide: Bool[Array, " points"] = struct.array(default=None)
distance: Float[Array, " points"] = struct.array(default=None)

tree_at ¤

tree_at(
    where: Callable[[Self], Node | Sequence[Node]],
    replace: Any | Sequence[Any] = ...,
    replace_fn: Callable[[Node], Any] = ...,
    is_leaf: Callable[[Any], bool] | None = None,
) -> Self
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
    *,
    stiffness: float = 1e3,
    rest_length: float = 1e-3,
    max_dist: float | None = None,
    epsilon: float = 1e-3,
) -> Self:
    if max_dist is None:
        max_dist = 2.0 * rest_length
    return cls(
        rigid=rigid,
        soft=soft,
        stiffness=jnp.asarray(stiffness),
        rest_length=jnp.asarray(rest_length),
        max_dist=jnp.asarray(max_dist),
        epsilon=jnp.asarray(epsilon),

with_actors ¤

with_actors(actors: NodeContainer[Actor]) -> Self
Source code in src/liblaf/apple/energy/collision/vert_face/vert_face.py
71
72
73
@override
def with_actors(self, actors: struct.NodeContainer[sim.Actor]) -> Self:
    return self.evolve(rigid=actors[self.rigid.id], soft=actors[self.soft.id])

EnergyZero ¤

Bases: Energy

Parameters:

  • id (str, default: <dynamic> ) –
  • _actors (NodeContainer[Actor], default: <dynamic> ) –

Methods:

Attributes:

actors property ¤

id class-attribute instance-attribute ¤

id: str = static(
    default=Factory(uniq_id, takes_self=True), kw_only=True
)

__pdoc__ ¤

__pdoc__(**kwargs) -> AbstractDoc

...

References
  1. wadler_lindig._definitions._pformat_dataclass()
Source code in src/liblaf/apple/energy/zero.py
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@classmethod
def from_actors(cls, *actors: sim.Actor) -> Self:
    return cls(_actors=struct.NodeContainer(actors))

@property
@override
def actors(self) -> struct.NodeContainer[sim.Actor]:
    return self._actors

@override
def with_actors(self, actors: struct.NodeContainer[sim.Actor]) -> Self:
    return self.evolve(_actors=actors)

@override
@utils.jit_method(inline=True)
def fun(self, x: struct.ArrayDict, /, params: sim.GlobalParams) -> FloatScalar:
    return jnp.zeros(())

@override
@utils.jit_method(inline=True)
def jac(self, x: struct.ArrayDict, /, params: sim.GlobalParams) -> struct.ArrayDict:
    return struct.ArrayDict(
        {actor.id: jnp.zeros_like(x[actor.id]) for actor in self.actors.values()}
    )

__repr__ ¤

__repr__() -> str
Source code in src/liblaf/apple/energy/zero.py
43
44
@override
@utils.jit_method(inline=True)

evolve ¤

evolve(**changes) -> Self
Source code in src/liblaf/apple/energy/zero.py
46
47
    self, x: struct.ArrayDict, /, params: sim.GlobalParams
) -> struct.ArrayDict:

from_actors classmethod ¤

from_actors(*actors: Actor) -> Self
Source code in src/liblaf/apple/energy/zero.py
18
19
20
@classmethod
def from_actors(cls, *actors: sim.Actor) -> Self:
    return cls(_actors=struct.NodeContainer(actors))

fun ¤

fun(x: ArrayDict, /, params: GlobalParams) -> FloatScalar
Source code in src/liblaf/apple/energy/zero.py
31
32
33
34
@override
@utils.jit_method(inline=True)
def fun(self, x: struct.ArrayDict, /, params: sim.GlobalParams) -> FloatScalar:
    return jnp.zeros(())

fun_and_jac ¤

fun_and_jac(
    x: ArrayDict, /, params: GlobalParams
) -> tuple[Float[Array, ""], ArrayDict]

hess_diag ¤

hess_diag(
    x: ArrayDict, /, params: GlobalParams
) -> ArrayDict
Source code in src/liblaf/apple/energy/zero.py
43
44
45
46
47
48
49
50
@override
@utils.jit_method(inline=True)
def hess_diag(
    self, x: struct.ArrayDict, /, params: sim.GlobalParams
) -> struct.ArrayDict:
    return struct.ArrayDict(
        {actor.id: jnp.zeros_like(x[actor.id]) for actor in self.actors.values()}
    )

hess_quad ¤

hess_quad(
    x: ArrayDict, p: ArrayDict, /, params: GlobalParams
) -> FloatScalar
Source code in src/liblaf/apple/energy/zero.py
52
53
54
55
56
57
@override
@utils.jit_method(inline=True)
def hess_quad(
    self, x: struct.ArrayDict, p: struct.ArrayDict, /, params: sim.GlobalParams
) -> FloatScalar:
    return jnp.zeros(())

hessp ¤

hessp(
    x: ArrayDict, p: ArrayDict, /, params: GlobalParams
) -> ArrayDict
Source code in src/liblaf/apple/energy/zero.py
54
55
56
57
def hess_quad(
    self, x: struct.ArrayDict, p: struct.ArrayDict, /, params: sim.GlobalParams
) -> FloatScalar:
    return jnp.zeros(())

jac ¤

jac(x: ArrayDict, /, params: GlobalParams) -> ArrayDict
Source code in src/liblaf/apple/energy/zero.py
36
37
38
39
40
41
@override
@utils.jit_method(inline=True)
def jac(self, x: struct.ArrayDict, /, params: sim.GlobalParams) -> struct.ArrayDict:
    return struct.ArrayDict(
        {actor.id: jnp.zeros_like(x[actor.id]) for actor in self.actors.values()}
    )

jac_and_hess_diag ¤

jac_and_hess_diag(
    x: ArrayDict, /, params: GlobalParams
) -> tuple[ArrayDict, ArrayDict]

pre_optim_iter ¤

pre_optim_iter(params: GlobalParams) -> Self
Source code in src/liblaf/apple/energy/zero.py
24
25
def actors(self) -> struct.NodeContainer[sim.Actor]:
    return self._actors

pre_time_step ¤

pre_time_step(params: GlobalParams) -> Self
Source code in src/liblaf/apple/energy/zero.py
21
@property

tree_at ¤

tree_at(
    where: Callable[[Self], Node | Sequence[Node]],
    replace: Any | Sequence[Any] = ...,
    replace_fn: Callable[[Node], Any] = ...,
    is_leaf: Callable[[Any], bool] | None = None,
) -> Self
Source code in src/liblaf/apple/energy/zero.py
49
50
51
52
53
54
55
56
57
        {actor.id: jnp.zeros_like(x[actor.id]) for actor in self.actors.values()}
    )

@override
@utils.jit_method(inline=True)
def hess_quad(
    self, x: struct.ArrayDict, p: struct.ArrayDict, /, params: sim.GlobalParams
) -> FloatScalar:
    return jnp.zeros(())

with_actors ¤

with_actors(actors: NodeContainer[Actor]) -> Self
Source code in src/liblaf/apple/energy/zero.py
27
28
29
@override
def with_actors(self, actors: struct.NodeContainer[sim.Actor]) -> Self:
    return self.evolve(_actors=actors)

PhaceStatic ¤

Bases: Elastic

As-Rigid-As-Possible.

\[ \Psi = \frac{\mu}{2} \|F - R\|_F^2 = \frac{\mu}{2} (I_2 - 2 I_1 + 3) \]

Parameters:

  • id (str, default: <dynamic> ) –
  • actor (Actor) –
  • hess_diag_filter (bool, default: True ) –
  • hess_quad_filter (bool, default: True ) –

Methods:

Attributes:

actor class-attribute instance-attribute ¤

actor: Actor = data()

actors abstractmethod property ¤

hess_diag_filter class-attribute instance-attribute ¤

hess_diag_filter: bool = static(default=True, kw_only=True)

hess_quad_filter class-attribute instance-attribute ¤

hess_quad_filter: bool = static(default=True, kw_only=True)

id class-attribute instance-attribute ¤

id: str = static(
    default=Factory(uniq_id, takes_self=True), kw_only=True
)

lambda_ property ¤

lambda_: Float[Array, ' cells']

mu property ¤

mu: Float[Array, ' cells']

params property ¤

params: Float[Array, 'cells 2']

__pdoc__ ¤

__pdoc__(**kwargs) -> AbstractDoc

...

References
  1. wadler_lindig._definitions._pformat_dataclass()
Source code in src/liblaf/apple/energy/elastic/phace_static.py
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
$$
\Psi = \frac{\mu}{2} \|F - R\|_F^2 = \frac{\mu}{2} (I_2 - 2 I_1 + 3)
$$
"""

@property
def lambda_(self) -> Float[jax.Array, " cells"]:
    return self.actor.cell_data["lambda"]

@property
def mu(self) -> Float[jax.Array, " cells"]:
    return self.actor.cell_data["mu"]

@property
def params(self) -> Float[jax.Array, "cells 2"]:
    return jnp.stack((self.lambda_, self.mu), axis=-1)

@override
@utils.jit_method(inline=True)
def energy_density(
    self, field: sim.Field, /, params: sim.GlobalParams
) -> Float[jax.Array, "c q"]:
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)

__repr__ ¤

__repr__() -> str
Source code in src/liblaf/apple/energy/elastic/phace_static.py
43
44
Psi: Float[jax.Array, " cq"]
(Psi,) = phace_static_energy_density_warp(F, self.params)

energy_density ¤

energy_density(
    field: Field, /, params: GlobalParams
) -> Float[Array, "c q"]
Source code in src/liblaf/apple/energy/elastic/phace_static.py
35
36
37
38
39
40
41
42
43
44
45
46
@override
@utils.jit_method(inline=True)
def energy_density(
    self, field: sim.Field, /, params: sim.GlobalParams
) -> Float[jax.Array, "c q"]:
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)
    F: Float[jax.Array, "cq J J"] = region.squeeze_cq(F)
    Psi: Float[jax.Array, " cq"]
    (Psi,) = phace_static_energy_density_warp(F, self.params)
    Psi: Float[jax.Array, "c q"] = region.unsqueeze_cq(Psi)
    return Psi

energy_density_hess_diag ¤

energy_density_hess_diag(
    field: Field, /, params: GlobalParams
) -> Float[Array, "c q a J"]
Source code in src/liblaf/apple/energy/elastic/phace_static.py
61
62
63
64
65
66
67
68
69
70
71
72
73
@override
@utils.jit_method(inline=True)
def energy_density_hess_diag(
    self, field: sim.Field, /, params: sim.GlobalParams
) -> Float[jax.Array, "c q a J"]:
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)
    F: Float[jax.Array, "cq J J"] = region.squeeze_cq(F)
    dhdX: Float[jax.Array, "cq a J"] = region.squeeze_cq(region.dhdX)
    hess_diag: Float[jax.Array, "cq a J"]
    (hess_diag,) = phace_static_energy_density_hess_diag_warp(F, self.params, dhdX)
    hess_diag: Float[jax.Array, "c q a J"] = region.unsqueeze_cq(hess_diag)
    return hess_diag

energy_density_hess_quad ¤

energy_density_hess_quad(
    field: Field, p: Field, /, params: GlobalParams
) -> Float[Array, "c q"]
Source code in src/liblaf/apple/energy/elastic/phace_static.py
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
@override
@utils.jit_method(inline=True)
def energy_density_hess_quad(
    self, field: sim.Field, p: sim.Field, /, params: sim.GlobalParams
) -> Float[jax.Array, "c q"]:
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)
    F: Float[jax.Array, "cq J J"] = region.squeeze_cq(F)
    dhdX: Float[jax.Array, "cq a J"] = region.squeeze_cq(region.dhdX)
    hess_quad: Float[jax.Array, " cq"]
    (hess_quad,) = phace_static_energy_density_hess_quad_warp(
        F, region.scatter(p.values), self.params, dhdX
    )
    hess_quad: Float[jax.Array, "c q"] = region.unsqueeze_cq(hess_quad)
    return hess_quad

energy_density_jac ¤

energy_density_jac(
    field: Field, /, params: GlobalParams
) -> Float[Array, "c q a J"]
Source code in src/liblaf/apple/energy/elastic/phace_static.py
118
119
120
121
122
123
124
125
126
        F=F[tid], params=params_struct
    )


@no_type_check
@utils.jax_kernel
def phace_static_energy_density_hess_diag_warp(
    F: wp.array(dtype=mat33),
    params: wp.array(dtype=wp.vec2),

evolve ¤

evolve(**changes) -> Self
Source code in src/liblaf/apple/energy/elastic/phace_static.py
46
return Psi

first_piola_kirchhoff_stress ¤

first_piola_kirchhoff_stress(
    field: Field, /, params: GlobalParams
) -> Float[Array, "c q J J"]
Source code in src/liblaf/apple/energy/elastic/phace_static.py
48
49
50
51
52
53
54
55
56
57
58
59
@override
@utils.jit_method(inline=True)
def first_piola_kirchhoff_stress(
    self, field: sim.Field, /, params: sim.GlobalParams
) -> Float[jax.Array, "c q J J"]:
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)
    F: Float[jax.Array, "cq J J"] = region.squeeze_cq(F)
    PK1: Float[jax.Array, "cq J J"]
    (PK1,) = phace_static_first_piola_kirchhoff_stress_warp(F, self.params)
    PK1: Float[jax.Array, "c q J J"] = region.unsqueeze_cq(PK1)
    return PK1

from_actor classmethod ¤

from_actor(
    actor: Actor,
    *,
    hess_diag_filter: bool = True,
    hess_quad_filter: bool = True,
) -> Self
Source code in src/liblaf/apple/energy/elastic/phace_static.py
16
17
18
19
20
21
22
23
24
25
26
27
28
r"""As-Rigid-As-Possible.

$$
\Psi = \frac{\mu}{2} \|F - R\|_F^2 = \frac{\mu}{2} (I_2 - 2 I_1 + 3)
$$
"""

@property
def lambda_(self) -> Float[jax.Array, " cells"]:
    return self.actor.cell_data["lambda"]

@property
def mu(self) -> Float[jax.Array, " cells"]:

fun ¤

fun(
    x: ArrayDict, /, params: GlobalParams
) -> Float[Array, ""]
Source code in src/liblaf/apple/energy/elastic/phace_static.py
35
36
37
38
39
40
41
@override
@utils.jit_method(inline=True)
def energy_density(
    self, field: sim.Field, /, params: sim.GlobalParams
) -> Float[jax.Array, "c q"]:
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)

fun_and_jac ¤

fun_and_jac(
    x: ArrayDict, /, params: GlobalParams
) -> tuple[Float[Array, ""], ArrayDict]
Source code in src/liblaf/apple/energy/elastic/phace_static.py
78
79
80
81
82
83
    self, field: sim.Field, p: sim.Field, /, params: sim.GlobalParams
) -> Float[jax.Array, "c q"]:
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)
    F: Float[jax.Array, "cq J J"] = region.squeeze_cq(F)
    dhdX: Float[jax.Array, "cq a J"] = region.squeeze_cq(region.dhdX)

hess_diag ¤

hess_diag(
    x: ArrayDict, /, params: GlobalParams
) -> ArrayDict
Source code in src/liblaf/apple/energy/elastic/phace_static.py
61
62
63
64
65
66
67
68
69
@override
@utils.jit_method(inline=True)
def energy_density_hess_diag(
    self, field: sim.Field, /, params: sim.GlobalParams
) -> Float[jax.Array, "c q a J"]:
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)
    F: Float[jax.Array, "cq J J"] = region.squeeze_cq(F)
    dhdX: Float[jax.Array, "cq a J"] = region.squeeze_cq(region.dhdX)

hess_quad ¤

hess_quad(
    x: ArrayDict, p: ArrayDict, /, params: GlobalParams
) -> Float[Array, ""]
Source code in src/liblaf/apple/energy/elastic/phace_static.py
71
72
73
74
75
76
    (hess_diag,) = phace_static_energy_density_hess_diag_warp(F, self.params, dhdX)
    hess_diag: Float[jax.Array, "c q a J"] = region.unsqueeze_cq(hess_diag)
    return hess_diag

@override
@utils.jit_method(inline=True)

hessp ¤

hessp(
    x: ArrayDict, p: ArrayDict, /, params: GlobalParams
) -> ArrayDict
Source code in src/liblaf/apple/energy/elastic/phace_static.py
54
55
56
57
58
59
F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)
F: Float[jax.Array, "cq J J"] = region.squeeze_cq(F)
PK1: Float[jax.Array, "cq J J"]
(PK1,) = phace_static_first_piola_kirchhoff_stress_warp(F, self.params)
PK1: Float[jax.Array, "c q J J"] = region.unsqueeze_cq(PK1)
return PK1

jac ¤

jac(x: ArrayDict, /, params: GlobalParams) -> ArrayDict
Source code in src/liblaf/apple/energy/elastic/phace_static.py
43
44
45
46
47
48
49
50
51
52
    Psi: Float[jax.Array, " cq"]
    (Psi,) = phace_static_energy_density_warp(F, self.params)
    Psi: Float[jax.Array, "c q"] = region.unsqueeze_cq(Psi)
    return Psi

@override
@utils.jit_method(inline=True)
def first_piola_kirchhoff_stress(
    self, field: sim.Field, /, params: sim.GlobalParams
) -> Float[jax.Array, "c q J J"]:

jac_and_hess_diag ¤

jac_and_hess_diag(
    x: ArrayDict, /, params: GlobalParams
) -> tuple[ArrayDict, ArrayDict]
Source code in src/liblaf/apple/energy/elastic/phace_static.py
85
86
87
88
89
(hess_quad,) = phace_static_energy_density_hess_quad_warp(
    F, region.scatter(p.values), self.params, dhdX
)
hess_quad: Float[jax.Array, "c q"] = region.unsqueeze_cq(hess_quad)
return hess_quad

make_field ¤

make_field(x: ArrayDict) -> Field
Source code in src/liblaf/apple/energy/elastic/phace_static.py
39
40
41
) -> Float[jax.Array, "c q"]:
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)

pre_optim_iter ¤

pre_optim_iter(params: GlobalParams) -> Self
Source code in src/liblaf/apple/energy/elastic/phace_static.py
24
25
def lambda_(self) -> Float[jax.Array, " cells"]:
    return self.actor.cell_data["lambda"]

pre_time_step ¤

pre_time_step(params: GlobalParams) -> Self
Source code in src/liblaf/apple/energy/elastic/phace_static.py
21
"""

tree_at ¤

tree_at(
    where: Callable[[Self], Node | Sequence[Node]],
    replace: Any | Sequence[Any] = ...,
    replace_fn: Callable[[Node], Any] = ...,
    is_leaf: Callable[[Any], bool] | None = None,
) -> Self
Source code in src/liblaf/apple/energy/elastic/phace_static.py
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
@utils.jit_method(inline=True)
def first_piola_kirchhoff_stress(
    self, field: sim.Field, /, params: sim.GlobalParams
) -> Float[jax.Array, "c q J J"]:
    region: sim.Region = field.region
    F: Float[jax.Array, "c q J J"] = region.deformation_gradient(field.values)
    F: Float[jax.Array, "cq J J"] = region.squeeze_cq(F)
    PK1: Float[jax.Array, "cq J J"]
    (PK1,) = phace_static_first_piola_kirchhoff_stress_warp(F, self.params)
    PK1: Float[jax.Array, "c q J J"] = region.unsqueeze_cq(PK1)
    return PK1

@override
@utils.jit_method(inline=True)
def energy_density_hess_diag(

with_actors abstractmethod ¤

with_actors(actors: NodeContainer[Actor]) -> Self
Source code in src/liblaf/apple/energy/elastic/phace_static.py
27
28
29
@property
def mu(self) -> Float[jax.Array, " cells"]:
    return self.actor.cell_data["mu"]