![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /*
00002 * NCWriteHOMME.cpp
00003 *
00004 * Created on: April 9, 2014
00005 */
00006
00007 #include "NCWriteHOMME.hpp"
00008 #include "MBTagConventions.hpp"
00009
00010 namespace moab
00011 {
00012
00013 NCWriteHOMME::~NCWriteHOMME()
00014 {
00015 // TODO Auto-generated destructor stub
00016 }
00017
00018 ErrorCode NCWriteHOMME::collect_mesh_info()
00019 {
00020 Interface*& mbImpl = _writeNC->mbImpl;
00021 std::vector< std::string >& dimNames = _writeNC->dimNames;
00022 std::vector< int >& dimLens = _writeNC->dimLens;
00023 Tag& mGlobalIdTag = _writeNC->mGlobalIdTag;
00024
00025 ErrorCode rval;
00026
00027 // Look for time dimension
00028 std::vector< std::string >::iterator vecIt;
00029 if( ( vecIt = std::find( dimNames.begin(), dimNames.end(), "time" ) ) != dimNames.end() )
00030 tDim = vecIt - dimNames.begin();
00031 else
00032 {
00033 MB_SET_ERR( MB_FAILURE, "Couldn't find 'time' dimension" );
00034 }
00035 nTimeSteps = dimLens[tDim];
00036
00037 // Get number of levels
00038 if( ( vecIt = std::find( dimNames.begin(), dimNames.end(), "lev" ) ) != dimNames.end() )
00039 levDim = vecIt - dimNames.begin();
00040 else
00041 {
00042 MB_SET_ERR( MB_FAILURE, "Couldn't find 'lev' dimension" );
00043 }
00044 nLevels = dimLens[levDim];
00045
00046 // Get local vertices
00047 rval = mbImpl->get_entities_by_dimension( _fileSet, 0, localVertsOwned );MB_CHK_SET_ERR( rval, "Trouble getting local vertices in current file set" );
00048 assert( !localVertsOwned.empty() );
00049
00050 #ifdef MOAB_HAVE_MPI
00051 bool& isParallel = _writeNC->isParallel;
00052 if( isParallel )
00053 {
00054 ParallelComm*& myPcomm = _writeNC->myPcomm;
00055 int rank = myPcomm->proc_config().proc_rank();
00056 int procs = myPcomm->proc_config().proc_size();
00057 if( procs > 1 )
00058 {
00059 #ifndef NDEBUG
00060 unsigned int num_local_verts = localVertsOwned.size();
00061 #endif
00062 rval = myPcomm->filter_pstatus( localVertsOwned, PSTATUS_NOT_OWNED, PSTATUS_NOT );MB_CHK_SET_ERR( rval, "Trouble getting owned vertices in current set" );
00063
00064 // Assume that PARALLEL_RESOLVE_SHARED_ENTS option is set
00065 // Verify that not all local vertices are owned by the last processor
00066 if( procs - 1 == rank )
00067 assert( "PARALLEL_RESOLVE_SHARED_ENTS option is set" && localVertsOwned.size() < num_local_verts );
00068 }
00069 }
00070 #endif
00071
00072 std::vector< int > gids( localVertsOwned.size() );
00073 rval = mbImpl->tag_get_data( mGlobalIdTag, localVertsOwned, &gids[0] );MB_CHK_SET_ERR( rval, "Trouble getting global IDs on local vertices" );
00074
00075 // Get localGidVertsOwned
00076 std::copy( gids.rbegin(), gids.rend(), range_inserter( localGidVertsOwned ) );
00077
00078 return MB_SUCCESS;
00079 }
00080
00081 ErrorCode NCWriteHOMME::collect_variable_data( std::vector< std::string >& var_names, std::vector< int >& tstep_nums )
00082 {
00083 NCWriteHelper::collect_variable_data( var_names, tstep_nums );
00084
00085 std::map< std::string, WriteNC::VarData >& varInfo = _writeNC->varInfo;
00086
00087 for( size_t i = 0; i < var_names.size(); i++ )
00088 {
00089 std::string varname = var_names[i];
00090 std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( varname );
00091 if( vit == varInfo.end() ) MB_SET_ERR( MB_FAILURE, "Can't find variable " << varname );
00092 ;
00093
00094 WriteNC::VarData& currentVarData = vit->second;
00095 #ifndef NDEBUG
00096 std::vector< int >& varDims = currentVarData.varDims;
00097 #endif
00098
00099 // Skip set variables, which were already processed in
00100 // NCWriteHelper::collect_variable_data()
00101 if( WriteNC::ENTLOCSET == currentVarData.entLoc ) continue;
00102
00103 // Set up writeStarts and writeCounts (maximum number of dimensions is 3)
00104 currentVarData.writeStarts.resize( 3 );
00105 currentVarData.writeCounts.resize( 3 );
00106 unsigned int dim_idx = 0;
00107
00108 // First: time
00109 if( currentVarData.has_tsteps )
00110 {
00111 // Non-set variables with timesteps
00112 // 3 dimensions like (time, lev, ncol)
00113 // 2 dimensions like (time, ncol)
00114 assert( 3 == varDims.size() || 2 == varDims.size() );
00115
00116 // Time should be the first dimension
00117 assert( tDim == varDims[0] );
00118
00119 currentVarData.writeStarts[dim_idx] = 0; // This value is timestep dependent, will be set later
00120 currentVarData.writeCounts[dim_idx] = 1;
00121 dim_idx++;
00122 }
00123 else
00124 {
00125 // Non-set variables without timesteps
00126 // 2 dimensions like (lev, ncol)
00127 // 1 dimension like (ncol)
00128 assert( 2 == varDims.size() || 1 == varDims.size() );
00129 }
00130
00131 // Next: lev
00132 if( currentVarData.numLev > 0 )
00133 {
00134 // Non-set variables with levels
00135 // 3 dimensions like (time, lev, ncol)
00136 // 2 dimensions like (lev, ncol)
00137 assert( 3 == varDims.size() || 2 == varDims.size() );
00138
00139 currentVarData.writeStarts[dim_idx] = 0;
00140 currentVarData.writeCounts[dim_idx] = currentVarData.numLev;
00141 dim_idx++;
00142 }
00143 else
00144 {
00145 // Non-set variables without levels
00146 // 2 dimensions like (time, ncol)
00147 // 1 dimension like (ncol)
00148 assert( 2 == varDims.size() || 1 == varDims.size() );
00149 }
00150
00151 // Finally: ncol
00152 switch( currentVarData.entLoc )
00153 {
00154 case WriteNC::ENTLOCVERT:
00155 // Vertices
00156 // Start from the first localGidVerts
00157 // Actually, this will be reset later for writing
00158 currentVarData.writeStarts[dim_idx] = localGidVertsOwned[0] - 1;
00159 currentVarData.writeCounts[dim_idx] = localGidVertsOwned.size();
00160 break;
00161 default:
00162 MB_SET_ERR( MB_FAILURE, "Unexpected entity location type for variable " << varname );
00163 }
00164 dim_idx++;
00165
00166 // Get variable size
00167 currentVarData.sz = 1;
00168 for( std::size_t idx = 0; idx < dim_idx; idx++ )
00169 currentVarData.sz *= currentVarData.writeCounts[idx];
00170 }
00171
00172 return MB_SUCCESS;
00173 }
00174
00175 ErrorCode NCWriteHOMME::write_nonset_variables( std::vector< WriteNC::VarData >& vdatas,
00176 std::vector< int >& tstep_nums )
00177 {
00178 Interface*& mbImpl = _writeNC->mbImpl;
00179
00180 int success;
00181 int num_local_verts_owned = localVertsOwned.size();
00182
00183 // For each indexed variable tag, write a time step data
00184 for( unsigned int i = 0; i < vdatas.size(); i++ )
00185 {
00186 WriteNC::VarData& variableData = vdatas[i];
00187
00188 // Assume this variable is on vertices for the time being
00189 switch( variableData.entLoc )
00190 {
00191 case WriteNC::ENTLOCVERT:
00192 // Vertices
00193 break;
00194 default:
00195 MB_SET_ERR( MB_FAILURE, "Unexpected entity location type for variable " << variableData.varName );
00196 }
00197
00198 unsigned int num_timesteps;
00199 unsigned int ncol_idx = 0;
00200 if( variableData.has_tsteps )
00201 {
00202 // Non-set variables with timesteps
00203 // 3 dimensions like (time, lev, ncol)
00204 // 2 dimensions like (time, ncol)
00205 num_timesteps = tstep_nums.size();
00206 ncol_idx++;
00207 }
00208 else
00209 {
00210 // Non-set variables without timesteps
00211 // 2 dimensions like (lev, ncol)
00212 // 1 dimension like (ncol)
00213 num_timesteps = 1;
00214 }
00215
00216 unsigned int num_lev;
00217 if( variableData.numLev > 0 )
00218 {
00219 // Non-set variables with levels
00220 // 3 dimensions like (time, lev, ncol)
00221 // 2 dimensions like (lev, ncol)
00222 num_lev = variableData.numLev;
00223 ncol_idx++;
00224 }
00225 else
00226 {
00227 // Non-set variables without levels
00228 // 2 dimensions like (time, ncol)
00229 // 1 dimension like (ncol)
00230 num_lev = 1;
00231 }
00232
00233 // At each timestep, we need to transpose tag format (ncol, lev) back
00234 // to NC format (lev, ncol) for writing
00235 for( unsigned int t = 0; t < num_timesteps; t++ )
00236 {
00237 // We will write one time step, and count will be one; start will be different
00238 // Use tag_get_data instead of tag_iterate to copy tag data, as localVertsOwned
00239 // might not be contiguous. We should also transpose for level so that means
00240 // deep copy for transpose
00241 if( tDim == variableData.varDims[0] ) variableData.writeStarts[0] = t; // This is start for time
00242 std::vector< double > tag_data( num_local_verts_owned * num_lev );
00243 ErrorCode rval = mbImpl->tag_get_data( variableData.varTags[t], localVertsOwned, &tag_data[0] );MB_CHK_SET_ERR( rval, "Trouble getting tag data on owned vertices" );
00244
00245 #ifdef MOAB_HAVE_PNETCDF
00246 size_t nb_writes = localGidVertsOwned.psize();
00247 std::vector< int > requests( nb_writes ), statuss( nb_writes );
00248 size_t idxReq = 0;
00249 #endif
00250
00251 // Now transpose and write copied tag data
00252 // Use nonblocking put (request aggregation)
00253 switch( variableData.varDataType )
00254 {
00255 case NC_DOUBLE: {
00256 std::vector< double > tmpdoubledata( num_local_verts_owned * num_lev );
00257 if( num_lev > 1 )
00258 {
00259 // Transpose (ncol, lev) back to (lev, ncol)
00260 // Note, num_local_verts_owned is not used by jik_to_kji_stride()
00261 jik_to_kji_stride( num_local_verts_owned, 1, num_lev, &tmpdoubledata[0], &tag_data[0],
00262 localGidVertsOwned );
00263 }
00264
00265 size_t indexInDoubleArray = 0;
00266 size_t ic = 0;
00267 for( Range::pair_iterator pair_iter = localGidVertsOwned.pair_begin();
00268 pair_iter != localGidVertsOwned.pair_end(); ++pair_iter, ic++ )
00269 {
00270 EntityHandle starth = pair_iter->first;
00271 EntityHandle endh = pair_iter->second;
00272 variableData.writeStarts[ncol_idx] = (NCDF_SIZE)( starth - 1 );
00273 variableData.writeCounts[ncol_idx] = (NCDF_SIZE)( endh - starth + 1 );
00274
00275 // Do a partial write, in each subrange
00276 #ifdef MOAB_HAVE_PNETCDF
00277 // Wait outside this loop
00278 success =
00279 NCFUNCREQP( _vara_double )( _fileId, variableData.varId, &( variableData.writeStarts[0] ),
00280 &( variableData.writeCounts[0] ),
00281 &( tmpdoubledata[indexInDoubleArray] ), &requests[idxReq++] );
00282 #else
00283 success = NCFUNCAP(
00284 _vara_double )( _fileId, variableData.varId, &( variableData.writeStarts[0] ),
00285 &( variableData.writeCounts[0] ), &( tmpdoubledata[indexInDoubleArray] ) );
00286 #endif
00287 if( success )
00288 MB_SET_ERR( MB_FAILURE,
00289 "Failed to write double data in a loop for variable " << variableData.varName );
00290 // We need to increment the index in double array for the
00291 // next subrange
00292 indexInDoubleArray += ( endh - starth + 1 ) * num_lev;
00293 }
00294 assert( ic == localGidVertsOwned.psize() );
00295 #ifdef MOAB_HAVE_PNETCDF
00296 success = ncmpi_wait_all( _fileId, requests.size(), &requests[0], &statuss[0] );
00297 if( success ) MB_SET_ERR( MB_FAILURE, "Failed on wait_all" );
00298 #endif
00299 break;
00300 }
00301 default:
00302 MB_SET_ERR( MB_NOT_IMPLEMENTED, "Writing non-double data is not implemented yet" );
00303 }
00304 }
00305 }
00306
00307 return MB_SUCCESS;
00308 }
00309
00310 } /* namespace moab */