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...
 
virtual 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. Virtual so that grid-output writers (NCWriteScrip / NCWriteESMF / NCWriteDomain) can synthesize a fresh schema from mesh state instead of going through the climate var_names plumbing. More...
 
virtual 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. Virtual for the same reason as init_file. More...
 

Static Public Member Functions

static NCWriteHelper * get_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::NCWriteScrip, moab::ScdNCWriteHelper, moab::NCWriteESMF, moab::NCWriteDomain, moab::NCWriteMPAS, moab::NCWriteHOMME, 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::ScdNCWriteHelper, moab::NCWriteMPAS, moab::NCWriteHOMME, and moab::NCWriteGCRM.

Definition at line 60 of file NCWriteHelper.cpp.

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

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::NCWriteHOMME::collect_variable_data(), moab::NCWriteMPAS::collect_variable_data(), moab::ScdNCWriteHelper::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 33 of file NCWriteHelper.cpp.

37 {
38  std::string& grid_type = writeNC->grid_type;
39  if( grid_type == "CAM_EUL" )
40  return new( std::nothrow ) NCWriteEuler( writeNC, fileId, opts, fileSet );
41  else if( grid_type == "CAM_FV" )
42  return new( std::nothrow ) NCWriteFV( writeNC, fileId, opts, fileSet );
43  else if( grid_type == "CAM_SE" )
44  return new( std::nothrow ) NCWriteHOMME( writeNC, fileId, opts, fileSet );
45  else if( grid_type == "MPAS" )
46  return new( std::nothrow ) NCWriteMPAS( writeNC, fileId, opts, fileSet );
47  else if( grid_type == "GCRM" )
48  return new( std::nothrow ) NCWriteGCRM( writeNC, fileId, opts, fileSet );
49  else if( grid_type == "SCRIP" )
50  return new( std::nothrow ) NCWriteScrip( writeNC, fileId, opts, fileSet );
51  else if( grid_type == "ESMF" )
52  return new( std::nothrow ) NCWriteESMF( writeNC, fileId, opts, fileSet );
53  else if( grid_type == "DOMAIN" )
54  return new( std::nothrow ) NCWriteDomain( writeNC, fileId, opts, fileSet );
55 
56  // Unknown NetCDF grid
57  return NULL;
58 }

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 
)
virtual

Initialize file: this is where all defines are done. Virtual so that grid-output writers (NCWriteScrip / NCWriteESMF / NCWriteDomain) can synthesize a fresh schema from mesh state instead of going through the climate var_names plumbing.

Reimplemented in moab::NCWriteScrip, moab::NCWriteESMF, and moab::NCWriteDomain.

Definition at line 284 of file NCWriteHelper.cpp.

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

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 535 of file NCWriteHelper.cpp.

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

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 
)
virtual

Take the info from VarData and write first non-set variables, then set variables. Virtual for the same reason as init_file.

Reimplemented in moab::NCWriteScrip, moab::NCWriteESMF, and moab::NCWriteDomain.

Definition at line 478 of file NCWriteHelper.cpp.

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

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 67 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 80 of file NCWriteHelper.hpp.

Referenced by collect_variable_data().


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