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) { try { // Parameters Parameters param; // Output filename std::string strOutputFile; // Horizontal minimum wave number int nKmin; // Horizontal maximum wave number int nKmax; // Parse the command line BeginCommandLine() CommandLineInt(param.nPhiElements, "n", 40); CommandLineInt(nKmin, "kmin", 1); CommandLineInt(nKmax, "kmax", 20); CommandLineDouble(param.dXscale, "X", 1.0); CommandLineDouble(param.dT0, "T0", 300.0); CommandLineDouble(param.dU0, "U0", 20.0); CommandLineDouble(param.dG, "G", 9.80616); CommandLineDouble(param.dOmega, "omega", 7.29212e-5); CommandLineDouble(param.dGamma, "gamma", 1.4); CommandLineString(strOutputFile, "out", "wave.nc"); ParseCommandLine(argc, argv); EndCommandLine(argv) AnnounceBanner(); // Generate latitude values param.GenerateLatituteArray(param.nPhiElements); // Open NetCDF file NcFile ncdf_out(strOutputFile.c_str(), NcFile::Replace); NcDim *dimK = ncdf_out.add_dim("k", nKmax - nKmin + 1); NcDim *dimLat = ncdf_out.add_dim("lat", param.nPhiElements); NcDim *dimEig = ncdf_out.add_dim("eig", param.nPhiElements); // Write parameters and latitudes to file param.WriteToNcFile(ncdf_out, dimLat, dimLatS); // Wave numbers NcVar *varK = ncdf_out.add_var("k", ncInt, dimK); DataVector<int> vecK; vecK.Initialize(nKmax - nKmin + 1); for (int nK = nKmin; nK <= nKmax; nK++) { vecK[nK - nKmin] = nK; } varK->set_cur((long)0); varK->put(vecK, nKmax - nKmin + 1); // Eigenvalues NcVar *varMR = ncdf_out.add_var("mR", ncDouble, dimK, dimEig); NcVar *varMI = ncdf_out.add_var("mI", ncDouble, dimK, dimEig); NcVar *varUR = ncdf_out.add_var("uR", ncDouble, dimK, dimEig, dimLat); NcVar *varUI = ncdf_out.add_var("uI", ncDouble, dimK, dimEig, dimLat); NcVar *varVR = ncdf_out.add_var("vR", ncDouble, dimK, dimEig, dimLatS); NcVar *varVI = ncdf_out.add_var("vI", ncDouble, dimK, dimEig, dimLatS); NcVar *varPR = ncdf_out.add_var("pR", ncDouble, dimK, dimEig, dimLat); NcVar *varPI = ncdf_out.add_var("pI", ncDouble, dimK, dimEig, dimLat); NcVar *varWR = ncdf_out.add_var("wR", ncDouble, dimK, dimEig, dimLat); NcVar *varWI = ncdf_out.add_var("wI", ncDouble, dimK, dimEig, dimLat); NcVar *varRhoR = ncdf_out.add_var("rhoR", ncDouble, dimK, dimEig, dimLat); NcVar *varRhoI = ncdf_out.add_var("rhoI", ncDouble, dimK, dimEig, dimLat); // Allocate temporary arrays DataVector<double> dUR; dUR.Initialize(param.nPhiElements); DataVector<double> dUI; dUI.Initialize(param.nPhiElements); DataVector<double> dVR; dVR.Initialize(param.nPhiElements-1); DataVector<double> dVI; dVI.Initialize(param.nPhiElements-1); DataVector<double> dPR; dPR.Initialize(param.nPhiElements); DataVector<double> dPI; dPI.Initialize(param.nPhiElements); DataVector<double> dWR; dWR.Initialize(param.nPhiElements); DataVector<double> dWI; dWI.Initialize(param.nPhiElements); DataVector<double> dRhoR; dRhoR.Initialize(param.nPhiElements); DataVector<double> dRhoI; dRhoI.Initialize(param.nPhiElements); // Loop over all horizontal wave numbers for (int nK = nKmin; nK <= nKmax; nK++) { // Build matrices char szMessage[100]; sprintf(szMessage, "Building evolution matrices (k = %i)", nK); AnnounceStartBlock(szMessage); DataMatrix<double> matM; DataMatrix<double> matB; GenerateEvolutionMatrix(nK, param, matM, matB); AnnounceEndBlock("Done"); // Solve the matrices AnnounceStartBlock("Solving evolution matrices"); DataVector<double> vecAlphaR; DataVector<double> vecAlphaI; DataVector<double> vecBeta; DataMatrix<double> matVR; vecAlphaR.Initialize(matM.GetRows()); vecAlphaI.Initialize(matM.GetRows()); vecBeta .Initialize(matM.GetRows()); matVR .Initialize(matM.GetRows(), matM.GetColumns()); SolveEvolutionMatrix( matM, matB, vecAlphaR, vecAlphaI, vecBeta, matVR); // Sort eigenvalues std::multimap<double, int> mapSortedRows; for (int i = 0; i < vecBeta.GetRows(); i++) { if (vecBeta[i] != 0.0) { double dLambdaR = vecAlphaR[i] / vecBeta[i]; double dLambdaI = vecAlphaI[i] / vecBeta[i]; double dMR = dLambdaI; double dMI = - dLambdaR - 1.0; double dEvalMagnitude = fabs(dMR); //printf("\n%1.5e %1.5e ", dMR, dMI); // Purely imaginary eigenvalue if (dMR == 0.0) { // Wave must decay with height if (dMI < 0.0) { continue; } // Complex-conjugate pair of eigenvalues } else { // Phase propagation must be downward, and energy // propagation upwards if (dMR < 0.0) { continue; } } //printf("(OK)"); mapSortedRows.insert( std::pair<double, int>(dEvalMagnitude, i)); // Only store one entry for complex-conjugate pairs if (vecAlphaI[i] != 0.0) { i++; } } } Announce("%i eigenmodes found to satisfy entropy condition", mapSortedRows.size()); /* if (mapSortedRows.size() != param.nPhiElements) { _EXCEPTIONT("Mismatch between eigenmode count and latitude count"); } */ AnnounceEndBlock("Done"); // Write the matrices to a file AnnounceStartBlock("Writing results"); int iKix = nK - nKmin; int iWave = 0; std::map<double, int>::const_iterator it; for (it = mapSortedRows.begin(); it != mapSortedRows.end(); it++) { int i = it->second; double dLambdaR = vecAlphaR[i] / vecBeta[i]; double dLambdaI = vecAlphaI[i] / vecBeta[i]; double dMR = dLambdaI; double dMI = - dLambdaR - 1.0; // Dump eigenvalue to NetCDF file varMR->set_cur(iKix, iWave); varMR->put(&dMR, 1, 1); varMI->set_cur(iKix, iWave); varMI->put(&dMI, 1, 1); // Store real part of eigenfunction for (int j = 0; j < param.nPhiElements; j++) { dUR [j] = matVR[i][4*j ]; dPR [j] = matVR[i][4*j+1]; dWR [j] = matVR[i][4*j+2]; dRhoR[j] = matVR[i][4*j+3]; } for (int j = 0; j < param.nPhiElements-1; j++) { dVR[j] = matVR[i][4 * param.nPhiElements + j]; } // Complex eigenvalue / eigenfunction pair if (dLambdaI != 0.0) { // Eigenvalue Lambda is complex conjugate dMR = -dMR; // Dump eigenvalue to NetCDF file varMR->set_cur(iKix, iWave+1); varMR->put(&dMR, 1, 1); varMI->set_cur(iKix, iWave+1); varMI->put(&dMI, 1, 1); // Store imaginary component of vector for (int j = 0; j < param.nPhiElements; j++) { dUI [j] = matVR[i+1][4*j ]; dPI [j] = matVR[i+1][4*j+1]; dWI [j] = matVR[i+1][4*j+2]; dRhoI[j] = matVR[i+1][4*j+3]; } for (int j = 0; j < param.nPhiElements-1; j++) { dVI[j] = matVR[i+1][4 * param.nPhiElements + j]; } // Real eigenvalue / eigenvector pair } else { dUI.Zero(); dPI.Zero(); dWI.Zero(); dRhoI.Zero(); dVI.Zero(); } // Dump the first eigenfunction to the file varUR->set_cur(iKix, iWave, 0); varUR->put(dUR, 1, 1, param.nPhiElements); varVR->set_cur(iKix, iWave, 0); varVR->put(dVR, 1, 1, param.nPhiElements-1); varPR->set_cur(iKix, iWave, 0); varPR->put(dPR, 1, 1, param.nPhiElements); varWR->set_cur(iKix, iWave, 0); varWR->put(dWR, 1, 1, param.nPhiElements); varRhoR->set_cur(iKix, iWave, 0); varRhoR->put(dRhoR, 1, 1, param.nPhiElements); varUI->set_cur(iKix, iWave, 0); varUI->put(dUI, 1, 1, param.nPhiElements); varVI->set_cur(iKix, iWave, 0); varVI->put(dVI, 1, 1, param.nPhiElements-1); varPI->set_cur(iKix, iWave, 0); varPI->put(dPI, 1, 1, param.nPhiElements); varWI->set_cur(iKix, iWave, 0); varWI->put(dWI, 1, 1, param.nPhiElements); varRhoI->set_cur(iKix, iWave, 0); varRhoI->put(dRhoI, 1, 1, param.nPhiElements); // Complex eigenvalue / eigenvector pair if (dLambdaI != 0.0) { for (int j = 0; j < param.nPhiElements; j++) { dUI [j] = - dUI [j]; dPI [j] = - dPI [j]; dWI [j] = - dWI [j]; dRhoI[j] = - dRhoI[j]; } for (int j = 0; j < param.nPhiElements-1; j++) { dVI[j] = - dVI[j]; } varUR->set_cur(iKix, iWave+1, 0); varUR->put(dUR, 1, 1, param.nPhiElements); varVR->set_cur(iKix, iWave+1, 0); varVR->put(dVR, 1, 1, param.nPhiElements-1); varPR->set_cur(iKix, iWave+1, 0); varPR->put(dPR, 1, 1, param.nPhiElements); varWR->set_cur(iKix, iWave+1, 0); varWR->put(dWR, 1, 1, param.nPhiElements); varRhoR->set_cur(iKix, iWave+1, 0); varRhoR->put(dRhoR, 1, 1, param.nPhiElements); varUI->set_cur(iKix, iWave+1, 0); varUI->put(dUI, 1, 1, param.nPhiElements); varVI->set_cur(iKix, iWave+1, 0); varVI->put(dVI, 1, 1, param.nPhiElements-1); varPI->set_cur(iKix, iWave+1, 0); varPI->put(dPI, 1, 1, param.nPhiElements); varWI->set_cur(iKix, iWave+1, 0); varWI->put(dWI, 1, 1, param.nPhiElements); varRhoI->set_cur(iKix, iWave+1, 0); varRhoI->put(dRhoI, 1, 1, param.nPhiElements); } // Increment wave index iWave++; if (dLambdaI != 0.0) { iWave++; } } AnnounceEndBlock("Done"); AnnounceBanner(); } } catch(Exception & e) { Announce(e.ToString().c_str()); } }