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

Export NC files. More...

#include <WriteNC.hpp>

+ Inheritance diagram for moab::WriteNC:
+ Collaboration diagram for moab::WriteNC:

Classes

class  AttData
 
class  VarData
 

Public Member Functions

 WriteNC (Interface *impl=NULL)
 Constructor. More...
 
virtual ~WriteNC ()
 Destructor. More...
 
ErrorCode write_file (const char *file_name, const bool overwrite, const FileOptions &opts, const EntityHandle *output_list, const int num_sets, const std::vector< std::string > &qa_list, const Tag *tag_list=NULL, int num_tags=0, int export_dimension=3)
 Writes out a file. More...
 
- Public Member Functions inherited from moab::WriterIface
virtual ~WriterIface ()
 

Static Public Member Functions

static WriterIface * factory (Interface *)
 Factory method. More...
 

Private Types

enum  EntityLocation {
  ENTLOCVERT = 0 , ENTLOCNSEDGE , ENTLOCEWEDGE , ENTLOCFACE ,
  ENTLOCSET , ENTLOCEDGE , ENTLOCREGION
}
 ENTLOCNSEDGE for north/south edge ENTLOCWEEDGE for west/east edge. More...
 

Private Member Functions

ErrorCode parse_options (const FileOptions &opts, std::vector< std::string > &var_names, std::vector< std::string > &desired_names, std::vector< int > &tstep_nums, std::vector< double > &tstep_vals)
 
ErrorCode process_conventional_tags (EntityHandle fileSet)
 
ErrorCode process_concatenated_attribute (const void *attPtr, int attSz, std::vector< int > &attLen, std::map< std::string, AttData > &attributes)
 

Private Attributes

std::vector< std::string > dimNames
 This info will be reconstructed from metadata stored on conventional fileSet tags Dimension names. More...
 
std::vector< int > dimLens
 Dimension lengths. More...
 
std::set< std::string > usedCoordinates
 Will collect used dimensions (coordinate variables) More...
 
std::set< std::string > dummyVarNames
 Dummy variables (for dimensions that have no corresponding coordinate variables) More...
 
std::map< std::string, AttData > globalAtts
 Global attribs. More...
 
std::map< std::string, VarData > varInfo
 Variable info. More...
 
Interface * mbImpl
 Interface instance. More...
 
WriteUtilIface * mWriteIface
 
const char * fileName
 File var. More...
 
int fileId
 File numbers assigned by (p)netcdf. More...
 
DebugOutput dbgOut
 Debug stuff. More...
 
bool noMesh
 Write options. More...
 
bool noVars
 
bool append
 
Tag mGlobalIdTag
 Cached tags for writing. This will be important for ordering the data, in parallel. More...
 
bool isParallel
 Are we writing in parallel? (probably in the future) More...
 
std::string grid_type
 CAM Euler, etc,. More...
 
NCWriteHelper * myHelper
 Helper class instance. More...
 

Friends

class NCWriteHelper
 
class ScdNCWriteHelper
 
class UcdNCWriteHelper
 
class NCWriteEuler
 
class NCWriteFV
 
class NCWriteHOMME
 
class NCWriteMPAS
 
class NCWriteGCRM
 
class NCWriteScrip
 
class NCWriteESMF
 
class NCWriteDomain
 

Detailed Description

Export NC files.

Definition at line 71 of file WriteNC.hpp.

Member Enumeration Documentation

◆ EntityLocation

ENTLOCNSEDGE for north/south edge ENTLOCWEEDGE for west/east edge.

Enumerator
ENTLOCVERT 
ENTLOCNSEDGE 
ENTLOCEWEDGE 
ENTLOCFACE 
ENTLOCSET 
ENTLOCEDGE 
ENTLOCREGION 

Definition at line 109 of file WriteNC.hpp.

110  {
111  ENTLOCVERT = 0,
112  ENTLOCNSEDGE,
113  ENTLOCEWEDGE,
114  ENTLOCFACE,
115  ENTLOCSET,
116  ENTLOCEDGE,
118  };

Constructor & Destructor Documentation

◆ WriteNC()

moab::WriteNC::WriteNC ( Interface *  impl = NULL)
explicit

Constructor.

Definition at line 32 of file WriteNC.cpp.

33  : mbImpl( impl ), dbgOut( stderr ),
34 #ifdef MOAB_HAVE_MPI
35  myPcomm( NULL ),
36 #endif
37  noMesh( false ), noVars( false ), append( false ), mGlobalIdTag( 0 ), isParallel( false ), myHelper( NULL )
38 {
39  assert( impl != NULL );
40  impl->query_interface( mWriteIface );
41 }

References mWriteIface, and moab::Interface::query_interface().

Referenced by factory().

◆ ~WriteNC()

moab::WriteNC::~WriteNC ( )
virtual

Destructor.

Definition at line 43 of file WriteNC.cpp.

