21 #include "pism/coupler/surface/DEBMSimple.hh"
23 #include "pism/coupler/AtmosphereModel.hh"
24 #include "pism/util/Grid.hh"
25 #include "pism/util/Mask.hh"
26 #include "pism/util/Time.hh"
27 #include "pism/util/io/File.hh"
29 #include "pism/coupler/util/options.hh"
30 #include "pism/geometry/Geometry.hh"
31 #include "pism/util/array/CellType.hh"
32 #include "pism/util/error_handling.hh"
33 #include "pism/util/pism_utilities.hh"
34 #include "pism/util/Vars.hh"
35 #include "pism/util/array/Forcing.hh"
45 m_mass_flux(m_grid,
"climatic_mass_balance"),
46 m_snow_depth(m_grid,
"snow_depth"),
47 m_temperature_driven_melt(m_grid,
"debm_temperature_driven_melt_flux"),
48 m_insolation_driven_melt(m_grid,
"debm_insolation_driven_melt_flux"),
49 m_offset_melt(m_grid,
"debm_offset_melt_flux"),
50 m_surface_albedo(m_grid,
"surface_albedo"),
51 m_transmissivity(m_grid,
"atmosphere_transmissivity") {
58 m_Tmax =
m_config->get_number(
"surface.debm_simple.air_temp_all_precip_as_rain");
59 m_Tmin =
m_config->get_number(
"surface.debm_simple.air_temp_all_precip_as_snow");
63 "surface.debm_simple.air_temp_all_precip_as_rain has to exceed "
64 "surface.debm_simple.air_temp_all_precip_as_snow");
70 m_n_per_year =
static_cast<unsigned int>(
m_config->get_number(
"surface.debm_simple.max_evals_per_year"));
72 auto albedo_input =
m_config->get_string(
"surface.debm_simple.albedo_input.file");
73 if (not albedo_input.empty()) {
75 m_log->message(2,
" Surface albedo is read in from %s...", albedo_input.c_str());
79 int buffer_size =
static_cast<int>(
m_config->get_number(
"input.forcing.buffer_size"));
80 bool periodic =
m_config->get_flag(
"surface.debm_simple.albedo_input.periodic");
96 m_log->message(2,
" Reading standard deviation of near-surface air temperature from '%s'...\n",
99 int buffer_size =
static_cast<int>(
m_config->get_number(
"input.forcing.buffer_size"));
103 bool periodic =
m_config->get_flag(
"surface.debm_simple.std_dev.periodic");
106 buffer_size, periodic,
LINEAR);
108 double temp_std_dev =
m_config->get_number(
"surface.debm_simple.std_dev");
111 m_log->message(2,
" Using constant standard deviation of near-surface air temperature.\n");
115 .long_name(
"standard deviation of near-surface air temperature")
119 .
long_name(
"instantaneous surface mass balance (accumulation/ablation) rate")
121 .
standard_name(
"land_ice_surface_specific_mass_balance_flux");
133 .
long_name(
"temperature-driven melt in dEBM-simple")
138 .
long_name(
"insolation-driven melt in dEBM-simple")
149 .
long_name(
"snow cover depth (set to zero once a year)")
173 "* Initializing dEBM-simple, the diurnal Energy Balance Model (simple version).\n"
174 " Inputs: precipitation and 2m air temperature from an atmosphere model.\n"
175 " Outputs: SMB and ice upper surface temperature.\n");
181 auto default_albedo =
m_config->get_number(
"surface.debm_simple.albedo_max");
199 auto filename =
m_config->get_string(
"surface.debm_simple.albedo_input.file");
200 bool periodic =
m_config->get_flag(
"surface.debm_simple.albedo_input.periodic");
220 double balance_year_start_day =
m_config->get_number(
"surface.mass_balance_year_start_day"),
223 balance_year_start = year_start + (balance_year_start_day - 1.0) * one_day;
225 if (balance_year_start >
time) {
226 return balance_year_start;
268 const double melting_point = 273.15;
279 const double dtseries = dt / N;
280 std::vector<double> ts(N), T(N),
S(N), P(N), Alb(N);
281 std::vector<DEBMSimplePointwise::OrbitalParameters> orbital(N);
283 for (
int k = 0;
k < N; ++
k) {
284 ts[
k] = t +
k * dtseries;
324 ice_density =
m_config->get_number(
"constants.ice.density"),
325 sigmalapserate =
m_config->get_number(
"surface.pdd.std_dev.lapse_lat_rate"),
326 sigmabaselat =
m_config->get_number(
"surface.pdd.std_dev.lapse_lat_base");
333 for (
auto p =
m_grid->points(); p; p.next()) {
334 const int i = p.i(), j = p.j();
336 double latitude = geometry.
latitude(i, j);
341 if (mask.ice_free_ocean(i, j)) {
343 for (
int k = 0;
k < N; ++
k) {
352 for (
int k = 0;
k < N; ++
k) {
369 if (sigmalapserate != 0.0) {
371 for (
int k = 0;
k < N; ++
k) {
372 S[
k] += sigmalapserate * (latitude - sigmabaselat);
374 (*m_air_temp_sd)(i, j) =
S[0];
377 for (
int k = 0;
k < N; ++
k) {
380 (*m_air_temp_sd)(i, j) =
S[0];
390 ice_thickness = H(i, j),
392 surfelev = surface_altitude(i, j),
395 auto cell_type =
static_cast<MaskValue>(mask.as_int(i, j));
408 for (
int k = 0;
k < N; ++
k) {
410 if (ts[
k] >= next_snow_depth_reset) {
412 while (next_snow_depth_reset <= ts[
k]) {
423 orbital[
k].distance_factor,
433 melt_info.total_melt,
444 ice_thickness += changes.smb;
445 assert(ice_thickness >= 0);
447 snow += changes.snow_depth;
453 Mt += melt_info.temperature_melt;
454 Mi += melt_info.insolation_melt;
455 Mc += melt_info.offset_melt;
476 (*m_accumulation)(i, j) = A * ice_density;
477 (*m_melt)(i, j) = M * ice_density;
478 (*m_runoff)(i, j) = R * ice_density;
485 if (mask.ice_free_ocean(i, j)) {
565 namespace diagnostics {
575 "mean top of atmosphere insolation during the period when the sun is above the critical angle Phi")
582 auto result = allocate<array::Scalar>(
"insolation");
584 const auto *latitude =
m_grid->variables().get_2d_scalar(
"latitude");
588 const auto& M =
model->pointwise_model();
590 auto orbital = M.orbital_parameters(ctx->time()->current());
594 for (
auto p =
m_grid->points(); p; p.next()) {
595 const int i = p.i(), j = p.j();
597 (*result)(i, j) = M.insolation(orbital.declination,
598 orbital.distance_factor,
615 ?
"debm_insolation_driven_melt_flux"
616 :
"debm_insolation_driven_melt_rate",
622 name =
"debm_insolation_driven_melt_flux",
623 long_name =
"surface insolation melt, averaged over the reporting interval",
624 accumulator_units =
"kg m-2",
625 internal_units =
"kg m-2 second-1",
626 external_units =
"kg m-2 year-1";
628 name =
"debm_insolation_driven_melt_rate";
629 accumulator_units =
"kg";
630 internal_units =
"kg second-1";
631 external_units =
"Gt year-1";
638 .long_name(long_name)
639 .units(internal_units)
640 .output_units(external_units);
641 m_vars[0].set_string(
"cell_methods",
"time: mean");
644 m_vars[0].set_number(
"_FillValue", fill_value);
649 const auto &melt_amount =
model->insolation_driven_melt();
671 ?
"debm_temperature_driven_melt_flux"
672 :
"debm_temperature_driven_melt_rate",
678 name =
"debm_temperature_driven_melt_flux",
679 long_name =
"temperature-driven melt, averaged over the reporting interval",
680 accumulator_units =
"kg m-2",
681 internal_units =
"kg m-2 second-1",
682 external_units =
"kg m-2 year-1";
684 name =
"debm_temperature_driven_melt_rate";
685 accumulator_units =
"kg";
686 internal_units =
"kg second-1";
687 external_units =
"Gt year-1";
694 .long_name(long_name)
695 .units(internal_units)
696 .output_units(external_units);
697 m_vars[0].set_string(
"cell_methods",
"time: mean");
703 const auto &melt_amount =
model->temperature_driven_melt();
725 ?
"debm_offset_melt_flux"
726 :
"debm_offset_melt_rate",
731 std::string name =
"debm_offset_melt_flux",
732 long_name =
"offset melt, averaged over the reporting interval",
733 accumulator_units =
"kg m-2",
734 internal_units =
"kg m-2 second-1",
735 external_units =
"kg m-2 year-1";
738 name =
"debm_offset_melt_rate";
739 accumulator_units =
"kg";
740 internal_units =
"kg second-1";
741 external_units =
"Gt year-1";
747 .long_name(long_name)
748 .units(internal_units)
749 .output_units(external_units);
750 m_vars[0].set_string(
"cell_methods",
"time: mean");
756 const auto &melt_amount =
model->offset_melt();
787 {
"debm_insolation_driven_melt_rate",
Diagnostic::Ptr(
new DEBMSInsolationMelt(
this,
MASS)) },
789 {
"debm_temperature_driven_melt_rate",
Diagnostic::Ptr(
new DEBMSTemperatureMelt(
this,
MASS)) },
const units::System::Ptr m_sys
unit system used by this component
const Time & time() const
const Config::ConstPtr m_config
configuration database used by this component
const Logger::ConstPtr m_log
logger (for easy access)
const std::shared_ptr< const Grid > m_grid
grid used by this component
void regrid(const std::string &module_name, array::Array &variable, RegriddingFlag flag=NO_REGRID_WITHOUT_REGRID_VARS)
DiagnosticList diagnostics() const
array::Scalar m_accumulator
A template derived from Diagnostic, adding a "Model".
static Ptr wrap(const T &input)
double m_fill_value
fill value (used often enough to justify storing it)
const units::System::Ptr m_sys
the unit system
double to_internal(double x) const
std::vector< SpatialVariableMetadata > m_vars
metadata corresponding to NetCDF variables
std::shared_ptr< Diagnostic > Ptr
std::shared_ptr< const Grid > m_grid
the grid
High-level PISM I/O class.
array::Scalar2 ice_surface_elevation
array::CellType2 cell_type
array::Scalar2 ice_thickness
Combines the max. time step with the flag indicating if a restriction is active. Makes is possible to...
void failed()
Indicates a failure of a parallel section.
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
double increment_date(double T, double years) const
double calendar_year_start(double T) const
Returns the model time in seconds corresponding to the beginning of the year T falls into.
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
void copy_from(const Array2D< T > &source)
void read(const std::string &filename, unsigned int time)
void define(const File &file, io::Type default_type) const
Define variables corresponding to an Array in a file opened using file.
void write(const std::string &filename) const
void scale(double alpha)
Result: v <- v * alpha. Calls VecScale.
void set(double c)
Result: v[j] <- c for all j.
void regrid(const std::string &filename, io::Default default_value)
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata object containing metadata for the compoment N.
static std::shared_ptr< Forcing > Constant(std::shared_ptr< const Grid > grid, const std::string &short_name, double value)
double albedo(double melt_rate, MaskValue cell_type) const
DEBMSimpleMelt melt(double declination, double distance_factor, double dt, double T_std_deviation, double T, double surface_elevation, double lat, double albedo) const
Changes 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...
double atmosphere_transmissivity(double elevation) const
OrbitalParameters orbital_parameters(double time) const
A dEBM-simple implementation.
array::Scalar m_insolation_driven_melt
total insolation melt during the last time step
const array::Scalar & atmosphere_transmissivity() const
virtual const array::Scalar & mass_flux_impl() const
std::shared_ptr< array::Scalar > m_melt
total melt during the last time step
virtual void update_impl(const Geometry &geometry, double t, double dt)
double snow_accumulation(double T, double P) const
Extracts snow accumulation from mixed (snow and rain) precipitation using a temperature threshold wit...
const array::Scalar & insolation_driven_melt() const
const array::Scalar & surface_albedo() const
array::Scalar m_surface_albedo
albedo field
array::Scalar m_mass_flux
cached surface mass balance rate
std::shared_ptr< array::Scalar > m_runoff
total runoff during the last time step
array::Scalar m_temperature_driven_melt
total temperature melt during the last time step
const array::Scalar & air_temp_sd() const
array::Scalar m_snow_depth
snow depth (reset once a year)
virtual void define_model_state_impl(const File &output) const
The default (empty implementation).
std::shared_ptr< array::Forcing > m_air_temp_sd
standard deviation of the daily variability of the air temperature
virtual void write_model_state_impl(const File &output) const
The default (empty implementation).
double m_Tmax
the temperature above which all precipitation is rain
double m_next_balance_year_start
const array::Scalar & runoff_impl() const
unsigned int m_n_per_year
number of small time steps per year
array::Scalar m_transmissivity
transmissivity field
double compute_next_balance_year_start(double time)
std::shared_ptr< array::Scalar > m_accumulation
total accumulation during the last time step
unsigned int timeseries_length(double dt) const
The number of points for temperature and precipitation time-series.
DEBMSimplePointwise m_model
virtual DiagnosticList diagnostics_impl() const
const array::Scalar & offset_melt() const
const array::Scalar & accumulation_impl() const
const array::Scalar & snow_depth() const
const array::Scalar & temperature_driven_melt() const
virtual MaxTimestep max_timestep_impl(double t) const
const array::Scalar & melt_impl() const
array::Scalar m_offset_melt
total offset_melt during the last timestep
DEBMSimple(std::shared_ptr< const Grid > g, std::shared_ptr< atmosphere::AtmosphereModel > input)
virtual void init_impl(const Geometry &geometry)
double m_Tmin
the temperature below which all precipitation is snow
std::shared_ptr< array::Scalar > m_temperature
const DEBMSimplePointwise & pointwise_model() const
std::shared_ptr< array::Forcing > m_input_albedo
if albedo is given as input field
virtual const array::Scalar & temperature_impl() const
bool m_precip_as_snow
interpret all the precipitation as snow (no rain)
A class implementing a temperature-index (positive degree-day) scheme to compute melt and runoff,...
static std::shared_ptr< array::Scalar > allocate_runoff(std::shared_ptr< const Grid > grid)
std::shared_ptr< atmosphere::AtmosphereModel > m_atmosphere
virtual DiagnosticList diagnostics_impl() const
virtual void write_model_state_impl(const File &output) const
The default (empty implementation).
virtual void define_model_state_impl(const File &output) const
The default (empty implementation).
static std::shared_ptr< array::Scalar > allocate_temperature(std::shared_ptr< const Grid > grid)
const array::Scalar & accumulation() const
Returns accumulation.
static std::shared_ptr< array::Scalar > allocate_accumulation(std::shared_ptr< const Grid > grid)
static std::shared_ptr< array::Scalar > allocate_melt(std::shared_ptr< const Grid > grid)
virtual void init_impl(const Geometry &geometry)
The interface of PISM's surface models.
array::Scalar m_melt_mass
const array::Scalar & model_input()
DEBMSBackroundMelt(const DEBMSimple *m, AmountKind kind)
Report surface backround melt, averaged over the reporting interval.
DEBMSInsolationMelt(const DEBMSimple *m, AmountKind kind)
const array::Scalar & model_input()
array::Scalar m_melt_mass
Report surface insolation melt, averaged over the reporting interval.
DEBMSInsolation(const DEBMSimple *m)
std::shared_ptr< array::Array > compute_impl() const
Report mean top of atmosphere insolation.
array::Scalar m_melt_mass
const array::Scalar & model_input()
DEBMSTemperatureMelt(const DEBMSimple *m, AmountKind kind)
Report surface temperature melt, averaged over the reporting interval.
#define PISM_ERROR_LOCATION
double max(const array::Scalar &input)
Finds maximum over all the values in an array::Scalar object. Ignores ghosts.
@ PISM_READONLY
open an existing file for reading only
bool ice_free_ocean(int M)
double convert(System::Ptr system, double input, const std::string &spec1, const std::string &spec2)
Convert a quantity from unit1 to unit2.
InputOptions process_input_options(MPI_Comm com, Config::ConstPtr config)
std::map< std::string, Diagnostic::Ptr > DiagnosticList
T combine(const T &a, const T &b)
static double S(unsigned n)