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

#include <NCWriteHelper.hpp>

+ Inheritance diagram for moab::NCWriteHelper:
+ Collaboration diagram for moab::NCWriteHelper:

Public Member Functions

 NCWriteHelper (WriteNC *writeNC, int fileId, const FileOptions &opts, EntityHandle fileSet)
 
virtual ~NCWriteHelper ()
 
virtual ErrorCode collect_mesh_info ()=0
 Collect necessary info about local mesh (implemented in child classes) More...
 
virtual ErrorCode collect_variable_data (std::vector< std::string > &var_names, std::vector< int > &tstep_nums)
 Collect data for specified variables (partially implemented in child classes) More...
 
ErrorCode init_file (std::vector< std::string > &var_names, std::vector< std::string > &desired_names, bool _append)
 Initialize file: this is where all defines are done The VarData dimension ids are filled up after define. More...
 
ErrorCode write_values (std::vector< std::string > &var_names, std::vector< int > &tstep_nums)
 Take the info from VarData and write first non-set variables, then set variables. More...
 

Static Public Member Functions

static NCWriteHelperget_nc_helper (WriteNC *writeNC, int fileId, const FileOptions &opts, EntityHandle fileSet)
 Get appropriate helper instance for WriteNC class based on some info in the file set. More...
 

Protected Member Functions

virtual ErrorCode write_nonset_variables (std::vector< WriteNC::VarData > &vdatas, std::vector< int > &tstep_nums)=0
 

Protected Attributes

WriteNC_writeNC
 Allow NCWriteHelper to directly access members of WriteNC. More...
 
int _fileId
 Cache some information from WriteNC. More...
 
const FileOptions_opts
 
EntityHandle _fileSet
 
int nTimeSteps
 Dimensions of time and level. More...
 
int nLevels
 
int tDim
 Dimension numbers for time and level. More...
 
int levDim
 
Range localCellsOwned
 Local owned cells, edges and vertices. More...
 
Range localEdgesOwned
 
Range localVertsOwned
 
std::vector< double > timeStepVals
 Time values of output timesteps. More...
 

Private Member Functions

ErrorCode write_set_variables (std::vector< WriteNC::VarData > &vsetdatas, std::vector< int > &tstep_nums)
 

Detailed Description

Definition at line 22 of file NCWriteHelper.hpp.

Constructor & Destructor Documentation

◆ NCWriteHelper()

moab::NCWriteHelper::NCWriteHelper ( WriteNC writeNC,
int  fileId,
const FileOptions opts,
EntityHandle  fileSet 
)
inline

Definition at line 25 of file NCWriteHelper.hpp.

26  : _writeNC( writeNC ), _fileId( fileId ), _opts( opts ), _fileSet( fileSet ), nTimeSteps( 0 ), nLevels( 1 ),
27  tDim( -1 ), levDim( -1 )
28  {
29  }

◆ ~NCWriteHelper()

virtual moab::NCWriteHelper::~NCWriteHelper ( )
inlinevirtual

Definition at line 30 of file NCWriteHelper.hpp.

30 {};

Member Function Documentation

◆ collect_mesh_info()

virtual ErrorCode moab::NCWriteHelper::collect_mesh_info ( )
pure virtual

Collect necessary info about local mesh (implemented in child classes)

Implemented in moab::NCWriteMPAS, moab::NCWriteHOMME, moab::ScdNCWriteHelper, and moab::NCWriteGCRM.

Referenced by moab::WriteNC::write_file().

◆ collect_variable_data()

ErrorCode moab::NCWriteHelper::collect_variable_data ( std::vector< std::string > &  var_names,
std::vector< int > &  tstep_nums 
)
virtual

Collect data for specified variables (partially implemented in child classes)

Reimplemented in moab::NCWriteMPAS, moab::NCWriteHOMME, moab::ScdNCWriteHelper, and moab::NCWriteGCRM.

Definition at line 51 of file NCWriteHelper.cpp.