44 {
46  if( myHelper != NULL ) delete myHelper;
47 }

References mbImpl, mWriteIface, myHelper, and moab::Interface::release_interface().

Member Function Documentation

◆ factory()

WriterIface * moab::WriteNC::factory ( Interface *  iface)
static

Factory method.

Definition at line 27 of file WriteNC.cpp.

28 {
29  return new WriteNC( iface );
30 }

References iface, and WriteNC().

Referenced by moab::ReaderWriterSet::ReaderWriterSet().

◆ parse_options()

ErrorCode moab::WriteNC::parse_options ( const FileOptions &  opts,
std::vector< std::string > &  var_names,
std::vector< std::string > &  desired_names,
std::vector< int > &  tstep_nums,
std::vector< double > &  tstep_vals 
)
private

Definition at line 206 of file WriteNC.cpp.

211 {
212  int tmpval;
213  if( MB_SUCCESS == opts.get_int_option( "DEBUG_IO", 1, tmpval ) )
214  {
215  dbgOut.set_verbosity( tmpval );
216  dbgOut.set_prefix( "NCWrite" );
217  }
218 
219  ErrorCode rval = opts.get_strs_option( "VARIABLE", var_names );
220  if( MB_TYPE_OUT_OF_RANGE == rval )
221  noVars = true;
222  else
223  noVars = false;
224 
225  rval = opts.get_strs_option( "RENAME", desired_names );
226  if( MB_ENTITY_NOT_FOUND == rval )
227  {
228  if( !noVars )
229  {
230  desired_names.resize( var_names.size() );
231  std::copy( var_names.begin(), var_names.end(), desired_names.begin() );
232  }
233  }
234  // Either way
235  assert( desired_names.size() == var_names.size() );
236 
237  opts.get_ints_option( "TIMESTEP", tstep_nums );
238  opts.get_reals_option( "TIMEVAL", tstep_vals );
239  rval = opts.get_null_option( "NOMESH" );
240  if( MB_SUCCESS == rval ) noMesh = true;
241 
242  rval = opts.get_null_option( "APPEND" );
243  if( MB_SUCCESS == rval ) append = true;
244 
245  // WRITE_FORMAT: optional explicit output grid_type. Set this when you
246  // want to convert FROM one grid type TO another (e.g. MPAS → SCRIP),
247  // or when writing from a mesh that doesn't carry the climate
248  // __MESH_TYPE / __VAR_NAMES tags that process_conventional_tags
249  // expects. Valid values match the strings returned by the readers'
250  // get_mesh_type_name(): "CAM_EUL", "CAM_FV", "CAM_SE", "MPAS",
251  // "GCRM", "SCRIP", "ESMF", "DOMAIN".
252  std::string requestedFormat;
253  rval = opts.get_str_option( "WRITE_FORMAT", requestedFormat );
254  if( MB_SUCCESS == rval && !requestedFormat.empty() )
255  {
256  grid_type = requestedFormat;
257  dbgOut.tprintf( 1, "WRITE_FORMAT override: grid_type = %s\n", grid_type.c_str() );
258  }
259 
260  if( 2 <= dbgOut.get_verbosity() )
261  {
262  if( !var_names.empty() )
263  {
264  std::cerr << "Variables requested: ";
265  for( unsigned int i = 0; i < var_names.size(); i++ )
266  std::cerr << var_names[i];
267  std::cerr << std::endl;
268  }
269  if( !tstep_nums.empty() )
270  {
271  std::cerr << "Timesteps requested: ";
272  for( unsigned int i = 0; i < tstep_nums.size(); i++ )
273  std::cerr << tstep_nums[i];
274  std::cerr << std::endl;
275  }
276  if( !tstep_vals.empty() )
277  {
278  std::cerr << "Time vals requested: ";
279  for( unsigned int i = 0; i < tstep_vals.size(); i++ )
280  std::cerr << tstep_vals[i];
281  std::cerr << std::endl;
282  }
283  }
284 
285 // FIXME: copied from ReadNC, may need revise
286 #ifdef MOAB_HAVE_MPI
287  isParallel = ( opts.match_option( "PARALLEL", "WRITE_PART" ) != MB_ENTITY_NOT_FOUND );
288 
289  if( !isParallel )
290  // Return success here, since rval still has _NOT_FOUND from not finding option
291  // in this case, myPcomm will be NULL, so it can never be used; always check for isParallel
292  // before any use for myPcomm
293  return MB_SUCCESS;
294 
295  int pcomm_no = 0;
296  rval = opts.get_int_option( "PARALLEL_COMM", pcomm_no );
297  if( MB_TYPE_OUT_OF_RANGE == rval )
298  {
299  MB_SET_ERR( rval, "Invalid value for PARALLEL_COMM option" );
300  }
301 
302  myPcomm = ParallelComm::get_pcomm( mbImpl, pcomm_no );
303  if( 0 == myPcomm )
304  {
305  myPcomm = new ParallelComm( mbImpl, MPI_COMM_WORLD );
306  }
307 
308 #ifndef MOAB_HAVE_PNETCDF
309  const int procs = myPcomm->proc_config().proc_size();
310  if( procs > 1 )
311  {
312  MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Attempt to launch NC writer in parallel without pnetcdf support" );
313  }
314 #endif
315 
316  const int rank = myPcomm->proc_config().proc_rank();
317  dbgOut.set_rank( rank );
318 #endif
319 
320  return MB_SUCCESS;
321 }

