1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // File : ParaMEDSPLITTERTest_ParaDomainSelector.cxx
20 // Created : Tue Jul 21 16:25:50 2009
21 // Author : Edward AGAPOV (eap)
23 #include "ParaMEDSPLITTERTest.hxx"
24 #include "MEDSPLITTERTest_Utils.hxx"
26 #include "MEDSPLITTER_ParaDomainSelector.hxx"
27 #include "MEDSPLITTER_UserGraph.hxx"
28 #include "MEDSPLITTER_JointExchangeData.hxx"
29 #include "MEDSPLITTER_FaceModel.hxx"
31 #include <MEDMEM_Meshing.hxx>
32 #include <MEDMEM_Grid.hxx>
33 #include <MEDMEM_ConnectZone.hxx>
35 #include <cppunit/TestAssert.h>
39 using namespace MEDSPLITTER;
40 using namespace MED_EN;
42 //================================================================================
44 * \brief Test ParaDomainSelector::gatherGraph( graph )
46 //================================================================================
48 void ParaMEDSPLITTERTest::testParaDomainSelector_gatherGraph()
51 MPI_Comm_size(MPI_COMM_WORLD,&world_size);
53 if ( world_size != 2 )
56 // Combine two equal graphs:
58 // value: [ 1, 2, 1, 2, 3]
59 // partition: [ 0, 1 ]
62 // index: [ 1, 3, 6, 8, 11 ]
63 // value: [ 1, 2, 1, 2, 3, 1, 2, 1, 2, 3]
64 // partition: [ 0, 1, 0, 1 ]
66 ParaDomainSelector dom_sel;
67 CPPUNIT_ASSERT_NO_THROW( dom_sel.isOnDifferentHosts() );
69 cout << "On different hosts = " << dom_sel.isOnDifferentHosts() << endl;
72 // Let ParaDomainSelector know domain sizes
74 MEDMEM::MESHING meshing;
75 int nb_elems[] = { 2 }; medGeometryElement type = MED_POINT1;
76 meshing.setNumberOfTypes ( 1, MED_CELL );
77 meshing.setTypes ( &type, MED_CELL );
78 meshing.setNumberOfElements( nb_elems, MED_CELL );
80 vector<MEDMEM::MESH*> domain_meshes(2, (MEDMEM::MESH*)0);
81 domain_meshes[ dom_sel.rank() ] = &meshing;
82 dom_sel.gatherNbOf( MED_CELL, domain_meshes );
86 int index[] = { 1, 3, 6 };
87 int value[] = { 1, 2, 1, 2, 3 };
88 int* partition = new int[2];
89 partition[0]=0; partition[1] = 1;
90 MEDMEM::MEDSKYLINEARRAY* array = new MEDMEM::MEDSKYLINEARRAY( 2, 5, index, value);
91 auto_ptr<Graph> graph( new UserGraph( array, partition, 2 ));
95 auto_ptr<Graph> glob_graph( dom_sel.gatherGraph( graph.get() ));
97 const int* ind = glob_graph->getGraph()->getIndex();
98 const int* val = glob_graph->getGraph()->getValue();
99 const int* part= glob_graph->getPart();
101 CPPUNIT_ASSERT_EQUAL( 4, glob_graph->getGraph()->getNumberOf() );
102 CPPUNIT_ASSERT_EQUAL( index[0], ind[0] );
103 CPPUNIT_ASSERT_EQUAL( index[1], ind[1] );
104 CPPUNIT_ASSERT_EQUAL( index[2], ind[2] );
105 CPPUNIT_ASSERT_EQUAL( index[2]+ind[1]-ind[0], ind[3] );
106 CPPUNIT_ASSERT_EQUAL( index[2]+ind[2]-ind[0], ind[4] );
108 CPPUNIT_ASSERT_EQUAL( 10, glob_graph->getGraph()->getLength() );
109 CPPUNIT_ASSERT_EQUAL( value[0], val[0] );
110 CPPUNIT_ASSERT_EQUAL( value[1], val[1] );
111 CPPUNIT_ASSERT_EQUAL( value[2], val[2] );
112 CPPUNIT_ASSERT_EQUAL( value[3], val[3] );
113 CPPUNIT_ASSERT_EQUAL( value[4], val[4] );
114 CPPUNIT_ASSERT_EQUAL( value[0], val[5] );
115 CPPUNIT_ASSERT_EQUAL( value[1], val[6] );
116 CPPUNIT_ASSERT_EQUAL( value[2], val[7] );
117 CPPUNIT_ASSERT_EQUAL( value[3], val[8] );
118 CPPUNIT_ASSERT_EQUAL( value[4], val[9] );
120 CPPUNIT_ASSERT_EQUAL( partition[0], part[0] );
121 CPPUNIT_ASSERT_EQUAL( partition[1], part[1] );
122 CPPUNIT_ASSERT_EQUAL( partition[0], part[2] );
123 CPPUNIT_ASSERT_EQUAL( partition[1], part[3] );
126 //================================================================================
128 * \brief test ParaDomainSelector::gatherNbOf( entity, domain_meshes )
130 //================================================================================
132 void ParaMEDSPLITTERTest::testParaDomainSelector_gatherNbOf ()
135 MPI_Comm_size(MPI_COMM_WORLD,&world_size);
137 if ( world_size != 2 )
140 string filename = MEDSPLITTERTest_Utils::getResourceFile("square1_split1.med");
141 string meshname = "Mesh_2_1";
143 ParaDomainSelector dom_sel;
145 MEDMEM::MESH mesh_full( MEDMEM::MED_DRIVER, filename, meshname);
146 MEDMEM::MESH mesh_empty;
148 vector<MEDMEM::MESH*> meshes(2);
149 meshes[0] = & mesh_full;
150 meshes[1] = & mesh_empty;
151 if ( dom_sel.rank() > 0 )
152 swap( meshes[0], meshes[1] );
154 // test gatherNbOf( MED_CELL )
155 int nb_cells, init_nb_cells = mesh_full.getNumberOfElements( MED_CELL, MED_ALL_ELEMENTS );
156 CPPUNIT_ASSERT_NO_THROW( nb_cells = dom_sel.gatherNbOf( MED_CELL, meshes ));
157 CPPUNIT_ASSERT_EQUAL( 2 * init_nb_cells, nb_cells );
159 // test gatherNbOf( MED_EDGE )
160 int nb_edges, init_nb_edges = mesh_full.getNumberOfElements( MED_EDGE, MED_ALL_ELEMENTS );
161 CPPUNIT_ASSERT_NO_THROW( nb_edges = dom_sel.gatherNbOf( MED_EDGE, meshes ));
162 CPPUNIT_ASSERT_EQUAL( 2 * init_nb_edges, nb_edges );
164 // test getNbVertOfProcs()
165 int* nb_cell_by_proc;
166 CPPUNIT_ASSERT_NO_THROW( nb_cell_by_proc = dom_sel.getNbVertOfProcs() );
167 CPPUNIT_ASSERT_EQUAL( init_nb_cells, nb_cell_by_proc[1]-nb_cell_by_proc[0] );
168 CPPUNIT_ASSERT_EQUAL( init_nb_cells, nb_cell_by_proc[2]-nb_cell_by_proc[1] );
170 // test getProcShift()
171 if ( dom_sel.rank() == 0 )
172 CPPUNIT_ASSERT_EQUAL( 0, dom_sel.getProcShift() );
174 CPPUNIT_ASSERT_EQUAL( init_nb_cells, dom_sel.getProcShift() );
176 CPPUNIT_ASSERT_EQUAL( 0, dom_sel.getDomainShift(0) );
177 CPPUNIT_ASSERT_EQUAL( init_nb_cells, dom_sel.getDomainShift(1) );
180 //================================================================================
182 * \brief Test ParaDomainSelector::gatherEntityTypesInfo( domain_meshes, entity )
184 //================================================================================
186 void ParaMEDSPLITTERTest::testParaDomainSelector_gatherEntityTypesInfo ()
189 MPI_Comm_size(MPI_COMM_WORLD,&world_size);
191 if ( world_size != 2 )
194 string filename = MEDSPLITTERTest_Utils::getResourceFile("square1_split1.med");
195 string meshname = "Mesh_2_1";
197 ParaDomainSelector dom_sel;
199 MEDMEM::MESH mesh_full( MEDMEM::MED_DRIVER, filename, meshname);
200 MEDMEM::MESH mesh_empty;
202 vector<MEDMEM::MESH*> meshes(2);
203 meshes[0] = & mesh_full;
204 meshes[1] = & mesh_empty;
205 if ( dom_sel.rank() > 0 )
206 swap( meshes[0], meshes[1] );
212 const medGeometryElement * init_cell_types = mesh_full.getTypes (MED_CELL);
213 const int * init_cell_nb_index = mesh_full.getGlobalNumberingIndex(MED_CELL);
214 int nb_init_cell_types = mesh_full.getNumberOfTypes (MED_CELL);
216 // pass info on cell types from mesh_full on other proc to mesh_empty on this proc
217 CPPUNIT_ASSERT_NO_THROW( dom_sel.gatherEntityTypesInfo( meshes, MED_CELL ));
219 const medGeometryElement * got_cell_types = mesh_empty.getTypes (MED_CELL);
220 const int * got_cell_nb_index = mesh_empty.getGlobalNumberingIndex(MED_CELL);
221 int nb_got_cell_types = mesh_empty.getNumberOfTypes (MED_CELL);
223 // check that we got the same info
224 CPPUNIT_ASSERT_EQUAL( nb_init_cell_types, nb_got_cell_types);
225 CPPUNIT_ASSERT_EQUAL( nb_init_cell_types, mesh_full.getNumberOfTypes(MED_CELL));
226 CPPUNIT_ASSERT_EQUAL( init_cell_types, mesh_full.getTypes (MED_CELL));
227 for ( int i = 0; i < nb_got_cell_types; ++i )
229 CPPUNIT_ASSERT_EQUAL( init_cell_types[i], got_cell_types[i] );
230 CPPUNIT_ASSERT_EQUAL( mesh_full.getNumberOfElements(MED_CELL, MED_ALL_ELEMENTS ),
231 mesh_empty.getNumberOfElements(MED_CELL, MED_ALL_ELEMENTS ));
232 CPPUNIT_ASSERT_EQUAL( init_cell_nb_index[ i+1 ], got_cell_nb_index[ i+1 ]);
235 // test for faces - there are no faces
236 CPPUNIT_ASSERT_THROW( dom_sel.gatherEntityTypesInfo( meshes, MED_FACE ), MED_EXCEPTION);
242 const medGeometryElement * init_edge_types = mesh_full.getTypes (MED_EDGE);
243 const int * init_edge_nb_index = mesh_full.getGlobalNumberingIndex(MED_EDGE);
244 int nb_init_edge_types = mesh_full.getNumberOfTypes (MED_EDGE);
246 // pass info on edge types from mesh_full on other proc to mesh_empty on this proc
247 CPPUNIT_ASSERT_NO_THROW( dom_sel.gatherEntityTypesInfo( meshes, MED_EDGE ));
249 const medGeometryElement * got_edge_types = mesh_empty.getTypes (MED_EDGE);
250 const int * got_edge_nb_index = mesh_empty.getGlobalNumberingIndex(MED_EDGE);
251 int nb_got_edge_types = mesh_empty.getNumberOfTypes (MED_EDGE);
253 // check that we got the same info
254 CPPUNIT_ASSERT_EQUAL( nb_init_edge_types, nb_got_edge_types);
255 CPPUNIT_ASSERT_EQUAL( nb_init_edge_types, mesh_full.getNumberOfTypes(MED_EDGE));
256 CPPUNIT_ASSERT_EQUAL( init_edge_types, mesh_full.getTypes (MED_EDGE));
257 for ( int i = 0; i < nb_got_edge_types; ++i )
259 CPPUNIT_ASSERT_EQUAL( init_edge_types[i], got_edge_types[i] );
260 CPPUNIT_ASSERT_EQUAL( mesh_full.getNumberOfElements(MED_EDGE, MED_ALL_ELEMENTS ),
261 mesh_empty.getNumberOfElements(MED_EDGE, MED_ALL_ELEMENTS ));
262 CPPUNIT_ASSERT_EQUAL( init_edge_nb_index[ i+1 ], got_edge_nb_index[ i+1 ]);
266 void ParaMEDSPLITTERTest::testParaDomainSelector_gatherNbCellPairs ()
269 MPI_Comm_size(MPI_COMM_WORLD,&world_size);
271 if ( world_size != 2 )
274 ParaDomainSelector dom_sel;
275 CPPUNIT_ASSERT_EQUAL( 2, dom_sel.nbProcs() );
277 // imagine we have 5 domains
278 const int nb_domains = 5;
279 dom_sel.setNbDomains(nb_domains);
281 // ----------------------------------------
282 // test isMyDomain() and getProccessorID()
283 // ----------------------------------------
285 for ( int idomain = 0; idomain < nb_domains; ++idomain )
286 if ( dom_sel.isMyDomain( idomain ))
288 doms_here.insert( idomain );
289 CPPUNIT_ASSERT_EQUAL( dom_sel.getProccessorID( idomain ), dom_sel.rank() );
291 CPPUNIT_ASSERT( doms_here.size() == 2 || doms_here.size() == 3 );
297 set< pair< int, int> > dom_pairs;
298 for ( int idom1 = 0; idom1 < nb_domains; ++idom1 )
299 for ( int idom2 = 0; idom2 < nb_domains; ++idom2 )
300 if ( idom1 != idom2 )
302 joint_ids.insert( dom_sel.jointId( idom1, idom2 ));
303 dom_pairs.insert( idom1 < idom2 ? make_pair( idom1, idom2 ) : make_pair( idom2, idom1 ));
305 CPPUNIT_ASSERT_EQUAL( dom_pairs.size(), joint_ids.size() );
307 // -------------------------
308 // test gatherNbCellPairs()
309 // -------------------------
311 int nb_interproc_pairs = 0, nb_local_pairs = 0, total_joint_size = 0;
312 for ( int idom1 = 0; idom1 < nb_domains; ++idom1 )
313 for ( int idom2 = idom1+1; idom2 < nb_domains; ++idom2 )
315 // gather data for further checks
316 int nb_doms_here = doms_here.count( idom1 ) + doms_here.count( idom2 );
317 bool is_inter_proc = ( nb_doms_here == 1 );
318 bool is_local = ( nb_doms_here%2 == 0 );
319 int nb_pairs = dom_sel.jointId( idom1, idom2 );
320 total_joint_size += nb_pairs;
321 if ( is_inter_proc ) nb_interproc_pairs += nb_pairs;
322 if ( is_local ) nb_local_pairs += nb_pairs;
323 if ( nb_doms_here == 0 || idom1 == idom2 ) continue;
324 // set data to ParaDomainSelector
325 if ( is_inter_proc && doms_here.count( idom1 ) ||
326 is_local && nb_doms_here == 2 )
328 dom_sel.setNbCellPairs( nb_pairs, idom1, idom2 );
331 dom_sel.gatherNbCellPairs();
332 //CPPUNIT_ASSERT_EQUAL( nb_local_pairs, dom_sel.getNbSubentitiesWithoutProcJoints() );
334 for ( int idom1 = 0; idom1 < nb_domains; ++idom1 )
335 for ( int idom2 = 0; idom2 < nb_domains; ++idom2 )
337 //int nb_doms_here = doms_here.count( idom1 ) + doms_here.count( idom2 );
338 int nb_pairs_expect = dom_sel.jointId( idom1, idom2 );
339 if ( int nb_pairs = dom_sel.getNbCellPairs( idom1, idom2 ))
341 CPPUNIT_ASSERT_EQUAL( nb_pairs_expect, nb_pairs );
342 int fisrt_id = dom_sel.getFisrtGlobalIdOfSubentity( idom1, idom2 );
343 CPPUNIT_ASSERT(0 < fisrt_id && fisrt_id <= total_joint_size);
348 //================================================================================
350 * \brief Test work of JointExchangeData and of ParaDomainSelector::exchangeJoint(joint)
352 //================================================================================
354 void ParaMEDSPLITTERTest::testParaDomainSelector_exchangeJoint ()
357 MPI_Comm_size(MPI_COMM_WORLD,&world_size);
359 if ( world_size != 2 )
362 ParaDomainSelector dom_sel;
364 // Exchange a joint between two grids with following global ids
376 // make grids; actually we make one grid as their connectivities are same and
377 // coordinates doesn't matter here
378 const MEDMEM::MESH* grid = 0;
381 vector<vector<double> > xyz_array(dim);
382 vector<string> coord_name(dim,"coo");
383 vector<string> unit(dim,"m");
385 xyz_array[0].resize(2, 0.);
386 xyz_array[1].resize(3, 0.);
387 MEDMEM::GRID tmpGrid( xyz_array, coord_name, unit );
388 grid = tmpGrid.convertInMESH();
392 int cells1[] = { 1, 2 };
393 int cells2[] = { 3, 4 };
394 int nodes1[] = { 1, 2, 3, 4, 5, 6 };
395 int nodes2[] = { 2, 7, 4, 8, 6, 9 };
396 int* cells_here = dom_sel.rank() ? cells2 : cells1;
397 int* cells_dist = dom_sel.rank() ? cells2 : cells1;
398 int* nodes_here = dom_sel.rank() ? nodes2 : nodes1;
399 //int* nodes_dist = dom_sel.rank() ? nodes2 : nodes1;
401 int dom_here = dom_sel.isMyDomain( 0 ) ? 0 : 1;
402 int dom_dist = 1 - dom_here;
404 // store cell/cell correspondencies
405 JointExchangeData joint;
406 joint.addCellCorrespondence( grid, dom_dist, dom_here, cells_dist[0], cells_here[0], 1 );
407 joint.addCellCorrespondence( grid, dom_dist, dom_here, cells_dist[1], cells_here[1], 2 );
408 CPPUNIT_ASSERT_EQUAL( 2, joint.nbCellPairs());
410 // prepare to exchangeJoint()
411 joint.setMeshes( dom_dist, grid, dom_here, grid );
412 CPPUNIT_ASSERT_EQUAL( dom_dist, joint.distantDomain() );
413 CPPUNIT_ASSERT_EQUAL( dom_here, joint.localDomain() );
415 joint.setConnectivity( nodes_here );
416 // in general case we woul need to call dom_sel.gatherEntityTypesInfo() but grid
417 // knows nb of elements without connectivity initialization
418 CPPUNIT_ASSERT_THROW( dom_sel.exchangeJoint( & joint ), MED_EXCEPTION);
419 dom_sel.setNbDomains( 2 );
420 dom_sel.setNbCellPairs( 2, dom_dist, dom_here );
421 dom_sel.gatherNbCellPairs();
422 CPPUNIT_ASSERT_NO_THROW( dom_sel.exchangeJoint( & joint ));
425 const int joint_edge_glob_id = 100;
426 joint.setFisrtGlobalIdOfSubentity( joint_edge_glob_id );
427 TGeom2FacesByDomian face_map(2);
428 auto_ptr<MEDMEM::CONNECTZONE> cz( joint.makeConnectZone(face_map));
429 CPPUNIT_ASSERT( cz.get() );
435 CPPUNIT_ASSERT_EQUAL( dom_dist, cz->getDistantDomainNumber() );
436 CPPUNIT_ASSERT_EQUAL( dom_here, cz->getLocalDomainNumber() );
438 CPPUNIT_ASSERT_EQUAL( long(grid), long(cz->getLocalMesh()) );
439 CPPUNIT_ASSERT_EQUAL( long(grid), long(cz->getDistantMesh()) );
441 CPPUNIT_ASSERT( cz->isEntityCorrespPresent(MED_CELL, MED_CELL) );
442 CPPUNIT_ASSERT( !cz->isEntityCorrespPresent(MED_NODE, MED_NODE) );
443 CPPUNIT_ASSERT( !cz->isEntityCorrespPresent(MED_EDGE, MED_EDGE) );
444 CPPUNIT_ASSERT( !cz->isEntityCorrespPresent(MED_FACE, MED_FACE) );
446 CPPUNIT_ASSERT_EQUAL( 3, cz->getNodeNumber() );
447 CPPUNIT_ASSERT_EQUAL( 2, cz->getEntityCorrespNumber(MED_CELL,MED_CELL));
449 const int * node_index = cz->getNodeCorrespIndex();
450 CPPUNIT_ASSERT(node_index);
451 for ( int i = 0; i < 4; ++i )
452 CPPUNIT_ASSERT_EQUAL( i + 1, node_index[ i ]);
454 const int * node_value = cz->getNodeCorrespValue();
455 CPPUNIT_ASSERT(node_value);
456 int val[2][6] = {{ 2, 1, 4, 3, 6, 5 },
457 { 1, 2, 3, 4, 5, 6 }}; // local ids of neighbouring domain
458 for ( int i = 0; i < 6; ++i )
459 CPPUNIT_ASSERT_EQUAL( val[ dom_sel.rank()][ i ], node_value[ i ]);
461 const int * cell_index = cz->getEntityCorrespIndex(MED_CELL, MED_CELL);
462 CPPUNIT_ASSERT(cell_index);
463 for ( int i = 0; i < 3; ++i )
464 CPPUNIT_ASSERT_EQUAL( i + 1, cell_index[ i ]);
466 const int * cell_value = cz->getEntityCorrespValue(MED_CELL, MED_CELL);
467 CPPUNIT_ASSERT(cell_value);
468 CPPUNIT_ASSERT_EQUAL( 1, cell_value[ 0 ]);
469 CPPUNIT_ASSERT_EQUAL( 2, cell_value[ 1 ]);
471 CPPUNIT_ASSERT_EQUAL( 1, int( face_map[ dom_sel.rank() ].size() ));
472 CPPUNIT_ASSERT_EQUAL( 0, int( face_map[ 1 - dom_sel.rank() ].size() ));
473 CPPUNIT_ASSERT_EQUAL( MED_SEG2, face_map[ dom_sel.rank() ].begin()->first );
475 vector< MEDSPLITTER_FaceModel* >& faces = face_map[ dom_sel.rank() ][ MED_SEG2 ];
476 CPPUNIT_ASSERT_EQUAL( 2, int( faces.size() ));
477 CPPUNIT_ASSERT_EQUAL( MED_SEG2, faces[0]->getType());
478 CPPUNIT_ASSERT_EQUAL( joint_edge_glob_id+0, faces[0]->getGlobal());
479 CPPUNIT_ASSERT_EQUAL( joint_edge_glob_id+1, faces[1]->getGlobal());
481 CPPUNIT_ASSERT_EQUAL( dom_sel.rank() ? 1 : 4, (*faces[0])[0]);
482 CPPUNIT_ASSERT_EQUAL( dom_sel.rank() ? 3 : 2, (*faces[0])[1]);
483 CPPUNIT_ASSERT_EQUAL( dom_sel.rank() ? 3 : 6, (*faces[1])[0]);
484 CPPUNIT_ASSERT_EQUAL( dom_sel.rank() ? 5 : 4, (*faces[1])[1]);
486 grid->removeReference();
489 //================================================================================
491 * \brief Test ParaDomainSelector::exchangeSubentityIds()
493 //================================================================================
495 void ParaMEDSPLITTERTest::testParaDomainSelector_exchangeSubentityIds ()
498 MPI_Comm_size(MPI_COMM_WORLD,&world_size);
500 if ( world_size != 2 )
503 ParaDomainSelector dom_sel;
504 vector<int> loc_ids_here(3, -373);
507 ( dom_sel.exchangeSubentityIds( dom_sel.rank(), 1-dom_sel.rank(), loc_ids_here),MED_EXCEPTION);
508 dom_sel.setNbDomains( 2 );
509 CPPUNIT_ASSERT_NO_THROW
510 ( got_ids = dom_sel.exchangeSubentityIds( dom_sel.rank(), 1-dom_sel.rank(), loc_ids_here));
511 CPPUNIT_ASSERT_EQUAL( loc_ids_here[0], got_ids[0] );
512 CPPUNIT_ASSERT_EQUAL( loc_ids_here[1], got_ids[1] );
513 CPPUNIT_ASSERT_EQUAL( loc_ids_here[2], got_ids[2] );