52 {
53  Interface*& mbImpl = _writeNC->mbImpl;
54  std::vector< std::string >& dimNames = _writeNC->dimNames;
55  std::vector< int >& dimLens = _writeNC->dimLens;
56  std::set< std::string >& usedCoordinates = _writeNC->usedCoordinates;
57  std::set< std::string >& dummyVarNames = _writeNC->dummyVarNames;
58  std::map< std::string, WriteNC::VarData >& varInfo = _writeNC->varInfo;
59  DebugOutput& dbgOut = _writeNC->dbgOut;
60 
61  usedCoordinates.clear();
62  if( tstep_nums.empty() && nTimeSteps > 0 )
63  {
64  // No timesteps input, get them all
65  for( int i = 0; i < nTimeSteps; i++ )
66  tstep_nums.push_back( i );
67  }
68 
69  for( size_t i = 0; i < var_names.size(); i++ )
70  {
71  std::string varname = var_names[i];
72  std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( varname );
73  if( vit == varInfo.end() ) MB_SET_ERR( MB_FAILURE, "Can't find variable " << varname );
74 
75  WriteNC::VarData& currentVarData = vit->second;
76 
77  dbgOut.tprintf( 2, " for variable %s varDims.size %d \n", varname.c_str(),
78  (int)currentVarData.varDims.size() );
79  for( size_t j = 0; j < currentVarData.varDims.size(); j++ )
80  {
81  std::string dimName = dimNames[currentVarData.varDims[j]];
82  vit = varInfo.find( dimName );
83  if( vit == varInfo.end() ) MB_SET_ERR( MB_FAILURE, "Can't find coordinate variable " << dimName );
84 
85  usedCoordinates.insert( dimName ); // Collect those used, we will need to write them to the file
86  dbgOut.tprintf( 2, " for variable %s need dimension %s with length %d\n", varname.c_str(),
87  dimName.c_str(), dimLens[currentVarData.varDims[j]] );
88  }
89 
90  // Process coordinate variables later
91  if( usedCoordinates.find( varname ) != usedCoordinates.end() ) continue;
92 
93  // Default has_tsteps is false
94  if( std::find( currentVarData.varDims.begin(), currentVarData.varDims.end(), tDim ) !=
95  currentVarData.varDims.end() )
96  currentVarData.has_tsteps = true;
97 
98  // Default numLev is 0
99  if( ( std::find( currentVarData.varDims.begin(), currentVarData.varDims.end(), levDim ) !=
100  currentVarData.varDims.end() ) )
101  currentVarData.numLev = nLevels;
102 
103  // Process set variables
104  if( WriteNC::ENTLOCSET == currentVarData.entLoc )
105  {
106  if( currentVarData.has_tsteps )
107  {
108  // Set variables with timesteps, e.g. xtime(Time) or xtime(Time, StrLen)
109  // TBD
110  MB_SET_ERR( MB_NOT_IMPLEMENTED, "Writing set variables with timesteps is not implemented yet" );
111  }
112  else
113  {
114  // Get the tag with varname
115  Tag tag = 0;
116  MB_CHK_SET_ERR( mbImpl->tag_get_handle( varname.c_str(), tag ), "Can't find tag " << varname );
117  currentVarData.varTags.push_back( tag ); // Really, only one for these
118  const void* data;
119  int size;
120  MB_CHK_SET_ERR( mbImpl->tag_get_by_ptr( tag, &_fileSet, 1, &data, &size ),
121  "Can't get data of tag " << varname );
122 
123  // Find the type of tag, and use it
124  DataType type;
125  MB_CHK_SET_ERR( mbImpl->tag_get_data_type( tag, type ), "Can't get data type of tag " << varname );
126 
127  currentVarData.varDataType = NC_DOUBLE;
128  if( MB_TYPE_INTEGER == type ) currentVarData.varDataType = NC_INT;
129 
130  assert( 0 == currentVarData.memoryHogs.size() ); // Nothing so far
131  currentVarData.memoryHogs.push_back( (void*)data );
132 
133  if( currentVarData.varDims.empty() )
134  {
135  // Scalar variable
136  currentVarData.writeStarts.push_back( 0 );
137  currentVarData.writeCounts.push_back( 1 );
138  }
139  else
140  {
141  for( size_t j = 0; j < currentVarData.varDims.size(); j++ )
142  {
143  currentVarData.writeStarts.push_back( 0 );
144  currentVarData.writeCounts.push_back( dimLens[currentVarData.varDims[j]] );
145  }
146  }
147 
148  // Get variable size
149  currentVarData.sz = 1;
150  for( std::size_t idx = 0; idx != currentVarData.writeCounts.size(); idx++ )
151  currentVarData.sz *= currentVarData.writeCounts[idx];
152  }
153  } // if (WriteNC::ENTLOCSET == currentVarData.entLoc)
154  // Process non-set variables
155  else
156  {
157  Tag indexedTag = 0;
158 
159  if( currentVarData.has_tsteps )
160  {
161  for( unsigned int t = 0; t < tstep_nums.size(); t++ )
162  {
163  std::stringstream ssTagNameWithIndex;
164  ssTagNameWithIndex << varname << tstep_nums[t];
165  MB_CHK_SET_ERR( mbImpl->tag_get_handle( ssTagNameWithIndex.str().c_str(), indexedTag ),
166  "Can't find tag " << ssTagNameWithIndex.str() );
167  dbgOut.tprintf( 2, " found indexed tag %d with name %s\n", tstep_nums[t],
168  ssTagNameWithIndex.str().c_str() );
169  currentVarData.varTags.push_back( indexedTag );
170  }
171  }
172  else
173  {
174  // This should be a user-created non-set variable without timesteps
175  // Treat it like having one, 0th, timestep
176  std::stringstream ssTagNameWithIndex;
177  ssTagNameWithIndex << varname << 0;
178  MB_CHK_SET_ERR( mbImpl->tag_get_handle( ssTagNameWithIndex.str().c_str(), indexedTag ),
179  "Can't find tag " << ssTagNameWithIndex.str() << " for a user-created variable" );
180  dbgOut.tprintf( 2, " found indexed tag 0 with name %s\n", ssTagNameWithIndex.str().c_str() );
181  currentVarData.varTags.push_back( indexedTag );
182  }
183 
184  // The type of the tag is fixed though
185  DataType type;
186  MB_CHK_SET_ERR( mbImpl->tag_get_data_type( indexedTag, type ), "Can't get data type of tag " << varname );
187 
188  currentVarData.varDataType = NC_DOUBLE;
189  if( MB_TYPE_INTEGER == type ) currentVarData.varDataType = NC_INT;
190  }
191  } // for (size_t i = 0; i < var_names.size(); i++)
192 
193  // Process coordinate variables here
194  // Check that for used coordinates we have found the tags
195  for( std::set< std::string >::iterator setIt = usedCoordinates.begin(); setIt != usedCoordinates.end(); ++setIt )
196  {
197  const std::string& coordName = *setIt;
198 
199  std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( coordName );
200  if( vit == varInfo.end() ) MB_SET_ERR( MB_FAILURE, "Can't find coordinate variable " << coordName );
201 
202  WriteNC::VarData& varCoordData = vit->second;
203  Tag coordTag = 0;
204  MB_CHK_SET_ERR( mbImpl->tag_get_handle( coordName.c_str(), coordTag ), "Can't find tag " << coordName );
205  varCoordData.varTags.push_back( coordTag ); // Really, only one for these
206 
207  const void* data;
208  int sizeCoordinate;
209  MB_CHK_SET_ERR( mbImpl->tag_get_by_ptr( coordTag, &_fileSet, 1, &data, &sizeCoordinate ),
210  "Can't get coordinate values of " << coordName );
211  dbgOut.tprintf( 2, " found coordinate tag with name %s and length %d\n", coordName.c_str(), sizeCoordinate );
212 
213  // Find the type of tag, and use it
214  DataType type;
215  MB_CHK_SET_ERR( mbImpl->tag_get_data_type( coordTag, type ), "Can't get data type of tag " << coordName );
216  varCoordData.varDataType = NC_DOUBLE;
217  if( MB_TYPE_INTEGER == type ) varCoordData.varDataType = NC_INT;
218 
219  // Get dimension length (the only dimension of this coordinate variable, with the same name)
220  assert( 1 == varCoordData.varDims.size() );
221  int coordDimLen = dimLens[varCoordData.varDims[0]];
222 
223  if( dummyVarNames.find( coordName ) != dummyVarNames.end() )
224  {
225  // For a dummy coordinate variable, the tag size is always 1
226  // The number of coordinates should be set to dimension length, instead of 1
227  assert( 1 == sizeCoordinate );
228  sizeCoordinate = coordDimLen;
229 
230  // No variable data to write
231  data = NULL;
232  }
233  else
234  {
235  // The number of coordinates should be exactly the same as dimension length
236  // However, if timesteps spread across files and time tag has been updated,
237  // sizeCoordinate will be larger
238  if( varCoordData.varDims[0] != tDim ) assert( sizeCoordinate == coordDimLen );
239  }
240 
241  // For time, the actual output size and values are determined by tstep_nums
242  if( varCoordData.varDims[0] == tDim )
243  {
244  // Does not apply to dummy time tag (e.g. 'Time' tag of MPAS), when timesteps
245  // spread across files
246  if( NULL != data ) assert( tstep_nums.size() > 0 && tstep_nums.size() <= (size_t)sizeCoordinate );
247 
248  sizeCoordinate = tstep_nums.size();
249 
250  if( NULL != data )
251  {
252  assert( NC_DOUBLE == varCoordData.varDataType );
253  timeStepVals.resize( sizeCoordinate );
254  for( unsigned int t = 0; t < tstep_nums.size(); t++ )
255  timeStepVals[t] = ( (double*)data )[tstep_nums[t]];
256 
257  data = &timeStepVals[0];
258  }
259  }
260 
261  // This is the length
262  varCoordData.sz = sizeCoordinate;
263  varCoordData.writeStarts.resize( 1 );
264  varCoordData.writeStarts[0] = 0;
265  varCoordData.writeCounts.resize( 1 );
266  varCoordData.writeCounts[0] = sizeCoordinate;
267 
268  assert( 0 == varCoordData.memoryHogs.size() ); // Nothing so far
269  varCoordData.memoryHogs.push_back( (void*)data );
270  } // for (std::set<std::string>::iterator setIt ...
271 
272  return MB_SUCCESS;
273 }