References append, dbgOut, ErrorCode, moab::FileOptions::get_int_option(), moab::FileOptions::get_ints_option(), moab::FileOptions::get_null_option(), moab::ParallelComm::get_pcomm(), moab::FileOptions::get_reals_option(), moab::FileOptions::get_str_option(), moab::FileOptions::get_strs_option(), moab::DebugOutput::get_verbosity(), grid_type, isParallel, moab::FileOptions::match_option(), MB_ENTITY_NOT_FOUND, MB_SET_ERR, MB_SUCCESS, MB_TYPE_OUT_OF_RANGE, MB_UNSUPPORTED_OPERATION, mbImpl, noMesh, noVars, moab::DebugOutput::set_prefix(), moab::DebugOutput::set_rank(), moab::DebugOutput::set_verbosity(), and moab::DebugOutput::tprintf().

Referenced by write_file().

◆ process_concatenated_attribute()

ErrorCode moab::WriteNC::process_concatenated_attribute ( const void *  attPtr,
int  attSz,
std::vector< int > &  attLen,
std::map< std::string, AttData > &  attributes 
)
private

Definition at line 566 of file WriteNC.cpp.

570 {
571  std::size_t start = 0;
572  std::size_t att_counter = 0;
573  std::string concatString( (char*)attPtr, (char*)attPtr + attSz );
574 
575  for( std::size_t i = 0; i != (size_t)attSz; i++ )
576  {
577  if( concatString[i] == '\0' )
578  {
579  std::string att_name( &concatString[start], i - start );
580  start = i + 1;
581  while( concatString[i] != ';' )
582  ++i;
583  std::string data_type( &concatString[start], i - start );
584  ++i;
585  start = i;
586  i = attLen[att_counter];
587  if( concatString[i] != ';' ) MB_SET_ERR( MB_FAILURE, "Error parsing attributes" );
588 
589  std::string data_val( &concatString[start], i - start );
590  start = i + 1;
591 
592  AttData& attrib = attributes[att_name];
593  attrib.attValue = data_val;
594  attrib.attLen = data_val.size();
595 
596  if( data_type == "char" )
597  attrib.attDataType = NC_CHAR;
598  else if( data_type == "double" )
599  attrib.attDataType = NC_DOUBLE;
600  else if( data_type == "float" )
601  attrib.attDataType = NC_FLOAT;
602  else if( data_type == "int" )
603  attrib.attDataType = NC_INT;
604  else if( data_type == "short" )
605  attrib.attDataType = NC_SHORT;
606 
607  ++att_counter;
608  dbgOut.tprintf( 2, " Process attribute %s with value %s \n", att_name.c_str(), data_val.c_str() );
609  }
610  }
611 
612  return MB_SUCCESS;
613 }

References moab::WriteNC::AttData::attDataType, moab::WriteNC::AttData::attLen, moab::WriteNC::AttData::attValue, dbgOut, MB_SET_ERR, MB_SUCCESS, and moab::DebugOutput::tprintf().

Referenced by process_conventional_tags().

◆ process_conventional_tags()

ErrorCode moab::WriteNC::process_conventional_tags ( EntityHandle  fileSet)
private

Definition at line 325 of file WriteNC.cpp.

