19 #include "pism/basalstrength/MohrCoulombYieldStress.hh"
20 #include "pism/basalstrength/MohrCoulombPointwise.hh"
22 #include "pism/util/Grid.hh"
23 #include "pism/util/Mask.hh"
24 #include "pism/util/error_handling.hh"
25 #include "pism/util/io/File.hh"
26 #include "pism/util/MaxTimestep.hh"
27 #include "pism/util/pism_utilities.hh"
28 #include "pism/util/Time.hh"
29 #include "pism/util/array/CellType.hh"
30 #include "pism/util/array/Forcing.hh"
31 #include "pism/geometry/Geometry.hh"
32 #include "pism/coupler/util/options.hh"
92 m_till_phi(m_grid,
"tillphi") {
94 m_name =
"Mohr-Coulomb yield stress model";
97 .
long_name(
"friction angle for till under grounded ice sheet")
104 std::string hydrology_tillwat_max =
"hydrology.tillwat_max";
105 bool till_is_present =
m_config->get_number(hydrology_tillwat_max) > 0.0;
107 if (not till_is_present) {
109 "The Mohr-Coulomb yield stress model cannot be used without till.\n"
110 "Reset %s or choose a different yield stress model.",
111 hydrology_tillwat_max.c_str());
115 auto delta_file =
m_config->get_string(
"basal_yield_stress.mohr_coulomb.delta.file");
117 if (not delta_file.empty()) {
120 unsigned int buffer_size =
m_config->get_number(
"input.forcing.buffer_size");
126 "mohr_coulomb_delta",
131 .long_name(
"minimum effective pressure on till as a fraction of overburden pressure")
146 auto tauc_to_phi_file =
m_config->get_string(
"basal_yield_stress.mohr_coulomb.tauc_to_phi.file");
148 if (not tauc_to_phi_file.empty()) {
152 " Will compute till friction angle (tillphi) as a function"
153 " of the yield stress (tauc)...\n");
161 }
else if (
m_config->get_flag(
"basal_yield_stress.mohr_coulomb.topg_to_phi.enabled")) {
163 m_log->message(2,
" creating till friction angle map from bed elevation...\n");
168 "PISM WARNING: -topg_to_phi computation will override the '%s' field\n"
169 " present in the input file '%s'!\n",
176 double till_phi_default =
m_config->get_number(
"basal_yield_stress.mohr_coulomb.till_phi_default");
184 double till_phi_default =
m_config->get_number(
"basal_yield_stress.mohr_coulomb.till_phi_default");
212 auto dt =
m_delta->max_timestep(t);
267 double t,
double dt) {
271 bool slippery_grounding_lines =
m_config->get_flag(
"basal_yield_stress.slippery_grounding_lines"),
272 add_transportable_water =
m_config->get_flag(
"basal_yield_stress.add_transportable_water");
275 ice_density =
m_config->get_number(
"constants.ice.density"),
276 standard_gravity =
m_config->get_number(
"constants.standard_gravity");
278 const double high_tauc =
m_config->get_number(
"basal_yield_stress.ice_free_bedrock"),
279 W_till_max =
m_config->get_number(
"hydrology.tillwat_max"),
280 delta =
m_config->get_number(
"basal_yield_stress.mohr_coulomb.till_effective_fraction_overburden"),
281 tlftw =
m_config->get_number(
"basal_yield_stress.mohr_coulomb.till_log_factor_transportable_water");
295 &bed_topography, &sea_level, &ice_thickness};
297 if (add_transportable_water) {
298 list.
add(W_subglacial);
307 for (
auto p =
m_grid->points(); p; p.next()) {
308 const int i = p.i(), j = p.j();
310 if (cell_type.ice_free(i, j)) {
315 double water = W_till(i,j);
317 if (slippery_grounding_lines and
318 bed_topography(i, j) <= sea_level(i, j) and
319 (cell_type.next_to_floating_ice(i, j) or cell_type.next_to_ice_free_ocean(i, j))) {
321 }
else if (add_transportable_water) {
322 water = W_till(i, j) + tlftw * log(1.0 + W_subglacial(i, j) / tlftw);
325 double P_overburden = ice_density * standard_gravity * ice_thickness(i, j);
355 phi_min =
m_config->get_number(
"basal_yield_stress.mohr_coulomb.topg_to_phi.phi_min"),
356 phi_max =
m_config->get_number(
"basal_yield_stress.mohr_coulomb.topg_to_phi.phi_max"),
357 topg_min =
m_config->get_number(
"basal_yield_stress.mohr_coulomb.topg_to_phi.topg_min"),
358 topg_max =
m_config->get_number(
"basal_yield_stress.mohr_coulomb.topg_to_phi.topg_max");
361 " till friction angle (phi) is piecewise-linear function of bed elev (topg):\n"
362 " / %5.2f for topg < %.f\n"
363 " phi = | %5.2f + (topg - (%.f)) * (%.2f / %.f) for %.f < topg < %.f\n"
364 " \\ %5.2f for %.f < topg\n",
366 phi_min, topg_min, phi_max - phi_min, topg_max - topg_min, topg_min, topg_max,
369 if (phi_min >= phi_max) {
371 "invalid -topg_to_phi arguments: phi_min < phi_max is required");
374 if (topg_min >= topg_max) {
376 "invalid -topg_to_phi arguments: topg_min < topg_max is required");
379 const double slope = (phi_max - phi_min) / (topg_max - topg_min);
383 for (
auto p =
m_grid->points(); p; p.next()) {
384 const int i = p.i(), j = p.j();
385 const double bed = bed_topography(i, j);
387 if (bed <= topg_min) {
388 result(i, j) = phi_min;
389 }
else if (bed >= topg_max) {
390 result(i, j) = phi_max;
392 result(i, j) = phi_min + (bed - topg_min) * slope;
416 ice_density =
m_config->get_number(
"constants.ice.density"),
417 standard_gravity =
m_config->get_number(
"constants.standard_gravity");
420 delta =
m_config->get_number(
"basal_yield_stress.mohr_coulomb.till_effective_fraction_overburden");
423 &W_till = till_water_thickness;
425 array::AccessScope list{&cell_type, &basal_yield_stress, &W_till, &ice_thickness, &result};
427 for (
auto p =
m_grid->points(); p; p.next()) {
428 const int i = p.i(), j = p.j();
430 if (cell_type.
ocean(i, j)) {
432 }
else if (cell_type.
ice_free(i, j)) {
435 double P_overburden = ice_density * standard_gravity * ice_thickness(i, j);
437 result(i, j) = mc.
till_friction_angle(delta, P_overburden, W_till(i, j), basal_yield_stress(i, j));
const Time & time() const
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)
static Ptr wrap(const T &input)
VariableLookupData find_variable(const std::string &short_name, const std::string &std_name) const
Find a variable using its standard name and/or short name.
std::string filename() const
High-level PISM I/O class.
array::Scalar1 sea_level_elevation
array::CellType2 cell_type
array::Scalar2 ice_thickness
array::Scalar2 bed_elevation
Combines the max. time step with the flag indicating if a restriction is active. Makes is possible to...
double yield_stress(double delta, double P_overburden, double water_thickness, double phi) const
double till_friction_angle(double delta, double P_overburden, double water_thickness, double yield_stress) const
void init_impl(const YieldStressInputs &inputs)
void restart_impl(const File &input_file, int record)
void update_impl(const YieldStressInputs &inputs, double t, double dt)
DiagnosticList diagnostics_impl() const
MohrCoulombYieldStress(std::shared_ptr< const Grid > g)
void set_till_friction_angle(const array::Scalar &input)
void write_model_state_impl(const File &output) const
The default (empty implementation).
void define_model_state_impl(const File &output) const
void finish_initialization(const YieldStressInputs &inputs)
MaxTimestep max_timestep_impl(double t) const
std::shared_ptr< array::Forcing > m_delta
void till_friction_angle(const array::Scalar &bed_topography, array::Scalar &result)
Computes the till friction angle phi as a piecewise linear function of bed elevation,...
void bootstrap_impl(const File &input_file, const YieldStressInputs &inputs)
Initialize the pseudo-plastic till mechanical model.
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
void update(const YieldStressInputs &inputs, double t, double dt)
DiagnosticList diagnostics_impl() const
array::Scalar2 m_basal_yield_stress
The PISM basal yield stress model interface (virtual base class)
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
void set(double c)
Result: v[j] <- c for all j.
void regrid(const std::string &filename, io::Default default_value)
void update_ghosts()
Updates ghost points.
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata object containing metadata for the compoment N.
bool ice_free(int i, int j) const
bool ocean(int i, int j) const
"Cell type" mask. Adds convenience methods to array::Scalar.
#define PISM_ERROR_LOCATION
@ PISM_READONLY
open an existing file for reading only
std::map< std::string, Diagnostic::Ptr > DiagnosticList
T combine(const T &a, const T &b)