References _fileSet, _writeNC, moab::WriteNC::dbgOut, moab::WriteNC::dimLens, moab::WriteNC::dimNames, moab::WriteNC::dummyVarNames, moab::WriteNC::VarData::entLoc, moab::WriteNC::ENTLOCSET, moab::WriteNC::VarData::has_tsteps, levDim, MB_CHK_SET_ERR, MB_NOT_IMPLEMENTED, MB_SET_ERR, MB_SUCCESS, MB_TYPE_INTEGER, moab::WriteNC::mbImpl, moab::WriteNC::VarData::memoryHogs, nLevels, nTimeSteps, moab::WriteNC::VarData::numLev, moab::WriteNC::VarData::sz, moab::Interface::tag_get_by_ptr(), moab::Interface::tag_get_data_type(), moab::Interface::tag_get_handle(), tDim, timeStepVals, moab::DebugOutput::tprintf(), moab::WriteNC::usedCoordinates, moab::WriteNC::VarData::varDataType, moab::WriteNC::VarData::varDims, moab::WriteNC::varInfo, moab::WriteNC::VarData::varTags, moab::WriteNC::VarData::writeCounts, and moab::WriteNC::VarData::writeStarts.

Referenced by moab::NCWriteGCRM::collect_variable_data(), moab::ScdNCWriteHelper::collect_variable_data(), moab::NCWriteHOMME::collect_variable_data(), moab::NCWriteMPAS::collect_variable_data(), and moab::WriteNC::write_file().

