Branch data Line data Source code
1 : : #include "iMeshP.h"
2 : : #include "moab_mpi.h"
3 : : #include <iostream>
4 : : #include <algorithm>
5 : : #include <vector>
6 : : #include <sstream>
7 : : #include <assert.h>
8 : : #include <math.h>
9 : : #include <map>
10 : : #include <string.h>
11 : : #include <stdio.h> // remove()
12 : :
13 : : #if !defined( _MSC_VER ) && !defined( __MINGW32__ )
14 : : #include <unistd.h>
15 : : #endif
16 : :
17 : : #define STRINGIFY_( X ) #X
18 : : #define STRINGIFY( X ) STRINGIFY_( X )
19 : : const char* const FILENAME = "iMeshP_test_file";
20 : :
21 : : /**************************************************************************
22 : : Error Checking
23 : : **************************************************************************/
24 : :
25 : : #define CHKERR \
26 : : do \
27 : : { \
28 : : if( ierr ) \
29 : : { \
30 : : std::cerr << "Error code " << ierr << " at " << __FILE__ << ":" << __LINE__ << std::endl; \
31 : : return ierr; \
32 : : } \
33 : : } while( false )
34 : :
35 : : #define PCHECK \
36 : : do \
37 : : { \
38 : : ierr = is_any_proc_error( ierr ); \
39 : : CHKERR; \
40 : : } while( false )
41 : :
42 : : // Use my_rank instead of rank to avoid shadowed declaration
43 : : #define ASSERT( A ) \
44 : : do \
45 : : { \
46 : : if( is_any_proc_error( !( A ) ) ) \
47 : : { \
48 : : int my_rank = 0; \
49 : : MPI_Comm_rank( MPI_COMM_WORLD, &my_rank ); \
50 : : if( 0 == my_rank ) \
51 : : std::cerr << "Failed assertion: " #A << std::endl << " at " __FILE__ ":" << __LINE__ << std::endl; \
52 : : return 1; \
53 : : } \
54 : : } while( false )
55 : :
56 : : // Test if is_my_error is non-zero on any processor in MPI_COMM_WORLD
57 : 216 : int is_any_proc_error( int is_my_error )
58 : : {
59 : : int result;
60 [ + - ]: 216 : int err = MPI_Allreduce( &is_my_error, &result, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD );
61 [ + - ][ - + ]: 216 : return err || result;
62 : : }
63 : :
64 : : /**************************************************************************
65 : : Test Declarations
66 : : **************************************************************************/
67 : :
68 : : class PartMap;
69 : :
70 : : /**\brief Consistency check for parallel load
71 : : *
72 : : * All other tests depend on this one.
73 : : */
74 : : int test_load( iMesh_Instance, iMeshP_PartitionHandle prtn, PartMap& map, int comm_size );
75 : :
76 : : /**\brief Test partition query methods
77 : : *
78 : : * Test:
79 : : * - iMeshP_getPartitionComm
80 : : * - iMeshP_getNumPartitions
81 : : * - iMeshP_getPartitions
82 : : */
83 : : int test_get_partitions( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
84 : :
85 : : /**\brief Test part quyery methods
86 : : *
87 : : * Test:
88 : : * - iMeshP_getNumGlobalParts
89 : : * - iMeshP_getNumLocalParts
90 : : * - iMeshP_getLocalParts
91 : : */
92 : : int test_get_parts( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
93 : :
94 : : /**\brief Test query by entity type
95 : : *
96 : : * Test:
97 : : * - iMeshP_getNumOfTypeAll
98 : : * - iMeshP_getNumOfType
99 : : * - iMeshP_getEntities
100 : : * -
101 : : */
102 : : int test_get_by_type( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
103 : :
104 : : /**\brief Test query by entity topology
105 : : *
106 : : * Test:
107 : : * - iMeshP_getNumOfTopoAll
108 : : * - iMeshP_getNumOfTopo
109 : : * - iMeshP_getEntities
110 : : * -
111 : : */
112 : : int test_get_by_topo( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
113 : :
114 : : /**\brief Test mapping from part id to part handle
115 : : *
116 : : * Test:
117 : : * - iMeshP_getPartIdFromPartHandle
118 : : * - iMeshP_getPartIdsFromPartHandlesArr
119 : : * - iMeshP_getPartHandleFromPartId
120 : : * - iMeshP_getPartHandlesFromPartsIdsArr
121 : : * - iMeshP_getRankOfPart
122 : : * - iMeshP_getRankOfPartArr
123 : : */
124 : : int test_part_id_handle( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
125 : :
126 : : /**\brief Test get part rank
127 : : *
128 : : * Tests:
129 : : * - iMeshP_getRankOfPart
130 : : * - iMeshP_getRankOfPartArr
131 : : */
132 : : int test_part_rank( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
133 : :
134 : : /**\brief Test querying of part neighbors
135 : : *
136 : : * Test:
137 : : * - iMeshP_getNumPartNbors
138 : : * - iMeshP_getNumPartNborsArr
139 : : * - iMeshP_getPartNbors
140 : : * - iMeshP_getPartNborsArr
141 : : */
142 : : int test_get_neighbors( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
143 : :
144 : : /**\brief Test querying of part boundary entities
145 : : *
146 : : * Test:
147 : : * - iMeshP_getNumPartBdryEnts
148 : : * - iMeshP_getPartBdryEnts
149 : : */
150 : : int test_get_part_boundary( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
151 : :
152 : : /**\brief Test querying of part boundary entities
153 : : *
154 : : * Test:
155 : : * - iMeshP_initPartBdryEntIter
156 : : * - iMeshP_initPartBdryEntArrIter
157 : : */
158 : : int test_part_boundary_iter( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
159 : :
160 : : /**\brief Test adjacent entity query
161 : : *
162 : : * Test:
163 : : * - iMeshP_getAdjEntities
164 : : */
165 : : int test_get_adjacencies( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
166 : :
167 : : /**\brief Test entity iterators
168 : : *
169 : : * Test:
170 : : * - iMeshP_initEntIter
171 : : * - iMeshP_initEntArrIter
172 : : */
173 : : int test_entity_iterator( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
174 : :
175 : : /**\brief Test entity owner queries
176 : : *
177 : : * Test:
178 : : * - iMeshP_getEntOwnerPart
179 : : * - iMeshP_getEntOwnerPartArr
180 : : * - iMeshP_isEntOwner
181 : : * - iMeshP_isEntOwnerArr
182 : : */
183 : : int test_entity_owner( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
184 : :
185 : : /**\brief Test entity status
186 : : *
187 : : * Test:
188 : : * - iMeshP_getEntStatus
189 : : * - iMeshP_getEntStatusArr
190 : : */
191 : : int test_entity_status( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
192 : :
193 : : /**\brief Test information about entity copies for interface entities
194 : : *
195 : : * Test:
196 : : * - iMeshP_getNumCopies
197 : : * - iMeshP_getCopyParts
198 : : */
199 : : int test_entity_copy_parts( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
200 : :
201 : : /**\brief Test information about entity copies for interface entities
202 : : *
203 : : * Test:
204 : : * - iMeshP_getCopies
205 : : * - iMeshP_getCopyOnPart
206 : : * - iMeshP_getOwnerCopy
207 : : */
208 : : int test_entity_copies( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
209 : :
210 : : /**\brief Test creation of ghost entities
211 : : *
212 : : * Test:
213 : : * - iMeshP_createGhostEntsAll
214 : : */
215 : : int test_create_ghost_ents( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
216 : :
217 : : /**\brief Test commuinication of tag data
218 : : *
219 : : * Test:
220 : : * - iMeshP_pushTags
221 : : * - iMeshP_pushTagsEnt
222 : : */
223 : : int test_push_tag_data_iface( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
224 : : int test_push_tag_data_ghost( iMesh_Instance, iMeshP_PartitionHandle prtn, const PartMap& );
225 : :
226 : : int test_exchange_ents( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map );
227 : :
228 : : /**************************************************************************
229 : : Helper Funcions
230 : : **************************************************************************/
231 : :
232 [ + - ][ + - ]: 57 : class PartMap
[ + - ]
233 : : {
234 : : public:
235 : 4 : int num_parts() const
236 : : {
237 : 4 : return sortedPartList.size();
238 : : }
239 : :
240 : 1 : iMeshP_Part part_id_from_local_id( int local_id ) const
241 : : {
242 : 1 : return sortedPartList[idx_from_local_id( local_id )];
243 : : }
244 : :
245 : 0 : int local_id_from_part_id( iMeshP_Part part ) const
246 : : {
247 : 0 : return partLocalIds[idx_from_part_id( part )];
248 : : }
249 : :
250 : : int rank_from_part_id( iMeshP_Part part ) const
251 : : {
252 : : return partRanks[idx_from_part_id( part )];
253 : : }
254 : :
255 : : int rank_from_local_id( int id ) const
256 : : {
257 : : return partRanks[idx_from_local_id( id )];
258 : : }
259 : :
260 : 1 : int count_from_rank( int rank ) const
261 : : {
262 : 1 : return std::count( partRanks.begin(), partRanks.end(), rank );
263 : : }
264 : :
265 : : void part_id_from_rank( int rank, std::vector< iMeshP_Part >& parts ) const;
266 : :
267 : : void local_id_from_rank( int rank, std::vector< int >& ids ) const;
268 : :
269 : 15 : const std::vector< iMeshP_Part >& get_parts() const
270 : : {
271 : 15 : return sortedPartList;
272 : : }
273 : :
274 : 2 : const std::vector< int >& get_ranks() const
275 : : {
276 : 2 : return partRanks;
277 : : }
278 : :
279 : : int build_map( iMesh_Instance imesh, iMeshP_PartitionHandle partition, int num_expected_parts );
280 : :
281 : : static int part_from_coords( iMesh_Instance imesh, iMeshP_PartHandle part, int& id_out );
282 : :
283 : : private:
284 : 0 : inline int idx_from_part_id( iMeshP_Part id ) const
285 : : {
286 [ # # ][ # # ]: 0 : return std::lower_bound( sortedPartList.begin(), sortedPartList.end(), id ) - sortedPartList.begin();
287 : : }
288 : 1 : inline int idx_from_local_id( int id ) const
289 : : {
290 : 1 : return localIdReverseMap[id];
291 : : }
292 : :
293 : : std::vector< iMeshP_Part > sortedPartList;
294 : : std::vector< int > partRanks;
295 : : std::vector< int > partLocalIds;
296 : : std::vector< int > localIdReverseMap;
297 : : };
298 : :
299 : : /**\brief Create mesh for use in parallel tests */
300 : : int create_mesh( const char* filename, int num_parts );
301 : :
302 : : int create_mesh_in_memory( int rank, int size, iMesh_Instance imesh, iMeshP_PartitionHandle& prtn, PartMap& map );
303 : :
304 : : /**\brief get unique identifier for each vertex */
305 : : int vertex_tag( iMesh_Instance imesh, iBase_EntityHandle vertex, int& tag );
306 : :
307 : 28 : int get_local_parts( iMesh_Instance instance, iMeshP_PartitionHandle prtn, std::vector< iMeshP_PartHandle >& handles,
308 : : std::vector< iMeshP_Part >* ids = 0 )
309 : : {
310 : 28 : iMeshP_PartHandle* arr = 0;
311 : 28 : int ierr, alloc = 0, size;
312 [ + - ][ - + ]: 28 : iMeshP_getLocalParts( instance, prtn, &arr, &alloc, &size, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
313 [ + - ]: 28 : handles.resize( size );
314 [ + - ]: 28 : std::copy( arr, arr + size, handles.begin() );
315 : 28 : free( arr );
316 [ + + ]: 28 : if( !ids ) return iBase_SUCCESS;
317 : :
318 [ + - ]: 23 : ids->resize( size );
319 : 23 : alloc = size;
320 [ + - ]: 23 : iMeshP_Part* ptr = &( *ids )[0];
321 [ + - ][ + - ]: 23 : iMeshP_getPartIdsFromPartHandlesArr( instance, prtn, &handles[0], handles.size(), &ptr, &alloc, &size, &ierr );CHKERR;
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
322 [ - + ]: 23 : assert( size == (int)ids->size() );
323 [ + - ][ - + ]: 23 : assert( ptr == &( *ids )[0] );
324 : 28 : return iBase_SUCCESS;
325 : : }
326 : :
327 : 19 : static int get_entities( iMesh_Instance imesh, iBase_EntitySetHandle set, iBase_EntityType type,
328 : : iMesh_EntityTopology topo, std::vector< iBase_EntityHandle >& entities )
329 : : {
330 : 19 : iBase_EntityHandle* array = 0;
331 : 19 : int junk = 0, size = 0, err;
332 [ + - ]: 19 : iMesh_getEntities( imesh, set, type, topo, &array, &junk, &size, &err );
333 [ + - ]: 19 : if( !err )
334 : : {
335 : 19 : entities.clear();
336 [ + - ]: 19 : entities.resize( size );
337 [ + - ]: 19 : std::copy( array, array + size, entities.begin() );
338 : 19 : free( array );
339 : : }
340 : 19 : return err;
341 : : }
342 : :
343 : 3 : static int get_part_quads_and_verts( iMesh_Instance imesh, iMeshP_PartHandle part,
344 : : std::vector< iBase_EntityHandle >& elems,
345 : : std::vector< iBase_EntityHandle >& verts )
346 : : {
347 [ + - ][ - + ]: 3 : int ierr = get_entities( imesh, part, iBase_FACE, iMesh_QUADRILATERAL, elems );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
348 : :
349 [ + - ]: 3 : verts.resize( 4 * elems.size() );
350 [ + - ]: 3 : std::vector< int > junk( elems.size() + 1 );
351 : 3 : int junk1 = verts.size(), count, junk2 = junk.size(), junk3;
352 [ + - ]: 3 : iBase_EntityHandle* junk4 = &verts[0];
353 [ + - ]: 3 : int* junk5 = &junk[0];
354 [ + - ]: 3 : iMesh_getEntArrAdj( imesh, &elems[0], elems.size(), iBase_VERTEX, &junk4, &junk1, &count, &junk5, &junk2, &junk3,
355 [ + - ][ - + ]: 3 : &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
356 [ - + ]: 3 : assert( junk1 == (int)verts.size() );
357 [ - + ]: 3 : assert( count == (int)( 4 * elems.size() ) );
358 [ - + ]: 3 : assert( junk2 == (int)junk.size() );
359 [ + - ][ - + ]: 3 : assert( junk4 == &verts[0] );
360 [ + - ][ - + ]: 3 : assert( junk5 == &junk[0] );
361 [ + - ]: 3 : std::sort( verts.begin(), verts.end() );
362 [ + - ][ + - ]: 3 : verts.erase( std::unique( verts.begin(), verts.end() ), verts.end() );
363 : 3 : return iBase_SUCCESS;
364 : : }
365 : :
366 : 1 : static int get_coords( iMesh_Instance imesh, const iBase_EntityHandle* verts, int num_verts, double* coords )
367 : : {
368 : 1 : double* junk1 = coords;
369 : 1 : int junk2 = 3 * num_verts;
370 : : int junk3;
371 : : int ierr;
372 [ + - ]: 1 : iMesh_getVtxArrCoords( imesh, verts, num_verts, iBase_INTERLEAVED, &junk1, &junk2, &junk3, &ierr );
373 [ - + ]: 1 : if( iBase_SUCCESS != ierr ) return ierr;
374 [ - + ]: 1 : assert( junk1 == coords );
375 [ - + ]: 1 : assert( junk2 == 3 * num_verts );
376 [ - + ]: 1 : assert( junk3 == 3 * num_verts );
377 : 1 : return iBase_SUCCESS;
378 : : }
379 : :
380 : : /**************************************************************************
381 : : Main Method
382 : : **************************************************************************/
383 : :
384 : : #define RUN_TEST( A ) run_test( &A, #A )
385 : :
386 : 19 : int run_test( int ( *func )( iMesh_Instance, iMeshP_PartitionHandle, const PartMap& ), const char* func_name )
387 : : {
388 : : int rank, size, ierr;
389 [ + - ]: 19 : MPI_Comm_rank( MPI_COMM_WORLD, &rank );
390 [ + - ]: 19 : MPI_Comm_size( MPI_COMM_WORLD, &size );
391 : : iMesh_Instance imesh;
392 [ + - ]: 19 : iMesh_newMesh( 0, &imesh, &ierr, 0 );
393 [ + - ][ - + ]: 19 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
394 : :
395 : : iMeshP_PartitionHandle prtn;
396 [ + - ]: 19 : iMeshP_createPartitionAll( imesh, MPI_COMM_WORLD, &prtn, &ierr );
397 [ + - ][ - + ]: 19 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
398 : :
399 [ + - ]: 19 : PartMap map;
400 : :
401 : : #ifdef MOAB_HAVE_HDF5
402 [ + - ][ + - ]: 19 : if( rank == 0 ) { ierr = create_mesh( FILENAME, size ); }
403 [ + - ]: 19 : MPI_Bcast( &ierr, 1, MPI_INT, 0, MPI_COMM_WORLD );
404 [ - + ]: 19 : if( ierr )
405 : : {
406 [ # # ][ # # ]: 0 : if( rank == 0 ) { std::cerr << "Failed to create input test file on root processor. Aborting." << std::endl; }
[ # # ]
407 : 0 : abort();
408 : : }
409 : :
410 [ + - ]: 19 : ierr = test_load( imesh, prtn, map, size );
411 [ - + ]: 19 : if( ierr )
412 : : {
413 [ # # ]: 0 : if( rank == 0 )
414 : : {
415 [ # # ][ # # ]: 0 : std::cerr << "Failed to load input mesh." << std::endl
416 [ # # ][ # # ]: 0 : << "Cannot run further tests." << std::endl
417 [ # # ][ # # ]: 0 : << "ABORTING" << std::endl;
418 : : }
419 : 0 : abort();
420 : : }
421 : : #else
422 : : // so we have MPI and no HDF5; in order to run the test we need to create the
423 : : // model in memory, and then call sync to resolve shared ents, as if it was read
424 : : ierr = create_mesh_in_memory( rank, size, imesh, prtn, map );
425 : : MPI_Bcast( &ierr, 1, MPI_INT, 0, MPI_COMM_WORLD );
426 : : if( ierr )
427 : : {
428 : : if( rank == 0 ) { std::cerr << "Failed to create mesh. Aborting." << std::endl; }
429 : : abort();
430 : : }
431 : :
432 : : #endif
433 [ + - ]: 19 : int result = ( *func )( imesh, prtn, map );
434 [ + - ]: 19 : int is_err = is_any_proc_error( result );
435 [ + - ]: 19 : if( rank == 0 )
436 : : {
437 [ - + ]: 19 : if( is_err )
438 [ # # ][ # # ]: 0 : std::cout << func_name << " : FAILED!!" << std::endl;
[ # # ]
439 : : else
440 [ + - ][ + - ]: 19 : std::cout << func_name << " : success" << std::endl;
[ + - ]
441 : : }
442 : :
443 [ + - ][ - + ]: 19 : iMesh_dtor( imesh, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
444 : 19 : return is_err;
445 : : }
446 : :
447 : 1 : int main( int argc, char* argv[] )
448 : : {
449 [ + - ]: 1 : MPI_Init( &argc, &argv );
450 : : int size, rank;
451 [ + - ]: 1 : MPI_Comm_rank( MPI_COMM_WORLD, &rank );
452 [ + - ]: 1 : MPI_Comm_size( MPI_COMM_WORLD, &size );
453 : :
454 [ - + ][ # # ]: 1 : if( argc > 2 && !strcmp( argv[1], "-p" ) )
455 : : {
456 : : #if !defined( _MSC_VER ) && !defined( __MINGW32__ )
457 [ # # ][ # # ]: 0 : std::cout << "Processor " << rank << " of " << size << " with PID " << getpid() << std::endl;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
458 [ # # ]: 0 : std::cout.flush();
459 : : #endif
460 : : // loop forever on requested processor, giving the user time
461 : : // to attach a debugger. Once the debugger in attached, user
462 : : // can change 'pause'. E.g. on gdb do "set var pause = 0"
463 [ # # ]: 0 : if( atoi( argv[2] ) == rank )
464 : : {
465 : 0 : volatile int pause = 1;
466 [ # # ]: 0 : while( pause )
467 : : ;
468 : : }
469 [ # # ]: 0 : MPI_Barrier( MPI_COMM_WORLD );
470 : : }
471 : :
472 : 1 : int num_errors = 0;
473 [ + - ]: 1 : num_errors += RUN_TEST( test_get_partitions );
474 [ + - ]: 1 : num_errors += RUN_TEST( test_get_parts );
475 [ + - ]: 1 : num_errors += RUN_TEST( test_get_by_type );
476 [ + - ]: 1 : num_errors += RUN_TEST( test_get_by_topo );
477 [ + - ]: 1 : num_errors += RUN_TEST( test_part_id_handle );
478 [ + - ]: 1 : num_errors += RUN_TEST( test_part_rank );
479 [ + - ]: 1 : num_errors += RUN_TEST( test_get_neighbors );
480 [ + - ]: 1 : num_errors += RUN_TEST( test_get_part_boundary );
481 [ + - ]: 1 : num_errors += RUN_TEST( test_part_boundary_iter );
482 [ + - ]: 1 : num_errors += RUN_TEST( test_get_adjacencies );
483 [ + - ]: 1 : num_errors += RUN_TEST( test_entity_iterator );
484 [ + - ]: 1 : num_errors += RUN_TEST( test_entity_owner );
485 [ + - ]: 1 : num_errors += RUN_TEST( test_entity_status );
486 [ + - ]: 1 : num_errors += RUN_TEST( test_entity_copy_parts );
487 [ + - ]: 1 : num_errors += RUN_TEST( test_entity_copies );
488 [ + - ]: 1 : num_errors += RUN_TEST( test_push_tag_data_iface );
489 [ + - ]: 1 : num_errors += RUN_TEST( test_push_tag_data_ghost );
490 [ + - ]: 1 : num_errors += RUN_TEST( test_create_ghost_ents );
491 [ + - ]: 1 : num_errors += RUN_TEST( test_exchange_ents );
492 : :
493 : : // wait until all procs are done before writing summary data
494 [ + - ]: 1 : std::cout.flush();
495 [ + - ]: 1 : MPI_Barrier( MPI_COMM_WORLD );
496 : :
497 : : #ifdef MOAB_HAVE_HDF5
498 : : // clean up output file
499 [ + - ]: 1 : if( rank == 0 ) remove( FILENAME );
500 : : #endif
501 : :
502 [ + - ]: 1 : if( rank == 0 )
503 : : {
504 [ + - ]: 1 : if( !num_errors )
505 [ + - ][ + - ]: 1 : std::cout << "All tests passed" << std::endl;
506 : : else
507 [ # # ][ # # ]: 1 : std::cout << num_errors << " TESTS FAILED!" << std::endl;
[ # # ]
508 : : }
509 : :
510 [ + - ]: 1 : MPI_Finalize();
511 : 1 : return num_errors;
512 : : }
513 : :
514 : : // Create a mesh
515 : : //
516 : : //
517 : : // Groups of four quads will be arranged into parts as follows:
518 : : // +------+------+------+------+------+-----
519 : : // | | |
520 : : // | | |
521 : : // + Part 0 + Part 2 + Part 4
522 : : // | | |
523 : : // | | |
524 : : // +------+------+------+------+------+-----
525 : : // | | |
526 : : // | | |
527 : : // + Part 1 + Part 3 + Part 5
528 : : // | | |
529 : : // | | |
530 : : // +------+------+------+------+------+-----
531 : : //
532 : : // Vertices will be enumerated as follows:
533 : : // 1------6-----11-----16-----21-----26-----
534 : : // | | |
535 : : // | | |
536 : : // 2 7 12 17 22 27
537 : : // | | |
538 : : // | | |
539 : : // 3------8-----13-----18-----23-----28-----
540 : : // | | |
541 : : // | | |
542 : : // 4 9 14 19 24 29
543 : : // | | |
544 : : // | | |
545 : : // 5-----10-----15-----20-----25-----30-----
546 : : //
547 : : // Element IDs will be [4*rank+1,4*rank+5]
548 : : template < int size >
549 : : struct EHARR
550 : : {
551 : : iBase_EntityHandle h[size];
552 : 893 : iBase_EntityHandle& operator[]( int i )
553 : : {
554 : 893 : return h[i];
555 : : }
556 : 190 : operator iBase_EntityHandle*()
557 : : {
558 : 190 : return h;
559 : : }
560 : : };
561 : 19 : int create_mesh( const char* filename, int num_parts )
562 : : {
563 : 19 : const char* tagname = "GLOBAL_ID";
564 : : int ierr;
565 : :
566 : : iMesh_Instance imesh;
567 [ + - ][ - + ]: 19 : iMesh_newMesh( 0, &imesh, &ierr, 0 );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
568 : :
569 : 19 : const int num_full_cols = 2 * ( num_parts / 2 );
570 : 19 : const int need_half_cols = num_parts % 2;
571 : 19 : const int num_cols = num_full_cols + 2 * need_half_cols;
572 : 19 : const int num_vtx = 5 + 5 * num_cols - 4 * ( num_parts % 2 );
573 [ + - ]: 19 : std::vector< EHARR< 5 > > vertices( num_cols + 1 );
574 [ + - ]: 38 : std::vector< EHARR< 4 > > elements( num_cols );
575 [ + - ]: 38 : std::vector< int > vertex_ids( num_vtx );
576 [ + - ]: 38 : std::vector< iBase_EntityHandle > vertex_list( num_vtx );
577 [ + + ]: 228 : for( int i = 0; i < num_vtx; ++i )
578 [ + - ]: 209 : vertex_ids[i] = i + 1;
579 : :
580 : : // create vertices
581 : 19 : int vl_pos = 0;
582 [ + + ]: 76 : for( int i = 0; i <= num_cols; ++i )
583 : : {
584 : : double coords[15] = { static_cast< double >( i ), 0, 0, static_cast< double >( i ), 1, 0,
585 : : static_cast< double >( i ), 2, 0, static_cast< double >( i ), 3, 0,
586 : 57 : static_cast< double >( i ), 4, 0 };
587 [ + - ][ + - ]: 57 : iBase_EntityHandle* ptr = vertices[i];
588 [ + - ][ + + ]: 57 : const int n = ( num_full_cols == num_cols || i <= num_full_cols ) ? 5 : 3;
589 : 57 : int junk1 = n, junk2 = n;
590 [ + - ][ - + ]: 57 : iMesh_createVtxArr( imesh, n, iBase_INTERLEAVED, coords, 3 * n, &ptr, &junk1, &junk2, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
591 [ + - ][ + - ]: 57 : assert( ptr == vertices[i] );
[ - + ]
592 [ - + ]: 57 : assert( junk1 == n );
593 [ - + ]: 57 : assert( junk2 == n );
594 [ + + ]: 266 : for( int j = 0; j < n; ++j )
595 [ + - ][ + - ]: 209 : vertex_list[vl_pos++] = vertices[i][j];
[ + - ]
596 : : }
597 : :
598 : : // create elements
599 [ + + ]: 57 : for( int i = 0; i < num_cols; ++i )
600 : : {
601 : : iBase_EntityHandle conn[16];
602 [ + + ]: 190 : for( int j = 0; j < 4; ++j )
603 : : {
604 [ + - ][ + - ]: 152 : conn[4 * j] = vertices[i][j];
605 [ + - ][ + - ]: 152 : conn[4 * j + 1] = vertices[i][j + 1];
606 [ + - ][ + - ]: 152 : conn[4 * j + 2] = vertices[i + 1][j + 1];
607 [ + - ][ + - ]: 152 : conn[4 * j + 3] = vertices[i + 1][j];
608 : : }
609 [ + - ][ + - ]: 38 : iBase_EntityHandle* ptr = elements[i];
610 [ - + ]: 38 : const int n = ( i < num_full_cols ) ? 4 : 2;
611 : 38 : int junk1 = n, junk2 = n, junk3 = n, junk4 = n;
612 : : int stat[4];
613 : 38 : int* ptr2 = stat;
614 : : iMesh_createEntArr( imesh, iMesh_QUADRILATERAL, conn, 4 * n, &ptr, &junk1, &junk2, &ptr2, &junk3, &junk4,
615 [ + - ][ - + ]: 38 : &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
616 [ + - ][ + - ]: 38 : assert( ptr == elements[i] );
[ - + ]
617 [ - + ]: 38 : assert( junk1 == n );
618 [ - + ]: 38 : assert( junk2 == n );
619 [ - + ]: 38 : assert( ptr2 == stat );
620 [ - + ]: 38 : assert( junk3 == n );
621 [ - + ]: 38 : assert( junk4 == n );
622 : : }
623 : :
624 : : // create partition
625 : : iMeshP_PartitionHandle partition;
626 [ + - ][ - + ]: 19 : iMeshP_createPartitionAll( imesh, MPI_COMM_SELF, &partition, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
627 [ + + ]: 38 : for( int i = 0; i < num_parts; ++i )
628 : : {
629 : : iMeshP_PartHandle part;
630 [ + - ][ - + ]: 19 : iMeshP_createPart( imesh, partition, &part, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
631 [ + - ][ + - ]: 19 : iBase_EntityHandle quads[] = { elements[2 * ( i / 2 )][2 * ( i % 2 )],
632 [ + - ][ + - ]: 19 : elements[2 * ( i / 2 ) + 1][2 * ( i % 2 )],
633 [ + - ][ + - ]: 19 : elements[2 * ( i / 2 )][2 * ( i % 2 ) + 1],
634 [ + - ][ + - ]: 19 : elements[2 * ( i / 2 ) + 1][2 * ( i % 2 ) + 1] };
635 [ + - ][ - + ]: 19 : iMesh_addEntArrToSet( imesh, quads, 4, part, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
636 : : }
637 : :
638 : : // assign global ids to vertices
639 : 19 : iBase_TagHandle id_tag = 0;
640 [ + - ]: 19 : iMesh_getTagHandle( imesh, tagname, &id_tag, &ierr, strlen( tagname ) );
641 [ + - ]: 19 : if( iBase_SUCCESS == ierr )
642 : : {
643 : : int tag_size, tag_type;
644 [ + - ][ - + ]: 19 : iMesh_getTagSizeValues( imesh, id_tag, &tag_size, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
645 [ - + ]: 19 : if( tag_size != 1 ) return iBase_TAG_ALREADY_EXISTS;
646 [ + - ][ - + ]: 19 : iMesh_getTagType( imesh, id_tag, &tag_type, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
647 [ - + ]: 19 : if( tag_type != iBase_INTEGER ) return iBase_TAG_ALREADY_EXISTS;
648 : : }
649 : : else
650 : : {
651 [ # # ][ # # ]: 0 : iMesh_createTag( imesh, tagname, 1, iBase_INTEGER, &id_tag, &ierr, strlen( tagname ) );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
652 : : }
653 [ + - ][ + - ]: 19 : iMesh_setIntArrData( imesh, &vertex_list[0], num_vtx, id_tag, &vertex_ids[0], num_vtx, &ierr );CHKERR;
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
654 : :
655 : : // write file
656 : : iBase_EntitySetHandle root_set;
657 [ + - ]: 19 : iMesh_getRootSet( imesh, &root_set, &ierr );
658 [ + - ][ - + ]: 19 : iMeshP_saveAll( imesh, partition, root_set, filename, 0, &ierr, strlen( filename ), 0 );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
659 : :
660 [ + - ][ - + ]: 19 : iMesh_dtor( imesh, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
661 : :
662 : 38 : return 0;
663 : : }
664 : 0 : int create_mesh_in_memory( int rank, int num_parts, iMesh_Instance imesh, iMeshP_PartitionHandle& partition,
665 : : PartMap& map )
666 : : {
667 : 0 : const char* tagname = "GLOBAL_ID";
668 : : int ierr;
669 : :
670 : 0 : const int num_cols = 2;
671 : 0 : const int num_vtx = 9;
672 : : // we are on the top or botton row
673 : 0 : int bottom = rank % 2; // 0 2
674 : : // 1 3
675 [ # # ]: 0 : std::vector< EHARR< 3 > > vertices( 3 );
676 [ # # ]: 0 : std::vector< EHARR< 2 > > elements( 2 ); // 4 elements per process
677 [ # # ]: 0 : std::vector< int > vertex_ids( num_vtx );
678 [ # # ]: 0 : std::vector< iBase_EntityHandle > vertex_list( num_vtx );
679 : 0 : int start = 1 + 2 * bottom + 10 * ( rank / 2 );
680 : :
681 [ # # ]: 0 : for( int i = 0; i < 3; ++i )
682 [ # # ]: 0 : for( int j = 0; j < 3; ++j )
683 : : {
684 [ # # ]: 0 : vertex_ids[i + 3 * j] = start + i + 5 * j;
685 : : }
686 : :
687 : : // create vertices
688 : 0 : int vl_pos = 0;
689 : 0 : int startI = 2 * ( rank / 2 ); // so it will be 0, 0, 2, 2, ...)
690 [ # # ]: 0 : for( int i = 0; i <= 2; ++i )
691 : : {
692 : : double coords[9] = {
693 : 0 : static_cast< double >( i + startI ), 2. * bottom, 0,
694 : 0 : static_cast< double >( i + startI ), 1 + 2. * bottom, 0,
695 : 0 : static_cast< double >( i + startI ), 2 + 2. * bottom, 0,
696 : 0 : };
697 [ # # ][ # # ]: 0 : iBase_EntityHandle* ptr = vertices[i];
698 : 0 : const int n = 3;
699 : 0 : int junk1 = n, junk2 = n;
700 [ # # ][ # # ]: 0 : iMesh_createVtxArr( imesh, n, iBase_INTERLEAVED, coords, 3 * n, &ptr, &junk1, &junk2, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
701 [ # # ][ # # ]: 0 : assert( ptr == vertices[i] );
[ # # ]
702 [ # # ]: 0 : assert( junk1 == n );
703 [ # # ]: 0 : assert( junk2 == n );
704 [ # # ]: 0 : for( int j = 0; j < n; ++j )
705 [ # # ][ # # ]: 0 : vertex_list[vl_pos++] = vertices[i][j];
[ # # ]
706 : : }
707 : :
708 : : // create elements
709 [ # # ]: 0 : for( int i = 0; i < num_cols; ++i )
710 : : {
711 : : iBase_EntityHandle conn[8];
712 [ # # ]: 0 : for( int j = 0; j < 2; ++j )
713 : : {
714 [ # # ][ # # ]: 0 : conn[4 * j] = vertices[i][j];
715 [ # # ][ # # ]: 0 : conn[4 * j + 1] = vertices[i][j + 1];
716 [ # # ][ # # ]: 0 : conn[4 * j + 2] = vertices[i + 1][j + 1];
717 [ # # ][ # # ]: 0 : conn[4 * j + 3] = vertices[i + 1][j];
718 : : }
719 [ # # ][ # # ]: 0 : iBase_EntityHandle* ptr = elements[i];
720 : 0 : const int n = 2;
721 : 0 : int junk1 = n, junk2 = n, junk3 = n, junk4 = n;
722 : : int stat[4];
723 : 0 : int* ptr2 = stat;
724 : : iMesh_createEntArr( imesh, iMesh_QUADRILATERAL, conn, 4 * n, &ptr, &junk1, &junk2, &ptr2, &junk3, &junk4,
725 [ # # ][ # # ]: 0 : &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
726 [ # # ][ # # ]: 0 : assert( ptr == elements[i] );
[ # # ]
727 [ # # ]: 0 : assert( junk1 == n );
728 [ # # ]: 0 : assert( junk2 == n );
729 [ # # ]: 0 : assert( ptr2 == stat );
730 [ # # ]: 0 : assert( junk3 == n );
731 [ # # ]: 0 : assert( junk4 == n );
732 : : }
733 : :
734 : : // create partition
735 [ # # ][ # # ]: 0 : iMeshP_createPartitionAll( imesh, MPI_COMM_WORLD, &partition, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
736 : :
737 : : iMeshP_PartHandle part;
738 [ # # ][ # # ]: 0 : iMeshP_createPart( imesh, partition, &part, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
739 [ # # ][ # # ]: 0 : iBase_EntityHandle quads[] = { elements[0][0], elements[0][1], elements[1][0], elements[1][1] };
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
740 [ # # ][ # # ]: 0 : iMesh_addEntArrToSet( imesh, quads, 4, part, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
741 : :
742 : : // assign global ids to vertices
743 : 0 : iBase_TagHandle id_tag = 0;
744 [ # # ]: 0 : iMesh_getTagHandle( imesh, tagname, &id_tag, &ierr, strlen( tagname ) );
745 [ # # ]: 0 : if( iBase_SUCCESS == ierr )
746 : : {
747 : : int tag_size, tag_type;
748 [ # # ][ # # ]: 0 : iMesh_getTagSizeValues( imesh, id_tag, &tag_size, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
749 [ # # ]: 0 : if( tag_size != 1 ) return iBase_TAG_ALREADY_EXISTS;
750 [ # # ][ # # ]: 0 : iMesh_getTagType( imesh, id_tag, &tag_type, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
751 [ # # ]: 0 : if( tag_type != iBase_INTEGER ) return iBase_TAG_ALREADY_EXISTS;
752 : : }
753 : : else
754 : : {
755 [ # # ][ # # ]: 0 : iMesh_createTag( imesh, tagname, 1, iBase_INTEGER, &id_tag, &ierr, strlen( tagname ) );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
756 : : }
757 [ # # ][ # # ]: 0 : iMesh_setIntArrData( imesh, &vertex_list[0], num_vtx, id_tag, &vertex_ids[0], num_vtx, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
758 : :
759 : : // some mesh sync
760 [ # # ][ # # ]: 0 : iMeshP_syncPartitionAll( imesh, partition, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
761 [ # # ][ # # ]: 0 : iMeshP_syncMeshAll( imesh, partition, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
762 : :
763 [ # # ][ # # ]: 0 : ierr = map.build_map( imesh, partition, num_parts );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
764 : 0 : return 0;
765 : : }
766 : : // generate unique for each vertex from coordinates.
767 : : // Assume integer coordinate values with x in [0,inf] and y in [0,4]
768 : : // as generated by create_mean(..).
769 : 34 : int vertex_tag( iMesh_Instance imesh, iBase_EntityHandle vertex, int& tag )
770 : : {
771 : : int ierr;
772 : : double x, y, z;
773 [ + - ][ - + ]: 34 : iMesh_getVtxCoord( imesh, vertex, &x, &y, &z, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
774 : :
775 : 34 : int xc = (int)round( x );
776 : 34 : int yc = (int)round( y );
777 : 34 : tag = 5 * xc + yc + 1;
778 : 34 : return ierr;
779 : : }
780 : :
781 : : /**************************************************************************
782 : : Test Implementations
783 : : **************************************************************************/
784 : :
785 : 19 : int test_load( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, PartMap& map, int proc_size )
786 : : {
787 : : int ierr;
788 : :
789 : : iBase_EntitySetHandle root_set;
790 [ + - ]: 19 : iMesh_getRootSet( imesh, &root_set, &ierr );
791 : 19 : const char* opt = "moab:PARTITION=PARALLEL_PARTITION";
792 [ + - ]: 19 : iMeshP_loadAll( imesh, prtn, root_set, FILENAME, opt, &ierr, strlen( FILENAME ), strlen( opt ) );
793 [ + - ][ - + ]: 19 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
794 : :
795 [ + - ][ - + ]: 19 : ierr = map.build_map( imesh, prtn, proc_size );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
796 : 19 : return iBase_SUCCESS;
797 : : }
798 : :
799 : : /**\brief Test partition query methods
800 : : *
801 : : * Test:
802 : : * - iMeshP_getPartitionComm
803 : : * - iMeshP_getNumPartitions
804 : : * - iMeshP_getPartitions
805 : : */
806 : 1 : int test_get_partitions( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& )
807 : : {
808 : : int ierr;
809 : :
810 : : // test iMeshP_getPartitionCom
811 : 1 : MPI_Comm comm = MPI_COMM_SELF;
812 [ + - ]: 1 : iMeshP_getPartitionComm( imesh, prtn, &comm, &ierr );
813 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
814 [ + - ][ - + ]: 1 : ASSERT( comm == MPI_COMM_WORLD );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
815 : :
816 : : // test iMeshP_getPartitions
817 : 1 : iMeshP_PartitionHandle* array = 0;
818 : 1 : int alloc = 0, size = -1;
819 [ + - ]: 1 : iMeshP_getPartitions( imesh, &array, &alloc, &size, &ierr );
820 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
821 [ + - ][ - + ]: 1 : ASSERT( array != 0 );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
822 [ + - ][ - + ]: 1 : ASSERT( alloc == size );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
823 [ + - ][ - + ]: 1 : ASSERT( size > 0 );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
824 [ + - ]: 1 : int idx = std::find( array, array + size, prtn ) - array;
825 : 1 : free( array );
826 [ + - ][ - + ]: 1 : ASSERT( idx < size );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
827 : :
828 : : // test iMesP_getNumPartitions
829 : 1 : int size2 = -1;
830 [ + - ]: 1 : iMeshP_getNumPartitions( imesh, &size2, &ierr );
831 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
832 [ + - ][ - + ]: 1 : ASSERT( size2 == size );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
833 : 1 : return 0;
834 : : }
835 : :
836 : : /**\brief Test part quyery methods
837 : : *
838 : : * Test:
839 : : * - iMeshP_getNumGlobalParts
840 : : * - iMeshP_getNumLocalParts
841 : : * - iMeshP_getLocalParts
842 : : */
843 : 1 : int test_get_parts( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map )
844 : : {
845 : : int size, rank, ierr;
846 [ + - ]: 1 : MPI_Comm_rank( MPI_COMM_WORLD, &rank );
847 [ + - ]: 1 : MPI_Comm_size( MPI_COMM_WORLD, &size );
848 : :
849 : : int num_part_g;
850 [ + - ]: 1 : iMeshP_getNumGlobalParts( imesh, prtn, &num_part_g, &ierr );
851 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
852 [ + - ][ + - ]: 1 : ASSERT( num_part_g == map.num_parts() );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
853 : :
854 : : int num_part_l;
855 [ + - ]: 1 : iMeshP_getNumLocalParts( imesh, prtn, &num_part_l, &ierr );
856 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
857 [ + - ][ + - ]: 1 : ASSERT( num_part_l == map.count_from_rank( rank ) );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
858 : :
859 [ + - ]: 1 : std::vector< iMeshP_PartHandle > parts( num_part_l );
860 [ + - ]: 1 : iMeshP_PartHandle* ptr = &parts[0];
861 : 1 : int junk1 = num_part_l, count = -1;
862 [ + - ]: 1 : iMeshP_getLocalParts( imesh, prtn, &ptr, &junk1, &count, &ierr );
863 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
864 [ + - ][ - + ]: 1 : assert( ptr == &parts[0] );
865 [ - + ]: 1 : assert( junk1 == num_part_l );
866 [ + - ][ - + ]: 1 : ASSERT( count == num_part_l );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
867 : :
868 : 1 : return iBase_SUCCESS;
869 : : }
870 : :
871 : 2 : static int test_get_by_type_topo_all( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, bool test_type, int num_parts )
872 : : {
873 : : // calculate number of quads and vertices in entire mesh
874 : : // from number of parts (see create_mesh(..) function.)
875 : 2 : const int expected_global_quad_count = 4 * num_parts;
876 : 2 : const int num_col = 2 * ( num_parts / 2 + num_parts % 2 );
877 [ - + ][ # # ]: 2 : const int expected_global_vtx_count = num_parts == 1 ? 9 : num_parts % 2 ? 1 + 5 * num_col : 5 + 5 * num_col;
878 : :
879 : : // test getNumOf*All for root set
880 : : int ierr, count;
881 : : iBase_EntitySetHandle root;
882 [ + - ]: 2 : iMesh_getRootSet( imesh, &root, &ierr );
883 [ + + ]: 2 : if( test_type )
884 [ + - ]: 1 : iMeshP_getNumOfTypeAll( imesh, prtn, root, iBase_VERTEX, &count, &ierr );
885 : : else
886 [ + - ]: 1 : iMeshP_getNumOfTopoAll( imesh, prtn, root, iMesh_POINT, &count, &ierr );
887 [ + - ][ - + ]: 2 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
888 [ + - ][ - + ]: 2 : ASSERT( count == expected_global_vtx_count );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
889 [ + + ]: 2 : if( test_type )
890 [ + - ]: 1 : iMeshP_getNumOfTypeAll( imesh, prtn, root, iBase_FACE, &count, &ierr );
891 : : else
892 [ + - ]: 1 : iMeshP_getNumOfTopoAll( imesh, prtn, root, iMesh_QUADRILATERAL, &count, &ierr );
893 [ + - ][ - + ]: 2 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
894 [ + - ][ - + ]: 2 : ASSERT( count == expected_global_quad_count );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
895 : :
896 : : // create an entity set containing half of the quads
897 [ + - ][ + - ]: 4 : std::vector< iBase_EntityHandle > all_quads, half_quads;
898 [ + - ]: 2 : ierr = get_entities( imesh, root, iBase_FACE, iMesh_QUADRILATERAL, all_quads );
899 [ - + ]: 2 : assert( 0 == all_quads.size() % 2 );
900 [ + - ]: 2 : half_quads.resize( all_quads.size() / 2 );
901 [ + + ]: 6 : for( size_t i = 0; i < all_quads.size() / 2; ++i )
902 [ + - ][ + - ]: 4 : half_quads[i] = all_quads[2 * i];
903 : : iBase_EntitySetHandle set;
904 [ + - ][ - + ]: 2 : iMesh_createEntSet( imesh, 1, &set, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
905 [ + - ][ + - ]: 2 : iMesh_addEntArrToSet( imesh, &half_quads[0], half_quads.size(), set, &ierr );CHKERR;
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
906 : :
907 : : // test getNumOf*All with defined set
908 [ + + ]: 2 : if( test_type )
909 [ + - ]: 1 : iMeshP_getNumOfTypeAll( imesh, prtn, set, iBase_VERTEX, &count, &ierr );
910 : : else
911 [ + - ]: 1 : iMeshP_getNumOfTopoAll( imesh, prtn, set, iMesh_POINT, &count, &ierr );
912 [ + - ][ - + ]: 2 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
913 [ + - ][ - + ]: 2 : ASSERT( count == 0 );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
914 [ + + ]: 2 : if( test_type )
915 [ + - ]: 1 : iMeshP_getNumOfTypeAll( imesh, prtn, set, iBase_FACE, &count, &ierr );
916 : : else
917 [ + - ]: 1 : iMeshP_getNumOfTopoAll( imesh, prtn, set, iMesh_QUADRILATERAL, &count, &ierr );
918 [ + - ][ - + ]: 2 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
919 [ + - ][ - + ]: 2 : ASSERT( count == expected_global_quad_count / 2 );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
920 : :
921 : 4 : return 0;
922 : : }
923 : :
924 : 2 : static int test_get_by_type_topo_local( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, bool test_type )
925 : : {
926 : : int ierr;
927 : : iBase_EntitySetHandle root;
928 [ + - ]: 2 : iMesh_getRootSet( imesh, &root, &ierr );
929 : :
930 : : // select a single part
931 [ + - ]: 2 : std::vector< iMeshP_PartHandle > parts;
932 [ + - ][ - + ]: 2 : ierr = get_local_parts( imesh, prtn, parts );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
933 [ + - ]: 2 : iMeshP_PartHandle part = parts.front();
934 : :
935 : : // get the entities contained in the part
936 [ + - ][ + - ]: 4 : std::vector< iBase_EntityHandle > part_quads, part_all;
937 [ + - ][ - + ]: 2 : ierr = get_entities( imesh, part, iBase_FACE, iMesh_QUADRILATERAL, part_quads );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
938 [ + - ][ - + ]: 2 : ierr = get_entities( imesh, part, iBase_ALL_TYPES, iMesh_ALL_TOPOLOGIES, part_all );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
939 : :
940 : : // compare local counts (using root set)
941 : :
942 : : int count;
943 [ + + ]: 2 : if( test_type )
944 [ + - ]: 1 : iMeshP_getNumOfType( imesh, prtn, part, root, iBase_FACE, &count, &ierr );
945 : : else
946 [ + - ][ - + ]: 2 : iMeshP_getNumOfTopo( imesh, prtn, part, root, iMesh_QUADRILATERAL, &count, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
947 [ + - ][ - + ]: 2 : ASSERT( count == (int)part_quads.size() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
948 : :
949 [ + + ]: 2 : if( test_type )
950 [ + - ]: 1 : iMeshP_getNumOfType( imesh, prtn, part, root, iBase_ALL_TYPES, &count, &ierr );
951 : : else
952 [ + - ][ - + ]: 2 : iMeshP_getNumOfTopo( imesh, prtn, part, root, iMesh_ALL_TOPOLOGIES, &count, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
953 [ + - ][ - + ]: 2 : ASSERT( count == (int)part_all.size() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
954 : :
955 : : // compare local contents (using root set)
956 : :
957 : 2 : iBase_EntityHandle* ptr = 0;
958 : 2 : int num_ent, junk1 = 0;
959 : : iMeshP_getEntities( imesh, prtn, part, root, test_type ? iBase_FACE : iBase_ALL_TYPES,
960 [ + + ][ + + ]: 2 : test_type ? iMesh_ALL_TOPOLOGIES : iMesh_QUADRILATERAL, &ptr, &junk1, &num_ent, &ierr );CHKERR;
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
961 [ + - ]: 4 : std::vector< iBase_EntityHandle > act_quads( ptr, ptr + num_ent );
962 : 2 : free( ptr );
963 : 2 : junk1 = num_ent = 0;
964 : 2 : ptr = 0;
965 [ + - ][ - + ]: 2 : iMeshP_getEntities( imesh, prtn, part, root, iBase_ALL_TYPES, iMesh_ALL_TOPOLOGIES, &ptr, &junk1, &num_ent, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
966 [ + - ]: 4 : std::vector< iBase_EntityHandle > act_all( ptr, ptr + num_ent );
967 : 2 : free( ptr );
968 [ + - ]: 2 : std::sort( part_quads.begin(), part_quads.end() );
969 [ + - ]: 2 : std::sort( part_all.begin(), part_all.end() );
970 [ + - ]: 2 : std::sort( act_quads.begin(), act_quads.end() );
971 [ + - ]: 2 : std::sort( act_all.begin(), act_all.end() );
972 [ + - ][ + - ]: 2 : ASSERT( part_quads == act_quads );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
973 [ + - ][ + - ]: 2 : ASSERT( part_all == act_all );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
974 : :
975 : : // create an entity set containing half of the quads from the part
976 [ + - ]: 4 : std::vector< iBase_EntityHandle > half_quads( part_quads.size() / 2 );
977 [ + + ]: 6 : for( size_t i = 0; i < half_quads.size(); ++i )
978 [ + - ][ + - ]: 4 : half_quads[i] = part_quads[2 * i];
979 : : iBase_EntitySetHandle set;
980 [ + - ][ - + ]: 2 : iMesh_createEntSet( imesh, 1, &set, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
981 [ + - ][ + - ]: 2 : iMesh_addEntArrToSet( imesh, &half_quads[0], half_quads.size(), set, &ierr );CHKERR;
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
982 : :
983 : : // check if there exists any quads not in the part that we
984 : : // can add to the set
985 [ + - ][ + - ]: 4 : std::vector< iBase_EntityHandle > all_quads, other_quads;
986 [ + - ][ - + ]: 2 : ierr = get_entities( imesh, root, iBase_FACE, iMesh_QUADRILATERAL, all_quads );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
987 [ + - ]: 2 : std::sort( all_quads.begin(), all_quads.end() );
988 [ + - ]: 2 : std::sort( part_quads.begin(), part_quads.end() );
989 : : std::set_difference( all_quads.begin(), all_quads.end(), part_quads.begin(), part_quads.end(),
990 [ + - ][ + - ]: 2 : std::back_inserter( other_quads ) );
991 [ + - ][ + - ]: 2 : iMesh_addEntArrToSet( imesh, &other_quads[0], other_quads.size(), set, &ierr );CHKERR;
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
992 : :
993 : : // compare local counts (using non-root set)
994 : :
995 [ + + ]: 2 : if( test_type )
996 [ + - ]: 1 : iMeshP_getNumOfType( imesh, prtn, part, set, iBase_FACE, &count, &ierr );
997 : : else
998 [ + - ][ - + ]: 2 : iMeshP_getNumOfTopo( imesh, prtn, part, set, iMesh_QUADRILATERAL, &count, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
999 [ + - ][ - + ]: 2 : ASSERT( count == (int)half_quads.size() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1000 : :
1001 [ + + ]: 2 : if( test_type )
1002 [ + - ]: 1 : iMeshP_getNumOfType( imesh, prtn, part, set, iBase_VERTEX, &count, &ierr );
1003 : : else
1004 [ + - ][ - + ]: 2 : iMeshP_getNumOfTopo( imesh, prtn, part, set, iMesh_POINT, &count, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1005 [ + - ][ - + ]: 2 : ASSERT( count == 0 );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1006 : :
1007 : : // compare local contents (using non-root set)
1008 : :
1009 : 2 : junk1 = 0;
1010 : 2 : num_ent = 0;
1011 : 2 : ptr = 0;
1012 : : iMeshP_getEntities( imesh, prtn, part, set, test_type ? iBase_FACE : iBase_ALL_TYPES,
1013 [ + + ][ + + ]: 2 : test_type ? iMesh_ALL_TOPOLOGIES : iMesh_QUADRILATERAL, &ptr, &junk1, &num_ent, &ierr );CHKERR;
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1014 [ + - ]: 2 : act_quads.resize( num_ent );
1015 [ + - ]: 2 : std::copy( ptr, ptr + num_ent, act_quads.begin() );
1016 : 2 : free( ptr );
1017 [ + - ]: 2 : std::sort( half_quads.begin(), half_quads.end() );
1018 [ + - ]: 2 : std::sort( act_quads.begin(), act_quads.end() );
1019 [ + - ][ + - ]: 2 : ASSERT( act_quads == half_quads );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1020 : :
1021 : 4 : return iBase_SUCCESS;
1022 : : }
1023 : :
1024 : : /**\brief Test query by entity type
1025 : : *
1026 : : * Test:
1027 : : * - iMeshP_getNumOfTypeAll
1028 : : * - iMeshP_getNumOfType
1029 : : * - iMeshP_getEntities
1030 : : * -
1031 : : */
1032 : 1 : int test_get_by_type( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map )
1033 : : {
1034 : : int ierr;
1035 : 1 : ierr = test_get_by_type_topo_all( imesh, prtn, true, map.num_parts() );
1036 [ - + ]: 1 : PCHECK;
1037 : 1 : ierr = test_get_by_type_topo_local( imesh, prtn, true );
1038 [ - + ]: 1 : PCHECK;
1039 : 1 : return 0;
1040 : : }
1041 : :
1042 : : /**\brief Test query by entity topology
1043 : : *
1044 : : * Test:
1045 : : * - iMeshP_getNumOfTopoAll
1046 : : * - iMeshP_getNumOfTopo
1047 : : * - iMeshP_getEntities
1048 : : * -
1049 : : */
1050 : 1 : int test_get_by_topo( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map )
1051 : : {
1052 : : int ierr;
1053 : 1 : ierr = test_get_by_type_topo_all( imesh, prtn, false, map.num_parts() );
1054 [ - + ]: 1 : PCHECK;
1055 : 1 : ierr = test_get_by_type_topo_local( imesh, prtn, false );
1056 [ - + ]: 1 : PCHECK;
1057 : 1 : return 0;
1058 : : }
1059 : :
1060 : : /**\brief Test mapping from part id to part handle
1061 : : *
1062 : : * Test:
1063 : : * - iMeshP_getPartIdFromPartHandle
1064 : : * - iMeshP_getPartIdsFromPartHandlesArr
1065 : : * - iMeshP_getPartHandleFromPartId
1066 : : * - iMeshP_getPartHandlesFromPartsIdsArr
1067 : : */
1068 : 1 : int test_part_id_handle( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map )
1069 : : {
1070 : : // get local part ids
1071 : : int rank, ierr;
1072 [ + - ]: 1 : MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1073 [ + - ]: 1 : std::vector< iMeshP_Part > ids;
1074 [ + - ]: 1 : map.part_id_from_rank( rank, ids );
1075 : :
1076 : : // check single-part functions and build list of part handles
1077 [ + - ]: 2 : std::vector< iMeshP_PartHandle > handles( ids.size() );
1078 : : size_t i;
1079 [ + + ]: 2 : for( i = 0; i < ids.size(); ++i )
1080 : : {
1081 [ + - ][ + - ]: 1 : iMeshP_getPartHandleFromPartId( imesh, prtn, ids[i], &handles[i], &ierr );CHKERR;
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1082 : : iMeshP_Part id;
1083 [ + - ][ + - ]: 1 : iMeshP_getPartIdFromPartHandle( imesh, prtn, handles[i], &id, &ierr );CHKERR;
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1084 [ + - ][ - + ]: 1 : if( id != ids[i] ) break;
1085 : : }
1086 [ + - ][ - + ]: 1 : ASSERT( i == ids.size() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1087 : :
1088 : : // test iMeshP_getPartIdsFromPartHandlesArr
1089 [ + - ]: 2 : std::vector< iMeshP_Part > ids2( ids.size() );
1090 : 1 : int junk1 = ids.size(), junk2 = 0;
1091 [ + - ]: 1 : iMeshP_Part* ptr = &ids2[0];
1092 [ + - ][ + - ]: 1 : iMeshP_getPartIdsFromPartHandlesArr( imesh, prtn, &handles[0], handles.size(), &ptr, &junk1, &junk2, &ierr );
1093 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1094 [ + - ][ + - ]: 1 : ASSERT( ptr == &ids2[0] );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1095 [ + - ][ - + ]: 1 : ASSERT( junk2 == (int)ids2.size() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1096 [ + - ][ + - ]: 1 : ASSERT( ids == ids2 );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1097 : :
1098 : : // test iMeshP_getPartHandlesFromPartsIdsArr
1099 [ + - ]: 2 : std::vector< iMeshP_PartHandle > handles2( handles.size() );
1100 : 1 : junk1 = handles.size();
1101 : 1 : junk2 = 0;
1102 [ + - ]: 1 : iMeshP_PartHandle* ptr2 = &handles2[0];
1103 [ + - ][ + - ]: 1 : iMeshP_getPartHandlesFromPartsIdsArr( imesh, prtn, &ids[0], ids.size(), &ptr2, &junk1, &junk2, &ierr );
1104 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1105 [ + - ][ + - ]: 1 : ASSERT( ptr2 == &handles2[0] );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1106 [ + - ][ - + ]: 1 : ASSERT( junk2 == (int)handles2.size() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1107 [ + - ][ + - ]: 1 : ASSERT( handles == handles2 );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1108 : :
1109 : 2 : return 0;
1110 : : }
1111 : :
1112 : : /**\brief Test get part rank
1113 : : *
1114 : : * Tests:
1115 : : * - iMeshP_getRankOfPart
1116 : : * - iMeshP_getRankOfPartArr
1117 : : */
1118 : 1 : int test_part_rank( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map )
1119 : : {
1120 : 1 : int ierr = 0, rank;
1121 [ + - ][ + - ]: 2 : std::vector< iMeshP_Part > invalid, failed;
1122 [ + - ]: 1 : MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1123 : :
1124 : : // test iMeshP_getRankOfPart
1125 [ + - ][ + + ]: 2 : for( size_t i = 0; i < map.get_parts().size(); ++i )
1126 : : {
1127 : : int pr;
1128 [ + - ][ + - ]: 1 : iMeshP_getRankOfPart( imesh, prtn, map.get_parts()[i], &pr, &ierr );
[ + - ]
1129 [ - + ]: 1 : if( iBase_SUCCESS != ierr )
1130 [ # # ][ # # ]: 0 : failed.push_back( map.get_parts()[i] );
[ # # ]
1131 [ + - ][ + - ]: 1 : else if( pr != map.get_ranks()[i] )
[ - + ]
1132 [ # # ][ # # ]: 0 : invalid.push_back( map.get_parts()[i] );
[ # # ]
1133 : : }
1134 [ - + ]: 1 : if( !failed.empty() )
1135 : : {
1136 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": iMeshP_getRankOfPart failed for " << failed.size() << " parts."
[ # # ][ # # ]
[ # # ]
1137 [ # # ]: 0 : << std::endl;
1138 : 0 : ierr = iBase_FAILURE;
1139 : : }
1140 [ - + ]: 1 : if( !invalid.empty() )
1141 : : {
1142 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": iMeshP_getRankOfPart was incorrect for " << invalid.size() << " parts."
[ # # ][ # # ]
[ # # ]
1143 [ # # ]: 0 : << std::endl;
1144 : 0 : ierr = iBase_FAILURE;
1145 : : }
1146 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1147 : :
1148 : : // test iMeshP_getRankOfPartArr
1149 [ + - ][ + - ]: 2 : std::vector< int > ranks( map.get_parts().size() );
1150 [ + - ]: 1 : int junk1 = ranks.size(), junk2, *ptr = &ranks[0];
1151 [ + - ][ + - ]: 1 : iMeshP_getRankOfPartArr( imesh, prtn, &map.get_parts()[0], map.get_parts().size(), &ptr, &junk1, &junk2, &ierr );
[ + - ][ + - ]
1152 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1153 [ + - ][ - + ]: 1 : assert( ptr == &ranks[0] );
1154 [ - + ]: 1 : assert( junk1 == (int)ranks.size() );
1155 [ + - ][ - + ]: 1 : ASSERT( junk2 == (int)ranks.size() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1156 [ + - ][ + + ]: 2 : for( size_t i = 0; i < map.get_parts().size(); ++i )
1157 : : {
1158 [ + - ][ + - ]: 1 : if( ranks[i] != map.get_ranks()[i] ) invalid.push_back( map.get_parts()[i] );
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ]
1159 : : }
1160 [ - + ]: 1 : if( !invalid.empty() )
1161 : : {
1162 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": iMeshP_getRankOfPartArr was incorrect for " << invalid.size()
[ # # ][ # # ]
1163 [ # # ][ # # ]: 0 : << " parts." << std::endl;
1164 : 0 : ierr = iBase_FAILURE;
1165 : : }
1166 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1167 : :
1168 : 2 : return 0;
1169 : : }
1170 : :
1171 : : // see create_mesh(..)
1172 : 3 : static void get_part_neighbors( int logical_part_id, int num_parts, int neighbors[5], int& num_neighbors )
1173 : : {
1174 : 3 : num_neighbors = 0;
1175 [ - + ]: 3 : if( logical_part_id + 1 < num_parts ) neighbors[num_neighbors++] = logical_part_id + 1;
1176 [ - + ]: 3 : if( logical_part_id + 2 < num_parts ) neighbors[num_neighbors++] = logical_part_id + 2;
1177 [ - + ]: 3 : if( logical_part_id % 2 )
1178 : : {
1179 : 0 : neighbors[num_neighbors++] = logical_part_id - 1;
1180 [ # # ]: 0 : if( logical_part_id > 2 )
1181 : : {
1182 : 0 : neighbors[num_neighbors++] = logical_part_id - 3;
1183 : 0 : neighbors[num_neighbors++] = logical_part_id - 2;
1184 : : }
1185 : : }
1186 : : else
1187 : : {
1188 [ - + ]: 3 : if( logical_part_id + 3 < num_parts ) neighbors[num_neighbors++] = logical_part_id + 3;
1189 [ - + ]: 3 : if( logical_part_id > 1 )
1190 : : {
1191 : 0 : neighbors[num_neighbors++] = logical_part_id - 1;
1192 : 0 : neighbors[num_neighbors++] = logical_part_id - 2;
1193 : : }
1194 : : }
1195 : 3 : }
1196 : :
1197 : : /**\brief Test querying of part neighbors
1198 : : *
1199 : : * Test:
1200 : : * - iMeshP_getNumPartNbors
1201 : : * - iMeshP_getNumPartNborsArr
1202 : : * - iMeshP_getPartNbors
1203 : : * - iMeshP_getPartNborsArr
1204 : : */
1205 : 1 : int test_get_neighbors( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map )
1206 : : {
1207 : : int ierr, rank;
1208 [ + - ]: 1 : MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1209 : :
1210 [ + - ]: 1 : std::vector< iMeshP_Part > local_parts;
1211 [ + - ]: 1 : map.part_id_from_rank( rank, local_parts );
1212 : :
1213 : : // get handles for local parts
1214 [ + - ]: 2 : std::vector< iMeshP_PartHandle > handles( local_parts.size() );
1215 [ + - ]: 1 : iMeshP_PartHandle* ptr = &handles[0];
1216 : 1 : int junk1 = handles.size(), junk2 = 0;
1217 [ + - ]: 1 : iMeshP_getPartHandlesFromPartsIdsArr( imesh, prtn, &local_parts[0], local_parts.size(), &ptr, &junk1, &junk2,
1218 [ + - ]: 1 : &ierr );
1219 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1220 [ + - ][ - + ]: 1 : assert( ptr == &handles[0] );
1221 [ - + ]: 1 : assert( junk2 == (int)handles.size() );
1222 : :
1223 : : // get logical ids for local parts
1224 [ + - ]: 2 : std::vector< int > logical_ids;
1225 [ + - ]: 1 : map.local_id_from_rank( rank, logical_ids );
1226 : :
1227 : : // get neighbors for each local part
1228 [ + - ]: 2 : std::vector< std::vector< iMeshP_Part > > neighbors( logical_ids.size() );
1229 [ + + ]: 2 : for( size_t i = 0; i < logical_ids.size(); ++i )
1230 : : {
1231 : : int logical_neighbors[5], num_neighbors;
1232 [ + - ][ + - ]: 1 : get_part_neighbors( logical_ids[i], map.num_parts(), logical_neighbors, num_neighbors );
1233 [ + - ][ + - ]: 1 : neighbors[i].resize( num_neighbors );
1234 [ - + ]: 1 : for( int j = 0; j < num_neighbors; ++j )
1235 [ # # ][ # # ]: 0 : neighbors[i][j] = map.part_id_from_local_id( logical_neighbors[j] );
[ # # ]
1236 [ + - ][ + - ]: 1 : std::sort( neighbors[i].begin(), neighbors[i].end() );
[ + - ]
1237 : : }
1238 : :
1239 : : // test iMeshP_getNumPartNbors
1240 [ + - ][ + - ]: 2 : std::vector< iMeshP_Part > invalid, failed;
1241 [ + + ]: 2 : for( size_t i = 0; i < local_parts.size(); ++i )
1242 : : {
1243 : : int count;
1244 [ + - ][ + - ]: 1 : iMeshP_getNumPartNbors( imesh, prtn, handles[i], iBase_VERTEX, &count, &ierr );
1245 [ - + ]: 1 : if( ierr )
1246 [ # # ][ # # ]: 0 : failed.push_back( local_parts[i] );
1247 [ + - ][ - + ]: 1 : else if( count != (int)neighbors[i].size() )
1248 [ # # ][ # # ]: 0 : invalid.push_back( local_parts[i] );
1249 : : }
1250 [ - + ]: 1 : if( !failed.empty() )
1251 : : {
1252 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": iMeshP_getNumPartNbors failed for " << failed.size() << " parts."
[ # # ][ # # ]
[ # # ]
1253 [ # # ]: 0 : << std::endl;
1254 : 0 : ierr = iBase_FAILURE;
1255 [ # # ][ # # ]: 0 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1256 : : }
1257 [ - + ]: 1 : if( !invalid.empty() )
1258 : : {
1259 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": iMeshP_getNumPartNbors was incorrect for " << invalid.size()
[ # # ][ # # ]
1260 [ # # ][ # # ]: 0 : << " parts." << std::endl;
1261 : 0 : ierr = iBase_FAILURE;
1262 [ # # ][ # # ]: 0 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1263 : : }
1264 : :
1265 : : // test iMeshP_getPartNbors
1266 : 1 : ierr = 0;
1267 [ + + ]: 2 : for( size_t i = 0; i < local_parts.size(); ++i )
1268 : : {
1269 : 1 : int count, junk = 0, another_count;
1270 : 1 : iMeshP_Part* list = 0;
1271 [ + - ][ + - ]: 1 : iMeshP_getPartNbors( imesh, prtn, handles[i], iBase_VERTEX, &another_count, &list, &junk, &count, &ierr );
1272 [ - + ]: 1 : assert( count == another_count );
1273 [ - + ]: 1 : if( ierr )
1274 [ # # ][ # # ]: 0 : failed.push_back( local_parts[i] );
1275 : : else
1276 : : {
1277 [ + - ]: 1 : std::sort( list, list + count );
1278 [ + - ]: 1 : std::vector< iMeshP_Part > cpy( list, list + count );
1279 [ + - ][ + - ]: 1 : if( cpy != neighbors[i] ) invalid.push_back( local_parts[i] );
[ - + ][ # # ]
[ # # ]
1280 : 1 : free( list );
1281 : : }
1282 : : }
1283 [ - + ]: 1 : if( !failed.empty() )
1284 : : {
1285 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": iMeshP_getPartNbors failed for " << failed.size() << " parts."
[ # # ][ # # ]
[ # # ]
1286 [ # # ]: 0 : << std::endl;
1287 : 0 : ierr = iBase_FAILURE;
1288 : : }
1289 [ - + ]: 1 : if( !invalid.empty() )
1290 : : {
1291 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": iMeshP_getPartNbors was incorrect for " << invalid.size() << " parts."
[ # # ][ # # ]
[ # # ]
1292 [ # # ]: 0 : << std::endl;
1293 : 0 : ierr = iBase_FAILURE;
1294 : : }
1295 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1296 : :
1297 : : // test iMeshP_getNumPartNborsArr
1298 [ + - ]: 2 : std::vector< int > count_vect( handles.size() );
1299 [ + - ]: 1 : int* count_arr = &count_vect[0];
1300 : 1 : junk1 = handles.size();
1301 [ + - ]: 1 : iMeshP_getNumPartNborsArr( imesh, prtn, &handles[0], handles.size(), iBase_VERTEX, &count_arr, &junk1, &junk2,
1302 [ + - ]: 1 : &ierr );
1303 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1304 [ + - ][ - + ]: 1 : assert( count_arr == &count_vect[0] );
1305 [ - + ]: 1 : assert( junk2 == (int)handles.size() );
1306 [ + + ]: 2 : for( size_t i = 0; i < local_parts.size(); ++i )
1307 : : {
1308 [ + - ][ - + ]: 1 : if( count_arr[i] != (int)neighbors[i].size() ) invalid.push_back( local_parts[i] );
[ # # ][ # # ]
1309 : : }
1310 [ - + ]: 1 : if( !invalid.empty() )
1311 : : {
1312 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": iMeshP_getNumPartNborsArr was incorrect for " << invalid.size()
[ # # ][ # # ]
1313 [ # # ][ # # ]: 0 : << " parts." << std::endl;
1314 : 0 : ierr = iBase_FAILURE;
1315 : : }
1316 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1317 : :
1318 : : // test iMeshP_getPartNborsArr
1319 : 1 : iMeshP_Part* nbor_arr = 0;
1320 : 1 : junk1 = handles.size(), junk2 = 0;
1321 : 1 : int junk3 = 0, nbor_size;
1322 [ + - ]: 1 : iMeshP_getPartNborsArr( imesh, prtn, &handles[0], handles.size(), iBase_VERTEX, &count_arr, &junk1, &junk2,
1323 [ + - ]: 1 : &nbor_arr, &junk3, &nbor_size, &ierr );
1324 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1325 [ + - ][ - + ]: 1 : assert( count_arr == &count_vect[0] );
1326 [ - + ]: 1 : assert( junk2 == (int)handles.size() );
1327 [ + - ]: 2 : std::vector< iMeshP_Part > all_nbors( nbor_arr, nbor_arr + nbor_size );
1328 : 1 : free( nbor_arr );
1329 : 1 : std::vector< iMeshP_Part >::iterator j = all_nbors.begin();
1330 : 1 : bool bad_length = false;
1331 [ + + ]: 2 : for( size_t i = 0; i < local_parts.size(); ++i )
1332 : : {
1333 [ + - ][ - + ]: 1 : if( all_nbors.end() - j > count_arr[i] )
1334 : : {
1335 : 0 : bad_length = true;
1336 : 0 : break;
1337 : : }
1338 [ + - ][ - + ]: 1 : if( count_arr[i] != (int)neighbors[i].size() ) { invalid.push_back( local_parts[i] ); }
[ # # ][ # # ]
1339 : : else
1340 : : {
1341 [ + - ]: 1 : std::vector< iMeshP_Part >::iterator e = j + count_arr[i];
1342 [ + - ]: 1 : std::sort( j, e );
1343 [ + - ][ + - ]: 1 : if( !std::equal( j, e, neighbors[i].begin() ) ) invalid.push_back( local_parts[i] );
[ - + ][ # # ]
[ # # ]
1344 : : }
1345 : : }
1346 [ - + ]: 1 : if( bad_length )
1347 : : {
1348 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": iMeshP_getPartNborsArr had inconsistent result array lengths."
[ # # ]
1349 [ # # ]: 0 : << std::endl;
1350 : 0 : ierr = iBase_FAILURE;
1351 : : }
1352 [ - + ]: 1 : if( !invalid.empty() )
1353 : : {
1354 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": iMeshP_getPartNborsArr was incorrect for " << invalid.size()
[ # # ][ # # ]
1355 [ # # ][ # # ]: 0 : << " parts." << std::endl;
1356 : 0 : ierr = iBase_FAILURE;
1357 : : }
1358 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1359 : :
1360 : 2 : return 0;
1361 : : }
1362 : :
1363 : : // Determine the expected vertices on the interface between two parts.
1364 : : // Returns no vertices for non-adjacient parts and fails if both parts
1365 : : // are the same.
1366 : : // See create_mesh(..) for the assumed mesh.
1367 : 0 : static int interface_verts( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, iMeshP_PartHandle local_part,
1368 : : iMeshP_Part other_part, const PartMap& map, std::vector< iBase_EntityHandle >& vtx_handles )
1369 : : {
1370 : : int ierr, rank;
1371 [ # # ]: 0 : MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1372 : :
1373 : : iMeshP_Part local_id;
1374 [ # # ][ # # ]: 0 : iMeshP_getPartIdFromPartHandle( imesh, prtn, local_part, &local_id, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1375 : :
1376 [ # # ]: 0 : const int local_logical = map.local_id_from_part_id( local_id );
1377 [ # # ]: 0 : const int other_logical = map.local_id_from_part_id( other_part );
1378 : :
1379 : : // get grid of local vertices
1380 : :
1381 : : iBase_EntityHandle verts[3][3];
1382 : 0 : const double xbase = ( local_id / 2 ) * 2;
1383 : 0 : const double ybase = ( local_id % 2 ) * 2;
1384 : :
1385 : : // get quads in partition
1386 : 0 : iBase_EntityHandle quads[4], *ptr = quads;
1387 : 0 : int junk1 = 4, junk2;
1388 [ # # ][ # # ]: 0 : iMesh_getEntities( imesh, local_part, iBase_FACE, iMesh_QUADRILATERAL, &ptr, &junk1, &junk2, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1389 [ # # ]: 0 : assert( ptr == quads );
1390 [ # # ]: 0 : assert( junk1 == 4 );
1391 [ # # ]: 0 : assert( junk2 == 4 );
1392 : :
1393 : : // get vertices in quads
1394 : : iBase_EntityHandle conn[16];
1395 : 0 : int offsets[5], *off_ptr = offsets, junk3 = 5, junk4;
1396 : 0 : ptr = conn;
1397 : 0 : junk1 = 16;
1398 [ # # ][ # # ]: 0 : iMesh_getEntArrAdj( imesh, quads, 4, iBase_VERTEX, &ptr, &junk1, &junk2, &off_ptr, &junk3, &junk4, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1399 [ # # ]: 0 : assert( ptr == conn );
1400 [ # # ]: 0 : assert( junk1 == 16 );
1401 [ # # ]: 0 : assert( junk2 == 16 );
1402 [ # # ]: 0 : assert( off_ptr == offsets );
1403 [ # # ]: 0 : assert( junk3 == 5 );
1404 [ # # ]: 0 : assert( junk4 == 5 );
1405 : :
1406 : : // make unique vertex list
1407 [ # # ]: 0 : std::sort( conn, conn + 16 );
1408 [ # # ]: 0 : const int num_vtx = std::unique( conn, conn + 16 ) - conn;
1409 [ # # ]: 0 : assert( 9 == num_vtx );
1410 : :
1411 : : // get vertex coords
1412 [ # # ]: 0 : std::vector< double > coords( 27 );
1413 [ # # ][ # # ]: 0 : ierr = get_coords( imesh, conn, 9, &coords[0] );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1414 : :
1415 : : // use vertex coords to determine logical position
1416 [ # # ]: 0 : for( int i = 0; i < num_vtx; ++i )
1417 : : {
1418 [ # # ]: 0 : int x = (int)round( coords[3 * i] - xbase );
1419 [ # # ]: 0 : int y = (int)round( coords[3 * i + 1] - ybase );
1420 [ # # ][ # # ]: 0 : if( x < 0 || x > 2 || y < 0 || y > 2 )
[ # # ][ # # ]
1421 : : {
1422 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
[ # # ][ # # ]
[ # # ]
1423 [ # # ][ # # ]: 0 : << " Invalid vertex coordinate: (" << coords[3 * i] << ", " << coords[3 * i + 1] << ", "
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1424 [ # # ][ # # ]: 0 : << coords[3 * i + 2] << ")" << std::endl
[ # # ][ # # ]
1425 [ # # ][ # # ]: 0 : << " For logical partition " << local_id << std::endl;
[ # # ]
1426 : 0 : return iBase_FAILURE;
1427 : : }
1428 : 0 : verts[x][y] = conn[i];
1429 : : }
1430 : :
1431 [ # # ]: 0 : if( local_logical % 2 )
1432 : : {
1433 [ # # # # : 0 : switch( other_logical - local_logical )
# # # ]
1434 : : {
1435 : : case 0:
1436 : 0 : return iBase_FAILURE;
1437 : : case 1: // upper right
1438 [ # # ]: 0 : vtx_handles.resize( 1 );
1439 [ # # ]: 0 : vtx_handles[0] = verts[2][0];
1440 : 0 : break;
1441 : : case 2: // right
1442 [ # # ]: 0 : vtx_handles.resize( 3 );
1443 [ # # ]: 0 : std::copy( verts[2], verts[2] + 3, vtx_handles.begin() );
1444 : 0 : break;
1445 : : case -1: // above
1446 [ # # ]: 0 : vtx_handles.resize( 3 );
1447 [ # # ]: 0 : vtx_handles[0] = verts[0][0];
1448 [ # # ]: 0 : vtx_handles[1] = verts[1][0];
1449 [ # # ]: 0 : vtx_handles[2] = verts[2][0];
1450 : 0 : break;
1451 : : case -2: // left
1452 [ # # ]: 0 : vtx_handles.resize( 3 );
1453 [ # # ]: 0 : std::copy( verts[0], verts[0] + 3, vtx_handles.begin() );
1454 : 0 : break;
1455 : : case -3: // upper left
1456 [ # # ]: 0 : vtx_handles.resize( 1 );
1457 [ # # ]: 0 : vtx_handles[0] = verts[0][0];
1458 : 0 : break;
1459 : : default:
1460 : 0 : vtx_handles.clear();
1461 : 0 : break;
1462 : : }
1463 : : }
1464 : : else
1465 : : {
1466 [ # # # # : 0 : switch( other_logical - local_logical )
# # # ]
1467 : : {
1468 : : case 0:
1469 : 0 : return iBase_FAILURE;
1470 : : case 1: // below
1471 [ # # ]: 0 : vtx_handles.resize( 3 );
1472 [ # # ]: 0 : vtx_handles[0] = verts[0][2];
1473 [ # # ]: 0 : vtx_handles[1] = verts[1][2];
1474 [ # # ]: 0 : vtx_handles[2] = verts[2][2];
1475 : 0 : break;
1476 : : case 2: // right
1477 [ # # ]: 0 : vtx_handles.resize( 3 );
1478 [ # # ]: 0 : std::copy( verts[2], verts[2] + 3, vtx_handles.begin() );
1479 : 0 : break;
1480 : : case 3: // lower right
1481 [ # # ]: 0 : vtx_handles.resize( 1 );
1482 [ # # ]: 0 : vtx_handles[0] = verts[2][2];
1483 : 0 : break;
1484 : : case -1: // lower left
1485 [ # # ]: 0 : vtx_handles.resize( 1 );
1486 [ # # ]: 0 : vtx_handles[0] = verts[0][2];
1487 : 0 : break;
1488 : : case -2: // left
1489 [ # # ]: 0 : vtx_handles.resize( 3 );
1490 [ # # ]: 0 : std::copy( verts[0], verts[0] + 3, vtx_handles.begin() );
1491 : 0 : break;
1492 : : default:
1493 : 0 : vtx_handles.clear();
1494 : 0 : break;
1495 : : }
1496 : : }
1497 : :
1498 : 0 : return iBase_SUCCESS;
1499 : : }
1500 : :
1501 : : /**\brief Test querying of part boundary entities
1502 : : *
1503 : : * Test:
1504 : : * - iMeshP_getNumPartBdryEnts
1505 : : * - iMeshP_getPartBdryEnts
1506 : : */
1507 : 1 : int test_get_part_boundary( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map )
1508 : : {
1509 : : int ierr, rank;
1510 [ + - ]: 1 : MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1511 : :
1512 : : // get local part handles and part ids, and global part id list
1513 [ + - ]: 1 : std::vector< iMeshP_PartHandle > local_handles;
1514 [ + - ]: 2 : std::vector< iMeshP_Part > local_ids;
1515 [ + - ][ + - ]: 2 : std::vector< iMeshP_Part > all_parts = map.get_parts();
1516 [ + - ]: 2 : std::map< iMeshP_PartHandle, std::vector< iBase_EntityHandle > > part_bdry;
1517 [ + - ][ - + ]: 1 : ierr = get_local_parts( imesh, prtn, local_handles, &local_ids );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1518 : :
1519 : : // for each combination of local part with any other part,
1520 : : // check for valid function values.
1521 [ + - ][ + - ]: 2 : std::vector< std::pair< iMeshP_Part, iMeshP_Part > > num_failed, num_error, list_failed, list_error, error;
[ + - ][ + - ]
[ + - ]
1522 [ + + ]: 2 : for( size_t i = 0; i < local_handles.size(); ++i )
1523 : : {
1524 [ + - ]: 1 : iMeshP_PartHandle local_handle = local_handles[i];
1525 [ + - ]: 1 : iMeshP_Part local_id = local_ids[i];
1526 [ + - ][ + - ]: 2 : for( std::vector< iMeshP_Part >::iterator j = all_parts.begin(); j != all_parts.end(); ++j )
[ + + ]
1527 : : {
1528 [ + - ]: 1 : iMeshP_Part other_id = *j;
1529 [ + - ]: 1 : if( other_id == local_id ) continue;
1530 : :
1531 : 0 : std::pair< iMeshP_Part, iMeshP_Part > part_pair;
1532 : 0 : part_pair.first = local_id;
1533 : 0 : part_pair.second = other_id;
1534 : :
1535 : : // get expected values
1536 [ # # ]: 0 : std::vector< iBase_EntityHandle > shared_verts;
1537 [ # # ]: 0 : ierr = interface_verts( imesh, prtn, local_handle, other_id, map, shared_verts );
1538 [ # # ]: 0 : if( ierr != iBase_SUCCESS )
1539 : : {
1540 [ # # ]: 0 : error.push_back( part_pair );
1541 : 0 : continue;
1542 : : }
1543 [ # # ]: 0 : std::sort( shared_verts.begin(), shared_verts.end() );
1544 : :
1545 : : // test iMeshP_getNumPartBdryEnts
1546 : : int count;
1547 [ # # ]: 0 : iMeshP_getNumPartBdryEnts( imesh, prtn, local_handle, iBase_VERTEX, iMesh_POINT, other_id, &count, &ierr );
1548 [ # # ]: 0 : if( iBase_SUCCESS != ierr )
1549 [ # # ]: 0 : num_error.push_back( part_pair );
1550 [ # # ]: 0 : else if( count != (int)shared_verts.size() )
1551 [ # # ]: 0 : num_failed.push_back( part_pair );
1552 : :
1553 : : // test iMeshP_getPartBdryEnts
1554 : 0 : iBase_EntityHandle* ptr = 0;
1555 : 0 : int junk = 0;
1556 : : iMeshP_getPartBdryEnts( imesh, prtn, local_handle, iBase_VERTEX, iMesh_POINT, other_id, &ptr, &junk, &count,
1557 [ # # ]: 0 : &ierr );
1558 [ # # ]: 0 : if( iBase_SUCCESS != ierr )
1559 [ # # ]: 0 : list_error.push_back( part_pair );
1560 : : else
1561 : : {
1562 [ # # ][ # # ]: 0 : std::copy( ptr, ptr + count, std::back_inserter( part_bdry[local_handles[i]] ) );
[ # # ][ # # ]
1563 [ # # ]: 0 : std::sort( ptr, ptr + count );
1564 [ # # ][ # # ]: 0 : if( (int)shared_verts.size() != count || !std::equal( shared_verts.begin(), shared_verts.end(), ptr ) )
[ # # ][ # # ]
1565 [ # # ]: 0 : list_failed.push_back( part_pair );
1566 [ # # ]: 0 : free( ptr );
1567 : : }
1568 : 0 : }
1569 : : }
1570 : :
1571 [ - + ]: 1 : if( !error.empty() )
1572 : : {
1573 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
[ # # ][ # # ]
[ # # ]
1574 [ # # ][ # # ]: 0 : << " Internal error for " << error.size() << " part pairs." << std::endl;
[ # # ][ # # ]
1575 : 0 : ierr = iBase_FAILURE;
1576 : : }
1577 [ - + ]: 1 : if( !num_error.empty() )
1578 : : {
1579 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
[ # # ][ # # ]
[ # # ]
1580 [ # # ][ # # ]: 0 : << " iMeshP_getNumPartBdryEnts return error for " << num_error.size() << " part pairs." << std::endl;
[ # # ][ # # ]
1581 : 0 : ierr = iBase_FAILURE;
1582 : : }
1583 [ - + ]: 1 : if( !list_error.empty() )
1584 : : {
1585 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
[ # # ][ # # ]
[ # # ]
1586 [ # # ][ # # ]: 0 : << " iMeshP_getPartBdryEnts return error for " << list_error.size() << " part pairs." << std::endl;
[ # # ][ # # ]
1587 : 0 : ierr = iBase_FAILURE;
1588 : : }
1589 [ - + ]: 1 : if( !num_failed.empty() )
1590 : : {
1591 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
[ # # ][ # # ]
[ # # ]
1592 [ # # ][ # # ]: 0 : << " iMeshP_getNumPartBdryEnts return incorrect results for " << num_failed.size() << " part pairs."
[ # # ]
1593 [ # # ]: 0 : << std::endl;
1594 : 0 : ierr = iBase_FAILURE;
1595 : : }
1596 [ - + ]: 1 : if( !list_failed.empty() )
1597 : : {
1598 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
[ # # ][ # # ]
[ # # ]
1599 [ # # ][ # # ]: 0 : << " iMeshP_getPartBdryEnts return incorrect results for " << list_failed.size() << " part pairs."
[ # # ]
1600 [ # # ]: 0 : << std::endl;
1601 : 0 : ierr = iBase_FAILURE;
1602 : : }
1603 : :
1604 [ - + ]: 1 : if( iBase_SUCCESS != ierr ) return ierr;
1605 : :
1606 : : // test with iMeshP_ALL_PARTS
1607 [ + + ]: 2 : for( size_t i = 0; i < local_handles.size(); ++i )
1608 : : {
1609 [ + - ][ + - ]: 1 : std::vector< iBase_EntityHandle >& exp_bdry = part_bdry[local_handles[i]];
1610 [ + - ]: 1 : std::sort( exp_bdry.begin(), exp_bdry.end() );
1611 [ + - ][ + - ]: 1 : exp_bdry.erase( std::unique( exp_bdry.begin(), exp_bdry.end() ), exp_bdry.end() );
1612 : 1 : std::pair< iMeshP_Part, iMeshP_Part > part_pair;
1613 [ + - ]: 1 : part_pair.first = local_ids[i];
1614 : 1 : part_pair.second = iMeshP_ALL_PARTS;
1615 : :
1616 : 1 : int num = 0;
1617 [ + - ]: 1 : iMeshP_getNumPartBdryEnts( imesh, prtn, local_handles[i], iBase_VERTEX, iMesh_POINT, iMeshP_ALL_PARTS, &num,
1618 [ + - ]: 1 : &ierr );
1619 [ - + ]: 1 : if( ierr )
1620 [ # # ]: 0 : num_error.push_back( part_pair );
1621 [ - + ]: 1 : else if( num != (int)exp_bdry.size() )
1622 [ # # ]: 0 : num_failed.push_back( part_pair );
1623 : :
1624 : 1 : iBase_EntityHandle* bdry = 0;
1625 : 1 : int junk = num = 0;
1626 [ + - ]: 1 : iMeshP_getPartBdryEnts( imesh, prtn, local_handles[i], iBase_VERTEX, iMesh_POINT, iMeshP_ALL_PARTS, &bdry,
1627 [ + - ]: 1 : &junk, &num, &ierr );
1628 [ - + ]: 1 : if( ierr )
1629 [ # # ]: 0 : list_error.push_back( part_pair );
1630 : : else
1631 : : {
1632 [ + - ]: 1 : std::sort( bdry, bdry + num );
1633 [ + - ][ + - ]: 1 : if( num != (int)exp_bdry.size() || !std::equal( bdry, bdry + num, exp_bdry.begin() ) )
[ - + ][ - + ]
1634 [ # # ]: 0 : list_failed.push_back( part_pair );
1635 : 1 : free( bdry );
1636 : : }
1637 : : }
1638 [ - + ]: 1 : if( !num_error.empty() )
1639 : : {
1640 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
[ # # ][ # # ]
[ # # ]
1641 [ # # ][ # # ]: 0 : << " iMeshP_getNumPartBdryEnts return error for " << num_error.size() << " part pairs." << std::endl;
[ # # ][ # # ]
1642 : 0 : ierr = iBase_FAILURE;
1643 : : }
1644 [ - + ]: 1 : if( !list_error.empty() )
1645 : : {
1646 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
[ # # ][ # # ]
[ # # ]
1647 [ # # ][ # # ]: 0 : << " iMeshP_getPartBdryEnts return error for " << list_error.size() << " part pairs." << std::endl;
[ # # ][ # # ]
1648 : 0 : ierr = iBase_FAILURE;
1649 : : }
1650 [ - + ]: 1 : if( !num_failed.empty() )
1651 : : {
1652 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
[ # # ][ # # ]
[ # # ]
1653 [ # # ][ # # ]: 0 : << " iMeshP_getNumPartBdryEnts return incorrect results for " << num_failed.size() << " part pairs."
[ # # ]
1654 [ # # ]: 0 : << std::endl;
1655 : 0 : ierr = iBase_FAILURE;
1656 : : }
1657 [ - + ]: 1 : if( !list_failed.empty() )
1658 : : {
1659 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
[ # # ][ # # ]
[ # # ]
1660 [ # # ][ # # ]: 0 : << " iMeshP_getPartBdryEnts return incorrect results for " << list_failed.size() << " part pairs."
[ # # ]
1661 [ # # ]: 0 : << std::endl;
1662 : 0 : ierr = iBase_FAILURE;
1663 : : }
1664 : :
1665 : 2 : return ierr;
1666 : : }
1667 : :
1668 : : /**\brief Test querying of part boundary entities
1669 : : *
1670 : : * Test:
1671 : : * - iMeshP_initPartBdryEntIter
1672 : : * - iMeshP_initPartBdryEntArrIter
1673 : : */
1674 : 1 : int test_part_boundary_iter( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map )
1675 : : {
1676 : : int ierr, rank, has_data;
1677 [ + - ]: 1 : MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1678 : :
1679 : : // get local part handles and part ids, and global part id list
1680 [ + - ]: 1 : std::vector< iMeshP_PartHandle > local_handles;
1681 [ + - ]: 2 : std::vector< iMeshP_Part > local_ids;
1682 [ + - ][ + - ]: 2 : std::vector< iMeshP_Part > all_parts = map.get_parts();
1683 [ + - ][ - + ]: 1 : ierr = get_local_parts( imesh, prtn, local_handles, &local_ids );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1684 : :
1685 [ + - ][ + - ]: 2 : std::vector< std::pair< iMeshP_Part, iMeshP_Part > > single_failed, single_error, single_step_error, array_failed,
[ + - ][ + - ]
1686 [ + - ][ + - ]: 2 : array_error, array_step_error;
1687 [ + + ]: 2 : for( size_t i = 0; i < local_handles.size(); ++i )
1688 : : {
1689 [ + - ]: 1 : iMeshP_PartHandle local_handle = local_handles[i];
1690 [ + - ]: 1 : iMeshP_Part local_id = local_ids[i];
1691 [ + - ][ + - ]: 2 : for( std::vector< iMeshP_Part >::iterator j = all_parts.begin(); j != all_parts.end(); ++j )
[ + + ]
1692 : : {
1693 [ + - ]: 1 : iMeshP_Part other_id = *j;
1694 [ + - ]: 1 : if( other_id == local_id ) continue;
1695 : :
1696 : 0 : std::pair< iMeshP_Part, iMeshP_Part > part_pair;
1697 : 0 : part_pair.first = local_id;
1698 : 0 : part_pair.second = other_id;
1699 : :
1700 : : // get expected values
1701 [ # # ]: 0 : std::vector< iBase_EntityHandle > shared_verts;
1702 [ # # ]: 0 : ierr = interface_verts( imesh, prtn, local_handle, other_id, map, shared_verts );
1703 [ # # ][ # # ]: 0 : if( ierr != iBase_SUCCESS || 0 == shared_verts.size() ) continue;
[ # # ]
1704 [ # # ]: 0 : std::sort( shared_verts.begin(), shared_verts.end() );
1705 : :
1706 : : // test single entity iterator
1707 : : iBase_EntityIterator siter;
1708 [ # # ]: 0 : iMeshP_initPartBdryEntIter( imesh, prtn, local_handle, iBase_VERTEX, iMesh_POINT, other_id, &siter, &ierr );
1709 [ # # ][ # # ]: 0 : if( ierr != iBase_SUCCESS ) { single_error.push_back( part_pair ); }
1710 : : else
1711 : : {
1712 [ # # ]: 0 : std::vector< iBase_EntityHandle > results;
1713 : : for( ;; )
1714 : : {
1715 : : iBase_EntityHandle handle;
1716 [ # # ]: 0 : iMesh_getNextEntIter( imesh, siter, &handle, &has_data, &ierr );
1717 [ # # ]: 0 : if( ierr != iBase_SUCCESS )
1718 : : {
1719 [ # # ]: 0 : single_step_error.push_back( part_pair );
1720 : 0 : break;
1721 : : }
1722 [ # # ]: 0 : if( !has_data ) break;
1723 [ # # ]: 0 : results.push_back( handle );
1724 : 0 : }
1725 : :
1726 [ # # ]: 0 : std::sort( results.begin(), results.end() );
1727 [ # # ][ # # ]: 0 : if( results.size() != shared_verts.size() ||
[ # # ]
1728 [ # # ]: 0 : !std::equal( results.begin(), results.end(), shared_verts.begin() ) )
1729 [ # # ]: 0 : single_failed.push_back( part_pair );
1730 : : }
1731 [ # # ]: 0 : iMesh_endEntIter( imesh, siter, &ierr );
1732 : :
1733 : : // test array iterator
1734 : : iBase_EntityArrIterator aiter;
1735 : 0 : iMeshP_initPartBdryEntArrIter( imesh, prtn, local_handle, iBase_VERTEX, iMesh_POINT, shared_verts.size(),
1736 [ # # ]: 0 : other_id, &aiter, &ierr );
1737 [ # # ]: 0 : if( ierr != iBase_SUCCESS )
1738 : : {
1739 [ # # ]: 0 : array_error.push_back( part_pair );
1740 [ # # ]: 0 : iMesh_endEntArrIter( imesh, aiter, &ierr );
1741 : 0 : continue;
1742 : : }
1743 : 0 : iBase_EntityHandle results[5], *ptr = results;
1744 : 0 : int junk = 5, count;
1745 [ # # ]: 0 : iMesh_getNextEntArrIter( imesh, aiter, &ptr, &junk, &count, &has_data, &ierr );
1746 [ # # ][ # # ]: 0 : if( ierr != iBase_SUCCESS || !has_data )
1747 : : {
1748 [ # # ]: 0 : array_step_error.push_back( part_pair );
1749 [ # # ]: 0 : iMesh_endEntArrIter( imesh, aiter, &ierr );
1750 : 0 : continue;
1751 : : }
1752 [ # # ]: 0 : iMesh_endEntArrIter( imesh, aiter, &ierr );
1753 [ # # ]: 0 : assert( count <= 5 );
1754 [ # # ]: 0 : assert( ptr == results );
1755 [ # # ]: 0 : std::sort( ptr, ptr + count );
1756 [ # # ][ # # ]: 0 : if( count != (int)shared_verts.size() || !std::equal( shared_verts.begin(), shared_verts.end(), results ) )
[ # # ][ # # ]
1757 [ # # ][ # # ]: 0 : array_failed.push_back( part_pair );
1758 : 0 : }
1759 : : }
1760 : :
1761 [ - + ]: 1 : if( !single_error.empty() )
1762 : : {
1763 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
[ # # ][ # # ]
[ # # ]
1764 [ # # ][ # # ]: 0 : << " iMeshP_initPartBdryEntIter return error for " << single_error.size() << " part pairs."
[ # # ]
1765 [ # # ]: 0 : << std::endl;
1766 : 0 : ierr = iBase_FAILURE;
1767 : : }
1768 [ - + ]: 1 : if( !single_step_error.empty() )
1769 : : {
1770 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
[ # # ][ # # ]
[ # # ]
1771 [ # # ][ # # ]: 0 : << " iMesh_getNextEntIter return error for " << single_step_error.size() << " part pairs."
[ # # ]
1772 [ # # ]: 0 : << std::endl;
1773 : 0 : ierr = iBase_FAILURE;
1774 : : }
1775 [ - + ]: 1 : if( !single_failed.empty() )
1776 : : {
1777 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
[ # # ][ # # ]
[ # # ]
1778 [ # # ][ # # ]: 0 : << " iMeshP_initPartBdryEntIter iterator iterated over invalid entities for " << single_failed.size()
1779 [ # # ][ # # ]: 0 : << " part pairs." << std::endl;
1780 : 0 : ierr = iBase_FAILURE;
1781 : : }
1782 : :
1783 [ - + ]: 1 : if( !array_error.empty() )
1784 : : {
1785 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
[ # # ][ # # ]
[ # # ]
1786 [ # # ][ # # ]: 0 : << " iMeshP_initPartBdryEntArrIter return error for " << array_error.size() << " part pairs."
[ # # ]
1787 [ # # ]: 0 : << std::endl;
1788 : 0 : ierr = iBase_FAILURE;
1789 : : }
1790 [ - + ]: 1 : if( !array_step_error.empty() )
1791 : : {
1792 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
[ # # ][ # # ]
[ # # ]
1793 [ # # ][ # # ]: 0 : << " iMesh_getNextEntArrIter return error for " << array_step_error.size() << " part pairs."
[ # # ]
1794 [ # # ]: 0 : << std::endl;
1795 : 0 : ierr = iBase_FAILURE;
1796 : : }
1797 [ - + ]: 1 : if( !array_failed.empty() )
1798 : : {
1799 [ # # ][ # # ]: 0 : std::cerr << "Processor " << rank << ": Error at " __FILE__ ":" << __LINE__ << std::endl
[ # # ][ # # ]
[ # # ]
1800 [ # # ]: 0 : << " iMeshP_initPartBdryEntArrIter iterator iterated over invalid entities for "
1801 [ # # ][ # # ]: 0 : << array_failed.size() << " part pairs." << std::endl;
[ # # ]
1802 : 0 : ierr = iBase_FAILURE;
1803 : : }
1804 : :
1805 : 1 : return ierr;
1806 : : }
1807 : :
1808 : : /**\brief Test adjacent entity query
1809 : : *
1810 : : * Test:
1811 : : * - iMeshP_getAdjEntities
1812 : : */
1813 : 1 : int test_get_adjacencies( iMesh_Instance /* imesh */, iMeshP_PartitionHandle /* prtn */, const PartMap& )
1814 : : {
1815 : 1 : return iBase_SUCCESS;
1816 : : }
1817 : :
1818 : : /**\brief Test entity iterators
1819 : : *
1820 : : * Test:
1821 : : * - iMeshP_initEntIter
1822 : : * - iMeshP_initEntArrIter
1823 : : */
1824 : 1 : int test_entity_iterator( iMesh_Instance /*imesh */, iMeshP_PartitionHandle /*prtn*/, const PartMap& )
1825 : : {
1826 : 1 : return iBase_SUCCESS;
1827 : : }
1828 : :
1829 : : /**\brief Test entity owner queries
1830 : : *
1831 : : * Test:
1832 : : * - iMeshP_getEntOwnerPart
1833 : : * - iMeshP_getEntOwnerPartArr
1834 : : * - iMeshP_isEntOwner
1835 : : * - iMeshP_isEntOwnerArr
1836 : : */
1837 : 1 : int test_entity_owner( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& /* map */ )
1838 : : {
1839 : : int ierr, rank, size;
1840 [ + - ]: 1 : MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1841 [ + - ]: 1 : MPI_Comm_size( MPI_COMM_WORLD, &size );
1842 : :
1843 : : // get local part handles and part ids
1844 [ + - ]: 1 : std::vector< iMeshP_PartHandle > local_handles;
1845 [ + - ]: 2 : std::vector< iMeshP_Part > local_ids;
1846 [ + - ]: 1 : ierr = get_local_parts( imesh, prtn, local_handles, &local_ids );
1847 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1848 : :
1849 : : // test iMeshP_getEntOwnerPart for quads in each part
1850 [ + - ]: 2 : std::vector< iBase_EntityHandle > all_quads;
1851 [ + - ]: 2 : std::vector< iMeshP_Part > quad_owners;
1852 : 1 : int invalid_count = 0;
1853 [ + + ]: 2 : for( size_t i = 0; i < local_handles.size(); ++i )
1854 : : {
1855 [ + - ]: 1 : std::vector< iBase_EntityHandle > quads;
1856 [ + - ][ + - ]: 1 : ierr = get_entities( imesh, local_handles[0], iBase_FACE, iMesh_QUADRILATERAL, quads );
1857 [ - + ]: 1 : if( ierr ) break;
1858 : :
1859 [ + + ]: 5 : for( size_t j = 0; j < quads.size(); ++j )
1860 : : {
1861 [ + - ][ + - ]: 4 : all_quads.push_back( quads[j] );
1862 [ + - ][ + - ]: 4 : quad_owners.push_back( local_ids[i] );
1863 : : iMeshP_Part owner;
1864 [ + - ][ + - ]: 4 : iMeshP_getEntOwnerPart( imesh, prtn, quads[j], &owner, &ierr );
1865 [ - + ]: 4 : if( iBase_SUCCESS != ierr ) break;
1866 : :
1867 [ + - ][ - + ]: 4 : if( owner != local_ids[i] ) ++invalid_count;
1868 : : }
1869 [ - + ][ + - ]: 1 : if( iBase_SUCCESS != ierr ) break;
1870 : 1 : }
1871 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1872 [ + - ][ - + ]: 1 : ASSERT( 0 == invalid_count );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1873 : :
1874 : : // test iMeshP_getEntOwnerPartArr for quads in each part
1875 : 1 : invalid_count = 0;
1876 [ + + ]: 2 : for( size_t i = 0; i < local_handles.size(); ++i )
1877 : : {
1878 [ + - ]: 1 : std::vector< iBase_EntityHandle > quads;
1879 [ + - ][ + - ]: 1 : ierr = get_entities( imesh, local_handles[0], iBase_FACE, iMesh_QUADRILATERAL, quads );
1880 [ - + ]: 1 : if( ierr ) break;
1881 : :
1882 [ + - ][ + - ]: 2 : std::vector< iMeshP_Part > owners( quads.size() ), expected( quads.size(), local_ids[i] );
[ + - ][ + - ]
[ + - ]
1883 : 1 : int junk = owners.size(), count;
1884 [ + - ]: 1 : iMeshP_Part* ptr = &owners[0];
1885 [ + - ][ + - ]: 1 : iMeshP_getEntOwnerPartArr( imesh, prtn, &quads[0], quads.size(), &ptr, &junk, &count, &ierr );
1886 [ - + ]: 1 : if( ierr ) break;
1887 [ + - ][ - + ]: 1 : assert( ptr == &owners[0] );
1888 [ - + ]: 1 : assert( junk == (int)owners.size() );
1889 [ - + ]: 1 : assert( count == (int)quads.size() );
1890 [ + - ][ - + ]: 1 : if( owners != expected ) ++invalid_count;
[ + - ]
1891 : 1 : }
1892 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1893 [ + - ][ - + ]: 1 : ASSERT( 0 == invalid_count );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1894 : :
1895 : : // get all vertices
1896 : 1 : iBase_EntityHandle* vtx_arr = 0;
1897 : 1 : int junk1 = 0, num_vtx;
1898 : 1 : int *junk2 = 0, junk3 = 0, junk4;
1899 [ + - ]: 1 : iMesh_getEntArrAdj( imesh, &all_quads[0], all_quads.size(), iBase_VERTEX, &vtx_arr, &junk1, &num_vtx, &junk2,
1900 [ + - ]: 1 : &junk3, &junk4, &ierr );
1901 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1902 : 1 : free( junk2 );
1903 [ + - ]: 1 : std::sort( vtx_arr, vtx_arr + num_vtx );
1904 [ + - ]: 1 : num_vtx = std::unique( vtx_arr, vtx_arr + num_vtx ) - vtx_arr;
1905 [ + - ]: 2 : std::vector< iBase_EntityHandle > all_verts( vtx_arr, vtx_arr + num_vtx );
1906 : 1 : free( vtx_arr );
1907 : :
1908 : : // check consistency between iMeshP_getEntOwnerPart and iMeshP_getEntOwnerPartArr
1909 : : // for all vertices
1910 [ + - ]: 2 : std::vector< iMeshP_Part > vert_owners( all_verts.size() );
1911 : 1 : junk1 = vert_owners.size();
1912 [ + - ]: 1 : iMeshP_Part* junk5 = &vert_owners[0];
1913 [ + - ][ + - ]: 1 : iMeshP_getEntOwnerPartArr( imesh, prtn, &all_verts[0], all_verts.size(), &junk5, &junk1, &junk3, &ierr );
1914 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1915 [ + - ][ - + ]: 1 : assert( junk5 == &vert_owners[0] );
1916 [ - + ]: 1 : assert( junk1 == (int)vert_owners.size() );
1917 [ - + ]: 1 : assert( junk3 == (int)all_verts.size() );
1918 : :
1919 : 1 : invalid_count = 0;
1920 [ + + ]: 10 : for( size_t i = 0; i < all_verts.size(); ++i )
1921 : : {
1922 : : iMeshP_Part owner;
1923 [ + - ][ + - ]: 9 : iMeshP_getEntOwnerPart( imesh, prtn, all_verts[i], &owner, &ierr );
1924 [ + - ][ + - ]: 9 : if( iBase_SUCCESS != ierr || owner != vert_owners[i] ) ++invalid_count;
[ - + ][ - + ]
1925 : : }
1926 [ + - ][ - + ]: 1 : ASSERT( 0 == invalid_count );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1927 : :
1928 : : // get lists for all entities
1929 [ + - ]: 2 : std::vector< iBase_EntityHandle > all_entities( all_verts );
1930 [ + - ][ + - ]: 1 : std::copy( all_quads.begin(), all_quads.end(), std::back_inserter( all_entities ) );
1931 [ + - ]: 2 : std::vector< iMeshP_Part > all_owners( vert_owners );
1932 [ + - ][ + - ]: 1 : std::copy( quad_owners.begin(), quad_owners.end(), std::back_inserter( all_owners ) );
1933 : :
1934 : : // check consistency of iMeshP_isEntOwner for all entities
1935 : 1 : invalid_count = 0;
1936 : 1 : ierr = iBase_SUCCESS;
1937 [ + + ]: 2 : for( size_t i = 0; i < local_handles.size(); ++i )
1938 : : {
1939 [ + - ][ + + ]: 14 : for( size_t j = 0; ierr == iBase_SUCCESS && j < all_entities.size(); ++j )
[ + + ]
1940 : : {
1941 : : int is_owner;
1942 [ + - ][ + - ]: 13 : iMeshP_isEntOwner( imesh, prtn, local_handles[i], all_entities[j], &is_owner, &ierr );
[ + - ]
1943 [ - + ]: 13 : if( ierr != iBase_SUCCESS ) break;
1944 [ + - ][ + - ]: 13 : if( !is_owner == ( local_ids[i] == all_owners[j] ) ) ++invalid_count;
[ - + ]
1945 : : }
1946 : : }
1947 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1948 [ + - ][ - + ]: 1 : ASSERT( 0 == invalid_count );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1949 : :
1950 : : // check consistency of iMeshP_isEntOwnerArr for all entities
1951 [ + + ]: 2 : for( size_t i = 0; i < local_handles.size(); ++i )
1952 : : {
1953 [ + - ]: 1 : std::vector< int > is_owner_list( all_entities.size() );
1954 : 1 : junk1 = is_owner_list.size();
1955 [ + - ]: 1 : int* junk6 = &is_owner_list[0];
1956 [ + - ][ + - ]: 1 : iMeshP_isEntOwnerArr( imesh, prtn, local_handles[i], &all_entities[0], all_entities.size(), &junk6, &junk1,
1957 [ + - ]: 1 : &junk3, &ierr );
1958 [ - + ]: 1 : if( iBase_SUCCESS != ierr ) break;
1959 [ + - ][ - + ]: 1 : assert( junk6 == &is_owner_list[0] );
1960 [ - + ]: 1 : assert( junk1 == (int)is_owner_list.size() );
1961 [ - + ]: 1 : assert( junk3 == (int)all_entities.size() );
1962 : 1 : invalid_count = 0;
1963 [ + + ][ + - ]: 14 : for( size_t j = 0; j < all_entities.size(); ++j )
1964 : : {
1965 [ + - ][ + - ]: 13 : if( !( is_owner_list[j] ) == ( local_ids[0] == all_owners[j] ) ) ++invalid_count;
[ + - ][ - + ]
1966 : : }
1967 : 1 : }
1968 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1969 [ + - ][ - + ]: 1 : ASSERT( 0 == invalid_count );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1970 : :
1971 : : // check globally consistent owners for all vertices
1972 : :
1973 : : // first communicate total number of vertex entries to be sent to root proc
1974 : 1 : int local_count = all_verts.size(), global_count = 0;
1975 [ + - ][ - + ]: 1 : ierr = MPI_Reduce( &local_count, &global_count, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1976 : :
1977 : : // for each vertex, store { (x << 2) | y, owning part id }
1978 [ + - ]: 2 : std::vector< int > vtxdata( 2 * all_verts.size() );
1979 [ + - ]: 2 : std::vector< double > coords( 3 * all_verts.size() );
1980 [ + - ][ + - ]: 1 : ierr = get_coords( imesh, &all_verts[0], all_verts.size(), &coords[0] );CHKERR;
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1981 [ + + ]: 10 : for( size_t i = 0; i < all_verts.size(); ++i )
1982 : : {
1983 [ + - ]: 9 : int x = (int)round( coords[3 * i] );
1984 [ + - ]: 9 : int y = (int)round( coords[3 * i + 1] );
1985 [ + - ]: 9 : vtxdata[2 * i] = ( x << 3 ) | y;
1986 [ + - ][ + - ]: 9 : vtxdata[2 * i + 1] = vert_owners[i];
1987 : : }
1988 : :
1989 : : // collect all data on root procesor
1990 [ + - ]: 2 : std::vector< int > all_data( 2 * global_count );
1991 [ + - ][ + - ]: 2 : std::vector< int > displ( size ), counts( size );
1992 [ + + ]: 2 : for( int i = 0; i < size; i++ )
1993 : : {
1994 [ + - ]: 1 : counts[i] = vtxdata.size();
1995 [ + - ]: 1 : displ[i] = i * vtxdata.size();
1996 : : }
1997 : :
1998 : : // we could have used a simple gather, because all sequences are the same
1999 [ + - ][ + - ]: 1 : ierr = MPI_Gatherv( &vtxdata[0], vtxdata.size(), MPI_INT, &all_data[0], &counts[0], &displ[0], MPI_INT, 0,
[ + - ][ + - ]
2000 [ + - ][ - + ]: 1 : MPI_COMM_WORLD );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2001 : :
2002 [ + - ]: 1 : if( rank == 0 )
2003 : : {
2004 : : // map from vertex tag to indices into data
2005 [ + - ]: 1 : std::multimap< int, int > data_map;
2006 [ + + ]: 10 : for( int i = 0; i < global_count; ++i )
2007 : : {
2008 : 9 : std::pair< int, int > p;
2009 [ + - ]: 9 : p.first = all_data[2 * i];
2010 : 9 : p.second = i;
2011 [ + - ]: 9 : data_map.insert( p );
2012 : : }
2013 : :
2014 : : // check consistent data for each vtx
2015 [ + - ][ + - ]: 1 : std::multimap< int, int >::const_iterator a, b;
2016 [ + - ][ + - ]: 10 : for( a = data_map.begin(); a != data_map.end(); a = b )
[ + - ][ + + ]
2017 : : {
2018 [ + - ][ + - ]: 18 : for( b = a; b != data_map.end() && a->first == b->first; ++b )
[ + - ][ + + ]
[ + - ][ + - ]
[ + + ][ + - ]
[ + - ][ + +
# # # # ]
2019 : : {
2020 [ + - ]: 9 : int idx1 = a->second;
2021 [ + - ]: 9 : int idx2 = b->second;
2022 [ + - ][ + - ]: 9 : if( all_data[2 * idx1 + 1] == all_data[2 * idx2 + 1] ) continue;
[ + - ]
2023 : :
2024 : 0 : ierr = iBase_FAILURE;
2025 : :
2026 [ # # ][ # # ]: 0 : int proc1 = std::lower_bound( displ.begin(), displ.end(), 2 * idx1 ) - displ.begin();
2027 [ # # ][ # # ]: 0 : if( displ[proc1] != 2 * idx1 ) ++proc1;
2028 [ # # ][ # # ]: 0 : int proc2 = std::lower_bound( displ.begin(), displ.end(), 2 * idx2 ) - displ.begin();
2029 [ # # ][ # # ]: 0 : if( displ[proc2] != 2 * idx2 ) ++proc2;
2030 : :
2031 [ # # ][ # # ]: 0 : std::cerr << "Error at " __FILE__ ":" << __LINE__ << " : " << std::endl
[ # # ][ # # ]
2032 [ # # ][ # # ]: 0 : << " For vertex at (" << ( a->first >> 2 ) << ", " << ( a->first & 3 ) << ") :" << std::endl
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2033 [ # # ][ # # ]: 0 : << " Processor " << proc1 << " has " << all_data[2 * idx1 + 1] << " as the owning part"
[ # # ][ # # ]
[ # # ][ # # ]
2034 [ # # ]: 0 : << std::endl
2035 [ # # ][ # # ]: 0 : << " Processor " << proc2 << " has " << all_data[2 * idx2 + 1] << " as the owning part"
[ # # ][ # # ]
[ # # ][ # # ]
2036 [ # # ]: 0 : << std::endl;
2037 : : }
2038 : 1 : }
2039 : : }
2040 : :
2041 : 2 : return ierr;
2042 : : }
2043 : :
2044 : 1 : static int get_part_boundary_verts( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map,
2045 : : iMeshP_PartHandle part, std::vector< iBase_EntityHandle >& boundary )
2046 : : {
2047 : : int ierr, logical_id;
2048 [ + - ][ - + ]: 1 : ierr = map.part_from_coords( imesh, part, logical_id );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2049 : :
2050 : : int neighbors[5], num_neighbors;
2051 [ + - ]: 1 : get_part_neighbors( logical_id, map.get_parts().size(), neighbors, num_neighbors );
2052 : :
2053 [ - + ]: 1 : for( int j = 0; j < num_neighbors; ++j )
2054 : : {
2055 [ # # ]: 0 : std::vector< iBase_EntityHandle > iface;
2056 [ # # ][ # # ]: 0 : ierr = interface_verts( imesh, prtn, part, neighbors[j], map, iface );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2057 [ # # ][ # # ]: 0 : std::copy( iface.begin(), iface.end(), std::back_inserter( boundary ) );
[ # # ]
2058 : 0 : }
2059 : :
2060 [ + - ]: 1 : std::sort( boundary.begin(), boundary.end() );
2061 [ + - ][ + - ]: 1 : boundary.erase( std::unique( boundary.begin(), boundary.end() ), boundary.end() );
2062 : 1 : return iBase_SUCCESS;
2063 : : }
2064 : :
2065 : : /**\brief Test entity status
2066 : : *
2067 : : * Test:
2068 : : * - iMeshP_getEntStatus
2069 : : * - iMeshP_getEntStatusArr
2070 : : */
2071 : 1 : int test_entity_status( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map )
2072 : : {
2073 : : int ierr, rank, size;
2074 [ + - ]: 1 : MPI_Comm_rank( MPI_COMM_WORLD, &rank );
2075 [ + - ]: 1 : MPI_Comm_size( MPI_COMM_WORLD, &size );
2076 : :
2077 : : // get local part handles
2078 [ + - ]: 1 : std::vector< iMeshP_PartHandle > parts;
2079 [ + - ]: 1 : ierr = get_local_parts( imesh, prtn, parts );
2080 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2081 : :
2082 : : // for each part
2083 : 1 : int num_quad_ent_incorrect = 0, num_quad_ent_error = 0;
2084 : 1 : int num_quad_arr_incorrect = 0, num_quad_arr_error = 0;
2085 : 1 : int num_vert_ent_incorrect = 0, num_vert_ent_error = 0;
2086 : 1 : int num_vert_arr_incorrect = 0, num_vert_arr_error = 0;
2087 [ + + ]: 2 : for( size_t i = 0; i < parts.size(); ++i )
2088 : : {
2089 [ + - ]: 1 : const iMeshP_PartHandle part = parts[i];
2090 : :
2091 : : // get quads and vertices
2092 [ + - ][ + - ]: 2 : std::vector< iBase_EntityHandle > quads, verts;
[ + - - ]
2093 [ + - ]: 1 : ierr = get_part_quads_and_verts( imesh, part, quads, verts );
2094 [ - + ]: 1 : if( ierr ) break;
2095 : :
2096 : : // check quad status (no ghosting yet)
2097 [ + + ]: 5 : for( size_t j = 0; j < quads.size(); ++j )
2098 : : {
2099 : : int status;
2100 [ + - ][ + - ]: 4 : iMeshP_getEntStatus( imesh, prtn, part, quads[j], &status, &ierr );
2101 [ - + ]: 4 : if( ierr != iBase_SUCCESS )
2102 : : {
2103 : 0 : ++num_quad_ent_error;
2104 : 0 : ierr = iBase_SUCCESS;
2105 : 0 : continue;
2106 : : }
2107 : :
2108 [ - + ]: 4 : if( status != iMeshP_INTERNAL ) ++num_quad_ent_incorrect;
2109 : : }
2110 : :
2111 : : // check quad status using iMeshP_getEntStatusArr
2112 [ + - ]: 2 : std::vector< int > stat_list( quads.size() );
[ + - - ]
2113 [ + - ]: 1 : int* junk1 = &stat_list[0];
2114 : 1 : int junk2 = stat_list.size(), count;
2115 [ + - ][ + - ]: 1 : iMeshP_getEntStatusArr( imesh, prtn, part, &quads[0], quads.size(), &junk1, &junk2, &count, &ierr );
2116 [ - + ]: 1 : if( ierr != iBase_SUCCESS )
2117 : : {
2118 : 0 : ++num_quad_arr_error;
2119 : 0 : ierr = iBase_SUCCESS;
2120 : 0 : continue;
2121 : : }
2122 [ + - ][ - + ]: 1 : assert( junk1 == &stat_list[0] );
2123 [ - + ]: 1 : assert( junk2 == (int)stat_list.size() );
2124 [ - + ]: 1 : assert( count == (int)quads.size() );
2125 [ + + ]: 5 : for( size_t j = 0; j < quads.size(); ++j )
2126 [ + - ][ - + ]: 4 : if( stat_list[j] != iMeshP_INTERNAL ) ++num_quad_arr_incorrect;
2127 : :
2128 : : // figure out which vertices are on the boundary
2129 [ + - ]: 2 : std::vector< iBase_EntityHandle > boundary;
[ + - - ]
2130 [ + - ]: 1 : ierr = get_part_boundary_verts( imesh, prtn, map, part, boundary );
2131 [ - + ]: 1 : if( ierr ) break;
2132 [ + - ]: 1 : std::sort( boundary.begin(), boundary.end() );
2133 : :
2134 : : // check vertex status (no ghosting yet)
2135 [ + + ]: 10 : for( size_t j = 0; j < verts.size(); ++j )
2136 : : {
2137 : : int status;
2138 [ + - ][ + - ]: 9 : iMeshP_getEntStatus( imesh, prtn, part, verts[j], &status, &ierr );
2139 [ - + ]: 9 : if( ierr != iBase_SUCCESS )
2140 : : {
2141 : 0 : ++num_vert_ent_error;
2142 : 0 : ierr = iBase_SUCCESS;
2143 : 0 : continue;
2144 : : }
2145 [ + - ][ + - ]: 9 : bool on_boundary = std::binary_search( boundary.begin(), boundary.end(), verts[j] );
2146 [ - + ][ - + ]: 9 : if( status != ( on_boundary ? iMeshP_BOUNDARY : iMeshP_INTERNAL ) ) ++num_vert_ent_incorrect;
2147 : : }
2148 : :
2149 : : // check vert status using iMeshP_getEntStatusArr
2150 [ + - ]: 1 : stat_list.resize( verts.size() );
2151 [ + - ]: 1 : junk1 = &stat_list[0];
2152 : 1 : junk2 = stat_list.size();
2153 [ + - ][ + - ]: 1 : iMeshP_getEntStatusArr( imesh, prtn, part, &verts[0], verts.size(), &junk1, &junk2, &count, &ierr );
2154 [ - + ]: 1 : if( ierr != iBase_SUCCESS )
2155 : : {
2156 : 0 : ++num_vert_arr_error;
2157 : 0 : ierr = iBase_SUCCESS;
2158 : 0 : continue;
2159 : : }
2160 [ + - ][ - + ]: 1 : assert( junk1 == &stat_list[0] );
2161 [ - + ]: 1 : assert( junk2 == (int)stat_list.size() );
2162 [ - + ]: 1 : assert( count == (int)verts.size() );
2163 [ + + ]: 10 : for( size_t j = 0; j < verts.size(); ++j )
[ + - - ]
2164 : : {
2165 [ + - ][ + - ]: 9 : bool on_boundary = std::binary_search( boundary.begin(), boundary.end(), verts[j] );
2166 [ + - ][ - + ]: 9 : if( stat_list[j] != ( on_boundary ? iMeshP_BOUNDARY : iMeshP_INTERNAL ) ) ++num_vert_arr_incorrect;
[ - + ]
2167 : : }
2168 : 1 : }
2169 [ + - ][ - + ]: 1 : PCHECK; // check if loop interrupted by any internal errors
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2170 : :
2171 [ + - ][ - + ]: 1 : ASSERT( 0 == num_quad_ent_error );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2172 [ + - ][ - + ]: 1 : ASSERT( 0 == num_quad_arr_error );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2173 [ + - ][ - + ]: 1 : ASSERT( 0 == num_vert_ent_error );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2174 [ + - ][ - + ]: 1 : ASSERT( 0 == num_vert_arr_error );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2175 [ + - ][ - + ]: 1 : ASSERT( 0 == num_quad_ent_incorrect );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2176 [ + - ][ - + ]: 1 : ASSERT( 0 == num_quad_arr_incorrect );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2177 [ + - ][ - + ]: 1 : ASSERT( 0 == num_vert_ent_incorrect );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2178 [ + - ][ - + ]: 1 : ASSERT( 0 == num_vert_arr_incorrect );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2179 : :
2180 : 1 : return iBase_SUCCESS;
2181 : : }
2182 : :
2183 : : /**\brief Test information about entity copies for interface entities
2184 : : *
2185 : : * Test:
2186 : : * - iMeshP_getNumCopies
2187 : : * - iMeshP_getCopyParts
2188 : : */
2189 : 1 : int test_entity_copy_parts( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map )
2190 : : {
2191 : : int ierr, rank, size;
2192 [ + - ]: 1 : MPI_Comm_rank( MPI_COMM_WORLD, &rank );
2193 [ + - ]: 1 : MPI_Comm_size( MPI_COMM_WORLD, &size );
2194 : :
2195 : : // get local part handles
2196 [ + - ]: 1 : std::vector< iMeshP_PartHandle > parts;
2197 [ + - ]: 1 : ierr = get_local_parts( imesh, prtn, parts );
2198 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2199 [ + - ][ - + ]: 1 : ASSERT( !parts.empty() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2200 : :
2201 : : // select a singe part to test
2202 [ + - ]: 1 : const iMeshP_PartHandle part = parts[0];
2203 : : int logical_id;
2204 [ + - ][ - + ]: 1 : ierr = map.part_from_coords( imesh, part, logical_id );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2205 [ + - ]: 1 : const iMeshP_Part part_id = map.part_id_from_local_id( logical_id );
2206 : :
2207 : : // get vertices in part
2208 [ + - ][ + - ]: 2 : std::vector< iBase_EntityHandle > quads, verts;
2209 [ + - ]: 1 : ierr = get_part_quads_and_verts( imesh, part, quads, verts );
2210 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2211 : :
2212 : : // get neighbors
2213 : : int neighbors[5], num_neighbors;
2214 [ + - ]: 1 : get_part_neighbors( logical_id, map.get_parts().size(), neighbors, num_neighbors );
2215 : :
2216 : : // build map of sharing data for each vertex
2217 [ + - ]: 2 : std::map< iBase_EntityHandle, std::vector< iMeshP_Part > > vert_sharing;
2218 [ - + ]: 1 : for( int j = 0; j < num_neighbors; ++j )
2219 : : {
2220 [ # # ]: 0 : std::vector< iBase_EntityHandle > iface;
2221 [ # # ][ # # ]: 0 : ierr = interface_verts( imesh, prtn, part, neighbors[j], map, iface );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2222 [ # # ][ # # ]: 0 : for( size_t k = 0; k < iface.size(); ++k )
2223 [ # # ][ # # ]: 0 : vert_sharing[iface[k]].push_back( map.part_id_from_local_id( neighbors[j] ) );
[ # # ][ # # ]
2224 : 0 : }
2225 : :
2226 : : // test getNumCopies for each vertex
2227 [ + - ]: 1 : std::map< iBase_EntityHandle, std::vector< iMeshP_Part > >::iterator i;
2228 : 1 : int num_failed = 0, num_incorrect = 0;
2229 [ # # ][ + - ]: 1 : for( i = vert_sharing.begin(); i != vert_sharing.end(); ++i )
[ - + ]
2230 : : {
2231 : : int count;
2232 [ # # ]: 0 : iBase_EntityHandle vtx = i->first;
2233 [ # # ]: 0 : iMeshP_getNumCopies( imesh, prtn, vtx, &count, &ierr );
2234 [ # # ]: 0 : if( ierr )
2235 : 0 : ++num_failed;
2236 [ # # ][ # # ]: 0 : else if( (unsigned)count != i->second.size() + 1 ) // add one for the part we queried from
2237 : 0 : ++num_incorrect;
2238 : : }
2239 [ + - ][ - + ]: 1 : ASSERT( 0 == num_failed );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2240 [ + - ][ - + ]: 1 : ASSERT( 0 == num_incorrect );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2241 : :
2242 : : // get getCopyParts for each vertex
2243 : 1 : num_failed = num_incorrect = 0;
2244 [ # # ][ + - ]: 1 : for( i = vert_sharing.begin(); i != vert_sharing.end(); ++i )
[ - + ]
2245 : : {
2246 : 0 : iMeshP_Part* list = 0;
2247 : 0 : int junk = 0, count;
2248 [ # # ][ # # ]: 0 : iMeshP_getCopyParts( imesh, prtn, i->first, &list, &junk, &count, &ierr );
2249 [ # # ]: 0 : if( iBase_SUCCESS != ierr )
2250 : : {
2251 : 0 : ++num_failed;
2252 : 0 : continue;
2253 : : }
2254 [ # # ][ # # ]: 0 : if( (unsigned)count != i->second.size() + 1 )
2255 : : { // add one for the part we queried from
2256 : 0 : ++num_incorrect;
2257 : 0 : free( list );
2258 : 0 : continue;
2259 : : }
2260 : :
2261 [ # # ][ # # ]: 0 : std::vector< iMeshP_Part > expected( i->second );
2262 [ # # ]: 0 : expected.push_back( part_id );
2263 [ # # ]: 0 : std::sort( list, list + count );
2264 [ # # ]: 0 : std::sort( expected.begin(), expected.end() );
2265 [ # # ]: 0 : bool eq = std::equal( list, list + count, expected.begin() );
2266 : 0 : free( list );
2267 [ # # ]: 0 : if( !eq ) ++num_incorrect;
2268 : 0 : }
2269 [ + - ][ - + ]: 1 : ASSERT( 0 == num_failed );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2270 [ + - ][ - + ]: 1 : ASSERT( 0 == num_incorrect );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2271 : :
2272 : 2 : return iBase_SUCCESS;
2273 : : }
2274 : :
2275 : : // store remote handle data for a vertex
2276 [ + - ]: 27 : struct VtxCopyData
2277 : : {
2278 : : std::vector< iMeshP_Part > parts;
2279 : : std::vector< iBase_EntityHandle > handles;
2280 : : };
2281 : :
2282 : : /**\brief Test information about entity copies for interface entities
2283 : : *
2284 : : * Test:
2285 : : * - iMeshP_getCopies
2286 : : * - iMeshP_getCopyOnPart
2287 : : * - iMeshP_getOwnerCopy
2288 : : */
2289 : 1 : int test_entity_copies( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& /* map */ )
2290 : : {
2291 : : int ierr, rank, size;
2292 [ + - ]: 1 : MPI_Comm_rank( MPI_COMM_WORLD, &rank );
2293 [ + - ]: 1 : MPI_Comm_size( MPI_COMM_WORLD, &size );
2294 : :
2295 : : // generate a unique ID for each vertex using the coordinates.
2296 : : // see create_mesh(..): each vertex has integer coordinates (x,y,0)
2297 : : // with x in [0,inf] and y in [0,4]
2298 : : // then to an Allgatherv to exchange handles for each processor
2299 : :
2300 : : // cast everything to iBase_EntityHandle so we can pack it all in one communication
2301 : : MPI_Datatype tmp_type;
2302 : : if( sizeof( iBase_EntityHandle ) == sizeof( unsigned ) )
2303 : : tmp_type = MPI_UNSIGNED;
2304 : : else if( sizeof( iBase_EntityHandle ) == sizeof( unsigned long ) )
2305 : 1 : tmp_type = MPI_UNSIGNED_LONG;
2306 : : else if( sizeof( iBase_EntityHandle ) == sizeof( unsigned long long ) )
2307 : : tmp_type = MPI_UNSIGNED_LONG_LONG;
2308 : : else
2309 : : return iBase_FAILURE;
2310 : 1 : const MPI_Datatype type = tmp_type; // make it const
2311 : :
2312 : : // get local part handles
2313 [ + - ]: 1 : std::vector< iMeshP_PartHandle > parts;
2314 [ + - ]: 1 : ierr = get_local_parts( imesh, prtn, parts );
2315 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2316 [ + - ]: 2 : std::vector< iMeshP_Part > part_ids( parts.size() );
2317 [ + - ]: 1 : iMeshP_Part* junk1 = &part_ids[0];
2318 : 1 : int junk2 = part_ids.size(), junk3;
2319 [ + - ][ + - ]: 1 : iMeshP_getPartIdsFromPartHandlesArr( imesh, prtn, &parts[0], parts.size(), &junk1, &junk2, &junk3, &ierr );
2320 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2321 [ + - ][ - + ]: 1 : assert( junk1 == &part_ids[0] );
2322 [ - + ]: 1 : assert( junk2 == (int)part_ids.size() );
2323 [ - + ]: 1 : assert( junk3 == (int)parts.size() );
2324 : :
2325 : : // build list of {vtx_id, part_id, handle} tuples to send
2326 : : // also build list of local vertex handles
2327 [ + - ][ + - ]: 2 : std::vector< iBase_EntityHandle > local_data, local_vertices;
2328 [ + + ]: 2 : for( size_t i = 0; i < parts.size(); ++i )
2329 : : {
2330 : : // get vertices
2331 [ + - ][ + - ]: 2 : std::vector< iBase_EntityHandle > quads, verts;
[ + - ]
2332 [ + - ][ + - ]: 1 : ierr = get_part_quads_and_verts( imesh, parts[i], quads, verts );
2333 [ - + ]: 1 : if( ierr ) break;
2334 : :
2335 : : // add all vertices to local_data
2336 [ + + ]: 10 : for( size_t j = 0; j < verts.size(); ++j )
2337 : : {
2338 : 9 : int tag = 0;
2339 [ + - ][ + - ]: 9 : ierr = vertex_tag( imesh, verts[j], tag );
2340 [ - + ]: 9 : if( ierr ) break;
2341 : 9 : long tmp_h = tag;
2342 [ + - ]: 9 : local_data.push_back( (iBase_EntityHandle)tmp_h );
2343 [ + - ]: 9 : tmp_h = part_ids[i];
2344 [ + - ]: 9 : local_data.push_back( (iBase_EntityHandle)tmp_h );
2345 [ + - ][ + - ]: 9 : local_data.push_back( verts[j] );
2346 : : }
2347 [ - + ]: 1 : if( ierr ) break;
2348 : :
2349 [ + - ][ + - ]: 1 : std::copy( verts.begin(), verts.end(), std::back_inserter( local_vertices ) );
[ + - ]
2350 : 1 : }
2351 : :
2352 : : // build list of local vertices
2353 [ + - ]: 1 : std::sort( local_vertices.begin(), local_vertices.end() );
2354 [ + - ][ + - ]: 1 : local_vertices.erase( std::unique( local_vertices.begin(), local_vertices.end() ), local_vertices.end() );
2355 [ + - ][ - + ]: 2 : std::vector< int > local_vtx_tags( local_vertices.size() );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2356 [ + + ]: 10 : for( size_t i = 0; i < local_vertices.size(); ++i )
2357 : : {
2358 [ + - ][ + - ]: 9 : ierr = vertex_tag( imesh, local_vertices[i], local_vtx_tags[i] );
[ + - ]
2359 [ - + ]: 9 : if( ierr ) break;
2360 : : }
2361 [ - + ][ # # ]: 1 : CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2362 : :
2363 : : // communicate data
2364 [ + - ][ + - ]: 2 : std::vector< int > gcounts( size ), gdisp( size );
2365 : 1 : int local_data_size = local_data.size();
2366 [ + - ][ + - ]: 1 : ierr = MPI_Allgather( &local_data_size, 1, MPI_INT, &gcounts[0], 1, MPI_INT, MPI_COMM_WORLD );CHKERR;
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2367 [ + - ]: 1 : gdisp[0] = 0;
2368 [ - + ]: 1 : for( int i = 1; i < size; ++i )
2369 [ # # ][ # # ]: 0 : gdisp[i] = gdisp[i - 1] + gcounts[i - 1];
[ # # ]
2370 [ + - ][ + - ]: 2 : std::vector< iBase_EntityHandle > global_data( gdisp[size - 1] + gcounts[size - 1] );
[ + - ]
2371 [ + - ][ + - ]: 1 : ierr = MPI_Allgatherv( &local_data[0], local_data_size, type, &global_data[0], &gcounts[0], &gdisp[0], type,
[ + - ][ + - ]
2372 [ + - ][ - + ]: 1 : MPI_COMM_WORLD );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2373 : :
2374 : : // arrange global data in a more useful way
2375 [ + - ]: 2 : std::map< int, VtxCopyData > vtx_sharing;
2376 [ - + ]: 1 : assert( global_data.size() % 3 == 0 );
2377 [ + + ]: 10 : for( size_t i = 0; i < global_data.size(); i += 3 )
2378 : : {
2379 [ + - ]: 9 : int tag = (int)(size_t)global_data[i];
2380 [ + - ]: 9 : iMeshP_Part part = ( iMeshP_Part )(size_t)global_data[i + 1];
2381 [ + - ]: 9 : iBase_EntityHandle handle = global_data[i + 2];
2382 [ + - ][ + - ]: 9 : vtx_sharing[tag].parts.push_back( part );
2383 [ + - ][ + - ]: 9 : vtx_sharing[tag].handles.push_back( handle );
2384 : : }
2385 : :
2386 : : // test iMeshP_getCopies for each local vertex
2387 : 1 : int num_error = 0, num_incorrect = 0, junk4;
2388 [ + + ]: 10 : for( size_t i = 0; i < local_vertices.size(); ++i )
2389 : : {
2390 : 9 : int num_copies = -1;
2391 : : // iMeshP_Part* part_ids = 0;
2392 : 9 : iMeshP_Part* ptr_part_ids = 0; // Use ptr_part_ids to avoid shadowing std::vector<iMeshP_Part> part_ids
2393 : 9 : iBase_EntityHandle* copies = 0;
2394 : 9 : junk2 = junk3 = junk4 = 0;
2395 [ + - ]: 9 : iMeshP_getCopies( imesh, prtn, local_vertices[i], &ptr_part_ids, &junk2, &num_copies, &copies, &junk3, &junk4,
2396 [ + - ]: 9 : &ierr );
2397 [ - + ]: 9 : if( iBase_SUCCESS != ierr )
2398 : : {
2399 : 0 : ++num_error;
2400 : 0 : continue;
2401 : : }
2402 [ - + ]: 9 : assert( junk4 == num_copies );
2403 : :
2404 [ + - ][ + - ]: 9 : VtxCopyData& expected = vtx_sharing[local_vtx_tags[i]];
2405 [ - + ]: 9 : if( num_copies != (int)expected.parts.size() )
2406 : 0 : ++num_incorrect;
2407 : : else
2408 [ + + ]: 18 : for( size_t j = 0; j < expected.parts.size(); ++j )
2409 : : {
2410 [ + - ][ + - ]: 9 : int idx = std::find( ptr_part_ids, ptr_part_ids + num_copies, expected.parts[j] ) - ptr_part_ids;
2411 [ + - ][ + - ]: 9 : if( idx == num_copies || copies[idx] != expected.handles[j] )
[ - + ][ - + ]
2412 : : {
2413 : 0 : ++num_incorrect;
2414 : 0 : break;
2415 : : }
2416 : : }
2417 : 9 : free( ptr_part_ids );
2418 : 9 : free( copies );
2419 : : }
2420 [ + - ][ - + ]: 1 : ASSERT( 0 == num_error );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2421 [ + - ][ - + ]: 1 : ASSERT( 0 == num_incorrect );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2422 : :
2423 : : // test iMeshP_getCopyOnPart for each local vertex
2424 : 1 : num_error = num_incorrect = 0;
2425 [ + + ]: 10 : for( size_t i = 0; i < local_vertices.size(); ++i )
2426 : : {
2427 [ + - ][ + - ]: 9 : VtxCopyData& expected = vtx_sharing[local_vtx_tags[i]];
2428 [ + + ]: 18 : for( size_t j = 0; j < expected.parts.size(); ++j )
2429 : : {
2430 : : iBase_EntityHandle copy;
2431 [ + - ][ + - ]: 9 : iMeshP_getCopyOnPart( imesh, prtn, local_vertices[i], expected.parts[j], ©, &ierr );
[ + - ]
2432 [ - + ]: 9 : if( iBase_SUCCESS != ierr )
2433 : 0 : ++num_error;
2434 [ + - ][ - + ]: 9 : else if( expected.handles[j] != copy )
2435 : 0 : ++num_incorrect;
2436 : : }
2437 : : }
2438 [ + - ][ - + ]: 1 : ASSERT( 0 == num_error );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2439 [ + - ][ - + ]: 1 : ASSERT( 0 == num_incorrect );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2440 : :
2441 : : // test iMeshP_getOwnerCopy for each local vertex
2442 : 1 : num_error = num_incorrect = 0;
2443 [ + + ]: 10 : for( size_t i = 0; i < local_vertices.size(); ++i )
2444 : : {
2445 [ + - ][ + - ]: 9 : VtxCopyData& expected = vtx_sharing[local_vtx_tags[i]];
2446 : 9 : iMeshP_Part owner_id = 0;
2447 [ + - ][ + - ]: 9 : iMeshP_getEntOwnerPart( imesh, prtn, local_vertices[i], &owner_id, &ierr );
2448 [ - + ]: 9 : if( iBase_SUCCESS != ierr ) continue; // not testing getEntOwnerPart here
2449 : :
2450 [ + - ][ + - ]: 9 : size_t idx = std::find( expected.parts.begin(), expected.parts.end(), owner_id ) - expected.parts.begin();
2451 [ - + ]: 9 : if( idx == expected.parts.size() ) continue; // not testing getEntOwnerPart here
2452 : :
2453 : 9 : iMeshP_Part owner_id_2 = 0;
2454 : 9 : iBase_EntityHandle copy = 0;
2455 [ + - ][ + - ]: 9 : iMeshP_getOwnerCopy( imesh, prtn, local_vertices[i], &owner_id_2, ©, &ierr );
2456 [ - + ]: 9 : if( iBase_SUCCESS != ierr )
2457 : 0 : ++num_error;
2458 [ - + ][ # # ]: 9 : else if( owner_id_2 != owner_id && copy != expected.handles[idx] )
[ # # ][ - + ]
2459 : 9 : ++num_incorrect;
2460 : : }
2461 [ + - ][ - + ]: 1 : ASSERT( 0 == num_error );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2462 [ + - ][ - + ]: 1 : ASSERT( 0 == num_incorrect );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2463 : :
2464 : 2 : return iBase_SUCCESS;
2465 : : }
2466 : :
2467 : 50 : int get_num_adj_quads( iMesh_Instance imesh, iBase_EntityHandle vtx, int& num )
2468 : : {
2469 : 50 : iBase_EntityHandle* list = 0;
2470 : 50 : int ierr, junk = 0;
2471 [ + - ]: 50 : iMesh_getEntAdj( imesh, vtx, iBase_FACE, &list, &junk, &num, &ierr );
2472 [ + - ]: 50 : if( iBase_SUCCESS == ierr ) free( list );
2473 : 50 : return ierr;
2474 : : }
2475 : :
2476 : 0 : int get_adj( iMesh_Instance imesh, iBase_EntityHandle ent, int type, std::vector< iBase_EntityHandle >& adj )
2477 : : {
2478 : 0 : iBase_EntityHandle* list = 0;
2479 : 0 : int ierr, num, junk = 0;
2480 [ # # ]: 0 : iMesh_getEntAdj( imesh, ent, type, &list, &junk, &num, &ierr );
2481 [ # # ]: 0 : if( iBase_SUCCESS == ierr )
2482 : : {
2483 [ # # ][ # # ]: 0 : std::copy( list, list + num, std::back_inserter( adj ) );
2484 : 0 : free( list );
2485 : : }
2486 : 0 : return ierr;
2487 : : }
2488 : :
2489 : : // assume regular quad mesh
2490 : 2 : int get_boundary_vertices( iMesh_Instance imesh, std::vector< iBase_EntityHandle >& bdry )
2491 : : {
2492 : : int ierr, n;
2493 : : iBase_EntitySetHandle root;
2494 [ + - ][ - + ]: 2 : iMesh_getRootSet( imesh, &root, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2495 [ + - ]: 2 : std::vector< iBase_EntityHandle > all_verts;
2496 [ + - ][ - + ]: 2 : ierr = get_entities( imesh, root, iBase_VERTEX, iMesh_POINT, all_verts );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2497 : 2 : bdry.clear();
2498 [ + + ]: 20 : for( size_t i = 0; i < all_verts.size(); ++i )
2499 : : {
2500 [ + - ][ + - ]: 18 : ierr = get_num_adj_quads( imesh, all_verts[i], n );CHKERR;
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2501 [ + + ][ + - ]: 18 : if( n != 4 ) bdry.push_back( all_verts[i] );
[ + - ]
2502 : : }
2503 : 2 : return iBase_SUCCESS;
2504 : : }
2505 : :
2506 : 8 : int check_one_layer( iMesh_Instance imesh, iBase_EntityHandle vtx,
2507 : : const std::vector< iBase_EntityHandle >& sorted_vertices )
2508 : : {
2509 : : int ierr;
2510 [ + - ][ + - ]: 8 : if( std::binary_search( sorted_vertices.begin(), sorted_vertices.end(), vtx ) ) return iBase_SUCCESS;
2511 [ # # ][ # # ]: 0 : std::vector< iBase_EntityHandle > quads, verts;
2512 [ # # ][ # # ]: 0 : ierr = get_adj( imesh, vtx, iBase_FACE, quads );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2513 [ # # ]: 0 : for( size_t i = 0; i < quads.size(); ++i )
2514 : : {
2515 : 0 : verts.clear();
2516 [ # # ][ # # ]: 0 : ierr = get_adj( imesh, quads[i], iBase_VERTEX, verts );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2517 [ # # ]: 0 : for( size_t j = 0; j < verts.size(); ++j )
2518 : : {
2519 [ # # ][ # # ]: 0 : if( std::binary_search( sorted_vertices.begin(), sorted_vertices.end(), verts[j] ) ) return iBase_SUCCESS;
[ # # ]
2520 : : }
2521 : : }
2522 : :
2523 : 8 : return iBase_FAILURE;
2524 : : }
2525 : :
2526 : : // get number of adjacent quads to each vertex, both on the local
2527 : : // processor and in the entire mesh
2528 : 2 : int get_num_adj_all( iMesh_Instance imesh, const std::vector< iBase_EntityHandle >& verts,
2529 : : std::vector< int >& num_local_adj, std::vector< int >& num_all_adj )
2530 : : {
2531 : : int ierr, size;
2532 [ + - ]: 2 : MPI_Comm_size( MPI_COMM_WORLD, &size );
2533 : :
2534 [ + - ]: 2 : std::vector< int > vtx_tags( verts.size() );
2535 [ + - ]: 2 : num_local_adj.resize( verts.size() );
2536 [ + + ]: 18 : for( size_t i = 0; i < verts.size(); ++i )
2537 : : {
2538 [ + - ][ + - ]: 16 : ierr = get_num_adj_quads( imesh, verts[i], num_local_adj[i] );CHKERR;
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2539 [ + - ][ + - ]: 16 : ierr = vertex_tag( imesh, verts[i], vtx_tags[i] );CHKERR;
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2540 : : }
2541 : :
2542 [ + - ][ + - ]: 4 : std::vector< int > counts( size ), displ( size );
2543 : 2 : int num_vtx = verts.size();
2544 [ + - ][ + - ]: 2 : ierr = MPI_Allgather( &num_vtx, 1, MPI_INT, &counts[0], 1, MPI_INT, MPI_COMM_WORLD );CHKERR;
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2545 [ + - ]: 2 : displ[0] = 0;
2546 [ - + ]: 2 : for( int i = 1; i < size; ++i )
2547 [ # # ][ # # ]: 0 : displ[i] = displ[i - 1] + counts[i - 1];
[ # # ]
2548 [ + - ][ + - ]: 2 : int total = displ[size - 1] + counts[size - 1];
2549 [ + - ][ + - ]: 4 : std::vector< int > all_tags( total ), all_adj_counts( total );
2550 [ + - ][ + - ]: 2 : ierr = MPI_Allgatherv( &vtx_tags[0], vtx_tags.size(), MPI_INT, &all_tags[0], &counts[0], &displ[0], MPI_INT,
[ + - ][ + - ]
2551 [ + - ][ - + ]: 2 : MPI_COMM_WORLD );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2552 [ + - ][ + - ]: 2 : ierr = MPI_Allgatherv( &num_local_adj[0], num_local_adj.size(), MPI_INT, &all_adj_counts[0], &counts[0], &displ[0],
[ + - ][ + - ]
2553 [ + - ][ - + ]: 2 : MPI_INT, MPI_COMM_WORLD );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2554 : :
2555 : 2 : num_all_adj.clear();
2556 [ + - ]: 2 : num_all_adj.resize( total, 0 );
2557 [ + + ]: 18 : for( int i = 0; i < total; ++i )
2558 : : {
2559 [ + - ][ + - ]: 16 : std::vector< int >::iterator it = std::find( vtx_tags.begin(), vtx_tags.end(), all_tags[i] );
2560 [ + - ][ - + ]: 16 : if( it == vtx_tags.end() ) continue;
2561 [ + - ]: 16 : int idx = it - vtx_tags.begin();
2562 [ + - ][ + - ]: 16 : num_all_adj[idx] += all_adj_counts[i];
2563 : : }
2564 : :
2565 : 4 : return iBase_SUCCESS;
2566 : : }
2567 : :
2568 : : /**\brief Test creation of ghost entities
2569 : : *
2570 : : * Test:
2571 : : * - iMeshP_createGhostEntsAll
2572 : : */
2573 : 1 : int test_create_ghost_ents( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& /* map */ )
2574 : : {
2575 : : int ierr;
2576 : :
2577 : : // get boundary vertices
2578 [ + - ]: 1 : std::vector< iBase_EntityHandle > bdry;
2579 [ + - ]: 1 : ierr = get_boundary_vertices( imesh, bdry );
2580 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2581 : : // get counts of adjacent entities
2582 [ + - ][ + - ]: 2 : std::vector< int > num_local_adj, num_global_adj;
2583 [ + - ]: 1 : ierr = get_num_adj_all( imesh, bdry, num_local_adj, num_global_adj );
2584 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2585 : : // create one layer of ghost entities
2586 [ + - ]: 1 : iMeshP_createGhostEntsAll( imesh, prtn, iBase_FACE, iBase_VERTEX, 1, 0, &ierr );
2587 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2588 : : // check that each vertex has the correct number of adjacent entities
2589 : 1 : int num_incorrect = 0;
2590 [ + + ]: 9 : for( size_t i = 0; i < bdry.size(); ++i )
2591 : : {
2592 : : int n;
2593 [ + - ][ + - ]: 8 : ierr = get_num_adj_quads( imesh, bdry[i], n );
2594 [ + - ][ + - ]: 8 : if( iBase_SUCCESS != ierr || num_global_adj[i] != n ) ++num_incorrect;
[ - + ][ - + ]
2595 : : }
2596 [ + - ][ - + ]: 1 : ASSERT( 0 == num_incorrect );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2597 : : // get new the new boundary
2598 [ + - ]: 2 : std::vector< iBase_EntityHandle > new_bdry;
2599 [ + - ]: 1 : ierr = get_boundary_vertices( imesh, new_bdry );
2600 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2601 : : // check that each vertex on the new boundary is separated by
2602 : : // at most one layer from the old boundary
2603 [ + - ]: 1 : std::sort( bdry.begin(), bdry.end() );
2604 : 1 : num_incorrect = 0;
2605 [ + + ]: 9 : for( size_t i = 0; i < new_bdry.size(); ++i )
2606 : : {
2607 [ + - ][ + - ]: 8 : ierr = check_one_layer( imesh, new_bdry[i], bdry );
2608 [ - + ]: 8 : if( ierr ) ++num_incorrect;
2609 : : }
2610 [ + - ][ - + ]: 1 : ASSERT( 0 == num_incorrect );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2611 : : // make another layer of ghost entiites
2612 : 1 : bdry.swap( new_bdry );
2613 : 1 : new_bdry.clear();
2614 [ + - ]: 1 : ierr = get_num_adj_all( imesh, bdry, num_local_adj, num_global_adj );
2615 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2616 [ + - ]: 1 : iMeshP_createGhostEntsAll( imesh, prtn, iBase_FACE, iBase_VERTEX, 2, 0, &ierr );
2617 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2618 : : // check that each vertex has the correct number of adjacent entities
2619 : 1 : num_incorrect = 0;
2620 [ + + ]: 9 : for( size_t i = 0; i < bdry.size(); ++i )
2621 : : {
2622 : : int n;
2623 [ + - ][ + - ]: 8 : ierr = get_num_adj_quads( imesh, bdry[i], n );
2624 [ + - ][ + - ]: 8 : if( iBase_SUCCESS != ierr || num_global_adj[i] != n ) ++num_incorrect;
[ - + ][ - + ]
2625 : : }
2626 : : // check that each vertex on the new boundary is separated by
2627 : : // at most one layer from the old boundary
2628 [ + - ]: 1 : std::sort( bdry.begin(), bdry.end() );
2629 : 1 : num_incorrect = 0;
2630 [ - + ]: 1 : for( size_t i = 0; i < new_bdry.size(); ++i )
2631 : : {
2632 [ # # ][ # # ]: 0 : ierr = check_one_layer( imesh, new_bdry[i], bdry );
2633 [ # # ]: 0 : if( ierr ) ++num_incorrect;
2634 : : }
2635 [ + - ][ - + ]: 1 : ASSERT( 0 == num_incorrect );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2636 : :
2637 : 2 : return iBase_SUCCESS;
2638 : : }
2639 : :
2640 : : /**\brief Test exchange entities
2641 : : *
2642 : : * Test:
2643 : : * - iMeshP_exchEntArrToPartsAll
2644 : : */
2645 : 1 : int test_exchange_ents( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map )
2646 : : {
2647 : : int ierr, rank, size;
2648 : 1 : int num_err = 0;
2649 : : iMeshP_RequestHandle request;
2650 [ + - ]: 1 : MPI_Comm_rank( MPI_COMM_WORLD, &rank );
2651 [ + - ]: 1 : MPI_Comm_size( MPI_COMM_WORLD, &size );
2652 : :
2653 [ + - ]: 1 : std::vector< iBase_EntityHandle > all_elems;
2654 [ + - ]: 2 : std::vector< iMeshP_Part > all_ids;
2655 [ + - ]: 2 : std::vector< iBase_EntityHandle > quads;
2656 : :
2657 : : // get local part handles and part ids
2658 [ + - ]: 2 : std::vector< iMeshP_PartHandle > local_handles;
2659 [ + - ]: 2 : std::vector< iMeshP_Part > local_ids;
2660 [ + - ]: 1 : ierr = get_local_parts( imesh, prtn, local_handles, &local_ids );
2661 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2662 : :
2663 : : // get loacal quads before exchange
2664 : 1 : quads.clear();
2665 [ + - ][ + - ]: 1 : ierr = get_entities( imesh, local_handles[0], iBase_FACE, iMesh_QUADRILATERAL, quads );CHKERR;
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2666 : 1 : int n_quads = quads.size();
2667 : :
2668 : : // send all elements in local processor to all other processors
2669 [ + - ][ + + ]: 2 : for( size_t i = 0; i < map.get_parts().size(); ++i )
2670 : : {
2671 [ + - ][ + - ]: 1 : if( map.get_parts()[i] == (unsigned int)rank ) continue; // skip own rank
[ + - ]
2672 : :
2673 [ # # ]: 0 : for( int j = 0; j < n_quads; j++ )
2674 : : {
2675 [ # # ][ # # ]: 0 : all_elems.push_back( quads[j] );
2676 [ # # ][ # # ]: 0 : all_ids.push_back( map.get_parts()[i] );
[ # # ]
2677 : : }
2678 : : }
2679 : :
2680 : : // exchange entities
2681 [ + - ][ + - ]: 1 : iMeshP_exchEntArrToPartsAll( imesh, prtn, &all_elems[0], all_elems.size(), &all_ids[0], 0, 0, &request, &ierr );
[ + - ]
2682 [ - + ]: 1 : if( iBase_SUCCESS != ierr ) ++num_err;
2683 : :
2684 : : // get local quads after exchange
2685 : 1 : quads.clear();
2686 [ + - ][ + - ]: 1 : ierr = get_entities( imesh, local_handles[0], iBase_FACE, iMesh_QUADRILATERAL, quads );CHKERR;
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2687 : :
2688 : : // # of elements should be # of quads * # of processors
2689 [ + - ][ - + ]: 1 : ASSERT( quads.size() == (unsigned int)n_quads * size );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2690 : :
2691 [ + - ][ - + ]: 1 : ASSERT( 0 == num_err );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2692 : :
2693 : 2 : return iBase_SUCCESS;
2694 : : }
2695 : :
2696 : : /**\brief Test commuinication of tag data
2697 : : *
2698 : : * Test:
2699 : : * - iMeshP_pushTags
2700 : : * - iMeshP_pushTagsEnt
2701 : : */
2702 : 2 : int test_push_tag_data_common( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, int num_ghost_layers )
2703 : : {
2704 : 2 : const char* src_name = "test_src";
2705 : 2 : const char* dst_name = "test_dst";
2706 : : int ierr, rank;
2707 [ + - ]: 2 : MPI_Comm_rank( MPI_COMM_WORLD, &rank );
2708 : :
2709 [ + + ]: 2 : if( num_ghost_layers )
2710 : : {
2711 [ + - ]: 1 : iMeshP_createGhostEntsAll( imesh, prtn, iBase_FACE, iBase_VERTEX, num_ghost_layers, 0, &ierr );
2712 [ + - ][ - + ]: 1 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2713 : : }
2714 : :
2715 : : iBase_TagHandle src_tag, dst_tag;
2716 [ + - ][ - + ]: 2 : iMesh_createTag( imesh, src_name, 1, iBase_INTEGER, &src_tag, &ierr, strlen( src_name ) );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2717 [ + - ][ - + ]: 2 : iMesh_createTag( imesh, dst_name, 1, iBase_INTEGER, &dst_tag, &ierr, strlen( dst_name ) );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2718 : :
2719 : : iBase_EntitySetHandle root;
2720 [ + - ][ - + ]: 2 : iMesh_getRootSet( imesh, &root, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2721 : :
2722 [ + - ]: 2 : std::vector< iBase_EntityHandle > verts;
2723 [ + - ][ - + ]: 2 : ierr = get_entities( imesh, root, iBase_VERTEX, iMesh_POINT, verts );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2724 : :
2725 : : // test iMeshP_pushTags
2726 : : // each processor writes its rank on all vertices
2727 : : // after push, each vertex should be tagged with the rank of its owner
2728 : :
2729 [ + - ]: 4 : std::vector< int > tag_vals( verts.size(), rank );
2730 [ + - ][ + - ]: 2 : iMesh_setIntArrData( imesh, &verts[0], verts.size(), src_tag, &tag_vals[0], tag_vals.size(), &ierr );CHKERR;
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2731 : :
2732 [ + - ]: 2 : iMeshP_pushTags( imesh, prtn, src_tag, dst_tag, iBase_VERTEX, iMesh_POINT, &ierr );
2733 [ + - ][ - + ]: 2 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2734 : :
2735 : 2 : tag_vals.clear();
2736 [ + - ]: 2 : tag_vals.resize( verts.size(), -1 );
2737 : : iBase_TagHandle id_tag;
2738 [ + - ]: 2 : iMesh_getTagHandle( imesh, "GLOBAL_ID", &id_tag, &ierr, strlen( "GLOBAL_ID" ) );
2739 [ + - ]: 4 : std::vector< int > ids( verts.size() );
2740 [ + - ]: 2 : int *junk1 = &ids[0], junk2 = ids.size(), junk3;
2741 [ + - ][ + - ]: 2 : iMesh_getIntArrData( imesh, &verts[0], verts.size(), id_tag, &junk1, &junk2, &junk3, &ierr );
2742 [ + - ][ - + ]: 2 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2743 : 2 : int errcount = 0;
2744 [ + + ]: 20 : for( size_t i = 0; i < verts.size(); ++i )
2745 : : {
2746 [ + - ][ + - ]: 18 : iMesh_getIntData( imesh, verts[i], dst_tag, &tag_vals[i], &ierr );
[ + - ]
2747 [ - + ]: 18 : if( ierr != iBase_SUCCESS )
2748 : : {
2749 [ # # ][ # # ]: 0 : std::cerr << "Rank " << rank << " : getIntData failed for vertex " << ids[i] << std::endl;
[ # # ][ # # ]
[ # # ][ # # ]
2750 [ # # ]: 0 : std::cerr.flush();
2751 : 0 : ++errcount;
2752 : : }
2753 : : }
2754 [ + - ][ - + ]: 2 : ASSERT( 0 == errcount );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2755 : :
2756 : : // int *junk1 = &tag_vals[0], junk2 = tag_vals.size(), junk3;
2757 : : // iMesh_getIntArrData( imesh, &verts[0], verts.size(), dst_tag, &junk1, &junk2, &junk3, &ierr
2758 : : // ); PCHECK; assert( junk1 == &tag_vals[0] ); assert( junk2 == (int)tag_vals.size() ); assert(
2759 : : // junk3 == (int)verts.size() );
2760 : :
2761 [ + - ]: 4 : std::vector< int > expected( verts.size() );
2762 [ + - ]: 4 : std::vector< iMeshP_Part > parts( verts.size() );
2763 [ + - ]: 2 : iMeshP_Part* junk4 = &parts[0];
2764 : 2 : junk2 = parts.size();
2765 [ + - ][ + - ]: 2 : iMeshP_getEntOwnerPartArr( imesh, prtn, &verts[0], verts.size(), &junk4, &junk2, &junk3, &ierr );
2766 [ + - ][ - + ]: 2 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2767 [ + - ][ - + ]: 2 : assert( junk4 == &parts[0] );
2768 [ - + ]: 2 : assert( junk2 == (int)parts.size() );
2769 [ - + ]: 2 : assert( junk3 == (int)verts.size() );
2770 [ + - ]: 2 : junk1 = &expected[0];
2771 : 2 : junk2 = expected.size();
2772 [ + - ][ + - ]: 2 : iMeshP_getRankOfPartArr( imesh, prtn, &parts[0], parts.size(), &junk1, &junk2, &junk3, &ierr );
2773 [ + - ][ - + ]: 2 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2774 [ + - ][ - + ]: 2 : assert( junk1 == &expected[0] );
2775 [ - + ]: 2 : assert( junk2 == (int)expected.size() );
2776 [ - + ]: 2 : assert( junk3 == (int)parts.size() );
2777 : :
2778 [ + - ][ + - ]: 2 : ASSERT( tag_vals == expected );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2779 : :
2780 : : // test iMeshP_pushTagsEnt
2781 : : // write -1 on all vertices
2782 : : // For each vertex owned by this processor and shared with more than
2783 : : // two others, write the rank of the owning processor.
2784 : :
2785 : 2 : tag_vals.clear();
2786 [ + - ]: 2 : tag_vals.resize( verts.size(), -1 );
2787 [ + - ][ + - ]: 2 : iMesh_setIntArrData( imesh, &verts[0], verts.size(), src_tag, &tag_vals[0], tag_vals.size(), &ierr );
[ + - ]
2788 [ + - ][ - + ]: 2 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2789 [ + - ]: 2 : tag_vals.resize( verts.size(), -1 );
2790 [ + - ][ + - ]: 2 : iMesh_setIntArrData( imesh, &verts[0], verts.size(), dst_tag, &tag_vals[0], tag_vals.size(), &ierr );
[ + - ]
2791 [ + - ][ - + ]: 2 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2792 : :
2793 [ + - ]: 4 : std::vector< iBase_EntityHandle > some;
2794 [ + + ]: 20 : for( size_t i = 0; i < verts.size(); ++i )
2795 : : {
2796 : : int num;
2797 [ + - ][ + - ]: 18 : iMeshP_getNumCopies( imesh, prtn, verts[i], &num, &ierr );
2798 [ - + ]: 18 : if( iBase_SUCCESS != ierr ) break;
2799 [ - + ]: 18 : if( num > 2 )
2800 [ # # ][ # # ]: 0 : some.push_back( verts[i] );
2801 : : else
2802 [ + - ]: 18 : expected[i] = -1;
2803 : : }
2804 : :
2805 : 2 : tag_vals.clear();
2806 [ + - ]: 2 : tag_vals.resize( some.size(), rank );
2807 [ + - ][ + - ]: 2 : iMesh_setIntArrData( imesh, &some[0], some.size(), src_tag, &tag_vals[0], tag_vals.size(), &ierr );
[ + - ]
2808 [ + - ][ - + ]: 2 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2809 : :
2810 [ + - ][ + - ]: 2 : iMeshP_pushTagsEnt( imesh, prtn, src_tag, dst_tag, &some[0], some.size(), &ierr );
2811 [ + - ][ - + ]: 2 : PCHECK;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2812 : :
2813 : 2 : tag_vals.clear();
2814 [ + - ]: 2 : tag_vals.resize( verts.size(), -1 );
2815 [ + - ]: 2 : junk1 = &tag_vals[0];
2816 : 2 : junk2 = tag_vals.size();
2817 [ + - ][ + - ]: 2 : iMesh_getIntArrData( imesh, &verts[0], verts.size(), dst_tag, &junk1, &junk2, &junk3, &ierr );CHKERR;
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2818 [ + - ][ - + ]: 2 : assert( junk1 == &tag_vals[0] );
2819 [ - + ]: 2 : assert( junk2 == (int)tag_vals.size() );
2820 [ - + ]: 2 : assert( junk3 == (int)verts.size() );
2821 : :
2822 [ + - ][ + - ]: 2 : ASSERT( tag_vals == expected );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2823 : 4 : return iBase_SUCCESS;
2824 : : }
2825 : :
2826 : : /**\brief Test commuinication of tag data
2827 : : *
2828 : : * Test:
2829 : : * - iMeshP_pushTags
2830 : : * - iMeshP_pushTagsEnt
2831 : : */
2832 : 1 : int test_push_tag_data_iface( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& )
2833 : : {
2834 : 1 : return test_push_tag_data_common( imesh, prtn, 0 );
2835 : : }
2836 : :
2837 : : /**\brief Test commuinication of tag data
2838 : : *
2839 : : * Test:
2840 : : * - iMeshP_pushTags
2841 : : * - iMeshP_pushTagsEnt
2842 : : */
2843 : 1 : int test_push_tag_data_ghost( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& )
2844 : : {
2845 : 1 : return test_push_tag_data_common( imesh, prtn, 1 );
2846 : : }
2847 : :
2848 : : /**************************************************************************
2849 : : PartMap class
2850 : : **************************************************************************/
2851 : :
2852 : 19 : int PartMap::build_map( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, int num_expected_parts )
2853 : : {
2854 : : int ierr, rank, size;
2855 [ + - ]: 19 : MPI_Comm_rank( MPI_COMM_WORLD, &rank );
2856 [ + - ]: 19 : MPI_Comm_size( MPI_COMM_WORLD, &size );
2857 : :
2858 : : // get local parts
2859 [ + - ]: 19 : std::vector< iMeshP_PartHandle > local_parts;
2860 [ + - ]: 38 : std::vector< iMeshP_Part > imesh_ids;
2861 [ + - ][ - + ]: 19 : ierr = get_local_parts( imesh, prtn, local_parts, &imesh_ids );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2862 : :
2863 : : // get logical ids for local parts
2864 [ + - ]: 38 : std::vector< int > local_ids( local_parts.size() );
2865 [ + + ]: 38 : for( size_t i = 0; i < local_parts.size(); ++i )
2866 : : {
2867 [ + - ][ + - ]: 19 : ierr = part_from_coords( imesh, local_parts[i], local_ids[i] );CHKERR;
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2868 : : }
2869 : :
2870 : : // get total number of parts
2871 : 19 : int num_global = 0, num_local = local_parts.size();
2872 [ + - ][ - + ]: 19 : ierr = MPI_Allreduce( &num_local, &num_global, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2873 [ - + ]: 19 : if( num_global != num_expected_parts )
2874 : : {
2875 [ # # ][ # # ]: 0 : std::cerr << "Invalid/unexpected global part count at " __FILE__ ":" << __LINE__ << " (proc " << rank
[ # # ][ # # ]
2876 [ # # ][ # # ]: 0 : << "): " << std::endl
2877 [ # # ][ # # ]: 0 : << " Expected: " << num_expected_parts << std::endl
[ # # ]
2878 [ # # ][ # # ]: 0 : << " Actual: " << num_global << std::endl;
[ # # ]
2879 : 0 : return 1;
2880 : : }
2881 : :
2882 : : // get counts and displacements for Allgatherv calls
2883 [ + - ][ + - ]: 38 : std::vector< int > dspls( size ), counts( size );
2884 [ + - ][ + - ]: 19 : ierr = MPI_Allgather( &num_local, 1, MPI_INT, &counts[0], 1, MPI_INT, MPI_COMM_WORLD );CHKERR;
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2885 [ + - ]: 19 : dspls[0] = 0;
2886 [ - + ]: 19 : for( int i = 1; i < size; ++i )
2887 [ # # ][ # # ]: 0 : dspls[i] = dspls[i - 1] + counts[i - 1];
[ # # ]
2888 : :
2889 : : // gather iMeshP_Part list from each processor
2890 [ + - ]: 38 : std::vector< unsigned > global_part_ids( num_expected_parts );
2891 : : assert( sizeof( iMeshP_Part ) == sizeof( int ) );
2892 [ + - ][ + - ]: 19 : ierr = MPI_Allgatherv( &imesh_ids[0], num_local, MPI_UNSIGNED, &global_part_ids[0], &counts[0], &dspls[0],
[ + - ][ + - ]
2893 [ + - ][ - + ]: 19 : MPI_UNSIGNED, MPI_COMM_WORLD );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2894 : :
2895 : : // gather local ids from each processor
2896 [ + - ]: 38 : std::vector< int > global_id_list( num_expected_parts );
2897 [ + - ][ + - ]: 19 : ierr = MPI_Allgatherv( &local_ids[0], num_local, MPI_INT, &global_id_list[0], &counts[0], &dspls[0], MPI_INT,
[ + - ][ + - ]
2898 [ + - ][ - + ]: 19 : MPI_COMM_WORLD );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2899 : :
2900 : : // build owner list
2901 [ + - ]: 38 : std::vector< int > global_owners( num_expected_parts );
2902 [ + + ]: 38 : for( int i = 0; i < size; ++i )
2903 [ + - ][ + + ]: 38 : for( int j = 0; j < counts[i]; ++j )
2904 [ + - ][ + - ]: 19 : global_owners[dspls[i] + j] = i;
2905 : :
2906 : : // populate member lists
2907 [ + - ]: 19 : sortedPartList = global_part_ids;
2908 [ + - ]: 19 : std::sort( sortedPartList.begin(), sortedPartList.end() );
2909 [ + - ]: 19 : partLocalIds.resize( num_expected_parts );
2910 [ + - ]: 19 : partRanks.resize( num_expected_parts );
2911 [ + + ]: 38 : for( int i = 0; i < num_expected_parts; ++i )
2912 : : {
2913 [ + - ][ + - ]: 19 : int idx = std::lower_bound( sortedPartList.begin(), sortedPartList.end(), global_part_ids[i] ) -
[ + - ]
2914 : 38 : sortedPartList.begin();
2915 [ + - ][ + - ]: 19 : partLocalIds[idx] = global_id_list[i];
2916 [ + - ][ + - ]: 19 : partRanks[idx] = global_owners[i];
2917 : : }
2918 : :
2919 : : // do some consistency checking
2920 [ + - ][ + - ]: 19 : if( std::unique( sortedPartList.begin(), sortedPartList.end() ) != sortedPartList.end() )
[ - + ]
2921 : : {
2922 [ # # ]: 0 : if( rank == 0 )
2923 [ # # ][ # # ]: 0 : { std::cerr << "ERROR: Duplicate iMeshP_Part values detected at " __FILE__ ":" << __LINE__ << std::endl; }
[ # # ]
2924 : 0 : return 1;
2925 : : }
2926 : :
2927 : : // build revesre local id map and check for duplicates
2928 : 19 : localIdReverseMap.clear();
2929 [ + - ]: 19 : localIdReverseMap.resize( num_expected_parts, -1 );
2930 [ + + ]: 38 : for( int i = 0; i < num_expected_parts; ++i )
2931 : : {
2932 [ + - ]: 19 : int idx = partLocalIds[i];
2933 [ + - ][ - + ]: 19 : if( localIdReverseMap[idx] != -1 )
2934 : : {
2935 [ # # ]: 0 : if( rank == 0 )
2936 : : {
2937 [ # # ][ # # ]: 0 : std::cerr << "ERROR: Part mesh has been duplicated in multiple parts." << std::endl
2938 [ # # ][ # # ]: 0 : << " Detected at " __FILE__ ":" << __LINE__ << std::endl
[ # # ]
2939 [ # # ][ # # ]: 0 : << " See PartMap::part_from_coords" << std::endl;
2940 : : }
2941 : 0 : return 1;
2942 : : }
2943 [ - + ]: 19 : if( idx >= num_expected_parts )
2944 : : {
2945 [ # # ]: 0 : if( rank == 0 )
2946 : : {
2947 [ # # ][ # # ]: 0 : std::cerr << "ERROR: Part mesh invalid/incorrect mesh." << std::endl
2948 [ # # ][ # # ]: 0 : << " Detected at " __FILE__ ":" << __LINE__ << std::endl
[ # # ]
2949 [ # # ][ # # ]: 0 : << " See PartMap::part_from_coords" << std::endl;
2950 : : }
2951 : 0 : return 1;
2952 : : }
2953 : :
2954 [ + - ]: 19 : localIdReverseMap[idx] = i;
2955 : : }
2956 : :
2957 : 38 : return 0;
2958 : : }
2959 : :
2960 : 2 : void PartMap::part_id_from_rank( int rank, std::vector< iMeshP_Part >& parts ) const
2961 : : {
2962 [ + + ]: 4 : for( size_t i = 0; i < sortedPartList.size(); ++i )
2963 [ + - ]: 2 : if( partRanks[i] == rank ) parts.push_back( sortedPartList[i] );
2964 : 2 : }
2965 : :
2966 : 1 : void PartMap::local_id_from_rank( int rank, std::vector< int >& ids ) const
2967 : : {
2968 [ + + ]: 2 : for( size_t i = 0; i < sortedPartList.size(); ++i )
2969 [ + - ]: 1 : if( partRanks[i] == rank ) ids.push_back( partLocalIds[i] );
2970 : 1 : }
2971 : :
2972 : 21 : int PartMap::part_from_coords( iMesh_Instance imesh, iMeshP_PartHandle part, int& id )
2973 : : {
2974 : : int ierr, rank;
2975 [ + - ]: 21 : MPI_Comm_rank( MPI_COMM_WORLD, &rank );
2976 : :
2977 : : // get elements
2978 : 21 : const int num_elem = 4;
2979 : : iBase_EntityHandle array[num_elem];
2980 : 21 : iBase_EntityHandle* ptr = array;
2981 : 21 : int junk1 = num_elem, n = -1;
2982 [ + - ][ - + ]: 21 : iMesh_getEntities( imesh, part, iBase_FACE, iMesh_QUADRILATERAL, &ptr, &junk1, &n, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2983 [ - + ]: 21 : assert( ptr == array );
2984 [ - + ]: 21 : assert( junk1 == num_elem );
2985 [ - + ]: 21 : if( n != num_elem )
2986 : : {
2987 [ # # ][ # # ]: 0 : std::cerr << "Internal error at " __FILE__ ":" << __LINE__ << " (proc " << rank
[ # # ][ # # ]
2988 [ # # ][ # # ]: 0 : << "): Expected all parts to have " << num_elem << " elements. Found one with " << n << std::endl;
[ # # ][ # # ]
[ # # ]
2989 : 0 : return 1;
2990 : : }
2991 : :
2992 : : // get vertices
2993 : : iBase_EntityHandle adj_array[4 * num_elem];
2994 : : int junk2, junk3, offset_array[5];
2995 : 21 : ptr = adj_array;
2996 : 21 : junk1 = sizeof( adj_array ) / sizeof( adj_array[0] );
2997 : 21 : junk2 = sizeof( offset_array ) / sizeof( offset_array[0] );
2998 : 21 : int* ptr2 = offset_array;
2999 [ + - ][ - + ]: 21 : iMesh_getEntArrAdj( imesh, array, num_elem, iBase_VERTEX, &ptr, &junk1, &n, &ptr2, &junk2, &junk3, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
3000 [ - + ]: 21 : assert( ptr == adj_array );
3001 [ - + ]: 21 : assert( ptr2 == offset_array );
3002 [ - + ]: 21 : assert( junk1 == sizeof( adj_array ) / sizeof( adj_array[0] ) );
3003 [ - + ]: 21 : assert( junk2 == sizeof( offset_array ) / sizeof( offset_array[0] ) );
3004 [ - + ]: 21 : assert( n == 4 * num_elem );
3005 [ - + ]: 21 : assert( offset_array[0] == 0 );
3006 [ + + ]: 105 : for( int i = 1; i < junk3; ++i )
3007 [ - + ]: 84 : assert( offset_array[i] - offset_array[i - 1] == 4 );
3008 : :
3009 : : // find center vertex
3010 : : iBase_EntityHandle vtx;
3011 : : bool all_match;
3012 [ + - ]: 63 : for( int i = 0; i < 4; ++i )
3013 : : {
3014 : 63 : vtx = adj_array[i];
3015 : 63 : all_match = true;
3016 [ + + ]: 252 : for( int j = 1; j < 4; ++j )
3017 : : {
3018 : 189 : iBase_EntityHandle* mvtx = adj_array + 4 * j;
3019 : : int k;
3020 [ + + ]: 693 : for( k = 0; k < 4; ++k )
3021 [ + + ]: 588 : if( mvtx[k] == vtx ) break;
3022 [ + + ]: 189 : if( k == 4 ) all_match = false;
3023 : : }
3024 [ + + ]: 63 : if( all_match ) break;
3025 : : }
3026 [ - + ]: 21 : assert( all_match );
3027 : :
3028 : : // get center vertex coordinates
3029 : : double x, y, z;
3030 [ + - ][ - + ]: 21 : iMesh_getVtxCoord( imesh, vtx, &x, &y, &z, &ierr );CHKERR;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
3031 [ - + ]: 21 : assert( 0.0 == z );
3032 : 21 : const int xi = ( (int)round( x ) - 1 ) / 2;
3033 : 21 : const int yi = ( (int)round( y ) - 1 ) / 2;
3034 [ - + ]: 21 : assert( xi >= 0 );
3035 [ - + ]: 21 : assert( yi >= 0 );
3036 [ - + ]: 21 : assert( fabs( x - 2 * xi - 1 ) < 1e-12 );
3037 [ - + ]: 21 : assert( fabs( y - 2 * yi - 1 ) < 1e-12 );
3038 : :
3039 : 21 : id = 2 * xi + yi;
3040 : 21 : return 0;
3041 [ + - ][ + - ]: 4 : }
|