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