void OutputManager::PerformOutput( const Time & time ) { // Open the file if (!m_fIsFileOpen) { std::string strActiveFileName; GetFileName(time, strActiveFileName); m_fIsFileOpen = OpenFile(strActiveFileName); if (!m_fIsFileOpen) { _EXCEPTION1("Unable to open file \"%s\"", strActiveFileName.c_str()); } } // Output Output(time); m_ixOutputTime ++; // Check if time limit is reached if (m_ixOutputTime == m_nOutputsPerFile) { CloseFile(); m_fIsFileOpen = false; m_ixOutputFile ++; m_ixOutputTime = 0; } }
void ExchangeBuffer::Reset() { if (m_dSendBuffer.GetByteSize() < sizeof(MessageHeader)) { _EXCEPTION1("Invalid ExchangeBuffer send buffer (%i)", m_dSendBuffer.GetByteSize()); } if (sizeof(MessageHeader) % sizeof(double) != 0) { _EXCEPTIONT("sizeof(MessageHeader) % sizeof(double) != 0"); } // Store ExchangeBuffer::MessageHeader GetSendMessageHeader((MessageHeader *)(&(m_dSendBuffer[0]))); // Set read and write indices to just beyond the MessageHeader m_ixRecvBuffer = sizeof(MessageHeader) / sizeof(double); m_ixSendBuffer = sizeof(MessageHeader) / sizeof(double); }
GridSpacingGaussLobatto::GridSpacingGaussLobatto( double dDeltaElement, double dZeroCoord, int nOrder ) : GridSpacing(dDeltaElement, dZeroCoord), m_nOrder(nOrder) { // Check order if (m_nOrder < 2) { _EXCEPTION1("Invalid order of accuracy %i (Order < 2)", m_nOrder); } // Obtain GLL nodes GaussLobattoQuadrature::GetPoints( nOrder, 0.0, dDeltaElement, m_dG, m_dW); }
/// <summary> /// Load in the contents of a text file containing one filename per /// line and store in a vector of strings. /// </summary> void GetInputFileList( const std::string & strInputFileList, std::vector<std::string> & vecInputFiles ) { FILE * fp = fopen(strInputFileList.c_str(), "r"); char szBuffer[1024]; for (;;) { fgets(szBuffer, 1024, fp); if (feof(fp)) { break; } // Remove end-of-line characters for (;;) { int nLen = strlen(szBuffer); if ((szBuffer[nLen-1] == '\n') || (szBuffer[nLen-1] == '\r') || (szBuffer[nLen-1] == ' ') ) { szBuffer[nLen-1] = '\0'; continue; } break; } vecInputFiles.push_back(szBuffer); } if (vecInputFiles.size() == 0) { _EXCEPTION1("No files found in file \"%s\"", strInputFileList.c_str()); } fclose(fp); }
bool OutputManagerComposite::OpenFile( const std::string & strFileName ) { #ifdef USE_MPI // Determine processor rank int nRank; MPI_Comm_rank(MPI_COMM_WORLD, &nRank); // Open file at root if (nRank == 0) { // Check for existing file if (m_ofsActiveOutput.is_open()) { _EXCEPTIONT("Restart file already open"); } // Open new binary output stream std::string strRestartFileName = strFileName + ".restart.dat"; m_ofsActiveOutput.open( strRestartFileName.c_str(), std::ios::binary | std::ios::out); if (!m_ofsActiveOutput) { _EXCEPTION1("Error opening output file \"%s\"", strRestartFileName.c_str()); } } // Wait for all processes to complete MPI_Barrier(MPI_COMM_WORLD); return true; #else _EXCEPTIONT("Not implemented without USE_MPI"); #endif }
void CubedSphereTrans::CoVecTransRLLFromABP( double dX, double dY, int nP, double dUalpha, double dUbeta, double & dUlon, double & dUlat ) { double dDelta2 = 1.0 + dX * dX + dY * dY; double dRadius; double dRadius2; double lat; switch (nP) { // Equatorial panels case 0: case 1: case 2: case 3: // Calculate new vector components dUlon = dDelta2 / (1.0 + dX * dX) * dUalpha + dDelta2 * dX * dY / (1.0 + dX * dX) / (1.0 + dY * dY) * dUbeta; dUlat = dDelta2 / sqrt(1.0 + dX * dX) / (1.0 + dY * dY) * dUbeta; // Convert spherical coords to geometric basis lat = atan(dY / sqrt(1.0 + dX * dX)); dUlon *= cos(lat); break; // North polar panel case 4: // Calculate new vector components dRadius2 = (dX * dX + dY * dY); dRadius = sqrt(dRadius2); dUlon = - dDelta2 * dY / (1.0 + dX * dX) / dRadius2 * dUalpha + dDelta2 * dX / (1.0 + dY * dY) / dRadius2 * dUbeta; dUlat = - dDelta2 * dX / (1.0 + dX * dX) / dRadius * dUalpha - dDelta2 * dY / (1.0 + dY * dY) / dRadius * dUbeta; // Convert spherical coords to geometric basis lat = 0.5 * M_PI - atan(sqrt(dX * dX + dY * dY)); dUlon *= cos(lat); break; // South polar panel case 5: // Calculate new vector components dRadius2 = (dX * dX + dY * dY); dRadius = sqrt(dRadius2); dUlon = + dDelta2 * dY / (1.0 + dX * dX) / dRadius2 * dUalpha - dDelta2 * dX / (1.0 + dY * dY) / dRadius2 * dUbeta; dUlat = + dDelta2 * dX / (1.0 + dX * dX) / dRadius * dUalpha + dDelta2 * dY / (1.0 + dY * dY) / dRadius * dUbeta; // Convert spherical coords to geometric basis lat = 0.5 * M_PI - atan(sqrt(dX * dX + dY * dY)); dUlon *= cos(lat); break; // Invalid panel default: _EXCEPTION1( "Invalid nP coordinate. Given: %d, Expected: [0-5].\n", nP); } }
void Connectivity::BuildFluxConnectivity() { // PatchBox const PatchBox & box = m_patch.GetPatchBox(); // Allocate space for edges m_vecExteriorEdge[0].resize(box.GetBTotalWidth(), NULL); m_vecExteriorEdge[1].resize(box.GetATotalWidth(), NULL); m_vecExteriorEdge[2].resize(box.GetBTotalWidth(), NULL); m_vecExteriorEdge[3].resize(box.GetATotalWidth(), NULL); m_vecExteriorEdge[4].resize(1, NULL); m_vecExteriorEdge[5].resize(1, NULL); m_vecExteriorEdge[6].resize(1, NULL); m_vecExteriorEdge[7].resize(1, NULL); // Loop over all exterior edges, hook up pointers to ExteriorNeighbors for (int n = 0; n < m_vecExteriorNeighbors.size(); n++) { ExteriorNeighbor * pNeighbor = m_vecExteriorNeighbors[n]; int iDir = static_cast<int>(pNeighbor->m_dir); // Right or Left side of this PatchBox if ((pNeighbor->m_dir == Direction_Right) || (pNeighbor->m_dir == Direction_Left) ) { int j = pNeighbor->m_ixFirst; for (; j < pNeighbor->m_ixSecond; j++) { if ((j < box.GetBInteriorBegin()) || (j >= box.GetBInteriorEnd()) ) { _EXCEPTIONT("Edge index out of range"); } m_vecExteriorEdge[iDir][j] = pNeighbor; } // Top or Bottom side of this PatchBox } else if ( (pNeighbor->m_dir == Direction_Top) || (pNeighbor->m_dir == Direction_Bottom) ) { int i = pNeighbor->m_ixFirst; for (; i < pNeighbor->m_ixSecond; i++) { if ((i < box.GetAInteriorBegin()) || (i >= box.GetAInteriorEnd()) ) { _EXCEPTIONT("Edge index out of range"); } m_vecExteriorEdge[iDir][i] = pNeighbor; } // Corners of this PatchBox } else if ( (pNeighbor->m_dir == Direction_TopRight) || (pNeighbor->m_dir == Direction_TopLeft) || (pNeighbor->m_dir == Direction_BottomRight) || (pNeighbor->m_dir == Direction_BottomLeft) ) { if (m_vecExteriorEdge[iDir][0] != NULL) { _EXCEPTION1("Corner patch %i already set", iDir); } m_vecExteriorEdge[iDir][0] = pNeighbor; } else { _EXCEPTIONT("Invalid direction"); } } }
void CubedSphereTrans::RLLFromXYP( double dX, double dY, int nP, double &lon, double &lat ) { switch (nP) { // Equatorial panel 1 case 0: lon = atan(dX); lat = atan(dY / sqrt(1.0 + dX * dX)); break; // Equatorial panel 2 case 1: lon = atan(dX) + 0.5 * M_PI; lat = atan(dY / sqrt(1.0 + dX * dX)); break; // Equatorial panel 3 case 2: lon = atan(dX) + M_PI; lat = atan(dY / sqrt(1.0 + dX * dX)); break; // Equatorial panel 4 case 3: lon = atan(dX) + 1.5 * M_PI; lat = atan(dY / sqrt(1.0 + dX * dX)); break; // North polar panel case 4: if (fabs(dX) > DBL_EPSILON) { lon = atan2(dX, -dY); } else if (dY <= 0.0) { lon = 0.0; } else { lon = M_PI; } lat = 0.5 * M_PI - atan(sqrt(dX * dX + dY * dY)); break; // South polar panel case 5: if (fabs(dX) > DBL_EPSILON) { lon = atan2(dX, dY); } else if (dY > 0.0) { lon = 0.0; } else { lon = M_PI; } lat = -0.5 * M_PI + atan(sqrt(dX * dX + dY * dY)); break; // Invalid panel default: _EXCEPTION1( "Invalid nP coordinate. Given: %d, Expected: [0-5].\n", nP); } // Map to the interval [0, 2 pi] if (lon < 0.0) { lon += 2.0 * M_PI; } }
void CubedSphereTrans::CoVecTransABPFromRLL( double dX, double dY, int nP, double dUlon, double dUlat, double & dUalpha, double & dUbeta ) { double dDelta2 = 1.0 + dX * dX + dY * dY; double dRadius; double lat; if ((nP > 3) && (fabs(dX) < 1.0e-13) && (fabs(dY) < 1.0e-13)) { if (nP == 4) { dUalpha = dUlon; } else { dUalpha = - dUlon; } dUbeta = dUlat; return; } switch (nP) { // Equatorial panels case 0: case 1: case 2: case 3: // Convert Ulon from geometric basis lat = atan(dY / sqrt(1.0 + dX * dX)); dUlon = dUlon / cos(lat); // Calculate vector component dUalpha = (1.0 + dX * dX) / dDelta2 * dUlon - dX * dY * sqrt(1.0 + dX * dX) / dDelta2 * dUlat; dUbeta = sqrt(1.0 + dX * dX) * (1.0 + dY * dY) / dDelta2 * dUlat; break; // North polar panel case 4: // Convert Ulon from geometric basis lat = 0.5 * M_PI - atan(sqrt(dX * dX + dY * dY)); dUlon = dUlon / cos(lat); // Calculate vector component dRadius = sqrt(dX * dX + dY * dY); dUalpha = - dY * (1.0 + dX * dX) / dDelta2 * dUlon - dX * (1.0 + dX * dX) / (dDelta2 * dRadius) * dUlat; dUbeta = + dX * (1.0 + dY * dY) / dDelta2 * dUlon - dY * (1.0 + dY * dY) / (dDelta2 * dRadius) * dUlat; break; // South polar panel case 5: // Convert Ulon from geometric basis lat = -0.5 * M_PI + atan(sqrt(dX * dX + dY * dY)); dUlon = dUlon / cos(lat); // Calculate vector component dRadius = sqrt(dX * dX + dY * dY); dUalpha = + dY * (1.0 + dX * dX) / dDelta2 * dUlon + dX * (1.0 + dX * dX) / (dDelta2 * dRadius) * dUlat; dUbeta = - dX * (1.0 + dY * dY) / dDelta2 * dUlon + dY * (1.0 + dY * dY) / (dDelta2 * dRadius) * dUlat; break; // Invalid panel default: _EXCEPTION1( "Invalid nP coordinate. Given: %d, Expected: [0-5].\n", nP); } }
void ParseLevelArray( const std::string & strLevels, std::vector<double> & vecLevels ) { int iLevelBegin = 0; int iLevelCurrent = 0; vecLevels.clear(); if (strLevels == "") { return; } // Parse pressure levels bool fRangeMode = false; for (;;) { if ((iLevelCurrent >= strLevels.length()) || (strLevels[iLevelCurrent] == ',') || (strLevels[iLevelCurrent] == ' ') || (strLevels[iLevelCurrent] == ':') ) { // Range mode if ((!fRangeMode) && (strLevels[iLevelCurrent] == ':') ) { if (vecLevels.size() != 0) { _EXCEPTIONT("Invalid set of pressure levels"); } fRangeMode = true; } if (fRangeMode) { if ((strLevels[iLevelCurrent] != ':') && (iLevelCurrent < strLevels.length()) ) { _EXCEPTION1("Invalid character in pressure range (%c)", strLevels[iLevelCurrent]); } } if (iLevelCurrent == iLevelBegin) { if (iLevelCurrent >= strLevels.length()) { break; } continue; } std::string strPressureLevelSubStr = strLevels.substr( iLevelBegin, iLevelCurrent - iLevelBegin); vecLevels.push_back(atof(strPressureLevelSubStr.c_str())); iLevelBegin = iLevelCurrent + 1; } iLevelCurrent++; } // Range mode -- repopulate array if (fRangeMode) { if (vecLevels.size() != 3) { _EXCEPTIONT("Exactly three pressure level entries required " "for range mode"); } double dLevelBegin = vecLevels[0]; double dLevelStep = vecLevels[1]; double dLevelEnd = vecLevels[2]; if (dLevelStep == 0.0) { _EXCEPTIONT("Level step size cannot be zero"); } if ((dLevelEnd - dLevelBegin) / dLevelStep > 10000.0) { _EXCEPTIONT("Too many levels in range (limit 10000)"); } if ((dLevelEnd - dLevelBegin) / dLevelStep < 0.0) { _EXCEPTIONT("Sign mismatch in level step"); } vecLevels.clear(); for (int i = 0 ;; i++) { double dLevel = dLevelBegin + static_cast<double>(i) * dLevelStep; if ((dLevelStep > 0.0) && (dLevel > dLevelEnd)) { break; } if ((dLevelStep < 0.0) && (dLevel < dLevelEnd)) { break; } vecLevels.push_back(dLevel); } } }
int main(int argc, char ** argv) { MPI_Init(&argc, &argv); NcError error(NcError::silent_nonfatal); try { // Input filename std::string strInputFile; // Output filename std::string strOutputFile; // Separate topography file std::string strTopographyFile; // List of variables to extract std::string strVariables; // Extract geopotential height bool fGeopotentialHeight; // Pressure levels to extract std::string strPressureLevels; // Height levels to extract std::string strHeightLevels; // Extract variables at the surface bool fExtractSurface; // Extract total energy bool fExtractTotalEnergy; // Parse the command line BeginCommandLine() CommandLineString(strInputFile, "in", ""); CommandLineString(strOutputFile, "out", ""); CommandLineString(strVariables, "var", ""); CommandLineBool(fGeopotentialHeight, "output_z"); CommandLineBool(fExtractTotalEnergy, "output_energy"); CommandLineString(strPressureLevels, "p", ""); CommandLineString(strHeightLevels, "z", ""); CommandLineBool(fExtractSurface, "surf"); ParseCommandLine(argc, argv); EndCommandLine(argv) AnnounceBanner(); // Check command line arguments if (strInputFile == "") { _EXCEPTIONT("No input file specified"); } if (strOutputFile == "") { _EXCEPTIONT("No output file specified"); } if (strVariables == "") { _EXCEPTIONT("No variables specified"); } // Parse variable string std::vector< std::string > vecVariableStrings; ParseVariableList(strVariables, vecVariableStrings); // Check variables if (vecVariableStrings.size() == 0) { _EXCEPTIONT("No variables specified"); } // Parse pressure level string std::vector<double> vecPressureLevels; ParseLevelArray(strPressureLevels, vecPressureLevels); int nPressureLevels = (int)(vecPressureLevels.size()); for (int k = 0; k < nPressureLevels; k++) { if (vecPressureLevels[k] <= 0.0) { _EXCEPTIONT("Non-positive pressure values not allowed"); } } // Parse height level string std::vector<double> vecHeightLevels; ParseLevelArray(strHeightLevels, vecHeightLevels); int nHeightLevels = (int)(vecHeightLevels.size()); // Check pressure levels if ((nPressureLevels == 0) && (nHeightLevels == 0) && (!fExtractSurface) ) { _EXCEPTIONT("No pressure / height levels to process"); } // Open input file AnnounceStartBlock("Loading input file"); NcFile ncdf_in(strInputFile.c_str(), NcFile::ReadOnly); if (!ncdf_in.is_valid()) { _EXCEPTION1("Unable to open file \"%s\" for reading", strInputFile.c_str()); } // Load time array Announce("Time"); NcVar * varTime = ncdf_in.get_var("time"); if (varTime == NULL) { _EXCEPTION1("File \"%s\" does not contain variable \"time\"", strInputFile.c_str()); } int nTime = varTime->get_dim(0)->size(); DataArray1D<double> dTime(nTime); varTime->set_cur((long)0); varTime->get(&(dTime[0]), nTime); // Load latitude array Announce("Latitude"); NcVar * varLat = ncdf_in.get_var("lat"); if (varLat == NULL) { _EXCEPTION1("File \"%s\" does not contain variable \"lat\"", strInputFile.c_str()); } int nLat = varLat->get_dim(0)->size(); DataArray1D<double> dLat(nLat); varLat->set_cur((long)0); varLat->get(&(dLat[0]), nLat); // Load longitude array Announce("Longitude"); NcVar * varLon = ncdf_in.get_var("lon"); if (varLon == NULL) { _EXCEPTION1("File \"%s\" does not contain variable \"lon\"", strInputFile.c_str()); } int nLon = varLon->get_dim(0)->size(); DataArray1D<double> dLon(nLon); varLon->set_cur((long)0); varLon->get(&(dLon[0]), nLon); // Load level array Announce("Level"); NcVar * varLev = ncdf_in.get_var("lev"); if (varLev == NULL) { _EXCEPTION1("File \"%s\" does not contain variable \"lev\"", strInputFile.c_str()); } int nLev = varLev->get_dim(0)->size(); DataArray1D<double> dLev(nLev); varLev->set_cur((long)0); varLev->get(&(dLev[0]), nLev); // Load level interface array Announce("Interface"); NcVar * varILev = ncdf_in.get_var("ilev"); int nILev = 0; DataArray1D<double> dILev; if (varILev == NULL) { Announce("Warning: Variable \"ilev\" not found"); } else { nILev = varILev->get_dim(0)->size(); if (nILev != nLev + 1) { _EXCEPTIONT("Variable \"ilev\" must have size lev+1"); } dILev.Allocate(nILev); varILev->set_cur((long)0); varILev->get(&(dILev[0]), nILev); } // Load topography Announce("Topography"); NcVar * varZs = ncdf_in.get_var("Zs"); if (varZs == NULL) { _EXCEPTION1("File \"%s\" does not contain variable \"Zs\"", strInputFile.c_str()); } DataArray2D<double> dZs(nLat, nLon); varZs->set_cur((long)0, (long)0); varZs->get(&(dZs[0][0]), nLat, nLon); AnnounceEndBlock("Done"); // Open output file AnnounceStartBlock("Constructing output file"); NcFile ncdf_out(strOutputFile.c_str(), NcFile::Replace); if (!ncdf_out.is_valid()) { _EXCEPTION1("Unable to open file \"%s\" for writing", strOutputFile.c_str()); } CopyNcFileAttributes(&ncdf_in, &ncdf_out); // Output time array Announce("Time"); NcDim * dimOutTime = ncdf_out.add_dim("time"); NcVar * varOutTime = ncdf_out.add_var("time", ncDouble, dimOutTime); varOutTime->set_cur((long)0); varOutTime->put(&(dTime[0]), nTime); CopyNcVarAttributes(varTime, varOutTime); // Output pressure array NcDim * dimOutP = NULL; NcVar * varOutP = NULL; if (nPressureLevels > 0) { Announce("Pressure"); dimOutP = ncdf_out.add_dim("p", nPressureLevels); varOutP = ncdf_out.add_var("p", ncDouble, dimOutP); varOutP->set_cur((long)0); varOutP->put(&(vecPressureLevels[0]), nPressureLevels); } // Output height array NcDim * dimOutZ = NULL; NcVar * varOutZ = NULL; if (nHeightLevels > 0) { Announce("Height"); dimOutZ = ncdf_out.add_dim("z", nHeightLevels); varOutZ = ncdf_out.add_var("z", ncDouble, dimOutZ); varOutZ->set_cur((long)0); varOutZ->put(&(vecHeightLevels[0]), nHeightLevels); } // Output latitude and longitude array Announce("Latitude"); NcDim * dimOutLat = ncdf_out.add_dim("lat", nLat); NcVar * varOutLat = ncdf_out.add_var("lat", ncDouble, dimOutLat); varOutLat->set_cur((long)0); varOutLat->put(&(dLat[0]), nLat); CopyNcVarAttributes(varLat, varOutLat); Announce("Longitude"); NcDim * dimOutLon = ncdf_out.add_dim("lon", nLon); NcVar * varOutLon = ncdf_out.add_var("lon", ncDouble, dimOutLon); varOutLon->set_cur((long)0); varOutLon->put(&(dLon[0]), nLon); CopyNcVarAttributes(varLon, varOutLon); // Output topography Announce("Topography"); NcVar * varOutZs = ncdf_out.add_var( "Zs", ncDouble, dimOutLat, dimOutLon); varOutZs->set_cur((long)0, (long)0); varOutZs->put(&(dZs[0][0]), nLat, nLon); AnnounceEndBlock("Done"); // Done AnnounceEndBlock("Done"); // Load all variables Announce("Loading variables"); std::vector<NcVar *> vecNcVar; for (int v = 0; v < vecVariableStrings.size(); v++) { vecNcVar.push_back(ncdf_in.get_var(vecVariableStrings[v].c_str())); if (vecNcVar[v] == NULL) { _EXCEPTION1("Unable to load variable \"%s\" from file", vecVariableStrings[v].c_str()); } } // Physical constants Announce("Initializing thermodynamic variables"); NcAtt * attEarthRadius = ncdf_in.get_att("earth_radius"); double dEarthRadius = attEarthRadius->as_double(0); NcAtt * attRd = ncdf_in.get_att("Rd"); double dRd = attRd->as_double(0); NcAtt * attCp = ncdf_in.get_att("Cp"); double dCp = attCp->as_double(0); double dGamma = dCp / (dCp - dRd); NcAtt * attP0 = ncdf_in.get_att("P0"); double dP0 = attP0->as_double(0); double dPressureScaling = dP0 * std::pow(dRd / dP0, dGamma); NcAtt * attZtop = ncdf_in.get_att("Ztop"); double dZtop = attZtop->as_double(0); // Input data DataArray3D<double> dataIn(nLev, nLat, nLon); DataArray3D<double> dataInt(nILev, nLat, nLon); // Output data DataArray2D<double> dataOut(nLat, nLon); // Pressure in column DataArray1D<double> dataColumnP(nLev); // Height in column DataArray1D<double> dataColumnZ(nLev); DataArray1D<double> dataColumnIZ(nILev); // Column weights DataArray1D<double> dW(nLev); DataArray1D<double> dIW(nILev); // Loop through all times, pressure levels and variables AnnounceStartBlock("Interpolating"); // Add energy variable NcVar * varEnergy; if (fExtractTotalEnergy) { varEnergy = ncdf_out.add_var("TE", ncDouble, dimOutTime); } // Create output pressure variables std::vector<NcVar *> vecOutNcVarP; if (nPressureLevels > 0) { for (int v = 0; v < vecVariableStrings.size(); v++) { vecOutNcVarP.push_back( ncdf_out.add_var( vecVariableStrings[v].c_str(), ncDouble, dimOutTime, dimOutP, dimOutLat, dimOutLon)); // Copy attributes CopyNcVarAttributes(vecNcVar[v], vecOutNcVarP[v]); } } // Create output height variables std::vector<NcVar *> vecOutNcVarZ; if (nHeightLevels > 0) { for (int v = 0; v < vecVariableStrings.size(); v++) { std::string strVarName = vecVariableStrings[v]; if (nPressureLevels > 0) { strVarName += "z"; } vecOutNcVarZ.push_back( ncdf_out.add_var( strVarName.c_str(), ncDouble, dimOutTime, dimOutZ, dimOutLat, dimOutLon)); // Copy attributes CopyNcVarAttributes(vecNcVar[v], vecOutNcVarZ[v]); } } // Create output surface variable std::vector<NcVar *> vecOutNcVarS; if (fExtractSurface) { for (int v = 0; v < vecVariableStrings.size(); v++) { std::string strVarName = vecVariableStrings[v]; strVarName += "S"; vecOutNcVarS.push_back( ncdf_out.add_var( strVarName.c_str(), ncDouble, dimOutTime, dimOutLat, dimOutLon)); // Copy attributes CopyNcVarAttributes(vecNcVar[v], vecOutNcVarS[v]); } } // Loop over all times for (int t = 0; t < nTime; t++) { char szAnnounce[256]; sprintf(szAnnounce, "Time %i", t); AnnounceStartBlock(szAnnounce); // Rho DataArray3D<double> dataRho(nLev, nLat, nLon); NcVar * varRho = ncdf_in.get_var("Rho"); if (varRho == NULL) { _EXCEPTIONT("Unable to load variable \"Rho\" from file"); } varRho->set_cur(t, 0, 0, 0); varRho->get(&(dataRho[0][0][0]), 1, nLev, nLat, nLon); // Pressure DataArray3D<double> dataP(nLev, nLat, nLon); if (nPressureLevels != 0) { NcVar * varP = ncdf_in.get_var("P"); if (varP == NULL) { _EXCEPTIONT("Unable to load variable \"P\" from file"); } varP->set_cur(t, 0, 0, 0); varP->get(&(dataP[0][0][0]), 1, nLev, nLat, nLon); } /* // Populate pressure array if (nPressureLevels > 0) { // Calculate pointwise pressure for (int k = 0; k < nLev; k++) { for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { dataP[k][i][j] = dPressureScaling * exp(log(dataRho[k][i][j] * dataP[k][i][j]) * dGamma); } } } } */ // Height everywhere DataArray3D<double> dataZ(nLev, nLat, nLon); DataArray3D<double> dataIZ; if (nILev != 0) { dataIZ.Allocate(nILev, nLat, nLon); } // Populate height array if ((nHeightLevels > 0) || (fGeopotentialHeight)) { for (int k = 0; k < nLev; k++) { for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { dataZ[k][i][j] = dZs[i][j] + dLev[k] * (dZtop - dZs[i][j]); } } } for (int k = 0; k < nILev; k++) { for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { dataIZ[k][i][j] = dZs[i][j] + dILev[k] * (dZtop - dZs[i][j]); } } } } // Loop through all pressure levels and variables for (int v = 0; v < vecNcVar.size(); v++) { bool fOnInterfaces = false; // Load in the data array vecNcVar[v]->set_cur(t, 0, 0, 0); if (vecNcVar[v]->get_dim(1)->size() == nLev) { vecNcVar[v]->get(&(dataIn[0][0][0]), 1, nLev, nLat, nLon); Announce("%s (n)", vecVariableStrings[v].c_str()); } else if (vecNcVar[v]->get_dim(1)->size() == nILev) { vecNcVar[v]->get(&(dataInt[0][0][0]), 1, nILev, nLat, nLon); fOnInterfaces = true; Announce("%s (i)", vecVariableStrings[v].c_str()); } else { _EXCEPTION1("Variable \"%s\" has invalid level dimension", vecVariableStrings[v].c_str()); } // At the physical surface if (fExtractSurface) { if (fOnInterfaces) { for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { dataOut[i][j] = dataInt[0][i][j]; } } } else { int kBegin = 0; int kEnd = 3; PolynomialInterp::LagrangianPolynomialCoeffs( 3, dLev, dW, 0.0); // Loop thorugh all latlon indices for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { // Interpolate in the vertical dataOut[i][j] = 0.0; for (int k = kBegin; k < kEnd; k++) { dataOut[i][j] += dW[k] * dataIn[k][i][j]; } } } } // Write variable vecOutNcVarS[v]->set_cur(t, 0, 0); vecOutNcVarS[v]->put(&(dataOut[0][0]), 1, nLat, nLon); } // Loop through all pressure levels for (int p = 0; p < nPressureLevels; p++) { // Loop thorugh all latlon indices for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { // Store column pressure for (int k = 0; k < nLev; k++) { dataColumnP[k] = dataP[k][i][j]; } // Find weights int kBegin = 0; int kEnd = 0; // On a pressure surface InterpolationWeightsLinear( vecPressureLevels[p], dataColumnP, kBegin, kEnd, dW); // Interpolate in the vertical dataOut[i][j] = 0.0; for (int k = kBegin; k < kEnd; k++) { dataOut[i][j] += dW[k] * dataIn[k][i][j]; } } } // Write variable vecOutNcVarP[v]->set_cur(t, p, 0, 0); vecOutNcVarP[v]->put(&(dataOut[0][0]), 1, 1, nLat, nLon); } // Loop through all height levels for (int z = 0; z < nHeightLevels; z++) { // Loop thorugh all latlon indices for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { // Find weights int kBegin = 0; int kEnd = 0; // Interpolate from levels to z surfaces if (!fOnInterfaces) { for (int k = 0; k < nLev; k++) { dataColumnZ[k] = dataZ[k][i][j]; } InterpolationWeightsLinear( vecHeightLevels[z], dataColumnZ, kBegin, kEnd, dW); dataOut[i][j] = 0.0; for (int k = kBegin; k < kEnd; k++) { dataOut[i][j] += dW[k] * dataIn[k][i][j]; } // Interpolate from interfaces to z surfaces } else { for (int k = 0; k < nILev; k++) { dataColumnIZ[k] = dataIZ[k][i][j]; } InterpolationWeightsLinear( vecHeightLevels[z], dataColumnIZ, kBegin, kEnd, dIW); dataOut[i][j] = 0.0; for (int k = kBegin; k < kEnd; k++) { dataOut[i][j] += dIW[k] * dataInt[k][i][j]; } } } } // Write variable vecOutNcVarZ[v]->set_cur(t, z, 0, 0); vecOutNcVarZ[v]->put(&(dataOut[0][0]), 1, 1, nLat, nLon); } } // Output geopotential height if (fGeopotentialHeight) { Announce("Geopotential height"); // Output variables NcVar * varOutZ; NcVar * varOutZs; if (nPressureLevels > 0) { varOutZ = ncdf_out.add_var( "PHIZ", ncDouble, dimOutTime, dimOutP, dimOutLat, dimOutLon); } if (fExtractSurface) { varOutZs = ncdf_out.add_var( "PHIZS", ncDouble, dimOutTime, dimOutLat, dimOutLon); } // Interpolate onto pressure levels for (int p = 0; p < nPressureLevels; p++) { // Loop thorugh all latlon indices for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { int kBegin = 0; int kEnd = 0; for (int k = 0; k < nLev; k++) { dataColumnP[k] = dataP[k][i][j]; } InterpolationWeightsLinear( vecPressureLevels[p], dataColumnP, kBegin, kEnd, dW); // Interpolate in the vertical dataOut[i][j] = 0.0; for (int k = kBegin; k < kEnd; k++) { dataOut[i][j] += dW[k] * dataZ[k][i][j]; } } } // Write variable varOutZ->set_cur(t, p, 0, 0); varOutZ->put(&(dataOut[0][0]), 1, 1, nLat, nLon); } // Interpolate onto the physical surface if (fExtractSurface) { int kBegin = 0; int kEnd = 3; PolynomialInterp::LagrangianPolynomialCoeffs( 3, dLev, dW, 0.0); // Loop thorugh all latlon indices for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { // Interpolate in the vertical dataOut[i][j] = 0.0; for (int k = kBegin; k < kEnd; k++) { dataOut[i][j] += dW[k] * dataZ[k][i][j]; } } } // Write variable varOutZs->set_cur(t, 0, 0); varOutZs->put(&(dataOut[0][0]), 1, nLat, nLon); } } // Extract total energy if (fExtractTotalEnergy) { Announce("Total Energy"); // Zonal velocity DataArray3D<double> dataU(nLev, nLat, nLon); NcVar * varU = ncdf_in.get_var("U"); varU->set_cur(t, 0, 0, 0); varU->get(&(dataU[0][0][0]), 1, nLev, nLat, nLon); // Meridional velocity DataArray3D<double> dataV(nLev, nLat, nLon); NcVar * varV = ncdf_in.get_var("V"); varV->set_cur(t, 0, 0, 0); varV->get(&(dataV[0][0][0]), 1, nLev, nLat, nLon); // Vertical velocity DataArray3D<double> dataW(nLev, nLat, nLon); NcVar * varW = ncdf_in.get_var("W"); varW->set_cur(t, 0, 0, 0); varW->get(&(dataW[0][0][0]), 1, nLev, nLat, nLon); // Calculate total energy double dTotalEnergy = 0.0; double dElementRefArea = dEarthRadius * dEarthRadius * M_PI / static_cast<double>(nLat) * 2.0 * M_PI / static_cast<double>(nLon); for (int k = 0; k < nLev; k++) { for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { double dKineticEnergy = 0.5 * dataRho[k][i][j] * ( dataU[k][i][j] * dataU[k][i][j] + dataV[k][i][j] * dataV[k][i][j] + dataW[k][i][j] * dataW[k][i][j]); double dInternalEnergy = dataP[k][i][j] / (dGamma - 1.0); dTotalEnergy += (dKineticEnergy + dInternalEnergy) * std::cos(M_PI * dLat[i] / 180.0) * dElementRefArea * (dZtop - dZs[i][j]) / static_cast<double>(nLev); } } } // Put total energy into file varEnergy->set_cur(t); varEnergy->put(&dTotalEnergy, 1); } AnnounceEndBlock("Done"); } AnnounceEndBlock("Done"); } catch(Exception & e) { Announce(e.ToString().c_str()); } // Finalize MPI MPI_Finalize(); }
int main(int argc, char** argv) { NcError error(NcError::silent_nonfatal); try { // Input / Output types enum DiscretizationType { DiscretizationType_FV, DiscretizationType_CGLL, DiscretizationType_DGLL }; // Input mesh file std::string strInputMesh; // Overlap mesh file std::string strOverlapMesh; // Input metadata file std::string strInputMeta; // Output metadata file std::string strOutputMeta; // Input data type std::string strInputType; // Output data type std::string strOutputType; // Order of polynomial in each element int nPin; // Order of polynomial in each output element int nPout; // Use bubble on interior of spectral element nodes bool fBubble; // Enforce monotonicity bool fMonotoneType1; // Enforce monotonicity bool fMonotoneType2; // Enforce monotonicity bool fMonotoneType3; // Volumetric remapping bool fVolumetric; // No conservation bool fNoConservation; // Turn off checking for conservation / consistency bool fNoCheck; // Output mesh file std::string strOutputMesh; // Variable list std::string strVariables; // Output map file std::string strOutputMap; // Input data file std::string strInputData; // Output data file std::string strOutputData; // Name of the ncol variable std::string strNColName; // Output as double bool fOutputDouble; // List of variables to preserve std::string strPreserveVariables; // Preserve all non-remapped variables bool fPreserveAll; // Fill value override double dFillValueOverride; // Parse the command line BeginCommandLine() //CommandLineStringD(strMethod, "method", "", "[se]"); CommandLineString(strInputMesh, "in_mesh", ""); CommandLineString(strOutputMesh, "out_mesh", ""); CommandLineString(strOverlapMesh, "ov_mesh", ""); CommandLineString(strInputMeta, "in_meta", ""); CommandLineString(strOutputMeta, "out_meta", ""); CommandLineStringD(strInputType, "in_type", "fv", "[fv|cgll|dgll]"); CommandLineStringD(strOutputType, "out_type", "fv", "[fv|cgll|dgll]"); CommandLineInt(nPin, "in_np", 4); CommandLineInt(nPout, "out_np", 4); CommandLineBool(fBubble, "bubble"); CommandLineBool(fMonotoneType1, "mono"); CommandLineBool(fMonotoneType2, "mono2"); CommandLineBool(fMonotoneType3, "mono3"); CommandLineBool(fVolumetric, "volumetric"); CommandLineBool(fNoConservation, "noconserve"); CommandLineBool(fNoCheck, "nocheck"); CommandLineString(strVariables, "var", ""); CommandLineString(strOutputMap, "out_map", ""); CommandLineString(strInputData, "in_data", ""); CommandLineString(strOutputData, "out_data", ""); CommandLineString(strNColName, "ncol_name", "ncol"); CommandLineBool(fOutputDouble, "out_double"); CommandLineString(strPreserveVariables, "preserve", ""); CommandLineBool(fPreserveAll, "preserveall"); CommandLineDouble(dFillValueOverride, "fillvalue", 0.0); ParseCommandLine(argc, argv); EndCommandLine(argv) AnnounceBanner(); // Check command line parameters (mesh arguments) if (strInputMesh == "") { _EXCEPTIONT("No input mesh (--in_mesh) specified"); } if (strOutputMesh == "") { _EXCEPTIONT("No output mesh (--out_mesh) specified"); } // Overlap mesh if (strOverlapMesh == "") { _EXCEPTIONT("No overlap mesh specified"); } // Check command line parameters (data arguments) if ((strInputData != "") && (strOutputData == "")) { _EXCEPTIONT("--in_data specified without --out_data"); } if ((strInputData == "") && (strOutputData != "")) { _EXCEPTIONT("--out_data specified without --in_data"); } // Check metadata parameters if ((strInputMeta != "") && (strInputType == "fv")) { _EXCEPTIONT("--in_meta cannot be used with --in_type fv"); } if ((strOutputMeta != "") && (strOutputType == "fv")) { _EXCEPTIONT("--out_meta cannot be used with --out_type fv"); } // Check command line parameters (data type arguments) STLStringHelper::ToLower(strInputType); STLStringHelper::ToLower(strOutputType); DiscretizationType eInputType; DiscretizationType eOutputType; if (strInputType == "fv") { eInputType = DiscretizationType_FV; } else if (strInputType == "cgll") { eInputType = DiscretizationType_CGLL; } else if (strInputType == "dgll") { eInputType = DiscretizationType_DGLL; } else { _EXCEPTION1("Invalid \"in_type\" value (%s), expected [fv|cgll|dgll]", strInputType.c_str()); } if (strOutputType == "fv") { eOutputType = DiscretizationType_FV; } else if (strOutputType == "cgll") { eOutputType = DiscretizationType_CGLL; } else if (strOutputType == "dgll") { eOutputType = DiscretizationType_DGLL; } else { _EXCEPTION1("Invalid \"out_type\" value (%s), expected [fv|cgll|dgll]", strOutputType.c_str()); } // Monotonicity flags int nMonotoneType = 0; if (fMonotoneType1) { nMonotoneType = 1; } if (fMonotoneType2) { if (nMonotoneType != 0) { _EXCEPTIONT("Only one of --mono, --mono2 and --mono3 may be set"); } nMonotoneType = 2; } if (fMonotoneType3) { if (nMonotoneType != 0) { _EXCEPTIONT("Only one of --mono, --mono2 and --mono3 may be set"); } nMonotoneType = 3; } /* // Volumetric if (fVolumetric && (nMonotoneType != 0)) { _EXCEPTIONT("--volumetric cannot be used in conjunction with --mono#"); } */ // Create Offline Map OfflineMap mapRemap; // Initialize dimension information from file AnnounceStartBlock("Initializing dimensions of map"); Announce("Input mesh"); mapRemap.InitializeSourceDimensionsFromFile(strInputMesh); Announce("Output mesh"); mapRemap.InitializeTargetDimensionsFromFile(strOutputMesh); AnnounceEndBlock(NULL); // Parse variable list std::vector< std::string > vecVariableStrings; ParseVariableList(strVariables, vecVariableStrings); // Parse preserve variable list std::vector< std::string > vecPreserveVariableStrings; ParseVariableList(strPreserveVariables, vecPreserveVariableStrings); if (fPreserveAll && (vecPreserveVariableStrings.size() != 0)) { _EXCEPTIONT("--preserveall and --preserve cannot both be specified"); } // Load input mesh AnnounceStartBlock("Loading input mesh"); Mesh meshInput(strInputMesh); meshInput.RemoveZeroEdges(); AnnounceEndBlock(NULL); // Calculate Face areas AnnounceStartBlock("Calculating input mesh Face areas"); double dTotalAreaInput = meshInput.CalculateFaceAreas(); Announce("Input Mesh Geometric Area: %1.15e", dTotalAreaInput); AnnounceEndBlock(NULL); // Input mesh areas if (eInputType == DiscretizationType_FV) { mapRemap.SetSourceAreas(meshInput.vecFaceArea); } // Load output mesh AnnounceStartBlock("Loading output mesh"); Mesh meshOutput(strOutputMesh); meshOutput.RemoveZeroEdges(); AnnounceEndBlock(NULL); // Calculate Face areas AnnounceStartBlock("Calculating output mesh Face areas"); Real dTotalAreaOutput = meshOutput.CalculateFaceAreas(); Announce("Output Mesh Geometric Area: %1.15e", dTotalAreaOutput); AnnounceEndBlock(NULL); // Output mesh areas if (eOutputType == DiscretizationType_FV) { mapRemap.SetTargetAreas(meshOutput.vecFaceArea); } // Load overlap mesh AnnounceStartBlock("Loading overlap mesh"); Mesh meshOverlap(strOverlapMesh); meshOverlap.RemoveZeroEdges(); // Verify that overlap mesh is in the correct order int ixSourceFaceMax = (-1); int ixTargetFaceMax = (-1); if (meshOverlap.vecSourceFaceIx.size() != meshOverlap.vecTargetFaceIx.size() ) { _EXCEPTIONT("Invalid overlap mesh:\n" " Possible mesh file corruption?"); } for (int i = 0; i < meshOverlap.vecSourceFaceIx.size(); i++) { if (meshOverlap.vecSourceFaceIx[i] + 1 > ixSourceFaceMax) { ixSourceFaceMax = meshOverlap.vecSourceFaceIx[i] + 1; } if (meshOverlap.vecTargetFaceIx[i] + 1 > ixTargetFaceMax) { ixTargetFaceMax = meshOverlap.vecTargetFaceIx[i] + 1; } } // Check for forward correspondence in overlap mesh if (ixSourceFaceMax == meshInput.faces.size() //&& //(ixTargetFaceMax == meshOutput.faces.size()) ) { Announce("Overlap mesh forward correspondence found"); // Check for reverse correspondence in overlap mesh } else if ( ixSourceFaceMax == meshOutput.faces.size() //&& //(ixTargetFaceMax == meshInput.faces.size()) ) { Announce("Overlap mesh reverse correspondence found (reversing)"); // Reorder overlap mesh meshOverlap.ExchangeFirstAndSecondMesh(); // No correspondence found } else { _EXCEPTION2("Invalid overlap mesh:\n" " No correspondence found with input and output meshes (%i,%i)", ixSourceFaceMax, ixTargetFaceMax); } AnnounceEndBlock(NULL); // Calculate Face areas AnnounceStartBlock("Calculating overlap mesh Face areas"); Real dTotalAreaOverlap = meshOverlap.CalculateFaceAreas(); Announce("Overlap Mesh Area: %1.15e", dTotalAreaOverlap); AnnounceEndBlock(NULL); // Partial cover if (fabs(dTotalAreaOverlap - dTotalAreaInput) > 1.0e-10) { if (!fNoCheck) { Announce("WARNING: Significant mismatch between overlap mesh area " "and input mesh area.\n Automatically enabling --nocheck"); fNoCheck = true; } } /* // Recalculate input mesh area from overlap mesh if (fabs(dTotalAreaOverlap - dTotalAreaInput) > 1.0e-10) { AnnounceStartBlock("Overlap mesh only covers a sub-area of the sphere"); Announce("Recalculating source mesh areas"); dTotalAreaInput = meshInput.CalculateFaceAreasFromOverlap(meshOverlap); Announce("New Input Mesh Geometric Area: %1.15e", dTotalAreaInput); AnnounceEndBlock(NULL); } */ // Finite volume input / Finite volume output if ((eInputType == DiscretizationType_FV) && (eOutputType == DiscretizationType_FV) ) { // Generate reverse node array and edge map meshInput.ConstructReverseNodeArray(); meshInput.ConstructEdgeMap(); // Initialize coordinates for map mapRemap.InitializeSourceCoordinatesFromMeshFV(meshInput); mapRemap.InitializeTargetCoordinatesFromMeshFV(meshOutput); // Construct OfflineMap AnnounceStartBlock("Calculating offline map"); LinearRemapFVtoFV( meshInput, meshOutput, meshOverlap, nPin, mapRemap); // Finite volume input / Finite element output } else if (eInputType == DiscretizationType_FV) { DataMatrix3D<int> dataGLLNodes; DataMatrix3D<double> dataGLLJacobian; if (strOutputMeta != "") { AnnounceStartBlock("Loading meta data file"); LoadMetaDataFile(strOutputMeta, dataGLLNodes, dataGLLJacobian); AnnounceEndBlock(NULL); } else { AnnounceStartBlock("Generating output mesh meta data"); double dNumericalArea = GenerateMetaData( meshOutput, nPout, fBubble, dataGLLNodes, dataGLLJacobian); Announce("Output Mesh Numerical Area: %1.15e", dNumericalArea); AnnounceEndBlock(NULL); } // Initialize coordinates for map mapRemap.InitializeSourceCoordinatesFromMeshFV(meshInput); mapRemap.InitializeTargetCoordinatesFromMeshFE( meshOutput, nPout, dataGLLNodes); // Generate the continuous Jacobian bool fContinuous = (eOutputType == DiscretizationType_CGLL); if (eOutputType == DiscretizationType_CGLL) { GenerateUniqueJacobian( dataGLLNodes, dataGLLJacobian, mapRemap.GetTargetAreas()); } else { GenerateDiscontinuousJacobian( dataGLLJacobian, mapRemap.GetTargetAreas()); } // Generate reverse node array and edge map meshInput.ConstructReverseNodeArray(); meshInput.ConstructEdgeMap(); // Generate remap weights AnnounceStartBlock("Calculating offline map"); if (fVolumetric) { LinearRemapFVtoGLL_Volumetric( meshInput, meshOutput, meshOverlap, dataGLLNodes, dataGLLJacobian, mapRemap.GetTargetAreas(), nPin, mapRemap, nMonotoneType, fContinuous, fNoConservation); } else { LinearRemapFVtoGLL( meshInput, meshOutput, meshOverlap, dataGLLNodes, dataGLLJacobian, mapRemap.GetTargetAreas(), nPin, mapRemap, nMonotoneType, fContinuous, fNoConservation); } // Finite element input / Finite volume output } else if ( (eInputType != DiscretizationType_FV) && (eOutputType == DiscretizationType_FV) ) { DataMatrix3D<int> dataGLLNodes; DataMatrix3D<double> dataGLLJacobian; if (strInputMeta != "") { AnnounceStartBlock("Loading meta data file"); LoadMetaDataFile(strInputMeta, dataGLLNodes, dataGLLJacobian); AnnounceEndBlock(NULL); } else { AnnounceStartBlock("Generating input mesh meta data"); double dNumericalArea = GenerateMetaData( meshInput, nPin, fBubble, dataGLLNodes, dataGLLJacobian); Announce("Input Mesh Numerical Area: %1.15e", dNumericalArea); AnnounceEndBlock(NULL); if (fabs(dNumericalArea - dTotalAreaInput) > 1.0e-12) { Announce("WARNING: Significant mismatch between input mesh " "numerical area and geometric area"); } } if (dataGLLNodes.GetSubColumns() != meshInput.faces.size()) { _EXCEPTIONT("Number of element does not match between metadata and " "input mesh"); } // Initialize coordinates for map mapRemap.InitializeSourceCoordinatesFromMeshFE( meshInput, nPin, dataGLLNodes); mapRemap.InitializeTargetCoordinatesFromMeshFV(meshOutput); // Generate the continuous Jacobian for input mesh bool fContinuousIn = (eInputType == DiscretizationType_CGLL); if (eInputType == DiscretizationType_CGLL) { GenerateUniqueJacobian( dataGLLNodes, dataGLLJacobian, mapRemap.GetSourceAreas()); } else { GenerateDiscontinuousJacobian( dataGLLJacobian, mapRemap.GetSourceAreas()); } // Generate offline map AnnounceStartBlock("Calculating offline map"); if (fVolumetric) { _EXCEPTIONT("Unimplemented: Volumetric currently unavailable for" "GLL input mesh"); } LinearRemapSE4( meshInput, meshOutput, meshOverlap, dataGLLNodes, dataGLLJacobian, nMonotoneType, fContinuousIn, fNoConservation, mapRemap ); // Finite element input / Finite element output } else if ( (eInputType != DiscretizationType_FV) && (eOutputType != DiscretizationType_FV) ) { DataMatrix3D<int> dataGLLNodesIn; DataMatrix3D<double> dataGLLJacobianIn; DataMatrix3D<int> dataGLLNodesOut; DataMatrix3D<double> dataGLLJacobianOut; // Input metadata if (strInputMeta != "") { AnnounceStartBlock("Loading input meta data file"); LoadMetaDataFile( strInputMeta, dataGLLNodesIn, dataGLLJacobianIn); AnnounceEndBlock(NULL); } else { AnnounceStartBlock("Generating input mesh meta data"); double dNumericalAreaIn = GenerateMetaData( meshInput, nPin, fBubble, dataGLLNodesIn, dataGLLJacobianIn); Announce("Input Mesh Numerical Area: %1.15e", dNumericalAreaIn); AnnounceEndBlock(NULL); if (fabs(dNumericalAreaIn - dTotalAreaInput) > 1.0e-12) { Announce("WARNING: Significant mismatch between input mesh " "numerical area and geometric area"); } } // Output metadata if (strOutputMeta != "") { AnnounceStartBlock("Loading output meta data file"); LoadMetaDataFile( strOutputMeta, dataGLLNodesOut, dataGLLJacobianOut); AnnounceEndBlock(NULL); } else { AnnounceStartBlock("Generating output mesh meta data"); double dNumericalAreaOut = GenerateMetaData( meshOutput, nPout, fBubble, dataGLLNodesOut, dataGLLJacobianOut); Announce("Output Mesh Numerical Area: %1.15e", dNumericalAreaOut); AnnounceEndBlock(NULL); if (fabs(dNumericalAreaOut - dTotalAreaOutput) > 1.0e-12) { Announce("WARNING: Significant mismatch between output mesh " "numerical area and geometric area"); } } // Initialize coordinates for map mapRemap.InitializeSourceCoordinatesFromMeshFE( meshInput, nPin, dataGLLNodesIn); mapRemap.InitializeTargetCoordinatesFromMeshFE( meshOutput, nPout, dataGLLNodesOut); // Generate the continuous Jacobian for input mesh bool fContinuousIn = (eInputType == DiscretizationType_CGLL); if (eInputType == DiscretizationType_CGLL) { GenerateUniqueJacobian( dataGLLNodesIn, dataGLLJacobianIn, mapRemap.GetSourceAreas()); } else { GenerateDiscontinuousJacobian( dataGLLJacobianIn, mapRemap.GetSourceAreas()); } // Generate the continuous Jacobian for output mesh bool fContinuousOut = (eOutputType == DiscretizationType_CGLL); if (eOutputType == DiscretizationType_CGLL) { GenerateUniqueJacobian( dataGLLNodesOut, dataGLLJacobianOut, mapRemap.GetTargetAreas()); } else { GenerateDiscontinuousJacobian( dataGLLJacobianOut, mapRemap.GetTargetAreas()); } // Generate offline map AnnounceStartBlock("Calculating offline map"); LinearRemapGLLtoGLL2( meshInput, meshOutput, meshOverlap, dataGLLNodesIn, dataGLLJacobianIn, dataGLLNodesOut, dataGLLJacobianOut, mapRemap.GetTargetAreas(), nPin, nPout, nMonotoneType, fContinuousIn, fContinuousOut, fNoConservation, mapRemap ); } else { _EXCEPTIONT("Not implemented"); } //#pragma warning "NOTE: VERIFICATION DISABLED" // Verify consistency, conservation and monotonicity if (!fNoCheck) { AnnounceStartBlock("Verifying map"); mapRemap.IsConsistent(1.0e-8); mapRemap.IsConservative(1.0e-8); if (nMonotoneType != 0) { mapRemap.IsMonotone(1.0e-12); } AnnounceEndBlock(NULL); } AnnounceEndBlock(NULL); // Initialize element dimensions from input/output Mesh AnnounceStartBlock("Writing output"); // Output the Offline Map if (strOutputMap != "") { AnnounceStartBlock("Writing offline map"); mapRemap.Write(strOutputMap); AnnounceEndBlock(NULL); } // Apply Offline Map to data if (strInputData != "") { AnnounceStartBlock("Applying offline map to data"); mapRemap.SetFillValueOverride(static_cast<float>(dFillValueOverride)); mapRemap.Apply( strInputData, strOutputData, vecVariableStrings, strNColName, fOutputDouble, false); AnnounceEndBlock(NULL); } AnnounceEndBlock(NULL); // Copy variables from input file to output file if ((strInputData != "") && (strOutputData != "")) { if (fPreserveAll) { AnnounceStartBlock("Preserving variables"); mapRemap.PreserveAllVariables(strInputData, strOutputData); AnnounceEndBlock(NULL); } else if (vecPreserveVariableStrings.size() != 0) { AnnounceStartBlock("Preserving variables"); mapRemap.PreserveVariables( strInputData, strOutputData, vecPreserveVariableStrings); AnnounceEndBlock(NULL); } } AnnounceBanner(); return (0); } catch(Exception & e) { Announce(e.ToString().c_str()); return (-1); } catch(...) { return (-2); } }
int main(int argc, char** argv) { NcError error(NcError::silent_nonfatal); try { // Input filename std::string strInputFile; // Output mesh filename std::string strOutputFile; // Parse the command line BeginCommandLine() CommandLineString(strInputFile, "in", ""); CommandLineString(strOutputFile, "out", ""); ParseCommandLine(argc, argv); EndCommandLine(argv) // Check file names if (strInputFile == "") { std::cout << "ERROR: No input file specified" << std::endl; return (-1); } if (strOutputFile == "") { std::cout << "ERROR: No output file specified" << std::endl; return (-1); } AnnounceBanner(); // Load shapefile AnnounceStartBlock("Loading shapefile"); std::ifstream shpfile( strInputFile.c_str(), std::ios::in | std::ios::binary); SHPHeader shphead; shpfile.read((char*)(&shphead), sizeof(SHPHeader)); if (O32_HOST_ORDER == O32_LITTLE_ENDIAN) { shphead.iFileCode = SwapEndianInt32(shphead.iFileCode); shphead.iFileLength = SwapEndianInt32(shphead.iFileLength); } else if (O32_HOST_ORDER == O32_BIG_ENDIAN) { shphead.iVersion = SwapEndianInt32(shphead.iVersion); shphead.iShapeType = SwapEndianInt32(shphead.iShapeType); } else { _EXCEPTIONT("Invalid system Endian"); } if (shphead.iFileCode != SHPFileCodeRef) { _EXCEPTIONT("Input file does not appear to be a ESRI Shapefile: " "File code mismatch"); } if (shphead.iVersion != SHPVersionRef) { _EXCEPTIONT("Input file error: Version mismatch"); } if (shphead.iShapeType != SHPPolygonType) { _EXCEPTIONT("Input file error: Polygon type expected"); } SHPBounds shpbounds; shpfile.read((char*)(&shpbounds), sizeof(SHPBounds)); if (O32_HOST_ORDER == O32_BIG_ENDIAN) { shpbounds.dXmin = SwapEndianDouble(shpbounds.dXmin); shpbounds.dYmin = SwapEndianDouble(shpbounds.dYmin); shpbounds.dXmax = SwapEndianDouble(shpbounds.dXmax); shpbounds.dYmax = SwapEndianDouble(shpbounds.dXmax); shpbounds.dZmin = SwapEndianDouble(shpbounds.dZmin); shpbounds.dZmax = SwapEndianDouble(shpbounds.dZmax); shpbounds.dMmin = SwapEndianDouble(shpbounds.dMmin); shpbounds.dMmax = SwapEndianDouble(shpbounds.dMmax); } // Current position (in 16-bit words) int32_t iCurrentPosition = 50; int32_t iPolygonIx = 1; // Exodus mesh Mesh mesh; // Load records while (iCurrentPosition < shphead.iFileLength) { // Read the record header SHPRecordHeader shprechead; shpfile.read((char*)(&shprechead), sizeof(SHPRecordHeader)); if (shpfile.eof()) { break; } if (O32_HOST_ORDER == O32_LITTLE_ENDIAN) { shprechead.iNumber = SwapEndianInt32(shprechead.iNumber); shprechead.nLength = SwapEndianInt32(shprechead.nLength); } char szBuffer[128]; sprintf(szBuffer, "Polygon %i", shprechead.iNumber); iPolygonIx++; AnnounceStartBlock(szBuffer); iCurrentPosition += shprechead.nLength; // Read the shape type int32_t iShapeType; shpfile.read((char*)(&iShapeType), sizeof(int32_t)); if (shpfile.eof()) { break; } if (O32_HOST_ORDER == O32_BIG_ENDIAN) { iShapeType = SwapEndianInt32(iShapeType); } if (iShapeType != SHPPolygonType) { _EXCEPTIONT("Input file error: Record Polygon type expected"); } // Read the polygon header SHPPolygonHeader shppolyhead; shpfile.read((char*)(&shppolyhead), sizeof(SHPPolygonHeader)); if (shpfile.eof()) { break; } if (O32_HOST_ORDER == O32_BIG_ENDIAN) { shppolyhead.dXmin = SwapEndianDouble(shppolyhead.dXmin); shppolyhead.dYmin = SwapEndianDouble(shppolyhead.dYmin); shppolyhead.dXmax = SwapEndianDouble(shppolyhead.dXmax); shppolyhead.dYmax = SwapEndianDouble(shppolyhead.dYmax); shppolyhead.nNumParts = SwapEndianInt32(shppolyhead.nNumParts); shppolyhead.nNumPoints = SwapEndianInt32(shppolyhead.nNumPoints); } // Sanity check if (shppolyhead.nNumParts > 0x1000000) { _EXCEPTION1("Polygon NumParts exceeds sanity bound (%i)", shppolyhead.nNumParts); } if (shppolyhead.nNumPoints > 0x1000000) { _EXCEPTION1("Polygon NumPoints exceeds sanity bound (%i)", shppolyhead.nNumPoints); } Announce("containing %i part(s) with %i points", shppolyhead.nNumParts, shppolyhead.nNumPoints); Announce("Xmin: %3.5f", shppolyhead.dXmin); Announce("Ymin: %3.5f", shppolyhead.dYmin); Announce("Xmax: %3.5f", shppolyhead.dXmax); Announce("Ymax: %3.5f", shppolyhead.dYmax); if (shppolyhead.nNumParts != 1) { _EXCEPTIONT("Only polygons with 1 part currently supported" " in Exodus format"); } DataVector<int32_t> iParts(shppolyhead.nNumParts); shpfile.read((char*)&(iParts[0]), shppolyhead.nNumParts * sizeof(int32_t)); if (shpfile.eof()) { break; } DataVector<double> dPoints(shppolyhead.nNumPoints * 2); shpfile.read((char*)&(dPoints[0]), shppolyhead.nNumPoints * 2 * sizeof(double)); if (shpfile.eof()) { break; } if (O32_HOST_ORDER == O32_BIG_ENDIAN) { for (int i = 0; i < shppolyhead.nNumParts; i++) { iParts[i] = SwapEndianInt32(iParts[i]); } for (int i = 0; i < shppolyhead.nNumPoints * 2; i++) { dPoints[i] = SwapEndianDouble(dPoints[i]); } } // Convert to Exodus mesh int nFaces = mesh.faces.size(); int nNodes = mesh.nodes.size(); mesh.faces.resize(nFaces+1); mesh.nodes.resize(nNodes + shppolyhead.nNumPoints); mesh.faces[nFaces] = Face(shppolyhead.nNumPoints); for (int i = 0; i < shppolyhead.nNumPoints; i++) { double dLonRad = dPoints[2*i] / 180.0 * M_PI; double dLatRad = dPoints[2*i+1] / 180.0 * M_PI; mesh.nodes[nNodes+i].x = cos(dLatRad) * cos(dLonRad); mesh.nodes[nNodes+i].y = cos(dLatRad) * sin(dLonRad); mesh.nodes[nNodes+i].z = sin(dLatRad); mesh.faces[nFaces].SetNode(i, nNodes + i); } AnnounceEndBlock("Done"); } AnnounceEndBlock("Done"); // Write to file AnnounceStartBlock("Write Exodus mesh"); mesh.Write(strOutputFile); AnnounceEndBlock("Done"); // Announce AnnounceBanner(); return (0); } catch(Exception & e) { Announce(e.ToString().c_str()); return (-1); } catch(...) { return (-2); } }
void GridPatchCartesianGLL::EvaluateGeometricTerms() { // Physical constants const PhysicalConstants & phys = m_grid.GetModel().GetPhysicalConstants(); // Obtain Gauss Lobatto quadrature nodes and weights DataVector<double> dGL; DataVector<double> dWL; GaussLobattoQuadrature::GetPoints(m_nHorizontalOrder, 0.0, 1.0, dGL, dWL); // Obtain normalized areas in the vertical const DataVector<double> & dWNode = m_grid.GetREtaLevelsNormArea(); const DataVector<double> & dWREdge = m_grid.GetREtaInterfacesNormArea(); // Verify that normalized areas are correct double dWNodeSum = 0.0; for (int k = 0; k < dWNode.GetRows(); k++) { dWNodeSum += dWNode[k]; } if (fabs(dWNodeSum - 1.0) > 1.0e-13) { _EXCEPTION1("Error in normalized areas (%1.15e)", dWNodeSum); } if (m_grid.GetVerticalStaggering() != Grid::VerticalStaggering_Interfaces ) { double dWREdgeSum = 0.0; for (int k = 0; k < dWREdge.GetRows(); k++) { dWREdgeSum += dWREdge[k]; } if (fabs(dWREdgeSum - 1.0) > 1.0e-13) { _EXCEPTION1("Error in normalized areas (%1.15e)", dWREdgeSum); } } // Derivatives of basis functions GridCartesianGLL & gridCartesianGLL = dynamic_cast<GridCartesianGLL &>(m_grid); const DataMatrix<double> & dDxBasis1D = gridCartesianGLL.GetDxBasis1D(); double dy0 = 0.5 * fabs(m_dGDim[3] - m_dGDim[2]); double dfp = 2.0 * phys.GetOmega() * sin(m_dRefLat); double dbetap = 2.0 * phys.GetOmega() * cos(m_dRefLat) / phys.GetEarthRadius(); // Initialize the Coriolis force at each node for (int i = 0; i < m_box.GetATotalWidth(); i++) { for (int j = 0; j < m_box.GetBTotalWidth(); j++) { // Coriolis force by beta approximation //m_dataCoriolisF[i][j] = dfp + dbetap * (m_dataLat[i][j] - dy0); //m_dataCoriolisF[i][j] = dfp; //m_dataCoriolisF[i][j] = 0.0; } } // Initialize metric and Christoffel symbols in terrain-following coords for (int a = 0; a < GetElementCountA(); a++) { for (int b = 0; b < GetElementCountB(); b++) { for (int i = 0; i < m_nHorizontalOrder; i++) { for (int j = 0; j < m_nHorizontalOrder; j++) { // Nodal points int iElementA = m_box.GetAInteriorBegin() + a * m_nHorizontalOrder; int iElementB = m_box.GetBInteriorBegin() + b * m_nHorizontalOrder; int iA = iElementA + i; int iB = iElementB + j; // Topography height and its derivatives double dZs = m_dataTopography[iA][iB]; double dDaZs = m_dataTopographyDeriv[0][iA][iB]; double dDbZs = m_dataTopographyDeriv[1][iA][iB]; // Initialize 2D Jacobian m_dataJacobian2D[iA][iB] = 1.0; // Initialize 2D contravariant metric m_dataContraMetric2DA[iA][iB][0] = 1.0; m_dataContraMetric2DA[iA][iB][1] = 0.0; m_dataContraMetric2DB[iA][iB][0] = 0.0; m_dataContraMetric2DB[iA][iB][1] = 1.0; // Initialize 2D covariant metric m_dataCovMetric2DA[iA][iB][0] = 1.0; m_dataCovMetric2DA[iA][iB][1] = 0.0; m_dataCovMetric2DB[iA][iB][0] = 0.0; m_dataCovMetric2DB[iA][iB][1] = 1.0; // Vertical coordinate transform and its derivatives for (int k = 0; k < m_grid.GetRElements(); k++) { // Gal-Chen and Somerville (1975) terrain following coord // Schar Exponential Decay terrain following coord double dREta = m_grid.GetREtaLevel(k); double dREtaStretch; double dDxREtaStretch; m_grid.EvaluateVerticalStretchF( dREta, dREtaStretch, dDxREtaStretch); //double dZ = dZs + (m_grid.GetZtop() - dZs) * dREtaStretch; //double dbZ = sinh(m_grid.GetZtop() * (1.0 - dREtaStretch) / m_dSL) // / sinh(m_grid.GetZtop() / m_dSL); //double dZ = m_grid.GetZtop() * dREtaStretch + dZs; // * dbZ; double dZ = dZs + (m_grid.GetZtop() - dZs) * dREtaStretch; double dDaZ = (1.0 - dREtaStretch) * dDaZs; double dDbZ = (1.0 - dREtaStretch) * dDbZs; double dDxZ = (m_grid.GetZtop() - dZs) * dDxREtaStretch; /* double dDaZ = dbZ * dDaZs; double dDbZ = dbZ * dDbZs; double dDxZ = m_grid.GetZtop() - dZs * m_grid.GetZtop() * cosh(m_grid.GetZtop() * (1.0 - dREtaStretch) / m_dSL) / (m_dSL * sinh(m_grid.GetZtop() / m_dSL)); dDxZ *= dDxREtaStretch; */ // Calculate pointwise Jacobian m_dataJacobian[k][iA][iB] = dDxZ * m_dataJacobian2D[iA][iB]; // Element area associated with each model level GLL node m_dataElementArea[k][iA][iB] = m_dataJacobian[k][iA][iB] * dWL[i] * GetElementDeltaA() * dWL[j] * GetElementDeltaB() * dWNode[k]; // Contravariant metric components m_dataContraMetricA[k][iA][iB][0] = m_dataContraMetric2DA[iA][iB][0]; m_dataContraMetricA[k][iA][iB][1] = m_dataContraMetric2DA[iA][iB][1]; m_dataContraMetricA[k][iA][iB][2] = - dDaZ / dDxZ; m_dataContraMetricB[k][iA][iB][0] = m_dataContraMetric2DB[iA][iB][0]; m_dataContraMetricB[k][iA][iB][1] = m_dataContraMetric2DB[iA][iB][1]; m_dataContraMetricB[k][iA][iB][2] = - dDbZ / dDxZ; m_dataContraMetricXi[k][iA][iB][0] = m_dataContraMetricA[k][iA][iB][2]; m_dataContraMetricXi[k][iA][iB][1] = m_dataContraMetricB[k][iA][iB][2]; m_dataContraMetricXi[k][iA][iB][2] = (1.0 + dDaZ * dDaZ + dDbZ * dDbZ) / (dDxZ * dDxZ); // Covariant metric components m_dataCovMetricA[k][iA][iB][0] = m_dataCovMetric2DA[iA][iB][0] + dDaZ * dDaZ; m_dataCovMetricA[k][iA][iB][1] = m_dataCovMetric2DA[iA][iB][1] + dDaZ * dDbZ; m_dataCovMetricA[k][iA][iB][2] = dDaZ * dDxZ; m_dataCovMetricB[k][iA][iB][0] = m_dataCovMetric2DB[iA][iB][0] + dDbZ * dDaZ; m_dataCovMetricB[k][iA][iB][1] = m_dataCovMetric2DB[iA][iB][1] + dDbZ * dDbZ; m_dataCovMetricB[k][iA][iB][2] = dDbZ * dDxZ; m_dataCovMetricXi[k][iA][iB][0] = dDaZ * dDxZ; m_dataCovMetricXi[k][iA][iB][1] = dDbZ * dDxZ; m_dataCovMetricXi[k][iA][iB][2] = dDxZ * dDxZ; // Derivatives of the vertical coordinate transform m_dataDerivRNode[k][iA][iB][0] = dDaZ; m_dataDerivRNode[k][iA][iB][1] = dDbZ; m_dataDerivRNode[k][iA][iB][2] = dDxZ; } // Metric terms at vertical interfaces for (int k = 0; k <= m_grid.GetRElements(); k++) { // Gal-Chen and Somerville (1975) terrain following coord // Schar Exponential decay terrain following coord double dREta = m_grid.GetREtaInterface(k); /* double dREtaStretch; double dDxREtaStretch; m_grid.EvaluateVerticalStretchF( dREta, dREtaStretch, dDxREtaStretch); double dZ = dZs + (m_grid.GetZtop() - dZs) * dREtaStretch; double dDaZ = (1.0 - dREtaStretch) * dDaZs; double dDbZ = (1.0 - dREtaStretch) * dDbZs; double dDxZ = (m_grid.GetZtop() - dZs) * dDxREtaStretch; */ double dREtaStretch; double dDxREtaStretch; m_grid.EvaluateVerticalStretchF( dREta, dREtaStretch, dDxREtaStretch); /* //double dZ = dZs + (m_grid.GetZtop() - dZs) * dREtaStretch; double dbZ = sinh(m_grid.GetZtop() * (1.0 - dREtaStretch) / m_dSL) / sinh(m_grid.GetZtop() / m_dSL); double dZ = m_grid.GetZtop() * dREtaStretch + dZs * dbZ; */ double dDaZ = (1.0 - dREtaStretch) * dDaZs; double dDbZ = (1.0 - dREtaStretch) * dDbZs; double dDxZ = (m_grid.GetZtop() - dZs) * dDxREtaStretch; /* double dDaZ = dbZ * dDaZs; double dDbZ = dbZ * dDbZs; double dDxZ = m_grid.GetZtop() - dZs * m_grid.GetZtop() * cosh(m_grid.GetZtop() * (1.0 - dREtaStretch) / m_dSL) / (m_dSL * sinh(m_grid.GetZtop() / m_dSL)); dDxZ *= dDxREtaStretch; */ // Calculate pointwise Jacobian m_dataJacobianREdge[k][iA][iB] = dDxZ * m_dataJacobian2D[iA][iB]; // Element area associated with each model interface GLL node m_dataElementAreaREdge[k][iA][iB] = m_dataJacobianREdge[k][iA][iB] * dWL[i] * GetElementDeltaA() * dWL[j] * GetElementDeltaB() * dWREdge[k]; // Components of the contravariant metric m_dataContraMetricAREdge[k][iA][iB][0] = m_dataContraMetric2DA[iA][iB][0]; m_dataContraMetricAREdge[k][iA][iB][1] = m_dataContraMetric2DA[iA][iB][1]; m_dataContraMetricAREdge[k][iA][iB][2] = - dDaZ / dDxZ; m_dataContraMetricBREdge[k][iA][iB][0] = m_dataContraMetric2DB[iA][iB][0]; m_dataContraMetricBREdge[k][iA][iB][1] = m_dataContraMetric2DB[iA][iB][1]; m_dataContraMetricBREdge[k][iA][iB][2] = - dDbZ / dDxZ; m_dataContraMetricXiREdge[k][iA][iB][0] = - dDaZ / dDxZ; m_dataContraMetricXiREdge[k][iA][iB][1] = - dDbZ / dDxZ; m_dataContraMetricXiREdge[k][iA][iB][2] = (1.0 + dDaZ * dDaZ + dDbZ * dDbZ) / (dDxZ * dDxZ); // Derivatives of the vertical coordinate transform m_dataDerivRREdge[k][iA][iB][0] = dDaZ; m_dataDerivRREdge[k][iA][iB][1] = dDbZ; m_dataDerivRREdge[k][iA][iB][2] = dDxZ; } } } } } }
void ReadCFTimeDataFromNcFile( NcFile * ncfile, const std::string & strFilename, std::vector<Time> & vecTimes, bool fWarnOnMissingCalendar ) { // Empty existing Time vector vecTimes.clear(); // Get time dimension NcDim * dimTime = ncfile->get_dim("time"); if (dimTime == NULL) { _EXCEPTION1("Dimension \"time\" not found in file \"%s\"", strFilename.c_str()); } // Get time variable NcVar * varTime = ncfile->get_var("time"); if (varTime == NULL) { _EXCEPTION1("Variable \"time\" not found in file \"%s\"", strFilename.c_str()); } if (varTime->num_dims() != 1) { _EXCEPTION1("Variable \"time\" has more than one dimension in file \"%s\"", strFilename.c_str()); } if (strcmp(varTime->get_dim(0)->name(), "time") != 0) { _EXCEPTION1("Variable \"time\" does not have dimension \"time\" in file \"%s\"", strFilename.c_str()); } // Calendar attribute NcAtt * attTimeCal = varTime->get_att("calendar"); std::string strCalendar; if (attTimeCal == NULL) { if (fWarnOnMissingCalendar) { Announce("WARNING: Variable \"time\" is missing \"calendar\" attribute; assuming \"standard\""); } strCalendar = "standard"; } else { strCalendar = attTimeCal->as_string(0); } Time::CalendarType eCalendarType = Time::CalendarTypeFromString(strCalendar); // Units attribute NcAtt * attTimeUnits = varTime->get_att("units"); if (attTimeUnits == NULL) { _EXCEPTION1("Variable \"time\" is missing \"units\" attribute in file \"%s\"", strFilename.c_str()); } std::string strTimeUnits = attTimeUnits->as_string(0); // Load in time data DataVector<int> vecTimeInt; DataVector<float> vecTimeFloat; DataVector<double> vecTimeDouble; DataVector<ncint64> vecTimeInt64; if (varTime->type() == ncInt) { vecTimeInt.Initialize(dimTime->size()); varTime->set_cur((long)0); varTime->get(&(vecTimeInt[0]), dimTime->size()); } else if (varTime->type() == ncFloat) { vecTimeFloat.Initialize(dimTime->size()); varTime->set_cur((long)0); varTime->get(&(vecTimeFloat[0]), dimTime->size()); } else if (varTime->type() == ncDouble) { vecTimeDouble.Initialize(dimTime->size()); varTime->set_cur((long)0); varTime->get(&(vecTimeDouble[0]), dimTime->size()); } else if (varTime->type() == ncInt64) { vecTimeInt64.Initialize(dimTime->size()); varTime->set_cur((long)0); varTime->get(&(vecTimeInt64[0]), dimTime->size()); } else { _EXCEPTION1("Variable \"time\" has invalid type " "(expected \"int\", \"int64\", \"float\" or \"double\")" " in file \"%s\"", strFilename.c_str()); } for (int t = 0; t < dimTime->size(); t++) { Time time(eCalendarType); if (varTime->type() == ncInt) { time.FromCFCompliantUnitsOffsetInt( strTimeUnits, vecTimeInt[t]); } else if (varTime->type() == ncFloat) { time.FromCFCompliantUnitsOffsetDouble( strTimeUnits, static_cast<double>(vecTimeFloat[t])); } else if (varTime->type() == ncDouble) { time.FromCFCompliantUnitsOffsetDouble( strTimeUnits, vecTimeDouble[t]); } else if (varTime->type() == ncInt64) { time.FromCFCompliantUnitsOffsetInt( strTimeUnits, (int)(vecTimeInt64[t])); } vecTimes.push_back(time); } }
Time OutputManagerComposite::Input( const std::string & strFileName ) { #ifdef USE_MPI // Set the flag indicating that output came from a restart file m_fFromRestartFile = true; // Determine processor rank int nRank; MPI_Comm_rank(MPI_COMM_WORLD, &nRank); // The active model const Model & model = m_grid.GetModel(); // Open binary input stream std::ifstream ifsActiveInput; ifsActiveInput.open( strFileName.c_str(), std::ios::binary | std::ios::in); if (!ifsActiveInput) { _EXCEPTION1("Unable to open input file \"%s\"", strFileName.c_str()); } // Read check bits int iCheckInput; ifsActiveInput.read((char *)(&iCheckInput), sizeof(int)); if (iCheckInput != m_iCheck) { _EXCEPTION1("Invalid or incompatible input file \"%s\"", strFileName.c_str()); } // Read current time Time timeCurrent; ifsActiveInput.read((char *)(&(timeCurrent)), sizeof(Time)); // Read Grid parameters from file DataContainer & dcGridParameters = m_grid.GetDataContainerParameters(); int nGridParametersByteSize = dcGridParameters.GetTotalByteSize(); char * pGridParameters = (char *)(dcGridParameters.GetPointer()); ifsActiveInput.read(pGridParameters, nGridParametersByteSize); // Initialize the Grid from specified parameters m_grid.InitializeDataLocal(); // Load Grid data from file DataContainer & dcGridPatchData = m_grid.GetDataContainerPatchData(); int nGridPatchDataByteSize = dcGridPatchData.GetTotalByteSize(); char * pGridPatchData = (char *)(dcGridPatchData.GetPointer()); ifsActiveInput.read(pGridPatchData, nGridPatchDataByteSize); // Distribute GridPatches to processors m_grid.DistributePatches(); // Determine space allocation for each GridPatch m_vecGridPatchByteSize.Allocate(m_grid.GetPatchCount(), 2); for (int i = 0; i < m_grid.GetActivePatchCount(); i++) { const GridPatch * pPatch = m_grid.GetActivePatch(i); int iPatchIx = pPatch->GetPatchIndex(); if (iPatchIx > m_grid.GetPatchCount()) { _EXCEPTION2("PatchIndex (%i) out of range [0,%i)", iPatchIx, m_grid.GetPatchCount()); } const DataContainer & dcGeometric = pPatch->GetDataContainerGeometric(); m_vecGridPatchByteSize[iPatchIx][0] = dcGeometric.GetTotalByteSize(); const DataContainer & dcActiveState = pPatch->GetDataContainerActiveState(); m_vecGridPatchByteSize[iPatchIx][1] = dcActiveState.GetTotalByteSize(); } MPI_Allreduce( MPI_IN_PLACE, &(m_vecGridPatchByteSize[0][0]), m_vecGridPatchByteSize.GetTotalSize(), MPI_INT, MPI_MAX, MPI_COMM_WORLD); // Initialize byte location for each GridPatch m_vecGridPatchByteLoc.Allocate(m_grid.GetPatchCount(), 2); m_vecGridPatchByteLoc[0][0] = 0; m_vecGridPatchByteLoc[0][1] = m_vecGridPatchByteSize[0][0]; for (int i = 1; i < m_vecGridPatchByteSize.GetRows(); i++) { m_vecGridPatchByteLoc[i][0] = m_vecGridPatchByteLoc[i-1][1] + m_vecGridPatchByteSize[i-1][1]; m_vecGridPatchByteLoc[i][1] = m_vecGridPatchByteLoc[i][0] + m_vecGridPatchByteSize[i][0]; } // Reference position std::streampos posRefFile = ifsActiveInput.tellg(); if (posRefFile == (-1)) { _EXCEPTIONT("ActiveInput::tellg() fail"); } // Load in GridPatch data from file for (int i = 0; i < m_grid.GetActivePatchCount(); i++) { GridPatch * pPatch = m_grid.GetActivePatch(i); int iPatchIx = pPatch->GetPatchIndex(); if (iPatchIx > m_grid.GetPatchCount()) { _EXCEPTION2("PatchIndex (%i) out of range [0,%i)", iPatchIx, m_grid.GetPatchCount()); } DataContainer & dcGeometric = pPatch->GetDataContainerGeometric(); int nGeometricDataByteSize = dcGeometric.GetTotalByteSize(); char * pGeometricData = (char *)(dcGeometric.GetPointer()); ifsActiveInput.seekg( posRefFile + m_vecGridPatchByteLoc[iPatchIx][0]); ifsActiveInput.read( pGeometricData, m_vecGridPatchByteSize[iPatchIx][0]); DataContainer & dcActiveState = pPatch->GetDataContainerActiveState(); int nActiveStateDataByteSize = dcActiveState.GetTotalByteSize(); char * pActiveStateData = (char *)(dcActiveState.GetPointer()); ifsActiveInput.seekg( posRefFile + m_vecGridPatchByteLoc[iPatchIx][1]); ifsActiveInput.read( pActiveStateData, m_vecGridPatchByteSize[iPatchIx][1]); } // Close the file ifsActiveInput.close(); // Barrier MPI_Barrier(MPI_COMM_WORLD); #else _EXCEPTIONT("Not implemented without USE_MPI"); #endif return timeCurrent; }
void OutputManagerComposite::Output( const Time & time ) { #ifdef USE_MPI // Check for open file if (!IsFileOpen()) { _EXCEPTIONT("No file available for output"); } // Verify that only one output has been performed if (m_ixOutputTime != 0) { _EXCEPTIONT("Only one Composite output allowed per file"); } // Determine processor rank int nRank; MPI_Comm_rank(MPI_COMM_WORLD, &nRank); // Data types const int ExchangeDataType_Geometric = 0; const int ExchangeDataType_ActiveState = 1; const int ExchangeDataType_Count = 2; // Determine space allocation for each GridPatch m_vecGridPatchByteSize.Allocate(m_grid.GetPatchCount(), 2); for (int i = 0; i < m_grid.GetActivePatchCount(); i++) { const GridPatch * pPatch = m_grid.GetActivePatch(i); int iPatchIx = pPatch->GetPatchIndex(); if (iPatchIx > m_grid.GetPatchCount()) { _EXCEPTION2("PatchIndex (%i) out of range [0,%i)", iPatchIx, m_grid.GetPatchCount()); } const DataContainer & dcGeometric = pPatch->GetDataContainerGeometric(); m_vecGridPatchByteSize[iPatchIx][0] = dcGeometric.GetTotalByteSize(); const DataContainer & dcActiveState = pPatch->GetDataContainerActiveState(); m_vecGridPatchByteSize[iPatchIx][1] = dcActiveState.GetTotalByteSize(); } // Reduce GridPatch byte size if (nRank != 0) { MPI_Reduce( &(m_vecGridPatchByteSize[0][0]), &(m_vecGridPatchByteSize[0][0]), m_vecGridPatchByteSize.GetTotalSize(), MPI_INT, MPI_MAX, 0, MPI_COMM_WORLD); // Reduce GridPatch byte size and write Grid information } else if (nRank == 0) { // Reduce MPI_Reduce( MPI_IN_PLACE, &(m_vecGridPatchByteSize[0][0]), m_vecGridPatchByteSize.GetTotalSize(), MPI_INT, MPI_MAX, 0, MPI_COMM_WORLD); // The active Model const Model & model = m_grid.GetModel(); // Get maximum byte size for exchange int sMaxRecvBufferByteSize = 0; for (int i = 0; i < m_vecGridPatchByteSize.GetRows(); i++) { if (m_vecGridPatchByteSize[i][0] > sMaxRecvBufferByteSize) { sMaxRecvBufferByteSize = m_vecGridPatchByteSize[i][0]; } if (m_vecGridPatchByteSize[i][1] > sMaxRecvBufferByteSize) { sMaxRecvBufferByteSize = m_vecGridPatchByteSize[i][1]; } } // Allocate Recv buffer at root if (m_vecRecvBuffer.GetRows() < sMaxRecvBufferByteSize) { m_vecRecvBuffer.Allocate(sMaxRecvBufferByteSize); } // Initialize byte location for each GridPatch m_vecGridPatchByteLoc.Allocate(m_grid.GetPatchCount(), 2); m_vecGridPatchByteLoc[0][0] = 0; m_vecGridPatchByteLoc[0][1] = m_vecGridPatchByteSize[0][0]; for (int i = 1; i < m_vecGridPatchByteSize.GetRows(); i++) { m_vecGridPatchByteLoc[i][0] = m_vecGridPatchByteLoc[i-1][1] + m_vecGridPatchByteSize[i-1][1]; m_vecGridPatchByteLoc[i][1] = m_vecGridPatchByteLoc[i][0] + m_vecGridPatchByteSize[i][0]; } // Write check bits m_ofsActiveOutput.write((const char *)(&m_iCheck), sizeof(int)); // Write current time const Time & timeCurrent = model.GetCurrentTime(); m_ofsActiveOutput.write((const char *)(&(timeCurrent)), sizeof(Time)); // Write Grid information to file const DataContainer & dcGridParameters = m_grid.GetDataContainerParameters(); int nGridParametersByteSize = dcGridParameters.GetTotalByteSize(); const char * pGridParameters = (const char *)(dcGridParameters.GetPointer()); m_ofsActiveOutput.write( pGridParameters, nGridParametersByteSize); const DataContainer & dcGridPatchData = m_grid.GetDataContainerPatchData(); int nGridPatchDataByteSize = dcGridPatchData.GetTotalByteSize(); const char * pGridPatchData = (const char *)(dcGridPatchData.GetPointer()); m_ofsActiveOutput.write( pGridPatchData, nGridPatchDataByteSize); } // Send data from GridPatches to root if (nRank != 0) { int nActivePatches = m_grid.GetActivePatchCount(); if (nActivePatches == 0) { _EXCEPTIONT("No GridPatches on processor"); } DataArray1D<MPI_Request> vecSendReqGeo(nActivePatches); DataArray1D<MPI_Request> vecSendReqAcS(nActivePatches); for (int i = 0; i < nActivePatches; i++) { const GridPatch * pPatch = m_grid.GetActivePatch(i); const DataContainer & dcGeometric = pPatch->GetDataContainerGeometric(); int nGeometricDataByteSize = dcGeometric.GetTotalByteSize(); const unsigned char * pGeometricData = dcGeometric.GetPointer(); MPI_Isend( const_cast<unsigned char *>(pGeometricData), nGeometricDataByteSize, MPI_BYTE, 0, ExchangeDataType_Geometric, MPI_COMM_WORLD, &(vecSendReqGeo[i])); const DataContainer & dcActiveState = pPatch->GetDataContainerActiveState(); int nActiveStateDataByteSize = dcActiveState.GetTotalByteSize(); const unsigned char * pActiveStateData = dcActiveState.GetPointer(); MPI_Isend( const_cast<unsigned char *>(pActiveStateData), nActiveStateDataByteSize, MPI_BYTE, 0, ExchangeDataType_ActiveState, MPI_COMM_WORLD, &(vecSendReqAcS[i])); /* printf("Send Geo %i %i\n", pPatch->GetPatchIndex(), nGeometricDataByteSize); printf("Send AcS %i %i\n", pPatch->GetPatchIndex(), nActiveStateDataByteSize); */ } int iWaitAllMsgGeo = MPI_Waitall( nActivePatches, &(vecSendReqGeo[0]), MPI_STATUSES_IGNORE); if (iWaitAllMsgGeo == MPI_ERR_IN_STATUS) { _EXCEPTIONT("MPI_Waitall returned MPI_ERR_IN_STATUS"); } int iWaitAllMsgAcS = MPI_Waitall( nActivePatches, &(vecSendReqAcS[0]), MPI_STATUSES_IGNORE); if (iWaitAllMsgAcS == MPI_ERR_IN_STATUS) { _EXCEPTIONT("MPI_Waitall returned MPI_ERR_IN_STATUS"); } //std::cout << "WAIT DONE" << std::endl; // Receive data and output to file } else { // Reference position std::streampos posRefFile = m_ofsActiveOutput.tellp(); if (posRefFile == (-1)) { _EXCEPTIONT("ActiveOutput::tellp() fail"); } // Write my GridPatch data to file for (int i = 0; i < m_grid.GetActivePatchCount(); i++) { const GridPatch * pPatch = m_grid.GetActivePatch(i); int iPatchIx = pPatch->GetPatchIndex(); if (iPatchIx > m_grid.GetPatchCount()) { _EXCEPTION2("PatchIndex (%i) out of range [0,%i)", iPatchIx, m_grid.GetPatchCount()); } /* printf("Write %i %i %i %i %i\n", iPatchIx, m_vecGridPatchByteLoc[iPatchIx][0], m_vecGridPatchByteSize[iPatchIx][0], m_vecGridPatchByteLoc[iPatchIx][1], m_vecGridPatchByteSize[iPatchIx][1]); */ const DataContainer & dcGeometric = pPatch->GetDataContainerGeometric(); int nGeometricDataByteSize = dcGeometric.GetTotalByteSize(); const char * pGeometricData = (const char *)(dcGeometric.GetPointer()); m_ofsActiveOutput.seekp( posRefFile + m_vecGridPatchByteLoc[iPatchIx][0]); m_ofsActiveOutput.write( pGeometricData, m_vecGridPatchByteSize[iPatchIx][0]); const DataContainer & dcActiveState = pPatch->GetDataContainerActiveState(); int nActiveStateDataByteSize = dcActiveState.GetTotalByteSize(); const char * pActiveStateData = (const char *)(dcActiveState.GetPointer()); m_ofsActiveOutput.seekp( posRefFile + m_vecGridPatchByteLoc[iPatchIx][1]); m_ofsActiveOutput.write( pActiveStateData, m_vecGridPatchByteSize[iPatchIx][1]); } // Recieve all data objects from neighbors int nRemainingMessages = 2 * (m_grid.GetPatchCount() - m_grid.GetActivePatchCount()); for (; nRemainingMessages > 0; nRemainingMessages--) { // Receive a consolidation message MPI_Status status; MPI_Recv( &(m_vecRecvBuffer[0]), m_vecRecvBuffer.GetRows(), MPI_CHAR, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); // Data type from TAG int iDataType = status.MPI_TAG; if ((iDataType < 0) || (iDataType >= ExchangeDataType_Count)) { _EXCEPTION1("MPI_TAG (%i) out of range", iDataType); } // Check patch index int iPatchIx = *((int*)(&(m_vecRecvBuffer[0]))); if (iPatchIx > m_vecGridPatchByteLoc.GetRows()) { _EXCEPTION2("PatchIndex (%i) out of range [0,%i)", iPatchIx, m_vecGridPatchByteLoc.GetRows()); } /* if (iDataType == 0) { printf("Recv Geo %i %i\n", pPatchIx[0], m_vecGridPatchByteSize[pPatchIx[0]][iDataType]); } else { printf("Recv AcS %i %i\n", pPatchIx[0], m_vecGridPatchByteSize[pPatchIx[0]][iDataType]); } */ m_ofsActiveOutput.seekp( posRefFile + m_vecGridPatchByteLoc[iPatchIx][iDataType]); m_ofsActiveOutput.write( (const char *)(&(m_vecRecvBuffer[0])), m_vecGridPatchByteSize[iPatchIx][iDataType]); } } // Barrier MPI_Barrier(MPI_COMM_WORLD); #else _EXCEPTIONT("Not implemented without USE_MPI"); #endif }
void MeshUtilities::FindFaceFromNode( const Mesh & mesh, const Node & node, FindFaceStruct & aFindFaceStruct ) { // Reset the FaceStruct aFindFaceStruct.vecFaceIndices.clear(); aFindFaceStruct.vecFaceLocations.clear(); aFindFaceStruct.loc = Face::NodeLocation_Undefined; // Loop through all faces to find overlaps // Note: This algorithm can likely be dramatically improved for (int l = 0; l < mesh.faces.size(); l++) { Face::NodeLocation loc; int ixLocation; ContainsNode( mesh.faces[l], mesh.nodes, node, loc, ixLocation); if (loc == Face::NodeLocation_Exterior) { continue; } #ifdef VERBOSE printf("%i\n", l); printf("n: %1.5e %1.5e %1.5e\n", node.x, node.y, node.z); printf("n0: %1.5e %1.5e %1.5e\n", mesh.nodes[mesh.faces[l][0]].x, mesh.nodes[mesh.faces[l][0]].y, mesh.nodes[mesh.faces[l][0]].z); printf("n1: %1.5e %1.5e %1.5e\n", mesh.nodes[mesh.faces[l][1]].x, mesh.nodes[mesh.faces[l][1]].y, mesh.nodes[mesh.faces[l][1]].z); printf("n2: %1.5e %1.5e %1.5e\n", mesh.nodes[mesh.faces[l][2]].x, mesh.nodes[mesh.faces[l][2]].y, mesh.nodes[mesh.faces[l][2]].z); printf("n3: %1.5e %1.5e %1.5e\n", mesh.nodes[mesh.faces[l][3]].x, mesh.nodes[mesh.faces[l][3]].y, mesh.nodes[mesh.faces[l][3]].z); #endif if (aFindFaceStruct.loc == Face::NodeLocation_Undefined) { aFindFaceStruct.loc = loc; } // Node is in the interior of this face if (loc == Face::NodeLocation_Interior) { if (loc != aFindFaceStruct.loc) { _EXCEPTIONT("No consensus on location of Node"); } aFindFaceStruct.vecFaceIndices.push_back(l); aFindFaceStruct.vecFaceLocations.push_back(ixLocation); break; } // Node is on the edge of this face if (loc == Face::NodeLocation_Edge) { if (loc != aFindFaceStruct.loc) { _EXCEPTIONT("No consensus on location of Node"); } aFindFaceStruct.vecFaceIndices.push_back(l); aFindFaceStruct.vecFaceLocations.push_back(ixLocation); } // Node is at the corner of this face if (loc == Face::NodeLocation_Corner) { if (loc != aFindFaceStruct.loc) { _EXCEPTIONT("No consensus on location of Node"); } aFindFaceStruct.vecFaceIndices.push_back(l); aFindFaceStruct.vecFaceLocations.push_back(ixLocation); } } // Edges can only have two adjacent Faces if (aFindFaceStruct.loc == Face::NodeLocation_Edge) { if (aFindFaceStruct.vecFaceIndices.size() != 2) { printf("n: %1.5e %1.5e %1.5e\n", node.x, node.y, node.z); _EXCEPTION2("Node found on edge with %i neighboring face(s) (%i)", aFindFaceStruct.vecFaceIndices.size(), (int)(aFindFaceStruct.vecFaceIndices.size())); } } // Corners must have at least three adjacent Faces if (aFindFaceStruct.loc == Face::NodeLocation_Corner) { if (aFindFaceStruct.vecFaceIndices.size() < 3) { printf("n: %1.5e %1.5e %1.5e\n", node.x, node.y, node.z); _EXCEPTION1("Two Faced corner detected (%i)", (int)(aFindFaceStruct.vecFaceIndices.size())); } } }
bool OutputManagerReference::OpenFile( const std::string & strFileName ) { #ifdef TEMPEST_NETCDF // Determine processor rank; only proceed if root node int nRank = 0; #ifdef TEMPEST_MPIOMP MPI_Comm_rank(MPI_COMM_WORLD, &nRank); #endif // The active model const Model & model = m_grid.GetModel(); // Open NetCDF file on root process if (nRank == 0) { // Check for existing NetCDF file if (m_pActiveNcOutput != NULL) { _EXCEPTIONT("NetCDF file already open"); } // Append .nc extension to file std::string strNcFileName = strFileName + ".nc"; // Open new NetCDF file m_pActiveNcOutput = new NcFile(strNcFileName.c_str(), NcFile::Replace); if (m_pActiveNcOutput == NULL) { _EXCEPTION1("Error opening NetCDF file \"%s\"", strNcFileName.c_str()); } if (!m_pActiveNcOutput->is_valid()) { _EXCEPTION1("Error opening NetCDF file \"%s\"", strNcFileName.c_str()); } // Create nodal time dimension NcDim * dimTime = m_pActiveNcOutput->add_dim("time"); if (dimTime == NULL) { _EXCEPTIONT("Error creating \"time\" dimension"); } m_varTime = m_pActiveNcOutput->add_var("time", ncDouble, dimTime); if (m_varTime == NULL) { _EXCEPTIONT("Error creating \"time\" variable"); } std::string strUnits = "days since " + model.GetStartTime().ToDateString(); std::string strCalendarName = model.GetStartTime().GetCalendarName(); m_varTime->add_att("long_name", "time"); m_varTime->add_att("units", strUnits.c_str()); m_varTime->add_att("calendar", strCalendarName.c_str()); m_varTime->add_att("bounds", "time_bnds"); // Create levels dimension NcDim * dimLev = m_pActiveNcOutput->add_dim("lev", m_dREtaCoord.GetRows()); // Create interfaces dimension NcDim * dimILev = m_pActiveNcOutput->add_dim("ilev", m_grid.GetRElements()+1); // Create latitude dimension NcDim * dimLat = m_pActiveNcOutput->add_dim("lat", m_nYReference); // Create longitude dimension NcDim * dimLon = m_pActiveNcOutput->add_dim("lon", m_nXReference); // Output physical constants const PhysicalConstants & phys = model.GetPhysicalConstants(); m_pActiveNcOutput->add_att("earth_radius", phys.GetEarthRadius()); m_pActiveNcOutput->add_att("g", phys.GetG()); m_pActiveNcOutput->add_att("omega", phys.GetOmega()); m_pActiveNcOutput->add_att("alpha", phys.GetAlpha()); m_pActiveNcOutput->add_att("Rd", phys.GetR()); m_pActiveNcOutput->add_att("Cp", phys.GetCp()); m_pActiveNcOutput->add_att("T0", phys.GetT0()); m_pActiveNcOutput->add_att("P0", phys.GetP0()); m_pActiveNcOutput->add_att("rho_water", phys.GetRhoWater()); m_pActiveNcOutput->add_att("Rvap", phys.GetRvap()); m_pActiveNcOutput->add_att("Mvap", phys.GetMvap()); m_pActiveNcOutput->add_att("Lvap", phys.GetLvap()); // Output grid parameters m_pActiveNcOutput->add_att("Ztop", m_grid.GetZtop()); // Output equation set const EquationSet & eqn = model.GetEquationSet(); m_pActiveNcOutput->add_att("equation_set", eqn.GetName().c_str()); // Create variables for (int c = 0; c < eqn.GetComponents(); c++) { if ((m_fOutputAllVarsOnNodes) || (m_grid.GetVarLocation(c) == DataLocation_Node) ) { m_vecComponentVar.push_back( m_pActiveNcOutput->add_var( eqn.GetComponentShortName(c).c_str(), ncDouble, dimTime, dimLev, dimLat, dimLon)); } else { m_vecComponentVar.push_back( m_pActiveNcOutput->add_var( eqn.GetComponentShortName(c).c_str(), ncDouble, dimTime, dimILev, dimLat, dimLon)); } } for (int c = 0; c < eqn.GetTracers(); c++) { m_vecTracersVar.push_back( m_pActiveNcOutput->add_var( eqn.GetTracerShortName(c).c_str(), ncDouble, dimTime, dimLev, dimLat, dimLon)); } // Vorticity variable if (m_fOutputVorticity) { m_varVorticity = m_pActiveNcOutput->add_var( "ZETA", ncDouble, dimTime, dimLev, dimLat, dimLon); } // Divergence variable if (m_fOutputDivergence) { m_varDivergence = m_pActiveNcOutput->add_var( "DELTA", ncDouble, dimTime, dimLev, dimLat, dimLon); } // Temperature variable if (m_fOutputTemperature) { m_varTemperature = m_pActiveNcOutput->add_var( "T", ncDouble, dimTime, dimLev, dimLat, dimLon); } // Surface pressure variable if (m_fOutputSurfacePressure) { m_varSurfacePressure = m_pActiveNcOutput->add_var( "PS", ncDouble, dimTime, dimLat, dimLon); } // Richardson number variable if (m_fOutputRichardson) { m_varRichardson = m_pActiveNcOutput->add_var( "Ri", ncDouble, dimTime, dimLev, dimLat, dimLon); } // User data variables const UserDataMeta & metaUserData = model.GetUserDataMeta(); m_vecUserData2DVar.resize(metaUserData.GetUserData2DItemCount()); for (int i = 0; i < metaUserData.GetUserData2DItemCount(); i++) { m_vecUserData2DVar[i] = m_pActiveNcOutput->add_var( metaUserData.GetUserData2DItemName(i).c_str(), ncDouble, dimTime, dimLat, dimLon); } // Output longitudes and latitudes NcVar * varLon = m_pActiveNcOutput->add_var("lon", ncDouble, dimLon); NcVar * varLat = m_pActiveNcOutput->add_var("lat", ncDouble, dimLat); varLon->put(m_dXCoord, m_dXCoord.GetRows()); varLat->put(m_dYCoord, m_dYCoord.GetRows()); varLon->add_att("long_name", "longitude"); varLon->add_att("units", "degrees_east"); varLat->add_att("long_name", "latitude"); varLat->add_att("units", "degrees_north"); // Output levels NcVar * varLev = m_pActiveNcOutput->add_var("lev", ncDouble, dimLev); varLev->put( m_dREtaCoord, m_dREtaCoord.GetRows()); varLev->add_att("long_name", "level"); varLev->add_att("units", "level"); // Output interface levels NcVar * varILev = m_pActiveNcOutput->add_var("ilev", ncDouble, dimILev); varILev->put( m_grid.GetREtaStretchInterfaces(), m_grid.GetREtaStretchInterfaces().GetRows()); varILev->add_att("long_name", "interface level"); varILev->add_att("units", "level"); // Topography variable m_varTopography = m_pActiveNcOutput->add_var("Zs", ncDouble, dimLat, dimLon); // Fresh output file m_fFreshOutputFile = true; } #ifdef TEMPEST_MPIOMP // Wait for all processes to complete MPI_Barrier(MPI_COMM_WORLD); #endif #endif return true; }
int main(int argc, char** argv) { NcError error(NcError::verbose_nonfatal); try { // Input file std::string strInputFile; // Input file list std::string strInputFileList; // Input file format std::string strInputFormat; // NetCDF file containing latitude and longitude arrays std::string strLatLonFile; // Output file (NetCDF) std::string strOutputFile; // Output variable name std::string strOutputVariable; // Column in which the longitude index appears int iLonIxCol; // Column in which the latitude index appears int iLatIxCol; // Begin latitude double dLatBegin; // End latitude double dLatEnd; // Begin longitude double dLonBegin; // End longitude double dLonEnd; // Number of latitudes in output int nLat; // Number of longitudes in output int nLon; // Parse the command line BeginCommandLine() CommandLineString(strInputFile, "in", ""); CommandLineString(strInputFileList, "inlist", ""); CommandLineStringD(strInputFormat, "in_format", "std", "(std|visit)"); CommandLineString(strOutputFile, "out", ""); CommandLineString(strOutputVariable, "outvar", "density"); CommandLineInt(iLonIxCol, "iloncol", 8); CommandLineInt(iLatIxCol, "ilatcol", 9); CommandLineDouble(dLatBegin, "lat_begin", -90.0); CommandLineDouble(dLatEnd, "lat_end", 90.0); CommandLineDouble(dLonBegin, "lon_begin", 0.0); CommandLineDouble(dLonEnd, "lon_end", 360.0); CommandLineInt(nLat, "nlat", 180); CommandLineInt(nLon, "nlon", 360); ParseCommandLine(argc, argv); EndCommandLine(argv) AnnounceBanner(); // Check input if ((strInputFile == "") && (strInputFileList == "")) { _EXCEPTIONT("No input file (--in) or (--inlist) specified"); } if ((strInputFile != "") && (strInputFileList != "")) { _EXCEPTIONT("Only one input file (--in) or (--inlist) allowed"); } if (strInputFormat != "std") { _EXCEPTIONT("UNIMPLEMENTED: Only \"--in_format std\" supported"); } // Check output if (strOutputFile == "") { _EXCEPTIONT("No output file (--out) specified"); } // Check output variable if (strOutputVariable == "") { _EXCEPTIONT("No output variable name (--outvar) specified"); } // Number of latitudes and longitudes if (nLat == 0) { _EXCEPTIONT("UNIMPLEMENTED: --nlat must be specified currently"); } if (nLon == 0) { _EXCEPTIONT("UNIMPLEMENTED: --nlon must be specified currently"); } // Input file list std::vector<std::string> vecInputFiles; if (strInputFile != "") { vecInputFiles.push_back(strInputFile); } if (strInputFileList != "") { GetInputFileList(strInputFileList, vecInputFiles); } int nFiles = vecInputFiles.size(); // Density DataMatrix<int> nCounts; nCounts.Initialize(nLat, nLon); // Loop through all files in list AnnounceStartBlock("Processing files"); std::string strBuffer; strBuffer.reserve(1024); for (int f = 0; f < nFiles; f++) { Announce("File \"%s\"", vecInputFiles[f].c_str()); FILE * fp = fopen(vecInputFiles[f].c_str(), "r"); if (fp == NULL) { _EXCEPTION1("Unable to open input file \"%s\"", vecInputFiles[f].c_str()); } for (;;) { // Read in the next line fgets(&(strBuffer[0]), 1024, fp); int nLength = strlen(&(strBuffer[0])); // Check for end of file if (feof(fp)) { break; } // Check for comment line if (strBuffer[0] == '#') { continue; } // Check for new storm if (strncmp(&(strBuffer[0]), "start", 5) == 0) { continue; } // Parse line double dLon; double dLat; int iCol = 0; int iLast = 0; bool fWhitespace = true; for (int i = 0; i <= nLength; i++) { if ((strBuffer[i] == ' ') || (strBuffer[i] == ',') || (strBuffer[i] == '\t') || (strBuffer[i] == '\0') ) { if (!fWhitespace) { if (iCol == iLonIxCol) { strBuffer[i] = '\0'; dLon = atof(&(strBuffer[iLast])); } if (iCol == iLatIxCol) { strBuffer[i] = '\0'; dLat = atof(&(strBuffer[iLast])); } } fWhitespace = true; } else { if (fWhitespace) { iLast = i; iCol++; } fWhitespace = false; } } // Latitude and longitude index int iLon = static_cast<int>(static_cast<double>(nLon) * (dLon - dLonBegin) / (dLonEnd - dLonBegin)); int iLat = static_cast<int>(static_cast<double>(nLat) * (dLat - dLatBegin) / (dLatEnd - dLatBegin)); if (iLon == (-1)) { iLon = 0; } if (iLon == nLon) { iLon = nLon - 1; } if (iLat == (-1)) { iLat = 0; } if (iLat == nLat) { iLat = nLat - 1; } if ((iLat < 0) || (iLat >= nLat)) { _EXCEPTION1("Latitude index (%i) out of range", iLat); } if ((iLon < 0) || (iLon >= nLon)) { _EXCEPTION1("Longitude index (%i) out of range", iLon); } nCounts[iLat][iLon]++; } fclose(fp); } AnnounceEndBlock("Done"); // Output results AnnounceStartBlock("Output results"); // Load the netcdf output file NcFile ncOutput(strOutputFile.c_str(), NcFile::Replace); if (!ncOutput.is_valid()) { _EXCEPTION1("Unable to open output file \"%s\"", strOutputFile.c_str()); } // Create output NcDim * dimLat = ncOutput.add_dim("lat", nLat); NcDim * dimLon = ncOutput.add_dim("lon", nLon); NcVar * varLat = ncOutput.add_var("lat", ncDouble, dimLat); NcVar * varLon = ncOutput.add_var("lon", ncDouble, dimLon); varLat->add_att("units", "degrees_north"); varLon->add_att("units", "degrees_east"); DataVector<double> dLat(nLat); DataVector<double> dLon(nLon); for (int j = 0; j < nLat; j++) { dLat[j] = dLatBegin + (dLatEnd - dLatBegin) * (static_cast<double>(j) + 0.5) / static_cast<double>(nLat); } for (int i = 0; i < nLon; i++) { dLon[i] = dLonBegin + (dLonEnd - dLonBegin) * (static_cast<double>(i) + 0.5) / static_cast<double>(nLon); } varLat->put(&(dLat[0]), nLat); varLon->put(&(dLon[0]), nLon); // Output counts NcVar * varCount = ncOutput.add_var( strOutputVariable.c_str(), ncInt, dimLat, dimLon); varCount->put(&(nCounts[0][0]), nLat, nLon); ncOutput.close(); AnnounceEndBlock("Done"); AnnounceBanner(); } catch(Exception & e) { Announce(e.ToString().c_str()); } }
void CopyNcVar( NcFile & ncIn, NcFile & ncOut, const std::string & strVarName, bool fCopyAttributes, bool fCopyData ) { if (!ncIn.is_valid()) { _EXCEPTIONT("Invalid input file specified"); } if (!ncOut.is_valid()) { _EXCEPTIONT("Invalid output file specified"); } NcVar * var = ncIn.get_var(strVarName.c_str()); if (var == NULL) { _EXCEPTION1("NetCDF file does not contain variable \"%s\"", strVarName.c_str()); } NcVar * varOut; std::vector<NcDim *> dimOut; dimOut.resize(var->num_dims()); std::vector<long> counts; counts.resize(var->num_dims()); long nDataSize = 1; for (int d = 0; d < var->num_dims(); d++) { NcDim * dimA = var->get_dim(d); dimOut[d] = ncOut.get_dim(dimA->name()); if (dimOut[d] == NULL) { if (dimA->is_unlimited()) { dimOut[d] = ncOut.add_dim(dimA->name()); } else { dimOut[d] = ncOut.add_dim(dimA->name(), dimA->size()); } if (dimOut[d] == NULL) { _EXCEPTION2("Failed to add dimension \"%s\" (%i) to file", dimA->name(), dimA->size()); } } if (dimOut[d]->size() != dimA->size()) { if (dimA->is_unlimited() && !dimOut[d]->is_unlimited()) { _EXCEPTION2("Mismatch between input file dimension \"%s\" and " "output file dimension (UNLIMITED / %i)", dimA->name(), dimOut[d]->size()); } else if (!dimA->is_unlimited() && dimOut[d]->is_unlimited()) { _EXCEPTION2("Mismatch between input file dimension \"%s\" and " "output file dimension (%i / UNLIMITED)", dimA->name(), dimA->size()); } else if (!dimA->is_unlimited() && !dimOut[d]->is_unlimited()) { _EXCEPTION3("Mismatch between input file dimension \"%s\" and " "output file dimension (%i / %i)", dimA->name(), dimA->size(), dimOut[d]->size()); } } counts[d] = dimA->size(); nDataSize *= counts[d]; } // ncByte / ncChar type if ((var->type() == ncByte) || (var->type() == ncChar)) { DataVector<char> data; data.Initialize(nDataSize); varOut = ncOut.add_var( var->name(), var->type(), dimOut.size(), (const NcDim**)&(dimOut[0])); if (varOut == NULL) { _EXCEPTION1("Cannot create variable \"%s\"", var->name()); } var->get(&(data[0]), &(counts[0])); varOut->put(&(data[0]), &(counts[0])); } // ncShort type if (var->type() == ncShort) { DataVector<short> data; data.Initialize(nDataSize); varOut = ncOut.add_var( var->name(), var->type(), dimOut.size(), (const NcDim**)&(dimOut[0])); if (varOut == NULL) { _EXCEPTION1("Cannot create variable \"%s\"", var->name()); } if (fCopyData) { var->get(&(data[0]), &(counts[0])); varOut->put(&(data[0]), &(counts[0])); } } // ncInt type if (var->type() == ncInt) { DataVector<int> data; data.Initialize(nDataSize); varOut = ncOut.add_var( var->name(), var->type(), dimOut.size(), (const NcDim**)&(dimOut[0])); if (varOut == NULL) { _EXCEPTION1("Cannot create variable \"%s\"", var->name()); } if (fCopyData) { var->get(&(data[0]), &(counts[0])); varOut->put(&(data[0]), &(counts[0])); } } // ncFloat type if (var->type() == ncFloat) { DataVector<float> data; data.Initialize(nDataSize); varOut = ncOut.add_var( var->name(), var->type(), dimOut.size(), (const NcDim**)&(dimOut[0])); if (varOut == NULL) { _EXCEPTION1("Cannot create variable \"%s\"", var->name()); } if (fCopyData) { var->get(&(data[0]), &(counts[0])); varOut->put(&(data[0]), &(counts[0])); } } // ncDouble type if (var->type() == ncDouble) { DataVector<double> data; data.Initialize(nDataSize); varOut = ncOut.add_var( var->name(), var->type(), dimOut.size(), (const NcDim**)&(dimOut[0])); if (varOut == NULL) { _EXCEPTION1("Cannot create variable \"%s\"", var->name()); } if (fCopyData) { var->get(&(data[0]), &(counts[0])); varOut->put(&(data[0]), &(counts[0])); } } // ncInt64 type if (var->type() == ncInt64) { DataVector<ncint64> data; data.Initialize(nDataSize); varOut = ncOut.add_var( var->name(), var->type(), dimOut.size(), (const NcDim**)&(dimOut[0])); if (varOut == NULL) { _EXCEPTION1("Cannot create variable \"%s\"", var->name()); } if (fCopyData) { var->get(&(data[0]), &(counts[0])); varOut->put(&(data[0]), &(counts[0])); } } // Check output variable exists if (varOut == NULL) { _EXCEPTION1("Unable to create output variable \"%s\"", var->name()); } // Copy attributes if (fCopyAttributes) { CopyNcVarAttributes(var, varOut); } }
void LegendrePolynomial::AllDerivativeRoots( int nDegree, double * dRoots ) { // Iteration tolerance const double IterationTolerance = 1.0e-14; // Check for degree 0 or 1 if ((nDegree == 0) || (nDegree == 1)) { return; } // Check for negative degree if (nDegree < 0) { _EXCEPTION1("Invalid degree (%i)", nDegree); } // Check for NULL dRoots pointer if (dRoots == NULL) { _EXCEPTIONT("NULL pointer passed into AllRoots argument dRoots"); } // Double degree double dDegree = static_cast<double>(nDegree); // Additional storage for roots double * dBuffer = new double[nDegree-1]; // Set initial estimate for (int k = 0; k < nDegree-1; k++) { dRoots[k] = (static_cast<double>(k) + 0.5) * 2.0 / (dDegree - 1.0) - 1.0; } // Refine estimate using Aberth-Ehrlich method for (int iter = 0; iter < nDegree + 10; iter++) { /* for (int k = 0; k < nDegree - 1; k++) { printf("%i %i: %1.15e\n", iter, k, dRoots[k]); } */ int nFoundRoots = 0; for (int k = 0; k < nDegree - 1; k++) { double dValue; double dDerivative; EvaluateValueAndDerivative(nDegree, dRoots[k], dValue, dDerivative); if (fabs(dDerivative) < IterationTolerance) { nFoundRoots++; dBuffer[k] = dRoots[k]; continue; } double dMod = 0.0; for (int l = 0; l < nDegree - 1; l++) { if (l == k) { continue; } dMod += 1.0 / (dRoots[k] - dRoots[l]); } // Second derivative obtained from double dSecondDerivative = 1.0 / (1.0 - dRoots[k] * dRoots[k]) * (2.0 * dRoots[k] * dDerivative - dDegree * (dDegree + 1.0) * dValue); dBuffer[k] = dRoots[k] - 1.0 / (dSecondDerivative / dDerivative - dMod); } // Copy buffer to roots memcpy(dRoots, dBuffer, (nDegree - 1) * sizeof(double)); // Check if all roots have been found if (nFoundRoots == nDegree - 1) { break; } } // Sort roots std::sort(dRoots, dRoots + nDegree - 1); // Delete buffer delete[] dBuffer; }
int main(int argc, char ** argv){ NcError error(NcError::verbose_nonfatal); try{ std::string inFile; std::string outFile; std::string varName; std::string inList; // bool calcStdDev; BeginCommandLine() CommandLineString(inFile, "in", ""); CommandLineString(inList, "inlist",""); CommandLineString(varName, "var", ""); CommandLineString(outFile, "out", ""); // CommandLineBool(calcStdDev, "std"); ParseCommandLine(argc, argv); EndCommandLine(argv) AnnounceBanner(); if ((inFile != "") && (inList != "")){ _EXCEPTIONT("Can only open one file (--in) or list (--inlist)."); } //file list vector std::vector<std::string> vecFiles; if (inFile != ""){ vecFiles.push_back(inFile); } if (inList != ""){ GetInputFileList(inList,vecFiles); } //open up first file NcFile readin(vecFiles[0].c_str()); if (!readin.is_valid()){ _EXCEPTION1("Unable to open file %s for reading",\ vecFiles[0].c_str()); } int tLen,latLen,lonLen; NcDim * time = readin.get_dim("time"); tLen = time->size(); NcVar * timeVar = readin.get_var("time"); NcDim * lat = readin.get_dim("lat"); latLen = lat->size(); NcVar * latVar = readin.get_var("lat"); NcDim * lon = readin.get_dim("lon"); lonLen = lon->size(); NcVar * lonVar = readin.get_var("lon"); //read input variable NcVar * inVar = readin.get_var(varName.c_str()); //Create output matrix DataMatrix<double> outMat(latLen,lonLen); densCalc(inVar,outMat); //Option for calculating the yearly standard deviation /* if (calcStdDev){ for (int a=0; a<latLen; a++){ for (int b=0; b<lonLen; b++){ storeMat[0][a][b] = outMat[a][b]; } } } */ //If multiple files, add these values to the output if (vecFiles.size()>1){ DataMatrix<double> addMat(latLen,lonLen); std::cout<<"There are "<<vecFiles.size()<<" files."<<std::endl; for (int v=1; v<vecFiles.size(); v++){ NcFile addread(vecFiles[v].c_str()); NcVar * inVar = addread.get_var(varName.c_str()); densCalc(inVar,addMat); for (int a=0; a<latLen; a++){ for (int b=0; b<lonLen; b++){ outMat[a][b]+=addMat[a][b]; } } /* if (calcStdDev){ for (int a=0; a<latLen; a++){ for (int b=0; b<lonLen; b++){ storeMat[v][a][b] = addMat[a][b]; } } }*/ addread.close(); } //Divide output by number of files double div = 1./((double) vecFiles.size()); for (int a=0; a<latLen; a++){ for (int b=0; b<lonLen; b++){ outMat[a][b]*=div; } } } NcFile readout(outFile.c_str(),NcFile::Replace, NULL,0,NcFile::Offset64Bits); NcDim * outLat = readout.add_dim("lat", latLen); NcDim * outLon = readout.add_dim("lon", lonLen); NcVar * outLatVar = readout.add_var("lat",ncDouble,outLat); NcVar * outLonVar = readout.add_var("lon",ncDouble,outLon); std::cout<<"Copying dimension attributes."<<std::endl; copy_dim_var(latVar,outLatVar); copy_dim_var(lonVar,outLonVar); std::cout<<"Creating density variable."<<std::endl; NcVar * densVar = readout.add_var("dens",ncDouble,outLat,outLon); densVar->set_cur(0,0); densVar->put((&outMat[0][0]),latLen,lonLen); /* if (calcStdDev){ NcVar * stdDevVar = readout.add_var("stddev", ncDouble,outLat,outLon); DataMatrix<double> stdDevMat(latLen,lonLen); yearlyStdDev(storeMat,vecFiles.size(),latLen,lonLen,stdDevMat); stdDevVar->set_cur(0,0); stdDevVar->put(&(stdDevMat[0][0]),latLen,lonLen); std::cout<<" created sd variable"<<std::endl; } */ readout.close(); readin.close(); } catch (Exception &e){ std::cout<<e.ToString()<<std::endl; } }
void GridPatchCSGLL::EvaluateGeometricTerms() { // Physical constants const PhysicalConstants & phys = m_grid.GetModel().GetPhysicalConstants(); // 2D equation set bool fIs2DEquationSet = false; if (m_grid.GetModel().GetEquationSet().GetDimensionality() == 2) { fIs2DEquationSet = true; } if ((fIs2DEquationSet) && (m_grid.GetZtop() != 1.0)) { _EXCEPTIONT("Ztop must be 1.0 for 2D equation sets"); } // Obtain Gauss Lobatto quadrature nodes and weights DataArray1D<double> dGL; DataArray1D<double> dWL; GaussLobattoQuadrature::GetPoints(m_nHorizontalOrder, 0.0, 1.0, dGL, dWL); // Obtain normalized areas in the vertical const DataArray1D<double> & dWNode = m_grid.GetREtaLevelsNormArea(); const DataArray1D<double> & dWREdge = m_grid.GetREtaInterfacesNormArea(); // Verify that normalized areas are correct double dWNodeSum = 0.0; for (int k = 0; k < dWNode.GetRows(); k++) { dWNodeSum += dWNode[k]; } if (fabs(dWNodeSum - 1.0) > 1.0e-13) { _EXCEPTION1("Error in normalized areas (%1.15e)", dWNodeSum); } if (m_grid.GetVerticalStaggering() != Grid::VerticalStaggering_Interfaces ) { double dWREdgeSum = 0.0; for (int k = 0; k < dWREdge.GetRows(); k++) { dWREdgeSum += dWREdge[k]; } if (fabs(dWREdgeSum - 1.0) > 1.0e-13) { _EXCEPTION1("Error in normalized areas (%1.15e)", dWREdgeSum); } } // Derivatives of basis functions GridCSGLL & gridCSGLL = dynamic_cast<GridCSGLL &>(m_grid); const DataArray2D<double> & dDxBasis1D = gridCSGLL.GetDxBasis1D(); // Initialize the Coriolis force at each node for (int i = 0; i < m_box.GetATotalWidth(); i++) { for (int j = 0; j < m_box.GetBTotalWidth(); j++) { m_dataCoriolisF[i][j] = 2.0 * phys.GetOmega() * sin(m_dataLat[i][j]); } } // Initialize metric in terrain-following coords for (int a = 0; a < GetElementCountA(); a++) { for (int b = 0; b < GetElementCountB(); b++) { for (int i = 0; i < m_nHorizontalOrder; i++) { for (int j = 0; j < m_nHorizontalOrder; j++) { // Nodal points int iElementA = m_box.GetAInteriorBegin() + a * m_nHorizontalOrder; int iElementB = m_box.GetBInteriorBegin() + b * m_nHorizontalOrder; int iA = iElementA + i; int iB = iElementB + j; // Gnomonic coordinates double dX = tan(m_dANode[iA]); double dY = tan(m_dBNode[iB]); double dDelta2 = (1.0 + dX * dX + dY * dY); double dDelta = sqrt(dDelta2); // Topography height and its derivatives double dZs = m_dataTopography[iA][iB]; double dDaZs = m_dataTopographyDeriv[0][iA][iB]; double dDbZs = m_dataTopographyDeriv[1][iA][iB]; // 2D equations if (fIs2DEquationSet) { dZs = 0.0; dDaZs = 0.0; dDbZs = 0.0; } // Initialize 2D Jacobian m_dataJacobian2D[iA][iB] = (1.0 + dX * dX) * (1.0 + dY * dY) / (dDelta * dDelta * dDelta); m_dataJacobian2D[iA][iB] *= phys.GetEarthRadius() * phys.GetEarthRadius(); // Initialize 2D contravariant metric double dContraMetricScale = dDelta2 / (1.0 + dX * dX) / (1.0 + dY * dY) / (phys.GetEarthRadius() * phys.GetEarthRadius()); m_dataContraMetric2DA[iA][iB][0] = dContraMetricScale * (1.0 + dY * dY); m_dataContraMetric2DA[iA][iB][1] = dContraMetricScale * dX * dY; m_dataContraMetric2DB[iA][iB][0] = dContraMetricScale * dX * dY; m_dataContraMetric2DB[iA][iB][1] = dContraMetricScale * (1.0 + dX * dX); // Initialize 2D covariant metric double dCovMetricScale = phys.GetEarthRadius() * phys.GetEarthRadius() * (1.0 + dX * dX) * (1.0 + dY * dY) / (dDelta2 * dDelta2); m_dataCovMetric2DA[iA][iB][0] = dCovMetricScale * (1.0 + dX * dX); m_dataCovMetric2DA[iA][iB][1] = dCovMetricScale * (- dX * dY); m_dataCovMetric2DB[iA][iB][0] = dCovMetricScale * (- dX * dY); m_dataCovMetric2DB[iA][iB][1] = dCovMetricScale * (1.0 + dY * dY); // Vertical coordinate transform and its derivatives for (int k = 0; k < m_grid.GetRElements(); k++) { // Gal-Chen and Somerville (1975) linear terrain-following coord double dREta = m_grid.GetREtaLevel(k); /* double dREtaStretch; double dDxREtaStretch; m_grid.EvaluateVerticalStretchF( dREta, dREtaStretch, dDxREtaStretch); double dZ = dZs + (m_grid.GetZtop() - dZs) * dREtaStretch; double dDaR = (1.0 - dREtaStretch) * dDaZs; double dDbR = (1.0 - dREtaStretch) * dDbZs; double dDxR = (m_grid.GetZtop() - dZs) * dDxREtaStretch; */ double dZ = dZs + (m_grid.GetZtop() - dZs) * dREta; double dDaR = (1.0 - dREta) * dDaZs; double dDbR = (1.0 - dREta) * dDbZs; double dDxR = (m_grid.GetZtop() - dZs); // Calculate pointwise Jacobian m_dataJacobian[k][iA][iB] = dDxR * m_dataJacobian2D[iA][iB]; // Element area associated with each model level GLL node m_dataElementAreaNode[k][iA][iB] = m_dataJacobian[k][iA][iB] * dWL[i] * GetElementDeltaA() * dWL[j] * GetElementDeltaB() * dWNode[k]; // Contravariant metric components m_dataContraMetricA[k][iA][iB][0] = m_dataContraMetric2DA[iA][iB][0]; m_dataContraMetricA[k][iA][iB][1] = m_dataContraMetric2DA[iA][iB][1]; m_dataContraMetricA[k][iA][iB][2] = - dContraMetricScale / dDxR * ( (1.0 + dY * dY) * dDaR + dX * dY * dDbR); m_dataContraMetricB[k][iA][iB][0] = m_dataContraMetric2DB[iA][iB][0]; m_dataContraMetricB[k][iA][iB][1] = m_dataContraMetric2DB[iA][iB][1]; m_dataContraMetricB[k][iA][iB][2] = - dContraMetricScale / dDxR * ( dX * dY * dDaR + (1.0 + dX * dX) * dDbR); m_dataContraMetricXi[k][iA][iB][0] = m_dataContraMetricA[k][iA][iB][2]; m_dataContraMetricXi[k][iA][iB][1] = m_dataContraMetricB[k][iA][iB][2]; m_dataContraMetricXi[k][iA][iB][2] = 1.0 / (dDxR * dDxR) - 1.0 / dDxR * ( m_dataContraMetricXi[k][iA][iB][0] * dDaR + m_dataContraMetricXi[k][iA][iB][1] * dDbR); // Derivatives of the vertical coordinate transform m_dataDerivRNode[k][iA][iB][0] = dDaR; m_dataDerivRNode[k][iA][iB][1] = dDbR; m_dataDerivRNode[k][iA][iB][2] = dDxR; } // Metric terms at vertical interfaces for (int k = 0; k <= m_grid.GetRElements(); k++) { // Gal-Chen and Somerville (1975) linear terrain-following coord double dREta = m_grid.GetREtaInterface(k); /* double dREtaStretch; double dDxREtaStretch; m_grid.EvaluateVerticalStretchF( dREta, dREtaStretch, dDxREtaStretch); double dZ = dZs + (m_grid.GetZtop() - dZs) * dREtaStretch; double dDaR = (1.0 - dREtaStretch) * dDaZs; double dDbR = (1.0 - dREtaStretch) * dDbZs; double dDxR = (m_grid.GetZtop() - dZs) * dDxREtaStretch; */ double dZ = dZs + (m_grid.GetZtop() - dZs) * dREta; double dDaR = (1.0 - dREta) * dDaZs; double dDbR = (1.0 - dREta) * dDbZs; double dDxR = (m_grid.GetZtop() - dZs); // Calculate pointwise Jacobian m_dataJacobianREdge[k][iA][iB] = (1.0 + dX * dX) * (1.0 + dY * dY) / (dDelta * dDelta * dDelta); m_dataJacobianREdge[k][iA][iB] *= dDxR * phys.GetEarthRadius() * phys.GetEarthRadius(); // Element area associated with each model interface GLL node m_dataElementAreaREdge[k][iA][iB] = m_dataJacobianREdge[k][iA][iB] * dWL[i] * GetElementDeltaA() * dWL[j] * GetElementDeltaB() * dWREdge[k]; // Contravariant metric (alpha) m_dataContraMetricAREdge[k][iA][iB][0] = m_dataContraMetric2DA[iA][iB][0]; m_dataContraMetricAREdge[k][iA][iB][1] = m_dataContraMetric2DA[iA][iB][1]; m_dataContraMetricAREdge[k][iA][iB][2] = - dContraMetricScale / dDxR * ( (1.0 + dY * dY) * dDaR + dX * dY * dDbR); // Contravariant metric (beta) m_dataContraMetricBREdge[k][iA][iB][0] = m_dataContraMetric2DB[iA][iB][0]; m_dataContraMetricBREdge[k][iA][iB][1] = m_dataContraMetric2DB[iA][iB][1]; m_dataContraMetricBREdge[k][iA][iB][2] = - dContraMetricScale / dDxR * ( dX * dY * dDaR + (1.0 + dX * dX) * dDbR); // Contravariant metric (xi) m_dataContraMetricXiREdge[k][iA][iB][0] = - dContraMetricScale / dDxR * ( (1.0 + dY * dY) * dDaR + dX * dY * dDbR); m_dataContraMetricXiREdge[k][iA][iB][1] = - dContraMetricScale / dDxR * ( dX * dY * dDaR + (1.0 + dX * dX) * dDbR); m_dataContraMetricXiREdge[k][iA][iB][2] = 1.0 / (dDxR * dDxR) - 1.0 / dDxR * ( m_dataContraMetricXiREdge[k][iA][iB][0] * dDaR + m_dataContraMetricXiREdge[k][iA][iB][1] * dDbR); // Derivatives of the vertical coordinate transform m_dataDerivRREdge[k][iA][iB][0] = dDaR; m_dataDerivRREdge[k][iA][iB][1] = dDbR; m_dataDerivRREdge[k][iA][iB][2] = dDxR; } } } } } }