8#include <kernel/util/math.hpp>
9#include <kernel/util/tiny_algebra.hpp>
27 template<
typename Shape_>
37 return String(
"UNDEFINED");
58 template<
typename IdxType_,
typename VtxType_>
59 static typename VtxType_::CoordType
compute(
const IdxType_& idx,
const VtxType_& vtx);
69 return String(
"max( h(T) / vol(T)^1/2):");
72 template<
typename IdxType_,
typename VtxType_>
73 static typename VtxType_::CoordType angle(
const IdxType_& idx,
const VtxType_& vtx,
74 typename VtxType_::CoordType* cell_worst_angle =
nullptr)
77 typedef typename VtxType_::CoordType CoordType;
79 CoordType min_angle(Math::huge<CoordType>());
80 CoordType max_angle(0);
81 for(
Index cell(0); cell < idx.get_num_entities(); ++cell)
87 auto v1 = vtx[i1] - vtx[i0];
88 auto v2 = vtx[i2] - vtx[i0];
89 auto v3 = vtx[i2] - vtx[i1];
91 CoordType n1(v1.norm_euclid());
92 CoordType n2(v2.norm_euclid());
93 CoordType n3(v3.norm_euclid());
104 if(cell_worst_angle !=
nullptr)
106 cell_worst_angle[cell] = CoordType(360)/(CoordType(2)*Math::pi<CoordType>())
110 min_angle =
Math::min(my_min_angle, min_angle);
111 max_angle =
Math::max(my_max_angle, max_angle);
114 CoordType worst_angle(
Math::min(min_angle,
Math::abs(Math::pi<CoordType>() - max_angle)));
116 return worst_angle*(CoordType(360))/(CoordType(2)*Math::pi<CoordType>());
119 template<
typename IdxType_,
typename VtxType_>
120 static void compute(
typename VtxType_::CoordType& qual_min,
typename VtxType_::CoordType& qual_sum,
121 const IdxType_& idx,
const VtxType_& vtx,
typename VtxType_::CoordType* cell_qual =
nullptr)
123 typedef typename VtxType_::CoordType CoordType;
125 CoordType rho_min(Math::huge<CoordType>());
126 CoordType rho_sum(0);
130 Tiny::Matrix<CoordType, VtxType_::num_coords, VtxType_::num_coords> A(CoordType(0));
132 for(
Index cell(0); cell < idx.get_num_entities(); ++cell)
140 A[0] = vtx[i1] - vtx[i0];
141 A[1] = vtx[i2] - vtx[i0];
143 vol = A.vol()/CoordType(2);
145 CoordType h0((vtx[i2] - vtx[i0]).norm_euclid());
148 CoordType h1(A[1].norm_euclid());
151 CoordType h2(A[0].norm_euclid());
156 if(cell_qual !=
nullptr)
173 struct MeshQualityHeuristic<Shape::Simplex<3>>
178 return String(
"max( h(T) / vol(T)^1/2):");
181 template<
typename IdxType_,
typename VtxType_>
182 static typename VtxType_::CoordType angle(
const IdxType_& idx,
const VtxType_& vtx,
183 typename VtxType_::CoordType* cell_worst_angle =
nullptr)
186 typedef typename VtxType_::CoordType CoordType;
188 Tiny::Matrix<CoordType, 6, VtxType_::num_coords> E(CoordType(0));
189 CoordType edgelengths[6];
192 CoordType min_angle(Math::huge<CoordType>());
193 CoordType max_angle(0);
194 for(
Index cell(0); cell < idx.get_num_entities(); ++cell)
197 CoordType my_min_angle(Math::huge<CoordType>());
198 CoordType my_max_angle(0);
205 E[0] = vtx[i1] - vtx[i0];
206 E[1] = vtx[i2] - vtx[i0];
207 E[2] = vtx[i3] - vtx[i0];
208 E[3] = vtx[i2] - vtx[i1];
209 E[4] = vtx[i3] - vtx[i1];
210 E[5] = vtx[i3] - vtx[i2];
212 for(
int i(0); i < 6; ++i)
214 edgelengths[i] = E[i].norm_euclid();
224 for(
int i(0); i < 6; ++i)
226 my_min_angle =
Math::min(my_min_angle, angle[i]);
227 my_max_angle =
Math::max(my_max_angle, angle[i]);
230 min_angle =
Math::min(my_min_angle, min_angle);
231 max_angle =
Math::max(my_max_angle, max_angle);
233 if(cell_worst_angle !=
nullptr)
235 cell_worst_angle[cell] = CoordType(360)/(CoordType(2)*Math::pi<CoordType>())
241 CoordType worst_angle(
Math::min(min_angle,
Math::abs(Math::pi<CoordType>() - max_angle)));
243 return worst_angle*(CoordType(360))/(CoordType(2)*Math::pi<CoordType>());
246 template<
typename IdxType_,
typename VtxType_>
247 static void compute(
typename VtxType_::CoordType& qual_min,
typename VtxType_::CoordType& qual_sum,
248 const IdxType_& idx,
const VtxType_& vtx,
typename VtxType_::CoordType* cell_qual =
nullptr)
250 typedef typename VtxType_::CoordType CoordType;
251 const CoordType vol_ref(
Math::sqrt(CoordType(3))/CoordType(4)*
Math::sqrt(CoordType(6))/CoordType(3*3));
252 const CoordType fac(
Math::pow(vol_ref, -CoordType(1)/CoordType(3)));
254 CoordType rho_min(Math::huge<CoordType>());
255 CoordType rho_sum(0);
259 Tiny::Matrix<CoordType, VtxType_::num_coords, VtxType_::num_coords> A(CoordType(0));
260 Tiny::Matrix<CoordType, 6, VtxType_::num_coords> E(CoordType(0));
261 CoordType edgelengths[6];
263 for(
Index cell(0); cell < idx.get_num_entities(); ++cell)
272 A[0] = vtx[i1] - vtx[i0];
273 A[1] = vtx[i2] - vtx[i0];
274 A[2] = vtx[i3] - vtx[i0];
276 vol = A.det()/CoordType(6);
278 E[0] = vtx[i1] - vtx[i0];
279 E[1] = vtx[i2] - vtx[i0];
280 E[2] = vtx[i3] - vtx[i0];
281 E[3] = vtx[i2] - vtx[i1];
282 E[4] = vtx[i3] - vtx[i1];
283 E[5] = vtx[i3] - vtx[i2];
285 for(
int i(0); i < 6; ++i)
287 edgelengths[i] = E[i].norm_euclid();
291 CoordType my_rho(
Math::pow(vol, CoordType(1)/CoordType(3))/diam);
293 if(cell_qual !=
nullptr)
295 cell_qual[cell] = fac*my_rho;
303 qual_min = fac*rho_min;
304 qual_sum = fac*rho_sum;
310 struct MeshQualityHeuristic<Shape::Hypercube<2>>
315 return String(
"h_min/h_max*sqrt(1 - cos(alpha_min)):");
318 template<
typename IdxType_,
typename VtxType_>
319 static typename VtxType_::CoordType angle(
const IdxType_& idx,
const VtxType_& vtx,
320 typename VtxType_::CoordType* cell_worst_angle =
nullptr)
323 typedef typename VtxType_::CoordType CoordType;
325 CoordType min_angle(Math::huge<CoordType>());
326 CoordType max_angle(0);
327 for(
Index cell(0); cell < idx.get_num_entities(); ++cell)
330 CoordType my_min_angle(Math::huge<CoordType>());
331 CoordType my_max_angle(0);
338 auto v0 = vtx[i1] - vtx[i0];
339 auto v1 = vtx[i3] - vtx[i2];
340 auto v2 = vtx[i2] - vtx[i0];
341 auto v3 = vtx[i3] - vtx[i1];
343 CoordType h0(v0.norm_euclid());
344 CoordType h1(v1.norm_euclid());
345 CoordType h2(v2.norm_euclid());
346 CoordType h3(v3.norm_euclid());
364 min_angle =
Math::min(my_min_angle, min_angle);
365 max_angle =
Math::max(my_max_angle, max_angle);
367 if(cell_worst_angle !=
nullptr)
369 cell_worst_angle[cell] = CoordType(360)/(CoordType(2)*Math::pi<CoordType>())
376 CoordType worst_angle(
Math::min(min_angle,
Math::abs(Math::pi<CoordType>() - max_angle)));
378 return worst_angle*CoordType(360)/(CoordType(2)*Math::pi<CoordType>());
381 template<
typename IdxType_,
typename VtxType_>
382 static void compute(
typename VtxType_::CoordType& qual_min,
typename VtxType_::CoordType& qual_sum,
383 const IdxType_& idx,
const VtxType_& vtx,
typename VtxType_::CoordType* cell_qual =
nullptr)
386 typedef typename VtxType_::CoordType CoordType;
388 qual_min = Math::huge<CoordType>();
389 qual_sum = CoordType(0);
391 for(
Index cell(0); cell < idx.get_num_entities(); ++cell)
394 CoordType angle(Math::huge<CoordType>());
401 auto v0 = vtx[i1] - vtx[i0];
402 auto v1 = vtx[i3] - vtx[i2];
403 auto v2 = vtx[i2] - vtx[i0];
404 auto v3 = vtx[i3] - vtx[i1];
406 CoordType h_min(Math::huge<CoordType>());
407 CoordType h_max(Math::eps<CoordType>());
409 CoordType h0(v0.norm_euclid());
413 CoordType h1(v1.norm_euclid());
417 CoordType h2(v2.norm_euclid());
421 CoordType h3(v3.norm_euclid());
443 CoordType my_qual(h_min/h_max*
Math::sqrt(CoordType(1) - gamma));
445 if(cell_qual !=
nullptr)
447 cell_qual[cell] = my_qual;
457 struct MeshQualityHeuristic<Shape::Hypercube<3>>
463 return String(
"h_min*min(det( nabla Phi))/(h_max*max(det nabla Phi)):");
466 template<
typename IdxType_,
typename VtxType_>
467 static typename VtxType_::CoordType angle(
const IdxType_& idx,
const VtxType_& vtx,
468 typename VtxType_::CoordType* cell_worst_angle =
nullptr)
471 typedef typename VtxType_::CoordType CoordType;
473 Tiny::Matrix<CoordType, 12, VtxType_::num_coords> E(CoordType(0));
474 CoordType edgelengths[12];
477 CoordType min_angle(Math::huge<CoordType>());
478 CoordType max_angle(0);
479 for(
Index cell(0); cell < idx.get_num_entities(); ++cell)
482 CoordType my_min_angle(Math::huge<CoordType>());
483 CoordType my_max_angle(0);
485 E[0] = vtx[idx(cell,
Index(1))] - vtx[idx(cell,
Index(0))];
486 E[1] = vtx[idx(cell,
Index(3))] - vtx[idx(cell,
Index(2))];
487 E[2] = vtx[idx(cell,
Index(5))] - vtx[idx(cell,
Index(4))];
488 E[3] = vtx[idx(cell,
Index(7))] - vtx[idx(cell,
Index(6))];
489 E[4] = vtx[idx(cell,
Index(2))] - vtx[idx(cell,
Index(0))];
490 E[5] = vtx[idx(cell,
Index(3))] - vtx[idx(cell,
Index(1))];
491 E[6] = vtx[idx(cell,
Index(6))] - vtx[idx(cell,
Index(4))];
492 E[7] = vtx[idx(cell,
Index(7))] - vtx[idx(cell,
Index(5))];
493 E[8] = vtx[idx(cell,
Index(4))] - vtx[idx(cell,
Index(0))];
494 E[9] = vtx[idx(cell,
Index(5))] - vtx[idx(cell,
Index(1))];
495 E[10] = vtx[idx(cell,
Index(6))] - vtx[idx(cell,
Index(2))];
496 E[11] = vtx[idx(cell,
Index(7))] - vtx[idx(cell,
Index(3))];
498 for(
int i(0); i < 12; ++i)
500 edgelengths[i] = E[i].norm_euclid();
543 for(
int i(0); i < 24; ++i)
545 my_min_angle =
Math::min(my_min_angle,angle[i]);
546 my_max_angle =
Math::max(my_max_angle,angle[i]);
549 min_angle =
Math::min(my_min_angle, min_angle);
550 max_angle =
Math::max(my_max_angle, max_angle);
552 if(cell_worst_angle !=
nullptr)
554 cell_worst_angle[cell] = CoordType(360)/(CoordType(2)*Math::pi<CoordType>())
560 CoordType worst_angle(
Math::min(min_angle,
Math::abs(Math::pi<CoordType>() - max_angle)));
562 return worst_angle*(CoordType(360))/(CoordType(2)*Math::pi<CoordType>());
565 template<
typename IdxType_,
typename VtxType_>
566 static void compute(
typename VtxType_::CoordType& qual_min,
typename VtxType_::CoordType& qual_sum,
567 const IdxType_& idx,
const VtxType_& vtx,
typename VtxType_::CoordType* cell_qual =
nullptr)
570 typedef typename VtxType_::CoordType CoordType;
571 typedef typename VtxType_::VertexType DomainPointType;
573 static constexpr int num_coords = VtxType_::num_coords;
575 typedef Tiny::Matrix<CoordType, 3, num_coords> JacobiMatrixType;
577 CoordType coeff[num_coords][8];
578 DomainPointType xq(0);
580 Tiny::Matrix<CoordType, 12, VtxType_::num_coords> E(CoordType(0));
581 CoordType edgelengths[12];
583 qual_min = Math::huge<CoordType>();
584 qual_sum = CoordType(0);
586 for(
Index cell(0); cell < idx.get_num_entities(); ++cell)
588 CoordType h_min(Math::huge<CoordType>());
591 CoordType jac_det_min(Math::huge<CoordType>());
592 CoordType jac_det_max(0);
594 const DomainPointType& v0 = vtx[idx(cell, 0)];
595 const DomainPointType& v1 = vtx[idx(cell, 1)];
596 const DomainPointType& v2 = vtx[idx(cell, 2)];
597 const DomainPointType& v3 = vtx[idx(cell, 3)];
598 const DomainPointType& v4 = vtx[idx(cell, 4)];
599 const DomainPointType& v5 = vtx[idx(cell, 5)];
600 const DomainPointType& v6 = vtx[idx(cell, 6)];
601 const DomainPointType& v7 = vtx[idx(cell, 7)];
616 for(
int i(0); i < 12; ++i)
618 edgelengths[i] = E[i].norm_euclid();
619 h_min =
Math::min(edgelengths[i], h_min);
620 h_max =
Math::max(edgelengths[i], h_max);
626 for(
int i(0); i < num_coords; ++i)
628 coeff[i][0] = CoordType(0.125) * CoordType( + v0[i] + v1[i] + v2[i] + v3[i] + v4[i] + v5[i] + v6[i] + v7[i]);
629 coeff[i][1] = CoordType(0.125) * CoordType( - v0[i] + v1[i] - v2[i] + v3[i] - v4[i] + v5[i] - v6[i] + v7[i]);
630 coeff[i][2] = CoordType(0.125) * CoordType( - v0[i] - v1[i] + v2[i] + v3[i] - v4[i] - v5[i] + v6[i] + v7[i]);
631 coeff[i][3] = CoordType(0.125) * CoordType( - v0[i] - v1[i] - v2[i] - v3[i] + v4[i] + v5[i] + v6[i] + v7[i]);
632 coeff[i][4] = CoordType(0.125) * CoordType( + v0[i] - v1[i] - v2[i] + v3[i] + v4[i] - v5[i] - v6[i] + v7[i]);
633 coeff[i][5] = CoordType(0.125) * CoordType( + v0[i] - v1[i] + v2[i] - v3[i] - v4[i] + v5[i] - v6[i] + v7[i]);
634 coeff[i][6] = CoordType(0.125) * CoordType( + v0[i] + v1[i] - v2[i] - v3[i] - v4[i] - v5[i] + v6[i] + v7[i]);
635 coeff[i][7] = CoordType(0.125) * CoordType( - v0[i] + v1[i] + v2[i] - v3[i] + v4[i] - v5[i] - v6[i] + v7[i]);
638 for(
int i(0); i < 8; ++i)
641 for(
int j(0); j < 3; ++j)
643 xq(j) = (CoordType(((i >> j) & 1) << 1) - CoordType(1)) * CoordType(1);
646 for(
int j(0); j <
jac_mat.m; ++j)
648 jac_mat(j,0) = coeff[j][1] + xq[1] * coeff[j][4] + xq[2] * (coeff[j][5] + xq[1] * coeff[j][7]);
649 jac_mat(j,1) = coeff[j][2] + xq[0] * coeff[j][4] + xq[2] * (coeff[j][6] + xq[0] * coeff[j][7]);
650 jac_mat(j,2) = coeff[j][3] + xq[0] * coeff[j][5] + xq[1] * (coeff[j][6] + xq[0] * coeff[j][7]);
659 CoordType my_qual(h_min*jac_det_min/(h_max*jac_det_max));
661 if(cell_qual !=
nullptr)
663 cell_qual[cell] = my_qual;
#define ASSERT(expr)
Debug-Assertion macro definition.
String class implementation.
T_ sqrt(T_ x)
Returns the square-root of a value.
T_ abs(T_ x)
Returns the absolute value.
T_ acos(T_ x)
Returns the arccosine of a value.
T_ pow(T_ x, T_ y)
Returns x raised to the power of y.
T_ min(T_ a, T_ b)
Returns the minimum of two values.
T_ max(T_ a, T_ b)
Returns the maximum of two values.
CUDA_HOST_DEVICE T_ dot(const T_ &a, const T_ &b)
Computes the dot-product of two scalars.
std::uint64_t Index
Index data type.
@ jac_mat
specifies whether the trafo should supply jacobian matrices
@ jac_det
specifies whether the trafo should supply jacobian determinants
Helper class for computing heuristic mesh quality.
static String description()
Returns a descriptive String.
static VtxType_::CoordType compute(const IdxType_ &idx, const VtxType_ &vtx)
Computes minimum cell quality.