Skip to content
Snippets Groups Projects
Commit 42ddcc96 authored by Christophe Geuzaine's avatar Christophe Geuzaine
Browse files

new algo to compute partition boundaries (much faster)

parent 6bc7162e
No related branches found
No related tags found
No related merge requests found
...@@ -5,7 +5,10 @@ ...@@ -5,7 +5,10 @@
#include "SimplePartition.h" #include "SimplePartition.h"
#include "GModel.h" #include "GModel.h"
#include "partitionFace.h"
#include "partitionEdge.h"
#include "MElement.h" #include "MElement.h"
#include "MLine.h"
#include "MFace.h" #include "MFace.h"
#include "MEdge.h" #include "MEdge.h"
#if defined(HAVE_MESH) #if defined(HAVE_MESH)
...@@ -57,34 +60,40 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v) ...@@ -57,34 +60,40 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v)
GModel *m = GModel::current(); GModel *m = GModel::current();
SBoundingBox3d bbox = m->bounds(); SBoundingBox3d bbox = m->bounds();
double pmin = bbox.min()[direction], pmax = bbox.max()[direction]; double pmin = bbox.min()[direction], pmax = bbox.max()[direction];
std::vector<double> pp(numSlices + 1);
for(int p = 0; p <= numSlices; p++)
pp[p] = pmin + p * (pmax - pmin) / numSlices;
int dim = m->getDim(); int dim = m->getDim();
std::vector<GEntity*> entities; std::vector<GEntity*> entities;
m->getEntities(entities); m->getEntities(entities);
std::map<int, std::set<MFace, Less_Face> > bndFaces; std::vector<std::set<MFace, Less_Face> > bndFaces(numSlices);
std::map<int, std::set<MEdge, Less_Edge> > bndEdges; std::vector<std::set<MEdge, Less_Edge> > bndEdges(numSlices);
std::vector<std::set<MElement*> > cutElements(numSlices);
for(unsigned int i = 0; i < entities.size(); i++){ for(unsigned int i = 0; i < entities.size(); i++){
GEntity *ge = entities[i]; GEntity *ge = entities[i];
if(ge->dim() != dim) continue; if(ge->dim() != dim) continue;
for(int j = 0; j < ge->getNumMeshElements(); j++){ for(int j = 0; j < ge->getNumMeshElements(); j++){
MElement *e = ge->getMeshElement(j); MElement *e = ge->getMeshElement(j);
double val = pmax; double valmin = pmax;
double valmax = pmin;
bool bnd = false; bool bnd = false;
for(int k = 0; k < e->getNumVertices(); k++){ for(int k = 0; k < e->getNumVertices(); k++){
MVertex *v = e->getVertex(k); MVertex *v = e->getVertex(k);
val = std::min(val, v->point()[direction]); valmin = std::min(valmin, v->point()[direction]);
valmax = std::max(valmax, v->point()[direction]);
if(v->onWhat() && v->onWhat()->dim() != dim) bnd = true; if(v->onWhat() && v->onWhat()->dim() != dim) bnd = true;
} }
for(int p = 0; p < numSlices; p++){ for(int p = 0; p < numSlices; p++){
double p1 = pmin + p * (pmax - pmin) / numSlices; if(valmin >= pp[p] && valmin < pp[p + 1]){
double p2 = pmin + (p + 1) * (pmax - pmin) / numSlices;
if(val >= p1 && val < p2){
e->setPartition(p + 1); e->setPartition(p + 1);
if(bnd){ if(bnd){
for(int k = 0; k < e->getNumEdges(); k++) for(int k = 0; k < e->getNumEdges(); k++)
bndEdges[p + 1].insert(e->getEdge(k)); bndEdges[p].insert(e->getEdge(k));
for(int k = 0; k < e->getNumFaces(); k++) for(int k = 0; k < e->getNumFaces(); k++)
bndFaces[p + 1].insert(e->getFace(k)); bndFaces[p].insert(e->getFace(k));
} }
if(valmax >= pp[p + 1])
cutElements[p].insert(e);
break; break;
} }
} }
...@@ -94,6 +103,8 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v) ...@@ -94,6 +103,8 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v)
// partition lower dimension elements // partition lower dimension elements
Msg::Info("Partitioning lower dimension elements"); Msg::Info("Partitioning lower dimension elements");
std::set<MFace, Less_Face> allLowerDimFaces;
std::set<MEdge, Less_Edge> allLowerDimEdges;
for(unsigned int i = 0; i < entities.size(); i++){ for(unsigned int i = 0; i < entities.size(); i++){
GEntity *ge = entities[i]; GEntity *ge = entities[i];
if(ge->dim() == dim) continue; if(ge->dim() == dim) continue;
...@@ -101,8 +112,9 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v) ...@@ -101,8 +112,9 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v)
MElement *e = ge->getMeshElement(j); MElement *e = ge->getMeshElement(j);
if(e->getDim() == 2){ if(e->getDim() == 2){
MFace f = e->getFace(0); MFace f = e->getFace(0);
if(createBoundaries) allLowerDimFaces.insert(f);
for(int p = 0; p < numSlices; p++){ for(int p = 0; p < numSlices; p++){
if(bndFaces[p + 1].find(f) != bndFaces[p + 1].end()){ if(bndFaces[p].find(f) != bndFaces[p].end()){
e->setPartition(p + 1); e->setPartition(p + 1);
break; break;
} }
...@@ -110,8 +122,9 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v) ...@@ -110,8 +122,9 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v)
} }
else if(e->getDim() == 1){ else if(e->getDim() == 1){
MEdge f = e->getEdge(0); MEdge f = e->getEdge(0);
if(createBoundaries) allLowerDimEdges.insert(f);
for(int p = 0; p < numSlices; p++){ for(int p = 0; p < numSlices; p++){
if(bndEdges[p + 1].find(f) != bndEdges[p + 1].end()){ if(bndEdges[p].find(f) != bndEdges[p].end()){
e->setPartition(p + 1); e->setPartition(p + 1);
break; break;
} }
...@@ -121,13 +134,9 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v) ...@@ -121,13 +134,9 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v)
} }
if(createBoundaries){ if(createBoundaries){
#if defined(HAVE_MESH)
Msg::Info("Creating partition boundaries"); Msg::Info("Creating partition boundaries");
#if 0 && defined(HAVE_MESH) // correct & general, but too slow
CreatePartitionBoundaries(m, false, false); CreatePartitionBoundaries(m, false, false);
#else
Msg::Error("Creating partition boundaries requires the mesh module");
#endif
// renumber partition boundaries using the natural slicing order
Msg::Info("Renumbering partition boundaries"); Msg::Info("Renumbering partition boundaries");
std::vector<std::pair<double, GFace*> > parFaces; std::vector<std::pair<double, GFace*> > parFaces;
std::vector<std::pair<double, GEdge*> > parEdges; std::vector<std::pair<double, GEdge*> > parEdges;
...@@ -136,22 +145,22 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v) ...@@ -136,22 +145,22 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v)
GEntity *ge = entities[i]; GEntity *ge = entities[i];
if(ge->geomType() == GEntity::PartitionSurface || if(ge->geomType() == GEntity::PartitionSurface ||
ge->geomType() == GEntity::PartitionCurve){ ge->geomType() == GEntity::PartitionCurve){
double val = pmax; double valmin = pmax;
for(int j = 0; j < ge->getNumMeshElements(); j++){ for(int j = 0; j < ge->getNumMeshElements(); j++){
MElement *e = ge->getMeshElement(j); MElement *e = ge->getMeshElement(j);
for(int k = 0; k < e->getNumVertices(); k++){ for(int k = 0; k < e->getNumVertices(); k++){
MVertex *v = e->getVertex(k); MVertex *v = e->getVertex(k);
val = std::min(val, v->point()[direction]); valmin = std::min(valmin, v->point()[direction]);
} }
} }
if(ge->dim() == 2){ if(ge->dim() == 2){
GFace *gf = (GFace*)ge; GFace *gf = (GFace*)ge;
parFaces.push_back(std::pair<double, GFace*>(val, gf)); parFaces.push_back(std::pair<double, GFace*>(valmin, gf));
m->remove(gf); m->remove(gf);
} }
else{ else{
GEdge *gc = (GEdge*)ge; GEdge *gc = (GEdge*)ge;
parEdges.push_back(std::pair<double, GEdge*>(val, gc)); parEdges.push_back(std::pair<double, GEdge*>(valmin, gc));
m->remove(gc); m->remove(gc);
} }
} }
...@@ -170,6 +179,87 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v) ...@@ -170,6 +179,87 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v)
ge->setMeshMaster(-i-1); ge->setMeshMaster(-i-1);
m->add(ge); m->add(ge);
} }
#else
for(int p = 0; p < numSlices - 1; p++){
std::vector<int> v2(2);
v2[0] = p + 1;
v2[1] = p + 2;
if(dim == 2){
// create partition edge
partitionEdge *pe = new partitionEdge(m, -(p + 1), 0, 0, v2);
m->add(pe);
// compute boundary of cut surface elements
std::set<MEdge, Less_Edge> myBndEdges;
for(std::set<MElement*>::iterator it = cutElements[p].begin();
it != cutElements[p].end(); it++){
for(int i = 0; i < (*it)->getNumEdges(); i++){
MEdge e = (*it)->getEdge(i);
if(myBndEdges.find(e) == myBndEdges.end())
myBndEdges.insert(e);
else
myBndEdges.erase(e);
}
}
// keep edges whose vertices are all >= than the plane, but are not on a
// curve of the original mesh
for(std::set<MEdge, Less_Edge>::iterator it = myBndEdges.begin();
it != myBndEdges.end(); it++){
bool bnd = true;
for(int j = 0; j < it->getNumVertices(); j++){
if(it->getVertex(j)->point()[direction] < pp[p + 1]){
bnd = false;
break;
}
}
if(bnd){
if(allLowerDimEdges.find(*it) == allLowerDimEdges.end()){
pe->lines.push_back(new MLine(it->getVertex(0), it->getVertex(1)));
}
}
}
}
if(dim == 3){
// create partition face
partitionFace *pf = new partitionFace(m, -(p + 1), v2);
m->add(pf);
// compute boundary of cut elements
std::set<MFace, Less_Face> myBndFaces;
for(std::set<MElement*>::iterator it = cutElements[p].begin();
it != cutElements[p].end(); it++){
for(int i = 0; i < (*it)->getNumFaces(); i++){
MFace f = (*it)->getFace(i);
if(myBndFaces.find(f) == myBndFaces.end())
myBndFaces.insert(f);
else
myBndFaces.erase(f);
}
}
// keep faces whose vertices are all >= than the plane, but are not on a
// surface of the original mesh
for(std::set<MFace, Less_Face>::iterator it = myBndFaces.begin();
it != myBndFaces.end(); it++){
bool bnd = true;
for(int j = 0; j < it->getNumVertices(); j++){
if(it->getVertex(j)->point()[direction] < pp[p + 1]){
bnd = false;
break;
}
}
if(bnd){
if(allLowerDimFaces.find(*it) == allLowerDimFaces.end()){
if (it->getNumVertices() == 3)
pf->triangles.push_back
(new MTriangle(it->getVertex(0), it->getVertex(1), it->getVertex(2)));
else
pf->quadrangles.push_back
(new MQuadrangle(it->getVertex(0), it->getVertex(1),
it->getVertex(2), it->getVertex(3)));
}
}
}
}
}
#endif
} }
return v; return v;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment