19 static const double cTri = 2 / std::sqrt(3);
20 static const double cTet = std::sqrt(2);
21 static const double cPyr = 4 * std::sqrt(2);
27 int sz1 = numCoeff > -1 ? numCoeff : mat.
size1();
37 Msg::Warning(
"Unknown element type %d for quality computation", type);
43 for(
int i = 0; i < sz1; i++) {
44 coeff(i, 0) = std::sqrt(
pow_int(mat(i, 0), 2) +
pow_int(mat(i, 1), 2) +
46 coeff(i, 1) = std::sqrt(
pow_int(mat(i, 3), 2) +
pow_int(mat(i, 4), 2) +
50 for(
int i = 0; i < sz1; i++) {
51 coeff(i, 2) = std::sqrt(
pow_int(mat(i, 3) - mat(i, 0), 2) +
52 pow_int(mat(i, 4) - mat(i, 1), 2) +
53 pow_int(mat(i, 5) - mat(i, 2), 2));
57 for(
int i = 0; i < sz1; i++) {
58 coeff(i, 2) = std::sqrt(
pow_int(mat(i, 6), 2) +
pow_int(mat(i, 7), 2) +
63 for(
int i = 0; i < sz1; i++) {
64 coeff(i, 3) = std::sqrt(
pow_int(mat(i, 3) - mat(i, 0), 2) +
65 pow_int(mat(i, 4) - mat(i, 1), 2) +
66 pow_int(mat(i, 5) - mat(i, 2), 2));
70 for(
int i = 0; i < sz1; i++) {
71 coeff(i, 4) = std::sqrt(
pow_int(mat(i, 6) - mat(i, 0), 2) +
72 pow_int(mat(i, 7) - mat(i, 1), 2) +
73 pow_int(mat(i, 8) - mat(i, 2), 2));
74 coeff(i, 5) = std::sqrt(
pow_int(mat(i, 6) - mat(i, 3), 2) +
75 pow_int(mat(i, 7) - mat(i, 4), 2) +
76 pow_int(mat(i, 8) - mat(i, 5), 2));
81 for(
int i = 0; i < sz1; i++) {
88 coeff(i, 2) = std::sqrt(
pow_int(mat(i, 6) + mat(i, 0) + mat(i, 3), 2) +
89 pow_int(mat(i, 7) + mat(i, 1) + mat(i, 4), 2) +
90 pow_int(mat(i, 8) + mat(i, 2) + mat(i, 5), 2));
91 coeff(i, 3) = std::sqrt(
pow_int(mat(i, 6) - mat(i, 0) + mat(i, 3), 2) +
92 pow_int(mat(i, 7) - mat(i, 1) + mat(i, 4), 2) +
93 pow_int(mat(i, 8) - mat(i, 2) + mat(i, 5), 2));
94 coeff(i, 4) = std::sqrt(
pow_int(mat(i, 6) - mat(i, 0) - mat(i, 3), 2) +
95 pow_int(mat(i, 7) - mat(i, 1) - mat(i, 4), 2) +
96 pow_int(mat(i, 8) - mat(i, 2) - mat(i, 5), 2));
97 coeff(i, 5) = std::sqrt(
pow_int(mat(i, 6) + mat(i, 0) - mat(i, 3), 2) +
98 pow_int(mat(i, 7) + mat(i, 1) - mat(i, 4), 2) +
99 pow_int(mat(i, 8) + mat(i, 2) - mat(i, 5), 2));
108 int sz = std::min(det.
size(), v.
size1());
113 for(
int i = 0; i < sz; i++) { ige(i) = det(i) / v(i, 0) / v(i, 1); }
116 for(
int i = 0; i < sz; i++) {
117 ige(i) = det(i) / v(i, 0) / v(i, 1) / v(i, 2);
121 for(
int i = 0; i < sz; i++) {
122 ige(i) =
cTri * det(i) *
123 (1 / v(i, 0) / v(i, 1) + 1 / v(i, 0) / v(i, 2) +
124 1 / v(i, 1) / v(i, 2)) /
129 for(
int i = 0; i < sz; i++) {
132 (1 / v(i, 0) / v(i, 1) / v(i, 2) + 1 / v(i, 0) / v(i, 3) / v(i, 2) +
133 1 / v(i, 1) / v(i, 3) / v(i, 2)) /
138 for(
int i = 0; i < sz; i++) {
141 (1 / v(i, 0) / v(i, 5) / v(i, 1) + 1 / v(i, 0) / v(i, 5) / v(i, 2) +
142 1 / v(i, 0) / v(i, 5) / v(i, 3) + 1 / v(i, 0) / v(i, 5) / v(i, 4) +
143 1 / v(i, 1) / v(i, 4) / v(i, 0) + 1 / v(i, 1) / v(i, 4) / v(i, 2) +
144 1 / v(i, 1) / v(i, 4) / v(i, 3) + 1 / v(i, 1) / v(i, 4) / v(i, 5) +
145 1 / v(i, 2) / v(i, 3) / v(i, 0) + 1 / v(i, 2) / v(i, 3) / v(i, 1) +
146 1 / v(i, 2) / v(i, 3) / v(i, 4) + 1 / v(i, 2) / v(i, 3) / v(i, 5)) /
151 for(
int i = 0; i < sz; i++) {
154 (1 / v(i, 0) / v(i, 1) / v(i, 2) + 1 / v(i, 0) / v(i, 1) / v(i, 3) +
155 1 / v(i, 0) / v(i, 1) / v(i, 4) + 1 / v(i, 0) / v(i, 1) / v(i, 5) +
156 1 / v(i, 2) / v(i, 3) / v(i, 4) + 1 / v(i, 2) / v(i, 3) / v(i, 5) +
157 1 / v(i, 4) / v(i, 5) / v(i, 2) + 1 / v(i, 4) / v(i, 5) / v(i, 3)) /
168 int sz = std::min(det.
size(), grad.
size1());
171 for(
int i = 0; i < sz; i++) {
173 for(
int k = 0; k < grad.
size2(); ++k) { p +=
pow_int(grad(i, k), 2); }
175 icn(i) = 2 * det(i) / p;
177 icn(i) = 3 * std::pow(det(i), 2 / 3.) / p;
183 int orderSamplingPoints = 0)
185 const int type = el->
getType();
187 if(orderSamplingPoints < 1) {
189 const int jacOrder = order * el->
getDim();
208 fsDet =
FuncSpaceData(el,
false, jacOrder, jacOrder - 3,
false);
211 Msg::Info(
"Quality measure not implemented for %s",
217 const int type = el->
getType();
228 fsGrad =
FuncSpaceData(el,
true, 1, orderSamplingPoints - 1,
false);
229 fsDet =
FuncSpaceData(el,
true, 1, orderSamplingPoints - 1,
false);
232 Msg::Info(
"Quality measure not implemented for %s",
248 Msg::Warning(
"Jacobian function space not implemented for %s",
266 std::vector<_coeffData *> domains(1,
new _coeffDataJac(bez));
270 min = std::numeric_limits<double>::max();
272 for(std::size_t i = 0; i < domains.size(); ++i) {
273 min = std::min(min, domains[i]->minB());
274 max = std::max(max, domains[i]->maxB());
275 domains[i]->deleteBezierCoeff();
288 if((jmin <= 0 && jmax >= 0) || (jmax < 0 && !reversedOk))
return 0;
308 if(coeffDetLag(0) < 0) coeffDetLag.
scale(-1);
313 static_cast<std::size_t
>(coeffMatLag.
size1()) *
314 static_cast<std::size_t
>(coeffMatLag.
size2()));
319 std::vector<_coeffData *> domains;
334 if((jmin <= 0 && jmax >= 0) || (jmax < 0 && !reversedOk))
return 0;
354 if(coeffDetLag(0) < 0) coeffDetLag.
scale(-1);
359 static_cast<std::size_t
>(coeffMatLag.
size1()) *
360 static_cast<std::size_t
>(coeffMatLag.
size2()));
365 std::vector<_coeffData *> domains;
378 min = std::numeric_limits<double>::max();
380 for(
int i = 0; i < jac.
size(); ++i) {
381 min = std::min(min, jac(i));
382 max = std::max(max, jac(i));
391 min = std::numeric_limits<double>::max();
393 for(
int i = 0; i < ige.
size(); ++i) {
394 min = std::min(min, ige(i));
395 max = std::max(max, ige(i));
404 min = std::numeric_limits<double>::max();
406 for(
int i = 0; i < icn.
size(); ++i) {
407 min = std::min(min, icn(i));
408 max = std::max(max, icn(i));
453 const int type = el->
getType();
512 double tol = std::max(std::abs(
minL), std::abs(
maxL)) * 1e-3;
513 return (minL <= 0 || _minB > 0) && (
maxL >= 0 ||
_maxB < 0) &&
520 std::vector<bezierCoeff *> sub;
524 for(std::size_t i = 0; i < sub.size(); i++) {
534 :
_coeffData(), _coeffDet(det), _coeffMat(mat), _type(type)
549 static const double tolmin = 1e-3;
550 static const double tolmax = 1e-2;
551 const double tol = tolmin + (tolmax - tolmin) * std::max(
_minB, .0);
557 std::vector<bezierCoeff *> subD;
558 std::vector<bezierCoeff *> subM;
563 for(std::size_t i = 0; i < subD.size(); i++) {
585 min = std::numeric_limits<double>::max();
587 for(
int i = 0; i < ige.
size(); ++i) {
588 min = std::min(min, ige(i));
589 max = std::max(max, ige(i));
603 for(
int i = 0; i < det.
size(); ++i) {
604 if(det(i) < 0) {
return 0; }
619 raiser->
computeCoeff(prox[0], prox[1], coeffDenominator);
623 raiser->
computeCoeff(prox[0], prox[1], coeffDenominator);
625 raiser->
computeCoeff(prox[0], prox[2], coeffDenominator);
627 raiser->
computeCoeff(prox[1], prox[2], coeffDenominator);
637 return cTri * result / 3;
640 raiser->
computeCoeff(prox[0], prox[1], prox[2], coeffDenominator);
644 raiser->
computeCoeff(prox[0], prox[1], prox[2], coeffDenominator);
646 raiser->
computeCoeff(prox[0], prox[3], prox[2], coeffDenominator);
648 raiser->
computeCoeff(prox[1], prox[3], prox[2], coeffDenominator);
651 return cTri * result / 3;
656 thirdTerm.
axpy(prox[2]);
657 thirdTerm.
axpy(prox[3]);
658 thirdTerm.
axpy(prox[4]);
659 raiser->
computeCoeff(prox[0], prox[5], thirdTerm, coeffNum1);
661 thirdTerm.
axpy(prox[2]);
662 thirdTerm.
axpy(prox[3]);
663 thirdTerm.
axpy(prox[5]);
667 thirdTerm.
axpy(prox[1]);
668 thirdTerm.
axpy(prox[4]);
669 thirdTerm.
axpy(prox[5]);
674 raiser->
computeCoeff(prox[0], prox[1], prox[2], coeffDen1);
675 raiser->
computeCoeff(prox[3], prox[4], prox[5], coeffDen2);
680 raiserBis->
computeCoeff(coeffNum1, det, coeffNumerator);
681 raiserBis->
computeCoeff(coeffDen1, coeffDen2, coeffDenominator);
684 return cTet * result / 12;
690 thirdTerm.
axpy(prox[3]);
691 thirdTerm.
axpy(prox[4]);
692 thirdTerm.
axpy(prox[5]);
693 raiser->
computeCoeff(prox[0], prox[1], thirdTerm, coeffNum1);
695 thirdTerm.
axpy(prox[5]);
699 thirdTerm.
axpy(prox[3]);
704 raiser->
computeCoeff(prox[0], prox[1], prox[2], coeffDen1);
705 raiser->
computeCoeff(prox[3], prox[4], prox[5], coeffDen2);
710 raiserBis->
computeCoeff(coeffNum1, det, coeffNumerator);
711 raiserBis->
computeCoeff(coeffDen1, coeffDen2, coeffDenominator);
714 return cPyr * result / 8;
717 default:
Msg::Info(
"Unknown element type %d for IGE",
_type);
return -1;
724 :
_coeffData(), _coeffDet(det), _coeffMat(mat), _dim(dim)
739 static const double tolmin = 1e-3;
740 static const double tolmax = 1e-2;
741 const double tol = tolmin + (tolmax - tolmin) * std::max(
_minB, .0);
747 std::vector<bezierCoeff *> subD;
748 std::vector<bezierCoeff *> subM;
753 for(std::size_t i = 0; i < subD.size(); i++) {
772 min = std::numeric_limits<double>::max();
774 for(
int i = 0; i < icn.
size(); i++) {
775 min = std::min(min, icn(i));
776 max = std::max(max, icn(i));
789 for(
int i = 0; i < det.
size(); ++i) {
790 if(det(i) < 0) {
return 0; }
798 for(
int k = 0; k < mat.
size2(); ++k) {
802 if(k == 0) coeffDenominator.
resize(tmp.
size());
803 coeffDenominator.
axpy(tmp, 1);
815 for(
int i = 0; i < mat.
size1(); ++i) {
816 for(
int k = 0; k < mat.
size2(); ++k) { P(i) += mat(i, k) * mat(i, k); }
817 P(i) = std::sqrt(P(i));
822 const double boundFraction =
825 return 3 * std::pow(boundFraction * boundFraction, 1. / 3);
829 template <
typename Comp>
831 double &minL,
double &maxL,
bool debug)
833 std::vector<_coeffData *> subs;
834 make_heap(domains.begin(), domains.end(), Comp());
836 const int max_subdivision = 1000;
837 while(!domains[0]->boundsOk(minL, maxL) && k + 1 < max_subdivision) {
839 pop_heap(domains.begin(), domains.end(), Comp());
845 for(std::size_t i = 0; i < subs.size(); i++) {
846 minL = std::min(minL, subs[i]->minL());
847 maxL = std::max(maxL, subs[i]->maxL());
848 domains.push_back(subs[i]);
849 push_heap(domains.begin(), domains.end(), Comp());
853 if(debug) { std::cout <<
"Number of subdivisions: " << k << std::endl; }
854 else if(k == max_subdivision) {
855 Msg::Error(
"Max subdivision (%d) (size domains %d)", max_subdivision,
863 if(domains.empty()) {
864 Msg::Warning(
"Empty vector in Bezier subdivision, nothing to do");
867 double minL = domains[0]->minL();
868 double maxL = domains[0]->maxL();
869 for(std::size_t i = 1; i < domains.size(); ++i) {
870 minL = std::min(minL, domains[i]->minL());
871 maxL = std::max(maxL, domains[i]->maxL());
874 _subdivideDomainsMinOrMax<_lessMinB>(domains, minL, maxL, debug);
876 _subdivideDomainsMinOrMax<_lessMaxB>(domains, minL, maxL, debug);
881 double minB = domains[0]->minB();
882 double minL = domains[0]->minL();
883 domains[0]->deleteBezierCoeff();
885 for(std::size_t i = 1; i < domains.size(); ++i) {
886 minB = std::min(minB, domains[i]->minB());
887 minL = std::min(minL, domains[i]->minL());
888 domains[i]->deleteBezierCoeff();
891 double fact = .5 * (minB + minL);
900 return fact * minL + (1 - fact) * minB;
905 bool lower,
bool positiveDenom)
907 if(numerator.
size() != denominator.
size()) {
908 Msg::Error(
"In order to compute a bound on a rational function, I need "
909 "vectors of the same size! (%d vs %d)",
910 numerator.
size(), denominator.
size());
915 const double inf = std::numeric_limits<double>::max();
916 double upperBound = inf;
917 double lowerBound = -inf;
919 if(!positiveDenom) lower = !lower;
923 for(
int i = 0; i < numerator.
size(); ++i) {
924 if(denominator(i) == 0) {
925 if(numerator(i) < 0)
return -inf;
927 else if(denominator(i) > 0) {
928 upperBound = std::min(upperBound, numerator(i) / denominator(i));
931 lowerBound = std::max(lowerBound, numerator(i) / denominator(i));
934 if(lowerBound > upperBound)
941 for(
int i = 0; i < numerator.
size(); ++i) {
942 if(denominator(i) == 0) {
943 if(numerator(i) > 0)
return inf;
945 else if(denominator(i) > 0) {
946 lowerBound = std::max(lowerBound, numerator(i) / denominator(i));
949 upperBound = std::min(upperBound, numerator(i) / denominator(i));
952 if(lowerBound > upperBound)
962 std::set<GEntity *, GEntityPtrFullLessThan> entities;
964 entities.insert(*it);
966 entities.insert(*it);
968 entities.insert(*it);
970 for(
auto it = entities.begin(); it != entities.end(); ++it) {
971 unsigned num = (*it)->getNumMeshElements();
972 for(
unsigned i = 0; i < num; ++i) {
973 MElement *el = (*it)->getMeshElement(i);
981 static int orderSampling = 50;
982 static double tol = 1e-5;
983 double minSampled, maxSampled, minAlgo, maxAlgo;
984 std::cout << std::endl;
985 std::cout <<
"Element #" << el->
getNum() <<
" (type: " << el->
getType();
986 std::cout <<
", " << el->
getTypeForMSH() <<
")" << std::endl;
991 std::cout <<
"JAC sampled: " << minSampled <<
" " << maxSampled;
992 std::cout <<
" v.s. computed: " << minAlgo <<
" " << maxAlgo << std::endl;
993 if(minSampled < minAlgo * (1 - tol) || maxSampled > maxAlgo * (1 + tol)) {
994 std::cout <<
"ERROR sampled measure outside the bounds" << std::endl;
998 if(minAlgo <= 0 && maxAlgo >= 0) {
999 std::cout <<
"GOOD (Invalid)" << std::endl;
1005 std::cout <<
"IGE sampled: " << minSampled <<
" " << maxSampled;
1006 std::cout <<
" v.s. computed: " << minAlgo <<
" -" << std::endl;
1007 if(minSampled < minAlgo * (1 - tol)) {
1008 std::cout <<
"ERROR sampled measure smaller than the bound" << std::endl;
1014 std::cout <<
"ICN sampled: " << minSampled <<
" " << maxSampled;
1015 std::cout <<
" v.s. computed: " << minAlgo <<
" -" << std::endl;
1016 if(minSampled < minAlgo * (1 - tol)) {
1017 std::cout <<
"ERROR sampled measure smaller than the bound" << std::endl;
1020 std::cout <<
"GOOD" << std::endl;