22 #include "pism/coupler/OceanModel.hh"
23 #include "pism/util/EnthalpyConverter.hh"
24 #include "pism/rheology/FlowLaw.hh"
25 #include "pism/util/IceGrid.hh"
26 #include "pism/util/Mask.hh"
27 #include "pism/util/ConfigInterface.hh"
28 #include "pism/util/Vars.hh"
29 #include "pism/util/error_handling.hh"
30 #include "pism/util/Profiling.hh"
31 #include "pism/util/IceModelVec2CellType.hh"
32 #include "pism/util/Time.hh"
33 #include "pism/geometry/Geometry.hh"
34 #include "pism/util/Context.hh"
37 namespace stressbalance {
68 auto config = ctx->config();
70 File output(ctx->com(), filename,
74 config->write(output);
77 io::append_time(output, config->get_string(
"time.dimension_name"), ctx->time()->current());
140 std::shared_ptr<ShallowStressBalance> sb,
141 std::shared_ptr<SSB_Modifier> ssb_mod)
144 m_strain_heating(m_grid,
"strain_heating",
WITHOUT_GHOSTS, m_grid->z()),
145 m_shallow_stress_balance(sb),
146 m_modifier(ssb_mod) {
149 "vertical velocity of ice, relative to base of ice directly below",
150 "m s-1",
"m year-1",
"", 0);
154 "rate of strain heating in ice (dissipation heating)",
155 "W m-3",
"W m-3",
"", 0);
173 profiling.
begin(
"stress_balance.shallow");
175 profiling.
end(
"stress_balance.shallow");
177 profiling.
begin(
"stress_balance.modifier");
179 inputs, full_update);
180 profiling.
end(
"stress_balance.modifier");
186 profiling.
begin(
"stress_balance.strain_heat");
188 profiling.
end(
"stress_balance.strain_heat");
190 profiling.
begin(
"stress_balance.vertical_velocity");
193 profiling.
end(
"stress_balance.vertical_velocity");
286 const bool use_upstream_fd =
m_config->get_string(
"stress_balance.vertical_velocity_approximation") ==
"upstream";
290 if (basal_melt_rate) {
291 list.
add(*basal_melt_rate);
294 const std::vector<double> &z =
m_grid->z();
295 const unsigned int Mz =
m_grid->Mz();
301 std::vector<double> u_x_plus_v_y(Mz);
304 const int i = p.i(), j = p.j();
333 if (use_upstream_fd) {
335 uw = 0.5 * (u_w[0] + u_ij[0]),
336 ue = 0.5 * (u_ij[0] + u_e[0]);
338 if (uw > 0.0 and ue >= 0.0) {
341 }
else if (uw <= 0.0 and ue < 0.0) {
357 if (east + west > 0) {
358 D_x = 1.0 / (dx * (east + west));
368 if (use_upstream_fd) {
370 vs = 0.5 * (v_s[0] + v_ij[0]),
371 vn = 0.5 * (v_ij[0] + v_n[0]);
373 if (vs > 0.0 and vn >= 0.0) {
376 }
else if (vs <= 0.0 and vn < 0.0) {
392 if (north + south > 0) {
393 D_y = 1.0 / (dy * (north + south));
400 for (
unsigned int k = 0;
k < Mz; ++
k) {
402 u_x = D_x * (west * (u_ij[
k] - u_w[
k]) + east * (u_e[
k] - u_ij[
k])),
403 v_y = D_y * (south * (v_ij[
k] - v_s[
k]) + north * (v_n[
k] - v_ij[
k]));
404 u_x_plus_v_y[
k] = u_x + v_y;
408 if (basal_melt_rate != NULL) {
409 w_ij[0] = - (*basal_melt_rate)(i,j);
415 for (
unsigned int k = 1;
k < Mz; ++
k) {
416 const double dz = z[
k] - z[
k-1];
418 w_ij[
k] = w_ij[
k - 1] - (0.5 * dz) * (u_x_plus_v_y[
k] + u_x_plus_v_y[
k - 1]);
443 static inline double D2(
double u_x,
double u_y,
double u_z,
double v_x,
double v_y,
double v_z) {
444 return 0.5 * (PetscSqr(u_x + v_y) + u_x*u_x + v_y*v_y + 0.5 * (PetscSqr(u_y + v_x) + u_z*u_z + v_z*v_z));
522 exponent = 0.5 * (1.0 /
n + 1.0),
523 e_to_a_power = pow(enhancement_factor,-1.0/
n);
527 const std::vector<double> &z =
m_grid->z();
528 const unsigned int Mz =
m_grid->Mz();
529 std::vector<double> depth(Mz), pressure(Mz), hardness(Mz);
534 const int i = p.i(), j = p.j();
536 double H = thickness(i, j);
537 int ks =
m_grid->kBelowHeight(H);
539 *u_ij, *u_w, *u_n, *u_e, *u_s,
540 *v_ij, *v_w, *v_n, *v_e, *v_s;
544 double west = 1, east = 1, south = 1, north = 1,
557 if (east + west > 0) {
558 D_x = 1.0 / (
m_grid->dx() * (east + west));
573 if (north + south > 0) {
574 D_y = 1.0 / (
m_grid->dy() * (north + south));
586 v_ij = v.get_column(i, j);
587 v_w = v.get_column(i - 1, j);
588 v_e = v.get_column(i + 1, j);
589 v_s = v.get_column(i, j - 1);
590 v_n = v.get_column(i, j + 1);
595 for (
int k = 0;
k <= ks; ++
k) {
601 EC->pressure(depth, ks, pressure);
603 flow_law.
hardness_n(E_ij, &pressure[0], ks + 1, &hardness[0]);
605 for (
int k = 0;
k <= ks; ++
k) {
608 double u_z = 0.0, v_z = 0.0,
609 u_x = D_x * (west * (u_ij[
k] - u_w[
k]) + east * (u_e[
k] - u_ij[
k])),
610 u_y = D_y * (south * (u_ij[
k] - u_s[
k]) + north * (u_n[
k] - u_ij[
k])),
611 v_x = D_x * (west * (v_ij[
k] - v_w[
k]) + east * (v_e[
k] - v_ij[
k])),
612 v_y = D_y * (south * (v_ij[
k] - v_s[
k]) + north * (v_n[
k] - v_ij[
k]));
615 dz = z[
k+1] - z[
k-1];
616 u_z = (u_ij[
k+1] - u_ij[
k-1]) / dz;
617 v_z = (v_ij[
k+1] - v_ij[
k-1]) / dz;
621 u_z = (u_ij[1] - u_ij[0]) / dz;
622 v_z = (v_ij[1] - v_ij[0]) / dz;
625 Sigma[
k] = 2.0 * e_to_a_power * hardness[
k] * pow(
D2(u_x, u_y, u_z, v_x, v_y, v_z), exponent);
628 int remaining_levels = Mz - (ks + 1);
629 if (remaining_levels > 0) {
630 #if PETSC_VERSION_LT(3, 12, 0)
631 ierr = PetscMemzero(&Sigma[ks+1],
632 remaining_levels*
sizeof(
double));
634 ierr = PetscArrayzero(&Sigma[ks+1], remaining_levels);
692 double dx = grid->dx();
693 double dy = grid->dy();
695 if (result.
ndof() != 2) {
702 const int i = p.i(), j = p.j();
710 auto m = mask.
star(i,j);
711 auto U = V.
star(i,j);
714 double u_x = 0, u_y = 0, v_x = 0, v_y = 0,
715 east = 1, west = 1, south = 1, north = 1;
748 if (west + east > 0) {
749 u_x = 1.0 / (dx * (west + east)) * (west * (U.ij.u - U[
West].u) + east * (U[
East].u - U.ij.u));
750 v_x = 1.0 / (dx * (west + east)) * (west * (U.ij.v - U[
West].v) + east * (U[
East].v - U.ij.v));
753 if (south + north > 0) {
754 u_y = 1.0 / (dy * (south + north)) * (south * (U.ij.u - U[
South].u) + north * (U[
North].u - U.ij.u));
755 v_y = 1.0 / (dy * (south + north)) * (south * (U.ij.v - U[
South].v) + north * (U[
North].v - U.ij.v));
758 const double A = 0.5 * (u_x + v_y),
759 B = 0.5 * (u_x - v_y),
760 Dxy = 0.5 * (v_x + u_y),
761 q = sqrt(B*B + Dxy*Dxy);
762 result(i,j,0) = A + q;
763 result(i,j,1) = A - q;
778 auto grid = result.
grid();
784 if (result.
ndof() != 3) {
791 const int i = p.i(), j = p.j();
800 auto m = cell_type.
star(i,j);
801 auto U = velocity.
star(i,j);
804 double u_x = 0, u_y = 0, v_x = 0, v_y = 0,
805 east = 1, west = 1, south = 1, north = 1;
838 if (west + east > 0) {
839 u_x = 1.0 / (dx * (west + east)) * (west * (U.ij.u - U[
West].u) + east * (U[
East].u - U.ij.u));
840 v_x = 1.0 / (dx * (west + east)) * (west * (U.ij.v - U[
West].v) + east * (U[
East].v - U.ij.v));
843 if (south + north > 0) {
844 u_y = 1.0 / (dy * (south + north)) * (south * (U.ij.u - U[
South].u) + north * (U[
North].u - U.ij.u));
845 v_y = 1.0 / (dy * (south + north)) * (south * (U.ij.v - U[
South].v) + north * (U[
North].v - U.ij.v));
854 result(i,j,0) = 2.0*nu*u_x;
855 result(i,j,1) = 2.0*nu*v_y;
856 result(i,j,2) = nu*(u_y+v_x);
Makes sure that we call begin_access() and end_access() for all accessed IceModelVecs.
const Config::ConstPtr m_config
configuration database used by this component
const IceGrid::ConstPtr m_grid
grid used by this component
A class defining a common interface for most PISM sub-models.
std::shared_ptr< EnthalpyConverter > Ptr
High-level PISM I/O class.
IceModelVec2S ice_surface_elevation
IceModelVec2S cell_grounded_fraction
IceModelVec2CellType cell_type
IceModelVec2S bed_elevation
IceModelVec2S ice_area_specific_volume
IceModelVec2S sea_level_elevation
IceModelVec2S ice_thickness
std::shared_ptr< const IceGrid > ConstPtr
bool icy(int i, int j) const
bool ice_free(int i, int j) const
"Cell type" mask. Adds convenience methods to IceModelVec2Int.
stencils::Star< int > star(int i, int j) const
A class for storing and accessing internal staggered-grid 2D fields. Uses dof=2 storage....
stencils::Star< T > star(int i, int j) const
double * get_column(int i, int j)
A virtual class collecting methods common to ice and bedrock 3D fields.
void set_attrs(const std::string &pism_intent, const std::string &long_name, const std::string &units, const std::string &glaciological_units, const std::string &standard_name, unsigned int component)
Sets NetCDF attributes of an IceModelVec object.
IceGrid::ConstPtr grid() const
void write(const std::string &filename) const
unsigned int ndof() const
Returns the number of degrees of freedom per grid point.
void add(double alpha, const IceModelVec &x)
Result: v <- v + alpha * x. Calls VecAXPY.
void set_time_independent(bool flag)
Set the time independent flag for all variables corresponding to this IceModelVec instance.
void failed()
Indicates a failure of a parallel section.
void begin(const char *name) const
void end(const char *name) const
void add_context(const std::string &message)
Add a message providing some context. This way we can (sort of) get a stack trace even though C++ exc...
This class represents a 2D vector field (such as ice velocity) at a certain grid point.
void effective_viscosity(double hardness, double gamma, double *nu, double *dnu) const
Computes the regularized effective viscosity and its derivative with respect to the second invariant ...
void hardness_n(const double *enthalpy, const double *pressure, unsigned int n, double *result) const
Shallow stress balance modifier (such as the non-sliding SIA).
Shallow stress balance (such as the SSA).
const IceModelVec3 & velocity_u() const
Get components of the the 3D velocity field.
IceModelVec3 m_strain_heating
StressBalance(IceGrid::ConstPtr g, std::shared_ptr< ShallowStressBalance > sb, std::shared_ptr< SSB_Modifier > ssb_mod)
std::shared_ptr< SSB_Modifier > m_modifier
virtual void write_model_state_impl(const File &output) const
The default (empty implementation).
const IceModelVec2S & basal_frictional_heating() const
Get the basal frictional heating.
const IceModelVec3 & volumetric_strain_heating() const
CFLData max_timestep_cfl_3d() const
virtual void define_model_state_impl(const File &output) const
The default (empty implementation).
const IceModelVec2V & advective_velocity() const
Get the thickness-advective (SSA) 2D velocity.
const SSB_Modifier * modifier() const
Returns a pointer to a stress balance modifier implementation.
virtual void compute_volumetric_strain_heating(const Inputs &inputs)
Computes the volumetric strain heating using horizontal velocity.
std::shared_ptr< ShallowStressBalance > m_shallow_stress_balance
CFLData max_timestep_cfl_2d() const
double max_diffusivity() const
Get the max diffusivity (for the adaptive time-stepping).
virtual void compute_vertical_velocity(const IceModelVec2CellType &mask, const IceModelVec3 &u, const IceModelVec3 &v, const IceModelVec2S *bmr, IceModelVec3 &result)
Compute vertical velocity using incompressibility of the ice.
void init()
Initialize the StressBalance object.
const ShallowStressBalance * shallow() const
Returns a pointer to a shallow stress balance solver implementation.
std::string stdout_report() const
Produce a report string for the standard output.
void update(const Inputs &inputs, bool full_update)
Update all the fields if (full_update), only update diffusive flux and max. diffusivity otherwise.
const IceModelVec2Stag & diffusive_flux() const
Get the diffusive (SIA) vertically-averaged flux on the staggered grid.
const IceModelVec3 & velocity_v() const
const IceModelVec3 & velocity_w() const
#define PISM_CHK(errcode, name)
#define PISM_ERROR_LOCATION
void append_time(const File &file, const Config &config, double time_seconds)
Prepare a file for output.
void define_time(const File &file, const Context &ctx)
Prepare a file for output.
bool ice_free(int M)
Ice-free cell (grounded or ocean).
void compute_2D_stresses(const rheology::FlowLaw &flow_law, const IceModelVec2V &velocity, const IceModelVec2S &hardness, const IceModelVec2CellType &cell_type, IceModelVec3 &result)
Compute 2D deviatoric stresses.
void compute_2D_principal_strain_rates(const IceModelVec2V &V, const IceModelVec2CellType &mask, IceModelVec3 &result)
Compute eigenvalues of the horizontal, vertically-integrated strain rate tensor.
static double D2(double u_x, double u_y, double u_z, double v_x, double v_y, double v_z)
IO_Backend string_to_backend(const std::string &backend)
CFLData max_timestep_cfl_2d(const IceModelVec2S &ice_thickness, const IceModelVec2CellType &cell_type, const IceModelVec2V &velocity)
Compute the CFL constant associated to first-order upwinding for the sliding contribution to mass con...
CFLData max_timestep_cfl_3d(const IceModelVec2S &ice_thickness, const IceModelVec2CellType &cell_type, const IceModelVec3 &u3, const IceModelVec3 &v3, const IceModelVec3 &w3)
Compute the maximum velocities for time-stepping and reporting to user.
static double secondInvariant_2D(const Vector2 &U_x, const Vector2 &U_y)
@ PISM_READWRITE_MOVE
create a file for writing, move foo.nc to foo.nc~ if present