moab
NCHelperFV.cpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines