Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
moab::NCHelperHOMME Class Reference

Child helper class for HOMME grid (CAM_SE) More...

#include <NCHelperHOMME.hpp>

+ Inheritance diagram for moab::NCHelperHOMME:
+ Collaboration diagram for moab::NCHelperHOMME:

Public Member Functions

 NCHelperHOMME (ReadNC *readNC, int fileId, const FileOptions &opts, EntityHandle fileSet)
 
- Public Member Functions inherited from moab::UcdNCHelper
 UcdNCHelper (ReadNC *readNC, int fileId, const FileOptions &opts, EntityHandle fileSet)
 
virtual ~UcdNCHelper ()
 
- Public Member Functions inherited from moab::NCHelper
 NCHelper (ReadNC *readNC, int fileId, const FileOptions &opts, EntityHandle fileSet)
 
virtual ~NCHelper ()
 
ErrorCode create_conventional_tags (const std::vector< int > &tstep_nums)
 Create NC conventional tags. More...
 
ErrorCode update_time_tag_vals ()
 Update time tag values if timesteps spread across files. More...
 

Static Public Member Functions

static bool can_read_file (ReadNC *readNC, int fileId)
 
- Static Public Member Functions inherited from moab::NCHelper
static ReadNC::NCFormatType get_nc_format (ReadNC *readNC, int fileId)
 Get appropriate format to read the file. More...
 
static std::string get_default_ncformat_options (ReadNC::NCFormatType format)
 Get appropriate format to read the file. More...
 
static NCHelperget_nc_helper (ReadNC *readNC, int fileId, const FileOptions &opts, EntityHandle fileSet)
 Get appropriate helper instance for ReadNC class. More...
 

Private Member Functions

virtual ErrorCode init_mesh_vals ()
 Implementation of NCHelper::init_mesh_vals() More...
 
virtual ErrorCode check_existing_mesh ()
 Implementation of NCHelper::check_existing_mesh() More...
 
virtual ErrorCode create_mesh (Range &faces)
 Implementation of NCHelper::create_mesh() More...
 
virtual std::string get_mesh_type_name ()
 Implementation of NCHelper::get_mesh_type_name() More...
 
virtual ErrorCode read_ucd_variables_to_nonset_allocate (std::vector< ReadNC::VarData > &vdatas, std::vector< int > &tstep_nums)
 Implementation of UcdNCHelper::read_ucd_variables_to_nonset_allocate() More...
 
virtual ErrorCode read_ucd_variables_to_nonset (std::vector< ReadNC::VarData > &vdatas, std::vector< int > &tstep_nums)
 Implementation of UcdNCHelper::read_ucd_variables_to_nonset() More...
 

Private Attributes

int _spectralOrder
 
int connectId
 
bool isConnFile
 

Additional Inherited Members

- Protected Member Functions inherited from moab::UcdNCHelper
template<typename T >
void kji_to_jik_stride (size_t, size_t nj, size_t nk, void *dest, T *source, Range &localGid)
 This version takes as input the moab range, from which we actually need just the size of each sequence, for a proper transpose of the data. More...
 
- Protected Member Functions inherited from moab::NCHelper
ErrorCode read_variables_setup (std::vector< std::string > &var_names, std::vector< int > &tstep_nums, std::vector< ReadNC::VarData > &vdatas, std::vector< ReadNC::VarData > &vsetdatas)
 Separate set and non-set variables (common to scd mesh and ucd mesh) More...
 
ErrorCode read_variables_to_set (std::vector< ReadNC::VarData > &vdatas, std::vector< int > &tstep_nums)
 Read set variables (common to scd mesh and ucd mesh) More...
 
ErrorCode read_coordinate (const char *var_name, int lmin, int lmax, std::vector< double > &cvals)
 
ErrorCode get_tag_to_set (ReadNC::VarData &var_data, int tstep_num, Tag &tagh)
 
ErrorCode get_tag_to_nonset (ReadNC::VarData &var_data, int tstep_num, Tag &tagh, int num_lev)
 
ErrorCode create_attrib_string (const std::map< std::string, ReadNC::AttData > &attMap, std::string &attString, std::vector< int > &attLen)
 Create a character string attString of attMap. with '\0' terminating each attribute name, ';' separating the data type and value, and ';' separating one name/data type/value from the next'. attLen stores the end position for each name/data type/ value. More...
 
ErrorCode create_dummy_variables ()
 For a dimension that does not have a corresponding coordinate variable (e.g. ncol for HOMME), create a dummy variable with a sparse tag to store the dimension length. More...
 
- Protected Attributes inherited from moab::UcdNCHelper
int nCells
 Dimensions of global grid in file. More...
 
int nEdges
 
int nVertices
 
int nLocalCells
 Dimensions of my local part of grid. More...
 
int nLocalEdges
 
int nLocalVertices
 
std::vector< double > xVertVals
 Coordinate values for vertices. More...
 
std::vector< double > yVertVals
 
std::vector< double > zVertVals
 
int cDim
 Dimension numbers for nCells, nEdges and nVertices. More...
 
int eDim
 
int vDim
 
Range localGidCells
 Local global ID for cells, edges and vertices. More...
 
Range localGidEdges
 
Range localGidVerts
 
- Protected Attributes inherited from moab::NCHelper
ReadNC_readNC
 Allow NCHelper to directly access members of ReadNC. More...
 
int _fileId
 Cache some information from ReadNC. More...
 
const FileOptions_opts
 
EntityHandle _fileSet
 
int nTimeSteps
 Dimensions of time and level. More...
 
int nLevels
 
std::vector< double > tVals
 Values for time and level. More...
 
std::vector< double > levVals
 
int tDim
 Dimension numbers for time and level. More...
 
int levDim
 
std::set< std::string > ignoredVarNames
 Ignored variables. More...
 
std::set< std::string > dummyVarNames
 Dummy variables. More...
 

Detailed Description

Child helper class for HOMME grid (CAM_SE)

Definition at line 18 of file NCHelperHOMME.hpp.

Constructor & Destructor Documentation

◆ NCHelperHOMME()

moab::NCHelperHOMME::NCHelperHOMME ( ReadNC readNC,
int  fileId,
const FileOptions opts,
EntityHandle  fileSet 
)

Definition at line 11 of file NCHelperHOMME.cpp.

