21 #include <gsl/gsl_rng.h>
22 #include <gsl/gsl_randist.h>
23 #include <gsl/gsl_math.h>
27 #include "pism/util/ConfigInterface.hh"
28 #include "pism/coupler/surface/localMassBalance.hh"
29 #include "pism/util/Grid.hh"
30 #include "pism/util/Context.hh"
31 #include "pism/util/VariableMetadata.hh"
57 Tmin =
m_config->get_number(
"surface.pdd.air_temp_all_precip_as_snow");
58 Tmax =
m_config->get_number(
"surface.pdd.air_temp_all_precip_as_rain");
62 m_method =
"an expectation integral";
70 const unsigned int NperYear =
static_cast<unsigned int>(
m_config->get_number(
"surface.pdd.max_evals_per_year"));
73 return std::max(1U,
static_cast<unsigned int>(ceil(NperYear * dt_years)));
100 const double Z = TacC / (sqrt(2.0) * sigma);
101 return (sigma / sqrt(2.0 * M_PI)) * exp(-Z*Z) + (TacC / 2.0) * erfc(-Z);
116 const std::vector<double> &
S,
117 const std::vector<double> &T,
118 std::vector<double> &PDDs) {
119 assert(
S.size() == T.size() and T.size() == PDDs.size());
120 assert(dt_series > 0.0);
123 const size_t N =
S.size();
125 for (
unsigned int k = 0;
k < N; ++
k) {
148 std::vector<double> &P) {
150 assert(T.size() == P.size());
151 const size_t N = T.size();
154 for (
unsigned int i = 0; i < N; i++) {
163 }
else if (T[i] <
Tmax) {
197 double old_firn_depth,
198 double old_snow_depth,
199 double accumulation) {
201 firn_depth = old_firn_depth,
202 snow_depth = old_snow_depth,
203 max_snow_melted = PDDs * ddf.
snow,
208 assert(thickness >= 0);
211 snow_depth =
std::min(snow_depth, thickness);
213 assert(snow_depth >= 0);
216 firn_depth =
std::min(firn_depth, thickness - snow_depth);
218 assert(firn_depth >= 0);
220 double ice_thickness = thickness - snow_depth - firn_depth;
222 assert(ice_thickness >= 0);
224 snow_depth += accumulation;
230 }
else if (max_snow_melted <= snow_depth) {
234 snow_melted = max_snow_melted;
237 }
else if (max_snow_melted <= firn_depth + snow_depth) {
241 snow_melted = snow_depth;
242 firn_melted = max_snow_melted - snow_melted;
247 firn_melted = firn_depth;
248 snow_melted = snow_depth;
249 excess_pdds = PDDs - ((firn_melted + snow_melted) / ddf.
snow);
253 ice_melted =
std::min(excess_pdds * ddf.
ice, ice_thickness),
254 melt = snow_melted + firn_melted + ice_melted,
255 ice_created_by_refreeze = 0.0;
264 const double runoff = melt - ice_created_by_refreeze;
266 snow_depth =
std::max(snow_depth - snow_melted, 0.0);
267 firn_depth =
std::max(firn_depth - firn_melted, 0.0);
274 const double smb = accumulation - runoff;
280 result.
smb = thickness + smb >= 0 ? smb : -thickness;
281 result.
firn_depth = firn_depth - old_firn_depth;
282 result.
snow_depth = snow_depth - old_snow_depth;
286 assert(thickness + result.
smb >= 0);
305 m_impl->
rng = gsl_rng_alloc(gsl_rng_default);
309 ?
"simulation of a random process"
310 :
"repeatable simulation of a random process");
351 const std::vector<double> &
S,
352 const std::vector<double> &T,
353 std::vector<double> &PDDs) {
354 assert(
S.size() == T.size() and T.size() == PDDs.size());
355 assert(dt_series > 0.0);
358 const size_t N =
S.size();
360 for (
unsigned int k = 0;
k < N; ++
k) {
362 double T_k = T[
k] + gsl_ran_gaussian(
m_impl->
rng,
S[
k]);
372 : m_grid(grid), m_config(grid->ctx()->config()),
373 m_temp_mj(grid,
"temp_mj_faustogreve")
390 .
long_name(
"mean July air temp from Fausto et al (2009) parameterization")
410 }
else if (T_mj <=
m_T_c) {
426 ddf.
snow *= iwfactor;
441 d_mj =
m_config->get_number(
"atmosphere.fausto_air_temp.d_mj"),
442 gamma_mj =
m_config->get_number(
"atmosphere.fausto_air_temp.gamma_mj"),
443 c_mj =
m_config->get_number(
"atmosphere.fausto_air_temp.c_mj"),
444 kappa_mj =
m_config->get_number(
"atmosphere.fausto_air_temp.kappa_mj");
453 for (
auto p =
m_grid->points(); p; p.next()) {
454 const int i = p.i(), j = p.j();
455 m_temp_mj(i,j) = d_mj + gamma_mj * h(i,j) + c_mj * lat_degN(i,j) + kappa_mj * (-lon_degE(i,j));
std::shared_ptr< const Config > ConstPtr
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata object containing metadata for the compoment N.
double m_pdd_fausto_latitude_beta_w
LocalMassBalance::DegreeDayFactors degree_day_factors(int i, int j, double latitude)
const Config::ConstPtr m_config
std::shared_ptr< const Grid > m_grid
FaustoGrevePDDObject(std::shared_ptr< const Grid > g)
double m_fresh_water_density
double m_refreeze_fraction
void update_temp_mj(const array::Scalar &surfelev, const array::Scalar &lat, const array::Scalar &lon)
Updates mean July near-surface air temperature.
const units::System::Ptr m_unit_system
std::string method() const
const double m_seconds_per_day
const Config::ConstPtr m_config
LocalMassBalance(Config::ConstPtr config, units::System::Ptr system)
Base class for a model which computes surface mass flux rate (ice thickness per time) from precipitat...
void get_snow_accumulation(const std::vector< double > &T, std::vector< double > &precip_rate)
Extract snow accumulation from mixed (snow and rain) precipitation using the temperature time-series.
bool refreeze_ice_melt
refreeze melted ice
bool precip_as_snow
interpret all the precipitation as snow (no rain)
virtual void get_PDDs(double dt_series, const std::vector< double > &S, const std::vector< double > &T, std::vector< double > &PDDs)
Compute the expected number of positive degree days from the input temperature time-series.
double Tmax
the temperature above which all precipitation is rain
Changes step(const DegreeDayFactors &ddf, double PDDs, double ice_thickness, double firn_depth, double snow_depth, double accumulation)
Compute the surface mass balance at a location from the number of positive degree days and the accumu...
double pdd_threshold_temp
threshold temperature for the PDD computation
double Tmin
the temperature below which all precipitation is snow
PDDMassBalance(Config::ConstPtr config, units::System::Ptr system)
virtual unsigned int get_timeseries_length(double dt)
Compute the number of points for temperature and precipitation time-series.
A PDD implementation which computes the local mass balance based on an expectation integral.
virtual ~PDDrandMassBalance()
virtual unsigned int get_timeseries_length(double dt)
PDDrandMassBalance(Config::ConstPtr config, units::System::Ptr system, Kind kind)
virtual void get_PDDs(double dt_series, const std::vector< double > &S, const std::vector< double > &T, std::vector< double > &PDDs)
std::shared_ptr< System > Ptr
double max(const array::Scalar &input)
Finds maximum over all the values in an array::Scalar object. Ignores ghosts.
double min(const array::Scalar &input)
Finds minimum over all the values in an array::Scalar object. Ignores ghosts.
static double CalovGreveIntegrand(double sigma, double TacC)
Compute the integrand in integral (6) in [CalovGreve05].
double convert(System::Ptr system, double input, const std::string &spec1, const std::string &spec2)
Convert a quantity from unit1 to unit2.
double ice
m day^-1 K^-1; ice-equivalent amount of ice melted, per PDD
double refreeze_fraction
fraction of melted snow which refreezes as ice
double snow
m day^-1 K^-1; ice-equivalent amount of snow melted, per PDD
A struct which holds degree day factors.
static double S(unsigned n)