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