Branch data Line data Source code
1 : : /*
2 : : * NCWriteHelper.cpp
3 : : *
4 : : * Created on: Mar 28, 2014
5 : : * Author: iulian
6 : : */
7 : :
8 : : #include "NCWriteHelper.hpp"
9 : : #include "NCWriteEuler.hpp"
10 : : #include "NCWriteFV.hpp"
11 : : #include "NCWriteHOMME.hpp"
12 : : #include "NCWriteMPAS.hpp"
13 : : #include "NCWriteGCRM.hpp"
14 : :
15 : : #include "moab/WriteUtilIface.hpp"
16 : : #include "MBTagConventions.hpp"
17 : :
18 : : #include <sstream>
19 : :
20 : : #ifdef WIN32
21 : : #ifdef size_t
22 : : #undef size_t
23 : : #endif
24 : : #endif
25 : :
26 : : namespace moab
27 : : {
28 : :
29 : : //! Get appropriate helper instance for WriteNC class; based on some info in the file set
30 : 0 : NCWriteHelper* NCWriteHelper::get_nc_helper( WriteNC* writeNC, int fileId, const FileOptions& opts,
31 : : EntityHandle fileSet )
32 : : {
33 : 0 : std::string& grid_type = writeNC->grid_type;
34 [ # # ]: 0 : if( grid_type == "CAM_EUL" )
35 [ # # ][ # # ]: 0 : return new( std::nothrow ) NCWriteEuler( writeNC, fileId, opts, fileSet );
36 [ # # ]: 0 : else if( grid_type == "CAM_FV" )
37 [ # # ][ # # ]: 0 : return new( std::nothrow ) NCWriteFV( writeNC, fileId, opts, fileSet );
38 [ # # ]: 0 : else if( grid_type == "CAM_SE" )
39 [ # # ][ # # ]: 0 : return new( std::nothrow ) NCWriteHOMME( writeNC, fileId, opts, fileSet );
40 [ # # ]: 0 : else if( grid_type == "MPAS" )
41 [ # # ][ # # ]: 0 : return new( std::nothrow ) NCWriteMPAS( writeNC, fileId, opts, fileSet );
42 [ # # ]: 0 : else if( grid_type == "GCRM" )
43 [ # # ][ # # ]: 0 : return new( std::nothrow ) NCWriteGCRM( writeNC, fileId, opts, fileSet );
44 : :
45 : : // Unknown NetCDF grid
46 : 0 : return NULL;
47 : : }
48 : :
49 : 0 : ErrorCode NCWriteHelper::collect_variable_data( std::vector< std::string >& var_names, std::vector< int >& tstep_nums )
50 : : {
51 : 0 : Interface*& mbImpl = _writeNC->mbImpl;
52 : 0 : std::vector< std::string >& dimNames = _writeNC->dimNames;
53 : 0 : std::vector< int >& dimLens = _writeNC->dimLens;
54 : 0 : std::set< std::string >& usedCoordinates = _writeNC->usedCoordinates;
55 : 0 : std::set< std::string >& dummyVarNames = _writeNC->dummyVarNames;
56 : 0 : std::map< std::string, WriteNC::VarData >& varInfo = _writeNC->varInfo;
57 : 0 : DebugOutput& dbgOut = _writeNC->dbgOut;
58 : :
59 : : ErrorCode rval;
60 : :
61 : 0 : usedCoordinates.clear();
62 : :
63 [ # # ][ # # ]: 0 : if( tstep_nums.empty() && nTimeSteps > 0 )
[ # # ]
64 : : {
65 : : // No timesteps input, get them all
66 [ # # ]: 0 : for( int i = 0; i < nTimeSteps; i++ )
67 [ # # ]: 0 : tstep_nums.push_back( i );
68 : : }
69 : :
70 [ # # ]: 0 : for( size_t i = 0; i < var_names.size(); i++ )
71 : : {
72 [ # # ][ # # ]: 0 : std::string varname = var_names[i];
73 [ # # ]: 0 : std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( varname );
74 [ # # ][ # # ]: 0 : if( vit == varInfo.end() ) MB_SET_ERR( MB_FAILURE, "Can't find variable " << varname );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
75 : :
76 [ # # ]: 0 : WriteNC::VarData& currentVarData = vit->second;
77 : :
78 : : dbgOut.tprintf( 2, " for variable %s varDims.size %d \n", varname.c_str(),
79 [ # # ]: 0 : (int)currentVarData.varDims.size() );
80 [ # # ]: 0 : for( size_t j = 0; j < currentVarData.varDims.size(); j++ )
81 : : {
82 [ # # ][ # # ]: 0 : std::string dimName = dimNames[currentVarData.varDims[j]];
[ # # ]
83 [ # # ]: 0 : vit = varInfo.find( dimName );
84 [ # # ][ # # ]: 0 : if( vit == varInfo.end() ) MB_SET_ERR( MB_FAILURE, "Can't find coordinate variable " << dimName );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
85 : :
86 [ # # ]: 0 : usedCoordinates.insert( dimName ); // Collect those used, we will need to write them to the file
87 : : dbgOut.tprintf( 2, " for variable %s need dimension %s with length %d\n", varname.c_str(),
88 [ # # ][ # # ]: 0 : dimName.c_str(), dimLens[currentVarData.varDims[j]] );
[ # # ][ # # ]
89 : 0 : }
90 : :
91 : : // Process coordinate variables later
92 [ # # ][ # # ]: 0 : if( usedCoordinates.find( varname ) != usedCoordinates.end() ) continue;
[ # # ]
93 : :
94 : : // Default has_tsteps is false
95 [ # # ][ # # ]: 0 : if( std::find( currentVarData.varDims.begin(), currentVarData.varDims.end(), tDim ) !=
[ # # ]
96 : 0 : currentVarData.varDims.end() )
97 : 0 : currentVarData.has_tsteps = true;
98 : :
99 : : // Default numLev is 0
100 [ # # ][ # # ]: 0 : if( ( std::find( currentVarData.varDims.begin(), currentVarData.varDims.end(), levDim ) !=
[ # # ]
101 : 0 : currentVarData.varDims.end() ) )
102 : 0 : currentVarData.numLev = nLevels;
103 : :
104 : : // Process set variables
105 [ # # ]: 0 : if( WriteNC::ENTLOCSET == currentVarData.entLoc )
106 : : {
107 [ # # ]: 0 : if( currentVarData.has_tsteps )
108 : : {
109 : : // Set variables with timesteps, e.g. xtime(Time) or xtime(Time, StrLen)
110 : : // TBD
111 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_NOT_IMPLEMENTED, "Writing set variables with timesteps is not implemented yet" );
[ # # ][ # # ]
[ # # ]
112 : : }
113 : : else
114 : : {
115 : : // Get the tag with varname
116 : 0 : Tag tag = 0;
117 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_handle( varname.c_str(), tag );MB_CHK_SET_ERR( rval, "Can't find tag " << varname );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
118 [ # # ]: 0 : currentVarData.varTags.push_back( tag ); // Really, only one for these
119 : : const void* data;
120 : : int size;
121 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_by_ptr( tag, &_fileSet, 1, &data, &size );MB_CHK_SET_ERR( rval, "Can't get data of tag " << varname );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
122 : :
123 : : // Find the type of tag, and use it
124 : : DataType type;
125 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_data_type( tag, type );MB_CHK_SET_ERR( rval, "Can't get data type of tag " << varname );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
126 : :
127 : 0 : currentVarData.varDataType = NC_DOUBLE;
128 [ # # ]: 0 : if( MB_TYPE_INTEGER == type ) currentVarData.varDataType = NC_INT;
129 : :
130 [ # # ]: 0 : assert( 0 == currentVarData.memoryHogs.size() ); // Nothing so far
131 [ # # ]: 0 : currentVarData.memoryHogs.push_back( (void*)data );
132 : :
133 [ # # ]: 0 : if( currentVarData.varDims.empty() )
134 : : {
135 : : // Scalar variable
136 [ # # ]: 0 : currentVarData.writeStarts.push_back( 0 );
137 [ # # ]: 0 : currentVarData.writeCounts.push_back( 1 );
138 : : }
139 : : else
140 : : {
141 [ # # ]: 0 : for( size_t j = 0; j < currentVarData.varDims.size(); j++ )
142 : : {
143 [ # # ]: 0 : currentVarData.writeStarts.push_back( 0 );
144 [ # # ][ # # ]: 0 : currentVarData.writeCounts.push_back( dimLens[currentVarData.varDims[j]] );
[ # # ]
145 : : }
146 : : }
147 : :
148 : : // Get variable size
149 : 0 : currentVarData.sz = 1;
150 [ # # ]: 0 : for( std::size_t idx = 0; idx != currentVarData.writeCounts.size(); idx++ )
151 [ # # ]: 0 : currentVarData.sz *= currentVarData.writeCounts[idx];
152 : : }
153 : : } // if (WriteNC::ENTLOCSET == currentVarData.entLoc)
154 : : // Process non-set variables
155 : : else
156 : : {
157 : 0 : Tag indexedTag = 0;
158 : :
159 [ # # ]: 0 : if( currentVarData.has_tsteps )
160 : : {
161 [ # # ]: 0 : for( unsigned int t = 0; t < tstep_nums.size(); t++ )
162 : : {
163 [ # # ][ # # ]: 0 : std::stringstream ssTagNameWithIndex;
164 [ # # ][ # # ]: 0 : ssTagNameWithIndex << varname << tstep_nums[t];
[ # # ]
165 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_handle( ssTagNameWithIndex.str().c_str(), indexedTag );MB_CHK_SET_ERR( rval, "Can't find tag " << ssTagNameWithIndex.str() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
166 [ # # ]: 0 : dbgOut.tprintf( 2, " found indexed tag %d with name %s\n", tstep_nums[t],
167 [ # # ][ # # ]: 0 : ssTagNameWithIndex.str().c_str() );
168 [ # # ][ # # ]: 0 : currentVarData.varTags.push_back( indexedTag );
169 : 0 : }
170 : : }
171 : : else
172 : : {
173 : : // This should be a user-created non-set variable without timesteps
174 : : // Treat it like having one, 0th, timestep
175 [ # # ][ # # ]: 0 : std::stringstream ssTagNameWithIndex;
176 [ # # ][ # # ]: 0 : ssTagNameWithIndex << varname << 0;
177 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_handle( ssTagNameWithIndex.str().c_str(), indexedTag );MB_CHK_SET_ERR( rval, "Can't find tag " << ssTagNameWithIndex.str() << " for a user-created variable" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
178 [ # # ][ # # ]: 0 : dbgOut.tprintf( 2, " found indexed tag 0 with name %s\n", ssTagNameWithIndex.str().c_str() );
179 [ # # ][ # # ]: 0 : currentVarData.varTags.push_back( indexedTag );
180 : : }
181 : :
182 : : // The type of the tag is fixed though
183 : : DataType type;
184 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_data_type( indexedTag, type );MB_CHK_SET_ERR( rval, "Can't get data type of tag " << varname );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
185 : :
186 : 0 : currentVarData.varDataType = NC_DOUBLE;
187 [ # # ]: 0 : if( MB_TYPE_INTEGER == type ) currentVarData.varDataType = NC_INT;
[ # # # ]
188 : : }
189 : 0 : } // for (size_t i = 0; i < var_names.size(); i++)
190 : :
191 : : // Process coordinate variables here
192 : : // Check that for used coordinates we have found the tags
193 [ # # ][ # # ]: 0 : for( std::set< std::string >::iterator setIt = usedCoordinates.begin(); setIt != usedCoordinates.end(); ++setIt )
[ # # ]
194 : : {
195 [ # # ]: 0 : const std::string& coordName = *setIt;
196 : :
197 [ # # ]: 0 : std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( coordName );
198 [ # # ][ # # ]: 0 : if( vit == varInfo.end() ) MB_SET_ERR( MB_FAILURE, "Can't find coordinate variable " << coordName );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
199 : :
200 [ # # ]: 0 : WriteNC::VarData& varCoordData = vit->second;
201 : 0 : Tag coordTag = 0;
202 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_handle( coordName.c_str(), coordTag );MB_CHK_SET_ERR( rval, "Can't find tag " << coordName );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
203 [ # # ]: 0 : varCoordData.varTags.push_back( coordTag ); // Really, only one for these
204 : :
205 : : const void* data;
206 : : int sizeCoordinate;
207 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_by_ptr( coordTag, &_fileSet, 1, &data, &sizeCoordinate );MB_CHK_SET_ERR( rval, "Can't get coordinate values of " << coordName );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
208 [ # # ]: 0 : dbgOut.tprintf( 2, " found coordinate tag with name %s and length %d\n", coordName.c_str(), sizeCoordinate );
209 : :
210 : : // Find the type of tag, and use it
211 : : DataType type;
212 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_data_type( coordTag, type );MB_CHK_SET_ERR( rval, "Can't get data type of tag " << coordName );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
213 : 0 : varCoordData.varDataType = NC_DOUBLE;
214 [ # # ]: 0 : if( MB_TYPE_INTEGER == type ) varCoordData.varDataType = NC_INT;
215 : :
216 : : // Get dimension length (the only dimension of this coordinate variable, with the same name)
217 [ # # ]: 0 : assert( 1 == varCoordData.varDims.size() );
218 [ # # ][ # # ]: 0 : int coordDimLen = dimLens[varCoordData.varDims[0]];
219 : :
220 [ # # ][ # # ]: 0 : if( dummyVarNames.find( coordName ) != dummyVarNames.end() )
[ # # ]
221 : : {
222 : : // For a dummy coordinate variable, the tag size is always 1
223 : : // The number of coordinates should be set to dimension length, instead of 1
224 [ # # ]: 0 : assert( 1 == sizeCoordinate );
225 : 0 : sizeCoordinate = coordDimLen;
226 : :
227 : : // No variable data to write
228 : 0 : data = NULL;
229 : : }
230 : : else
231 : : {
232 : : // The number of coordinates should be exactly the same as dimension length
233 : : // However, if timesteps spread across files and time tag has been updated,
234 : : // sizeCoordinate will be larger
235 [ # # ][ # # ]: 0 : if( varCoordData.varDims[0] != tDim ) assert( sizeCoordinate == coordDimLen );
[ # # ]
236 : : }
237 : :
238 : : // For time, the actual output size and values are determined by tstep_nums
239 [ # # ][ # # ]: 0 : if( varCoordData.varDims[0] == tDim )
240 : : {
241 : : // Does not apply to dummy time tag (e.g. 'Time' tag of MPAS), when timesteps
242 : : // spread across files
243 [ # # ][ # # ]: 0 : if( NULL != data ) assert( tstep_nums.size() > 0 && tstep_nums.size() <= (size_t)sizeCoordinate );
[ # # ]
244 : :
245 : 0 : sizeCoordinate = tstep_nums.size();
246 : :
247 [ # # ]: 0 : if( NULL != data )
248 : : {
249 [ # # ]: 0 : assert( NC_DOUBLE == varCoordData.varDataType );
250 [ # # ]: 0 : timeStepVals.resize( sizeCoordinate );
251 [ # # ]: 0 : for( unsigned int t = 0; t < tstep_nums.size(); t++ )
252 [ # # ][ # # ]: 0 : timeStepVals[t] = ( (double*)data )[tstep_nums[t]];
253 : :
254 [ # # ]: 0 : data = &timeStepVals[0];
255 : : }
256 : : }
257 : :
258 : : // This is the length
259 : 0 : varCoordData.sz = sizeCoordinate;
260 [ # # ]: 0 : varCoordData.writeStarts.resize( 1 );
261 [ # # ]: 0 : varCoordData.writeStarts[0] = 0;
262 [ # # ]: 0 : varCoordData.writeCounts.resize( 1 );
263 [ # # ]: 0 : varCoordData.writeCounts[0] = sizeCoordinate;
264 : :
265 [ # # ]: 0 : assert( 0 == varCoordData.memoryHogs.size() ); // Nothing so far
266 [ # # ]: 0 : varCoordData.memoryHogs.push_back( (void*)data );
267 : : } // for (std::set<std::string>::iterator setIt ...
268 : :
269 : 0 : return MB_SUCCESS;
270 : : }
271 : :
272 : 0 : ErrorCode NCWriteHelper::init_file( std::vector< std::string >& var_names, std::vector< std::string >& desired_names,
273 : : bool append )
274 : : {
275 : 0 : std::vector< std::string >& dimNames = _writeNC->dimNames;
276 : 0 : std::set< std::string >& usedCoordinates = _writeNC->usedCoordinates;
277 : 0 : std::set< std::string >& dummyVarNames = _writeNC->dummyVarNames;
278 : 0 : std::map< std::string, WriteNC::VarData >& varInfo = _writeNC->varInfo;
279 : 0 : std::map< std::string, WriteNC::AttData >& globalAtts = _writeNC->globalAtts;
280 : 0 : DebugOutput& dbgOut = _writeNC->dbgOut;
281 : :
282 : 0 : int tDim_in_dimNames = tDim;
283 : 0 : int levDim_in_dimNames = levDim;
284 : :
285 : : // If append mode, make sure we are in define mode; a simple open will not allow creation of new
286 : : // variables
287 [ # # ]: 0 : if( append )
288 : : {
289 [ # # ]: 0 : int errcode = NCFUNC( redef )( _fileId );
290 [ # # ][ # # ]: 0 : if( errcode != NC_NOERR ) MB_SET_ERR( MB_FAILURE, "Can't open file in redefine mode" );
[ # # ][ # # ]
[ # # ][ # # ]
291 : : }
292 : :
293 : : // First initialize all coordinates, then fill VarData for actual variables (and dimensions)
294 : : // Check that for used coordinates we have found the tags
295 [ # # ][ # # ]: 0 : for( std::set< std::string >::iterator setIt = usedCoordinates.begin(); setIt != usedCoordinates.end(); ++setIt )
[ # # ]
296 : : {
297 [ # # ]: 0 : const std::string& coordName = *setIt;
298 : :
299 [ # # ]: 0 : std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( coordName );
300 [ # # ][ # # ]: 0 : if( vit == varInfo.end() ) MB_SET_ERR( MB_FAILURE, "Can't find coordinate variable " << coordName );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
301 : :
302 [ # # ]: 0 : WriteNC::VarData& varCoordData = vit->second;
303 [ # # ]: 0 : varCoordData.varDims.resize( 1 );
304 : :
305 : : // If not append, create it for sure
306 : : // If append, we might already have it, including the tag / variable with the same name
307 : : /*
308 : : * int ncmpi_inq_dimid(int ncid, const char *name, int *idp);
309 : : */
310 [ # # ]: 0 : if( append )
311 : : {
312 : : int dimId;
313 [ # # ][ # # ]: 0 : if( NCFUNC( inq_dimid )( _fileId, coordName.c_str(), &dimId ) == NC_NOERR )
314 : : { // If not found, create it later
315 [ # # ]: 0 : varCoordData.varDims[0] = dimId;
316 : : dbgOut.tprintf( 2, " file already has coordName %s dim id is %d \n", coordName.c_str(),
317 [ # # ][ # # ]: 0 : (int)varCoordData.varDims[0] );
318 : :
319 : : // Update tDim and levDim to actual dimension id
320 [ # # ][ # # ]: 0 : if( coordName == dimNames[tDim_in_dimNames] )
[ # # ]
321 [ # # ]: 0 : tDim = varCoordData.varDims[0];
322 [ # # ][ # # ]: 0 : else if( coordName == dimNames[levDim_in_dimNames] )
[ # # ]
323 [ # # ]: 0 : levDim = varCoordData.varDims[0];
324 : :
325 : : // Skip dummy coordinate variables (e.g. ncol)
326 [ # # ][ # # ]: 0 : if( dummyVarNames.find( coordName ) != dummyVarNames.end() ) continue;
[ # # ]
327 : :
328 : : // Check that the coordinate is a variable too
329 : : // Inquire for a variable with the same name
330 : : int varId;
331 [ # # ][ # # ]: 0 : if( NCFUNC( inq_varid )( _fileId, coordName.c_str(), &varId ) != NC_NOERR )
332 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "We do not have a variable with the same name " << coordName );
[ # # ][ # # ]
[ # # ][ # # ]
333 : : // We should also check that this variable has one dimension, and it is dimId
334 : 0 : varCoordData.varId = varId;
335 [ # # ]: 0 : dbgOut.tprintf( 2, " file already has coordinate %s and varId is %d \n", coordName.c_str(), varId );
336 : :
337 : 0 : continue; // Maybe more checks are needed here
338 : : }
339 : : }
340 : :
341 : : /* int nc_def_dim (int ncid, const char *name, size_t len, int *dimidp);
342 : : * example: status = nc_def_dim(fileId, "lat", 18L, &latid);
343 : : */
344 : :
345 : : // Actually define a dimension
346 [ # # ][ # # ]: 0 : if( NCFUNC( def_dim )( _fileId, coordName.c_str(), (size_t)varCoordData.sz, &varCoordData.varDims[0] ) !=
[ # # ]
347 : : NC_NOERR )
348 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Failed to generate dimension " << coordName );
[ # # ][ # # ]
[ # # ][ # # ]
349 [ # # ][ # # ]: 0 : dbgOut.tprintf( 2, " for coordName %s dim id is %d \n", coordName.c_str(), (int)varCoordData.varDims[0] );
350 : :
351 : : // Update tDim and levDim to actual dimension id
352 [ # # ][ # # ]: 0 : if( coordName == dimNames[tDim_in_dimNames] )
[ # # ]
353 [ # # ]: 0 : tDim = varCoordData.varDims[0];
354 [ # # ][ # # ]: 0 : else if( coordName == dimNames[levDim_in_dimNames] )
[ # # ]
355 [ # # ]: 0 : levDim = varCoordData.varDims[0];
356 : :
357 : : // Create a variable with the same name, and its only dimension the one we just defined
358 : : /*
359 : : * int nc_def_var (int ncid, const char *name, nc_type xtype,
360 : : int ndims, const int dimids[], int *varidp);
361 : : example:
362 : : http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c/nc_005fdef_005fvar.html#nc_005fdef_005fvar
363 : : */
364 : :
365 : : // Skip dummy coordinate variables (e.g. ncol)
366 [ # # ][ # # ]: 0 : if( dummyVarNames.find( coordName ) != dummyVarNames.end() ) continue;
[ # # ]
367 : :
368 : : // Define a coordinate variable
369 [ # # ][ # # ]: 0 : if( NCFUNC( def_var )( _fileId, coordName.c_str(), varCoordData.varDataType, 1, &( varCoordData.varDims[0] ),
370 [ # # ]: 0 : &varCoordData.varId ) != NC_NOERR )
371 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Failed to create coordinate variable " << coordName );
[ # # ][ # # ]
[ # # ][ # # ]
372 : :
373 [ # # ]: 0 : dbgOut.tprintf( 2, " for coordName %s variable id is %d \n", coordName.c_str(), varCoordData.varId );
374 : : }
375 : :
376 : : // Now look at requested variables, and update from the index in dimNames to the actual
377 : : // dimension id
378 [ # # ]: 0 : for( size_t i = 0; i < var_names.size(); i++ )
379 : : {
380 [ # # ][ # # ]: 0 : std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( var_names[i] );
381 [ # # ][ # # ]: 0 : if( vit == varInfo.end() ) MB_SET_ERR( MB_FAILURE, "Can't find requested variable " << var_names[i] );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
382 : :
383 : : // Skip coordinate variables
384 [ # # ][ # # ]: 0 : if( usedCoordinates.find( var_names[i] ) != usedCoordinates.end() ) continue;
[ # # ][ # # ]
385 : :
386 [ # # ]: 0 : WriteNC::VarData& variableData = vit->second;
387 : :
388 : : // The index is for dimNames; we need to find out the actual dimension id (from above)
389 : 0 : int numDims = (int)variableData.varDims.size();
390 [ # # ]: 0 : for( int j = 0; j < numDims; j++ )
391 : : {
392 [ # # ][ # # ]: 0 : std::string dimName = dimNames[variableData.varDims[j]];
[ # # ]
393 [ # # ]: 0 : std::map< std::string, WriteNC::VarData >::iterator vit2 = varInfo.find( dimName );
394 [ # # ][ # # ]: 0 : if( vit2 == varInfo.end() )
395 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Can't find requested coordinate variable " << dimName );
[ # # ][ # # ]
[ # # ][ # # ]
396 : :
397 [ # # ]: 0 : WriteNC::VarData& coordData = vit2->second;
398 : : // Index in dimNames to actual dimension id
399 [ # # ][ # # ]: 0 : variableData.varDims[j] = coordData.varDims[0]; // This one, being a coordinate, is the only one
400 : : dbgOut.tprintf( 2, " dimension with index %d name %s has ID %d \n", j, dimName.c_str(),
401 [ # # ][ # # ]: 0 : variableData.varDims[j] );
[ # # ]
402 : 0 : }
403 : :
404 : : // Define the variable now:
405 : : int errCode =
406 [ # # ]: 0 : NCFUNC( def_var )( _fileId, desired_names[i].c_str(), variableData.varDataType,
407 [ # # ][ # # ]: 0 : (int)variableData.varDims.size(), &( variableData.varDims[0] ), &variableData.varId );
408 [ # # ][ # # ]: 0 : if( errCode != NC_NOERR ) MB_SET_ERR( MB_FAILURE, "Failed to create requested variable " << desired_names[i] );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
409 : :
410 [ # # ]: 0 : dbgOut.tprintf( 2, " for variable %s with desired name %s variable id is %d \n", var_names[i].c_str(),
411 [ # # ][ # # ]: 0 : desired_names[i].c_str(), variableData.varId );
412 : : // Now define the variable, with all dimensions
413 : : }
414 : :
415 : : // Define global attributes (exactly copied from the original file for the time being)
416 : : // Should we modify some of them (e.g. revision_Id) later?
417 [ # # ]: 0 : std::map< std::string, WriteNC::AttData >::iterator attIt;
418 [ # # ][ # # ]: 0 : for( attIt = globalAtts.begin(); attIt != globalAtts.end(); ++attIt )
[ # # ]
419 : : {
420 [ # # ]: 0 : const std::string& attName = attIt->first;
421 [ # # ]: 0 : WriteNC::AttData& attData = attIt->second;
422 : 0 : NCDF_SIZE& attLen = attData.attLen;
423 : 0 : nc_type& attDataType = attData.attDataType;
424 : 0 : const std::string& attValue = attData.attValue;
425 : :
426 [ # # # # : 0 : switch( attDataType )
# # ]
427 : : {
428 : : case NC_BYTE:
429 : : case NC_CHAR:
430 [ # # ]: 0 : if( NC_NOERR !=
431 [ # # ]: 0 : NCFUNC( put_att_text )( _fileId, NC_GLOBAL, attName.c_str(), attLen, attValue.c_str() ) )
432 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Failed to define text type attribute" );
[ # # ][ # # ]
[ # # ]
433 : 0 : break;
434 : : case NC_DOUBLE:
435 [ # # ]: 0 : if( NC_NOERR != NCFUNC( put_att_double )( _fileId, NC_GLOBAL, attName.c_str(), NC_DOUBLE, 1,
436 [ # # ]: 0 : (double*)attValue.c_str() ) )
437 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Failed to define double type attribute" );
[ # # ][ # # ]
[ # # ]
438 : 0 : break;
439 : : case NC_FLOAT:
440 [ # # ]: 0 : if( NC_NOERR != NCFUNC( put_att_float )( _fileId, NC_GLOBAL, attName.c_str(), NC_FLOAT, 1,
441 [ # # ]: 0 : (float*)attValue.c_str() ) )
442 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Failed to define float type attribute" );
[ # # ][ # # ]
[ # # ]
443 : 0 : break;
444 : : case NC_INT:
445 [ # # ]: 0 : if( NC_NOERR !=
446 [ # # ]: 0 : NCFUNC( put_att_int )( _fileId, NC_GLOBAL, attName.c_str(), NC_INT, 1, (int*)attValue.c_str() ) )
447 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Failed to define int type attribute" );
[ # # ][ # # ]
[ # # ]
448 : 0 : break;
449 : : case NC_SHORT:
450 [ # # ]: 0 : if( NC_NOERR != NCFUNC( put_att_short )( _fileId, NC_GLOBAL, attName.c_str(), NC_SHORT, 1,
451 [ # # ]: 0 : (short*)attValue.c_str() ) )
452 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Failed to define short type attribute" );
[ # # ][ # # ]
[ # # ]
453 : 0 : break;
454 : : default:
455 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Unknown attribute data type" );
[ # # ][ # # ]
[ # # ]
456 : : }
457 : : }
458 : :
459 : : // Take it out of define mode
460 [ # # ][ # # ]: 0 : if( NC_NOERR != NCFUNC( enddef )( _fileId ) ) MB_SET_ERR( MB_FAILURE, "Failed to close define mode" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
461 : :
462 : 0 : return MB_SUCCESS;
463 : : }
464 : :
465 : 0 : ErrorCode NCWriteHelper::write_values( std::vector< std::string >& var_names, std::vector< int >& tstep_nums )
466 : : {
467 : 0 : std::set< std::string >& usedCoordinates = _writeNC->usedCoordinates;
468 : 0 : std::set< std::string >& dummyVarNames = _writeNC->dummyVarNames;
469 : 0 : std::map< std::string, WriteNC::VarData >& varInfo = _writeNC->varInfo;
470 : :
471 [ # # ]: 0 : std::vector< WriteNC::VarData > vdatas;
472 [ # # ]: 0 : std::vector< WriteNC::VarData > vsetdatas;
473 : :
474 : : // For set variables, include coordinates used by requested var_names
475 [ # # ][ # # ]: 0 : for( std::set< std::string >::iterator setIt = usedCoordinates.begin(); setIt != usedCoordinates.end(); ++setIt )
[ # # ]
476 : : {
477 [ # # ]: 0 : const std::string& coordName = *setIt;
478 : :
479 : : // Skip dummy coordinate variables (if any)
480 [ # # ][ # # ]: 0 : if( dummyVarNames.find( coordName ) != dummyVarNames.end() ) continue;
[ # # ]
481 : :
482 [ # # ]: 0 : std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( coordName );
483 [ # # ][ # # ]: 0 : if( vit == varInfo.end() ) { MB_SET_ERR( MB_FAILURE, "Can't find coordinate variable " << coordName ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
484 : :
485 [ # # ][ # # ]: 0 : vsetdatas.push_back( vit->second );
486 : : }
487 : :
488 : : // Collect non-set and set variables from requested var_names
489 [ # # ]: 0 : for( unsigned int i = 0; i < var_names.size(); i++ )
490 : : {
491 [ # # ][ # # ]: 0 : std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( var_names[i] );
492 [ # # ][ # # ]: 0 : if( vit == varInfo.end() ) { MB_SET_ERR( MB_FAILURE, "Can't find requested variable " << var_names[i] ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
493 : :
494 [ # # ]: 0 : WriteNC::VarData& variableData = vit->second;
495 [ # # ]: 0 : if( WriteNC::ENTLOCSET == variableData.entLoc )
496 : : {
497 : : // Used coordinates has all ready been included
498 [ # # ][ # # ]: 0 : if( usedCoordinates.find( var_names[i] ) != usedCoordinates.end() ) continue;
[ # # ][ # # ]
499 : :
500 [ # # ]: 0 : vsetdatas.push_back( variableData );
501 : : }
502 : : else
503 [ # # ]: 0 : vdatas.push_back( variableData );
504 : : }
505 : :
506 : : // Assume that the data ranges do not overlap across processors
507 : : // While overlapped writing might still work, we should better not take that risk
508 [ # # ]: 0 : write_nonset_variables( vdatas, tstep_nums );
509 : :
510 : : // Use independent I/O mode put, since this write is only for the root processor
511 [ # # ]: 0 : write_set_variables( vsetdatas, tstep_nums );
512 : :
513 : 0 : return MB_SUCCESS;
514 : : }
515 : :
516 : 0 : ErrorCode NCWriteHelper::write_set_variables( std::vector< WriteNC::VarData >& vsetdatas,
517 : : std::vector< int >& /* tstep_nums */ )
518 : : {
519 : : int success;
520 : :
521 : : // CAUTION: if the NetCDF ID is from a previous call to ncmpi_create rather than ncmpi_open,
522 : : // all processors need to call ncmpi_begin_indep_data(). If only the root processor does so,
523 : : // ncmpi_begin_indep_data() call will be blocked forever :(
524 : : #ifdef MOAB_HAVE_PNETCDF
525 : : // Enter independent I/O mode
526 : : success = NCFUNC( begin_indep_data )( _fileId );
527 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to begin independent I/O mode" );
528 : : #endif
529 : :
530 : 0 : int rank = 0;
531 : : #ifdef MOAB_HAVE_MPI
532 : 0 : bool& isParallel = _writeNC->isParallel;
533 [ # # ]: 0 : if( isParallel )
534 : : {
535 : 0 : ParallelComm*& myPcomm = _writeNC->myPcomm;
536 : 0 : rank = myPcomm->proc_config().proc_rank();
537 : : }
538 : : #endif
539 [ # # ]: 0 : if( 0 == rank )
540 : : {
541 [ # # ]: 0 : for( unsigned int i = 0; i < vsetdatas.size(); i++ )
542 : : {
543 : 0 : WriteNC::VarData& variableData = vsetdatas[i];
544 : :
545 : : // Set variables with timesteps, e.g. xtime(Time) or xtime(Time, StrLen)
546 [ # # ]: 0 : if( variableData.has_tsteps )
547 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_NOT_IMPLEMENTED, "Writing set variables with timesteps is not implemented yet" ); }
[ # # ][ # # ]
[ # # ]
548 : :
549 [ # # # ]: 0 : switch( variableData.varDataType )
550 : : {
551 : : case NC_DOUBLE:
552 : : // Independent I/O mode put
553 : 0 : success = NCFUNCP( _vara_double )( _fileId, variableData.varId, &variableData.writeStarts[0],
554 : 0 : &variableData.writeCounts[0],
555 : 0 : (double*)( variableData.memoryHogs[0] ) );
556 [ # # ]: 0 : if( success )
557 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Failed to write double data for variable " << variableData.varName );
[ # # ][ # # ]
[ # # ][ # # ]
558 : 0 : break;
559 : : case NC_INT:
560 : : // Independent I/O mode put
561 : : success =
562 : 0 : NCFUNCP( _vara_int )( _fileId, variableData.varId, &variableData.writeStarts[0],
563 : 0 : &variableData.writeCounts[0], (int*)( variableData.memoryHogs[0] ) );
564 [ # # ]: 0 : if( success )
565 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Failed to write int data for variable " << variableData.varName );
[ # # ][ # # ]
[ # # ][ # # ]
566 : 0 : break;
567 : : default:
568 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_NOT_IMPLEMENTED, "Writing non-double or non-int data is not implemented yet" );
[ # # ][ # # ]
[ # # ]
569 : : }
570 : : }
571 : : }
572 : :
573 : : #ifdef MOAB_HAVE_PNETCDF
574 : : // End independent I/O mode
575 : : success = NCFUNC( end_indep_data )( _fileId );
576 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to end independent I/O mode" );
577 : : #endif
578 : :
579 : 0 : return MB_SUCCESS;
580 : : }
581 : :
582 : 0 : ErrorCode ScdNCWriteHelper::collect_mesh_info()
583 : : {
584 : 0 : Interface*& mbImpl = _writeNC->mbImpl;
585 : 0 : std::vector< std::string >& dimNames = _writeNC->dimNames;
586 : 0 : std::vector< int >& dimLens = _writeNC->dimLens;
587 : :
588 : : ErrorCode rval;
589 : :
590 : : // Look for time dimension
591 : 0 : std::vector< std::string >::iterator vecIt;
592 [ # # ][ # # ]: 0 : if( ( vecIt = std::find( dimNames.begin(), dimNames.end(), "time" ) ) != dimNames.end() )
[ # # ]
593 [ # # ]: 0 : tDim = vecIt - dimNames.begin();
594 [ # # ][ # # ]: 0 : else if( ( vecIt = std::find( dimNames.begin(), dimNames.end(), "t" ) ) != dimNames.end() )
[ # # ]
595 [ # # ]: 0 : tDim = vecIt - dimNames.begin();
596 : : else
597 : : {
598 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Couldn't find 'time' or 't' dimension" );
[ # # ][ # # ]
[ # # ]
599 : : }
600 [ # # ]: 0 : nTimeSteps = dimLens[tDim];
601 : :
602 : : // Get number of levels
603 [ # # ][ # # ]: 0 : if( ( vecIt = std::find( dimNames.begin(), dimNames.end(), "lev" ) ) != dimNames.end() )
[ # # ]
604 [ # # ]: 0 : levDim = vecIt - dimNames.begin();
605 [ # # ][ # # ]: 0 : else if( ( vecIt = std::find( dimNames.begin(), dimNames.end(), "ilev" ) ) != dimNames.end() )
[ # # ]
606 [ # # ]: 0 : levDim = vecIt - dimNames.begin();
607 : : else
608 : : {
609 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Couldn't find 'lev' or 'ilev' dimension" );
[ # # ][ # # ]
[ # # ]
610 : : }
611 [ # # ]: 0 : nLevels = dimLens[levDim];
612 : :
613 : : // __<dim_name>_LOC_MINMAX (for slon, slat, lon and lat)
614 : 0 : Tag convTag = 0;
615 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_handle( "__slon_LOC_MINMAX", 0, MB_TYPE_INTEGER, convTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag __slon_LOC_MINMAX" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
616 : : int val[2];
617 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_data( convTag, &_fileSet, 1, val );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag __slon_LOC_MINMAX" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
618 : 0 : lDims[0] = val[0];
619 : 0 : lDims[3] = val[1];
620 : :
621 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_handle( "__slat_LOC_MINMAX", 0, MB_TYPE_INTEGER, convTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag __slat_LOC_MINMAX" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
622 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_data( convTag, &_fileSet, 1, val );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag __slat_LOC_MINMAX" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
623 : 0 : lDims[1] = val[0];
624 : 0 : lDims[4] = val[1];
625 : :
626 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_handle( "__lon_LOC_MINMAX", 0, MB_TYPE_INTEGER, convTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag __lon_LOC_MINMAX" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
627 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_data( convTag, &_fileSet, 1, val );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag __lon_LOC_MINMAX" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
628 : 0 : lCDims[0] = val[0];
629 : 0 : lCDims[3] = val[1];
630 : :
631 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_handle( "__lat_LOC_MINMAX", 0, MB_TYPE_INTEGER, convTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag __lat_LOC_MINMAX" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
632 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_data( convTag, &_fileSet, 1, val );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag __lat_LOC_MINMAX" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
633 : 0 : lCDims[1] = val[0];
634 : 0 : lCDims[4] = val[1];
635 : :
636 : : // Get local faces
637 [ # # ][ # # ]: 0 : rval = mbImpl->get_entities_by_dimension( _fileSet, 2, localCellsOwned );MB_CHK_SET_ERR( rval, "Trouble getting local faces in current file set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
638 [ # # ][ # # ]: 0 : assert( !localCellsOwned.empty() );
639 : :
640 : : #ifdef MOAB_HAVE_MPI
641 : 0 : bool& isParallel = _writeNC->isParallel;
642 [ # # ]: 0 : if( isParallel )
643 : : {
644 : 0 : ParallelComm*& myPcomm = _writeNC->myPcomm;
645 [ # # ][ # # ]: 0 : int procs = myPcomm->proc_config().proc_size();
646 [ # # ]: 0 : if( procs > 1 )
647 : : {
648 [ # # ][ # # ]: 0 : rval = myPcomm->filter_pstatus( localCellsOwned, PSTATUS_NOT_OWNED, PSTATUS_NOT );MB_CHK_SET_ERR( rval, "Trouble getting owned faces in current file set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
649 : : }
650 : : }
651 : : #endif
652 : :
653 : 0 : return MB_SUCCESS;
654 : : }
655 : :
656 : 0 : ErrorCode ScdNCWriteHelper::collect_variable_data( std::vector< std::string >& var_names,
657 : : std::vector< int >& tstep_nums )
658 : : {
659 : 0 : NCWriteHelper::collect_variable_data( var_names, tstep_nums );
660 : :
661 : 0 : std::map< std::string, WriteNC::VarData >& varInfo = _writeNC->varInfo;
662 : :
663 [ # # ]: 0 : for( size_t i = 0; i < var_names.size(); i++ )
664 : : {
665 [ # # ][ # # ]: 0 : std::string varname = var_names[i];
666 [ # # ]: 0 : std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( varname );
667 [ # # ][ # # ]: 0 : if( vit == varInfo.end() ) MB_SET_ERR( MB_FAILURE, "Can't find variable " << varname );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
668 : :
669 [ # # ]: 0 : WriteNC::VarData& currentVarData = vit->second;
670 : : #ifndef NDEBUG
671 : 0 : std::vector< int >& varDims = currentVarData.varDims;
672 : : #endif
673 : :
674 : : // Skip set variables, which were already processed in
675 : : // NCWriteHelper::collect_variable_data()
676 [ # # ]: 0 : if( WriteNC::ENTLOCSET == currentVarData.entLoc ) continue;
677 : :
678 : : // Set up writeStarts and writeCounts (maximum number of dimensions is 4)
679 [ # # ]: 0 : currentVarData.writeStarts.resize( 4 );
680 [ # # ]: 0 : currentVarData.writeCounts.resize( 4 );
681 : 0 : unsigned int dim_idx = 0;
682 : :
683 : : // First: time
684 [ # # ]: 0 : if( currentVarData.has_tsteps )
685 : : {
686 : : // Non-set variables with timesteps
687 : : // 4 dimensions like (time, lev, lat, lon)
688 : : // 3 dimensions like (time, lat, lon)
689 [ # # ][ # # ]: 0 : assert( 4 == varDims.size() || 3 == varDims.size() );
690 : :
691 : : // Time should be the first dimension
692 [ # # ][ # # ]: 0 : assert( tDim == varDims[0] );
693 : :
694 [ # # ]: 0 : currentVarData.writeStarts[dim_idx] = 0; // This value is timestep dependent, will be set later
695 [ # # ]: 0 : currentVarData.writeCounts[dim_idx] = 1;
696 : 0 : dim_idx++;
697 : : }
698 : : else
699 : : {
700 : : // Non-set variables without timesteps
701 : : // 3 dimensions like (lev, lat, lon)
702 : : // 2 dimensions like (lat, lon)
703 [ # # ][ # # ]: 0 : assert( 3 == varDims.size() || 2 == varDims.size() );
704 : : }
705 : :
706 : : // Next: lev
707 [ # # ]: 0 : if( currentVarData.numLev > 0 )
708 : : {
709 : : // Non-set variables with levels
710 : : // 4 dimensions like (time, lev, lat, lon)
711 : : // 3 dimensions like (lev, lat, lon)
712 [ # # ][ # # ]: 0 : assert( 4 == varDims.size() || 3 == varDims.size() );
713 : :
714 [ # # ]: 0 : currentVarData.writeStarts[dim_idx] = 0;
715 [ # # ]: 0 : currentVarData.writeCounts[dim_idx] = currentVarData.numLev;
716 : 0 : dim_idx++;
717 : : }
718 : : else
719 : : {
720 : : // Non-set variables without levels
721 : : // 3 dimensions like (time, lat, lon)
722 : : // 2 dimensions like (lat, lon)
723 [ # # ][ # # ]: 0 : assert( 3 == varDims.size() || 2 == varDims.size() );
724 : : }
725 : :
726 : : // Finally: lat and lon
727 [ # # ]: 0 : switch( currentVarData.entLoc )
728 : : {
729 : : case WriteNC::ENTLOCFACE:
730 : : // Faces
731 [ # # ]: 0 : currentVarData.writeStarts[dim_idx] = lCDims[1];
732 [ # # ]: 0 : currentVarData.writeCounts[dim_idx] = lCDims[4] - lCDims[1] + 1;
733 [ # # ]: 0 : currentVarData.writeStarts[dim_idx + 1] = lCDims[0];
734 [ # # ]: 0 : currentVarData.writeCounts[dim_idx + 1] = lCDims[3] - lCDims[0] + 1;
735 : 0 : break;
736 : : default:
737 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Unexpected entity location type for variable " << varname );
[ # # ][ # # ]
[ # # ][ # # ]
738 : : }
739 : 0 : dim_idx += 2;
740 : :
741 : : // Get variable size
742 : 0 : currentVarData.sz = 1;
743 [ # # ]: 0 : for( std::size_t idx = 0; idx < dim_idx; idx++ )
[ # # # ]
744 [ # # ]: 0 : currentVarData.sz *= currentVarData.writeCounts[idx];
745 : 0 : } // for (size_t i = 0; i < var_names.size(); i++)
746 : :
747 : 0 : return MB_SUCCESS;
748 : : }
749 : :
750 : : // Write CAM-EUL and CAM-FV non-set variables on non-shared quads (e.g. T)
751 : : // We assume that there are no variables on vertices and we do not support
752 : : // variables on edges (e.g. US in CAM-FV) for the time being
753 : 0 : ErrorCode ScdNCWriteHelper::write_nonset_variables( std::vector< WriteNC::VarData >& vdatas,
754 : : std::vector< int >& tstep_nums )
755 : : {
756 : 0 : Interface*& mbImpl = _writeNC->mbImpl;
757 : :
758 : : int success;
759 : :
760 : : // For each indexed variable tag, write a time step data
761 [ # # ]: 0 : for( unsigned int i = 0; i < vdatas.size(); i++ )
762 : : {
763 : 0 : WriteNC::VarData& variableData = vdatas[i];
764 : :
765 : : // Assume this variable is on faces for the time being
766 [ # # ]: 0 : switch( variableData.entLoc )
767 : : {
768 : : case WriteNC::ENTLOCFACE:
769 : : // Faces
770 : 0 : break;
771 : : default:
772 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Unexpected entity location type for variable " << variableData.varName );
[ # # ][ # # ]
[ # # ][ # # ]
773 : : }
774 : :
775 : : unsigned int num_timesteps;
776 : 0 : unsigned int lat_idx = 0;
777 : 0 : unsigned int lon_idx = 1;
778 [ # # ]: 0 : if( variableData.has_tsteps )
779 : : {
780 : : // Non-set variables with timesteps
781 : : // 4 dimensions like (time, lev, lat, lon)
782 : : // 3 dimensions like (time, lat, lon)
783 : 0 : num_timesteps = tstep_nums.size();
784 : 0 : lat_idx++;
785 : 0 : lon_idx++;
786 : : }
787 : : else
788 : : {
789 : : // Non-set variables without timesteps
790 : : // 3 dimensions like (lev, lat, lon)
791 : : // 2 dimensions like (lat, lon)
792 : 0 : num_timesteps = 1;
793 : : }
794 : :
795 : : unsigned int num_lev;
796 [ # # ]: 0 : if( variableData.numLev > 0 )
797 : : {
798 : : // Non-set variables with levels
799 : : // 4 dimensions like (time, lev, lat, lon)
800 : : // 3 dimensions like (lev, lat, lon)
801 : 0 : num_lev = variableData.numLev;
802 : 0 : lat_idx++;
803 : 0 : lon_idx++;
804 : : }
805 : : else
806 : : {
807 : : // Non-set variables without levels
808 : : // 3 dimensions like (time, lat, lon)
809 : : // 2 dimensions like (lat, lon)
810 : 0 : num_lev = 1;
811 : : }
812 : :
813 : 0 : size_t ni = variableData.writeCounts[lon_idx]; // lon
814 : 0 : size_t nj = variableData.writeCounts[lat_idx]; // lat
815 : :
816 : : // At each timestep, we need to transpose tag format (lat, lon, lev) back
817 : : // to NC format (lev, lat, lon) for writing
818 [ # # ]: 0 : for( unsigned int t = 0; t < num_timesteps; t++ )
819 : : {
820 : : // We will write one time step, and count will be one; start will be different
821 : : // Use tag_iterate to get tag data (assume that localCellsOwned is contiguous)
822 : : // We should also transpose for level so that means deep copy for transpose
823 [ # # ][ # # ]: 0 : if( tDim == variableData.varDims[0] ) variableData.writeStarts[0] = t; // This is start for time
[ # # ]
824 : : int count;
825 : : void* dataptr;
826 [ # # ]: 0 : ErrorCode rval = mbImpl->tag_iterate( variableData.varTags[t], localCellsOwned.begin(),
827 [ # # ][ # # ]: 0 : localCellsOwned.end(), count, dataptr );MB_CHK_SET_ERR( rval, "Failed to iterate tag on owned faces" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
828 [ # # ][ # # ]: 0 : assert( count == (int)localCellsOwned.size() );
829 : :
830 : : // Now transpose and write tag data
831 : : // Use collective I/O mode put (synchronous write) for the time being, we can try
832 : : // nonblocking put (request aggregation) later
833 [ # # ]: 0 : switch( variableData.varDataType )
834 : : {
835 : : case NC_DOUBLE: {
836 [ # # ]: 0 : std::vector< double > tmpdoubledata( ni * nj * num_lev );
837 [ # # ]: 0 : if( num_lev > 1 )
838 : : // Transpose (lat, lon, lev) back to (lev, lat, lon)
839 [ # # ][ # # ]: 0 : jik_to_kji( ni, nj, num_lev, &tmpdoubledata[0], (double*)( dataptr ) );
840 [ # # ]: 0 : success = NCFUNCAP( _vara_double )( _fileId, variableData.varId, &variableData.writeStarts[0],
841 [ # # ][ # # ]: 0 : &variableData.writeCounts[0], &tmpdoubledata[0] );
[ # # ]
842 [ # # ]: 0 : if( success )
843 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Failed to write double data for variable " << variableData.varName );
[ # # ][ # # ]
[ # # ][ # # ]
844 [ # # ]: 0 : break;
845 : : }
846 : : default:
847 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_NOT_IMPLEMENTED, "Writing non-double data is not implemented yet" );
[ # # ][ # # ]
[ # # ]
848 : : }
849 : : }
850 : : }
851 : :
852 : 0 : return MB_SUCCESS;
853 : : }
854 : :
855 [ + - ][ + - ]: 228 : } /* namespace moab */
|