Salome HOME
Reduced version of INTERPKernel tests can be run in MICROMED mode.
[tools/medcoupling.git] / src / MEDPartitioner / Test / MEDPARTITIONERTest.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D
2 //
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, or (at your option) any later version.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "MEDPARTITIONERTest.hxx"
21
22 #include "MEDPARTITIONER_MeshCollection.hxx"
23 #include "MEDPARTITIONER_ParallelTopology.hxx"
24 #include "MEDPARTITIONER_ParaDomainSelector.hxx"
25 #include "MEDPARTITIONER_Utils.hxx"
26
27 #include "CellModel.hxx"
28 #include "MEDFileMesh.hxx"
29 #include "MEDLoader.hxx"
30 #include "MEDLoaderBase.hxx"
31 #include "MEDCouplingUMesh.hxx"
32 #include "MEDCouplingExtrudedMesh.hxx"
33 #include "MEDCouplingFieldDouble.hxx"
34 #include "MEDCouplingMemArray.hxx"
35 #include "MEDCouplingMultiFields.hxx"
36
37 #include <cppunit/TestAssert.h>
38
39 #include <sstream>
40 #include <fstream>
41 #include <cmath>
42 #include <list>
43 #include <stdexcept>
44 #include <cstdlib>
45 #include <vector>
46 #include <unistd.h>
47
48 #ifdef HAVE_MPI
49 #include <mpi.h>
50 #endif
51
52 using namespace std;
53 using namespace ParaMEDMEM;
54 using namespace MEDPARTITIONER;
55
56 void MEDPARTITIONERTest::setSize(int ni, int nj, int nk)
57 {
58   this->_ni=ni;  //nb of hexa9
59   this->_nj=nj;
60   this->_nk=nk;
61   this->_ntot=_ni*_nj*_nk;
62   string ijk=IntToStr(ni)+"x"+IntToStr(nj)+"x"+IntToStr(nk);
63   this->_file_name="tmp_testMesh_"+ijk+".med";
64   this->_file_name_with_faces="tmp_testMeshWithFaces_"+ijk+".med";
65   string ij=IntToStr(ni)+"x"+IntToStr(nj);
66   this->_file_name2="tmp_testMesh_"+ij+".med";
67   this->_mesh_name="testMesh";
68 }
69
70 void MEDPARTITIONERTest::setSmallSize()
71 {
72   setSize(2,3,5); //nb of hexa9
73 }
74
75 void MEDPARTITIONERTest::setMedianSize()
76 {
77   setSize(20,30,50); //nb of hexa9
78 }
79
80 void MEDPARTITIONERTest::setbigSize()
81 {
82   setSize(200,300,500); //nb of hexa9
83 }
84
85 std::string MEDPARTITIONERTest::getPartitionerExe() const
86 {
87   std::string execName;
88   if ( getenv("MEDCOUPLING_ROOT_DIR") )
89     {
90       execName=getenv("MEDCOUPLING_ROOT_DIR");  //.../INSTALL/MED
91       execName+="/bin/medpartitioner";
92       std::ifstream my_file(execName);
93       if (my_file.good())
94         return execName;
95     }
96   execName = get_current_dir_name();
97   execName += "/../../MEDPartitioner/medpartitioner";
98   if (! std::ifstream(execName.c_str()))
99     CPPUNIT_FAIL("Can't find medpartitioner, please set MEDCOUPLING_ROOT_DIR");
100
101   return execName;
102 }
103
104 // ============================================================================
105 /*!
106  *  Set up the environment called at every CPPUNIT_TEST ()
107  */
108 // ============================================================================
109 void MEDPARTITIONERTest::setUp()
110 {
111   this->_verbose=0;
112 #if defined(HAVE_MPI)
113   if (MyGlobals::_Rank==-1)  //do once only
114     {
115       MPI_Init(0,0);
116       MPI_Comm_size(MPI_COMM_WORLD, &MyGlobals::_World_Size);
117       MPI_Comm_rank(MPI_COMM_WORLD, &MyGlobals::_Rank);
118     }
119 #else
120   //sequential : no MPI
121   MyGlobals::_World_Size=1;
122   MyGlobals::_Rank=0;
123 #endif
124
125   if (_verbose>10)
126     {
127 #if defined(HAVE_MPI)
128       cout<<"\ndefined(HAVE_MPI)"<<endl;
129 #else
130       cout<<"\nNOT defined(HAVE_MPI)"<<endl;
131 #endif
132 #if defined(MED_ENABLE_PARMETIS)
133       cout<<"defined(MED_ENABLE_PARMETIS)"<<endl;
134 #else
135       cout<<"NOT defined(MED_ENABLE_PARMETIS)"<<endl;
136 #endif
137 #if defined(MED_ENABLE_METIS)
138       cout<<"defined(MED_ENABLE_METIS)"<<endl;
139 #else
140       cout<<"NOT defined(MED_ENABLE_METIS)"<<endl;
141 #endif
142 #if defined(MED_ENABLE_SCOTCH)
143       cout<<"defined(MED_ENABLE_SCOTCH)"<<endl;
144 #else
145       cout<<"NOT defined(MED_ENABLE_SCOTCH)"<<endl;
146 #endif
147     }
148 }
149
150 // ============================================================================
151 /*!
152  *  - delete
153  */
154 // ============================================================================
155 void MEDPARTITIONERTest::tearDown()
156 {
157 }
158
159 ParaMEDMEM::MEDCouplingUMesh * MEDPARTITIONERTest::buildCUBE3DMesh()
160 //only hexa8
161 {
162   vector<int> conn;
163   vector<double> coor;
164   for (int k=0; k<=_nk; k++)
165     for (int j=0; j<=_nj; j++)
166       for (int i=0; i<=_ni; i++)
167         {
168           coor.push_back(i+.1);
169           coor.push_back(j+.2);
170           coor.push_back(k+.3);
171         }
172   int ii;
173   for (int k=0; k<_nk; k++)
174     for (int j=0; j<_nj; j++)
175       for (int i=0; i<_ni; i++)
176         {
177           ii=i + j*(_ni+1) + k*(_ni+1)*(_nj+1);
178           conn.push_back(ii);
179           conn.push_back(ii+1);
180           ii=ii + _ni + 2 ;
181           conn.push_back(ii);
182           conn.push_back(ii-1);
183
184           ii=i + j*(_ni+1) + (k+1)*(_ni+1)*(_nj+1);
185           conn.push_back(ii);
186           conn.push_back(ii+1);
187           ii=ii + _ni + 2 ;
188           conn.push_back(ii);
189           conn.push_back(ii-1);
190         }
191
192   /*
193   if (_verbose)  //only for debug
194     {
195       cout<< "\nnb coor " << (_ni+1)*(_nj+1)*(_nk+1)*3 << " " << coor.size() << endl;
196       for (int i=0; i<(int)coor.size(); i++)
197         cout << coor[i] << " ";
198       cout << endl;
199       cout << "\nnb conn " << (_ni)*(_nj)*(_nk)*8 << " " << conn.size() << endl;
200       for (int i=0; i<(int)conn.size(); i=i+8)
201         {
202           for (int j=0; j<8; j++)
203             cout << conn[i+j] << " ";
204           cout << endl;
205         }
206       cout << endl;
207     }
208   */
209
210   MEDCouplingUMesh *mesh=MEDCouplingUMesh::New();
211   mesh->setMeshDimension(3);
212   int nbc=conn.size()/8; //nb of cells
213   int nbv=coor.size()/3; //nb of vertices
214   mesh->allocateCells(nbc);
215   for(int i=0; i<nbc; i++)
216     {
217       int onehexa[8];
218       std::copy(conn.begin()+i*8,conn.begin()+(i+1)*8,onehexa);
219       if (false) //(_verbose)
220         {
221           for (int j=0; j<8; j++) cout<<onehexa[j]<<" ";
222           cout<<endl;
223         }
224       mesh->insertNextCell(INTERP_KERNEL::NORM_HEXA8,8,onehexa);
225     }
226   mesh->finishInsertingCells();
227   DataArrayDouble *myCoords=DataArrayDouble::New();
228   myCoords->alloc(nbv,3);
229   std::copy(coor.begin(),coor.end(),myCoords->getPointer());
230   mesh->setCoords(myCoords);
231   mesh->setName(_mesh_name.c_str());
232   myCoords->decrRef();
233   mesh->checkCoherency();
234   return mesh;
235 }
236
237 ParaMEDMEM::MEDCouplingUMesh * MEDPARTITIONERTest::buildCARRE3DMesh()
238 //only quad4 in oblique (k=j)
239 {
240   vector<int> conn;
241   vector<double> coor;
242   for (int j=0; j<=_nj; j++)
243     for (int i=0; i<=_ni; i++)
244       {
245         int k=j;
246         coor.push_back(i+.1);
247         coor.push_back(j+.2);
248         coor.push_back(k+.3);
249       }
250   int ii;
251   int k=0;
252   for (int j=0; j<_nj; j++)
253     for (int i=0; i<_ni; i++)
254       {
255         ii=i + j*(_ni+1) + k*(_ni+1)*(_nj+1);
256         conn.push_back(ii);
257         conn.push_back(ii+1);
258         ii=ii + _ni + 2 ;
259         conn.push_back(ii);
260         conn.push_back(ii-1);
261       }
262
263   if (false) //(_verbose)
264     {
265       cout<<"\nnb coor "<<(_ni+1)*(_nj+1)*3<<" "<<coor.size()<<endl;
266       for (int i=0; i<(int)coor.size(); i++)
267         cout << coor[i] << " ";
268       cout<<endl;
269       cout<<"\nnb conn "<<(_ni)*(_nj)*4<<" "<<conn.size()<<endl;
270       for (int i=0; i<(int)conn.size(); i=i+4)
271         {
272           for (int j=0; j<4; j++) cout<<conn[i+j]<<" ";
273           cout<<endl;
274         }
275       cout<<endl;
276     }
277
278   MEDCouplingUMesh *mesh=MEDCouplingUMesh::New();
279   mesh->setMeshDimension(2);
280   int nbc=conn.size()/4; //nb of cells
281   int nbv=coor.size()/3; //nb of vertices
282   mesh->allocateCells(nbc);
283   for(int i=0; i<nbc; i++)
284     {
285       int onequa[4];
286       std::copy(conn.begin()+i*4,conn.begin()+(i+1)*4,onequa);
287       if (false) //(_verbose)
288         {
289           for (int j=0; j<4; j++) cout<<onequa[j]<<" ";
290           cout<<endl;
291         }
292       mesh->insertNextCell(INTERP_KERNEL::NORM_QUAD4,4,onequa);
293     }
294   mesh->finishInsertingCells();
295   DataArrayDouble *myCoords=DataArrayDouble::New();
296   myCoords->alloc(nbv,3);
297   std::copy(coor.begin(),coor.end(),myCoords->getPointer());
298   mesh->setCoords(myCoords);
299   mesh->setName(_mesh_name.c_str());
300   myCoords->decrRef();
301   mesh->checkCoherency();
302   return mesh;
303 }
304
305 ParaMEDMEM::MEDCouplingUMesh * MEDPARTITIONERTest::buildFACE3DMesh()
306 //only quad4 on a global face of the CUBE3D (k=0)
307 {
308   vector<int> conn;
309   vector<double> coor;
310   for (int j=0; j<=_nj; j++)
311     for (int i=0; i<=_ni; i++)
312       {
313         int k=0;
314         coor.push_back(i+.1);
315         coor.push_back(j+.2);
316         coor.push_back(k+.3);
317       }
318   int ii;
319   int k=0;
320   for (int j=0; j<_nj; j++)
321     for (int i=0; i<_ni; i++)
322       {
323         ii=i + j*(_ni+1) + k*(_ni+1)*(_nj+1);
324         conn.push_back(ii);
325         conn.push_back(ii+1);
326         ii=ii + _ni + 2 ;
327         conn.push_back(ii);
328         conn.push_back(ii-1);
329       }
330
331   if (false) //(_verbose)
332     {
333       cout<<"\nnb coor "<<(_ni+1)*(_nj+1)*3<<" "<<coor.size()<<endl;
334       for (int i=0; i<(int)coor.size(); i++)
335         cout << coor[i] << " ";
336       cout<<endl;
337       cout<<"\nnb conn "<<(_ni)*(_nj)*4<<" "<<conn.size()<<endl;
338       for (int i=0; i<(int)conn.size(); i=i+4)
339         {
340           for (int j=0; j<4; j++)
341             cout << conn[i+j] << " ";
342           cout << endl;
343         }
344       cout << endl;
345     }
346
347   MEDCouplingUMesh *mesh=MEDCouplingUMesh::New();
348   mesh->setMeshDimension(2);
349   int nbc=conn.size()/4; //nb of cells
350   int nbv=coor.size()/3; //nb of vertices
351   mesh->allocateCells(nbc);
352   for(int i=0; i<nbc; i++)
353     {
354       int onequa[4];
355       std::copy(conn.begin()+i*4,conn.begin()+(i+1)*4,onequa);
356       if (false) //(_verbose)
357         {
358           for (int j=0; j<4; j++) cout<<onequa[j]<<" ";
359           cout<<endl;
360         }
361       mesh->insertNextCell(INTERP_KERNEL::NORM_QUAD4,4,onequa);
362     }
363   mesh->finishInsertingCells();
364   DataArrayDouble *myCoords=DataArrayDouble::New();
365   myCoords->alloc(nbv,3);
366   std::copy(coor.begin(),coor.end(),myCoords->getPointer());
367   mesh->setCoords(myCoords);
368   mesh->setName(_mesh_name.c_str());
369   myCoords->decrRef();
370   mesh->checkCoherency();
371   return mesh;
372 }
373
374 MEDCouplingFieldDouble * MEDPARTITIONERTest::buildVecFieldOnCells(string myfileName)
375 {
376   //int ni=2,nj=3,nk=5; //nb of hexa9
377   vector<double> field;
378   for (int k=0; k<_nk; k++)
379     for (int j=0; j<_nj; j++)
380       for (int i=0; i<_ni; i++)
381         {
382           field.push_back(i+.1);
383           field.push_back(j+.2);
384           field.push_back(k+.3);
385         }
386
387   MEDCouplingUMesh *mesh=MEDLoader::ReadUMeshFromFile(myfileName.c_str(),_mesh_name.c_str(),0);
388   int nbOfCells=mesh->getNumberOfCells();
389   MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
390   f1->setName("VectorFieldOnCells");
391   f1->setDescription("DescriptionOfFieldOnCells"); //not saved in file?
392   f1->setMesh(mesh);
393   DataArrayDouble *myField=DataArrayDouble::New();
394   myField->alloc(nbOfCells,3);
395   std::copy(field.begin(),field.end(),myField->getPointer());
396   f1->setArray(myField);
397   myField->setInfoOnComponent(0,"vx");
398   myField->setInfoOnComponent(1,"vy");
399   myField->setInfoOnComponent(2,"vz");
400   myField->decrRef();
401   f1->setTime(2.,0,1);
402   f1->checkCoherency();
403   mesh->decrRef();
404   return f1;
405 }
406
407 MEDCouplingFieldDouble * MEDPARTITIONERTest::buildVecFieldOnNodes()
408 {
409   //int ni=2,nj=3,nk=5; //nb of hexa9
410   vector<double> field;
411   for (int k=0; k<=_nk; k++)
412     for (int j=0; j<=_nj; j++)
413       for (int i=0; i<=_ni; i++)
414         {
415           field.push_back(i+.1);
416           field.push_back(j+.2);
417           field.push_back(k+.3);
418         }
419
420   MEDCouplingUMesh *mesh=MEDLoader::ReadUMeshFromFile(_file_name.c_str(),_mesh_name.c_str(),0);
421   int nbOfNodes=mesh->getNumberOfNodes();
422   MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_NODES,ONE_TIME);
423   f1->setName("VectorFieldOnNodes");
424   f1->setDescription("DescriptionOfFieldOnNodes"); //not saved in file?
425   f1->setMesh(mesh);
426   DataArrayDouble *myField=DataArrayDouble::New();
427   myField->alloc(nbOfNodes,3);
428   std::copy(field.begin(),field.end(),myField->getPointer());
429   f1->setArray(myField);
430   myField->setInfoOnComponent(0,"vx");
431   myField->setInfoOnComponent(1,"vy");
432   myField->setInfoOnComponent(2,"vz");
433   myField->decrRef();
434   f1->setTime(2.,0,1);
435   f1->checkCoherency();
436   mesh->decrRef();
437   return f1;
438 }
439
440
441 void MEDPARTITIONERTest::createTestMeshWithoutField()
442 {
443   {
444     MEDCouplingUMesh * mesh = buildCUBE3DMesh();
445     MEDLoader::WriteUMesh(_file_name.c_str(),mesh,true);
446     if (_verbose) cout<<endl<<_file_name<<" created"<<endl;
447     if (_ntot<1000000) //too long
448       {
449         MEDCouplingUMesh *mesh_rw=MEDLoader::ReadUMeshFromFile(_file_name.c_str(),mesh->getName().c_str(),0);
450         if (_verbose) cout<<_file_name<<" reread"<<endl;
451         CPPUNIT_ASSERT(mesh->isEqual(mesh_rw,1e-12));
452         mesh_rw->decrRef();
453       }
454     mesh->decrRef();
455   }
456
457   {
458     vector<const ParaMEDMEM::MEDCouplingUMesh*> meshes;
459     MEDCouplingUMesh * mesh1 = buildCUBE3DMesh();
460     MEDCouplingUMesh * mesh2 = buildFACE3DMesh();
461     mesh1->setName("testMesh");
462     mesh2->setName("theFaces");
463     mesh2->tryToShareSameCoordsPermute(*mesh1, 1e-9);
464     mesh2->checkCoherency();
465     mesh1->checkCoherency();
466     meshes.push_back(mesh1);
467     meshes.push_back(mesh2);
468     MEDLoader::WriteUMeshes(_file_name_with_faces.c_str(), meshes, true);
469
470     ParaMEDMEM::MEDFileUMesh* mfm=ParaMEDMEM::MEDFileUMesh::New(_file_name_with_faces.c_str(), mesh1->getName().c_str());
471     DataArrayInt* FacesFam=DataArrayInt::New();
472     FacesFam->alloc(mfm->getSizeAtLevel(-1),1);
473     FacesFam->fillWithValue(-1);
474     DataArrayInt* CellsFam=DataArrayInt::New();
475     CellsFam->alloc(mfm->getSizeAtLevel(0),1);
476     CellsFam->fillWithValue(1);
477     mfm->setFamilyFieldArr(-1,FacesFam);
478     mfm->setFamilyFieldArr(0,CellsFam);
479     map<string,int> theFamilies;
480     theFamilies["FAMILLE_ZERO"]=0;
481     theFamilies["FamilyFaces"]=-1;
482     theFamilies["FamilyCells"]=1;
483     map<string, vector<string> > theGroups;
484     theGroups["GroupFaces"].push_back("FamilyFaces");
485     theGroups["GroupCells"].push_back("FamilyCells");
486     mfm->setFamilyInfo(theFamilies);
487     mfm->setGroupInfo(theGroups);
488     mfm->write(_file_name_with_faces.c_str(),0);
489     FacesFam->decrRef();
490     CellsFam->decrRef();
491
492     /*ce truc marche pas!
493       ParaMEDMEM::MEDFileUMesh* mfm=ParaMEDMEM::MEDFileUMesh::New(_file_name_with_faces.c_str(), mesh1->getName());
494       vector<const ParaMEDMEM::MEDCouplingUMesh*> ms;
495       ms.push_back(mesh2);
496       mfm->setGroupsFromScratch(-1, ms);
497       mfm->write(_file_name_with_faces.c_str(),0);
498     */
499
500     if (_verbose) cout<<endl<<_file_name_with_faces<<" created"<<endl;
501     if (_ntot<1000000) //too long
502       {
503         MEDCouplingUMesh *mesh_rw=MEDLoader::ReadUMeshFromFile(_file_name_with_faces.c_str(),mesh1->getName().c_str(),0);
504         if (_verbose) cout<<_file_name_with_faces<<" reread"<<endl;
505         CPPUNIT_ASSERT(mesh1->isEqual(mesh_rw,1e-12));
506         mesh_rw->decrRef();
507       }
508     mesh1->decrRef();
509     mesh2->decrRef();
510     mfm->decrRef();
511   }
512
513   {
514     MEDCouplingUMesh * mesh = buildCARRE3DMesh();
515     MEDLoader::WriteUMesh(_file_name2.c_str(),mesh,true);
516     if (_verbose) cout<<endl<<_file_name2<<" created"<<endl;
517     MEDCouplingUMesh *mesh_rw=MEDLoader::ReadUMeshFromFile(_file_name2.c_str(),mesh->getName().c_str(),0);
518     if (_verbose) cout<<_file_name2<<" reread"<<endl;
519     CPPUNIT_ASSERT(mesh->isEqual(mesh_rw,1e-12));
520     mesh_rw->decrRef();
521     mesh->decrRef();
522   }
523 }
524
525 /*
526 create a set of nbx*nby*nbz files mesh of ni*ny*nz cells
527 */
528 void MEDPARTITIONERTest::createHugeTestMesh(int ni, int nj, int nk, int nbx, int nby, int nbz, int nbTarget)
529 {
530   setSize(ni,nj,nk);
531   _nb_target_huge=nbTarget;
532   MEDCouplingUMesh * mesh = buildCUBE3DMesh();
533   //int nbx=1, nby=1, nbz=2;
534   std::vector< double > cooDep,cooFin;
535   mesh->getCoordinatesOfNode(0, cooDep);
536   mesh->getCoordinatesOfNode(mesh->getNumberOfNodes()-1, cooFin);
537   //cout<<endl<<cooDep[0]<<" "<<cooDep[1]<<" "<<cooDep[2]<<endl;
538   //cout<<cooFin[0]<<" "<<cooFin[1]<<" "<<cooFin[2]<<endl;
539
540   string tagXml="\
541 <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n \
542 <root>\n \
543   <version maj=\"2\" min=\"3\" ver=\"1\"/>\n \
544   <description what=\"\" when=\"YYMMDDHHmm\"/>\n \
545   <content>\n \
546     <mesh name=\"testMesh\"/>\n \
547   </content>\n \
548   <splitting>\n \
549     <subdomain number=\"$subdomainNumber\"/>\n \
550     <global_numbering present=\"no\"/>\n \
551   </splitting>\n \
552   <files>\n$tagSubfile \
553   </files>\n \
554   <mapping>\n$tagMesh \
555   </mapping>\n \
556 </root>\n";
557
558   string tagSubfiles, tagSubfile="\
559     <subfile id=\"$xyz\">\n \
560       <name>$fileName</name>\n \
561       <machine>localhost</machine>\n \
562     </subfile>\n";
563   string tagMeshes, tagMesh="\
564     <mesh name=\"testMesh\">\n \
565       <chunk subdomain=\"$xyz\">\n \
566         <name>testMesh</name>\n \
567       </chunk>\n \
568     </mesh>\n";
569
570   int xyz=1;
571   string sxyz;
572   DataArrayDouble* coordsInit=mesh->getCoords()->deepCpy();
573   double* ptrInit=coordsInit->getPointer();
574   double deltax=cooFin[0]-cooDep[0];
575   double deltay=cooFin[1]-cooDep[1];
576   double deltaz=cooFin[2]-cooDep[2];
577
578   double dz=0.;
579   for (int z=0; z<nbz; z++)
580     {
581       double dy=0.;
582       for (int y=0; y<nby; y++)
583         {
584           double dx=0.;
585           for (int x=0; x<nbx; x++)
586             {
587               string fileName;
588               sxyz=IntToStr(xyz);
589               fileName="tmp_testMeshHuge_"+IntToStr(_ni)+"x"+IntToStr(_nj)+"x"+IntToStr(_nk)+"_"+sxyz+".med";
590
591               DataArrayDouble* coords=mesh->getCoords();
592               //int nbOfComp=coords->getNumberOfComponents();  //be 3D
593               int nbOfTuple=coords->getNumberOfTuples();
594               double* ptr=coords->getPointer();
595               double* ptrini=ptrInit;
596               for (int i=0; i<nbOfTuple; i++)
597                 {
598                   *ptr=(*ptrini)+dx; ptr++; ptrini++; //be 3D
599                   *ptr=(*ptrini)+dy; ptr++; ptrini++;
600                   *ptr=(*ptrini)+dz; ptr++; ptrini++;
601                 }
602
603               MEDLoader::WriteUMesh(fileName.c_str(),mesh,true);
604
605               tagSubfiles+=tagSubfile;
606               tagSubfiles.replace(tagSubfiles.find("$xyz"),4,sxyz);
607               tagSubfiles.replace(tagSubfiles.find("$fileName"),9,fileName);
608
609               tagMeshes+=tagMesh;
610               tagMeshes.replace(tagMeshes.find("$xyz"),4,sxyz);
611               xyz++;
612               dx+=deltax;
613             }
614           dy+=deltay;
615         }
616       dz+=deltaz;
617     }
618   coordsInit->decrRef();
619
620   tagXml.replace(tagXml.find("$subdomainNumber"),16,sxyz);
621   tagXml.replace(tagXml.find("$tagSubfile"),11,tagSubfiles);
622   tagXml.replace(tagXml.find("$tagMesh"),8,tagMeshes);
623
624   string nameFileXml;
625   _file_name_huge_xml="tmp_testMeshHuge_"+IntToStr(_ni)+"x"+IntToStr(_nj)+"x"+IntToStr(_nk)+"_"+sxyz+".xml";
626   std::ofstream f(_file_name_huge_xml.c_str());
627   f<<tagXml;
628   f.close();
629   //cout<<"\n"<<tagXml<<endl;
630   if (_verbose)
631     cout<<endl<<nameFileXml<<" created"<<endl;
632   mesh->decrRef();
633 }
634
635 void MEDPARTITIONERTest::createTestMeshWithVecFieldOnCells()
636 {
637   {
638     string name=_file_name;
639     MEDCouplingFieldDouble *f1=buildVecFieldOnCells(name);
640     name.replace(name.find(".med"),4,"_WithVecFieldOnCells.med");
641     MEDLoader::WriteField(name.c_str(),f1,true);
642     f1->setTime(3.,1,1);  //time,it,order
643     f1->applyFunc("x/2.");
644     MEDLoader::WriteField(name.c_str(),f1,false);
645     if (_verbose) cout<<endl<<name<<" created"<<endl;
646     if (_ntot<1000000) //too long
647       {
648         MEDCouplingFieldDouble *f2=MEDLoader::ReadFieldCell(name.c_str(),f1->getMesh()->getName().c_str(),0,f1->getName().c_str(),0,1);
649         //DataArrayDouble *res=f2->getArray();
650         if (_verbose) cout<<name<<" reread"<<endl;
651         //CPPUNIT_ASSERT(f1->isEqual(f2,1e-12,1e-12));
652         f2->decrRef();
653       }
654     f1->decrRef();
655   }
656   {
657     string name=_file_name;
658     MEDCouplingFieldDouble *f1=buildVecFieldOnCells(name);
659     name.replace(name.find(".med"),4,"_WithVecFieldOnGaussNe.med");
660     MEDCouplingFieldDouble *f3=MEDCouplingFieldDouble::New(ON_GAUSS_NE,ONE_TIME);
661     f3->setMesh(f1->getMesh());
662     //cout<<"\nNumberOfMeshPlacesExpected "<<f3->getNumberOfMeshPlacesExpected()<<" "
663     //                                     /*<<getNumberOfTuples(f1->getMesh())<<" "*/
664     //                                     <<f3->getMesh()->getNumberOfNodes()<<" "
665     //                                     <<f3->getMesh()->getNumberOfCells()<<endl;
666     f3->setName("MyFieldOnGaussNE");
667     f3->setDescription("MyDescriptionNE");
668     DataArrayDouble *array=DataArrayDouble::New();
669     //int nb=f1->getMesh()->getNumberOfNodes();
670
671     /*8 pt de gauss by cell
672       int nb=f3->getMesh()->getNumberOfCells()*8;
673       array->alloc(nb,2);
674       double *ptr=array->getPointer();
675       for (int i=0; i<nb*2; i=i+2) {ptr[i]=(double)(i/8) ; ptr[i]=2.*(double)(i/8);}
676     */
677
678     //more nbptgauss=8 by default needs set MEDCouplingFieldDiscretizationPerCell
679     //theory: (may be) http://www.code-aster.org/V2/doc/v9/fr/man_r/r3/r3.06.03.pdf
680     int nbptgauss=8; //nb pt de gauss by cell
681     int nbcell=f3->getMesh()->getNumberOfCells();
682     int nb=nbcell*nbptgauss;
683     int nbcomp=2;
684     array->alloc(nb,nbcomp);
685     double *ptr=array->getPointer();
686     int ii=0;
687     for (int i=0; i<nbcell; i++)
688       for (int j=0; j<nbptgauss; j++)
689         for (int k=0; k<nbcomp; k++)
690           {
691             //123.4 for 12th cell,3rd component, 4th gausspoint
692             ptr[ii]=(double)((i+1)*10+(k+1))+((double)(j+1))/10.;
693             ii++;
694           }
695     array->setInfoOnComponent(0,"vGx");
696     array->setInfoOnComponent(1,"vGy");
697     f3->setTime(4.,5,6);
698     f3->setArray(array);
699     array->decrRef();
700     MEDLoader::WriteField(name.c_str(),f3,true);
701     if (_verbose) cout<<endl<<name<<" created"<<endl;
702     f3->checkCoherency();
703     f1->decrRef();
704     if (_ntot<1000000) //too long
705       {
706         MEDCouplingFieldDouble* f4=MEDLoader::ReadField(ON_GAUSS_NE,
707                                                         name.c_str(), f3->getMesh()->getName().c_str(), 0, "MyFieldOnGaussNE", 5, 6);
708         if (_verbose) cout<<"MyFieldOnGaussNE reread"<<endl;
709         f4->decrRef();
710       }
711     f3->decrRef();
712   }
713   {
714     string name=_file_name_with_faces;
715     MEDCouplingFieldDouble *f1=buildVecFieldOnCells(name);
716     name.replace(name.find(".med"),4,"_WithVecFieldOnCells.med");
717     MEDLoader::WriteField(name.c_str(),f1,true);
718     if (_verbose) cout<<endl<<name<<" created"<<endl;
719     if (_ntot<1000000) //too long
720       {
721         MEDCouplingFieldDouble *f2=MEDLoader::ReadFieldCell(name.c_str(),f1->getMesh()->getName().c_str(),0,f1->getName().c_str(),0,1);
722         if (_verbose) cout<<name<<" reread"<<endl;
723         //CPPUNIT_ASSERT(f1->isEqual(f2,1e-12,1e-12)); assertion failed!!
724         f2->decrRef();
725       }
726     f1->decrRef();
727   }
728 }
729
730 void MEDPARTITIONERTest::createTestMeshWithVecFieldOnNodes()
731 {
732   MEDCouplingFieldDouble *f1=buildVecFieldOnNodes();
733   string name=_file_name;
734   name.replace(name.find(".med"),4,"_WithVecFieldOnNodes.med");
735   MEDLoader::WriteField(name.c_str(),f1,true);
736   if (_verbose) cout<<endl<<name<<" created"<<endl;
737   if (_ntot<1000000) //too long
738     {
739       MEDCouplingFieldDouble *f2=MEDLoader::ReadFieldNode(name.c_str(),f1->getMesh()->getName().c_str(),0,f1->getName().c_str(),0,1);
740       if (_verbose) cout<<name<<" reread"<<endl;
741       //CPPUNIT_ASSERT(f1->isEqual(f2,1e-12,1e-12)); assertion failed!!
742       f2->decrRef();
743     }
744   f1->decrRef();
745 }
746
747 void MEDPARTITIONERTest::verifyTestMeshWithVecFieldOnNodes()
748 {
749   string name=_file_name;
750   name.replace(name.find(".med"),4,"_WithVecFieldOnNodes.med");
751   MEDCouplingUMesh * m=MEDLoader::ReadUMeshFromFile(name.c_str(),_mesh_name.c_str(),0);
752   std::set<INTERP_KERNEL::NormalizedCellType> types(m->getAllGeoTypes());
753   if (_verbose)
754     {
755       cout<<"\n types in "<<name<<" : ";
756       //for (std::set<INTERP_KERNEL::NormalizedCellType>::iterator t=types.begin(); t!=types.end(); ++t) cout<<" "<<*t;
757       for (std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator t=types.begin(); t!=types.end(); ++t)
758         {
759           //INTERP_KERNEL::CellModel essai=INTERP_KERNEL::CellModel::GetCellModel(*t);
760           cout<<" "<<(INTERP_KERNEL::CellModel::GetCellModel(*t)).getRepr();
761         }
762       cout<<endl;
763     }
764   m->decrRef();
765
766   MEDFileUMesh * mf = MEDFileUMesh::New(_file_name.c_str(),_mesh_name.c_str(),-1,-1);
767   vector<int> lev;
768   lev=mf->getNonEmptyLevels();
769   if (_verbose)
770     {
771       cout<<" levels in "<<name<<" : ";
772       for (vector<int>::iterator l=lev.begin(); l!=lev.end(); ++l) cout<<" "<<*l;
773       cout<<endl;
774     }
775   mf->decrRef();
776 }
777
778 void MEDPARTITIONERTest::createTestMeshes()
779 {
780   createTestMeshWithoutField();
781   createTestMeshWithVecFieldOnCells();
782   createTestMeshWithVecFieldOnNodes();
783 }
784
785 void MEDPARTITIONERTest::deleteTestMeshes()
786 {
787   string cmd="rm *tmp_testMesh*";
788   if (_verbose) cout<<endl<<cmd<<endl;
789   system(cmd.c_str());  //may be not if debug
790 }
791
792 void MEDPARTITIONERTest::testMeshCollectionSingle()
793 {
794   setSmallSize();
795   createTestMeshes();
796   MyGlobals::_World_Size=1;
797   MyGlobals::_Rank=0;
798   string fileName=_file_name_with_faces;
799   MEDPARTITIONER::ParaDomainSelector parallelizer(false);
800   MEDPARTITIONER::MeshCollection collection(fileName,parallelizer);
801   CPPUNIT_ASSERT(collection.isParallelMode());
802   CPPUNIT_ASSERT_EQUAL(3, collection.getMeshDimension());
803   CPPUNIT_ASSERT(collection.getName()=="testMesh");
804   CPPUNIT_ASSERT_EQUAL(1,collection.getNbOfLocalMeshes());
805   CPPUNIT_ASSERT_EQUAL(1,collection.getNbOfGlobalMeshes());
806   CPPUNIT_ASSERT_EQUAL(_ni*_nj*_nk,collection.getNbOfLocalCells());
807   CPPUNIT_ASSERT_EQUAL(_ni*_nj,collection.getNbOfLocalFaces());
808 }
809
810 void MEDPARTITIONERTest::testMeshCollectionXml()
811 {
812   setSmallSize();
813   createHugeTestMesh(_ni, _nj, _nk, 2, 2, 2, 32); //xml but not so huge
814   string fileName=_file_name_huge_xml;
815   MEDPARTITIONER::ParaDomainSelector parallelizer(false);
816   MEDPARTITIONER::MeshCollection collection(fileName,parallelizer);
817   CPPUNIT_ASSERT(collection.isParallelMode());
818   CPPUNIT_ASSERT_EQUAL(3, collection.getMeshDimension());
819   CPPUNIT_ASSERT(collection.getName()=="testMesh");
820   CPPUNIT_ASSERT_EQUAL(8,collection.getNbOfLocalMeshes());
821   CPPUNIT_ASSERT_EQUAL(8,collection.getNbOfGlobalMeshes());
822   CPPUNIT_ASSERT_EQUAL(_ni*_nj*_nk*8,collection.getNbOfLocalCells());
823   CPPUNIT_ASSERT_EQUAL(0,collection.getNbOfLocalFaces());
824 }
825
826
827 //#################for metis
828
829
830
831 #if defined(MED_ENABLE_METIS)
832 void MEDPARTITIONERTest::testMeshCollectionSinglePartitionMetis()
833 {
834   setSmallSize();
835   createTestMeshes();
836   //MyGlobals::_Verbose=500;
837   string fileName=_file_name_with_faces;
838   int ndomains=2;
839   bool split_family=false;
840   bool empty_groups=false;
841   MEDPARTITIONER::ParaDomainSelector parallelizer(false);
842   MEDPARTITIONER::MeshCollection collection(fileName,parallelizer);
843
844   MEDPARTITIONER::ParallelTopology* aPT = (MEDPARTITIONER::ParallelTopology*) collection.getTopology();
845   aPT->setGlobalNumerotationDefault(collection.getParaDomainSelector());
846   //Creating the graph and partitioning it
847   auto_ptr< MEDPARTITIONER::Topology > new_topo;
848   new_topo.reset( collection.createPartition(ndomains,MEDPARTITIONER::Graph::METIS) );
849   //Creating a new mesh collection from the partitioning
850   MEDPARTITIONER::MeshCollection new_collection(collection,new_topo.get(),split_family,empty_groups);
851
852   //example to create files
853   //MyGlobals::_General_Informations.clear();
854   //MyGlobals::_General_Informations.push_back(SerializeFromString("finalMeshName=Merge"));
855   //if (MyGlobals::_Verbose>100) cout << "generalInformations : \n"<<ReprVectorOfString(MyGlobals::_General_Informations);
856   //new_collection.write("ttmp")
857
858   CPPUNIT_ASSERT(new_collection.isParallelMode());
859   CPPUNIT_ASSERT_EQUAL(3, new_collection.getMeshDimension());
860   CPPUNIT_ASSERT(new_collection.getName()==collection.getName());
861   CPPUNIT_ASSERT_EQUAL(ndomains,new_collection.getNbOfLocalMeshes());
862   CPPUNIT_ASSERT_EQUAL(ndomains,new_collection.getNbOfGlobalMeshes());
863   CPPUNIT_ASSERT_EQUAL(collection.getNbOfLocalCells(),new_collection.getNbOfLocalCells());
864   CPPUNIT_ASSERT_EQUAL(collection.getNbOfLocalFaces(),new_collection.getNbOfLocalFaces());
865 }
866
867 void MEDPARTITIONERTest::testMeshCollectionComplexPartitionMetis()
868 {
869   setSmallSize();
870   createHugeTestMesh(_ni, _nj, _nk, 2, 2, 2, 32); //xml on 2*2*2 meshes but not so huge
871   string fileName=_file_name_huge_xml;
872   bool split_family=false;
873   bool empty_groups=false;
874   MEDPARTITIONER::ParaDomainSelector parallelizer(false);
875   MEDPARTITIONER::MeshCollection collection(fileName,parallelizer);
876
877   MEDPARTITIONER::ParallelTopology* aPT = (MEDPARTITIONER::ParallelTopology*) collection.getTopology();
878   aPT->setGlobalNumerotationDefault(collection.getParaDomainSelector());
879
880   for (int ndomains=2 ; ndomains<=16 ; ndomains++)
881     {
882       //Creating the graph and partitioning it
883       auto_ptr< MEDPARTITIONER::Topology > new_topo;
884       new_topo.reset( collection.createPartition(ndomains,MEDPARTITIONER::Graph::METIS) );
885       //Creating a new mesh collection from the partitioning
886       MEDPARTITIONER::MeshCollection new_collection(collection,new_topo.get(),split_family,empty_groups);
887
888       CPPUNIT_ASSERT_EQUAL(ndomains,new_collection.getNbOfLocalMeshes());
889       CPPUNIT_ASSERT_EQUAL(ndomains,new_collection.getNbOfGlobalMeshes());
890       CPPUNIT_ASSERT_EQUAL(collection.getNbOfLocalCells(),new_collection.getNbOfLocalCells());
891       CPPUNIT_ASSERT_EQUAL(collection.getNbOfLocalFaces(),new_collection.getNbOfLocalFaces());
892     }
893 }
894
895 void MEDPARTITIONERTest::testMetisSmallSize()
896 {
897   //#if !defined(HAVE_MPI)
898   setSmallSize();
899   createTestMeshes();
900   std::string MetisOrScotch("metis");
901   launchMetisOrScotchMedpartitionerOnTestMeshes(MetisOrScotch);
902   verifyMetisOrScotchMedpartitionerOnSmallSizeForMesh(MetisOrScotch);
903   verifyMetisOrScotchMedpartitionerOnSmallSizeForFieldOnCells(MetisOrScotch);
904   verifyMetisOrScotchMedpartitionerOnSmallSizeForFieldOnGaussNe(MetisOrScotch);
905   //#endif
906 }
907 #endif
908
909
910 //#################for scotch
911
912
913 #if defined(MED_ENABLE_SCOTCH)
914 void MEDPARTITIONERTest::testMeshCollectionSinglePartitionScotch()
915 {
916   setSmallSize();
917   createTestMeshes();
918   //MyGlobals::_Verbose=500;
919   string fileName=_file_name_with_faces;
920   int ndomains=2;
921   bool split_family=false;
922   bool empty_groups=false;
923   MEDPARTITIONER::ParaDomainSelector parallelizer(false);
924   MEDPARTITIONER::MeshCollection collection(fileName,parallelizer);
925
926   MEDPARTITIONER::ParallelTopology* aPT = (MEDPARTITIONER::ParallelTopology*) collection.getTopology();
927   aPT->setGlobalNumerotationDefault(collection.getParaDomainSelector());
928   //Creating the graph and partitioning it
929   auto_ptr< MEDPARTITIONER::Topology > new_topo;
930   new_topo.reset( collection.createPartition(ndomains,MEDPARTITIONER::Graph::SCOTCH) );
931   //Creating a new mesh collection from the partitioning
932   MEDPARTITIONER::MeshCollection new_collection(collection,new_topo.get(),split_family,empty_groups);
933
934   //example to create files
935   //MyGlobals::_General_Informations.clear();
936   //MyGlobals::_General_Informations.push_back(SerializeFromString("finalMeshName=Merge"));
937   //if (MyGlobals::_Verbose>100) cout << "generalInformations : \n"<<ReprVectorOfString(MyGlobals::_General_Informations);
938   //new_collection.write("ttmp")
939
940   CPPUNIT_ASSERT(new_collection.isParallelMode());
941   CPPUNIT_ASSERT_EQUAL(3, new_collection.getMeshDimension());
942   CPPUNIT_ASSERT(new_collection.getName()==collection.getName());
943   CPPUNIT_ASSERT_EQUAL(ndomains,new_collection.getNbOfLocalMeshes());
944   CPPUNIT_ASSERT_EQUAL(ndomains,new_collection.getNbOfGlobalMeshes());
945   CPPUNIT_ASSERT_EQUAL(collection.getNbOfLocalCells(),new_collection.getNbOfLocalCells());
946   CPPUNIT_ASSERT_EQUAL(collection.getNbOfLocalFaces(),new_collection.getNbOfLocalFaces());
947 }
948
949 void MEDPARTITIONERTest::testMeshCollectionComplexPartitionScotch()
950 {
951   setSmallSize();
952   createHugeTestMesh(_ni, _nj, _nk, 2, 2, 2, 32); //xml on 2*2*2 meshes but not so huge
953   string fileName=_file_name_huge_xml;
954   bool split_family=false;
955   bool empty_groups=false;
956   MEDPARTITIONER::ParaDomainSelector parallelizer(false);
957   MEDPARTITIONER::MeshCollection collection(fileName,parallelizer);
958
959   MEDPARTITIONER::ParallelTopology* aPT = (MEDPARTITIONER::ParallelTopology*) collection.getTopology();
960   aPT->setGlobalNumerotationDefault(collection.getParaDomainSelector());
961
962   for (int ndomains=2 ; ndomains<=16 ; ndomains++)
963     {
964       //Creating the graph and partitioning it
965       auto_ptr< MEDPARTITIONER::Topology > new_topo;
966       new_topo.reset( collection.createPartition(ndomains,MEDPARTITIONER::Graph::SCOTCH) );
967       //Creating a new mesh collection from the partitioning
968       MEDPARTITIONER::MeshCollection new_collection(collection,new_topo.get(),split_family,empty_groups);
969
970       CPPUNIT_ASSERT_EQUAL(ndomains,new_collection.getNbOfLocalMeshes());
971       CPPUNIT_ASSERT_EQUAL(ndomains,new_collection.getNbOfGlobalMeshes());
972       CPPUNIT_ASSERT_EQUAL(collection.getNbOfLocalCells(),new_collection.getNbOfLocalCells());
973       CPPUNIT_ASSERT_EQUAL(collection.getNbOfLocalFaces(),new_collection.getNbOfLocalFaces());
974     }
975 }
976
977 void MEDPARTITIONERTest::testScotchSmallSize()
978 {
979   //#if !defined(HAVE_MPI)
980   setSmallSize();
981   createTestMeshes();
982   std::string MetisOrScotch("scotch");
983   launchMetisOrScotchMedpartitionerOnTestMeshes(MetisOrScotch);
984   verifyMetisOrScotchMedpartitionerOnSmallSizeForMesh(MetisOrScotch);
985   verifyMetisOrScotchMedpartitionerOnSmallSizeForFieldOnCells(MetisOrScotch);
986   verifyMetisOrScotchMedpartitionerOnSmallSizeForFieldOnGaussNe(MetisOrScotch);
987   //#endif
988 }
989 #endif
990
991 void MEDPARTITIONERTest::launchMetisOrScotchMedpartitionerOnTestMeshes(std::string MetisOrScotch)
992 {
993   int res;
994   string cmd,execName,sourceName,targetName;
995
996   execName=getPartitionerExe();
997
998   cmd="which "+execName+" 2>/dev/null 1>/dev/null";  //no trace
999   res=system(cmd.c_str());
1000   CPPUNIT_ASSERT_EQUAL_MESSAGE(execName + " - INVALID PATH TO medpartitioner", 0, res);
1001
1002   cmd=execName+" --ndomains=2 --split-method="+MetisOrScotch;  //on same proc
1003   sourceName=_file_name;
1004   targetName=_file_name;
1005   targetName.replace(targetName.find(".med"),4,"_partitionedTo2_");
1006   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
1007   if (_verbose) cout<<endl<<cmd<<endl;
1008   res=system(cmd.c_str());
1009   CPPUNIT_ASSERT_EQUAL(0, res);
1010
1011   cmd=execName+" --ndomains=5 --split-method="+MetisOrScotch; //on less proc
1012   sourceName=_file_name;
1013   targetName=_file_name;
1014   targetName.replace(targetName.find(".med"),4,"_partitionedTo5_");
1015   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
1016   if (_verbose) cout<<endl<<cmd<<endl;
1017   res=system(cmd.c_str());
1018   CPPUNIT_ASSERT_EQUAL(0, res);
1019
1020   cmd=execName+" --ndomains=1 --split-method="+MetisOrScotch;  //on 1 proc
1021   sourceName=targetName+".xml";
1022   targetName=_file_name;
1023   targetName.replace(targetName.find(".med"),4,"_remergedFrom5_");
1024   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
1025   if (_verbose) cout<<endl<<cmd<<endl;
1026   res=system(cmd.c_str());
1027   CPPUNIT_ASSERT_EQUAL(0, res);
1028
1029   cmd=execName+" --ndomains=1 --split-method="+MetisOrScotch;  //on more proc
1030   //sourceName=targetName+".xml";
1031   targetName=_file_name;
1032   targetName.replace(targetName.find(".med"),4,"_remergedFrom5_");
1033   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
1034   if (_verbose) cout<<endl<<cmd<<endl;
1035   res=system(cmd.c_str());
1036   CPPUNIT_ASSERT_EQUAL(0, res);
1037 }
1038
1039 void MEDPARTITIONERTest::verifyMetisOrScotchMedpartitionerOnSmallSizeForMesh(std::string MetisOrScotch)
1040 {
1041   int res;
1042   string fileName,cmd,execName,sourceName,targetName,input;
1043   execName=getPartitionerExe();
1044   fileName=_file_name_with_faces;
1045
1046   ParaMEDMEM::MEDFileUMesh* initialMesh=ParaMEDMEM::MEDFileUMesh::New(fileName.c_str(),_mesh_name.c_str());
1047   ParaMEDMEM::MEDCouplingUMesh* cellMesh=initialMesh->getLevel0Mesh(false);
1048   ParaMEDMEM::MEDCouplingUMesh* faceMesh=initialMesh->getLevelM1Mesh(false);
1049
1050   cmd=execName+" --ndomains=5 --split-method="+MetisOrScotch;  //on same proc
1051   sourceName=fileName;
1052   targetName=fileName;
1053   targetName.replace(targetName.find(".med"),4,"_partitionedTo5_");
1054   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
1055   if (_verbose) cout<<endl<<cmd<<endl;
1056   res=system(cmd.c_str());
1057   CPPUNIT_ASSERT_EQUAL(0, res);
1058   input=targetName+".xml";
1059
1060   MEDPARTITIONER::ParaDomainSelector parallelizer(false);
1061   MEDPARTITIONER::MeshCollection collection(input,parallelizer);
1062   CPPUNIT_ASSERT_EQUAL(3, collection.getMeshDimension());
1063   std::vector<ParaMEDMEM::MEDCouplingUMesh*>cellMeshes=collection.getMesh();
1064   CPPUNIT_ASSERT_EQUAL(5, (int) cellMeshes.size());
1065   int nbcells=0;
1066   for (std::size_t i = 0; i < cellMeshes.size(); i++)
1067     nbcells+=cellMeshes[i]->getNumberOfCells();
1068   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), nbcells);
1069
1070   std::vector<ParaMEDMEM::MEDCouplingUMesh*>faceMeshes=collection.getFaceMesh();
1071   CPPUNIT_ASSERT_EQUAL(5, (int) faceMeshes.size());
1072   int nbfaces=0;
1073   for (std::size_t i=0; i < faceMeshes.size(); i++)
1074     nbfaces+=faceMeshes[i]->getNumberOfCells();
1075   CPPUNIT_ASSERT_EQUAL(faceMesh->getNumberOfCells(), nbfaces);
1076
1077   //merge split meshes and test equality
1078   cmd=execName+" --ndomains=1 --split-method="+MetisOrScotch;  //on same proc
1079   sourceName=targetName+".xml";
1080   targetName=fileName;
1081   targetName.replace(targetName.find(".med"),4,"_remergedFrom5_");
1082   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
1083   if (_verbose) cout<<endl<<cmd<<endl;
1084   res=system(cmd.c_str());
1085   CPPUNIT_ASSERT_EQUAL(0, res);
1086
1087   string refusedName=targetName+"1.med";
1088   ParaMEDMEM::MEDFileUMesh* refusedMesh=ParaMEDMEM::MEDFileUMesh::New(refusedName.c_str(),_mesh_name.c_str());
1089   ParaMEDMEM::MEDCouplingUMesh* refusedCellMesh=refusedMesh->getLevel0Mesh(false);
1090   ParaMEDMEM::MEDCouplingUMesh* refusedFaceMesh=refusedMesh->getLevelM1Mesh(false);
1091
1092   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), refusedCellMesh->getNumberOfCells());
1093   CPPUNIT_ASSERT_EQUAL(faceMesh->getNumberOfCells(), refusedFaceMesh->getNumberOfCells());
1094
1095   /*not the good job
1096     ParaMEDMEM::MEDCouplingMesh* mergeCell=cellMesh->mergeMyselfWith(refusedCellMesh);
1097     CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), mergeCell->getNumberOfCells());
1098
1099     ParaMEDMEM::MEDCouplingMesh* mergeFace=faceMesh->mergeMyselfWith(refusedFaceMesh);
1100     CPPUNIT_ASSERT_EQUAL(faceMesh->getNumberOfCells(), mergeFace->getNumberOfCells());
1101
1102     CPPUNIT_ASSERT(faceMesh->isEqual(refusedFaceMesh,1e-12));
1103   */
1104
1105   std::vector<const MEDCouplingUMesh *> meshes;
1106   std::vector<DataArrayInt *> corr;
1107   meshes.push_back(cellMesh);
1108   refusedCellMesh->tryToShareSameCoordsPermute(*cellMesh, 1e-9);
1109   meshes.push_back(refusedCellMesh);
1110   MEDCouplingUMesh* fusedCell=MEDCouplingUMesh::FuseUMeshesOnSameCoords(meshes,0,corr);
1111   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), fusedCell->getNumberOfCells());
1112
1113   meshes.resize(0);
1114   for (std::size_t i = 0; i < corr.size(); i++)
1115     corr[i]->decrRef();
1116   corr.resize(0);
1117   meshes.push_back(faceMesh);
1118   refusedFaceMesh->tryToShareSameCoordsPermute(*faceMesh, 1e-9);
1119   meshes.push_back(refusedFaceMesh);
1120   MEDCouplingUMesh* fusedFace=MEDCouplingUMesh::FuseUMeshesOnSameCoords(meshes,0,corr);
1121   CPPUNIT_ASSERT_EQUAL(faceMesh->getNumberOfCells(), fusedFace->getNumberOfCells());
1122
1123   for (std::size_t i = 0; i < corr.size(); i++)
1124     corr[i]->decrRef();
1125   fusedFace->decrRef();
1126   refusedFaceMesh->decrRef();
1127   faceMesh->decrRef();
1128   fusedCell->decrRef();
1129   refusedCellMesh->decrRef();
1130   refusedMesh->decrRef();
1131   cellMesh->decrRef();
1132   initialMesh->decrRef();
1133   //done in ~collection
1134   //for (int i = 0; i < faceMeshes.size(); i++) faceMeshes[i]->decrRef();
1135   //for (int i = 0; i < cellMeshes.size(); i++) cellMeshes[i]->decrRef();
1136 }
1137
1138 void MEDPARTITIONERTest::verifyMetisOrScotchMedpartitionerOnSmallSizeForFieldOnCells(std::string MetisOrScotch)
1139 {
1140   int res;
1141   string fileName,cmd,execName,sourceName,targetName,input;
1142   execName=getPartitionerExe();
1143   fileName=_file_name;
1144   fileName.replace(fileName.find(".med"),4,"_WithVecFieldOnCells.med");
1145
1146   ParaMEDMEM::MEDFileUMesh* initialMesh=ParaMEDMEM::MEDFileUMesh::New(fileName.c_str(),_mesh_name.c_str());
1147   ParaMEDMEM::MEDCouplingUMesh* cellMesh=initialMesh->getLevel0Mesh(false);
1148
1149   cmd=execName+" --ndomains=5 --split-method="+MetisOrScotch;  //on same proc
1150   sourceName=fileName;
1151   targetName=fileName;
1152   targetName.replace(targetName.find(".med"),4,"_partitionedTo5_");
1153   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
1154   if (_verbose) cout<<endl<<cmd<<endl;
1155   res=system(cmd.c_str());
1156   CPPUNIT_ASSERT_EQUAL(0, res);
1157   input=targetName+".xml";
1158
1159   //merge split meshes and test equality
1160   cmd=execName+" --ndomains=1 --split-method="+MetisOrScotch;  //on same proc
1161   sourceName=targetName+".xml";
1162   targetName=fileName;
1163   targetName.replace(targetName.find(".med"),4,"_remergedFrom5_");
1164   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
1165   if (_verbose) cout<<endl<<cmd<<endl;
1166   res=system(cmd.c_str());
1167   CPPUNIT_ASSERT_EQUAL(0, res);
1168
1169   string refusedName=targetName+"1.med";
1170   ParaMEDMEM::MEDFileUMesh* refusedMesh=ParaMEDMEM::MEDFileUMesh::New(refusedName.c_str(),_mesh_name.c_str());
1171   ParaMEDMEM::MEDCouplingUMesh* refusedCellMesh=refusedMesh->getLevel0Mesh(false);
1172
1173   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), refusedCellMesh->getNumberOfCells());
1174
1175   std::vector<const MEDCouplingUMesh *> meshes;
1176   std::vector<DataArrayInt *> corr;
1177   meshes.push_back(cellMesh);
1178   refusedCellMesh->tryToShareSameCoordsPermute(*cellMesh, 1e-9);
1179   meshes.push_back(refusedCellMesh);
1180   MEDCouplingUMesh* fusedCell=MEDCouplingUMesh::FuseUMeshesOnSameCoords(meshes,0,corr);
1181   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), fusedCell->getNumberOfCells());
1182
1183   MEDCouplingFieldDouble* field1=MEDLoader::ReadFieldCell(fileName.c_str(),initialMesh->getName().c_str(),0,"VectorFieldOnCells",0,1);
1184   MEDCouplingFieldDouble* field2=MEDLoader::ReadFieldCell(refusedName.c_str(),refusedCellMesh->getName().c_str(),0,"VectorFieldOnCells",0,1);
1185
1186   int nbcells=corr[1]->getNumberOfTuples();
1187   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), nbcells);
1188   //use corr to test equality of field
1189   DataArrayDouble* f1=field1->getArray();
1190   DataArrayDouble* f2=field2->getArray();
1191   if (_verbose>300)
1192     {
1193       cout<<"\nf1 : "<<f1->reprZip();
1194       cout<<"\nf2 : "<<f2->reprZip(); //field2->advancedRepradvancedRepr();
1195       for (std::size_t i = 0; i < corr.size(); i++)
1196         cout << "\ncorr " << i << " : " << corr[i]->reprZip();
1197
1198     }
1199   int nbequal=0;
1200   int nbcomp=field1->getNumberOfComponents();
1201   double* p1=f1->getPointer();
1202   double* p2=f2->getPointer();
1203   int* pc=corr[1]->getPointer();
1204   for (int i = 0; i < nbcells; i++)
1205     {
1206       int i1=pc[i]*nbcomp;
1207       int i2=i*nbcomp;
1208       for (int j = 0; j < nbcomp; j++)
1209         {
1210           if (p1[i1+j]==p2[i2+j]) nbequal++;
1211           //cout<<" "<<p1[i1+j]<<"="<<p2[i2+j];
1212         }
1213     }
1214   CPPUNIT_ASSERT_EQUAL(nbcells*nbcomp, nbequal);
1215
1216   for (std::size_t i = 0; i < corr.size(); i++)
1217     corr[i]->decrRef();
1218   field1->decrRef();
1219   field2->decrRef();
1220   fusedCell->decrRef();
1221   refusedMesh->decrRef();
1222   refusedCellMesh->decrRef();
1223   cellMesh->decrRef();
1224   initialMesh->decrRef();
1225 }
1226
1227 void MEDPARTITIONERTest::verifyMetisOrScotchMedpartitionerOnSmallSizeForFieldOnGaussNe(std::string MetisOrScotch)
1228 {
1229   int res;
1230   string fileName,cmd,execName,sourceName,targetName,input;
1231   execName=getPartitionerExe();
1232   fileName=_file_name;
1233   fileName.replace(fileName.find(".med"),4,"_WithVecFieldOnGaussNe.med");
1234
1235   ParaMEDMEM::MEDFileUMesh* initialMesh=ParaMEDMEM::MEDFileUMesh::New(fileName.c_str(),_mesh_name.c_str());
1236   ParaMEDMEM::MEDCouplingUMesh* cellMesh=initialMesh->getLevel0Mesh(false);
1237
1238   cmd=execName+" --ndomains=5 --split-method="+MetisOrScotch;  //on same proc
1239   sourceName=fileName;
1240   targetName=fileName;
1241   targetName.replace(targetName.find(".med"),4,"_partitionedTo5_");
1242   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
1243   if (_verbose) cout<<endl<<cmd<<endl;
1244   res=system(cmd.c_str());
1245   CPPUNIT_ASSERT_EQUAL(0, res);
1246   input=targetName+".xml";
1247
1248   //merge split meshes and test equality
1249   cmd=execName+" --ndomains=1 --split-method="+MetisOrScotch;  //on same proc
1250   sourceName=targetName+".xml";
1251   targetName=fileName;
1252   targetName.replace(targetName.find(".med"),4,"_remergedFrom5_");
1253   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
1254   if (_verbose) cout<<endl<<cmd<<endl;
1255   res=system(cmd.c_str());
1256   CPPUNIT_ASSERT_EQUAL(0, res);
1257
1258   string refusedName=targetName+"1.med";
1259   ParaMEDMEM::MEDFileUMesh* refusedMesh=ParaMEDMEM::MEDFileUMesh::New(refusedName.c_str(),_mesh_name.c_str());
1260   ParaMEDMEM::MEDCouplingUMesh* refusedCellMesh=refusedMesh->getLevel0Mesh(false);
1261
1262   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), refusedCellMesh->getNumberOfCells());
1263
1264   std::vector<const MEDCouplingUMesh *> meshes;
1265   std::vector<DataArrayInt *> corr;
1266   meshes.push_back(cellMesh);
1267   refusedCellMesh->tryToShareSameCoordsPermute(*cellMesh, 1e-9);
1268   meshes.push_back(refusedCellMesh);
1269   MEDCouplingUMesh* fusedCell=MEDCouplingUMesh::FuseUMeshesOnSameCoords(meshes,0,corr);
1270   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), fusedCell->getNumberOfCells());
1271
1272   MEDCouplingFieldDouble* field1=MEDLoader::ReadField(ON_GAUSS_NE,fileName.c_str(),initialMesh->getName().c_str(),0,"MyFieldOnGaussNE",5,6);
1273   MEDCouplingFieldDouble* field2=MEDLoader::ReadField(ON_GAUSS_NE,refusedName.c_str(),refusedCellMesh->getName().c_str(),0,"MyFieldOnGaussNE",5,6);
1274
1275   int nbcells=corr[1]->getNumberOfTuples();
1276   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), nbcells);
1277   //use corr to test equality of field
1278   DataArrayDouble* f1=field1->getArray();
1279   DataArrayDouble* f2=field2->getArray();
1280   if (_verbose>300)
1281     {
1282       cout << "\nf1 : " << f1->reprZip(); //123.4 for 12th cell,3rd component, 4th gausspoint
1283       cout << "\nf2 : " << f2->reprZip(); //field2->advancedRepradvancedRepr();
1284       for (std::size_t i = 0; i < corr.size(); i++)
1285         cout << "\ncorr " << i << " : " << corr[i]->reprZip();
1286
1287     }
1288   int nbequal=0;
1289   int nbptgauss=8;
1290   int nbcomp=field1->getNumberOfComponents();
1291   double* p1=f1->getPointer();
1292   double* p2=f2->getPointer();
1293   int* pc=corr[1]->getPointer();
1294   for (int i = 0; i < nbcells; i++)
1295     {
1296       int i1=pc[i]*nbcomp*nbptgauss;
1297       int i2=i*nbcomp*nbptgauss;
1298       for (int j = 0; j < nbcomp*nbptgauss; j++)
1299         {
1300           if (p1[i1+j]==p2[i2+j]) nbequal++;
1301           //cout<<" "<<p1[i1+j]<<"="<<p2[i2+j];
1302         }
1303     }
1304   CPPUNIT_ASSERT_EQUAL(nbcells*nbcomp*nbptgauss, nbequal);
1305
1306   for (std::size_t i = 0; i < corr.size(); i++)
1307     corr[i]->decrRef();
1308   field1->decrRef();
1309   field2->decrRef();
1310   fusedCell->decrRef();
1311   refusedMesh->decrRef();
1312   refusedCellMesh->decrRef();
1313   cellMesh->decrRef();
1314   initialMesh->decrRef();
1315 }
1316
1317 //================================================================================
1318 /*!
1319  * \brief Test for 0021756: [CEA 602] MEDPartitioner improvements
1320  */
1321 //================================================================================
1322
1323 void MEDPARTITIONERTest::testCreateBoundaryFaces2D()
1324 {
1325   // Fixed complains are:
1326   // - 2D is not available
1327   // - groups and family handling is bugged (probably due to bug in the handling
1328   //   of arrayTo in castIntField())
1329   // - creates boundary faces option is not handled
1330
1331   // Create a 2D mesh in a file
1332
1333   const char fileName[] = "tmp_testCreateBoundaryFaces2D.med";
1334
1335   const int idFam1 = 3, idFam2 = 2;
1336   int nbFam1, nbFam2, nbc;
1337   {
1338     const int nbX = 20, nbY = 15;
1339     vector<int> conn;
1340     vector<double> coor;
1341     for (int j=0; j<=nbY; j++)
1342       for (int i=0; i<=nbX; i++)
1343         {
1344           coor.push_back(i+.1);
1345           coor.push_back(j+.2);
1346         }
1347     int ii;
1348     for (int j=0; j<nbY; j++)
1349       for (int i=0; i<nbX; i++)
1350         {
1351           ii=i + j*(nbX+1);
1352           conn.push_back(ii);
1353           conn.push_back(ii+1);
1354           ii=ii + nbX + 2 ;
1355           conn.push_back(ii);
1356           conn.push_back(ii-1);
1357         }
1358     MEDCouplingUMesh *mesh=MEDCouplingUMesh::New();
1359     mesh->setMeshDimension(2);
1360
1361     nbc=conn.size()/4; //nb of cells
1362     mesh->allocateCells(nbc);
1363     int* pConn = &conn[0];
1364     for(int i=0; i<nbc; i++, pConn+=4)
1365       mesh->insertNextCell(INTERP_KERNEL::NORM_QUAD4,4,pConn);
1366     mesh->finishInsertingCells();
1367
1368     int nbv=coor.size()/2; //nb of vertices
1369     DataArrayDouble *myCoords=DataArrayDouble::New();
1370     myCoords->useArray( &coor[0], /*ownership=*/false, CPP_DEALLOC, nbv, 2 );
1371     mesh->setCoords(myCoords);
1372     mesh->setName("FacesIn2D");
1373     myCoords->decrRef();
1374     mesh->checkCoherency();
1375
1376     // groups of cells
1377     DataArrayInt* cellsFam=DataArrayInt::New();
1378     cellsFam->alloc(nbc,1);
1379     nbFam1 = nbc/3, nbFam2 = nbc/2;
1380     int iE = 0;
1381     for ( int i = 0; i < nbFam1; ++i ) cellsFam->getPointer()[ iE++ ] = idFam1;
1382     for ( int i = 0; i < nbFam2; ++i ) cellsFam->getPointer()[ iE++ ] = idFam2;
1383     for (            ; iE < nbc;     ) cellsFam->getPointer()[ iE++ ] = 0;
1384     map<string,int> theFamilies;
1385     theFamilies["FAMILLE_ZERO"]=0;
1386     theFamilies["Family1"     ]=idFam1;
1387     theFamilies["Family2"     ]=idFam2;
1388     map<string, vector<string> > theGroups;
1389     theGroups["Group1"].push_back("Family1");
1390     theGroups["Group2"].push_back("Family2");
1391
1392     // write mesh
1393     MEDFileUMesh * fileMesh = MEDFileUMesh::New();
1394     fileMesh->setMeshAtLevel(0, mesh);
1395     fileMesh->setFamilyInfo(theFamilies);
1396     fileMesh->setGroupInfo(theGroups);
1397     fileMesh->setFamilyFieldArr(0, cellsFam);
1398     fileMesh->write(fileName,2);
1399
1400     cellsFam->decrRef();
1401     mesh    ->decrRef();
1402     fileMesh->decrRef();
1403
1404   } // mesh creation
1405
1406   // Partition the mesh into 4 parts
1407
1408   const int ndomains = 4;
1409   ParaDomainSelector parallelizer(false);
1410   MeshCollection collection(fileName,parallelizer);
1411   ParallelTopology* aPT = (ParallelTopology*) collection.getTopology();
1412   aPT->setGlobalNumerotationDefault(collection.getParaDomainSelector());
1413
1414   std::auto_ptr< Topology > new_topo;
1415 #if defined(MED_ENABLE_METIS) || defined(MED_ENABLE_PARMETIS)
1416   new_topo.reset( collection.createPartition(ndomains,Graph::METIS) );
1417 #endif
1418 #if defined(MED_ENABLE_SCOTCH)
1419   if ( !new_topo.get() )
1420     new_topo.reset( collection.createPartition(ndomains,Graph::SCOTCH) );
1421 #endif
1422   if ( !new_topo.get() )
1423     return;
1424
1425   // Check that "2D is available"
1426
1427   const char xmlName[] = "tmp_testCreateBoundaryFaces2D";
1428   {
1429     MyGlobals::_Creates_Boundary_Faces = true;
1430     MeshCollection new_collection(collection,new_topo.get());
1431
1432     CPPUNIT_ASSERT_EQUAL(ndomains,new_collection.getNbOfLocalMeshes());
1433     CPPUNIT_ASSERT_EQUAL(ndomains,new_collection.getNbOfGlobalMeshes());
1434     CPPUNIT_ASSERT_EQUAL(collection.getNbOfLocalCells(),new_collection.getNbOfLocalCells());
1435     CPPUNIT_ASSERT_EQUAL(0,collection.getNbOfLocalFaces());
1436     CPPUNIT_ASSERT      (new_collection.getNbOfLocalFaces() > 0 );
1437
1438     MyGlobals::_General_Informations.clear();
1439     MyGlobals::_General_Informations.push_back(SerializeFromString("finalMeshName=2D"));
1440     new_collection.write( xmlName );
1441   }
1442
1443   // Check that "groups and family handling is NOT bugged"
1444
1445   MeshCollection new_collection(std::string(xmlName)+".xml");
1446   std::map< int, int > famId2nb; // count total nb of cells in divided families
1447   std::map< int, int >::iterator id2nn;
1448   {
1449     const std::vector<ParaMEDMEM::DataArrayInt*>& famIdsVec = new_collection.getCellFamilyIds();
1450     for ( size_t i = 0; i < famIdsVec.size(); ++i )
1451       {
1452         ParaMEDMEM::DataArrayInt* famIdsArr = famIdsVec[i];
1453         for ( int j = famIdsArr->getNbOfElems()-1; j >= 0; --j )
1454           {
1455             id2nn = famId2nb.insert( make_pair( famIdsArr->getPointer()[j], 0 )).first;
1456             id2nn->second++;
1457           }
1458       }
1459   }
1460   CPPUNIT_ASSERT_EQUAL( 3, (int) famId2nb.size() ); // 3 fams/groups in all
1461   CPPUNIT_ASSERT_EQUAL( 1, (int) famId2nb.count( 0      ));
1462   CPPUNIT_ASSERT_EQUAL( 1, (int) famId2nb.count( idFam1 ));
1463   CPPUNIT_ASSERT_EQUAL( 1, (int) famId2nb.count( idFam2 ));
1464   CPPUNIT_ASSERT_EQUAL( nbFam1, famId2nb[ idFam1 ]);
1465   CPPUNIT_ASSERT_EQUAL( nbFam2, famId2nb[ idFam2 ]);
1466   CPPUNIT_ASSERT_EQUAL( nbc - nbFam1 - nbFam2, famId2nb[ 0 ]);
1467
1468   // Check that "creates boundary faces option is handled"
1469
1470   famId2nb.clear();
1471   const std::vector<ParaMEDMEM::DataArrayInt*>& famIdsVec = new_collection.getFaceFamilyIds();
1472   for ( size_t i = 0; i < famIdsVec.size(); ++i )
1473     {
1474       ParaMEDMEM::DataArrayInt* famIdsArr = famIdsVec[i];
1475       for ( int j = famIdsArr->getNbOfElems()-1; j >= 0; --j )
1476         {
1477           id2nn = famId2nb.insert( make_pair( famIdsArr->getPointer()[j], 0 )).first;
1478           id2nn->second++;
1479         }
1480     }
1481
1482   CPPUNIT_ASSERT( !famId2nb.empty() );
1483
1484   // for each "JOINT_n_p_..." group there must be "JOINT_p_n_..." group
1485   // of the same size
1486   std::map<std::string,int>& famName2id = new_collection.getFamilyInfo();
1487   std::map<std::string,int>::iterator na2id = famName2id.begin(), na2id2;
1488   std::set< int > okFamIds;
1489   okFamIds.insert(0);
1490   for ( ; na2id != famName2id.end(); ++na2id )
1491     {
1492       if ( okFamIds.count( na2id->second ) || na2id->first[0] != 'J')
1493         continue;
1494       na2id2 = na2id;
1495       bool groupOK = false;
1496       while ( !groupOK && ++na2id2 != famName2id.end() )
1497         groupOK = ( na2id2->first.find_first_not_of( na2id->first ) == std::string::npos );
1498
1499       CPPUNIT_ASSERT( groupOK );
1500       CPPUNIT_ASSERT( na2id->second != na2id2->second);
1501       CPPUNIT_ASSERT_EQUAL( 1, (int) famId2nb.count( na2id2->second ));
1502       CPPUNIT_ASSERT_EQUAL( 1, (int) famId2nb.count( na2id->second ));
1503       CPPUNIT_ASSERT_EQUAL( (int) famId2nb[ na2id2->second ],
1504                             (int) famId2nb[ na2id->second ]);
1505       okFamIds.insert( na2id2->second );
1506     }
1507 }