17 #include <unordered_map>
18 #include "GmshConfig.h"
25 const std::pair<int, GEntity *> &p2)
const
27 if(p1.first != p2.first)
return p1.first < p2.first;
28 if(p1.second->dim() != p2.second->dim())
29 return p1.second->dim() < p2.second->dim();
30 return p1.second->tag() < p2.second->tag();
37 #define hashmap std::unordered_map
38 #define hashmapentity \
39 std::unordered_map<GEntity *, setorientity, GEntityPtrFullHash, \
41 #define hashmapelement \
42 std::unordered_map<MElement *, GEntity *, MElementPtrHash, MElementPtrEqual>
43 #define hashmapelementpart \
44 std::unordered_map<MElement *, int, MElementPtrHash, MElementPtrEqual>
46 std::unordered_map<MFace, \
47 std::vector<std::pair<MElement *, std::vector<int> > >, \
48 MFaceHash, MFaceEqual>
50 std::unordered_map<MEdge, \
51 std::vector<std::pair<MElement *, std::vector<int> > >, \
52 MEdgeHash, MEdgeEqual>
53 #define hashmapvertex \
54 std::unordered_map<MVertex *, \
55 std::vector<std::pair<MElement *, std::vector<int> > >, \
56 MVertexPtrHash, MVertexPtrEqual>
58 #if defined(HAVE_METIS)
102 std::vector<idx_t> _eind;
105 std::vector<idx_t> _eptr;
107 idx_t *_xadj, *_adjncy;
111 std::vector<MElement *> _element;
113 std::vector<idx_t> _vertex;
116 std::vector<int> _partition;
120 : _model(model), _nparts(0), _ne(0), _nn(0), _dim(0), _xadj(nullptr),
121 _adjncy(nullptr), _vwgt(nullptr)
124 ~Graph() { clear(); }
125 std::size_t nparts()
const {
return _nparts; };
126 std::size_t ne()
const {
return _ne; };
127 std::size_t nn()
const {
return _nn; };
128 int dim()
const {
return _dim; };
129 std::size_t eind(std::size_t i)
const {
return _eind[i]; };
130 std::size_t eptr(std::size_t i)
const {
return _eptr[i]; };
131 idx_t xadj(std::size_t i)
const {
return _xadj[i]; };
132 idx_t *xadj()
const {
return _xadj; };
133 idx_t adjncy(std::size_t i)
const {
return _adjncy[i]; };
134 idx_t *adjncy()
const {
return _adjncy; };
135 idx_t *vwgt()
const {
return _vwgt; };
137 idx_t vertex(std::size_t i)
const {
return _vertex[i]; };
138 int partition(std::size_t i)
const {
return _partition[i]; };
139 std::size_t numNodes()
const {
return _ne; };
140 std::size_t numEdges()
const {
return _xadj[_ne] / 2; };
141 void nparts(std::size_t nparts) { _nparts = nparts; };
142 void ne(std::size_t ne) { _ne = ne; };
143 void nn(std::size_t nn) { _nn = nn; };
144 void dim(
int dim) { _dim = dim; };
145 void eindResize(std::size_t size)
148 _eind.resize(size, 0);
150 void eind(std::size_t i, idx_t eind) { _eind[i] = eind; };
151 void eptrResize(std::size_t size)
154 _eptr.resize(size, 0);
156 void eptr(std::size_t i, idx_t eptr) { _eptr[i] = eptr; };
157 void elementResize(std::size_t size)
160 _element.resize(size,
nullptr);
163 void vertexResize(std::size_t size)
166 _vertex.resize(size, -1);
168 void adjncy(std::size_t i, idx_t adjncy) { _adjncy[i] = adjncy; };
169 void vertex(std::size_t i, idx_t vertex) { _vertex[i] = vertex; };
170 void partition(
const std::vector<idx_t> &epart)
173 _partition.resize(epart.size());
174 for(std::size_t i = 0; i < epart.size(); i++) _partition[i] = epart[i];
191 void clearDualGraph()
204 for(std::size_t i = 0; i < _vertex.size(); i++) _vertex[i] = -1;
206 std::vector<std::set<MElement *, MElementPtrLessThan> >
207 getBoundaryElements(idx_t size = 0)
209 std::vector<std::set<MElement *, MElementPtrLessThan> > elements(
210 (size ? size : _nparts), std::set<MElement *, MElementPtrLessThan>());
211 for(std::size_t i = 0; i < _ne; i++) {
212 for(idx_t j = _xadj[i]; j < _xadj[i + 1]; j++) {
213 if(_partition[i] != _partition[_adjncy[j]]) {
214 if(_element[i]->getDim() == _dim) {
215 elements[_partition[i]].insert(_element[i]);
223 std::vector<GEntity *> createGhostEntities()
225 std::vector<GEntity *> ghostEntities(_nparts, (
GEntity *)
nullptr);
227 for(std::size_t i = 1; i <= _nparts; i++) {
230 ghostEntities[i - 1] =
new ghostEdge(_model, ++elementaryNumber, i);
231 _model->
add(
static_cast<ghostEdge *
>(ghostEntities[i - 1]));
234 ghostEntities[i - 1] =
new ghostFace(_model, ++elementaryNumber, i);
235 _model->
add(
static_cast<ghostFace *
>(ghostEntities[i - 1]));
238 ghostEntities[i - 1] =
new ghostRegion(_model, ++elementaryNumber, i);
244 return ghostEntities;
246 void assignGhostCells()
248 std::vector<GEntity *> ghostEntities = createGhostEntities();
249 for(std::size_t i = 0; i < _ne; i++) {
250 std::set<int> ghostCellsPartition;
251 for(idx_t j = _xadj[i]; j < _xadj[i + 1]; j++) {
252 if(_partition[i] != _partition[_adjncy[j]] &&
253 ghostCellsPartition.find(_partition[_adjncy[j]]) ==
254 ghostCellsPartition.end()) {
255 if(_element[i]->getDim() == _dim) {
258 static_cast<ghostEdge *
>(ghostEntities[_partition[_adjncy[j]]])
259 ->addElement(_element[i]->
getType(), _element[i],
263 static_cast<ghostFace *
>(ghostEntities[_partition[_adjncy[j]]])
264 ->addElement(_element[i]->
getType(), _element[i],
268 static_cast<ghostRegion *
>(ghostEntities[_partition[_adjncy[j]]])
269 ->addElement(_element[i]->
getType(), _element[i],
274 ghostCellsPartition.insert(_partition[_adjncy[j]]);
280 void createDualGraph(
bool connectedAll)
282 std::vector<idx_t> nptr(_nn + 1, 0);
283 std::vector<idx_t> nind(_eptr[_ne], 0);
285 for(std::size_t i = 0; i < _ne; i++) {
286 for(idx_t j = _eptr[i]; j < _eptr[i + 1]; j++) { nptr[_eind[j]]++; }
289 for(std::size_t i = 1; i < _nn; i++) nptr[i] += nptr[i - 1];
290 for(std::size_t i = _nn; i > 0; i--) nptr[i] = nptr[i - 1];
293 for(std::size_t i = 0; i < _ne; i++) {
294 for(idx_t j = _eptr[i]; j < _eptr[i + 1]; j++) {
295 nind[nptr[_eind[j]]++] = i;
299 for(std::size_t i = _nn; i > 0; i--) nptr[i] = nptr[i - 1];
302 _xadj =
new idx_t[_ne + 1];
303 for(std::size_t i = 0; i < _ne + 1; i++) _xadj[i] = 0;
305 std::vector<idx_t> nbrs(_ne, 0);
306 std::vector<idx_t> marker(_ne, 0);
307 for(std::size_t i = 0; i < _ne; i++) {
309 for(idx_t j = _eptr[i]; j < _eptr[i + 1]; j++) {
310 for(idx_t k = nptr[_eind[j]]; k < nptr[_eind[j] + 1]; k++) {
311 if(nind[k] != (idx_t)i) {
312 if(marker[nind[k]] == 0) nbrs[l++] = nind[k];
318 std::size_t nbrsNeighbors = 0;
319 for(std::size_t j = 0; j < l; j++) {
320 if(marker[nbrs[j]] >=
323 _element[i]->numCommonNodesInDualGraph(_element[nbrs[j]])))
329 _xadj[i] = nbrsNeighbors;
332 for(std::size_t i = 1; i < _ne; i++) _xadj[i] = _xadj[i] + _xadj[i - 1];
333 for(std::size_t i = _ne; i > 0; i--) _xadj[i] = _xadj[i - 1];
336 _adjncy =
new idx_t[_xadj[_ne]];
337 for(idx_t i = 0; i < _xadj[_ne]; i++) _adjncy[i] = 0;
339 for(std::size_t i = 0; i < _ne; i++) {
341 for(idx_t j = _eptr[i]; j < _eptr[i + 1]; j++) {
342 for(idx_t k = nptr[_eind[j]]; k < nptr[_eind[j] + 1]; k++) {
343 if(nind[k] != (idx_t)i) {
344 if(marker[nind[k]] == 0) nbrs[l++] = nind[k];
350 for(std::size_t j = 0; j < l; j++) {
351 if(marker[nbrs[j]] >=
354 _element[i]->numCommonNodesInDualGraph(_element[nbrs[j]]))) {
355 _adjncy[_xadj[i]] = nbrs[j];
356 _xadj[i] = _xadj[i] + 1;
362 for(std::size_t i = _ne; i > 0; i--) _xadj[i] = _xadj[i - 1];
365 void fillDefaultWeights()
376 _vwgt =
new idx_t[_ne];
384 for(std::size_t i = 0; i < _ne; i++) {
385 if(!_element[i]) { _vwgt[i] = 1; }
387 _vwgt[i] = (_element[i]->getDim() == _dim ? 1 : 0);
392 for(std::size_t i = 0; i < _ne; i++) {
393 if(!_element[i]) { _vwgt[i] = 1; }
395 switch(_element[i]->
getType()) {
417 default: _vwgt[i] = 1;
break;
425 template <
class ITERATOR>
426 static void fillElementsToNodesMap(Graph &graph,
GEntity *entity,
427 idx_t &eptrIndex, idx_t &eindIndex,
428 idx_t &numVertex, ITERATOR it_beg,
431 for(ITERATOR it = it_beg; it != it_end; ++it) {
432 const std::size_t numVertices = (*it)->getNumPrimaryVertices();
433 graph.element(eptrIndex++, *it);
434 graph.eptr(eptrIndex, graph.eptr(eptrIndex - 1) + numVertices);
435 for(std::size_t i = 0; i < numVertices; i++) {
436 if(graph.vertex((*it)->getVertex(i)->getNum() - 1) == -1) {
437 graph.vertex((*it)->getVertex(i)->getNum() - 1, numVertex++);
439 graph.eind(eindIndex, graph.vertex((*it)->getVertex(i)->getNum() - 1));
445 static std::size_t getSizeOfEind(
GModel *model)
447 std::size_t size = 0;
450 size += 4 * (*it)->tetrahedra.size();
451 size += 8 * (*it)->hexahedra.size();
452 size += 6 * (*it)->prisms.size();
453 size += 5 * (*it)->pyramids.size();
454 size += 4 * (*it)->trihedra.size();
459 size += 3 * (*it)->triangles.size();
460 size += 4 * (*it)->quadrangles.size();
465 size += 2 * (*it)->lines.size();
470 size += 1 * (*it)->points.size();
478 static int makeGraph(
GModel *model, Graph &graph,
int selectDim)
480 std::size_t eindSize = 0;
485 graph.elementResize(graph.ne());
487 graph.eptrResize(graph.ne() + 1);
489 eindSize = getSizeOfEind(model);
490 graph.eindResize(eindSize);
494 std::vector<GEntity *> entities;
497 std::set<MVertex *> vertices;
498 for(std::size_t i = 0; i < entities.size(); i++) {
499 if(entities[i]->dim() == selectDim) {
500 switch(entities[i]->dim()) {
501 case 3: tmp->
add(
static_cast<GRegion *
>(entities[i]));
break;
502 case 2: tmp->
add(
static_cast<GFace *
>(entities[i]));
break;
503 case 1: tmp->
add(
static_cast<GEdge *
>(entities[i]));
break;
504 case 0: tmp->
add(
static_cast<GVertex *
>(entities[i]));
break;
507 for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++) {
508 for(std::size_t k = 0;
510 vertices.insert(entities[i]->getMeshElement(j)->getVertex(k));
517 graph.nn(vertices.size());
519 graph.elementResize(graph.ne());
521 graph.eptrResize(graph.ne() + 1);
523 eindSize = getSizeOfEind(tmp);
524 graph.eindResize(eindSize);
534 if(graph.ne() == 0) {
538 if(graph.dim() == 0) {
544 if(selectDim < 0 || selectDim == 3) {
547 fillElementsToNodesMap(graph, r, eptrIndex, eindIndex, numVertex,
549 fillElementsToNodesMap(graph, r, eptrIndex, eindIndex, numVertex,
551 fillElementsToNodesMap(graph, r, eptrIndex, eindIndex, numVertex,
553 fillElementsToNodesMap(graph, r, eptrIndex, eindIndex, numVertex,
555 fillElementsToNodesMap(graph, r, eptrIndex, eindIndex, numVertex,
561 if(selectDim < 0 || selectDim == 2) {
564 fillElementsToNodesMap(graph,
f, eptrIndex, eindIndex, numVertex,
565 f->triangles.begin(),
f->triangles.end());
566 fillElementsToNodesMap(graph,
f, eptrIndex, eindIndex, numVertex,
567 f->quadrangles.begin(),
f->quadrangles.end());
572 if(selectDim < 0 || selectDim == 1) {
575 fillElementsToNodesMap(graph, e, eptrIndex, eindIndex, numVertex,
581 if(selectDim < 0 || selectDim == 0) {
584 fillElementsToNodesMap(graph, v, eptrIndex, eindIndex, numVertex,
594 static int partitionGraph(Graph &graph,
bool verbose)
597 std::stringstream opt;
599 idx_t metisOptions[METIS_NOPTIONS];
600 METIS_SetDefaultOptions(metisOptions);
602 opt <<
"npart:" << graph.nparts();
604 opt <<
", sizeof(idx_t):" << 8 *
sizeof(idx_t);
609 metisOptions[METIS_OPTION_PTYPE] = METIS_PTYPE_RB;
613 metisOptions[METIS_OPTION_PTYPE] = METIS_PTYPE_KWAY;
616 default: opt <<
"default";
break;
621 metisOptions[METIS_OPTION_UFACTOR] =
632 metisOptions[METIS_OPTION_CTYPE] = METIS_CTYPE_RM;
636 metisOptions[METIS_OPTION_CTYPE] = METIS_CTYPE_SHEM;
639 default: opt <<
"default";
break;
645 metisOptions[METIS_OPTION_RTYPE] = METIS_RTYPE_FM;
649 metisOptions[METIS_OPTION_RTYPE] = METIS_RTYPE_GREEDY;
653 metisOptions[METIS_OPTION_RTYPE] = METIS_RTYPE_SEP2SIDED;
657 metisOptions[METIS_OPTION_RTYPE] = METIS_RTYPE_SEP1SIDED;
660 default: opt <<
"default";
break;
666 metisOptions[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT;
670 metisOptions[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_VOL;
673 default: opt <<
"default";
break;
679 metisOptions[METIS_OPTION_MINCONN] = 0;
683 metisOptions[METIS_OPTION_MINCONN] = 1;
686 default: opt <<
"default";
break;
689 if(verbose)
Msg::Info(
"Running METIS with %s", opt.str().c_str());
692 metisOptions[METIS_OPTION_NUMBERING] = 0;
695 std::vector<idx_t> epart(graph.ne());
696 idx_t ne = graph.ne();
697 idx_t numPart = graph.nparts();
699 graph.fillDefaultWeights();
702 graph.createDualGraph(
false);
704 if(metisOptions[METIS_OPTION_PTYPE] == METIS_PTYPE_KWAY) {
705 metisError = METIS_PartGraphKway(
706 &ne, &ncon, graph.xadj(), graph.adjncy(), graph.vwgt(),
nullptr,
707 nullptr, &numPart,
nullptr,
nullptr, metisOptions, &objval, &epart[0]);
710 metisError = METIS_PartGraphRecursive(
711 &ne, &ncon, graph.xadj(), graph.adjncy(), graph.vwgt(),
nullptr,
712 nullptr, &numPart,
nullptr,
nullptr, metisOptions, &objval, &epart[0]);
716 case METIS_OK:
break;
717 case METIS_ERROR_INPUT:
Msg::Error(
"METIS input error");
return 1;
718 case METIS_ERROR_MEMORY:
Msg::Error(
"METIS memory error");
return 1;
724 for(
int i = 1; i < 4; i++) {
725 for(std::size_t j = 0; j < graph.ne(); j++) {
726 if(graph.element(j)->getDim() == graph.dim())
continue;
728 for(idx_t k = graph.xadj(j); k < graph.xadj(j + 1); k++) {
729 if(graph.element(j)->getDim() ==
730 graph.element(graph.adjncy(k))->getDim() - i) {
731 if(epart[j] != epart[graph.adjncy(k)]) {
732 epart[j] = epart[graph.adjncy(k)];
739 graph.partition(epart);
740 if(verbose)
Msg::Info(
"%d partitions, %d total edge-cuts", numPart, objval);
750 template <
class ENTITY,
class ITERATOR>
753 std::vector<ENTITY *> &newEntities, ITERATOR it_beg,
754 ITERATOR it_end,
int &elementaryNumber)
756 for(ITERATOR it = it_beg; it != it_end; ++it) {
757 int partition = elmToPartition[(*it)] - 1;
759 if(!newEntities[partition]) {
760 std::vector<int> partitions;
761 partitions.push_back(partition + 1);
762 ENTITY *de =
new ENTITY(model, ++elementaryNumber, partitions);
764 newEntities[partition] = de;
767 newEntities[partition]->addElement((*it)->getType(), *it);
771 template <
class ITERATOR>
772 static void setVerticesToEntity(
GEntity *entity, ITERATOR it_beg,
775 for(ITERATOR it = it_beg; it != it_end; ++it) {
776 for(std::size_t i = 0; i < (*it)->getNumVertices(); i++) {
777 if(!(*it)->getVertex(i)->onWhat()) {
778 (*it)->getVertex(i)->setEntity(entity);
785 template <
class ITERATOR>
786 static void removeVerticesEntity(ITERATOR it_beg, ITERATOR it_end)
788 for(ITERATOR it = it_beg; it != it_end; ++it) {
789 for(std::size_t i = 0; i < (*it)->getNumMeshElements(); i++) {
790 for(std::size_t j = 0; j < (*it)->getMeshElement(i)->
getNumVertices();
792 (*it)->getMeshElement(i)->getVertex(j)->setEntity(
nullptr);
795 (*it)->mesh_vertices.clear();
800 static void assignMeshVertices(
GModel *model)
809 setVerticesToEntity(*it, (*it)->points.begin(), (*it)->points.end());
814 setVerticesToEntity(*it, (*it)->lines.begin(), (*it)->lines.end());
819 setVerticesToEntity(*it, (*it)->triangles.begin(), (*it)->triangles.end());
820 setVerticesToEntity(*it, (*it)->quadrangles.begin(),
821 (*it)->quadrangles.end());
826 setVerticesToEntity(*it, (*it)->tetrahedra.begin(),
827 (*it)->tetrahedra.end());
828 setVerticesToEntity(*it, (*it)->hexahedra.begin(), (*it)->hexahedra.end());
829 setVerticesToEntity(*it, (*it)->prisms.begin(), (*it)->prisms.end());
830 setVerticesToEntity(*it, (*it)->pyramids.begin(), (*it)->pyramids.end());
831 setVerticesToEntity(*it, (*it)->trihedra.begin(), (*it)->trihedra.end());
835 static void fillConnectedElements(
836 std::vector<std::set<MElement *, MElementPtrLessThan> > &connectedElements,
839 std::stack<idx_t> elementStack;
840 std::set<MElement *, MElementPtrLessThan> elements;
841 idx_t startElement = 0;
843 std::size_t size = 0;
844 idx_t isolatedElements = 0;
848 elementStack.push(startElement);
849 elements.insert(graph.element(startElement));
851 while(elementStack.size() != 0) {
852 idx_t top = elementStack.top();
854 elements.insert(graph.element(top));
856 for(idx_t i = graph.xadj(top); i < graph.xadj(top + 1); i++) {
857 if(graph.adjncy(i) != 0) {
858 elementStack.push(graph.adjncy(i));
863 connectedElements.push_back(elements);
864 size += elements.size();
867 stop = (size == graph.ne() ? true :
false);
871 for(std::size_t i = 0; i < graph.ne(); i++) {
872 for(idx_t j = graph.xadj(i); j < graph.xadj(i + 1); j++) {
873 if(graph.adjncy(j) != 0) {
880 if(startElement == 0) {
881 idx_t skipIsolatedElements = 0;
882 for(std::size_t i = 1; i < graph.ne(); i++) {
883 if(graph.xadj(i) == graph.xadj(i + 1)) {
884 if(skipIsolatedElements == isolatedElements) {
889 skipIsolatedElements++;
898 divideNonConnectedEntities(
GModel *model,
int dim,
899 std::set<GRegion *, GEntityPtrLessThan> ®ions,
900 std::set<GFace *, GEntityPtrLessThan> &
faces,
901 std::set<GEdge *, GEntityPtrLessThan> &
edges,
902 std::set<GVertex *, GEntityPtrLessThan> &vertices)
907 if(dim < 0 || dim == 0) {
910 for(
auto it = vertices.begin(); it != vertices.end(); ++it) {
928 std::vector<GEdge *> BRepEdges = vertex->
edges();
929 if(!BRepEdges.empty()) {
930 for(
auto itBRep = BRepEdges.begin(); itBRep != BRepEdges.end();
932 if(vertex == (*itBRep)->getBeginVertex()) {
933 (*itBRep)->setVertex(pvertex, 1);
936 if(vertex == (*itBRep)->getEndVertex()) {
937 (*itBRep)->setVertex(pvertex, -1);
954 if(dim < 0 || dim == 1) {
960 graph.elementResize(graph.ne());
962 graph.eptrResize(graph.ne() + 1);
964 std::size_t eindSize = getSizeOfEind(model);
965 graph.eindResize(eindSize);
969 for(
auto it =
edges.begin(); it !=
edges.end(); ++it) {
976 graph.clearDualGraph();
983 fillElementsToNodesMap(graph, edge, eptrIndex, eindIndex, numVertex,
986 graph.createDualGraph(
false);
990 if(((graph.numNodes() - 1) * (graph.numNodes() - 2)) / 2 <
995 std::vector<std::set<MElement *, MElementPtrLessThan> >
997 fillConnectedElements(connectedElements, graph);
999 if(connectedElements.size() > 1) {
1001 std::vector<GFace *> BRepFaces = edge->
faces();
1003 std::vector<int> oldOrientations;
1004 oldOrientations.reserve(BRepFaces.size());
1006 if(!BRepFaces.empty()) {
1007 for(
auto itBRep = BRepFaces.begin(); itBRep != BRepFaces.end();
1009 oldOrientations.push_back((*itBRep)->delEdge(edge));
1013 for(std::size_t i = 0; i < connectedElements.size(); i++) {
1016 new partitionEdge(model, ++elementaryNumber,
nullptr,
nullptr,
1022 for(
auto itSet = connectedElements[i].begin();
1023 itSet != connectedElements[i].end(); ++itSet) {
1025 pedge->
addElement((*itSet)->getType(), (*itSet));
1028 if(BRepFaces.size() > 0) {
1030 for(
auto itBRep = BRepFaces.begin(); itBRep != BRepFaces.end();
1032 (*itBRep)->setEdge(pedge, oldOrientations[j]);
1040 edge->
lines.clear();
1045 connectedElements.clear();
1051 if(dim < 0 || dim == 2) {
1057 graph.elementResize(graph.ne());
1059 graph.eptrResize(graph.ne() + 1);
1061 std::size_t eindSize = getSizeOfEind(model);
1062 graph.eindResize(eindSize);
1066 for(
auto it =
faces.begin(); it !=
faces.end(); ++it) {
1073 graph.clearDualGraph();
1074 graph.eraseVertex();
1076 idx_t eptrIndex = 0;
1077 idx_t eindIndex = 0;
1078 idx_t numVertex = 0;
1080 fillElementsToNodesMap(graph, face, eptrIndex, eindIndex, numVertex,
1082 fillElementsToNodesMap(graph, face, eptrIndex, eindIndex, numVertex,
1085 graph.nn(numVertex);
1086 graph.createDualGraph(
false);
1090 if(((graph.numNodes() - 1) * (graph.numNodes() - 2)) / 2 <
1095 std::vector<std::set<MElement *, MElementPtrLessThan> >
1097 fillConnectedElements(connectedElements, graph);
1099 if(connectedElements.size() > 1) {
1101 std::list<GRegion *> BRepRegions = face->
regions();
1102 std::vector<int> oldOrientations;
1103 if(BRepRegions.size() > 0) {
1104 for(
auto itBRep = BRepRegions.begin(); itBRep != BRepRegions.end();
1106 oldOrientations.push_back((*itBRep)->delFace(face));
1110 for(std::size_t i = 0; i < connectedElements.size(); i++) {
1118 for(
auto itSet = connectedElements[i].begin();
1119 itSet != connectedElements[i].end(); ++itSet) {
1121 pface->
addElement((*itSet)->getType(), (*itSet));
1124 if(BRepRegions.size() > 0) {
1126 for(
auto itBRep = BRepRegions.begin();
1127 itBRep != BRepRegions.end(); ++itBRep) {
1128 (*itBRep)->setFace(pface, oldOrientations[j]);
1142 connectedElements.clear();
1148 if(dim < 0 || dim == 3) {
1154 graph.elementResize(graph.ne());
1156 graph.eptrResize(graph.ne() + 1);
1158 std::size_t eindSize = getSizeOfEind(model);
1159 graph.eindResize(eindSize);
1163 for(
auto it = regions.begin(); it != regions.end(); ++it) {
1170 graph.clearDualGraph();
1171 graph.eraseVertex();
1173 idx_t eptrIndex = 0;
1174 idx_t eindIndex = 0;
1175 idx_t numVertex = 0;
1177 fillElementsToNodesMap(graph, region, eptrIndex, eindIndex, numVertex,
1180 fillElementsToNodesMap(graph, region, eptrIndex, eindIndex, numVertex,
1183 fillElementsToNodesMap(graph, region, eptrIndex, eindIndex, numVertex,
1185 fillElementsToNodesMap(graph, region, eptrIndex, eindIndex, numVertex,
1188 fillElementsToNodesMap(graph, region, eptrIndex, eindIndex, numVertex,
1191 graph.nn(numVertex);
1192 graph.createDualGraph(
false);
1196 if(((graph.numNodes() - 1) * (graph.numNodes() - 2)) / 2 <
1201 std::vector<std::set<MElement *, MElementPtrLessThan> >
1203 fillConnectedElements(connectedElements, graph);
1205 if(connectedElements.size() > 1) {
1207 for(std::size_t i = 0; i < connectedElements.size(); i++) {
1214 model->
add(pregion);
1215 for(
auto itSet = connectedElements[i].begin();
1216 itSet != connectedElements[i].end(); ++itSet) {
1218 pregion->
addElement((*itSet)->getType(), (*itSet));
1232 connectedElements.clear();
1243 std::set<GRegion *, GEntityPtrLessThan> regions = model->
getRegions();
1244 std::set<GFace *, GEntityPtrLessThan>
faces = model->
getFaces();
1245 std::set<GEdge *, GEntityPtrLessThan>
edges = model->
getEdges();
1246 std::set<GVertex *, GEntityPtrLessThan> vertices = model->
getVertices();
1249 for(
auto it = vertices.begin(); it != vertices.end(); ++it) {
1253 assignElementsToEntities(model, elmToPartition, newVertices,
1254 (*it)->points.begin(), (*it)->points.end(),
1258 if(newVertices[i]) {
1259 static_cast<partitionVertex *
>(newVertices[i])->setParentEntity((*it));
1265 (*it)->points.clear();
1269 for(
auto it =
edges.begin(); it !=
edges.end(); ++it) {
1272 assignElementsToEntities(model, elmToPartition, newEdges,
1273 (*it)->lines.begin(), (*it)->lines.end(),
1278 static_cast<partitionEdge *
>(newEdges[i])->setParentEntity(*it);
1284 (*it)->lines.clear();
1288 for(
auto it =
faces.begin(); it !=
faces.end(); ++it) {
1291 assignElementsToEntities(model, elmToPartition, newFaces,
1292 (*it)->triangles.begin(), (*it)->triangles.end(),
1294 assignElementsToEntities(model, elmToPartition, newFaces,
1295 (*it)->quadrangles.begin(),
1296 (*it)->quadrangles.end(), elementaryNumber);
1298 std::list<GRegion *> BRepRegions = (*it)->regions();
1301 static_cast<partitionFace *
>(newFaces[i])->setParentEntity(*it);
1307 (*it)->triangles.clear();
1308 (*it)->quadrangles.clear();
1312 for(
auto it = regions.begin(); it != regions.end(); ++it) {
1316 assignElementsToEntities(model, elmToPartition, newRegions,
1317 (*it)->tetrahedra.begin(), (*it)->tetrahedra.end(),
1319 assignElementsToEntities(model, elmToPartition, newRegions,
1320 (*it)->hexahedra.begin(), (*it)->hexahedra.end(),
1322 assignElementsToEntities(model, elmToPartition, newRegions,
1323 (*it)->prisms.begin(), (*it)->prisms.end(),
1325 assignElementsToEntities(model, elmToPartition, newRegions,
1326 (*it)->pyramids.begin(), (*it)->pyramids.end(),
1328 assignElementsToEntities(model, elmToPartition, newRegions,
1329 (*it)->trihedra.begin(), (*it)->trihedra.end(),
1340 (*it)->tetrahedra.clear();
1341 (*it)->hexahedra.clear();
1342 (*it)->prisms.clear();
1343 (*it)->pyramids.clear();
1344 (*it)->trihedra.clear();
1354 divideNonConnectedEntities(model, -1, regions,
faces,
edges, vertices);
1361 if(dim < 0 || dim == 3) {
1363 for(
auto itElm = (*it)->tetrahedra.begin();
1364 itElm != (*it)->tetrahedra.end(); ++itElm)
1365 elmToEntity.insert(std::make_pair(*itElm, *it));
1366 for(
auto itElm = (*it)->hexahedra.begin();
1367 itElm != (*it)->hexahedra.end(); ++itElm)
1368 elmToEntity.insert(std::make_pair(*itElm, *it));
1369 for(
auto itElm = (*it)->prisms.begin(); itElm != (*it)->prisms.end();
1371 elmToEntity.insert(std::make_pair(*itElm, *it));
1372 for(
auto itElm = (*it)->pyramids.begin(); itElm != (*it)->pyramids.end();
1374 elmToEntity.insert(std::make_pair(*itElm, *it));
1375 for(
auto itElm = (*it)->trihedra.begin(); itElm != (*it)->trihedra.end();
1377 elmToEntity.insert(std::make_pair(*itElm, *it));
1382 if(dim < 0 || dim == 2) {
1384 for(
auto itElm = (*it)->triangles.begin();
1385 itElm != (*it)->triangles.end(); ++itElm)
1386 elmToEntity.insert(std::make_pair(*itElm, *it));
1387 for(
auto itElm = (*it)->quadrangles.begin();
1388 itElm != (*it)->quadrangles.end(); ++itElm)
1389 elmToEntity.insert(std::make_pair(*itElm, *it));
1394 if(dim < 0 || dim == 1) {
1396 for(
auto itElm = (*it)->lines.begin(); itElm != (*it)->lines.end();
1398 elmToEntity.insert(std::make_pair(*itElm, *it));
1403 if(dim < 0 || dim == 0) {
1405 for(
auto itElm = (*it)->points.begin(); itElm != (*it)->points.end();
1407 elmToEntity.insert(std::make_pair(*itElm, *it));
1412 static MElement *getReferenceElement(
1413 const std::vector<std::pair<
MElement *, std::vector<int> > > &elementPairs)
1415 int min = std::numeric_limits<int>::max();
1416 std::vector<std::pair<MElement *, std::vector<int> > > minSizeElementPairs;
1417 std::vector<std::pair<MElement *, std::vector<int> > > minSizeElementPairsTmp;
1421 for(std::size_t i = 0; i < elementPairs.size(); i++) {
1422 if(min > (
int)elementPairs[i].second.size()) {
1423 minSizeElementPairs.clear();
1424 min = elementPairs[i].second.size();
1425 minSizeElementPairs.push_back(elementPairs[i]);
1427 else if(min == (
int)elementPairs[i].second.size()) {
1428 minSizeElementPairs.push_back(elementPairs[i]);
1433 if(minSizeElementPairs.size() == elementPairs.size()) {
1434 bool isEqual =
true;
1435 for(std::size_t i = 1; i < minSizeElementPairs.size(); i++) {
1436 if(minSizeElementPairs[i].second != minSizeElementPairs[0].second) {
1441 if(isEqual)
return nullptr;
1444 while(minSizeElementPairs.size() > 1) {
1445 min = std::numeric_limits<int>::max();
1446 for(std::size_t i = 0; i < minSizeElementPairs.size(); i++) {
1448 if(minSizeElementPairs[i].second.size() == 0)
1449 return minSizeElementPairs[0].first;
1450 if(min > minSizeElementPairs[i].second[0]) {
1451 min = minSizeElementPairs[i].second[0];
1455 for(std::size_t i = 0; i < minSizeElementPairs.size(); i++) {
1456 if(min == minSizeElementPairs[i].second[0]) {
1457 minSizeElementPairs[i].second.erase(
1458 minSizeElementPairs[i].second.begin());
1459 minSizeElementPairsTmp.push_back(minSizeElementPairs[i]);
1462 minSizeElementPairs.clear();
1463 minSizeElementPairs = std::move(minSizeElementPairsTmp);
1464 minSizeElementPairsTmp.clear();
1467 return minSizeElementPairs[0].first;
1470 static void getPartitionInVector(
1471 std::vector<int> &partitions,
1472 const std::vector<std::pair<
MElement *, std::vector<int> > > &boundaryPair)
1474 for(std::size_t i = 0; i < boundaryPair.size(); i++) {
1475 for(std::size_t j = 0; j < boundaryPair[i].second.size(); j++) {
1476 if(std::find(partitions.begin(), partitions.end(),
1477 boundaryPair[i].second[j]) == partitions.end()) {
1478 partitions.push_back(boundaryPair[i].second[j]);
1483 std::sort(partitions.begin(), partitions.end());
1486 template <
class PART_ENTITY,
class LESS_PART_ENTITY>
1487 static PART_ENTITY *createPartitionEntity(
1488 std::pair<
typename std::multimap<PART_ENTITY *,
GEntity *,
1489 LESS_PART_ENTITY>::iterator,
1490 typename std::multimap<PART_ENTITY *,
GEntity *,
1491 LESS_PART_ENTITY>::iterator> &ret,
1492 GModel *model,
int &numEntity,
const std::vector<int> &partitions,
1493 GEntity *referenceEntity, PART_ENTITY **newEntity,
1494 typename std::multimap<PART_ENTITY *, GEntity *, LESS_PART_ENTITY> &pentities)
1496 PART_ENTITY *ppe =
nullptr;
1498 if(ret.first == ret.second) {
1500 ppe =
new PART_ENTITY(model, ++numEntity, partitions);
1502 pentities.insert(std::make_pair(ppe, referenceEntity));
1507 for(
auto it = ret.first; it != ret.second; ++it) {
1508 if(referenceEntity == it->second) { ppe = it->first; }
1512 ppe =
new PART_ENTITY(model, ++numEntity, partitions);
1514 pentities.insert(std::make_pair(ppe, referenceEntity));
1525 const std::vector<int> &partitions,
1526 std::multimap<partitionFace *, GEntity *, partitionFacePtrLessThan> &pfaces,
1535 ret = pfaces.equal_range(&pf);
1538 createPartitionEntity(ret, model, numEntity, partitions,
1539 elementToEntity[reference], &newEntity, pfaces);
1541 for(
int i = 0; i < reference->
getNumFaces(); i++) {
1542 if(reference->
getFace(i) == me) {
1549 std::vector<MVertex *> verts;
1552 if(verts.size() == 3) {
1556 else if(verts.size() == 6) {
1562 new MTriangleN(verts, verts.back()->getPolynomialOrder());
1567 std::vector<MVertex *> verts;
1570 if(verts.size() == 4) {
1574 else if(verts.size() == 8) {
1578 else if(verts.size() == 9) {
1584 new MQuadrangleN(verts, verts.back()->getPolynomialOrder());
1594 const std::vector<int> &partitions,
1595 std::multimap<partitionEdge *, GEntity *, partitionEdgePtrLessThan> &pedges,
1604 ret = pedges.equal_range(&pe);
1607 createPartitionEntity(ret, model, numEntity, partitions,
1608 elementToEntity[reference], &newEntity, pedges);
1611 for(
int i = 0; i < reference->
getNumEdges(); i++) {
1612 if(reference->
getEdge(i) == me) {
1619 std::vector<MVertex *> verts;
1622 if(verts.size() == 2) {
1626 else if(verts.size() == 3) {
1641 const std::vector<int> &partitions,
1642 std::multimap<partitionVertex *, GEntity *, partitionVertexPtrLessThan>
1652 ret = pvertices.equal_range(&pv);
1655 createPartitionEntity(ret, model, numEntity, partitions,
1656 elementToEntity[reference], &newEntity, pvertices);
1666 std::vector<MVertex *> vertices;
1667 element->getVertices(vertices);
1669 for(
int i = 0; i < reference->
getNumFaces(); i++) {
1670 if(reference->
getFace(i) == face) {
1671 std::vector<MVertex *> referenceVertices;
1674 if(referenceVertices == vertices)
1681 else if(
element->getDim() == 1) {
1682 std::vector<MVertex *> vertices;
1683 element->getVertices(vertices);
1685 for(
int i = 0; i < reference->
getNumEdges(); i++) {
1686 if(reference->
getEdge(i) == face) {
1687 std::vector<MVertex *> referenceVertices;
1690 if(referenceVertices == vertices)
1697 else if(
element->getDim() == 0) {
1698 std::vector<MVertex *> vertices;
1699 element->getVertices(vertices);
1701 std::vector<MVertex *> referenceVertices;
1704 if(referenceVertices[0] == vertices[0])
return 1;
1705 if(referenceVertices[1] == vertices[0])
return -1;
1711 static void assignBrep(
GModel *model,
1712 std::map<GEntity *, MElement *, GEntityPtrFullLessThan>
1713 &boundaryEntityAndRefElement,
1719 for(
auto it = boundaryEntityAndRefElement.begin();
1720 it != boundaryEntityAndRefElement.end(); ++it) {
1721 static_cast<GRegion *
>(it->first)->setFace(
1722 entity, computeOrientation(it->second, entity->
getMeshElement(0)));
1726 else if(e->
dim() == 1) {
1729 for(
auto it = boundaryEntityAndRefElement.begin();
1730 it != boundaryEntityAndRefElement.end(); ++it) {
1731 static_cast<GFace *
>(it->first)->setEdge(
1732 entity, computeOrientation(it->second, entity->
getMeshElement(0)));
1736 else if(e->
dim() == 0) {
1739 for(
auto it = boundaryEntityAndRefElement.begin();
1740 it != boundaryEntityAndRefElement.end(); ++it) {
1741 static_cast<GEdge *
>(it->first)->setVertex(
1742 entity, computeOrientation(it->second, entity->
getMeshElement(0)));
1748 static void assignNewEntityBRep(Graph &graph,
hashmapelement &elementToEntity)
1750 std::set<std::pair<GEntity *, GEntity *> > brepWithoutOri;
1752 for(std::size_t i = 0; i < graph.ne(); i++) {
1753 MElement *current = graph.element(i);
1754 for(idx_t j = graph.xadj(i); j < graph.xadj(i + 1); j++) {
1755 if(current->
getDim() == graph.element(graph.adjncy(j))->getDim() + 1) {
1756 GEntity *g1 = elementToEntity[current];
1757 GEntity *g2 = elementToEntity[graph.element(graph.adjncy(j))];
1758 if(brepWithoutOri.find(std::pair<GEntity *, GEntity *>(g1, g2)) ==
1759 brepWithoutOri.end()) {
1761 computeOrientation(current, graph.element(graph.adjncy(j)));
1762 brepWithoutOri.insert(std::make_pair(g1, g2));
1763 brep[g1].insert(std::make_pair(ori, g2));
1769 for(
auto it = brep.begin(); it != brep.end(); ++it) {
1770 switch(it->first->dim()) {
1772 for(
auto itSet = it->second.begin(); itSet != it->second.end(); ++itSet) {
1773 static_cast<GRegion *
>(it->first)->setFace(
1774 static_cast<GFace *
>(itSet->second), itSet->first);
1775 static_cast<GFace *
>(itSet->second)
1776 ->addRegion(
static_cast<GRegion *
>(it->first));
1780 for(
auto itSet = it->second.begin(); itSet != it->second.end(); ++itSet) {
1781 static_cast<GFace *
>(it->first)->setEdge(
1782 static_cast<GEdge *
>(itSet->second), itSet->first);
1783 static_cast<GEdge *
>(itSet->second)
1784 ->addFace(
static_cast<GFace *
>(it->first));
1788 for(
auto itSet = it->second.begin(); itSet != it->second.end(); ++itSet) {
1789 static_cast<GEdge *
>(it->first)->setVertex(
1790 static_cast<GVertex *
>(itSet->second), itSet->first);
1791 static_cast<GVertex *
>(itSet->second)
1792 ->addEdge(
static_cast<GEdge *
>(it->first));
1801 static void createPartitionTopology(
1803 const std::vector<std::set<MElement *, MElementPtrLessThan> >
1809 fillElementToEntity(model, elementToEntity, -1);
1810 assignNewEntityBRep(meshGraph, elementToEntity);
1812 std::multimap<partitionFace *, GEntity *, partitionFacePtrLessThan> pfaces;
1813 std::multimap<partitionEdge *, GEntity *, partitionEdgePtrLessThan> pedges;
1814 std::multimap<partitionVertex *, GEntity *, partitionVertexPtrLessThan>
1821 std::set<GRegion *, GEntityPtrLessThan> regions = model->
getRegions();
1822 std::set<GFace *, GEntityPtrLessThan>
faces = model->
getFaces();
1823 std::set<GEdge *, GEntityPtrLessThan>
edges = model->
getEdges();
1824 std::set<GVertex *, GEntityPtrLessThan> vertices = model->
getVertices();
1827 Msg::Info(
" - Creating partition surfaces");
1830 for(
auto it = boundaryElements[i].begin();
1831 it != boundaryElements[i].end(); ++it) {
1832 for(
int j = 0; j < (*it)->getNumFaces(); j++) {
1833 faceToElement[(*it)->getFace(j)].push_back(
1834 std::make_pair(*it, std::vector<int>(1, i + 1)));
1839 for(
auto it = faceToElement.begin(); it != faceToElement.end(); ++it) {
1842 std::vector<int> partitions;
1843 getPartitionInVector(partitions, it->second);
1844 if(partitions.size() < 2)
continue;
1846 MElement *reference = getReferenceElement(it->second);
1847 if(!reference)
continue;
1850 assignPartitionBoundary(model,
f, reference, partitions, pfaces,
1851 elementToEntity, numFaceEntity);
1853 std::map<GEntity *, MElement *, GEntityPtrFullLessThan>
1854 boundaryEntityAndRefElement;
1855 for(std::size_t i = 0; i < it->second.size(); i++)
1856 boundaryEntityAndRefElement.insert(std::make_pair(
1857 elementToEntity[it->second[i].first], it->second[i].first));
1859 assignBrep(model, boundaryEntityAndRefElement, pf);
1862 faceToElement.clear();
1865 divideNonConnectedEntities(model, 2, regions,
faces,
edges, vertices);
1866 elementToEntity.clear();
1867 fillElementToEntity(model, elementToEntity, 2);
1871 Msg::Info(
" - Creating partition curves");
1875 for(
auto it = boundaryElements[i].begin();
1876 it != boundaryElements[i].end(); ++it) {
1877 for(
int j = 0; j < (*it)->getNumEdges(); j++) {
1878 edgeToElement[(*it)->getEdge(j)].push_back(
1879 std::make_pair(*it, std::vector<int>(1, i + 1)));
1885 Graph subGraph(model);
1886 makeGraph(model, subGraph, 2);
1887 subGraph.createDualGraph(
false);
1888 std::vector<idx_t> part(subGraph.ne());
1891 std::map<idx_t, std::vector<int> > mapOfPartitions;
1892 idx_t mapOfPartitionsTag = 0;
1895 std::vector<int> partitions =
1897 mapOfPartitions.insert(std::make_pair(mapOfPartitionsTag, partitions));
1899 for(
auto itElm = (*it)->triangles.begin();
1900 itElm != (*it)->triangles.end(); ++itElm)
1901 part[partIndex++] = mapOfPartitionsTag;
1902 for(
auto itElm = (*it)->quadrangles.begin();
1903 itElm != (*it)->quadrangles.end(); ++itElm)
1904 part[partIndex++] = mapOfPartitionsTag;
1905 mapOfPartitionsTag++;
1908 subGraph.partition(part);
1910 std::vector<std::set<MElement *, MElementPtrLessThan> >
1911 subBoundaryElements = subGraph.getBoundaryElements(mapOfPartitionsTag);
1913 for(idx_t i = 0; i < mapOfPartitionsTag; i++) {
1914 for(
auto it = subBoundaryElements[i].begin();
1915 it != subBoundaryElements[i].end(); ++it) {
1916 for(
int j = 0; j < (*it)->getNumEdges(); j++) {
1917 edgeToElement[(*it)->getEdge(j)].push_back(
1918 std::make_pair(*it, mapOfPartitions[i]));
1925 for(
auto it = edgeToElement.begin(); it != edgeToElement.end(); ++it) {
1926 MEdge e = it->first;
1928 std::vector<int> partitions;
1929 getPartitionInVector(partitions, it->second);
1930 if(partitions.size() < 2)
continue;
1932 MElement *reference = getReferenceElement(it->second);
1933 if(!reference)
continue;
1936 assignPartitionBoundary(model, e, reference, partitions, pedges,
1937 elementToEntity, numEdgeEntity);
1939 std::map<GEntity *, MElement *, GEntityPtrFullLessThan>
1940 boundaryEntityAndRefElement;
1941 for(std::size_t i = 0; i < it->second.size(); i++) {
1942 boundaryEntityAndRefElement.insert(std::make_pair(
1943 elementToEntity[it->second[i].first], it->second[i].first));
1946 assignBrep(model, boundaryEntityAndRefElement, pe);
1949 edgeToElement.clear();
1952 divideNonConnectedEntities(model, 1, regions,
faces,
edges, vertices);
1953 elementToEntity.clear();
1954 fillElementToEntity(model, elementToEntity, 1);
1958 Msg::Info(
" - Creating partition points");
1961 for(
auto it = boundaryElements[i].begin();
1962 it != boundaryElements[i].end(); ++it) {
1963 for(std::size_t j = 0; j < (*it)->getNumPrimaryVertices(); j++) {
1964 vertexToElement[(*it)->getVertex(j)].push_back(
1965 std::make_pair(*it, std::vector<int>(1, i + 1)));
1971 Graph subGraph(model);
1972 makeGraph(model, subGraph, 1);
1973 subGraph.createDualGraph(
false);
1974 std::vector<idx_t> part(subGraph.ne());
1977 std::map<idx_t, std::vector<int> > mapOfPartitions;
1978 idx_t mapOfPartitionsTag = 0;
1981 std::vector<int> partitions =
1983 mapOfPartitions.insert(std::make_pair(mapOfPartitionsTag, partitions));
1985 for(
auto itElm = (*it)->lines.begin(); itElm != (*it)->lines.end();
1987 part[partIndex++] = mapOfPartitionsTag;
1988 mapOfPartitionsTag++;
1991 subGraph.partition(part);
1993 std::vector<std::set<MElement *, MElementPtrLessThan> >
1994 subBoundaryElements = subGraph.getBoundaryElements(mapOfPartitionsTag);
1996 for(idx_t i = 0; i < mapOfPartitionsTag; i++) {
1997 for(
auto it = subBoundaryElements[i].begin();
1998 it != subBoundaryElements[i].end(); ++it) {
1999 for(std::size_t j = 0; j < (*it)->getNumPrimaryVertices(); j++) {
2000 vertexToElement[(*it)->getVertex(j)].push_back(
2001 std::make_pair(*it, mapOfPartitions[i]));
2007 for(
auto it = vertexToElement.begin(); it != vertexToElement.end(); ++it) {
2010 std::vector<int> partitions;
2011 getPartitionInVector(partitions, it->second);
2012 if(partitions.size() < 2)
continue;
2014 MElement *reference = getReferenceElement(it->second);
2015 if(!reference)
continue;
2018 assignPartitionBoundary(model, v, reference, partitions, pvertices,
2019 elementToEntity, numVertexEntity);
2021 std::map<GEntity *, MElement *, GEntityPtrFullLessThan>
2022 boundaryEntityAndRefElement;
2023 for(std::size_t i = 0; i < it->second.size(); i++)
2024 boundaryEntityAndRefElement.insert(std::make_pair(
2025 elementToEntity[it->second[i].first], it->second[i].first));
2027 assignBrep(model, boundaryEntityAndRefElement, pv);
2030 vertexToElement.clear();
2033 divideNonConnectedEntities(model, 0, regions,
faces,
edges, vertices);
2038 hashmap<std::string, int> &nameToNumber,
2039 std::vector<GModel::piter> &iterators,
int &numPhysical)
2042 if(parent ==
nullptr)
return;
2046 if(parent->
dim() == entity->
dim()) {
2053 std::size_t numPartitions = 0;
2054 if(entity->
dim() == 3) {
2055 numPartitions =
static_cast<partitionRegion *
>(entity)->numPartitions();
2057 else if(entity->
dim() == 2) {
2058 numPartitions =
static_cast<partitionFace *
>(entity)->numPartitions();
2060 else if(entity->
dim() == 1) {
2061 numPartitions =
static_cast<partitionEdge *
>(entity)->numPartitions();
2063 else if(entity->
dim() == 0) {
2064 numPartitions =
static_cast<partitionVertex *
>(entity)->numPartitions();
2068 int dim = entity->
dim();
2069 for(
size_t phys = 0; phys < physical.size(); ++phys) {
2070 std::string name =
"_part{";
2072 for(std::size_t i = 0; i < numPartitions; i++) {
2073 if(i > 0) name +=
",";
2075 if(entity->
dim() == 3) {
2078 else if(entity->
dim() == 2) {
2079 partition =
static_cast<partitionFace *
>(entity)->getPartition(i);
2081 else if(entity->
dim() == 1) {
2082 partition =
static_cast<partitionEdge *
>(entity)->getPartition(i);
2084 else if(entity->
dim() == 0) {
2087 name += std::to_string(partition);
2089 name +=
"}_physical{";
2091 std::to_string(physical[phys]) +
"}_dim{" + std::to_string(dim) +
"}";
2094 auto it = nameToNumber.find(name);
2095 if(it == nameToNumber.end()) {
2096 number = ++numPhysical;
2098 iterators[entity->
dim()], name, entity->
dim(), number);
2099 nameToNumber.insert(std::make_pair(name, number));
2102 number = it->second;
2107 if(physical.size() == 0) {
2108 std::string name =
"_part{";
2110 for(std::size_t i = 0; i < numPartitions; i++) {
2111 if(i > 0) name +=
",";
2113 if(entity->
dim() == 3) {
2116 else if(entity->
dim() == 2) {
2117 partition =
static_cast<partitionFace *
>(entity)->getPartition(i);
2119 else if(entity->
dim() == 1) {
2120 partition =
static_cast<partitionEdge *
>(entity)->getPartition(i);
2122 else if(entity->
dim() == 0) {
2125 name += std::to_string(partition);
2128 name +=
"physical{0}_dim{" + std::to_string(dim) +
"}";
2131 auto it = nameToNumber.find(name);
2132 if(it == nameToNumber.end()) {
2133 number = ++numPhysical;
2135 iterators[entity->
dim()], name, entity->
dim(), number);
2136 nameToNumber.insert(std::make_pair(name, number));
2139 number = it->second;
2146 static void assignPhysicals(
GModel *model)
2148 hashmap<std::string, int> nameToNumber;
2149 std::vector<GModel::piter> iterators;
2155 addPhysical(model, *it, nameToNumber, iterators, numPhysical);
2162 addPhysical(model, *it, nameToNumber, iterators, numPhysical);
2169 addPhysical(model, *it, nameToNumber, iterators, numPhysical);
2176 addPhysical(model, *it, nameToNumber, iterators, numPhysical);
2181 bool cmp_hedges(
const std::pair<MEdge, size_t> &he0,
2182 const std::pair<MEdge, size_t> &he1)
2185 return cmp(he0.first, he1.first);
2190 std::vector<std::pair<MEdge, size_t> > halfEdges;
2191 halfEdges.reserve(gf->
triangles.size() * 3);
2192 for(
size_t i = 0; i < gf->
triangles.size(); ++i) {
2193 for(
size_t j = 0; j < 3; ++j) {
2194 halfEdges.push_back(std::make_pair(gf->
triangles[i]->getEdge(j), i));
2197 std::sort(halfEdges.begin(), halfEdges.end(), cmp_hedges);
2198 std::vector<idx_t> neighbors(gf->
triangles.size() * 3, -1);
2199 std::vector<double> neighborsWeight(gf->
triangles.size() * 3, -1);
2201 double minEdgeLength = std::numeric_limits<double>::max();
2202 for(
size_t i = 0; i + 1 < halfEdges.size(); ++i) {
2203 if(eq(halfEdges[i].first, halfEdges[i + 1].first)) {
2204 size_t t0 = halfEdges[i].second;
2205 size_t t1 = halfEdges[i + 1].second;
2206 double l = halfEdges[i].first.length();
2207 minEdgeLength = std::min(l, minEdgeLength);
2208 for(
int j = 0; j < 3; ++j) {
2209 if(neighbors[t0 * 3 + j] == -1) {
2210 neighbors[t0 * 3 + j] = t1;
2211 neighborsWeight[t0 * 3 + j] = l;
2215 for(
int j = 0; j < 3; ++j) {
2216 if(neighbors[t1 * 3 + j] == -1) {
2217 neighbors[t1 * 3 + j] = t0;
2218 neighborsWeight[t1 * 3 + j] = l;
2225 std::vector<idx_t> adjncy;
2226 std::vector<idx_t> xadjncy;
2227 std::vector<idx_t> adjncyw;
2228 xadjncy.push_back(0);
2229 for(
size_t i = 0; i < gf->
triangles.size(); ++i) {
2230 for(
size_t j = 0; j < 3; ++j) {
2231 if(neighbors[i * 3 + j] == -1)
break;
2232 adjncy.push_back(neighbors[i * 3 + j]);
2234 (idx_t)(neighborsWeight[i * 3 + j] / minEdgeLength * 10));
2236 xadjncy.push_back(adjncy.size());
2238 idx_t nvtxs = gf->
triangles.size(), ncon = 1, nparts = np, objval;
2239 std::vector<idx_t> epart(gf->
triangles.size());
2241 METIS_PartGraphKway(&nvtxs, &ncon, &xadjncy[0], &adjncy[0],
nullptr,
nullptr,
2242 &adjncyw[0], &nparts,
nullptr, &ubvec,
nullptr, &objval,
2244 for(
size_t i = 0; i < gf->
triangles.size(); ++i) {
2245 gf->
triangles[i]->setPartition(epart[i]);
2254 if(numPart <= 0)
return 0;
2260 if(makeGraph(model, graph, -1))
return 1;
2261 graph.nparts(numPart);
2262 if(partitionGraph(graph,
true))
return 1;
2265 for(
int i = 0; i <
TYPE_MAX_NUM + 1; i++) { elmCount[i].resize(numPart, 0); }
2269 for(std::size_t i = 0; i < graph.ne(); i++) {
2270 if(graph.element(i)) {
2271 if(graph.nparts() > 1) {
2272 elmToPartition.insert(std::make_pair(
2273 graph.element(i), graph.partition(i) + 1));
2274 elmCount[graph.element(i)->getType()][graph.partition(i)]++;
2276 graph.element(i)->setPartition(graph.partition(i) + 1);
2279 elmToPartition.insert(std::make_pair(graph.element(i), 1));
2281 graph.element(i)->setPartition(1);
2287 createNewEntities(model, elmToPartition);
2288 elmToPartition.clear();
2291 Msg::StatusBar(
true,
"Done partitioning mesh (Wall %gs, CPU %gs)", w2 -
w1,
2295 std::vector<std::size_t> &count = elmCount[i];
2296 std::size_t minCount = std::numeric_limits<std::size_t>::max();
2297 std::size_t maxCount = 0;
2298 std::size_t totCount = 0;
2299 for(std::size_t j = 0; j < count.size(); j++) {
2300 minCount = std::min(count[j], minCount);
2301 maxCount = std::max(count[j], maxCount);
2302 totCount += count[j];
2305 Msg::Info(
" - Repartition of %d %s: %lu(min) %lu(max) %g(avg)", totCount,
2307 minCount, maxCount, totCount / (
double)numPart);
2313 std::vector<std::set<MElement *, MElementPtrLessThan> > boundaryElements =
2314 graph.getBoundaryElements();
2315 createPartitionTopology(model, boundaryElements, graph);
2316 boundaryElements.clear();
2318 Msg::StatusBar(
true,
"Done creating partition topology (Wall %gs, CPU %gs)",
2322 assignPhysicals(model);
2323 assignMeshVertices(model);
2328 graph.clearDualGraph();
2329 graph.createDualGraph(
true);
2330 graph.assignGhostCells();
2332 Msg::StatusBar(
true,
"Done creating ghost cells (Wall %gs, CPU %gs)",
2339 template <
class ITERATOR,
class PART_ENTITY>
2340 static void assignToParent(std::set<MVertex *> &verts, PART_ENTITY *entity,
2341 ITERATOR it_beg, ITERATOR it_end)
2343 for(ITERATOR it = it_beg; it != it_end; ++it) {
2344 entity->getParentEntity()->addElement((*it)->getType(), *it);
2345 (*it)->setPartition(0);
2347 for(std::size_t i = 0; i < (*it)->getNumVertices(); i++) {
2348 if(verts.find((*it)->getVertex(i)) == verts.end()) {
2349 (*it)->getVertex(i)->setEntity(entity->getParentEntity());
2350 entity->getParentEntity()->addMeshVertex((*it)->getVertex(i));
2351 verts.insert((*it)->getVertex(i));
2362 std::set<GRegion *, GEntityPtrLessThan> regions = model->
getRegions();
2363 std::set<GFace *, GEntityPtrLessThan>
faces = model->
getFaces();
2364 std::set<GEdge *, GEntityPtrLessThan>
edges = model->
getEdges();
2365 std::set<GVertex *, GEntityPtrLessThan> vertices = model->
getVertices();
2367 std::set<MVertex *> verts;
2370 for(
auto it = vertices.begin(); it != vertices.end(); ++it) {
2376 assignToParent(verts, pvertex, pvertex->
points.begin(),
2380 for(std::size_t j = 0; j < pvertex->
points.size(); j++)
2381 delete pvertex->
points[j];
2392 for(
auto it =
edges.begin(); it !=
edges.end(); ++it) {
2397 assignToParent(verts, pedge, pedge->
lines.begin(), pedge->
lines.end());
2400 for(std::size_t j = 0; j < pedge->
lines.size(); j++)
2401 delete pedge->
lines[j];
2403 pedge->
lines.clear();
2418 for(
auto it =
faces.begin(); it !=
faces.end(); ++it) {
2424 assignToParent(verts, pface, pface->
triangles.begin(),
2426 assignToParent(verts, pface, pface->
quadrangles.begin(),
2430 for(std::size_t j = 0; j < pface->
triangles.size(); j++)
2432 for(std::size_t j = 0; j < pface->quadrangles.size(); j++)
2438 pface->
set(std::vector<GEdge *>());
2451 for(
auto it = regions.begin(); it != regions.end(); ++it) {
2457 assignToParent(verts, pregion, pregion->
tetrahedra.begin(),
2459 assignToParent(verts, pregion, pregion->
hexahedra.begin(),
2461 assignToParent(verts, pregion, pregion->
prisms.begin(),
2463 assignToParent(verts, pregion, pregion->
pyramids.begin(),
2465 assignToParent(verts, pregion, pregion->
trihedra.begin(),
2469 for(std::size_t j = 0; j < pregion->
tetrahedra.size(); j++)
2471 for(std::size_t j = 0; j < pregion->hexahedra.size(); j++)
2473 for(std::size_t j = 0; j < pregion->
prisms.size(); j++)
2474 delete pregion->
prisms[j];
2475 for(std::size_t j = 0; j < pregion->pyramids.size(); j++)
2477 for(std::size_t j = 0; j < pregion->
trihedra.size(); j++)
2486 pregion->
set(std::vector<GFace *>());
2500 std::map<std::pair<int, int>, std::string> physicalNames =
2502 for(
auto it = physicalNames.begin(); it != physicalNames.end(); ++it) {
2503 std::size_t found = it->second.find(
"_");
2504 if(found != std::string::npos) {
2515 std::vector<std::pair<MElement *, int> > &elmToPart)
2518 if(makeGraph(model, graph, -1))
return 1;
2522 std::vector<std::pair<MElement*, int> > elmGhosts;
2523 for(
auto item : elmToPart) {
2525 int part = item.second;
2530 if(part > 0) elmToPartition[el] = part;
2531 else elmGhosts.push_back(std::make_pair(el, -part));
2532 numPart = std::max(std::abs(part), numPart);
2535 graph.createDualGraph(
false);
2536 graph.nparts(numPart);
2538 if(elmToPartition.size() != graph.ne()) {
2539 Msg::Error(
"All elements are not partitioned");
2543 std::vector<idx_t> part(graph.ne());
2544 for(std::size_t i = 0; i < graph.ne(); i++) {
2545 if(graph.element(i)) { part[i] = elmToPartition[graph.element(i)] - 1; }
2549 for(
int i = 1; i < 4; i++) {
2550 for(std::size_t j = 0; j < graph.ne(); j++) {
2551 if(graph.element(j)->getDim() == graph.dim())
continue;
2553 for(idx_t k = graph.xadj(j); k < graph.xadj(j + 1); k++) {
2554 if(graph.element(j)->getDim() ==
2555 graph.element(graph.adjncy(k))->getDim() - i) {
2556 if(part[j] != part[graph.adjncy(k)]) {
2557 part[j] = part[graph.adjncy(k)];
2564 graph.partition(part);
2568 createNewEntities(model, elmToPartition);
2572 std::vector<std::set<MElement *, MElementPtrLessThan> > boundaryElements =
2573 graph.getBoundaryElements();
2574 createPartitionTopology(model, boundaryElements, graph);
2575 boundaryElements.clear();
2579 assignPhysicals(model);
2580 assignMeshVertices(model);
2582 if (!elmGhosts.empty()) {
2583 std::sort(elmGhosts.begin(), elmGhosts.end());
2584 auto last = std::unique(elmGhosts.begin(), elmGhosts.end());
2585 elmGhosts.erase(last, elmGhosts.end());
2586 std::vector<GEntity *> ghostEntities = graph.createGhostEntities();
2587 for (
auto elmGhost : elmGhosts) {
2589 int part = elmGhost.second;
2590 if(el->
getDim() == graph.dim()) {
2591 switch(graph.dim()) {
2593 static_cast<ghostEdge *
>(ghostEntities[part - 1])
2594 ->addElement(el->
getType(), el, elmToPartition[el]);
2597 static_cast<ghostFace *
>(ghostEntities[part - 1])
2598 ->addElement(el->
getType(), el, elmToPartition[el]);
2601 static_cast<ghostRegion *
>(ghostEntities[part - 1])
2602 ->addElement(el->
getType(), el, elmToPartition[el]);
2610 graph.clearDualGraph();
2611 graph.createDualGraph(
true);
2612 graph.assignGhostCells();
2614 elmToPartition.clear();
2626 std::vector<std::pair<MElement *, int> > elmToPartition;
2627 std::set<int> partitions;
2628 std::vector<GEntity *> entities;
2630 for(std::size_t i = 0; i < entities.size(); i++) {
2631 for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++) {
2632 MElement *e = entities[i]->getMeshElement(j);
2634 if(part < 0) part = -part;
2636 elmToPartition.push_back(std::make_pair(e, part));
2637 partitions.insert(part);
2648 Msg::Error(
"Gmsh must be compiled with METIS support to partition meshes");
2657 GModel *model, std::vector<std::pair<MElement *, int> > &elmToPartition)
2659 Msg::Error(
"Gmsh must be compiled with METIS support to partition meshes");
2665 Msg::Error(
"Gmsh must be compiled with METIS support to partition meshes");