326 {
327  ErrorCode rval;
328 
329  // Start copy
330  Tag dimNamesTag = 0;
331  std::string tag_name = "__DIM_NAMES";
332  const void* data = NULL;
333  int dimNamesSz = 0;
334  MB_CHK_SET_ERR( mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, dimNamesTag, MB_TAG_ANY ),
335  "Trouble getting conventional tag " << tag_name );
336  MB_CHK_SET_ERR( mbImpl->tag_get_by_ptr( dimNamesTag, &fileSet, 1, &data, &dimNamesSz ),
337  "Trouble getting data of conventional tag " << tag_name );
338  const char* p = static_cast< const char* >( data );
339  dbgOut.tprintf( 1, "__DIM_NAMES tag has string length %d\n", dimNamesSz );
340 
341  std::size_t start = 0;
342 
343  Tag dimLensTag = 0;
344  tag_name = "__DIM_LENS";
345  data = NULL;
346  int dimLensSz = 0;
347  MB_CHK_SET_ERR( mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_INTEGER, dimLensTag, MB_TAG_ANY ),
348  "Trouble getting conventional tag " << tag_name );
349  MB_CHK_SET_ERR( mbImpl->tag_get_by_ptr( dimLensTag, &fileSet, 1, &data, &dimLensSz ),
350  "Trouble getting data of conventional tag " << tag_name );
351  const int* int_p = static_cast< const int* >( data );
352  dbgOut.tprintf( 1, "__DIM_LENS tag has %d values\n", dimLensSz );
353 
354  int idxDim = 0;
355  // Dim names are separated by '\0' in the string of __DIM_NAMES tag
356  for( std::size_t i = 0; i != static_cast< std::size_t >( dimNamesSz ); i++ )
357  {
358  if( p[i] == '\0' )
359  {
360  std::string dim_name( &p[start], i - start );
361  int len = int_p[idxDim];
362  dimNames.push_back( dim_name );
363  dimLens.push_back( len );
364  dbgOut.tprintf( 2, "Dimension %s has length %d\n", dim_name.c_str(), len );
365  // FIXME: Need info from moab to set unlimited dimension
366  // Currently assume each file has the same number of time dimensions
367  /*if ((dim_name == "time") || (dim_name == "Time"))
368  insert(dim_name, *(new pcdim(dim_name, len * m_file_names.size(), true)));
369  else
370  insert(dim_name, *(new pcdim(dim_name, len)));*/
371  start = i + 1;
372  idxDim++;
373  }
374  }
375 
376  Tag meshTypeTag = 0;
377  tag_name = "__MESH_TYPE";
378  data = NULL;
379  int meshTypeSz = 0;
380  MB_CHK_SET_ERR( mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, meshTypeTag, MB_TAG_ANY ),
381  "Trouble getting conventional tag " << tag_name );
382  MB_CHK_SET_ERR( mbImpl->tag_get_by_ptr( meshTypeTag, &fileSet, 1, &data, &meshTypeSz ),
383  "Trouble getting data of conventional tag " << tag_name );
384  p = static_cast< const char* >( data );
385  grid_type = std::string( &p[0], meshTypeSz );
386  dbgOut.tprintf( 2, "Mesh type: %s\n", grid_type.c_str() );
387 
388  // Read <__VAR_NAMES_LOCATIONS> tag
389  Tag varNamesLocsTag = 0;
390  tag_name = "__VAR_NAMES_LOCATIONS";
391  data = NULL;
392  int varNamesLocsSz = 0;
393  MB_CHK_SET_ERR( mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_INTEGER, varNamesLocsTag, MB_TAG_ANY ),
394  "Trouble getting conventional tag " << tag_name );
395  MB_CHK_SET_ERR( mbImpl->tag_get_by_ptr( varNamesLocsTag, &fileSet, 1, &data, &varNamesLocsSz ),
396  "Trouble getting data of conventional tag " << tag_name );
397  int_p = static_cast< const int* >( data );
398  std::vector< int > varNamesLocs( varNamesLocsSz );
399  std::copy( int_p, int_p + varNamesLocsSz, varNamesLocs.begin() );
400 
401  Tag varNamesTag = 0;
402  tag_name = "__VAR_NAMES";
403  MB_CHK_SET_ERR( mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, varNamesTag, MB_TAG_ANY ),
404  "Trouble getting conventional tag " << tag_name );
405  data = NULL;
406  int varNamesSz = 0;
407  MB_CHK_SET_ERR( mbImpl->tag_get_by_ptr( varNamesTag, &fileSet, 1, &data, &varNamesSz ),
408  "Trouble getting data of conventional tag " << tag_name );
409  dbgOut.tprintf( 2, "__VAR_NAMES tag has string length %d\n", varNamesSz );
410  p = static_cast< const char* >( data );
411 
412  start = 0;
413  int idxVar = 0;
414  int sz;
415  // Var names are separated by '\0' in the string of __VAR_NAMES tag
416  for( std::size_t i = 0; i != static_cast< std::size_t >( varNamesSz ); i++ )
417  {
418  if( p[i] == '\0' )
419  {
420  std::string var_name( &p[start], i - start );
421 
422  dbgOut.tprintf( 2, "var name: %s index %d \n", var_name.c_str(), idxVar );
423  // Process var name:
424  // This will create/initiate map; we will populate variableDataStruct with info about
425  // dims, tags, etc reference & is important; otherwise variableDataStruct will go out of
426  // scope, and deleted :(
427  VarData& variableDataStruct = varInfo[var_name];
428  variableDataStruct.varName = var_name;
429  variableDataStruct.entLoc = varNamesLocs[idxVar];
430 
431  dbgOut.tprintf( 2, "at var name %s varInfo size %d \n", var_name.c_str(), (int)varInfo.size() );
432 
433  sz = 0;
434  Tag dims_tag = 0;
435  std::string dim_names = "__" + var_name + "_DIMS";
436  rval = mbImpl->tag_get_handle( dim_names.c_str(), 0, MB_TYPE_OPAQUE, dims_tag, MB_TAG_ANY );
437  if( MB_SUCCESS != rval )
438  {
439  if( MB_TAG_NOT_FOUND == rval )
440  {
441  dbgOut.tprintf( 2, "tag : %s not found, continue \n", dim_names.c_str() );
442  start = i + 1;
443  idxVar++;
444  continue;
445  }
446  MB_SET_ERR( rval, "Trouble getting conventional tag " << dim_names );
447  }
448  MB_CHK_SET_ERR( mbImpl->tag_get_length( dims_tag, sz ),
449  "Trouble getting size of dimensions for variable " << var_name );
450  sz /= sizeof( Tag ); // The type is MB_TYPE_OPAQUE, but it is a list of tags, so we
451  // need to divide by the size of Tag
452  // sz is used for number of dimension tags in this list
453  dbgOut.tprintf( 2, "var name: %s has %d dimensions \n", var_name.c_str(), sz );
454 
455  variableDataStruct.varDims.resize( sz );
456  const void* ptr = NULL;
457  MB_CHK_SET_ERR( mbImpl->tag_get_by_ptr( dims_tag, &fileSet, 1, &ptr ),
458  "Could not get tag by pointer" );
459 
460  const Tag* ptags = static_cast< const moab::Tag* >( ptr );
461  for( std::size_t j = 0; j != static_cast< std::size_t >( sz ); j++ )
462  {
463  std::string dim_name;
464  MB_CHK_SET_ERR( mbImpl->tag_get_name( ptags[j], dim_name ),
465  "Trouble getting dimension of variable " << var_name );
466  dbgOut.tprintf( 2, "var name: %s has %s as dimension \n", var_name.c_str(), dim_name.c_str() );
467  std::vector< std::string >::iterator vit = std::find( dimNames.begin(), dimNames.end(), dim_name );
468  if( vit == dimNames.end() )
469  MB_SET_ERR( MB_FAILURE, "Dimension " << dim_name << " not found for variable " << var_name );
470  variableDataStruct.varDims[j] = (int)( vit - dimNames.begin() ); // Will be used for writing
471  // This will have to change to actual file dimension, for writing
472  }
473 
474  // Attributes for this variable
475  std::stringstream ssTagName;
476  ssTagName << "__" << var_name << "_ATTRIBS";
477  tag_name = ssTagName.str();
478  Tag varAttTag = 0;
479  MB_CHK_SET_ERR( mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, varAttTag,
481  "Trouble getting conventional tag " << tag_name );
482  const void* varAttPtr = NULL;
483  int varAttSz = 0;
484  MB_CHK_SET_ERR( mbImpl->tag_get_by_ptr( varAttTag, &fileSet, 1, &varAttPtr, &varAttSz ),
485  "Trouble getting data of conventional tag " << tag_name );
486  dbgOut.tprintf( 2, "Tag retrieved for variable %s\n", tag_name.c_str() );
487 
488  std::string attribString( (char*)varAttPtr, (char*)varAttPtr + varAttSz );
489  if( attribString == "NO_ATTRIBS" )
490  {
491  // This variable has no attributes
492  variableDataStruct.numAtts = 0;
493  }
494  else if( attribString == "DUMMY_VAR" )
495  {
496  // This variable is a dummy coordinate variable
497  variableDataStruct.numAtts = 0;
498  dummyVarNames.insert( variableDataStruct.varName );
499  }
500  else
501  {
502  ssTagName << "_LEN";
503  tag_name = ssTagName.str();
504  Tag varAttLenTag = 0;
505  MB_CHK_SET_ERR( mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_INTEGER, varAttLenTag,
506  MB_TAG_ANY ),
507  "Trouble getting conventional tag " << tag_name );
508  int varAttLenSz = 0;
509  MB_CHK_SET_ERR( mbImpl->tag_get_length( varAttLenTag, varAttLenSz ),
510  "Trouble getting length of conventional tag " << tag_name );
511  std::vector< int > varAttLen( varAttLenSz );
512  MB_CHK_SET_ERR( mbImpl->tag_get_data( varAttLenTag, &fileSet, 1, &varAttLen[0] ),
513  "Trouble getting data of conventional tag " << tag_name );
514 
515  MB_CHK_SET_ERR( process_concatenated_attribute( varAttPtr, varAttSz, varAttLen,
516  variableDataStruct.varAtts ),
517  "Trouble processing attributes of variable " << var_name );
518 
519  dbgOut.tprintf( 2, "Tag metadata for variable %s\n", tag_name.c_str() );
520  }
521  // End attribute
522 
523  start = i + 1;
524  idxVar++;
525  } // if (p[i] == '\0')
526  }
527 
528  // Global attributes
529  tag_name = "__GLOBAL_ATTRIBS";
530  Tag globalAttTag = 0;
531  MB_CHK_SET_ERR( mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, globalAttTag,
533  "Trouble getting conventional tag " << tag_name );
534  std::vector< int > gattLen;
535 
536  const void* gattptr = NULL;
537  int globalAttSz = 0;
538  MB_CHK_SET_ERR( mbImpl->tag_get_by_ptr( globalAttTag, &fileSet, 1, &gattptr, &globalAttSz ),
539  "Trouble getting data of conventional tag " << tag_name );
540 
541  dbgOut.tprintf( 2, "Tag value retrieved for %s size %d\n", tag_name.c_str(), globalAttSz );
542 
543  // <__GLOBAL_ATTRIBS_LEN>
544  tag_name = "__GLOBAL_ATTRIBS_LEN";
545  Tag globalAttLenTag = 0;
546 
547  MB_CHK_SET_ERR( mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_INTEGER, globalAttLenTag, MB_TAG_ANY ),
548  "Trouble getting conventional tag " << tag_name );
549  int sizeGAtt = 0;
550  MB_CHK_SET_ERR( mbImpl->tag_get_length( globalAttLenTag, sizeGAtt ),
551  "Trouble getting length of conventional tag " << tag_name );
552 
553  gattLen.resize( sizeGAtt );
554  MB_CHK_SET_ERR( mbImpl->tag_get_data( globalAttLenTag, &fileSet, 1, &gattLen[0] ),
555  "Trouble getting data of conventional tag " << tag_name );
556 
557  dbgOut.tprintf( 2, "Tag retrieved for variable %s\n", tag_name.c_str() );
558 
559  MB_CHK_SET_ERR( process_concatenated_attribute( gattptr, globalAttSz, gattLen, globalAtts ),
560  "Trouble processing global attributes" );
561 
562  return MB_SUCCESS;
563 }

