23#include "pism/coupler/surface/DEBMSimplePointwise.hh"
24#include "pism/util/ConfigInterface.hh"
25#include "pism/util/Context.hh"
26#include "pism/util/Time.hh"
65 return std::max(temperature, 0.0);
68 double Z = temperature / (sqrt(2.0) * sigma);
69 return (sigma / sqrt(2.0 * M_PI)) * exp(-Z * Z) + (temperature / 2.0) * erfc(-Z);
86 double cos_h_phi = ((sin(
phi) - sin(latitude) * sin(declination)) /
87 (cos(latitude) * cos(declination)));
103 double perihelion_longitude) {
108 double E3 = E * E * E;
112 const double equinox_day_number = 80.0;
113 double delta_lambda = 2.0 * M_PI * (year_fraction - equinox_day_number / 365.0);
114 double beta = sqrt(1.0 - E2);
116 double lambda_m = (-2.0 * ((E / 2.0 + E3 / 8.0) * (1.0 + beta) * sin(-L_p) -
117 E2 / 4.0 * (1.0 / 2.0 + beta) * sin(-2.0 * L_p) +
118 E3 / 8.0 * (1.0 / 3.0 + beta) * sin(-3.0 * L_p)) +
122 (2.0 * E - E3 / 4.0) * sin(lambda_m - L_p) +
123 (5.0 / 4.0) * E2 * sin(2.0 * (lambda_m - L_p)) +
124 (13.0 / 12.0) * E3 * sin(3.0 * (lambda_m - L_p)));
152 double t = 2. * M_PI * year_fraction;
155 a1 * cos(t) + b1 * sin(t) +
156 a2 * cos(2. * t) + b2 * sin(2. * t));
180 "invalid eccentricity value: 1.0");
183 return pow((1.0 + E * cos(true_anomaly)) / (1.0 - E * E), 2);
203 double t = 2. * M_PI * year_fraction;
206 a1 * cos(t) + b1 * sin(t) +
207 a2 * cos(2. * t) + b2 * sin(2. * t) +
208 a3 * cos(3. * t) + b3 * sin(3. * t));
222 double solar_longitude) {
276 double hour_angle,
double latitude,
double declination) {
281 return ((solar_constant /
hour_angle) * distance_factor *
282 (
hour_angle * sin(latitude) * sin(declination) +
283 cos(latitude) * cos(declination) * sin(
hour_angle)));
308 m_L = config.
get_number(
"constants.fresh_water.latent_heat_of_fusion");
334 std::string paleo_file = config.
get_string(
"surface.debm_simple.paleo.file");
336 if (not paleo_file.empty()) {
338 "1",
"eccentricity of the earth"));
341 "degree",
"obliquity of the earth"));
344 new ScalarForcing(ctx,
"surface.debm_simple.paleo",
"perihelion_longitude",
"radian",
345 "degree",
"longitude of the perihelion relative to the vernal equinox, "
346 "in the geocentric ecliptic coordinate system"));
362 assert(melt_rate >= 0.0);
379 double solar_declination = 0.0;
380 double distance_factor = 0.0;
382 double year_fraction =
m_time->year_fraction(time);
387 double sun_true_longitude =
404 double earth_true_anomaly = sun_true_longitude - geocentric_perihelion_longitude;
412 return { solar_declination, distance_factor };
423 double latitude_degrees)
const {
424 const double degrees_to_radians = M_PI / 180.0;
425 double latitude_rad = latitude_degrees * degrees_to_radians;
447 double distance_factor,
449 double T_std_deviation,
451 double surface_elevation,
453 double albedo)
const {
456 const double degrees_to_radians = M_PI / 180.0;
457 double latitude_rad = latitude * degrees_to_radians;
466 const double eps = 1.0e-4;
484 result.
total_melt = std::max(total_melt, 0.0);
500 double old_snow_depth,
double accumulation)
const {
504 snow_depth = old_snow_depth,
508 assert(ice_thickness >= 0);
511 snow_depth = std::min(snow_depth, ice_thickness);
513 assert(snow_depth >= 0);
515 snow_depth += accumulation;
517 if (max_melt <= 0.0) {
520 }
else if (max_melt <= snow_depth) {
523 snow_melted = max_melt;
527 snow_melted = snow_depth;
528 ice_melted = std::min(max_melt - snow_melted, ice_thickness);
536 snow_depth = std::max(snow_depth - snow_melted, 0.0);
538 double total_melt = (snow_melted + ice_melted);
539 double runoff = total_melt - ice_created_by_refreeze;
540 double smb = accumulation - runoff;
542 result.
snow_depth = snow_depth - old_snow_depth;
543 result.
melt = total_melt;
545 result.
smb = ice_thickness + smb >= 0 ? smb : -ice_thickness;
547 assert(ice_thickness + result.
smb >= 0);
580 L_p = L_p + 2 * M_PI;
double get_number(const std::string &name, UseFlag flag=REMEMBER_THIS_USE) const
std::string get_string(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.
std::shared_ptr< const Config > config() const
std::shared_ptr< const Time > time() const
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
double albedo(double melt_rate, MaskValue cell_type) const
static double insolation(double solar_constant, double distance_factor, double hour_angle, double latitude, double declination)
double m_melt_threshold_temp
double m_transmissivity_slope
slope used in the linear parameterization of transmissivity
std::unique_ptr< ScalarForcing > m_eccentricity
double m_constant_obliquity
std::unique_ptr< ScalarForcing > m_obliquity
double m_refreeze_fraction
refreeze fraction
double m_positive_threshold_temperature
threshold temperature for the computation of temperature-driven melt
double eccentricity(double time) const
static double CalovGreveIntegrand(double sigma, double temperature)
static double solar_longitude(double year_fraction, double eccentricity, double perihelion_longitude)
DEBMSimpleMelt melt(double declination, double distance_factor, double dt, double T_std_deviation, double T, double surface_elevation, double lat, double albedo) const
static double distance_factor_paleo(double eccentricity, double true_anomaly)
double m_albedo_slope
slope used in the linear parameterization of the albedo as a function of melt
double insolation_diagnostic(double declination, double distance_factor, double latitude_degrees) const
bool m_refreeze_ice_melt
refreeze melted ice
double perihelion_longitude(double time) const
double m_solar_constant
the solar constant
static double hour_angle(double phi, double latitude, double declination)
static double distance_factor_present_day(double year_fraction)
double m_constant_perihelion_longitude
double m_phi
minimum solar elevation angle above which melt is possible
static double solar_declination_paleo(double obliquity, double solar_longitude)
double atmosphere_transmissivity(double elevation) const
DEBMSimpleOrbitalParameters orbital_parameters(double time) const
double m_constant_eccentricity
std::unique_ptr< ScalarForcing > m_perihelion_longitude
static double solar_declination_present_day(double year_fraction)
DEBMSimpleChanges step(double ice_thickness, double max_melt, double snow_depth, double accumulation) const
Compute the surface mass balance at a location from the amount of melted snow and the solid accumulat...
std::shared_ptr< const Time > m_time
double m_L
latent heat of fusion
double obliquity(double time) const
DEBMSimplePointwise(const Context &ctx)
double m_transmissivity_intercept
#define PISM_ERROR_LOCATION