PolyFEM
Loading...
Searching...
No Matches
GenericElastic.hpp
Go to the documentation of this file.
1#pragma once
2
5
7
8// non linear NeoHookean material model
9namespace polyfem::assembler
10{
11 enum class AutodiffType
12 {
13 FULL,
14 STRESS,
15 NONE
16 };
17
18 template <typename T>
19 using DefGradMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3>;
20
21 template <typename Derived>
23 {
24 public:
28
30 virtual ~GenericElastic() = default;
31
32 // energy, gradient, and hessian used in newton method
33 double compute_energy(const NonLinearAssemblerData &data) const override;
34 Eigen::MatrixXd assemble_hessian(const NonLinearAssemblerData &data) const override;
35 Eigen::VectorXd assemble_gradient(const NonLinearAssemblerData &data) const override;
36
37 void assign_stress_tensor(const OutputData &data,
38 const int all_size,
39 const ElasticityTensorType &type,
40 Eigen::MatrixXd &all,
41 const std::function<Eigen::MatrixXd(const Eigen::MatrixXd &)> &fun) const override;
42
44 const Eigen::MatrixXd &mat,
45 Eigen::MatrixXd &stress,
46 Eigen::MatrixXd &result) const override;
47
49 Eigen::MatrixXd &stress,
50 Eigen::MatrixXd &result) const override;
51
53 const Eigen::MatrixXd &vect,
54 Eigen::MatrixXd &stress,
55 Eigen::MatrixXd &result) const override;
56
58 Derived &derived() { return static_cast<Derived &>(*this); }
60 const Derived &derived() const { return static_cast<const Derived &>(*this); }
61
62 // sets material params
63 virtual void add_multimaterial(const int index, const json &params, const Units &units, const io::ResourceIO &resources) override = 0;
64
65 bool allow_inversion() const override { return true; }
66
67 virtual bool real_def_grad(const RowVectorNd &p, const double t, const int el_id) const { return true; }
68
69 protected:
71
72 virtual Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> gradient(
73 const RowVectorNd &p,
74 const double t,
75 const int el_id,
76 const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> &F) const
77 {
78 log_and_throw_error("gradient not implemented");
79 }
80
81 virtual Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 9, 9> hessian(
82 const RowVectorNd &p,
83 const double t,
84 const int el_id,
85 const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> &F) const
86 {
87 log_and_throw_error("hessian not implemented");
88 }
89
90 private:
91 // Absolute AMIPS: E = sum_e AMIPS(D_e), one term per element. D_e maps the regular
92 // element to the deformed one; the rest mesh does not enter it, so it must not weight
93 // it either. da integrates over the rest mesh; dividing by det(dX/dxi) * |reference
94 // element| turns that into the mean of AMIPS over the reference element.
95 // Each quadrature point takes the weight of its own mode.
96 Eigen::VectorXd point_weights(const NonLinearAssemblerData &data) const
97 {
98 const int n_pts = data.da.size();
99 bool any_absolute = false;
100 for (int p = 0; p < n_pts; ++p)
101 any_absolute |= !rest_pose_at(data, p);
102 if (!any_absolute)
103 return data.da;
104
105 // A per-element AMIPS is defined only on straight simplices with linear displacement.
106 const int n_simplex_bases = size() + 1;
107 if (int(data.vals.basis_values.size()) != n_simplex_bases || data.vals.n_geometric_bases != n_simplex_bases)
109 "Absolute mode (use_rest_pose false) needs straight simplices with linear displacement; element {} has {} bases and {} geometric bases",
110 data.vals.element_id, data.vals.basis_values.size(), data.vals.n_geometric_bases);
111
112 const Eigen::VectorXd reference = data.da.array() / data.vals.det.array();
113 const double reference_volume = reference.sum();
114 Eigen::VectorXd w = data.da;
115 for (int p = 0; p < n_pts; ++p)
116 if (!rest_pose_at(data, p))
117 w(p) = reference(p) / reference_volume;
118 return w;
119 }
120
121 // Whether quadrature point p measures distortion from the rest pose (true) or from the regular element.
122 bool rest_pose_at(const NonLinearAssemblerData &data, const long p) const
123 {
124 return derived().real_def_grad(data.vals.val.row(p), data.t, data.vals.element_id);
125 }
126
127 // utility function that computes energy, the template is used for double, DScalar1, and DScalar2 in energy, gradient and hessian
128 template <typename T>
130 {
131 typedef Eigen::Matrix<T, Eigen::Dynamic, 1> AutoDiffVect;
132 typedef Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> AutoDiffGradMat;
133 typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> DoubleGradMat;
134
135 AutoDiffVect local_disp;
136 get_local_disp(data, size(), local_disp);
137
138 AutoDiffGradMat def_grad(size(), size());
139
140 T energy = T(0.0);
141
142 const int n_pts = data.da.size();
143 const Eigen::VectorXd w = point_weights(data);
144 for (long p = 0; p < n_pts; ++p)
145 {
146 compute_disp_grad_at_quad(data, local_disp, p, size(), def_grad);
147
148 // Id + grad d
149 for (int d = 0; d < size(); ++d)
150 def_grad(d, d) += T(1);
151
152 if (!rest_pose_at(data, p))
153 {
154 DoubleGradMat tmp_jac_it = data.vals.jac_it[p];
155 tmp_jac_it = tmp_jac_it.inverse();
156
157 AutoDiffGradMat jac_it(size(), size());
158 for (long k = 0; k < jac_it.size(); ++k)
159 jac_it(k) = T(tmp_jac_it(k));
160
161 def_grad *= jac_it;
162 }
163
164 const T val = derived().elastic_energy(data.vals.val.row(p), data.t, data.vals.element_id, def_grad);
165
166 energy += val * w(p);
167 }
168 return energy;
169 }
170
171 Eigen::MatrixXd assemble_hessian_full_ad(const NonLinearAssemblerData &data) const;
172 Eigen::VectorXd assemble_gradient_full_ad(const NonLinearAssemblerData &data) const;
173
174 Eigen::MatrixXd assemble_hessian_stress_ad(const NonLinearAssemblerData &data) const;
175 Eigen::VectorXd assemble_gradient_stress_ad(const NonLinearAssemblerData &data) const;
176
177 Eigen::MatrixXd assemble_hessian_stress_noad(const NonLinearAssemblerData &data) const;
178 Eigen::VectorXd assemble_gradient_stress_noad(const NonLinearAssemblerData &data) const;
179
180 template <int n_basis, int dim>
181 void compute_gradient_from_stress(const NonLinearAssemblerData &data, Eigen::VectorXd &res) const
182 {
184 typedef Eigen::Matrix<Diff, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> AutoDiffGradMat;
185 typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> DoubleGradMat;
186
187 const int n_pts = data.da.size();
188 const Eigen::VectorXd w = point_weights(data);
189
190 Eigen::Matrix<double, n_basis, dim> local_disp(data.vals.basis_values.size(), size());
191 local_disp.setZero();
192 for (size_t i = 0; i < data.vals.basis_values.size(); ++i)
193 {
194 const auto &bs = data.vals.basis_values[i];
195 for (size_t ii = 0; ii < bs.global.size(); ++ii)
196 {
197 for (int d = 0; d < dim; ++d)
198 {
199 local_disp(i, d) += bs.global[ii].val * data.x(bs.global[ii].index * size() + d);
200 }
201 }
202 }
203
204 Eigen::Matrix<double, dim, dim> def_grad(size(), size());
206 AutoDiffGradMat def_grad_ad(size(), size());
207
208 res.resize(data.vals.basis_values.size() * size());
209 res.setZero();
210
211 for (long p = 0; p < n_pts; ++p)
212 {
213 Eigen::Matrix<double, n_basis, dim> grad(data.vals.basis_values.size(), size());
214
215 for (size_t i = 0; i < data.vals.basis_values.size(); ++i)
216 grad.row(i) = data.vals.basis_values[i].grad.row(p);
217
218 Eigen::Matrix<double, dim, dim> jac_it = data.vals.jac_it[p];
219 Eigen::Matrix<double, n_basis, dim> G = grad * jac_it;
220 def_grad = local_disp.transpose() * G + Eigen::Matrix<double, dim, dim>::Identity(size(), size());
221
222 for (int d1 = 0; d1 < size(); ++d1)
223 for (int d2 = 0; d2 < size(); ++d2)
224 def_grad_ad(d1, d2) = Diff(d1 * size() + d2, def_grad(d1, d2));
225
226 if (!rest_pose_at(data, p))
227 {
228 DoubleGradMat tmp_jac_it = data.vals.jac_it[p];
229 tmp_jac_it = tmp_jac_it.inverse();
230
231 AutoDiffGradMat jac_it(size(), size());
232 for (long k = 0; k < jac_it.size(); ++k)
233 jac_it(k) = Diff(tmp_jac_it(k));
234
235 def_grad_ad *= jac_it;
236 }
237
238 const Diff val = derived().elastic_energy(data.vals.val.row(p), data.t, data.vals.element_id, def_grad_ad);
239
240 Eigen::Matrix<double, dim, dim> P;
241 for (int i = 0; i < size(); ++i)
242 for (int j = 0; j < size(); ++j)
243 P(i, j) = val.getGradient()(i * size() + j);
244
245 const Eigen::Matrix<double, n_basis, dim> Rloc = G * P.transpose() * w(p);
246
247 for (int a = 0; a < data.vals.basis_values.size(); ++a)
248 for (int d = 0; d < size(); ++d)
249 res(a * size() + d) += Rloc(a, d);
250 }
251 }
252
253 template <int n_basis, int dim>
254 void compute_gradient_from_stress_noad(const NonLinearAssemblerData &data, Eigen::VectorXd &res) const
255 {
256 typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> DoubleGradMat;
257
258 const int n_pts = data.da.size();
259 const Eigen::VectorXd w = point_weights(data);
260
261 Eigen::Matrix<double, n_basis, dim> local_disp(data.vals.basis_values.size(), size());
262 local_disp.setZero();
263 for (size_t i = 0; i < data.vals.basis_values.size(); ++i)
264 {
265 const auto &bs = data.vals.basis_values[i];
266 for (size_t ii = 0; ii < bs.global.size(); ++ii)
267 {
268 for (int d = 0; d < dim; ++d)
269 {
270 local_disp(i, d) += bs.global[ii].val * data.x(bs.global[ii].index * size() + d);
271 }
272 }
273 }
274
275 Eigen::Matrix<double, dim, dim> def_grad(size(), size());
276 res.resize(data.vals.basis_values.size() * size());
277 res.setZero();
278
279 for (long p = 0; p < n_pts; ++p)
280 {
281 Eigen::Matrix<double, n_basis, dim> grad(data.vals.basis_values.size(), size());
282
283 for (size_t i = 0; i < data.vals.basis_values.size(); ++i)
284 grad.row(i) = data.vals.basis_values[i].grad.row(p);
285
286 Eigen::Matrix<double, dim, dim> jac_it = data.vals.jac_it[p];
287 Eigen::Matrix<double, n_basis, dim> G = grad * jac_it;
288 def_grad = local_disp.transpose() * G + Eigen::Matrix<double, dim, dim>::Identity(size(), size());
289
290 if (!rest_pose_at(data, p))
291 {
292 DoubleGradMat jac_it = data.vals.jac_it[p];
293 jac_it = jac_it.inverse();
294
295 def_grad *= jac_it;
296 }
297
298 const Eigen::Matrix<double, dim, dim> P = derived().gradient(data.vals.val.row(p), data.t, data.vals.element_id, def_grad);
299 const Eigen::Matrix<double, n_basis, dim> Bgrad = rest_pose_at(data, p) ? G : grad;
300 const Eigen::Matrix<double, n_basis, dim> Rloc = Bgrad * P.transpose() * w(p);
301
302 for (int a = 0; a < data.vals.basis_values.size(); ++a)
303 for (int d = 0; d < size(); ++d)
304 res(a * size() + d) += Rloc(a, d);
305 }
306 }
307
308 template <int n_basis, int dim>
309 void compute_hessian_from_stress(const NonLinearAssemblerData &data, Eigen::MatrixXd &H) const
310 {
311 typedef DScalar2<double, Eigen::Matrix<double, Eigen::Dynamic, 1, 0, 9, 1>, Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 9, 9>> Diff2;
312 typedef Eigen::Matrix<Diff2, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> AutoDiffGradMat;
313 typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> DoubleGradMat;
314
315 const int d = size();
316 const int nb = data.vals.basis_values.size();
317 const int n_pts = data.da.size();
318 const Eigen::VectorXd w = point_weights(data);
319
320 Eigen::Matrix<double, n_basis, dim> local_disp(nb, d);
321 local_disp.setZero();
322 for (size_t i = 0; i < data.vals.basis_values.size(); ++i)
323 {
324 const auto &bs = data.vals.basis_values[i];
325 for (size_t ii = 0; ii < bs.global.size(); ++ii)
326 {
327 for (int dd = 0; dd < d; ++dd)
328 local_disp(i, dd) += bs.global[ii].val * data.x(bs.global[ii].index * d + dd);
329 }
330 }
331
333 AutoDiffGradMat def_grad_ad(d, d);
334 Eigen::Matrix<double, dim, dim> def_grad(d, d);
335
336 H.resize(nb * d, nb * d);
337 H.setZero();
338
339 for (long p = 0; p < n_pts; ++p)
340 {
341 Eigen::Matrix<double, n_basis, dim> grad_ref(nb, d);
342 for (size_t i = 0; i < data.vals.basis_values.size(); ++i)
343 grad_ref.row(i) = data.vals.basis_values[i].grad.row(p);
344
345 const Eigen::Matrix<double, dim, dim> jac_it = data.vals.jac_it[p];
346 const Eigen::Matrix<double, n_basis, dim> G = grad_ref * jac_it;
347
348 def_grad = local_disp.transpose() * G + Eigen::Matrix<double, dim, dim>::Identity();
349
350 for (int i = 0; i < d; ++i)
351 for (int j = 0; j < d; ++j)
352 def_grad_ad(i, j) = Diff2(i * d + j, def_grad(i, j));
353
354 if (!rest_pose_at(data, p))
355 {
356 DoubleGradMat tmp_jac_it = data.vals.jac_it[p];
357 tmp_jac_it = tmp_jac_it.inverse();
358
359 AutoDiffGradMat jac_it(size(), size());
360 for (long k = 0; k < jac_it.size(); ++k)
361 jac_it(k) = Diff2(tmp_jac_it(k));
362
363 def_grad_ad *= jac_it;
364 }
365
366 const Diff2 val = derived().elastic_energy(data.vals.val.row(p), data.t, data.vals.element_id, def_grad_ad);
367
368 Eigen::Matrix<double, dim * dim, dim * dim> A(d * d, d * d);
369 A.setZero();
370
371 // Material tangent A = d vec(P) / d vec(F)
372 // Since P = dW/dF, A is just the Hessian of W wrt vec(F).
373 for (int r = 0; r < d * d; ++r)
374 for (int c = 0; c < d * d; ++c)
375 A(r, c) = val.getHessian()(r, c);
376
377 for (int a = 0; a < nb; ++a)
378 {
379 const Eigen::Matrix<double, dim * dim, dim> Ba = compute_B_block<dim>(G.row(a));
380
381 for (int b = 0; b < nb; ++b)
382 {
383 const Eigen::Matrix<double, dim * dim, dim> Bb = compute_B_block<dim>(G.row(b));
384
385 const Eigen::Matrix<double, dim, dim> Kab =
386 Ba.transpose() * A * Bb * w(p);
387
388 H.template block<dim, dim>(a * d, b * d) += Kab;
389 }
390 }
391 }
392 }
393
394 template <int n_basis, int dim>
395 void compute_hessian_from_stress_noad(const NonLinearAssemblerData &data, Eigen::MatrixXd &H) const
396 {
397 typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> DoubleGradMat;
398
399 const int d = size();
400 const int nb = data.vals.basis_values.size();
401 const int n_pts = data.da.size();
402 const Eigen::VectorXd w = point_weights(data);
403
404 Eigen::Matrix<double, n_basis, dim> local_disp(nb, d);
405 local_disp.setZero();
406 for (size_t i = 0; i < data.vals.basis_values.size(); ++i)
407 {
408 const auto &bs = data.vals.basis_values[i];
409 for (size_t ii = 0; ii < bs.global.size(); ++ii)
410 {
411 for (int dd = 0; dd < d; ++dd)
412 local_disp(i, dd) += bs.global[ii].val * data.x(bs.global[ii].index * d + dd);
413 }
414 }
415
416 Eigen::Matrix<double, dim, dim> def_grad(d, d);
417
418 H.resize(nb * d, nb * d);
419 H.setZero();
420
421 for (long p = 0; p < n_pts; ++p)
422 {
423 Eigen::Matrix<double, n_basis, dim> grad_ref(nb, d);
424 for (size_t i = 0; i < data.vals.basis_values.size(); ++i)
425 grad_ref.row(i) = data.vals.basis_values[i].grad.row(p);
426
427 const Eigen::Matrix<double, dim, dim> jac_it = data.vals.jac_it[p];
428 const Eigen::Matrix<double, n_basis, dim> G = grad_ref * jac_it;
429
430 def_grad = local_disp.transpose() * G + Eigen::Matrix<double, dim, dim>::Identity();
431
432 if (!rest_pose_at(data, p))
433 {
434 DoubleGradMat jac_it = data.vals.jac_it[p];
435 jac_it = jac_it.inverse();
436
437 def_grad *= jac_it;
438 }
439
440 // Material tangent A = d vec(P) / d vec(F)
441 // Since P = dW/dF, A is just the Hessian of W wrt vec(F).
442 Eigen::Matrix<double, dim * dim, dim * dim> A = derived().hessian(data.vals.val.row(p), data.t, data.vals.element_id, def_grad);
443
444 const Eigen::Matrix<double, n_basis, dim> Bgrad = rest_pose_at(data, p) ? G : grad_ref;
445
446 for (int a = 0; a < nb; ++a)
447 {
448 const Eigen::Matrix<double, dim * dim, dim> Ba = compute_B_block<dim>(Bgrad.row(a));
449
450 for (int b = 0; b < nb; ++b)
451 {
452 const Eigen::Matrix<double, dim * dim, dim> Bb = compute_B_block<dim>(Bgrad.row(b));
453
454 const Eigen::Matrix<double, dim, dim> Kab =
455 Ba.transpose() * A * Bb * w(p);
456
457 H.template block<dim, dim>(a * d, b * d) += Kab;
458 }
459 }
460 }
461 }
462
463 template <int dim>
464 Eigen::Matrix<double, dim * dim, dim> compute_B_block(const Eigen::Matrix<double, 1, dim> &g) const;
465 };
466} // namespace polyfem::assembler
double val
Definition Assembler.cpp:90
virtual void assemble_gradient(const bool is_volume, const int n_basis, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &cache, const double t, const double dt, const Eigen::MatrixXd &displacement, const Eigen::MatrixXd &displacement_prev, Eigen::MatrixXd &rhs) const
virtual void assemble_hessian(const bool is_volume, const int n_basis, const bool project_to_psd, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &cache, const double t, const double dt, const Eigen::MatrixXd &displacement, const Eigen::MatrixXd &displacement_prev, utils::MatrixCache &mat_cache, StiffnessMatrix &grad) const
virtual double assemble_energy(const bool is_volume, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &cache, const double t, const double dt, const Eigen::MatrixXd &displacement, const Eigen::MatrixXd &displacement_prev) const
Definition Assembler.hpp:82
std::vector< Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > > jac_it
void compute_stress_grad_multiply_stress(const OptAssemblerData &data, Eigen::MatrixXd &stress, Eigen::MatrixXd &result) const override
void compute_hessian_from_stress_noad(const NonLinearAssemblerData &data, Eigen::MatrixXd &H) const
void assign_stress_tensor(const OutputData &data, const int all_size, const ElasticityTensorType &type, Eigen::MatrixXd &all, const std::function< Eigen::MatrixXd(const Eigen::MatrixXd &)> &fun) const override
Eigen::Matrix< double, dim *dim, dim > compute_B_block(const Eigen::Matrix< double, 1, dim > &g) const
bool rest_pose_at(const NonLinearAssemblerData &data, const long p) const
Eigen::VectorXd assemble_gradient_full_ad(const NonLinearAssemblerData &data) const
virtual Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 9, 9 > hessian(const RowVectorNd &p, const double t, const int el_id, const Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > &F) const
Derived & derived()
Returns this as a reference to derived class.
Eigen::MatrixXd assemble_hessian_full_ad(const NonLinearAssemblerData &data) const
const Derived & derived() const
Returns this as a const reference to derived class.
Eigen::MatrixXd assemble_hessian_stress_noad(const NonLinearAssemblerData &data) const
virtual void add_multimaterial(const int index, const json &params, const Units &units, const io::ResourceIO &resources) override=0
virtual bool real_def_grad(const RowVectorNd &p, const double t, const int el_id) const
Eigen::VectorXd assemble_gradient_stress_noad(const NonLinearAssemblerData &data) const
Eigen::MatrixXd assemble_hessian_stress_ad(const NonLinearAssemblerData &data) const
Eigen::MatrixXd assemble_hessian(const NonLinearAssemblerData &data) const override
void compute_stress_grad_multiply_vect(const OptAssemblerData &data, const Eigen::MatrixXd &vect, Eigen::MatrixXd &stress, Eigen::MatrixXd &result) const override
Eigen::VectorXd assemble_gradient(const NonLinearAssemblerData &data) const override
bool allow_inversion() const override
Eigen::VectorXd assemble_gradient_stress_ad(const NonLinearAssemblerData &data) const
void compute_hessian_from_stress(const NonLinearAssemblerData &data, Eigen::MatrixXd &H) const
void compute_gradient_from_stress_noad(const NonLinearAssemblerData &data, Eigen::VectorXd &res) const
virtual Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > gradient(const RowVectorNd &p, const double t, const int el_id, const Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > &F) const
Eigen::VectorXd point_weights(const NonLinearAssemblerData &data) const
void compute_gradient_from_stress(const NonLinearAssemblerData &data, Eigen::VectorXd &res) const
double compute_energy(const NonLinearAssemblerData &data) const override
T compute_energy_aux(const NonLinearAssemblerData &data) const
void compute_stress_grad_multiply_mat(const OptAssemblerData &data, const Eigen::MatrixXd &mat, Eigen::MatrixXd &stress, Eigen::MatrixXd &result) const override
Read-only interface to a hierarchical collection of simulation resources.
Used for test only.
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > DefGradMatrix
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > AutoDiffGradMat
Eigen::Matrix< T, Eigen::Dynamic, 1 > AutoDiffVect
void compute_disp_grad_at_quad(const assembler::NonLinearAssemblerData &data, const AutoDiffVect &local_disp, const int p, const int size, AutoDiffGradMat &def_grad)
nlohmann::json json
Definition Common.hpp:9
void get_local_disp(const assembler::NonLinearAssemblerData &data, const int size, AutoDiffVect &local_disp)
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd
Definition Types.hpp:13
void log_and_throw_error(const std::string &msg)
Definition Logger.cpp:73
Automatic differentiation scalar with first-order derivatives.
Definition autodiff.h:112
Automatic differentiation scalar with first- and second-order derivatives.
Definition autodiff.h:493
static void setVariableCount(size_t value)
Set the independent variable count used by the automatic differentiation layer.
Definition autodiff.h:54