References dbgOut, dimLens, dimNames, dummyVarNames, moab::WriteNC::VarData::entLoc, ErrorCode, globalAtts, grid_type, MB_CHK_SET_ERR, MB_SET_ERR, MB_SUCCESS, MB_TAG_ANY, MB_TAG_NOT_FOUND, MB_TAG_SPARSE, MB_TAG_VARLEN, MB_TYPE_INTEGER, MB_TYPE_OPAQUE, mbImpl, moab::WriteNC::VarData::numAtts, process_concatenated_attribute(), moab::Interface::tag_get_by_ptr(), moab::Interface::tag_get_data(), moab::Interface::tag_get_handle(), moab::Interface::tag_get_length(), moab::Interface::tag_get_name(), moab::DebugOutput::tprintf(), moab::WriteNC::VarData::varAtts, moab::WriteNC::VarData::varDims, varInfo, and moab::WriteNC::VarData::varName.

Referenced by write_file().

◆ write_file()

ErrorCode moab::WriteNC::write_file ( const char *  file_name,
const bool  overwrite,
const FileOptions &  opts,
const EntityHandle *  output_list,
const int  num_sets,
const std::vector< std::string > &  qa_list,
const Tag *  tag_list = NULL,
int  num_tags = 0,
int  export_dimension = 3 
)
virtual

