![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 #include "NCHelperFV.hpp"
00002 #include "moab/FileOptions.hpp"
00003
00004 #include
00005 #include
00006
00007 namespace moab
00008 {
00009
00010 bool NCHelperFV::can_read_file( ReadNC* readNC, int fileId )
00011 {
00012 std::vector< std::string >& dimNames = readNC->dimNames;
00013
00014 // If dimension names "lon" AND "lat" AND "slon" AND "slat" exist then it should be the FV grid
00015 if( ( std::find( dimNames.begin(), dimNames.end(), std::string( "lon" ) ) != dimNames.end() ) &&
00016 ( std::find( dimNames.begin(), dimNames.end(), std::string( "lat" ) ) != dimNames.end() ) &&
00017 ( std::find( dimNames.begin(), dimNames.end(), std::string( "slon" ) ) != dimNames.end() ) &&
00018 ( std::find( dimNames.begin(), dimNames.end(), std::string( "slat" ) ) != dimNames.end() ) )
00019 {
00020 // Make sure it is CAM grid
00021 std::map< std::string, ReadNC::AttData >::iterator attIt = readNC->globalAtts.find( "source" );
00022 if( attIt == readNC->globalAtts.end() ) return false;
00023 unsigned int sz = attIt->second.attLen;
00024 std::string att_data;
00025 att_data.resize( sz + 1 );
00026 att_data[sz] = '\000';
00027 int success =
00028 NCFUNC( get_att_text )( fileId, attIt->second.attVarId, attIt->second.attName.c_str(), &att_data[0] );
00029 if( success ) return false;
00030 if( att_data.find( "CAM" ) == std::string::npos ) return false;
00031
00032 return true;
00033 }
00034
00035 return false;
00036 }
00037
00038 ErrorCode NCHelperFV::init_mesh_vals()
00039 {
00040 Interface*& mbImpl = _readNC->mbImpl;
00041 std::vector< std::string >& dimNames = _readNC->dimNames;
00042 std::vector< int >& dimLens = _readNC->dimLens;
00043 std::map< std::string, ReadNC::VarData >& varInfo = _readNC->varInfo;
00044 DebugOutput& dbgOut = _readNC->dbgOut;
00045 bool& isParallel = _readNC->isParallel;
00046 int& partMethod = _readNC->partMethod;
00047 ScdParData& parData = _readNC->parData;
00048
00049 // Look for names of i/j dimensions
00050 // First i
00051 std::vector< std::string >::iterator vit;
00052 unsigned int idx;
00053 if( ( vit = std::find( dimNames.begin(), dimNames.end(), "slon" ) ) != dimNames.end() )
00054 idx = vit - dimNames.begin();
00055 else
00056 {
00057 MB_SET_ERR( MB_FAILURE, "Couldn't find 'slon' variable" );
00058 }
00059 iDim = idx;
00060 gDims[0] = 0;
00061 gDims[3] = dimLens[idx] - 1;
00062
00063 // Then j
00064 if( ( vit = std::find( dimNames.begin(), dimNames.end(), "slat" ) ) != dimNames.end() )
00065 idx = vit - dimNames.begin();
00066 else
00067 {
00068 MB_SET_ERR( MB_FAILURE, "Couldn't find 'slat' variable" );
00069 }
00070 jDim = idx;
00071 gDims[1] = 0;
00072 gDims[4] = dimLens[idx] - 1 + 2; // Add 2 for the pole points
00073
00074 // Look for names of center i/j dimensions
00075 // First i
00076 if( ( vit = std::find( dimNames.begin(), dimNames.end(), "lon" ) ) != dimNames.end() )
00077 idx = vit - dimNames.begin();
00078 else
00079 {
00080 MB_SET_ERR( MB_FAILURE, "Couldn't find 'lon' variable" );
00081 }
00082 iCDim = idx;
00083 gCDims[0] = 0;
00084 gCDims[3] = dimLens[idx] - 1;
00085
00086 // Check i periodicity and set globallyPeriodic[0]
00087 std::vector< double > til_vals( 2 );
00088 ErrorCode rval = read_coordinate( "lon", gCDims[3] - 1, gCDims[3], til_vals );MB_CHK_SET_ERR( rval, "Trouble reading 'lon' variable" );
00089 if( std::fabs( 2 * til_vals[1] - til_vals[0] - 360 ) < 0.001 ) globallyPeriodic[0] = 1;
00090 if( globallyPeriodic[0] )
00091 assert( "Number of vertices and edges should be same" && gDims[3] == gCDims[3] );
00092 else
00093 assert( "Number of vertices should equal to number of edges plus one" && gDims[3] == gCDims[3] + 1 );
00094
00095 // Then j
00096 if( ( vit = std::find( dimNames.begin(), dimNames.end(), "lat" ) ) != dimNames.end() )
00097 idx = vit - dimNames.begin();
00098 else
00099 {
00100 MB_SET_ERR( MB_FAILURE, "Couldn't find 'lat' dimension" );
00101 }
00102 jCDim = idx;
00103 gCDims[1] = 0;
00104 gCDims[4] = dimLens[idx] - 1;
00105
00106 // For FV models, will always be non-periodic in j
00107 assert( gDims[4] == gCDims[4] + 1 );
00108
00109 // Try a truly 2D mesh
00110 gDims[2] = -1;
00111 gDims[5] = -1;
00112
00113 // Look for time dimension
00114 if( ( vit = std::find( dimNames.begin(), dimNames.end(), "time" ) ) != dimNames.end() )
00115 idx = vit - dimNames.begin();
00116 else if( ( vit = std::find( dimNames.begin(), dimNames.end(), "t" ) ) != dimNames.end() )
00117 idx = vit - dimNames.begin();
00118 else
00119 {
00120 MB_SET_ERR( MB_FAILURE, "Couldn't find 'time' or 't' dimension" );
00121 }
00122 tDim = idx;
00123 nTimeSteps = dimLens[idx];
00124
00125 // Get number of levels
00126 if( ( vit = std::find( dimNames.begin(), dimNames.end(), "lev" ) ) != dimNames.end() )
00127 idx = vit - dimNames.begin();
00128 else if( ( vit = std::find( dimNames.begin(), dimNames.end(), "ilev" ) ) != dimNames.end() )
00129 idx = vit - dimNames.begin();
00130 else
00131 {
00132 MB_SET_ERR( MB_FAILURE, "Couldn't find 'lev' or 'ilev' dimension" );
00133 }
00134 levDim = idx;
00135 nLevels = dimLens[idx];
00136
00137 // Parse options to get subset
00138 int rank = 0, procs = 1;
00139 #ifdef MOAB_HAVE_MPI
00140 if( isParallel )
00141 {
00142 ParallelComm*& myPcomm = _readNC->myPcomm;
00143 rank = myPcomm->proc_config().proc_rank();
00144 procs = myPcomm->proc_config().proc_size();
00145 }
00146 #endif
00147 if( procs > 1 )
00148 {
00149 for( int i = 0; i < 6; i++ )
00150 parData.gDims[i] = gDims[i];
00151 for( int i = 0; i < 3; i++ )
00152 parData.gPeriodic[i] = globallyPeriodic[i];
00153 parData.partMethod = partMethod;
00154 int pdims[3];
00155
00156 rval = ScdInterface::compute_partition( procs, rank, parData, lDims, locallyPeriodic, pdims );MB_CHK_ERR( rval );
00157 for( int i = 0; i < 3; i++ )
00158 parData.pDims[i] = pdims[i];
00159
00160 dbgOut.tprintf( 1, "Partition: %dx%d (out of %dx%d)\n", lDims[3] - lDims[0] + 1, lDims[4] - lDims[1] + 1,
00161 gDims[3] - gDims[0] + 1, gDims[4] - gDims[1] + 1 );
00162 if( 0 == rank )
00163 dbgOut.tprintf( 1, "Contiguous chunks of size %d bytes.\n",
00164 8 * ( lDims[3] - lDims[0] + 1 ) * ( lDims[4] - lDims[1] + 1 ) );
00165 }
00166 else
00167 {
00168 for( int i = 0; i < 6; i++ )
00169 lDims[i] = gDims[i];
00170 locallyPeriodic[0] = globallyPeriodic[0];
00171 }
00172
00173 _opts.get_int_option( "IMIN", lDims[0] );
00174 _opts.get_int_option( "IMAX", lDims[3] );
00175 _opts.get_int_option( "JMIN", lDims[1] );
00176 _opts.get_int_option( "JMAX", lDims[4] );
00177
00178 // Now get actual coordinate values for vertices and cell centers
00179 lCDims[0] = lDims[0];
00180 if( locallyPeriodic[0] )
00181 // If locally periodic, doesn't matter what global periodicity is, # vertex coords = # elem
00182 // coords
00183 lCDims[3] = lDims[3];
00184 else
00185 lCDims[3] = lDims[3] - 1;
00186
00187 // For FV models, will always be non-periodic in j
00188 lCDims[1] = lDims[1];
00189 lCDims[4] = lDims[4] - 1;
00190
00191 // Resize vectors to store values later
00192 if( -1 != lDims[0] ) ilVals.resize( lDims[3] - lDims[0] + 1 );
00193 if( -1 != lCDims[0] ) ilCVals.resize( lCDims[3] - lCDims[0] + 1 );
00194 if( -1 != lDims[1] ) jlVals.resize( lDims[4] - lDims[1] + 1 );
00195 if( -1 != lCDims[1] ) jlCVals.resize( lCDims[4] - lCDims[1] + 1 );
00196 if( nTimeSteps > 0 ) tVals.resize( nTimeSteps );
00197
00198 // Now read coord values
00199 std::map< std::string, ReadNC::VarData >::iterator vmit;
00200 if( -1 != lCDims[0] )
00201 {
00202 if( ( vmit = varInfo.find( "lon" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 )
00203 {
00204 rval = read_coordinate( "lon", lCDims[0], lCDims[3], ilCVals );MB_CHK_SET_ERR( rval, "Trouble reading 'lon' variable" );
00205 }
00206 else
00207 {
00208 MB_SET_ERR( MB_FAILURE, "Couldn't find 'lon' variable" );
00209 }
00210 }
00211
00212 if( -1 != lCDims[1] )
00213 {
00214 if( ( vmit = varInfo.find( "lat" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 )
00215 {
00216 rval = read_coordinate( "lat", lCDims[1], lCDims[4], jlCVals );MB_CHK_SET_ERR( rval, "Trouble reading 'lat' variable" );
00217 }
00218 else
00219 {
00220 MB_SET_ERR( MB_FAILURE, "Couldn't find 'lat' variable" );
00221 }
00222 }
00223
00224 if( -1 != lDims[0] )
00225 {
00226 if( ( vmit = varInfo.find( "slon" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 )
00227 {
00228 // Last column
00229 if( !locallyPeriodic[0] && globallyPeriodic[0] && lDims[3] > gDims[3] )
00230 {
00231 assert( lDims[3] == gDims[3] + 1 );
00232 std::vector< double > dummyVar( lDims[3] - lDims[0] );
00233 rval = read_coordinate( "slon", lDims[0], lDims[3] - 1, dummyVar );
00234 double dif = dummyVar[1] - dummyVar[0];
00235 std::size_t i;
00236 for( i = 0; i != dummyVar.size(); i++ )
00237 ilVals[i] = dummyVar[i];
00238 ilVals[i] = ilVals[i - 1] + dif;
00239 }
00240 else
00241 {
00242 rval = read_coordinate( "slon", lDims[0], lDims[3], ilVals );MB_CHK_SET_ERR( rval, "Trouble reading 'slon' variable" );
00243 }
00244 }
00245 else
00246 {
00247 MB_SET_ERR( MB_FAILURE, "Couldn't find 'slon' variable" );
00248 }
00249 }
00250
00251 if( -1 != lDims[1] )
00252 {
00253 if( ( vmit = varInfo.find( "slat" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 )
00254 {
00255 if( !isParallel || ( ( gDims[4] - gDims[1] ) == ( lDims[4] - lDims[1] ) ) )
00256 {
00257 std::vector< double > dummyVar( lDims[4] - lDims[1] - 1 );
00258 rval = read_coordinate( "slat", lDims[1], lDims[4] - 2, dummyVar );MB_CHK_SET_ERR( rval, "Trouble reading 'slat' variable" );
00259 // Copy the correct piece
00260 jlVals[0] = -90.0;
00261 std::size_t i = 0;
00262 for( i = 1; i != dummyVar.size() + 1; i++ )
00263 jlVals[i] = dummyVar[i - 1];
00264 jlVals[i] = 90.0; // Using value of i after loop exits.
00265 }
00266 else
00267 {
00268 // If this is the first row
00269 // Need to read one less then available and read it into a dummy var
00270 if( lDims[1] == gDims[1] )
00271 {
00272 std::vector< double > dummyVar( lDims[4] - lDims[1] );
00273 rval = read_coordinate( "slat", lDims[1], lDims[4] - 1, dummyVar );MB_CHK_SET_ERR( rval, "Trouble reading 'slat' variable" );
00274 // Copy the correct piece
00275 jlVals[0] = -90.0;
00276 for( int i = 1; i < lDims[4] + 1; i++ )
00277 jlVals[i] = dummyVar[i - 1];
00278 }
00279 // Or if it's the last row
00280 else if( lDims[4] == gDims[4] )
00281 {
00282 std::vector< double > dummyVar( lDims[4] - lDims[1] );
00283 rval = read_coordinate( "slat", lDims[1] - 1, lDims[4] - 2, dummyVar );MB_CHK_SET_ERR( rval, "Trouble reading 'slat' variable" );
00284 // Copy the correct piece
00285 std::size_t i = 0;
00286 for( i = 0; i != dummyVar.size(); i++ )
00287 jlVals[i] = dummyVar[i];
00288 jlVals[i] = 90.0; // Using value of i after loop exits.
00289 }
00290 // It's in the middle
00291 else
00292 {
00293 rval = read_coordinate( "slat", lDims[1] - 1, lDims[4] - 1, jlVals );MB_CHK_SET_ERR( rval, "Trouble reading 'slat' variable" );
00294 }
00295 }
00296 }
00297 else
00298 {
00299 MB_SET_ERR( MB_FAILURE, "Couldn't find 'slat' variable" );
00300 }
00301 }
00302
00303 // Store time coordinate values in tVals
00304 if( nTimeSteps > 0 )
00305 {
00306 if( ( vmit = varInfo.find( "time" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 )
00307 {
00308 rval = read_coordinate( "time", 0, nTimeSteps - 1, tVals );MB_CHK_SET_ERR( rval, "Trouble reading 'time' variable" );
00309 }
00310 else if( ( vmit = varInfo.find( "t" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 )
00311 {
00312 rval = read_coordinate( "t", 0, nTimeSteps - 1, tVals );MB_CHK_SET_ERR( rval, "Trouble reading 't' variable" );
00313 }
00314 else
00315 {
00316 // If expected time variable is not available, set dummy time coordinate values to tVals
00317 for( int t = 0; t < nTimeSteps; t++ )
00318 tVals.push_back( (double)t );
00319 }
00320 }
00321
00322 dbgOut.tprintf( 1, "I=%d-%d, J=%d-%d\n", lDims[0], lDims[3], lDims[1], lDims[4] );
00323 dbgOut.tprintf( 1, "%d elements, %d vertices\n", ( lDims[3] - lDims[0] ) * ( lDims[4] - lDims[1] ),
00324 ( lDims[3] - lDims[0] + 1 ) * ( lDims[4] - lDims[1] + 1 ) );
00325
00326 // For each variable, determine the entity location type and number of levels
00327 std::map< std::string, ReadNC::VarData >::iterator mit;
00328 for( mit = varInfo.begin(); mit != varInfo.end(); ++mit )
00329 {
00330 ReadNC::VarData& vd = ( *mit ).second;
00331
00332 // Default entLoc is ENTLOCSET
00333 if( std::find( vd.varDims.begin(), vd.varDims.end(), tDim ) != vd.varDims.end() )
00334 {
00335 if( ( std::find( vd.varDims.begin(), vd.varDims.end(), iCDim ) != vd.varDims.end() ) &&
00336 ( std::find( vd.varDims.begin(), vd.varDims.end(), jCDim ) != vd.varDims.end() ) )
00337 vd.entLoc = ReadNC::ENTLOCFACE;
00338 else if( ( std::find( vd.varDims.begin(), vd.varDims.end(), jDim ) != vd.varDims.end() ) &&
00339 ( std::find( vd.varDims.begin(), vd.varDims.end(), iCDim ) != vd.varDims.end() ) )
00340 vd.entLoc = ReadNC::ENTLOCNSEDGE;
00341 else if( ( std::find( vd.varDims.begin(), vd.varDims.end(), jCDim ) != vd.varDims.end() ) &&
00342 ( std::find( vd.varDims.begin(), vd.varDims.end(), iDim ) != vd.varDims.end() ) )
00343 vd.entLoc = ReadNC::ENTLOCEWEDGE;
00344 }
00345
00346 // Default numLev is 0
00347 if( std::find( vd.varDims.begin(), vd.varDims.end(), levDim ) != vd.varDims.end() ) vd.numLev = nLevels;
00348 }
00349
00350 std::vector< std::string > ijdimNames( 4 );
00351 ijdimNames[0] = "__slon";
00352 ijdimNames[1] = "__slat";
00353 ijdimNames[2] = "__lon";
00354 ijdimNames[3] = "__lat";
00355
00356 std::string tag_name;
00357 Tag tagh;
00358
00359 // ___LOC_MINMAX (for slon, slat, lon and lat)
00360 for( unsigned int i = 0; i != ijdimNames.size(); i++ )
00361 {
00362 std::vector< int > val( 2, 0 );
00363 if( ijdimNames[i] == "__slon" )
00364 {
00365 val[0] = lDims[0];
00366 val[1] = lDims[3];
00367 }
00368 else if( ijdimNames[i] == "__slat" )
00369 {
00370 val[0] = lDims[1];
00371 val[1] = lDims[4];
00372 }
00373 else if( ijdimNames[i] == "__lon" )
00374 {
00375 val[0] = lCDims[0];
00376 val[1] = lCDims[3];
00377 }
00378 else if( ijdimNames[i] == "__lat" )
00379 {
00380 val[0] = lCDims[1];
00381 val[1] = lCDims[4];
00382 }
00383 std::stringstream ss_tag_name;
00384 ss_tag_name << ijdimNames[i] << "_LOC_MINMAX";
00385 tag_name = ss_tag_name.str();
00386 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 );
00387 rval = mbImpl->tag_set_data( tagh, &_fileSet, 1, &val[0] );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name );
00388 if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Conventional tag %s is created.\n", tag_name.c_str() );
00389 }
00390
00391 // ___LOC_VALS (for slon, slat, lon and lat)
00392 // Assume all have the same data type as lon (expected type is float or double)
00393 switch( varInfo["lon"].varDataType )
00394 {
00395 case NC_FLOAT:
00396 case NC_DOUBLE:
00397 break;
00398 default:
00399 MB_SET_ERR( MB_FAILURE, "Unexpected variable data type for 'lon'" );
00400 }
00401
00402 for( unsigned int i = 0; i != ijdimNames.size(); i++ )
00403 {
00404 void* val = NULL;
00405 int val_len = 0;
00406 if( ijdimNames[i] == "__slon" )
00407 {
00408 val = &ilVals[0];
00409 val_len = ilVals.size();
00410 }
00411 else if( ijdimNames[i] == "__slat" )
00412 {
00413 val = &jlVals[0];
00414 val_len = jlVals.size();
00415 }
00416 else if( ijdimNames[i] == "__lon" )
00417 {
00418 val = &ilCVals[0];
00419 val_len = ilCVals.size();
00420 }
00421 else if( ijdimNames[i] == "__lat" )
00422 {
00423 val = &jlCVals[0];
00424 val_len = jlCVals.size();
00425 }
00426
00427 std::stringstream ss_tag_name;
00428 ss_tag_name << ijdimNames[i] << "_LOC_VALS";
00429 tag_name = ss_tag_name.str();
00430 rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_DOUBLE, tagh,
00431 MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name );
00432 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 );
00433 if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Conventional tag %s is created.\n", tag_name.c_str() );
00434 }
00435
00436 // ___GLOBAL_MINMAX (for slon, slat, lon and lat)
00437 for( unsigned int i = 0; i != ijdimNames.size(); i++ )
00438 {
00439 std::vector< int > val( 2, 0 );
00440 if( ijdimNames[i] == "__slon" )
00441 {
00442 val[0] = gDims[0];
00443 val[1] = gDims[3];
00444 }
00445 else if( ijdimNames[i] == "__slat" )
00446 {
00447 val[0] = gDims[1];
00448 val[1] = gDims[4];
00449 }
00450 else if( ijdimNames[i] == "__lon" )
00451 {
00452 val[0] = gCDims[0];
00453 val[1] = gCDims[3];
00454 }
00455 else if( ijdimNames[i] == "__lat" )
00456 {
00457 val[0] = gCDims[1];
00458 val[1] = gCDims[4];
00459 }
00460 std::stringstream ss_tag_name;
00461 ss_tag_name << ijdimNames[i] << "_GLOBAL_MINMAX";
00462 tag_name = ss_tag_name.str();
00463 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 );
00464 rval = mbImpl->tag_set_data( tagh, &_fileSet, 1, &val[0] );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name );
00465 if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Conventional tag %s is created.\n", tag_name.c_str() );
00466 }
00467
00468 // Hack: create dummy variables, if needed, for dimensions with no corresponding coordinate
00469 // variables
00470 rval = create_dummy_variables();MB_CHK_SET_ERR( rval, "Failed to create dummy variables" );
00471
00472 return MB_SUCCESS;
00473 }
00474
00475 } // namespace moab