@@ -302,53 +302,85 @@ namespace polyfem::assembler
302302
303303 double NeoHookeanElasticity::compute_energy (const NonLinearAssemblerData &data) const
304304 {
305- return compute_energy_aux<double >(data);
305+ if (size () == 2 )
306+ {
307+ switch (data.vals .basis_values .size ())
308+ {
309+ case 3 :
310+ return compute_energy_aux<double , 3 , 2 >(data);
311+ case 6 :
312+ return compute_energy_aux<double , 6 , 2 >(data);
313+ case 10 :
314+ return compute_energy_aux<double , 10 , 2 >(data);
315+ default :
316+ return compute_energy_aux<double , Eigen::Dynamic, 2 >(data);
317+ }
318+ }
319+ else // if (size() == 3)
320+ {
321+ assert (size () == 3 );
322+ switch (data.vals .basis_values .size ())
323+ {
324+ case 4 :
325+ return compute_energy_aux<double , 4 , 3 >(data);
326+ case 10 :
327+ return compute_energy_aux<double , 10 , 3 >(data);
328+ case 20 :
329+ return compute_energy_aux<double , 20 , 3 >(data);
330+ default :
331+ return compute_energy_aux<double , Eigen::Dynamic, 3 >(data);
332+ }
333+ }
306334 }
307335
308336 // Compute ∫ ½μ (tr(FᵀF) - 3 - 2ln(J)) + ½λ ln²(J) du
309- template <typename T>
337+ template <typename T, int n_basis, int dim >
310338 T NeoHookeanElasticity::compute_energy_aux (const NonLinearAssemblerData &data) const
311339 {
312340 if constexpr (std::is_same_v<T, double >)
313341 {
314- Eigen::MatrixXd local_disp (data.vals .basis_values .size (), size ());
342+ Eigen::Matrix<T, n_basis, dim> local_disp (data.vals .basis_values .size (), size ());
315343 local_disp.setZero ();
316344 for (size_t i = 0 ; i < data.vals .basis_values .size (); ++i)
317345 {
318346 const auto &bs = data.vals .basis_values [i];
319347 for (size_t ii = 0 ; ii < bs.global .size (); ++ii)
320348 {
321- for (int d = 0 ; d < size () ; ++d)
349+ for (int d = 0 ; d < dim ; ++d)
322350 {
323351 local_disp (i, d) += bs.global [ii].val * data.x (bs.global [ii].index * size () + d);
324352 }
325353 }
326354 }
355+
327356 Eigen::VectorXd jacs;
328357 if (use_robust_jacobian)
329358 jacs = data.vals .eval_deformed_jacobian_determinant (data.x );
330- Eigen::MatrixXd def_grad (size (), size ());
359+
360+ Eigen::Matrix<T, dim, dim> def_grad (size (), size ());
331361
332362 T energy = T (0.0 );
333363
334364 const int n_pts = data.da .size ();
335365 for (long p = 0 ; p < n_pts; ++p)
336366 {
337- Eigen::MatrixXd grad (data.vals .basis_values .size (), size ());
367+ Eigen::Matrix<T, n_basis, dim> grad (data.vals .basis_values .size (), size ());
338368
339369 for (size_t i = 0 ; i < data.vals .basis_values .size (); ++i)
340370 {
341371 grad.row (i) = data.vals .basis_values [i].grad .row (p);
342372 }
343373
344- const Eigen::MatrixXd jac_it = data.vals .jac_it [p];
374+ const Eigen::Matrix<T, dim, dim> jac_it = data.vals .jac_it [p];
345375 // Id + grad d
346- def_grad = local_disp.transpose () * grad * jac_it + Eigen::MatrixXd::Identity (size (), size ());
376+ def_grad = (local_disp.transpose () * grad) * jac_it + Eigen::Matrix<T, dim, dim>::Identity (size (), size ());
377+
347378 double lambda, mu;
348379 params_.lambda_mu (data.vals .quadrature .points .row (p), data.vals .val .row (p), data.t , data.vals .element_id , lambda, mu);
380+
349381 const T J = use_robust_jacobian ? jacs (p) * jac_it.determinant () : def_grad.determinant ();
350382 const T log_det_j = log (J);
351- const T val = mu / 2 * (( def_grad.transpose () * def_grad). trace () - size () - 2 * log_det_j) +
383+ const T val = mu / 2 * (def_grad.squaredNorm () - size () - 2 * log_det_j) +
352384 lambda / 2 * log_det_j * log_det_j;
353385 energy += val * data.da (p);
354386 }
@@ -357,7 +389,7 @@ namespace polyfem::assembler
357389 else
358390 {
359391 typedef Eigen::Matrix<T, Eigen::Dynamic, 1 > AutoDiffVect;
360- typedef Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, 0 , 3 , 3 > AutoDiffGradMat;
392+ typedef Eigen::Matrix<T, dim, dim > AutoDiffGradMat;
361393
362394 AutoDiffVect local_disp;
363395 get_local_disp (data, size (), local_disp);
@@ -372,7 +404,7 @@ namespace polyfem::assembler
372404 compute_disp_grad_at_quad (data, local_disp, p, size (), def_grad);
373405
374406 // Id + grad d
375- for (int d = 0 ; d < size () ; ++d)
407+ for (int d = 0 ; d < dim ; ++d)
376408 def_grad (d, d) += T (1 );
377409
378410 double lambda, mu;
@@ -432,7 +464,7 @@ namespace polyfem::assembler
432464 const auto &bs = data.vals .basis_values [i];
433465 for (size_t ii = 0 ; ii < bs.global .size (); ++ii)
434466 {
435- for (int d = 0 ; d < size () ; ++d)
467+ for (int d = 0 ; d < dim ; ++d)
436468 {
437469 local_disp (i, d) += bs.global [ii].val * data.x (bs.global [ii].index * size () + d);
438470 }
@@ -458,9 +490,10 @@ namespace polyfem::assembler
458490 }
459491
460492 Eigen::Matrix<double , dim, dim> jac_it = data.vals .jac_it [p];
493+ Eigen::Matrix<double , n_basis, dim> delF_delU = grad * jac_it;
461494
462495 // Id + grad d
463- def_grad = local_disp.transpose () * grad * jac_it + Eigen::Matrix<double , dim, dim>::Identity (size (), size ());
496+ def_grad = local_disp.transpose () * delF_delU + Eigen::Matrix<double , dim, dim>::Identity (size (), size ());
464497
465498 const double J = use_robust_jacobian ? jacs (p) * jac_it.determinant () : def_grad.determinant ();
466499 const double log_det_j = log (J);
@@ -496,8 +529,6 @@ namespace polyfem::assembler
496529 double lambda, mu;
497530 params_.lambda_mu (data.vals .quadrature .points .row (p), data.vals .val .row (p), data.t , data.vals .element_id , lambda, mu);
498531
499- Eigen::Matrix<double , n_basis, dim> delF_delU = grad * jac_it;
500-
501532 Eigen::Matrix<double , dim, dim> gradient_temp = mu * def_grad - mu * (1 / J) * delJ_delF + lambda * log_det_j * (1 / J) * delJ_delF;
502533 Eigen::Matrix<double , n_basis, dim> gradient = delF_delU * gradient_temp.transpose ();
503534
@@ -528,10 +559,7 @@ namespace polyfem::assembler
528559 const auto &bs = data.vals .basis_values [i];
529560 for (size_t ii = 0 ; ii < bs.global .size (); ++ii)
530561 {
531- for (int d = 0 ; d < size (); ++d)
532- {
533- local_disp (i, d) += bs.global [ii].val * data.x (bs.global [ii].index * size () + d);
534- }
562+ local_disp.row (i) += bs.global [ii].val * data.x .block <dim, 1 >(bs.global [ii].index * size (), 0 ).transpose ();
535563 }
536564 }
537565
@@ -551,9 +579,10 @@ namespace polyfem::assembler
551579 }
552580
553581 Eigen::Matrix<double , dim, dim> jac_it = data.vals .jac_it [p];
582+ const Eigen::Matrix<double , n_basis, dim> delF_delU = grad * jac_it;
554583
555584 // Id + grad d
556- def_grad = local_disp.transpose () * grad * jac_it + Eigen::Matrix<double , dim, dim>::Identity (size (), size ());
585+ def_grad = local_disp.transpose () * delF_delU + Eigen::Matrix<double , dim, dim>::Identity (size (), size ());
557586
558587 const double J = use_robust_jacobian ? jacs (p) * jac_it.determinant () : def_grad.determinant ();
559588 double log_det_j = log (J);
@@ -606,16 +635,15 @@ namespace polyfem::assembler
606635
607636 Eigen::Matrix<double , dim * dim, dim * dim> hessian_temp = (mu * id) + (((mu + lambda * (1 - log_det_j)) / (J * J)) * (g_j * g_j.transpose ())) + (((lambda * log_det_j - mu) / (J)) * del2J_delF2);
608637
609- Eigen::Matrix<double , dim * dim, N> delF_delU_tensor (jac_it.size (), grad.size ());
638+ Eigen::Matrix<double , dim * dim, N> delF_delU_tensor = Eigen::Matrix< double , dim * dim, N>:: Zero (jac_it.size (), grad.size ());
610639
611640 for (size_t i = 0 ; i < local_disp.rows (); ++i)
612641 {
613642 for (size_t j = 0 ; j < local_disp.cols (); ++j)
614643 {
615644 Eigen::Matrix<double , dim, dim> temp (size (), size ());
616645 temp.setZero ();
617- temp.row (j) = grad.row (i);
618- temp = temp * jac_it;
646+ temp.row (j) = delF_delU.row (i);
619647 Eigen::Matrix<double , dim * dim, 1 > temp_flattened (Eigen::Map<Eigen::Matrix<double , dim * dim, 1 >>(temp.data (), temp.size ()));
620648 delF_delU_tensor.col (i * size () + j) = temp_flattened;
621649 }
0 commit comments