OGS
anonymous_namespace{MeshRevision.cpp} Namespace Reference

Functions

template<typename ElementType >
std::unique_ptr< MeshLib::ElementcreateElement (std::span< MeshLib::Node *const > const element_nodes, std::vector< MeshLib::Node * > const &nodes, std::array< std::size_t, ElementType::n_all_nodes > const local_ids)
 
unsigned subdivideQuad (MeshLib::Element const *const quad, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &new_elements)
 Subdivides a nonplanar quad into two triangles.
 
unsigned subdividePrism (MeshLib::Element const *const prism, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &new_elements)
 Subdivides a prism with nonplanar quad faces into two tets.
 
unsigned subdivideHex (MeshLib::Element const *const hex, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &new_elements)
 Subdivides a Hex with nonplanar faces into tets.
 
unsigned subdividePyramid (MeshLib::Element const *const pyramid, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &new_elements)
 Subdivides a pyramid with a nonplanar base into two tets.
 
MeshLib::ElementconstructLine (MeshLib::Element const *const element, const std::vector< MeshLib::Node * > &nodes)
 
MeshLib::ElementconstructTri (MeshLib::Element const *const element, const std::vector< MeshLib::Node * > &nodes)
 
MeshLib::ElementconstructFourNodeElement (MeshLib::Element const *const element, std::vector< MeshLib::Node * > const &nodes, unsigned const min_elem_dim=1)
 
void reducePyramid (MeshLib::Element const *const org_elem, unsigned const n_unique_nodes, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &new_elements, unsigned const min_elem_dim)
 
unsigned reducePrism (MeshLib::Element const *const org_elem, unsigned const n_unique_nodes, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &new_elements, unsigned const min_elem_dim)
 
std::array< unsigned, 4 > lutHexCuttingQuadNodes (unsigned id1, unsigned id2)
 
unsigned lutHexDiametralNode (unsigned const id)
 
std::pair< unsigned, unsigned > lutHexBackNodes (unsigned const i, unsigned const j, unsigned const k, unsigned const l)
 
unsigned findPyramidTopNode (MeshLib::Element const &element, std::array< std::size_t, 4 > const &base_node_ids)
 
unsigned reduceHex (MeshLib::Element const *const org_elem, unsigned const n_unique_nodes, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &new_elements, unsigned const min_elem_dim)
 
std::size_t subdivideElement (MeshLib::Element const *const element, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &elements)
 
std::size_t reduceElement (MeshLib::Element const *const element, unsigned const n_unique_nodes, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &elements, unsigned const min_elem_dim)
 
unsigned getNumberOfUniqueNodes (MeshLib::Element const *const element)
 
template<typename T >
void fillNodeProperty (std::vector< T > &new_prop, std::vector< T > const &old_prop, std::vector< size_t > const &node_ids)
 
template<typename T >
void fillElemProperty (std::vector< T > &new_prop, std::vector< T > const &old_prop, std::vector< size_t > const &elem_ids)
 
MeshLib::Properties copyProperties (MeshLib::Properties const &props, std::vector< std::size_t > const &node_ids, std::vector< std::size_t > const &elem_ids)
 

Function Documentation

◆ constructFourNodeElement()

MeshLib::Element * anonymous_namespace{MeshRevision.cpp}::constructFourNodeElement ( MeshLib::Element const *const element,
std::vector< MeshLib::Node * > const & nodes,
unsigned const min_elem_dim = 1 )

Creates a quad or a tet, depending if the four nodes being coplanar or not (element should have exactly four unique nodes!)

Definition at line 215 of file MeshRevision.cpp.

219{
220 std::array<MeshLib::Node*, 4> new_nodes;
221 unsigned count(0);
222 new_nodes[count++] = nodes[element->getNode(0)->getID()];
223 for (unsigned i = 1; i < element->getNumberOfBaseNodes(); ++i)
224 {
225 if (count > 3)
226 {
227 break;
228 }
229 bool unique_node(true);
230 for (unsigned j = 0; j < i; ++j)
231 {
232 if (element->getNode(i)->getID() == element->getNode(j)->getID())
233 {
234 unique_node = false;
235 break;
236 }
237 }
238 if (unique_node)
239 {
240 new_nodes[count++] = nodes[element->getNode(i)->getID()];
241 };
242 }
243
244 // test if quad or tet
245 const bool isQuad(MathLib::isCoplanar(*new_nodes[0], *new_nodes[1],
246 *new_nodes[2], *new_nodes[3]));
247 if (isQuad && min_elem_dim < 3)
248 {
249 MeshLib::Element* elem(new MeshLib::Quad(new_nodes));
250 for (unsigned i = 1; i < 3; ++i)
251 {
252 if (elem->validate().none())
253 {
254 return elem;
255 }
256
257 // change node order if not convex
258 MeshLib::Node* tmp = new_nodes[i + 1];
259 new_nodes[i + 1] = new_nodes[i];
260 new_nodes[i] = tmp;
261 }
262 return elem;
263 }
264 if (!isQuad)
265 {
266 return new MeshLib::Tet(new_nodes);
267 }
268 // is quad but min elem dim == 3
269
270 return nullptr;
271}
bool isCoplanar(const MathLib::Point3d &a, const MathLib::Point3d &b, const MathLib::Point3d &c, const MathLib::Point3d &d)
Checks if the four given points are located on a plane.
TemplateElement< MeshLib::TetRule4 > Tet
Definition Tet.h:25

References MathLib::Point3dWithID::getID(), MeshLib::Element::getNode(), MeshLib::Element::getNumberOfBaseNodes(), MathLib::isCoplanar(), and MeshLib::Element::validate().