12  : UcdNCHelper( readNC, fileId, opts, fileSet ), _spectralOrder( -1 ), connectId( -1 ), isConnFile( false )
13 {
14  // Calculate spectral order
15  std::map< std::string, ReadNC::AttData >::iterator attIt = readNC->globalAtts.find( "np" );
16  if( attIt != readNC->globalAtts.end() )
17  {
18  int success = NCFUNC( get_att_int )( readNC->fileId, attIt->second.attVarId, attIt->second.attName.c_str(),
19  &_spectralOrder );
20  if( 0 == success ) _spectralOrder--; // Spectral order is one less than np
21  }
22  else
23  {
24  // As can_read_file() returns true and there is no global attribute "np", it should be a
25  // connectivity file
26  isConnFile = true;
27  _spectralOrder = 3; // Assume np is 4
28  }
29 }

References _spectralOrder, moab::ReadNC::fileId, moab::ReadNC::globalAtts, isConnFile, and NCFUNC.

Member Function Documentation

◆ can_read_file()

bool moab::NCHelperHOMME::can_read_file ( ReadNC readNC,
int  fileId 
)
static

Definition at line 31 of file NCHelperHOMME.cpp.

32 {
33  // If global attribute "np" exists then it should be the HOMME grid
34  if( readNC->globalAtts.find( "np" ) != readNC->globalAtts.end() )
35  {
36  // Make sure it is CAM grid
37  std::map< std::string, ReadNC::AttData >::iterator attIt = readNC->globalAtts.find( "source" );
38  if( attIt == readNC->globalAtts.end() ) return false;
39  unsigned int sz = attIt->second.attLen;
40  std::string att_data;
41  att_data.resize( sz + 1 );
42  att_data[sz] = '\000';
43  int success =
44  NCFUNC( get_att_text )( fileId, attIt->second.attVarId, attIt->second.attName.c_str(), &att_data[0] );
45  if( success ) return false;
46  if( att_data.find( "CAM" ) == std::string::npos ) return false;
47 
48  return true;
49  }
50  else
51  {
52  // If dimension names "ncol" AND "ncorners" AND "ncells" exist, then it should be the HOMME
53  // connectivity file In this case, the mesh can still be created
54  std::vector< std::string >& dimNames = readNC->dimNames;
55  if( ( std::find( dimNames.begin(), dimNames.end(), std::string( "ncol" ) ) != dimNames.end() ) &&
56  ( std::find( dimNames.begin(), dimNames.end(), std::string( "ncorners" ) ) != dimNames.end() ) &&
57  ( std::find( dimNames.begin(), dimNames.end(), std::string( "ncells" ) ) != dimNames.end() ) )
58  return true;
59  }
60 
61  return false;
62 }

References moab::ReadNC::dimNames, moab::ReadNC::globalAtts, and NCFUNC.

Referenced by moab::NCHelper::get_nc_format().

◆ check_existing_mesh()

ErrorCode moab::NCHelperHOMME::check_existing_mesh ( )
privatevirtual

Implementation of NCHelper::check_existing_mesh()

Implements moab::NCHelper.

Definition at line 222 of file NCHelperHOMME.cpp.

223 {
224  Interface*& mbImpl = _readNC->mbImpl;
225  Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
226  bool& noMesh = _readNC->noMesh;
227 
228  if( noMesh && localGidVerts.empty() )
229  {
230  // We need to populate localGidVerts range with the gids of vertices from current file set
231  // localGidVerts is important in reading the variable data into the nodes
232  // Also, for our purposes, localGidVerts is truly the GLOBAL_ID tag data, not other
233  // file_id tags that could get passed around in other scenarios for parallel reading
234 
235  // Get all vertices from current file set (it is the input set in no_mesh scenario)
236  Range local_verts;
237  MB_CHK_SET_ERR( mbImpl->get_entities_by_dimension( _fileSet, 0, local_verts ),
238  "Trouble getting local vertices in current file set" );
239 
240  if( !local_verts.empty() )
241  {
242  std::vector< int > gids( local_verts.size() );
243 
244  // !IMPORTANT : this has to be the GLOBAL_ID tag
245  MB_CHK_SET_ERR( mbImpl->tag_get_data( mGlobalIdTag, local_verts, &gids[0] ),
246  "Trouble getting local gid values of vertices" );
247 
248  // Restore localGidVerts
249  std::copy( gids.rbegin(), gids.rend(), range_inserter( localGidVerts ) );
251  }
252  }
253 
254  return MB_SUCCESS;
255 }

References moab::NCHelper::_fileSet, moab::NCHelper::_readNC, moab::Range::empty(), moab::Interface::get_entities_by_dimension(), moab::UcdNCHelper::localGidVerts, MB_CHK_SET_ERR, MB_SUCCESS, moab::ReadNC::mbImpl, moab::ReadNC::mGlobalIdTag, moab::UcdNCHelper::nLocalVertices, moab::ReadNC::noMesh, moab::Range::size(), and moab::Interface::tag_get_data().

◆ create_mesh()

ErrorCode moab::NCHelperHOMME::create_mesh ( Range faces)
privatevirtual

Implementation of NCHelper::create_mesh()

Implements moab::NCHelper.

Definition at line 257 of file NCHelperHOMME.cpp.

