1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "MEDPARTITIONER_MeshCollection.hxx"
21 #include "MEDPARTITIONER_Topology.hxx"
22 #include "MEDPARTITIONER_Graph.hxx"
23 #include "MEDPARTITIONER_ParallelTopology.hxx"
24 #include "MEDPARTITIONER_ConnectZone.hxx"
25 #include "MEDPARTITIONER_Utils.hxx"
27 #include "MEDCouplingUMesh.hxx"
28 #include "InterpKernelHashMap.hxx"
39 using namespace MEDPARTITIONER;
41 ParallelTopology::ParallelTopology():_nb_domain(0),_mesh_dimension(0)
45 //constructing topology according to mesh collection without global numerotation (use setGlobalNumerotation later)
46 ParallelTopology::ParallelTopology(const std::vector<ParaMEDMEM::MEDCouplingUMesh*>& meshes)
48 _nb_domain=meshes.size();
49 _nb_cells.resize(_nb_domain);
50 _nb_nodes.resize(_nb_domain);
51 // _nb_faces.resize(_nb_domain);
53 if (MyGlobals::_Is0verbose>100)
54 std::cout << "new ParallelTopology\n";
55 _loc_to_glob.resize(0); //precaution, need gatherNbOf() setGlobalNumerotation()
56 _node_loc_to_glob.resize(0); //precaution, need gatherNbOf() setGlobalNumerotation()
57 //_face_loc_to_glob.resize(_nb_domain);
59 bool parallel_mode = false;
60 for (int idomain=0; !parallel_mode && idomain<_nb_domain; idomain++)
61 parallel_mode = (!meshes[idomain]);
63 if (MyGlobals::_Is0verbose>20 && !parallel_mode)
64 std::cout << "WARNING : ParallelTopology contructor without parallel_mode" << std::endl;
65 for (int idomain=0; idomain<_nb_domain; idomain++)
67 if ( !meshes[idomain] ) continue;
68 if (_mesh_dimension==-1)
70 _mesh_dimension = meshes[idomain]->getMeshDimension();
74 if (_mesh_dimension!=meshes[idomain]->getMeshDimension())
75 throw INTERP_KERNEL::Exception("meshes dimensions incompatible");
77 _nb_cells[idomain]=meshes[idomain]->getNumberOfCells();
78 _nb_nodes[idomain]=meshes[idomain]->getNumberOfNodes();
79 //note: in parallel mode _nb_cells and _nb_nodes are not complete now, needs gatherNbOf()
83 //constructing _loc_to_glob etc by default, needs gatherNbOf() done
84 void ParallelTopology::setGlobalNumerotationDefault(ParaDomainSelector* domainSelector)
86 if (MyGlobals::_Is0verbose>100)
87 std::cout<< "setGlobalNumerotationDefault on " << _nb_domain << " domains\n";
88 if (_loc_to_glob.size()!=0) throw INTERP_KERNEL::Exception("a global numerotation is done yet");
89 _loc_to_glob.resize(_nb_domain);
90 _node_loc_to_glob.resize(_nb_domain);
92 //warning because _nb_cells[idomain] is 0 if not my domain(s)
93 //we set loc_to_glob etc.. only for my domain(s)
94 if (MyGlobals::_Is0verbose>500)
95 std::cout << "(c)idomain|ilocalCell|iglobalCell" << std::endl;
96 for (int idomain=0; idomain<_nb_domain; idomain++)
98 _loc_to_glob[idomain].resize(_nb_cells[idomain]);
99 int domainCellShift=domainSelector->getDomainCellShift(idomain);
100 for (int i=0; i<_nb_cells[idomain]; i++)
102 int global=domainCellShift+i ;
103 _glob_to_loc.insert(std::make_pair(global,std::make_pair(idomain,i)));
104 _loc_to_glob[idomain][i]=global;
105 if (MyGlobals::_Verbose>500)
106 std::cout << "c" << idomain << "|" << i << "|" << global << " ";
110 if (MyGlobals::_Verbose>500 && MyGlobals::_World_Size>1) MPI_Barrier(MPI_COMM_WORLD); //synchronize verbose trace
112 if (MyGlobals::_Is0verbose>500) std::cout << std::endl;
114 if (MyGlobals::_Is0verbose>500) std::cout << "(n)idomain|ilocalNode|iglobalNode" << std::endl;
115 for (int idomain=0; idomain<_nb_domain; idomain++)
117 _node_loc_to_glob[idomain].resize(_nb_nodes[idomain]);
118 int domainNodeShift=domainSelector->getDomainNodeShift(idomain);
119 for (int i=0; i<_nb_nodes[idomain]; i++)
121 int global=domainNodeShift+i ;
122 _node_glob_to_loc.insert(std::make_pair(global,std::make_pair(idomain,i)));
123 _node_loc_to_glob[idomain][i]=global;
124 if (MyGlobals::_Verbose>500)
125 std::cout << "n" << idomain << "|" << i << "|" << global << " ";
129 if (MyGlobals::_Verbose>500 && MyGlobals::_World_Size>1) MPI_Barrier(MPI_COMM_WORLD); //synchronize verbose trace
131 if (MyGlobals::_Is0verbose>500) std::cout << std::endl;
133 _nb_total_cells=domainSelector->getNbTotalCells();
134 _nb_total_nodes=domainSelector->getNbTotalNodes();
135 _nb_total_faces=domainSelector->getNbTotalFaces();
136 if (MyGlobals::_Is0verbose>200)
137 std::cout << "globalNumerotation default done meshDimension " << _mesh_dimension << " nbTotalCells " << _nb_total_cells << " nbTotalNodes " << _nb_total_nodes << std::endl;
140 //constructing topology according to mesh collection
141 ParallelTopology::ParallelTopology(const std::vector<ParaMEDMEM::MEDCouplingUMesh*>& meshes,
142 const std::vector<MEDPARTITIONER::ConnectZone*>& cz,
143 std::vector<int*>& cellglobal,
144 std::vector<int*>& nodeglobal,
145 std::vector<int*>& faceglobal)
147 _nb_domain=meshes.size();
149 int index_node_global=0;
150 int index_face_global=0;
152 _nb_cells.resize(_nb_domain);
153 _nb_nodes.resize(_nb_domain);
154 // _nb_faces.resize(_nb_domain);
156 _loc_to_glob.resize(_nb_domain);
157 _node_loc_to_glob.resize(_nb_domain);
158 // _face_loc_to_glob.resize(_nb_domain);
160 bool parallel_mode = false;
161 for (int idomain=0; !parallel_mode && idomain<_nb_domain; idomain++)
162 parallel_mode = (!meshes[idomain]);
164 for (int idomain=0; idomain<_nb_domain; idomain++)
166 if ( !meshes[idomain] ) continue;
167 _mesh_dimension = meshes[idomain]->getMeshDimension();
170 _nb_cells[idomain]=meshes[idomain]->getNumberOfCells();
171 // cout << "Nb cells (domain "<<idomain<<") = "<<_nb_cells[idomain];
172 _loc_to_glob[idomain].resize(_nb_cells[idomain]);
174 if (cellglobal[idomain]==0 || parallel_mode)
176 //int cellDomainShift=_cell_shift_by_domain[idomain];
177 //creating global numbering from scratch
178 for (int i=0; i<_nb_cells[idomain]; i++)
180 int global=i ;//cellDomainShift+i;
181 _glob_to_loc.insert(std::make_pair(global,std::make_pair(idomain,i)));
182 _loc_to_glob[idomain][i]=global;
186 //using global numbering coming from a previous numbering
189 for (int i=0; i<_nb_cells[idomain]; i++)
191 int global=cellglobal[idomain][i];
192 _glob_to_loc.insert(std::make_pair(global,std::make_pair(idomain,i)));
193 //_loc_to_glob[make_pair(idomain,i+1)]=global;
194 _loc_to_glob[idomain][i]=global;
202 _nb_total_cells=index_global;
203 _nb_cells[0]=index_global;
204 _node_loc_to_glob[idomain].resize(meshes[idomain]->getNumberOfNodes());
205 for (int i=0; i<meshes[idomain]->getNumberOfNodes(); i++)
207 _node_glob_to_loc.insert(std::make_pair(i,std::make_pair(0,i)));
208 _node_loc_to_glob[0][i]=i;
210 _nb_total_nodes=meshes[idomain]->getNumberOfNodes();
211 _nb_nodes[0]=_nb_total_nodes;
216 _nb_nodes[idomain]=meshes[idomain]->getNumberOfNodes();
217 INTERP_KERNEL::HashMap <int,std::pair<int,int> > local2distant;
218 _node_loc_to_glob[idomain].resize(_nb_nodes[idomain]);
219 for (std::size_t icz=0; icz<cz.size(); icz++)
221 if (cz[icz]->getLocalDomainNumber() == idomain &&
222 cz[icz]->getLocalDomainNumber()>cz[icz]->getDistantDomainNumber())
224 int nb_node= cz[icz]->getNodeNumber();
225 const int* node_corresp=cz[icz]->getNodeCorrespValue();
226 int distant_ip = cz[icz]->getDistantDomainNumber();
227 for (int i=0; i< nb_node; i++)
229 int local= node_corresp[i*2];
230 int distant = node_corresp[i*2+1];
231 local2distant.insert(std::make_pair(local, std::make_pair(distant_ip,distant)));
235 // setting mappings for all nodes
236 if (nodeglobal[idomain]==0)
238 for (int inode=0; inode<_nb_nodes[idomain]; inode++)
240 if (local2distant.find(inode)==local2distant.end())
243 _node_glob_to_loc.insert(std::make_pair(index_node_global,std::make_pair(idomain,inode)));
244 //_node_loc_to_glob[make_pair(idomain,inode+1)]=index_node_global;
245 _node_loc_to_glob[idomain][inode]=index_node_global;
249 int ip = (local2distant.find(inode)->second).first;
250 int distant = (local2distant.find(inode)->second).second;
251 int global_number=_loc_to_glob[ip][distant];
252 _node_glob_to_loc.insert(std::make_pair(global_number,std::make_pair(idomain,inode)));
253 _node_loc_to_glob[idomain][inode]=global_number;
257 //using former node numbering
260 for (int inode=0; inode<_nb_nodes[idomain]; inode++)
262 int global_number=nodeglobal[idomain][inode];
263 _node_glob_to_loc.insert(std::make_pair(global_number,std::make_pair(idomain,inode)));
264 _node_loc_to_glob[idomain][inode]=global_number;
269 _nb_total_cells=index_global;
270 _nb_total_nodes=index_node_global;
271 _nb_total_faces=index_face_global;
275 //constructing ParallelTopology from an old topology and a graph
276 ParallelTopology::ParallelTopology(Graph* graph, Topology* oldTopology, int nb_domain, int mesh_dimension)
279 _nb_domain=nb_domain;
280 _mesh_dimension=mesh_dimension;
282 if (MyGlobals::_Verbose>200)
283 std::cout << "proc " << MyGlobals::_Rank << " : new topology oldNbDomain " <<
284 oldTopology->nbDomain() << " newNbDomain " << _nb_domain << std::endl;
285 _nb_cells.resize(_nb_domain,0);
286 _nb_nodes.resize(_nb_domain,0);
287 _nb_faces.resize(_nb_domain,0);
289 _loc_to_glob.resize(_nb_domain);
290 _node_loc_to_glob.resize(_nb_domain);
291 _face_loc_to_glob.resize(_nb_domain);
293 const int* part=graph->getPart(); //all cells for this proc (may be more domains)
294 _nb_total_cells=graph->nbVertices(); //all cells for this proc (may be more domains)
295 if (MyGlobals::_Verbose>300)
296 std::cout << "proc " << MyGlobals::_Rank << " : topology from partition, nbTotalCells " << _nb_total_cells << std::endl;
298 int icellProc=0; //all cells of my domains are concatenated in part
299 for (int iold=0; iold<oldTopology->nbDomain(); iold++)
301 int ioldNbCell=oldTopology->getCellNumber(iold);
302 //std::cout<<"proc "<<MyGlobals::_Rank<<" : cell number old domain "<<iold<<" : "<<ioldNbCell<<std::endl;
303 //if not my old domains getCellNumber is 0
304 std::vector<int> globalids(ioldNbCell);
305 oldTopology->getCellList(iold, &globalids[0]); //unique global numerotation
306 for (int icell=0; icell<ioldNbCell; icell++)
308 int idomain=part[icellProc];
309 _nb_cells[idomain]++;
311 int iGlobalCell=globalids[icell];
312 _loc_to_glob[idomain].push_back(iGlobalCell);
313 _glob_to_loc.insert(std::make_pair(iGlobalCell, std::make_pair(idomain, _nb_cells[idomain])));
317 if (MyGlobals::_Verbose>300)
318 for (int idomain=0; idomain<_nb_domain; idomain++)
319 std::cout << "proc " << MyGlobals::_Rank << " : nbCells in new domain " << idomain << " : " << _nb_cells[idomain] << std::endl;
322 ParallelTopology::~ParallelTopology()
326 /*!Converts a list of global node numbers
327 * to a distributed array with local cell numbers.
329 * If a node in the list is represented on several domains,
330 * only the first value is returned
332 void ParallelTopology::convertGlobalNodeList(const int* node_list, int nbnode, int* local, int* ip)
334 if (_node_glob_to_loc.empty())
335 throw INTERP_KERNEL::Exception("Node mapping has not yet been built");
336 for (int i=0; i< nbnode; i++)
338 std::pair<int,int> local_node = _node_glob_to_loc.find(node_list[i])->second;
339 ip[i]=local_node.first;
340 local[i]=local_node.second;
344 /*!Converts a list of global node numbers on domain ip
345 * to a distributed array with local cell numbers.
347 * If a node in the list is represented on several domains,
348 * only the value with domain ip is returned
351 void ParallelTopology::convertGlobalNodeList(const int* node_list, int nbnode, int* local, int ip)
353 if (_node_glob_to_loc.empty())
354 throw INTERP_KERNEL::Exception("Node mapping has not yet been built");
356 for (int i=0; i< nbnode; i++)
358 typedef INTERP_KERNEL::HashMultiMap<int,std::pair<int,int> >::iterator mmiter;
359 std::pair<mmiter,mmiter> range=_node_glob_to_loc.equal_range(node_list[i]);
360 for (mmiter it=range.first; it !=range.second; it++)
362 int ipfound=(it->second).first;
364 local[i]=(it->second).second;
369 /*!Converts a list of global node numbers
370 * to a distributed array with local cell numbers.
372 * If a node in the list is represented on several domains,
373 * all the values are put in the array
375 void ParallelTopology::convertGlobalNodeListWithTwins(const int* node_list, int nbnode, int*& local, int*& ip,int*& full_array, int& size)
377 if (_node_glob_to_loc.empty())
378 throw INTERP_KERNEL::Exception("Node mapping has not yet been built");
381 for (int i=0; i< nbnode; i++)
383 int count= _node_glob_to_loc.count(node_list[i]);
389 full_array=new int[size];
390 for (int i=0; i< nbnode; i++)
392 typedef INTERP_KERNEL::HashMultiMap<int,std::pair<int,int> >::iterator mmiter;
393 std::pair<mmiter,mmiter> range=_node_glob_to_loc.equal_range(node_list[i]);
394 for (mmiter it=range.first; it !=range.second; it++)
396 ip[index]=(it->second).first;
397 local[index]=(it->second).second;
398 full_array [index]=node_list[i];
405 /*!Converts a list of global face numbers
406 * to a distributed array with local face numbers.
408 * If a face in the list is represented on several domains,
409 * all the values are put in the array
411 void ParallelTopology::convertGlobalFaceListWithTwins(const int* face_list, int nbface, int*& local, int*& ip, int*& full_array,int& size)
414 for (int i=0; i< nbface; i++)
416 //int count = _face_glob_to_loc.count(face_list[i]);
417 //if (count >1) MESSAGE_MED("face en doublon "<<face_list[i]);
418 size+= _face_glob_to_loc.count(face_list[i]);
423 full_array=new int[size];
424 for (int i=0; i< nbface; i++)
426 typedef INTERP_KERNEL::HashMultiMap<int,std::pair<int,int> >::iterator mmiter;
427 std::pair<mmiter,mmiter> range=_face_glob_to_loc.equal_range(face_list[i]);
428 for (mmiter it=range.first; it !=range.second; it++)
430 ip[index]=(it->second).first;
431 local[index]=(it->second).second;
432 full_array[index]=face_list[i];
439 //!converts a list of global cell numbers
440 //!to a distributed array with local cell numbers
441 void ParallelTopology::convertGlobalCellList(const int* cell_list, int nbcell, int* local, int* ip)
443 for (int i=0; i<nbcell; i++)
445 INTERP_KERNEL::HashMap<int, std::pair<int,int> >::const_iterator iter = _glob_to_loc.find(cell_list[i]);
446 if (iter == _glob_to_loc.end())
448 std::cerr << "proc " << MyGlobals::_Rank << " : KO cell_list[" << i << "] : " << cell_list[i] << std::endl;
449 throw INTERP_KERNEL::Exception("ParallelTopology::convertGlobalCellList : Cell not found");
453 ip[i]=(iter->second).first; //no domain
454 local[i]=(iter->second).second; //no local cell
459 /*!Converts a list of global face numbers
460 * to a distributed array with local face numbers
462 void ParallelTopology::convertGlobalFaceList(const int* face_list, int nbface, int* local, int* ip)
464 for (int i=0; i< nbface; i++)
466 INTERP_KERNEL::HashMap<int, std::pair<int,int> >::const_iterator iter = _face_glob_to_loc.find(face_list[i]);
467 if (iter == _face_glob_to_loc.end())
469 throw INTERP_KERNEL::Exception("ParallelTopology::convertGlobalFaceList : Face not found");
471 ip[i]=(iter->second).first;
472 local[i]=(iter->second).second;
476 /*!Converts a list of global node numbers on domain ip
477 * to a distributed array with local cell numbers.
479 * If a node in the list is represented on several domains,
480 * only the value with domain ip is returned
483 void ParallelTopology::convertGlobalFaceList(const int* face_list, int nbface, int* local, int ip)
485 for (int i=0; i< nbface; i++)
487 typedef INTERP_KERNEL::HashMultiMap<int,std::pair<int,int> >::iterator mmiter;
488 std::pair<mmiter,mmiter> range=_face_glob_to_loc.equal_range(face_list[i]);
489 for (mmiter it=range.first; it !=range.second; it++)
491 int ipfound=(it->second).first;
493 local[i]=(it->second).second;
499 //replacing a table of global numbering with a table with local numberings
500 // type_connectivity contains global connectivity for each type in input
501 // type_connectivity contains local connectivity for each type in output
502 void ParallelTopology::convertToLocal2ndVersion(int* nodes, int nbnodes, int idomain)
504 for (int inode=0; inode<nbnodes; inode++)
506 // cout <<" inode :"<<inode<< " global = "<<type_connectivity[type][inode];
507 int global = nodes[inode];
508 typedef INTERP_KERNEL::HashMultiMap<int,std::pair<int,int> >::iterator mmiter;
509 std::pair<mmiter,mmiter> range=_node_glob_to_loc.equal_range(global);
510 for (mmiter it=range.first; it !=range.second; it++)
512 if ((it->second).first==idomain)
513 nodes[inode]=(it->second).second;
519 * \brief Return max global face number
521 int ParallelTopology::getMaxGlobalFace() const
524 TGlob2LocsMap::const_iterator g_l_l = _face_glob_to_loc.begin();
525 for ( ; g_l_l != _face_glob_to_loc.end(); ++g_l_l )
526 if ( g_l_l->first > max )
531 int ParallelTopology::getNodeNumber() const
533 if (_node_glob_to_loc.empty()) return 0;
535 for (INTERP_KERNEL::HashMultiMap<int, std::pair<int,int> >::const_iterator iter= _node_glob_to_loc.begin(); iter!=_node_glob_to_loc.end(); iter++)
537 keys.insert(iter->first);
543 * retrieving list of nodes in global numbers
545 void ParallelTopology::getNodeList(int idomain, int *list) const
547 for (int i=0; i<_nb_nodes[idomain]; i++)
548 list[i]=_node_loc_to_glob[idomain][i];
552 * retrieving list of nodes in global numbers
554 void ParallelTopology::getCellList(int idomain, int *list) const
556 for (int i=0; i<_nb_cells[idomain];i++)
557 list[i]=_loc_to_glob[idomain][i];
560 int ParallelTopology::getFaceNumber() const
562 if (_face_glob_to_loc.empty())
565 for (INTERP_KERNEL::HashMultiMap<int, std::pair<int,int> >::const_iterator iter= _face_glob_to_loc.begin(); iter!=_face_glob_to_loc.end(); iter++)
567 keys.insert(iter->first);
573 * retrieving list of faces in global numbers
575 void ParallelTopology::getFaceList(int idomain, int *list) const
577 for (int i=0; i<_nb_faces[idomain];i++)
578 list[i]=_face_loc_to_glob[idomain][i];
581 int ParallelTopology::convertGlobalFace(int iglobal, int idomain)
583 typedef INTERP_KERNEL::HashMultiMap<int, std::pair<int,int> >::const_iterator MMiter;
584 std::pair<MMiter,MMiter> eq = _face_glob_to_loc.equal_range(iglobal);
585 for (MMiter it=eq.first; it != eq.second; it++)
586 if (it->second.first == idomain)
587 return it->second.second;
591 int ParallelTopology::convertGlobalNode(int iglobal, int idomain)
593 typedef INTERP_KERNEL::HashMultiMap<int, std::pair<int,int> >::const_iterator MMiter;
594 std::pair<MMiter,MMiter> eq = _node_glob_to_loc.equal_range(iglobal);
595 for (MMiter it=eq.first; it != eq.second; it++)
597 if (it->second.first == idomain)
598 return it->second.second;
604 * adding a face to the topology
606 void ParallelTopology::appendFace(int idomain, int ilocal, int iglobal)
608 _face_loc_to_glob[idomain].push_back(iglobal);
609 _face_glob_to_loc.insert(std::make_pair(iglobal,std::make_pair(idomain,ilocal)));