LCOV - code coverage report
Current view: top level - src/io - NCHelperMPAS.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 1 685 0.1 %
Date: 2020-12-16 07:07:30 Functions: 2 18 11.1 %
Branches: 2 2584 0.1 %

           Branch data     Line data    Source code
       1                 :            : #include "NCHelperMPAS.hpp"
       2                 :            : #include "moab/ReadUtilIface.hpp"
       3                 :            : #include "moab/FileOptions.hpp"
       4                 :            : #include "moab/SpectralMeshTool.hpp"
       5                 :            : #include "MBTagConventions.hpp"
       6                 :            : 
       7                 :            : #ifdef MOAB_HAVE_ZOLTAN
       8                 :            : #include "moab/ZoltanPartitioner.hpp"
       9                 :            : #endif
      10                 :            : 
      11                 :            : #include <cmath>
      12                 :            : 
      13                 :            : namespace moab
      14                 :            : {
      15                 :            : 
      16                 :            : const int DEFAULT_MAX_EDGES_PER_CELL = 10;
      17                 :            : 
      18                 :          0 : NCHelperMPAS::NCHelperMPAS( ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet )
      19                 :            :     : UcdNCHelper( readNC, fileId, opts, fileSet ), maxEdgesPerCell( DEFAULT_MAX_EDGES_PER_CELL ), numCellGroups( 0 ),
      20 [ #  # ][ #  # ]:          0 :       createGatherSet( false )
      21                 :            : {
      22                 :            :     // Ignore variables containing topological information
      23 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "nEdgesOnEdge" );
      24 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "nEdgesOnCell" );
      25 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "edgesOnVertex" );
      26 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "cellsOnVertex" );
      27 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "verticesOnEdge" );
      28 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "edgesOnEdge" );
      29 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "cellsOnEdge" );
      30 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "verticesOnCell" );
      31 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "edgesOnCell" );
      32 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "cellsOnCell" );
      33                 :            :     // ignore variables containing mesh related info, that are currently saved as variable tags on
      34                 :            :     // file set ; if needed, these should be saved as dense tags, and read accordingly, in parallel
      35 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "weightsOnEdge" );
      36 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "angleEdge" );
      37 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "areaCell" );
      38 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "areaTriangle" );
      39 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "dcEdge" );
      40 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "dv1Edge" );
      41 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "dv2Edge" );
      42 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "fEdge" );
      43 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "fVertex" );
      44 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "h_s" );
      45 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "kiteAreasOnVertex" );
      46 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "latCell" );
      47 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "latEdge" );
      48 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "latVertex" );
      49 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "lonCell" );
      50 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "lonEdge" );
      51 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "lonVertex" );
      52 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "meshDensity" );
      53 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "xCell" );
      54 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "xEdge" );
      55 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "xVertex" );
      56 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "yCell" );
      57 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "yEdge" );
      58 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "yVertex" );
      59 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "zCell" );
      60 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "zEdge" );
      61 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "zVertex" );
      62                 :            :     // Ignore variables for index conversion
      63 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "indexToVertexID" );
      64 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "indexToEdgeID" );
      65 [ #  # ][ #  # ]:          0 :     ignoredVarNames.insert( "indexToCellID" );
      66                 :          0 : }
      67                 :            : 
      68                 :          0 : bool NCHelperMPAS::can_read_file( ReadNC* readNC )
      69                 :            : {
      70                 :          0 :     std::vector< std::string >& dimNames = readNC->dimNames;
      71                 :            : 
      72                 :            :     // If dimension name "vertexDegree" exists then it should be the MPAS grid
      73 [ #  # ][ #  # ]:          0 :     if( std::find( dimNames.begin(), dimNames.end(), std::string( "vertexDegree" ) ) != dimNames.end() ) return true;
         [ #  # ][ #  # ]
      74                 :            : 
      75                 :          0 :     return false;
      76                 :            : }
      77                 :            : 
      78                 :          0 : ErrorCode NCHelperMPAS::init_mesh_vals()
      79                 :            : {
      80                 :          0 :     std::vector< std::string >& dimNames              = _readNC->dimNames;
      81                 :          0 :     std::vector< int >& dimLens                       = _readNC->dimLens;
      82                 :          0 :     std::map< std::string, ReadNC::VarData >& varInfo = _readNC->varInfo;
      83                 :            : 
      84                 :            :     ErrorCode rval;
      85                 :            :     unsigned int idx;
      86                 :          0 :     std::vector< std::string >::iterator vit;
      87                 :            : 
      88                 :            :     // Get max edges per cell reported in the MPAS file header
      89 [ #  # ][ #  # ]:          0 :     if( ( vit = std::find( dimNames.begin(), dimNames.end(), "maxEdges" ) ) != dimNames.end() )
                 [ #  # ]
      90                 :            :     {
      91         [ #  # ]:          0 :         idx             = vit - dimNames.begin();
      92         [ #  # ]:          0 :         maxEdgesPerCell = dimLens[idx];
      93         [ #  # ]:          0 :         if( maxEdgesPerCell > DEFAULT_MAX_EDGES_PER_CELL )
      94                 :            :         {
      95 [ #  # ][ #  # ]:          0 :             MB_SET_ERR( MB_INVALID_SIZE,
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
      96                 :            :                         "maxEdgesPerCell read from the MPAS file header has exceeded " << DEFAULT_MAX_EDGES_PER_CELL );
      97                 :            :         }
      98                 :            :     }
      99                 :            : 
     100                 :            :     // Look for time dimension
     101 [ #  # ][ #  # ]:          0 :     if( ( vit = std::find( dimNames.begin(), dimNames.end(), "Time" ) ) != dimNames.end() )
                 [ #  # ]
     102         [ #  # ]:          0 :         idx = vit - dimNames.begin();
     103 [ #  # ][ #  # ]:          0 :     else if( ( vit = std::find( dimNames.begin(), dimNames.end(), "time" ) ) != dimNames.end() )
                 [ #  # ]
     104         [ #  # ]:          0 :         idx = vit - dimNames.begin();
     105                 :            :     else
     106                 :            :     {
     107 [ #  # ][ #  # ]:          0 :         MB_SET_ERR( MB_FAILURE, "Couldn't find 'Time' or 'time' dimension" );
         [ #  # ][ #  # ]
                 [ #  # ]
     108                 :            :     }
     109                 :          0 :     tDim       = idx;
     110         [ #  # ]:          0 :     nTimeSteps = dimLens[idx];
     111                 :            : 
     112                 :            :     // Get number of cells
     113 [ #  # ][ #  # ]:          0 :     if( ( vit = std::find( dimNames.begin(), dimNames.end(), "nCells" ) ) != dimNames.end() )
                 [ #  # ]
     114         [ #  # ]:          0 :         idx = vit - dimNames.begin();
     115                 :            :     else
     116                 :            :     {
     117 [ #  # ][ #  # ]:          0 :         MB_SET_ERR( MB_FAILURE, "Couldn't find 'nCells' dimension" );
         [ #  # ][ #  # ]
                 [ #  # ]
     118                 :            :     }
     119                 :          0 :     cDim   = idx;
     120         [ #  # ]:          0 :     nCells = dimLens[idx];
     121                 :            : 
     122                 :            :     // Get number of edges
     123 [ #  # ][ #  # ]:          0 :     if( ( vit = std::find( dimNames.begin(), dimNames.end(), "nEdges" ) ) != dimNames.end() )
                 [ #  # ]
     124         [ #  # ]:          0 :         idx = vit - dimNames.begin();
     125                 :            :     else
     126                 :            :     {
     127 [ #  # ][ #  # ]:          0 :         MB_SET_ERR( MB_FAILURE, "Couldn't find 'nEdges' dimension" );
         [ #  # ][ #  # ]
                 [ #  # ]
     128                 :            :     }
     129                 :          0 :     eDim   = idx;
     130         [ #  # ]:          0 :     nEdges = dimLens[idx];
     131                 :            : 
     132                 :            :     // Get number of vertices
     133                 :          0 :     vDim = -1;
     134 [ #  # ][ #  # ]:          0 :     if( ( vit = std::find( dimNames.begin(), dimNames.end(), "nVertices" ) ) != dimNames.end() )
                 [ #  # ]
     135         [ #  # ]:          0 :         idx = vit - dimNames.begin();
     136                 :            :     else
     137                 :            :     {
     138 [ #  # ][ #  # ]:          0 :         MB_SET_ERR( MB_FAILURE, "Couldn't find 'nVertices' dimension" );
         [ #  # ][ #  # ]
                 [ #  # ]
     139                 :            :     }
     140                 :          0 :     vDim      = idx;
     141         [ #  # ]:          0 :     nVertices = dimLens[idx];
     142                 :            : 
     143                 :            :     // Get number of vertex levels
     144 [ #  # ][ #  # ]:          0 :     if( ( vit = std::find( dimNames.begin(), dimNames.end(), "nVertLevels" ) ) != dimNames.end() )
                 [ #  # ]
     145         [ #  # ]:          0 :         idx = vit - dimNames.begin();
     146                 :            :     else
     147                 :            :     {
     148                 :            :         std::cerr << "Warning: dimension nVertLevels not found in header.\nThe file may contain "
     149         [ #  # ]:          0 :                      "just the mesh"
     150         [ #  # ]:          0 :                   << std::endl;
     151                 :            :     }
     152                 :          0 :     levDim  = idx;
     153         [ #  # ]:          0 :     nLevels = dimLens[idx];
     154                 :            : 
     155                 :            :     // Dimension indices for other optional levels
     156         [ #  # ]:          0 :     std::vector< unsigned int > opt_lev_dims;
     157                 :            : 
     158                 :            :     // Get index of vertex levels P1
     159 [ #  # ][ #  # ]:          0 :     if( ( vit = std::find( dimNames.begin(), dimNames.end(), "nVertLevelsP1" ) ) != dimNames.end() )
                 [ #  # ]
     160                 :            :     {
     161         [ #  # ]:          0 :         idx = vit - dimNames.begin();
     162         [ #  # ]:          0 :         opt_lev_dims.push_back( idx );
     163                 :            :     }
     164                 :            : 
     165                 :            :     // Get index of vertex levels P2
     166 [ #  # ][ #  # ]:          0 :     if( ( vit = std::find( dimNames.begin(), dimNames.end(), "nVertLevelsP2" ) ) != dimNames.end() )
                 [ #  # ]
     167                 :            :     {
     168         [ #  # ]:          0 :         idx = vit - dimNames.begin();
     169         [ #  # ]:          0 :         opt_lev_dims.push_back( idx );
     170                 :            :     }
     171                 :            : 
     172                 :            :     // Get index of soil levels
     173 [ #  # ][ #  # ]:          0 :     if( ( vit = std::find( dimNames.begin(), dimNames.end(), "nSoilLevels" ) ) != dimNames.end() )
                 [ #  # ]
     174                 :            :     {
     175         [ #  # ]:          0 :         idx = vit - dimNames.begin();
     176         [ #  # ]:          0 :         opt_lev_dims.push_back( idx );
     177                 :            :     }
     178                 :            : 
     179         [ #  # ]:          0 :     std::map< std::string, ReadNC::VarData >::iterator vmit;
     180                 :            : 
     181                 :            :     // Store time coordinate values in tVals
     182         [ #  # ]:          0 :     if( nTimeSteps > 0 )
     183                 :            :     {
     184                 :            :         // Note, two possible types for xtime variable: double(Time) or char(Time, StrLen)
     185 [ #  # ][ #  # ]:          0 :         if( ( vmit = varInfo.find( "xtime" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  #  
          #  #  #  #  #  
                      # ]
     186                 :            :         {
     187                 :            :             // If xtime variable is double type, read time coordinate values to tVals
     188 [ #  # ][ #  # ]:          0 :             rval = read_coordinate( "xtime", 0, nTimeSteps - 1, tVals );MB_CHK_SET_ERR( rval, "Trouble reading 'xtime' variable" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     189                 :            :         }
     190                 :            :         else
     191                 :            :         {
     192                 :            :             // If xtime variable does not exist, or it is string type, set dummy values to tVals
     193         [ #  # ]:          0 :             for( int t = 0; t < nTimeSteps; t++ )
     194         [ #  # ]:          0 :                 tVals.push_back( (double)t );
     195                 :            :         }
     196                 :            :     }
     197                 :            : 
     198                 :            :     // For each variable, determine the entity location type and number of levels
     199 [ #  # ][ #  # ]:          0 :     for( vmit = varInfo.begin(); vmit != varInfo.end(); ++vmit )
                 [ #  # ]
     200                 :            :     {
     201         [ #  # ]:          0 :         ReadNC::VarData& vd = ( *vmit ).second;
     202                 :            : 
     203                 :            :         // Default entLoc is ENTLOCSET
     204 [ #  # ][ #  # ]:          0 :         if( std::find( vd.varDims.begin(), vd.varDims.end(), tDim ) != vd.varDims.end() )
                 [ #  # ]
     205                 :            :         {
     206 [ #  # ][ #  # ]:          0 :             if( std::find( vd.varDims.begin(), vd.varDims.end(), vDim ) != vd.varDims.end() )
                 [ #  # ]
     207                 :          0 :                 vd.entLoc = ReadNC::ENTLOCVERT;
     208 [ #  # ][ #  # ]:          0 :             else if( std::find( vd.varDims.begin(), vd.varDims.end(), eDim ) != vd.varDims.end() )
                 [ #  # ]
     209                 :          0 :                 vd.entLoc = ReadNC::ENTLOCEDGE;
     210 [ #  # ][ #  # ]:          0 :             else if( std::find( vd.varDims.begin(), vd.varDims.end(), cDim ) != vd.varDims.end() )
                 [ #  # ]
     211                 :          0 :                 vd.entLoc = ReadNC::ENTLOCFACE;
     212                 :            :         }
     213                 :            : 
     214                 :            :         // Default numLev is 0
     215 [ #  # ][ #  # ]:          0 :         if( std::find( vd.varDims.begin(), vd.varDims.end(), levDim ) != vd.varDims.end() )
                 [ #  # ]
     216                 :          0 :             vd.numLev = nLevels;
     217                 :            :         else
     218                 :            :         {
     219                 :            :             // If nVertLevels dimension is not found, try other optional levels such as
     220                 :            :             // nVertLevelsP1
     221         [ #  # ]:          0 :             for( unsigned int i = 0; i < opt_lev_dims.size(); i++ )
     222                 :            :             {
     223 [ #  # ][ #  # ]:          0 :                 if( std::find( vd.varDims.begin(), vd.varDims.end(), opt_lev_dims[i] ) != vd.varDims.end() )
         [ #  # ][ #  # ]
     224                 :            :                 {
     225 [ #  # ][ #  # ]:          0 :                     vd.numLev = dimLens[opt_lev_dims[i]];
     226                 :          0 :                     break;
     227                 :            :                 }
     228                 :            :             }
     229                 :            :         }
     230                 :            : 
     231                 :            :         // Hack: ignore variables with more than 3 dimensions, e.g. tracers(Time, nCells,
     232                 :            :         // nVertLevels, nTracers)
     233 [ #  # ][ #  # ]:          0 :         if( vd.varDims.size() > 3 ) ignoredVarNames.insert( vd.varName );
     234                 :            :     }
     235                 :            : 
     236                 :            :     // Hack: create dummy variables for dimensions (like nCells) with no corresponding coordinate
     237                 :            :     // variables
     238 [ #  # ][ #  # ]:          0 :     rval = create_dummy_variables();MB_CHK_SET_ERR( rval, "Failed to create dummy variables" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     239                 :            : 
     240                 :          0 :     return MB_SUCCESS;
     241                 :            : }
     242                 :            : 
     243                 :            : // When noMesh option is used on this read, the old ReadNC class instance for last read can get out
     244                 :            : // of scope (and deleted). The old instance initialized some variables properly when the mesh was
     245                 :            : // created, but they are now lost. The new instance (will not create the mesh with noMesh option)
     246                 :            : // has to restore them based on the existing mesh from last read
     247                 :          0 : ErrorCode NCHelperMPAS::check_existing_mesh()
     248                 :            : {
     249                 :          0 :     Interface*& mbImpl = _readNC->mbImpl;
     250                 :          0 :     Tag& mGlobalIdTag  = _readNC->mGlobalIdTag;
     251                 :          0 :     bool& noMesh       = _readNC->noMesh;
     252                 :            : 
     253         [ #  # ]:          0 :     if( noMesh )
     254                 :            :     {
     255                 :            :         ErrorCode rval;
     256                 :            : 
     257                 :            :         // Restore numCellGroups
     258         [ #  # ]:          0 :         if( 0 == numCellGroups )
     259                 :            :         {
     260                 :            :             Tag numCellGroupsTag;
     261 [ #  # ][ #  # ]:          0 :             rval = mbImpl->tag_get_handle( "__NUM_CELL_GROUPS", 1, MB_TYPE_INTEGER, numCellGroupsTag );MB_CHK_SET_ERR( rval, "Trouble getting __NUM_CELL_GROUPS tag" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     262 [ #  # ][ #  # ]:          0 :             if( MB_SUCCESS == rval ) rval = mbImpl->tag_get_data( numCellGroupsTag, &_fileSet, 1, &numCellGroups );MB_CHK_SET_ERR( rval, "Trouble getting data of __NUM_CELL_GROUPS tag" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     263                 :            :         }
     264                 :            : 
     265         [ #  # ]:          0 :         if( localGidVerts.empty() )
     266                 :            :         {
     267                 :            :             // Get all vertices from current file set (it is the input set in no_mesh scenario)
     268         [ #  # ]:          0 :             Range local_verts;
     269 [ #  # ][ #  # ]:          0 :             rval = mbImpl->get_entities_by_dimension( _fileSet, 0, local_verts );MB_CHK_SET_ERR( rval, "Trouble getting local vertices in current file set" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     270                 :            : 
     271 [ #  # ][ #  # ]:          0 :             if( !local_verts.empty() )
     272                 :            :             {
     273 [ #  # ][ #  # ]:          0 :                 std::vector< int > gids( local_verts.size() );
     274                 :            : 
     275                 :            :                 // !IMPORTANT : this has to be the GLOBAL_ID tag
     276 [ #  # ][ #  # ]:          0 :                 rval = mbImpl->tag_get_data( mGlobalIdTag, local_verts, &gids[0] );MB_CHK_SET_ERR( rval, "Trouble getting local gid values of vertices" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     277                 :            : 
     278                 :            :                 // Restore localGidVerts
     279 [ #  # ][ #  # ]:          0 :                 std::copy( gids.rbegin(), gids.rend(), range_inserter( localGidVerts ) );
     280 [ #  # ][ #  # ]:          0 :                 nLocalVertices = localGidVerts.size();
                 [ #  # ]
     281                 :          0 :             }
     282                 :            :         }
     283                 :            : 
     284         [ #  # ]:          0 :         if( localGidEdges.empty() )
     285                 :            :         {
     286                 :            :             // Get all edges from current file set (it is the input set in no_mesh scenario)
     287         [ #  # ]:          0 :             Range local_edges;
     288 [ #  # ][ #  # ]:          0 :             rval = mbImpl->get_entities_by_dimension( _fileSet, 1, local_edges );MB_CHK_SET_ERR( rval, "Trouble getting local edges in current file set" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     289                 :            : 
     290 [ #  # ][ #  # ]:          0 :             if( !local_edges.empty() )
     291                 :            :             {
     292 [ #  # ][ #  # ]:          0 :                 std::vector< int > gids( local_edges.size() );
     293                 :            : 
     294                 :            :                 // !IMPORTANT : this has to be the GLOBAL_ID tag
     295 [ #  # ][ #  # ]:          0 :                 rval = mbImpl->tag_get_data( mGlobalIdTag, local_edges, &gids[0] );MB_CHK_SET_ERR( rval, "Trouble getting local gid values of edges" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     296                 :            : 
     297                 :            :                 // Restore localGidEdges
     298 [ #  # ][ #  # ]:          0 :                 std::copy( gids.rbegin(), gids.rend(), range_inserter( localGidEdges ) );
     299 [ #  # ][ #  # ]:          0 :                 nLocalEdges = localGidEdges.size();
                 [ #  # ]
     300                 :          0 :             }
     301                 :            :         }
     302                 :            : 
     303         [ #  # ]:          0 :         if( localGidCells.empty() )
     304                 :            :         {
     305                 :            :             // Get all cells from current file set (it is the input set in no_mesh scenario)
     306         [ #  # ]:          0 :             Range local_cells;
     307 [ #  # ][ #  # ]:          0 :             rval = mbImpl->get_entities_by_dimension( _fileSet, 2, local_cells );MB_CHK_SET_ERR( rval, "Trouble getting local cells in current file set" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     308                 :            : 
     309 [ #  # ][ #  # ]:          0 :             if( !local_cells.empty() )
     310                 :            :             {
     311 [ #  # ][ #  # ]:          0 :                 std::vector< int > gids( local_cells.size() );
     312                 :            : 
     313                 :            :                 // !IMPORTANT : this has to be the GLOBAL_ID tag
     314 [ #  # ][ #  # ]:          0 :                 rval = mbImpl->tag_get_data( mGlobalIdTag, local_cells, &gids[0] );MB_CHK_SET_ERR( rval, "Trouble getting local gid values of cells" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     315                 :            : 
     316                 :            :                 // Restore localGidCells
     317 [ #  # ][ #  # ]:          0 :                 std::copy( gids.rbegin(), gids.rend(), range_inserter( localGidCells ) );
     318         [ #  # ]:          0 :                 nLocalCells = localGidCells.size();
     319                 :            : 
     320         [ #  # ]:          0 :                 if( numCellGroups > 1 )
     321                 :            :                 {
     322                 :            :                     // Restore cellHandleToGlobalID map
     323         [ #  # ]:          0 :                     Range::const_iterator rit;
     324                 :            :                     int i;
     325 [ #  # ][ #  # ]:          0 :                     for( rit = local_cells.begin(), i = 0; rit != local_cells.end(); ++rit, i++ )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     326 [ #  # ][ #  # ]:          0 :                         cellHandleToGlobalID[*rit] = gids[i];
                 [ #  # ]
     327         [ #  # ]:          0 :                 }
     328                 :          0 :             }
     329                 :            :         }
     330                 :            :     }
     331                 :            : 
     332                 :          0 :     return MB_SUCCESS;
     333                 :            : }
     334                 :            : 
     335                 :          0 : ErrorCode NCHelperMPAS::create_mesh( Range& faces )
     336                 :            : {
     337                 :          0 :     Interface*& mbImpl    = _readNC->mbImpl;
     338                 :          0 :     bool& noMixedElements = _readNC->noMixedElements;
     339                 :          0 :     bool& noEdges         = _readNC->noEdges;
     340                 :          0 :     DebugOutput& dbgOut   = _readNC->dbgOut;
     341                 :            : 
     342                 :            : #ifdef MOAB_HAVE_MPI
     343                 :          0 :     int rank         = 0;
     344                 :          0 :     int procs        = 1;
     345                 :          0 :     bool& isParallel = _readNC->isParallel;
     346         [ #  # ]:          0 :     if( isParallel )
     347                 :            :     {
     348                 :          0 :         ParallelComm*& myPcomm = _readNC->myPcomm;
     349 [ #  # ][ #  # ]:          0 :         rank                   = myPcomm->proc_config().proc_rank();
     350 [ #  # ][ #  # ]:          0 :         procs                  = myPcomm->proc_config().proc_size();
     351                 :            :     }
     352                 :            : 
     353                 :            :     // Need to know whether we'll be creating gather mesh
     354         [ #  # ]:          0 :     if( rank == _readNC->gatherSetRank ) createGatherSet = true;
     355                 :            : 
     356         [ #  # ]:          0 :     if( procs >= 2 )
     357                 :            :     {
     358                 :            :         // Shift rank to obtain a rotated trivial partition
     359                 :          0 :         int shifted_rank           = rank;
     360                 :          0 :         int& trivialPartitionShift = _readNC->trivialPartitionShift;
     361         [ #  # ]:          0 :         if( trivialPartitionShift > 0 ) shifted_rank = ( rank + trivialPartitionShift ) % procs;
     362                 :            : 
     363                 :            :         // Compute the number of local cells on this proc
     364                 :          0 :         nLocalCells = int( std::floor( 1.0 * nCells / procs ) );
     365                 :            : 
     366                 :            :         // The starting global cell index in the MPAS file for this proc
     367                 :          0 :         int start_cell_idx = shifted_rank * nLocalCells;
     368                 :            : 
     369                 :            :         // Number of extra cells after equal split over procs
     370                 :          0 :         int iextra = nCells % procs;
     371                 :            : 
     372                 :            :         // Allocate extra cells over procs
     373         [ #  # ]:          0 :         if( shifted_rank < iextra ) nLocalCells++;
     374         [ #  # ]:          0 :         start_cell_idx += std::min( shifted_rank, iextra );
     375                 :            : 
     376                 :          0 :         start_cell_idx++;  // 0 based -> 1 based
     377                 :            : 
     378                 :            :         // Redistribute local cells after trivial partition (e.g. apply Zoltan partition)
     379 [ #  # ][ #  # ]:          0 :         ErrorCode rval = redistribute_local_cells( start_cell_idx );MB_CHK_SET_ERR( rval, "Failed to redistribute local cells after trivial partition" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     380                 :            :     }
     381                 :            :     else
     382                 :            :     {
     383                 :          0 :         nLocalCells = nCells;
     384         [ #  # ]:          0 :         localGidCells.insert( 1, nLocalCells );
     385                 :            :     }
     386                 :            : #else
     387                 :            :     nLocalCells = nCells;
     388                 :            :     localGidCells.insert( 1, nLocalCells );
     389                 :            : #endif
     390 [ #  # ][ #  # ]:          0 :     dbgOut.tprintf( 1, " localGidCells.psize() = %d\n", (int)localGidCells.psize() );
     391 [ #  # ][ #  # ]:          0 :     dbgOut.tprintf( 1, " localGidCells.size() = %d\n", (int)localGidCells.size() );
     392                 :            : 
     393                 :            :     // Read number of edges on each local cell, to calculate actual maxEdgesPerCell
     394                 :            :     int nEdgesOnCellVarId;
     395         [ #  # ]:          0 :     int success = NCFUNC( inq_varid )( _fileId, "nEdgesOnCell", &nEdgesOnCellVarId );
     396 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of nEdgesOnCell" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     397         [ #  # ]:          0 :     std::vector< int > num_edges_on_local_cells( nLocalCells );
     398                 :            : #ifdef MOAB_HAVE_PNETCDF
     399                 :            :     size_t nb_reads = localGidCells.psize();
     400                 :            :     std::vector< int > requests( nb_reads );
     401                 :            :     std::vector< int > statuss( nb_reads );
     402                 :            :     size_t idxReq = 0;
     403                 :            : #endif
     404                 :          0 :     size_t indexInArray = 0;
     405 [ #  # ][ #  # ]:          0 :     for( Range::pair_iterator pair_iter = localGidCells.pair_begin(); pair_iter != localGidCells.pair_end();
         [ #  # ][ #  # ]
                 [ #  # ]
     406                 :            :          ++pair_iter )
     407                 :            :     {
     408         [ #  # ]:          0 :         EntityHandle starth  = pair_iter->first;
     409         [ #  # ]:          0 :         EntityHandle endh    = pair_iter->second;
     410                 :          0 :         NCDF_SIZE read_start = ( NCDF_SIZE )( starth - 1 );
     411                 :          0 :         NCDF_SIZE read_count = ( NCDF_SIZE )( endh - starth + 1 );
     412                 :            : 
     413                 :            :         // Do a partial read in each subrange
     414                 :            : #ifdef MOAB_HAVE_PNETCDF
     415                 :            :         success = NCFUNCREQG( _vara_int )( _fileId, nEdgesOnCellVarId, &read_start, &read_count,
     416                 :            :                                            &( num_edges_on_local_cells[indexInArray] ), &requests[idxReq++] );
     417                 :            : #else
     418                 :            :         success = NCFUNCAG( _vara_int )( _fileId, nEdgesOnCellVarId, &read_start, &read_count,
     419 [ #  # ][ #  # ]:          0 :                                          &( num_edges_on_local_cells[indexInArray] ) );
     420                 :            : #endif
     421 [ #  # ][ #  # ]:          0 :         if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read nEdgesOnCell data in a loop" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     422                 :            : 
     423                 :            :         // Increment the index for next subrange
     424                 :          0 :         indexInArray += ( endh - starth + 1 );
     425                 :            :     }
     426                 :            : 
     427                 :            : #ifdef MOAB_HAVE_PNETCDF
     428                 :            :     // Wait outside the loop
     429                 :            :     success = NCFUNC( wait_all )( _fileId, requests.size(), &requests[0], &statuss[0] );
     430                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed on wait_all" );
     431                 :            : #endif
     432                 :            : 
     433                 :            :     // Get local maxEdgesPerCell on this proc
     434                 :            :     int local_max_edges_per_cell =
     435 [ #  # ][ #  # ]:          0 :         *( std::max_element( num_edges_on_local_cells.begin(), num_edges_on_local_cells.end() ) );
     436                 :          0 :     maxEdgesPerCell = local_max_edges_per_cell;
     437                 :            : 
     438                 :            :     // If parallel, do a MPI_Allreduce to get global maxEdgesPerCell across all procs
     439                 :            : #ifdef MOAB_HAVE_MPI
     440         [ #  # ]:          0 :     if( procs >= 2 )
     441                 :            :     {
     442                 :            :         int global_max_edges_per_cell;
     443                 :          0 :         ParallelComm*& myPcomm = _readNC->myPcomm;
     444                 :            :         MPI_Allreduce( &local_max_edges_per_cell, &global_max_edges_per_cell, 1, MPI_INT, MPI_MAX,
     445 [ #  # ][ #  # ]:          0 :                        myPcomm->proc_config().proc_comm() );
                 [ #  # ]
     446         [ #  # ]:          0 :         assert( local_max_edges_per_cell <= global_max_edges_per_cell );
     447                 :          0 :         maxEdgesPerCell = global_max_edges_per_cell;
     448 [ #  # ][ #  # ]:          0 :         if( 0 == rank ) dbgOut.tprintf( 1, "  global_max_edges_per_cell = %d\n", global_max_edges_per_cell );
     449                 :            :     }
     450                 :            : #endif
     451                 :            : 
     452                 :            :     // Read vertices on each local cell, to get localGidVerts and cell connectivity later
     453                 :            :     int verticesOnCellVarId;
     454         [ #  # ]:          0 :     success = NCFUNC( inq_varid )( _fileId, "verticesOnCell", &verticesOnCellVarId );
     455 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of verticesOnCell" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     456         [ #  # ]:          0 :     std::vector< int > vertices_on_local_cells( nLocalCells * maxEdgesPerCell );
     457                 :            : #ifdef MOAB_HAVE_PNETCDF
     458                 :            :     idxReq = 0;
     459                 :            : #endif
     460                 :          0 :     indexInArray = 0;
     461 [ #  # ][ #  # ]:          0 :     for( Range::pair_iterator pair_iter = localGidCells.pair_begin(); pair_iter != localGidCells.pair_end();
         [ #  # ][ #  # ]
                 [ #  # ]
     462                 :            :          ++pair_iter )
     463                 :            :     {
     464         [ #  # ]:          0 :         EntityHandle starth      = pair_iter->first;
     465         [ #  # ]:          0 :         EntityHandle endh        = pair_iter->second;
     466                 :          0 :         NCDF_SIZE read_starts[2] = { static_cast< NCDF_SIZE >( starth - 1 ), 0 };
     467                 :          0 :         NCDF_SIZE read_counts[2] = { static_cast< NCDF_SIZE >( endh - starth + 1 ),
     468                 :          0 :                                      static_cast< NCDF_SIZE >( maxEdgesPerCell ) };
     469                 :            : 
     470                 :            :         // Do a partial read in each subrange
     471                 :            : #ifdef MOAB_HAVE_PNETCDF
     472                 :            :         success = NCFUNCREQG( _vara_int )( _fileId, verticesOnCellVarId, read_starts, read_counts,
     473                 :            :                                            &( vertices_on_local_cells[indexInArray] ), &requests[idxReq++] );
     474                 :            : #else
     475                 :            :         success = NCFUNCAG( _vara_int )( _fileId, verticesOnCellVarId, read_starts, read_counts,
     476 [ #  # ][ #  # ]:          0 :                                          &( vertices_on_local_cells[indexInArray] ) );
     477                 :            : #endif
     478 [ #  # ][ #  # ]:          0 :         if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read verticesOnCell data in a loop" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     479                 :            : 
     480                 :            :         // Increment the index for next subrange
     481                 :          0 :         indexInArray += ( endh - starth + 1 ) * maxEdgesPerCell;
     482                 :            :     }
     483                 :            : 
     484                 :            : #ifdef MOAB_HAVE_PNETCDF
     485                 :            :     // Wait outside the loop
     486                 :            :     success = NCFUNC( wait_all )( _fileId, requests.size(), &requests[0], &statuss[0] );
     487                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed on wait_all" );
     488                 :            : #endif
     489                 :            : 
     490                 :            :     // Correct local cell vertices array, replace the padded vertices with the last vertices
     491                 :            :     // in the corresponding cells; sometimes the padded vertices are 0, sometimes a large
     492                 :            :     // vertex id. Make sure they are consistent to our padded option
     493         [ #  # ]:          0 :     for( int local_cell_idx = 0; local_cell_idx < nLocalCells; local_cell_idx++ )
     494                 :            :     {
     495         [ #  # ]:          0 :         int num_edges             = num_edges_on_local_cells[local_cell_idx];
     496                 :          0 :         int idx_in_local_vert_arr = local_cell_idx * maxEdgesPerCell;
     497         [ #  # ]:          0 :         int last_vert_idx         = vertices_on_local_cells[idx_in_local_vert_arr + num_edges - 1];
     498         [ #  # ]:          0 :         for( int i = num_edges; i < maxEdgesPerCell; i++ )
     499         [ #  # ]:          0 :             vertices_on_local_cells[idx_in_local_vert_arr + i] = last_vert_idx;
     500                 :            :     }
     501                 :            : 
     502                 :            :     // Create local vertices
     503                 :            :     EntityHandle start_vertex;
     504 [ #  # ][ #  # ]:          0 :     ErrorCode rval = create_local_vertices( vertices_on_local_cells, start_vertex );MB_CHK_SET_ERR( rval, "Failed to create local vertices for MPAS mesh" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     505                 :            : 
     506                 :            :     // Create local edges (unless NO_EDGES read option is set)
     507         [ #  # ]:          0 :     if( !noEdges )
     508                 :            :     {
     509 [ #  # ][ #  # ]:          0 :         rval = create_local_edges( start_vertex, num_edges_on_local_cells );MB_CHK_SET_ERR( rval, "Failed to create local edges for MPAS mesh" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     510                 :            :     }
     511                 :            : 
     512                 :            :     // Create local cells, either unpadded or padded
     513         [ #  # ]:          0 :     if( noMixedElements )
     514                 :            :     {
     515 [ #  # ][ #  # ]:          0 :         rval = create_padded_local_cells( vertices_on_local_cells, start_vertex, faces );MB_CHK_SET_ERR( rval, "Failed to create padded local cells for MPAS mesh" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     516                 :            :     }
     517                 :            :     else
     518                 :            :     {
     519 [ #  # ][ #  # ]:          0 :         rval = create_local_cells( vertices_on_local_cells, num_edges_on_local_cells, start_vertex, faces );MB_CHK_SET_ERR( rval, "Failed to create local cells for MPAS mesh" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     520                 :            :     }
     521                 :            : 
     522                 :            :     // Set tag for numCellGroups
     523                 :          0 :     Tag numCellGroupsTag = 0;
     524                 :            :     rval                 = mbImpl->tag_get_handle( "__NUM_CELL_GROUPS", 1, MB_TYPE_INTEGER, numCellGroupsTag,
     525 [ #  # ][ #  # ]:          0 :                                    MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_SET_ERR( rval, "Trouble creating __NUM_CELL_GROUPS tag" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     526 [ #  # ][ #  # ]:          0 :     rval = mbImpl->tag_set_data( numCellGroupsTag, &_fileSet, 1, &numCellGroups );MB_CHK_SET_ERR( rval, "Trouble setting data to __NUM_CELL_GROUPS tag" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     527                 :            : 
     528         [ #  # ]:          0 :     if( createGatherSet )
     529                 :            :     {
     530                 :            :         EntityHandle gather_set;
     531 [ #  # ][ #  # ]:          0 :         rval = _readNC->readMeshIface->create_gather_set( gather_set );MB_CHK_SET_ERR( rval, "Failed to create gather set" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     532                 :            : 
     533                 :            :         // Create gather set vertices
     534                 :            :         EntityHandle start_gather_set_vertex;
     535 [ #  # ][ #  # ]:          0 :         rval = create_gather_set_vertices( gather_set, start_gather_set_vertex );MB_CHK_SET_ERR( rval, "Failed to create gather set vertices for MPAS mesh" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     536                 :            : 
     537                 :            :         // Create gather set edges (unless NO_EDGES read option is set)
     538         [ #  # ]:          0 :         if( !noEdges )
     539                 :            :         {
     540 [ #  # ][ #  # ]:          0 :             rval = create_gather_set_edges( gather_set, start_gather_set_vertex );MB_CHK_SET_ERR( rval, "Failed to create gather set edges for MPAS mesh" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     541                 :            :         }
     542                 :            : 
     543                 :            :         // Create gather set cells, either unpadded or padded
     544         [ #  # ]:          0 :         if( noMixedElements )
     545                 :            :         {
     546 [ #  # ][ #  # ]:          0 :             rval = create_padded_gather_set_cells( gather_set, start_gather_set_vertex );MB_CHK_SET_ERR( rval, "Failed to create padded gather set cells for MPAS mesh" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     547                 :            :         }
     548                 :            :         else
     549                 :            :         {
     550 [ #  # ][ #  # ]:          0 :             rval = create_gather_set_cells( gather_set, start_gather_set_vertex );MB_CHK_SET_ERR( rval, "Failed to create gather set cells for MPAS mesh" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     551                 :            :         }
     552                 :            :     }
     553                 :            : 
     554                 :          0 :     return MB_SUCCESS;
     555                 :            : }
     556                 :            : 
     557                 :          0 : ErrorCode NCHelperMPAS::read_ucd_variables_to_nonset_allocate( std::vector< ReadNC::VarData >& vdatas,
     558                 :            :                                                                std::vector< int >& tstep_nums )
     559                 :            : {
     560                 :          0 :     Interface*& mbImpl          = _readNC->mbImpl;
     561                 :          0 :     std::vector< int >& dimLens = _readNC->dimLens;
     562                 :          0 :     bool& noEdges               = _readNC->noEdges;
     563                 :          0 :     DebugOutput& dbgOut         = _readNC->dbgOut;
     564                 :            : 
     565                 :          0 :     Range* range = NULL;
     566                 :            : 
     567                 :            :     // Get vertices
     568         [ #  # ]:          0 :     Range verts;
     569 [ #  # ][ #  # ]:          0 :     ErrorCode rval = mbImpl->get_entities_by_dimension( _fileSet, 0, verts );MB_CHK_SET_ERR( rval, "Trouble getting vertices in current file set" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     570 [ #  # ][ #  # ]:          0 :     assert( "Should only have a single vertex subrange, since they were read in one shot" && verts.psize() == 1 );
     571                 :            : 
     572                 :            :     // Get edges
     573         [ #  # ]:          0 :     Range edges;
     574 [ #  # ][ #  # ]:          0 :     rval = mbImpl->get_entities_by_dimension( _fileSet, 1, edges );MB_CHK_SET_ERR( rval, "Trouble getting edges in current file set" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     575                 :            : 
     576                 :            :     // Get faces
     577         [ #  # ]:          0 :     Range faces;
     578 [ #  # ][ #  # ]:          0 :     rval = mbImpl->get_entities_by_dimension( _fileSet, 2, faces );MB_CHK_SET_ERR( rval, "Trouble getting faces in current file set" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     579                 :            :     // Note, for MPAS faces.psize() can be more than 1
     580                 :            : 
     581                 :            : #ifdef MOAB_HAVE_MPI
     582                 :          0 :     bool& isParallel = _readNC->isParallel;
     583         [ #  # ]:          0 :     if( isParallel )
     584                 :            :     {
     585                 :          0 :         ParallelComm*& myPcomm = _readNC->myPcomm;
     586 [ #  # ][ #  # ]:          0 :         rval                   = myPcomm->filter_pstatus( faces, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &facesOwned );MB_CHK_SET_ERR( rval, "Trouble getting owned faces in current file set" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     587                 :            :     }
     588                 :            :     else
     589         [ #  # ]:          0 :         facesOwned = faces;  // not running in parallel, but still with MPI
     590                 :            : #else
     591                 :            :     facesOwned = faces;
     592                 :            : #endif
     593                 :            : 
     594         [ #  # ]:          0 :     for( unsigned int i = 0; i < vdatas.size(); i++ )
     595                 :            :     {
     596                 :            :         // Skip edge variables, if specified by the read options
     597 [ #  # ][ #  # ]:          0 :         if( noEdges && vdatas[i].entLoc == ReadNC::ENTLOCEDGE ) continue;
         [ #  # ][ #  # ]
     598                 :            : 
     599                 :            :         // Support non-set variables with 3 dimensions like (Time, nCells, nVertLevels), or
     600                 :            :         // 2 dimensions like (Time, nCells)
     601 [ #  # ][ #  # ]:          0 :         assert( 3 == vdatas[i].varDims.size() || 2 == vdatas[i].varDims.size() );
         [ #  # ][ #  # ]
     602                 :            : 
     603                 :            :         // For a non-set variable, time should be the first dimension
     604 [ #  # ][ #  # ]:          0 :         assert( tDim == vdatas[i].varDims[0] );
                 [ #  # ]
     605                 :            : 
     606                 :            :         // Set up readStarts and readCounts
     607 [ #  # ][ #  # ]:          0 :         vdatas[i].readStarts.resize( 3 );
     608 [ #  # ][ #  # ]:          0 :         vdatas[i].readCounts.resize( 3 );
     609                 :            : 
     610                 :            :         // First: Time
     611 [ #  # ][ #  # ]:          0 :         vdatas[i].readStarts[0] = 0;  // This value is timestep dependent, will be set later
     612 [ #  # ][ #  # ]:          0 :         vdatas[i].readCounts[0] = 1;
     613                 :            : 
     614                 :            :         // Next: nVertices / nCells / nEdges
     615         [ #  # ]:          0 :         switch( vdatas[i].entLoc )
           [ #  #  #  # ]
     616                 :            :         {
     617                 :            :             case ReadNC::ENTLOCVERT:
     618                 :            :                 // Vertices
     619                 :            :                 // Start from the first localGidVerts
     620                 :            :                 // Actually, this will be reset later on in a loop
     621 [ #  # ][ #  # ]:          0 :                 vdatas[i].readStarts[1] = localGidVerts[0] - 1;
                 [ #  # ]
     622 [ #  # ][ #  # ]:          0 :                 vdatas[i].readCounts[1] = nLocalVertices;
     623                 :          0 :                 range                   = &verts;
     624                 :          0 :                 break;
     625                 :            :             case ReadNC::ENTLOCFACE:
     626                 :            :                 // Faces
     627                 :            :                 // Start from the first localGidCells
     628                 :            :                 // Actually, this will be reset later on in a loop
     629 [ #  # ][ #  # ]:          0 :                 vdatas[i].readStarts[1] = localGidCells[0] - 1;
                 [ #  # ]
     630 [ #  # ][ #  # ]:          0 :                 vdatas[i].readCounts[1] = nLocalCells;
     631                 :          0 :                 range                   = &facesOwned;
     632                 :          0 :                 break;
     633                 :            :             case ReadNC::ENTLOCEDGE:
     634                 :            :                 // Edges
     635                 :            :                 // Start from the first localGidEdges
     636                 :            :                 // Actually, this will be reset later on in a loop
     637 [ #  # ][ #  # ]:          0 :                 vdatas[i].readStarts[1] = localGidEdges[0] - 1;
                 [ #  # ]
     638 [ #  # ][ #  # ]:          0 :                 vdatas[i].readCounts[1] = nLocalEdges;
     639                 :          0 :                 range                   = &edges;
     640                 :          0 :                 break;
     641                 :            :             default:
     642 [ #  # ][ #  # ]:          0 :                 MB_SET_ERR( MB_FAILURE, "Unexpected entity location type for variable " << vdatas[i].varName );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     643                 :            :         }
     644                 :            : 
     645                 :            :         // Finally: nVertLevels or other optional levels, it is possible that there is no
     646                 :            :         // level dimension (numLev is 0) for this non-set variable, e.g. (Time, nCells)
     647 [ #  # ][ #  # ]:          0 :         if( vdatas[i].numLev < 1 ) vdatas[i].numLev = 1;
                 [ #  # ]
     648 [ #  # ][ #  # ]:          0 :         vdatas[i].readStarts[2] = 0;
     649 [ #  # ][ #  # ]:          0 :         vdatas[i].readCounts[2] = vdatas[i].numLev;
                 [ #  # ]
     650                 :            : 
     651                 :            :         // Get variable size
     652         [ #  # ]:          0 :         vdatas[i].sz = 1;
     653         [ #  # ]:          0 :         for( std::size_t idx = 0; idx != 3; idx++ )
     654 [ #  # ][ #  # ]:          0 :             vdatas[i].sz *= vdatas[i].readCounts[idx];
                 [ #  # ]
     655                 :            : 
     656         [ #  # ]:          0 :         for( unsigned int t = 0; t < tstep_nums.size(); t++ )
     657                 :            :         {
     658 [ #  # ][ #  # ]:          0 :             dbgOut.tprintf( 2, "Reading variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t] );
                 [ #  # ]
     659                 :            : 
     660 [ #  # ][ #  # ]:          0 :             if( tstep_nums[t] >= dimLens[tDim] )
                 [ #  # ]
     661 [ #  # ][ #  # ]:          0 :             { MB_SET_ERR( MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number " << tstep_nums[t] ); }
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     662                 :            : 
     663                 :            :             // Get the tag to read into
     664 [ #  # ][ #  # ]:          0 :             if( !vdatas[i].varTags[t] )
                 [ #  # ]
     665                 :            :             {
     666 [ #  # ][ #  # ]:          0 :                 rval = get_tag_to_nonset( vdatas[i], tstep_nums[t], vdatas[i].varTags[t], vdatas[i].numLev );MB_CHK_SET_ERR( rval, "Trouble getting tag for variable " << vdatas[i].varName );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     667                 :            :             }
     668                 :            : 
     669                 :            :             // Get ptr to tag space
     670 [ #  # ][ #  # ]:          0 :             if( vdatas[i].entLoc == ReadNC::ENTLOCFACE && numCellGroups > 1 )
         [ #  # ][ #  # ]
     671                 :            :             {
     672                 :            :                 // For a cell variable that is NOT on one contiguous chunk of faces, defer its tag
     673                 :            :                 // space allocation
     674 [ #  # ][ #  # ]:          0 :                 vdatas[i].varDatas[t] = NULL;
     675                 :            :             }
     676                 :            :             else
     677                 :            :             {
     678 [ #  # ][ #  # ]:          0 :                 assert( 1 == range->psize() );
     679                 :            :                 void* data;
     680                 :            :                 int count;
     681 [ #  # ][ #  # ]:          0 :                 rval = mbImpl->tag_iterate( vdatas[i].varTags[t], range->begin(), range->end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate tag for variable " << vdatas[i].varName );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     682 [ #  # ][ #  # ]:          0 :                 assert( (unsigned)count == range->size() );
     683 [ #  # ][ #  # ]:          0 :                 vdatas[i].varDatas[t] = data;
     684                 :            :             }
     685                 :            :         }
     686                 :            :     }
     687                 :            : 
     688                 :          0 :     return rval;
     689                 :            : }
     690                 :            : 
     691                 :            : #ifdef MOAB_HAVE_PNETCDF
     692                 :            : ErrorCode NCHelperMPAS::read_ucd_variables_to_nonset_async( std::vector< ReadNC::VarData >& vdatas,
     693                 :            :                                                             std::vector< int >& tstep_nums )
     694                 :            : {
     695                 :            :     Interface*& mbImpl  = _readNC->mbImpl;
     696                 :            :     bool& noEdges       = _readNC->noEdges;
     697                 :            :     DebugOutput& dbgOut = _readNC->dbgOut;
     698                 :            : 
     699                 :            :     ErrorCode rval = read_ucd_variables_to_nonset_allocate( vdatas, tstep_nums );MB_CHK_SET_ERR( rval, "Trouble allocating space to read non-set variables" );
     700                 :            : 
     701                 :            :     // Finally, read into that space
     702                 :            :     int success;
     703                 :            :     Range* pLocalGid = NULL;
     704                 :            : 
     705                 :            :     for( unsigned int i = 0; i < vdatas.size(); i++ )
     706                 :            :     {
     707                 :            :         // Skip edge variables, if specified by the read options
     708                 :            :         if( noEdges && vdatas[i].entLoc == ReadNC::ENTLOCEDGE ) continue;
     709                 :            : 
     710                 :            :         switch( vdatas[i].entLoc )
     711                 :            :         {
     712                 :            :             case ReadNC::ENTLOCVERT:
     713                 :            :                 pLocalGid = &localGidVerts;
     714                 :            :                 break;
     715                 :            :             case ReadNC::ENTLOCFACE:
     716                 :            :                 pLocalGid = &localGidCells;
     717                 :            :                 break;
     718                 :            :             case ReadNC::ENTLOCEDGE:
     719                 :            :                 pLocalGid = &localGidEdges;
     720                 :            :                 break;
     721                 :            :             default:
     722                 :            :                 MB_SET_ERR( MB_FAILURE, "Unexpected entity location type for variable " << vdatas[i].varName );
     723                 :            :         }
     724                 :            : 
     725                 :            :         std::size_t sz = vdatas[i].sz;
     726                 :            : 
     727                 :            :         for( unsigned int t = 0; t < tstep_nums.size(); t++ )
     728                 :            :         {
     729                 :            :             // We will synchronize all these reads with the other processors,
     730                 :            :             // so the wait will be inside this double loop; is it too much?
     731                 :            :             size_t nb_reads = pLocalGid->psize();
     732                 :            :             std::vector< int > requests( nb_reads ), statuss( nb_reads );
     733                 :            :             size_t idxReq = 0;
     734                 :            : 
     735                 :            :             // Set readStart for each timestep along time dimension
     736                 :            :             vdatas[i].readStarts[0] = tstep_nums[t];
     737                 :            : 
     738                 :            :             switch( vdatas[i].varDataType )
     739                 :            :             {
     740                 :            :                 case NC_FLOAT:
     741                 :            :                 case NC_DOUBLE: {
     742                 :            :                     // Read float as double
     743                 :            :                     std::vector< double > tmpdoubledata( sz );
     744                 :            : 
     745                 :            :                     // In the case of ucd mesh, and on multiple proc,
     746                 :            :                     // we need to read as many times as subranges we have in the
     747                 :            :                     // localGid range;
     748                 :            :                     // basically, we have to give a different point
     749                 :            :                     // for data to start, for every subrange :(
     750                 :            :                     size_t indexInDoubleArray = 0;
     751                 :            :                     size_t ic                 = 0;
     752                 :            :                     for( Range::pair_iterator pair_iter = pLocalGid->pair_begin(); pair_iter != pLocalGid->pair_end();
     753                 :            :                          ++pair_iter, ic++ )
     754                 :            :                     {
     755                 :            :                         EntityHandle starth     = pair_iter->first;
     756                 :            :                         EntityHandle endh       = pair_iter->second;  // Inclusive
     757                 :            :                         vdatas[i].readStarts[1] = ( NCDF_SIZE )( starth - 1 );
     758                 :            :                         vdatas[i].readCounts[1] = ( NCDF_SIZE )( endh - starth + 1 );
     759                 :            : 
     760                 :            :                         // Do a partial read, in each subrange
     761                 :            :                         // Wait outside this loop
     762                 :            :                         success =
     763                 :            :                             NCFUNCREQG( _vara_double )( _fileId, vdatas[i].varId, &( vdatas[i].readStarts[0] ),
     764                 :            :                                                         &( vdatas[i].readCounts[0] ),
     765                 :            :                                                         &( tmpdoubledata[indexInDoubleArray] ), &requests[idxReq++] );
     766                 :            :                         if( success )
     767                 :            :                             MB_SET_ERR( MB_FAILURE,
     768                 :            :                                         "Failed to read double data in a loop for variable " << vdatas[i].varName );
     769                 :            :                         // We need to increment the index in double array for the
     770                 :            :                         // next subrange
     771                 :            :                         indexInDoubleArray += ( endh - starth + 1 ) * 1 * vdatas[i].numLev;
     772                 :            :                     }
     773                 :            :                     assert( ic == pLocalGid->psize() );
     774                 :            : 
     775                 :            :                     success = NCFUNC( wait_all )( _fileId, requests.size(), &requests[0], &statuss[0] );
     776                 :            :                     if( success ) MB_SET_ERR( MB_FAILURE, "Failed on wait_all" );
     777                 :            : 
     778                 :            :                     if( vdatas[i].entLoc == ReadNC::ENTLOCFACE && numCellGroups > 1 )
     779                 :            :                     {
     780                 :            :                         // For a cell variable that is NOT on one contiguous chunk of faces,
     781                 :            :                         // allocate tag space for each cell group, and utilize cellHandleToGlobalID
     782                 :            :                         // map to read tag data
     783                 :            :                         Range::iterator iter = facesOwned.begin();
     784                 :            :                         while( iter != facesOwned.end() )
     785                 :            :                         {
     786                 :            :                             int count;
     787                 :            :                             void* ptr;
     788                 :            :                             rval = mbImpl->tag_iterate( vdatas[i].varTags[t], iter, facesOwned.end(), count, ptr );MB_CHK_SET_ERR( rval, "Failed to iterate tag on owned faces" );
     789                 :            : 
     790                 :            :                             for( int j = 0; j < count; j++ )
     791                 :            :                             {
     792                 :            :                                 int global_cell_idx =
     793                 :            :                                     cellHandleToGlobalID[*( iter + j )];  // Global cell index, 1 based
     794                 :            :                                 int local_cell_idx =
     795                 :            :                                     localGidCells.index( global_cell_idx );  // Local cell index, 0 based
     796                 :            :                                 assert( local_cell_idx != -1 );
     797                 :            :                                 for( int level = 0; level < vdatas[i].numLev; level++ )
     798                 :            :                                     ( (double*)ptr )[j * vdatas[i].numLev + level] =
     799                 :            :                                         tmpdoubledata[local_cell_idx * vdatas[i].numLev + level];
     800                 :            :                             }
     801                 :            : 
     802                 :            :                             iter += count;
     803                 :            :                         }
     804                 :            :                     }
     805                 :            :                     else
     806                 :            :                     {
     807                 :            :                         void* data = vdatas[i].varDatas[t];
     808                 :            :                         for( std::size_t idx = 0; idx != tmpdoubledata.size(); idx++ )
     809                 :            :                             ( (double*)data )[idx] = tmpdoubledata[idx];
     810                 :            :                     }
     811                 :            : 
     812                 :            :                     break;
     813                 :            :                 }
     814                 :            :                 default:
     815                 :            :                     MB_SET_ERR( MB_FAILURE, "Unexpected data type for variable " << vdatas[i].varName );
     816                 :            :             }
     817                 :            :         }
     818                 :            :     }
     819                 :            : 
     820                 :            :     // Debug output, if requested
     821                 :            :     if( 1 == dbgOut.get_verbosity() )
     822                 :            :     {
     823                 :            :         dbgOut.printf( 1, "Read variables: %s", vdatas.begin()->varName.c_str() );
     824                 :            :         for( unsigned int i = 1; i < vdatas.size(); i++ )
     825                 :            :             dbgOut.printf( 1, ", %s ", vdatas[i].varName.c_str() );
     826                 :            :         dbgOut.tprintf( 1, "\n" );
     827                 :            :     }
     828                 :            : 
     829                 :            :     return rval;
     830                 :            : }
     831                 :            : #else
     832                 :          0 : ErrorCode NCHelperMPAS::read_ucd_variables_to_nonset( std::vector< ReadNC::VarData >& vdatas,
     833                 :            :                                                       std::vector< int >& tstep_nums )
     834                 :            : {
     835                 :          0 :     Interface*& mbImpl = _readNC->mbImpl;
     836                 :          0 :     bool& noEdges = _readNC->noEdges;
     837                 :          0 :     DebugOutput& dbgOut = _readNC->dbgOut;
     838                 :            : 
     839 [ #  # ][ #  # ]:          0 :     ErrorCode rval = read_ucd_variables_to_nonset_allocate( vdatas, tstep_nums );MB_CHK_SET_ERR( rval, "Trouble allocating space to read non-set variables" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     840                 :            : 
     841                 :            :     // Finally, read into that space
     842                 :            :     int success;
     843                 :          0 :     Range* pLocalGid = NULL;
     844                 :            : 
     845         [ #  # ]:          0 :     for( unsigned int i = 0; i < vdatas.size(); i++ )
     846                 :            :     {
     847                 :            :         // Skip edge variables, if specified by the read options
     848 [ #  # ][ #  # ]:          0 :         if( noEdges && vdatas[i].entLoc == ReadNC::ENTLOCEDGE ) continue;
                 [ #  # ]
     849                 :            : 
     850   [ #  #  #  # ]:          0 :         switch( vdatas[i].entLoc )
     851                 :            :         {
     852                 :            :             case ReadNC::ENTLOCVERT:
     853                 :          0 :                 pLocalGid = &localGidVerts;
     854                 :          0 :                 break;
     855                 :            :             case ReadNC::ENTLOCFACE:
     856                 :          0 :                 pLocalGid = &localGidCells;
     857                 :          0 :                 break;
     858                 :            :             case ReadNC::ENTLOCEDGE:
     859                 :          0 :                 pLocalGid = &localGidEdges;
     860                 :          0 :                 break;
     861                 :            :             default:
     862 [ #  # ][ #  # ]:          0 :                 MB_SET_ERR( MB_FAILURE, "Unexpected entity location type for variable " << vdatas[i].varName );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     863                 :            :         }
     864                 :            : 
     865                 :          0 :         std::size_t sz = vdatas[i].sz;
     866                 :            : 
     867         [ #  # ]:          0 :         for( unsigned int t = 0; t < tstep_nums.size(); t++ )
     868                 :            :         {
     869                 :            :             // Set readStart for each timestep along time dimension
     870                 :          0 :             vdatas[i].readStarts[0] = tstep_nums[t];
     871                 :            : 
     872         [ #  # ]:          0 :             switch( vdatas[i].varDataType )
     873                 :            :             {
     874                 :            :                 case NC_FLOAT:
     875                 :            :                 case NC_DOUBLE: {
     876                 :            :                     // Read float as double
     877         [ #  # ]:          0 :                     std::vector< double > tmpdoubledata( sz );
     878                 :            : 
     879                 :            :                     // In the case of ucd mesh, and on multiple proc,
     880                 :            :                     // we need to read as many times as subranges we have in the
     881                 :            :                     // localGid range;
     882                 :            :                     // basically, we have to give a different point
     883                 :            :                     // for data to start, for every subrange :(
     884                 :          0 :                     size_t indexInDoubleArray = 0;
     885                 :          0 :                     size_t ic = 0;
     886 [ #  # ][ #  # ]:          0 :                     for( Range::pair_iterator pair_iter = pLocalGid->pair_begin(); pair_iter != pLocalGid->pair_end();
         [ #  # ][ #  # ]
                 [ #  # ]
     887                 :            :                          ++pair_iter, ic++ )
     888                 :            :                     {
     889         [ #  # ]:          0 :                         EntityHandle starth = pair_iter->first;
     890         [ #  # ]:          0 :                         EntityHandle endh = pair_iter->second;  // Inclusive
     891 [ #  # ][ #  # ]:          0 :                         vdatas[i].readStarts[1] = ( NCDF_SIZE )( starth - 1 );
     892 [ #  # ][ #  # ]:          0 :                         vdatas[i].readCounts[1] = ( NCDF_SIZE )( endh - starth + 1 );
     893                 :            : 
     894 [ #  # ][ #  # ]:          0 :                         success = NCFUNCAG( _vara_double )( _fileId, vdatas[i].varId, &( vdatas[i].readStarts[0] ),
                 [ #  # ]
     895 [ #  # ][ #  # ]:          0 :                                                             &( vdatas[i].readCounts[0] ),
     896 [ #  # ][ #  # ]:          0 :                                                             &( tmpdoubledata[indexInDoubleArray] ) );
     897         [ #  # ]:          0 :                         if( success )
     898 [ #  # ][ #  # ]:          0 :                             MB_SET_ERR( MB_FAILURE,
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     899                 :            :                                         "Failed to read double data in a loop for variable " << vdatas[i].varName );
     900                 :            :                         // We need to increment the index in double array for the
     901                 :            :                         // next subrange
     902         [ #  # ]:          0 :                         indexInDoubleArray += ( endh - starth + 1 ) * 1 * vdatas[i].numLev;
     903                 :            :                     }
     904 [ #  # ][ #  # ]:          0 :                     assert( ic == pLocalGid->psize() );
     905                 :            : 
     906 [ #  # ][ #  # ]:          0 :                     if( vdatas[i].entLoc == ReadNC::ENTLOCFACE && numCellGroups > 1 )
         [ #  # ][ #  # ]
     907                 :            :                     {
     908                 :            :                         // For a cell variable that is NOT on one contiguous chunk of faces,
     909                 :            :                         // allocate tag space for each cell group, and utilize cellHandleToGlobalID
     910                 :            :                         // map to read tag data
     911         [ #  # ]:          0 :                         Range::iterator iter = facesOwned.begin();
     912 [ #  # ][ #  # ]:          0 :                         while( iter != facesOwned.end() )
                 [ #  # ]
     913                 :            :                         {
     914                 :            :                             int count;
     915                 :            :                             void* ptr;
     916 [ #  # ][ #  # ]:          0 :                             rval = mbImpl->tag_iterate( vdatas[i].varTags[t], iter, facesOwned.end(), count, ptr );MB_CHK_SET_ERR( rval, "Failed to iterate tag on owned faces" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     917                 :            : 
     918         [ #  # ]:          0 :                             for( int j = 0; j < count; j++ )
     919                 :            :                             {
     920                 :            :                                 int global_cell_idx =
     921 [ #  # ][ #  # ]:          0 :                                     cellHandleToGlobalID[*( iter + j )];  // Global cell index, 1 based
                 [ #  # ]
     922                 :            :                                 int local_cell_idx =
     923         [ #  # ]:          0 :                                     localGidCells.index( global_cell_idx );  // Local cell index, 0 based
     924         [ #  # ]:          0 :                                 assert( local_cell_idx != -1 );
     925 [ #  # ][ #  # ]:          0 :                                 for( int level = 0; level < vdatas[i].numLev; level++ )
     926         [ #  # ]:          0 :                                     ( (double*)ptr )[j * vdatas[i].numLev + level] =
     927 [ #  # ][ #  # ]:          0 :                                         tmpdoubledata[local_cell_idx * vdatas[i].numLev + level];
     928                 :            :                             }
     929                 :            : 
     930         [ #  # ]:          0 :                             iter += count;
     931                 :            :                         }
     932                 :            :                     }
     933                 :            :                     else
     934                 :            :                     {
     935 [ #  # ][ #  # ]:          0 :                         void* data = vdatas[i].varDatas[t];
     936         [ #  # ]:          0 :                         for( std::size_t idx = 0; idx != tmpdoubledata.size(); idx++ )
     937         [ #  # ]:          0 :                             ( (double*)data )[idx] = tmpdoubledata[idx];
     938                 :            :                     }
     939                 :            : 
     940         [ #  # ]:          0 :                     break;
     941                 :            :                 }
     942                 :            :                 default:
     943 [ #  # ][ #  # ]:          0 :                     MB_SET_ERR( MB_FAILURE, "Unexpected data type for variable " << vdatas[i].varName );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     944                 :            :             }
     945                 :            :         }
     946                 :            :     }
     947                 :            : 
     948                 :            :     // Debug output, if requested
     949         [ #  # ]:          0 :     if( 1 == dbgOut.get_verbosity() )
     950                 :            :     {
     951 [ #  # ][ #  # ]:          0 :         dbgOut.printf( 1, "Read variables: %s", vdatas.begin()->varName.c_str() );
     952         [ #  # ]:          0 :         for( unsigned int i = 1; i < vdatas.size(); i++ )
     953                 :          0 :             dbgOut.printf( 1, ", %s ", vdatas[i].varName.c_str() );
     954                 :          0 :         dbgOut.tprintf( 1, "\n" );
     955                 :            :     }
     956                 :            : 
     957                 :          0 :     return rval;
     958                 :            : }
     959                 :            : #endif
     960                 :            : 
     961                 :            : #ifdef MOAB_HAVE_MPI
     962                 :          0 : ErrorCode NCHelperMPAS::redistribute_local_cells( int start_cell_idx )
     963                 :            : {
     964                 :            :     // If possible, apply Zoltan partition
     965                 :            : #ifdef MOAB_HAVE_ZOLTAN
     966                 :            :     if( ScdParData::RCBZOLTAN == _readNC->partMethod )
     967                 :            :     {
     968                 :            :         // Read x coordinates of cell centers
     969                 :            :         int xCellVarId;
     970                 :            :         int success = NCFUNC( inq_varid )( _fileId, "xCell", &xCellVarId );
     971                 :            :         if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of xCell" );
     972                 :            :         std::vector< double > xCell( nLocalCells );
     973                 :            :         NCDF_SIZE read_start = static_cast< NCDF_SIZE >( start_cell_idx - 1 );
     974                 :            :         NCDF_SIZE read_count = static_cast< NCDF_SIZE >( nLocalCells );
     975                 :            :         success              = NCFUNCAG( _vara_double )( _fileId, xCellVarId, &read_start, &read_count, &xCell[0] );
     976                 :            :         if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read xCell data" );
     977                 :            : 
     978                 :            :         // Read y coordinates of cell centers
     979                 :            :         int yCellVarId;
     980                 :            :         success = NCFUNC( inq_varid )( _fileId, "yCell", &yCellVarId );
     981                 :            :         if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of yCell" );
     982                 :            :         std::vector< double > yCell( nLocalCells );
     983                 :            :         success = NCFUNCAG( _vara_double )( _fileId, yCellVarId, &read_start, &read_count, &yCell[0] );
     984                 :            :         if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read yCell data" );
     985                 :            : 
     986                 :            :         // Read z coordinates of cell centers
     987                 :            :         int zCellVarId;
     988                 :            :         success = NCFUNC( inq_varid )( _fileId, "zCell", &zCellVarId );
     989                 :            :         if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of zCell" );
     990                 :            :         std::vector< double > zCell( nLocalCells );
     991                 :            :         success = NCFUNCAG( _vara_double )( _fileId, zCellVarId, &read_start, &read_count, &zCell[0] );
     992                 :            :         if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read zCell data" );
     993                 :            : 
     994                 :            :         // Zoltan partition using RCB; maybe more studies would be good, as to which partition
     995                 :            :         // is better
     996                 :            :         Interface*& mbImpl         = _readNC->mbImpl;
     997                 :            :         DebugOutput& dbgOut        = _readNC->dbgOut;
     998                 :            :         ZoltanPartitioner* mbZTool = new ZoltanPartitioner( mbImpl, false, 0, NULL );
     999                 :            :         ErrorCode rval             = mbZTool->repartition( xCell, yCell, zCell, start_cell_idx, "RCB", localGidCells );MB_CHK_SET_ERR( rval, "Error in Zoltan partitioning" );
    1000                 :            :         delete mbZTool;
    1001                 :            : 
    1002                 :            :         dbgOut.tprintf( 1, "After Zoltan partitioning, localGidCells.psize() = %d\n", (int)localGidCells.psize() );
    1003                 :            :         dbgOut.tprintf( 1, "                           localGidCells.size() = %d\n", (int)localGidCells.size() );
    1004                 :            : 
    1005                 :            :         // This is important: local cells are now redistributed, so nLocalCells might be different!
    1006                 :            :         nLocalCells = localGidCells.size();
    1007                 :            : 
    1008                 :            :         return MB_SUCCESS;
    1009                 :            :     }
    1010                 :            : #endif
    1011                 :            : 
    1012                 :            :     // By default, apply trivial partition
    1013                 :          0 :     localGidCells.insert( start_cell_idx, start_cell_idx + nLocalCells - 1 );
    1014                 :            : 
    1015                 :          0 :     return MB_SUCCESS;
    1016                 :            : }
    1017                 :            : #endif
    1018                 :            : 
    1019                 :          0 : ErrorCode NCHelperMPAS::create_local_vertices( const std::vector< int >& vertices_on_local_cells,
    1020                 :            :                                                EntityHandle& start_vertex )
    1021                 :            : {
    1022                 :          0 :     Interface*& mbImpl      = _readNC->mbImpl;
    1023                 :          0 :     Tag& mGlobalIdTag       = _readNC->mGlobalIdTag;
    1024                 :          0 :     const Tag*& mpFileIdTag = _readNC->mpFileIdTag;
    1025                 :          0 :     DebugOutput& dbgOut     = _readNC->dbgOut;
    1026                 :            : 
    1027                 :            :     // Make a copy of vertices_on_local_cells for sorting (keep original one to set cell
    1028                 :            :     // connectivity later)
    1029         [ #  # ]:          0 :     std::vector< int > vertices_on_local_cells_sorted( vertices_on_local_cells );
    1030         [ #  # ]:          0 :     std::sort( vertices_on_local_cells_sorted.begin(), vertices_on_local_cells_sorted.end() );
    1031                 :            :     std::copy( vertices_on_local_cells_sorted.rbegin(), vertices_on_local_cells_sorted.rend(),
    1032 [ #  # ][ #  # ]:          0 :                range_inserter( localGidVerts ) );
    1033         [ #  # ]:          0 :     nLocalVertices = localGidVerts.size();
    1034                 :            : 
    1035 [ #  # ][ #  # ]:          0 :     dbgOut.tprintf( 1, "   localGidVerts.psize() = %d\n", (int)localGidVerts.psize() );
    1036 [ #  # ][ #  # ]:          0 :     dbgOut.tprintf( 1, "   localGidVerts.size() = %d\n", (int)localGidVerts.size() );
    1037                 :            : 
    1038                 :            :     // Create local vertices
    1039         [ #  # ]:          0 :     std::vector< double* > arrays;
    1040                 :            :     ErrorCode rval =
    1041                 :            :         _readNC->readMeshIface->get_node_coords( 3, nLocalVertices, 0, start_vertex, arrays,
    1042                 :            :                                                  // Might have to create gather mesh later
    1043 [ #  # ][ #  # ]:          0 :                                                  ( createGatherSet ? nLocalVertices + nVertices : nLocalVertices ) );MB_CHK_SET_ERR( rval, "Failed to create local vertices" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1044                 :            : 
    1045                 :            :     // Add local vertices to current file set
    1046         [ #  # ]:          0 :     Range local_verts_range( start_vertex, start_vertex + nLocalVertices - 1 );
    1047 [ #  # ][ #  # ]:          0 :     rval = _readNC->mbImpl->add_entities( _fileSet, local_verts_range );MB_CHK_SET_ERR( rval, "Failed to add local vertices to current file set" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1048                 :            : 
    1049                 :            :     // Get ptr to GID memory for local vertices
    1050                 :          0 :     int count  = 0;
    1051                 :          0 :     void* data = NULL;
    1052 [ #  # ][ #  # ]:          0 :     rval       = mbImpl->tag_iterate( mGlobalIdTag, local_verts_range.begin(), local_verts_range.end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate global id tag on local vertices" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1053         [ #  # ]:          0 :     assert( count == nLocalVertices );
    1054                 :          0 :     int* gid_data = (int*)data;
    1055 [ #  # ][ #  # ]:          0 :     std::copy( localGidVerts.begin(), localGidVerts.end(), gid_data );
                 [ #  # ]
    1056                 :            : 
    1057                 :            :     // Duplicate GID data, which will be used to resolve sharing
    1058         [ #  # ]:          0 :     if( mpFileIdTag )
    1059                 :            :     {
    1060 [ #  # ][ #  # ]:          0 :         rval = mbImpl->tag_iterate( *mpFileIdTag, local_verts_range.begin(), local_verts_range.end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate file id tag on local vertices" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1061         [ #  # ]:          0 :         assert( count == nLocalVertices );
    1062                 :          0 :         int bytes_per_tag = 4;
    1063 [ #  # ][ #  # ]:          0 :         rval              = mbImpl->tag_get_bytes( *mpFileIdTag, bytes_per_tag );MB_CHK_SET_ERR( rval, "Can't get number of bytes for file id tag" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1064         [ #  # ]:          0 :         if( 4 == bytes_per_tag )
    1065                 :            :         {
    1066                 :          0 :             gid_data = (int*)data;
    1067 [ #  # ][ #  # ]:          0 :             std::copy( localGidVerts.begin(), localGidVerts.end(), gid_data );
                 [ #  # ]
    1068                 :            :         }
    1069         [ #  # ]:          0 :         else if( 8 == bytes_per_tag )
    1070                 :            :         {  // Should be a handle tag on 64 bit machine?
    1071                 :          0 :             long* handle_tag_data = (long*)data;
    1072 [ #  # ][ #  # ]:          0 :             std::copy( localGidVerts.begin(), localGidVerts.end(), handle_tag_data );
                 [ #  # ]
    1073                 :            :         }
    1074                 :            :     }
    1075                 :            : 
    1076                 :            : #ifdef MOAB_HAVE_PNETCDF
    1077                 :            :     size_t nb_reads = localGidVerts.psize();
    1078                 :            :     std::vector< int > requests( nb_reads );
    1079                 :            :     std::vector< int > statuss( nb_reads );
    1080                 :            :     size_t idxReq = 0;
    1081                 :            : #endif
    1082                 :            : 
    1083                 :            :     // Read x coordinates for local vertices
    1084         [ #  # ]:          0 :     double* xptr = arrays[0];
    1085                 :            :     int xVertexVarId;
    1086         [ #  # ]:          0 :     int success = NCFUNC( inq_varid )( _fileId, "xVertex", &xVertexVarId );
    1087 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of xVertex" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1088                 :          0 :     size_t indexInArray = 0;
    1089 [ #  # ][ #  # ]:          0 :     for( Range::pair_iterator pair_iter = localGidVerts.pair_begin(); pair_iter != localGidVerts.pair_end();
         [ #  # ][ #  # ]
                 [ #  # ]
    1090                 :            :          ++pair_iter )
    1091                 :            :     {
    1092         [ #  # ]:          0 :         EntityHandle starth  = pair_iter->first;
    1093         [ #  # ]:          0 :         EntityHandle endh    = pair_iter->second;
    1094                 :          0 :         NCDF_SIZE read_start = ( NCDF_SIZE )( starth - 1 );
    1095                 :          0 :         NCDF_SIZE read_count = ( NCDF_SIZE )( endh - starth + 1 );
    1096                 :            : 
    1097                 :            :         // Do a partial read in each subrange
    1098                 :            : #ifdef MOAB_HAVE_PNETCDF
    1099                 :            :         success = NCFUNCREQG( _vara_double )( _fileId, xVertexVarId, &read_start, &read_count, &( xptr[indexInArray] ),
    1100                 :            :                                               &requests[idxReq++] );
    1101                 :            : #else
    1102         [ #  # ]:          0 :         success = NCFUNCAG( _vara_double )( _fileId, xVertexVarId, &read_start, &read_count, &( xptr[indexInArray] ) );
    1103                 :            : #endif
    1104 [ #  # ][ #  # ]:          0 :         if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read xVertex data in a loop" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1105                 :            : 
    1106                 :            :         // Increment the index for next subrange
    1107                 :          0 :         indexInArray += ( endh - starth + 1 );
    1108                 :            :     }
    1109                 :            : 
    1110                 :            : #ifdef MOAB_HAVE_PNETCDF
    1111                 :            :     // Wait outside the loop
    1112                 :            :     success = NCFUNC( wait_all )( _fileId, requests.size(), &requests[0], &statuss[0] );
    1113                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed on wait_all" );
    1114                 :            : #endif
    1115                 :            : 
    1116                 :            :     // Read y coordinates for local vertices
    1117         [ #  # ]:          0 :     double* yptr = arrays[1];
    1118                 :            :     int yVertexVarId;
    1119         [ #  # ]:          0 :     success = NCFUNC( inq_varid )( _fileId, "yVertex", &yVertexVarId );
    1120 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of yVertex" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1121                 :            : #ifdef MOAB_HAVE_PNETCDF
    1122                 :            :     idxReq = 0;
    1123                 :            : #endif
    1124                 :          0 :     indexInArray = 0;
    1125 [ #  # ][ #  # ]:          0 :     for( Range::pair_iterator pair_iter = localGidVerts.pair_begin(); pair_iter != localGidVerts.pair_end();
         [ #  # ][ #  # ]
                 [ #  # ]
    1126                 :            :          ++pair_iter )
    1127                 :            :     {
    1128         [ #  # ]:          0 :         EntityHandle starth  = pair_iter->first;
    1129         [ #  # ]:          0 :         EntityHandle endh    = pair_iter->second;
    1130                 :          0 :         NCDF_SIZE read_start = ( NCDF_SIZE )( starth - 1 );
    1131                 :          0 :         NCDF_SIZE read_count = ( NCDF_SIZE )( endh - starth + 1 );
    1132                 :            : 
    1133                 :            :         // Do a partial read in each subrange
    1134                 :            : #ifdef MOAB_HAVE_PNETCDF
    1135                 :            :         success = NCFUNCREQG( _vara_double )( _fileId, yVertexVarId, &read_start, &read_count, &( yptr[indexInArray] ),
    1136                 :            :                                               &requests[idxReq++] );
    1137                 :            : #else
    1138         [ #  # ]:          0 :         success = NCFUNCAG( _vara_double )( _fileId, yVertexVarId, &read_start, &read_count, &( yptr[indexInArray] ) );
    1139                 :            : #endif
    1140 [ #  # ][ #  # ]:          0 :         if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read yVertex data in a loop" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1141                 :            : 
    1142                 :            :         // Increment the index for next subrange
    1143                 :          0 :         indexInArray += ( endh - starth + 1 );
    1144                 :            :     }
    1145                 :            : 
    1146                 :            : #ifdef MOAB_HAVE_PNETCDF
    1147                 :            :     // Wait outside the loop
    1148                 :            :     success = NCFUNC( wait_all )( _fileId, requests.size(), &requests[0], &statuss[0] );
    1149                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed on wait_all" );
    1150                 :            : #endif
    1151                 :            : 
    1152                 :            :     // Read z coordinates for local vertices
    1153         [ #  # ]:          0 :     double* zptr = arrays[2];
    1154                 :            :     int zVertexVarId;
    1155         [ #  # ]:          0 :     success = NCFUNC( inq_varid )( _fileId, "zVertex", &zVertexVarId );
    1156 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of zVertex" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1157                 :            : #ifdef MOAB_HAVE_PNETCDF
    1158                 :            :     idxReq = 0;
    1159                 :            : #endif
    1160                 :          0 :     indexInArray = 0;
    1161 [ #  # ][ #  # ]:          0 :     for( Range::pair_iterator pair_iter = localGidVerts.pair_begin(); pair_iter != localGidVerts.pair_end();
         [ #  # ][ #  # ]
                 [ #  # ]
    1162                 :            :          ++pair_iter )
    1163                 :            :     {
    1164         [ #  # ]:          0 :         EntityHandle starth  = pair_iter->first;
    1165         [ #  # ]:          0 :         EntityHandle endh    = pair_iter->second;
    1166                 :          0 :         NCDF_SIZE read_start = ( NCDF_SIZE )( starth - 1 );
    1167                 :          0 :         NCDF_SIZE read_count = ( NCDF_SIZE )( endh - starth + 1 );
    1168                 :            : 
    1169                 :            :         // Do a partial read in each subrange
    1170                 :            : #ifdef MOAB_HAVE_PNETCDF
    1171                 :            :         success = NCFUNCREQG( _vara_double )( _fileId, zVertexVarId, &read_start, &read_count, &( zptr[indexInArray] ),
    1172                 :            :                                               &requests[idxReq++] );
    1173                 :            : #else
    1174         [ #  # ]:          0 :         success = NCFUNCAG( _vara_double )( _fileId, zVertexVarId, &read_start, &read_count, &( zptr[indexInArray] ) );
    1175                 :            : #endif
    1176 [ #  # ][ #  # ]:          0 :         if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read zVertex data in a loop" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1177                 :            : 
    1178                 :            :         // Increment the index for next subrange
    1179                 :          0 :         indexInArray += ( endh - starth + 1 );
    1180                 :            :     }
    1181                 :            : 
    1182                 :            : #ifdef MOAB_HAVE_PNETCDF
    1183                 :            :     // Wait outside the loop
    1184                 :            :     success = NCFUNC( wait_all )( _fileId, requests.size(), &requests[0], &statuss[0] );
    1185                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed on wait_all" );
    1186                 :            : #endif
    1187                 :            : 
    1188                 :          0 :     return MB_SUCCESS;
    1189                 :            : }
    1190                 :            : 
    1191                 :          0 : ErrorCode NCHelperMPAS::create_local_edges( EntityHandle start_vertex,
    1192                 :            :                                             const std::vector< int >& num_edges_on_local_cells )
    1193                 :            : {
    1194                 :          0 :     Interface*& mbImpl  = _readNC->mbImpl;
    1195                 :          0 :     Tag& mGlobalIdTag   = _readNC->mGlobalIdTag;
    1196                 :          0 :     DebugOutput& dbgOut = _readNC->dbgOut;
    1197                 :            : 
    1198                 :            :     // Read edges on each local cell, to get localGidEdges
    1199                 :            :     int edgesOnCellVarId;
    1200         [ #  # ]:          0 :     int success = NCFUNC( inq_varid )( _fileId, "edgesOnCell", &edgesOnCellVarId );
    1201 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of edgesOnCell" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1202                 :            : 
    1203         [ #  # ]:          0 :     std::vector< int > edges_on_local_cells( nLocalCells * maxEdgesPerCell );
    1204         [ #  # ]:          0 :     dbgOut.tprintf( 1, "   edges_on_local_cells.size() = %d\n", (int)edges_on_local_cells.size() );
    1205                 :            : 
    1206                 :            : #ifdef MOAB_HAVE_PNETCDF
    1207                 :            :     size_t nb_reads = localGidCells.psize();
    1208                 :            :     std::vector< int > requests( nb_reads );
    1209                 :            :     std::vector< int > statuss( nb_reads );
    1210                 :            :     size_t idxReq = 0;
    1211                 :            : #endif
    1212                 :          0 :     size_t indexInArray = 0;
    1213 [ #  # ][ #  # ]:          0 :     for( Range::pair_iterator pair_iter = localGidCells.pair_begin(); pair_iter != localGidCells.pair_end();
         [ #  # ][ #  # ]
                 [ #  # ]
    1214                 :            :          ++pair_iter )
    1215                 :            :     {
    1216         [ #  # ]:          0 :         EntityHandle starth      = pair_iter->first;
    1217         [ #  # ]:          0 :         EntityHandle endh        = pair_iter->second;
    1218                 :          0 :         NCDF_SIZE read_starts[2] = { static_cast< NCDF_SIZE >( starth - 1 ), 0 };
    1219                 :          0 :         NCDF_SIZE read_counts[2] = { static_cast< NCDF_SIZE >( endh - starth + 1 ),
    1220                 :          0 :                                      static_cast< NCDF_SIZE >( maxEdgesPerCell ) };
    1221                 :            : 
    1222                 :            :         // Do a partial read in each subrange
    1223                 :            : #ifdef MOAB_HAVE_PNETCDF
    1224                 :            :         success = NCFUNCREQG( _vara_int )( _fileId, edgesOnCellVarId, read_starts, read_counts,
    1225                 :            :                                            &( edges_on_local_cells[indexInArray] ), &requests[idxReq++] );
    1226                 :            : #else
    1227                 :            :         success = NCFUNCAG( _vara_int )( _fileId, edgesOnCellVarId, read_starts, read_counts,
    1228 [ #  # ][ #  # ]:          0 :                                          &( edges_on_local_cells[indexInArray] ) );
    1229                 :            : #endif
    1230 [ #  # ][ #  # ]:          0 :         if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read edgesOnCell data in a loop" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1231                 :            : 
    1232                 :            :         // Increment the index for next subrange
    1233                 :          0 :         indexInArray += ( endh - starth + 1 ) * maxEdgesPerCell;
    1234                 :            :     }
    1235                 :            : 
    1236                 :            : #ifdef MOAB_HAVE_PNETCDF
    1237                 :            :     // Wait outside the loop
    1238                 :            :     success = NCFUNC( wait_all )( _fileId, requests.size(), &requests[0], &statuss[0] );
    1239                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed on wait_all" );
    1240                 :            : #endif
    1241                 :            : 
    1242                 :            :     // Correct local cell edges array in the same way as local cell vertices array, replace the
    1243                 :            :     // padded edges with the last edges in the corresponding cells
    1244         [ #  # ]:          0 :     for( int local_cell_idx = 0; local_cell_idx < nLocalCells; local_cell_idx++ )
    1245                 :            :     {
    1246         [ #  # ]:          0 :         int num_edges             = num_edges_on_local_cells[local_cell_idx];
    1247                 :          0 :         int idx_in_local_edge_arr = local_cell_idx * maxEdgesPerCell;
    1248         [ #  # ]:          0 :         int last_edge_idx         = edges_on_local_cells[idx_in_local_edge_arr + num_edges - 1];
    1249         [ #  # ]:          0 :         for( int i = num_edges; i < maxEdgesPerCell; i++ )
    1250         [ #  # ]:          0 :             edges_on_local_cells[idx_in_local_edge_arr + i] = last_edge_idx;
    1251                 :            :     }
    1252                 :            : 
    1253                 :            :     // Collect local edges
    1254         [ #  # ]:          0 :     std::sort( edges_on_local_cells.begin(), edges_on_local_cells.end() );
    1255 [ #  # ][ #  # ]:          0 :     std::copy( edges_on_local_cells.rbegin(), edges_on_local_cells.rend(), range_inserter( localGidEdges ) );
    1256         [ #  # ]:          0 :     nLocalEdges = localGidEdges.size();
    1257                 :            : 
    1258 [ #  # ][ #  # ]:          0 :     dbgOut.tprintf( 1, "   localGidEdges.psize() = %d\n", (int)localGidEdges.psize() );
    1259 [ #  # ][ #  # ]:          0 :     dbgOut.tprintf( 1, "   localGidEdges.size() = %d\n", (int)localGidEdges.size() );
    1260                 :            : 
    1261                 :            :     // Create local edges
    1262                 :            :     EntityHandle start_edge;
    1263                 :          0 :     EntityHandle* conn_arr_edges = NULL;
    1264                 :            :     ErrorCode rval =
    1265                 :            :         _readNC->readMeshIface->get_element_connect( nLocalEdges, 2, MBEDGE, 0, start_edge, conn_arr_edges,
    1266                 :            :                                                      // Might have to create gather mesh later
    1267 [ #  # ][ #  # ]:          0 :                                                      ( createGatherSet ? nLocalEdges + nEdges : nLocalEdges ) );MB_CHK_SET_ERR( rval, "Failed to create local edges" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1268                 :            : 
    1269                 :            :     // Add local edges to current file set
    1270         [ #  # ]:          0 :     Range local_edges_range( start_edge, start_edge + nLocalEdges - 1 );
    1271 [ #  # ][ #  # ]:          0 :     rval = _readNC->mbImpl->add_entities( _fileSet, local_edges_range );MB_CHK_SET_ERR( rval, "Failed to add local edges to current file set" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1272                 :            : 
    1273                 :            :     // Get ptr to GID memory for edges
    1274                 :          0 :     int count  = 0;
    1275                 :          0 :     void* data = NULL;
    1276 [ #  # ][ #  # ]:          0 :     rval       = mbImpl->tag_iterate( mGlobalIdTag, local_edges_range.begin(), local_edges_range.end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate global id tag on local edges" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1277         [ #  # ]:          0 :     assert( count == nLocalEdges );
    1278                 :          0 :     int* gid_data = (int*)data;
    1279 [ #  # ][ #  # ]:          0 :     std::copy( localGidEdges.begin(), localGidEdges.end(), gid_data );
                 [ #  # ]
    1280                 :            : 
    1281                 :            :     int verticesOnEdgeVarId;
    1282                 :            : 
    1283                 :            :     // Read vertices on each local edge, to get edge connectivity
    1284         [ #  # ]:          0 :     success = NCFUNC( inq_varid )( _fileId, "verticesOnEdge", &verticesOnEdgeVarId );
    1285 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of verticesOnEdge" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1286                 :            :     // Utilize the memory storage pointed by conn_arr_edges
    1287                 :          0 :     int* vertices_on_local_edges = (int*)conn_arr_edges;
    1288                 :            : #ifdef MOAB_HAVE_PNETCDF
    1289                 :            :     nb_reads = localGidEdges.psize();
    1290                 :            :     requests.resize( nb_reads );
    1291                 :            :     statuss.resize( nb_reads );
    1292                 :            :     idxReq = 0;
    1293                 :            : #endif
    1294                 :          0 :     indexInArray = 0;
    1295 [ #  # ][ #  # ]:          0 :     for( Range::pair_iterator pair_iter = localGidEdges.pair_begin(); pair_iter != localGidEdges.pair_end();
         [ #  # ][ #  # ]
                 [ #  # ]
    1296                 :            :          ++pair_iter )
    1297                 :            :     {
    1298         [ #  # ]:          0 :         EntityHandle starth      = pair_iter->first;
    1299         [ #  # ]:          0 :         EntityHandle endh        = pair_iter->second;
    1300                 :          0 :         NCDF_SIZE read_starts[2] = { static_cast< NCDF_SIZE >( starth - 1 ), 0 };
    1301                 :          0 :         NCDF_SIZE read_counts[2] = { static_cast< NCDF_SIZE >( endh - starth + 1 ), 2 };
    1302                 :            : 
    1303                 :            :         // Do a partial read in each subrange
    1304                 :            : #ifdef MOAB_HAVE_PNETCDF
    1305                 :            :         success = NCFUNCREQG( _vara_int )( _fileId, verticesOnEdgeVarId, read_starts, read_counts,
    1306                 :            :                                            &( vertices_on_local_edges[indexInArray] ), &requests[idxReq++] );
    1307                 :            : #else
    1308                 :            :         success = NCFUNCAG( _vara_int )( _fileId, verticesOnEdgeVarId, read_starts, read_counts,
    1309         [ #  # ]:          0 :                                          &( vertices_on_local_edges[indexInArray] ) );
    1310                 :            : #endif
    1311 [ #  # ][ #  # ]:          0 :         if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read verticesOnEdge data in a loop" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1312                 :            : 
    1313                 :            :         // Increment the index for next subrange
    1314                 :          0 :         indexInArray += ( endh - starth + 1 ) * 2;
    1315                 :            :     }
    1316                 :            : 
    1317                 :            : #ifdef MOAB_HAVE_PNETCDF
    1318                 :            :     // Wait outside the loop
    1319                 :            :     success = NCFUNC( wait_all )( _fileId, requests.size(), &requests[0], &statuss[0] );
    1320                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed on wait_all" );
    1321                 :            : #endif
    1322                 :            : 
    1323                 :            :     // Populate connectivity data for local edges
    1324                 :            :     // Convert in-place from int (stored in the first half) to EntityHandle
    1325                 :            :     // Reading backward is the trick
    1326         [ #  # ]:          0 :     for( int edge_vert = nLocalEdges * 2 - 1; edge_vert >= 0; edge_vert-- )
    1327                 :            :     {
    1328                 :          0 :         int global_vert_idx = vertices_on_local_edges[edge_vert];      // Global vertex index, 1 based
    1329         [ #  # ]:          0 :         int local_vert_idx  = localGidVerts.index( global_vert_idx );  // Local vertex index, 0 based
    1330         [ #  # ]:          0 :         assert( local_vert_idx != -1 );
    1331                 :          0 :         conn_arr_edges[edge_vert] = start_vertex + local_vert_idx;
    1332                 :            :     }
    1333                 :            : 
    1334                 :          0 :     return MB_SUCCESS;
    1335                 :            : }
    1336                 :            : 
    1337                 :          0 : ErrorCode NCHelperMPAS::create_local_cells( const std::vector< int >& vertices_on_local_cells,
    1338                 :            :                                             const std::vector< int >& num_edges_on_local_cells,
    1339                 :            :                                             EntityHandle start_vertex, Range& faces )
    1340                 :            : {
    1341                 :          0 :     Interface*& mbImpl = _readNC->mbImpl;
    1342                 :          0 :     Tag& mGlobalIdTag  = _readNC->mGlobalIdTag;
    1343                 :            : 
    1344                 :            :     // Divide local cells into groups based on the number of edges
    1345 [ #  # ][ #  # ]:          0 :     Range local_cells_with_n_edges[DEFAULT_MAX_EDGES_PER_CELL + 1];
                 [ #  # ]
    1346                 :            :     // Insert larger values before smaller ones to increase efficiency
    1347         [ #  # ]:          0 :     for( int i = nLocalCells - 1; i >= 0; i-- )
    1348                 :            :     {
    1349         [ #  # ]:          0 :         int num_edges = num_edges_on_local_cells[i];
    1350 [ #  # ][ #  # ]:          0 :         local_cells_with_n_edges[num_edges].insert( localGidCells[i] );  // Global cell index
    1351                 :            :     }
    1352                 :            : 
    1353         [ #  # ]:          0 :     std::vector< int > num_edges_on_cell_groups;
    1354         [ #  # ]:          0 :     for( int i = 3; i <= maxEdgesPerCell; i++ )
    1355                 :            :     {
    1356 [ #  # ][ #  # ]:          0 :         if( local_cells_with_n_edges[i].size() > 0 ) num_edges_on_cell_groups.push_back( i );
                 [ #  # ]
    1357                 :            :     }
    1358                 :          0 :     numCellGroups = num_edges_on_cell_groups.size();
    1359                 :            : 
    1360                 :            :     EntityHandle* conn_arr_local_cells_with_n_edges[DEFAULT_MAX_EDGES_PER_CELL + 1];
    1361         [ #  # ]:          0 :     for( int i = 0; i < numCellGroups; i++ )
    1362                 :            :     {
    1363         [ #  # ]:          0 :         int num_edges_per_cell = num_edges_on_cell_groups[i];
    1364         [ #  # ]:          0 :         int num_group_cells    = (int)local_cells_with_n_edges[num_edges_per_cell].size();
    1365                 :            : 
    1366                 :            :         // Create local cells for each non-empty cell group
    1367                 :            :         EntityHandle start_element;
    1368                 :            :         ErrorCode rval = _readNC->readMeshIface->get_element_connect(
    1369                 :            :             num_group_cells, num_edges_per_cell, MBPOLYGON, 0, start_element,
    1370 [ #  # ][ #  # ]:          0 :             conn_arr_local_cells_with_n_edges[num_edges_per_cell], num_group_cells );MB_CHK_SET_ERR( rval, "Failed to create local cells" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1371         [ #  # ]:          0 :         faces.insert( start_element, start_element + num_group_cells - 1 );
    1372                 :            : 
    1373                 :            :         // Add local cells to current file set
    1374         [ #  # ]:          0 :         Range local_cells_range( start_element, start_element + num_group_cells - 1 );
    1375 [ #  # ][ #  # ]:          0 :         rval = _readNC->mbImpl->add_entities( _fileSet, local_cells_range );MB_CHK_SET_ERR( rval, "Failed to add local cells to current file set" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1376                 :            : 
    1377                 :            :         // Get ptr to gid memory for local cells
    1378                 :          0 :         int count  = 0;
    1379                 :          0 :         void* data = NULL;
    1380 [ #  # ][ #  # ]:          0 :         rval = mbImpl->tag_iterate( mGlobalIdTag, local_cells_range.begin(), local_cells_range.end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate global id tag on local cells" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1381         [ #  # ]:          0 :         assert( count == num_group_cells );
    1382                 :          0 :         int* gid_data = (int*)data;
    1383                 :            :         std::copy( local_cells_with_n_edges[num_edges_per_cell].begin(),
    1384 [ #  # ][ #  # ]:          0 :                    local_cells_with_n_edges[num_edges_per_cell].end(), gid_data );
                 [ #  # ]
    1385                 :            : 
    1386                 :            :         // Set connectivity array with proper local vertices handles
    1387 [ #  # ][ #  # ]:          0 :         for( int j = 0; j < num_group_cells; j++ )
    1388                 :            :         {
    1389                 :            :             EntityHandle global_cell_idx =
    1390         [ #  # ]:          0 :                 local_cells_with_n_edges[num_edges_per_cell][j];          // Global cell index, 1 based
    1391         [ #  # ]:          0 :             int local_cell_idx = localGidCells.index( global_cell_idx );  // Local cell index, 0 based
    1392         [ #  # ]:          0 :             assert( local_cell_idx != -1 );
    1393                 :            : 
    1394         [ #  # ]:          0 :             if( numCellGroups > 1 )
    1395                 :            :             {
    1396                 :            :                 // Populate cellHandleToGlobalID map to read cell variables
    1397         [ #  # ]:          0 :                 cellHandleToGlobalID[start_element + j] = global_cell_idx;
    1398                 :            :             }
    1399                 :            : 
    1400         [ #  # ]:          0 :             for( int k = 0; k < num_edges_per_cell; k++ )
    1401                 :            :             {
    1402                 :            :                 EntityHandle global_vert_idx =
    1403         [ #  # ]:          0 :                     vertices_on_local_cells[local_cell_idx * maxEdgesPerCell + k];  // Global vertex index, 1 based
    1404         [ #  # ]:          0 :                 int local_vert_idx = localGidVerts.index( global_vert_idx );        // Local vertex index, 0 based
    1405         [ #  # ]:          0 :                 assert( local_vert_idx != -1 );
    1406                 :          0 :                 conn_arr_local_cells_with_n_edges[num_edges_per_cell][j * num_edges_per_cell + k] =
    1407                 :          0 :                     start_vertex + local_vert_idx;
    1408                 :            :             }
    1409                 :            :         }
    1410                 :          0 :     }
    1411                 :            : 
    1412         [ #  # ]:          0 :     return MB_SUCCESS;
           [ #  #  #  # ]
    1413                 :            : }
    1414                 :            : 
    1415                 :          0 : ErrorCode NCHelperMPAS::create_padded_local_cells( const std::vector< int >& vertices_on_local_cells,
    1416                 :            :                                                    EntityHandle start_vertex, Range& faces )
    1417                 :            : {
    1418                 :          0 :     Interface*& mbImpl = _readNC->mbImpl;
    1419                 :          0 :     Tag& mGlobalIdTag  = _readNC->mGlobalIdTag;
    1420                 :            : 
    1421                 :            :     // Only one group of cells (each cell is represented by a polygon with maxEdgesPerCell edges)
    1422                 :          0 :     numCellGroups = 1;
    1423                 :            : 
    1424                 :            :     // Create cells for this cell group
    1425                 :            :     EntityHandle start_element;
    1426                 :          0 :     EntityHandle* conn_arr_local_cells = NULL;
    1427                 :            :     ErrorCode rval =
    1428                 :            :         _readNC->readMeshIface->get_element_connect( nLocalCells, maxEdgesPerCell, MBPOLYGON, 0, start_element,
    1429                 :            :                                                      conn_arr_local_cells,
    1430                 :            :                                                      // Might have to create gather mesh later
    1431 [ #  # ][ #  # ]:          0 :                                                      ( createGatherSet ? nLocalCells + nCells : nLocalCells ) );MB_CHK_SET_ERR( rval, "Failed to create local cells" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1432         [ #  # ]:          0 :     faces.insert( start_element, start_element + nLocalCells - 1 );
    1433                 :            : 
    1434                 :            :     // Add local cells to current file set
    1435         [ #  # ]:          0 :     Range local_cells_range( start_element, start_element + nLocalCells - 1 );
    1436 [ #  # ][ #  # ]:          0 :     rval = _readNC->mbImpl->add_entities( _fileSet, local_cells_range );MB_CHK_SET_ERR( rval, "Failed to add local cells to current file set" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1437                 :            : 
    1438                 :            :     // Get ptr to GID memory for local cells
    1439                 :          0 :     int count  = 0;
    1440                 :          0 :     void* data = NULL;
    1441 [ #  # ][ #  # ]:          0 :     rval       = mbImpl->tag_iterate( mGlobalIdTag, local_cells_range.begin(), local_cells_range.end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate global id tag on local cells" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1442         [ #  # ]:          0 :     assert( count == nLocalCells );
    1443                 :          0 :     int* gid_data = (int*)data;
    1444 [ #  # ][ #  # ]:          0 :     std::copy( localGidCells.begin(), localGidCells.end(), gid_data );
                 [ #  # ]
    1445                 :            : 
    1446                 :            :     // Set connectivity array with proper local vertices handles
    1447                 :            :     // vertices_on_local_cells array was already corrected to have the last vertices padded
    1448                 :            :     // no need for extra checks considering
    1449         [ #  # ]:          0 :     for( int local_cell_idx = 0; local_cell_idx < nLocalCells; local_cell_idx++ )
    1450                 :            :     {
    1451         [ #  # ]:          0 :         for( int i = 0; i < maxEdgesPerCell; i++ )
    1452                 :            :         {
    1453                 :            :             EntityHandle global_vert_idx =
    1454         [ #  # ]:          0 :                 vertices_on_local_cells[local_cell_idx * maxEdgesPerCell + i];  // Global vertex index, 1 based
    1455         [ #  # ]:          0 :             int local_vert_idx = localGidVerts.index( global_vert_idx );        // Local vertex index, 0 based
    1456         [ #  # ]:          0 :             assert( local_vert_idx != -1 );
    1457                 :          0 :             conn_arr_local_cells[local_cell_idx * maxEdgesPerCell + i] = start_vertex + local_vert_idx;
    1458                 :            :         }
    1459                 :            :     }
    1460                 :            : 
    1461                 :          0 :     return MB_SUCCESS;
    1462                 :            : }
    1463                 :            : 
    1464                 :          0 : ErrorCode NCHelperMPAS::create_gather_set_vertices( EntityHandle gather_set, EntityHandle& gather_set_start_vertex )
    1465                 :            : {
    1466                 :          0 :     Interface*& mbImpl      = _readNC->mbImpl;
    1467                 :          0 :     Tag& mGlobalIdTag       = _readNC->mGlobalIdTag;
    1468                 :          0 :     const Tag*& mpFileIdTag = _readNC->mpFileIdTag;
    1469                 :            : 
    1470                 :            :     // Create gather set vertices
    1471         [ #  # ]:          0 :     std::vector< double* > arrays;
    1472                 :            :     // Don't need to specify allocation number here, because we know enough vertices were created
    1473                 :            :     // before
    1474 [ #  # ][ #  # ]:          0 :     ErrorCode rval = _readNC->readMeshIface->get_node_coords( 3, nVertices, 0, gather_set_start_vertex, arrays );MB_CHK_SET_ERR( rval, "Failed to create gather set vertices" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1475                 :            : 
    1476                 :            :     // Add vertices to the gather set
    1477         [ #  # ]:          0 :     Range gather_set_verts_range( gather_set_start_vertex, gather_set_start_vertex + nVertices - 1 );
    1478 [ #  # ][ #  # ]:          0 :     rval = mbImpl->add_entities( gather_set, gather_set_verts_range );MB_CHK_SET_ERR( rval, "Failed to add vertices to the gather set" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1479                 :            : 
    1480                 :            :     // Read x coordinates for gather set vertices
    1481         [ #  # ]:          0 :     double* xptr = arrays[0];
    1482                 :            :     int xVertexVarId;
    1483         [ #  # ]:          0 :     int success = NCFUNC( inq_varid )( _fileId, "xVertex", &xVertexVarId );
    1484 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of xVertex" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1485                 :          0 :     NCDF_SIZE read_start = 0;
    1486                 :          0 :     NCDF_SIZE read_count = static_cast< NCDF_SIZE >( nVertices );
    1487                 :            : #ifdef MOAB_HAVE_PNETCDF
    1488                 :            :     // Enter independent I/O mode, since this read is only for the gather processor
    1489                 :            :     success = NCFUNC( begin_indep_data )( _fileId );
    1490                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to begin independent I/O mode" );
    1491                 :            :     success = NCFUNCG( _vara_double )( _fileId, xVertexVarId, &read_start, &read_count, xptr );
    1492                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read xVertex data" );
    1493                 :            :     success = NCFUNC( end_indep_data )( _fileId );
    1494                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to end independent I/O mode" );
    1495                 :            : #else
    1496         [ #  # ]:          0 :     success = NCFUNCG( _vara_double )( _fileId, xVertexVarId, &read_start, &read_count, xptr );
    1497 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read xVertex data" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1498                 :            : #endif
    1499                 :            : 
    1500                 :            :     // Read y coordinates for gather set vertices
    1501         [ #  # ]:          0 :     double* yptr = arrays[1];
    1502                 :            :     int yVertexVarId;
    1503         [ #  # ]:          0 :     success = NCFUNC( inq_varid )( _fileId, "yVertex", &yVertexVarId );
    1504 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of yVertex" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1505                 :            : #ifdef MOAB_HAVE_PNETCDF
    1506                 :            :     // Enter independent I/O mode, since this read is only for the gather processor
    1507                 :            :     success = NCFUNC( begin_indep_data )( _fileId );
    1508                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to begin independent I/O mode" );
    1509                 :            :     success = NCFUNCG( _vara_double )( _fileId, yVertexVarId, &read_start, &read_count, yptr );
    1510                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read yVertex data" );
    1511                 :            :     success = NCFUNC( end_indep_data )( _fileId );
    1512                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to end independent I/O mode" );
    1513                 :            : #else
    1514         [ #  # ]:          0 :     success = NCFUNCG( _vara_double )( _fileId, yVertexVarId, &read_start, &read_count, yptr );
    1515 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read yVertex data" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1516                 :            : #endif
    1517                 :            : 
    1518                 :            :     // Read z coordinates for gather set vertices
    1519         [ #  # ]:          0 :     double* zptr = arrays[2];
    1520                 :            :     int zVertexVarId;
    1521         [ #  # ]:          0 :     success = NCFUNC( inq_varid )( _fileId, "zVertex", &zVertexVarId );
    1522 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of zVertex" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1523                 :            : #ifdef MOAB_HAVE_PNETCDF
    1524                 :            :     // Enter independent I/O mode, since this read is only for the gather processor
    1525                 :            :     success = NCFUNC( begin_indep_data )( _fileId );
    1526                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to begin independent I/O mode" );
    1527                 :            :     success = NCFUNCG( _vara_double )( _fileId, zVertexVarId, &read_start, &read_count, zptr );
    1528                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read zVertex data" );
    1529                 :            :     success = NCFUNC( end_indep_data )( _fileId );
    1530                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to end independent I/O mode" );
    1531                 :            : #else
    1532         [ #  # ]:          0 :     success = NCFUNCG( _vara_double )( _fileId, zVertexVarId, &read_start, &read_count, zptr );
    1533 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read zVertex data" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1534                 :            : #endif
    1535                 :            : 
    1536                 :            :     // Get ptr to GID memory for gather set vertices
    1537                 :          0 :     int count  = 0;
    1538                 :          0 :     void* data = NULL;
    1539                 :            :     rval =
    1540 [ #  # ][ #  # ]:          0 :         mbImpl->tag_iterate( mGlobalIdTag, gather_set_verts_range.begin(), gather_set_verts_range.end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate global id tag on gather set vertices" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1541         [ #  # ]:          0 :     assert( count == nVertices );
    1542                 :          0 :     int* gid_data = (int*)data;
    1543         [ #  # ]:          0 :     for( int j = 1; j <= nVertices; j++ )
    1544                 :          0 :         gid_data[j - 1] = j;
    1545                 :            : 
    1546                 :            :     // Set the file id tag too, it should be bigger something not interfering with global id
    1547         [ #  # ]:          0 :     if( mpFileIdTag )
    1548                 :            :     {
    1549                 :            :         rval = mbImpl->tag_iterate( *mpFileIdTag, gather_set_verts_range.begin(), gather_set_verts_range.end(), count,
    1550 [ #  # ][ #  # ]:          0 :                                     data );MB_CHK_SET_ERR( rval, "Failed to iterate file id tag on gather set vertices" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1551         [ #  # ]:          0 :         assert( count == nVertices );
    1552                 :          0 :         int bytes_per_tag = 4;
    1553 [ #  # ][ #  # ]:          0 :         rval              = mbImpl->tag_get_bytes( *mpFileIdTag, bytes_per_tag );MB_CHK_SET_ERR( rval, "Can't get number of bytes for file id tag" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1554         [ #  # ]:          0 :         if( 4 == bytes_per_tag )
    1555                 :            :         {
    1556                 :          0 :             gid_data = (int*)data;
    1557         [ #  # ]:          0 :             for( int j = 1; j <= nVertices; j++ )
    1558                 :          0 :                 gid_data[j - 1] = nVertices + j;  // Bigger than global id tag
    1559                 :            :         }
    1560         [ #  # ]:          0 :         else if( 8 == bytes_per_tag )
    1561                 :            :         {  // Should be a handle tag on 64 bit machine?
    1562                 :          0 :             long* handle_tag_data = (long*)data;
    1563         [ #  # ]:          0 :             for( int j = 1; j <= nVertices; j++ )
    1564                 :          0 :                 handle_tag_data[j - 1] = nVertices + j;  // Bigger than global id tag
    1565                 :            :         }
    1566                 :            :     }
    1567                 :            : 
    1568                 :          0 :     return MB_SUCCESS;
    1569                 :            : }
    1570                 :            : 
    1571                 :          0 : ErrorCode NCHelperMPAS::create_gather_set_edges( EntityHandle gather_set, EntityHandle gather_set_start_vertex )
    1572                 :            : {
    1573                 :          0 :     Interface*& mbImpl = _readNC->mbImpl;
    1574                 :            : 
    1575                 :            :     // Create gather set edges
    1576                 :            :     EntityHandle start_edge;
    1577                 :          0 :     EntityHandle* conn_arr_gather_set_edges = NULL;
    1578                 :            :     // Don't need to specify allocation number here, because we know enough edges were created
    1579                 :            :     // before
    1580                 :            :     ErrorCode rval =
    1581 [ #  # ][ #  # ]:          0 :         _readNC->readMeshIface->get_element_connect( nEdges, 2, MBEDGE, 0, start_edge, conn_arr_gather_set_edges );MB_CHK_SET_ERR( rval, "Failed to create gather set edges" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1582                 :            : 
    1583                 :            :     // Add edges to the gather set
    1584         [ #  # ]:          0 :     Range gather_set_edges_range( start_edge, start_edge + nEdges - 1 );
    1585 [ #  # ][ #  # ]:          0 :     rval = mbImpl->add_entities( gather_set, gather_set_edges_range );MB_CHK_SET_ERR( rval, "Failed to add edges to the gather set" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1586                 :            : 
    1587                 :            :     // Read vertices on each edge
    1588                 :            :     int verticesOnEdgeVarId;
    1589         [ #  # ]:          0 :     int success = NCFUNC( inq_varid )( _fileId, "verticesOnEdge", &verticesOnEdgeVarId );
    1590 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of verticesOnEdge" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1591                 :            :     // Utilize the memory storage pointed by conn_arr_gather_set_edges
    1592                 :          0 :     int* vertices_on_gather_set_edges = (int*)conn_arr_gather_set_edges;
    1593                 :          0 :     NCDF_SIZE read_starts[2]          = { 0, 0 };
    1594                 :          0 :     NCDF_SIZE read_counts[2]          = { static_cast< NCDF_SIZE >( nEdges ), 2 };
    1595                 :            : #ifdef MOAB_HAVE_PNETCDF
    1596                 :            :     // Enter independent I/O mode, since this read is only for the gather processor
    1597                 :            :     success = NCFUNC( begin_indep_data )( _fileId );
    1598                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to begin independent I/O mode" );
    1599                 :            :     success =
    1600                 :            :         NCFUNCG( _vara_int )( _fileId, verticesOnEdgeVarId, read_starts, read_counts, vertices_on_gather_set_edges );
    1601                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read verticesOnEdge data" );
    1602                 :            :     success = NCFUNC( end_indep_data )( _fileId );
    1603                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to end independent I/O mode" );
    1604                 :            : #else
    1605                 :            :     success =
    1606         [ #  # ]:          0 :         NCFUNCG( _vara_int )( _fileId, verticesOnEdgeVarId, read_starts, read_counts, vertices_on_gather_set_edges );
    1607 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read verticesOnEdge data" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1608                 :            : #endif
    1609                 :            : 
    1610                 :            :     // Populate connectivity data for gather set edges
    1611                 :            :     // Convert in-place from int (stored in the first half) to EntityHandle
    1612                 :            :     // Reading backward is the trick
    1613         [ #  # ]:          0 :     for( int edge_vert = nEdges * 2 - 1; edge_vert >= 0; edge_vert-- )
    1614                 :            :     {
    1615                 :          0 :         int gather_set_vert_idx = vertices_on_gather_set_edges[edge_vert];  // Global vertex index, 1 based
    1616                 :          0 :         gather_set_vert_idx--;                                              // 1 based -> 0 based
    1617                 :            :         // Connectivity array is shifted by where the gather set vertices start
    1618                 :          0 :         conn_arr_gather_set_edges[edge_vert] = gather_set_start_vertex + gather_set_vert_idx;
    1619                 :            :     }
    1620                 :            : 
    1621                 :          0 :     return MB_SUCCESS;
    1622                 :            : }
    1623                 :            : 
    1624                 :          0 : ErrorCode NCHelperMPAS::create_gather_set_cells( EntityHandle gather_set, EntityHandle gather_set_start_vertex )
    1625                 :            : {
    1626                 :          0 :     Interface*& mbImpl = _readNC->mbImpl;
    1627                 :            : 
    1628                 :            :     // Read number of edges on each gather set cell
    1629                 :            :     int nEdgesOnCellVarId;
    1630         [ #  # ]:          0 :     int success = NCFUNC( inq_varid )( _fileId, "nEdgesOnCell", &nEdgesOnCellVarId );
    1631 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of nEdgesOnCell" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1632         [ #  # ]:          0 :     std::vector< int > num_edges_on_gather_set_cells( nCells );
    1633                 :          0 :     NCDF_SIZE read_start = 0;
    1634                 :          0 :     NCDF_SIZE read_count = static_cast< NCDF_SIZE >( nCells );
    1635                 :            : #ifdef MOAB_HAVE_PNETCDF
    1636                 :            :     // Enter independent I/O mode, since this read is only for the gather processor
    1637                 :            :     success = NCFUNC( begin_indep_data )( _fileId );
    1638                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to begin independent I/O mode" );
    1639                 :            :     success =
    1640                 :            :         NCFUNCG( _vara_int )( _fileId, nEdgesOnCellVarId, &read_start, &read_count, &num_edges_on_gather_set_cells[0] );
    1641                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read nEdgesOnCell data" );
    1642                 :            :     success = NCFUNC( end_indep_data )( _fileId );
    1643                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to end independent I/O mode" );
    1644                 :            : #else
    1645                 :            :     success =
    1646 [ #  # ][ #  # ]:          0 :         NCFUNCG( _vara_int )( _fileId, nEdgesOnCellVarId, &read_start, &read_count, &num_edges_on_gather_set_cells[0] );
    1647 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read nEdgesOnCell data" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1648                 :            : #endif
    1649                 :            : 
    1650                 :            :     // Read vertices on each gather set cell (connectivity)
    1651                 :            :     int verticesOnCellVarId;
    1652         [ #  # ]:          0 :     success = NCFUNC( inq_varid )( _fileId, "verticesOnCell", &verticesOnCellVarId );
    1653 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of verticesOnCell" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1654         [ #  # ]:          0 :     std::vector< int > vertices_on_gather_set_cells( nCells * maxEdgesPerCell );
    1655                 :          0 :     NCDF_SIZE read_starts[2] = { 0, 0 };
    1656                 :          0 :     NCDF_SIZE read_counts[2] = { static_cast< NCDF_SIZE >( nCells ), static_cast< NCDF_SIZE >( maxEdgesPerCell ) };
    1657                 :            : #ifdef MOAB_HAVE_PNETCDF
    1658                 :            :     // Enter independent I/O mode, since this read is only for the gather processor
    1659                 :            :     success = NCFUNC( begin_indep_data )( _fileId );
    1660                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to begin independent I/O mode" );
    1661                 :            :     success = NCFUNCG( _vara_int )( _fileId, verticesOnCellVarId, read_starts, read_counts,
    1662                 :            :                                     &vertices_on_gather_set_cells[0] );
    1663                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read verticesOnCell data" );
    1664                 :            :     success = NCFUNC( end_indep_data )( _fileId );
    1665                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to end independent I/O mode" );
    1666                 :            : #else
    1667                 :            :     success = NCFUNCG( _vara_int )( _fileId, verticesOnCellVarId, read_starts, read_counts,
    1668 [ #  # ][ #  # ]:          0 :                                     &vertices_on_gather_set_cells[0] );
    1669 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read verticesOnCell data" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1670                 :            : #endif
    1671                 :            : 
    1672                 :            :     // Divide gather set cells into groups based on the number of edges
    1673 [ #  # ][ #  # ]:          0 :     Range gather_set_cells_with_n_edges[DEFAULT_MAX_EDGES_PER_CELL + 1];
                 [ #  # ]
           [ #  #  #  # ]
    1674                 :            :     // Insert larger values before smaller values to increase efficiency
    1675         [ #  # ]:          0 :     for( int i = nCells - 1; i >= 0; i-- )
    1676                 :            :     {
    1677         [ #  # ]:          0 :         int num_edges = num_edges_on_gather_set_cells[i];
    1678         [ #  # ]:          0 :         gather_set_cells_with_n_edges[num_edges].insert( i + 1 );  // 0 based -> 1 based
    1679                 :            :     }
    1680                 :            : 
    1681                 :            :     // Create gather set cells
    1682                 :            :     EntityHandle* conn_arr_gather_set_cells_with_n_edges[DEFAULT_MAX_EDGES_PER_CELL + 1];
    1683         [ #  # ]:          0 :     for( int num_edges_per_cell = 3; num_edges_per_cell <= maxEdgesPerCell; num_edges_per_cell++ )
    1684                 :            :     {
    1685         [ #  # ]:          0 :         int num_group_cells = gather_set_cells_with_n_edges[num_edges_per_cell].size();
    1686         [ #  # ]:          0 :         if( num_group_cells > 0 )
    1687                 :            :         {
    1688                 :            :             EntityHandle start_element;
    1689                 :            :             ErrorCode rval = _readNC->readMeshIface->get_element_connect(
    1690                 :            :                 num_group_cells, num_edges_per_cell, MBPOLYGON, 0, start_element,
    1691 [ #  # ][ #  # ]:          0 :                 conn_arr_gather_set_cells_with_n_edges[num_edges_per_cell], num_group_cells );MB_CHK_SET_ERR( rval, "Failed to create gather set cells" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1692                 :            : 
    1693                 :            :             // Add cells to the gather set
    1694         [ #  # ]:          0 :             Range gather_set_cells_range( start_element, start_element + num_group_cells - 1 );
    1695 [ #  # ][ #  # ]:          0 :             rval = mbImpl->add_entities( gather_set, gather_set_cells_range );MB_CHK_SET_ERR( rval, "Failed to add cells to the gather set" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1696                 :            : 
    1697 [ #  # ][ #  # ]:          0 :             for( int j = 0; j < num_group_cells; j++ )
    1698                 :            :             {
    1699                 :            :                 int gather_set_cell_idx =
    1700         [ #  # ]:          0 :                     gather_set_cells_with_n_edges[num_edges_per_cell][j];  // Global cell index, 1 based
    1701                 :          0 :                 gather_set_cell_idx--;                                     // 1 based -> 0 based
    1702                 :            : 
    1703         [ #  # ]:          0 :                 for( int k = 0; k < num_edges_per_cell; k++ )
    1704                 :            :                 {
    1705                 :            :                     EntityHandle gather_set_vert_idx =
    1706                 :          0 :                         vertices_on_gather_set_cells[gather_set_cell_idx * maxEdgesPerCell +
    1707         [ #  # ]:          0 :                                                      k];  // Global vertex index, 1 based
    1708                 :          0 :                     gather_set_vert_idx--;                // 1 based -> 0 based
    1709                 :            : 
    1710                 :            :                     // Connectivity array is shifted by where the gather set vertices start
    1711                 :          0 :                     conn_arr_gather_set_cells_with_n_edges[num_edges_per_cell][j * num_edges_per_cell + k] =
    1712                 :          0 :                         gather_set_start_vertex + gather_set_vert_idx;
    1713                 :            :                 }
    1714                 :          0 :             }
    1715                 :            :         }
    1716                 :            :     }
    1717                 :            : 
    1718                 :          0 :     return MB_SUCCESS;
    1719                 :            : }
    1720                 :            : 
    1721                 :          0 : ErrorCode NCHelperMPAS::create_padded_gather_set_cells( EntityHandle gather_set, EntityHandle gather_set_start_vertex )
    1722                 :            : {
    1723                 :          0 :     Interface*& mbImpl = _readNC->mbImpl;
    1724                 :            : 
    1725                 :            :     // Read number of edges on each gather set cell
    1726                 :            :     int nEdgesOnCellVarId;
    1727         [ #  # ]:          0 :     int success = NCFUNC( inq_varid )( _fileId, "nEdgesOnCell", &nEdgesOnCellVarId );
    1728 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of nEdgesOnCell" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1729         [ #  # ]:          0 :     std::vector< int > num_edges_on_gather_set_cells( nCells );
    1730                 :          0 :     NCDF_SIZE read_start = 0;
    1731                 :          0 :     NCDF_SIZE read_count = static_cast< NCDF_SIZE >( nCells );
    1732                 :            : #ifdef MOAB_HAVE_PNETCDF
    1733                 :            :     // Enter independent I/O mode, since this read is only for the gather processor
    1734                 :            :     success = NCFUNC( begin_indep_data )( _fileId );
    1735                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to begin independent I/O mode" );
    1736                 :            :     success =
    1737                 :            :         NCFUNCG( _vara_int )( _fileId, nEdgesOnCellVarId, &read_start, &read_count, &num_edges_on_gather_set_cells[0] );
    1738                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read nEdgesOnCell data" );
    1739                 :            :     success = NCFUNC( end_indep_data )( _fileId );
    1740                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to end independent I/O mode" );
    1741                 :            : #else
    1742                 :            :     success =
    1743 [ #  # ][ #  # ]:          0 :         NCFUNCG( _vara_int )( _fileId, nEdgesOnCellVarId, &read_start, &read_count, &num_edges_on_gather_set_cells[0] );
    1744 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read nEdgesOnCell data" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1745                 :            : #endif
    1746                 :            : 
    1747                 :            :     // Create gather set cells
    1748                 :            :     EntityHandle start_element;
    1749                 :          0 :     EntityHandle* conn_arr_gather_set_cells = NULL;
    1750                 :            :     // Don't need to specify allocation number here, because we know enough cells were created
    1751                 :            :     // before
    1752                 :            :     ErrorCode rval = _readNC->readMeshIface->get_element_connect( nCells, maxEdgesPerCell, MBPOLYGON, 0, start_element,
    1753 [ #  # ][ #  # ]:          0 :                                                                   conn_arr_gather_set_cells );MB_CHK_SET_ERR( rval, "Failed to create gather set cells" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1754                 :            : 
    1755                 :            :     // Add cells to the gather set
    1756         [ #  # ]:          0 :     Range gather_set_cells_range( start_element, start_element + nCells - 1 );
    1757 [ #  # ][ #  # ]:          0 :     rval = mbImpl->add_entities( gather_set, gather_set_cells_range );MB_CHK_SET_ERR( rval, "Failed to add cells to the gather set" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1758                 :            : 
    1759                 :            :     // Read vertices on each gather set cell (connectivity)
    1760                 :            :     int verticesOnCellVarId;
    1761         [ #  # ]:          0 :     success = NCFUNC( inq_varid )( _fileId, "verticesOnCell", &verticesOnCellVarId );
    1762 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of verticesOnCell" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1763                 :            :     // Utilize the memory storage pointed by conn_arr_gather_set_cells
    1764                 :          0 :     int* vertices_on_gather_set_cells = (int*)conn_arr_gather_set_cells;
    1765                 :          0 :     NCDF_SIZE read_starts[2]          = { 0, 0 };
    1766                 :          0 :     NCDF_SIZE read_counts[2] = { static_cast< NCDF_SIZE >( nCells ), static_cast< NCDF_SIZE >( maxEdgesPerCell ) };
    1767                 :            : #ifdef MOAB_HAVE_PNETCDF
    1768                 :            :     // Enter independent I/O mode, since this read is only for the gather processor
    1769                 :            :     success = NCFUNC( begin_indep_data )( _fileId );
    1770                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to begin independent I/O mode" );
    1771                 :            :     success =
    1772                 :            :         NCFUNCG( _vara_int )( _fileId, verticesOnCellVarId, read_starts, read_counts, vertices_on_gather_set_cells );
    1773                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read verticesOnCell data" );
    1774                 :            :     success = NCFUNC( end_indep_data )( _fileId );
    1775                 :            :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to end independent I/O mode" );
    1776                 :            : #else
    1777                 :            :     success =
    1778         [ #  # ]:          0 :         NCFUNCG( _vara_int )( _fileId, verticesOnCellVarId, read_starts, read_counts, vertices_on_gather_set_cells );
    1779 [ #  # ][ #  # ]:          0 :     if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read verticesOnCell data" );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1780                 :            : #endif
    1781                 :            : 
    1782                 :            :     // Correct gather set cell vertices array in the same way as local cell vertices array,
    1783                 :            :     // replace the padded vertices with the last vertices in the corresponding cells
    1784         [ #  # ]:          0 :     for( int gather_set_cell_idx = 0; gather_set_cell_idx < nCells; gather_set_cell_idx++ )
    1785                 :            :     {
    1786         [ #  # ]:          0 :         int num_edges                  = num_edges_on_gather_set_cells[gather_set_cell_idx];
    1787                 :          0 :         int idx_in_gather_set_vert_arr = gather_set_cell_idx * maxEdgesPerCell;
    1788                 :          0 :         int last_vert_idx              = vertices_on_gather_set_cells[idx_in_gather_set_vert_arr + num_edges - 1];
    1789         [ #  # ]:          0 :         for( int i = num_edges; i < maxEdgesPerCell; i++ )
    1790                 :          0 :             vertices_on_gather_set_cells[idx_in_gather_set_vert_arr + i] = last_vert_idx;
    1791                 :            :     }
    1792                 :            : 
    1793                 :            :     // Populate connectivity data for gather set cells
    1794                 :            :     // Convert in-place from int (stored in the first half) to EntityHandle
    1795                 :            :     // Reading backward is the trick
    1796         [ #  # ]:          0 :     for( int cell_vert = nCells * maxEdgesPerCell - 1; cell_vert >= 0; cell_vert-- )
    1797                 :            :     {
    1798                 :          0 :         int gather_set_vert_idx = vertices_on_gather_set_cells[cell_vert];  // Global vertex index, 1 based
    1799                 :          0 :         gather_set_vert_idx--;                                              // 1 based -> 0 based
    1800                 :            :         // Connectivity array is shifted by where the gather set vertices start
    1801                 :          0 :         conn_arr_gather_set_cells[cell_vert] = gather_set_start_vertex + gather_set_vert_idx;
    1802                 :            :     }
    1803                 :            : 
    1804                 :          0 :     return MB_SUCCESS;
    1805                 :            : }
    1806                 :            : 
    1807 [ +  - ][ +  - ]:        228 : }  // namespace moab

Generated by: LCOV version 1.11