From 1d3cc55c15dba6b127ebe613a144a64d0757fec4 Mon Sep 17 00:00:00 2001 From: Thomas Toulorge <thomas.toulorge@mines-paristech.fr> Date: Fri, 18 Oct 2013 17:39:40 +0000 Subject: [PATCH] Added local surface parametrization for high-order mesh optimization, worked on one-by-one strategy --- contrib/HighOrderMeshOptimizer/OptHomMesh.cpp | 2 +- contrib/HighOrderMeshOptimizer/OptHomRun.cpp | 191 +++++++++--------- contrib/HighOrderMeshOptimizer/ParamCoord.cpp | 103 +++++++++- contrib/HighOrderMeshOptimizer/ParamCoord.h | 50 +++-- 4 files changed, 223 insertions(+), 123 deletions(-) diff --git a/contrib/HighOrderMeshOptimizer/OptHomMesh.cpp b/contrib/HighOrderMeshOptimizer/OptHomMesh.cpp index 4b81c780dd..e24731670d 100644 --- a/contrib/HighOrderMeshOptimizer/OptHomMesh.cpp +++ b/contrib/HighOrderMeshOptimizer/OptHomMesh.cpp @@ -73,7 +73,7 @@ Mesh::Mesh(const std::map<MElement*,GEntity*> &element2entity, if (vDim == 3) param = new ParamCoordPhys3D(); else if (hasParam) param = new ParamCoordParent(vert); else { - if (vDim == 2) param = new ParamCoordPhys2D(); //todo: make 2d local surf. param + if (vDim == 2) param = new ParamCoordLocalSurf(vert); else param = new ParamCoordLocalLine(vert); nonGeoMove = true; } diff --git a/contrib/HighOrderMeshOptimizer/OptHomRun.cpp b/contrib/HighOrderMeshOptimizer/OptHomRun.cpp index 8c0b20135c..7a013dec96 100644 --- a/contrib/HighOrderMeshOptimizer/OptHomRun.cpp +++ b/contrib/HighOrderMeshOptimizer/OptHomRun.cpp @@ -499,111 +499,112 @@ static void optimizeOneByOne for (int iterBlob=0; iterBlob<p.maxAdaptBlob; iterBlob++) { -// OptHOM *opt; -// -// // First step: small blob with unsafe optimization (only 1st-order -// // bnd. vertices fixed) -// std::set<MElement*> toOptimizePrim = getSurroundingBlob -// (worstEl, nbLayers, vertex2elements, distanceFactor, 0); -// std::set<MVertex*> toFix1 = getPrimBndVertices(toOptimizePrim, vertex2elements); -// std::set<MElement*> toOptimize1; -// std::set_difference(toOptimizePrim.begin(),toOptimizePrim.end(), -// badElts.begin(),badElts.end(), // Do not optimize badElts -// std::inserter(toOptimize1, toOptimize1.end())); -// Msg::Info("Optimizing primary blob %i (max. %i remaining) composed of" -// " %4d elements", iBadEl, badElts.size(), toOptimize1.size()); -// fflush(stdout); -// opt = new OptHOM(toOptimize1, toFix1, p.fixBndNodes); -// //std::ostringstream ossI1; -// //ossI1 << "initial_primary_" << iter << ".msh"; -// //opt->mesh.writeMSH(ossI1.str().c_str()); -// success = opt->optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN, p.BARRIER_MAX, -// false, samples, p.itMax, p.optPassMax); -// -// // Second step: add external layer, check it and optimize it safely (all -// // bnd. vertices fixed) if new broken element -// if (success > 0) { -// opt->mesh.updateGEntityPositions(); -// std::set<MElement*> layer = addBlobLayer(toOptimizePrim, vertex2elements); -// if (detectNewBrokenElement(layer, badElts, p)) { -// delete opt; -// std::set<MVertex*> toFix2 = getAllBndVertices(toOptimizePrim, vertex2elements); -// std::set<MElement*> toOptimize2; -// std::set_difference(toOptimizePrim.begin(),toOptimizePrim.end(), -// badElts.begin(),badElts.end(), -// std::inserter(toOptimize2, toOptimize2.end())); -// Msg::Info("Optimizing corrective blob %i (max. %i remaining) " -// "composed of %4d elements", iBadEl, badElts.size(), -// toOptimize2.size()); -// fflush(stdout); -// opt = new OptHOM(toOptimize2, toFix2, p.fixBndNodes); -// //std::ostringstream ossI1; -// //ossI1 << "initial_corrective_" << iter << ".msh"; -// //opt->mesh.writeMSH(ossI1.str().c_str()); -// success = opt->optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN, -// p.BARRIER_MAX, false, samples, p.itMax, p.optPassMax); -// if (success >= 0 && p.BARRIER_MIN_METRIC > 0) { -// Msg::Info("Jacobian optimization succeed, starting svd optimization"); -// success = opt->optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN_METRIC, -// p.BARRIER_MAX, true, samples, p.itMax, p.optPassMax); -// } -// } -// else { -// Msg::Info("Primary blob %i did not break new elements, " -// "no correction needed", iBadEl); -// fflush(stdout); -// } -// } + OptHOM *opt; + // First step: small blob with unsafe optimization (only 1st-order + // bnd. vertices fixed) std::set<MElement*> toOptimizePrim = getSurroundingBlob - (worstEl, nbLayers, vertex2elements, distanceFactor, 1, p.optPrimSurfMesh); -// std::set<MElement*> layer = addBlobLayer(toOptimizePrim, vertex2elements); - std::set<MVertex*> toFix = getAllBndVertices(toOptimizePrim, vertex2elements); - std::set<MElement*> toOptimize; + (worstEl, nbLayers, vertex2elements, distanceFactor, 0, p.optPrimSurfMesh); + std::set<MVertex*> toFix1 = getPrimBndVertices(toOptimizePrim, vertex2elements); + std::set<MElement*> toOptimize1; std::set_difference(toOptimizePrim.begin(),toOptimizePrim.end(), - badElts.begin(),badElts.end(), - std::inserter(toOptimize, toOptimize.end())); - Msg::Info("Optimizing blob %i (max. %i remaining) " - "composed of %4d elements", iBadEl, badElts.size(), - toOptimize.size()); + badElts.begin(),badElts.end(), // Do not optimize badElts + std::inserter(toOptimize1, toOptimize1.end())); + Msg::Info("Optimizing primary blob %i (max. %i remaining) composed of" + " %4d elements", iBadEl, badElts.size(), toOptimize1.size()); fflush(stdout); - OptHOM *opt = new OptHOM(element2entity, toOptimize, toFix, p.fixBndNodes); + opt = new OptHOM(element2entity, toOptimize1, toFix1, p.fixBndNodes); //std::ostringstream ossI1; - //ossI1 << "initial_corrective_" << iter << ".msh"; + //ossI1 << "initial_primary_" << iter << ".msh"; //opt->mesh.writeMSH(ossI1.str().c_str()); - success = opt->optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN, - p.BARRIER_MAX, false, samples, p.itMax, p.optPassMax); - if (success >= 0 && p.BARRIER_MIN_METRIC > 0) { - Msg::Info("Jacobian optimization succeed, starting svd optimization"); - success = opt->optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN_METRIC, - p.BARRIER_MAX, true, samples, p.itMax, p.optPassMax); - } + success = opt->optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN, p.BARRIER_MAX, + false, samples, p.itMax, p.optPassMax); - // Measure min and max Jac., update mesh - if ((success > 0) || (iterBlob == p.maxAdaptBlob-1)) { - double minJac, maxJac, distMaxBND, distAvgBND; - opt->recalcJacDist(); - opt->getJacDist(minJac, maxJac, distMaxBND, distAvgBND); - p.minJac = std::min(p.minJac,minJac); - p.maxJac = std::max(p.maxJac,maxJac); + // Second step: add external layer, check it and optimize it safely (all + // bnd. vertices fixed) if new broken element + if (success > 0) { opt->mesh.updateGEntityPositions(); + std::set<MElement*> layer = addBlobLayer(toOptimizePrim, vertex2elements); + if (detectNewBrokenElement(layer, badElts, p)) { + delete opt; + std::set<MVertex*> toFix2 = getAllBndVertices(toOptimizePrim, vertex2elements); + std::set<MElement*> toOptimize2; + std::set_difference(toOptimizePrim.begin(),toOptimizePrim.end(), + badElts.begin(),badElts.end(), + std::inserter(toOptimize2, toOptimize2.end())); + Msg::Info("Optimizing corrective blob %i (max. %i remaining) " + "composed of %4d elements", iBadEl, badElts.size(), + toOptimize2.size()); + fflush(stdout); + opt = new OptHOM(element2entity, toOptimize2, toFix2, p.fixBndNodes); + //std::ostringstream ossI1; + //ossI1 << "initial_corrective_" << iter << ".msh"; + //opt->mesh.writeMSH(ossI1.str().c_str()); + success = opt->optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN, + p.BARRIER_MAX, false, samples, p.itMax, p.optPassMax); + if (success >= 0 && p.BARRIER_MIN_METRIC > 0) { + Msg::Info("Jacobian optimization succeed, starting svd optimization"); + success = opt->optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN_METRIC, + p.BARRIER_MAX, true, samples, p.itMax, p.optPassMax); + } + } + else { + Msg::Info("Primary blob %i did not break new elements, " + "no correction needed", iBadEl); + fflush(stdout); + } } - //std::ostringstream ossI2; - //ossI2 << "final_ITER_" << iter << ".msh"; - //temp.mesh.writeMSH(ossI2.str().c_str()); - if (success <= 0) { - distanceFactor *= p.adaptBlobDistFact; - nbLayers *= p.adaptBlobLayerFact; - Msg::Info("Blob %i failed (adapt #%i), adapting with increased size", - iBadEl, iterBlob); -// if (iterBlob == p.maxAdaptBlob-1) { - std::ostringstream ossI2; - ossI2 << "final_" << iBadEl << ".msh"; - opt->mesh.writeMSH(ossI2.str().c_str()); -// } - } - else break; +// std::set<MElement*> toOptimizePrim = getSurroundingBlob +// (worstEl, nbLayers, vertex2elements, distanceFactor, 1, p.optPrimSurfMesh); +//// std::set<MElement*> layer = addBlobLayer(toOptimizePrim, vertex2elements); +// std::set<MVertex*> toFix = getAllBndVertices(toOptimizePrim, vertex2elements); +// std::set<MElement*> toOptimize; +// std::set_difference(toOptimizePrim.begin(),toOptimizePrim.end(), +// badElts.begin(),badElts.end(), +// std::inserter(toOptimize, toOptimize.end())); +// Msg::Info("Optimizing blob %i (max. %i remaining) " +// "composed of %4d elements", iBadEl, badElts.size(), +// toOptimize.size()); +// fflush(stdout); +// OptHOM *opt = new OptHOM(element2entity, toOptimize, toFix, p.fixBndNodes); +// //std::ostringstream ossI1; +// //ossI1 << "initial_corrective_" << iter << ".msh"; +// //opt->mesh.writeMSH(ossI1.str().c_str()); +// success = opt->optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN, +// p.BARRIER_MAX, false, samples, p.itMax, p.optPassMax); +// if (success >= 0 && p.BARRIER_MIN_METRIC > 0) { +// Msg::Info("Jacobian optimization succeed, starting svd optimization"); +// success = opt->optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN_METRIC, +// p.BARRIER_MAX, true, samples, p.itMax, p.optPassMax); +// } +// +// // Measure min and max Jac., update mesh +// if ((success > 0) || (iterBlob == p.maxAdaptBlob-1)) { +// double minJac, maxJac, distMaxBND, distAvgBND; +// opt->recalcJacDist(); +// opt->getJacDist(minJac, maxJac, distMaxBND, distAvgBND); +// p.minJac = std::min(p.minJac,minJac); +// p.maxJac = std::max(p.maxJac,maxJac); +// opt->mesh.updateGEntityPositions(); +// } +// +// //std::ostringstream ossI2; +// //ossI2 << "final_ITER_" << iter << ".msh"; +// //temp.mesh.writeMSH(ossI2.str().c_str()); +// if (success <= 0) { +// distanceFactor *= p.adaptBlobDistFact; +// nbLayers *= p.adaptBlobLayerFact; +// Msg::Info("Blob %i failed (adapt #%i), adapting with increased size", +// iBadEl, iterBlob); +//// if (iterBlob == p.maxAdaptBlob-1) { +// std::ostringstream ossI2; +// ossI2 << "final_" << iBadEl << ".msh"; +// opt->mesh.writeMSH(ossI2.str().c_str()); +//// } +// } +// else break; + } //#pragma omp critical diff --git a/contrib/HighOrderMeshOptimizer/ParamCoord.cpp b/contrib/HighOrderMeshOptimizer/ParamCoord.cpp index 1361610e1d..97ce05ee4a 100644 --- a/contrib/HighOrderMeshOptimizer/ParamCoord.cpp +++ b/contrib/HighOrderMeshOptimizer/ParamCoord.cpp @@ -117,21 +117,106 @@ void ParamCoordParent::gXyz2gUvw(const SPoint3 &uvw, } -ParamCoordLocalLine::ParamCoordLocalLine(MVertex* v) : dir(0.) +namespace { + +SVector3 getLineElTangent(MElement *el, int iNode) { + + double gsf[1256][3], u, v, w; + el->getNode(iNode,u,v,w); +// el->getGradShapeFunctions(u,v,w,gsf); + el->getGradShapeFunctions(u,v,w,gsf,1); + + SVector3 dxyzdu(0.); +// int nSF = el->getNumShapeFunctions()(); + int nSF = el->getNumPrimaryVertices(); + for (int j=0; j<nSF; j++) { + const SPoint3 p = el->getVertex(j)->point(); + dxyzdu(0) += gsf[j][0]*p.x(); + dxyzdu(1) += gsf[j][0]*p.y(); + dxyzdu(2) += gsf[j][0]*p.z(); + } + dxyzdu.normalize(); + + return dxyzdu; + +} + +SVector3 getSurfElNormal(MElement *el, int iNode) { + + double gsf[1256][3], u, v, w; + el->getNode(iNode,u,v,w); +// el->getGradShapeFunctions(u,v,w,gsf); + el->getGradShapeFunctions(u,v,w,gsf,1); + + SVector3 dxyzdu(0.), dxyzdv(0.); +// int nSF = el->getNumShapeFunctions()(); + int nSF = el->getNumPrimaryVertices(); + for (int j=0; j<nSF; j++) { + const SPoint3 p = el->getVertex(j)->point(); + dxyzdu(0) += gsf[j][0]*p.x(); + dxyzdu(1) += gsf[j][0]*p.y(); + dxyzdu(2) += gsf[j][0]*p.z(); + dxyzdv(0) += gsf[j][1]*p.x(); + dxyzdv(1) += gsf[j][1]*p.y(); + dxyzdv(2) += gsf[j][1]*p.z(); + } + + SVector3 normal = crossprod(dxyzdu,dxyzdv); + normal.normalize(); + return normal; + +} + +} + +ParamCoordLocalLine::ParamCoordLocalLine(MVertex* v) : + dir(0.), x0(v->x()), y0(v->y()), z0(v->z()) { - GEdge *ge = static_cast<GEdge*>(v->onWhat()); + GEntity *ge = v->onWhat(); + const unsigned nEl = ge->getNumMeshElements(); - for (std::vector<MLine*>::iterator it = ge->lines.begin(); it != ge->lines.end(); it++) { + for (unsigned iEl = 0; iEl < nEl; iEl++) { + MElement *el = ge->getMeshElement(iEl); std::vector<MVertex*> lVerts; - (*it)->getVertices(lVerts); - if (std::find(lVerts.begin(),lVerts.end(),v) == lVerts.end()) { - SVector3 tan(lVerts[0]->point(),lVerts[1]->point()); - tan.normalize(); - dir += tan; + el->getVertices(lVerts); + std::vector<MVertex*>::iterator itV = std::find(lVerts.begin(),lVerts.end(),v); + if (itV != lVerts.end()) { + const int iNode = std::distance(lVerts.begin(),itV); + dir += getLineElTangent(el,iNode); } } - dir.normalize(); } + +ParamCoordLocalSurf::ParamCoordLocalSurf(MVertex* v) : x0(v->x()), y0(v->y()), z0(v->z()) +{ + + GEntity *ge = v->onWhat(); + const unsigned nEl = ge->getNumMeshElements(); + + SVector3 n(0.); + for (unsigned iEl = 0; iEl < nEl; iEl++) { + MElement *el = ge->getMeshElement(iEl); + std::vector<MVertex*> lVerts; + el->getVertices(lVerts); + std::vector<MVertex*>::iterator itV = std::find(lVerts.begin(),lVerts.end(),v); + if (itV != lVerts.end()) { + const int iNode = std::distance(lVerts.begin(),itV); + n += getSurfElNormal(el,iNode); + } + } + n.normalize(); + + if (fabs(fabs(dot(n,SVector3(1.,0.,0.)))-1.) < 1.e-10) { // If normal is x-axis, take y- and z- axis as dir. + dir0 = SVector3(0.,1.,0.); + dir1 = SVector3(0.,0.,1.); + } + else { + dir0 = SVector3(1.-n.x()*n.x(),-n.x()*n.y(),-n.x()*n.z()); // 1st dir. = (normalized) proj. of e_x in plane + dir0.normalize(); + dir1 = crossprod(dir0,n); + } + +} diff --git a/contrib/HighOrderMeshOptimizer/ParamCoord.h b/contrib/HighOrderMeshOptimizer/ParamCoord.h index 3c509cb83e..a0bb4f597e 100644 --- a/contrib/HighOrderMeshOptimizer/ParamCoord.h +++ b/contrib/HighOrderMeshOptimizer/ParamCoord.h @@ -65,23 +65,6 @@ public: } }; -class ParamCoordPhys2D : public ParamCoord -{ -public: - SPoint3 getUvw(MVertex* v) { return v->point(); } - SPoint3 uvw2Xyz(const SPoint3 &uvw) { return uvw; } - void gXyz2gUvw(const SPoint3 &uvw, const SPoint3 &gXyz, SPoint3 &gUvw) { gUvw = gXyz; } - void gXyz2gUvw(const SPoint3 &uvw, const std::vector<SPoint3> &gXyz, std::vector<SPoint3> &gUvw) - { - std::vector<SPoint3>::iterator itUvw=gUvw.begin(); - for (std::vector<SPoint3>::const_iterator itXyz=gXyz.begin(); itXyz != gXyz.end(); - itXyz++) { - *itUvw = *itXyz; - itUvw++; - } - } -}; - class ParamCoordParent : public ParamCoord { public: @@ -102,7 +85,9 @@ class ParamCoordLocalLine : public ParamCoord public: ParamCoordLocalLine(MVertex* v); SPoint3 getUvw(MVertex* v) { return SPoint3(0.,0.,0.); } - SPoint3 uvw2Xyz(const SPoint3 &uvw) { return SPoint3(uvw[0]*dir[0],uvw[0]*dir[1],uvw[0]*dir[2]); } + SPoint3 uvw2Xyz(const SPoint3 &uvw) { + return SPoint3(x0+uvw[0]*dir[0],y0+uvw[0]*dir[1],z0+uvw[0]*dir[2]); + } void gXyz2gUvw(const SPoint3 &uvw, const SPoint3 &gXyz, SPoint3 &gUvw) { gUvw[0] = gXyz.x()*dir[0] + gXyz.y()*dir[1] + gXyz.z()*dir[2]; } @@ -115,7 +100,36 @@ public: } } protected: + double x0, y0, z0; SVector3 dir; }; +class ParamCoordLocalSurf : public ParamCoord +{ +public: + ParamCoordLocalSurf(MVertex* v); + SPoint3 getUvw(MVertex* v) { return SPoint3(0.,0.,0.); } + SPoint3 uvw2Xyz(const SPoint3 &uvw) { + return SPoint3(x0+uvw[0]*dir0[0]+uvw[1]*dir1[0], + y0+uvw[0]*dir0[1]+uvw[1]*dir1[1], + z0+uvw[0]*dir0[2]+uvw[1]*dir1[2]); + } + void gXyz2gUvw(const SPoint3 &uvw, const SPoint3 &gXyz, SPoint3 &gUvw) { + gUvw[0] = gXyz.x()*dir0[0] + gXyz.y()*dir0[1] + gXyz.z()*dir0[2]; + gUvw[1] = gXyz.x()*dir1[0] + gXyz.y()*dir1[1] + gXyz.z()*dir1[2]; + } + void gXyz2gUvw(const SPoint3 &uvw, const std::vector<SPoint3> &gXyz, std::vector<SPoint3> &gUvw) { + std::vector<SPoint3>::iterator itUvw = gUvw.begin(); + for (std::vector<SPoint3>::const_iterator itXyz=gXyz.begin(); + itXyz != gXyz.end(); itXyz++) { + (*itUvw)[0] = itXyz->x()*dir0[0] + itXyz->y()*dir0[1] + itXyz->z()*dir0[2]; + (*itUvw)[1] = itXyz->x()*dir1[0] + itXyz->y()*dir1[1] + itXyz->z()*dir1[2]; + itUvw++; + } + } +protected: + double x0, y0, z0; + SVector3 dir0, dir1; +}; + #endif -- GitLab