PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
GoldsbyKohlstedt.cc
Go to the documentation of this file.
1 /* Copyright (C) 2015, 2016, 2021, 2023 PISM Authors
2  *
3  * This file is part of PISM.
4  *
5  * PISM is free software; you can redistribute it and/or modify it under the
6  * terms of the GNU General Public License as published by the Free Software
7  * Foundation; either version 3 of the License, or (at your option) any later
8  * version.
9  *
10  * PISM is distributed in the hope that it will be useful, but WITHOUT ANY
11  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13  * details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with PISM; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #include "pism/rheology/GoldsbyKohlstedt.hh"
21 #include <cmath> // for pow, exp, fabs, M_PI
22 #include <memory> // for __shared_ptr_access
23 #include <stdexcept> // for runtime_error
24 
25 namespace pism {
26 namespace rheology {
27 
28 // Goldsby-Kohlstedt (forward) ice flow law
29 
30 GoldsbyKohlstedt::GoldsbyKohlstedt(const std::string &prefix,
31  const Config &config, EnthalpyConverter::Ptr ec)
32  : FlowLaw(prefix, config, ec) {
33  m_name = "Goldsby-Kohlstedt / Paterson-Budd (hybrid)";
34 
35  m_V_act_vol = -13.e-6; // m^3/mol
36  m_d_grain_size = 1.0e-3; // m (see p. ?? of G&K paper)
37  //--- dislocation creep ---
38  m_disl_crit_temp = 258.0; // Kelvin
39  //disl_A_cold = 4.0e5; // MPa^{-4.0} s^{-1}
40  //disl_A_warm = 6.0e28; // MPa^{-4.0} s^{-1}
41  m_disl_A_cold = 4.0e-19; // Pa^{-4.0} s^{-1}
42  m_disl_A_warm = 6.0e4; // Pa^{-4.0} s^{-1} (GK)
43  m_disl_n = 4.0; // stress exponent
44  m_disl_Q_cold = 60.e3; // J/mol Activation energy
45  m_disl_Q_warm = 180.e3; // J/mol Activation energy (GK)
46  //--- grain boundary sliding ---
47  m_gbs_crit_temp = 255.0; // Kelvin
48  //gbs_A_cold = 3.9e-3; // MPa^{-1.8} m^{1.4} s^{-1}
49  //gbs_A_warm = 3.e26; // MPa^{-1.8} m^{1.4} s^{-1}
50  m_gbs_A_cold = 6.1811e-14; // Pa^{-1.8} m^{1.4} s^{-1}
51  m_gbs_A_warm = 4.7547e15; // Pa^{-1.8} m^{1.4} s^{-1}
52  m_gbs_n = 1.8; // stress exponent
53  m_gbs_Q_cold = 49.e3; // J/mol Activation energy
54  m_gbs_Q_warm = 192.e3; // J/mol Activation energy
55  m_p_grain_sz_exp = 1.4; // from Peltier
56  //--- easy slip (basal) ---
57  //basal_A = 5.5e7; // MPa^{-2.4} s^{-1}
58  m_basal_A = 2.1896e-7; // Pa^{-2.4} s^{-1}
59  m_basal_n = 2.4; // stress exponent
60  m_basal_Q = 60.e3; // J/mol Activation energy
61  //--- diffusional flow ---
62  m_diff_crit_temp = 258.0; // when to use enhancement factor
63  m_diff_V_m = 1.97e-5; // Molar volume (m^3/mol)
64  m_diff_D_0v = 9.10e-4; // Preexponential volume diffusion (m^2 second-1)
65  m_diff_Q_v = 59.4e3; // activation energy, vol. diff. (J/mol)
66  m_diff_D_0b = 5.8e-4; // preexponential grain boundary coeff.
67  m_diff_Q_b = 49.e3; // activation energy, g.b. (J/mol)
68  m_diff_delta = 9.04e-10; // grain boundary width (m)
69 }
70 
71 double GoldsbyKohlstedt::flow_impl(double stress, double E,
72  double pressure, double grainsize) const {
73  double temp = m_EC->temperature(E, pressure);
74  return flow_from_temp(stress, temp, pressure, grainsize);
75 }
76 
77 double GoldsbyKohlstedt::hardness_impl(double enthalpy, double pressure) const {
78 
79  // We use the Paterson-Budd relation for the hardness parameter. It would be nice if we didn't
80  // have to, but we currently need ice hardness to compute the strain heating. See
81  // SIAFD::compute_volumetric_strain_heating().
82  double
83  T_pa = m_EC->pressure_adjusted_temperature(enthalpy, pressure),
84  A = softness_paterson_budd(T_pa);
85 
86  return pow(A, m_hardness_power);
87 }
88 
89 double GoldsbyKohlstedt::softness_impl(double , double) const {
90  throw std::runtime_error("double GoldsbyKohlstedt::softness is not implemented");
91 
92 #ifndef __GNUC__
93  return 0;
94 #endif
95 }
96 
97 /*!
98  This is the (forward) Goldsby-Kohlstedt flow law. See:
99  D. L. Goldsby & D. L. Kohlstedt (2001), "Superplastic deformation
100  of ice: experimental observations", J. Geophys. Res. 106(M6), 11017-11030.
101 */
102 double GoldsbyKohlstedt::flow_from_temp(double stress, double temp,
103  double pressure, double gs) const {
104  double eps_diff, eps_disl, eps_basal, eps_gbs, diff_D_b;
105 
106  if (fabs(stress) < 1e-10) {
107  return 0;
108  }
109  const double T = temp + (m_beta_CC_grad / (m_rho * m_standard_gravity)) * pressure;
110  const double pV = pressure * m_V_act_vol;
111  const double RT = m_ideal_gas_constant * T;
112  // Diffusional Flow
113  const double diff_D_v = m_diff_D_0v * exp(-m_diff_Q_v/RT);
114  diff_D_b = m_diff_D_0b * exp(-m_diff_Q_b/RT);
115  if (T > m_diff_crit_temp) {
116  diff_D_b *= 1000; // Coble creep scaling
117  }
118  eps_diff = 42 * m_diff_V_m *
119  (diff_D_v + M_PI * m_diff_delta * diff_D_b / gs) / (RT*(gs*gs));
120  // Dislocation Creep
121  if (T > m_disl_crit_temp) {
122  eps_disl = m_disl_A_warm * pow(stress, m_disl_n-1) * exp(-(m_disl_Q_warm + pV)/RT);
123  } else {
124  eps_disl = m_disl_A_cold * pow(stress, m_disl_n-1) * exp(-(m_disl_Q_cold + pV)/RT);
125  }
126  // Basal Slip
127  eps_basal = m_basal_A * pow(stress, m_basal_n-1) * exp(-(m_basal_Q + pV)/RT);
128  // Grain Boundary Sliding
129  if (T > m_gbs_crit_temp) {
130  eps_gbs = m_gbs_A_warm * (pow(stress, m_gbs_n-1) / pow(gs, m_p_grain_sz_exp)) *
131  exp(-(m_gbs_Q_warm + pV)/RT);
132  } else {
133  eps_gbs = m_gbs_A_cold * (pow(stress, m_gbs_n-1) / pow(gs, m_p_grain_sz_exp)) *
134  exp(-(m_gbs_Q_cold + pV)/RT);
135  }
136 
137  return eps_diff + eps_disl + (eps_basal * eps_gbs) / (eps_basal + eps_gbs);
138 }
139 
140 
141 /*****************
142 THE NEXT PROCEDURE REPEATS CODE; INTENDED ONLY FOR DEBUGGING
143 *****************/
144 GKparts GoldsbyKohlstedt::flowParts(double stress, double temp, double pressure) const {
145  double gs, eps_diff, eps_disl, eps_basal, eps_gbs, diff_D_b;
146  GKparts p;
147 
148  if (fabs(stress) < 1e-10) {
149  p.eps_total=0.0;
150  p.eps_diff=0.0; p.eps_disl=0.0; p.eps_gbs=0.0; p.eps_basal=0.0;
151  return p;
152  }
153  const double T = temp + (m_beta_CC_grad / (m_rho * m_standard_gravity)) * pressure;
154  const double pV = pressure * m_V_act_vol;
155  const double RT = m_ideal_gas_constant * T;
156  // Diffusional Flow
157  const double diff_D_v = m_diff_D_0v * exp(-m_diff_Q_v/RT);
158  diff_D_b = m_diff_D_0b * exp(-m_diff_Q_b/RT);
159  if (T > m_diff_crit_temp) {
160  diff_D_b *= 1000; // Coble creep scaling
161  }
162  gs = m_d_grain_size;
163  eps_diff = 14 * m_diff_V_m *
164  (diff_D_v + M_PI * m_diff_delta * diff_D_b / gs) / (RT*(gs*gs));
165  // Dislocation Creep
166  if (T > m_disl_crit_temp) {
167  eps_disl = m_disl_A_warm * pow(stress, m_disl_n-1) * exp(-(m_disl_Q_warm + pV)/RT);
168  } else {
169  eps_disl = m_disl_A_cold * pow(stress, m_disl_n-1) * exp(-(m_disl_Q_cold + pV)/RT);
170  }
171  // Basal Slip
172  eps_basal = m_basal_A * pow(stress, m_basal_n-1) * exp(-(m_basal_Q + pV)/RT);
173  // Grain Boundary Sliding
174  if (T > m_gbs_crit_temp) {
175  eps_gbs = m_gbs_A_warm * (pow(stress, m_gbs_n-1) / pow(gs, m_p_grain_sz_exp)) *
176  exp(-(m_gbs_Q_warm + pV)/RT);
177  } else {
178  eps_gbs = m_gbs_A_cold * (pow(stress, m_gbs_n-1) / pow(gs, m_p_grain_sz_exp)) *
179  exp(-(m_gbs_Q_cold + pV)/RT);
180  }
181 
182  p.eps_diff=eps_diff;
183  p.eps_disl=eps_disl;
184  p.eps_basal=eps_basal;
185  p.eps_gbs=eps_gbs;
186  p.eps_total=eps_diff + eps_disl + (eps_basal * eps_gbs) / (eps_basal + eps_gbs);
187  return p;
188 }
189 /*****************/
190 
192  const Config &config,
194  : GoldsbyKohlstedt(prefix, config, ec) {
195  m_name = "Goldsby-Kohlstedt / Paterson-Budd (hybrid, simplified)";
196 
197  m_d_grain_size_stripped = 3.0e-3; // m; = 3mm (see Peltier et al 2000 paper)
198 }
199 
200 
201 double GoldsbyKohlstedtStripped::flow_from_temp(double stress, double temp, double pressure, double) const {
202  // note value of gs is ignored
203  // note pressure only effects the temperature; the "P V" term is dropped
204  // note no diffusional flow
205  double eps_disl, eps_basal, eps_gbs;
206 
207  if (fabs(stress) < 1e-10) {
208  return 0;
209  }
210  const double T = temp + (m_beta_CC_grad / (m_rho * m_standard_gravity)) * pressure;
211  const double RT = m_ideal_gas_constant * T;
212  // NO Diffusional Flow
213  // Dislocation Creep
214  if (T > m_disl_crit_temp) {
215  eps_disl = m_disl_A_warm * pow(stress, m_disl_n-1) * exp(-m_disl_Q_warm/RT);
216  } else {
217  eps_disl = m_disl_A_cold * pow(stress, m_disl_n-1) * exp(-m_disl_Q_cold/RT);
218  }
219  // Basal Slip
220  eps_basal = m_basal_A * pow(stress, m_basal_n-1) * exp(-m_basal_Q/RT);
221  // Grain Boundary Sliding
222  if (T > m_gbs_crit_temp) {
223  eps_gbs = m_gbs_A_warm *
224  (pow(stress, m_gbs_n-1) / pow(m_d_grain_size_stripped, m_p_grain_sz_exp)) *
225  exp(-m_gbs_Q_warm/RT);
226  } else {
227  eps_gbs = m_gbs_A_cold *
228  (pow(stress, m_gbs_n-1) / pow(m_d_grain_size_stripped, m_p_grain_sz_exp)) *
229  exp(-m_gbs_Q_cold/RT);
230  }
231 
232  return eps_disl + (eps_basal * eps_gbs) / (eps_basal + eps_gbs);
233 }
234 
235 
236 } // end of namespace rheology
237 } // end of namespace pism
A class for storing and accessing PISM configuration flags and parameters.
std::shared_ptr< EnthalpyConverter > Ptr
double softness_paterson_budd(double T_pa) const
Return the softness parameter A(T) for a given temperature T.
Definition: FlowLaw.cc:80
double m_standard_gravity
acceleration due to gravity
Definition: FlowLaw.hh:150
std::string m_name
Definition: FlowLaw.hh:117
double m_rho
ice density
Definition: FlowLaw.hh:120
double m_hardness_power
; used to compute hardness
Definition: FlowLaw.hh:136
double m_beta_CC_grad
Clausius-Clapeyron gradient.
Definition: FlowLaw.hh:122
double m_ideal_gas_constant
ideal gas constant
Definition: FlowLaw.hh:152
EnthalpyConverter::Ptr m_EC
Definition: FlowLaw.hh:126
virtual double flow_from_temp(double stress, double temp, double pressure, double gs) const
GoldsbyKohlstedtStripped(const std::string &prefix, const Config &config, EnthalpyConverter::Ptr EC)
virtual double flow_impl(double stress, double E, double pressure, double grainsize) const
double hardness_impl(double E, double p) const
double softness_impl(double E, double p) const __attribute__((noreturn))
GKparts flowParts(double stress, double temp, double pressure) const
virtual double flow_from_temp(double stress, double temp, double pressure, double gs) const
GoldsbyKohlstedt(const std::string &prefix, const Config &config, EnthalpyConverter::Ptr EC)
A hybrid of Goldsby-Kohlstedt (2001) ice (constitutive form) and Paterson-Budd (1982)-Glen (viscosity...