void GenerateEvolutionMatrix( int nK, const Parameters & param, DataMatrix<double> & matM, DataMatrix<double> & matB ) { int nMatrixSize = 5 * param.nPhiElements - 1; matM.Initialize(nMatrixSize, nMatrixSize); matB.Initialize(nMatrixSize, nMatrixSize); // Radius of the Earth const double ParamEarthRadius = 6.37122e6; // Ideal gas constant const double ParamRd = 287.0; // Inverse Rossby number double dInvRo = 2.0 * ParamEarthRadius * param.dOmega * param.dXscale / param.dU0; // Scale height double dH = ParamRd * param.dT0 / param.dG; // Froude number double dFr = param.dU0 / sqrt(param.dG * dH); // Squared Froude number double dFr2 = dFr * dFr; // Aspect ratio double dAs = dH / (ParamEarthRadius / param.dXscale); // Velocity ratio double dAv = dAs; // Wave number double dK2 = static_cast<double>(nK * nK); // Gamma double dInvGamma = 1.0 / param.dGamma; // Grid spacing double dDeltaPhi = param.vecNode[1] - param.vecNode[0]; // Loop through all elements for (int j = 0; j < param.nPhiElements; j++) { // Index of the start of this block int ix = 4 * j; int ixU = ix; int ixP = ix + 1; int ixW = ix + 2; int ixR = ix + 3; int ixVL = 4 * param.nPhiElements + j - 1; int ixVR = 4 * param.nPhiElements + j; // Phi at this node double dPhi = param.vecNode[j]; // Cosine Phi double dCosPhi = cos(dPhi); // Sin Phi double dSinPhi = sin(dPhi); // Tan Phi double dTanPhi = tan(dPhi); // U evolution equations matM[ixU][ixU] = dFr2 * dCosPhi * dCosPhi; matM[ixP][ixU] = 1.0; if (j != 0) { matM[ixVL][ixU] = - 0.5 * dFr2 * (2.0 + dInvRo) * dSinPhi * dCosPhi; } if (j != param.nPhiElements - 1) { matM[ixVR][ixU] = - 0.5 * dFr2 * (2.0 + dInvRo) * dSinPhi * dCosPhi; } // V evolution equations if (j != 0) { int ixV = ixVL; int ixUL = ix - 4; int ixPL = ix - 3; int ixRL = ix - 1; int ixUR = ix; int ixPR = ix + 1; int ixRR = ix + 3; double dPhiS = param.vecEdge[j]; double dSinPhiS = sin(dPhiS); double dCosPhiS = cos(dPhiS); matM[ixUL][ixV] = 0.5 * dFr2 * (2.0 + dInvRo) * dSinPhiS * dCosPhiS; matM[ixUR][ixV] = 0.5 * dFr2 * (2.0 + dInvRo) * dSinPhiS * dCosPhiS; matM[ixV][ixV] = - dK2 * dFr2; matM[ixPL][ixV] = - 0.5 * dFr2 * (1.0 + dInvRo) * dSinPhiS * dCosPhiS - 1.0 / dDeltaPhi; matM[ixPR][ixV] = - 0.5 * dFr2 * (1.0 + dInvRo) * dSinPhiS * dCosPhiS + 1.0 / dDeltaPhi; matM[ixRL][ixV] = 0.5 * dFr2 * (1.0 + dInvRo) * dSinPhiS * dCosPhiS; matM[ixRR][ixV] = 0.5 * dFr2 * (1.0 + dInvRo) * dSinPhiS * dCosPhiS; } // P evolution equations matM[ixU][ixP] = 1.0; matM[ixR][ixP] = 1.0; if (j != 0) { matM[ixVL][ixP] = - 0.5 * dFr2 * (1.0 + dInvRo) * dSinPhi * dCosPhi - 0.5 * dTanPhi - 1.0 / dDeltaPhi; } if (j != param.nPhiElements - 1) { matM[ixVR][ixP] = - 0.5 * dFr2 * (1.0 + dInvRo) * dSinPhi * dCosPhi - 0.5 * dTanPhi + 1.0 / dDeltaPhi; } // W evolution equation matM[ixW][ixW] = - dK2 * dAs * dAv * dFr2; matM[ixR][ixW] = 1.0; // R evolution equation matM[ixP][ixR] = dInvGamma / (1.0 - dInvGamma); matM[ixW][ixR] = dAv / dAs; matM[ixR][ixR] = - 1.0 / (1.0 - dInvGamma); if (j != 0) { matM[ixVL][ixR] = 0.5 * dFr2 * (1.0 + dInvRo) * dSinPhi * dCosPhi; } if (j != param.nPhiElements - 1) { matM[ixVR][ixR] = 0.5 * dFr2 * (1.0 + dInvRo) * dSinPhi * dCosPhi; } // B matrix coefficients matB[ixP][ixW] = -1.0; matB[ixW][ixP] = -1.0; } }
int main(int argc, char ** argv) { MPI_Init(&argc, &argv); try { // Number of latitudes int nLat; // Number of longitudes int nLon; // Zonal wavenumber int nK; // Meridional power int nLpow; // Output file std::string strOutputFile; // Parse the command line BeginCommandLine() CommandLineInt(nLat, "lat", 40); CommandLineInt(nLon, "lon", 80); CommandLineString(strOutputFile, "out", "topo.nc"); ParseCommandLine(argc, argv); EndCommandLine(argv) // Generate longitude and latitude arrays AnnounceBanner(); AnnounceStartBlock("Generating longitude and latitude arrays"); DataVector<double> dLon; dLon.Initialize(nLon); Parameters param; param.GenerateLatituteArray(nLat); std::vector<double> & dLat = param.vecNode; double dDeltaLon = 2.0 * M_PI / static_cast<double>(nLon); for (int i = 0; i < nLon; i++) { dLon[i] = (static_cast<double>(i) + 0.5) * dDeltaLon; } AnnounceEndBlock("Done"); // Open NetCDF output file AnnounceStartBlock("Writing to file"); NcFile ncdf_out(strOutputFile.c_str(), NcFile::Replace); // Output coordinates NcDim * dimLat = ncdf_out.add_dim("lat", nLat); NcDim * dimLon = ncdf_out.add_dim("lon", nLon); NcVar * varLat = ncdf_out.add_var("lat", ncDouble, dimLat); varLat->set_cur((long)0); varLat->put(&(param.vecNode[0]), nLat); NcVar * varLon = ncdf_out.add_var("lon", ncDouble, dimLon); varLon->set_cur((long)0); varLon->put(&(dLon[0]), nLon); // Generate topography DataMatrix<double> dTopo; dTopo.Initialize(nLat, nLon); double dK = static_cast<double>(nK); double dLpow = static_cast<double>(nLpow); double dA = 6.37122e6; double dX = 500.0; double dLatM = 0.0; double dLonM = M_PI / 4.0; double dD = 5000.0; double dH0 = 1.0; double dXiM = 4000.0; for (int j = 0; j < nLat; j++) { for (int i = 0; i < nLon; i++) { // Great circle distance double dR = dA / dX * acos(sin(dLatM) * sin(dLat[j]) + cos(dLatM) * cos(dLat[j]) * cos(dLon[i] - dLonM)); double dCosXi = 1.0; //cos(M_PI * dR / dXiM); dTopo[j][i] = dH0 * exp(- dR * dR / (dD * dD)) * dCosXi * dCosXi; } } // Write topography NcVar * varZs = ncdf_out.add_var("Zs", ncDouble, dimLat, dimLon); varZs->set_cur(0, 0); varZs->put(&(dTopo[0][0]), nLat, nLon); AnnounceEndBlock("Done"); Announce("Completed successfully!"); AnnounceBanner(); } catch(Exception & e) { Announce(e.ToString().c_str()); } MPI_Finalize(); }
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()); } }