diff --git a/Fltk/classificationEditor.cpp b/Fltk/classificationEditor.cpp index db7ccb344527cfa1cb05774ad8750afeebd6c9a6..d61509385d2b8aab1bcd2f811cbcddb951f974f7 100644 --- a/Fltk/classificationEditor.cpp +++ b/Fltk/classificationEditor.cpp @@ -196,29 +196,6 @@ static void class_ok_cb(Fl_Widget *w, void *data) Msg::StatusBar(3, false, ""); } -static int maxEdgeNum() -{ - GModel::eiter it = GModel::current()->firstEdge(); - GModel::eiter ite = GModel::current()->lastEdge(); - int MAXX = 0; - while(it != ite){ - MAXX = std::max(MAXX, (*it)->tag()); - ++it; - } - return MAXX; -} - -static int maxFaceNum() -{ - GModel::fiter it = GModel::current()->firstFace(); - GModel::fiter ite = GModel::current()->lastFace(); - int MAXX = 0; - while(it != ite){ - MAXX = std::max(MAXX, (*it)->tag()); - ++it; - } - return MAXX; -} struct compareMLinePtr { @@ -263,7 +240,7 @@ static GEdge *getNewModelEdge(GFace *gf1, GFace *gf2, std::map<std::pair<int, int>, GEdge*>::iterator it = newEdges.find(std::make_pair<int, int>(i1, i2)); if(it == newEdges.end()){ - discreteEdge *temporary = new discreteEdge(GModel::current(), maxEdgeNum() + 1, 0, 0); + discreteEdge *temporary = new discreteEdge(GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0); printf("add new edge gf1=%d gf2=%d \n", t1, t2); GModel::current()->add(temporary); newEdges[std::make_pair<int, int>(i1, i2)] = temporary; @@ -343,7 +320,7 @@ static void class_color_cb(Fl_Widget* w, void* data) std::list<MTri3*> ::iterator it = tris.begin(); while(it != tris.end()){ if(!(*it)->isDeleted()){ - discreteFace *temporary = new discreteFace(GModel::current(), maxFaceNum() + 1); + discreteFace *temporary = new discreteFace(GModel::current(), GModel::current()->maxFaceNum() + 1); recurClassify(*it, temporary, lines, reverse); GModel::current()->add(temporary); } @@ -372,7 +349,7 @@ static void class_color_cb(Fl_Widget* w, void* data) for (std::map<std::pair<int, int>, GEdge*>::iterator it = newEdges.begin() ; it != newEdges.end() ; ++it){ GEdge *ge = it->second; - printf("NEW edge with tag = %d \n", ge->tag()); + //printf("NEW edge with tag = %d \n", ge->tag()); std::list<MLine*> segments; for (unsigned int i = 0; i < ge->lines.size(); i++){ @@ -381,25 +358,20 @@ static void class_color_cb(Fl_Widget* w, void* data) //for each actual GEdge while (!segments.empty()) { - std::vector<MLine*> myLines; std::list<MLine*>::iterator it = segments.begin(); - MVertex *vB = (*it)->getVertex(0); MVertex *vE = (*it)->getVertex(1); myLines.push_back(*it); segments.erase(it); it++; - //printf("***candidate mline %d %d of size %d \n", vB->getNum(), vE->getNum(), segments.size()); for (int i=0; i<2; i++) { - for (std::list<MLine*>::iterator it = segments.begin() ; it != segments.end(); ++it){ MVertex *v1 = (*it)->getVertex(0); MVertex *v2 = (*it)->getVertex(1); //printf("mline %d %d \n", v1->getNum(), v2->getNum()); - std::list<MLine*>::iterator itp; if ( v1 == vE ){ //printf("->push back this mline \n"); @@ -419,39 +391,22 @@ static void class_color_cb(Fl_Widget* w, void* data) vE = v1; i=-1; } - if (it == segments.end()) break; - } - if (vB == vE) break; - if (segments.empty()) break; - //printf("not found VB=%d vE=%d\n", vB->getNum(), vE->getNum()); MVertex *temp = vB; vB = vE; vE = temp; //printf("not found VB=%d vE=%d\n", vB->getNum(), vE->getNum()); - } - -// printf("************ CANDIDATE NEW EDGE \n"); -// for (std::vector<MLine*>::iterator it = myLines.begin() ; it != myLines.end() ; ++it){ -// MVertex *v1 = (*it)->getVertex(0); -// MVertex *v2 = (*it)->getVertex(1); -// printf("Line %d %d \n", v1->getNum(), v2->getNum()); -// } - GEdge *newGe = new discreteEdge(GModel::current(), maxEdgeNum() + 1, 0, 0); + GEdge *newGe = new discreteEdge(GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0); newGe->lines.insert(newGe->lines.end(), myLines.begin(), myLines.end()); GModel::current()->add(newGe); - printf("create new edge with tag =%d\n", maxEdgeNum()); - }//end for each actual GEdge - } - - printf("end new edge with tag \n"); + //printf("end new edge with tag \n"); for (std::map<std::pair<int, int>, GEdge*>::iterator it = newEdges.begin() ; it != newEdges.end() ; ++it){ GEdge *ge = it->second; @@ -716,9 +671,9 @@ classificationEditor::classificationEditor() // saved for the ones that have been saved by the user // and that will be used for next step - temporary = new discreteEdge(GModel::current(), maxEdgeNum() + 1, 0, 0); + temporary = new discreteEdge(GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0); GModel::current()->add(temporary); - saved = new discreteEdge(GModel::current(), maxEdgeNum() + 1, 0, 0); + saved = new discreteEdge(GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0); GModel::current()->add(saved); _window->end(); diff --git a/Fltk/classificationEditor.h b/Fltk/classificationEditor.h index 9c9b32633546ec1b9c4db05ded65a80cc3036fa1..8b51e09ee10bc4896f3efef233eb9a6aa8a533f9 100644 --- a/Fltk/classificationEditor.h +++ b/Fltk/classificationEditor.h @@ -10,6 +10,7 @@ #include <FL/Fl_Toggle_Button.H> #include <FL/Fl_Round_Button.H> #include <FL/Fl_Window.H> +#include <FL/Fl_Value_Input.H> #include "GModel.h" #include "MElement.h" #include "ColorTable.h" diff --git a/Geo/GEdgeCompound.cpp b/Geo/GEdgeCompound.cpp index 33214081625cc2b07813c049668a63a34290f5d5..74900f2711c358b9eea093be68f022a8d978add8 100644 --- a/Geo/GEdgeCompound.cpp +++ b/Geo/GEdgeCompound.cpp @@ -25,7 +25,15 @@ GEdgeCompound::GEdgeCompound(GModel *m, int tag, std::vector<GEdge*> &compound, for (unsigned int i = 0; i < _compound.size(); i++) _compound[i]->setCompound(this); - parametrize(); + for(std::vector<GEdge*>::iterator it = _compound.begin(); it != _compound.end(); ++it){ + if(!(*it)){ + Msg::Error("Incorrect edge in compound edge %d\n", tag); + Msg::Exit(1); + } + } + + parametrize(); + } GEdgeCompound::GEdgeCompound(GModel *m, int tag, std::vector<GEdge*> &compound) diff --git a/Geo/GFace.h b/Geo/GFace.h index 35404222159af861122b4a1e310068ae2927717e..1eb20a716879e58b39ea2b9663e7aed2466565c7 100644 --- a/Geo/GFace.h +++ b/Geo/GFace.h @@ -124,6 +124,7 @@ class GFace : public GEntity int poincareMesh (); int genusMesh () { return (poincareMesh() + edgeLoops.size() - 2) / 2; } virtual int genusGeom (); + virtual bool checkTopology() = 0 ; // return the point on the face corresponding to the given parameter virtual GPoint point(double par1, double par2) const = 0; diff --git a/Geo/GFaceCompound.cpp b/Geo/GFaceCompound.cpp index a7e18bc7449b11f8d0a5a723313c636af680d275..9af2f27800c35e3715e1c28f45cfc7d4835b0a5a 100644 --- a/Geo/GFaceCompound.cpp +++ b/Geo/GFaceCompound.cpp @@ -27,6 +27,13 @@ #include "linearSystemCSR.h" #include "linearSystemFull.h" #include "linearSystemPETSc.h" +#include "meshPartitionOptions.h" +#include "meshPartition.h" +#include "CreateFile.h" +#include "Context.h" +#include "meshGFace.h" +#include "meshGEdge.h" +#include "discreteFace.h" static void fixEdgeToValue(GEdge *ed, double value, dofManager<double, double> &myAssembler) { @@ -194,6 +201,10 @@ bool GFaceCompound::trivial() const bool GFaceCompound::checkOrientation() const { + + //Only check orientation for stl files (1 patch) + if(_compound.size() > 1.0) return true; + std::list<GFace*>::const_iterator it = _compound.begin(); double a_old = 0, a_new; bool oriented = true; @@ -292,8 +303,8 @@ void GFaceCompound::one2OneMap() const // printf("Kernel CG: ucg=%g vcg=%g \n", u_cg, v_cg); // bool testbadCavity = checkCavity(vTri); -// if(testbadCavity == true ) printf("**** New cavity is KO \n"); -// else printf("-- New cavity is OK \n"); +// if(testbadCavity == true ) printf("**** New cavity is KOÂ \n"); +// else printf("-- New cavity is OKÂ \n"); // for(int i=0; i< vTri.size(); i++){ // MTriangle *t = (MTriangle*) vTri[i]; @@ -327,6 +338,7 @@ void GFaceCompound::parametrize() const if(trivial()) return; if(!oct){ + coordinates.clear(); //Laplace parametrization @@ -344,10 +356,9 @@ void GFaceCompound::parametrize() const //----------------- //compute_distance(); - //checkOrientation(); - computeNormals(); buildOct(); - + checkOrientation(); + computeNormals(); } } @@ -357,9 +368,13 @@ void GFaceCompound::getBoundingEdges() for(std::list<GFace*>::iterator it = _compound.begin(); it != _compound.end(); ++it){ (*it)->setCompound(this); } - - //in case the bounding edges are explicitely given + + std::set<GEdge*> _unique; + getUniqueEdges(_unique); + std::set<GEdge*>::iterator itf = _unique.begin(); + if(_U0.size()){ + //in case the bounding edges are explicitely given std::list<GEdge*>::const_iterator it = _U0.begin(); for( ; it != _U0.end() ; ++it){ l_edges.push_back(*it); @@ -370,23 +385,22 @@ void GFaceCompound::getBoundingEdges() l_edges.push_back(*it); (*it)->addFace(this); } - return; + std::list<GEdge*> loop; + computeALoop(_unique, loop); + while(!_unique.empty()) computeALoop(_unique,loop); } - - std::set<GEdge*> _unique; - getUniqueEdges(_unique); - std::set<GEdge*>::iterator itf = _unique.begin(); - for( ; itf != _unique.end(); ++itf){ - l_edges.push_back(*itf); - (*itf)->addFace(this); + else{ + //in case the bounding edges are NOT explicitely given + for( ; itf != _unique.end(); ++itf){ + l_edges.push_back(*itf); + (*itf)->addFace(this); + } + computeALoop(_unique, _U0); + while(!_unique.empty()) computeALoop(_unique,_U1); } - computeALoop(_unique, _U0); - while(!_unique.empty()){ - computeALoop(_unique, _U1); - printf("%d in unique\n", (int)_unique.size()); - _interior_loops.push_back(_U1); - } + return; + } void GFaceCompound::getUniqueEdges(std::set<GEdge*> &_unique) @@ -418,10 +432,12 @@ void GFaceCompound::getUniqueEdges(std::set<GEdge*> &_unique) (*itf)->addFace(this); } } - void GFaceCompound::computeALoop(std::set<GEdge*> &_unique, std::list<GEdge*> &loop) { std::list<GEdge*> _loop; + + if (_unique.empty()) return; + while(!_unique.empty()) { std::set<GEdge*>::iterator it = _unique.begin(); GVertex *vB = (*it)->getBeginVertex(); @@ -472,7 +488,11 @@ void GFaceCompound::computeALoop(std::set<GEdge*> &_unique, std::list<GEdge*> &l if(found == true) break; } + loop = _loop; + _interior_loops.push_back(loop); + return; + } GFaceCompound::GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound, @@ -503,7 +523,7 @@ GFaceCompound::GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound, Msg::Exit(1); } } - + getBoundingEdges(); if(!_U0.size()) _type = UNITCIRCLE; else if(!_V1.size()) _type = UNITCIRCLE; @@ -821,7 +841,7 @@ void GFaceCompound::parametrize_conformal() const } MVertex *v1 = ordered[0]; - MVertex *v2; + MVertex *v2 = ordered[1]; // if (!_interior_loops.empty()){ // std::vector<MVertex*> ordered2; // bool success2 = orderVertices(_U1, ordered2, coords); @@ -831,8 +851,6 @@ void GFaceCompound::parametrize_conformal() const // v2 = ordered[1]; // //v2 = ordered[ordered.size()/2]; // } - - v2 = ordered[1]; //printf("Pinned vertex %g %g %g / %g %g %g \n", v1->x(), v1->y(), v1->z(), v2->x(), v2->y(), v2->z()); //exit(1); @@ -894,7 +912,7 @@ void GFaceCompound::parametrize_conformal() const coordinates[v] = SPoint3(value1,value2,0.0); } - // checkOrientation(); + checkOrientation(); computeNormals(); buildOct(); _lsys->clear(); @@ -904,10 +922,10 @@ void GFaceCompound::compute_distance() const { SBoundingBox3d bbox = GModel::current()->bounds(); double L = norm(SVector3(bbox.max(), bbox.min())); - double mu = L / 28; - simpleFunction<double> DIFF(mu * mu), ONE(1.0); + double mu = L/28; + simpleFunction<double> DIFF(mu * mu), MONE(1.0); dofManager<double, double> myAssembler(_lsys); - distanceTerm distance(model(), 1, &DIFF, &ONE); + distanceTerm distance(model(), 1, &DIFF, &MONE); std::vector<MVertex*> ordered; boundVertices(_U0, ordered); @@ -1282,32 +1300,145 @@ void GFaceCompound::buildOct() const nbT = count; Octree_Arrange(oct); } +//Verify topological conditions for computing the harmonic map +bool GFaceCompound::checkTopology() +{ + + bool correctTopo = true; + + int Nb = _interior_loops.size(); + int G = genusGeom() ; + if( G != 0 || Nb < 1) correctTopo = false; + + if (!correctTopo){ + + Msg::Info("--> Wrong topology: Genus=%d and N boundary=%d", G, Nb); + + //Partition the mesh and createTopology fror new faces + //----------------------------------------------------- + meshPartitionOptions options; + int N = std::max(G+1, 2); + options = CTX::instance()->partitionOptions; + options.num_partitions = N; + options.partitioner = 2; //METIS + options.algorithm = 1 ; + int ier = PartitionMesh(GModel::current(), options); + int numv = GModel::current()->maxVertexNum() + 1; + int nume = GModel::current()->maxEdgeNum() + 1; + int numf = GModel::current()->maxFaceNum() + 1; + CreateTopologyFromPartition(GModel::current(), this, N); + GModel::current()->createTopologyFromMesh(); + + //Remesh new faces (Compound Lines and Compound Surfaces) + //----------------------------------------------------- + + discreteFace *gdf = new discreteFace(GModel::current(), numf+2*N); + GModel::current()->add(gdf); + //printf("*** Remesh face %d in new discreteFace =%d\n", this->tag(), gdf->tag()); + + int numEdges = GModel::current()->maxEdgeNum() - nume + 1; + //printf("*** Created %d discretEdges \n", numEdges); + for (int i=0; i < numEdges; i++){ + std::vector<GEdge*>e_compound; + GEdge *pe = GModel::current()->getEdgeByTag(nume+i);//partition edge + int num_gec = GModel::current()->maxEdgeNum() + 1; + e_compound.push_back(pe); + printf("*** Remeshing discreteEdge %d with CompoundLine %d\n", pe->tag(), num_gec); + GEdge *gec = new GEdgeCompound(GModel::current(), num_gec, e_compound); + + meshGEdge mge; + mge(gec);//meshing 1D + + GModel::current()->remove(pe); + //GModel::current()->add(gec); + } + + int numVert = GModel::current()->maxVertexNum() - numv + 1; + printf("*** Created %d discreteVert \n", numVert); + for (int i=0; i < numEdges; i++){ + GVertex *pv = GModel::current()->getVertexByTag(numv+i);//partition vertex + GModel::current()->remove(pv); + } + + std::list<GEdge*> b[4]; + std::set<MVertex*> all_vertices; + for (int i=0; i < N; i++){ + std::list<GFace*>f_compound; + GFace *pf = GModel::current()->getFaceByTag(numf+i);//partition face + int num_gfc = numf + N + i ; + f_compound.push_back(pf); + + printf("*** Remeshing discreteFace %d with CompoundSurface %d\n", pf->tag(), num_gfc); + GFace *gfc = new GFaceCompound(GModel::current(), num_gfc, f_compound, + b[0], b[1], b[2], b[3]); + meshGFace mgf; + mgf(gfc);//meshing 2D + + for (int j=0; j < gfc->triangles.size(); j++){ + MTriangle *t = gfc->triangles[j]; + MVertex *v1 = t->getVertex(0); + MVertex *v2 = t->getVertex(1); + MVertex *v3 = t->getVertex(2); + gdf->triangles.push_back(new MTriangle(v1, v2, v3)); + all_vertices.insert(v1); + all_vertices.insert(v2); + all_vertices.insert(v3); + } + + GModel::current()->remove(pf); + //GModel::current()->add(gfc); + } + + //Put new mesh in a new discreteFace + //----------------------------------------------------- + for(std::set<MVertex*>::iterator it = all_vertices.begin(); it != all_vertices.end(); ++it){ + gdf->mesh_vertices.push_back(*it); + } + + printf("*** Mesh of surface %d done by assembly remeshed faces\n", this->tag()); + gdf->setTag(this->tag()); + meshStatistics.status = GFace::DONE; + + //CreateOutputFile(CTX::instance()->outputFileName, CTX::instance()->mesh.format); + //Msg::Exit(1); + + } + + return correctTopo; + +} -int GFaceCompound::genusGeom() +int GFaceCompound::genusGeom() const { std::list<GFace*>::const_iterator it = _compound.begin(); - std::set<MEdge, Less_Edge> es; + std::set<MEdge, Less_Edge> es; std::set<MVertex*> vs; int N = 0; for( ; it != _compound.end() ; ++it){ for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){ N++; MTriangle *e = (*it)->triangles[i]; - for(int j = 0; j < e->getNumVertices(); j++) vs.insert(e->getVertex(j)); - for(int j = 0; j < e->getNumEdges(); j++) es.insert(e->getEdge(j)); + for(int j = 0; j < e->getNumVertices(); j++){ + vs.insert(e->getVertex(j)); + } + for(int j = 0; j < e->getNumEdges(); j++){ + es.insert(e->getEdge(j)); + } } } - int poincare = vs.size() - es.size() + N;// = 2g + 2 - b + int poincare = vs.size() - es.size() + N; + + return (int)(-poincare + 2 - _interior_loops.size())/2; - return (poincare - 2 + edgeLoops.size())/2; } void GFaceCompound::printStuff() const { std::list<GFace*>::const_iterator it = _compound.begin(); - char name1[256], name2[256], name3[256]; + char name0[256], name1[256], name2[256], name3[256]; char name4[256], name5[256], name6[256]; + sprintf(name0, "UVAREA-%d.pos", (*it)->tag()); sprintf(name1, "UVX-%d.pos", (*it)->tag()); sprintf(name2, "UVY-%d.pos", (*it)->tag()); sprintf(name3, "UVZ-%d.pos", (*it)->tag()); @@ -1322,6 +1453,7 @@ void GFaceCompound::printStuff() const // sprintf(name5, "XYZV.pos"); // sprintf(name6, "XYZC.pos"); + FILE * uva = fopen(name0,"w"); FILE * uvx = fopen(name1,"w"); FILE * uvy = fopen(name2,"w"); FILE * uvz = fopen(name3,"w"); @@ -1329,6 +1461,7 @@ void GFaceCompound::printStuff() const FILE * xyzv = fopen(name5,"w"); FILE * xyzc = fopen(name6,"w"); + fprintf(uva,"View \"\"{\n"); fprintf(uvx,"View \"\"{\n"); fprintf(uvy,"View \"\"{\n"); fprintf(uvz,"View \"\"{\n"); @@ -1373,6 +1506,20 @@ void GFaceCompound::printStuff() const it0->second.z(),it1->second.z(),it2->second.z()); //K1, K2, K3); + double p0[3] = {t->getVertex(0)->x(), t->getVertex(0)->y(), t->getVertex(0)->z()}; + double p1[3] = {t->getVertex(1)->x(), t->getVertex(1)->y(), t->getVertex(1)->z()}; + double p2[3] = {t->getVertex(2)->x(), t->getVertex(2)->y(), t->getVertex(2)->z()}; + double a_3D = fabs(triangle_area(p0, p1, p2)); + double q0[3] = {it0->second.x(), it0->second.y(), 0.0}; + double q1[3] = {it1->second.x(), it1->second.y(), 0.0}; + double q2[3] = {it2->second.x(), it2->second.y(), 0.0}; + double a_2D = fabs(triangle_area(q0, q1, q2)); + double area = a_3D/a_2D; + fprintf(uva,"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g};\n", + it0->second.x(), it0->second.y(), 0.0, + it1->second.x(), it1->second.y(), 0.0, + it2->second.x(), it2->second.y(), 0.0, + area, area, area); fprintf(uvx,"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g};\n", it0->second.x(), it0->second.y(), 0.0, it1->second.x(), it1->second.y(), 0.0, @@ -1390,6 +1537,8 @@ void GFaceCompound::printStuff() const t->getVertex(0)->z(), t->getVertex(1)->z(), t->getVertex(2)->z()); } } + fprintf(uva,"};\n"); + fclose(uva); fprintf(uvx,"};\n"); fclose(uvx); fprintf(uvy,"};\n"); diff --git a/Geo/GFaceCompound.h b/Geo/GFaceCompound.h index cde7ea41dd66dfa48986be9a213335a0ab7add2c..8d431236988e73527afa9e672fe42caf722c5c2a 100644 --- a/Geo/GFaceCompound.h +++ b/Geo/GFaceCompound.h @@ -95,7 +95,9 @@ class GFaceCompound : public GFace { void * getNativePtr() const { return 0; } virtual SPoint2 getCoordinates(MVertex *v) const; virtual double curvatureMax(const SPoint2 ¶m) const; - virtual int genusGeom (); + virtual int genusGeom () const; + virtual bool checkTopology(); + virtual std::list<GFace*> getCompounds() {return _compound;}; private: typeOfIsomorphism _type; typeOfMapping _mapping; diff --git a/Geo/GModel.cpp b/Geo/GModel.cpp index da749249b847abedb2f497606fb95743e312af3f..7e89222a25f4d12d1b54683ac428cc61e8e752c7 100644 --- a/Geo/GModel.cpp +++ b/Geo/GModel.cpp @@ -128,6 +128,44 @@ bool GModel::empty() const return vertices.empty() && edges.empty() && faces.empty() && regions.empty(); } +int GModel::maxVertexNum() +{ + viter it = firstVertex(); + viter itv = lastVertex(); + int MAXX = 0; + while(it != itv){ + MAXX = std::max(MAXX, (*it)->tag()); + ++it; + } + return MAXX; + +} +int GModel::maxEdgeNum() +{ + eiter it = firstEdge(); + eiter ite = lastEdge(); + int MAXX = 0; + while(it != ite){ + MAXX = std::max(MAXX, (*it)->tag()); + ++it; + } + return MAXX; + +} + +int GModel::maxFaceNum() +{ + + fiter it = firstFace(); + fiter ite = lastFace(); + int MAXX = 0; + while(it != ite){ + MAXX = std::max(MAXX, (*it)->tag()); + ++it; + } + return MAXX; +} + GRegion *GModel::getRegionByTag(int n) const { GEntity tmp((GModel*)this, n); @@ -982,6 +1020,7 @@ void GModel::createTopologyFromMesh() std::vector<GEntity*> entities; getEntities(entities); + std::vector<discreteEdge*> discreteEdges; for(eiter it = firstEdge(); it != lastEdge(); it++) if((*it)->geomType() == GEntity::DiscreteCurve) @@ -991,38 +1030,36 @@ void GModel::createTopologyFromMesh() for(fiter it = firstFace(); it != lastFace(); it++) if((*it)->geomType() == GEntity::DiscreteSurface) discreteFaces.push_back((discreteFace*) *it); + std::vector<discreteRegion*> discreteRegions; for(riter it = firstRegion(); it != lastRegion(); it++) if((*it)->geomType() == GEntity::DiscreteVolume) discreteRegions.push_back((discreteRegion*) *it); - + Msg::Debug("Creating topology from mesh:"); - Msg::Debug("%d discrete edges", discreteEdges.size()); - Msg::Debug("%d discrete faces", discreteFaces.size()); + Msg::Debug("%d discrete edges", discreteEdges.size()); + Msg::Debug("%d discrete faces", discreteFaces.size()); Msg::Debug("%d discrete regions", discreteRegions.size()); // for each discreteRegion, create topology - - for (std::vector<discreteRegion*>::iterator it = discreteRegions.begin(); - it != discreteRegions.end(); it++) + for (std::vector<discreteRegion*>::iterator it = discreteRegions.begin(); it != discreteRegions.end(); it++) (*it)->setBoundFaces(); - // for each discreteFace, create topology and if needed create - // discreteEdges - + // for each discreteFace, create topology and if needed create discreteEdges int initSizeEdges = discreteEdges.size(); // find boundary edges of each face and put them in a map_edges that // associates the MEdges with the tags of the adjacent faces std::map<MEdge, std::vector<int>, Less_Edge > map_edges; - for (std::vector<discreteFace*>::iterator it = discreteFaces.begin(); - it != discreteFaces.end(); it++) + for (std::vector<discreteFace*>::iterator it = discreteFaces.begin(); it != discreteFaces.end(); it++) (*it)->findEdges(map_edges); + //return if no boundary edges (torus, sphere, ..) + if (map_edges.empty()) return; + // create reverse map, for each face find set of MEdges that are // candidate for new discrete Edges - int num = discreteEdges.size() + 1; std::map<int, std::vector<int> > face2Edges; while (!map_edges.empty()){ @@ -1089,6 +1126,7 @@ void GModel::createTopologyFromMesh() } else{ // for each actual GEdge + int num = maxEdgeNum()+1; while (!myEdges.empty()) { std::vector<MEdge> myLines; myLines.clear(); @@ -1130,28 +1168,24 @@ void GModel::createTopologyFromMesh() discreteEdge *e = new discreteEdge(this, num, 0, 0); add(e); discreteEdges.push_back(e); - std::list<MVertex*> all_vertices; + + std::vector<MVertex*> allV; for(unsigned int i = 0; i < myLines.size(); i++) { MVertex *v0 = myLines[i].getVertex(0); MVertex *v1 = myLines[i].getVertex(1); e->lines.push_back(new MLine( v0, v1)); - if (std::find(all_vertices.begin(), all_vertices.end(), v0) == - all_vertices.end()) all_vertices.push_back(v0); - if (std::find(all_vertices.begin(), all_vertices.end(), v1) == - all_vertices.end()) all_vertices.push_back(v1); + if (std::find(allV.begin(), allV.end(), v0) == allV.end()) allV.push_back(v0); + if (std::find(allV.begin(), allV.end(), v1) == allV.end()) allV.push_back(v1); + v0->setEntity(e); + v1->setEntity(e); } - e->mesh_vertices.insert(e->mesh_vertices.begin(), all_vertices.begin(), - all_vertices.end()); - - for (std::vector<int>::iterator itFace = tagFaces.begin(); - itFace != tagFaces.end(); itFace++) { - GFace *dFace = getFaceByTag(abs(*itFace)); - for (std::list<MVertex*>::iterator itv = all_vertices.begin(); - itv != all_vertices.end(); itv++) { - std::vector<MVertex*>::iterator itve = - std::find(dFace->mesh_vertices.begin(), dFace->mesh_vertices.end(), *itv); - if (itve != dFace->mesh_vertices.end()) dFace->mesh_vertices.erase(itve); - (*itv)->setEntity(e); + e->mesh_vertices.insert(e->mesh_vertices.begin(), allV.begin(),allV.end()); + + for (std::vector<int>::iterator itFace = tagFaces.begin(); itFace != tagFaces.end(); itFace++) { + GFace *dFace = getFaceByTag(*itFace); + for (std::vector<MVertex*>::iterator itv = allV.begin(); itv != allV.end(); itv++) { + std::vector<MVertex*>::iterator itve = std::find(dFace->mesh_vertices.begin(), dFace->mesh_vertices.end(), *itv); + if (itve != dFace->mesh_vertices.end()) dFace->mesh_vertices.erase(itve); } std::map<int, std::vector<int> >::iterator f2e = face2Edges.find(*itFace); @@ -1172,19 +1206,20 @@ void GModel::createTopologyFromMesh() } // set boundary edges for each face - for (std::vector<discreteFace*>::iterator it = discreteFaces.begin(); - it != discreteFaces.end(); it++){ + for (std::vector<discreteFace*>::iterator it = discreteFaces.begin(); it != discreteFaces.end(); it++){ std::map<int, std::vector<int> >::iterator ite = face2Edges.find((*it)->tag()); - std::vector<int> myEdges = ite->second; - (*it)->setBoundEdges(myEdges); + if (ite != face2Edges.end()){ + std::vector<int> myEdges = ite->second; + (*it)->setBoundEdges(myEdges); + } } // for each discreteEdge, create Topology - for (std::vector<discreteEdge*>::iterator it = discreteEdges.begin(); - it != discreteEdges.end(); it++){ + for (std::vector<discreteEdge*>::iterator it = discreteEdges.begin(); it != discreteEdges.end(); it++){ (*it)->createTopo(); (*it)->parametrize(); } + } GModel *GModel::buildCutGModel(gLevelset *ls) diff --git a/Geo/GModel.h b/Geo/GModel.h index 96a913fd616e68ae7cc6171b16cba559958b21e0..5812fa461bfc030221880760b0ab5cc06b8d5664 100644 --- a/Geo/GModel.h +++ b/Geo/GModel.h @@ -154,6 +154,9 @@ class GModel int getNumFaces() const { return faces.size(); } int getNumEdges() const { return edges.size(); } int getNumVertices() const { return vertices.size(); } + int maxVertexNum(); + int maxEdgeNum(); + int maxFaceNum(); // quickly check if the model is empty (i.e., if it contains no // entities) diff --git a/Geo/OCCFace.h b/Geo/OCCFace.h index 863d184ea2fe27f6f196e8bc17df096ca1172713..ee170f7f2e898953d7b595307fb3d7b3e4722b0f 100644 --- a/Geo/OCCFace.h +++ b/Geo/OCCFace.h @@ -40,6 +40,7 @@ class OCCFace : public GFace { virtual double curvatures(const SPoint2 ¶m, SVector3 *dirMax, SVector3 *dirMin, double *curvMax, double *curvMin) const; surface_params getSurfaceParams() const; + virtual bool checkTopology() {return true;}; }; #endif diff --git a/Geo/discreteEdge.cpp b/Geo/discreteEdge.cpp index 4caeca19000e2f685b61b105b89452fbc005858e..207b05f30d1721801004e02b502cb3c5cf1825bf 100644 --- a/Geo/discreteEdge.cpp +++ b/Geo/discreteEdge.cpp @@ -30,6 +30,7 @@ discreteEdge::discreteEdge(GModel *model, int num, GVertex *_v0, GVertex *_v1) void discreteEdge::createTopo() { + if(!createdTopo){ orderMLines(); setBoundVertices(); @@ -121,6 +122,17 @@ void discreteEdge::orderMLines() //lines is now a list of ordered MLines lines = _m; + + //mesh_vertices + mesh_vertices.clear(); + for (unsigned int i = 0; i < lines.size(); ++i){ + MVertex *v1 = lines[i]->getVertex(0); + MVertex *v2 = lines[i]->getVertex(1); + if (std::find(mesh_vertices.begin(), mesh_vertices.end(), v1) == mesh_vertices.end()) mesh_vertices.push_back(v1); + if (std::find(mesh_vertices.begin(), mesh_vertices.end(), v2) == mesh_vertices.end()) mesh_vertices.push_back(v2); + v1->setEntity(this); + v2->setEntity(this); + } //special case reverse orientation if (lines.size() < 2) return; @@ -129,6 +141,7 @@ void discreteEdge::orderMLines() printf("coucou here \n"); for (unsigned int i = 0; i < lines.size(); i++) _orientation[i] = !_orientation[i]; } + } void discreteEdge::setBoundVertices() @@ -149,21 +162,35 @@ void discreteEdge::setBoundVertices() } } if(!existVertex){ - GVertex *gvB = new discreteVertex(model(),vE->getNum()); + GVertex *gvB = new discreteVertex(model(), model()->maxVertexNum()+1); bound_vertices.push_back(gvB); vE->setEntity(gvB); gvB->mesh_vertices.push_back(vE); gvB->points.push_back(new MPoint(gvB->mesh_vertices.back())); model()->add(gvB); } - std::vector<MVertex*>::iterator itve = std::find(mesh_vertices.begin(), - mesh_vertices.end(), vE); + std::vector<MVertex*>::iterator itve = std::find(mesh_vertices.begin(), mesh_vertices.end(), vE); if (itve != mesh_vertices.end()) mesh_vertices.erase(itve); + + for(GModel::eiter edge = model()->firstEdge(); edge != model()->lastEdge(); edge++){ + std::vector<MVertex*>::iterator itve = std::find((*edge)->mesh_vertices.begin(), (*edge)->mesh_vertices.end(), vE); + if (itve != (*edge)->mesh_vertices.end()) (*edge)->mesh_vertices.erase(itve); + } + for(GModel::fiter face = model()->firstFace(); face != model()->lastFace(); face++){ + std::vector<MVertex*>::iterator itve = std::find((*face)->mesh_vertices.begin(), (*face)->mesh_vertices.end(), vE); + if (itve != (*face)->mesh_vertices.end()) (*face)->mesh_vertices.erase(itve); + } + for(GModel::riter reg = model()->firstRegion(); reg != model()->lastRegion(); reg++){ + std::vector<MVertex*>::iterator itve = std::find((*reg)->mesh_vertices.begin(), (*reg)->mesh_vertices.end(), vE); + if (itve != (*reg)->mesh_vertices.end()) (*reg)->mesh_vertices.erase(itve); + } + } v0 = bound_vertices[0]; v1 = bound_vertices[1]; } else if (boundv.size() == 0){ + //printf("closed loop for discrete Edge =%d \n", this->tag()); GVertex* bound_vertex; std::vector<MLine*>::const_iterator it = lines.begin(); MVertex* vE = (*it)->getVertex(0); @@ -172,25 +199,41 @@ void discreteEdge::setBoundVertices() if ((*point)->mesh_vertices[0]->getNum() == vE->getNum()){ bound_vertex = (*point); existVertex = true; + //printf("vertex exist (%g,%g,%g)\n", vE->x(), vE->y(), vE->z()); break; } } if(!existVertex){ - GVertex *gvB = new discreteVertex(model(),vE->getNum()); + GVertex *gvB = new discreteVertex(model(), model()->maxVertexNum()+1); bound_vertex = gvB; + vE->setEntity(gvB); gvB->mesh_vertices.push_back(vE); gvB->points.push_back(new MPoint(gvB->mesh_vertices.back())); model()->add(gvB); } - std::vector<MVertex*>::iterator itve = std::find(mesh_vertices.begin(), - mesh_vertices.end(), vE); - if (itve != mesh_vertices.end()) mesh_vertices.erase(itve); + std::vector<MVertex*>::iterator itve = std::find(mesh_vertices.begin(),mesh_vertices.end(), vE); + if (itve != mesh_vertices.end()) mesh_vertices.erase(itve); + + for(GModel::eiter edge = model()->firstEdge(); edge != model()->lastEdge(); edge++){ + std::vector<MVertex*>::iterator itve = std::find((*edge)->mesh_vertices.begin(), (*edge)->mesh_vertices.end(), vE); + if (itve != (*edge)->mesh_vertices.end()) (*edge)->mesh_vertices.erase(itve); + } + for(GModel::fiter face = model()->firstFace(); face != model()->lastFace(); face++){ + std::vector<MVertex*>::iterator itve = std::find((*face)->mesh_vertices.begin(), (*face)->mesh_vertices.end(), vE); + if (itve != (*face)->mesh_vertices.end()) (*face)->mesh_vertices.erase(itve); + } + for(GModel::riter reg = model()->firstRegion(); reg != model()->lastRegion(); reg++){ + std::vector<MVertex*>::iterator itve = std::find((*reg)->mesh_vertices.begin(), (*reg)->mesh_vertices.end(), vE); + if (itve != (*reg)->mesh_vertices.end()) (*reg)->mesh_vertices.erase(itve); + } + v0 = bound_vertex; v1 = bound_vertex; } v0->addEdge(this); v1->addEdge(this); + } /* @@ -218,8 +261,7 @@ void discreteEdge::parametrize() if (_orientation[i] == 1 ) vR = lines[i]->getVertex(1); else vR = lines[i]->getVertex(0); int param = i+1; - MVertex *vNEW = new MEdgeVertex(vR->x(),vR->y(),vR->z(), this, param, - -1., vR->getNum()); + MVertex *vNEW = new MEdgeVertex(vR->x(),vR->y(),vR->z(), this, param, -1., vR->getNum()); old2new.insert(std::make_pair(vR,vNEW)); newVertices.push_back(vNEW); newLines.push_back(new MLine(vL, vNEW)); @@ -231,6 +273,7 @@ void discreteEdge::parametrize() _orientation[i] = 1; mesh_vertices = newVertices; + deleteVertexArrays(); lines.clear(); lines = newLines; diff --git a/Geo/discreteFace.cpp b/Geo/discreteFace.cpp index ac9995b337b452484d42a677e1b4d409cdc1e292..1c58800b397c32a8c87cc4ebddf1687f8283872a 100644 --- a/Geo/discreteFace.cpp +++ b/Geo/discreteFace.cpp @@ -55,9 +55,8 @@ void discreteFace::findEdges(std::map<MEdge, std::vector<int>, Less_Edge> &map_e void discreteFace::setBoundEdges(std::vector<int> tagEdges) { - for (std::vector<int>::iterator it = tagEdges.begin(); - it != tagEdges.end(); it++){ - GEdge *ge = GModel::current()->getEdgeByTag(abs(*it)); + for (std::vector<int>::iterator it = tagEdges.begin();it != tagEdges.end(); it++){ + GEdge *ge = GModel::current()->getEdgeByTag(*it); l_edges.push_back(ge); l_dirs.push_back(1); ge->addFace(this); diff --git a/Geo/discreteFace.h b/Geo/discreteFace.h index 87ed1db371b2153eefba5257e1fe3318e3e3baab..f210ebf2a3a83c62ee9d48fd7eec68f60b039105 100644 --- a/Geo/discreteFace.h +++ b/Geo/discreteFace.h @@ -24,6 +24,7 @@ class discreteFace : public GFace { SVector3 *dudu, SVector3 *dvdv, SVector3 *dudv) const; void setBoundEdges(std::vector<int> tagEdges); void findEdges(std::map<MEdge, std::vector<int>, Less_Edge > &map_edges); + virtual bool checkTopology() {return true;}; }; #endif diff --git a/Geo/gmshFace.h b/Geo/gmshFace.h index 59a368be3e6870111e8ef91913e45191f0088f1f..34440a14ab6dc7f2744ff2d557d341ff88404857 100644 --- a/Geo/gmshFace.h +++ b/Geo/gmshFace.h @@ -33,6 +33,7 @@ class gmshFace : public GFace { void *getNativePtr() const { return s; } virtual SPoint2 parFromPoint(const SPoint3 &) const; virtual void resetMeshAttributes(); + virtual bool checkTopology() {return true;}; }; #endif diff --git a/Mesh/Generator.cpp b/Mesh/Generator.cpp index 676cc757c7a4a8d346552b530799ef08986292f7..45db31cc540288042e48045a8b1ca11e774ac6ff 100644 --- a/Mesh/Generator.cpp +++ b/Mesh/Generator.cpp @@ -409,7 +409,12 @@ static void Mesh2D(GModel *m) // and curve meshes) is global as it depends on a smooth normal // field generated from the surface mesh of the source surfaces if(!Mesh2DWithBoundaryLayers(m)){ - std::for_each(m->firstFace(), m->lastFace(), meshGFace()); + //std::for_each(m->firstFace(), m->lastFace(), meshGFace()); + std::set<GFace*> actualFaces; + for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it){ + actualFaces.insert(*it); + } + std::for_each(actualFaces.begin(), actualFaces.end(), meshGFace()); int nIter = 0; while(1){ meshGFace mesher; diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp index e877eff47a95f4d1568c25c913e323ea3c85ea9f..6d93676c53e2ec3d15b4ee926e4d726ab35b4a28 100644 --- a/Mesh/meshGFace.cpp +++ b/Mesh/meshGFace.cpp @@ -252,6 +252,8 @@ static bool meshGenerator(GFace *gf, int RECUR_ITER, // replace edges by their compounds if(gf->geomType() == GEntity::CompoundSurface){ + bool correct = gf->checkTopology(); + if (!correct) return true; std::set<GEdge*> mySet; std::list<GEdge*>::iterator it = edges.begin(); while(it != edges.end()){ diff --git a/Mesh/meshPartition.cpp b/Mesh/meshPartition.cpp index 342e929221b70e765c79adc2a700775ce6bce147..afba861b7bd8e996e4221cb3782273ef3ba1553b 100644 --- a/Mesh/meshPartition.cpp +++ b/Mesh/meshPartition.cpp @@ -24,6 +24,9 @@ #include "partitionVertex.h" #include "partitionEdge.h" #include "partitionFace.h" +#include "discreteEdge.h" +#include "discreteFace.h" +#include "GFaceCompound.h" //--Prototype for Chaco interface @@ -136,8 +139,8 @@ int PartitionMesh(GModel *const model, meshPartitionOptions &options) model->recomputeMeshPartitions(); - // if (options.createPartitionBoundaries) - CreatePartitionBoundaries (model); + if (options.createPartitionBoundaries) + CreatePartitionBoundaries (model); Msg::Info("Partitioning complete"); Msg::StatusBar(1, false, "Mesh"); @@ -247,11 +250,18 @@ int PartitionGraph(Graph &graph, meshPartitionOptions &options) metisOptions[2] = 1; metisOptions[3] = options.refine_algorithm; metisOptions[4] = 0; - METIS_PartGraphKway + METIS_PartGraphKway (&n, &graph.xadj[graph.section[iSec]], &graph.adjncy[graph.section[iSec]], NULL, NULL, &wgtflag, &numflag, &options.num_partitions, metisOptions, &edgeCut, &graph.partition[graph.section[iSec]]); +// printf("METIS with weights\n"); +// wgtflag = 2; +// METIS_PartGraphKway +// (&n, &graph.xadj[graph.section[iSec]], +// &graph.adjncy[graph.section[iSec]], &graph.vwgts[graph.section[iSec]], NULL, &wgtflag, &numflag, +// &options.num_partitions, metisOptions, &edgeCut, +// &graph.partition[graph.section[iSec]]); break; } } @@ -724,7 +734,7 @@ void assignPartitionBoundary(GModel *model, ppe = new partitionFace(model, -(int)pfaces.size()-1, v2); pfaces.insert (ppe); model->add(ppe); - printf("created partitionFace %d (", ppe->tag()); + printf("*** Created partitionFace %d (", ppe->tag()); for (unsigned int i = 0; i < v2.size(); ++i) printf("%d ", v2[i]); printf(")\n"); } @@ -765,7 +775,7 @@ void assignPartitionBoundary(GModel *model, ppe = new partitionEdge(model, -(int)pedges.size()-1, 0, 0, v2); pedges.insert (ppe); model->add(ppe); - printf("created partitionEdge %d (", ppe->tag()); + printf("*** Create partitionEdge %d (", ppe->tag()); for (unsigned int i = 0; i < v2.size(); ++i) printf("%d ", v2[i]); printf(")\n"); } @@ -773,6 +783,72 @@ void assignPartitionBoundary(GModel *model, ppe->lines.push_back(new MLine (me.getVertex(0),me.getVertex(1))); } +void splitBoundaryEdges(GModel *model, std::set<partitionEdge*, Less_partitionEdge> &newEdges) +{ + + for (std::set<partitionEdge*, Less_partitionEdge>::iterator it = newEdges.begin() ; it != newEdges.end() ; ++it){ + + int nbSplit = 0; + partitionEdge *ge = *it; + std::list<MLine*> segments; + for (unsigned int i = 0; i < ge->lines.size(); i++){ + segments.push_back(ge->lines[i]); + } + + while (!segments.empty()) { + std::vector<MLine*> myLines; + std::list<MLine*>::iterator it = segments.begin(); + MVertex *vB = (*it)->getVertex(0); + MVertex *vE = (*it)->getVertex(1); + myLines.push_back(*it); + segments.erase(it); + it++; + for (int i=0; i<2; i++) { + for (std::list<MLine*>::iterator it = segments.begin() ; it != segments.end(); ++it){ + MVertex *v1 = (*it)->getVertex(0); + MVertex *v2 = (*it)->getVertex(1); + std::list<MLine*>::iterator itp; + if ( v1 == vE ){ + myLines.push_back(*it); + itp = it; + it++; + segments.erase(itp); + vE = v2; + i = -1; + } + else if ( v2 == vE){ + myLines.push_back(*it); + itp = it; + it++; + segments.erase(itp); + vE = v1; + i=-1; + } + if (it == segments.end()) break; + } + if (vB == vE) break; + if (segments.empty()) break; + MVertex *temp = vB; + vB = vE; + vE = temp; + } + if (nbSplit == 0 && segments.empty()) break; + int numEdge = model->maxEdgeNum() + 1; + discreteEdge *newGe = new discreteEdge(model, numEdge, 0, 0); + newGe->lines.insert(newGe->lines.end(), myLines.begin(), myLines.end()); + model->add(newGe); + newGe->orderMLines(); //this creates also mesh_vertices + + nbSplit++; + printf("*** split partitionEdge with tag =%d\n", numEdge); + } + if (nbSplit > 0) model->remove(ge); + } + + return; + +} + void assignPartitionBoundary(GModel *model, MVertex *ve, std::set<partitionVertex*, Less_partitionVertex> &pvertices, @@ -809,7 +885,7 @@ void assignPartitionBoundary(GModel *model, ppv = new partitionVertex(model, -(int)pvertices.size()-1,v2); pvertices.insert (ppv); model->add(ppv); - printf("created partitionVertex %d (", ppv->tag()); + printf("*** created partitionVertex %d (", ppv->tag()); for (unsigned int i = 0; i < v2.size(); ++i) printf("%d ", v2[i]); printf(")\n"); } @@ -883,6 +959,7 @@ int CreatePartitionBoundaries(GModel *model) }while (oper (e,it->first)); assignPartitionBoundary (model,e,pedges,voe,pfaces); } + //splitBoundaryEdges(model,pedges); } } @@ -922,6 +999,55 @@ int CreatePartitionBoundaries(GModel *model) return 1; } + +void CreateTopologyFromPartition(GModel *model, GFaceCompound *gf, int N) +{ + + printf("---> CreateTopologyFromPartition for Compound Face %d \n", gf->tag()); + // Compound is partitioned in N discrete faces + //-------------------------------------------- + std::vector<discreteFace*> discreteFaces; + std::vector<std::set<MVertex*> > allNodes; + int numMax = model->maxFaceNum() + 1; + for( int i =0; i < N; i++){ + //printf("*** Created discreteFace %d \n", numMax+i); + discreteFace *face = new discreteFace(model, numMax+i); + discreteFaces.push_back(face); + model->add(face); + std::set<MVertex*> mySet; + allNodes.push_back(mySet); + } + + std::list<GFace*> _compound = gf->getCompounds(); + std::list<GFace*>::iterator it = _compound.begin(); + + for( ; it != _compound.end() ; ++it){ + for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){ + MTriangle *e = (*it)->triangles[i]; + int part = e->getPartition(); + for(int j = 0; j < 3; j++){ + MVertex *v0 = e->getVertex(j); + if (v0->onWhat()->dim() == 2) allNodes[part-1].insert(v0); + } + discreteFaces[part-1]->triangles.push_back(new MTriangle(e->getVertex(0),e->getVertex(1),e->getVertex(2))); + } + } + + for( int i =0; i < N; i++){ + GFace *face = model->getFaceByTag(numMax+i); + for (std::set<MVertex*>::iterator it = allNodes[i].begin(); it != allNodes[i].end(); it++){ + face->mesh_vertices.push_back(*it); + } + } + + //remove the discrete face that is not topologically correct + //for(it = _compound.begin() ; it != _compound.end() ; ++it){ + // model->remove(*it); + //} + + return; + +} /******************************************************************************* * diff --git a/Mesh/meshPartition.h b/Mesh/meshPartition.h index b9d40cdea91736285cfc11fa5a7c12df7ebb70de..2b8728f6b4cc6320a194c4b452d99fce2fe6c932 100644 --- a/Mesh/meshPartition.h +++ b/Mesh/meshPartition.h @@ -7,6 +7,8 @@ #define _PARTITION_H_ #include <vector> +#include "partitionEdge.h" +#include "GFaceCompound.h" struct meshPartitionOptions; struct BoElemGr; @@ -26,5 +28,7 @@ int MakeGraph(GModel *const model, Graph &graph, int PartitionGraph(Graph &graph, meshPartitionOptions &options); int PartitionMesh(GModel *const model, meshPartitionOptions &options); int CreatePartitionBoundaries (GModel *model); +void splitBoundaryEdges(GModel *model, std::set<partitionEdge*, Less_partitionEdge> &newEdges); +void CreateTopologyFromPartition(GModel *model, GFaceCompound *gf, int num_parts); #endif diff --git a/Mesh/meshPartitionObjects.h b/Mesh/meshPartitionObjects.h index 96680252d59f696bac6ff79acd462e59da9cc127..309ed488c59c12816da4a1ef57c018af16136541 100644 --- a/Mesh/meshPartitionObjects.h +++ b/Mesh/meshPartitionObjects.h @@ -29,6 +29,7 @@ class GrVertex public: const int index; // This is the creation index, *not* the // index in 'adjncy' + int dualWeight; private: unsigned short size; unsigned short sizeC; // Complete size (all possible 'grEdge') @@ -86,6 +87,8 @@ class Graph std::vector<int> adjncy; // Connectivity between graph vertex // xadj[i] and its neighbour graph // vertices. + std::vector<int> vwgts; // Weights assigned for each + // vertex std::vector<int> section; // For separate partitioning of // different parts of the mesh std::vector<int> partition; // The partitions output from the @@ -128,6 +131,7 @@ class Graph totalGrVert = _totalGrVert; xadj.resize(_totalGrVert + 1); adjncy.reserve(2*totalGrEdge); + vwgts.resize(_totalGrVert); partition.resize(_totalGrVert); element.resize(_totalGrVert); c2w = new int[_totalGrVert]; @@ -137,6 +141,7 @@ class Graph { const int i = numGrVert++; xadj[i] = adjncy.size(); + vwgts[i-1]=(int)(1.0); grVertMapIt->second.write(adjncy); element[i] = grVertMapIt->first; // Translated vertex numbers start from 1 @@ -154,6 +159,7 @@ class Graph Msg::Warning("Internal error - Graph vertices are missing"); } xadj[numGrVert] = adjncy.size(); + vwgts[numGrVert-1]=(int)(1.0); const int nAdj = adjncy.size(); for(int i = 0; i != nAdj; ++i) adjncy[i] = c2w[adjncy[i]]; delete[] c2w; diff --git a/Solver/convexCombinationTerm.h b/Solver/convexCombinationTerm.h index 1f77c8137ac72423a8ad520c9cafc7c2e8fca7dd..dcaef8fb3b8f7546895c5b60181a8a1bd6361c39 100644 --- a/Solver/convexCombinationTerm.h +++ b/Solver/convexCombinationTerm.h @@ -6,20 +6,22 @@ #ifndef _CONVEX_COMBINATION_TERM_H_ #define _CONVEX_COMBINATION_TERM_H_ +#include <assert.h> #include "femTerm.h" #include "simpleFunction.h" #include "Gmsh.h" #include "GModel.h" #include "SElement.h" #include "fullMatrix.h" +#include "Numeric.h" -class convexCombinationTerm : public femTerm<double, double> { +class convexCombinationTerm : public femTerm<double,double> { protected: - const simpleFunction<double> *_diffusivity; + const simpleFunction<double> *_k; const int _iField; public: - convexCombinationTerm(GModel *gm, int iField, simpleFunction<double> *diffusivity) - : femTerm<double, double>(gm), _iField(iField), _diffusivity(diffusivity) {} + convexCombinationTerm(GModel *gm, int iField, simpleFunction<double> *k) + : femTerm<double,double>(gm), _iField(iField), _k(k) {} virtual int sizeOfR(SElement *se) const { return se->getMeshElement()->getNumVertices(); @@ -30,16 +32,16 @@ class convexCombinationTerm : public femTerm<double, double> { } Dof getLocalDofR(SElement *se, int iRow) const { - return Dof(se->getMeshElement()->getVertex(iRow)->getNum(), _iField); + return Dof(se->getMeshElement()->getVertex(iRow)->getNum(), + Dof::createTypeWithTwoInts(0, _iField)); } - virtual void elementMatrix(SElement *e, fullMatrix<double> &m) const + virtual void elementMatrix(SElement *se, fullMatrix<double> &m) const { + + MElement *e = se->getMeshElement(); m.set_all(0.); - int nbNodes = e->getMeshElement()->getNumVertices(); - //double x = 0.3*(e->getVertex(0)->x()+e->getVertex(1)->x()+e->getVertex(2)->x()); - //double y = 0.3*(e->getVertex(0)->y()+e->getVertex(1)->y()+e->getVertex(2)->y()); - //double z = 0.3*(e->getVertex(0)->z()+e->getVertex(1)->z()+e->getVertex(2)->z()); - const double _diff = 1.0; + const int nbNodes = e->getNumVertices(); + const double _diff = 1.0; for (int j = 0; j < nbNodes; j++){ for (int k = 0; k < nbNodes; k++){ m(j,k) = -1.*_diff; @@ -47,6 +49,8 @@ class convexCombinationTerm : public femTerm<double, double> { m(j,j) = (nbNodes - 1) * _diff; } } + + }; #endif diff --git a/Solver/helmholtzTerm.h b/Solver/helmholtzTerm.h index 7eb14217710f5ea672aaf572fb10f437e965a852..c120bbb2adff8e596346f80deaa18d9e13715c44 100644 --- a/Solver/helmholtzTerm.h +++ b/Solver/helmholtzTerm.h @@ -15,7 +15,7 @@ #include "fullMatrix.h" #include "Numeric.h" -// \nabla \cdot k \nabla U + a U +// \nabla \cdot k \nabla U - a U template<class scalar> class helmholtzTerm : public femTerm<scalar, scalar> { protected: diff --git a/benchmarks/2d/square.geo b/benchmarks/2d/square.geo index 34634b39110208370f6c4029e643a3cf52fc3679..6475d2fad2650de9072f870f760f2839d37d3457 100644 --- a/benchmarks/2d/square.geo +++ b/benchmarks/2d/square.geo @@ -11,5 +11,5 @@ Line(4) = {1, 2}; Line Loop(5) = {1, 2, 3, 4}; Plane Surface(10) = {5}; -Compound Surface(11)={10} Boundary{{}}; +Compound Surface(11)={10}; diff --git a/benchmarks/3d/Torus2.geo b/benchmarks/3d/Torus2.geo index 0460cb7ea84b609456c263cd3fff2e5cae7a480b..245f082097f7e64738fb512962545044168a83d3 100644 --- a/benchmarks/3d/Torus2.geo +++ b/benchmarks/3d/Torus2.geo @@ -14,4 +14,7 @@ Extrude Surface {6, {0,1,0}, {-2,0,0}, 2*Pi/3}; Extrude Surface {28, {0,1,0}, {-2,0,0}, 2*Pi/3}; Extrude Surface {50, {0,1,0}, {-2,0,0}, 2*Pi/3}; Surface Loop(72) = {45,23,67,71,49,27,15,59,37,41,19,63}; -Volume(73) = {72}; + +//Compound Surface(100)={45,23,67,71,49,27,15,59,37,41,19,63}; + +//Volume(73) = {72}; diff --git a/benchmarks/3d/Torus_GEO.geo b/benchmarks/3d/Torus_GEO.geo index c0dc7f1354e026c6701d2a155880563e5feb4fd9..bdda121a002a85fac8b4d8aec41bdd98b5971184 100644 --- a/benchmarks/3d/Torus_GEO.geo +++ b/benchmarks/3d/Torus_GEO.geo @@ -1,4 +1,4 @@ -Mesh.CharacteristicLengthFactor=1.0; +Mesh.CharacteristicLengthFactor=0.4; Merge "Torus2_CLASS.msh"; CreateTopology; @@ -6,5 +6,6 @@ CreateTopology; Compound Line(100)={1}; Compound Line(200)={2}; -Compound Surface(1000)={150} Boundary {{}}; -Compound Surface(2000)={250} Boundary {{}}; +Compound Surface(1000)={150}; +Compound Surface(2000)={250}; + diff --git a/benchmarks/stl/PelvisARTHUR_CLASS_GEO.geo b/benchmarks/stl/PelvisARTHUR_CLASS_GEO.geo index 3e288e9ac468e3b813bbffc8e4b4cea5e8a73912..437b2d692850cb7cbed47a5cbdf4ec2dfea48659 100644 --- a/benchmarks/stl/PelvisARTHUR_CLASS_GEO.geo +++ b/benchmarks/stl/PelvisARTHUR_CLASS_GEO.geo @@ -1,13 +1,13 @@ -Mesh.CharacteristicLengthFactor=0.1; +Mesh.CharacteristicLengthFactor=0.2; -Merge "PelvisARTHUR_CLASS.msh"; +Merge "PelvisKO.msh"; //ARTHUR_CLASS.msh"; CreateTopology; Surface Loop(1002)={2,3}; Volume(1003)={1002}; Compound Line(10)={4}; -Compound Line(20)={5}; +//Compound Line(20)={5}; Compound Surface(200)={2}; Compound Surface(400)={3}; diff --git a/benchmarks/stl/implant_CLASS_GEO.geo b/benchmarks/stl/implant_CLASS_GEO.geo index 8636edf12c00bf61ac247e2a83c1896f58779c36..fcfa5a5a1766c3fb188f9f4cfe1dc5a8331f8229 100644 --- a/benchmarks/stl/implant_CLASS_GEO.geo +++ b/benchmarks/stl/implant_CLASS_GEO.geo @@ -1,4 +1,4 @@ -Mesh.CharacteristicLengthFactor=0.5; +Mesh.CharacteristicLengthFactor=0.1; Merge "implant_CLASS.msh"; CreateTopology; @@ -7,7 +7,6 @@ Compound Line(20)={3}; Compound Surface(100)={2} Boundary {{}}; Compound Surface(200)={3} Boundary {{}}; - //Compound Line(20)={6}; //Compound Line(30)={7}; //Compound Line(40)={8};