19#include "pism/hydrology/Hydrology.hh"
20#include "pism/util/error_handling.hh"
21#include "pism/util/io/File.hh"
22#include "pism/util/array/CellType.hh"
23#include "pism/geometry/Geometry.hh"
24#include "pism/util/io/IO_Flags.hh"
29namespace diagnostics {
41 .
long_name(
"rate of change of the total mass of subglacial water")
42 .
units(
"kg second^-1")
44 m_vars[0][
"cell_methods"] =
"time: mean";
47 m_vars[0][
"comment"] =
"positive flux corresponds to water gain";
52 return model->mass_change();
68 .
long_name(
"water input rate from the ice surface into the subglacial water system")
71 m_vars[0][
"cell_methods"] =
"time: mean";
73 m_vars[0][
"comment"] =
"positive flux corresponds to water gain";
78 return model->surface_input_rate();
90 m_vars = { {
m_sys,
"tendency_of_subglacial_water_mass_due_to_input", *
m_grid } };
92 .
long_name(
"subglacial water flux due to input")
93 .
units(
"kg second^-1")
95 m_vars[0][
"cell_methods"] =
"time: mean";
97 m_vars[0][
"comment"] =
"positive flux corresponds to water gain";
102 return model->mass_change_due_to_input();
118 .
long_name(
"magnitude of the subglacial water flux")
119 .
units(
"m^2 second^-1")
121 m_vars[0][
"cell_methods"] =
"time: mean";
125 .
long_name(
"magnitude of the subglacial water flux")
151 m_vars = { {
m_sys,
"tendency_of_subglacial_water_mass_at_grounded_margins", *
m_grid } };
153 .
long_name(
"subglacial water flux at grounded ice margins")
154 .
units(
"kg second^-1")
156 m_vars[0][
"cell_methods"] =
"time: mean";
158 m_vars[0][
"comment"] =
"positive flux corresponds to water gain";
163 return model->mass_change_at_grounded_margin();
176 m_vars = { {
m_sys,
"tendency_of_subglacial_water_mass_at_grounding_line", *
m_grid } };
178 .
long_name(
"subglacial water flux at grounding lines")
179 .
units(
"kg second^-1")
181 m_vars[0][
"cell_methods"] =
"time: mean";
184 m_vars[0][
"comment"] =
"positive flux corresponds to water gain";
189 return model->mass_change_at_grounding_line();
202 m_vars = { {
m_sys,
"tendency_of_subglacial_water_mass_due_to_conservation_error", *
m_grid } };
205 "subglacial water flux due to conservation error (mass added to preserve non-negativity)")
206 .
units(
"kg second^-1")
208 m_vars[0][
"cell_methods"] =
"time: mean";
210 m_vars[0][
"comment"] =
"positive flux corresponds to water gain";
215 return model->mass_change_due_to_conservation_error();
228 m_vars = { {
m_sys,
"tendency_of_subglacial_water_mass_at_domain_boundary", *
m_grid } };
230 .
long_name(
"subglacial water flux at domain boundary (in regional model configurations)")
231 .
units(
"kg second^-1")
233 m_vars[0][
"cell_methods"] =
"time: mean";
235 m_vars[0][
"comment"] =
"positive flux corresponds to water gain";
240 return model->mass_change_at_domain_boundary();
253 m_vars = { {
m_sys,
"tendency_of_subglacial_water_mass_due_to_flow", *
m_grid } };
255 .
long_name(
"rate of change subglacial water mass due to lateral flow")
256 .
units(
"kg second^-1")
258 m_vars[0][
"cell_methods"] =
"time: mean";
260 m_vars[0][
"comment"] =
"positive flux corresponds to water gain";
265 return model->mass_change_due_to_lateral_flow();
281 m_Q(m_grid,
"water_flux"),
282 m_Wtill(m_grid,
"tillwat"),
284 m_Pover(m_grid,
"overburden_pressure"),
285 m_surface_input_rate(m_grid,
"water_input_rate_from_surface"),
286 m_basal_melt_rate(m_grid,
"water_input_rate_due_to_basal_melt"),
287 m_flow_change_incremental(m_grid,
"water_thickness_change_due_to_flow"),
288 m_conservation_error_change(m_grid,
"conservation_error_change"),
289 m_grounded_margin_change(m_grid,
"grounded_margin_change"),
290 m_grounding_line_change(m_grid,
"grounding_line_change"),
291 m_input_change(m_grid,
"water_mass_change_due_to_input"),
292 m_no_model_mask_change(m_grid,
"no_model_mask_change"),
293 m_total_change(m_grid,
"water_mass_change"),
294 m_flow_change(m_grid,
"water_mass_change_due_to_flow") {
297 .
long_name(
"hydrology model workspace for water input rate from the ice surface")
301 .
long_name(
"hydrology model workspace for water input rate due to basal melt")
306 .
long_name(
"effective thickness of subglacial water stored in till")
315 .
long_name(
"thickness of transportable subglacial water layer")
320 .
long_name(
"advective subglacial water flux")
330 "change in water mass over one time step due to the input (basal melt and surface drainage)")
334 .
long_name(
"change in water mass due to lateral flow (over one time step)")
338 .
long_name(
"changes in subglacial water thickness at the grounded margin")
342 .
long_name(
"changes in subglacial water thickness at the grounding line")
347 "changes in subglacial water thickness at the edge of the modeling domain (regional models)")
352 "changes in subglacial water thickness required to preserve non-negativity or keep water thickness within bounds")
381 double tillwat_default =
m_config->get_number(
"bootstrapping.defaults.tillwat");
415 for (
auto p :
m_grid->points()) {
416 const int i = p.i(), j = p.j();
424 for (
auto p :
m_grid->points()) {
425 const int i = p.i(), j = p.j();
432 double water_density =
m_config->get_number(
"constants.fresh_water.density"),
433 kg_per_m = water_density *
m_grid->cell_area();
436 for (
auto p :
m_grid->points()) {
437 const int i = p.i(), j = p.j();
445 using namespace diagnostics;
449 {
"subglacial_water_input_rate",
Diagnostic::Ptr(
new TotalInputRate(
this)) },
450 {
"tendency_of_subglacial_water_mass_due_to_input",
Diagnostic::Ptr(
new WaterInputFlux(
this)) },
451 {
"tendency_of_subglacial_water_mass_due_to_flow",
453 {
"tendency_of_subglacial_water_mass_due_to_conservation_error",
455 {
"tendency_of_subglacial_water_mass",
Diagnostic::Ptr(
new TendencyOfWaterMass(
this)) },
456 {
"tendency_of_subglacial_water_mass_at_grounded_margins",
458 {
"tendency_of_subglacial_water_mass_at_grounding_line",
460 {
"tendency_of_subglacial_water_mass_at_domain_boundary",
462 {
"subglacial_water_flux_mag",
Diagnostic::Ptr(
new SubglacialWaterFlux(
this)) },
485 const double ice_density =
m_config->get_number(
"constants.ice.density"),
486 standard_gravity =
m_config->get_number(
"constants.standard_gravity");
490 for (
auto p :
m_grid->points()) {
491 const int i = p.i(), j = p.j();
493 result(i, j) = ice_density * standard_gravity * ice_thickness(i, j);
556 std::string name = W.
metadata()[
"long_name"];
558 auto grid = W.
grid();
563 for (
auto p : grid->points()) {
564 const int i = p.i(), j = p.j();
568 "Hydrology: negative %s of %.6f m at (i, j) = (%d, %d)",
569 name.c_str(), W(i, j), i, j);
572 if (W(i,j) > W_max) {
574 "Hydrology: %s of %.6f m exceeds the maximum value %.6f at (i, j) = (%d, %d)",
575 name.c_str(), W(i, j), W_max, i, j);
606 water_density =
m_config->get_number(
"constants.fresh_water.density");
608 for (
auto p :
m_grid->points()) {
609 const int i = p.i(), j = p.j();
611 if (mask.
icy(i, j)) {
612 result(i,j) = (*surface_input_rate)(i, j) / water_density;
635 ice_density =
m_config->get_number(
"constants.ice.density"),
636 water_density =
m_config->get_number(
"constants.fresh_water.density"),
637 C = ice_density / water_density;
639 for (
auto p :
m_grid->points()) {
640 const int i = p.i(), j = p.j();
642 if (mask.
icy(i, j)) {
643 result(i,j) = C * basal_melt_rate(i, j);
672 double max_thickness,
673 double ocean_water_thickness,
680 bool include_floating =
m_config->get_flag(
"hydrology.routing.include_floating_ice");
683 &grounded_margin_change, &grounding_line_change, &conservation_error_change,
684 &no_model_mask_change};
687 fresh_water_density =
m_config->get_number(
"constants.fresh_water.density"),
688 kg_per_m =
m_grid->cell_area() * fresh_water_density;
690 for (
auto p :
m_grid->points()) {
691 const int i = p.i(), j = p.j();
693 if (water_thickness(i, j) < 0.0) {
694 conservation_error_change(i, j) += -water_thickness(i, j) * kg_per_m;
695 water_thickness(i, j) = 0.0;
698 if (max_thickness > 0.0 and water_thickness(i, j) > max_thickness) {
699 double excess = water_thickness(i, j) - max_thickness;
701 conservation_error_change(i, j) += -excess * kg_per_m;
702 water_thickness(i, j) = max_thickness;
706 double grounded_ice_free_max_thickness = 0.0;
707 double excess = water_thickness(i, j) - grounded_ice_free_max_thickness;
708 grounded_margin_change(i, j) += -excess * kg_per_m;
709 water_thickness(i, j) = grounded_ice_free_max_thickness;
725 (not include_floating and cell_type.
ocean(i, j))) {
727 double mismatch = water_thickness(i, j) - ocean_water_thickness;
729 grounding_line_change(i, j) += -mismatch * kg_per_m;
730 water_thickness(i, j) = ocean_water_thickness;
734 if (no_model_mask !=
nullptr) {
739 for (
auto p :
m_grid->points()) {
740 const int i = p.i(), j = p.j();
743 no_model_mask_change(i, j) += -water_thickness(i, j) * kg_per_m;
745 water_thickness(i, j) = 0.0;
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)
A class defining a common interface for most PISM sub-models.
array::Scalar m_accumulator
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::CellType2 cell_type
array::Scalar2 ice_thickness
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
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
std::shared_ptr< const Grid > grid() const
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.
bool ice_free_ocean(int i, int j) const
bool ocean(int i, int j) const
bool ice_free_land(int i, int j) const
bool icy(int i, int j) const
"Cell type" mask. Adds convenience methods to array::Scalar.
array::Scalar m_flow_change
const array::Scalar & till_water_thickness() const
Return the effective thickness of the water stored in till.
void restart(const File &input_file, int record)
Hydrology(std::shared_ptr< const Grid > g)
virtual void bootstrap_impl(const File &input_file, const array::Scalar &ice_thickness)
virtual std::map< std::string, Diagnostic::Ptr > spatial_diagnostics_impl() const
array::Scalar m_surface_input_rate
array::Scalar m_total_change
void bootstrap(const File &input_file, const array::Scalar &ice_thickness)
array::Scalar m_grounding_line_change
const array::Scalar & mass_change_at_domain_boundary() const
virtual std::set< VariableMetadata > state_impl() const
const array::Scalar & surface_input_rate() const
virtual void initialization_message() const =0
void enforce_bounds(const array::CellType &cell_type, const array::Scalar *no_model_mask, double max_thickness, double ocean_water_thickness, array::Scalar &water_thickness, array::Scalar &grounded_margin_change, array::Scalar &grounding_line_change, array::Scalar &conservation_error_change, array::Scalar &no_model_mask_change)
Correct the new water thickness based on boundary requirements.
const array::Scalar & subglacial_water_thickness() const
Return the effective thickness of the transportable basal water layer.
array::Scalar m_basal_melt_rate
const array::Scalar & mass_change_due_to_lateral_flow() const
virtual void init_impl(const array::Scalar &W_till, const array::Scalar &W, const array::Scalar &P)
const array::Scalar & mass_change_due_to_conservation_error() const
array::Scalar1 m_W
effective thickness of transportable basal water
void compute_overburden_pressure(const array::Scalar &ice_thickness, array::Scalar &result) const
Update the overburden pressure from ice thickness.
const array::Scalar & mass_change_at_grounded_margin() const
virtual void restart_impl(const File &input_file, int record)
array::Scalar m_input_change
void update(double t, double dt, const Inputs &inputs)
array::Scalar m_Wtill
effective thickness of basal water stored in till
const array::Scalar & overburden_pressure() const
virtual void update_impl(double t, double dt, const Inputs &inputs)=0
const array::Scalar & mass_change_due_to_input() const
array::Scalar m_Pover
overburden pressure
const array::Vector & flux() const
void compute_basal_melt_rate(const array::CellType &mask, const array::Scalar &basal_melt_rate, array::Scalar &result)
array::Scalar m_grounded_margin_change
const array::Scalar & mass_change_at_grounding_line() const
virtual void write_state_impl(const OutputFile &output) const
The default (empty implementation).
array::Scalar m_no_model_mask_change
void compute_surface_input_rate(const array::CellType &mask, const array::Scalar *surface_input_rate, array::Scalar &result)
void init(const array::Scalar &W_till, const array::Scalar &W, const array::Scalar &P)
const array::Scalar & mass_change() const
array::Scalar m_conservation_error_change
The PISM subglacial hydrology model interface.
const array::Scalar & model_input()
ConservationErrorFlux(const Hydrology *m)
Report subglacial water conservation error flux (mass added to preserve non-negativity).
const array::Scalar & model_input()
DomainBoundaryFlux(const Hydrology *m)
Report subglacial water flux at domain boundary (in regional model configurations).
const array::Scalar & model_input()
GroundedMarginFlux(const Hydrology *m)
Report water flux at the grounded margin.
const array::Scalar & model_input()
GroundingLineFlux(const Hydrology *m)
Report subglacial water flux at grounding lines.
array::Scalar m_flux_magnitude
SubglacialWaterFlux(const Hydrology *m)
void update_impl(double dt)
Report advective subglacial water flux.
const array::Scalar & model_input()
TendencyOfWaterMassDueToFlow(const Hydrology *m)
Report water flux at the grounded margin.
TendencyOfWaterMass(const Hydrology *m)
const array::Scalar & model_input()
#define PISM_ERROR_LOCATION
std::set< VariableMetadata > metadata(std::initializer_list< const Array * > vecs)
void check_bounds(const array::Scalar &W, double W_max)
std::map< std::string, Diagnostic::Ptr > DiagnosticList