258 {
259  Interface*& mbImpl = _readNC->mbImpl;
260  std::string& fileName = _readNC->fileName;
261  Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
262  const Tag*& mpFileIdTag = _readNC->mpFileIdTag;
263  DebugOutput& dbgOut = _readNC->dbgOut;
264  bool& spectralMesh = _readNC->spectralMesh;
265  int& gatherSetRank = _readNC->gatherSetRank;
266  int& trivialPartitionShift = _readNC->trivialPartitionShift;
267 
268  int rank = 0;
269  int procs = 1;
270 #ifdef MOAB_HAVE_MPI
271  bool& isParallel = _readNC->isParallel;
272  if( isParallel )
273  {
274  ParallelComm*& myPcomm = _readNC->myPcomm;
275  rank = myPcomm->proc_config().proc_rank();
276  procs = myPcomm->proc_config().proc_size();
277  }
278 #endif
279 
280  int success = 0;
281 
282  // Need to get/read connectivity data before creating elements
283  std::string conn_fname;
284 
285  if( isConnFile )
286  {
287  // Connectivity file has already been read
289  }
290  else
291  {
292  // Try to open the connectivity file through CONN option, if used
293  if( MB_SUCCESS != _opts.get_str_option( "CONN", conn_fname ) )
294  {
295  // Default convention for reading HOMME is a file HommeMapping.nc in same dir as data
296  // file
297  conn_fname = std::string( fileName );
298  size_t idx = conn_fname.find_last_of( "/" );
299  if( idx != std::string::npos )
300  conn_fname = conn_fname.substr( 0, idx ).append( "/HommeMapping.nc" );
301  else
302  conn_fname = "HommeMapping.nc";
303  }
304  // Format-aware open via the runtime dispatch layer. Mirrors the
305  // open path in ReadNC::load_file — probe the on-disk format on
306  // rank 0, broadcast, pick the backend, then dispatch.
307  int connFormat = NCFMT_UNKNOWN;
308 #ifdef MOAB_HAVE_MPI
309  if( isParallel )
310  {
311  ParallelComm*& myPcomm = _readNC->myPcomm;
312  int rank = myPcomm->proc_config().proc_rank();
313  if( rank == 0 ) connFormat = mbnc_detect_format( conn_fname.c_str() );
314  MPI_Bcast( &connFormat, 1, MPI_INT, 0, myPcomm->proc_config().proc_comm() );
315  }
316  else
317 #endif
318  {
319  connFormat = mbnc_detect_format( conn_fname.c_str() );
320  }
321 
322 #ifdef MOAB_HAVE_MPI
323  const int conn_mpi_size = isParallel ? _readNC->myPcomm->proc_config().proc_size() : 1;
324 #else
325  const int conn_mpi_size = 1;
326 #endif
327 
328  const NcBackend connBackend = mbnc_choose_backend_for_read( connFormat, conn_mpi_size );
329  if( connBackend == NCB_NONE )
330  {
331  MB_SET_ERR( MB_FAILURE, "Cannot find a compatible reader for HOMME connectivity file '"
332  << conn_fname << "'" );
333  }
334 
335 #ifdef MOAB_HAVE_MPI
336  if( connBackend == NCB_NETCDF_SERIAL || conn_mpi_size == 1 )
337  {
338  success = mbnc_open( conn_fname.c_str(), 0, &connectId );
339  }
340  else
341  {
342  ParallelComm*& myPcomm = _readNC->myPcomm;
343  success = mbnc_open_par( connBackend, myPcomm->proc_config().proc_comm(), MPI_INFO_NULL,
344  conn_fname.c_str(), 0, &connectId );
345  }
346 #else
347  success = mbnc_open( conn_fname.c_str(), 0, &connectId );
348 #endif
349  if( success ) MB_SET_ERR( MB_FAILURE, "Failed on open" );
350  }
351 
352  std::vector< std::string > conn_names;
353  std::vector< int > conn_vals;
354  MB_CHK_SET_ERR( _readNC->get_dimensions( connectId, conn_names, conn_vals ),
355  "Failed to get dimensions for connectivity" );
356 
357  // Read connectivity into temporary variable
358  int num_fine_quads = 0;
359  int num_coarse_quads = 0;
360  int start_idx = 0;
361  std::vector< std::string >::iterator vit;
362  int idx = 0;
363  if( ( vit = std::find( conn_names.begin(), conn_names.end(), "ncells" ) ) != conn_names.end() )
364  idx = vit - conn_names.begin();
365  else if( ( vit = std::find( conn_names.begin(), conn_names.end(), "ncenters" ) ) != conn_names.end() )
366  idx = vit - conn_names.begin();
367  else
368  {
369  MB_SET_ERR( MB_FAILURE, "Failed to get number of quads" );
370  }
371  int num_quads = conn_vals[idx];
372  if( !isConnFile && num_quads != nCells )
373  {
374  dbgOut.tprintf( 1,
375  "Warning: number of quads from %s and cells from %s are inconsistent; "
376  "num_quads = %d, nCells = %d.\n",
377  conn_fname.c_str(), fileName.c_str(), num_quads, nCells );
378  }
379 
380  // Get the connectivity into tmp_conn2 and permute into tmp_conn
381  int cornerVarId;
382  success = NCFUNC( inq_varid )( connectId, "element_corners", &cornerVarId );
383  if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of 'element_corners'" );
384  NCDF_SIZE tmp_starts[2] = { 0, 0 };
385  NCDF_SIZE tmp_counts[2] = { 4, static_cast< NCDF_SIZE >( num_quads ) };
386  std::vector< int > tmp_conn( 4 * num_quads ), tmp_conn2( 4 * num_quads );
387  success = NCFUNCAG( _vara_int )( connectId, cornerVarId, tmp_starts, tmp_counts, &tmp_conn2[0] );
388  if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get temporary connectivity" );
389  if( isConnFile )
390  {
391  // This data/connectivity file will be closed later in ReadNC::load_file()
392  }
393  else
394  {
395  success = NCFUNC( close )( connectId );
396  if( success ) MB_SET_ERR( MB_FAILURE, "Failed on close" );
397  }
398  // Permute the connectivity
399  for( int i = 0; i < num_quads; i++ )
400  {
401  tmp_conn[4 * i] = tmp_conn2[i];
402  tmp_conn[4 * i + 1] = tmp_conn2[i + 1 * num_quads];
403  tmp_conn[4 * i + 2] = tmp_conn2[i + 2 * num_quads];
404  tmp_conn[4 * i + 3] = tmp_conn2[i + 3 * num_quads];
405  }
406 
407  // Need to know whether we'll be creating gather mesh later, to make sure
408  // we allocate enough space in one shot
409  bool create_gathers = false;
410  if( rank == gatherSetRank ) create_gathers = true;
411 
412  // Shift rank to obtain a rotated trivial partition
413  int shifted_rank = rank;
414  if( procs >= 2 && trivialPartitionShift > 0 ) shifted_rank = ( rank + trivialPartitionShift ) % procs;
415 
416  // Compute the number of local quads, accounting for coarse or fine representation
417  // spectral_unit is the # fine quads per coarse quad, or spectralOrder^2
418  int spectral_unit = ( spectralMesh ? _spectralOrder * _spectralOrder : 1 );
419  // num_coarse_quads is the number of quads instantiated in MOAB; if !spectralMesh,
420  // num_coarse_quads = num_fine_quads
421  num_coarse_quads = int( std::floor( 1.0 * num_quads / ( spectral_unit * procs ) ) );
422  // start_idx is the starting index in the HommeMapping connectivity list for this proc, before
423  // converting to coarse quad representation
424  start_idx = 4 * shifted_rank * num_coarse_quads * spectral_unit;
425  // iextra = # coarse quads extra after equal split over procs
426  int iextra = num_quads % ( procs * spectral_unit );
427  if( shifted_rank < iextra ) num_coarse_quads++;
428  start_idx += 4 * spectral_unit * std::min( shifted_rank, iextra );
429  // num_fine_quads is the number of quads in the connectivity list in HommeMapping file assigned
430  // to this proc
431  num_fine_quads = spectral_unit * num_coarse_quads;
432 
433  // Now create num_coarse_quads
434  EntityHandle* conn_arr;
435  EntityHandle start_vertex;
436  Range tmp_range;
437 
438  // Read connectivity into that space
439  EntityHandle* sv_ptr = NULL;
440  EntityHandle start_quad;
441  SpectralMeshTool smt( mbImpl, _spectralOrder );
442  if( !spectralMesh )
443  {
445  num_coarse_quads, 4, MBQUAD, 0, start_quad, conn_arr,
446  // Might have to create gather mesh later
447  ( create_gathers ? num_coarse_quads + num_quads : num_coarse_quads ) ),
448  "Failed to create local quads" );
449  tmp_range.insert( start_quad, start_quad + num_coarse_quads - 1 );
450  int* tmp_conn_end = ( &tmp_conn[start_idx + 4 * num_fine_quads - 1] ) + 1;
451  std::copy( &tmp_conn[start_idx], tmp_conn_end, conn_arr );
452  std::copy( conn_arr, conn_arr + 4 * num_fine_quads, range_inserter( localGidVerts ) );
453  }
454  else
455  {
456  MB_CHK_SET_ERR( smt.create_spectral_elems( &tmp_conn[0], num_fine_quads, 2, tmp_range, start_idx,
457  &localGidVerts ),
458  "Failed to create spectral elements" );
459  int count, v_per_e;
460  MB_CHK_SET_ERR( mbImpl->connect_iterate( tmp_range.begin(), tmp_range.end(), conn_arr, v_per_e, count ),
461  "Failed to get connectivity of spectral elements" );
462  MB_CHK_SET_ERR( mbImpl->tag_iterate( smt.spectral_vertices_tag( true ), tmp_range.begin(), tmp_range.end(),
463  count, (void*&)sv_ptr ),
464  "Failed to get fine connectivity of spectral elements" );
465  }
466 
467  // Create vertices
469  std::vector< double* > arrays;
471  _readNC->readMeshIface->get_node_coords( 3, nLocalVertices, 0, start_vertex, arrays,
472  // Might have to create gather mesh later
473  ( create_gathers ? nLocalVertices + nVertices : nLocalVertices ) ),
474  "Failed to create local vertices" );
475 
476  // Set vertex coordinates
477  Range::iterator rit;
478  double* xptr = arrays[0];
479  double* yptr = arrays[1];
480  double* zptr = arrays[2];
481  int i;
482  for( i = 0, rit = localGidVerts.begin(); i < nLocalVertices; i++, ++rit )
483  {
484  assert( *rit < xVertVals.size() + 1 );
485  xptr[i] = xVertVals[( *rit ) - 1]; // lon
486  yptr[i] = yVertVals[( *rit ) - 1]; // lat
487  }
488 
489  // Convert lon/lat/rad to x/y/z
490  const double pideg = acos( -1.0 ) / 180.0;
491  double rad = ( isConnFile ) ? 8000.0 : 8000.0 + levVals[0];
492  for( i = 0; i < nLocalVertices; i++ )
493  {
494  double cosphi = cos( pideg * yptr[i] );
495  double zmult = sin( pideg * yptr[i] );
496  double xmult = cosphi * cos( xptr[i] * pideg );
497  double ymult = cosphi * sin( xptr[i] * pideg );
498  xptr[i] = rad * xmult;
499  yptr[i] = rad * ymult;
500  zptr[i] = rad * zmult;
501  }
502 
503  // Get ptr to gid memory for vertices
504  Range vert_range( start_vertex, start_vertex + nLocalVertices - 1 );
505  void* data;
506  int count;
507  MB_CHK_SET_ERR( mbImpl->tag_iterate( mGlobalIdTag, vert_range.begin(), vert_range.end(), count, data ),
508  "Failed to iterate global id tag on local vertices" );
509  assert( count == nLocalVertices );
510  int* gid_data = (int*)data;
511  std::copy( localGidVerts.begin(), localGidVerts.end(), gid_data );
512 
513  // Duplicate global id data, which will be used to resolve sharing
514  if( mpFileIdTag )
515  {
516  MB_CHK_SET_ERR( mbImpl->tag_iterate( *mpFileIdTag, vert_range.begin(), vert_range.end(), count, data ),
517  "Failed to iterate file id tag on local vertices" );
518  assert( count == nLocalVertices );
519  int bytes_per_tag = 4;
520  MB_CHK_SET_ERR( mbImpl->tag_get_bytes( *mpFileIdTag, bytes_per_tag ),
521  "Can't get number of bytes for file id tag" );
522  if( 4 == bytes_per_tag )
523  {
524  gid_data = (int*)data;
525  std::copy( localGidVerts.begin(), localGidVerts.end(), gid_data );
526  }
527  else if( 8 == bytes_per_tag )
528  { // Should be a handle tag on 64 bit machine?
529  long* handle_tag_data = (long*)data;
530  std::copy( localGidVerts.begin(), localGidVerts.end(), handle_tag_data );
531  }
532  }
533 
534  // Create map from file ids to vertex handles, used later to set connectivity
535  std::map< EntityHandle, EntityHandle > vert_handles;
536  for( rit = localGidVerts.begin(), i = 0; rit != localGidVerts.end(); ++rit, i++ )
537  vert_handles[*rit] = start_vertex + i;
538 
539  // Compute proper handles in connectivity using offset
540  for( int q = 0; q < 4 * num_coarse_quads; q++ )
541  {
542  conn_arr[q] = vert_handles[conn_arr[q]];
543  assert( conn_arr[q] );
544  }
545  if( spectralMesh )
546  {
547  int verts_per_quad = ( _spectralOrder + 1 ) * ( _spectralOrder + 1 );
548  for( int q = 0; q < verts_per_quad * num_coarse_quads; q++ )
549  {
550  sv_ptr[q] = vert_handles[sv_ptr[q]];
551  assert( sv_ptr[q] );
552  }
553  }
554 
555  // Add new vertices and quads to current file set
556  faces.merge( tmp_range );
557  tmp_range.insert( start_vertex, start_vertex + nLocalVertices - 1 );
558  MB_CHK_SET_ERR( mbImpl->add_entities( _fileSet, tmp_range ),
559  "Failed to add new vertices and quads to current file set" );
560 
561  // Mark the set with the spectral order
562  Tag sporder;
563  MB_CHK_SET_ERR( mbImpl->tag_get_handle( "SPECTRAL_ORDER", 1, MB_TYPE_INTEGER, sporder,
565  "Trouble creating SPECTRAL_ORDER tag" );
566  MB_CHK_SET_ERR( mbImpl->tag_set_data( sporder, &_fileSet, 1, &_spectralOrder ),
567  "Trouble setting data to SPECTRAL_ORDER tag" );
568 
569  if( create_gathers )
570  {
571  EntityHandle gather_set;
572  MB_CHK_SET_ERR( _readNC->readMeshIface->create_gather_set( gather_set ), "Failed to create gather set" );
573 
574  // Create vertices
575  arrays.clear();
576  // Don't need to specify allocation number here, because we know enough verts were created
577  // before
578  MB_CHK_SET_ERR( _readNC->readMeshIface->get_node_coords( 3, nVertices, 0, start_vertex, arrays ),
579  "Failed to create gather set vertices" );
580 
581  xptr = arrays[0];
582  yptr = arrays[1];
583  zptr = arrays[2];
584  for( i = 0; i < nVertices; i++ )
585  {
586  double cosphi = cos( pideg * yVertVals[i] );
587  double zmult = sin( pideg * yVertVals[i] );
588  double xmult = cosphi * cos( xVertVals[i] * pideg );
589  double ymult = cosphi * sin( xVertVals[i] * pideg );
590  xptr[i] = rad * xmult;
591  yptr[i] = rad * ymult;
592  zptr[i] = rad * zmult;
593  }
594 
595  // Get ptr to gid memory for vertices
596  Range gather_set_verts_range( start_vertex, start_vertex + nVertices - 1 );
597  MB_CHK_SET_ERR( mbImpl->tag_iterate( mGlobalIdTag, gather_set_verts_range.begin(), gather_set_verts_range.end(),
598  count, data ),
599  "Failed to iterate global id tag on gather set vertices" );
600  assert( count == nVertices );
601  gid_data = (int*)data;
602  for( int j = 1; j <= nVertices; j++ )
603  gid_data[j - 1] = j;
604  // Set the file id tag too, it should be bigger something not interfering with global id
605  if( mpFileIdTag )
606  {
607  MB_CHK_SET_ERR( mbImpl->tag_iterate( *mpFileIdTag, gather_set_verts_range.begin(),
608  gather_set_verts_range.end(), count, data ),
609  "Failed to iterate file id tag on gather set vertices" );
610  assert( count == nVertices );
611  int bytes_per_tag = 4;
612  MB_CHK_SET_ERR( mbImpl->tag_get_bytes( *mpFileIdTag, bytes_per_tag ),
613  "Can't get number of bytes for file id tag" );
614  if( 4 == bytes_per_tag )
615  {
616  gid_data = (int*)data;
617  for( int j = 1; j <= nVertices; j++ )
618  gid_data[j - 1] = nVertices + j; // Bigger than global id tag
619  }
620  else if( 8 == bytes_per_tag )
621  { // Should be a handle tag on 64 bit machine?
622  long* handle_tag_data = (long*)data;
623  for( int j = 1; j <= nVertices; j++ )
624  handle_tag_data[j - 1] = nVertices + j; // Bigger than global id tag
625  }
626  }
627 
628  MB_CHK_SET_ERR( mbImpl->add_entities( gather_set, gather_set_verts_range ),
629  "Failed to add vertices to the gather set" );
630 
631  // Create quads
632  Range gather_set_quads_range;
633  // Don't need to specify allocation number here, because we know enough quads were created
634  // before
635  MB_CHK_SET_ERR( _readNC->readMeshIface->get_element_connect( num_quads, 4, MBQUAD, 0, start_quad, conn_arr ),
636  "Failed to create gather set quads" );
637  gather_set_quads_range.insert( start_quad, start_quad + num_quads - 1 );
638  int* tmp_conn_end = ( &tmp_conn[4 * num_quads - 1] ) + 1;
639  std::copy( &tmp_conn[0], tmp_conn_end, conn_arr );
640  for( i = 0; i != 4 * num_quads; i++ )
641  conn_arr[i] += start_vertex - 1; // Connectivity array is shifted by where the gather verts start
642  MB_CHK_SET_ERR( mbImpl->add_entities( gather_set, gather_set_quads_range ),
643  "Failed to add quads to the gather set" );
644  }
645 
646  return MB_SUCCESS;
647 }

