diff --git a/contrib/HighOrderMeshOptimizer/OptHOM.cpp b/contrib/HighOrderMeshOptimizer/OptHOM.cpp index aeeb08df770a0dd17f275208731729e160799084..355a0c443f6728ce802756bca5fb881f02959c54 100644 --- a/contrib/HighOrderMeshOptimizer/OptHOM.cpp +++ b/contrib/HighOrderMeshOptimizer/OptHOM.cpp @@ -24,6 +24,9 @@ OptHOM::OptHOM(GEntity *ge, std::set<MVertex*> & toFix, int method) : bool OptHOM::addJacObjGrad(double &Obj, alglib::real_1d_array &gradObj) { + minJac = 1.e300; + maxJac = -1.e300; + for (int iEl = 0; iEl < mesh.nEl(); iEl++) { std::vector<double> sJ(mesh.nBezEl(iEl)); // Scaled Jacobians mesh.scaledJac(iEl,sJ); @@ -34,6 +37,8 @@ bool OptHOM::addJacObjGrad(double &Obj, alglib::real_1d_array &gradObj) const double f1 = compute_f1(sJ[l]); for (int iPC = 0; iPC < mesh.nPCEl(iEl); iPC++) gradObj[mesh.indPCEl(iEl,iPC)] += f1*gSJ[mesh.indGSJ(iEl,l,iPC)]; + minJac = std::min(minJac,sJ[l]); + maxJac = std::max(maxJac,sJ[l]); } } @@ -47,13 +52,22 @@ bool OptHOM::addJacObjGrad(double &Obj, alglib::real_1d_array &gradObj) bool OptHOM::addDistObjGrad(double Fact, double Fact2, double &Obj, alglib::real_1d_array &gradObj) { + maxDist = 0; + avgDist = 0; + int nbBnd = 0; + for (int iFV = 0; iFV < mesh.nFV(); iFV++) { const double Factor = invLengthScaleSq*(mesh.forced(iFV) ? Fact : Fact2); - Obj += Factor * mesh.distSq(iFV); + const double dSq = mesh.distSq(iFV), dist = sqrt(dSq); + Obj += Factor * dSq; std::vector<double> gDSq(mesh.nPCFV(iFV)); mesh.gradDistSq(iFV,gDSq); for (int iPC = 0; iPC < mesh.nPCFV(iFV); iPC++) gradObj[mesh.indPCFV(iFV,iPC)] += Factor*gDSq[iPC]; + maxDist = std::max(maxDist, dist); + avgDist += dist; + nbBnd++; } + if (nbBnd != 0) avgDist /= nbBnd; return true; @@ -69,8 +83,11 @@ void OptHOM::evalObjGrad(const alglib::real_1d_array &x, double &Obj, alglib::re Obj = 0.; for (int i = 0; i < gradObj.length(); i++) gradObj[i] = 0.; - addJacObjGrad(Obj, gradObj); - addDistObjGrad(lambda, lambda2, Obj, gradObj); + if (minJac > barrier) printf("INFO: reached minimum Jacobian requirement, setting null gradient\n"); + else { + addJacObjGrad(Obj, gradObj); + addDistObjGrad(lambda, lambda2, Obj, gradObj); + } } @@ -78,39 +95,30 @@ void OptHOM::evalObjGrad(const alglib::real_1d_array &x, double &Obj, alglib::re void evalObjGradFunc(const alglib::real_1d_array &x, double &Obj, alglib::real_1d_array &gradObj, void *HOInst) { - OptHOM &HO = *static_cast<OptHOM*> (HOInst); - HO.evalObjGrad(x, Obj, gradObj); - double distMaxBnd, distAvgBnd, minJac, maxJac; - HO.getDistances(distMaxBnd, distAvgBnd, minJac, maxJac); - if (minJac > HO.barrier) { - printf("STOP\n"); - for (int i = 0; i < gradObj.length(); ++i) { - gradObj[i] = 0; - } - } + (static_cast<OptHOM*>(HOInst))->evalObjGrad(x, Obj, gradObj); } -void OptHOM::getDistances(double &distMaxBND, double &distAvgBND, double &minJac, double &maxJac) +void OptHOM::recalcJacDist() { - distMaxBND = 0; - distAvgBND = 0; + maxDist = 0; + avgDist = 0; int nbBnd = 0; for (int iFV = 0; iFV < mesh.nFV(); iFV++) { if (mesh.forced(iFV)) { double dSq = mesh.distSq(iFV); - distMaxBND = std::max(distMaxBND, sqrt(dSq)); - distAvgBND += sqrt(dSq); + maxDist = std::max(maxDist, sqrt(dSq)); + avgDist += sqrt(dSq); nbBnd++; } } - if (nbBnd != 0) distAvgBND /= nbBnd; + if (nbBnd != 0) avgDist /= nbBnd; - minJac = 1000; - maxJac = -1000; + minJac = 1.e300; + maxJac = -1.e300; for (int iEl = 0; iEl < mesh.nEl(); iEl++) { std::vector<double> sJ(mesh.nBezEl(iEl)); // Scaled Jacobians mesh.scaledJac(iEl,sJ); @@ -128,12 +136,7 @@ void OptHOM::printProgress(const alglib::real_1d_array &x, double Obj) { iter++; - - if (iter % progressInterv == 0) { - double maxD, avgD, minJ, maxJ; - getDistances(maxD, avgD, minJ, maxJ); - printf("--> Iteration %3d --- OBJ %12.5E (relative decrease = %12.5E) -- minJ = %12.5E maxJ = %12.5E Max D = %12.5E Avg D = %12.5E\n", iter, Obj, Obj/initObj, minJ, maxJ, maxD, avgD); - } + if (iter % progressInterv == 0) printf("--> Iteration %3d --- OBJ %12.5E (relative decrease = %12.5E) -- minJ = %12.5E maxJ = %12.5E Max D = %12.5E Avg D = %12.5E\n", iter, Obj, Obj/initObj, minJac, maxJac, maxDist, avgDist); } @@ -192,7 +195,7 @@ void OptHOM::OptimPass(alglib::real_1d_array &x, const alglib::real_1d_array &in -int OptHOM::optimize(double weightFixed, double weightFree, double barrier_, int pInt, int itMax, double &minJ, double &maxJ) +int OptHOM::optimize(double weightFixed, double weightFree, double barrier_, int pInt, int itMax) { barrier = barrier_; progressInterv = pInt; @@ -213,10 +216,11 @@ int OptHOM::optimize(double weightFixed, double weightFree, double barrier_, int mesh.getUvw(x.getcontent()); // Calculate initial performance - // double minJ, maxJ; - getDistances(initMaxD, initAvgD, minJ, maxJ); + recalcJacDist(); + initMaxDist = maxDist; + initAvgDist = avgDist; - const double jacBarStart = (minJ > 0.) ? 0.9*minJ : 1.1*minJ; + const double jacBarStart = (minJac > 0.) ? 0.9*minJac : 1.1*minJac; jacBar = jacBarStart; setBarrierTerm(jacBarStart); @@ -227,15 +231,14 @@ int OptHOM::optimize(double weightFixed, double weightFree, double barrier_, int for (int i = 0; i < mesh.nPC(); i++) gradObj[i] = 0.; evalObjGrad(x, initObj, gradObj); - std::cout << "Initial mesh: Obj = " << initObj << ", minJ = " << minJ << ", maxJ = " << maxJ << ", maxD = " << initMaxD << ", avgD = " << initAvgD << std::endl; + std::cout << "Initial mesh: Obj = " << initObj << ", minJ = " << minJac << ", maxJ = " << maxJac << ", maxD = " << initMaxDist << ", avgD = " << initAvgDist << std::endl; - std::cout << "Start optimizing with barrier = " << barrier << std::endl; + std::cout << "Start optimizing " << mesh.nEl() << " elements (" << mesh.nVert() << " vertices, " + << mesh.nFV() << " free vertices, " << mesh.nPC() << " variables) with barrier = " << barrier << std::endl; - while (minJ < barrier) { + while (minJac < barrier) { OptimPass(x, gradObj, itMax); - double dumMaxD, dumAvgD; - getDistances(dumMaxD, dumAvgD, minJ, maxJ); - jacBar = (minJ > 0.) ? 0.9*minJ : 1.1*minJ; + jacBar = (minJac > 0.) ? 0.9*minJac : 1.1*minJac; setBarrierTerm(jacBar); } @@ -244,10 +247,9 @@ int OptHOM::optimize(double weightFixed, double weightFree, double barrier_, int // OptimPass(x, gradObj, itMax); // } - double finalObj = 0., finalMaxD, finalAvgD; + double finalObj = 0.; evalObjGrad(x, finalObj, gradObj); - getDistances(finalMaxD, finalAvgD, minJ, maxJ); - std::cout << "Final mesh: Obj = " << finalObj << ", maxD = " << finalMaxD << ", avgD = " << finalAvgD << ", minJ = " << minJ << ", maxJ = " << maxJ << std::endl; + std::cout << "Final mesh: Obj = " << finalObj << ", maxD = " << maxDist << ", avgD = " << avgDist << ", minJ = " << minJac << ", maxJ = " << maxJac << std::endl; return 0; diff --git a/contrib/HighOrderMeshOptimizer/OptHOM.h b/contrib/HighOrderMeshOptimizer/OptHOM.h index 23c7efaab920da8ba8b0ca1ad69adafafdbd5f75..e16620958dcb83f84cd92f83163e7b490ee507da 100644 --- a/contrib/HighOrderMeshOptimizer/OptHOM.h +++ b/contrib/HighOrderMeshOptimizer/OptHOM.h @@ -22,8 +22,9 @@ public: Mesh mesh; OptHOM(GEntity *gf, std::set<MVertex*> & toFix, int method); - void getDistances(double &distMaxBND, double &distAvgBND, double &minJac, double &maxJac); - int optimize(double lambda, double lambda2, double barrier, int pInt, int itMax, double &minJ, double &maxJ); // optimize one list of elements + void recalcJacDist(); + inline void getJacDist(double &minJ, double &maxJ, double &maxD, double &avgD); + int optimize(double lambda, double lambda2, double barrier, int pInt, int itMax); // optimize one list of elements void updateMesh(const alglib::real_1d_array &x); void evalObjGrad(const alglib::real_1d_array &x, double &Obj, alglib::real_1d_array &gradObj); void printProgress(const alglib::real_1d_array &x, double Obj); @@ -35,7 +36,8 @@ private: // double lambda, lambda2, powM, powP, invLengthScaleSq; double lambda, lambda2, jacBar, bTerm, invLengthScaleSq; int iter, progressInterv; // Current iteration, interval of iterations for reporting - double initObj, initMaxD, initAvgD; // Values for reporting + double initObj, initMaxDist, initAvgDist; // Values for reporting + double minJac, maxJac, maxDist, avgDist; // Values for reporting inline double setBarrierTerm(double jacBarrier) { bTerm = jacBarrier/(1.-jacBarrier); } inline double compute_f(double v); @@ -78,6 +80,14 @@ inline double OptHOM::compute_f1(double v) +void OptHOM::getJacDist(double &minJ, double &maxJ, double &maxD, double &avgD) +{ + minJ = minJac; maxJ = maxJac; maxD = maxDist; avgD = avgDist; + std::cout << "getJacDist: minJac = " << minJac << ", maxJac = " << maxJac << ", maxDist = " << maxDist << ", avgDist = " << avgDist << std::endl; +} + + + #endif diff --git a/contrib/HighOrderMeshOptimizer/OptHomRun.cpp b/contrib/HighOrderMeshOptimizer/OptHomRun.cpp index 444544e99e38c8379218f43908792ee93e86f601..1bac92a11bb759c05a7cacef9bdd1e1ca7087e12 100644 --- a/contrib/HighOrderMeshOptimizer/OptHomRun.cpp +++ b/contrib/HighOrderMeshOptimizer/OptHomRun.cpp @@ -171,7 +171,7 @@ std::set<MVertex*> filter3D(GRegion *gr, int nbLayers, double _qual) void HighOrderMeshOptimizer (GModel *gm, OptHomParameters &p) { - int samples = 30; + int samples = 20; // int method = Mesh::METHOD_RELAXBND | Mesh::METHOD_PHYSCOORD | Mesh::METHOD_PROJJAC; // int method = Mesh::METHOD_FIXBND | Mesh::METHOD_PHYSCOORD | Mesh::METHOD_PROJJAC; @@ -196,13 +196,15 @@ void HighOrderMeshOptimizer (GModel *gm, OptHomParameters &p) (*itf)->quadrangles = quas; double distMaxBND, distAvgBND, minJac, maxJac; - temp->getDistances(distMaxBND, distAvgBND, minJac, maxJac); + temp->recalcJacDist(); + temp->getJacDist(minJac, maxJac, distMaxBND, distAvgBND); // std::ostringstream ossI; // ossI << "initial_" << (*itf)->tag() << ".msh"; // temp->mesh.writeMSH(ossI.str().c_str()); // printf("--> Mesh Loaded for GFace %d : minJ %12.5E -- maxJ %12.5E\n", (*itf)->tag(), minJac, maxJac); if (distMaxBND < 1.e-8 * SIZE && minJac > p.BARRIER) continue; - p.SUCCESS = temp->optimize(p.weightFixed, p.weightFree, p.BARRIER, samples, p.itMax, p.minJac, p.maxJac); + p.SUCCESS = temp->optimize(p.weightFixed, p.weightFree, p.BARRIER, samples, p.itMax); + temp->getJacDist(p.minJac, p.maxJac, distMaxBND, distAvgBND); temp->mesh.updateGEntityPositions(); // std::ostringstream ossF; // ossF << "final_" << (*itf)->tag() << ".msh"; @@ -217,11 +219,13 @@ void HighOrderMeshOptimizer (GModel *gm, OptHomParameters &p) filter3D(*itr, p.nbLayers, p.BARRIER); OptHOM *temp = new OptHOM(*itr, toFix, method); double distMaxBND, distAvgBND, minJac, maxJac; - temp->getDistances(distMaxBND, distAvgBND, minJac, maxJac); + temp->recalcJacDist(); + temp->getJacDist(minJac, maxJac, distMaxBND, distAvgBND); // temp->mesh.writeMSH("initial.msh"); // printf("--> Mesh Loaded for GRegion %d : minJ %12.5E -- maxJ %12.5E\n", (*itr)->tag(), minJac, maxJac); if (distMaxBND < 1.e-8 * SIZE && minJac > p.BARRIER) continue; - p.SUCCESS = temp->optimize(p.weightFixed, p.weightFree, p.BARRIER, samples, p.itMax, p.minJac, p.maxJac); + p.SUCCESS = temp->optimize(p.weightFixed, p.weightFree, p.BARRIER, samples, p.itMax); + temp->getJacDist(p.minJac, p.maxJac, distMaxBND, distAvgBND); temp->mesh.updateGEntityPositions(); (*itr)->tetrahedra = tets; // temp->mesh.writeMSH("final.msh"); diff --git a/contrib/HighOrderMeshOptimizer/OptHomRun.h b/contrib/HighOrderMeshOptimizer/OptHomRun.h index 10ad8a3f86390d0327571c97eedfde2ee8b4d399..c77229145d4ff2eea93f2a4343af823c279cb2c6 100644 --- a/contrib/HighOrderMeshOptimizer/OptHomRun.h +++ b/contrib/HighOrderMeshOptimizer/OptHomRun.h @@ -5,7 +5,6 @@ class GModel; struct OptHomParameters { // INPUT ------> - double STOP ; // stop criterion double BARRIER ; // minimum scaled jcaobian double weightFixed ; // weight of the energy for fixed nodes double weightFree ; // weight of the energy for free nodes @@ -21,8 +20,8 @@ struct OptHomParameters { OptHomParameters () // default values - : STOP (0.01) , BARRIER (0.1) , weightFixed (10.), weightFree (1.e-3), - nbLayers (6) , dim(3) , itMax(10000), onlyVisible(true) + : BARRIER (0.1) , weightFixed (10.), weightFree (1.e-3), + nbLayers (6) , dim(3) , itMax(1000), onlyVisible(true) { } };