13 #include "libmesh/enum_to_string.h" 14 #include "libmesh/fe_interface.h" 15 #include "metaphysicl/dualnumberarray.h" 16 #include "Eigen/Dense" 18 using MetaPhysicL::NumberArray;
20 typedef DualNumber<Real, NumberArray<2, Real>>
Dual2;
26 std::vector<unsigned int>
29 if (sub_elem >= parent_elem.n_sub_elem())
30 mooseError(
"Invalid 3D mortar sub-element index ",
32 " for parent element ",
35 libMesh::Utility::enum_to_string<ElemType>(parent_elem.type()),
37 parent_elem.n_sub_elem(),
40 switch (parent_elem.type())
59 mooseError(
"Invalid 3D mortar triangular sub-element index ", sub_elem,
".");
75 mooseError(
"Invalid 3D mortar QUAD8 sub-element index ", sub_elem,
".");
89 mooseError(
"Invalid 3D mortar QUAD9 sub-element index ", sub_elem,
".");
94 " has unsupported type ",
95 libMesh::Utility::enum_to_string<ElemType>(parent_elem.type()),
96 " for 3D mortar sub-element topology.");
103 const QBase & qrule_msm,
104 std::vector<Point> & secondary_q_pts,
105 std::vector<Point> & primary_q_pts)
107 mooseAssert(mortar_segment_elem.type() ==
TRI3,
108 "Reference interpolation expects triangular mortar segments.");
111 for (
const auto qp :
make_range(qrule_msm.n_points()))
119 FEInterface::shape(fe_type, &mortar_segment_elem, n, qrule_msm.qp(qp),
false);
124 secondary_q_pts.push_back(secondary_qp);
125 primary_q_pts.push_back(primary_qp);
131 const Elem *
const primal_elem,
132 const unsigned int sub_elem_index,
133 const QBase & qrule_msm,
134 std::vector<Point> & q_pts)
136 const auto msm_elem_order = msm_elem->default_order();
137 const auto msm_elem_type = msm_elem->type();
140 const Point e1 = msm_elem->point(0) - msm_elem->point(1);
141 const Point e2 = msm_elem->point(2) - msm_elem->point(1);
142 const Point normal = e2.cross(e1).unit();
145 const auto sub_elem = msm_elem->get_extra_integer(sub_elem_index);
146 const ElemType primal_type = primal_elem->type();
150 auto transform_qp = [primal_type, sub_elem](
const Real nu,
const Real xi)
155 return Point(nu, xi, 0);
157 return Point(nu, xi, 0);
163 return Point(0.5 * nu, 0.5 * xi, 0);
165 return Point(0.5 * (1 - xi), 0.5 * (nu + xi), 0);
167 return Point(0.5 * (1 + nu), 0.5 * xi, 0);
169 return Point(0.5 * nu, 0.5 * (1 + xi), 0);
171 mooseError(
"get_sub_elem_indices: Invalid sub_elem: ", sub_elem);
177 return Point(nu - 1, xi - 1, 0);
179 return Point(nu + xi, xi - 1, 0);
181 return Point(1 - xi, nu + xi, 0);
183 return Point(nu - 1, nu + xi, 0);
185 return Point(0.5 * (nu - xi), 0.5 * (nu + xi), 0);
187 mooseError(
"get_sub_elem_indices: Invalid sub_elem: ", sub_elem);
193 return Point(0.5 * (nu - 1), 0.5 * (xi - 1), 0);
195 return Point(0.5 * (nu + 1), 0.5 * (xi - 1), 0);
197 return Point(0.5 * (nu + 1), 0.5 * (xi + 1), 0);
199 return Point(0.5 * (nu - 1), 0.5 * (xi + 1), 0);
201 mooseError(
"get_sub_elem_indices: Invalid sub_elem: ", sub_elem);
204 mooseError(
"transform_qp: Face element type: ",
205 libMesh::Utility::enum_to_string<ElemType>(primal_type),
206 " invalid for 3D mortar");
210 auto sub_element_type = [primal_type, sub_elem]()
232 mooseError(
"sub_element_type: Invalid sub_elem: ", sub_elem);
235 mooseError(
"sub_element_type: Face element type: ",
236 libMesh::Utility::enum_to_string<ElemType>(primal_type),
237 " invalid for 3D mortar");
245 for (
auto qp :
make_range(qrule_msm.n_points()))
249 for (
auto n :
make_range(msm_elem->n_nodes()))
259 xi1.value() = qrule_msm.qp(qp)(0);
260 xi1.derivatives()[0] = 1.0;
262 xi2.value() = qrule_msm.qp(qp)(1);
263 xi2.derivatives()[1] = 1.0;
264 VectorValue<Dual2> xi(xi1, xi2, 0);
265 unsigned int current_iterate = 0, max_iterates = 10;
271 VectorValue<Dual2> x1;
272 for (
auto n :
make_range(sub_elem_node_indices.size()))
274 primal_elem->point(sub_elem_node_indices[n]);
277 VectorValue<Dual2> F(u(1) * normal(2) - u(2) * normal(1),
278 u(2) * normal(0) - u(0) * normal(2),
279 u(0) * normal(1) - u(1) * normal(0));
281 Real projection_tolerance(1e-10);
287 if (!u.is_zero() && u.norm().value() > 1.0)
288 projection_tolerance *= u.norm().value();
294 J << F(0).derivatives()[0], F(0).derivatives()[1], F(1).derivatives()[0],
295 F(1).derivatives()[1], F(2).derivatives()[0], F(2).derivatives()[1];
297 f << F(0).value(), F(1).value(), F(2).value();
302 }
while (++current_iterate < max_iterates);
304 if (current_iterate < max_iterates)
307 q_pts.push_back(transform_qp(xi(0).
value(), xi(1).
value()));
313 auto & qp_back = q_pts.back();
314 if (primal_elem->type() ==
TRI3 || primal_elem->type() ==
TRI6 || primal_elem->type() ==
TRI7)
316 if (qp_back(0) < -TOLERANCE || qp_back(1) < -TOLERANCE ||
317 qp_back(0) + qp_back(1) > (1 + TOLERANCE))
318 mooseException(
"Quadrature point: ", qp_back,
" out of bounds, truncating.");
320 else if (primal_elem->type() ==
QUAD4 || primal_elem->type() ==
QUAD8 ||
321 primal_elem->type() ==
QUAD9)
323 if (qp_back(0) < (-1 - TOLERANCE) || qp_back(0) > (1 + TOLERANCE) ||
324 qp_back(1) < (-1 - TOLERANCE) || qp_back(1) > (1 + TOLERANCE))
325 mooseException(
"Quadrature point: ", qp_back,
" out of bounds, truncating");
330 mooseError(
"Newton iteration for mortar quadrature mapping msm element: ",
334 " didn't converge. MSM element volume: ",
T fe_lagrange_2D_shape(const libMesh::ElemType type, const Order order, const unsigned int i, const VectorType< T > &p)
DualNumber< Real, NumberArray< 2, Real > > Dual2
std::vector< unsigned int > getMortarSubElementNodeIndices(const Elem &parent_elem, unsigned int sub_elem)
Return the node indices for a first-order sub-element of a parent face.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
void mapQPoints3dFromReference(const Elem &mortar_segment_elem, const MortarSegmentReferencePoints &reference_points, const QBase &qrule_msm, std::vector< Point > &secondary_q_pts, std::vector< Point > &primary_q_pts)
3D mapping operator that interpolates stored parent reference points on each triangular mortar segmen...
std::array< Point, 3 > secondary_reference_points
std::array< Point, 3 > primary_reference_points
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
Eigen::Matrix< Real, Eigen::Dynamic, Eigen::Dynamic > RealEigenMatrix
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Parent-face reference coordinates associated with the vertices of one triangular mortar segment...
IntRange< T > make_range(T beg, T end)
Eigen::Matrix< Real, Eigen::Dynamic, 1 > RealEigenVector
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
auto index_range(const T &sizable)
void projectQPoints3d(const Elem *msm_elem, const Elem *primal_elem, unsigned int sub_elem_index, const QBase &qrule_msm, std::vector< Point > &q_pts)
3D projection operator for mapping qpoints on mortar segments to secondary or primary elements ...