19#include "pism/basalstrength/MohrCoulombYieldStress.hh"
20#include "pism/basalstrength/MohrCoulombPointwise.hh"
22#include "pism/util/Grid.hh"
23#include "pism/util/error_handling.hh"
24#include "pism/util/io/File.hh"
25#include "pism/util/MaxTimestep.hh"
26#include "pism/util/pism_utilities.hh"
27#include "pism/util/Time.hh"
28#include "pism/util/array/CellType.hh"
29#include "pism/util/array/Forcing.hh"
30#include "pism/geometry/Geometry.hh"
31#include "pism/coupler/util/options.hh"
32#include "pism/util/Logger.hh"
33#include "pism/util/io/IO_Flags.hh"
93 m_till_phi(m_grid,
"tillphi") {
95 m_name =
"Mohr-Coulomb yield stress model";
98 .
long_name(
"friction angle for till under grounded ice sheet")
105 std::string hydrology_tillwat_max =
"hydrology.tillwat_max";
108 if (not till_is_present) {
110 "The Mohr-Coulomb yield stress model cannot be used without till.\n"
111 "Reset %s or choose a different yield stress model.",
112 hydrology_tillwat_max.c_str());
116 auto delta_file =
m_config->get_string(
"basal_yield_stress.mohr_coulomb.delta.file");
118 if (not delta_file.empty()) {
121 unsigned int buffer_size =
m_config->get_number(
"input.forcing.buffer_size");
127 "mohr_coulomb_delta",
132 .long_name(
"minimum effective pressure on till as a fraction of overburden pressure")
147 auto tauc_to_phi_file =
m_config->get_string(
"basal_yield_stress.mohr_coulomb.tauc_to_phi.file");
149 if (not tauc_to_phi_file.empty()) {
153 " Will compute till friction angle (tillphi) as a function"
154 " of the yield stress (tauc)...\n");
162 }
else if (
m_config->get_flag(
"basal_yield_stress.mohr_coulomb.topg_to_phi.enabled")) {
164 m_log->message(2,
" creating till friction angle map from bed elevation...\n");
169 "PISM WARNING: -topg_to_phi computation will override the '%s' field\n"
170 " present in the input file '%s'!\n",
177 double till_phi_default =
m_config->get_number(
"basal_yield_stress.mohr_coulomb.till_phi_default");
185 double till_phi_default =
m_config->get_number(
"basal_yield_stress.mohr_coulomb.till_phi_default");
213 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()) {
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()) {
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()) {
428 const int i = p.i(), j = p.j();
433 double P_overburden = ice_density * standard_gravity * ice_thickness(i, j);
435 result(i, j) = mc.
till_friction_angle(delta, P_overburden, W_till(i, j), basal_yield_stress(i, j));
const Time & time() const
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)
static Ptr wrap(const T &input)
bool variable_exists(const std::string &short_name) const
Checks if a variable exists.
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
DiagnosticList spatial_diagnostics_impl() 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)
MohrCoulombYieldStress(std::shared_ptr< const Grid > g)
void set_till_friction_angle(const array::Scalar &input)
void finish_initialization(const YieldStressInputs &inputs)
MaxTimestep max_timestep_impl(double t) const
std::shared_ptr< array::Forcing > m_delta
virtual std::set< VariableMetadata > state_impl() const
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.
void write_state_impl(const OutputFile &output) const
The default (empty implementation).
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
DiagnosticList spatial_diagnostics_impl() const
void update(const YieldStressInputs &inputs, double t, double dt)
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 write(const OutputFile &file) 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.
VariableMetadata & metadata(unsigned int N=0)
Returns a reference to the VariableMetadata 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
std::set< VariableMetadata > metadata(std::initializer_list< const Array * > vecs)
@ PISM_READONLY
open an existing file for reading only
std::map< std::string, Diagnostic::Ptr > DiagnosticList
T combine(const T &a, const T &b)