diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp index f863409c310229baed5b517f2ec23c8290efebe0..6d7b81afd25a9343bbbf7bccfe584346fc268804 100644 --- a/Geo/MElement.cpp +++ b/Geo/MElement.cpp @@ -337,8 +337,8 @@ void MElement::signedInvCondNumRange(double &iCNMin, double &iCNMax, GEntity *ge void MElement::signedInvGradErrorRange(double &minSIGE, double &maxSIGE, GEntity *ge) { - minSIGE = jacobianBasedQuality::minSampledICNMeasure(this, getPolynomialOrder()); - maxSIGE = 1; + jacobianBasedQuality::sampleIGEMeasure(this, getPolynomialOrder(), + minSIGE, maxSIGE); return; } diff --git a/Mesh/qualityMeasuresJacobian.cpp b/Mesh/qualityMeasuresJacobian.cpp index 06b5307b1bac321464f64e4db374414562a0c6c1..fa960a6ed24c140208f4e2e5020e2b4bf8e5a7c1 100644 --- a/Mesh/qualityMeasuresJacobian.cpp +++ b/Mesh/qualityMeasuresJacobian.cpp @@ -16,11 +16,156 @@ #include "pointsGenerators.h" #include "OS.h" -namespace jacobianBasedQuality { +static const double cTri = 2/std::sqrt(3); +static const double cTet = std::sqrt(2); +static const double cPyr = std::sqrt(2); + +static void computeCoeffLengthVectors_(const fullMatrix<double> &mat, + fullMatrix<double> &coeff, + int type, int numCoeff = -1) +{ + int sz1 = numCoeff > -1 ? numCoeff : mat.size1(); + + switch (type) { + case TYPE_QUA: coeff.resize(sz1, 2); break; + case TYPE_TRI: coeff.resize(sz1, 3); break; + case TYPE_HEX: coeff.resize(sz1, 3); break; + case TYPE_PRI: coeff.resize(sz1, 4); break; + case TYPE_TET: coeff.resize(sz1, 6); break; + case TYPE_PYR: coeff.resize(sz1, 6); break; + default: + Msg::Error("Unkown type for IGE computation"); + coeff.resize(0, 0); + return; + } + + if (type != TYPE_PYR) { + for (int i = 0; i < sz1; i++) { + coeff(i, 0) = std::sqrt(pow_int(mat(i, 0), 2) + + pow_int(mat(i, 1), 2) + + pow_int(mat(i, 2), 2) ); + coeff(i, 1) = std::sqrt(pow_int(mat(i, 3), 2) + + pow_int(mat(i, 4), 2) + + pow_int(mat(i, 5), 2) ); + } + if (mat.size2() > 6) { // if 3D + for (int i = 0; i < sz1; i++) { + coeff(i, 2) = std::sqrt(pow_int(mat(i, 6), 2) + + pow_int(mat(i, 7), 2) + + pow_int(mat(i, 8), 2) ); + } + } + else if (type == TYPE_TRI) { + for (int i = 0; i < sz1; i++) { + coeff(i, 2) = std::sqrt(pow_int(mat(i, 3) - mat(i, 0), 2) + + pow_int(mat(i, 4) - mat(i, 1), 2) + + pow_int(mat(i, 5) - mat(i, 2), 2) ); + } + } + switch (type) { + case TYPE_TET: + case TYPE_PRI: + for (int i = 0; i < sz1; i++) { + coeff(i, 3) = std::sqrt(pow_int(mat(i, 3) - mat(i, 0), 2) + + pow_int(mat(i, 4) - mat(i, 1), 2) + + pow_int(mat(i, 5) - mat(i, 2), 2) ); + } + } + if (type == TYPE_TET) { + for (int i = 0; i < sz1; i++) { + coeff(i, 4) = std::sqrt(pow_int(mat(i, 6) - mat(i, 0), 2) + + pow_int(mat(i, 7) - mat(i, 1), 2) + + pow_int(mat(i, 8) - mat(i, 2), 2) ); + coeff(i, 5) = std::sqrt(pow_int(mat(i, 6) - mat(i, 3), 2) + + pow_int(mat(i, 7) - mat(i, 4), 2) + + pow_int(mat(i, 8) - mat(i, 5), 2) ); + } + } + } + else { + for (int i = 0; i < sz1; i++) { + coeff(i, 0) = std::sqrt(pow_int(2*mat(i, 0), 2) + + pow_int(2*mat(i, 1), 2) + + pow_int(2*mat(i, 2), 2) ); + coeff(i, 1) = std::sqrt(pow_int(2*mat(i, 3), 2) + + pow_int(2*mat(i, 4), 2) + + pow_int(2*mat(i, 5), 2) ); + coeff(i, 2) = std::sqrt(pow_int(mat(i, 6) + mat(i, 0) + mat(i, 3), 2) + + pow_int(mat(i, 7) + mat(i, 1) + mat(i, 4), 2) + + pow_int(mat(i, 8) + mat(i, 2) + mat(i, 5), 2) ); + coeff(i, 3) = std::sqrt(pow_int(mat(i, 6) - mat(i, 0) + mat(i, 3), 2) + + pow_int(mat(i, 7) - mat(i, 1) + mat(i, 4), 2) + + pow_int(mat(i, 8) - mat(i, 2) + mat(i, 5), 2) ); + coeff(i, 4) = std::sqrt(pow_int(mat(i, 6) - mat(i, 0) - mat(i, 3), 2) + + pow_int(mat(i, 7) - mat(i, 1) - mat(i, 4), 2) + + pow_int(mat(i, 8) - mat(i, 2) - mat(i, 5), 2) ); + coeff(i, 5) = std::sqrt(pow_int(mat(i, 6) + mat(i, 0) - mat(i, 3), 2) + + pow_int(mat(i, 7) + mat(i, 1) - mat(i, 4), 2) + + pow_int(mat(i, 8) + mat(i, 2) - mat(i, 5), 2) ); + } + } +} + +static void computeIGE_(const fullVector<double> &det, + const fullMatrix<double> &v, + fullVector<double> &ige, + int type) +{ + int sz = std::min(det.size(), v.size1()); + ige.resize(sz); + + switch(type) { + case TYPE_QUA: + for (int i = 0; i < sz; i++) { + ige(i) = det(i)/v(i, 0)/v(i, 1); + } + break; + case TYPE_HEX: + for (int i = 0; i < sz; i++) { + ige(i) = det(i)/v(i, 0)/v(i, 1)/v(i, 2); + } + case TYPE_TRI: + for (int i = 0; i < sz; i++) { + ige(i) = cTri * det(i) * (1/v(i,0)/v(i,1) + + 1/v(i,0)/v(i,2) + + 1/v(i,1)/v(i,2)) / 3; + } + case TYPE_PRI: + for (int i = 0; i < sz; i++) { + ige(i) = cTri * det(i) * (1/v(i,0)/v(i,1)/v(i,2) + + 1/v(i,0)/v(i,3)/v(i,2) + + 1/v(i,1)/v(i,3)/v(i,2)) / 3; + } + case TYPE_TET: + for (int i = 0; i < sz; i++) { + ige(i) = cTet * det(i) * (1/v(i,0)/v(i,5)/v(i,1) + + 1/v(i,0)/v(i,5)/v(i,2) + + 1/v(i,0)/v(i,5)/v(i,3) + + 1/v(i,0)/v(i,5)/v(i,4) + + 1/v(i,1)/v(i,4)/v(i,0) + + 1/v(i,1)/v(i,4)/v(i,2) + + 1/v(i,1)/v(i,4)/v(i,3) + + 1/v(i,1)/v(i,4)/v(i,5) + + 1/v(i,2)/v(i,3)/v(i,0) + + 1/v(i,2)/v(i,3)/v(i,1) + + 1/v(i,2)/v(i,3)/v(i,4) + + 1/v(i,2)/v(i,3)/v(i,5)) / 12; + } + case TYPE_PYR: + for (int i = 0; i < sz; i++) { + ige(i) = cPyr * det(i) * (1/v(i,0)/v(i,1)/v(i,2) + + 1/v(i,0)/v(i,1)/v(i,3) + + 1/v(i,0)/v(i,1)/v(i,4) + + 1/v(i,0)/v(i,1)/v(i,5) + + 1/v(i,2)/v(i,3)/v(i,4) + + 1/v(i,2)/v(i,3)/v(i,5) + + 1/v(i,4)/v(i,5)/v(i,2) + + 1/v(i,4)/v(i,5)/v(i,3) ) / 8; + } + } +} -double _CoeffDataIGE::cTri = 2/std::sqrt(3); -double _CoeffDataIGE::cTet = std::sqrt(2); -double _CoeffDataIGE::cPyr = std::sqrt(2); +namespace jacobianBasedQuality { void minMaxJacobianDeterminant(MElement *el, double &min, double &max, const fullMatrix<double> *normals) @@ -254,6 +399,58 @@ double minICNMeasure(MElement *el, return min; } +void sampleIGEMeasure(MElement *el, int deg, double &min, double &max) +{ + fullMatrix<double> nodesXYZ(el->getNumVertices(), 3); + el->getNodesCoord(nodesXYZ); + + const bool serendipFalse = false; + FuncSpaceData jacMatSpace, jacDetSpace; + + const int type = el->getType(); + switch(type) { + case TYPE_TRI: + case TYPE_TET: + case TYPE_QUA: + case TYPE_HEX: + case TYPE_PRI: + jacMatSpace = FuncSpaceData(el, deg, &serendipFalse); + jacDetSpace = FuncSpaceData(el, deg, &serendipFalse); + break; + case TYPE_PYR: +// jacMatSpace = FuncSpaceData(el, false, order, order-1, &serendipFalse); +// jacDetSpace = FuncSpaceData(el, false, jacOrder, jacOrder-3, &serendipFalse); + break; + default: + Msg::Error("ICN not implemented for type of element %d", el->getType()); + return; + } + + const GradientBasis *gradBasis = BasisFactory::getGradientBasis(jacMatSpace); + const JacobianBasis *jacBasis = BasisFactory::getJacobianBasis(jacDetSpace); + + fullVector<double> coeffDeterminant(jacBasis->getNumJacNodes()); + jacBasis->getSignedIdealJacobian(nodesXYZ, coeffDeterminant); + + fullMatrix<double> coeffMatLag(gradBasis->getNumSamplingPoints(), 9); + gradBasis->getAllIdealGradientsFromNodes(nodesXYZ, coeffMatLag); + + fullMatrix<double> v; + computeCoeffLengthVectors_(coeffMatLag, v, type); + + fullVector<double> ige; + computeIGE_(coeffDeterminant, v, ige, type); + + min = std::numeric_limits<double>::infinity(); + max = -min; + for (int i = 0; i < ige.size(); ++i) { + min = std::min(min, ige(i)); + max = std::max(max, ige(i)); + } + + return; +} + double minSampledICNMeasure(MElement *el, int deg)//fordebug { fullMatrix<double> nodesXYZ(el->getNumVertices(), 3); @@ -504,61 +701,17 @@ void _CoeffDataIGE::getSubCoeff(std::vector<_CoeffData*> &v) const void _CoeffDataIGE::_computeAtCorner(double &min, double &max) const { - min = std::numeric_limits<double>::infinity(); - max = -min; - fullMatrix<double> v; - _getCoeffLengthVectors(v, true); + computeCoeffLengthVectors_(_coeffsJacMat, v, _type, _bfsDet->getNumLagCoeff()); - for (int i = 0; i < _bfsDet->getNumLagCoeff(); i++) { - double sJ; - switch(_type) { - case TYPE_QUA: - sJ = _coeffsJacDet(i)/v(i, 0)/v(i,1); - break; - case TYPE_HEX: - sJ = _coeffsJacDet(i)/v(i,0)/v(i,1)/v(i,2); - break; - case TYPE_TRI: - sJ = cTri * _coeffsJacDet(i) * (1/v(i,0)/v(i,1) + - 1/v(i,0)/v(i,2) + - 1/v(i,1)/v(i,2)) / 3; - break; - case TYPE_TET: - sJ = cTet * _coeffsJacDet(i) * (1/v(i,0)/v(i,5)/v(i,1) + - 1/v(i,0)/v(i,5)/v(i,2) + - 1/v(i,0)/v(i,5)/v(i,3) + - 1/v(i,0)/v(i,5)/v(i,4) + - 1/v(i,1)/v(i,4)/v(i,0) + - 1/v(i,1)/v(i,4)/v(i,2) + - 1/v(i,1)/v(i,4)/v(i,3) + - 1/v(i,1)/v(i,4)/v(i,5) + - 1/v(i,2)/v(i,3)/v(i,0) + - 1/v(i,2)/v(i,3)/v(i,1) + - 1/v(i,2)/v(i,3)/v(i,4) + - 1/v(i,2)/v(i,3)/v(i,5)) / 12; - break; - case TYPE_PRI: - sJ = cTri * _coeffsJacDet(i) * (1/v(i,0)/v(i,1)/v(i,2) + - 1/v(i,0)/v(i,3)/v(i,2) + - 1/v(i,1)/v(i,3)/v(i,2)) / 3; - break; - case TYPE_PYR: - sJ = cPyr * _coeffsJacDet(i) * (1/v(i,0)/v(i,1)/v(i,2) + - 1/v(i,0)/v(i,1)/v(i,3) + - 1/v(i,0)/v(i,1)/v(i,4) + - 1/v(i,0)/v(i,1)/v(i,5) + - 1/v(i,2)/v(i,3)/v(i,4) + - 1/v(i,2)/v(i,3)/v(i,5) + - 1/v(i,4)/v(i,5)/v(i,2) + - 1/v(i,4)/v(i,5)/v(i,3) ) / 8; - break; - default: - Msg::Error("Unkown type for IGE computation"); - return; - } - min = std::min(min, sJ); - max = std::max(max, sJ); + fullVector<double> ige; + computeIGE_(_coeffsJacDet, v, ige, _type); + + min = std::numeric_limits<double>::infinity(); + max = -min; + for (int i = 0; i < ige.size(); ++i) { + min = std::min(min, ige(i)); + max = std::max(max, ige(i)); } } diff --git a/Mesh/qualityMeasuresJacobian.h b/Mesh/qualityMeasuresJacobian.h index ab83afda9ad4cc9f8245c3da8292c3a1317a0c26..5466765b0b1bb0a2bad7ac0e84f553ab2c913501 100644 --- a/Mesh/qualityMeasuresJacobian.h +++ b/Mesh/qualityMeasuresJacobian.h @@ -23,6 +23,7 @@ double minIGEMeasure(MElement *el, double minICNMeasure(MElement *el, bool knownValid = false, bool reversedOk = false); +void sampleIGEMeasure(MElement *el, int order, double &min, double &max); double minSampledICNMeasure(MElement *el, int order);//fordebug double minSampledIGEMeasure(MElement *el, int order);//fordebug @@ -78,9 +79,6 @@ private: const fullMatrix<double> _coeffsJacMat; const bezierBasis *_bfsDet, *_bfsMat; int _type; - static double cTri; - static double cTet; - static double cPyr; public: _CoeffDataIGE(fullVector<double> &det, @@ -98,8 +96,6 @@ private: void _computeAtCorner(double &min, double &max) const; double _computeLowerBound() const; void _getCoeffLengthVectors(fullMatrix<double> &, bool corners = false) const; - void _getCoeffScaledJacobian(const fullMatrix<double> &coeffLengthVectors, - fullMatrix<double> &coeffScaledJacobian) const; }; class _CoeffDataICN: public _CoeffData