21 #include "pism/hydrology/Routing.hh"
22 #include "pism/util/array/CellType.hh"
24 #include "pism/util/error_handling.hh"
26 #include "pism/util/pism_utilities.hh"
27 #include "pism/util/Vars.hh"
28 #include "pism/geometry/Geometry.hh"
29 #include "pism/util/Profiling.hh"
30 #include "pism/util/Context.hh"
35 namespace diagnostics {
44 m_vars[0].long_name(
"pressure of transportable water in subglacial layer").units(
"Pa");
49 auto result = allocate<array::Scalar>(
"bwp");
51 result->copy_from(
model->subglacial_water_pressure());
68 "pressure of transportable water in subglacial layer as fraction of the overburden pressure")
77 auto result = allocate<array::Scalar>(
"bwprel");
80 &P =
model->subglacial_water_pressure(),
81 &Po =
model->overburden_pressure();
84 for (
auto p =
m_grid->points(); p; p.next()) {
85 const int i = p.i(), j = p.j();
88 (*result)(i,j) = P(i, j) / Po(i,j);
90 (*result)(i,j) = fill_value;
108 .long_name(
"effective pressure of transportable water in subglacial layer"
109 " (overburden pressure minus water pressure)")
116 auto result = allocate<array::Scalar>(
"effbwp");
119 &P =
model->subglacial_water_pressure(),
120 &Po =
model->overburden_pressure();
124 for (
auto p =
m_grid->points(); p; p.next()) {
125 const int i = p.i(), j = p.j();
127 (*result)(i, j) = Po(i, j) - P(i, j);
144 .long_name(
"wall melt into subglacial hydrology layer from (turbulent)"
145 " dissipation of energy in transportable water")
147 .output_units(
"m year-1");
152 auto result = allocate<array::Scalar>(
"wallmelt");
154 const array::Scalar &bed_elevation = *
m_grid->variables().get_2d_scalar(
"bedrock_altitude");
169 m_vars[0].long_name(
"velocity of water in subglacial layer, i-offset").units(
"m s-1");
170 m_vars[1].long_name(
"velocity of water in subglacial layer, j-offset").units(
"m s-1");
174 auto result = allocate<array::Staggered>(
"bwatvel");
176 result->copy_from(
model->velocity_staggered());
193 auto grid = result.
grid();
198 ice_density = config->get_number(
"constants.ice.density"),
199 sea_water_density = config->get_number(
"constants.sea_water.density"),
200 C = ice_density / sea_water_density,
201 rg = (config->get_number(
"constants.fresh_water.density") *
202 config->get_number(
"constants.standard_gravity"));
206 for (
auto p = grid->points(); p; p.next()) {
207 const int i = p.i(), j = p.j();
209 double b =
std::max(bed(i, j), sea_level(i, j) -
C * ice_thickness(i, j));
211 result(i, j) = P(i, j) + rg * (b + W(i, j));
221 m_vars[0].long_name(
"hydraulic potential in the subglacial hydrology system").units(
"Pa");
227 auto result = allocate<array::Scalar>(
"hydraulic_potential");
229 const auto &sea_level = *
m_grid->variables().get_2d_scalar(
"sea_level");
230 const auto &bed_elevation = *
m_grid->variables().get_2d_scalar(
"bedrock_altitude");
231 const auto &ice_thickness = *
m_grid->variables().get_2d_scalar(
"land_ice_thickness");
234 model->subglacial_water_pressure(),
248 m_Qstag(grid,
"advection_flux"),
249 m_Qstag_average(grid,
"cumulative_advection_flux"),
250 m_Vstag(grid,
"water_velocity"),
251 m_Wstag(grid,
"W_staggered"),
252 m_Kstag(grid,
"K_staggered"),
253 m_Wnew(grid,
"W_new"),
254 m_Wtillnew(grid,
"Wtill_new"),
255 m_R(grid,
"potential_workspace"),
258 m_bottom_surface(grid,
"ice_bottom_surface_elevation") {
260 m_rg = (
m_config->get_number(
"constants.fresh_water.density") *
261 m_config->get_number(
"constants.standard_gravity"));
264 .
long_name(
"cell face-centered (staggered) components of advective subglacial water flux")
268 .
long_name(
"average (over time) advection flux on the staggered grid")
273 "cell face-centered (staggered) components of water velocity in subglacial water layer")
278 .
long_name(
"cell face-centered (staggered) values of water layer thickness")
283 .
long_name(
"cell face-centered (staggered) values of nonlinear conductivity");
287 .
long_name(
"work space for modeled subglacial water hydraulic potential")
292 .
long_name(
"new thickness of transportable subglacial water layer during update")
297 .
long_name(
"new thickness of till (subglacial) water layer during update")
302 double alpha =
m_config->get_number(
"hydrology.thickness_power_in_flux");
305 "alpha = %f < 1 which is not allowed", alpha);
308 if (
m_config->get_number(
"hydrology.tillwat_max") < 0.0) {
310 "hydrology::Routing: hydrology.tillwat_max is negative.\n"
311 "This is not allowed.");
318 "* Initializing the routing subglacial hydrology model ...\n");
320 if (
m_config->get_flag(
"hydrology.routing.include_floating_ice")) {
321 m_log->message(2,
" ... routing subglacial water under grounded and floating ice.\n");
323 m_log->message(2,
" ... routing subglacial water under grounded ice only.\n");
339 double bwat_default =
m_config->get_number(
"bootstrapping.defaults.bwat");
381 bool include_floating =
m_config->get_flag(
"hydrology.routing.include_floating_ice");
385 for (
auto p =
m_grid->points(); p; p.next()) {
386 const int i = p.i(), j = p.j();
388 if (include_floating) {
390 if (mask.
icy(i, j)) {
391 result(i, j, 0) = mask.
icy(i + 1, j) ? 0.5 * (W(i, j) + W(i + 1, j)) : W(i, j);
393 result(i, j, 0) = mask.
icy(i + 1, j) ? W(i + 1, j) : 0.0;
396 if (mask.
icy(i, j)) {
397 result(i, j, 1) = mask.
icy(i, j + 1) ? 0.5 * (W(i, j) + W(i, j + 1)) : W(i, j);
399 result(i, j, 1) = mask.
icy(i, j + 1) ? W(i, j + 1) : 0.0;
404 result(i, j, 0) = mask.
grounded_ice(i + 1, j) ? 0.5 * (W(i, j) + W(i + 1, j)) : W(i, j);
406 result(i, j, 0) = mask.
grounded_ice(i + 1, j) ? W(i + 1, j) : 0.0;
410 result(i, j, 1) = mask.
grounded_ice(i, j + 1) ? 0.5 * (W(i, j) + W(i, j + 1)) : W(i, j);
412 result(i, j, 1) = mask.
grounded_ice(i, j + 1) ? W(i, j + 1) : 0.0;
440 double &KW_max)
const {
442 k =
m_config->get_number(
"hydrology.hydraulic_conductivity"),
443 alpha =
m_config->get_number(
"hydrology.thickness_power_in_flux"),
444 beta =
m_config->get_number(
"hydrology.gradient_power_in_flux"),
445 betapow = (beta - 2.0) / 2.0;
463 for (
auto p =
m_grid->points(); p; p.next()) {
464 const int i = p.i(), j = p.j();
468 dRdy = (
m_R(i + 1, j + 1) +
m_R(i, j + 1) -
m_R(i + 1, j - 1) -
m_R(i, j - 1)) / (4.0 *
m_dy);
469 result(i, j, 0) = dRdx * dRdx + dRdy * dRdy;
471 dRdx = (
m_R(i + 1, j + 1) +
m_R(i + 1, j) -
m_R(i - 1, j + 1) -
m_R(i - 1, j)) / (4.0 *
m_dx);
473 result(i, j, 1) = dRdx * dRdx + dRdy * dRdy;
479 const double eps = beta < 2.0 ? 1.0 : 0.0;
481 for (
auto p =
m_grid->points(); p; p.next()) {
482 const int i = p.i(), j = p.j();
484 for (
int o = 0; o < 2; ++o) {
485 const double Pi = result(i, j, o);
489 double B = pow(Pi + eps * eps, betapow);
491 result(i, j, o) =
k * pow(W(i, j, o), alpha - 1.0) * B;
493 KW_max =
std::max(KW_max, result(i, j, o) * W(i, j, o));
497 for (
auto p =
m_grid->points(); p; p.next()) {
498 const int i = p.i(), j = p.j();
500 for (
int o = 0; o < 2; ++o) {
501 result(i, j, o) =
k * pow(W(i, j, o), alpha - 1.0);
503 KW_max =
std::max(KW_max, result(i, j, o) * W(i, j, o));
531 auto grid = result.
grid();
536 k = config->get_number(
"hydrology.hydraulic_conductivity"),
537 L = config->get_number(
"constants.fresh_water.latent_heat_of_fusion"),
538 alpha = config->get_number(
"hydrology.thickness_power_in_flux"),
539 beta = config->get_number(
"hydrology.gradient_power_in_flux"),
540 g = config->get_number(
"constants.standard_gravity"),
541 rhow = config->get_number(
"constants.fresh_water.density"),
548 "alpha = %f < 1 which is not allowed", alpha);
562 double dx = grid->dx();
563 double dy = grid->dy();
565 for (
auto p = grid->points(); p; p.next()) {
566 const int i = p.i(), j = p.j();
571 if (W(i + 1, j) > 0.0) {
572 dRdx = (R(i + 1, j) - R(i, j)) / (2.0 * dx);
574 if (W(i - 1, j) > 0.0) {
575 dRdx += (R(i, j) - R(i - 1, j)) / (2.0 * dx);
578 if (W(i, j + 1) > 0.0) {
579 dRdy = (R(i, j + 1) - R(i, j)) / (2.0 * dy);
581 if (W(i, j - 1) > 0.0) {
582 dRdy += (R(i, j) - R(i, j - 1)) / (2.0 * dy);
584 result(i, j) = CC * pow(W(i, j), alpha) * pow(dRdx * dRdx + dRdy * dRdy, beta/2.0);
622 for (
auto p =
m_grid->points(); p; p.next()) {
623 const int i = p.i(), j = p.j();
625 if (W(i, j, 0) > 0.0) {
627 P_x = (P(i + 1, j) - P(i, j)) /
m_dx,
628 b_x = (bed(i + 1, j) - bed(i, j)) /
m_dx;
629 result(i, j, 0) = -
K(i, j, 0) * (P_x +
m_rg * b_x);
631 result(i, j, 0) = 0.0;
634 if (W(i, j, 1) > 0.0) {
636 P_y = (P(i, j + 1) - P(i, j)) /
m_dy,
637 b_y = (bed(i, j + 1) - bed(i, j)) /
m_dy;
638 result(i, j, 1) = -
K(i, j, 1) * (P_y +
m_rg * b_y);
640 result(i, j, 1) = 0.0;
645 list.
add(*no_model_mask);
647 for (
auto p =
m_grid->points(); p; p.next()) {
648 const int i = p.i(), j = p.j();
650 auto M = no_model_mask->
star(i, j);
653 result(i, j, 0) = 0.0;
657 result(i, j, 1) = 0.0;
677 for (
auto p =
m_grid->points(); p; p.next()) {
678 const int i = p.i(), j = p.j();
680 result(i, j, 0) = V(i, j, 0) * (V(i, j, 0) >= 0.0 ? W(i, j) : W(i + 1, j));
681 result(i, j, 1) = V(i, j, 1) * (V(i, j, 1) >= 0.0 ? W(i, j) : W(i, j + 1));
691 double D_max =
m_rg * KW_max;
693 return 0.25 / (D_max * result);
707 return alpha * 0.5 / (tmp[0]/
m_dx + tmp[1]/
m_dy + eps);
736 tillwat_max =
m_config->get_number(
"hydrology.tillwat_max"),
737 C =
m_config->get_number(
"hydrology.tillwat_decay_rate",
"m / second");
741 bool add_surface_input =
m_config->get_flag(
"hydrology.add_water_input_to_till_storage");
742 if (add_surface_input) {
746 for (
auto p =
m_grid->points(); p; p.next()) {
747 const int i = p.i(), j = p.j();
749 double input_rate = basal_melt_rate(i, j);
750 if (add_surface_input) {
754 Wtill_new(i, j) =
clip(Wtill(i, j) + dt * (input_rate -
C),
771 for (
auto p =
m_grid->points(); p; p.next()) {
772 const int i = p.i(), j = p.j();
774 auto q = Q.
star(i, j);
775 const double divQ = (q.e - q.w) /
m_dx + (q.n - q.s) /
m_dy;
777 auto k =
K.star(i, j);
778 auto ws = Wstag.
star(i, j);
781 De =
m_rg *
k.e * ws.e,
782 Dw =
m_rg *
k.w * ws.w,
783 Dn =
m_rg *
k.n * ws.n,
784 Ds =
m_rg *
k.s * ws.s;
786 auto w = W.
star(i, j);
787 const double diffW = (wux * (De * (w.e - w.c) - Dw * (w.c - w.w)) +
788 wuy * (Dn * (w.n - w.c) - Ds * (w.c - w.s)));
790 result(i, j) = dt * (- divQ + diffW);
812 for (
auto p =
m_grid->points(); p; p.next()) {
813 const int i = p.i(), j = p.j();
817 double Wtill_change = Wtill_new(i, j) - Wtill(i, j);
845 dt_max =
m_config->get_number(
"hydrology.maximum_time_step",
"seconds"),
846 tillwat_max =
m_config->get_number(
"hydrology.tillwat_max");
853 unsigned int step_counter = 0;
854 for (; ht < t_final; ht += hdt) {
858 double huge_number = 1e6;
900 hdt =
std::min(t_final - ht, dt_max);
905 m_log->message(3,
" hydrology step %05d, dt = %f s\n", step_counter, hdt);
960 m_config->get_flag(
"hydrology.routing.include_floating_ice"),
965 " took %d hydrology sub-steps with average dt = %.6f years (%.3f s or %.3f hours)\n",
969 (dt / step_counter) / 3600.0);
981 {
"hydraulic_potential",
Diagnostic::Ptr(
new HydraulicPotential(
this))},
987 std::map<std::string, TSDiagnostic::Ptr> result = {
const units::System::Ptr m_sys
unit system used by this component
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
const Profiling & profiling() const
std::shared_ptr< const Config > ConstPtr
A template derived from Diagnostic, adding a "Model".
double m_fill_value
fill value (used often enough to justify storing it)
const units::System::Ptr m_sys
the unit system
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
void begin(const char *name) const
void end(const char *name) const
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 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
void scale(double alpha)
Result: v <- v * alpha. Calls VecScale.
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)
void add(double alpha, const Array &x)
Result: v <- v + alpha * x. Calls VecAXPY.
void update_ghosts()
Updates ghost points.
unsigned int stencil_width() const
Get the stencil width of the current Array. Returns 0 if ghosts are not available.
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata object containing metadata for the compoment N.
bool grounded_ice(int i, int j) const
bool icy(int i, int j) const
stencils::Star< double > star(int i, int j) const
Returns the values at interfaces of the cell i,j using the staggered grid.
A class for storing and accessing internal staggered-grid 2D fields. Uses dof=2 storage....
array::Scalar m_flow_change
array::Scalar m_flow_change_incremental
virtual void bootstrap_impl(const File &input_file, const array::Scalar &ice_thickness)
array::Scalar m_surface_input_rate
virtual void define_model_state_impl(const File &output) const
The default (empty implementation).
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.
const array::Scalar & subglacial_water_thickness() const
Return the effective thickness of the transportable basal water layer.
array::Scalar m_basal_melt_rate
virtual void init_impl(const array::Scalar &W_till, const array::Scalar &W, const array::Scalar &P)
array::Scalar1 m_W
effective thickness of transportable basal water
virtual void restart_impl(const File &input_file, int record)
array::Scalar m_input_change
array::Scalar m_Wtill
effective thickness of basal water stored in till
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).
array::Scalar m_grounded_margin_change
array::Scalar m_no_model_mask_change
array::Scalar m_conservation_error_change
The PISM subglacial hydrology model interface.
virtual void init_impl(const array::Scalar &W_till, const array::Scalar &W, const array::Scalar &P)
array::Staggered1 m_Qstag_average
virtual void initialization_message() const
virtual std::map< std::string, Diagnostic::Ptr > diagnostics_impl() const
const array::Scalar & subglacial_water_pressure() const
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 W_change_due_to_flow(double dt, const array::Scalar1 &W, const array::Staggered1 &Wstag, const array::Staggered1 &K, const array::Staggered1 &Q, array::Scalar &result)
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().
virtual void update_impl(double t, double dt, const Inputs &inputs)
Update the model state variables W and Wtill by applying the subglacial hydrology model equations.
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.
const array::Staggered & velocity_staggered() const
array::Staggered1 m_Qstag
virtual void define_model_state_impl(const File &output) const
The default (empty implementation).
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 write_model_state_impl(const File &output) const
The default (empty implementation).
Routing(std::shared_ptr< const Grid > g)
virtual std::map< std::string, TSDiagnostic::Ptr > ts_diagnostics_impl() const
virtual void restart_impl(const File &input_file, int record)
array::Scalar1 m_bottom_surface
A subglacial hydrology model which assumes water pressure equals overburden pressure.
virtual std::shared_ptr< array::Array > compute_impl() const
BasalWaterPressure(const Routing *m)
Reports the pressure of the transportable water in the subglacial layer.
BasalWaterVelocity(const Routing *m)
virtual std::shared_ptr< array::Array > compute_impl() const
Diagnostically reports the staggered-grid components of the velocity of the water in the subglacial l...
virtual std::shared_ptr< array::Array > compute_impl() const
EffectiveBasalWaterPressure(const Routing *m)
Reports the effective pressure of the transportable water in the subglacial layer,...
HydraulicPotential(const Routing *m)
std::shared_ptr< array::Array > compute_impl() const
Report hydraulic potential in the subglacial hydrology system.
virtual std::shared_ptr< array::Array > compute_impl() const
RelativeBasalWaterPressure(const Routing *m)
Reports the pressure of the transportable water in the subglacial layer as a fraction of the overburd...
virtual std::shared_ptr< array::Array > compute_impl() const
WallMelt(const Routing *m)
Report the wall melt rate from dissipation of the potential energy of the transportable water.
#define PISM_ERROR_LOCATION
void staggered_to_regular(const array::CellType1 &cell_type, const array::Staggered1 &input, bool include_floating_ice, array::Scalar &result)
double max(const array::Scalar &input)
Finds maximum over all the values in an array::Scalar object. Ignores ghosts.
double min(const array::Scalar &input)
Finds minimum over all the values in an array::Scalar object. Ignores ghosts.
double absmax(const array::Scalar &input)
Finds maximum over all the absolute values in an array::Scalar object. Ignores ghosts.
void hydraulic_potential(const array::Scalar &W, const array::Scalar &P, const array::Scalar &sea_level, const array::Scalar &bed, const array::Scalar &ice_thickness, array::Scalar &result)
Compute the hydraulic potential.
static double K(double psi_x, double psi_y, double speed, double epsilon)
void wall_melt(const Routing &model, const array::Scalar &bed_elevation, array::Scalar &result)
Compute the wall melt rate which comes from (turbulent) dissipation of flow energy.
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 GlobalMax(MPI_Comm comm, double *local, double *result, int count)
std::map< std::string, Diagnostic::Ptr > DiagnosticList
void ice_bottom_surface(const Geometry &geometry, array::Scalar &result)
T combine(const T &a, const T &b)