293 const auto ref_vol = target_elem->reference_elem()->volume();
296 const Real sqrt_2 = std::sqrt(
Real(2));
297 const Real sqrt_3 = std::sqrt(
Real(3));
298 std::vector<std::unique_ptr<Node>> owned_nodes;
303 if (type_str.compare(0, 3,
"TRI") == 0)
310 const auto side_length = std::sqrt(4. / sqrt_3 * ref_vol);
313 const auto & s = side_length;
332 owned_nodes.emplace_back(
Node::build(
Point(0.75 * s, 0.25 * sqrt_3 * s), 4));
333 owned_nodes.emplace_back(
Node::build(
Point(0.25 * s, 0.25 * sqrt_3 * s), 5));
338 const auto & on = owned_nodes;
339 owned_nodes.emplace_back(
Node::build(
Point((*on[0] + *on[1] + *on[2]) / 3.), 6));
346 libmesh_error_msg(
"Unsupported triangular element: " << type_str);
352 else if (type_str.compare(0, 5,
"PRISM") == 0)
370 const auto side_length = std::cbrt(16. * ref_vol / 3.);
372 const auto target_height = 0.25 * side_length * sqrt_3;
374 const auto & s = side_length;
375 const auto & h = target_height;
379 owned_nodes.emplace_back(
Node::build(
Point(0.5 * s, 0.5 * sqrt_3 * s, 0.), 2));
382 owned_nodes.emplace_back(
Node::build(
Point(0.5 * s, 0.5 * sqrt_3 * s, h), 5));
387 const auto & on = owned_nodes;
401 owned_nodes.emplace_back(
Node::build(
Point((*on[0] + *on[1] + *on[3] + *on[4]) / 4.), 15));
402 owned_nodes.emplace_back(
Node::build(
Point((*on[1] + *on[2] + *on[4] + *on[5]) / 4.), 16));
403 owned_nodes.emplace_back(
Node::build(
Point((*on[0] + *on[2] + *on[3] + *on[5]) / 4.), 17));
408 owned_nodes.emplace_back(
Node::build(
Point((*on[0] + *on[1] + *on[2]) / 3.), 18));
409 owned_nodes.emplace_back(
Node::build(
Point((*on[3] + *on[4] + *on[5]) / 3.), 19));
413 owned_nodes.emplace_back(
Node::build(
Point((*on[9] + *on[10] + *on[11]) / 3.), 20));
420 libmesh_error_msg(
"Unsupported prism element: " << type_str);
425 else if (type_str.compare(0, 7,
"PYRAMID") == 0)
439 const auto side_length = std::cbrt(3. * sqrt_2 * ref_vol);
441 const auto target_height = side_length / sqrt_2;
443 const auto & s = side_length;
444 const auto & h = target_height;
455 const auto & on = owned_nodes;
459 owned_nodes.emplace_back(
Node::build((*on[0] + *on[1]) / 2., 5));
460 owned_nodes.emplace_back(
Node::build((*on[1] + *on[2]) / 2., 6));
461 owned_nodes.emplace_back(
Node::build((*on[2] + *on[3]) / 2., 7));
462 owned_nodes.emplace_back(
Node::build((*on[3] + *on[0]) / 2., 8));
473 owned_nodes.emplace_back(
479 owned_nodes.emplace_back(
Node::build(
Point((*on[0] + *on[1] + *on[4]) / 3.), 14));
480 owned_nodes.emplace_back(
Node::build(
Point((*on[1] + *on[2] + *on[4]) / 3.), 15));
481 owned_nodes.emplace_back(
Node::build(
Point((*on[2] + *on[3] + *on[4]) / 3.), 16));
482 owned_nodes.emplace_back(
Node::build(
Point((*on[3] + *on[0] + *on[4]) / 3.), 17));
488 libmesh_error_msg(
"Unsupported pyramid element: " << type_str);
493 else if (type_str.compare(0, 3,
"TET") == 0)
510 const auto side_length = std::cbrt(6. * sqrt_2 * ref_vol);
512 const auto target_height = sqrt_2 / sqrt_3 * side_length;
514 const auto & s = side_length;
515 const auto & h = target_height;
521 owned_nodes.emplace_back(
Node::build(
Point(0.5 * s, 0.5 * sqrt_3 * s, 0.), 2));
522 owned_nodes.emplace_back(
Node::build(
Point(0.5 * s, sqrt_3 / 6. * s, h), 3));
526 const auto & on = owned_nodes;
541 owned_nodes.emplace_back(
Node::build(
Point((*on[0] + *on[1] + *on[2]) / 3.), 10));
542 owned_nodes.emplace_back(
Node::build(
Point((*on[0] + *on[1] + *on[3]) / 3.), 11));
543 owned_nodes.emplace_back(
Node::build(
Point((*on[1] + *on[2] + *on[3]) / 3.), 12));
544 owned_nodes.emplace_back(
Node::build(
Point((*on[0] + *on[2] + *on[3]) / 3.), 13));
548 else if (type !=
TET4)
549 libmesh_error_msg(
"Unsupported tet element: " << type_str);
555 for (
const auto & node : target_elem->reference_elem()->node_ref_range())
556 owned_nodes.emplace_back(
Node::build(node, node.id()));
559 for (
const auto & node_ptr : owned_nodes)
560 target_elem->set_node(node_ptr->id(), node_ptr.get());
564 return std::make_pair(std::move(target_elem), std::move(owned_nodes));