Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
Child helper class for Eulerian Spectral grid (CAM_EUL) More...
#include <NCHelperEuler.hpp>
Public Member Functions | |
NCHelperEuler (ReadNC *readNC, int fileId, const FileOptions &opts, EntityHandle fileSet) | |
Static Public Member Functions | |
static bool | can_read_file (ReadNC *readNC, int fileId) |
Private Member Functions | |
virtual ErrorCode | init_mesh_vals () |
Interfaces to be implemented in child classes. | |
virtual std::string | get_mesh_type_name () |
Child helper class for Eulerian Spectral grid (CAM_EUL)
Definition at line 24 of file NCHelperEuler.hpp.
moab::NCHelperEuler::NCHelperEuler | ( | ReadNC * | readNC, |
int | fileId, | ||
const FileOptions & | opts, | ||
EntityHandle | fileSet | ||
) | [inline] |
Definition at line 27 of file NCHelperEuler.hpp.
: ScdNCHelper( readNC, fileId, opts, fileSet ) { }
bool moab::NCHelperEuler::can_read_file | ( | ReadNC * | readNC, |
int | fileId | ||
) | [static] |
Definition at line 21 of file NCHelperEuler.cpp.
References moab::ReadNC::dimNames, moab::ReadNC::globalAtts, and NCFUNC.
Referenced by moab::NCHelper::get_nc_helper().
{ std::vector< std::string >& dimNames = readNC->dimNames; // If dimension names "lon" AND "lat' exist then it could be either the Eulerian Spectral grid // or the FV grid if( ( std::find( dimNames.begin(), dimNames.end(), std::string( "lon" ) ) != dimNames.end() ) && ( std::find( dimNames.begin(), dimNames.end(), std::string( "lat" ) ) != dimNames.end() ) ) { // If dimension names "lon" AND "lat" AND "slon" AND "slat" exist then it should be the FV // grid if( ( std::find( dimNames.begin(), dimNames.end(), std::string( "slon" ) ) != dimNames.end() ) && ( std::find( dimNames.begin(), dimNames.end(), std::string( "slat" ) ) != dimNames.end() ) ) return false; // Make sure it is CAM grid std::map< std::string, ReadNC::AttData >::iterator attIt = readNC->globalAtts.find( "source" ); if( attIt == readNC->globalAtts.end() ) return false; unsigned int sz = attIt->second.attLen; std::string att_data; att_data.resize( sz + 1 ); att_data[sz] = '\000'; int success = NCFUNC( get_att_text )( fileId, attIt->second.attVarId, attIt->second.attName.c_str(), &att_data[0] ); if( success ) return false; if( att_data.find( "CAM" ) == std::string::npos ) return false; return true; } return false; }
virtual std::string moab::NCHelperEuler::get_mesh_type_name | ( | ) | [inline, private, virtual] |
ErrorCode moab::NCHelperEuler::init_mesh_vals | ( | ) | [private, virtual] |
Interfaces to be implemented in child classes.
Implements moab::NCHelper.
Definition at line 54 of file NCHelperEuler.cpp.
References moab::NCHelper::_fileSet, moab::NCHelper::_opts, moab::NCHelper::_readNC, moab::ScdInterface::compute_partition(), moab::NCHelper::create_dummy_variables(), moab::ReadNC::dbgOut, moab::ReadNC::dimLens, moab::ReadNC::dimNames, moab::ReadNC::VarData::entLoc, moab::ReadNC::ENTLOCFACE, ErrorCode, moab::ScdNCHelper::gCDims, moab::ScdParData::gDims, moab::ScdNCHelper::gDims, moab::FileOptions::get_int_option(), moab::ScdNCHelper::globallyPeriodic, moab::ScdParData::gPeriodic, moab::ScdNCHelper::iCDim, moab::ScdNCHelper::ilCVals, moab::ScdNCHelper::ilVals, moab::ReadNC::isParallel, moab::ScdNCHelper::jCDim, moab::ScdNCHelper::jlCVals, moab::ScdNCHelper::jlVals, moab::ScdNCHelper::lCDims, moab::ScdNCHelper::lDims, moab::NCHelper::levDim, moab::ScdNCHelper::locallyPeriodic, MB_CHK_ERR, MB_CHK_SET_ERR, MB_SET_ERR, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_SPARSE, MB_TAG_VARLEN, MB_TYPE_DOUBLE, MB_TYPE_INTEGER, moab::ReadNC::mbImpl, moab::NCHelper::nLevels, moab::NCHelper::nTimeSteps, moab::ReadNC::VarData::numLev, moab::ReadNC::parData, moab::ScdParData::partMethod, moab::ReadNC::partMethod, moab::ScdParData::pDims, moab::ParallelComm::proc_config(), moab::ProcConfig::proc_rank(), moab::ProcConfig::proc_size(), moab::NCHelper::read_coordinate(), t, moab::Interface::tag_get_handle(), moab::Interface::tag_set_by_ptr(), moab::Interface::tag_set_data(), moab::NCHelper::tDim, moab::DebugOutput::tprintf(), moab::NCHelper::tVals, moab::ReadNC::VarData::varDims, and moab::ReadNC::varInfo.
{ Interface*& mbImpl = _readNC->mbImpl; std::vector< std::string >& dimNames = _readNC->dimNames; std::vector< int >& dimLens = _readNC->dimLens; std::map< std::string, ReadNC::VarData >& varInfo = _readNC->varInfo; DebugOutput& dbgOut = _readNC->dbgOut; bool& isParallel = _readNC->isParallel; int& partMethod = _readNC->partMethod; ScdParData& parData = _readNC->parData; // Look for names of center i/j dimensions // First i std::vector< std::string >::iterator vit; unsigned int idx; if( ( vit = std::find( dimNames.begin(), dimNames.end(), "lon" ) ) != dimNames.end() ) idx = vit - dimNames.begin(); else { MB_SET_ERR( MB_FAILURE, "Couldn't find 'lon' dimension" ); } iCDim = idx; gCDims[0] = 0; gCDims[3] = dimLens[idx] - 1; // Check i periodicity and set globallyPeriodic[0] std::vector< double > til_vals( 2 ); ErrorCode rval = read_coordinate( "lon", gCDims[3] - 1, gCDims[3], til_vals );MB_CHK_SET_ERR( rval, "Trouble reading 'lon' variable" ); if( std::fabs( 2 * til_vals[1] - til_vals[0] - 360 ) < 0.001 ) globallyPeriodic[0] = 1; // Now we can set gDims for i gDims[0] = 0; gDims[3] = gCDims[3] + ( globallyPeriodic[0] ? 0 : 1 ); // Only if not periodic is vertex param max > elem param max // Then j if( ( vit = std::find( dimNames.begin(), dimNames.end(), "lat" ) ) != dimNames.end() ) idx = vit - dimNames.begin(); else { MB_SET_ERR( MB_FAILURE, "Couldn't find 'lat' dimension" ); } jCDim = idx; gCDims[1] = 0; gCDims[4] = dimLens[idx] - 1; // For Eul models, will always be non-periodic in j gDims[1] = 0; gDims[4] = gCDims[4] + 1; // Try a truly 2D mesh gDims[2] = -1; gDims[5] = -1; // Look for time dimension if( ( vit = std::find( dimNames.begin(), dimNames.end(), "time" ) ) != dimNames.end() ) idx = vit - dimNames.begin(); else if( ( vit = std::find( dimNames.begin(), dimNames.end(), "t" ) ) != dimNames.end() ) idx = vit - dimNames.begin(); else { MB_SET_ERR( MB_FAILURE, "Couldn't find 'time' or 't' dimension" ); } tDim = idx; nTimeSteps = dimLens[idx]; // Look for level dimension if( ( vit = std::find( dimNames.begin(), dimNames.end(), "lev" ) ) != dimNames.end() ) idx = vit - dimNames.begin(); else if( ( vit = std::find( dimNames.begin(), dimNames.end(), "ilev" ) ) != dimNames.end() ) idx = vit - dimNames.begin(); else { MB_SET_ERR( MB_FAILURE, "Couldn't find 'lev' or 'ilev' dimension" ); } levDim = idx; nLevels = dimLens[idx]; // Parse options to get subset int rank = 0, procs = 1; #ifdef MOAB_HAVE_MPI if( isParallel ) { ParallelComm*& myPcomm = _readNC->myPcomm; rank = myPcomm->proc_config().proc_rank(); procs = myPcomm->proc_config().proc_size(); } #endif if( procs > 1 ) { for( int i = 0; i < 6; i++ ) parData.gDims[i] = gDims[i]; for( int i = 0; i < 3; i++ ) parData.gPeriodic[i] = globallyPeriodic[i]; parData.partMethod = partMethod; int pdims[3]; rval = ScdInterface::compute_partition( procs, rank, parData, lDims, locallyPeriodic, pdims );MB_CHK_ERR( rval ); for( int i = 0; i < 3; i++ ) parData.pDims[i] = pdims[i]; dbgOut.tprintf( 1, "Partition: %dx%d (out of %dx%d)\n", lDims[3] - lDims[0] + 1, lDims[4] - lDims[1] + 1, gDims[3] - gDims[0] + 1, gDims[4] - gDims[1] + 1 ); if( 0 == rank ) dbgOut.tprintf( 1, "Contiguous chunks of size %d bytes.\n", 8 * ( lDims[3] - lDims[0] + 1 ) * ( lDims[4] - lDims[1] + 1 ) ); } else { for( int i = 0; i < 6; i++ ) lDims[i] = gDims[i]; locallyPeriodic[0] = globallyPeriodic[0]; } _opts.get_int_option( "IMIN", lDims[0] ); _opts.get_int_option( "IMAX", lDims[3] ); _opts.get_int_option( "JMIN", lDims[1] ); _opts.get_int_option( "JMAX", lDims[4] ); // Now get actual coordinate values for vertices and cell centers lCDims[0] = lDims[0]; if( locallyPeriodic[0] ) // If locally periodic, doesn't matter what global periodicity is, # vertex coords = # elem // coords lCDims[3] = lDims[3]; else lCDims[3] = lDims[3] - 1; // For Eul models, will always be non-periodic in j lCDims[1] = lDims[1]; lCDims[4] = lDims[4] - 1; // Resize vectors to store values later if( -1 != lDims[0] ) ilVals.resize( lDims[3] - lDims[0] + 1 ); if( -1 != lCDims[0] ) ilCVals.resize( lCDims[3] - lCDims[0] + 1 ); if( -1 != lDims[1] ) jlVals.resize( lDims[4] - lDims[1] + 1 ); if( -1 != lCDims[1] ) jlCVals.resize( lCDims[4] - lCDims[1] + 1 ); if( nTimeSteps > 0 ) tVals.resize( nTimeSteps ); // Now read coord values std::map< std::string, ReadNC::VarData >::iterator vmit; if( -1 != lCDims[0] ) { if( ( vmit = varInfo.find( "lon" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 ) { rval = read_coordinate( "lon", lCDims[0], lCDims[3], ilCVals );MB_CHK_SET_ERR( rval, "Trouble reading 'lon' variable" ); } else { MB_SET_ERR( MB_FAILURE, "Couldn't find 'lon' variable" ); } } if( -1 != lCDims[1] ) { if( ( vmit = varInfo.find( "lat" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 ) { rval = read_coordinate( "lat", lCDims[1], lCDims[4], jlCVals );MB_CHK_SET_ERR( rval, "Trouble reading 'lat' variable" ); } else { MB_SET_ERR( MB_FAILURE, "Couldn't find 'lat' variable" ); } } if( -1 != lDims[0] ) { if( ( vmit = varInfo.find( "lon" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 ) { double dif = ( ilCVals[1] - ilCVals[0] ) / 2; std::size_t i; for( i = 0; i != ilCVals.size(); i++ ) ilVals[i] = ilCVals[i] - dif; // The last one is needed only if not periodic if( !locallyPeriodic[0] ) ilVals[i] = ilCVals[i - 1] + dif; } else { MB_SET_ERR( MB_FAILURE, "Couldn't find 'lon' variable" ); } } if( -1 != lDims[1] ) { if( ( vmit = varInfo.find( "lat" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 ) { if( !isParallel || ( ( gDims[4] - gDims[1] ) == ( lDims[4] - lDims[1] ) ) ) { std::string gwName( "gw" ); std::vector< double > gwVals( lDims[4] - lDims[1] - 1 ); rval = read_coordinate( gwName.c_str(), lDims[1], lDims[4] - 2, gwVals );MB_CHK_SET_ERR( rval, "Trouble reading 'gw' variable" ); // Copy the correct piece jlVals[0] = -( M_PI / 2 ) * 180 / M_PI; std::size_t i = 0; double gwSum = -1; for( i = 1; i != gwVals.size() + 1; i++ ) { gwSum += gwVals[i - 1]; jlVals[i] = std::asin( gwSum ) * 180 / M_PI; } jlVals[i] = 90.0; // Using value of i after loop exits. } else { std::string gwName( "gw" ); double gwSum = 0; // If this is the first row if( lDims[1] == gDims[1] ) { std::vector< double > gwVals( lDims[4] ); rval = read_coordinate( gwName.c_str(), 0, lDims[4] - 1, gwVals );MB_CHK_SET_ERR( rval, "Trouble reading 'gw' variable" ); // Copy the correct piece jlVals[0] = -( M_PI / 2 ) * 180 / M_PI; gwSum = -1; for( std::size_t i = 1; i != jlVals.size(); i++ ) { gwSum += gwVals[i - 1]; jlVals[i] = std::asin( gwSum ) * 180 / M_PI; } } // Or if it's the last row else if( lDims[4] == gDims[4] ) { std::vector< double > gwVals( lDims[4] - 1 ); rval = read_coordinate( gwName.c_str(), 0, lDims[4] - 2, gwVals );MB_CHK_SET_ERR( rval, "Trouble reading 'gw' variable" ); // Copy the correct piece gwSum = -1; for( int j = 0; j != lDims[1] - 1; j++ ) gwSum += gwVals[j]; std::size_t i = 0; for( ; i != jlVals.size() - 1; i++ ) { gwSum += gwVals[lDims[1] - 1 + i]; jlVals[i] = std::asin( gwSum ) * 180 / M_PI; } jlVals[i] = 90.0; // Using value of i after loop exits. } // It's in the middle else { int start = lDims[1] - 1; int end = lDims[4] - 1; std::vector< double > gwVals( end ); rval = read_coordinate( gwName.c_str(), 0, end - 1, gwVals );MB_CHK_SET_ERR( rval, "Trouble reading 'gw' variable" ); gwSum = -1; for( int j = 0; j != start - 1; j++ ) gwSum += gwVals[j]; std::size_t i = 0; for( ; i != jlVals.size(); i++ ) { gwSum += gwVals[start - 1 + i]; jlVals[i] = std::asin( gwSum ) * 180 / M_PI; } } } } else { MB_SET_ERR( MB_FAILURE, "Couldn't find 'lat' variable" ); } } // Store time coordinate values in tVals if( nTimeSteps > 0 ) { if( ( vmit = varInfo.find( "time" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 ) { rval = read_coordinate( "time", 0, nTimeSteps - 1, tVals );MB_CHK_SET_ERR( rval, "Trouble reading 'time' variable" ); } else if( ( vmit = varInfo.find( "t" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 ) { rval = read_coordinate( "t", 0, nTimeSteps - 1, tVals );MB_CHK_SET_ERR( rval, "Trouble reading 't' variable" ); } else { // If expected time variable is not available, set dummy time coordinate values to tVals for( int t = 0; t < nTimeSteps; t++ ) tVals.push_back( (double)t ); } } dbgOut.tprintf( 1, "I=%d-%d, J=%d-%d\n", lDims[0], lDims[3], lDims[1], lDims[4] ); dbgOut.tprintf( 1, "%d elements, %d vertices\n", ( lDims[3] - lDims[0] ) * ( lDims[4] - lDims[1] ), ( lDims[3] - lDims[0] + 1 ) * ( lDims[4] - lDims[1] + 1 ) ); // For each variable, determine the entity location type and number of levels std::map< std::string, ReadNC::VarData >::iterator mit; for( mit = varInfo.begin(); mit != varInfo.end(); ++mit ) { ReadNC::VarData& vd = ( *mit ).second; // Default entLoc is ENTLOCSET if( std::find( vd.varDims.begin(), vd.varDims.end(), tDim ) != vd.varDims.end() ) { if( ( std::find( vd.varDims.begin(), vd.varDims.end(), iCDim ) != vd.varDims.end() ) && ( std::find( vd.varDims.begin(), vd.varDims.end(), jCDim ) != vd.varDims.end() ) ) vd.entLoc = ReadNC::ENTLOCFACE; } // Default numLev is 0 if( std::find( vd.varDims.begin(), vd.varDims.end(), levDim ) != vd.varDims.end() ) vd.numLev = nLevels; } // For Eul models, slon and slat are "virtual" dimensions (not defined in the file header) std::vector< std::string > ijdimNames( 4 ); ijdimNames[0] = "__slon"; ijdimNames[1] = "__slat"; ijdimNames[2] = "__lon"; ijdimNames[3] = "__lat"; std::string tag_name; Tag tagh; // __<dim_name>_LOC_MINMAX (for virtual slon, virtual slat, lon and lat) for( unsigned int i = 0; i != ijdimNames.size(); i++ ) { std::vector< int > val( 2, 0 ); if( ijdimNames[i] == "__slon" ) { val[0] = lDims[0]; val[1] = lDims[3]; } else if( ijdimNames[i] == "__slat" ) { val[0] = lDims[1]; val[1] = lDims[4]; } else if( ijdimNames[i] == "__lon" ) { val[0] = lCDims[0]; val[1] = lCDims[3]; } else if( ijdimNames[i] == "__lat" ) { val[0] = lCDims[1]; val[1] = lCDims[4]; } std::stringstream ss_tag_name; ss_tag_name << ijdimNames[i] << "_LOC_MINMAX"; tag_name = ss_tag_name.str(); rval = mbImpl->tag_get_handle( tag_name.c_str(), 2, MB_TYPE_INTEGER, tagh, MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name ); rval = mbImpl->tag_set_data( tagh, &_fileSet, 1, &val[0] );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name ); if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Conventional tag %s is created.\n", tag_name.c_str() ); } // __<dim_name>_LOC_VALS (for virtual slon, virtual slat, lon and lat) // Assume all have the same data type as lon (expected type is float or double) switch( varInfo["lon"].varDataType ) { case NC_FLOAT: case NC_DOUBLE: break; default: MB_SET_ERR( MB_FAILURE, "Unexpected variable data type for 'lon'" ); } for( unsigned int i = 0; i != ijdimNames.size(); i++ ) { void* val = NULL; int val_len = 0; if( ijdimNames[i] == "__slon" ) { val = &ilVals[0]; val_len = ilVals.size(); } else if( ijdimNames[i] == "__slat" ) { val = &jlVals[0]; val_len = jlVals.size(); } else if( ijdimNames[i] == "__lon" ) { val = &ilCVals[0]; val_len = ilCVals.size(); } else if( ijdimNames[i] == "__lat" ) { val = &jlCVals[0]; val_len = jlCVals.size(); } std::stringstream ss_tag_name; ss_tag_name << ijdimNames[i] << "_LOC_VALS"; tag_name = ss_tag_name.str(); rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_DOUBLE, tagh, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name ); rval = mbImpl->tag_set_by_ptr( tagh, &_fileSet, 1, &val, &val_len );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name ); if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Conventional tag %s is created.\n", tag_name.c_str() ); } // __<dim_name>_GLOBAL_MINMAX (for virtual slon, virtual slat, lon and lat) for( unsigned int i = 0; i != ijdimNames.size(); i++ ) { std::vector< int > val( 2, 0 ); if( ijdimNames[i] == "__slon" ) { val[0] = gDims[0]; val[1] = gDims[3]; } else if( ijdimNames[i] == "__slat" ) { val[0] = gDims[1]; val[1] = gDims[4]; } else if( ijdimNames[i] == "__lon" ) { val[0] = gCDims[0]; val[1] = gCDims[3]; } else if( ijdimNames[i] == "__lat" ) { val[0] = gCDims[1]; val[1] = gCDims[4]; } std::stringstream ss_tag_name; ss_tag_name << ijdimNames[i] << "_GLOBAL_MINMAX"; tag_name = ss_tag_name.str(); rval = mbImpl->tag_get_handle( tag_name.c_str(), 2, MB_TYPE_INTEGER, tagh, MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name ); rval = mbImpl->tag_set_data( tagh, &_fileSet, 1, &val[0] );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name ); if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Conventional tag %s is created.\n", tag_name.c_str() ); } // Hack: create dummy variables, if needed, for dimensions with no corresponding coordinate // variables rval = create_dummy_variables();MB_CHK_SET_ERR( rval, "Failed to create dummy variables" ); return MB_SUCCESS; }