◆ get_nc_helper()

NCWriteHelper * moab::NCWriteHelper::get_nc_helper ( WriteNC writeNC,
int  fileId,
const FileOptions opts,
EntityHandle  fileSet 
)
static

Get appropriate helper instance for WriteNC class based on some info in the file set.

Get appropriate helper instance for WriteNC class; based on some info in the file set.

Definition at line 30 of file NCWriteHelper.cpp.

34 {
35  std::string& grid_type = writeNC->grid_type;
36  if( grid_type == "CAM_EUL" )
37  return new( std::nothrow ) NCWriteEuler( writeNC, fileId, opts, fileSet );
38  else if( grid_type == "CAM_FV" )
39  return new( std::nothrow ) NCWriteFV( writeNC, fileId, opts, fileSet );
40  else if( grid_type == "CAM_SE" )
41  return new( std::nothrow ) NCWriteHOMME( writeNC, fileId, opts, fileSet );
42  else if( grid_type == "MPAS" )
43  return new( std::nothrow ) NCWriteMPAS( writeNC, fileId, opts, fileSet );
44  else if( grid_type == "GCRM" )
45  return new( std::nothrow ) NCWriteGCRM( writeNC, fileId, opts, fileSet );
46 
47  // Unknown NetCDF grid
48  return NULL;
49 }

References moab::WriteNC::grid_type.

Referenced by moab::WriteNC::write_file().

◆ init_file()

ErrorCode moab::NCWriteHelper::init_file ( std::vector< std::string > &  var_names,
std::vector< std::string > &  desired_names,
bool  _append 
)

Initialize file: this is where all defines are done The VarData dimension ids are filled up after define.

Definition at line 275 of file NCWriteHelper.cpp.

