/// <summary> /// Evaluate the state vector at the given point. /// </summary> virtual void EvaluatePointwiseState( const PhysicalConstants & phys, const Time & time, double dZp, double dXp, double dYp, double * dState, double * dTracer ) const { const double dG = phys.GetG(); const double dCv = phys.GetCv(); const double dCp = phys.GetCp(); const double dRd = phys.GetR(); const double dP0 = phys.GetP0(); // The Brunt-Vaisala frequency const double dNbar = dG / sqrt(dCp * m_dT0); // Base potential temperature field const double dTheta0 = m_dT0; double dThetaBar = dTheta0 * exp(dNbar * dNbar / dG * dZp); // Set the uniform U, V, W field for all time dState[0] = m_dU0; dState[1] = 0.0; dState[3] = 0.0; // Set the initial potential temperature field dState[2] = dThetaBar; // Set the initial density based on the Exner pressure double dExnerP = exp(-dG / (dCp * m_dT0) * dZp); double dRho = dP0 / (dRd * dThetaBar) * pow(dExnerP,(dCv / dRd)); dState[4] = dRho; }
/// <summary> /// Evaluate the reference state at the given point. /// </summary> virtual void EvaluateReferenceState( const PhysicalConstants & phys, double dZ, double dLon, double dLat, double * dState ) const { // 3D temperature double dT = m_dT0 - m_dGamma * dZ; // 3D pressure double dPressure = phys.GetP0() * pow(1.0 - m_dGamma / m_dT0 * dZ, phys.GetG() / (phys.GetR() * m_dGamma)); // 3D density double dRho = dPressure / (phys.GetR() * dT); // Store the state dState[0] = 0.0; dState[1] = 0.0; dState[2] = phys.RhoThetaFromPressure(dPressure) / dRho; dState[3] = 0.0; dState[4] = dRho; }
/// <summary> /// Calculate the geopotential and temperature at the given point. /// </summary> void CalculateGeopotentialTemperature( const PhysicalConstants & phys, double dEta, double dXp, double dYp, double & dGeopotential, double & dTemperature ) const { // Get some constants const double dG = phys.GetG(); const double dCv = phys.GetCv(); const double dCp = phys.GetCp(); const double dRd = phys.GetR(); const double dP0 = phys.GetP0(); const double dae = phys.GetEarthRadius(); const double df0 = 2 * phys.GetOmega() * sin(m_dRefLat); //const double df0 = 0.0; const double dbeta0 = 2 * phys.GetOmega() * cos(m_dRefLat) / dae; //const double dbeta0 = 0.0; const double dLy = m_dGDim[3] - m_dGDim[2]; // Horizontally averaged temperature double dAvgTemperature = m_dT0 * pow(dEta, dRd * m_ddTdz / dG); // Horizontally averaged geopotential double dAvgGeopotential = m_dT0 * dG / m_ddTdz * (1.0 - pow(dEta, dRd * m_ddTdz / dG)); // Horizontal variation geopotential function double dXYGeopotential = 0.5 * m_dU0 * ((df0 - dbeta0 * m_dY0) * (dYp - m_dY0 - m_dY0 / m_dpiC * sin(2 * m_dpiC * dYp / dLy)) + 0.5 * dbeta0 * (dYp * dYp - dLy * dYp / m_dpiC * sin(2 * m_dpiC * dYp / dLy) - 0.5 * dLy * dLy / (m_dpiC * m_dpiC) * cos(2 * m_dpiC * dYp / dLy) - dLy * dLy / 3 - 0.5 * dLy * dLy / (m_dpiC * m_dpiC))); double dExpDecay = exp(-(log(dEta) / m_dbC) * (log(dEta) / m_dbC)); double dRefProfile1 = log(dEta); double dRefProfile2 = 2 / (m_dbC * m_dbC) * log(dEta) * log(dEta) - 1.0; // Total geopotential distribution dGeopotential = dAvgGeopotential + dXYGeopotential* dRefProfile1 * dExpDecay; // Total temperature distribution dTemperature = dAvgTemperature + dXYGeopotential / dRd * dRefProfile2 * dExpDecay; }
/// <summary> /// Evaluate the reference state at the given point. /// </summary> virtual void EvaluateReferenceState( const PhysicalConstants & phys, double dZp, double dXp, double dYp, double * dState ) const { const double dG = phys.GetG(); const double dCv = phys.GetCv(); const double dCp = phys.GetCp(); const double dRd = phys.GetR(); const double dP0 = phys.GetP0(); // Base potential temperature field double dThetaBar = m_dTheta0 * exp(m_dNbar * m_dNbar / dG * dZp); // Set the uniform U, V, W field for all time dState[0] = m_dU0; dState[1] = 0.0; dState[3] = 0.0; // Zero gravity case if (dG == 0.0) { static double dT0 = 300.0; dState[2] = dT0 * pow(dP0, (dRd / dCp)); dState[4] = dP0 / (dRd * dT0); // Stratification with gravity } else { // Set the initial density based on the Exner pressure double dExnerP = (dG * dG) / (dCp * m_dTheta0 * m_dNbar * m_dNbar); dExnerP *= (exp(-m_dNbar * m_dNbar / dG * dZp) - 1.0); dExnerP += 1.0; double dRho = dP0 / (dRd * dThetaBar) * pow(dExnerP,(dCv / dRd)); dState[4] = dRho; // Set the initial potential temperature field //dState[2] = phys.PressureFromRhoTheta(dThetaBar * dRho); //dState[2] = (dThetaBar * dRho); dState[2] = dThetaBar; } }
/// <summary> /// Evaluate the reference state at the given point. /// </summary> virtual void EvaluateReferenceState( const PhysicalConstants & phys, double dZp, double dXp, double dYp, double * dState ) const { const double dLy = m_dGDim[3] - m_dGDim[2]; // Pressure coordinate double dGeopotential; double dTemperature; double dEta = EtaFromRLL( phys, dZp, dXp, dYp, dGeopotential, dTemperature); // Calculate zonal velocity and set other velocity components double dExpDecay = exp(-(log(dEta) / m_dbC) * (log(dEta) / m_dbC)); double dUlon = -m_dU0 * sin(m_dpiC * dYp / dLy) * sin(m_dpiC * dYp / dLy) * log(dEta) * dExpDecay; dState[0] = dUlon; dState[1] = 0.0; dState[3] = 0.0; // Calculate rho and theta double dPressure = phys.GetP0() * dEta; //std::cout << std::setprecision(16) << "Z = " << dZp << " Eta = " << dEta << "\n"; double dRho = dPressure / (phys.GetR() * dTemperature); double dRhoTheta = phys.RhoThetaFromPressure(dPressure); dState[2] = dRhoTheta / dRho; dState[4] = dRho; }
/// <summary> /// Evaluate the state vector at the given point. /// </summary> virtual void EvaluatePointwiseState( const PhysicalConstants & phys, const Time & time, double dZp, double dXp, double dYp, double * dState, double * dTracer ) const { const double dG = phys.GetG(); const double dCv = phys.GetCv(); const double dCp = phys.GetCp(); const double dRd = phys.GetR(); const double dP0 = phys.GetP0(); // Base potential temperature field double dThetaBar = m_dTheta0 * exp(m_dNbar * m_dNbar / dG * dZp); // Set the uniform U, V, W field for all time dState[0] = m_dU0; dState[1] = 0.0; dState[3] = 0.0; dState[3] = sin(M_PI * dZp / m_dGDim[5]); // Set the initial density based on the Exner pressure double dExnerP = (dG * dG) / (dCp * m_dTheta0 * m_dNbar * m_dNbar); dExnerP *= (exp(-m_dNbar * m_dNbar / dG * dZp) - 1.0); dExnerP += 1.0; double dRho = dP0 / (dRd * dThetaBar) * pow(dExnerP,(dCv / dRd)); dState[4] = dRho; // Set the initial theta field //dState[2] = phys.PressureFromRhoTheta(dThetaBar * dRho); //dState[2] = (dThetaBar * dRho); dState[2] = dThetaBar; }
/// <summary> /// Evaluate the state vector at the given point. /// </summary> virtual void EvaluatePointwiseState( const PhysicalConstants & phys, const Time & time, double dZ, double dLon, double dLat, double * dState, double * dTracer ) const { // Radius double dR = dZ + phys.GetEarthRadius(); // Calculate parameters double dT0 = 0.5 * (ParamT0E + ParamT0P); double dConstA = 1.0 / ParamLapseRate; double dConstB = (dT0 - ParamT0P) / (dT0 * ParamT0P); double dConstC = 0.5 * (ParamK + 2.0) * (ParamT0E - ParamT0P) / (ParamT0E * ParamT0P); double dConstH = phys.GetR() * dT0 / phys.GetG(); // Computed quantities double dScaledZ = dZ / (ParamB * dConstH); // Calculate tau values double dTau1 = dConstA * ParamLapseRate / dT0 * exp(ParamLapseRate / dT0 * dZ) + dConstB * (1.0 - 2.0 * dScaledZ * dScaledZ) * exp(- dScaledZ * dScaledZ); double dTau2 = dConstC * (1.0 - 2.0 * dScaledZ * dScaledZ) * exp(- dScaledZ * dScaledZ); double dIntTau1 = dConstA * (exp(ParamLapseRate / dT0 * dZ) - 1.0) + dConstB * dZ * exp(- dScaledZ * dScaledZ); double dIntTau2 = dConstC * dZ * exp(- dScaledZ * dScaledZ); // Calculate utility terms double dRRatio; if (m_fDeepAtmosphere) { dRRatio = dR / phys.GetEarthRadius(); } else { dRRatio = 1.0; } double dInteriorTerm = pow(dRRatio * cos(dLat), ParamK) - ParamK / (ParamK + 2.0) * pow(dRRatio * cos(dLat), ParamK + 2.0); // Calculate temperature double dTemperature = 1.0 / (dRRatio * dRRatio) / (dTau1 - dTau2 * dInteriorTerm); // Calculate hydrostatic pressure double dPressure = phys.GetP0() * exp( - phys.GetG() / phys.GetR() * (dIntTau1 - dIntTau2 * dInteriorTerm)); // Calculate hydrostatic density double dRho = dPressure / (phys.GetR() * dTemperature); // Velocity field double dInteriorTermU = pow(dRRatio * cos(dLat), ParamK - 1.0) - pow(dRRatio * cos(dLat), ParamK + 1.0); double dBigU = phys.GetG() / phys.GetEarthRadius() * ParamK * dIntTau2 * dInteriorTermU * dTemperature; double dRCosLat; if (m_fDeepAtmosphere) { dRCosLat = dR * cos(dLat); } else { dRCosLat = phys.GetEarthRadius() * cos(dLat); } double dOmegaRCosLat = phys.GetOmega() * dRCosLat; if (dOmegaRCosLat * dOmegaRCosLat + dRCosLat * dBigU < 0.0) { _EXCEPTIONT("Negative discriminant detected."); } double dUlon = - dOmegaRCosLat + sqrt(dOmegaRCosLat * dOmegaRCosLat + dRCosLat * dBigU); double dUlat = 0.0; // Calculate velocity perturbation double dUlonPert; double dUlatPert; EvaluatePointwisePerturbation( phys, dZ, dLon, dLat, dUlonPert, dUlatPert); dUlon += dUlonPert; dUlat += dUlatPert; // Store the state dState[0] = dUlon; dState[1] = dUlat; dState[2] = phys.RhoThetaFromPressure(dPressure) / dRho; dState[3] = 0.0; dState[4] = dRho; }
/// <summary> /// Evaluate the reference state at the given point. /// </summary> virtual void EvaluateReferenceState( const PhysicalConstants & phys, double dZ, double dLon, double dLat, double * dState ) const { // Radius double dR = dZ + phys.GetEarthRadius(); // Calculate parameters double dT0 = 0.5 * (ParamT0E + ParamT0P); double dConstA = 1.0 / ParamLapseRate; double dConstB = (dT0 - ParamT0P) / (dT0 * ParamT0P); double dConstC = 0.5 * (ParamK + 2.0) * (ParamT0E - ParamT0P) / (ParamT0E * ParamT0P); double dConstH = phys.GetR() * dT0 / phys.GetG(); // Computed quantities double dScaledZ = dZ / (ParamB * dConstH); // Calculate tau values double dTau1 = dConstA * ParamLapseRate / dT0 * exp(ParamLapseRate / dT0 * dZ) + dConstB * (1.0 - 2.0 * dScaledZ * dScaledZ) * exp(- dScaledZ * dScaledZ); double dTau2 = dConstC * (1.0 - 2.0 * dScaledZ * dScaledZ) * exp(- dScaledZ * dScaledZ); double dIntTau1 = dConstA * (exp(ParamLapseRate / dT0 * dZ) - 1.0) + dConstB * dZ * exp(- dScaledZ * dScaledZ); double dIntTau2 = dConstC * dZ * exp(- dScaledZ * dScaledZ); // Calculate utility terms double dRRatio; if (m_fDeepAtmosphere) { dRRatio = dR / phys.GetEarthRadius(); } else { dRRatio = 1.0; } double dInteriorTerm = pow(dRRatio * cos(dLat), ParamK) - ParamK / (ParamK + 2.0) * pow(dRRatio * cos(dLat), ParamK + 2.0); // Calculate temperature double dTemperature = 1.0 / (dRRatio * dRRatio) / (dTau1 - dTau2 * dInteriorTerm); // Calculate hydrostatic pressure double dPressure = phys.GetP0() * exp( - phys.GetG() / phys.GetR() * (dIntTau1 - dIntTau2 * dInteriorTerm)); /* // Calculate pressure derivative double dDrPressure; if (m_fDeepAtmosphere) { dDrPressure = dPressure * phys.GetG() / phys.GetR() * ( - dTau1 + dTau2 * dInteriorTerm + dIntTau2 * ParamK / dR * (pow(dRRatio * cos(dLat), ParamK) - pow(dRRatio * cos(dLat), ParamK + 2.0))); } else { dDrPressure = dPressure * phys.GetG() / phys.GetR() * ( - dTau1 + dTau2 * dInteriorTerm); } // Calculate hydrostatic density double dHydroRho = - dRRatio * dRRatio / phys.GetG() * dDrPressure; */ // Calculate exact density double dRho = dPressure / (phys.GetR() * dTemperature); // Store the state dState[0] = 0.0; dState[1] = 0.0; dState[2] = phys.RhoThetaFromPressure(dPressure) / dRho; dState[3] = 0.0; dState[4] = dRho; }