References moab::NCHelper::_fileSet, moab::NCHelper::_opts, moab::NCHelper::_readNC, _spectralOrder, moab::Interface::add_entities(), moab::Range::begin(), moab::Interface::connect_iterate(), connectId, moab::ReadUtilIface::create_gather_set(), moab::SpectralMeshTool::create_spectral_elems(), moab::ReadNC::dbgOut, moab::Range::end(), moab::ReadNC::fileId, moab::ReadNC::fileName, moab::ReadNC::gatherSetRank, moab::ReadNC::get_dimensions(), moab::ReadUtilIface::get_element_connect(), moab::ReadUtilIface::get_node_coords(), moab::FileOptions::get_str_option(), moab::Range::insert(), isConnFile, moab::ReadNC::isParallel, moab::NCHelper::levVals, moab::UcdNCHelper::localGidVerts, MB_CHK_SET_ERR, MB_SET_ERR, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_SPARSE, MB_TYPE_INTEGER, moab::ReadNC::mbImpl, moab::mbnc_choose_backend_for_read(), moab::mbnc_detect_format(), moab::mbnc_open(), MBQUAD, moab::Range::merge(), moab::ReadNC::mGlobalIdTag, moab::ReadNC::mpFileIdTag, moab::NCB_NETCDF_SERIAL, moab::NCB_NONE, NCDF_SIZE, moab::UcdNCHelper::nCells, moab::NCFMT_UNKNOWN, NCFUNC, NCFUNCAG, moab::UcdNCHelper::nLocalVertices, moab::UcdNCHelper::nVertices, moab::pideg, moab::ProcConfig::proc_comm(), moab::ParallelComm::proc_config(), moab::ProcConfig::proc_rank(), moab::ProcConfig::proc_size(), moab::ReadNC::readMeshIface, moab::Range::size(), moab::SpectralMeshTool::spectral_vertices_tag(), moab::ReadNC::spectralMesh, moab::Interface::tag_get_bytes(), moab::Interface::tag_get_handle(), moab::Interface::tag_iterate(), moab::Interface::tag_set_data(), moab::DebugOutput::tprintf(), moab::ReadNC::trivialPartitionShift, moab::UcdNCHelper::xVertVals, and moab::UcdNCHelper::yVertVals.

