From b82028bd706c5f7db007698d0016ec44207b00b3 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Thu, 17 Jan 2013 19:40:26 +0000
Subject: [PATCH] better: correct lower dim + sort partition boundaries w.r.t.
 slices

---
 Geo/GEntity.cpp            | 12 +++--
 Plugin/SimplePartition.cpp | 98 ++++++++++++++++++++++++++++++++++++--
 2 files changed, 101 insertions(+), 9 deletions(-)

diff --git a/Geo/GEntity.cpp b/Geo/GEntity.cpp
index 19c2f63cc5..1769283202 100644
--- a/Geo/GEntity.cpp
+++ b/Geo/GEntity.cpp
@@ -72,6 +72,8 @@ GRegion *GEntity::cast2Region() { return dynamic_cast<GRegion*>(this); }
 // sets the entity m from which the mesh will be copied
 void GEntity::setMeshMaster(int m_signed){
 
+  if(m_signed == tag()){ _meshMaster = m_signed; return; }
+
   //  printf("setting mesh master %d to mesh entity %d\n",m_signed,tag());
 
   GEntity *gMaster = 0;
@@ -81,12 +83,12 @@ void GEntity::setMeshMaster(int m_signed){
   case 1 : gMaster = model()->getEdgeByTag(m); break;
   case 2 : gMaster = model()->getFaceByTag(m); break;
   case 3 : gMaster = model()->getRegionByTag(m); break;
-  } 
+  }
   if (!gMaster){
     Msg::Fatal("Model entity %d of dimension %d cannot be the mesh master of model entity %d",m,dim(), tag());
   }
   int masterOfMaster = gMaster->meshMaster();
-  
+
   if (masterOfMaster == gMaster->tag()){
     _meshMaster = m_signed;
   }
@@ -98,7 +100,7 @@ void GEntity::setMeshMaster(int m_signed){
 
 // gets the entity from which the mesh will be copied
 int GEntity::meshMaster() const{
-  
+
   if (_meshMaster == tag()) return tag();
 
   GEntity *gMaster = 0;
@@ -107,12 +109,12 @@ int GEntity::meshMaster() const{
   case 1 : gMaster = model()->getEdgeByTag(abs(_meshMaster)); break;
   case 2 : gMaster = model()->getFaceByTag(abs(_meshMaster)); break;
   case 3 : gMaster = model()->getRegionByTag(abs(_meshMaster)); break;
-  } 
+  }
   if (!gMaster){
     Msg::Fatal("meshMaster : Model entity %d of dimension %d cannot be the mesh master of model entity %d",_meshMaster,dim(),tag());
   }
   int masterOfMaster = gMaster->meshMaster();
-  
+
   if (masterOfMaster == gMaster->tag()){
     return _meshMaster ;
   }
diff --git a/Plugin/SimplePartition.cpp b/Plugin/SimplePartition.cpp
index a5e1a8d69c..4cba39f175 100644
--- a/Plugin/SimplePartition.cpp
+++ b/Plugin/SimplePartition.cpp
@@ -6,6 +6,8 @@
 #include "SimplePartition.h"
 #include "GModel.h"
 #include "MElement.h"
+#include "MFace.h"
+#include "MEdge.h"
 #if defined(HAVE_MESH)
 #include "meshPartition.h"
 #endif
@@ -45,26 +47,40 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v)
   int numSlices = (int)SimplePartitionOptions_Number[0].def;
   int direction = (int)SimplePartitionOptions_Number[1].def;
 
-  // partition the current model
+  // partition the highest dimension elements in the current model (lower
+  // dimension elements en boundaries cannot be tagged a priori: there are
+  // special geometrical cases)
   GModel *m = GModel::current();
   SBoundingBox3d bbox = m->bounds();
   double pmin = bbox.min()[direction], pmax = bbox.max()[direction];
+  int dim = m->getDim();
   std::vector<GEntity*> entities;
   m->getEntities(entities);
+  std::map<int, std::set<MFace, Less_Face> > bndFaces;
+  std::map<int, std::set<MEdge, Less_Edge> > bndEdges;
   for(unsigned int i = 0; i < entities.size(); i++){
-    int n = entities[i]->getNumMeshElements();
-    for(int j = 0; j < n; j++){
-      MElement *e = entities[i]->getMeshElement(j);
+    GEntity *ge = entities[i];
+    if(ge->dim() != dim) continue;
+    for(int j = 0; j < ge->getNumMeshElements(); j++){
+      MElement *e = ge->getMeshElement(j);
       double val = pmax;
+      bool bnd = false;
       for(int k = 0; k < e->getNumVertices(); k++){
         MVertex *v = e->getVertex(k);
         val = std::min(val, v->point()[direction]);
+        if(v->onWhat() && v->onWhat()->dim() != dim) bnd = true;
       }
       for(int p = 0; p < numSlices; p++){
         double p1 = pmin + p * (pmax - pmin) / numSlices;
         double p2 = pmin + (p + 1) * (pmax - pmin) / numSlices;
         if(val >= p1 && val < p2){
           e->setPartition(p + 1);
+          if(bnd){
+            for(int k = 0; k < e->getNumEdges(); k++)
+              bndEdges[p + 1].insert(e->getEdge(k));
+            for(int k = 0; k < e->getNumFaces(); k++)
+              bndFaces[p + 1].insert(e->getFace(k));
+          }
           break;
         }
       }
@@ -72,8 +88,82 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v)
   }
   m->recomputeMeshPartitions();
 
+  // partition lower dimension elements
+  for(unsigned int i = 0; i < entities.size(); i++){
+    GEntity *ge = entities[i];
+    if(ge->dim() == dim) continue;
+    for(int j = 0; j < ge->getNumMeshElements(); j++){
+      MElement *e = ge->getMeshElement(j);
+      if(e->getDim() == 2){
+        MFace f = e->getFace(0);
+        for(int p = 0; p < numSlices; p++){
+          if(bndFaces[p + 1].find(f) != bndFaces[p + 1].end()){
+            e->setPartition(p + 1);
+            break;
+          }
+        }
+      }
+      else if(e->getDim() == 1){
+        MEdge f = e->getEdge(0);
+        for(int p = 0; p < numSlices; p++){
+          if(bndEdges[p + 1].find(f) != bndEdges[p + 1].end()){
+            e->setPartition(p + 1);
+            break;
+          }
+        }
+      }
+    }
+  }
+
+  // create partition boundaries
 #if defined(HAVE_MESH)
   CreatePartitionBoundaries(m, false, false);
 #endif
+
+  // renumber partition boundaries using the natural slicing order
+  std::vector<std::pair<double, GFace*> > parFaces;
+  std::vector<std::pair<double, GEdge*> > parEdges;
+  m->getEntities(entities);
+  for(unsigned int i = 0; i < entities.size(); i++){
+    GEntity *ge = entities[i];
+    if(ge->geomType() == GEntity::PartitionSurface ||
+       ge->geomType() == GEntity::PartitionCurve){
+      double val = pmax;
+      for(int j = 0; j < ge->getNumMeshElements(); j++){
+        MElement *e = ge->getMeshElement(j);
+        for(int k = 0; k < e->getNumVertices(); k++){
+          MVertex *v = e->getVertex(k);
+          val = std::min(val, v->point()[direction]);
+        }
+      }
+      if(ge->dim() == 2){
+        GFace *gf = (GFace*)ge;
+        parFaces.push_back(std::pair<double, GFace*>(val, gf));
+        m->remove(gf);
+      }
+      else{
+        GEdge *gc = (GEdge*)ge;
+        parEdges.push_back(std::pair<double, GEdge*>(val, gc));
+        m->remove(gc);
+      }
+    }
+  }
+
+  std::sort(parFaces.begin(), parFaces.end());
+  for(unsigned int i = 0; i < parFaces.size(); i++){
+    GFace *gf = parFaces[i].second;
+    gf->setTag(-i-1);
+    gf->setMeshMaster(-i-1);
+    m->add(gf);
+  }
+
+  std::sort(parEdges.begin(), parEdges.end());
+  for(unsigned int i = 0; i < parEdges.size(); i++){
+    GEdge *ge = parEdges[i].second;
+    ge->setTag(-i-1);
+    ge->setMeshMaster(-i-1);
+    m->add(ge);
+  }
+
   return v;
 }
-- 
GitLab