Skip to content

Commit e2edd7a

Browse files
committed
Modify elasticity codegen for nvcc compliance
std::tuple is not supported by nvcc.
1 parent 3bb23c8 commit e2edd7a

File tree

11 files changed

+994
-875
lines changed

11 files changed

+994
-875
lines changed

python/elasticity/potentials.py

Lines changed: 73 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ def codegen(fpsi, energy_name: str):
5555
#include "pbat/math/linalg/mini/Matrix.h"
5656
5757
#include <cmath>
58-
#include <tuple>
5958
6059
namespace pbat {{
6160
namespace physics {{
@@ -82,17 +81,17 @@ def codegen(fpsi, energy_name: str):
8281
hesspsicode = cg.codegen(hesspsi.transpose(
8382
), lhs=sp.MatrixSymbol("H", vecF.shape[0], vecF.shape[0]), scalar_type="ScalarType")
8483
evalgradpsi = cg.codegen([psi, gradpsi], lhs=[sp.Symbol(
85-
"psi"), sp.MatrixSymbol("G", *gradpsi.shape)], scalar_type="ScalarType")
84+
"psi"), sp.MatrixSymbol("gF", *gradpsi.shape)], scalar_type="ScalarType")
8685
evalgradhesspsi = cg.codegen([psi, gradpsi, hesspsi], lhs=[
8786
sp.Symbol("psi"),
88-
sp.MatrixSymbol("G", *gradpsi.shape),
87+
sp.MatrixSymbol("gF", *gradpsi.shape),
8988
sp.MatrixSymbol(
90-
"H", vecF.shape[0], vecF.shape[0])
89+
"HF", vecF.shape[0], vecF.shape[0])
9190
], scalar_type="ScalarType")
9291
gradhesspsi = cg.codegen([gradpsi, hesspsi], lhs=[
93-
sp.MatrixSymbol("G", *gradpsi.shape),
92+
sp.MatrixSymbol("gF", *gradpsi.shape),
9493
sp.MatrixSymbol(
95-
"H", vecF.shape[0], vecF.shape[0])
94+
"HF", vecF.shape[0], vecF.shape[0])
9695
], scalar_type="ScalarType")
9796
impl = f"""
9897
template <>
@@ -131,39 +130,45 @@ def codegen(fpsi, energy_name: str):
131130
typename TMatrix::ScalarType mu,
132131
typename TMatrix::ScalarType lambda) const;
133132
134-
template <math::linalg::mini::CReadableVectorizedMatrix TMatrix>
135-
PBAT_HOST_DEVICE
136-
std::tuple<
137-
typename TMatrix::ScalarType,
138-
SVector<typename TMatrix::ScalarType, {vecF.shape[0]}>
133+
template <
134+
math::linalg::mini::CReadableVectorizedMatrix TMatrix,
135+
math::linalg::mini::CWriteableVectorizedMatrix TMatrixGF
139136
>
137+
PBAT_HOST_DEVICE
138+
typename TMatrix::ScalarType
140139
evalWithGrad(
141140
TMatrix const& F,
142141
typename TMatrix::ScalarType mu,
143-
typename TMatrix::ScalarType lambda) const;
142+
typename TMatrix::ScalarType lambda,
143+
TMatrixGF& gF) const;
144144
145-
template <math::linalg::mini::CReadableVectorizedMatrix TMatrix>
146-
PBAT_HOST_DEVICE
147-
std::tuple<
148-
typename TMatrix::ScalarType,
149-
SVector<typename TMatrix::ScalarType, {vecF.shape[0]}>,
150-
SMatrix<typename TMatrix::ScalarType, {vecF.shape[0]},{vecF.shape[0]}>
145+
template <
146+
math::linalg::mini::CReadableVectorizedMatrix TMatrix,
147+
math::linalg::mini::CWriteableVectorizedMatrix TMatrixGF,
148+
math::linalg::mini::CWriteableVectorizedMatrix TMatrixHF
151149
>
150+
PBAT_HOST_DEVICE
151+
typename TMatrix::ScalarType
152152
evalWithGradAndHessian(
153153
TMatrix const& F,
154154
typename TMatrix::ScalarType mu,
155-
typename TMatrix::ScalarType lambda) const;
156-
157-
template <math::linalg::mini::CReadableVectorizedMatrix TMatrix>
158-
PBAT_HOST_DEVICE
159-
std::tuple<
160-
SVector<typename TMatrix::ScalarType, {vecF.shape[0]}>,
161-
SMatrix<typename TMatrix::ScalarType, {vecF.shape[0]},{vecF.shape[0]}>
155+
typename TMatrix::ScalarType lambda,
156+
TMatrixGF& gF,
157+
TMatrixHF& HF) const;
158+
159+
template <
160+
math::linalg::mini::CReadableVectorizedMatrix TMatrix,
161+
math::linalg::mini::CWriteableVectorizedMatrix TMatrixGF,
162+
math::linalg::mini::CWriteableVectorizedMatrix TMatrixHF
162163
>
164+
PBAT_HOST_DEVICE
165+
void
163166
gradAndHessian(
164167
TMatrix const& F,
165168
typename TMatrix::ScalarType mu,
166-
typename TMatrix::ScalarType lambda) const;
169+
typename TMatrix::ScalarType lambda,
170+
TMatrixGF& gF,
171+
TMatrixHF& HF) const;
167172
}};
168173
169174
template <math::linalg::mini::CReadableVectorizedMatrix TMatrix>
@@ -208,60 +213,75 @@ def codegen(fpsi, energy_name: str):
208213
return H;
209214
}}
210215
211-
template <math::linalg::mini::CReadableVectorizedMatrix TMatrix>
212-
PBAT_HOST_DEVICE
213-
std::tuple<
214-
typename TMatrix::ScalarType,
215-
{energy_name}<{d}>::SVector<typename TMatrix::ScalarType, {vecF.shape[0]}>
216+
template <
217+
math::linalg::mini::CReadableVectorizedMatrix TMatrix,
218+
math::linalg::mini::CWriteableVectorizedMatrix TMatrixGF
216219
>
220+
PBAT_HOST_DEVICE
221+
typename TMatrix::ScalarType
217222
{energy_name}<{d}>::evalWithGrad(
218223
[[maybe_unused]] TMatrix const& F,
219224
[[maybe_unused]] typename TMatrix::ScalarType mu,
220-
[[maybe_unused]] typename TMatrix::ScalarType lambda) const
225+
[[maybe_unused]] typename TMatrix::ScalarType lambda,
226+
TMatrixGF& gF) const
221227
{{
228+
static_assert(
229+
TMatrixGF::kRows == {vecF.shape[0]} and TMatrixGF::kCols == 1,
230+
"Grad w.r.t. F must have dimensions {vecF.shape[0]}x1");
222231
using ScalarType = typename TMatrix::ScalarType;
223232
ScalarType psi;
224-
SVector<ScalarType, {vecF.shape[0]}> G;
225233
{cg.tabulate(evalgradpsi, spaces=4)}
226-
return {{psi, G}};
234+
return psi;
227235
}}
228236
229-
template <math::linalg::mini::CReadableVectorizedMatrix TMatrix>
230-
PBAT_HOST_DEVICE
231-
std::tuple<
232-
typename TMatrix::ScalarType,
233-
{energy_name}<{d}>::SVector<typename TMatrix::ScalarType, {vecF.shape[0]}>,
234-
{energy_name}<{d}>::SMatrix<typename TMatrix::ScalarType, {vecF.shape[0]},{vecF.shape[0]}>
237+
template <
238+
math::linalg::mini::CReadableVectorizedMatrix TMatrix,
239+
math::linalg::mini::CWriteableVectorizedMatrix TMatrixGF,
240+
math::linalg::mini::CWriteableVectorizedMatrix TMatrixHF
235241
>
242+
PBAT_HOST_DEVICE
243+
typename TMatrix::ScalarType
236244
{energy_name}<{d}>::evalWithGradAndHessian(
237245
[[maybe_unused]] TMatrix const& F,
238246
[[maybe_unused]] typename TMatrix::ScalarType mu,
239-
[[maybe_unused]] typename TMatrix::ScalarType lambda) const
247+
[[maybe_unused]] typename TMatrix::ScalarType lambda,
248+
TMatrixGF& gF,
249+
TMatrixHF& HF) const
240250
{{
251+
static_assert(
252+
TMatrixGF::kRows == {vecF.shape[0]} and TMatrixGF::kCols == 1,
253+
"Grad w.r.t. F must have dimensions {vecF.shape[0]}x1");
254+
static_assert(
255+
TMatrixHF::kRows == {vecF.shape[0]} and TMatrixHF::kCols == {vecF.shape[0]},
256+
"Hessian w.r.t. F must have dimensions {vecF.shape[0]}x{vecF.shape[0]}");
241257
using ScalarType = typename TMatrix::ScalarType;
242258
ScalarType psi;
243-
SVector<ScalarType, {vecF.shape[0]}> G;
244-
SMatrix<ScalarType, {vecF.shape[0]},{vecF.shape[0]}> H;
245259
{cg.tabulate(evalgradhesspsi, spaces=4)}
246-
return {{psi, G, H}};
260+
return psi;
247261
}}
248262
249-
template <math::linalg::mini::CReadableVectorizedMatrix TMatrix>
250-
PBAT_HOST_DEVICE
251-
std::tuple<
252-
{energy_name}<{d}>::SVector<typename TMatrix::ScalarType, {vecF.shape[0]}>,
253-
{energy_name}<{d}>::SMatrix<typename TMatrix::ScalarType, {vecF.shape[0]},{vecF.shape[0]}>
263+
template <
264+
math::linalg::mini::CReadableVectorizedMatrix TMatrix,
265+
math::linalg::mini::CWriteableVectorizedMatrix TMatrixGF,
266+
math::linalg::mini::CWriteableVectorizedMatrix TMatrixHF
254267
>
268+
PBAT_HOST_DEVICE
269+
void
255270
{energy_name}<{d}>::gradAndHessian(
256271
[[maybe_unused]] TMatrix const& F,
257272
[[maybe_unused]] typename TMatrix::ScalarType mu,
258-
[[maybe_unused]] typename TMatrix::ScalarType lambda) const
273+
[[maybe_unused]] typename TMatrix::ScalarType lambda,
274+
TMatrixGF& gF,
275+
TMatrixHF& HF) const
259276
{{
277+
static_assert(
278+
TMatrixGF::kRows == {vecF.shape[0]} and TMatrixGF::kCols == 1,
279+
"Grad w.r.t. F must have dimensions {vecF.shape[0]}x1");
280+
static_assert(
281+
TMatrixHF::kRows == {vecF.shape[0]} and TMatrixHF::kCols == {vecF.shape[0]},
282+
"Hessian w.r.t. F must have dimensions {vecF.shape[0]}x{vecF.shape[0]}");
260283
using ScalarType = typename TMatrix::ScalarType;
261-
SVector<ScalarType, {vecF.shape[0]}> G;
262-
SMatrix<ScalarType, {vecF.shape[0]},{vecF.shape[0]}> H;
263284
{cg.tabulate(gradhesspsi, spaces=4)}
264-
return {{G, H}};
265285
}}
266286
"""
267287
source.append(impl)

python/examples/elasticity.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
# Create hyper elastic potential
5454
Y, nu, energy = args.Y, args.nu, pbat.fem.HyperElasticEnergy.StableNeoHookean
5555
hep, detJeU, GNeU = pbat.fem.hyper_elastic_potential(
56-
mesh, Y=Y, nu=nu, energy=energy, detJ=detJeF)
56+
mesh, Y=Y, nu=nu, energy=energy, detJe=detJeF)
5757

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

python/examples/ipc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ def __call__(self, xk: np.ndarray):
379379
# Create hyper elastic potential
380380
Y, nu, psi = args.Y, args.nu, pbat.fem.HyperElasticEnergy.StableNeoHookean
381381
hep, detJeU, GNeU = pbat.fem.hyper_elastic_potential(
382-
mesh, Y=Y, nu=nu, energy=psi, detJ=detJeF)
382+
mesh, Y=Y, nu=nu, energy=psi, detJe=detJeF)
383383

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

python/examples/vbd.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def partition_vertices(GVT, dbcs):
118118
GNeU = pbat.fem.shape_function_gradients(mesh, quadrature_order=1)
119119
g = np.zeros(mesh.dims)
120120
g[-1] = -9.81
121-
f, detJeF = pbat.fem.load_vector(mesh, rho*g, detJ=detJeU, flatten=False)
121+
f, detJeF = pbat.fem.load_vector(mesh, rho*g, detJe=detJeU, flatten=False)
122122
a = f / m
123123

