Salome HOME
866409f0e94aef10d6c5f00f1f106f64d07c067f
[tools/medcoupling.git] / src / MEDPartitioner / Test / MEDPARTITIONERTestPara.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 <cmath>
41 #include <list>
42 #include <stdexcept>
43 #include <cstdlib>
44 #include <vector>
45
46 #include <mpi.h>
47
48 using namespace std;
49 using namespace ParaMEDMEM;
50 using namespace MEDPARTITIONER;
51
52 #if defined(HAVE_MPI)
53 std::string MEDPARTITIONERTest::getPartitionerParaExe() const
54 {
55   std::string execName;
56   if ( getenv("MEDCOUPLING_ROOT_DIR") )
57     {
58       execName=getenv("MEDCOUPLING_ROOT_DIR");  //.../INSTALL/MED
59       execName+="/bin/medpartitioner_para";
60     }
61   else
62     {
63       execName = get_current_dir_name();
64       execName += "/../../MEDPartitioner/medpartitioner_para";
65       if (! std::ifstream(execName.c_str()))
66         CPPUNIT_FAIL("Can't find medpartitioner_para, please set MEDCOUPLING_ROOT_DIR");
67     }
68   return execName;
69 }
70
71 void MEDPARTITIONERTest::verifyMedpartitionerOnSmallSizeForMesh()
72 {
73   int res;
74   string fileName,cmd,execName,sourceName,targetName,input;
75   execName=getPartitionerParaExe();
76   fileName=_file_name_with_faces;
77
78   ParaMEDMEM::MEDFileUMesh* initialMesh=ParaMEDMEM::MEDFileUMesh::New(fileName.c_str(),_mesh_name.c_str());
79   ParaMEDMEM::MEDCouplingUMesh* cellMesh=initialMesh->getLevel0Mesh(false);
80   ParaMEDMEM::MEDCouplingUMesh* faceMesh=initialMesh->getLevelM1Mesh(false);
81
82   cmd="mpirun -np 5 "+execName+" --ndomains=5 --split-method=metis";  //on same proc
83   sourceName=fileName;
84   targetName=fileName;
85   targetName.replace(targetName.find(".med"),4,"_partitionedTo5_");
86   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
87   if (_verbose) cout<<endl<<cmd<<endl;
88   res=system(cmd.c_str());
89   CPPUNIT_ASSERT_EQUAL(0, res);
90   input=targetName+".xml";
91
92   MEDPARTITIONER::ParaDomainSelector parallelizer(false);
93   MEDPARTITIONER::MeshCollection collection(input,parallelizer);
94   CPPUNIT_ASSERT_EQUAL(3, collection.getMeshDimension());
95   std::vector<ParaMEDMEM::MEDCouplingUMesh*>cellMeshes=collection.getMesh();
96   CPPUNIT_ASSERT_EQUAL(5, (int) cellMeshes.size());
97   int nbcells=0;
98   for (std::size_t i = 0; i < cellMeshes.size(); i++)
99     nbcells+=cellMeshes[i]->getNumberOfCells();
100   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), nbcells);
101
102   std::vector<ParaMEDMEM::MEDCouplingUMesh*>faceMeshes=collection.getFaceMesh();
103   CPPUNIT_ASSERT_EQUAL(5, (int) faceMeshes.size());
104   int nbfaces=0;
105   for (std::size_t i=0; i < faceMeshes.size(); i++)
106     nbfaces+=faceMeshes[i]->getNumberOfCells();
107   CPPUNIT_ASSERT_EQUAL(faceMesh->getNumberOfCells(), nbfaces);
108
109   //merge split meshes and test equality
110   cmd="mpirun -np 1 "+execName+" --ndomains=1 --split-method=metis";  //on same proc
111   sourceName=targetName+".xml";
112   targetName=fileName;
113   targetName.replace(targetName.find(".med"),4,"_remergedFrom5_");
114   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
115   if (_verbose) cout<<endl<<cmd<<endl;
116   res=system(cmd.c_str());
117   CPPUNIT_ASSERT_EQUAL(0, res);
118
119   string refusedName=targetName+"1.med";
120   ParaMEDMEM::MEDFileUMesh* refusedMesh=ParaMEDMEM::MEDFileUMesh::New(refusedName.c_str(),_mesh_name.c_str());
121   ParaMEDMEM::MEDCouplingUMesh* refusedCellMesh=refusedMesh->getLevel0Mesh(false);
122   ParaMEDMEM::MEDCouplingUMesh* refusedFaceMesh=refusedMesh->getLevelM1Mesh(false);
123
124   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), refusedCellMesh->getNumberOfCells());
125   CPPUNIT_ASSERT_EQUAL(faceMesh->getNumberOfCells(), refusedFaceMesh->getNumberOfCells());
126
127   /*not the good job
128     ParaMEDMEM::MEDCouplingMesh* mergeCell=cellMesh->mergeMyselfWith(refusedCellMesh);
129     CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), mergeCell->getNumberOfCells());
130
131     ParaMEDMEM::MEDCouplingMesh* mergeFace=faceMesh->mergeMyselfWith(refusedFaceMesh);
132     CPPUNIT_ASSERT_EQUAL(faceMesh->getNumberOfCells(), mergeFace->getNumberOfCells());
133
134     CPPUNIT_ASSERT(faceMesh->isEqual(refusedFaceMesh,1e-12));
135   */
136
137   std::vector<const MEDCouplingUMesh *> meshes;
138   std::vector<DataArrayInt *> corr;
139   meshes.push_back(cellMesh);
140   refusedCellMesh->tryToShareSameCoordsPermute(*cellMesh, 1e-9);
141   meshes.push_back(refusedCellMesh);
142   MEDCouplingUMesh* fusedCell=MEDCouplingUMesh::FuseUMeshesOnSameCoords(meshes,0,corr);
143   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), fusedCell->getNumberOfCells());
144
145   meshes.resize(0);
146   for (std::size_t i = 0; i < corr.size(); i++)
147     corr[i]->decrRef();
148   corr.resize(0);
149   meshes.push_back(faceMesh);
150   refusedFaceMesh->tryToShareSameCoordsPermute(*faceMesh, 1e-9);
151   meshes.push_back(refusedFaceMesh);
152   MEDCouplingUMesh* fusedFace=MEDCouplingUMesh::FuseUMeshesOnSameCoords(meshes,0,corr);
153   CPPUNIT_ASSERT_EQUAL(faceMesh->getNumberOfCells(), fusedFace->getNumberOfCells());
154
155   for (std::size_t i = 0; i < corr.size(); i++)
156     corr[i]->decrRef();
157   fusedFace->decrRef();
158   refusedFaceMesh->decrRef();
159   faceMesh->decrRef();
160   fusedCell->decrRef();
161   refusedCellMesh->decrRef();
162   cellMesh->decrRef();
163   //done in ~collection
164   //for (int i = 0; i < faceMeshes.size(); i++) faceMeshes[i]->decrRef();
165   //for (int i = 0; i < cellMeshes.size(); i++) cellMeshes[i]->decrRef();
166 }
167
168 void MEDPARTITIONERTest::verifyMedpartitionerOnSmallSizeForFieldOnCells()
169 {
170   int res;
171   string fileName,cmd,execName,sourceName,targetName,input;
172   execName=getPartitionerParaExe();
173   fileName=_file_name;
174   fileName.replace(fileName.find(".med"),4,"_WithVecFieldOnCells.med");
175
176   ParaMEDMEM::MEDFileUMesh* initialMesh=ParaMEDMEM::MEDFileUMesh::New(fileName.c_str(),_mesh_name.c_str());
177   ParaMEDMEM::MEDCouplingUMesh* cellMesh=initialMesh->getLevel0Mesh(false);
178
179   cmd="mpirun -np 5 "+execName+" --ndomains=5 --split-method=metis";  //on same proc
180   sourceName=fileName;
181   targetName=fileName;
182   targetName.replace(targetName.find(".med"),4,"_partitionedTo5_");
183   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
184   if (_verbose) cout<<endl<<cmd<<endl;
185   res=system(cmd.c_str());
186   CPPUNIT_ASSERT_EQUAL(0, res);
187   input=targetName+".xml";
188
189   //merge split meshes and test equality
190   cmd="mpirun -np 1 "+execName+" --ndomains=1 --split-method=metis";  //on same proc
191   sourceName=targetName+".xml";
192   targetName=fileName;
193   targetName.replace(targetName.find(".med"),4,"_remergedFrom5_");
194   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
195   if (_verbose) cout<<endl<<cmd<<endl;
196   res=system(cmd.c_str());
197   CPPUNIT_ASSERT_EQUAL(0, res);
198
199   string refusedName=targetName+"1.med";
200   ParaMEDMEM::MEDFileUMesh* refusedMesh=ParaMEDMEM::MEDFileUMesh::New(refusedName.c_str(),_mesh_name.c_str());
201   ParaMEDMEM::MEDCouplingUMesh* refusedCellMesh=refusedMesh->getLevel0Mesh(false);
202
203   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), refusedCellMesh->getNumberOfCells());
204
205   std::vector<const MEDCouplingUMesh *> meshes;
206   std::vector<DataArrayInt *> corr;
207   meshes.push_back(cellMesh);
208   refusedCellMesh->tryToShareSameCoordsPermute(*cellMesh, 1e-9);
209   meshes.push_back(refusedCellMesh);
210   MEDCouplingUMesh* fusedCell=MEDCouplingUMesh::FuseUMeshesOnSameCoords(meshes,0,corr);
211   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), fusedCell->getNumberOfCells());
212
213   MEDCouplingFieldDouble* field1=MEDLoader::ReadFieldCell(fileName.c_str(),initialMesh->getName().c_str(),0,"VectorFieldOnCells",0,1);
214   MEDCouplingFieldDouble* field2=MEDLoader::ReadFieldCell(refusedName.c_str(),refusedCellMesh->getName().c_str(),0,"VectorFieldOnCells",0,1);
215
216   int nbcells=corr[1]->getNumberOfTuples();
217   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), nbcells);
218   //use corr to test equality of field
219   DataArrayDouble* f1=field1->getArray();
220   DataArrayDouble* f2=field2->getArray();
221   if (_verbose>300)
222     {
223       cout<<"\nf1 : "<<f1->reprZip();
224       cout<<"\nf2 : "<<f2->reprZip(); //field2->advancedRepradvancedRepr();
225       for (std::size_t i = 0; i < corr.size(); i++)
226         cout << "\ncorr " << i << " : " << corr[i]->reprZip();
227
228     }
229   int nbequal=0;
230   int nbcomp=field1->getNumberOfComponents();
231   double* p1=f1->getPointer();
232   double* p2=f2->getPointer();
233   int* pc=corr[1]->getPointer();
234   for (int i = 0; i < nbcells; i++)
235     {
236       int i1=pc[i]*nbcomp;
237       int i2=i*nbcomp;
238       for (int j = 0; j < nbcomp; j++)
239         {
240           if (p1[i1+j]==p2[i2+j]) nbequal++;
241           //cout<<" "<<p1[i1+j]<<"="<<p2[i2+j];
242         }
243     }
244   CPPUNIT_ASSERT_EQUAL(nbcells*nbcomp, nbequal);
245
246   for (std::size_t i = 0; i < corr.size(); i++)
247     corr[i]->decrRef();
248   field1->decrRef();
249   field2->decrRef();
250   fusedCell->decrRef();
251   refusedCellMesh->decrRef();
252   cellMesh->decrRef();
253 }
254
255 void MEDPARTITIONERTest::verifyMedpartitionerOnSmallSizeForFieldOnGaussNe()
256 {
257   int res;
258   string fileName,cmd,execName,sourceName,targetName,input;
259   execName=getPartitionerParaExe();
260   fileName=_file_name;
261   fileName.replace(fileName.find(".med"),4,"_WithVecFieldOnGaussNe.med");
262
263   ParaMEDMEM::MEDFileUMesh* initialMesh=ParaMEDMEM::MEDFileUMesh::New(fileName.c_str(),_mesh_name.c_str());
264   ParaMEDMEM::MEDCouplingUMesh* cellMesh=initialMesh->getLevel0Mesh(false);
265
266   cmd="mpirun -np 5 "+execName+" --ndomains=5 --split-method=metis";  //on same proc
267   sourceName=fileName;
268   targetName=fileName;
269   targetName.replace(targetName.find(".med"),4,"_partitionedTo5_");
270   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
271   if (_verbose) cout<<endl<<cmd<<endl;
272   res=system(cmd.c_str());
273   CPPUNIT_ASSERT_EQUAL(0, res);
274   input=targetName+".xml";
275
276   //merge split meshes and test equality
277   cmd="mpirun -np 1 "+execName+" --ndomains=1 --split-method=metis";  //on same proc
278   sourceName=targetName+".xml";
279   targetName=fileName;
280   targetName.replace(targetName.find(".med"),4,"_remergedFrom5_");
281   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
282   if (_verbose) cout<<endl<<cmd<<endl;
283   res=system(cmd.c_str());
284   CPPUNIT_ASSERT_EQUAL(0, res);
285
286   string refusedName=targetName+"1.med";
287   ParaMEDMEM::MEDFileUMesh* refusedMesh=ParaMEDMEM::MEDFileUMesh::New(refusedName.c_str(),_mesh_name.c_str());
288   ParaMEDMEM::MEDCouplingUMesh* refusedCellMesh=refusedMesh->getLevel0Mesh(false);
289
290   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), refusedCellMesh->getNumberOfCells());
291
292   std::vector<const MEDCouplingUMesh *> meshes;
293   std::vector<DataArrayInt *> corr;
294   meshes.push_back(cellMesh);
295   refusedCellMesh->tryToShareSameCoordsPermute(*cellMesh, 1e-9);
296   meshes.push_back(refusedCellMesh);
297   MEDCouplingUMesh* fusedCell=MEDCouplingUMesh::FuseUMeshesOnSameCoords(meshes,0,corr);
298   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), fusedCell->getNumberOfCells());
299
300   MEDCouplingFieldDouble* field1=MEDLoader::ReadField(ON_GAUSS_NE,fileName.c_str(),initialMesh->getName().c_str(),0,"MyFieldOnGaussNE",5,6);
301   MEDCouplingFieldDouble* field2=MEDLoader::ReadField(ON_GAUSS_NE,refusedName.c_str(),refusedCellMesh->getName().c_str(),0,"MyFieldOnGaussNE",5,6);
302
303   int nbcells=corr[1]->getNumberOfTuples();
304   CPPUNIT_ASSERT_EQUAL(cellMesh->getNumberOfCells(), nbcells);
305   //use corr to test equality of field
306   DataArrayDouble* f1=field1->getArray();
307   DataArrayDouble* f2=field2->getArray();
308   if (_verbose>300)
309     {
310       cout << "\nf1 : " << f1->reprZip(); //123.4 for 12th cell,3rd component, 4th gausspoint
311       cout << "\nf2 : " << f2->reprZip(); //field2->advancedRepradvancedRepr();
312       for (std::size_t i = 0; i < corr.size(); i++)
313         cout << "\ncorr " << i << " : " << corr[i]->reprZip();
314
315     }
316   int nbequal=0;
317   int nbptgauss=8;
318   int nbcomp=field1->getNumberOfComponents();
319   double* p1=f1->getPointer();
320   double* p2=f2->getPointer();
321   int* pc=corr[1]->getPointer();
322   for (int i = 0; i < nbcells; i++)
323     {
324       int i1=pc[i]*nbcomp*nbptgauss;
325       int i2=i*nbcomp*nbptgauss;
326       for (int j = 0; j < nbcomp*nbptgauss; j++)
327         {
328           if (p1[i1+j]==p2[i2+j]) nbequal++;
329           //cout<<" "<<p1[i1+j]<<"="<<p2[i2+j];
330         }
331     }
332   CPPUNIT_ASSERT_EQUAL(nbcells*nbcomp*nbptgauss, nbequal);
333
334   for (std::size_t i = 0; i < corr.size(); i++)
335     corr[i]->decrRef();
336   field1->decrRef();
337   field2->decrRef();
338   fusedCell->decrRef();
339   refusedCellMesh->decrRef();
340   cellMesh->decrRef();
341 }
342
343 void MEDPARTITIONERTest::launchMedpartitionerOnTestMeshes()
344 {
345
346   /* examples
347      export INFI=/home/vb144235/resources/blade.med
348      //no need export MESH=Fuse_1
349      export INFI=tmp_testMeshxxx.med
350      //no need export MESH=testMesh
351      mpirun -np 2 medpartitioner_para --input-file=$INFI --output-file=ttmp1_ --ndomains=4
352      mpirun -np 5 medpartitioner_para --input-file=ttmp1_.xml --output-file=ttmp2_ --ndomains=5
353      mpirun -np 2 valgrind  medpartitioner_para --input-file=tmp_testMesh_20x30x50.med  --output-file=ttmp1petit_ --ndomains=4  --dump-cpu-memory --verbose=111
354   */
355   int res;
356   string cmd,execName,sourceName,targetName;
357
358   res=system("which mpirun 2>/dev/null 1>/dev/null"); //no trace
359   CPPUNIT_ASSERT_EQUAL(0, res);
360
361   execName=getPartitionerParaExe();
362
363   cmd="which "+execName+" 2>/dev/null 1>/dev/null";  //no trace
364   res=system(cmd.c_str());
365   CPPUNIT_ASSERT_EQUAL(0, res);
366
367   cmd="mpirun -np 2 "+execName+" --ndomains=2 --split-method=metis";  //on same proc
368   sourceName=_file_name;
369   targetName=_file_name;
370   targetName.replace(targetName.find(".med"),4,"_partitionedTo2_");
371   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
372   if (_verbose) cout<<endl<<cmd<<endl;
373   res=system(cmd.c_str());
374   CPPUNIT_ASSERT_EQUAL(0, res);
375
376   cmd="mpirun -np 3 "+execName+" --ndomains=5 --split-method=metis"; //on less proc
377   sourceName=_file_name;
378   targetName=_file_name;
379   targetName.replace(targetName.find(".med"),4,"_partitionedTo5_");
380   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
381   if (_verbose) cout<<endl<<cmd<<endl;
382   res=system(cmd.c_str());
383   CPPUNIT_ASSERT_EQUAL(0, res);
384
385   cmd="mpirun -np 1 "+execName+" --ndomains=1 --split-method=metis";  //on 1 proc
386   sourceName=targetName+".xml";
387   targetName=_file_name;
388   targetName.replace(targetName.find(".med"),4,"_remergedFrom5_");
389   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
390   if (_verbose) cout<<endl<<cmd<<endl;
391   res=system(cmd.c_str());
392   CPPUNIT_ASSERT_EQUAL(0, res);
393
394   cmd="mpirun -np 8 "+execName+" --ndomains=1 --split-method=metis";  //on more proc
395   //sourceName=targetName+".xml";
396   targetName=_file_name;
397   targetName.replace(targetName.find(".med"),4,"_remergedFrom5_");
398   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
399   if (_verbose) cout<<endl<<cmd<<endl;
400   res=system(cmd.c_str());
401   CPPUNIT_ASSERT_EQUAL(0, res);
402 }
403
404 void MEDPARTITIONERTest::launchMedpartitionerOnHugeTestMeshes()
405 {
406   int res=0;
407   string cmd,execName,sourceName,targetName;
408   execName=getPartitionerParaExe();
409
410   string snbTarget=IntToStr(_nb_target_huge);
411   cmd="mpirun -np "+snbTarget+" "+execName+" --ndomains="+snbTarget+" --split-method=metis";  //on same proc
412   sourceName=_file_name_huge_xml;
413   targetName=_file_name_huge_xml;
414   string tmp="_partitionedTo"+snbTarget+"_";
415   targetName.replace(targetName.find(".xml"),4,tmp);
416   cmd+=" --input-file="+sourceName+" --output-file="+targetName+" --verbose="+IntToStr(_verbose);
417   if (_verbose) cout<<endl<<cmd<<endl;
418   res=system(cmd.c_str());
419   CPPUNIT_ASSERT_EQUAL(0, res);
420 }
421
422 void MEDPARTITIONERTest::testMpirunSmallSize()
423 {
424   setSmallSize();
425   createTestMeshes();
426   launchMedpartitionerOnTestMeshes();
427   verifyMedpartitionerOnSmallSizeForMesh();
428   verifyMedpartitionerOnSmallSizeForFieldOnCells();
429   verifyMedpartitionerOnSmallSizeForFieldOnGaussNe();
430 }
431
432 void MEDPARTITIONERTest::testMpirunMedianSize()
433 {
434   setMedianSize();
435   createTestMeshes();
436   launchMedpartitionerOnTestMeshes();
437 }
438
439 void MEDPARTITIONERTest::testMpirunHugeSize()
440 {
441   //setBigSize(); //may be a lot for now
442   setMedianSize();
443   //create a set of nbx*nby*nbz files mesh of ni*ny*nz cells
444   //_verbose=1;
445   createHugeTestMesh(_ni, _nj, _nk, 2, 2, 2, 32); //it is now to know how far we are going to test
446   launchMedpartitionerOnHugeTestMeshes();
447 }
448 #endif