Referenced by reduceHex(), reducePrism(), and reducePyramid().

◆ constructLine()

MeshLib::Element * anonymous_namespace{MeshRevision.cpp}::constructLine ( MeshLib::Element const *const element,
const std::vector< MeshLib::Node * > & nodes )

Creates a line element from the first two unique nodes found in the element (element should have exactly two unique nodes!)

Definition at line 161 of file MeshRevision.cpp.

163{
164 std::array<std::size_t, 2> line_node_ids = {0, 0};
165 for (unsigned i = 1; i < element->getNumberOfBaseNodes(); ++i)
166 {
167 if (element->getNode(i)->getID() != element->getNode(0)->getID())
168 {
169 line_node_ids[1] = i;
170 break;
171 }
172 }
173 assert(line_node_ids[1] != 0);
174 return createElement<MeshLib::Line>(element->nodes(), nodes, line_node_ids)
175 .release();
176}

References MathLib::Point3dWithID::getID(), MeshLib::Element::getNode(), MeshLib::Element::getNumberOfBaseNodes(), and MeshLib::Element::nodes().

Referenced by reduceElement(), reduceHex(), reducePrism(), and reducePyramid().

◆ constructTri()

MeshLib::Element * anonymous_namespace{MeshRevision.cpp}::constructTri ( MeshLib::Element const *const element,
const std::vector< MeshLib::Node * > & nodes )

Creates a triangle element from the first three unique nodes found in the element (element should have exactly three unique nodes!)

Definition at line 180 of file MeshRevision.cpp.

182{
183 // TODO?
184 // In theory three unique nodes could also be reduced to two lines e.g. with
185 // a quad where two diametral nodes collapse. This case is currently not
186 // implemented!
187 std::array<MeshLib::Node*, 3> tri_nodes;
188 tri_nodes[0] = nodes[element->getNode(0)->getID()];
189 tri_nodes[2] = nullptr;
190 for (unsigned i = 1; i < element->getNumberOfBaseNodes(); ++i)
191 {
192 if (element->getNode(i)->getID() != tri_nodes[0]->getID())
193 {
194 tri_nodes[1] = nodes[element->getNode(i)->getID()];
195 for (unsigned j = i + 1; j < element->getNumberOfBaseNodes(); ++j)
196 {
197 if (element->getNode(j)->getID() != tri_nodes[1]->getID())
198 {
199 tri_nodes[2] = nodes[element->getNode(j)->getID()];
200 break;
201 }
202 }
203 if (tri_nodes[2])
204 {
205 break;
206 }
207 }
208 }
209 assert(tri_nodes[2] != nullptr);
210 return new MeshLib::Tri(tri_nodes);
211}
TemplateElement< MeshLib::TriRule3 > Tri
Definition Tri.h:26

References MathLib::Point3dWithID::getID(), MeshLib::Element::getNode(), and MeshLib::Element::getNumberOfBaseNodes().

Referenced by reduceElement(), reduceHex(), reducePrism(), and reducePyramid().

◆ copyProperties()

MeshLib::Properties anonymous_namespace{MeshRevision.cpp}::copyProperties ( MeshLib::Properties const & props,
std::vector< std::size_t > const & node_ids,
std::vector< std::size_t > const & elem_ids )

Copies all scalar arrays according to the restructured Node- and Element-vectors after the mesh revision process (i.e. collapsed nodes, split elements, etc.)

Definition at line 928 of file MeshRevision.cpp.

