LCOV - code coverage report
Current view: top level - itaps/imesh - MOAB_iMeshP_unit_tests.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 1149 1597 71.9 %
Date: 2020-12-16 07:07:30 Functions: 58 67 86.6 %
Branches: 1464 6950 21.1 %

           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], &copy, &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, &copy, &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 : }

Generated by: LCOV version 1.11