278 {
279  std::vector< std::string >& dimNames = _writeNC->dimNames;
280  std::set< std::string >& usedCoordinates = _writeNC->usedCoordinates;
281  std::set< std::string >& dummyVarNames = _writeNC->dummyVarNames;
282  std::map< std::string, WriteNC::VarData >& varInfo = _writeNC->varInfo;
283  std::map< std::string, WriteNC::AttData >& globalAtts = _writeNC->globalAtts;
284  DebugOutput& dbgOut = _writeNC->dbgOut;
285 
286  int tDim_in_dimNames = tDim;
287  int levDim_in_dimNames = levDim;
288 
289  // If append mode, make sure we are in define mode; a simple open will not allow creation of new
290  // variables
291  if( append )
292  {
293  int errcode = NCFUNC( redef )( _fileId );
294  if( errcode != NC_NOERR ) MB_SET_ERR( MB_FAILURE, "Can't open file in redefine mode" );
295  }
296 
297  // First initialize all coordinates, then fill VarData for actual variables (and dimensions)
298  // Check that for used coordinates we have found the tags
299  for( std::set< std::string >::iterator setIt = usedCoordinates.begin(); setIt != usedCoordinates.end(); ++setIt )
300  {
301  const std::string& coordName = *setIt;
302 
303  std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( coordName );
304  if( vit == varInfo.end() ) MB_SET_ERR( MB_FAILURE, "Can't find coordinate variable " << coordName );
305 
306  WriteNC::VarData& varCoordData = vit->second;
307  varCoordData.varDims.resize( 1 );
308 
309  // If not append, create it for sure
310  // If append, we might already have it, including the tag / variable with the same name
311  /*
312  * int ncmpi_inq_dimid(int ncid, const char *name, int *idp);
313  */
314  if( append )
315  {
316  int dimId;
317  if( NCFUNC( inq_dimid )( _fileId, coordName.c_str(), &dimId ) == NC_NOERR )
318  { // If not found, create it later
319  varCoordData.varDims[0] = dimId;
320  dbgOut.tprintf( 2, " file already has coordName %s dim id is %d \n", coordName.c_str(),
321  (int)varCoordData.varDims[0] );
322 
323  // Update tDim and levDim to actual dimension id
324  if( coordName == dimNames[tDim_in_dimNames] )
325  tDim = varCoordData.varDims[0];
326  else if( coordName == dimNames[levDim_in_dimNames] )
327  levDim = varCoordData.varDims[0];
328 
329  // Skip dummy coordinate variables (e.g. ncol)
330  if( dummyVarNames.find( coordName ) != dummyVarNames.end() ) continue;
331 
332  // Check that the coordinate is a variable too
333  // Inquire for a variable with the same name
334  int varId;
335  if( NCFUNC( inq_varid )( _fileId, coordName.c_str(), &varId ) != NC_NOERR )
336  MB_SET_ERR( MB_FAILURE, "We do not have a variable with the same name " << coordName );
337  // We should also check that this variable has one dimension, and it is dimId
338  varCoordData.varId = varId;
339  dbgOut.tprintf( 2, " file already has coordinate %s and varId is %d \n", coordName.c_str(), varId );
340 
341  continue; // Maybe more checks are needed here
342  }
343  }
344 
345  /* int nc_def_dim (int ncid, const char *name, size_t len, int *dimidp);
346  * example: status = nc_def_dim(fileId, "lat", 18L, &latid);
347  */
348 
349  // Actually define a dimension
350  if( NCFUNC( def_dim )( _fileId, coordName.c_str(), (size_t)varCoordData.sz, &varCoordData.varDims[0] ) !=
351  NC_NOERR )
352  MB_SET_ERR( MB_FAILURE, "Failed to generate dimension " << coordName );
353  dbgOut.tprintf( 2, " for coordName %s dim id is %d \n", coordName.c_str(), (int)varCoordData.varDims[0] );
354 
355  // Update tDim and levDim to actual dimension id
356  if( coordName == dimNames[tDim_in_dimNames] )
357  tDim = varCoordData.varDims[0];
358  else if( coordName == dimNames[levDim_in_dimNames] )
359  levDim = varCoordData.varDims[0];
360 
361  // Create a variable with the same name, and its only dimension the one we just defined
362  /*
363  * int nc_def_var (int ncid, const char *name, nc_type xtype,
364  int ndims, const int dimids[], int *varidp);
365  example:
366  http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c/nc_005fdef_005fvar.html#nc_005fdef_005fvar
367  */
368 
369  // Skip dummy coordinate variables (e.g. ncol)
370  if( dummyVarNames.find( coordName ) != dummyVarNames.end() ) continue;
371 
372  // Define a coordinate variable
373  if( NCFUNC( def_var )( _fileId, coordName.c_str(), varCoordData.varDataType, 1, &( varCoordData.varDims[0] ),
374  &varCoordData.varId ) != NC_NOERR )
375  MB_SET_ERR( MB_FAILURE, "Failed to create coordinate variable " << coordName );
376 
377  dbgOut.tprintf( 2, " for coordName %s variable id is %d \n", coordName.c_str(), varCoordData.varId );
378  }
379 
380  // Now look at requested variables, and update from the index in dimNames to the actual
381  // dimension id
382  for( size_t i = 0; i < var_names.size(); i++ )
383  {
384  std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( var_names[i] );
385  if( vit == varInfo.end() ) MB_SET_ERR( MB_FAILURE, "Can't find requested variable " << var_names[i] );
386 
387  // Skip coordinate variables
388  if( usedCoordinates.find( var_names[i] ) != usedCoordinates.end() ) continue;
389 
390  WriteNC::VarData& variableData = vit->second;
391 
392  // The index is for dimNames; we need to find out the actual dimension id (from above)
393  int numDims = (int)variableData.varDims.size();
394  for( int j = 0; j < numDims; j++ )
395  {
396  std::string dimName = dimNames[variableData.varDims[j]];
397  std::map< std::string, WriteNC::VarData >::iterator vit2 = varInfo.find( dimName );
398  if( vit2 == varInfo.end() )
399  MB_SET_ERR( MB_FAILURE, "Can't find requested coordinate variable " << dimName );
400 
401  WriteNC::VarData& coordData = vit2->second;
402  // Index in dimNames to actual dimension id
403  variableData.varDims[j] = coordData.varDims[0]; // This one, being a coordinate, is the only one
404  dbgOut.tprintf( 2, " dimension with index %d name %s has ID %d \n", j, dimName.c_str(),
405  variableData.varDims[j] );
406  }
407 
408  // Define the variable now:
409  int errCode =
410  NCFUNC( def_var )( _fileId, desired_names[i].c_str(), variableData.varDataType,
411  (int)variableData.varDims.size(), &( variableData.varDims[0] ), &variableData.varId );
412  if( errCode != NC_NOERR ) MB_SET_ERR( MB_FAILURE, "Failed to create requested variable " << desired_names[i] );
413 
414  dbgOut.tprintf( 2, " for variable %s with desired name %s variable id is %d \n", var_names[i].c_str(),
415  desired_names[i].c_str(), variableData.varId );
416  // Now define the variable, with all dimensions
417  }
418 
419  // Define global attributes (exactly copied from the original file for the time being)
420  // Should we modify some of them (e.g. revision_Id) later?
421  std::map< std::string, WriteNC::AttData >::iterator attIt;
422  for( attIt = globalAtts.begin(); attIt != globalAtts.end(); ++attIt )
423  {
424  const std::string& attName = attIt->first;
425  WriteNC::AttData& attData = attIt->second;
426  NCDF_SIZE& attLen = attData.attLen;
427  nc_type& attDataType = attData.attDataType;
428  const std::string& attValue = attData.attValue;
429 
430  switch( attDataType )
431  {
432  case NC_BYTE:
433  case NC_CHAR:
434  if( NC_NOERR !=
435  NCFUNC( put_att_text )( _fileId, NC_GLOBAL, attName.c_str(), attLen, attValue.c_str() ) )
436  MB_SET_ERR( MB_FAILURE, "Failed to define text type attribute" );
437  break;
438  case NC_DOUBLE:
439  if( NC_NOERR != NCFUNC( put_att_double )( _fileId, NC_GLOBAL, attName.c_str(), NC_DOUBLE, 1,
440  (double*)attValue.c_str() ) )
441  MB_SET_ERR( MB_FAILURE, "Failed to define double type attribute" );
442  break;
443  case NC_FLOAT:
444  if( NC_NOERR != NCFUNC( put_att_float )( _fileId, NC_GLOBAL, attName.c_str(), NC_FLOAT, 1,
445  (float*)attValue.c_str() ) )
446  MB_SET_ERR( MB_FAILURE, "Failed to define float type attribute" );
447  break;
448  case NC_INT:
449  if( NC_NOERR !=
450  NCFUNC( put_att_int )( _fileId, NC_GLOBAL, attName.c_str(), NC_INT, 1, (int*)attValue.c_str() ) )
451  MB_SET_ERR( MB_FAILURE, "Failed to define int type attribute" );
452  break;
453  case NC_SHORT:
454  if( NC_NOERR != NCFUNC( put_att_short )( _fileId, NC_GLOBAL, attName.c_str(), NC_SHORT, 1,
455  (short*)attValue.c_str() ) )
456  MB_SET_ERR( MB_FAILURE, "Failed to define short type attribute" );
457  break;
458  default:
459  MB_SET_ERR( MB_FAILURE, "Unknown attribute data type" );
460  }
461  }
462 
463  // Take it out of define mode
464  if( NC_NOERR != NCFUNC( enddef )( _fileId ) ) MB_SET_ERR( MB_FAILURE, "Failed to close define mode" );
465 
466  return MB_SUCCESS;
467 }

