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