Writes out a file.

Implements moab::WriterIface.

Definition at line 50 of file WriteNC.cpp.

59 {
60  // See if opts has variable(s) specified
61  std::vector< std::string > var_names;
62  std::vector< std::string > desired_names;
63  std::vector< int > tstep_nums;
64  std::vector< double > tstep_vals;
65 
66  // Get and cache predefined tag handles
68 
69  // num set has to be 1, we will write only one set, the original file set used to load
70  if( num_set != 1 ) MB_SET_ERR( MB_FAILURE, "We should write only one set (the file set used to read data into)" );
71 
72  MB_CHK_SET_ERR( parse_options( options, var_names, desired_names, tstep_nums, tstep_vals ),
73  "Trouble parsing option string" );
74 
75  // Important to create some data that will be used to write the file; dimensions, variables, etc
76  // new variables still need to have some way of defining their dimensions
77  // maybe it will be passed as write options
78  // Process the climate-style conventional tags only if the user did NOT
79  // override grid_type via WRITE_FORMAT. Grid-output writers (NCWriteScrip,
80  // NCWriteESMF, NCWriteDomain) synthesize their schema from mesh state
81  // and don't need the prior-read __VAR_NAMES / __MESH_TYPE tag chain;
82  // running process_conventional_tags would also fail on meshes that
83  // weren't loaded via ReadNC (h5m, exodus, ...).
84  if( grid_type.empty() )
85  {
86  MB_CHK_SET_ERR( process_conventional_tags( *file_set ), "Trouble processing conventional tags" );
87  }
88  else
89  {
90  dbgOut.tprintf( 2, "Skipping process_conventional_tags; grid_type already set by WRITE_FORMAT: %s\n",
91  grid_type.c_str() );
92  }
93 
94  // Create or append the file
95  if( append )
96  dbgOut.tprintf( 1, "opening file %s for appending \n", file_name );
97  else
98  dbgOut.tprintf( 1, "creating file %s\n", file_name );
99  fileName = file_name;
100  int success;
101 
102  // Format-aware open/create via the runtime dispatch layer. For append
103  // mode the format is detected from the existing file. For create mode
104  // we pick CLASSIC by default (preserves the behavior of PNetCDF builds
105  // which write CDF-5 via ncmpi_create) — a NetCDF-4 write path can be
106  // added later behind an explicit WriteNC option.
107 #ifdef MOAB_HAVE_MPI
108  const int write_mpi_size = isParallel ? myPcomm->proc_config().proc_size() : 1;
109 #else
110  const int write_mpi_size = 1;
111 #endif
112 
113  if( append )
114  {
115  int omode = NC_WRITE;
116 
117  int existingFormat = NCFMT_UNKNOWN;
118 #ifdef MOAB_HAVE_MPI
119  if( isParallel )
120  {
121  int rank = myPcomm->proc_config().proc_rank();
122  if( rank == 0 ) existingFormat = mbnc_detect_format( file_name );
123  MPI_Bcast( &existingFormat, 1, MPI_INT, 0, myPcomm->proc_config().proc_comm() );
124  }
125  else
126 #endif
127  {
128  existingFormat = mbnc_detect_format( file_name );
129  }
130 
131  const NcBackend backend = mbnc_choose_backend_for_write( existingFormat, write_mpi_size );
132  if( backend == NCB_NONE )
133  {
134  MB_SET_ERR( MB_FAILURE, "Cannot find a compatible parallel writer for appending to '"
135  << file_name << "' (file format not recognized or no compatible backend)" );
136  }
137 
138 #ifdef MOAB_HAVE_MPI
139  if( backend == NCB_NETCDF_SERIAL || write_mpi_size == 1 )
140  {
141  success = mbnc_open( file_name, omode, &fileId );
142  }
143  else
144  {
145  success =
146  mbnc_open_par( backend, myPcomm->proc_config().proc_comm(), MPI_INFO_NULL, file_name, omode, &fileId );
147  }
148 #else
149  success = mbnc_open( file_name, omode, &fileId );
150 #endif
151  if( success ) MB_SET_ERR( MB_FAILURE, "Trouble opening file " << file_name << " for appending" );
152  }
153  else
154  {
155  // Case when the file is new — choose classic format to match the
156  // long-standing default of the PNetCDF-built path (ncmpi_create
157  // defaults to CDF-5). Future: expose a "FORMAT" option on the
158  // WriteNC option string to let the caller request NetCDF-4.
159  int cmode = overwrite ? NC_CLOBBER : NC_NOCLOBBER;
160 
161  const NcBackend backend = mbnc_choose_backend_for_write( NCFMT_CLASSIC, write_mpi_size );
162  if( backend == NCB_NONE )
163  {
164  MB_SET_ERR( MB_FAILURE, "Cannot find a compatible parallel writer for creating '" << file_name << "'" );
165  }
166 
167 #ifdef MOAB_HAVE_MPI
168  if( backend == NCB_NETCDF_SERIAL || write_mpi_size == 1 )
169  {
170  success = mbnc_create( file_name, cmode, &fileId );
171  }
172  else
173  {
174  success =
175  mbnc_create_par( backend, myPcomm->proc_config().proc_comm(), MPI_INFO_NULL, file_name, cmode, &fileId );
176  }
177 #else
178  success = mbnc_create( file_name, cmode, &fileId );
179 #endif
180  if( success ) MB_SET_ERR( MB_FAILURE, "Trouble creating file " << file_name << " for writing" );
181  }
182 
183  if( NULL != myHelper ) delete myHelper;
184 
185  // Get appropriate helper instance for WriteNC class based on some info in the file set
186  myHelper = NCWriteHelper::get_nc_helper( this, fileId, options, *file_set );
187  if( NULL == myHelper )
188  {
189  MB_SET_ERR( MB_FAILURE, "Failed to get NCWriteHelper class instance" );
190  }
191 
192  MB_CHK_SET_ERR( myHelper->collect_mesh_info(), "Trouble collecting mesh information" );
193 
194  MB_CHK_SET_ERR( myHelper->collect_variable_data( var_names, tstep_nums ), "Trouble collecting variable data" );
195 
196  MB_CHK_SET_ERR( myHelper->init_file( var_names, desired_names, append ), "Trouble initializing file" );
197 
198  MB_CHK_SET_ERR( myHelper->write_values( var_names, tstep_nums ), "Trouble writing values to file" );
199 
200  success = NCFUNC( close )( fileId );
201  if( success ) MB_SET_ERR( MB_FAILURE, "Trouble closing file" );
202 
203  return MB_SUCCESS;
204 }

