23 #include "pism/stressbalance/StressBalance_diagnostics.hh"
24 #include "pism/stressbalance/SSB_Modifier.hh"
25 #include "pism/stressbalance/ShallowStressBalance.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/pism_utilities.hh"
31 #include "pism/util/array/CellType.hh"
32 #include "pism/rheology/FlowLaw.hh"
33 #include "pism/rheology/FlowLawFactory.hh"
34 #include "pism/util/Context.hh"
37 namespace stressbalance {
65 if (
m_config->get_flag(
"output.ISMIP6")) {
86 auto ismip6 =
m_config->get_flag(
"output.ISMIP6");
90 {
m_sys, ismip6 ?
"yvelmean" :
"vbar"}};
93 .long_name(
"vertical mean of horizontal ice velocity in the X direction")
94 .standard_name(
"land_ice_vertical_mean_x_velocity")
96 .output_units(
"m year-1");
98 .long_name(
"vertical mean of horizontal ice velocity in the Y direction")
99 .standard_name(
"land_ice_vertical_mean_y_velocity")
101 .output_units(
"m year-1");
112 result->metadata(0) =
m_vars[0];
113 result->metadata(1) =
m_vars[1];
117 for (
auto p =
m_grid->points(); p; p.next()) {
118 const int i = p.i(), j = p.j();
119 double thk = (*thickness)(i,j);
124 (*result)(i,j) /= thk;
126 (*result)(i,j) = 0.0;
140 .long_name(
"magnitude of vertically-integrated horizontal velocity of ice")
142 .output_units(
"m year-1");
145 m_vars[0][
"valid_min"] = {0.0};
149 auto result = allocate<array::Scalar>(
"velbar_mag");
172 .long_name(
"Vertically integrated horizontal flux of ice in the X direction")
174 .output_units(
"m2 year-1");
176 .long_name(
"Vertically integrated horizontal flux of ice in the Y direction")
178 .output_units(
"m2 year-1");
182 double H_threshold =
m_config->get_number(
"geometry.ice_free_thickness_standard");
184 auto result = allocate<array::Vector>(
"flux");
190 &u3 =
model->velocity_u(),
191 &v3 =
model->velocity_v();
195 const auto &z =
m_grid->z();
199 for (
auto p =
m_grid->points(); p; p.next()) {
200 const int i = p.i(), j = p.j();
202 double H = (*thickness)(i,j);
205 if (H < H_threshold) {
206 (*result)(i, j) = 0.0;
213 auto v = v3.get_column(i, j);
218 int ks =
m_grid->kBelowHeight(H);
223 for (
int k = 1;
k <= ks; ++
k) {
227 Q += (z[
k] - z[
k - 1]) * 0.5 * (
v0 + v1);
234 Q += (H - z[ks]) *
Vector2d(u[ks], v[ks]);
254 .long_name(
"magnitude of vertically-integrated horizontal flux of ice")
256 .output_units(
"m2 year-1");
258 m_vars[0][
"valid_min"] = {0.0};
267 result->metadata() =
m_vars[0];
271 for (
auto p =
m_grid->points(); p; p.next()) {
272 const int i = p.i(), j = p.j();
274 (*result)(i,j) *= (*thickness)(i,j);
287 .long_name(
"magnitude of horizontal velocity of ice at base of ice")
289 .output_units(
"m year-1");
291 m_vars[0][
"valid_min"] = {0.0};
295 auto result = allocate<array::Scalar>(
"velbase_mag");
301 const auto &mask = *
m_grid->variables().get_2d_cell_type(
"mask");
305 for (
auto p =
m_grid->points(); p; p.next()) {
306 const int i = p.i(), j = p.j();
308 if (mask.ice_free(i, j)) {
309 (*result)(i, j) = fill_value;
320 .long_name(
"magnitude of horizontal velocity of ice at ice surface")
322 .output_units(
"m year-1");
324 m_vars[0][
"valid_min"] = {0.0};
330 auto result = allocate<array::Scalar>(
"velsurf_mag");
334 const auto &mask = *
m_grid->variables().get_2d_cell_type(
"mask");
338 for (
auto p =
m_grid->points(); p; p.next()) {
339 const int i = p.i(), j = p.j();
341 if (mask.ice_free(i, j)) {
342 (*result)(i, j) = fill_value;
353 auto ismip6 =
m_config->get_flag(
"output.ISMIP6");
354 m_vars = { {
m_sys, ismip6 ?
"xvelsurf" :
"uvelsurf" },
355 {
m_sys, ismip6 ?
"yvelsurf" :
"vvelsurf" } };
357 .long_name(
"x-component of the horizontal velocity of ice at ice surface")
358 .standard_name(
"land_ice_surface_x_velocity");
360 .long_name(
"y-component of the horizontal velocity of ice at ice surface")
361 .standard_name(
"land_ice_surface_y_velocity");
365 v.units(
"m s-1").output_units(
"m year-1");
366 v[
"valid_range"] = {-large_number, large_number};
374 auto result = allocate<array::Vector>(
"surf");
380 &u3 =
model->velocity_u(),
381 &v3 =
model->velocity_v();
388 const auto &cell_type = *
m_grid->variables().get_2d_cell_type(
"mask");
392 for (
auto p =
m_grid->points(); p; p.next()) {
393 const int i = p.i(), j = p.j();
395 if (cell_type.ice_free(i, j)) {
396 (*result)(i, j) = fill_value;
398 (*result)(i, j) = { u_surf(i, j), v_surf(i, j) };
408 .long_name(
"vertical velocity of ice, relative to geoid")
410 .output_units(
"m year-1");
413 m_vars[0][
"valid_range"] = { -large_number, large_number };
417 std::shared_ptr<array::Array3D> result3(
419 result3->metadata() =
m_vars[0];
422 bed =
m_grid->variables().get_2d_scalar(
"bedrock_altitude");
423 uplift =
m_grid->variables().get_2d_scalar(
"tendency_of_bedrock_altitude");
426 const auto &mask = *
m_grid->variables().get_2d_cell_type(
"mask");
429 &w3 =
model->velocity_w();
431 array::AccessScope list{ &thickness, &mask, bed, &u3, &v3, &w3, uplift, result3.get() };
433 const double ice_density =
m_config->get_number(
"constants.ice.density"),
434 sea_water_density =
m_config->get_number(
"constants.sea_water.density"),
435 R = ice_density / sea_water_density;
439 for (
auto p =
m_grid->points(); p; p.next()) {
440 const int i = p.i(), j = p.j();
442 const double *u = u3.
get_column(i, j), *v = v3.get_column(i, j), *w = w3.get_column(i, j);
443 double *result = result3->get_column(i, j);
445 int ks =
m_grid->kBelowHeight(thickness(i, j));
448 if (mask.grounded(i, j)) {
450 uplift_ij = (*uplift)(i, j);
451 for (
int k = 0;
k <= ks;
k++) {
452 result[
k] = w[
k] + uplift_ij + u[
k] * bed_dx + v[
k] * bed_dy;
456 const double z_sl = R * thickness(i, j), w_sl = w3.interpolate(i, j, z_sl);
458 for (
int k = 0;
k <= ks;
k++) {
459 result[
k] = w[
k] - w_sl;
466 for (
unsigned int k = ks + 1;
k <
m_grid->Mz();
k++) {
471 for (
unsigned int k = ks + 1;
k <
m_grid->Mz();
k++) {
472 result[
k] = result[ks];
490 auto ismip6 =
m_config->get_flag(
"output.ISMIP6");
493 m_vars = { {
m_sys, ismip6 ?
"zvelsurf" :
"wvelsurf" } };
496 .long_name(
"vertical velocity of ice at ice surface, relative to the geoid")
497 .standard_name(
"land_ice_surface_upward_velocity")
499 .output_units(
"m year-1");
502 m_vars[0][
"valid_range"] = { -large_number, large_number };
509 auto result = allocate<array::Scalar>(
"wvelsurf");
518 const auto &mask = *
m_grid->variables().get_2d_cell_type(
"mask");
522 for (
auto p =
m_grid->points(); p; p.next()) {
523 const int i = p.i(), j = p.j();
525 if (mask.ice_free(i, j)) {
526 (*result)(i, j) = fill_value;
535 auto ismip6 =
m_config->get_flag(
"output.ISMIP6");
537 m_vars = { {
m_sys, ismip6 ?
"zvelbase" :
"wvelbase" } };
539 .long_name(
"vertical velocity of ice at the base of ice, relative to the geoid")
540 .standard_name(
"land_ice_basal_upward_velocity")
542 .output_units(
"m year-1");
546 m_vars[0][
"valid_range"] = { -large_number, large_number };
553 auto result = allocate<array::Scalar>(
"wvelbase");
560 const auto &mask = *
m_grid->variables().get_2d_cell_type(
"mask");
564 for (
auto p =
m_grid->points(); p; p.next()) {
565 const int i = p.i(), j = p.j();
567 if (mask.ice_free(i, j)) {
568 (*result)(i, j) = fill_value;
577 auto ismip6 =
m_config->get_flag(
"output.ISMIP6");
580 m_vars = { {
m_sys, ismip6 ?
"xvelbase" :
"uvelbase" },
581 {
m_sys, ismip6 ?
"yvelbase" :
"vvelbase" } };
583 .long_name(
"x-component of the horizontal velocity of ice at the base of ice")
584 .standard_name(
"land_ice_basal_x_velocity");
586 .long_name(
"y-component of the horizontal velocity of ice at the base of ice")
587 .standard_name(
"land_ice_basal_y_velocity");
593 v.units(
"m s-1").output_units(
"m year-1");
594 v[
"valid_range"] = { -large_number, large_number };
595 v[
"_FillValue"] = { fill_value };
602 auto result = allocate<array::Vector>(
"base");
612 const auto &mask = *
m_grid->variables().get_2d_cell_type(
"mask");
616 for (
auto p =
m_grid->points(); p; p.next()) {
617 const int i = p.i(), j = p.j();
619 if (mask.ice_free(i, j)) {
620 (*result)(i, j) = fill_value;
622 (*result)(i, j) = { u_base(i, j), v_base(i, j) };
632 m_vars[0].long_name(
"basal frictional heating").units(
"W m-2");
637 auto result = allocate<array::Scalar>(
"bfrict");
639 result->copy_from(
model->basal_frictional_heating());
648 .long_name(
"horizontal velocity of ice in the X direction")
649 .standard_name(
"land_ice_x_velocity")
651 .output_units(
"m year-1");
662 auto grid = result.
grid();
664 auto Mz = grid->Mz();
668 for (
auto p = grid->points(); p; p.next()) {
669 const int i = p.i(), j = p.j();
671 int ks = grid->kBelowHeight(H(i, j));
673 const double *F_ij =
F.get_column(i, j);
677 for (
int k = 0;
k <= ks;
k++) {
678 F_out_ij[
k] = F_ij[
k];
681 for (
unsigned int k = ks + 1;
k < Mz;
k++) {
693 std::shared_ptr<array::Array3D> result(
695 result->metadata() =
m_vars[0];
706 .long_name(
"horizontal velocity of ice in the Y direction")
707 .standard_name(
"land_ice_y_velocity")
709 .output_units(
"m year-1");
714 std::shared_ptr<array::Array3D> result(
716 result->metadata() =
m_vars[0];
727 .long_name(
"vertical velocity of ice, relative to base of ice directly below")
729 .output_units(
"m year-1");
734 std::shared_ptr<array::Array3D> result(
736 result->metadata() =
m_vars[0];
748 .long_name(
"rate of strain heating in ice (dissipation heating)")
750 .output_units(
"mW m-3");
757 result->metadata() =
m_vars[0];
759 result->copy_from(
model->volumetric_strain_heating());
768 .long_name(
"first eigenvalue of the horizontal, vertically-integrated strain rate tensor")
771 .long_name(
"second eigenvalue of the horizontal, vertically-integrated strain rate tensor")
778 auto result = std::make_shared<array::Array2D<PrincipalStrainRates> >(
m_grid,
"strain_rates",
780 result->metadata(0) =
m_vars[0];
781 result->metadata(1) =
m_vars[1];
790 const auto &mask = *
m_grid->variables().get_2d_cell_type(
"mask");
802 m_vars[0].long_name(
"deviatoric stress in X direction").units(
"Pa");
803 m_vars[1].long_name(
"deviatoric stress in Y direction").units(
"Pa");
804 m_vars[2].long_name(
"deviatoric shear stress").units(
"Pa");
809 auto result = std::make_shared<array::Array2D<stressbalance::DeviatoricStresses> >(
811 result->metadata(0) =
m_vars[0];
812 result->metadata(1) =
m_vars[1];
813 result->metadata(2) =
m_vars[2];
828 const auto &mask = *
m_grid->variables().get_2d_cell_type(
"mask");
840 m_vars[0].long_name(
"pressure in ice (hydrostatic)").units(
"Pa");
845 std::shared_ptr<array::Array3D> result(
847 result->metadata(0) =
m_vars[0];
853 const double rg =
m_config->get_number(
"constants.ice.density") *
854 m_config->get_number(
"constants.standard_gravity");
858 for (
auto p =
m_grid->points(); p; p.next()) {
859 const int i = p.i(), j = p.j();
861 unsigned int ks =
m_grid->kBelowHeight((*thickness)(i, j));
862 double *P_out_ij = result->get_column(i, j);
863 const double H = (*thickness)(i, j);
865 for (
unsigned int k = 0;
k <= ks; ++
k) {
866 P_out_ij[
k] = rg * (H -
m_grid->z(
k));
869 for (
unsigned int k = ks + 1;
k <
m_grid->Mz(); ++
k) {
884 m_vars[0].long_name(
"shear stress xz component (in shallow ice approximation SIA)").units(
"Pa");
896 std::shared_ptr<array::Array3D> result(
898 result->metadata() =
m_vars[0];
902 thickness =
m_grid->variables().get_2d_scalar(
"land_ice_thickness");
903 surface =
m_grid->variables().get_2d_scalar(
"surface_altitude");
907 const double rg =
m_config->get_number(
"constants.ice.density") *
908 m_config->get_number(
"constants.standard_gravity");
912 for (
auto p =
m_grid->points(); p; p.next()) {
913 const int i = p.i(), j = p.j();
915 unsigned int ks =
m_grid->kBelowHeight((*thickness)(i, j));
916 double *tauxz_out_ij = result->get_column(i, j);
917 const double H = (*thickness)(i, j), dhdx =
diff_x_p(*surface, i, j);
920 for (
unsigned int k = 0;
k <= ks; ++
k) {
921 tauxz_out_ij[
k] = -rg * (H -
m_grid->z(
k)) * dhdx;
924 for (
unsigned int k = ks + 1;
k <
m_grid->Mz(); ++
k) {
925 tauxz_out_ij[
k] = 0.0;
939 m_vars[0].long_name(
"shear stress yz component (in shallow ice approximation SIA)").units(
"Pa");
951 std::shared_ptr<array::Array3D> result(
953 result->metadata(0) =
m_vars[0];
960 const double rg =
m_config->get_number(
"constants.ice.density") *
961 m_config->get_number(
"constants.standard_gravity");
965 for (
auto p =
m_grid->points(); p; p.next()) {
966 const int i = p.i(), j = p.j();
968 unsigned int ks =
m_grid->kBelowHeight((*thickness)(i, j));
969 double *tauyz_out_ij = result->get_column(i, j);
970 const double H = (*thickness)(i, j), dhdy =
diff_y_p(*surface, i, j);
973 for (
unsigned int k = 0;
k <= ks; ++
k) {
974 tauyz_out_ij[
k] = -rg * (H -
m_grid->z(
k)) * dhdy;
977 for (
unsigned int k = ks + 1;
k <
m_grid->Mz(); ++
k) {
978 tauyz_out_ij[
k] = 0.0;
991 m_vars[0].long_name(
"tensile von Mises stress").units(
"Pascal");
1000 auto result = allocate<array::Scalar>(
"vonmises_stress");
1009 const auto &strain_rates = *eigen12;
1011 const array::Scalar &ice_thickness = *
m_grid->variables().get_2d_scalar(
"land_ice_thickness");
1013 const auto &mask = *
m_grid->variables().get_2d_cell_type(
"mask");
1015 std::shared_ptr<const rheology::FlowLaw> flow_law;
1017 if (
m_config->get_flag(
"calving.vonmises_calving.use_custom_flow_law")) {
1020 flow_law = factory.
create();
1022 flow_law =
model->shallow()->flow_law();
1025 const double *z = &
m_grid->z()[0];
1027 double glen_exponent = flow_law->exponent();
1032 for (
auto pt =
m_grid->points(); pt; pt.next()) {
1033 const int i = pt.i(), j = pt.j();
1035 if (mask.icy(i, j)) {
1037 const double H = ice_thickness(i, j);
1038 const unsigned int k =
m_grid->kBelowHeight(H);
1041 *enthalpy_column = enthalpy->
get_column(i, j),
1043 eigen1 = strain_rates(i, j).eigen1,
1044 eigen2 = strain_rates(i, j).eigen2;
1047 const double effective_tensile_strain_rate = sqrt(0.5 * (pow(
max(0.0, eigen1), 2) +
1048 pow(
max(0.0, eigen2), 2)));
1050 vonmises_stress(i, j) = sqrt(3.0) * hardness * pow(effective_tensile_strain_rate,
1051 1.0 / glen_exponent);
1054 vonmises_stress(i, j) = 0.0;
const Config::ConstPtr m_config
configuration database used by this component
const StressBalance * model
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
double to_internal(double x) const
std::vector< SpatialVariableMetadata > m_vars
metadata corresponding to NetCDF variables
std::shared_ptr< Diagnostic > Ptr
std::shared_ptr< const Grid > m_grid
the grid
std::shared_ptr< array::Array > compute() const
Compute a diagnostic quantity and return a pointer to a newly-allocated Array.
const Config::ConstPtr m_config
Configuration flags and parameters.
std::shared_ptr< EnthalpyConverter > Ptr
void failed()
Indicates a failure of a parallel section.
This class represents a 2D vector field (such as ice velocity) at a certain grid point.
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
void copy_from(const Array2D< T > &source)
A storage vector combining related fields in a struct.
double * get_column(int i, int j)
A virtual class collecting methods common to ice and bedrock 3D fields.
std::shared_ptr< const Grid > grid() const
std::shared_ptr< FlowLaw > create()
virtual std::shared_ptr< array::Array > compute_impl() const
PSB_bfrict(const StressBalance *m)
Computes basal frictional heating.
PSB_deviatoric_stresses(const StressBalance *m)
virtual std::shared_ptr< array::Array > compute_impl() const
Reports the vertically-integrated (2D) deviatoric stresses.
virtual std::shared_ptr< array::Array > compute_impl() const
PSB_flux_mag(const StressBalance *m)
Computes flux_mag, the magnitude of vertically-integrated horizontal flux of ice.
PSB_flux(const StressBalance *m)
virtual std::shared_ptr< array::Array > compute_impl() const
Computes uflux and vflux, components of vertically-integrated horizontal flux of ice.
PSB_pressure(const StressBalance *m)
virtual std::shared_ptr< array::Array > compute_impl() const
Reports the pressure within the ice (3D).
virtual std::shared_ptr< array::Array > compute_impl() const
PSB_strain_rates(const StressBalance *m)
Reports the vertically-integrated (2D) principal strain rates.
PSB_strainheat(const StressBalance *m)
virtual std::shared_ptr< array::Array > compute_impl() const
Reports the volumetric strain heating (3D).
PSB_tauxz(const StressBalance *m)
virtual std::shared_ptr< array::Array > compute_impl() const
Reports the xz component of the shear stress within the ice (3D), according to the SIA formula.
virtual std::shared_ptr< array::Array > compute_impl() const
PSB_tauyz(const StressBalance *m)
Reports the yz component of the shear stress within the ice (3D), according to the SIA formula.
virtual std::shared_ptr< array::Array > compute_impl() const
PSB_uvel(const StressBalance *m)
Computes the x-component of the horizontal ice velocity.
virtual std::shared_ptr< array::Array > compute_impl() const
PSB_velbar_mag(const StressBalance *m)
Computes velbar_mag, the magnitude of vertically-integrated horizontal velocity of ice and masks out ...
virtual std::shared_ptr< array::Array > compute_impl() const
PSB_velbar(const StressBalance *m)
Computes the vertically-averaged ice velocity.
virtual std::shared_ptr< array::Array > compute_impl() const
PSB_velbase_mag(const StressBalance *m)
Computes velbase_mag, the magnitude of horizontal velocity of ice at base of ice and masks out ice-fr...
virtual std::shared_ptr< array::Array > compute_impl() const
PSB_velbase(const StressBalance *m)
Computes horizontal ice velocity at the base of ice.
PSB_velsurf_mag(const StressBalance *m)
virtual std::shared_ptr< array::Array > compute_impl() const
Computes velsurf_mag, the magnitude of horizontal ice velocity at the surface.
PSB_velsurf(const StressBalance *m)
virtual std::shared_ptr< array::Array > compute_impl() const
Computes velsurf, the horizontal velocity of ice at ice surface.
PSB_vonmises_stress(const StressBalance *m)
std::shared_ptr< array::Array > compute_impl() const
virtual std::shared_ptr< array::Array > compute_impl() const
PSB_vvel(const StressBalance *m)
Computes the y-component of the horizontal ice velocity.
PSB_wvel_rel(const StressBalance *m)
virtual std::shared_ptr< array::Array > compute_impl() const
Computes vertical velocity of ice, relative to the bed directly below.
virtual std::shared_ptr< array::Array > compute_impl() const
PSB_wvel(const StressBalance *m)
Computes vertical ice velocity (relative to the geoid).
virtual std::shared_ptr< array::Array > compute_impl() const
PSB_wvelbase(const StressBalance *m)
Computes wvelbase, the vertical velocity of ice at the base of ice.
virtual std::shared_ptr< array::Array > compute_impl() const
PSB_wvelsurf(const StressBalance *m)
Computes wvelsurf, the vertical velocity of ice at ice surface.
std::shared_ptr< SSB_Modifier > m_modifier
virtual TSDiagnosticList ts_diagnostics_impl() const
std::shared_ptr< ShallowStressBalance > m_shallow_stress_balance
virtual DiagnosticList diagnostics_impl() const
The class defining PISM's interface to the shallow stress balance code.
void extract_surface(const Array3D &data, double z, Scalar &output)
Copies a horizontal slice at level z of an Array3D into output.
void apply_mask(const array::Scalar &M, double fill, array::Scalar &result)
Masks out all the areas where by setting them to fill.
double max(const array::Scalar &input)
Finds maximum over all the values in an array::Scalar object. Ignores ghosts.
double diff_x_p(const array::Scalar &array, int i, int j)
Returns the x-derivative at i,j approximated using centered finite differences. Respects grid periodi...
void compute_magnitude(const array::Vector &input, array::Scalar &result)
double diff_y_p(const array::Scalar &array, int i, int j)
Returns the y-derivative at i,j approximated using centered finite differences. Respects grid periodi...
void averaged_hardness_vec(const FlowLaw &ice, const array::Scalar &thickness, const array::Array3D &enthalpy, array::Scalar &result)
double averaged_hardness(const FlowLaw &ice, double thickness, unsigned int kbelowH, const double *zlevels, const double *enthalpy)
Computes vertical average of B(E, p) ice hardness, namely .
void compute_2D_principal_strain_rates(const array::Vector1 &V, const array::CellType1 &mask, array::Array2D< PrincipalStrainRates > &result)
Compute eigenvalues of the horizontal, vertically-integrated strain rate tensor.
static void zero_above_ice(const array::Array3D &F, const array::Scalar &H, array::Array3D &result)
void compute_2D_stresses(const rheology::FlowLaw &flow_law, const array::Vector1 &velocity, const array::Scalar &hardness, const array::CellType1 &cell_type, array::Array2D< DeviatoricStresses > &result)
Compute 2D deviatoric stresses.
static double F(double SL, double B, double H, double alpha)
std::map< std::string, TSDiagnostic::Ptr > TSDiagnosticList
std::map< std::string, Diagnostic::Ptr > DiagnosticList
T combine(const T &a, const T &b)