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)
std::vector< std::size_t > getSurvivingNodeIds (std::vector< std::size_t > const &node_ids)
template<typename T>
bool copyProperty (MeshLib::Properties const &props, MeshLib::Properties &new_properties, std::string const &name, MeshLib::MeshItemType const item_type, std::vector< std::size_t > const &source_ids)
template<typename... Ts>
bool copyPropertyOfAnyValueType (MeshLib::Properties const &props, MeshLib::Properties &new_properties, std::string const &name, MeshLib::MeshItemType const item_type, std::vector< std::size_t > const &source_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 207 of file MeshRevision.cpp.

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

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

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

956{
957 auto const prop_names = props.getPropertyVectorNames();
958 MeshLib::Properties new_properties;
959 auto const surviving_node_ids = getSurvivingNodeIds(node_ids);
960
961 for (auto const& name : prop_names)
962 {
964 props, new_properties, name, MeshLib::MeshItemType::Node,
965 surviving_node_ids) &&
967 props, new_properties, name, MeshLib::MeshItemType::Cell,
968 elem_ids))
969 {
970 WARN("PropertyVector {:s} not being converted.", name);
971 }
972 }
973 return new_properties;
974}
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....
bool copyPropertyOfAnyValueType(MeshLib::Properties const &props, MeshLib::Properties &new_properties, std::string const &name, MeshLib::MeshItemType const item_type, std::vector< std::size_t > const &source_ids)
std::vector< std::size_t > getSurvivingNodeIds(std::vector< std::size_t > const &node_ids)

References MeshLib::Cell, copyPropertyOfAnyValueType(), MeshLib::Properties::getPropertyVectorNames(), getSurvivingNodeIds(), MeshLib::Node, and WARN().

◆ copyProperty()

template<typename T>
bool anonymous_namespace{MeshRevision.cpp}::copyProperty ( MeshLib::Properties const & props,
MeshLib::Properties & new_properties,
std::string const & name,
MeshLib::MeshItemType const item_type,
std::vector< std::size_t > const & source_ids )

Copies the scalar property name of value type T and item type item_type, if such a property exists, to new_properties. The new property holds one value per entry of source_ids, gathered from the old property at that id. Returns false if no such property exists.

Definition at line 907 of file MeshRevision.cpp.

912{
913 if (!props.existsPropertyVector<T>(name, item_type, 1))
914 {
915 return false;
916 }
917 auto const& old_prop = *props.getPropertyVector<T>(name, item_type, 1);
918 auto* const new_prop = new_properties.createNewPropertyVector<T>(
919 name, item_type, source_ids.size(), 1);
920 if (new_prop == nullptr)
921 {
922 // MeshLib::Properties keys its property vectors by name alone, and
923 // each name of the source mesh is inserted here at most once, so this
924 // is a broken invariant rather than malformed input.
925 OGS_FATAL(
926 "Could not create the property vector '{:s}' in the revised mesh.",
927 name);
928 }
929 ranges::transform(source_ids, new_prop->begin(),
930 [&old_prop](std::size_t const i) { return old_prop[i]; });
931 return true;
932}
#define OGS_FATAL(...)
Definition Error.h:10
PropertyVector< T > * createNewPropertyVector(std::string_view name, MeshItemType mesh_item_type, std::size_t n_components=1)

References MeshLib::Properties::createNewPropertyVector(), MeshLib::Properties::existsPropertyVector(), MeshLib::Properties::getPropertyVector(), and OGS_FATAL.

Referenced by copyPropertyOfAnyValueType().

◆ copyPropertyOfAnyValueType()

template<typename... Ts>
bool anonymous_namespace{MeshRevision.cpp}::copyPropertyOfAnyValueType ( MeshLib::Properties const & props,
MeshLib::Properties & new_properties,
std::string const & name,
MeshLib::MeshItemType const item_type,
std::vector< std::size_t > const & source_ids )

Copies the scalar property name of item type item_type, trying the supported value types in turn. Returns false if no property of that name and item type exists in any of them.

Definition at line 938 of file MeshRevision.cpp.

943{
944 // The || fold stops at the first value type that exists.
945 return (
946 copyProperty<Ts>(props, new_properties, name, item_type, source_ids) ||
947 ...);
948}
bool copyProperty(MeshLib::Properties const &props, MeshLib::Properties &new_properties, std::string const &name, MeshLib::MeshItemType const item_type, std::vector< std::size_t > const &source_ids)

References copyProperty().

Referenced by copyProperties().

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

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

References MeshLib::views::ids.

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

◆ findPyramidTopNode()

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

Definition at line 548 of file MeshRevision.cpp.

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

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

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

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

◆ getSurvivingNodeIds()

std::vector< std::size_t > anonymous_namespace{MeshRevision.cpp}::getSurvivingNodeIds ( std::vector< std::size_t > const & node_ids)

Ids of the nodes surviving the collapsing, i.e. of those mapped onto themselves, in increasing order.

Definition at line 893 of file MeshRevision.cpp.

895{
896 return ranges::views::iota(std::size_t{0}, node_ids.size()) |
897 ranges::views::filter([&node_ids](std::size_t const i)
898 { return node_ids[i] == i; }) |
899 ranges::to<std::vector>;
900}

Referenced by copyProperties().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Referenced by subdivideElement().