From a2f6433e5d9c8326e6ff26b53386db6ac150af10 Mon Sep 17 00:00:00 2001 From: Thomas Toulorge <thomas.toulorge@mines-paristech.fr> Date: Thu, 4 Oct 2012 20:48:44 +0000 Subject: [PATCH] Changed determination of blobs for high-order mesh optimization (GUI still to be adapted) --- contrib/HighOrderMeshOptimizer/OptHomRun.cpp | 659 ++++++++----------- 1 file changed, 267 insertions(+), 392 deletions(-) diff --git a/contrib/HighOrderMeshOptimizer/OptHomRun.cpp b/contrib/HighOrderMeshOptimizer/OptHomRun.cpp index ec46317f4f..35b6fd192c 100644 --- a/contrib/HighOrderMeshOptimizer/OptHomRun.cpp +++ b/contrib/HighOrderMeshOptimizer/OptHomRun.cpp @@ -22,6 +22,8 @@ #include "FlGui.h" #endif + + void OptHomMessage (const char *s, ...) { char str[1024]; va_list args; @@ -39,16 +41,17 @@ void OptHomMessage (const char *s, ...) { } } else - fprintf(stdout,"%s\n",str); + fprintf(stdout,"%s\n", str); #else - fprintf(stdout,"%s\n",str); + fprintf(stdout,"%s\n", str); #endif } -// get all elements that are neighbors -double distMaxStraight (MElement *el){ +double distMaxStraight (MElement *el) +{ + const polynomialBasis *lagrange = el->getFunctionSpace(); const polynomialBasis *lagrange1 = el->getFunctionSpace(1); int nV = lagrange->points.size1(); @@ -68,23 +71,76 @@ double distMaxStraight (MElement *el){ for (int iV = nV1; iV < nV; iV++) { SVector3 d = el->getVertex(iV)->point()-sxyz[iV]; double dx = d.norm(); - if (dx > maxdx)maxdx=dx; + if (dx > maxdx) maxdx = dx; } + return maxdx; + +} + + + +SVector3 vecMaxStraight (MElement *el) +{ + + const polynomialBasis *lagrange = el->getFunctionSpace(); + const polynomialBasis *lagrange1 = el->getFunctionSpace(1); + int nV = lagrange->points.size1(); + int nV1 = lagrange1->points.size1(); + SPoint3 sxyz[256]; + for (int i = 0; i < nV1; ++i) { + sxyz[i] = el->getVertex(i)->point(); + } + for (int i = nV1; i < nV; ++i) { + double f[256]; + lagrange1->f(lagrange->points(i, 0), lagrange->points(i, 1), lagrange->points(i, 2), f); + for (int j = 0; j < nV1; ++j) + sxyz[i] += sxyz[j] * f[j]; + } + + double maxdx = 0.0; + SVector3 maxVec; + for (int iV = nV1; iV < nV; iV++) { + SVector3 d = el->getVertex(iV)->point()-sxyz[iV]; + double dx = d.norm(); + if (dx > maxdx) { + maxdx = dx; + maxVec = d; + } + } + + return maxVec; + +} + + + +static void PrintBlob (std::set<MElement*> &eles, int iTag){ + char name[256]; + sprintf(name,"BLOB%d.pos", iTag); + FILE *f = fopen (name,"w"); + fprintf(f,"View\"%s\"{\n", name); + for (std::set<MElement*>::iterator it = eles.begin(); it != eles.end();++it){ + (*it)->writePOS(f, true, false, false, false, false, false,1.0, iTag); + } + fprintf(f,"};\n"); + fclose(f); } + + void exportMeshToDassault (GModel *gm, const std::string &fn, int dim){ FILE *f = fopen(fn.c_str(),"w"); int numVertices = gm->indexMeshVertices(true); std::vector<GEntity*> entities; gm->getEntities(entities); - fprintf(f,"%d %d\n",numVertices,dim); + fprintf(f,"%d %d\n", numVertices, dim); for(unsigned int i = 0; i < entities.size(); i++) for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++){ MVertex *v = entities[i]->mesh_vertices[j]; - if (dim == 2)fprintf(f,"%d %22.15E %22.15E\n",v->getIndex(),v->x(),v->y()); - else if (dim == 3)fprintf(f,"%d %22.15E %22.15E %22.5E\n",v->getIndex(),v->x(),v->y(),v->z()); + if (dim == 2)fprintf(f,"%d %22.15E %22.15E\n", v->getIndex(), v->x(), v->y()); + else if (dim == 3)fprintf(f,"%d %22.15E %22.15E %22.5E\n", v->getIndex(), v->x(), v->y(), v->z()); } if (dim == 2){ @@ -95,15 +151,15 @@ void exportMeshToDassault (GModel *gm, const std::string &fn, int dim){ nt += tris.size(); if (tris.size())order = tris[0]->getPolynomialOrder(); } - fprintf(f,"%d %d\n",nt,(order+1)*(order+2)/2); + fprintf(f,"%d %d\n", nt,(order+1)*(order+2)/2); int count = 1; for (GModel::fiter itf = gm->firstFace(); itf != gm->lastFace(); ++itf){ std::vector<MTriangle*> &tris = (*itf)->triangles; for (size_t i=0;i<tris.size();i++){ MTriangle *t = tris[i]; - fprintf(f,"%d ",count++); + fprintf(f,"%d ", count++); for (int j=0;j<t->getNumVertices();j++){ - fprintf(f,"%d ",t->getVertex(j)->getIndex()); + fprintf(f,"%d ", t->getVertex(j)->getIndex()); } fprintf(f,"\n"); } @@ -113,15 +169,15 @@ void exportMeshToDassault (GModel *gm, const std::string &fn, int dim){ std::vector<MLine*> &l = (*ite)->lines; ne += l.size(); } - fprintf(f,"%d %d\n",ne,(order+1)); + fprintf(f,"%d %d\n", ne,(order+1)); count = 1; for (GModel::eiter ite = gm->firstEdge(); ite != gm->lastEdge(); ++ite){ std::vector<MLine*> &l = (*ite)->lines; for (size_t i=0;i<l.size();i++){ MLine *t = l[i]; - fprintf(f,"%d ",count++); + fprintf(f,"%d ", count++); for (int j=0;j<t->getNumVertices();j++){ - fprintf(f,"%d ",t->getVertex(j)->getIndex()); + fprintf(f,"%d ", t->getVertex(j)->getIndex()); } fprintf(f,"%d \n",(*ite)->tag()); } @@ -132,242 +188,136 @@ void exportMeshToDassault (GModel *gm, const std::string &fn, int dim){ -static void getTopologicalNeighbors(int nbLayers, - const std::vector<MElement*> &all, - const std::vector<MElement*> &elements, - std::set<MElement*> &result){ - - - std::set<MVertex*> touched; - - for (int i = 0; i < elements.size(); i++) - for (int j=0;j<elements[i]->getNumVertices();j++) - touched.insert(elements[i]->getVertex(j)); - - for (int layer = 0; layer < nbLayers; layer++) { - for (int i = 0; i < all.size(); i++) { - MElement *t = all[i]; - bool add_ = false; - for (int j = 0; j < t->getNumVertices(); j++) { - if (touched.find(t->getVertex(j)) != touched.end()) { - add_ = true; +static std::set<MVertex *> getBndVertices(std::set<MElement*> &elements, std::map<MVertex *, std::vector<MElement*> > &vertex2elements) +{ + std::set<MVertex*> bnd; + for (std::set<MElement*>::iterator itE = elements.begin(); itE != elements.end(); ++itE) { + for (int i = 0; i < (*itE)->getNumPrimaryVertices(); ++i) { + const std::vector<MElement*> &neighbours = vertex2elements[(*itE)->getVertex(i)]; + for (size_t k = 0; k < neighbours.size(); ++k) { + if (elements.find(neighbours[k]) == elements.end()) { + for (int j = 0; j < neighbours[k]->getNumVertices(); ++j) { + bnd.insert(neighbours[k]->getVertex(j)); + } } } - if (add_) result.insert(t); - } - for (std::set<MElement*>::iterator it = result.begin(); it != result.end(); ++it) { - for (int j = 0; j < (*it)->getNumVertices(); j++) { - touched.insert((*it)->getVertex(j)); - } } } - // printf("%d %d %d %d\n",all.size(),elements.size(), result.size(),nbLayers); - // exit(1); + return bnd; } -static void getGeometricalNeighbors (MElement *e, const std::vector<MElement*> &all, double F, std::set<MElement*> &result) { - double R = distMaxStraight (e); - SPoint3 p = e->barycenter_infty(); - for (int i = 0; i < all.size(); i++) { - MElement *e = all[i]; - double dist = p.distance(e->barycenter_infty()); - if (dist < R*F)result.insert(e); - } -} +static std::set<MElement*> getSurroundingBlob(MElement *el, int depth, std::map<MVertex *, std::vector<MElement*> > &vertex2elements, const double distFactor) +{ -static void intersection (const std::set<MElement*> &a, const std::set<MElement*> &b, std::set<MElement*> &result){ - for (std::set<MElement*>::const_iterator it = a.begin() ; it != a.end() ; ++it ){ - if (b.find(*it) != b.end()){ - result.insert(*it); - } - } -} + const SPoint3 p = el->barycenter_infty(); + const double limDist = distMaxStraight(el)*distFactor; + + std::set<MElement*> blob; + std::list<MElement*> currentLayer, lastLayer; -static void computeVertices (const std::set<MElement*> &a, std::set<MVertex*> &result){ - for (std::set<MElement*>::const_iterator it = a.begin() ; it != a.end() ; ++it ){ - for (int i=0;i<(*it)->getNumVertices();++i){ - result.insert((*it)->getVertex(i)); + blob.insert(el); + lastLayer.push_back(el); + for (int d = 0; d < depth; ++d) { + currentLayer.clear(); + for (std::list<MElement*>::iterator it = lastLayer.begin(); it != lastLayer.end(); ++it) { + for (int i = 0; i < (*it)->getNumPrimaryVertices(); ++i) { + const std::vector<MElement*> &neighbours = vertex2elements[(*it)->getVertex(i)]; + for (std::vector<MElement*>::const_iterator itN = neighbours.begin(); itN != neighbours.end(); ++itN) + if (p.distance((*itN)->barycenter_infty()) < limDist) + if (blob.insert(*itN).second) currentLayer.push_back(*itN); // Assume that if an el is too far, its neighbours are too far as well + } } + lastLayer = currentLayer; } -} -static MElement * compare_worst (MElement *a, MElement *b){ - if (!a)return b; - if (!b)return a; - if (a->distoShapeMeasure() < b->distoShapeMeasure()) return a; - return b; -} + return blob; -template <class ITERATOR> -MElement* getTheWorstElementDown (const ITERATOR &beg, const ITERATOR &end, double &q) { - MElement *worst = 0; - q = 1.e22; - ITERATOR it = beg; - for (;it != end;++it){ - MElement *t = *it; - double jmin,jmax; - t->scaledJacRange(jmin,jmax); - if (jmin < q) { - worst = t;q = jmin; - } - } - return worst; } -template <class ITERATOR> -MElement* getTheWorstElementUp (const ITERATOR &beg, const ITERATOR &end, double &q) { - MElement *worst = 0; - q = -1.e22; - ITERATOR it = beg; - for (;it != end;++it){ - MElement *t = *it; - double jmin,jmax; - t->scaledJacRange(jmin,jmax); - if (jmax > q) { - worst = t;q = jmax; - } - } - return worst; -} -static std::set<MVertex*> filterSimple(GEntity &ge, std::set<MElement*> &badElements, int nbLayers, std::set<MElement*> &result) + +// Returns max. dist. between primary vertices of an element +static double elementSize(MElement* el) { - std::vector<MElement*> allElements; - for (int i = 0; i < ge.getNumMeshElements(); ++i) - allElements.push_back(ge.getMeshElement(i)); - OptHomMessage("%d bad elements", badElements.size()); - getTopologicalNeighbors(nbLayers, allElements, std::vector<MElement*> (badElements.begin(), badElements.end()),result); - std::set<MVertex*> vs; - for (int i = 0; i < allElements.size(); i++) { - if (result.find(allElements[i]) == result.end()) { - for (int j = 0; j < allElements[i]->getNumVertices(); j++) { - vs.insert(allElements[i]->getVertex(j)); - } - } - } - return vs; -} -std::set<MVertex*> filter2D_boundaryLayer(GFace *gf, - int nbLayers, - double _qual_min, - double _qual_max, - double F , - std::set<MElement*> & badasses, - std::set<MElement*> & result - ) { - double jmin, jmax; - MElement *worstDown = getTheWorstElementDown(badasses.begin(),badasses.end(),jmin); - MElement *worstUp = getTheWorstElementUp(badasses.begin(),badasses.end(),jmax); - MElement *worst; - if (jmin < _qual_min)worst = worstDown; - else worst = worstUp; - - // MElement *worst = compare_worst (getTheWorstElement(gf->triangles), - // getTheWorstElement(gf->quadrangles)); - - std::vector<MElement*> vworst; vworst.push_back(worst); - std::vector<MElement*> all; - all.insert(all.begin(),gf->triangles.begin(),gf->triangles.end()); - all.insert(all.begin(),gf->quadrangles.begin(),gf->quadrangles.end()); - std::set<MElement*> result1; - getTopologicalNeighbors(nbLayers, all, vworst,result1); - std::set<MElement*> result2; - getGeometricalNeighbors (worst, all, F, result2); - intersection (result1,result2,result); - // printf("intsersection(%d,%d) = %d\n",result1.size(),result2.size(),result.size()); - - std::set<MVertex*> vs; - for (int i = 0; i < all.size(); i++) { - if (result.find(all[i]) == result.end()) { - for (int j = 0; j < all[i]->getNumVertices(); j++) { - vs.insert(all[i]->getVertex(j)); - } - } - } - return vs; -} + std::vector<SPoint3> vert; + vert.reserve(el->getNumPrimaryVertices()); + for (int i = 0; i < el->getNumPrimaryVertices(); i++) vert.push_back(el->getVertex(i)->point()); + double maxDistSq = 0; + for (int i = 0; i < el->getNumPrimaryVertices()-1; i++) + for (int j = i+1; j < el->getNumPrimaryVertices(); j++) + maxDistSq = std::max(maxDistSq, SVector3(vert[j]-vert[i]).normSq()); -std::set<MVertex*> filter3D_boundaryLayer(GRegion *gr, - int nbLayers, - double _qual_min, - double _qual_max, - double F, - std::set<MElement *> &result) { - double jmin,jmax; - MElement *worst = compare_worst (getTheWorstElementDown(gr->tetrahedra.begin(),gr->tetrahedra.end(),jmin), - getTheWorstElementDown(gr->prisms.begin(),gr->prisms.end(),jmin)); - worst = compare_worst (worst,getTheWorstElementDown(gr->hexahedra.begin(),gr->hexahedra.end(),jmin)); - - std::vector<MElement*> vworst; vworst.push_back(worst); - std::vector<MElement*> all; - all.insert(all.begin(),gr->tetrahedra.begin(),gr->tetrahedra.end()); - all.insert(all.begin(),gr->prisms.begin(),gr->prisms.end()); - all.insert(all.begin(),gr->hexahedra.begin(),gr->hexahedra.end()); - std::set<MElement*> result1; - getTopologicalNeighbors(nbLayers, all, vworst,result1); - std::set<MElement*> result2; - getGeometricalNeighbors (worst, all, F, result2); - intersection (result1,result2,result); - // printf("intsersection(%d,%d) = %d\n",result1.size(),result2.size(),result.size()); - - std::set<MVertex*> vs; - for (int i = 0; i < all.size(); i++) { - if (result.find(all[i]) == result.end()) { - for (int j = 0; j < all[i]->getNumVertices(); j++) { - vs.insert(all[i]->getVertex(j)); - } - } - } - return vs; -} + return sqrt(maxDistSq); -static std::set<MVertex *> getBndVertices(std::set<MElement*> &elements, std::map<MVertex *, std::vector<MElement*> > &vertex2elements) -{ - std::set<MVertex*> bnd; - for (std::set<MElement*>::iterator itE = elements.begin(); itE != elements.end(); ++itE) { - for (int i = 0; i < (*itE)->getNumPrimaryVertices(); ++i) { - const std::vector<MElement*> &neighbours = vertex2elements[(*itE)->getVertex(i)]; - for (size_t k = 0; k < neighbours.size(); ++k) { - if (elements.find(neighbours[k]) == elements.end()) { - for (int j = 0; j < neighbours[k]->getNumVertices(); ++j) { - bnd.insert(neighbours[k]->getVertex(j)); - } - } - } - } - } - return bnd; } -static std::set<MElement*> getSurroundingBlob(MElement *el, int depth, std::map<MVertex *, std::vector<MElement*> > &vertex2elements) + + +static std::set<MElement*> getSurroundingBlob_BL(MElement *el, int depth, std::map<MVertex *, std::vector<MElement*> > &vertex2elements, const double distFactor) { - std::set<MElement *> blob; - std::set<MElement *> currentLayer, lastLayer; + + const SPoint3 p = el->barycenter_infty(); + const double halfElSize = 0.5*elementSize(el); +//std::cout << "El. " << el->getNum() << " -> halfElSize = " << halfElSize << "\n"; + SVector3 dir = vecMaxStraight(el); + dir.normalize(); +//std::cout << "El. " << el->getNum() << " -> direction (" << dir(0) << ", " << dir(1) << ", " << dir(2) << ")\n"; + + std::set<MElement*> blob; + std::list<MElement*> currentLayer, lastLayer; + blob.insert(el); - lastLayer.insert(el); + lastLayer.push_back(el); for (int d = 0; d < depth; ++d) { - for (std::set<MElement *>::iterator it = lastLayer.begin(); it != lastLayer.end(); ++it) { - for (int i = 0; i < (*it)->getNumPrimaryVertices(); ++i){ + currentLayer.clear(); + for (std::list<MElement*>::iterator it = lastLayer.begin(); it != lastLayer.end(); ++it) { + for (int i = 0; i < (*it)->getNumPrimaryVertices(); ++i) { const std::vector<MElement*> &neighbours = vertex2elements[(*it)->getVertex(i)]; - for (size_t k = 0; k < neighbours.size(); ++k) { - if (blob.find(neighbours[k]) != blob.end()) - continue; - blob.insert(neighbours[k]); - currentLayer.insert(neighbours[k]); + for (std::vector<MElement*>::const_iterator itN = neighbours.begin(); itN != neighbours.end(); ++itN) { + const SVector3 barBar = (*itN)->barycenter_infty()-p; + const SVector3 barProj = dir*dot(dir, barBar); + double projDist = (barBar-barProj).norm(); +//std::cout << "El. " << el->getNum() << ", d = " << d << ", i = " << i << ", projDist = " << projDist << "\n"; + double elSize2 = elementSize(*itN); + if (projDist <= halfElSize+elSize2) + if (blob.insert(*itN).second) currentLayer.push_back(*itN); // Assume that if an el is too far, its neighbours are too far as well } } } lastLayer = currentLayer; } + +//std::cout << " -> Blob of " << blob.size() << " elements\n"; return blob; + +} + + + +static void addBlobChaintoGroup(std::set<int> &group, const std::vector<std::set<int> > &groupConnect, std::vector<bool> &todoPB, int iB) +{ + + if (todoPB[iB]) { + todoPB[iB] = false; + group.insert(iB); + const std::set<int> &connect = groupConnect[iB]; + for (std::set<int>::iterator itBC = connect.begin(); itBC != connect.end(); ++itBC) + addBlobChaintoGroup(group, groupConnect, todoPB, *itBC); + } + } -static std::vector<std::pair<std::set<MElement*> , std::set<MVertex*> > > getConnectedBlobs(GEntity &entity, const std::set<MElement*> &badElements, int depth) + + +static std::vector<std::pair<std::set<MElement*> , std::set<MVertex*> > > getConnectedBlobs(GEntity &entity, const std::set<MElement*> &badElements, int depth, const double distFactor) { + + // Compute vertex -> element connectivity +// std::cout << "Computing vertex -> element connectivity...\n"; std::map<MVertex*, std::vector<MElement *> > vertex2elements; for (size_t i = 0; i < entity.getNumMeshElements(); ++i) { MElement &element = *entity.getMeshElement(i); @@ -375,45 +325,69 @@ static std::vector<std::pair<std::set<MElement*> , std::set<MVertex*> > > getCon vertex2elements[element.getVertex(j)].push_back(&element); } } - std::vector<std::pair<std::set<MElement *>, std::set<MVertex*> > > result; - std::set<MElement *> badElementsDone; + + // Contruct primary blobs +// std::cout << "Constructing " << badElements.size() << " primary blobs...\n"; + std::vector<std::set<MElement*> > primBlobs; + primBlobs.reserve(badElements.size()); for (std::set<MElement*>::const_iterator it = badElements.begin(); it != badElements.end(); ++it) { - if(badElementsDone.find(*it) != badElementsDone.end()) - continue; - std::stack<MElement*> todo; - todo.push(*it); - result.resize(result.size() + 1); - while (!todo.empty()) { - MElement *el = todo.top(); - todo.pop(); - if(badElementsDone.find(el) == badElementsDone.end()) { - std::set<MElement*> blob = getSurroundingBlob(el, depth, vertex2elements); - for (std::set<MElement*>::iterator itE = blob.begin(); itE != blob.end(); ++itE) { - if(badElements.find(*itE) != badElements.end()) - todo.push(*itE); - } - badElementsDone.insert(el); - result.back().first.insert(blob.begin(), blob.end()); + primBlobs.push_back(getSurroundingBlob(*it, depth, vertex2elements, distFactor)); +// blobs.push_back(getSurroundingBlob_BL(*it, depth, vertex2elements, distFactor)); + } + + + // Compute blob connectivity +// std::cout << "Computing blob connectivity...\n"; + std::map<MElement*, std::set<int> > tags; + std::vector<std::set<int> > blobConnect(primBlobs.size()); + for (int iB = 0; iB < primBlobs.size(); ++iB) { + std::set<MElement*> &blob = primBlobs[iB]; + for(std::set<MElement*>::iterator itEl = blob.begin(); itEl != blob.end(); ++itEl) { + std::set<int> &blobInd = tags[*itEl]; + if (!blobInd.empty()) { + for (std::set<int>::iterator itBS = blobInd.begin(); itBS != blobInd.end(); ++itBS) blobConnect[*itBS].insert(iB); + blobConnect[iB].insert(blobInd.begin(), blobInd.end()); } + blobInd.insert(iB); } - result.back().second = getBndVertices(result.back().first, vertex2elements); } - return result; -} + // Identify groups of connected blobs +// std::cout << "Identifying groups of primary blobs...\n"; + std::list<std::set<int> > groups; + std::vector<bool> todoPB(primBlobs.size(), true); + for (int iB = 0; iB < primBlobs.size(); ++iB) + if (todoPB[iB]) { + std::set<int> group; + addBlobChaintoGroup(group, blobConnect, todoPB, iB); + groups.push_back(group); + } -static void PrintBlob (std::set<MElement*> &eles, int iTag){ - char name[256]; - sprintf(name,"BLOB%d.pos",iTag); - FILE *f = fopen (name,"w"); - fprintf(f,"View\"%s\"{\n",name); - for (std::set<MElement*>::iterator it = eles.begin(); it != eles.end();++it){ - (*it)->writePOS(f,true,false,false,false,false,false,1.0,iTag); + // Merge primary blobs according to groups +// std::cout << "Merging primary blobs into " << groups.size() << " blobs...\n"; + std::list<std::set<MElement*> > blobs; + for (std::list<std::set<int> >::iterator itG = groups.begin(); itG != groups.end(); ++itG) { + blobs.push_back(std::set<MElement*>()); + for (std::set<int>::iterator itB = itG->begin(); itB != itG->end(); ++itB) { + std::set<MElement*> primBlob = primBlobs[*itB]; + blobs.back().insert(primBlob.begin(), primBlob.end()); + } } - fprintf(f,"};\n"); - fclose(f); + + // Store and compute blob boundaries +// std::cout << "Storing and computing boundaries for " << blobs.size() << " blobs...\n"; + std::vector<std::pair<std::set<MElement *>, std::set<MVertex*> > > result; + for (std::list<std::set<MElement*> >::iterator itB = blobs.begin(); itB != blobs.end(); ++itB) + result.push_back(std::pair<std::set<MElement*>, std::set<MVertex*> >(*itB, getBndVertices(*itB, vertex2elements))); + +// std::cout << "Done with blobs\n"; + + return result; + } + + void HighOrderMeshOptimizer (GModel *gm, OptHomParameters &p) { @@ -421,9 +395,6 @@ void HighOrderMeshOptimizer (GModel *gm, OptHomParameters &p) int samples = 30; -// int method = Mesh::METHOD_RELAXBND | Mesh::METHOD_PHYSCOORD | Mesh::METHOD_PROJJAC; -// int method = Mesh::METHOD_FIXBND | Mesh::METHOD_PHYSCOORD | Mesh::METHOD_PROJJAC; -// int method = Mesh::METHOD_FIXBND | Mesh::METHOD_SURFCOORD | Mesh::METHOD_PROJJAC; int method = 0; if (p.method == 0) method = Mesh::METHOD_FIXBND | Mesh::METHOD_PROJJAC; @@ -434,161 +405,65 @@ void HighOrderMeshOptimizer (GModel *gm, OptHomParameters &p) else if(p.method < 0) method = -p.method; - // printf("p.method = %d\n",p.method); - -// int method = Mesh::METHOD_SURFCOORD | Mesh::METHOD_PROJJAC; -// int method = Mesh::METHOD_RELAXBND | Mesh::METHOD_SURFCOORD | Mesh::METHOD_PROJJAC; -// int method = Mesh::METHOD_PROJJAC; - SVector3 BND(gm->bounds().max(), gm->bounds().min()); OptHomMessage("High order mesh optimizer starts"); + std::vector<GEntity*> entities; + gm->getEntities(entities); - if (p.filter == 0) { - std::vector<GEntity*> entities; - gm->getEntities(entities); - for (int i = 0; i < entities.size(); ++i) { - double tf1 = Cpu();; - GEntity &entity = *entities[i]; - if (entity.dim() != p.dim || (p.onlyVisible && !entity.getVisibility())) - continue; - OptHomMessage("Optimizing Model entity %4d...", entity.tag()); - std::set<MElement*> badasses; - for (int i = 0; i < entity.getNumMeshElements();i++){ - double jmin,jmax; - //entity.getMeshElement(i)->scaledJacRange(jmin,jmax); - jmin = jmax = entity.getMeshElement(i)->distoShapeMeasure(); - if (jmin < p.BARRIER_MIN || jmax > p.BARRIER_MAX) - badasses.insert(entity.getMeshElement(i)); - } - if (badasses.empty()) - continue; - std::vector<std::pair<std::set<MElement*>, std::set<MVertex*> > > toOptimize = getConnectedBlobs(entity, badasses, p.nbLayers); - //#pragma omp parallel for schedule(dynamic, 1) - p.SUCCESS = 1; - for (int i = 0; i < toOptimize.size(); ++i) { - PrintBlob (toOptimize[i].first, i+1); - OptHomMessage("Optimizing a blob %i/%i composed of %4d elements", i+1, toOptimize.size(), toOptimize[i].first.size()); - fflush(stdout); - OptHOM temp(&entity, toOptimize[i].first, toOptimize[i].second, method); - int success = temp.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) { - OptHomMessage("jacobian optimization succeed, starting svd optimization"); - success = temp.optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN_METRIC, p.BARRIER_MAX, true, samples, p.itMax, p.optPassMax); - } - temp.mesh.updateGEntityPositions(); - if (success <= 0) { - std::ostringstream ossI2; - ossI2 << "final_" << entity.tag() << "ITER_" << i << ".msh"; - temp.mesh.writeMSH(ossI2.str().c_str()); - } - //#pragma omp critical - p.SUCCESS = std::min(p.SUCCESS, success); - } - double DTF = Cpu()-tf1; - if (p.SUCCESS == 1) - OptHomMessage("Optimization succeeded for entity %d (CPU %g sec)", entity.tag(), DTF); - else if (p.SUCCESS == 0) - OptHomMessage("Warning : Model entity %4d has all jacobians positive but not all in the range CPU %g",entity.tag(),DTF); - else if (p.SUCCESS == -1) - OptHomMessage("Error : Model entity %4d has still negative jacobians",entity.tag()); - } - } - else { - double distMaxBND, distAvgBND, minJac, maxJac; - if (p.dim == 2) { - double tf1 = Cpu();; - for (GModel::fiter itf = gm->firstFace(); itf != gm->lastFace(); ++itf) { - if (p.onlyVisible && !(*itf)->getVisibility())continue; - int ITER = 0; - OptHomMessage("Optimizing Model face %4d...",(*itf)->tag()); - p.SUCCESS = 1; - std::set<MElement*> badasses; - for (int i=0;i<(*itf)->getNumMeshElements();i++){ - double jmin,jmax; - (*itf)->getMeshElement(i)->scaledJacRange(jmin,jmax); - if (jmin < p.BARRIER_MIN || jmax > p.BARRIER_MAX)badasses.insert((*itf)->getMeshElement(i)); - } - // printf("START WITH %d bad asses\n",badasses.size()); - if (badasses.size() == 0)continue; - while (1){ - std::set<MVertex*> toFix; - std::set<MElement*> toOptimize; - - toFix = filter2D_boundaryLayer(*itf, p.nbLayers, p.BARRIER_MIN, p.BARRIER_MAX, p.DistanceFactor, badasses, toOptimize); - OptHOM temp(*itf, toOptimize, toFix, method); - - temp.recalcJacDist(); - temp.getJacDist(minJac, maxJac, distMaxBND, distAvgBND); - // if (minJac < 1.e2)OptHomMessage("Optimizing a blob of %4d elements minJ %12.5E -- maxJ %12.5E",(*itf)->getNumMeshElements(), minJac, maxJac); - std::ostringstream ossI; - ossI << "initial_" << (*itf)->tag() << "ITER_" << ITER << ".msh"; - temp.mesh.writeMSH(ossI.str().c_str()); - if (minJac > p.BARRIER_MIN && maxJac < p.BARRIER_MAX) break; - - p.SUCCESS = std::min(p.SUCCESS,temp.optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN, p.BARRIER_MAX, false, samples, p.itMax, p.optPassMax)); - - // temp.recalcJacDist(); - // temp.getJacDist(minJac, maxJac, distMaxBND, distAvgBND); - temp.mesh.updateGEntityPositions(); - if (p.SUCCESS == -1) break; - ITER ++; - if (p.filter == 1 && ITER > badasses.size() * 2)break; - - // std::ostringstream ossF; - // ossF << "final_" << (*itf)->tag() << ".msh"; - // temp.mesh.writeMSH(ossF.str().c_str()); - PrintBlob (toOptimize, ITER); - } - double DTF = Cpu()-tf1; - if (p.SUCCESS == 1){ - OptHomMessage("Optimization succeeded (CPU %g sec)",DTF); - } - else if (p.SUCCESS == 0) - OptHomMessage("Warning : Model face %4d has all jacobians positive but not all in the range CPU %g",(*itf)->tag(),DTF); - else if (p.SUCCESS == -1) - OptHomMessage("Error : Model face %4d has still negative jacobians",(*itf)->tag()); + for (int i = 0; i < entities.size(); ++i) { - Msg::Info("---------------------------------------------------------------------------------------------------------------"); - } - exportMeshToDassault (gm,gm->getName() + "_opti.das", 2); + double tf1 = Cpu(); + GEntity &entity = *entities[i]; + + if (entity.dim() != p.dim || (p.onlyVisible && !entity.getVisibility())) continue; + + OptHomMessage("Optimizing Model entity %4d...", entity.tag()); + std::set<MElement*> badasses; + for (int i = 0; i < entity.getNumMeshElements();i++) { + double jmin, jmax; + entity.getMeshElement(i)->scaledJacRange(jmin, jmax); + if (p.BARRIER_MIN_METRIC > 0) jmax = jmin; + if (jmin < p.BARRIER_MIN || jmax > p.BARRIER_MAX) + badasses.insert(entity.getMeshElement(i)); } - else if (p.dim == 3) { - for (GModel::riter itr = gm->firstRegion(); itr != gm->lastRegion(); ++itr) { - if (p.onlyVisible && !(*itr)->getVisibility())continue; - int ITER = 0; - Msg::Info("Model region %4d is considered",(*itr)->tag()); - p.SUCCESS = true; - while (1){ - std::set<MVertex*> toFix; - std::set<MElement*> toOptimize; - - toFix = filter3D_boundaryLayer(*itr, p.nbLayers, p.BARRIER_MIN, p.BARRIER_MAX, p.DistanceFactor, toOptimize); - - // if ((*itr)->tetrahedra.size() > 0) { - OptHOM temp(*itr, toOptimize, toFix, method); - double distMaxBND, distAvgBND, minJac, maxJac; - temp.recalcJacDist(); - temp.getJacDist(minJac, maxJac, distMaxBND, distAvgBND); - if (minJac < 1.e2)Msg::Info("Optimizing a blob of %4d elements minJ %12.5E -- maxJ %12.5E",(*itr)->getNumMeshElements(), minJac, maxJac); - std::ostringstream ossI; - ossI << "initial_" << (*itr)->tag() << "ITER_" << ITER << ".msh"; - temp.mesh.writeMSH(ossI.str().c_str()); - if (minJac > p.BARRIER_MIN && maxJac < p.BARRIER_MAX) break; - p.SUCCESS = temp.optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN, p.BARRIER_MAX, false, samples, p.itMax, p.optPassMax); - temp.recalcJacDist(); - temp.getJacDist(minJac, maxJac, distMaxBND, distAvgBND); - temp.mesh.updateGEntityPositions(); - if (!p.SUCCESS) break; - // } - ITER ++; - } - Msg::Info("Model region %4d is done (%d subdomains were computed) SUCCESS %1d",(*itr)->tag(),ITER,p.SUCCESS); - Msg::Info("----------------------------------------------------------------"); - // temp.mesh.writeMSH("final.msh"); + if (badasses.empty()) continue; + + std::vector<std::pair<std::set<MElement*>, std::set<MVertex*> > > toOptimize = getConnectedBlobs(entity, badasses, p.nbLayers, p.DistanceFactor); + + //#pragma omp parallel for schedule(dynamic, 1) + p.SUCCESS = 1; + for (int i = 0; i < toOptimize.size(); ++i) { +//PrintBlob (toOptimize[i].first, i+1); + OptHomMessage("Optimizing a blob %i/%i composed of %4d elements", i+1, toOptimize.size(), toOptimize[i].first.size()); + fflush(stdout); + OptHOM temp(&entity, toOptimize[i].first, toOptimize[i].second, method); + int success = temp.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) { + OptHomMessage("Jacobian optimization succeed, starting svd optimization"); + success = temp.optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN_METRIC, p.BARRIER_MAX, true, samples, p.itMax, p.optPassMax); } + temp.mesh.updateGEntityPositions(); + if (success <= 0) { + std::ostringstream ossI2; + ossI2 << "final_" << entity.tag() << "ITER_" << i << ".msh"; + temp.mesh.writeMSH(ossI2.str().c_str()); + } + //#pragma omp critical + p.SUCCESS = std::min(p.SUCCESS, success); } + + double DTF = Cpu()-tf1; + if (p.SUCCESS == 1) + OptHomMessage("Optimization succeeded for entity %d (CPU %g sec)", entity.tag(), DTF); + else if (p.SUCCESS == 0) + OptHomMessage("Warning : Model entity %4d has all jacobians positive but not all in the range (CPU %g sec)", entity.tag(), DTF); + else if (p.SUCCESS == -1) + OptHomMessage("Error : Model entity %4d has still negative jacobians (CPU %g sec)", entity.tag(), DTF); + } + double t2 = Cpu(); p.CPU = t2-t1; + } -- GitLab