diff --git a/Numeric/JacobianBasis.cpp b/Numeric/JacobianBasis.cpp index 24157004ccf46ff9f94923bf06db392c62557027..62a4a0e778cb1d04f6ad9b125a55b02875c3a532 100644 --- a/Numeric/JacobianBasis.cpp +++ b/Numeric/JacobianBasis.cpp @@ -88,11 +88,15 @@ void GradientBasis::getGradientsFromNodes(const fullMatrix<double> &nodes, if (dxyzdZ) gradShapeMatZ.mult(nodes, *dxyzdZ); } -JacobianBasis::JacobianBasis(int tag) +JacobianBasis::JacobianBasis(int tag, int jacOrder) { const int parentType = ElementType::ParentTypeFromTag(tag); const int order = ElementType::OrderFromTag(tag); - const int jacobianOrder = JacobianBasis::jacobianOrder(parentType, order); + int jacobianOrder; + if (jacOrder < 0) + jacobianOrder = JacobianBasis::jacobianOrder(parentType, order); + else + jacobianOrder = jacOrder; const int primJacobianOrder = JacobianBasis::jacobianOrder(parentType, 1); fullMatrix<double> lagPoints; // Sampling points diff --git a/Numeric/JacobianBasis.h b/Numeric/JacobianBasis.h index cdcd1adab34bc8bed90e26ccce24618af7a0d65c..aec12be7e6996f1bec5fe4d9825afa0b674ab7c9 100644 --- a/Numeric/JacobianBasis.h +++ b/Numeric/JacobianBasis.h @@ -44,7 +44,7 @@ class JacobianBasis { public : const bezierBasis *bezier; - JacobianBasis(int tag); + JacobianBasis(int tag, int jacOrder = -1); // Get methods inline int getNumJacNodes() const { return numJacNodes; } diff --git a/Numeric/MetricBasis.cpp b/Numeric/MetricBasis.cpp index 1b96d6f6df1a7e6f6bee81011092d8dad4375a57..1f3b277870b08d14c10326c8071db0dfc1bcaa09 100644 --- a/Numeric/MetricBasis.cpp +++ b/Numeric/MetricBasis.cpp @@ -8,24 +8,56 @@ #include "BasisFactory.h" #include "pointsGenerators.h" #include <cmath> - +#include <queue> +#include "OS.h" #if defined(HAVE_SCIP) -#include <scip/scip.h> -#include <soplex.h> +#include "scip/scip.h" +#include "scip/scipdefplugins.h" +#include "soplex/soplex.h" +#include <sstream> +#include "scip/cons.h" +#include "scip/struct_scip.h" +#endif -void MaFonctionScip() -{ - SCIP *scip; - SCIPcreate(&scip); +namespace { + double cubicCardanoRoot(double p, double q) + { + double sq = std::sqrt(q*q/4 + p*p*p/27); + return std::pow(-q/2+sq, 1/3.) + std::pow(-q/2-sq, 1/3.); + } + + int nChoosek(int n, int k) + { + if (n < k || k < 0) { + Msg::Error("Wrong argument for combination. n %d k %d", n, k); + return 1; + } + + if (k > n/2) k = n-k; + if (k == 1) + return n; + if (k == 0) + return 1; + + int c = 1; + for (int i = 1; i <= k; i++, n--) (c *= n) /= i; + return c; + } } -#endif MetricCoefficient::MetricCoefficient(MElement *el) : _element(el) { const int tag = el->getTypeForMSH(); const int type = ElementType::ParentTypeFromTag(tag); const int metricOrder = MetricCoefficient::metricOrder(tag); - _jacobian = BasisFactory::getJacobianBasis(tag); + if (type == TYPE_HEX || type == TYPE_PRI) { + int order = ElementType::OrderFromTag(tag); + _jacobian = new JacobianBasis(tag, 3*order); + } + else if (type == TYPE_TET) + _jacobian = BasisFactory::getJacobianBasis(tag); + else + Msg::Fatal("metric not implemented for element tag %d", tag); _gradients = BasisFactory::getGradientBasis(tag, metricOrder); _bezier = BasisFactory::getBezierBasis(type, metricOrder); @@ -67,13 +99,400 @@ MetricCoefficient::MetricCoefficient(MElement *el) : _element(el) _coefficientsLag(i, 1) = dvxdX - _coefficientsLag(i, 0); _coefficientsLag(i, 2) = dvxdY - _coefficientsLag(i, 0); _coefficientsLag(i, 3) = dvxdZ - _coefficientsLag(i, 0); - _coefficientsLag(i, 4) = dxdX*dxdY + dydX*dydY + dzdX*dzdY; - _coefficientsLag(i, 5) = dxdZ*dxdY + dydZ*dydY + dzdZ*dzdY; - _coefficientsLag(i, 6) = dxdX*dxdZ + dydX*dydZ + dzdX*dzdZ; + const double fact = std::sqrt(2); + _coefficientsLag(i, 4) = fact * (dxdX*dxdY + dydX*dydY + dzdX*dzdY); + _coefficientsLag(i, 5) = fact * (dxdZ*dxdY + dydZ*dydY + dzdZ*dzdY); + _coefficientsLag(i, 6) = fact * (dxdX*dxdZ + dydX*dydZ + dzdX*dzdZ); } } break; } + + _fillInequalities(metricOrder); +} + +void MetricCoefficient::_fillInequalities(int metricOrder) +{ + std::map<int, int> result2vect; + std::vector<std::pair<int,int> > v; + int dimSimplex = _bezier->_dimSimplex; + int dim = _bezier->getDim(); + fullMatrix<double> exp = _bezier->_exponents; + int ncoeff = _coefficientsLag.size1(); + Msg::Info("ncoeff %d", ncoeff); + int countP3 = 0, countJ2 = 0; + double tol = .99; + double tol2 = .001; + for (int i = 0; i < ncoeff; i++) { + for (int j = i; j < ncoeff; j++) { + double A = 1, B = 1; + { + int compl1 = metricOrder; + int compl2 = metricOrder; + int compl3 = 2*metricOrder; + for (int k = 0; k < dimSimplex; k++) { + A *= nChoosek(compl1, (int) exp(i, k)) + * nChoosek(compl2, (int) exp(j, k)); + B *= nChoosek(compl3, (int) exp(i, k) + (int) exp(j, k)); + compl1 -= (int) exp(i, k); + compl2 -= (int) exp(j, k); + compl3 -= (int) exp(i, k) + (int) exp(j, k); + } + } + for (int k = dimSimplex; k < dim; k++) { + A *= nChoosek(metricOrder, (int) exp(i, k)) + * nChoosek(metricOrder, (int) exp(j, k)); + B *= nChoosek(2*metricOrder, (int) exp(i, k) + (int) exp(j, k)); + } + + if (i != j) A *= 2; + + if (A > tol*B) { + v.push_back(std::make_pair(i, j)); + int ind; + int hash = 0; + for (int k = 0; k < dim; k++) { + hash += (int) (exp(i, k)+exp(j, k)) * pow_int(2*metricOrder+1, k); + } + std::map<int, int>::iterator it; + if ((it = result2vect.find(hash)) != result2vect.end()) { + ind = it->second; + } + else { + ind = _ineq2.size(); + _ineq2.push_back(std::map<std::pair<int, int>, double>()); + result2vect[hash] = ind; + } + _ineq2[ind][std::make_pair(i, j)] = A/B; + } + for (int k = j; k < ncoeff; ++k) { + double A = 1, B = 1; + { + int compl1 = metricOrder; + int compl2 = metricOrder; + int compl3 = metricOrder; + int compltot = 3*metricOrder; + for (int l = 0; l < dimSimplex; l++) { + A *= nChoosek(compl1, (int) exp(i, l)) + * nChoosek(compl2, (int) exp(j, l)) + * nChoosek(compl3, (int) exp(k, l)); + B *= nChoosek(compltot, (int) exp(i, l) + (int) exp(j, l) + (int) exp(k, l)); + compl1 -= (int) exp(i, l); + compl2 -= (int) exp(j, l); + compl3 -= (int) exp(k, l); + compltot -= (int) exp(i, l) + (int) exp(j, l) + (int) exp(k, l); + } + } + for (int l = dimSimplex; l < dim; l++) { + A *= nChoosek(metricOrder, (int) exp(i, l)) + * nChoosek(metricOrder, (int) exp(j, l)) + * nChoosek(metricOrder, (int) exp(k, l)); + B *= nChoosek(3*metricOrder, (int) exp(i, l) + (int) exp(j, l) + (int) exp(k, l)); + } + + if (i == j) { + if (j != k) A *= 3; + } + else { + if (j == k || i == k) A *= 3; + else A *= 6; + } + + ++countP3; + int hash = 0; + for (int l = 0; l < dim; l++) { + hash += (int) (exp(i, l)+exp(j, l)+exp(k, l)) * pow_int(3*metricOrder+1, l); + } + _ineqP3[hash].push_back(IneqData(A/B, i, j, k)); + //Msg::Info(" %d", _ineqP3[hash].back().k); + } + } + } + _inequations.resize(v.size(), 2); + exp = _jacobian->bezier->_exponents; + for (unsigned int k = 0; k < v.size(); ++k) { + //Msg::Info("%d %d", v[k].first, v[k].second); + _inequations(k, 0) = v[k].first; + _inequations(k, 1) = v[k].second; + } + + int njac = _jacobian->getNumJacNodes(); + for (int i = 0; i < njac; i++) { + for (int j = i; j < njac; j++) { + int order = metricOrder/2*3; + double A = 1, B = 1; + { + int compl1 = order; + int compl2 = order; + int compltot = 2*order; + for (int k = 0; k < dimSimplex; k++) { + A *= nChoosek(compl1, (int) exp(i, k)) + * nChoosek(compl2, (int) exp(j, k)); + B *= nChoosek(compltot, (int) exp(i, k) + (int) exp(j, k)); + compl1 -= (int) exp(i, k); + compl2 -= (int) exp(j, k); + compltot -= (int) exp(i, k) + (int) exp(j, k); + } + } + for (int k = dimSimplex; k < dim; k++) { + A *= nChoosek(order, (int) exp(i, k)) + * nChoosek(order, (int) exp(j, k)); + B *= nChoosek(2*order, (int) exp(i, k) + (int) exp(j, k)); + } + + if (i != j) A *= 2; + + ++countJ2; + int hash = 0; + for (int k = 0; k < dim; k++) { + hash += (int) (exp(i, k)+exp(j, k)) * pow_int(2*order+1, k); + } + _ineqJ2[hash].push_back(IneqData(A/B, i, j)); + } + } + + int ret = _lightenInequalities(tol, tol2, countJ2, countP3); + if (ret) { + Msg::Warning("Heavy Inequalities (error %d)", ret); + } + + Msg::Info("A : %d / %d", v.size(), ncoeff*(ncoeff+1)/2); + Msg::Info("J2 : %d / %d", countJ2, njac*(njac+1)/2); + Msg::Info("P3 : %d / %d", countP3, ncoeff*(ncoeff+1)*(ncoeff+2)/6); +} + +int MetricCoefficient::_lightenInequalities(double tol, double tol2, int &countj, int &countp) +{ +#ifndef BEFORE + std::map<int, std::vector<IneqData> >::iterator it, itbeg[3], itend[3]; + + int cnt[3] = {0,0,0}; + itbeg[0] = _ineqJ2.begin(); + itbeg[1] = _ineqP3.begin(); + //itbeg[2] = _ineqJ2.begin(); + itend[0] = _ineqJ2.end(); + itend[1] = _ineqP3.end(); + //itend[2] = _ineqJ2.end(); + for (int k = 0; k < 2; ++k) { + it = itbeg[k]; + while (it != itend[k]) { + std::sort(it->second.begin(), it->second.end(), gterIneq()); + + double rmved = .0; + while (it->second.size() && rmved + it->second.back().val <= tol) { + rmved += it->second.back().val; + it->second.pop_back(); + ++cnt[k]; + } + const double factor = 1-rmved; + for (unsigned int i = 0; i < it->second.size(); ++i) { + it->second[i].val /= factor; + } + ++it; + } + } + countj -= cnt[0]; + countp -= cnt[1]; + return 0; + +#else + std::map<int, std::vector<IneqData> >::iterator itJ, itP; + itJ = _ineqJ2.begin(); + itP = _ineqP3.begin(); + + while (itJ != _ineqJ2.end() && itP != _ineqP3.end()) { + double verif = 0; + for (unsigned int i = 0; i < itJ->second.size(); ++i) { + verif += itJ->second[i].val; + } + if (verif < 1. - 1e-7 || verif > 1. + 1e-7) Msg::Warning("verif J %g", verif); + verif = 0; + for (unsigned int i = 0; i < itP->second.size(); ++i) { + verif += itP->second[i].val; + } + if (verif < 1.-1e-7 || verif > 1.+1e-7) Msg::Warning("verif P %g", verif); + // TODO : remove + + std::sort(itJ->second.begin(), itJ->second.end(), gterIneq()); + std::sort(itP->second.begin(), itP->second.end(), gterIneq()); + + bool print = false; + if (true || itJ->second.back().val < tol && itP->second.back().val < tol) { + print = true; + Msg::Info(" "); + //Msg::Info("sizes %d %d", itJ->second.size(), itP->second.size()); + Msg::Info("JJ-before-JJJJJJJJJJJJJJJJJJJ"); + for (unsigned int i = 0; i < itJ->second.size(); ++i) { + Msg::Info("%g", itJ->second[i].val / tol); + } + Msg::Info("PP-before-PPPPPPPPPPPPPPPPPPP"); + for (unsigned int i = 0; i < itP->second.size(); ++i) { + Msg::Info("%g", itP->second[i].val / tol); + } + } + +#if defined(HAVE_SCIP) + SCIP* scip; + SCIP_CALL(SCIPcreate(&scip)); + SCIP_CALL(SCIPincludeDefaultPlugins(scip)); + //SCIP_CALL(SCIPsetMessagehdlr(NULL, NULL)); + SCIP_CALL(SCIPcreateProb(scip, "inequalities", NULL, NULL, + NULL, NULL, NULL, NULL, NULL)); + SCIP_CALL(SCIPsetObjsense(scip, SCIP_OBJSENSE_MAXIMIZE)); + + int nj = itJ->second.size(); + int np = itP->second.size(); + + SCIP_VAR** varj = new SCIP_VAR*[nj]; + SCIP_VAR** varp = new SCIP_VAR*[np]; + double* cj = new double[nj]; + double* cp = new double[np]; + + for (int i = 0; i < nj; ++i) { + std::ostringstream namebuf; + namebuf.str(""); + namebuf << "j" << i; + + SCIP_CALL(SCIPcreateVar(scip, &varj[i], namebuf.str().c_str(), .0, 1., + 1., SCIP_VARTYPE_BINARY, TRUE, FALSE, + NULL, NULL, NULL, NULL, NULL)); + SCIP_CALL(SCIPaddVar(scip, varj[i])); + cj[i] = itJ->second[i].val; + } + for (int i = 0; i < np; ++i) { + std::ostringstream namebuf; + namebuf.str(""); + namebuf << "p" << i; + + SCIP_CALL(SCIPcreateVar(scip, &varp[i], namebuf.str().c_str(), .0, 1., + 1., SCIP_VARTYPE_BINARY, TRUE, FALSE, + NULL, NULL, NULL, NULL, NULL)); + SCIP_CALL(SCIPaddVar(scip, varp[i])); + cp[i] = itP->second[i].val; + } + + SCIP_CONS* cons[3]; + for (int i = 0; i < nj; ++i) { + Msg::Info("+cj%d (%g)", i, cj[i]); + } + + Msg::Info("<= tol %g", tol); + SCIP_CALL(SCIPcreateConsLinear(scip, &cons[0], "bound J", + nj, varj, cj, .0, tol, TRUE, + TRUE, TRUE, TRUE, TRUE, FALSE, + FALSE, FALSE, FALSE, FALSE)); + SCIPconsPrint(cons[0], scip->set, NULL, NULL); + SCIP_CALL(SCIPcreateConsLinear(scip, &cons[1], "bound P", + np, varp, cp, .0, tol, TRUE, + TRUE, TRUE, TRUE, TRUE, FALSE, + FALSE, FALSE, FALSE, FALSE)); + SCIP_CALL(SCIPcreateConsLinear(scip, &cons[2], "difference", + nj, varj, cj, -tol2, tol2, TRUE, + TRUE, TRUE, TRUE, TRUE, FALSE, + FALSE, FALSE, FALSE, FALSE)); + for (int i = 0; i < np; ++i) { + //SCIP_CALL(SCIPaddCoefLinear(scip, cons[2], varp[i], -cp[i])); + } + + SCIP_CALL(SCIPsolve(scip)); + SCIPconsPrint(cons[0], scip->set, NULL, NULL); + SCIP_SOL* sol = SCIPgetBestSol(scip); + if (!sol) { + Msg::Error("Scip did not find a solution"); + } + else { + int ind = 0; + for (int i = 0; i < nj; ++i) { + Msg::Info("j%d = %g", i, SCIPgetSolVal(scip, sol, varj[i])); + if (SCIPgetSolVal(scip, sol, varj[i]) > .5) { + itJ->second[ind] = itJ->second.back(); + itJ->second.pop_back(); + } + else ++ind; + } + ind = 0; + for (int i = 0; i < np; ++i) { + if (SCIPgetSolVal(scip, sol, varp[i]) > .5) { + itP->second[ind] = itP->second.back(); + itP->second.pop_back(); + } + else ++ind; + } + } + + for (int i = 0; i < nj; ++i) + SCIP_CALL(SCIPreleaseVar(scip, &varj[i])); + for (int i = 0; i < np; ++i) + SCIP_CALL(SCIPreleaseVar(scip, &varp[i])); + //SCIP_CALL(SCIPreleaseCons(scip, &cons[0])); + //SCIP_CALL(SCIPreleaseCons(scip, &cons[1])); + //SCIP_CALL(SCIPreleaseCons(scip, &cons[2])); + SCIP_CALL(SCIPfree(&scip)); + delete[] varj; + delete[] varp; + delete[] cj; + delete[] cp; + +#else + + double rmvedJ = 0, rmvedP = 0; + bool changed = true; + + while (changed) { + changed = false; + double potentialJ = rmvedJ, potentialP = rmvedP; + int j = itJ->second.size(); + int p = itP->second.size(); + bool found = false; + + while (j > 1 && !found && potentialJ <= tol) { + double tmp = itP->second[p-1].val; + //if (potentialP - potentialJ > -tol2) found = true; + while (potentialP + tmp <= tol && potentialP + tmp - potentialJ <= tol2) { + potentialP += tmp; + --p; + if (p < 1) Msg::Fatal("me"); + tmp = itP->second[p-1].val; + if (potentialP - potentialJ >= -tol2) found = true; + } + if (!found) { + potentialJ += itJ->second[j-1].val; + --j; + if (j < 1) Msg::Fatal("ma"); + potentialP = rmvedP; + p = itP->second.size(); + } + } + if (found) { + rmvedJ = potentialJ, rmvedP = potentialP; + //countJ2 -= itJ->second.size() - j; + //countP3 -= itP->second.size() - p; // TODO + itJ->second.erase(itJ->second.begin() + j, itJ->second.end()); + //Msg::Info("%d %d", p, itP->second.size()); + itP->second.erase(itP->second.begin() + p, itP->second.end()); + changed = true; + } + } +#endif + + + if (print) { + //Msg::Info("sizes %d %d", itJ->second.size(), itP->second.size()); + Msg::Info("JJ-after-JJJJJJJJJJJJJJJJJJJ"); + for (unsigned int i = 0; i < itJ->second.size(); ++i) { + Msg::Info("%g", itJ->second[i].val / tol); + } + Msg::Info("PP-after-PPPPPPPPPPPPPPPPPPP"); + for (unsigned int i = 0; i < itP->second.size(); ++i) { + Msg::Info("%g", itP->second[i].val / tol); + } + } + + ++itJ; + ++itP; + } + return 0; +#endif } void MetricCoefficient::getCoefficients(fullMatrix<double> &coeff, bool bezier) @@ -112,12 +531,10 @@ void MetricCoefficient::getCoefficients(fullMatrix<double> &coeff, bool bezier) } coeff.resize(ref->size1(), 2); for (int i = 0; i < ref->size1(); ++i) { - double tmp = pow((*ref)(i, 1), 2); - tmp += pow((*ref)(i, 2), 2); - tmp += pow((*ref)(i, 3), 2); - tmp += 2 * pow((*ref)(i, 4), 2); - tmp += 2 * pow((*ref)(i, 5), 2); - tmp += 2 * pow((*ref)(i, 6), 2); + double tmp = 0; + for (int j = 1; j < 7; ++j) { + tmp += pow((*ref)(i, j), 2); + } tmp = std::sqrt(tmp); double factor = std::sqrt(6)/3; coeff(i, 0) = (*ref)(i, 0) - factor * tmp; @@ -131,24 +548,6 @@ void MetricCoefficient::getCoefficients(fullMatrix<double> &coeff, bool bezier) } } -static int nChoosek(int n, int k) -{ - if (n < k || k < 0) { - Msg::Error("Wrong argument for combination."); - return 1; - } - - if (k > n/2) k = n-k; - if (k == 1) - return n; - if (k == 0) - return 1; - - int c = 1; - for (int i = 1; i <= k; i++, n--) (c *= n) /= i; - return c; -} - void MetricCoefficient::interpolate(const double *uvw, double *minmaxQ) { if (minmaxQ == NULL) { @@ -243,14 +642,12 @@ void MetricCoefficient::interpolate(const double *uvw, double *minmaxQ) double tmp = pow(terms[1], 2); tmp += pow(terms[2], 2); tmp += pow(terms[3], 2); - tmp += 2 * pow(terms[4], 2); - tmp += 2 * pow(terms[5], 2); - tmp += 2 * pow(terms[6], 2); + tmp += pow(terms[4], 2); + tmp += pow(terms[5], 2); + tmp += pow(terms[6], 2); tmp = std::sqrt(tmp); double factor = std::sqrt(6)/3; if (tmp < 1e-3*terms[0]) { - static int aa = 0; - Msg::Info("%d", ++aa); minmaxQ[0] = terms[0] - factor * tmp; minmaxQ[1] = terms[0] + factor * tmp; } @@ -292,68 +689,46 @@ void MetricCoefficient::interpolate(const double *uvw, double *minmaxQ) delete [] terms; } -double MetricCoefficient::getBoundRmin(double tol) +double MetricCoefficient::getBoundRmin(double tol, int which) { + if (_coefficientsBez.size2() == 0) _computeBezCoeff(); + fullMatrix<double> nodes(_element->getNumShapeFunctions(),3); fullVector<double> jac(_jacobian->getNumJacNodes()); _element->getNodesCoord(nodes); _jacobian->getSignedJacobian(nodes, jac); - if(jac.size() != _coefficientsBez.size1()) - Msg::Fatal("not same size, jac %d, coeff %d", jac.size(), _coefficientsBez.size1()); - - // compute RminLag - double RminLag = 1.; - const double factor1 = std::sqrt(6) / 3; - const double factor2 = std::sqrt(6) * 3; - - for (int i = 0; i < _bezier->getNumLagCoeff(); ++i) { - double q = _coefficientsBez(i, 0); - double tmp = pow_int(_coefficientsBez(i, 1), 2); - tmp += pow_int(_coefficientsBez(i, 2), 2); - tmp += pow_int(_coefficientsBez(i, 3), 2); - tmp += 2 * pow_int(_coefficientsBez(i, 4), 2); - tmp += 2 * pow_int(_coefficientsBez(i, 5), 2); - tmp += 2 * pow_int(_coefficientsBez(i, 6), 2); - tmp = tmp*factor1; - if (tmp < 1e-3 * q) { - tmp = (q - tmp) / (q + tmp); - RminLag = std::min(RminLag, tmp); - } - else { - double phi = jac(i)*jac(i); - phi -= q * q * q; - phi += .5 * q * tmp * tmp; - phi /= tmp * tmp * tmp; - phi *= factor2; - if (phi > 1.1 || phi < -1.1) Msg::Warning("phi %g", phi); - if (phi > 1) phi = 1; - if (phi < -1) phi = -1; - phi = std::acos(phi)/3; - tmp = (q + tmp * std::cos(phi + 2*M_PI/3)) / (q + tmp * std::cos(phi)); - RminLag = std::min(RminLag, tmp); - } - } + double RminLag, RminBez; + if (which == 1) + _computeRmin1(_coefficientsBez, jac, RminLag, RminBez, 0); + else + _computeRmin2(_coefficientsBez, jac, RminLag, RminBez, 0, which); - // compute RminBez - /*double RminBez = 1.; - double minq = minq(); - double minp = minp(); - double maxq = maxq(); - double maxp = maxp(); - if (minq < 1e-3 * maxp) { - double tmp = (minq - maxp) / (minq + maxp); - RminLag = std::min(RminBez, tmp); + if (RminLag-RminBez < tol) { + Msg::Info("RETURNING %g", RminBez); + return RminBez; } else { - - }*/ - - - /*compute RminBez - if RminLag-RminBez < tol : return RminBez - return subdivide*/ - return RminLag; + fullMatrix<double> *copycoeff = new fullMatrix<double>(_coefficientsBez); + fullVector<double> *copyjac = new fullVector<double>(jac); + MetricData *md = new MetricData(copycoeff, copyjac, RminBez, 0); + __numSubdivision = 0; + __numSub.resize(20); + for (unsigned int i = 0; i < __numSub.size(); ++i) __numSub[i] = 0; + __maxdepth = 0; + double time = Cpu(); + double tt = _subdivideForRmin(md, RminLag, tol, which); + Msg::Info("> computation time %g", Cpu() - time); + Msg::Info("> maxDepth %d", __maxdepth); + Msg::Info("> numSubdivision %d", __numSubdivision); + int last = __numSub.size(); + while (--last > 0 && __numSub[last] == 0); + for (unsigned int i = 0; i < last+1; ++i) { + Msg::Info("> depth %d: %d", i, __numSub[i]); + } + Msg::Info("RETURNING %g after subdivision", tt); + return tt; + } } int MetricCoefficient::metricOrder(int tag) @@ -363,9 +738,12 @@ int MetricCoefficient::metricOrder(int tag) switch (parentType) { case TYPE_PNT : return 0; + case TYPE_LIN : return order; + case TYPE_TRI : case TYPE_TET : return 2*order-2; + case TYPE_QUA : case TYPE_PRI : case TYPE_HEX : @@ -435,3 +813,521 @@ void MetricCoefficient::_computeBezCoeff() _coefficientsLag.size2()); _bezier->matrixLag2Bez.mult(_coefficientsLag, _coefficientsBez); } + +void MetricCoefficient::_computeRmin1( + fullMatrix<double> &coeff, fullVector<double> &jac, + double &RminLag, double &RminBez, int depth) const +{ + RminLag = 1.; + static const double factor1 = std::sqrt(6) / 3; + static const double factor2 = std::sqrt(6) * 3; + + for (int i = 0; i < _bezier->getNumLagCoeff(); ++i) { + double q = coeff(i, 0); + double p = pow_int(coeff(i, 1), 2); + p += pow_int(coeff(i, 2), 2); + p += pow_int(coeff(i, 3), 2); + p += pow_int(coeff(i, 4), 2); + p += pow_int(coeff(i, 5), 2); + p += pow_int(coeff(i, 6), 2); + p = std::sqrt(p); + if (p < 1e-3 * q) { + p *= factor1; + RminLag = std::min(RminLag, std::sqrt((q - p) / (q + p))); + } + else { + double phi = q/p; + phi = .5 * phi - pow_int(phi,3); + phi += jac(i)/p/p*jac(i)/p; + phi *= factor2; + if (phi > 1.1 || phi < -1.1) { + if (!depth) { + Msg::Warning("+ phi %g (jac %g, q %g, p %g)", phi, jac(i), q, p); + Msg::Info("%g + %g - %g = %g", jac(i)*jac(i)/p/p/p, .5 * q/p, q*q*q/p/p/p, (jac(i)*jac(i)+.5 * q*p*p-q*q*q)/p/p/p); + } + else if (depth == 1) + Msg::Warning("- phi %g @ %d(%d) (jac %g, q %g, p %g)", phi, depth, i, jac(i), q, p); + } + + if (phi > 1) phi = 1; + if (phi < -1) phi = -1; + phi = std::acos(phi)/3; + p *= factor1; + double tmp = (q + p * std::cos(phi + 2*M_PI/3)) / (q + p * std::cos(phi)); + if (tmp < 0) Msg::Fatal("1 s normal ? %g", tmp); + RminLag = std::min(RminLag, std::sqrt(tmp)); + } + } + + double minq = _minq(coeff); + double maxp = _maxp(coeff); + if (maxp < 1e-3 * minq) { + maxp *= factor1; + double tmp = (minq - maxp) / (minq + maxp); + RminBez = std::sqrt(tmp); + } + else { + double minp = _minp(coeff); + double maxq = _maxq(coeff); + + double minJ2; + double maxJ2; + _minMaxJacobianSqr(jac, minJ2, maxJ2); + + double minphi = minJ2/pow_int(maxp, 3); + minphi -= pow_int(maxq/minp, 3); + minphi += .5 * minq/maxp; + minphi *= factor2; + if (minphi < -1) minphi = -1; + if (minphi > 1) minphi = 1; + minphi = std::acos(minphi) / 3 + 2*M_PI/3; + + double maxphi = maxJ2/pow_int(minp, 3); + maxphi -= pow_int(minq/maxp, 3); + maxphi += .5 * maxq/minp; + maxphi *= factor2; + if (maxphi < -1.) maxphi = -1.; + if (maxphi > 1.) maxphi = 1.; + maxphi = std::acos(maxphi) / 3; + + double tmp = minq + factor1 * maxp * std::cos(minphi); + tmp /= maxq + factor1 * maxp * std::cos(maxphi); + if (tmp < 0) RminBez = 0; + else RminBez = std::sqrt(tmp); + } +} + +void MetricCoefficient::_computeRmin2( + fullMatrix<double> &coeff, fullVector<double> &jac, + double &RminLag, double &RminBez, int depth, int which) const +{ + RminLag = 1.; + static const double factor1 = std::sqrt(6) / 3; + static const double factor2 = std::sqrt(6) * 3; + + for (int i = 0; i < _bezier->getNumLagCoeff(); ++i) { + double q = coeff(i, 0); + double p = pow_int(coeff(i, 1), 2); + p += pow_int(coeff(i, 2), 2); + p += pow_int(coeff(i, 3), 2); + p += pow_int(coeff(i, 4), 2); + p += pow_int(coeff(i, 5), 2); + p += pow_int(coeff(i, 6), 2); + p = std::sqrt(p); + if (p < 1e-3 * q) { + p *= factor1; + RminLag = std::min(RminLag, std::sqrt((q - p) / (q + p))); + } + else { + double phi = q/p; + phi = .5 * phi - pow_int(phi,3); + phi += jac(i)/p/p*jac(i)/p; + phi *= factor2; + if (phi > 1.1 || phi < -1.1) { + if (!depth) { + Msg::Warning("+ phi %g (jac %g, q %g, p %g)", phi, jac(i), q, p); + Msg::Info("%g + %g - %g = %g", jac(i)*jac(i)/p/p/p, .5 * q/p, q*q*q/p/p/p, (jac(i)*jac(i)+.5 * q*p*p-q*q*q)/p/p/p); + } + else if (depth == 1) + Msg::Warning("- phi %g @ %d(%d) (jac %g, q %g, p %g)", phi, depth, i, jac(i), q, p); + } + + if (phi > 1) phi = 1; + if (phi < -1) phi = -1; + phi = std::acos(phi)/3; + p *= factor1; + double tmp = (q + p * std::cos(phi + 2*M_PI/3)) / (q + p * std::cos(phi)); + if (tmp < 0) Msg::Fatal("2 s normal ? %g", tmp); + RminLag = std::min(RminLag, std::sqrt(tmp)); + } + } + + double minq = _minq(coeff); + double maxp = _maxp(coeff); + //Msg::Info("1: %g", maxp/minq); + if (maxp < 1e-3 * minq) { + maxp *= factor1; + double tmp = (minq - maxp) / (minq + maxp); //TODO il y a mieux ! + RminBez = std::sqrt(tmp); + /*if (RminBez > .6 || isnan(RminBez)) Msg::Info("minq %g maxp %g => %g", minq, maxp, RminBez);*/ + } + else { + double minJ; + if (which == 2 || which == 4) { + double maxJ; + _minMaxJacobianSqr(jac, minJ, maxJ); + minJ /= maxp*maxp*maxp; + } + else if (which == 3 || which == 5) { + _minJ2P3(coeff, jac, minJ); + } + else { + Msg::Fatal("don't know what to do %d", which); + return; + } + + double a1, a0; + { + double p = -1./2; + double q = -minJ-1/factor2; + a1 = cubicCardanoRoot(p, q); //plus grand => -1 + q = -minJ+1/factor2; + a0 = cubicCardanoRoot(p, q); //plus petit => 1 + } + + double mina; + double maxa; + if (which == 2 || which == 5) { + mina = minq/maxp; + double minp = _minp(coeff); + if (minp > 0.) + maxa = _maxq(coeff)/minp; + else + maxa = a1; + } + else if (which == 3 || which == 4) { + _minMaxA2(coeff, mina, maxa); + } + else { + Msg::Fatal("don't know what to do %d", which); + return; + } + + double phimin = std::acos(-factor1/2/mina) - M_PI/3; + if (mina > a1) { + RminBez = (mina+factor1*std::cos(phimin+2*M_PI/3))/(mina+factor1*std::cos(phimin)); //* + RminBez = std::sqrt(RminBez); + return; + } + + double phim = std::acos(-factor1/2/a1) - M_PI/3; + double am; + { + double p = -1./2; + double q = -minJ+std::cos(3*phim)/factor2; + am = cubicCardanoRoot(p, q); //milieu + } + + if (maxa < am) { + double phi = std::acos(factor2*(minJ-maxa*maxa*maxa+maxa/2))/3; + RminBez = (maxa+factor1*std::cos(phi+2*M_PI/3))/(maxa+factor1*std::cos(phi)); + RminBez = std::sqrt(RminBez); + return; + } + + if (mina > am) { + RminBez = (mina+factor1*std::cos(phimin+2*M_PI/3))/(mina+factor1*std::cos(phimin)); //same as * + RminBez = std::sqrt(RminBez); + return; + } + else { + RminBez = (a1+factor1*std::cos(phim+2*M_PI/3))/(a1+factor1*std::cos(phim)); + RminBez = std::sqrt(RminBez); + return; + } + } +} + +double MetricCoefficient::_subdivideForRmin( + MetricData *md, double RminLag, double tol, int which) const +{ + std::priority_queue<MetricData*, std::vector<MetricData*>, lessMinB> subdomains; + std::vector<MetricData*> vect; + const int numCoeff = md->_metcoeffs->size2(); + const int numMetPnts = md->_metcoeffs->size1(); + const int numJacPnts = md->_jaccoeffs->size(); + const int numSub = _jacobian->getNumDivisions(); + subdomains.push(md); + + std::vector<fullVector<double>*> trash; + + while (RminLag - subdomains.top()->_RminBez > tol && subdomains.size() < pow_int(8,8)) { + fullMatrix<double> *subcoeffs, *coeff; + fullVector<double> *subjac, *jac; + + MetricData *current = subdomains.top(); + subcoeffs = new fullMatrix<double>(numSub*numMetPnts, numCoeff); + subjac = new fullVector<double>(numSub*numJacPnts); + _bezier->subDivisor.mult(*current->_metcoeffs, *subcoeffs); + _jacobian->subdivideBezierCoeff(*current->_jaccoeffs, *subjac); + int depth = current->_depth; + //Msg::Info("d %d RminBez %g / %g", depth, current->_RminBez, RminLag); + delete current; + subdomains.pop(); + + ++((MetricCoefficient*)this)->__numSubdivision; + ++((MetricCoefficient*)this)->__numSub[depth]; + ((MetricCoefficient*)this)->__maxdepth = std::max(__maxdepth, depth+1); + + if (depth == 0) { + Msg::Info("Begin 1"); + } + for (int i = 0; i < numSub; ++i) { + coeff = new fullMatrix<double>(numMetPnts, numCoeff); + coeff->copy(*subcoeffs, i * numMetPnts, numMetPnts, 0, numCoeff, 0, 0); + jac = new fullVector<double>; + jac->setAsProxy(*subjac, i * numJacPnts, numJacPnts); + double minLag, minBez; + if (which == 1) + _computeRmin1(*coeff, *jac, minLag, minBez, depth+1); + else + _computeRmin2(*coeff, *jac, minLag, minBez, depth+1, which); + //Msg::Info("new RminBez %g", minBez); + RminLag = std::min(RminLag, minLag); + MetricData *metData = new MetricData(coeff, jac, minBez, depth+1); + subdomains.push(metData); + vect.push_back(metData); + } + if (depth == 0) { + Msg::Info("End 1"); + } + trash.push_back(subjac); + delete subcoeffs; + + /*for (unsigned int i = 0; i < vect.size(); ++i) { + Msg::Info("v %g", vect[i]->_RminBez); + } + Msg::Info("top %g (RminLag %g)", subdomains.top()->_RminBez, RminLag); + return 0;*/ + //Msg::Info("RminLag %g - RminBez %g @ %d", RminLag, subdomains.top()->_RminBez, subdomains.top()->_depth); + } + + md = subdomains.top(); + double ans = md->_RminBez; + + while (subdomains.size()) { + md = subdomains.top(); + subdomains.pop(); + delete md; + } + for (unsigned int i = 0; i < trash.size(); ++i) { + delete trash[i]; + } + + return ans; +} + +double MetricCoefficient::_minp(const fullMatrix<double> &coeff) const +{ + fullMatrix<double> minmaxCoeff(2, 6); + for (int j = 0; j < 6; ++j) { + minmaxCoeff(0, j) = coeff(0, j+1); + minmaxCoeff(1, j) = coeff(0, j+1); + } + + for (int i = 1; i < coeff.size1(); ++i) { + for (int j = 0; j < 6; ++j) { + if (minmaxCoeff(0, j) > coeff(i, j+1)) { + minmaxCoeff(0, j) = coeff(i, j+1); + } + if (minmaxCoeff(1, j) < coeff(i, j+1)) { + minmaxCoeff(1, j) = coeff(i, j+1); + } + } + } + + double ans = 0; + for (int j = 0; j < 6; ++j) { + if (minmaxCoeff(0, j) * minmaxCoeff(1, j) > 0) { + ans += minmaxCoeff(0, j) > 0 ? + pow_int(minmaxCoeff(0, j), 2) : + pow_int(minmaxCoeff(1, j), 2); + } + } + return std::sqrt(ans); +} + +double MetricCoefficient::_minq(const fullMatrix<double> &coeff) const +{ + double ans = coeff(0, 0); + for (int i = 1; i < coeff.size1(); ++i) { + if (ans > coeff(i, 0)) ans = coeff(i, 0); + } + return ans; +} + +double MetricCoefficient::_maxp(const fullMatrix<double> &coeff) const +{ + double ans = 0; + for (int i = 0; i < coeff.size1(); ++i) { + double tmp = pow_int(coeff(i, 1), 2); + tmp += pow_int(coeff(i, 2), 2); + tmp += pow_int(coeff(i, 3), 2); + tmp += pow_int(coeff(i, 4), 2); + tmp += pow_int(coeff(i, 5), 2); + tmp += pow_int(coeff(i, 6), 2); + if (ans < tmp) ans = tmp; + } + return std::sqrt(ans); +} + +double MetricCoefficient::_maxq(const fullMatrix<double> &coeff) const +{ + double ans = coeff(0, 0); + for (int i = 1; i < coeff.size1(); ++i) { + if (ans < coeff(i, 0)) ans = coeff(i, 0); + } + return ans; +} + +void MetricCoefficient::_minMaxA( + const fullMatrix<double> &coeff, double &min, double &max) const +{ + int i = _inequations(0, 0); + int j = _inequations(0, 1); + + // TODO : si coeff(0, m) < 0 + + min = max = 0; + for (int l = 1; l < 7; ++l) { + min += coeff(i, l) * coeff(j, l); + } + min /= coeff(i, 0) * coeff(j, 0); + // TODO : si coeff(0, i|j) == 0 + max = min; + + for (int k = 1; k < _inequations.size1(); ++k) { + double tmp = 0; + i = _inequations(k, 0); + j = _inequations(k, 1); + for (int l = 1; l < 7; ++l) { + tmp += coeff(i, l) * coeff(j, l); + } + tmp /= coeff(i, 0) * coeff(j, 0); + min = std::min(tmp, min); + max = std::max(tmp, max); + } + + if (min < 0) + Msg::Fatal("minA ne devrait pas etre negatif"); + + min = std::sqrt(min); + max = std::sqrt(max); + double tmp = min; + min = 1./max; + max = 1./tmp; +} + +void MetricCoefficient::_minMaxA2( + const fullMatrix<double> &coeff, double &min, double &max) const +{ + min = 1e10; + max = 0; + std::map<std::pair<int, int>, double>::const_iterator it; + + for (unsigned int k = 0; k < _ineq2.size(); ++k) { + double tmpNum = 0; + double tmpDen = 0; + //Msg::Info("%d/%d: %d", k, _ineq2.size(), _ineq2[k].size()); + //Msg::Info(" "); + for (it = _ineq2[k].begin(); it != _ineq2[k].end(); ++it) { + const int i = it->first.first; + const int j = it->first.second; + double tmp2 = 0; + for (int l = 1; l < 7; ++l) { + tmp2 += coeff(i, l) * coeff(j, l); + } + tmpNum += it->second * tmp2; + tmpDen += it->second * coeff(i, 0) * coeff(j, 0); + } + double val = tmpNum/tmpDen; + //Msg::Info("%g/%g = %g", tmpNum, tmpDen, val); + min = std::min(val, min); + max = std::max(val, max); + } + + if (min < 0) + Msg::Fatal("minA ne devrait pas etre negatif"); + + min = std::sqrt(min); + max = std::sqrt(max); + double tmp = min; + min = 1./max; + max = 1./tmp; +} + +void MetricCoefficient::_minMaxJacobianSqr( + const fullVector<double> &jac, double &min, double &max) const +{ + static int a = 1; + if (++a == 1) { + for (int i = 1; i < jac.size(); ++i) { + Msg::Info("<%g>", jac(i)); + } + } + min = max = jac(0); + for (int i = 1; i < jac.size(); ++i) { + if (min > jac(i)) min = jac(i); + if (max < jac(i)) max = jac(i); + } + + if (a == 1) { + Msg::Info("%g %g", min, max); + } + + if (min*max < 0) { + max = max > -min ? max*max : min*min; + min = 0; + } + else { + if (max > 0) { + max = max*max; + min = min*min; + } + else { + double tmp = max; + max = min*min; + min = tmp*tmp; + } + } +} + +void MetricCoefficient::_minJ2P3(const fullMatrix<double> &coeff, + const fullVector<double> &jac, double &min) const +{ + fullVector<double> r(coeff.size1()); + for (int i = 0; i < coeff.size1(); ++i) { + r(i) = 0; + for (int l = 1; l < 7; ++l) { + r(i) += coeff(i, l) * coeff(i, l); + } + r(i) = std::sqrt(r(i)); + } + + min = 1e10; + std::map<int, std::vector<IneqData> >::const_iterator itJ, itP; + itJ = _ineqJ2.begin(); + itP = _ineqP3.begin(); + + //Msg::Warning("sizes %d %d", _ineqJ2.size(), _ineqP3.size()); + int count = 0; + while (itJ != _ineqJ2.end() && itP != _ineqP3.end()) { + if (count >= _ineqJ2.size()) Msg::Fatal("aaargh"); + if (itJ->first != itP->first) Msg::Fatal("not same hash %d %d", itJ->first, itP->first); + + double num = 0; + //Msg::Info("sizej %d", itJ->second.size()); + for (int l = 0; l < itJ->second.size(); ++l) { + const int i = itJ->second[l].i; + const int j = itJ->second[l].j; + num += itJ->second[l].val * jac(i) * jac(j); + } + + double den = 0; + //Msg::Info("sizep %d", itP->second.size()); + for (int l = 0; l < itP->second.size(); ++l) { + const int i = itP->second[l].i; + const int j = itP->second[l].j; + const int k = itP->second[l].k; + //Msg::Info("i%d j%d k%d", i, j, k); + if (l>=itP->second.size()) Msg::Error("l %d/%d", l, itP->second.size()); + if (i>=r.size() || j>=r.size()||k>=r.size() ) Msg::Fatal("i%d j%d k%d /%d (%dl%d)", i, j, k, r.size(), count, l); + den += itP->second[l].val * r(i) * r(j) * r(k); + } + //Msg::Info("%g/%g = %g", num, den, num/den); + min = std::min(min, num/den); + ++itJ; + ++itP; + ++count; + } +} diff --git a/Numeric/MetricBasis.h b/Numeric/MetricBasis.h index dcf1ab97d919af34e74651c113f720e6627a9a2e..2ea5729fdb38740a7af3bc63e64b3a1985e1824c 100644 --- a/Numeric/MetricBasis.h +++ b/Numeric/MetricBasis.h @@ -11,25 +11,82 @@ #include "fullMatrix.h" class MetricCoefficient { +private: + class MetricData { + public: + fullMatrix<double> *_metcoeffs; + fullVector<double> *_jaccoeffs; + double _RminBez; + int _depth; + + public: + MetricData(fullMatrix<double> *m, fullVector<double> *j, double r, int d) : + _metcoeffs(m), _jaccoeffs(j), _RminBez(r), _depth(d) {} + ~MetricData() { + delete _metcoeffs; + delete _jaccoeffs; + } + }; + struct lessMinB { + bool operator()(const MetricData *md1, const MetricData *md2) const { + return md1->_RminBez > md2->_RminBez; + } + }; + + class IneqData { + public: + int i, j, k; + double val; + + public: + IneqData(double val, int i, int j, int k = -1) : i(i), j(j), k(k), val(val) {} + }; + class gterIneq { + public: + bool operator()(const IneqData &id1, const IneqData &id2) const { + return id1.val > id2.val; + } + }; + private: MElement *_element; const JacobianBasis *_jacobian; const GradientBasis *_gradients; const bezierBasis *_bezier; fullMatrix<double> _coefficientsLag, _coefficientsBez; + fullMatrix<double> _inequations; + std::vector<std::map<std::pair<int, int>, double> > _ineq2; //TODO : pas top + std::map<int, std::vector<IneqData> > _ineqJ2, _ineqP3; + int __maxdepth, __numSubdivision; + std::vector<int> __numSub; public: MetricCoefficient(MElement*); void getCoefficients(fullMatrix<double>&, bool bezier = true); void interpolate(const double *uvw, double *minmaxQ); - double getBoundRmin(double tol); + double getBoundRmin(double tol, int which); static int metricOrder(int tag); private: void _computeBezCoeff(); + void _fillInequalities(int order); + int _lightenInequalities(double, double, int&, int&); //TODO change void _interpolateBezierPyramid(const double *uvw, double *minmaxQ); + void _computeRmin1(fullMatrix<double>&, fullVector<double>&, + double &RminLag, double &RminBez, int) const; + void _computeRmin2(fullMatrix<double>&, fullVector<double>&, + double &RminLag, double &RminBez, int depth, int which) const; + double _subdivideForRmin(MetricData*, double RminLag, double tol, int which) const; + double _minp(const fullMatrix<double>&) const; + double _minq(const fullMatrix<double>&) const; + double _maxp(const fullMatrix<double>&) const; + double _maxq(const fullMatrix<double>&) const; + void _minMaxA(const fullMatrix<double>&, double &min, double &max) const; + void _minMaxA2(const fullMatrix<double>&, double &min, double &max) const; + void _minMaxJacobianSqr(const fullVector<double>&, double &min, double &max) const; + void _minJ2P3(const fullMatrix<double>&, const fullVector<double>&, double &min) const; }; #endif diff --git a/Numeric/bezierBasis.cpp b/Numeric/bezierBasis.cpp index 3bc3f9c50c6aa2196deb00ac6fda6f9f475299ee..9903be53515a43ea52a1cc4a661537ce164e30e8 100644 --- a/Numeric/bezierBasis.cpp +++ b/Numeric/bezierBasis.cpp @@ -551,59 +551,58 @@ void bezierBasis::_construct(int parentType, int p) return; } - int dimSimplex; switch (parentType) { case TYPE_PNT : dim = 0; numLagCoeff = 1; - dimSimplex = 0; + _dimSimplex = 0; _exponents = gmshGenerateMonomialsLine(0); subPoints.push_back(gmshGeneratePointsLine(0)); break; case TYPE_LIN : { dim = 1; - numLagCoeff = 2; - dimSimplex = 0; + numLagCoeff = order == 0 ? 1 : 2; + _dimSimplex = 0; _exponents = gmshGenerateMonomialsLine(order); subPoints = generateSubPointsLine(order); break; } case TYPE_TRI : { dim = 2; - numLagCoeff = 3; - dimSimplex = 2; + numLagCoeff = order == 0 ? 1 : 3; + _dimSimplex = 2; _exponents = gmshGenerateMonomialsTriangle(order); subPoints = generateSubPointsTriangle(order); break; } case TYPE_QUA : { dim = 2; - numLagCoeff = 4; - dimSimplex = 0; + numLagCoeff = order == 0 ? 1 : 4; + _dimSimplex = 0; _exponents = gmshGenerateMonomialsQuadrangle(order); subPoints = generateSubPointsQuad(order); break; } case TYPE_TET : { dim = 3; - numLagCoeff = 4; - dimSimplex = 3; + numLagCoeff = order == 0 ? 1 : 4; + _dimSimplex = 3; _exponents = gmshGenerateMonomialsTetrahedron(order); subPoints = generateSubPointsTetrahedron(order); break; } case TYPE_PRI : { dim = 3; - numLagCoeff = 6; - dimSimplex = 2; + numLagCoeff = order == 0 ? 1 : 6; + _dimSimplex = 2; _exponents = gmshGenerateMonomialsPrism(order); subPoints = generateSubPointsPrism(order); break; } case TYPE_HEX : { dim = 3; - numLagCoeff = 8; - dimSimplex = 0; + numLagCoeff = order == 0 ? 1 : 8; + _dimSimplex = 0; _exponents = gmshGenerateMonomialsHexahedron(order); subPoints = generateSubPointsHex(order); break; @@ -614,7 +613,7 @@ void bezierBasis::_construct(int parentType, int p) dim = 3; order = 0; numLagCoeff = 4; - dimSimplex = 3; + _dimSimplex = 3; _exponents = gmshGenerateMonomialsTetrahedron(order); subPoints = generateSubPointsTetrahedron(order); break; @@ -625,7 +624,7 @@ void bezierBasis::_construct(int parentType, int p) fullMatrix<double> bezierPoints = _exponents; bezierPoints.scale(1./order); - matrixBez2Lag = generateBez2LagMatrix(_exponents, bezierPoints, order, dimSimplex); + matrixBez2Lag = generateBez2LagMatrix(_exponents, bezierPoints, order, _dimSimplex); matrixBez2Lag.invert(matrixLag2Bez); - subDivisor = generateSubDivisor(_exponents, subPoints, matrixLag2Bez, order, dimSimplex); + subDivisor = generateSubDivisor(_exponents, subPoints, matrixLag2Bez, order, _dimSimplex); } diff --git a/Numeric/bezierBasis.h b/Numeric/bezierBasis.h index 3e236f1aae2ca2a0724bc8d35bec42686b533d29..257e54be4a66424454486c269686f51ba02effd6 100644 --- a/Numeric/bezierBasis.h +++ b/Numeric/bezierBasis.h @@ -19,6 +19,8 @@ class bezierBasis { int numLagCoeff; int dim, type, order; int numDivisions; + public: + int _dimSimplex; fullMatrix<double> _exponents; public :