931{
932 auto const prop_names = props.getPropertyVectorNames();
933 MeshLib::Properties new_properties;
934
935 for (auto name : prop_names)
936 {
937 if (props.existsPropertyVector<int>(name, MeshLib::MeshItemType::Node,
938 1))
939 {
940 auto const* p = props.getPropertyVector<int>(
942 auto new_node_vec = new_properties.createNewPropertyVector<int>(
944 fillNodeProperty(*new_node_vec, *p, node_ids);
945 continue;
946 }
947 if (props.existsPropertyVector<float>(name, MeshLib::MeshItemType::Node,
948 1))
949 {
950 auto const* p = props.getPropertyVector<float>(
952 auto new_node_vec = new_properties.createNewPropertyVector<float>(
954 fillNodeProperty(*new_node_vec, *p, node_ids);
955 continue;
956 }
957 if (props.existsPropertyVector<double>(name,
959 {
960 auto const* p = props.getPropertyVector<double>(
962 auto new_node_vec = new_properties.createNewPropertyVector<double>(
964 fillNodeProperty(*new_node_vec, *p, node_ids);
965 continue;
966 }
967 if (props.existsPropertyVector<int>(name, MeshLib::MeshItemType::Cell,
968 1))
969 {
970 auto const* p = props.getPropertyVector<int>(
972 auto new_cell_vec = new_properties.createNewPropertyVector<int>(
974 fillElemProperty(*new_cell_vec, *p, elem_ids);
975 continue;
976 }
977 if (props.existsPropertyVector<float>(name, MeshLib::MeshItemType::Cell,
978 1))
979 {
980 auto const* p = props.getPropertyVector<float>(
982 auto new_cell_vec = new_properties.createNewPropertyVector<float>(
984 fillElemProperty(*new_cell_vec, *p, elem_ids);
985 continue;
986 }
987 if (props.existsPropertyVector<double>(name,
989 {
990 auto const* p = props.getPropertyVector<double>(
992 auto new_cell_vec = new_properties.createNewPropertyVector<double>(
994 fillElemProperty(*new_cell_vec, *p, elem_ids);
995 continue;
996 }
997 WARN("PropertyVector {:s} not being converted.", name);
998 }
999 return new_properties;
1000}
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
Property manager on mesh items. Class Properties manages scalar, vector or matrix properties....
Definition Properties.h:36
PropertyVector< T > * createNewPropertyVector(std::string_view name, MeshItemType mesh_item_type, std::size_t n_components=1)
void fillElemProperty(std::vector< T > &new_prop, std::vector< T > const &old_prop, std::vector< size_t > const &elem_ids)
void fillNodeProperty(std::vector< T > &new_prop, std::vector< T > const &old_prop, std::vector< size_t > const &node_ids)

References MeshLib::Cell, MeshLib::Properties::createNewPropertyVector(), MeshLib::Properties::existsPropertyVector(), fillElemProperty(), fillNodeProperty(), MeshLib::Properties::getPropertyVector(), MeshLib::Properties::getPropertyVectorNames(), MeshLib::Node, and WARN().

◆ createElement()

template<typename ElementType >
std::unique_ptr< MeshLib::Element > anonymous_namespace{MeshRevision.cpp}::createElement ( std::span< MeshLib::Node *const > const element_nodes,
std::vector< MeshLib::Node * > const & nodes,
std::array< std::size_t, ElementType::n_all_nodes > const local_ids )

Definition at line 68 of file MeshRevision.cpp.

72{
73 using namespace MeshLib::views;
74 auto lookup_in = [](auto const& values)
75 {
76 return ranges::views::transform([&values](std::size_t const n)
77 { return values[n]; });
78 };
79
80 std::array<MeshLib::Node*, ElementType::n_all_nodes> new_nodes;
81 ranges::copy(local_ids | lookup_in(element_nodes) | ids | lookup_in(nodes),
82 begin(new_nodes));
83
84 return std::make_unique<ElementType>(new_nodes);
85}
MeshLib specific, lazy, non-owning, non-mutating, composable range views.
Definition Mesh.h:223

◆ fillElemProperty()

template<typename T >
void anonymous_namespace{MeshRevision.cpp}::fillElemProperty ( std::vector< T > & new_prop,
std::vector< T > const & old_prop,
std::vector< size_t > const & elem_ids )

Definition at line 916 of file MeshRevision.cpp.

919{
920 std::transform(elem_ids.cbegin(), elem_ids.cend(),
921 std::back_inserter(new_prop),
922 [&](std::size_t const i) { return old_prop[i]; });
923}

Referenced by copyProperties().

◆ fillNodeProperty()

template<typename T >
void anonymous_namespace{MeshRevision.cpp}::fillNodeProperty ( std::vector< T > & new_prop,
std::vector< T > const & old_prop,
std::vector< size_t > const & node_ids )

Definition at line 900 of file MeshRevision.cpp.

903{
904 std::size_t const n_nodes = node_ids.size();
905 for (std::size_t i = 0; i < n_nodes; ++i)
906 {
907 if (node_ids[i] != i)
908 {
909 continue;
910 }
911 new_prop.push_back(old_prop[i]);
912 }
913}

Referenced by copyProperties().

◆ findPyramidTopNode()

unsigned anonymous_namespace{MeshRevision.cpp}::findPyramidTopNode ( MeshLib::Element const & element,
std::array< std::size_t, 4 > const & base_node_ids )

Definition at line 556 of file MeshRevision.cpp.

558{
559 const std::size_t nNodes(element.getNumberOfBaseNodes());
560 for (std::size_t i = 0; i < nNodes; ++i)
561 {
562 bool top_node = true;
563 for (unsigned j = 0; j < 4; ++j)
564 {
565 if (element.getNode(i)->getID() == base_node_ids[j])
566 {
567 top_node = false;
568 }
569 }
570 if (top_node)
571 {
572 return i;
573 }
574 }
575 return std::numeric_limits<unsigned>::max(); // should never be reached if
576 // called correctly
577}

References MathLib::Point3dWithID::getID(), MeshLib::Element::getNode(), and MeshLib::Element::getNumberOfBaseNodes().

Referenced by reduceHex().

◆ getNumberOfUniqueNodes()

unsigned anonymous_namespace{MeshRevision.cpp}::getNumberOfUniqueNodes ( MeshLib::Element const *const element)

Calculates the number of unique nodes in an element (i.e. uncollapsed nodes).

Definition at line 880 of file MeshRevision.cpp.

881{
882 unsigned const nNodes(element->getNumberOfBaseNodes());
883 unsigned count(nNodes);
884
885 for (unsigned i = 0; i < nNodes - 1; ++i)
886 {
887 for (unsigned j = i + 1; j < nNodes; ++j)
888 {
889 if (element->getNode(i)->getID() == element->getNode(j)->getID())
890 {
891 count--;
892 break;
893 }
894 }
895 }
896 return count;
897}

References MathLib::Point3dWithID::getID(), MeshLib::Element::getNode(), and MeshLib::Element::getNumberOfBaseNodes().

◆ lutHexBackNodes()

std::pair< unsigned, unsigned > anonymous_namespace{MeshRevision.cpp}::lutHexBackNodes ( unsigned const i,
unsigned const j,
unsigned const k,
unsigned const l )

When a hex is subdivided into two prisms, this returns the nodes of the hex edge that will serve as the back of one of the prisms.

Definition at line 509 of file MeshRevision.cpp.

513{
514 // collapsed edges are *not* connected
515 if (lutHexDiametralNode(i) == k)
516 {
517 return {i, lutHexDiametralNode(l)};
518 }
519 if (lutHexDiametralNode(i) == l)
520 {
521 return {i, lutHexDiametralNode(k)};
522 }
523 if (lutHexDiametralNode(j) == k)
524 {
525 return {j, lutHexDiametralNode(l)};
526 }
527 if (lutHexDiametralNode(j) == l)
528 {
529 return {j, lutHexDiametralNode(k)};
530 }
531
532 // collapsed edges *are* connected
533 if (i == k)
534 {
535 return {lutHexDiametralNode(l), j};
536 }
537 if (i == l)
538 {
539 return {lutHexDiametralNode(k), j};
540 }
541 if (j == k)
542 {
543 return {lutHexDiametralNode(l), i};
544 }
545 if (j == l)
546 {
547 return {lutHexDiametralNode(k), i};
548 }
549
550 return {std::numeric_limits<unsigned>::max(),
551 std::numeric_limits<unsigned>::max()};
552}
unsigned lutHexDiametralNode(unsigned const id)

References lutHexDiametralNode().

Referenced by reduceHex().

◆ lutHexCuttingQuadNodes()

std::array< unsigned, 4 > anonymous_namespace{MeshRevision.cpp}::lutHexCuttingQuadNodes ( unsigned id1,
unsigned id2 )

Lookup-table for returning four nodes connected to the two nodes (id1, id2) forming an edge in a Hex.

Definition at line 392 of file MeshRevision.cpp.

393{
394 if (id1 == 0 && id2 == 1)
395 {
396 return {3, 2, 5, 4};
397 }
398 if (id1 == 1 && id2 == 2)
399 {
400 return {0, 3, 6, 5};
401 }
402 if (id1 == 2 && id2 == 3)
403 {
404 return {1, 0, 7, 6};
405 }
406 if (id1 == 3 && id2 == 0)
407 {
408 return {2, 1, 4, 7};
409 }
410 if (id1 == 4 && id2 == 5)
411 {
412 return {0, 1, 6, 7};
413 }
414 if (id1 == 5 && id2 == 6)
415 {
416 return {1, 2, 7, 4};
417 }
418 if (id1 == 6 && id2 == 7)
419 {
420 return {2, 3, 4, 5};
421 }
422 if (id1 == 7 && id2 == 4)
423 {
424 return {3, 0, 5, 6};
425 }
426 if (id1 == 0 && id2 == 4)
427 {
428 return {3, 7, 5, 1};
429 }
430 if (id1 == 1 && id2 == 5)
431 {
432 return {0, 4, 6, 2};
433 }
434 if (id1 == 2 && id2 == 6)
435 {
436 return {1, 5, 7, 3};
437 }
438 if (id1 == 3 && id2 == 7)
439 {
440 return {2, 6, 4, 0};
441 }
442 if (id1 == 1 && id2 == 0)
443 {
444 return {2, 3, 4, 5};
445 }
446 if (id1 == 2 && id2 == 1)
447 {
448 return {3, 0, 5, 6};
449 }
450 if (id1 == 3 && id2 == 2)
451 {
452 return {0, 1, 6, 7};
453 }
454 if (id1 == 0 && id2 == 3)
455 {
456 return {1, 2, 7, 4};
457 }
458 if (id1 == 5 && id2 == 4)
459 {
460 return {1, 0, 7, 6};
461 }
462 if (id1 == 6 && id2 == 5)
463 {
464 return {2, 1, 4, 7};
465 }
466 if (id1 == 7 && id2 == 6)
467 {
468 return {3, 2, 5, 4};
469 }
470 if (id1 == 4 && id2 == 7)
471 {
472 return {0, 3, 6, 5};
473 }
474 if (id1 == 4 && id2 == 0)
475 {
476 return {7, 3, 1, 5};
477 }
478 if (id1 == 5 && id2 == 1)
479 {
480 return {4, 0, 2, 6};
481 }
482 if (id1 == 6 && id2 == 2)
483 {
484 return {5, 1, 3, 7};
485 }
486 if (id1 == 7 && id2 == 3)
487 {
488 return {6, 2, 0, 4};
489 }
490
491 OGS_FATAL(
492 "lutHexCuttingQuadNodes() for nodes {} and {} does not have a valid "
493 "return value.",
494 id1, id2);
495}
#define OGS_FATAL(...)
Definition Error.h:26

References OGS_FATAL.

Referenced by reduceHex().

◆ lutHexDiametralNode()

unsigned anonymous_namespace{MeshRevision.cpp}::lutHexDiametralNode ( unsigned const id)

Lookup-table for returning the diametral node id of the given node id in a Hex.

Definition at line 499 of file MeshRevision.cpp.

500{
501 constexpr std::array<unsigned, 8> hex_diametral_node_ids = {
502 {6, 7, 4, 5, 2, 3, 0, 1}};
503
504 return hex_diametral_node_ids[id];
505}

Referenced by lutHexBackNodes(), and reduceHex().

◆ reduceElement()

std::size_t anonymous_namespace{MeshRevision.cpp}::reduceElement ( MeshLib::Element const *const element,
unsigned const n_unique_nodes,
std::vector< MeshLib::Node * > const & nodes,
std::vector< MeshLib::Element * > & elements,
unsigned const min_elem_dim )

Definition at line 831 of file MeshRevision.cpp.

836{
837 /***************
838 * TODO: modify neighbouring elements if one elements has been subdivided
839 ***************/
840 if (element->getGeomType() == MeshLib::MeshElemType::TRIANGLE &&
841 min_elem_dim == 1)
842 {
843 elements.push_back(constructLine(element, nodes));
844 return 1;
845 }
846 if ((element->getGeomType() == MeshLib::MeshElemType::QUAD) ||
847 (element->getGeomType() == MeshLib::MeshElemType::TETRAHEDRON))
848 {
849 if (n_unique_nodes == 3 && min_elem_dim < 3)
850 {
851 elements.push_back(constructTri(element, nodes));
852 }
853 else if (min_elem_dim == 1)
854 {
855 elements.push_back(constructLine(element, nodes));
856 }
857 return 1;
858 }
859 if (element->getGeomType() == MeshLib::MeshElemType::HEXAHEDRON)
860 {
861 return reduceHex(element, n_unique_nodes, nodes, elements,
862 min_elem_dim);
863 }
864 if (element->getGeomType() == MeshLib::MeshElemType::PYRAMID)
865 {
866 reducePyramid(element, n_unique_nodes, nodes, elements, min_elem_dim);
867 return 1;
868 }
869 if (element->getGeomType() == MeshLib::MeshElemType::PRISM)
870 {
871 return reducePrism(element, n_unique_nodes, nodes, elements,
872 min_elem_dim);
873 }
874
875 ERR("Unknown element type.");
876 return 0;
877}
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:45
MeshLib::Element * constructTri(MeshLib::Element const *const element, const std::vector< MeshLib::Node * > &nodes)
MeshLib::Element * constructLine(MeshLib::Element const *const element, const std::vector< MeshLib::Node * > &nodes)
unsigned reduceHex(MeshLib::Element const *const org_elem, unsigned const n_unique_nodes, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &new_elements, unsigned const min_elem_dim)
unsigned reducePrism(MeshLib::Element const *const org_elem, unsigned const n_unique_nodes, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &new_elements, unsigned const min_elem_dim)
void reducePyramid(MeshLib::Element const *const org_elem, unsigned const n_unique_nodes, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &new_elements, unsigned const min_elem_dim)

References constructLine(), constructTri(), ERR(), MeshLib::Element::getGeomType(), MeshLib::HEXAHEDRON, MeshLib::PRISM, MeshLib::PYRAMID, MeshLib::QUAD, reduceHex(), reducePrism(), reducePyramid(), MeshLib::TETRAHEDRON, and MeshLib::TRIANGLE.

◆ reduceHex()

unsigned anonymous_namespace{MeshRevision.cpp}::reduceHex ( MeshLib::Element const *const org_elem,
unsigned const n_unique_nodes,
std::vector< MeshLib::Node * > const & nodes,
std::vector< MeshLib::Element * > & new_elements,
unsigned const min_elem_dim )

Reduces a hexahedron element by removing collapsed nodes and constructing one or more new elements from the remaining nodes.

Returns
The number of newly created elements

Definition at line 582 of file MeshRevision.cpp.

587{
588 // TODO?
589 // if two diametral nodes collapse, all kinds of bizarre (2D-)element
590 // combinations could be the result. this case is currently not implemented!
591
592 if (n_unique_nodes == 7)
593 {
594 // reduce to prism + pyramid
595 for (unsigned i = 0; i < 7; ++i)
596 {
597 for (unsigned j = i + 1; j < 8; ++j)
598 {
599 if (org_elem->getNode(i)->getID() ==
600 org_elem->getNode(j)->getID())
601 {
602 const std::array<unsigned, 4> base_node_ids(
604 std::array<std::size_t, 5> const pyr_node_ids = {
605 base_node_ids[0], base_node_ids[1], base_node_ids[2],
606 base_node_ids[3], i};
607 new_elements.push_back(
608 createElement<MeshLib::Pyramid>(org_elem->nodes(),
609 nodes, pyr_node_ids)
610 .release());
611
612 if (i < 4 && j >= 4)
613 {
614 std::swap(i, j);
615 }
616 std::array<std::size_t, 6> const prism_node_ids{
617 base_node_ids[0], base_node_ids[3],
618 lutHexDiametralNode(j), base_node_ids[1],
619 base_node_ids[2], lutHexDiametralNode(i)};
620 new_elements.push_back(
621 createElement<MeshLib::Prism>(org_elem->nodes(), nodes,
622 prism_node_ids)
623 .release());
624 return 2;
625 }
626 }
627 }
628 }
629 else if (n_unique_nodes == 6)
630 {
631 // reduce to prism
632 for (unsigned i = 0; i < 6; ++i)
633 {
634 const MeshLib::Element* face(org_elem->getFace(i));
635 if (face->getNode(0)->getID() == face->getNode(1)->getID() &&
636 face->getNode(2)->getID() == face->getNode(3)->getID())
637 {
638 std::array<std::size_t, 6> const prism_node_ids{
640 getNodeIDinElement(*org_elem, face->getNode(0))),
642 getNodeIDinElement(*org_elem, face->getNode(1))),
643 getNodeIDinElement(*org_elem, face->getNode(2)),
645 getNodeIDinElement(*org_elem, face->getNode(2))),
647 getNodeIDinElement(*org_elem, face->getNode(3))),
648 getNodeIDinElement(*org_elem, face->getNode(0))};
649
650 new_elements.push_back(
651 createElement<MeshLib::Prism>(org_elem->nodes(), nodes,
652 prism_node_ids)
653 .release());
654 delete face;
655 return 1;
656 }
657 if (face->getNode(0)->getID() == face->getNode(3)->getID() &&
658 face->getNode(1)->getID() == face->getNode(2)->getID())
659 {
660 std::array<std::size_t, 6> const prism_node_ids{
662 getNodeIDinElement(*org_elem, face->getNode(0))),
664 getNodeIDinElement(*org_elem, face->getNode(3))),
665 getNodeIDinElement(*org_elem, face->getNode(2)),
667 getNodeIDinElement(*org_elem, face->getNode(1))),
669 getNodeIDinElement(*org_elem, face->getNode(2))),
670 getNodeIDinElement(*org_elem, face->getNode(0))};
671 new_elements.push_back(
672 createElement<MeshLib::Prism>(org_elem->nodes(), nodes,
673 prism_node_ids)
674 .release());
675 delete face;
676 return 1;
677 }
678 delete face;
679 }
680 // reduce to four tets -> divide into 2 prisms such that each has one
681 // collapsed node
682 for (unsigned i = 0; i < 7; ++i)
683 {
684 for (unsigned j = i + 1; j < 8; ++j)
685 {
686 if (org_elem->getNode(i)->getID() ==
687 org_elem->getNode(j)->getID())
688 {
689 for (unsigned k = i; k < 7; ++k)
690 {
691 for (unsigned l = k + 1; l < 8; ++l)
692 {
693 if (!(i == k && j == l) && org_elem->isEdge(i, j) &&
694 org_elem->isEdge(k, l) &&
695 org_elem->getNode(k)->getID() ==
696 org_elem->getNode(l)->getID())
697 {
698 const std::pair<unsigned, unsigned> back(
699 lutHexBackNodes(i, j, k, l));
700 if (back.first ==
701 std::numeric_limits<unsigned>::max() ||
702 back.second ==
703 std::numeric_limits<unsigned>::max())
704 {
705 ERR("Unexpected error during Hex "
706 "reduction");
707 return 0;
708 }
709
710 std::array<unsigned, 4> const cutting_plane(
711 lutHexCuttingQuadNodes(back.first,
712 back.second));
713 std::array<std::size_t, 6> const pris1_node_ids{
714 back.first, cutting_plane[0],
715 cutting_plane[3], back.second,
716 cutting_plane[1], cutting_plane[2]};
717 auto prism1 = createElement<MeshLib::Prism>(
718 org_elem->nodes(), nodes, pris1_node_ids);
719 unsigned nNewElements =
720 reducePrism(prism1.get(), 5, nodes,
721 new_elements, min_elem_dim);
722
723 std::array<std::size_t, 6> const pris2_node_ids{
724 lutHexDiametralNode(back.first),
725 cutting_plane[0],
726 cutting_plane[3],
727 lutHexDiametralNode(back.second),
728 cutting_plane[1],
729 cutting_plane[2]};
730 auto prism2 = createElement<MeshLib::Prism>(
731 org_elem->nodes(), nodes, pris2_node_ids);
732 nNewElements +=
733 reducePrism(prism2.get(), 5, nodes,
734 new_elements, min_elem_dim);
735 return nNewElements;
736 }
737 }
738 }
739 }
740 }
741 }
742 }
743 else if (n_unique_nodes == 5)
744 {
745 MeshLib::Element* tet1(constructFourNodeElement(org_elem, nodes));
746 std::array<std::size_t, 4> const first_four_node_ids = {
747 {tet1->getNode(0)->getID(), tet1->getNode(1)->getID(),
748 tet1->getNode(2)->getID(), tet1->getNode(3)->getID()}};
749 unsigned const fifth_node =
750 findPyramidTopNode(*org_elem, first_four_node_ids);
751
752 bool tet_changed(false);
753 if (tet1->getGeomType() == MeshLib::MeshElemType::QUAD)
754 {
755 delete tet1;
756 tet_changed = true;
757 std::array const tet1_nodes = {
758 nodes[first_four_node_ids[0]], nodes[first_four_node_ids[1]],
759 nodes[first_four_node_ids[2]],
760 nodes[org_elem->getNode(fifth_node)->getID()]};
761 new_elements.push_back(new MeshLib::Tet(tet1_nodes));
762 }
763 else
764 {
765 new_elements.push_back(tet1);
766 }
767
768 std::array const tet2_nodes = {
769 (tet_changed) ? nodes[first_four_node_ids[0]]
770 : nodes[first_four_node_ids[1]],
771 nodes[first_four_node_ids[2]], nodes[first_four_node_ids[3]],
772 nodes[org_elem->getNode(fifth_node)->getID()]};
773 new_elements.push_back(new MeshLib::Tet(tet2_nodes));
774 return 2;
775 }
776 else if (n_unique_nodes == 4)
777 {
778 MeshLib::Element* elem(
779 constructFourNodeElement(org_elem, nodes, min_elem_dim));
780 if (elem)
781 {
782 new_elements.push_back(elem);
783 return 1;
784 }
785 }
786 else if (n_unique_nodes == 3 && min_elem_dim < 3)
787 {
788 new_elements.push_back(constructTri(org_elem, nodes));
789 return 1;
790 }
791 else if (min_elem_dim == 1)
792 {
793 new_elements.push_back(constructLine(org_elem, nodes));
794 return 1;
795 }
796 return 0;
797}
unsigned getNodeIDinElement(Element const &element, const MeshLib::Node *node)
Returns the position of the given node in the node array of this element.
Definition Element.cpp:206
std::array< unsigned, 4 > lutHexCuttingQuadNodes(unsigned id1, unsigned id2)
std::pair< unsigned, unsigned > lutHexBackNodes(unsigned const i, unsigned const j, unsigned const k, unsigned const l)
unsigned findPyramidTopNode(MeshLib::Element const &element, std::array< std::size_t, 4 > const &base_node_ids)
MeshLib::Element * constructFourNodeElement(MeshLib::Element const *const element, std::vector< MeshLib::Node * > const &nodes, unsigned const min_elem_dim=1)

References constructFourNodeElement(), constructLine(), constructTri(), ERR(), findPyramidTopNode(), MeshLib::Element::getFace(), MeshLib::Element::getGeomType(), MathLib::Point3dWithID::getID(), MeshLib::Element::getNode(), MeshLib::Element::isEdge(), lutHexBackNodes(), lutHexCuttingQuadNodes(), lutHexDiametralNode(), MeshLib::Element::nodes(), MeshLib::QUAD, and reducePrism().

Referenced by reduceElement().

◆ reducePrism()

unsigned anonymous_namespace{MeshRevision.cpp}::reducePrism ( MeshLib::Element const *const org_elem,
unsigned const n_unique_nodes,
std::vector< MeshLib::Node * > const & nodes,
std::vector< MeshLib::Element * > & new_elements,
unsigned const min_elem_dim )

Reduces a prism element by removing collapsed nodes and constructing one or two new elements from the remaining nodes.

Returns
The number of newly created elements

Definition at line 303 of file MeshRevision.cpp.

308{
309 auto addTetrahedron =
310 [&org_elem, &nodes, &new_elements](std::array<std::size_t, 4> const ids)
311 {
312 new_elements.push_back(
313 createElement<MeshLib::Tet>(org_elem->nodes(), nodes, ids)
314 .release());
315 };
316
317 // TODO?
318 // In theory a node from the bottom triangle and a node from the top
319 // triangle that are not connected by an edge could collapse, resulting in a
320 // combination of tri and quad elements. This case is currently not tested.
321
322 // if one of the non-triangle edges collapsed, elem can be reduced to a
323 // pyramid, otherwise it will be two tets
324 if (n_unique_nodes == 5)
325 {
326 for (unsigned i = 0; i < 5; ++i)
327 {
328 for (unsigned j = i + 1; j < 6; ++j)
329 {
330 if (i != j && org_elem->getNode(i)->getID() ==
331 org_elem->getNode(j)->getID())
332 {
333 // non triangle edge collapsed
334 if (i % 3 == j % 3)
335 {
336 addTetrahedron(
337 {(i + 1) % 3, (i + 2) % 3, i, (i + 1) % 3 + 3});
338 addTetrahedron(
339 {(i + 1) % 3 + 3, (i + 2) % 3, i, (i + 2) % 3 + 3});
340 return 2;
341 }
342
343 // triangle edge collapsed
344 const unsigned i_offset = (i > 2) ? i - 3 : i + 3;
345 const unsigned j_offset = (i > 2) ? j - 3 : j + 3;
346 const unsigned k = MeshToolsLib::lutPrismThirdNode(i, j);
347 if (k == std::numeric_limits<unsigned>::max())
348 {
349 ERR("Unexpected error during prism reduction.");
350 return 0;
351 }
352 const unsigned k_offset = (i > 2) ? k - 3 : k + 3;
353
354 addTetrahedron({i_offset, j_offset, k_offset, i});
355
356 const unsigned l =
357 (MathLib::isCoplanar(*org_elem->getNode(i_offset),
358 *org_elem->getNode(k_offset),
359 *org_elem->getNode(i),
360 *org_elem->getNode(k)))
361 ? j
362 : i;
363 const unsigned l_offset = (i > 2) ? l - 3 : l + 3;
364 addTetrahedron({l_offset, k_offset, i, k});
365 return 2;
366 }
367 }
368 }
369 }
370 else if (n_unique_nodes == 4)
371 {
372 MeshLib::Element* const elem(
373 constructFourNodeElement(org_elem, nodes, min_elem_dim));
374 if (elem)
375 {
376 new_elements.push_back(elem);
377 }
378 }
379 else if (n_unique_nodes == 3 && min_elem_dim < 3)
380 {
381 new_elements.push_back(constructTri(org_elem, nodes));
382 }
383 else if (n_unique_nodes == 2 && min_elem_dim == 1)
384 {
385 new_elements.push_back(constructLine(org_elem, nodes));
386 }
387 return 1;
388}
unsigned lutPrismThirdNode(unsigned const id1, unsigned const id2)

References constructFourNodeElement(), constructLine(), constructTri(), ERR(), MathLib::Point3dWithID::getID(), MeshLib::Element::getNode(), MathLib::isCoplanar(), MeshToolsLib::lutPrismThirdNode(), and MeshLib::Element::nodes().

Referenced by reduceElement(), and reduceHex().

◆ reducePyramid()

void anonymous_namespace{MeshRevision.cpp}::reducePyramid ( MeshLib::Element const *const org_elem,
unsigned const n_unique_nodes,
std::vector< MeshLib::Node * > const & nodes,
std::vector< MeshLib::Element * > & new_elements,
unsigned const min_elem_dim )

Reduces a pyramid element by removing collapsed nodes and constructing a new elements from the remaining nodes.

Definition at line 275 of file MeshRevision.cpp.

280{
281 if (n_unique_nodes == 4)
282 {
283 MeshLib::Element* elem(
284 constructFourNodeElement(org_elem, nodes, min_elem_dim));
285 if (elem)
286 {
287 new_elements.push_back(elem);
288 }
289 }
290 else if (n_unique_nodes == 3 && min_elem_dim < 3)
291 {
292 new_elements.push_back(constructTri(org_elem, nodes));
293 }
294 else if (n_unique_nodes == 2 && min_elem_dim == 1)
295 {
296 new_elements.push_back(constructLine(org_elem, nodes));
297 }
298}

References constructFourNodeElement(), constructLine(), and constructTri().

Referenced by reduceElement().

◆ subdivideElement()

std::size_t anonymous_namespace{MeshRevision.cpp}::subdivideElement ( MeshLib::Element const *const element,
std::vector< MeshLib::Node * > const & nodes,
std::vector< MeshLib::Element * > & elements )

Subdivides an element if it has a face that is not coplanar

Parameters
elementthe element that will be subdivided
nodesvector containing the nodes the elements originated by the subdivision are based on
elementsvector of MeshLib::Elements; the elements originated by the subdivision will be inserted into elements
Returns
the number of elements originated by the subdivision

Definition at line 806 of file MeshRevision.cpp.

809{
810 if (element->getGeomType() == MeshLib::MeshElemType::QUAD)
811 {
812 return subdivideQuad(element, nodes, elements);
813 }
814 if (element->getGeomType() == MeshLib::MeshElemType::HEXAHEDRON)
815 {
816 return subdivideHex(element, nodes, elements);
817 }
818 if (element->getGeomType() == MeshLib::MeshElemType::PYRAMID)
819 {
820 return subdividePyramid(element, nodes, elements);
821 }
822 if (element->getGeomType() == MeshLib::MeshElemType::PRISM)
823 {
824 return subdividePrism(element, nodes, elements);
825 }
826 return 0;
827}
unsigned subdivideHex(MeshLib::Element const *const hex, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &new_elements)
Subdivides a Hex with nonplanar faces into tets.
unsigned subdividePrism(MeshLib::Element const *const prism, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &new_elements)
Subdivides a prism with nonplanar quad faces into two tets.
unsigned subdividePyramid(MeshLib::Element const *const pyramid, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &new_elements)
Subdivides a pyramid with a nonplanar base into two tets.
unsigned subdivideQuad(MeshLib::Element const *const quad, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &new_elements)
Subdivides a nonplanar quad into two triangles.

References MeshLib::Element::getGeomType(), MeshLib::HEXAHEDRON, MeshLib::PRISM, MeshLib::PYRAMID, MeshLib::QUAD, subdivideHex(), subdividePrism(), subdividePyramid(), and subdivideQuad().

◆ subdivideHex()

unsigned anonymous_namespace{MeshRevision.cpp}::subdivideHex ( MeshLib::Element const *const hex,
std::vector< MeshLib::Node * > const & nodes,
std::vector< MeshLib::Element * > & new_elements )

Subdivides a Hex with nonplanar faces into tets.

Definition at line 125 of file MeshRevision.cpp.

128{
129 auto prism1 =
130 createElement<MeshLib::Prism>(hex->nodes(), nodes, {0, 2, 1, 4, 6, 5});
131 subdividePrism(prism1.get(), nodes, new_elements);
132
133 auto prism2 =
134 createElement<MeshLib::Prism>(hex->nodes(), nodes, {4, 6, 7, 0, 2, 3});
135 subdividePrism(prism2.get(), nodes, new_elements);
136
137 return 6;
138}

References MeshLib::Element::nodes(), and subdividePrism().

Referenced by subdivideElement().

◆ subdividePrism()

unsigned anonymous_namespace{MeshRevision.cpp}::subdividePrism ( MeshLib::Element const *const prism,
std::vector< MeshLib::Node * > const & nodes,
std::vector< MeshLib::Element * > & new_elements )

Subdivides a prism with nonplanar quad faces into two tets.

Definition at line 106 of file MeshRevision.cpp.

109{
110 auto addTetrahedron =
111 [&prism, &nodes, &new_elements](std::array<std::size_t, 4> const ids)
112 {
113 new_elements.push_back(
114 createElement<MeshLib::Tet>(prism->nodes(), nodes, ids).release());
115 };
116
117 addTetrahedron({0, 1, 2, 3});
118 addTetrahedron({3, 2, 4, 5});
119 addTetrahedron({2, 1, 3, 4});
120
121 return 3;
122}

References MeshLib::Element::nodes().

Referenced by subdivideElement(), and subdivideHex().

◆ subdividePyramid()

unsigned anonymous_namespace{MeshRevision.cpp}::subdividePyramid ( MeshLib::Element const *const pyramid,
std::vector< MeshLib::Node * > const & nodes,
std::vector< MeshLib::Element * > & new_elements )

Subdivides a pyramid with a nonplanar base into two tets.

Definition at line 141 of file MeshRevision.cpp.

144{
145 auto addTetrahedron =
146 [&pyramid, &nodes, &new_elements](std::array<std::size_t, 4> const ids)
147 {
148 new_elements.push_back(
149 createElement<MeshLib::Tet>(pyramid->nodes(), nodes, ids)
150 .release());
151 };
152
153 addTetrahedron({0, 1, 2, 4});
154 addTetrahedron({0, 2, 3, 4});
155
156 return 2;
157}

References MeshLib::Element::nodes().

Referenced by subdivideElement().

◆ subdivideQuad()

unsigned anonymous_namespace{MeshRevision.cpp}::subdivideQuad ( MeshLib::Element const *const quad,
std::vector< MeshLib::Node * > const & nodes,
std::vector< MeshLib::Element * > & new_elements )

Subdivides a nonplanar quad into two triangles.

Definition at line 88 of file MeshRevision.cpp.

91{
92 std::array<std::size_t, 3> const tri1_node_ids{0, 1, 2};
93 new_elements.push_back(
94 createElement<MeshLib::Tri>(quad->nodes(), nodes, tri1_node_ids)
95 .release());
96
97 std::array<std::size_t, 3> const tri2_node_ids{0, 2, 3};
98 new_elements.push_back(
99 createElement<MeshLib::Tri>(quad->nodes(), nodes, tri2_node_ids)
100 .release());
101
102 return 2;
103}

References MeshLib::Element::nodes().

Referenced by subdivideElement().