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 (MeshLib::PropertyVector< T > &new_prop, MeshLib::PropertyVector< T > const &old_prop, std::vector< size_t > const &node_ids)
template<typename T>
void fillElemProperty (MeshLib::PropertyVector< T > &new_prop, MeshLib::PropertyVector< 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 205 of file MeshRevision.cpp.

209{
210 std::array<MeshLib::Node*, 4> new_nodes;
211 unsigned count(0);
212 new_nodes[count++] = nodes[element->getNode(0)->getID()];
213 for (unsigned i = 1; i < element->getNumberOfBaseNodes(); ++i)
214 {
215 if (count > 3)
216 {
217 break;
218 }
219 bool unique_node(true);
220 for (unsigned j = 0; j < i; ++j)
221 {
222 if (element->getNode(i)->getID() == element->getNode(j)->getID())
223 {
224 unique_node = false;
225 break;
226 }
227 }
228 if (unique_node)
229 {
230 new_nodes[count++] = nodes[element->getNode(i)->getID()];
231 };
232 }
233
234 // test if quad or tet
235 const bool isQuad(MathLib::isCoplanar(*new_nodes[0], *new_nodes[1],
236 *new_nodes[2], *new_nodes[3]));
237 if (isQuad && min_elem_dim < 3)
238 {
239 MeshLib::Element* elem(new MeshLib::Quad(new_nodes));
240 for (unsigned i = 1; i < 3; ++i)
241 {
242 if (elem->validate().none())
243 {
244 return elem;
245 }
246
247 // change node order if not convex
248 MeshLib::Node* tmp = new_nodes[i + 1];
249 new_nodes[i + 1] = new_nodes[i];
250 new_nodes[i] = tmp;
251 }
252 return elem;
253 }
254 if (!isQuad)
255 {
256 return new MeshLib::Tet(new_nodes);
257 }
258 // is quad but min elem dim == 3
259
260 return nullptr;
261}
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:14
TemplateElement< MeshLib::QuadRule4 > Quad
Definition Quad.h:17

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 151 of file MeshRevision.cpp.

153{
154 std::array<std::size_t, 2> line_node_ids = {0, 0};
155 for (unsigned i = 1; i < element->getNumberOfBaseNodes(); ++i)
156 {
157 if (element->getNode(i)->getID() != element->getNode(0)->getID())
158 {
159 line_node_ids[1] = i;
160 break;
161 }
162 }
163 assert(line_node_ids[1] != 0);
164 return createElement<MeshLib::Line>(element->nodes(), nodes, line_node_ids)
165 .release();
166}
std::unique_ptr< MeshLib::Element > 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)

References createElement(), 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 170 of file MeshRevision.cpp.

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

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 919 of file MeshRevision.cpp.

922{
923 auto const prop_names = props.getPropertyVectorNames();
924 MeshLib::Properties new_properties;
925
926 for (auto name : prop_names)
927 {
928 if (props.existsPropertyVector<int>(name, MeshLib::MeshItemType::Node,
929 1))
930 {
931 auto const* p = props.getPropertyVector<int>(
933 auto new_node_vec = new_properties.createNewPropertyVector<int>(
935 fillNodeProperty(*new_node_vec, *p, node_ids);
936 continue;
937 }
938 if (props.existsPropertyVector<float>(name, MeshLib::MeshItemType::Node,
939 1))
940 {
941 auto const* p = props.getPropertyVector<float>(
943 auto new_node_vec = new_properties.createNewPropertyVector<float>(
945 fillNodeProperty(*new_node_vec, *p, node_ids);
946 continue;
947 }
948 if (props.existsPropertyVector<double>(name,
950 {
951 auto const* p = props.getPropertyVector<double>(
953 auto new_node_vec = new_properties.createNewPropertyVector<double>(
955 fillNodeProperty(*new_node_vec, *p, node_ids);
956 continue;
957 }
958 if (props.existsPropertyVector<int>(name, MeshLib::MeshItemType::Cell,
959 1))
960 {
961 auto const* p = props.getPropertyVector<int>(
963 auto new_cell_vec = new_properties.createNewPropertyVector<int>(
964 name, MeshLib::MeshItemType::Cell, p->size(), 1);
965 fillElemProperty(*new_cell_vec, *p, elem_ids);
966 continue;
967 }
968 if (props.existsPropertyVector<float>(name, MeshLib::MeshItemType::Cell,
969 1))
970 {
971 auto const* p = props.getPropertyVector<float>(
973 auto new_cell_vec = new_properties.createNewPropertyVector<float>(
974 name, MeshLib::MeshItemType::Cell, p->size(), 1);
975 fillElemProperty(*new_cell_vec, *p, elem_ids);
976 continue;
977 }
978 if (props.existsPropertyVector<double>(name,
980 {
981 auto const* p = props.getPropertyVector<double>(
983 auto new_cell_vec = new_properties.createNewPropertyVector<double>(
984 name, MeshLib::MeshItemType::Cell, p->size(), 1);
985 fillElemProperty(*new_cell_vec, *p, elem_ids);
986 continue;
987 }
988 WARN("PropertyVector {:s} not being converted.", name);
989 }
990 return new_properties;
991}
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:34
Property manager on mesh items. Class Properties manages scalar, vector or matrix properties....
PropertyVector< T > * createNewPropertyVector(std::string_view name, MeshItemType mesh_item_type, std::size_t n_components=1)
void fillNodeProperty(MeshLib::PropertyVector< T > &new_prop, MeshLib::PropertyVector< T > const &old_prop, std::vector< size_t > const &node_ids)
void fillElemProperty(MeshLib::PropertyVector< T > &new_prop, MeshLib::PropertyVector< T > const &old_prop, std::vector< size_t > const &elem_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 58 of file MeshRevision.cpp.

62{
63 using namespace MeshLib::views;
64 auto lookup_in = [](auto const& values)
65 {
66 return ranges::views::transform([&values](std::size_t const n)
67 { return values[n]; });
68 };
69
70 std::array<MeshLib::Node*, ElementType::n_all_nodes> new_nodes;
71 ranges::copy(local_ids | lookup_in(element_nodes) | ids | lookup_in(nodes),
72 begin(new_nodes));
73
74 return std::make_unique<ElementType>(new_nodes);
75}
MeshLib specific, lazy, non-owning, non-mutating, composable range views.
Definition Mesh.h:214

References MeshLib::views::ids.

Referenced by constructLine(), reduceHex(), reducePrism(), subdivideHex(), subdividePrism(), subdividePyramid(), and subdivideQuad().

◆ fillElemProperty()

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

Definition at line 906 of file MeshRevision.cpp.

909{
910 assert(new_prop.size() == old_prop.size());
911 assert(new_prop.size() == elem_ids.size());
912 ranges::transform(elem_ids, new_prop.begin(),
913 [&](std::size_t const i) { return old_prop[i]; });
914}
constexpr PROP_VAL_TYPE * begin()
constexpr std::size_t size() const

References MeshLib::PropertyVector< PROP_VAL_TYPE >::begin(), and MeshLib::PropertyVector< PROP_VAL_TYPE >::size().

Referenced by copyProperties().

◆ fillNodeProperty()

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

Definition at line 890 of file MeshRevision.cpp.

893{
894 std::size_t const n_nodes = node_ids.size();
895 for (std::size_t i = 0; i < n_nodes; ++i)
896 {
897 if (node_ids[i] != i)
898 {
899 continue;
900 }
901 new_prop.push_back(old_prop[i]);
902 }
903}
constexpr void push_back(const PROP_VAL_TYPE &value)

References MeshLib::PropertyVector< PROP_VAL_TYPE >::push_back().

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 546 of file MeshRevision.cpp.

548{
549 const std::size_t nNodes(element.getNumberOfBaseNodes());
550 for (std::size_t i = 0; i < nNodes; ++i)
551 {
552 bool top_node = true;
553 for (unsigned j = 0; j < 4; ++j)
554 {
555 if (element.getNode(i)->getID() == base_node_ids[j])
556 {
557 top_node = false;
558 }
559 }
560 if (top_node)
561 {
562 return i;
563 }
564 }
565 return std::numeric_limits<unsigned>::max(); // should never be reached if
566 // called correctly
567}

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 870 of file MeshRevision.cpp.

871{
872 unsigned const nNodes(element->getNumberOfBaseNodes());
873 unsigned count(nNodes);
874
875 for (unsigned i = 0; i < nNodes - 1; ++i)
876 {
877 for (unsigned j = i + 1; j < nNodes; ++j)
878 {
879 if (element->getNode(i)->getID() == element->getNode(j)->getID())
880 {
881 count--;
882 break;
883 }
884 }
885 }
886 return count;
887}

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 499 of file MeshRevision.cpp.

503{
504 // collapsed edges are *not* connected
505 if (lutHexDiametralNode(i) == k)
506 {
507 return {i, lutHexDiametralNode(l)};
508 }
509 if (lutHexDiametralNode(i) == l)
510 {
511 return {i, lutHexDiametralNode(k)};
512 }
513 if (lutHexDiametralNode(j) == k)
514 {
515 return {j, lutHexDiametralNode(l)};
516 }
517 if (lutHexDiametralNode(j) == l)
518 {
519 return {j, lutHexDiametralNode(k)};
520 }
521
522 // collapsed edges *are* connected
523 if (i == k)
524 {
525 return {lutHexDiametralNode(l), j};
526 }
527 if (i == l)
528 {
529 return {lutHexDiametralNode(k), j};
530 }
531 if (j == k)
532 {
533 return {lutHexDiametralNode(l), i};
534 }
535 if (j == l)
536 {
537 return {lutHexDiametralNode(k), i};
538 }
539
540 return {std::numeric_limits<unsigned>::max(),
541 std::numeric_limits<unsigned>::max()};
542}
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 382 of file MeshRevision.cpp.

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

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 489 of file MeshRevision.cpp.

490{
491 constexpr std::array<unsigned, 8> hex_diametral_node_ids = {
492 {6, 7, 4, 5, 2, 3, 0, 1}};
493
494 return hex_diametral_node_ids[id];
495}

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 821 of file MeshRevision.cpp.

826{
827 /***************
828 * TODO: modify neighbouring elements if one elements has been subdivided
829 ***************/
830 if (element->getGeomType() == MeshLib::MeshElemType::TRIANGLE &&
831 min_elem_dim == 1)
832 {
833 elements.push_back(constructLine(element, nodes));
834 return 1;
835 }
836 if ((element->getGeomType() == MeshLib::MeshElemType::QUAD) ||
837 (element->getGeomType() == MeshLib::MeshElemType::TETRAHEDRON))
838 {
839 if (n_unique_nodes == 3 && min_elem_dim < 3)
840 {
841 elements.push_back(constructTri(element, nodes));
842 }
843 else if (min_elem_dim == 1)
844 {
845 elements.push_back(constructLine(element, nodes));
846 }
847 return 1;
848 }
849 if (element->getGeomType() == MeshLib::MeshElemType::HEXAHEDRON)
850 {
851 return reduceHex(element, n_unique_nodes, nodes, elements,
852 min_elem_dim);
853 }
854 if (element->getGeomType() == MeshLib::MeshElemType::PYRAMID)
855 {
856 reducePyramid(element, n_unique_nodes, nodes, elements, min_elem_dim);
857 return 1;
858 }
859 if (element->getGeomType() == MeshLib::MeshElemType::PRISM)
860 {
861 return reducePrism(element, n_unique_nodes, nodes, elements,
862 min_elem_dim);
863 }
864
865 ERR("Unknown element type.");
866 return 0;
867}
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
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 572 of file MeshRevision.cpp.

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

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

References constructFourNodeElement(), constructLine(), constructTri(), createElement(), ERR(), MathLib::Point3dWithID::getID(), MeshLib::Element::getNode(), MeshLib::views::ids, 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 265 of file MeshRevision.cpp.

270{
271 if (n_unique_nodes == 4)
272 {
273 MeshLib::Element* elem(
274 constructFourNodeElement(org_elem, nodes, min_elem_dim));
275 if (elem)
276 {
277 new_elements.push_back(elem);
278 }
279 }
280 else if (n_unique_nodes == 3 && min_elem_dim < 3)
281 {
282 new_elements.push_back(constructTri(org_elem, nodes));
283 }
284 else if (n_unique_nodes == 2 && min_elem_dim == 1)
285 {
286 new_elements.push_back(constructLine(org_elem, nodes));
287 }
288}

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 796 of file MeshRevision.cpp.

799{
800 if (element->getGeomType() == MeshLib::MeshElemType::QUAD)
801 {
802 return subdivideQuad(element, nodes, elements);
803 }
804 if (element->getGeomType() == MeshLib::MeshElemType::HEXAHEDRON)
805 {
806 return subdivideHex(element, nodes, elements);
807 }
808 if (element->getGeomType() == MeshLib::MeshElemType::PYRAMID)
809 {
810 return subdividePyramid(element, nodes, elements);
811 }
812 if (element->getGeomType() == MeshLib::MeshElemType::PRISM)
813 {
814 return subdividePrism(element, nodes, elements);
815 }
816 return 0;
817}
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 115 of file MeshRevision.cpp.

118{
119 auto prism1 =
120 createElement<MeshLib::Prism>(hex->nodes(), nodes, {0, 2, 1, 4, 6, 5});
121 subdividePrism(prism1.get(), nodes, new_elements);
122
123 auto prism2 =
124 createElement<MeshLib::Prism>(hex->nodes(), nodes, {4, 6, 7, 0, 2, 3});
125 subdividePrism(prism2.get(), nodes, new_elements);
126
127 return 6;
128}

References createElement(), 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 96 of file MeshRevision.cpp.

99{
100 auto addTetrahedron =
101 [&prism, &nodes, &new_elements](std::array<std::size_t, 4> const ids)
102 {
103 new_elements.push_back(
104 createElement<MeshLib::Tet>(prism->nodes(), nodes, ids).release());
105 };
106
107 addTetrahedron({0, 1, 2, 3});
108 addTetrahedron({3, 2, 4, 5});
109 addTetrahedron({2, 1, 3, 4});
110
111 return 3;
112}

References createElement(), MeshLib::views::ids, and 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 131 of file MeshRevision.cpp.

134{
135 auto addTetrahedron =
136 [&pyramid, &nodes, &new_elements](std::array<std::size_t, 4> const ids)
137 {
138 new_elements.push_back(
139 createElement<MeshLib::Tet>(pyramid->nodes(), nodes, ids)
140 .release());
141 };
142
143 addTetrahedron({0, 1, 2, 4});
144 addTetrahedron({0, 2, 3, 4});
145
146 return 2;
147}

References createElement(), MeshLib::views::ids, and 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 78 of file MeshRevision.cpp.

81{
82 std::array<std::size_t, 3> const tri1_node_ids{0, 1, 2};
83 new_elements.push_back(
84 createElement<MeshLib::Tri>(quad->nodes(), nodes, tri1_node_ids)
85 .release());
86
87 std::array<std::size_t, 3> const tri2_node_ids{0, 2, 3};
88 new_elements.push_back(
89 createElement<MeshLib::Tri>(quad->nodes(), nodes, tri2_node_ids)
90 .release());
91
92 return 2;
93}

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

Referenced by subdivideElement().