References append, moab::NCWriteHelper::collect_mesh_info(), moab::NCWriteHelper::collect_variable_data(), dbgOut, fileId, fileName, moab::NCWriteHelper::get_nc_helper(), moab::Interface::globalId_tag(), grid_type, moab::NCWriteHelper::init_file(), isParallel, MB_CHK_SET_ERR, MB_SET_ERR, MB_SUCCESS, mbImpl, moab::mbnc_choose_backend_for_write(), moab::mbnc_create(), moab::mbnc_detect_format(), moab::mbnc_open(), mGlobalIdTag, myHelper, moab::NCB_NETCDF_SERIAL, moab::NCB_NONE, moab::NCFMT_CLASSIC, moab::NCFMT_UNKNOWN, NCFUNC, parse_options(), process_conventional_tags(), moab::DebugOutput::tprintf(), and moab::NCWriteHelper::write_values().

Friends And Related Function Documentation

◆ NCWriteDomain

friend class NCWriteDomain
friend

Definition at line 83 of file WriteNC.hpp.

◆ NCWriteESMF

friend class NCWriteESMF
friend

Definition at line 82 of file WriteNC.hpp.

◆ NCWriteEuler

friend class NCWriteEuler
friend

Definition at line 76 of file WriteNC.hpp.

◆ NCWriteFV

