19 #include "pism/coupler/atmosphere/OrographicPrecipitationSerial.hh"
22 #include <gsl/gsl_math.h>
26 #include "pism/util/ConfigInterface.hh"
27 #include "pism/util/error_handling.hh"
28 #include "pism/util/fftw_utilities.hh"
31 namespace atmosphere {
47 : m_Mx(Mx), m_My(My), m_Nx(Nx), m_Ny(Ny) {
65 m_tau_c = config.
get_number(
"atmosphere.orographic_precipitation.conversion_time");
67 m_Hw = config.
get_number(
"atmosphere.orographic_precipitation.water_vapor_scale_height");
68 m_Nm = config.
get_number(
"atmosphere.orographic_precipitation.moist_stability_frequency");
72 m_Theta_m = config.
get_number(
"atmosphere.orographic_precipitation.moist_adiabatic_lapse_rate");
89 PetscErrorCode ierr = 0;
98 m_G_hat = (fftw_complex *)fftw_malloc(
sizeof(fftw_complex) *
m_Nx *
m_Ny);
102 FFTW_FORWARD, FFTW_ESTIMATE);
104 FFTW_BACKWARD, FFTW_ESTIMATE);
117 double sigma = config.
get_number(
"atmosphere.orographic_precipitation.smoothing_standard_deviation");
129 for (
int i = 0; i <
m_Nx; i++) {
130 for (
int j = 0; j <
m_Ny; j++) {
132 p = i <= Nx2 ? i :
m_Nx - i,
133 q = j <= Ny2 ? j :
m_Ny - j;
138 double G = std::exp(-0.5 * (x * x + y * y) / (sigma * sigma));
141 fftw_input(i, j) =
G;
147 for (
int i = 0; i <
m_Nx; i++) {
148 for (
int j = 0; j <
m_Ny; j++) {
149 fftw_input(i, j) /=
sum;
157 for (
int i = 0; i <
m_Nx; i++) {
158 for (
int j = 0; j <
m_Ny; j++) {
159 G_hat(i, j) = fftw_output(i, j);
165 for (
int i = 0; i <
m_Nx; i++) {
166 for (
int j = 0; j <
m_Ny; j++) {
202 std::complex<double>
I(0.0, 1.0);
222 for (
int i = 0; i <
m_Nx; i++) {
223 const double kx =
m_kx[i];
224 for (
int j = 0; j <
m_Ny; j++) {
225 const double ky =
m_ky[j];
228 const auto &h_hat = fftw_output(i, j) * G_hat(i, j);
230 double sigma =
m_u * kx +
m_v * ky;
233 std::complex<double> m;
235 double denominator = sigma * sigma -
m_f *
m_f;
238 if (fabs(denominator) <
m_eps) {
239 denominator = denominator >= 0 ?
m_eps : -
m_eps;
242 double m_squared = (
m_Nm *
m_Nm - sigma * sigma) * (kx * kx + ky * ky) / denominator;
245 m = std::sqrt(std::complex<double>(m_squared));
247 if (m_squared >= 0.0 and sigma != 0.0) {
248 m *= sigma > 0.0 ? 1.0 : -1.0;
260 auto P_hat = h_hat * (
m_Cw *
I * sigma /
261 ((1.0 -
I * m *
m_Hw + delta) *
270 fftw_input(i, j) = P_hat;
286 for (
int i = 0; i <
m_Mx; i++) {
287 for (
int j = 0; j <
m_My; j++) {
double get_number(const std::string &name, UseFlag flag=REMEMBER_THIS_USE) const
bool get_flag(const std::string &name, UseFlag flag=REMEMBER_THIS_USE) const
A class for storing and accessing PISM configuration flags and parameters.
~OrographicPrecipitationSerial()
double m_background_precip_post
double m_v
vertical wind component
std::vector< double > m_kx
void update(petsc::Vec &surface_elevation)
double m_precip_scale_factor
precipitation scale factor
std::vector< double > m_ky
double m_Cw
uplift sensitivity factor
double m_tau_c
cloud conversion time
OrographicPrecipitationSerial(const Config &config, int Mx, int My, double dx, double dy, int Nx, int Ny)
double m_wind_direction
wind direction
double m_tau_f
cloud fallout time
double m_latitude
latitude for Coriolis force
double m_wind_speed
wind speed
double m_Hw
water vapor scale height
Vec precipitation() const
double m_Theta_m
moist adiabatic lapse rate
double m_rho_Sref
reference density
petsc::Vec m_precipitation
double m_Nm
moist stability frequency
double m_background_precip_pre
background precipitation
double m_u
horizontal wind component
fftw_complex * m_fftw_output
fftw_complex * m_fftw_input
double m_gamma
moist lapse rate
double m_f
Coriolis force.
Wrapper around VecGetArray2d and VecRestoreArray2d.
#define PISM_CHK(errcode, name)
double max(const array::Scalar &input)
Finds maximum over all the values in an array::Scalar object. Ignores ghosts.
double sum(const array::Scalar &input)
Sums up all the values in an array::Scalar object. Ignores ghosts.
void clear_fftw_array(fftw_complex *input, int Nx, int Ny)
Fill input with zeros.
void get_real_part(fftw_complex *input, double normalization, int Mx, int My, int Nx, int Ny, int i0, int j0, petsc::Vec &output)
Get the real part of input and put it in output.
void set_real_part(petsc::Vec &input, double normalization, int Mx, int My, int Nx, int Ny, int i0, int j0, fftw_complex *output)
std::vector< double > fftfreq(int M, double normalization)