124124
# Compute material (Lame) constants

source/pbat/fem/HyperElasticPotential.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,9 @@ HyperElasticPotential<TMesh, THyperElasticEnergy, QuadratureOrder>::ComputeEleme
241241
auto constexpr kNodesPerElement = ElementType::kNodes;
242242
auto constexpr kDofsPerElement = kNodesPerElement * kDims;
243243
auto const wg = common::ToEigen(QuadratureRuleType::weights);
244-
using math::linalg::mini::FromEigen;
245-
using math::linalg::mini::ToEigen;
244+
namespace mini = math::linalg::mini;
245+
using mini::FromEigen;
246+
using mini::ToEigen;
246247
if (not bWithGradient and not bWithHessian)
247248
{
248249
tbb::parallel_for(Index{0}, Index{numberOfElements}, [&](Index e) {
@@ -275,7 +276,8 @@ HyperElasticPotential<TMesh, THyperElasticEnergy, QuadratureOrder>::ComputeEleme
275276
e * kStride + g * MeshType::kDims);
276277
Matrix<kDims, kDims> const F = xe * gradPhi;
277278
auto vecF = FromEigen(F);
278-
auto [psiF, gradPsiF] = Psi.evalWithGrad(vecF, mue(g, e), lambdae(g, e));
279+
mini::SVector<Scalar, kDims * kDims> gradPsiF;
280+
auto psiF = Psi.evalWithGrad(vecF, mue(g, e), lambdae(g, e), gradPsiF);
279281
Ue(e) += (wg(g) * detJe(g, e)) * psiF;
280282
auto const GP = FromEigen(gradPhi);
281283
auto GPsix = GradientWrtDofs<ElementType, kDims>(gradPsiF, GP);
@@ -321,8 +323,10 @@ HyperElasticPotential<TMesh, THyperElasticEnergy, QuadratureOrder>::ComputeEleme
321323
e * kStride + g * MeshType::kDims);
322324
Matrix<kDims, kDims> const F = xe * gradPhi;
323325
auto vecF = FromEigen(F);
324-
auto [psiF, gradPsiF, hessPsiF] =
325-
Psi.evalWithGradAndHessian(vecF, mue(g, e), lambdae(g, e));
326+
mini::SVector<Scalar, kDims * kDims> gradPsiF;
327+
mini::SMatrix<Scalar, kDims * kDims, kDims * kDims> hessPsiF;
328+
auto psiF =
329+
Psi.evalWithGradAndHessian(vecF, mue(g, e), lambdae(g, e), gradPsiF, hessPsiF);
326330
Ue(e) += (wg(g) * detJe(g, e)) * psiF;
327331
auto const GP = FromEigen(gradPhi);
328332
auto GPsix = GradientWrtDofs<ElementType, kDims>(gradPsiF, GP);

source/pbat/gpu/vbd/VbdImplKernels.cu

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,9 @@ __global__ void MinimizeBackwardEuler(BackwardEulerMinimization BDF)
4444
// 2. Accumulate results into vertex hessian and gradient
4545
SVector<GpuScalar, 3> xti = FromBuffers<3, 1>(BDF.xt, i);
4646
SVector<GpuScalar, 3> xitilde = FromBuffers<3, 1>(BDF.xtilde, i);
47-
SVector<GpuScalar, 3> xi{
48-
BDF.x[0][i],
49-
BDF.x[1][i],
50-
BDF.x[2][i]} /*= FromBuffers<3, 1>(BDF.x, i)*/;
51-
SMatrix<GpuScalar, 3, 3> Hi = Zeros<GpuScalar, 3, 3>{};
52-
SVector<GpuScalar, 3> gi = Zeros<GpuScalar, 3, 1>{};
47+
SVector<GpuScalar, 3> xi = FromBuffers<3, 1>(BDF.x, i);
48+
SMatrix<GpuScalar, 3, 3> Hi = Zeros<GpuScalar, 3, 3>{};
49+
SVector<GpuScalar, 3> gi = Zeros<GpuScalar, 3, 1>{};
5350
// Add elastic energy derivatives
5451
auto const nActiveThreads = min(nAdjacentElements, nThreadsPerBlock);
5552
for (auto j = 0; j < nActiveThreads; ++j)
@@ -93,14 +90,10 @@ PBAT_DEVICE void BackwardEulerMinimization::ComputeStableNeoHookeanDerivatives(
9390
SMatrix<GpuScalar, 3, 4> xe = FromBuffers(x, v.Transpose());
9491
SMatrix<GpuScalar, 4, 3> GPe = FromFlatBuffer<4, 3>(GP, e);
9592
SMatrix<GpuScalar, 3, 3> Fe = xe * GPe;
93+
physics::StableNeoHookeanEnergy<3> Psi{};
9694
SVector<GpuScalar, 9> gF;
9795
SMatrix<GpuScalar, 9, 9> HF;
98-
physics::StableNeoHookeanEnergy<3> Psi{};
99-
// NOTE:
100-
// For some reason, nvcc doesn't like structured bindings, so I can't write
101-
// auto [gF, HF] = Psi.gradAndHessian(Fe, lamee(0), lamee(1));
102-
// or else I get nan values?? Weird.
103-
std::tie(gF, HF) = Psi.gradAndHessian(Fe, lamee(0), lamee(1));
96+
Psi.gradAndHessian(Fe, lamee(0), lamee(1), gF, HF);
10497
// Write vertex-specific derivatives into output memory HGe
10598
SMatrixView<GpuScalar, 3, 4> HGei(Hge);
10699
auto Hi = HGei.Slice<3, 3>(0, 0);

source/pbat/physics/HyperElasticity.h

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#include <fmt/core.h>
1010
#include <pbat/Aliases.h>
1111
#include <string>
12-
#include <tuple>
1312

1413
namespace pbat {
1514
namespace physics {
@@ -40,26 +39,25 @@ concept CHyperElasticEnergy = requires(T t)
4039
t.evalWithGrad(
4140
math::linalg::mini::SMatrix<Scalar, T::kDims * T::kDims>{},
4241
Scalar{},
43-
Scalar{})
44-
} -> std::convertible_to<
45-
std::tuple<Scalar, math::linalg::mini::SVector<Scalar, T::kDims * T::kDims>>>;
42+
Scalar{},
43+
std::declval<math::linalg::mini::SVector<Scalar, T::kDims * T::kDims>&>())
44+
} -> std::convertible_to<Scalar>;
4645
{
4746
t.evalWithGradAndHessian(
4847
math::linalg::mini::SMatrix<Scalar, T::kDims * T::kDims>{},
4948
Scalar{},
50-
Scalar{})
51-
} -> std::convertible_to<std::tuple<
52-
Scalar,
53-
math::linalg::mini::SVector<Scalar, T::kDims * T::kDims>,
54-
math::linalg::mini::SMatrix<Scalar, T::kDims * T::kDims, T::kDims * T::kDims>>>;
55-
{
56-
t.gradAndHessian(
57-
math::linalg::mini::SMatrix<Scalar, T::kDims * T::kDims>{},
5849
Scalar{},
59-
Scalar{})
60-
} -> std::convertible_to<std::tuple<
61-
math::linalg::mini::SVector<Scalar, T::kDims * T::kDims>,
62-
math::linalg::mini::SMatrix<Scalar, T::kDims * T::kDims, T::kDims * T::kDims>>>;
50+
std::declval<math::linalg::mini::SVector<Scalar, T::kDims * T::kDims>&>(),
51+
std::declval<
52+
math::linalg::mini::SMatrix<Scalar, T::kDims * T::kDims, T::kDims * T::kDims>&>())
53+
} -> std::convertible_to<Scalar>;
54+
{t.gradAndHessian(
55+
math::linalg::mini::SMatrix<Scalar, T::kDims * T::kDims>{},
56+
Scalar{},
57+
Scalar{},
58+
std::declval<math::linalg::mini::SVector<Scalar, T::kDims * T::kDims>&>(),
59+
std::declval<
60+
math::linalg::mini::SMatrix<Scalar, T::kDims * T::kDims, T::kDims * T::kDims>&>())};
6361
};
6462