friend class NCWriteFV
friend

Definition at line 77 of file WriteNC.hpp.

◆ NCWriteGCRM

friend class NCWriteGCRM
friend

Definition at line 80 of file WriteNC.hpp.

◆ NCWriteHelper

friend class NCWriteHelper
friend

Definition at line 73 of file WriteNC.hpp.

◆ NCWriteHOMME

friend class NCWriteHOMME
friend

Definition at line 78 of file WriteNC.hpp.

◆ NCWriteMPAS

friend class NCWriteMPAS
friend

Definition at line 79 of file WriteNC.hpp.

◆ NCWriteScrip

friend class NCWriteScrip
friend

Definition at line 81 of file WriteNC.hpp.

◆ ScdNCWriteHelper

friend class ScdNCWriteHelper
friend

Definition at line 74 of file WriteNC.hpp.

◆ UcdNCWriteHelper

friend class UcdNCWriteHelper
friend

Definition at line 75 of file WriteNC.hpp.

Member Data Documentation

◆ append

bool moab::WriteNC::append
private

Definition at line 206 of file WriteNC.hpp.

Referenced by parse_options(), and write_file().

◆ dbgOut

◆ dimLens

◆ dimNames

◆ dummyVarNames

std::set< std::string > moab::WriteNC::dummyVarNames
private

Dummy variables (for dimensions that have no corresponding coordinate variables)

Definition at line 162 of file WriteNC.hpp.

Referenced by moab::NCWriteHelper::collect_variable_data(), moab::NCWriteHelper::init_file(), process_conventional_tags(), and moab::NCWriteHelper::write_values().

◆ fileId

int moab::WriteNC::fileId
private

File numbers assigned by (p)netcdf.

Definition at line 194 of file WriteNC.hpp.

Referenced by write_file().

◆ fileName

const char* moab::WriteNC::fileName
private

File var.

Definition at line 191 of file WriteNC.hpp.

Referenced by write_file().

◆ globalAtts

std::map< std::string, AttData > moab::WriteNC::globalAtts
private

Global attribs.

Definition at line 165 of file WriteNC.hpp.

Referenced by moab::NCWriteHelper::init_file(), and process_conventional_tags().

◆ grid_type

std::string moab::WriteNC::grid_type
private

CAM Euler, etc,.

Definition at line 215 of file WriteNC.hpp.

Referenced by moab::NCWriteHelper::get_nc_helper(), parse_options(), process_conventional_tags(), and write_file().

◆ isParallel

◆ mbImpl

◆ mGlobalIdTag

Tag moab::WriteNC::mGlobalIdTag
private

◆ mWriteIface

WriteUtilIface* moab::WriteNC::mWriteIface
private

Definition at line 188 of file WriteNC.hpp.

Referenced by WriteNC(), and ~WriteNC().

◆ myHelper

NCWriteHelper* moab::WriteNC::myHelper
private

Helper class instance.

Definition at line 218 of file WriteNC.hpp.

Referenced by write_file(), and ~WriteNC().

◆ noMesh

bool moab::WriteNC::noMesh
private

Write options.

Definition at line 204 of file WriteNC.hpp.

Referenced by parse_options().

◆ noVars

bool moab::WriteNC::noVars
private

Definition at line 205 of file WriteNC.hpp.

Referenced by parse_options().

◆ usedCoordinates

std::set< std::string > moab::WriteNC::usedCoordinates
private

Will collect used dimensions (coordinate variables)

Definition at line 159 of file WriteNC.hpp.

Referenced by moab::NCWriteHelper::collect_variable_data(), moab::NCWriteHelper::init_file(), and moab::NCWriteHelper::write_values().

◆ varInfo


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