References _fileId, _writeNC, moab::WriteNC::AttData::attDataType, moab::WriteNC::AttData::attLen, moab::WriteNC::AttData::attValue, moab::WriteNC::dbgOut, moab::WriteNC::dimNames, moab::WriteNC::dummyVarNames, moab::WriteNC::globalAtts, levDim, MB_SET_ERR, MB_SUCCESS, NCDF_SIZE, NCFUNC, moab::WriteNC::VarData::sz, tDim, moab::DebugOutput::tprintf(), moab::WriteNC::usedCoordinates, moab::WriteNC::VarData::varDataType, moab::WriteNC::VarData::varDims, moab::WriteNC::VarData::varId, and moab::WriteNC::varInfo.

Referenced by moab::WriteNC::write_file().

◆ write_nonset_variables()

virtual ErrorCode moab::NCWriteHelper::write_nonset_variables ( std::vector< WriteNC::VarData > &  vdatas,
std::vector< int > &  tstep_nums 
)
protectedpure virtual

◆ write_set_variables()

ErrorCode moab::NCWriteHelper::write_set_variables ( std::vector< WriteNC::VarData > &  vsetdatas,
std::vector< int > &  tstep_nums 
)
private

Definition at line 526 of file NCWriteHelper.cpp.

528 {
529  int success;
530 
531  // CAUTION: if the NetCDF ID is from a previous call to ncmpi_create rather than ncmpi_open,
532  // all processors need to call ncmpi_begin_indep_data(). If only the root processor does so,
533  // ncmpi_begin_indep_data() call will be blocked forever :(
534 #ifdef MOAB_HAVE_PNETCDF
535  // Enter independent I/O mode
536  success = NCFUNC( begin_indep_data )( _fileId );
537  if( success ) MB_SET_ERR( MB_FAILURE, "Failed to begin independent I/O mode" );
538 #endif
539 
540  int rank = 0;
541 #ifdef MOAB_HAVE_MPI
542  bool& isParallel = _writeNC->isParallel;
543  if( isParallel )
544  {
545  ParallelComm*& myPcomm = _writeNC->myPcomm;
546  rank = myPcomm->proc_config().proc_rank();
547  }
548 #endif
549  if( 0 == rank )
550  {
551  for( unsigned int i = 0; i < vsetdatas.size(); i++ )
552  {
553  WriteNC::VarData& variableData = vsetdatas[i];
554 
555  // Set variables with timesteps, e.g. xtime(Time) or xtime(Time, StrLen)
556  if( variableData.has_tsteps )
557  {
558  MB_SET_ERR( MB_NOT_IMPLEMENTED, "Writing set variables with timesteps is not implemented yet" );
559  }
560 
561  switch( variableData.varDataType )
562  {
563  case NC_DOUBLE:
564  // Independent I/O mode put
565  success = NCFUNCP( _vara_double )( _fileId, variableData.varId, &variableData.writeStarts[0],
566  &variableData.writeCounts[0],
567  (double*)( variableData.memoryHogs[0] ) );
568  if( success )
569  MB_SET_ERR( MB_FAILURE, "Failed to write double data for variable " << variableData.varName );
570  break;
571  case NC_INT:
572  // Independent I/O mode put
573  success =
574  NCFUNCP( _vara_int )( _fileId, variableData.varId, &variableData.writeStarts[0],
575  &variableData.writeCounts[0], (int*)( variableData.memoryHogs[0] ) );
576  if( success )
577  MB_SET_ERR( MB_FAILURE, "Failed to write int data for variable " << variableData.varName );
578  break;
579  default:
580  MB_SET_ERR( MB_NOT_IMPLEMENTED, "Writing non-double or non-int data is not implemented yet" );
581  }
582  }
583  }
584 
585 #ifdef MOAB_HAVE_PNETCDF
586  // End independent I/O mode
587  success = NCFUNC( end_indep_data )( _fileId );
588  if( success ) MB_SET_ERR( MB_FAILURE, "Failed to end independent I/O mode" );
589 #endif
590 
591  return MB_SUCCESS;
592 }