◆ get_mesh_type_name()

virtual std::string moab::NCHelperHOMME::get_mesh_type_name ( )
inlineprivatevirtual

Implementation of NCHelper::get_mesh_type_name()

Implements moab::NCHelper.

Definition at line 32 of file NCHelperHOMME.hpp.

33  {
34  return "CAM_SE";
35  }

◆ init_mesh_vals()

ErrorCode moab::NCHelperHOMME::init_mesh_vals ( )
privatevirtual

Implementation of NCHelper::init_mesh_vals()

Implements moab::NCHelper.

Definition at line 64 of file NCHelperHOMME.cpp.

65 {
66  std::vector< std::string >& dimNames = _readNC->dimNames;
67  std::vector< int >& dimLens = _readNC->dimLens;
68  std::map< std::string, ReadNC::VarData >& varInfo = _readNC->varInfo;
69 
70  unsigned int idx;
71  std::vector< std::string >::iterator vit;
72 
73  // Look for time dimension
74  if( isConnFile )
75  {
76  // Connectivity file might not have time dimension
77  }
78  else
79  {
80  if( ( vit = std::find( dimNames.begin(), dimNames.end(), "time" ) ) != dimNames.end() )
81  idx = vit - dimNames.begin();
82  else if( ( vit = std::find( dimNames.begin(), dimNames.end(), "t" ) ) != dimNames.end() )
83  idx = vit - dimNames.begin();
84  else
85  {
86  MB_SET_ERR( MB_FAILURE, "Couldn't find 'time' or 't' dimension" );
87  }
88  tDim = idx;
89  nTimeSteps = dimLens[idx];
90  }
91 
92  // Get number of vertices (labeled as number of columns)
93  if( ( vit = std::find( dimNames.begin(), dimNames.end(), "ncol" ) ) != dimNames.end() )
94  idx = vit - dimNames.begin();
95  else
96  {
97  MB_SET_ERR( MB_FAILURE, "Couldn't find 'ncol' dimension" );
98  }
99  vDim = idx;
100  nVertices = dimLens[idx];
101 
102  // Set number of cells
103  nCells = nVertices - 2;
104 
105  // Get number of levels
106  if( isConnFile )
107  {
108  // Connectivity file might not have level dimension
109  }
110  else
111  {
112  if( ( vit = std::find( dimNames.begin(), dimNames.end(), "lev" ) ) != dimNames.end() )
113  idx = vit - dimNames.begin();
114  else if( ( vit = std::find( dimNames.begin(), dimNames.end(), "ilev" ) ) != dimNames.end() )
115  idx = vit - dimNames.begin();
116  else
117  {
118  MB_SET_ERR( MB_FAILURE, "Couldn't find 'lev' or 'ilev' dimension" );
119  }
120  levDim = idx;
121  nLevels = dimLens[idx];
122  }
123 
124  // Store lon values in xVertVals
125  std::map< std::string, ReadNC::VarData >::iterator vmit;
126  if( ( vmit = varInfo.find( "lon" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 )
127  {
128  MB_CHK_SET_ERR( read_coordinate( "lon", 0, nVertices - 1, xVertVals ), "Trouble reading 'lon' variable" );
129  }
130  else
131  {
132  MB_SET_ERR( MB_FAILURE, "Couldn't find 'lon' variable" );
133  }
134 
135  // Store lat values in yVertVals
136  if( ( vmit = varInfo.find( "lat" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 )
137  {
138  MB_CHK_SET_ERR( read_coordinate( "lat", 0, nVertices - 1, yVertVals ), "Trouble reading 'lat' variable" );
139  }
140  else
141  {
142  MB_SET_ERR( MB_FAILURE, "Couldn't find 'lat' variable" );
143  }
144 
145  // Store lev values in levVals
146  if( isConnFile )
147  {
148  // Connectivity file might not have level variable
149  }
150  else
151  {
152  if( ( vmit = varInfo.find( "lev" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 )
153  {
154  MB_CHK_SET_ERR( read_coordinate( "lev", 0, nLevels - 1, levVals ), "Trouble reading 'lev' variable" );
155 
156  // Decide whether down is positive
157  char posval[10] = { 0 };
158  int success = NCFUNC( get_att_text )( _fileId, ( *vmit ).second.varId, "positive", posval );
159  if( 0 == success && !strcmp( posval, "down" ) )
160  {
161  for( std::vector< double >::iterator dvit = levVals.begin(); dvit != levVals.end(); ++dvit )
162  ( *dvit ) *= -1.0;
163  }
164  }
165  else
166  {
167  MB_SET_ERR( MB_FAILURE, "Couldn't find 'lev' variable" );
168  }
169  }
170 
171  // Store time coordinate values in tVals
172  if( isConnFile )
173  {
174  // Connectivity file might not have time variable
175  }
176  else
177  {
178  if( ( vmit = varInfo.find( "time" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 )
179  {
180  MB_CHK_SET_ERR( read_coordinate( "time", 0, nTimeSteps - 1, tVals ), "Trouble reading 'time' variable" );
181  }
182  else if( ( vmit = varInfo.find( "t" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 )
183  {
184  MB_CHK_SET_ERR( read_coordinate( "t", 0, nTimeSteps - 1, tVals ), "Trouble reading 't' variable" );
185  }
186  else
187  {
188  // If expected time variable does not exist, set dummy values to tVals
189  for( int t = 0; t < nTimeSteps; t++ )
190  tVals.push_back( (double)t );
191  }
192  }
193 
194  // For each variable, determine the entity location type and number of levels
195  std::map< std::string, ReadNC::VarData >::iterator mit;
196  for( mit = varInfo.begin(); mit != varInfo.end(); ++mit )
197  {
198  ReadNC::VarData& vd = ( *mit ).second;
199 
200  // Default entLoc is ENTLOCSET
201  if( std::find( vd.varDims.begin(), vd.varDims.end(), tDim ) != vd.varDims.end() )
202  {
203  if( std::find( vd.varDims.begin(), vd.varDims.end(), vDim ) != vd.varDims.end() )
204  vd.entLoc = ReadNC::ENTLOCVERT;
205  }
206 
207  // Default numLev is 0
208  if( std::find( vd.varDims.begin(), vd.varDims.end(), levDim ) != vd.varDims.end() ) vd.numLev = nLevels;
209  }
210 
211  // Hack: create dummy variables for dimensions (like ncol) with no corresponding coordinate
212  // variables
213  MB_CHK_SET_ERR( create_dummy_variables(), "Failed to create dummy variables" );
214 
215  return MB_SUCCESS;
216 }

References moab::NCHelper::_fileId, moab::NCHelper::_readNC, moab::NCHelper::create_dummy_variables(), moab::ReadNC::dimLens, moab::ReadNC::dimNames, moab::ReadNC::VarData::entLoc, moab::ReadNC::ENTLOCVERT, isConnFile, moab::NCHelper::levDim, moab::NCHelper::levVals, MB_CHK_SET_ERR, MB_SET_ERR, MB_SUCCESS, moab::UcdNCHelper::nCells, NCFUNC, moab::NCHelper::nLevels, moab::NCHelper::nTimeSteps, moab::ReadNC::VarData::numLev, moab::UcdNCHelper::nVertices, moab::NCHelper::read_coordinate(), moab::NCHelper::tDim, moab::NCHelper::tVals, moab::ReadNC::VarData::varDims, moab::ReadNC::varInfo, moab::UcdNCHelper::vDim, moab::UcdNCHelper::xVertVals, and moab::UcdNCHelper::yVertVals.

◆ read_ucd_variables_to_nonset()

ErrorCode moab::NCHelperHOMME::read_ucd_variables_to_nonset ( std::vector< ReadNC::VarData > &  vdatas,
std::vector< int > &  tstep_nums 
)
privatevirtual

Implementation of UcdNCHelper::read_ucd_variables_to_nonset()

Implements moab::UcdNCHelper.

Definition at line 838 of file NCHelperHOMME.cpp.

840 {
841  DebugOutput& dbgOut = _readNC->dbgOut;
842 
844  "Trouble allocating space to read non-set variables" );
845 
846  // Finally, read into that space
847  int success;
848  for( unsigned int i = 0; i < vdatas.size(); i++ )
849  {
850  std::size_t sz = vdatas[i].sz;
851 
852  // A typical supported variable: float T(time, lev, ncol)
853  // For tag values, need transpose (lev, ncol) to (ncol, lev)
854  size_t ni = vdatas[i].readCounts[2]; // ncol
855  size_t nj = 1; // Here we should just set nj to 1
856  size_t nk = vdatas[i].readCounts[1]; // lev
857 
858  for( unsigned int t = 0; t < tstep_nums.size(); t++ )
859  {
860  // Tag data for this timestep
861  void* data = vdatas[i].varDatas[t];
862 
863  // Set readStart for each timestep along time dimension
864  vdatas[i].readStarts[0] = tstep_nums[t];
865 
866  switch( vdatas[i].varDataType )
867  {
868  case NC_FLOAT:
869  case NC_DOUBLE: {
870  // Read float as double
871  std::vector< double > tmpdoubledata( sz );
872 
873  // In the case of ucd mesh, and on multiple proc,
874  // we need to read as many times as subranges we have in the
875  // localGidVerts range;
876  // basically, we have to give a different point
877  // for data to start, for every subrange :(
878  size_t indexInDoubleArray = 0;
879  size_t ic = 0;
880  for( Range::pair_iterator pair_iter = localGidVerts.pair_begin();
881  pair_iter != localGidVerts.pair_end(); ++pair_iter, ic++ )
882  {
883  EntityHandle starth = pair_iter->first;
884  EntityHandle endh = pair_iter->second; // Inclusive
885  vdatas[i].readStarts[2] = (NCDF_SIZE)( starth - 1 );
886  vdatas[i].readCounts[2] = (NCDF_SIZE)( endh - starth + 1 );
887 
888  success = NCFUNCAG( _vara_double )( _fileId, vdatas[i].varId, &( vdatas[i].readStarts[0] ),
889  &( vdatas[i].readCounts[0] ),
890  &( tmpdoubledata[indexInDoubleArray] ) );
891  if( success )
892  MB_SET_ERR( MB_FAILURE,
893  "Failed to read double data in a loop for variable " << vdatas[i].varName );
894  // We need to increment the index in double array for the
895  // next subrange
896  indexInDoubleArray += ( endh - starth + 1 ) * 1 * vdatas[i].numLev;
897  }
898  assert( ic == localGidVerts.psize() );
899 
900  if( vdatas[i].numLev > 1 )
901  // Transpose (lev, ncol) to (ncol, lev)
902  kji_to_jik_stride( ni, nj, nk, data, &tmpdoubledata[0], localGidVerts );
903  else
904  {
905  for( std::size_t idx = 0; idx != tmpdoubledata.size(); idx++ )
906  ( (double*)data )[idx] = tmpdoubledata[idx];
907  }
908 
909  break;
910  }
911  default:
912  MB_SET_ERR( MB_FAILURE, "Unexpected data type for variable " << vdatas[i].varName );
913  }
914  }
915  }
916 
917  // Debug output, if requested
918  if( 1 == dbgOut.get_verbosity() )
919  {
920  dbgOut.printf( 1, "Read variables: %s", vdatas.begin()->varName.c_str() );
921  for( unsigned int i = 1; i < vdatas.size(); i++ )
922  dbgOut.printf( 1, ", %s ", vdatas[i].varName.c_str() );
923  dbgOut.tprintf( 1, "\n" );
924  }
925 
926  return MB_SUCCESS;
927 }

References moab::NCHelper::_fileId, moab::NCHelper::_readNC, moab::ReadNC::dbgOut, moab::DebugOutput::get_verbosity(), moab::UcdNCHelper::kji_to_jik_stride(), moab::UcdNCHelper::localGidVerts, MB_CHK_SET_ERR, MB_SET_ERR, MB_SUCCESS, NCDF_SIZE, NCFUNCAG, moab::Range::pair_begin(), moab::Range::pair_end(), moab::DebugOutput::printf(), moab::Range::psize(), read_ucd_variables_to_nonset_allocate(), and moab::DebugOutput::tprintf().

◆ read_ucd_variables_to_nonset_allocate()

ErrorCode moab::NCHelperHOMME::read_ucd_variables_to_nonset_allocate ( std::vector< ReadNC::VarData > &  vdatas,
std::vector< int > &  tstep_nums 
)
privatevirtual

Implementation of UcdNCHelper::read_ucd_variables_to_nonset_allocate()

Implements moab::UcdNCHelper.

Definition at line 649 of file NCHelperHOMME.cpp.

651 {
652  Interface*& mbImpl = _readNC->mbImpl;
653  std::vector< int >& dimLens = _readNC->dimLens;
654  DebugOutput& dbgOut = _readNC->dbgOut;
655 
656  Range* range = NULL;
657 
658  // Get vertices
659  Range verts;
660  MB_CHK_SET_ERR( mbImpl->get_entities_by_dimension( _fileSet, 0, verts ),
661  "Trouble getting vertices in current file set" );
662  assert( "Should only have a single vertex subrange, since they were read in one shot" && verts.psize() == 1 );
663 
664  for( unsigned int i = 0; i < vdatas.size(); i++ )
665  {
666  // Support non-set variables with 3 dimensions like (time, lev, ncol)
667  assert( 3 == vdatas[i].varDims.size() );
668 
669  // For a non-set variable, time should be the first dimension
670  assert( tDim == vdatas[i].varDims[0] );
671 
672  // Set up readStarts and readCounts
673  vdatas[i].readStarts.resize( 3 );
674  vdatas[i].readCounts.resize( 3 );
675 
676  // First: time
677  vdatas[i].readStarts[0] = 0; // This value is timestep dependent, will be set later
678  vdatas[i].readCounts[0] = 1;
679 
680  // Next: lev
681  vdatas[i].readStarts[1] = 0;
682  vdatas[i].readCounts[1] = vdatas[i].numLev;
683 
684  // Finally: ncol
685  switch( vdatas[i].entLoc )
686  {
687  case ReadNC::ENTLOCVERT:
688  // Vertices
689  // Start from the first localGidVerts
690  // Actually, this will be reset later on in a loop
691  vdatas[i].readStarts[2] = localGidVerts[0] - 1;
692  vdatas[i].readCounts[2] = nLocalVertices;
693  range = &verts;
694  break;
695  default:
696  MB_SET_ERR( MB_FAILURE, "Unexpected entity location type for variable " << vdatas[i].varName );
697  }
698 
699  // Get variable size
700  vdatas[i].sz = 1;
701  for( std::size_t idx = 0; idx != 3; idx++ )
702  vdatas[i].sz *= vdatas[i].readCounts[idx];
703 
704  for( unsigned int t = 0; t < tstep_nums.size(); t++ )
705  {
706  dbgOut.tprintf( 2, "Reading variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t] );
707 
708  if( tstep_nums[t] >= dimLens[tDim] )
709  {
710  MB_SET_ERR( MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number " << tstep_nums[t] );
711  }
712 
713  // Get the tag to read into
714  if( !vdatas[i].varTags[t] )
715  {
716  MB_CHK_SET_ERR( get_tag_to_nonset( vdatas[i], tstep_nums[t], vdatas[i].varTags[t], vdatas[i].numLev ),
717  "Trouble getting tag for variable " << vdatas[i].varName );
718  }
719 
720  // Get ptr to tag space
721  void* data;
722  int count;
723  MB_CHK_SET_ERR( mbImpl->tag_iterate( vdatas[i].varTags[t], range->begin(), range->end(), count, data ),
724  "Failed to iterate tag for variable " << vdatas[i].varName );
725  assert( (unsigned)count == range->size() );
726  vdatas[i].varDatas[t] = data;
727  }
728  }
729 
730  return MB_SUCCESS;
731 }

References moab::NCHelper::_fileSet, moab::NCHelper::_readNC, moab::Range::begin(), moab::ReadNC::dbgOut, moab::ReadNC::dimLens, moab::Range::end(), moab::ReadNC::ENTLOCVERT, moab::Interface::get_entities_by_dimension(), moab::NCHelper::get_tag_to_nonset(), moab::UcdNCHelper::localGidVerts, MB_CHK_SET_ERR, MB_INDEX_OUT_OF_RANGE, MB_SET_ERR, MB_SUCCESS, moab::ReadNC::mbImpl, moab::UcdNCHelper::nLocalVertices, moab::Range::psize(), moab::Range::size(), moab::Interface::tag_iterate(), moab::NCHelper::tDim, and moab::DebugOutput::tprintf().

Referenced by read_ucd_variables_to_nonset().

Member Data Documentation

◆ _spectralOrder

int moab::NCHelperHOMME::_spectralOrder
private

Definition at line 51 of file NCHelperHOMME.hpp.

Referenced by create_mesh(), and NCHelperHOMME().

◆ connectId

int moab::NCHelperHOMME::connectId
private

Definition at line 52 of file NCHelperHOMME.hpp.

Referenced by create_mesh().

◆ isConnFile

bool moab::NCHelperHOMME::isConnFile
private

Definition at line 53 of file NCHelperHOMME.hpp.

Referenced by create_mesh(), init_mesh_vals(), and NCHelperHOMME().


The documentation for this class was generated from the following files: