OGS
AngleSkewMetric.cpp
Go to the documentation of this file.
1 
15 #include "AngleSkewMetric.h"
16 
17 #include <boost/math/constants/constants.hpp>
18 #include <cmath>
19 
20 #include "MathLib/MathTools.h"
21 #include "MeshLib/Node.h"
22 
23 using namespace boost::math::double_constants;
24 
25 namespace MeshLib
26 {
27 namespace
28 {
29 template <unsigned long N>
30 std::tuple<double, double> getMinMaxAngle(
31  std::array<MeshLib::Node, N> const& nodes)
32 {
33  double min_angle(two_pi);
34  double max_angle(0.0);
35 
36  for (decltype(N) i = 0; i < N; ++i)
37  {
38  const double angle(MathLib::getAngle(nodes[i], nodes[(i + 1) % N],
39  nodes[(i + 2) % N]));
40  min_angle = std::min(angle, min_angle);
41  max_angle = std::max(angle, max_angle);
42  }
43  return {min_angle, max_angle};
44 }
45 
46 double checkTriangle(Element const& elem)
47 {
48  std::array const nodes = {*elem.getNode(0), *elem.getNode(1),
49  *elem.getNode(2)};
50  auto const& [min_angle, max_angle] = getMinMaxAngle(nodes);
51  return std::max((max_angle - third_pi) / two_thirds_pi,
52  (third_pi - min_angle) / third_pi);
53 }
54 
55 double checkQuad(Element const& elem)
56 {
57  std::array const nodes = {*elem.getNode(0), *elem.getNode(1),
58  *elem.getNode(2), *elem.getNode(3)};
59  auto const& [min_angle, max_angle] = getMinMaxAngle(nodes);
60 
61  return std::max((max_angle - half_pi) / half_pi,
62  (half_pi - min_angle) / half_pi);
63 }
64 
65 double checkTetrahedron(Element const& elem)
66 {
67  std::array<double, 4> min;
68  std::array<double, 4> max;
69  for (auto face_number = 0; face_number < 4; ++face_number)
70  {
71  std::unique_ptr<Element const> face{elem.getFace(face_number)};
72  std::array const nodes = {*face->getNode(0), *face->getNode(1),
73  *face->getNode(2)};
74  std::tie(min[face_number], max[face_number]) = getMinMaxAngle(nodes);
75  }
76 
77  double const min_angle = *std::min_element(min.begin(), min.end());
78  double const max_angle = *std::max_element(max.begin(), max.end());
79 
80  return std::max((max_angle - third_pi) / two_thirds_pi,
81  (third_pi - min_angle) / third_pi);
82 }
83 
84 double checkHexahedron(Element const& elem)
85 {
86  std::array<double, 6> min;
87  std::array<double, 6> max;
88  for (auto face_number = 0; face_number < 6; ++face_number)
89  {
90  std::unique_ptr<Element const> face{elem.getFace(face_number)};
91  std::array const nodes = {*face->getNode(0), *face->getNode(1),
92  *face->getNode(2), *face->getNode(3)};
93  std::tie(min[face_number], max[face_number]) = getMinMaxAngle(nodes);
94  }
95 
96  double const min_angle = *std::min_element(min.begin(), min.end());
97  double const max_angle = *std::max_element(max.begin(), max.end());
98 
99  return std::max((max_angle - half_pi) / half_pi,
100  (half_pi - min_angle) / half_pi);
101 }
102 
103 double checkPrism(Element const& elem)
104 {
105  // face 0: triangle (0,1,2)
106  std::unique_ptr<Element const> f0{elem.getFace(0)};
107  std::array const nodes_f0 = {*f0->getNode(0), *f0->getNode(1),
108  *f0->getNode(2)};
109  auto const& [min_angle_tri0, max_angle_tri0] = getMinMaxAngle(nodes_f0);
110 
111  // face 4: triangle (3,4,5)
112  std::unique_ptr<Element const> f4{elem.getFace(4)};
113  std::array const nodes_f4 = {*f4->getNode(0), *f4->getNode(1),
114  *f4->getNode(2)};
115  auto const& [min_angle_tri1, max_angle_tri1] = getMinMaxAngle(nodes_f4);
116 
117  auto const min_angle_tri = std::min(min_angle_tri0, min_angle_tri1);
118  auto const max_angle_tri = std::max(max_angle_tri0, max_angle_tri1);
119 
120  double const tri_criterion(
121  std::max((max_angle_tri - third_pi) / two_thirds_pi,
122  (third_pi - min_angle_tri) / third_pi));
123 
124  std::array<double, 3> min;
125  std::array<double, 3> max;
126  for (int i = 1; i < 4; ++i)
127  {
128  std::unique_ptr<Element const> f{elem.getFace(i)};
129  std::array const nodes = {*f->getNode(0), *f->getNode(1),
130  *f->getNode(2), *f->getNode(3)};
131  std::tie(min[i - 1], max[i - 1]) = getMinMaxAngle(nodes);
132  }
133 
134  double const min_angle_quad = *std::min_element(min.begin(), min.end());
135  double const max_angle_quad = *std::max_element(max.begin(), max.end());
136 
137  double const quad_criterion(std::max((max_angle_quad - half_pi) / half_pi,
138  (half_pi - min_angle_quad) / half_pi));
139 
140  return std::min(tri_criterion, quad_criterion);
141 }
142 
143 } // end unnamed namespace
144 
145 void AngleSkewMetric::calculateQuality()
146 {
147  for (auto const e : _mesh.getElements())
148  {
149  switch (e->getGeomType())
150  {
151  case MeshElemType::LINE:
152  _element_quality_metric[e->getID()] = -1.0;
153  break;
154  case MeshElemType::TRIANGLE:
155  _element_quality_metric[e->getID()] = checkTriangle(*e);
156  break;
157  case MeshElemType::QUAD:
158  _element_quality_metric[e->getID()] = checkQuad(*e);
159  break;
160  case MeshElemType::TETRAHEDRON:
161  _element_quality_metric[e->getID()] = checkTetrahedron(*e);
162  break;
163  case MeshElemType::HEXAHEDRON:
164  _element_quality_metric[e->getID()] = checkHexahedron(*e);
165  break;
166  case MeshElemType::PRISM:
167  _element_quality_metric[e->getID()] = checkPrism(*e);
168  break;
169  default:
170  break;
171  }
172  }
173 }
174 
175 } // end namespace MeshLib
Definition of the AngleSkewMetric class.
Definition of the Node class.
virtual const Node * getNode(unsigned idx) const =0
virtual const Element * getFace(unsigned i) const =0
Returns the i-th face of the element.
double getAngle(Point3d const &p0, Point3d const &p1, Point3d const &p2)
Definition: MathTools.cpp:42
std::tuple< double, double > getMinMaxAngle(std::array< MeshLib::Node, N > const &nodes)