Skip to content

Commit 5065b43

Browse files
committed
Allow dynamic quadrature in HyperElasticPotential
1 parent c27a00c commit 5065b43

File tree

10 files changed

+428
-508
lines changed

10 files changed

+428
-508
lines changed

bindings/pypbat/fem/HyperElasticPotential.cpp

Lines changed: 191 additions & 239 deletions
Large diffs are not rendered by default.

python/examples/elasticity.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@
5252

5353
# Create hyper elastic potential
5454
Y, nu, energy = args.Y, args.nu, pbat.fem.HyperElasticEnergy.StableNeoHookean
55-
hep, detJeU, GNeU = pbat.fem.hyper_elastic_potential(
56-
mesh, Y=Y, nu=nu, energy=energy, detJe=detJeF)
55+
hep, egU, wgU, GNeU = pbat.fem.hyper_elastic_potential(
56+
mesh, Y=Y, nu=nu, energy=energy)
5757

5858
# Set Dirichlet boundary conditions
5959
Xmin = mesh.X.min(axis=1)

python/examples/elasticity_higher_order.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353

5454
# Create hyper elastic potential
5555
Y, nu, psi = args.Y, args.nu, pbat.fem.HyperElasticEnergy.StableNeoHookean
56-
hep, detJeU, GNeU = pbat.fem.hyper_elastic_potential(
56+
hep, egU, wgU, GNeU = pbat.fem.hyper_elastic_potential(
5757
mesh, Y=Y, nu=nu, energy=psi, quadrature_order=4)
5858

5959
# Set Dirichlet boundary conditions

python/examples/ipc.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,8 +378,8 @@ def __call__(self, xk: np.ndarray):
378378

379379
# Create hyper elastic potential
380380
Y, nu, psi = args.Y, args.nu, pbat.fem.HyperElasticEnergy.StableNeoHookean
381-
hep, detJeU, GNeU = pbat.fem.hyper_elastic_potential(
382-
mesh, Y=Y, nu=nu, energy=psi, detJe=detJeF)
381+
hep, egU, wgU, GNeU = pbat.fem.hyper_elastic_potential(
382+
mesh, Y=Y, nu=nu, energy=psi)
383383

384384
# Setup IPC contact handling
385385
F = igl.boundary_facets(C)

python/examples/modes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def signal(w: float, v: np.ndarray, t: float, c: float, k: float):
3737
x = mesh.X.reshape(math.prod(mesh.X.shape), order='f')
3838
M, detJeM = pbat.fem.mass_matrix(mesh, rho=args.rho)
3939
Y, nu, energy = args.Y, args.nu, pbat.fem.HyperElasticEnergy.StableNeoHookean
40-
hep, detJeU, GNeU = pbat.fem.hyper_elastic_potential(
40+
hep, egU, wgU, GNeU = pbat.fem.hyper_elastic_potential(
4141
mesh, Y, nu, energy=energy)
4242
hep.compute_element_elasticity(x)
4343
U, gradU, HU = hep.eval(), hep.gradient(), hep.hessian()

python/examples/multigrid/linear_restriction_prolongation.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ def __init__(self, MD: pbat.fem.Mesh, MS: pbat.fem.Mesh, MT: pbat.fem.Mesh, H, l
148148
self.P = (self.NT.T @ (rho * self.Ig) @ self.NS).asformat('csc')
149149
self.rho = rho
150150
energy = pbat.fem.HyperElasticEnergy.StableNeoHookean
151-
self.hep, self.detJeU, self.GNeU = pbat.fem.hyper_elastic_potential(
151+
self.hep, self.egU, self.wgU, self.GNeU = pbat.fem.hyper_elastic_potential(
152152
MT, Y, nu, energy=energy)
153153
self.hxreg = hxreg
154154
self.X = MT.X
@@ -219,7 +219,7 @@ def __matmul__(self, B):
219219
def rest_pose_hessian(mesh, Y, nu):
220220
x = mesh.X.reshape(math.prod(mesh.X.shape), order='f')
221221
energy = pbat.fem.HyperElasticEnergy.StableNeoHookean
222-
hep, detJeU, GNeU = pbat.fem.hyper_elastic_potential(
222+
hep, egU, wgU, GNeU = pbat.fem.hyper_elastic_potential(
223223
mesh, Y, nu, energy=energy)
224224
hep.compute_element_elasticity(x)
225225
HU = hep.hessian()

python/pbatoolkit/fem.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
with contextlib.redirect_stdout(_strio):
1717
help(_fem)
1818
_strio.seek(0)
19-
setattr(__module, "__doc__", f"{getattr(__module, "__doc__")}\n\n{_strio.read()}")
19+
setattr(__module, "__doc__", f"{
20+
getattr(__module, "__doc__")}\n\n{_strio.read()}")
21+
2022

2123
def divergence(mesh, quadrature_order: int = 1, GNe: np.ndarray = None):
2224
"""Construct an FEM divergence operator such that composing div(grad(u))
@@ -68,8 +70,9 @@ def hyper_elastic_potential(
6870
energy=_fem.HyperElasticEnergy.StableNeoHookean,
6971
precompute_sparsity: bool = True,
7072
quadrature_order: int = 1,
71-
detJe: np.ndarray = None,
72-
GNe: np.ndarray = None):
73+
eg: np.ndarray = None,
74+
wg: np.ndarray = None,
75+
GNeg: np.ndarray = None):
7376
"""Construct an FEM hyper elastic potential
7477
7578
Args:
@@ -79,23 +82,27 @@ def hyper_elastic_potential(
7982
energy (pbat.fem.HyperElasticEnergy, optional): Constitutive model. Defaults to pbat.fem.HyperElasticEnergy.StableNeoHookean.
8083
precompute_sparsity (bool, optional): Precompute an acceleration data structure for fast hessian construction. Defaults to True.
8184
quadrature_order (int, optional): Polynomial order to use for potential (and its derivatives) evaluation. Defaults to 1.
82-
detJe (np.ndarray, optional): Jacobian determinants at quadrature points. Defaults to None.
83-
GNe (np.ndarray, optional): Shape function gradients at quadrature points. Defaults to None.
85+
eg (np.ndarray, optional): Elements corresponding to each quadrature weight in wg.
86+
wg (np.ndarray, optional): Quadrature weights at quadrature points. Defaults to None.
87+
GNeg (np.ndarray, optional): Shape function gradients at quadrature points. Defaults to None.
8488
8589
Returns:
8690
(pbat.fem.HyperElasticPotential, np.ndarray, np.ndarray):
8791
"""
88-
if detJe is None:
89-
detJe = _fem.jacobian_determinants(
92+
if eg is None or wg is None or GNeg is None:
93+
wg = _fem.inner_product_weights(
9094
mesh, quadrature_order=quadrature_order)
91-
if GNe is None:
92-
GNe = _fem.shape_function_gradients(
95+
eg = np.linspace(0, mesh.E.shape[1]-1,
96+
num=mesh.E.shape[1], dtype=np.int64)
97+
eg = np.repeat(eg, wg.shape[0])
98+
wg = wg.flatten(order="F")
99+
GNeg = _fem.shape_function_gradients(
93100
mesh, quadrature_order=quadrature_order)
94101
hep = _fem.HyperElasticPotential(
95-
mesh, detJe, GNe, Y, nu, energy=energy, quadrature_order=quadrature_order)
102+
mesh, eg, wg, GNeg, Y, nu, energy=energy)
96103
if precompute_sparsity:
97104
hep.precompute_hessian_sparsity()
98-
return hep, detJe, GNe
105+
return hep, eg, wg, GNeg
99106

100107

101108
def laplacian(

source/pbat/fem/HyperElasticPotential.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,23 @@ TEST_CASE("[fem] HyperElasticPotential")
3838
else
3939
return kOrder - 1;
4040
}();
41-
using ElasticEnergyType = physics::StableNeoHookeanEnergy<3>;
42-
using ElementType = fem::Tetrahedron<kOrder>;
43-
using MeshType = fem::Mesh<ElementType, kDims>;
44-
using ElasticPotentialType =
45-
fem::HyperElasticPotential<MeshType, ElasticEnergyType, kQuadratureOrder>;
46-
using QuadratureType = ElasticPotentialType::QuadratureRuleType;
41+
using ElasticEnergyType = physics::StableNeoHookeanEnergy<3>;
42+
using ElementType = fem::Tetrahedron<kOrder>;
43+
using MeshType = fem::Mesh<ElementType, kDims>;
44+
using ElasticPotentialType = fem::HyperElasticPotential<MeshType, ElasticEnergyType>;
4745

4846
CHECK(math::CLinearOperator<ElasticPotentialType>);
4947

5048
MeshType const M(V, C);
51-
VectorX const x = M.X.reshaped();
52-
MatrixX const detJe = fem::DeterminantOfJacobian<kQuadratureOrder>(M);
53-
MatrixX const GNe = fem::ShapeFunctionGradients<kQuadratureOrder>(M);
54-
ElasticPotentialType U(M, detJe, GNe, x, Y, nu);
49+
VectorX const x = M.X.reshaped();
50+
MatrixX const WG = fem::InnerProductWeights<kQuadratureOrder>(M);
51+
VectorX const wg = WG.reshaped();
52+
MatrixX const GNeg = fem::ShapeFunctionGradients<kQuadratureOrder>(M);
53+
IndexVectorX const eg = IndexVectorX::LinSpaced(M.E.cols(), Index(0), M.E.cols() - 1)
54+
.replicate(1, WG.rows())
55+
.transpose()
56+
.reshaped();
57+
ElasticPotentialType U(M, eg, wg, GNeg, x, Y, nu);
5558
Scalar const UMaterial = U.Eval();
5659
VectorX const gradUMaterial = U.ToVector();
5760
CSCMatrix const HMaterial = U.ToMatrix();

0 commit comments

Comments
 (0)