References _fileId, _writeNC, moab::WriteNC::VarData::has_tsteps, moab::WriteNC::isParallel, MB_NOT_IMPLEMENTED, MB_SET_ERR, MB_SUCCESS, moab::WriteNC::VarData::memoryHogs, NCFUNC, NCFUNCP, moab::ParallelComm::proc_config(), moab::ProcConfig::proc_rank(), moab::WriteNC::VarData::varDataType, moab::WriteNC::VarData::varId, moab::WriteNC::VarData::varName, moab::WriteNC::VarData::writeCounts, and moab::WriteNC::VarData::writeStarts.

Referenced by write_values().

◆ write_values()

ErrorCode moab::NCWriteHelper::write_values ( std::vector< std::string > &  var_names,
std::vector< int > &  tstep_nums 
)

Take the info from VarData and write first non-set variables, then set variables.

Definition at line 469 of file NCWriteHelper.cpp.

470 {
471  std::set< std::string >& usedCoordinates = _writeNC->usedCoordinates;
472  std::set< std::string >& dummyVarNames = _writeNC->dummyVarNames;
473  std::map< std::string, WriteNC::VarData >& varInfo = _writeNC->varInfo;
474 
475  std::vector< WriteNC::VarData > vdatas;
476  std::vector< WriteNC::VarData > vsetdatas;
477 
478  // For set variables, include coordinates used by requested var_names
479  for( std::set< std::string >::iterator setIt = usedCoordinates.begin(); setIt != usedCoordinates.end(); ++setIt )
480  {
481  const std::string& coordName = *setIt;
482 
483  // Skip dummy coordinate variables (if any)
484  if( dummyVarNames.find( coordName ) != dummyVarNames.end() ) continue;
485 
486  std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( coordName );
487  if( vit == varInfo.end() )
488  {
489  MB_SET_ERR( MB_FAILURE, "Can't find coordinate variable " << coordName );
490  }
491 
492  vsetdatas.push_back( vit->second );
493  }
494 
495  // Collect non-set and set variables from requested var_names
496  for( unsigned int i = 0; i < var_names.size(); i++ )
497  {
498  std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( var_names[i] );
499  if( vit == varInfo.end() )
500  {
501  MB_SET_ERR( MB_FAILURE, "Can't find requested variable " << var_names[i] );
502  }
503 
504  WriteNC::VarData& variableData = vit->second;
505  if( WriteNC::ENTLOCSET == variableData.entLoc )
506  {
507  // Used coordinates has all ready been included
508  if( usedCoordinates.find( var_names[i] ) != usedCoordinates.end() ) continue;
509 
510  vsetdatas.push_back( variableData );
511  }
512  else
513  vdatas.push_back( variableData );
514  }
515 
516  // Assume that the data ranges do not overlap across processors
517  // While overlapped writing might still work, we should better not take that risk
518  write_nonset_variables( vdatas, tstep_nums );
519 
520  // Use independent I/O mode put, since this write is only for the root processor
521  write_set_variables( vsetdatas, tstep_nums );
522 
523  return MB_SUCCESS;
524 }

References _writeNC, moab::WriteNC::dummyVarNames, moab::WriteNC::VarData::entLoc, moab::WriteNC::ENTLOCSET, MB_SET_ERR, MB_SUCCESS, moab::WriteNC::usedCoordinates, moab::WriteNC::varInfo, write_nonset_variables(), and write_set_variables().

Referenced by moab::WriteNC::write_file().

Member Data Documentation

◆ _fileId

◆ _fileSet

◆ _opts

const FileOptions& moab::NCWriteHelper::_opts
protected

Definition at line 64 of file NCWriteHelper.hpp.

◆ _writeNC

◆ levDim

◆ localCellsOwned

◆ localEdgesOwned

◆ localVertsOwned

◆ nLevels

◆ nTimeSteps

int moab::NCWriteHelper::nTimeSteps
protected

◆ tDim

◆ timeStepVals

std::vector< double > moab::NCWriteHelper::timeStepVals
protected

Time values of output timesteps.

Definition at line 77 of file NCWriteHelper.hpp.

Referenced by collect_variable_data().


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