935 Eigen::DenseBase<TDerivedE>
const& E,
937 Eigen::DenseBase<TDerivedeg>
const& eg,
938 Eigen::DenseBase<TDerivedwg>
const& wg,
939 Eigen::MatrixBase<TDerivedGNeg>
const& GNeg,
940 Eigen::DenseBase<TDerivedmug>
const& mug,
941 Eigen::DenseBase<TDerivedlambdag>
const& lambdag,
942 Eigen::MatrixBase<TDerivedx>
const& x,
943 Eigen::PlainObjectBase<TDerivedUg>& Ug,
944 Eigen::PlainObjectBase<TDerivedGg>& Gg,
945 Eigen::PlainObjectBase<TDerivedHg>& Hg,
949 PBAT_PROFILE_NAMED_SCOPE(
"pbat.fem.ToElementElasticity");
951 using ScalarType =
typename TDerivedx::Scalar;
954 if (x.size() != nNodes * Dims)
956 std::string
const what = fmt::format(
957 "Generalized coordinate vector must have dimensions |#nodes|*kDims={}, but got "
961 throw std::invalid_argument(what);
963 if (GNeg.rows() != TElement::kNodes or GNeg.cols() != wg.size() * Dims)
965 std::string
const what = fmt::format(
966 "Shape function gradient matrix must have dimensions |#nodes per element| x "
967 "|kDims*#quad pts|={}x{}, but got {}x{}",
972 throw std::invalid_argument(what);
974 if (eg.size() != wg.size() or mug.size() != wg.size() or lambdag.size() != wg.size())
976 std::string
const what = fmt::format(
977 "Element index, quadrature weight, and Lame coefficient vectors must have the same "
978 "size of |#quad pts|={}, but got eg.size()={}, mug.size()={}, lambdag.size()={}",
983 throw std::invalid_argument(what);
986 auto const nQuadPts = wg.size();
987 using SizeType = std::remove_cvref_t<
decltype(nQuadPts)>;
988 auto constexpr kNodesPerElement = TElement::kNodes;
989 auto constexpr kDofsPerElement = kNodesPerElement * Dims;
991 using mini::FromEigen;
994 if (eFlags & EElementElasticityComputationFlags::Potential)
999 if (eFlags & EElementElasticityComputationFlags::Gradient)
1001 Gg.resize(kDofsPerElement, nQuadPts);
1004 if (eFlags & EElementElasticityComputationFlags::Hessian)
1006 Hg.resize(kDofsPerElement, kDofsPerElement * nQuadPts);
1010 THyperElasticEnergy Psi{};
1011 if (eFlags == EElementElasticityComputationFlags::Potential)
1013 tbb::parallel_for(SizeType{0}, nQuadPts, [&](
auto g) {
1014 auto const e = eg(g);
1015 auto const nodes = E.col(e);
1016 auto const xe = x.reshaped(Dims, nNodes)(Eigen::placeholders::all, nodes);
1017 auto const GPeg = GNeg.template block<kNodesPerElement, Dims>(0, g * Dims);
1018 Eigen::Matrix<ScalarType, Dims, Dims>
const F = xe * GPeg;
1019 auto vecF = FromEigen(F);
1020 auto psiF = Psi.eval(vecF, mug(g), lambdag(g));
1021 Ug(g) += wg(g) * psiF;
1025 eFlags == (EElementElasticityComputationFlags::Potential |
1026 EElementElasticityComputationFlags::Gradient))
1028 tbb::parallel_for(SizeType{0}, nQuadPts, [&](
auto g) {
1029 auto const e = eg(g);
1030 auto const nodes = E.col(e);
1031 auto const xe = x.reshaped(Dims, nNodes)(Eigen::placeholders::all, nodes);
1032 auto const GPeg = GNeg.template block<kNodesPerElement, Dims>(0, g * Dims);
1033 Eigen::Matrix<ScalarType, Dims, Dims>
const F = xe * GPeg;
1034 auto vecF = FromEigen(F);
1035 mini::SVector<ScalarType, Dims * Dims> gradPsiF;
1036 auto const psiF = Psi.evalWithGrad(vecF, mug(g), lambdag(g), gradPsiF);
1037 auto const GP = FromEigen(GPeg);
1039 Ug(g) += wg(g) * psiF;
1040 Gg.col(g) += wg(g) * ToEigen(GPsix);
1044 eFlags == (EElementElasticityComputationFlags::Potential |
1045 EElementElasticityComputationFlags::Hessian))
1047 tbb::parallel_for(SizeType{0}, nQuadPts, [&](
auto g) {
1048 auto const e = eg(g);
1049 auto const nodes = E.col(e);
1050 auto const xe = x.reshaped(Dims, nNodes)(Eigen::placeholders::all, nodes);
1051 auto const gradPhi = GNeg.template block<kNodesPerElement, Dims>(0, g * Dims);
1052 Eigen::Matrix<ScalarType, Dims, Dims>
const F = xe * gradPhi;
1053 auto vecF = FromEigen(F);
1054 auto psiF = Psi.eval(vecF, mug(g), lambdag(g));
1055 auto const hessPsiF = Psi.hessian(vecF, mug(g), lambdag(g));
1056 Eigen::Matrix<ScalarType, Dims * Dims, Dims * Dims> hessPsiFCorrected;
1061 auto const GP = FromEigen(gradPhi);
1063 auto heg = Hg.template block<kDofsPerElement, kDofsPerElement>(0, g * kDofsPerElement);
1064 Ug(g) += wg(g) * psiF;
1065 heg += wg(g) * ToEigen(HPsix);
1069 eFlags == (EElementElasticityComputationFlags::Potential |
1070 EElementElasticityComputationFlags::Gradient |
1071 EElementElasticityComputationFlags::Hessian))
1073 tbb::parallel_for(SizeType{0}, nQuadPts, [&](
auto g) {
1074 auto const e = eg(g);
1075 auto const nodes = E.col(e);
1076 Eigen::Matrix<ScalarType, Dims, kNodesPerElement>
const xe =
1077 x.reshaped(Dims, nNodes)(Eigen::placeholders::all, nodes);
1078 auto const GPeg = GNeg.template block<kNodesPerElement, Dims>(0, g * Dims);
1079 Eigen::Matrix<ScalarType, Dims, Dims>
const F = xe * GPeg;
1080 auto vecF = FromEigen(F);
1081 mini::SVector<ScalarType, Dims * Dims> gradPsiF;
1082 mini::SMatrix<ScalarType, Dims * Dims, Dims * Dims> hessPsiF;
1083 auto psiF = Psi.evalWithGradAndHessian(vecF, mug(g), lambdag(g), gradPsiF, hessPsiF);
1084 Eigen::Matrix<ScalarType, Dims * Dims, Dims * Dims> hessPsiFCorrected;
1089 auto const GP = FromEigen(GPeg);
1092 auto heg = Hg.template block<kDofsPerElement, kDofsPerElement>(0, g * kDofsPerElement);
1093 Ug(g) += wg(g) * psiF;
1094 Gg.col(g) += wg(g) * ToEigen(GPsix);
1095 heg += wg(g) * ToEigen(HPsix);
1098 else if (eFlags == EElementElasticityComputationFlags::Gradient)
1100 tbb::parallel_for(SizeType{0}, nQuadPts, [&](
auto g) {
1101 auto const e = eg(g);
1102 auto const nodes = E.col(e);
1103 auto const xe = x.reshaped(Dims, nNodes)(Eigen::placeholders::all, nodes);
1104 auto const GPeg = GNeg.template block<kNodesPerElement, Dims>(0, g * Dims);
1105 Eigen::Matrix<ScalarType, Dims, Dims>
const F = xe * GPeg;
1106 auto vecF = FromEigen(F);
1107 auto const gradPsiF = Psi.grad(vecF, mug(g), lambdag(g));
1108 auto const GP = FromEigen(GPeg);
1110 Gg.col(g) += wg(g) * ToEigen(GPsix);
1114 eFlags == (EElementElasticityComputationFlags::Gradient |
1115 EElementElasticityComputationFlags::Hessian))
1117 tbb::parallel_for(SizeType{0}, nQuadPts, [&](
auto g) {
1118 auto const e = eg(g);
1119 auto const nodes = E.col(e);
1120 auto const xe = x.reshaped(Dims, nNodes)(Eigen::placeholders::all, nodes);
1121 auto const GPeg = GNeg.template block<kNodesPerElement, Dims>(0, g * Dims);
1122 Eigen::Matrix<ScalarType, Dims, Dims>
const F = xe * GPeg;
1123 auto vecF = FromEigen(F);
1124 mini::SVector<ScalarType, Dims * Dims> gradPsiF;
1125 mini::SMatrix<ScalarType, Dims * Dims, Dims * Dims> hessPsiF;
1126 Psi.evalWithGradAndHessian(vecF, mug(g), lambdag(g), gradPsiF, hessPsiF);
1127 Eigen::Matrix<ScalarType, Dims * Dims, Dims * Dims> hessPsiFCorrected;
1132 auto const GP = FromEigen(GPeg);
1135 auto heg = Hg.template block<kDofsPerElement, kDofsPerElement>(0, g * kDofsPerElement);
1136 Gg.col(g) += wg(g) * ToEigen(GPsix);
1137 heg += wg(g) * ToEigen(HPsix);
1142 tbb::parallel_for(SizeType{0}, nQuadPts, [&](
auto g) {
1143 auto const e = eg(g);
1144 auto const nodes = E.col(e);
1145 Eigen::Matrix<ScalarType, Dims, kNodesPerElement>
const xe =
1146 x.reshaped(Dims, nNodes)(Eigen::placeholders::all, nodes);
1147 Eigen::Matrix<ScalarType, kNodesPerElement, Dims>
const GPeg =
1148 GNeg.template block<kNodesPerElement, Dims>(0, g * Dims);
1149 Eigen::Matrix<ScalarType, Dims, Dims>
const F = xe * GPeg;
1150 auto vecF = FromEigen(F);
1151 auto hessPsiF = Psi.hessian(vecF, mug(g), lambdag(g));
1152 Eigen::Matrix<ScalarType, Dims * Dims, Dims * Dims> hessPsiFCorrected;
1157 auto const GP = FromEigen(GPeg);
1158 mini::SMatrix<ScalarType, kDofsPerElement, kDofsPerElement> HPsix =
1160 auto heg = Hg.template block<kDofsPerElement, kDofsPerElement>(0, g * kDofsPerElement);
1161 heg += wg(g) * ToEigen(HPsix);