6563
template <class TDerivedY, class TDerivednu>

source/pbat/physics/SaintVenantKirchhoffEnergy.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,21 @@
99
TEST_CASE("[physics] SaintVenantKirchhoffEnergy")
1010
{
1111
using namespace pbat;
12+
namespace mini = pbat::math::linalg::mini;
1213
common::ForValues<1, 2, 3>([]<auto Dims>() {
13-
using math::linalg::mini::FromEigen;
14+
using mini::FromEigen;
1415
physics::SaintVenantKirchhoffEnergy<Dims> psi{};
1516
Matrix<Dims, Dims> const F = Matrix<Dims, Dims>::Identity();
1617
Scalar constexpr Y = 1e6;
1718
Scalar constexpr nu = 0.45;
1819
auto const [mu, lambda] = physics::LameCoefficients(Y, nu);
1920
auto vecF = FromEigen(F.reshaped());
2021
Scalar const ePsi = psi.eval(vecF, mu, lambda);
21-
auto const eGradPsi = psi.evalWithGrad(vecF, mu, lambda);
22-
Scalar const ePsiFromGrad = std::get<0>(eGradPsi);
23-
auto const eGradHessPsi = psi.evalWithGradAndHessian(vecF, mu, lambda);
24-
Scalar const ePsiFromHess = std::get<0>(eGradHessPsi);
22+
mini::SVector<Scalar, Dims * Dims> gF;
23+
Scalar const ePsiFromGrad = psi.evalWithGrad(vecF, mu, lambda, gF);
24+
gF.SetZero();
25+
mini::SMatrix<Scalar, Dims * Dims, Dims * Dims> HF;
26+
Scalar const ePsiFromHess = psi.evalWithGradAndHessian(vecF, mu, lambda, gF, HF);
2527
bool const bIsEnergyNonNegative =
2628
(ePsi >= 0.) && (ePsiFromGrad >= 0.) && (ePsiFromHess >= 0.);
2729
CHECK(bIsEnergyNonNegative);
@@ -30,8 +32,8 @@ TEST_CASE("[physics] SaintVenantKirchhoffEnergy")
3032
Scalar const trE = E.trace();
3133
Scalar const ePsiExpected = mu * (E.array() * E.array()).sum() + 0.5 * lambda * trE * trE;
3234
Scalar const ePsiError = std::abs(ePsi - ePsiExpected) +
33-
std::abs(std::get<0>(eGradPsi) - ePsiExpected) +
34-
std::abs(std::get<0>(eGradHessPsi) - ePsiExpected);
35+
std::abs(ePsiFromGrad - ePsiExpected) +
36+
std::abs(ePsiFromHess - ePsiExpected);
3537
Scalar constexpr zero = 1e-15;
3638
CHECK_LE(ePsiError, zero);
3739
});

0 commit comments

Comments
 (0)