22#include "pism/geometry/Geometry.hh"
23#include "pism/hydrology/Distributed.hh"
24#include "pism/util/array/CellType.hh"
25#include "pism/util/error_handling.hh"
26#include "pism/util/io/File.hh"
27#include "pism/util/pism_utilities.hh"
28#include "pism/util/Logger.hh"
29#include "pism/util/io/IO_Flags.hh"
35 :
Routing(
g), m_P(m_grid,
"bwp"), m_Pnew(m_grid,
"Pnew_internal") {
39 .
long_name(
"pressure of transportable water in subglacial layer")
44 .
long_name(
"new transportable subglacial water pressure during update")
51 "* Initializing the distributed, linked-cavities subglacial hydrology model...\n");
65 double bwp_default =
m_config->get_number(
"bootstrapping.defaults.bwp");
70 bool init_P_from_steady =
m_config->get_flag(
"hydrology.distributed.init_p_from_steady");
72 if (init_P_from_steady) {
73 m_log->message(2,
" initializing P from P(W) formula which applies in steady state\n");
80 std::string filename =
m_config->
get_string(
"hydrology.distributed.sliding_speed_file");
82 if (filename.empty()) {
84 "hydrology.distributed.sliding_speed_file is not set");
112 std::map<std::string, TSDiagnostic::Ptr> result = {
130 bool enforce_upper) {
136 for (
auto p :
m_grid->points()) {
137 const int i = p.i(), j = p.j();
141 "negative subglacial water pressure\n"
142 "P(%d, %d) = %.6f Pa",
147 P(i,j) = std::min(P(i,j), P_o(i,j));
148 }
else if (P(i,j) > P_o(i,j) + 0.001) {
150 "subglacial water pressure P = %.16f Pa exceeds\n"
151 "overburden pressure Po = %.16f Pa at (i,j)=(%d,%d)",
152 P(i, j), P_o(i, j), i, j);
178 ice_softness =
m_config->get_number(
"flow_law.isothermal_Glen.ice_softness"),
179 creep_closure_coefficient =
m_config->get_number(
"hydrology.creep_closure_coefficient"),
180 cavitation_opening_coefficient =
m_config->get_number(
"hydrology.cavitation_opening_coefficient"),
181 Glen_exponent =
m_config->get_number(
"stress_balance.sia.Glen_exponent"),
182 Wr =
m_config->get_number(
"hydrology.roughness_scale");
184 const double CC = cavitation_opening_coefficient / (creep_closure_coefficient * ice_softness);
188 for (
auto p :
m_grid->points()) {
189 const int i = p.i(), j = p.j();
191 double sb = pow(CC * sliding_speed(i, j), 1.0 / Glen_exponent);
192 if (W(i, j) == 0.0) {
200 result(i, j) = P_overburden(i, j);
203 double Wratio = std::max(0.0,
Wr - W(i, j)) / W(i, j);
206 result(i, j) = std::max(0.0, P_overburden(i, j) - sb * pow(Wratio, 1.0 / Glen_exponent));
212 return 2.0 * phi0 * dt_diff_w;
231 n =
m_config->get_number(
"stress_balance.sia.Glen_exponent"),
232 A =
m_config->get_number(
"flow_law.isothermal_Glen.ice_softness"),
233 c1 =
m_config->get_number(
"hydrology.cavitation_opening_coefficient"),
234 c2 =
m_config->get_number(
"hydrology.creep_closure_coefficient"),
235 Wr =
m_config->get_number(
"hydrology.roughness_scale"),
236 phi0 =
m_config->get_number(
"hydrology.regularizing_porosity");
240 CC = (
m_rg * dt) / phi0,
246 &cell_type, &P_overburden, &P_new};
248 for (
auto p :
m_grid->points()) {
249 const int i = p.i(), j = p.j();
251 auto w = W.
star(i, j);
252 double P_o = P_overburden(i, j);
256 }
else if (cell_type.
ocean(i, j)) {
258 }
else if (w.c <= 0.0) {
261 auto q = Q.
star(i, j);
262 auto k =
K.star(i, j);
263 auto ws = Ws.
star(i, j);
266 Open =
c1 * sliding_speed(i, j) * std::max(0.0,
Wr - w.c),
267 Close =
c2 * A * pow(P_o - P(i, j),
n) * w.c;
270 const double divadflux = (q.e - q.w) /
m_dx + (q.n - q.s) /
m_dy;
272 De =
m_rg *
k.e * ws.e,
273 Dw =
m_rg *
k.w * ws.w,
274 Dn =
m_rg *
k.n * ws.n,
275 Ds =
m_rg *
k.s * ws.s;
277 double diffW = (wux * (De * (w.e - w.c) - Dw * (w.c - w.w)) +
278 wuy * (Dn * (w.n - w.c) - Ds * (w.c - w.s)));
280 double divflux = -divadflux + diffW;
283 double Wtill_change = Wtill_new(i, j) - Wtill(i, j);
285 double ZZ = Close - Open + total_input - Wtill_change / dt;
287 P_new(i, j) = P(i, j) + CC * (divflux + ZZ);
290 P_new(i, j) =
clip(P_new(i, j), 0.0, P_o);
312 dt_max =
m_config->get_number(
"hydrology.maximum_time_step",
"seconds"),
313 phi0 =
m_config->get_number(
"hydrology.regularizing_porosity"),
314 tillwat_max =
m_config->get_number(
"hydrology.tillwat_max");
322 unsigned int step_counter = 0;
323 for (; ht < t_final; ht += hdt) {
327 double huge_number = 1e6;
335 bool enforce_upper = (step_counter == 1);
366 hdt = std::min(t_final - ht, dt_max);
367 hdt = std::min(hdt, dt_cfl);
368 hdt = std::min(hdt, dt_diff_w);
369 hdt = std::min(hdt, dt_diff_p);
372 m_log->message(3,
" hydrology step %05d, dt = %f s\n", step_counter, hdt);
429 m_config->get_flag(
"hydrology.routing.include_floating_ice"),
434 " took %d hydrology sub-steps with average dt = %.6f years (%.6f s)\n",
const units::System::Ptr m_sys
unit system used by this component
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)
High-level PISM I/O class.
array::CellType2 cell_type
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)
stencils::Star< T > star(int i, int j) const
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)
void add(double alpha, const Array &x)
Result: v <- v + alpha * x. Calls VecAXPY.
void update_ghosts()
Updates ghost points.
VariableMetadata & metadata(unsigned int N=0)
Returns a reference to the VariableMetadata object containing metadata for the compoment N.
bool ocean(int i, int j) const
bool ice_free_land(int i, int j) const
"Cell type" mask. Adds convenience methods to array::Scalar.
stencils::Star< double > star(int i, int j) const
Returns the values at interfaces of the cell i,j using the staggered grid.
virtual void bootstrap_impl(const File &input_file, const array::Scalar &ice_thickness)
std::map< std::string, TSDiagnostic::Ptr > scalar_diagnostics_impl() const
void update_P(double dt, const array::CellType &cell_type, const array::Scalar &sliding_speed, const array::Scalar &surface_input_rate, const array::Scalar &basal_melt_rate, const array::Scalar &P_overburden, const array::Scalar &Wtill, const array::Scalar &Wtill_new, const array::Scalar &P, const array::Scalar1 &W, const array::Staggered1 &Ws, const array::Staggered1 &K, const array::Staggered1 &Q, array::Scalar &P_new) const
virtual std::set< VariableMetadata > state_impl() const
void write_state_impl(const OutputFile &output) const
The default (empty implementation).
virtual void init_impl(const array::Scalar &W_till, const array::Scalar &W, const array::Scalar &P)
void P_from_W_steady(const array::Scalar &W, const array::Scalar &P_overburden, const array::Scalar &sliding_speed, array::Scalar &result)
Compute functional relationship P(W) which applies only in steady state.
const array::Scalar & subglacial_water_pressure() const
Copies the P state variable which is the modeled water pressure.
void initialization_message() const
Distributed(std::shared_ptr< const Grid > g)
void update_impl(double t, double dt, const Inputs &inputs)
Update the model state variables W,P by running the subglacial hydrology model.
virtual double max_timestep_P_diff(double phi0, double dt_diff_w) const
void check_P_bounds(array::Scalar &P, const array::Scalar &P_o, bool enforce_upper)
virtual void restart_impl(const File &input_file, int record)
array::Scalar m_surface_input_rate
array::Scalar m_grounding_line_change
const array::Scalar & surface_input_rate() const
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.
array::Scalar m_basal_melt_rate
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.
array::Scalar m_Wtill
effective thickness of basal water stored in till
array::Scalar m_Pover
overburden pressure
array::Scalar m_grounded_margin_change
array::Scalar m_no_model_mask_change
array::Scalar m_conservation_error_change
virtual void init_impl(const array::Scalar &W_till, const array::Scalar &W, const array::Scalar &P)
array::Staggered1 m_Qstag_average
virtual void write_state_impl(const OutputFile &output) const
The default (empty implementation).
array::Staggered1 m_Wstag
double max_timestep_W_diff(double KW_max) const
virtual void bootstrap_impl(const File &input_file, const array::Scalar &ice_thickness)
double max_timestep_W_cfl() const
void compute_conductivity(const array::Staggered &W, const array::Scalar &P, const array::Scalar &bed, array::Staggered &result, double &maxKW) const
Compute the nonlinear conductivity at the center of cell edges.
array::Staggered1 m_Kstag
void advective_fluxes(const array::Staggered &V, const array::Scalar &W, array::Staggered &result) const
Compute Q = V W at edge-centers (staggered grid) by first-order upwinding.
void update_W(double dt, const array::Scalar &surface_input_rate, const array::Scalar &basal_melt_rate, const array::Scalar1 &W, const array::Staggered1 &Wstag, const array::Scalar &Wtill, const array::Scalar &Wtill_new, const array::Staggered1 &K, const array::Staggered1 &Q, array::Scalar &W_new)
The computation of Wnew, called by update().
void water_thickness_staggered(const array::Scalar &W, const array::CellType1 &mask, array::Staggered &result)
Average the regular grid water thickness to values at the center of cell edges.
void compute_velocity(const array::Staggered &W, const array::Scalar &P, const array::Scalar &bed, const array::Staggered &K, const array::Scalar1 *no_model_mask, array::Staggered &result) const
Get the advection velocity V at the center of cell edges.
array::Staggered1 m_Qstag
void update_Wtill(double dt, const array::Scalar &Wtill, const array::Scalar &surface_input_rate, const array::Scalar &basal_melt_rate, array::Scalar &Wtill_new)
The computation of Wtillnew, called by update().
virtual void restart_impl(const File &input_file, int record)
array::Scalar1 m_bottom_surface
virtual std::set< VariableMetadata > state_impl() const
A subglacial hydrology model which assumes water pressure equals overburden pressure.
#define PISM_ERROR_LOCATION
std::set< VariableMetadata > metadata(std::initializer_list< const Array * > vecs)
static double K(double psi_x, double psi_y, double speed, double epsilon)
void check_bounds(const array::Scalar &W, double W_max)
double convert(System::Ptr system, double input, const std::string &spec1, const std::string &spec2)
Convert a quantity from unit1 to unit2.
void ice_bottom_surface(const Geometry &geometry, array::Scalar &result)
T combine(const T &a, const T &b)