Xyst test code coverage report
Current view: top level - Partition - ZoltanGeom.cpp (source / functions) Hit Total Coverage
Commit: ac3d28f3f8b86b070d167d5aee7fb8740cd81df6 Lines: 80 85 94.1 %
Date: 2024-11-28 14:04:12 Functions: 6 6 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 41 88 46.6 %

           Branch data     Line data    Source code
       1                 :            : // *****************************************************************************
       2                 :            : /*!
       3                 :            :   \file      src/Partition/ZoltanGeom.cpp
       4                 :            :   \copyright 2012-2015 J. Bakosi,
       5                 :            :              2016-2018 Los Alamos National Security, LLC.,
       6                 :            :              2019-2021 Triad National Security, LLC.,
       7                 :            :              2022-2024 J. Bakosi
       8                 :            :              All rights reserved. See the LICENSE file for details.
       9                 :            :   \brief     Interoperation with the Zoltan library's geometric partitioners
      10                 :            : */
      11                 :            : // *****************************************************************************
      12                 :            : 
      13                 :            : #include <numeric>
      14                 :            : 
      15                 :            : #include "Compiler.hpp"
      16                 :            : 
      17                 :            : #if defined(__clang__)
      18                 :            :   #pragma clang diagnostic push
      19                 :            :   #pragma clang diagnostic ignored "-Wold-style-cast"
      20                 :            :   #pragma clang diagnostic ignored "-Wsuggest-override"
      21                 :            :   #pragma clang diagnostic ignored "-Wsuggest-destructor-override"
      22                 :            :   #pragma clang diagnostic ignored "-Wsign-conversion"
      23                 :            :   #pragma clang diagnostic ignored "-Wcast-align"
      24                 :            :   #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
      25                 :            :   #pragma clang diagnostic ignored "-Wdocumentation"
      26                 :            :   #pragma clang diagnostic ignored "-Wundef"
      27                 :            :   #pragma clang diagnostic ignored "-Wdollar-in-identifier-extension"
      28                 :            : #elif defined(STRICT_GNUC)
      29                 :            :   #pragma GCC diagnostic push
      30                 :            :   #pragma GCC diagnostic ignored "-Wcast-function-type"
      31                 :            : #endif
      32                 :            : 
      33                 :            : #include "zoltan.h"
      34                 :            : 
      35                 :            : #if defined(__clang__)
      36                 :            :   #pragma clang diagnostic pop
      37                 :            : #elif defined(STRICT_GNUC)
      38                 :            :   #pragma GCC diagnostic pop
      39                 :            : #endif
      40                 :            : 
      41                 :            : #include "ZoltanGeom.hpp"
      42                 :            : #include "ContainerUtil.hpp"
      43                 :            : 
      44                 :            : namespace inciter {
      45                 :            : 
      46                 :            : //! Zoltan mesh data structure
      47                 :            : struct MESH_DATA {
      48                 :            :   int numMyElems;
      49                 :            :   ZOLTAN_ID_PTR myGlobalIDs;
      50                 :            :   tk::real* x;
      51                 :            :   tk::real* y;
      52                 :            :   tk::real* z;
      53                 :            : };
      54                 :            : 
      55                 :            : static int
      56                 :       1829 : get_number_of_objects( void* data, int* ierr ) {
      57                 :       1829 :   MESH_DATA* mesh = static_cast< MESH_DATA* >( data );
      58                 :       1829 :   *ierr = ZOLTAN_OK;
      59                 :       1829 :   return mesh->numMyElems;
      60                 :            : }
      61                 :            : 
      62                 :            : static void
      63                 :       1175 : get_object_list( void* data, int /* sizeGID */, int /* sizeLID */,
      64                 :            :                  ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID,
      65                 :            :                  int /* wgt_dim */, float* /*obj_wgts */, int* ierr )
      66                 :            : {
      67                 :       1175 :   MESH_DATA* mesh = static_cast< MESH_DATA* >( data );
      68                 :       1175 :   *ierr = ZOLTAN_OK;
      69         [ +  + ]:    1256771 :   for (int i=0; i<mesh->numMyElems; ++i){
      70                 :    1255596 :     globalID[i] = mesh->myGlobalIDs[i];
      71                 :    1255596 :     localID[i] = static_cast< ZOLTAN_ID_TYPE >( i );
      72                 :            :   }
      73                 :       1175 : }
      74                 :            : 
      75                 :            : static int
      76                 :        723 : get_num_geometry( void* /*data */, int* ierr ) {
      77                 :        723 :   *ierr = ZOLTAN_OK;
      78                 :        723 :   return 3;
      79                 :            : }
      80                 :            : 
      81                 :            : static void
      82                 :        723 : get_geometry_list( void* data, int sizeGID, int sizeLID,
      83                 :            :                    int num_obj, ZOLTAN_ID_PTR /* globalID */,
      84                 :            :                    ZOLTAN_ID_PTR /* localID */,
      85                 :            :                    int num_dim, double* geom_vec, int* ierr )
      86                 :            : {
      87                 :        723 :   MESH_DATA *mesh = static_cast< MESH_DATA* >( data );
      88 [ +  - ][ +  - ]:        723 :   if ( (sizeGID != 1) || (sizeLID != 1) || (num_dim != 3)){
                 [ -  + ]
      89                 :          0 :     *ierr = ZOLTAN_FATAL;
      90                 :          0 :     return;
      91                 :            :   }
      92                 :        723 :   *ierr = ZOLTAN_OK;
      93         [ +  + ]:     731097 :   for (int i=0; i<num_obj; ++i) {
      94                 :     730374 :     geom_vec[3*i+0] = static_cast< tk::real >( mesh->x[i] );
      95                 :     730374 :     geom_vec[3*i+1] = static_cast< tk::real >( mesh->y[i] );
      96                 :     730374 :     geom_vec[3*i+2] = static_cast< tk::real >( mesh->z[i] );
      97                 :            :   }
      98                 :            : }
      99                 :            : 
     100                 :            : static
     101                 :            : std::array< std::vector< tk::real >, 3 >
     102                 :        723 : centroids( const std::vector< std::size_t >& inpoel,
     103                 :            :            const std::array< std::vector< tk::real >, 3 >& coord )
     104                 :            : // *****************************************************************************
     105                 :            : //  Compute element centroid coordinates
     106                 :            : //! \param[in] inpoel Mesh connectivity with local ids
     107                 :            : //! \param[in] coord Node coordinates
     108                 :            : //! \return Centroids for all cells on this compute node
     109                 :            : // *****************************************************************************
     110                 :            : {
     111 [ +  - ][ -  + ]:        723 :   Assert( tk::uniquecopy(inpoel).size() == coord[0].size(), "Size mismatch" );
         [ -  - ][ -  - ]
                 [ -  - ]
     112                 :            : 
     113                 :        723 :   const auto& x = coord[0];
     114                 :        723 :   const auto& y = coord[1];
     115                 :        723 :   const auto& z = coord[2];
     116                 :            : 
     117                 :            :   // Make room for element centroid coordinates
     118                 :        723 :   std::array< std::vector< tk::real >, 3 > cent;
     119                 :        723 :   auto& cx = cent[0];
     120                 :        723 :   auto& cy = cent[1];
     121                 :        723 :   auto& cz = cent[2];
     122                 :        723 :   auto num = inpoel.size()/4;
     123         [ +  - ]:        723 :   cx.resize( num );
     124         [ +  - ]:        723 :   cy.resize( num );
     125         [ +  - ]:        723 :   cz.resize( num );
     126                 :            : 
     127                 :            :   // Compute element centroids for mesh passed in
     128         [ +  + ]:     731097 :   for (std::size_t e=0; e<num; ++e) {
     129                 :     730374 :     auto A = inpoel[e*4+0];
     130                 :     730374 :     auto B = inpoel[e*4+1];
     131                 :     730374 :     auto C = inpoel[e*4+2];
     132                 :     730374 :     auto D = inpoel[e*4+3];
     133                 :     730374 :     cx[e] = (x[A] + x[B] + x[C] + x[D]) / 4.0;
     134                 :     730374 :     cy[e] = (y[A] + y[B] + y[C] + y[D]) / 4.0;
     135                 :     730374 :     cz[e] = (z[A] + z[B] + z[C] + z[D]) / 4.0;
     136                 :            :   }
     137                 :            : 
     138                 :        723 :   return cent;
     139                 :          0 : }
     140                 :            : 
     141                 :            : std::vector< std::size_t >
     142                 :        723 : geomPartMesh( const char* alg,
     143                 :            :               const std::vector< std::string >& zoltan_params,
     144                 :            :               const std::vector< std::size_t >& inpoel,
     145                 :            :               const std::array< std::vector< tk::real >, 3 >& coord,
     146                 :            :               int npart )
     147                 :            : // *****************************************************************************
     148                 :            : //  Partition mesh using Zoltan with a geometric partitioner
     149                 :            : //! \param[in] alg Partitioning algorithm to use
     150                 :            : //! \param[in] zoltan_params Extra parameters pass to zoltan
     151                 :            : //! \param[in] inpoel Mesh connectivity with local ids
     152                 :            : //! \param[in] coord Node coordinates
     153                 :            : //! \param[in] npart Number of desired partitions
     154                 :            : //! \return Array of chare ownership IDs mapping elements to chares
     155                 :            : //! \details This function uses Zoltan to partition the mesh in parallel.
     156                 :            : //!   It assumes that the mesh is distributed among all the MPI ranks.
     157                 :            : // *****************************************************************************
     158                 :            : {
     159                 :            :   float ver;
     160                 :            :   struct Zoltan_Struct *zz;
     161                 :            :   int changes, numGidEntries, numLidEntries, numImport, numExport;
     162                 :            :   ZOLTAN_ID_PTR importGlobalGids, importLocalGids, exportGlobalGids,
     163                 :            :                 exportLocalGids;
     164                 :            :   int *importProcs, *importToPart, *exportProcs, *exportToPart;
     165                 :            : 
     166         [ +  - ]:        723 :   std::vector< unsigned int > elemid( inpoel.size()/4 );
     167                 :        723 :   std::iota( begin(elemid), end(elemid), 0 );
     168                 :            : 
     169                 :            :   MESH_DATA myMesh;
     170                 :        723 :   myMesh.numMyElems = static_cast< int >( elemid.size() );
     171                 :        723 :   myMesh.myGlobalIDs = const_cast< unsigned int* >( elemid.data() );
     172                 :            : 
     173         [ +  - ]:        723 :   auto cent = centroids( inpoel, coord );
     174                 :        723 :   myMesh.x = const_cast< tk::real* >( cent[0].data() );
     175                 :        723 :   myMesh.y = const_cast< tk::real* >( cent[1].data() );
     176                 :        723 :   myMesh.z = const_cast< tk::real* >( cent[2].data() );
     177                 :            : 
     178         [ +  - ]:        723 :   Zoltan_Initialize( 0, nullptr, &ver );
     179                 :            : 
     180         [ +  - ]:        723 :   zz = Zoltan_Create( MPI_COMM_WORLD );
     181                 :            : 
     182         [ +  - ]:        723 :   Zoltan_Set_Param( zz, "DEBUG_LEVEL", "0" );
     183         [ +  - ]:        723 :   Zoltan_Set_Param( zz, "LB_METHOD", alg );
     184         [ +  - ]:        723 :   Zoltan_Set_Param( zz, "LB_APPROACH", "PARTITION" );
     185         [ +  - ]:        723 :   Zoltan_Set_Param( zz, "NUM_GID_ENTRIES", "1" );
     186         [ +  - ]:        723 :   Zoltan_Set_Param( zz, "NUM_LID_ENTRIES", "1" );
     187         [ +  - ]:        723 :   Zoltan_Set_Param( zz, "OBJ_WEIGHT_DIM", "0" );
     188         [ +  - ]:        723 :   Zoltan_Set_Param( zz, "RETURN_LISTS", "PART" );
     189         [ +  - ]:        723 :   Zoltan_Set_Param( zz, "RCB_OUTPUT_LEVEL", "0" );
     190         [ +  - ]:        723 :   Zoltan_Set_Param( zz, "AVERAGE_CUTS", "1" );
     191         [ +  - ]:        723 :   Zoltan_Set_Param( zz, "NUM_GLOBAL_PARTS", std::to_string(npart).c_str() );
     192                 :            : 
     193         [ -  + ]:        723 :   for (std::size_t i=0; i<zoltan_params.size()/2; ++i) {
     194                 :          0 :     const auto p = zoltan_params.data() + i*2;
     195         [ -  - ]:          0 :     Zoltan_Set_Param( zz, p[0].c_str(), p[1].c_str() );
     196                 :            :   }
     197                 :            : 
     198                 :            :   /* Query functions, to provide geometry to Zoltan */
     199                 :            : 
     200         [ +  - ]:        723 :   Zoltan_Set_Num_Obj_Fn( zz, get_number_of_objects, &myMesh );
     201         [ +  - ]:        723 :   Zoltan_Set_Obj_List_Fn( zz, get_object_list, &myMesh );
     202         [ +  - ]:        723 :   Zoltan_Set_Num_Geom_Fn( zz, get_num_geometry, &myMesh );
     203         [ +  - ]:        723 :   Zoltan_Set_Geom_Multi_Fn( zz, get_geometry_list, &myMesh );
     204                 :            : 
     205         [ +  - ]:        723 :   Zoltan_LB_Partition(zz, /* input (all remaining fields are output) */
     206                 :            :         &changes,        /* 1 if partitioning was changed, 0 otherwise */
     207                 :            :         &numGidEntries,  /* Number of integers used for a global ID */
     208                 :            :         &numLidEntries,  /* Number of integers used for a local ID */
     209                 :            :         &numImport,      /* Number of vertices to be sent to me */
     210                 :            :         &importGlobalGids,  /* Global IDs of vertices to be sent to me */
     211                 :            :         &importLocalGids,   /* Local IDs of vertices to be sent to me */
     212                 :            :         &importProcs,    /* Process rank for source of each incoming vertex */
     213                 :            :         &importToPart,   /* New partition for each incoming vertex */
     214                 :            :         &numExport,      /* Number of vertices I must send to other processes*/
     215                 :            :         &exportGlobalGids,  /* Global IDs of the vertices I must send */
     216                 :            :         &exportLocalGids,   /* Local IDs of the vertices I must send */
     217                 :            :         &exportProcs,    /* Process to which I send each of the vertices */
     218                 :            :         &exportToPart);  /* Partition to which each vertex will belong */
     219                 :            : 
     220 [ -  + ][ -  - ]:        723 :   Assert( numExport == static_cast< int >( elemid.size() ), "Size mismatch" );
         [ -  - ][ -  - ]
     221                 :            : 
     222                 :            :   // Copy over array of chare IDs corresponding to the ownership of elements in
     223                 :            :   // our chunk of the mesh, i.e., the coloring or chare ids for the mesh
     224                 :            :   // elements we operate on.
     225         [ +  - ]:        723 :   std::vector< std::size_t > chare( elemid.size() );
     226         [ +  + ]:     731097 :   for (std::size_t p=0; p<static_cast<std::size_t>(numExport); ++p )
     227                 :     730374 :     chare[ exportLocalGids[p] ] = static_cast< std::size_t >( exportToPart[p] );
     228                 :            : 
     229                 :            :   /******************************************************************
     230                 :            :   ** Free the arrays allocated by Zoltan_LB_Partition, and free
     231                 :            :   ** the storage allocated for the Zoltan structure.
     232                 :            :   ******************************************************************/
     233                 :            : 
     234         [ +  - ]:        723 :   Zoltan_LB_Free_Part( &importGlobalGids, &importLocalGids,
     235                 :            :                        &importProcs, &importToPart );
     236         [ +  - ]:        723 :   Zoltan_LB_Free_Part( &exportGlobalGids, &exportLocalGids,
     237                 :            :                        &exportProcs, &exportToPart );
     238                 :            : 
     239         [ +  - ]:        723 :   Zoltan_Destroy( &zz );
     240                 :            : 
     241                 :       1446 :   return chare;
     242                 :        723 : }
     243                 :            : 
     244                 :            : } // inciter::

Generated by: LCOV version 1.16