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"
36#include "pism/util/Logger.hh"
37#include "pism/util/io/IO_Flags.hh"
47 m_mass_flux(m_grid,
"climatic_mass_balance"),
48 m_snow_depth(m_grid,
"snow_depth"),
49 m_temperature_driven_melt(m_grid,
"debm_temperature_driven_melt_flux"),
50 m_insolation_driven_melt(m_grid,
"debm_insolation_driven_melt_flux"),
51 m_offset_melt(m_grid,
"debm_offset_melt_flux"),
52 m_surface_albedo(m_grid,
"surface_albedo"),
53 m_transmissivity(m_grid,
"atmosphere_transmissivity") {
60 m_Tmax =
m_config->get_number(
"surface.debm_simple.air_temp_all_precip_as_rain");
61 m_Tmin =
m_config->get_number(
"surface.debm_simple.air_temp_all_precip_as_snow");
65 "surface.debm_simple.air_temp_all_precip_as_rain has to exceed "
66 "surface.debm_simple.air_temp_all_precip_as_snow");
72 m_n_per_year =
static_cast<unsigned int>(
m_config->get_number(
"surface.debm_simple.max_evals_per_year"));
74 auto albedo_input =
m_config->get_string(
"surface.debm_simple.albedo_input.file");
75 if (not albedo_input.empty()) {
77 m_log->message(2,
" Surface albedo is read in from %s...", albedo_input.c_str());
81 int buffer_size =
static_cast<int>(
m_config->get_number(
"input.forcing.buffer_size"));
82 bool periodic =
m_config->get_flag(
"surface.debm_simple.albedo_input.periodic");
98 m_log->message(2,
" Reading standard deviation of near-surface air temperature from '%s'...\n",
101 int buffer_size =
static_cast<int>(
m_config->get_number(
"input.forcing.buffer_size"));
105 bool periodic =
m_config->get_flag(
"surface.debm_simple.std_dev.periodic");
108 buffer_size, periodic,
LINEAR);
110 double temp_std_dev =
m_config->get_number(
"surface.debm_simple.std_dev");
113 m_log->message(2,
" Using constant standard deviation of near-surface air temperature.\n");
117 .long_name(
"standard deviation of near-surface air temperature")
121 .
long_name(
"instantaneous surface mass balance (accumulation/ablation) rate")
122 .
units(
"kg m^-2 s^-1")
123 .
standard_name(
"land_ice_surface_specific_mass_balance_flux");
135 .
long_name(
"temperature-driven melt in dEBM-simple")
140 .
long_name(
"insolation-driven melt in dEBM-simple")
151 .
long_name(
"snow cover depth (set to zero once a year)")
175 "* Initializing dEBM-simple, the diurnal Energy Balance Model (simple version).\n"
176 " Inputs: precipitation and 2m air temperature from an atmosphere model.\n"
177 " Outputs: SMB and ice upper surface temperature.\n");
183 auto default_albedo =
m_config->get_number(
"surface.debm_simple.albedo_max");
201 auto filename =
m_config->get_string(
"surface.debm_simple.albedo_input.file");
202 bool periodic =
m_config->get_flag(
"surface.debm_simple.albedo_input.periodic");
222 double balance_year_start_day =
m_config->get_number(
"surface.mass_balance_year_start_day"),
225 balance_year_start = year_start + (balance_year_start_day - 1.0) * one_day;
227 if (balance_year_start >
time) {
228 return balance_year_start;
270 const double melting_point = 273.15;
281 const double dtseries = dt / N;
282 std::vector<double> ts(N), T(N),
S(N), P(N), Alb(N);
283 std::vector<DEBMSimpleOrbitalParameters> orbital(N);
285 for (
int k = 0;
k < N; ++
k) {
286 ts[
k] = t +
k * dtseries;
326 ice_density =
m_config->get_number(
"constants.ice.density"),
327 sigmalapserate =
m_config->get_number(
"surface.pdd.std_dev.lapse_lat_rate"),
328 sigmabaselat =
m_config->get_number(
"surface.pdd.std_dev.lapse_lat_base");
335 for (
auto p :
m_grid->points()) {
336 const int i = p.i(), j = p.j();
338 double latitude = geometry.
latitude(i, j);
343 if (mask.ice_free_ocean(i, j)) {
345 for (
int k = 0;
k < N; ++
k) {
354 for (
int k = 0;
k < N; ++
k) {
371 if (sigmalapserate != 0.0) {
373 for (
int k = 0;
k < N; ++
k) {
374 S[
k] += sigmalapserate * (latitude - sigmabaselat);
376 (*m_air_temp_sd)(i, j) =
S[0];
379 for (
int k = 0;
k < N; ++
k) {
382 (*m_air_temp_sd)(i, j) =
S[0];
392 ice_thickness = H(i, j),
394 surfelev = surface_altitude(i, j),
397 auto cell_type =
static_cast<MaskValue>(mask.as_int(i, j));
410 for (
int k = 0;
k < N; ++
k) {
412 if (ts[
k] >= next_snow_depth_reset) {
414 while (next_snow_depth_reset <= ts[
k]) {
425 orbital[
k].distance_factor,
435 melt_info.total_melt,
446 ice_thickness += changes.smb;
447 assert(ice_thickness >= 0);
449 snow += changes.snow_depth;
455 Mt += melt_info.temperature_melt;
456 Mi += melt_info.insolation_melt;
457 Mc += melt_info.offset_melt;
478 (*m_accumulation)(i, j) = A * ice_density;
479 (*m_melt)(i, j) = M * ice_density;
480 (*m_runoff)(i, j) = R * ice_density;
487 if (mask.ice_free_ocean(i, j)) {
566namespace diagnostics {
576 "mean top of atmosphere insolation during the period when the sun is above the critical angle Phi")
583 auto result = allocate<array::Scalar>(
"insolation");
585 const auto *latitude =
m_grid->variables().get_2d_scalar(
"latitude");
589 const auto& M =
model->pointwise_model();
591 auto orbital = M.orbital_parameters(ctx->time()->current());
595 for (
auto p :
m_grid->points()) {
596 const int i = p.i(), j = p.j();
598 (*result)(i, j) = M.insolation_diagnostic(orbital.solar_declination,
599 orbital.distance_factor,
616 ?
"debm_insolation_driven_melt_flux"
617 :
"debm_insolation_driven_melt_rate",
623 name =
"debm_insolation_driven_melt_flux",
624 long_name =
"surface insolation melt, averaged over the reporting interval",
625 accumulator_units =
"kg m^-2",
626 internal_units =
"kg m^-2 second^-1",
627 external_units =
"kg m^-2 year^-1";
629 name =
"debm_insolation_driven_melt_rate";
630 accumulator_units =
"kg";
631 internal_units =
"kg second^-1";
632 external_units =
"Gt year^-1";
640 .
units(internal_units)
645 m_vars[0].set_number(
"_FillValue", fill_value);
650 const auto &melt_amount =
model->insolation_driven_melt();
672 ?
"debm_temperature_driven_melt_flux"
673 :
"debm_temperature_driven_melt_rate",
679 name =
"debm_temperature_driven_melt_flux",
680 long_name =
"temperature-driven melt, averaged over the reporting interval",
681 accumulator_units =
"kg m^-2",
682 internal_units =
"kg m^-2 second^-1",
683 external_units =
"kg m^-2 year^-1";
685 name =
"debm_temperature_driven_melt_rate";
686 accumulator_units =
"kg";
687 internal_units =
"kg second^-1";
688 external_units =
"Gt year^-1";
696 .
units(internal_units)
704 const auto &melt_amount =
model->temperature_driven_melt();
726 ?
"debm_offset_melt_flux"
727 :
"debm_offset_melt_rate",
732 std::string name =
"debm_offset_melt_flux",
733 long_name =
"offset melt, averaged over the reporting interval",
734 accumulator_units =
"kg m^-2",
735 internal_units =
"kg m^-2 second^-1",
736 external_units =
"kg m^-2 year^-1";
739 name =
"debm_offset_melt_rate";
740 accumulator_units =
"kg";
741 internal_units =
"kg second^-1";
742 external_units =
"Gt year^-1";
749 .
units(internal_units)
757 const auto &melt_amount =
model->offset_melt();
780 return std::max(1U,
static_cast<unsigned int>(ceil(
m_n_per_year * dt_years)));
784 using namespace diagnostics;
787 {
"debm_insolation_driven_melt_flux",
Diagnostic::Ptr(
new DEBMSInsolationMelt(
this, AMOUNT)) },
788 {
"debm_insolation_driven_melt_rate",
Diagnostic::Ptr(
new DEBMSInsolationMelt(
this, MASS)) },
789 {
"debm_temperature_driven_melt_flux",
Diagnostic::Ptr(
new DEBMSTemperatureMelt(
this, AMOUNT)) },
790 {
"debm_temperature_driven_melt_rate",
Diagnostic::Ptr(
new DEBMSTemperatureMelt(
this, MASS)) },
791 {
"debm_offset_melt_flux",
Diagnostic::Ptr(
new DEBMSBackroundMelt(
this, AMOUNT)) },
792 {
"debm_offset_melt_rate",
Diagnostic::Ptr(
new DEBMSBackroundMelt(
this, MASS)) },
const units::System::Ptr m_sys
unit system used by this component
const Time & time() const
std::shared_ptr< const Config > m_config
configuration database used by this component
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)
std::shared_ptr< const Logger > m_log
logger (for easy access)
array::Scalar m_accumulator
A template derived from Diagnostic, adding a "Model".
std::vector< VariableMetadata > m_vars
metadata corresponding to NetCDF variables
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::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 add(double alpha, const Array2D< T > &x)
void read(const std::string &filename, unsigned int time)
void write(const OutputFile &file) 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)
VariableMetadata & metadata(unsigned int N=0)
Returns a reference to the VariableMetadata 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
double atmosphere_transmissivity(double elevation) const
DEBMSimpleOrbitalParameters orbital_parameters(double time) const
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...
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)
std::shared_ptr< array::Forcing > m_air_temp_sd
standard deviation of the daily variability of the air temperature
virtual DiagnosticList spatial_diagnostics_impl() const
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
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 void write_state_impl(const OutputFile &output) const
The default (empty implementation).
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
virtual std::set< VariableMetadata > state_impl() 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
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 write_state_impl(const OutputFile &output) const
The default (empty implementation).
virtual std::set< VariableMetadata > state_impl() const
virtual DiagnosticList spatial_diagnostics_impl() const
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.
std::shared_ptr< array::Array > compute_impl() const
DEBMSInsolation(const DEBMSimple *m)
Report mean top of atmosphere insolation.
array::Scalar m_melt_mass
DEBMSTemperatureMelt(const DEBMSimple *m, AmountKind kind)
const array::Scalar & model_input()
Report surface temperature melt, averaged over the reporting interval.
#define PISM_ERROR_LOCATION
std::set< VariableMetadata > metadata(std::initializer_list< const Array * > vecs)
@ 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.
std::map< std::string, Diagnostic::Ptr > DiagnosticList
T combine(const T &a, const T &b)
InputOptions process_input_options(MPI_Comm com, std::shared_ptr< const Config > config)
static double S(unsigned n)