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"
28 namespace diagnostics {
38 m_vars = { {
m_sys,
"tendency_of_subglacial_water_mass" } };
40 .long_name(
"rate of change of the total mass of subglacial water")
42 .output_units(
"Gt year-1");
43 m_vars[0][
"cell_methods"] =
"time: mean";
46 m_vars[0][
"comment"] =
"positive flux corresponds to water gain";
51 return model->mass_change();
65 m_vars = { {
m_sys,
"subglacial_water_input_rate_from_surface" } };
67 .long_name(
"water input rate from the ice surface into the subglacial water system")
69 .output_units(
"m year-1");
70 m_vars[0][
"cell_methods"] =
"time: mean";
72 m_vars[0][
"comment"] =
"positive flux corresponds to water gain";
77 return model->surface_input_rate();
89 m_vars = { {
m_sys,
"tendency_of_subglacial_water_mass_due_to_input" } };
91 .long_name(
"subglacial water flux due to input")
93 .output_units(
"Gt year-1");
94 m_vars[0][
"cell_methods"] =
"time: mean";
96 m_vars[0][
"comment"] =
"positive flux corresponds to water gain";
101 return model->mass_change_due_to_input();
117 .long_name(
"magnitude of the subglacial water flux")
118 .units(
"m2 second-1")
119 .output_units(
"m2 year-1");
120 m_vars[0][
"cell_methods"] =
"time: mean";
124 .
long_name(
"magnitude of the subglacial water flux")
150 m_vars = { {
m_sys,
"tendency_of_subglacial_water_mass_at_grounded_margins" } };
152 .long_name(
"subglacial water flux at grounded ice margins")
153 .units(
"kg second-1")
154 .output_units(
"Gt year-1");
155 m_vars[0][
"cell_methods"] =
"time: mean";
157 m_vars[0][
"comment"] =
"positive flux corresponds to water gain";
162 return model->mass_change_at_grounded_margin();
175 m_vars = { {
m_sys,
"tendency_of_subglacial_water_mass_at_grounding_line" } };
177 .long_name(
"subglacial water flux at grounding lines")
178 .units(
"kg second-1")
179 .output_units(
"Gt year-1");
180 m_vars[0][
"cell_methods"] =
"time: mean";
183 m_vars[0][
"comment"] =
"positive flux corresponds to water gain";
188 return model->mass_change_at_grounding_line();
201 m_vars = { {
m_sys,
"tendency_of_subglacial_water_mass_due_to_conservation_error" } };
204 "subglacial water flux due to conservation error (mass added to preserve non-negativity)")
205 .units(
"kg second-1")
206 .output_units(
"Gt year-1");
207 m_vars[0][
"cell_methods"] =
"time: mean";
209 m_vars[0][
"comment"] =
"positive flux corresponds to water gain";
214 return model->mass_change_due_to_conservation_error();
227 m_vars = { {
m_sys,
"tendency_of_subglacial_water_mass_at_domain_boundary" } };
229 .long_name(
"subglacial water flux at domain boundary (in regional model configurations)")
230 .units(
"kg second-1")
231 .output_units(
"Gt year-1");
232 m_vars[0][
"cell_methods"] =
"time: mean";
234 m_vars[0][
"comment"] =
"positive flux corresponds to water gain";
239 return model->mass_change_at_domain_boundary();
252 m_vars = { {
m_sys,
"tendency_of_subglacial_water_mass_due_to_flow" } };
254 .long_name(
"rate of change subglacial water mass due to lateral flow")
255 .units(
"kg second-1")
256 .output_units(
"Gt year-1");
257 m_vars[0][
"cell_methods"] =
"time: mean";
259 m_vars[0][
"comment"] =
"positive flux corresponds to water gain";
264 return model->mass_change_due_to_lateral_flow();
280 m_Q(m_grid,
"water_flux"),
281 m_Wtill(m_grid,
"tillwat"),
283 m_Pover(m_grid,
"overburden_pressure"),
284 m_surface_input_rate(m_grid,
"water_input_rate_from_surface"),
285 m_basal_melt_rate(m_grid,
"water_input_rate_due_to_basal_melt"),
286 m_flow_change_incremental(m_grid,
"water_thickness_change_due_to_flow"),
287 m_conservation_error_change(m_grid,
"conservation_error_change"),
288 m_grounded_margin_change(m_grid,
"grounded_margin_change"),
289 m_grounding_line_change(m_grid,
"grounding_line_change"),
290 m_input_change(m_grid,
"water_mass_change_due_to_input"),
291 m_no_model_mask_change(m_grid,
"no_model_mask_change"),
292 m_total_change(m_grid,
"water_mass_change"),
293 m_flow_change(m_grid,
"water_mass_change_due_to_flow") {
296 .
long_name(
"hydrology model workspace for water input rate from the ice surface")
300 .
long_name(
"hydrology model workspace for water input rate due to basal melt")
305 .
long_name(
"effective thickness of subglacial water stored in till")
314 .
long_name(
"thickness of transportable subglacial water layer")
319 .
long_name(
"advective subglacial water flux")
329 "change in water mass over one time step due to the input (basal melt and surface drainage)")
333 .
long_name(
"change in water mass due to lateral flow (over one time step)")
337 .
long_name(
"changes in subglacial water thickness at the grounded margin")
341 .
long_name(
"changes in subglacial water thickness at the grounding line")
346 "changes in subglacial water thickness at the edge of the modeling domain (regional models)")
351 "changes in subglacial water thickness required to preserve non-negativity or keep water thickness within bounds")
380 double tillwat_default =
m_config->get_number(
"bootstrapping.defaults.tillwat");
414 for (
auto p =
m_grid->points(); p; p.next()) {
415 const int i = p.i(), j = p.j();
423 for (
auto p =
m_grid->points(); p; p.next()) {
424 const int i = p.i(), j = p.j();
431 double water_density =
m_config->get_number(
"constants.fresh_water.density"),
432 kg_per_m = water_density *
m_grid->cell_area();
435 for (
auto p =
m_grid->points(); p; p.next()) {
436 const int i = p.i(), j = p.j();
448 {
"subglacial_water_input_rate",
Diagnostic::Ptr(
new TotalInputRate(
this)) },
449 {
"tendency_of_subglacial_water_mass_due_to_input",
Diagnostic::Ptr(
new WaterInputFlux(
this)) },
450 {
"tendency_of_subglacial_water_mass_due_to_flow",
452 {
"tendency_of_subglacial_water_mass_due_to_conservation_error",
454 {
"tendency_of_subglacial_water_mass",
Diagnostic::Ptr(
new TendencyOfWaterMass(
this)) },
455 {
"tendency_of_subglacial_water_mass_at_grounded_margins",
457 {
"tendency_of_subglacial_water_mass_at_grounding_line",
459 {
"tendency_of_subglacial_water_mass_at_domain_boundary",
461 {
"subglacial_water_flux_mag",
Diagnostic::Ptr(
new SubglacialWaterFlux(
this)) },
484 const double ice_density =
m_config->get_number(
"constants.ice.density"),
485 standard_gravity =
m_config->get_number(
"constants.standard_gravity");
489 for (
auto p =
m_grid->points(); p; p.next()) {
490 const int i = p.i(), j = p.j();
492 result(i, j) = ice_density * standard_gravity * ice_thickness(i, j);
555 std::string name = W.
metadata()[
"long_name"];
562 for (
auto p =
grid->points(); p; p.next()) {
563 const int i = p.i(), j = p.j();
567 "Hydrology: negative %s of %.6f m at (i, j) = (%d, %d)",
568 name.c_str(), W(i, j), i, j);
571 if (W(i,j) > W_max) {
573 "Hydrology: %s of %.6f m exceeds the maximum value %.6f at (i, j) = (%d, %d)",
574 name.c_str(), W(i, j), W_max, i, j);
605 water_density =
m_config->get_number(
"constants.fresh_water.density");
607 for (
auto p =
m_grid->points(); p; p.next()) {
608 const int i = p.i(), j = p.j();
610 if (mask.
icy(i, j)) {
611 result(i,j) = (*surface_input_rate)(i, j) / water_density;
634 ice_density =
m_config->get_number(
"constants.ice.density"),
635 water_density =
m_config->get_number(
"constants.fresh_water.density"),
636 C = ice_density / water_density;
638 for (
auto p =
m_grid->points(); p; p.next()) {
639 const int i = p.i(), j = p.j();
641 if (mask.
icy(i, j)) {
642 result(i,j) =
C * basal_melt_rate(i, j);
671 double max_thickness,
672 double ocean_water_thickness,
679 bool include_floating =
m_config->get_flag(
"hydrology.routing.include_floating_ice");
682 &grounded_margin_change, &grounding_line_change, &conservation_error_change,
683 &no_model_mask_change};
686 fresh_water_density =
m_config->get_number(
"constants.fresh_water.density"),
687 kg_per_m =
m_grid->cell_area() * fresh_water_density;
689 for (
auto p =
m_grid->points(); p; p.next()) {
690 const int i = p.i(), j = p.j();
692 if (water_thickness(i, j) < 0.0) {
693 conservation_error_change(i, j) += -water_thickness(i, j) * kg_per_m;
694 water_thickness(i, j) = 0.0;
697 if (max_thickness > 0.0 and water_thickness(i, j) > max_thickness) {
698 double excess = water_thickness(i, j) - max_thickness;
700 conservation_error_change(i, j) += -excess * kg_per_m;
701 water_thickness(i, j) = max_thickness;
705 double grounded_ice_free_max_thickness = 0.0;
706 double excess = water_thickness(i, j) - grounded_ice_free_max_thickness;
707 grounded_margin_change(i, j) += -excess * kg_per_m;
708 water_thickness(i, j) = grounded_ice_free_max_thickness;
724 (not include_floating and cell_type.
ocean(i, j))) {
726 double mismatch = water_thickness(i, j) - ocean_water_thickness;
728 grounding_line_change(i, j) += -mismatch * kg_per_m;
729 water_thickness(i, j) = ocean_water_thickness;
733 if (no_model_mask !=
nullptr) {
738 for (
auto p =
m_grid->points(); p; p.next()) {
739 const int i = p.i(), j = p.j();
742 no_model_mask_change(i, j) += -water_thickness(i, j) * kg_per_m;
744 water_thickness(i, j) = 0.0;
std::shared_ptr< const Grid > grid() const
const Config::ConstPtr 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)
DiagnosticList diagnostics() const
A class defining a common interface for most PISM sub-models.
array::Scalar m_accumulator
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::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 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
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)
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata 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)
array::Scalar m_surface_input_rate
array::Scalar m_total_change
virtual void define_model_state_impl(const File &output) const
The default (empty implementation).
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
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
virtual std::map< std::string, Diagnostic::Ptr > diagnostics_impl() const
virtual void write_model_state_impl(const File &output) const
The default (empty implementation).
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
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.
ConservationErrorFlux(const Hydrology *m)
const array::Scalar & model_input()
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.
GroundingLineFlux(const Hydrology *m)
const array::Scalar & model_input()
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
void compute_magnitude(const array::Vector &input, array::Scalar &result)
void check_bounds(const array::Scalar &W, double W_max)
std::map< std::string, Diagnostic::Ptr > DiagnosticList