PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
FractureDensity.cc
Go to the documentation of this file.
1 /* Copyright (C) 2019, 2020, 2021, 2022, 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 <algorithm> // std::min, std::max
21 #include <cmath> // std::pow
22 
23 #include "pism/fracturedensity/FractureDensity.hh"
24 #include "pism/geometry/Geometry.hh"
25 #include "pism/stressbalance/StressBalance.hh"
26 #include "pism/util/pism_utilities.hh"
27 
28 namespace pism {
29 
30 FractureDensity::FractureDensity(std::shared_ptr<const Grid> grid,
31  std::shared_ptr<const rheology::FlowLaw> flow_law)
32  : Component(grid),
33  m_density(grid, "fracture_density"),
34  m_density_new(grid, "new_fracture_density"),
35  m_growth_rate(grid, "fracture_growth_rate"),
36  m_healing_rate(grid, "fracture_healing_rate"),
37  m_flow_enhancement(grid, "fracture_flow_enhancement"),
38  m_age(grid, "fracture_age"),
39  m_age_new(grid, "new_fracture_age"),
40  m_toughness(grid, "fracture_toughness"),
41  m_strain_rates(grid, "strain_rates", array::WITHOUT_GHOSTS),
42  m_deviatoric_stresses(grid, "sigma", array::WITHOUT_GHOSTS, 3),
43  m_velocity(grid, "ghosted_velocity"),
44  m_flow_law(flow_law) {
45 
46  m_density.metadata(0).long_name("fracture density in ice shelf").units("1");
47  m_density.metadata()["valid_max"] = { 1.0 };
48  m_density.metadata()["valid_min"] = { 0.0 };
49 
51  .long_name("fracture growth rate")
52  .units("second-1");
53  m_growth_rate.metadata()["valid_min"] = { 0.0 };
54 
56  .long_name("fracture healing rate")
57  .units("second-1");
58 
60  .long_name("fracture-induced flow enhancement");
61 
62  m_age.metadata(0)
63  .long_name("age since fracturing")
64  .units("seconds");
65 
67  .long_name("fracture toughness")
68  .units("Pa");
69 
70  m_strain_rates.metadata(0).set_name("eigen1");
71  m_strain_rates.metadata(0)
72  .long_name("major principal component of horizontal strain-rate")
73  .units("second-1");
74 
75  m_strain_rates.metadata(1).set_name("eigen2");
76  m_strain_rates.metadata(1)
77  .long_name("minor principal component of horizontal strain-rate")
78  .units("second-1");
79 
80  m_deviatoric_stresses.metadata(0).set_name("sigma_xx");
81  m_deviatoric_stresses.metadata(0).long_name("deviatoric stress in x direction").units("Pa");
82 
83  m_deviatoric_stresses.metadata(1).set_name("sigma_yy");
84  m_deviatoric_stresses.metadata(1).long_name("deviatoric stress in y direction").units("Pa");
85 
86  m_deviatoric_stresses.metadata(2).set_name("sigma_xy");
87  m_deviatoric_stresses.metadata(2).long_name("deviatoric shear stress").units("Pa");
88 }
89 
90 void FractureDensity::restart(const File &input_file, int record) {
91  m_log->message(2, "* Restarting the fracture density model from %s...\n",
92  input_file.filename().c_str());
93 
94  m_density.read(input_file, record);
95  m_age.read(input_file, record);
96 
97  regrid("Fracture density model", m_density, REGRID_WITHOUT_REGRID_VARS);
98  regrid("Fracture density model", m_age, REGRID_WITHOUT_REGRID_VARS);
99 }
100 
101 void FractureDensity::bootstrap(const File &input_file) {
102  m_log->message(2, "* Bootstrapping the fracture density model from %s...\n",
103  input_file.filename().c_str());
104 
105  m_density.regrid(input_file, io::Default(0.0));
106  m_age.regrid(input_file, io::Default(0.0));
107 }
108 
110  const array::Scalar &age) {
113 }
114 
116  m_density.set(0.0);
117  m_age.set(0.0);
118 }
119 
122  m_age.define(output, io::PISM_DOUBLE);
123 }
124 
126  m_density.write(output);
127  m_age.write(output);
128 }
129 
130 void FractureDensity::update(double dt,
131  const Geometry &geometry,
132  const array::Vector &velocity,
133  const array::Scalar &hardness,
134  const array::Scalar &bc_mask) {
135  using std::pow;
136 
137  const double
138  dx = m_grid->dx(),
139  dy = m_grid->dy();
140  const int
141  Mx = m_grid->Mx(),
142  My = m_grid->My();
143 
145  &A = m_age;
147  &D = m_density,
148  &D_new = m_density_new,
149  &A_new = m_age_new;
150 
151  m_velocity.copy_from(velocity);
152 
154  geometry.cell_type,
156 
158  m_velocity,
159  hardness,
160  geometry.cell_type,
162 
164  &D, &D_new, &geometry.cell_type, &bc_mask, &A, &A_new,
166  &m_toughness, &hardness, &geometry.ice_thickness};
167 
168  D_new.copy_from(D);
169 
170  //options
171  /////////////////////////////////////////////////////////
172  double soft_residual = m_config->get_number("fracture_density.softening_lower_limit");
173  // assume linear response function: E_fr = (1-(1-soft_residual)*phi) -> 1-phi
174  //
175  // See the following article for more:
176  //
177  // Albrecht, T. / Levermann, A.
178  // Fracture-induced softening for large-scale ice dynamics
179  // 2014-04
180  //
181  // The Cryosphere , Vol. 8, No. 2
182  // Copernicus GmbH
183  // p. 587-605
184  //
185  // doi:10.5194/tc-8-587-2014
186  //
187  // get four options for calculation of fracture density.
188  // 1st: fracture growth constant gamma
189  // 2nd: fracture initiation stress threshold sigma_cr
190  // 3rd: healing rate constant gamma_h
191  // 4th: healing strain rate threshold
192  //
193  // more: T. Albrecht, A. Levermann; Fracture field for large-scale
194  // ice dynamics; (2012), Journal of Glaciology, Vol. 58, No. 207,
195  // 165-176, DOI: 10.3189/2012JoG11J191.
196 
197  double gamma = m_config->get_number("fracture_density.gamma");
198  double initThreshold = m_config->get_number("fracture_density.initiation_threshold");
199  double gammaheal = m_config->get_number("fracture_density.gamma_h");
200  double healThreshold = m_config->get_number("fracture_density.healing_threshold");
201 
202  m_log->message(3, "PISM-PIK INFO: fracture density is found with parameters:\n"
203  " gamma=%.2f, sigma_cr=%.2f, gammah=%.2f, healing_cr=%.1e and soft_res=%f \n",
204  gamma, initThreshold, gammaheal, healThreshold, soft_residual);
205 
206  bool do_fracground = m_config->get_flag("fracture_density.include_grounded_ice");
207 
208  double fdBoundaryValue = m_config->get_number("fracture_density.phi0");
209 
210  bool constant_healing = m_config->get_flag("fracture_density.constant_healing");
211 
212  bool fracture_weighted_healing = m_config->get_flag("fracture_density.fracture_weighted_healing");
213 
214  bool max_shear_stress = m_config->get_flag("fracture_density.max_shear_stress");
215 
216  bool lefm = m_config->get_flag("fracture_density.lefm");
217 
218  bool constant_fd = m_config->get_flag("fracture_density.constant_fd");
219 
220  bool fd2d_scheme = m_config->get_flag("fracture_density.fd2d_scheme");
221 
222  double glen_exponent = m_flow_law->exponent();
223 
224  bool borstad_limit = m_config->get_flag("fracture_density.borstad_limit");
225 
226  double minH = m_config->get_number("stress_balance.ice_free_thickness_standard");
227 
228  for (auto p = m_grid->points(); p; p.next()) {
229  const int i = p.i(), j = p.j();
230 
231  double tempFD = 0.0;
232 
233  double u = m_velocity(i, j).u;
234  double v = m_velocity(i, j).v;
235 
236  if (fd2d_scheme) {
237  if (u >= dx * v / dy and v >= 0.0) { //1
238  tempFD = u * (D(i, j) - D(i - 1, j)) / dx + v * (D(i - 1, j) - D(i - 1, j - 1)) / dy;
239  } else if (u <= dx * v / dy and u >= 0.0) { //2
240  tempFD = u * (D(i, j - 1) - D(i - 1, j - 1)) / dx + v * (D(i, j) - D(i, j - 1)) / dy;
241  } else if (u >= -dx * v / dy and u <= 0.0) { //3
242  tempFD = -u * (D(i, j - 1) - D(i + 1, j - 1)) / dx + v * (D(i, j) - D(i, j - 1)) / dy;
243  } else if (u <= -dx * v / dy and v >= 0.0) { //4
244  tempFD = -u * (D(i, j) - D(i + 1, j)) / dx + v * (D(i + 1, j) - D(i + 1, j - 1)) / dy;
245  } else if (u <= dx * v / dy and v <= 0.0) { //5
246  tempFD = -u * (D(i, j) - D(i + 1, j)) / dx - v * (D(i + 1, j) - D(i + 1, j + 1)) / dy;
247  } else if (u >= dx * v / dy and u <= 0.0) { //6
248  tempFD = -u * (D(i, j + 1) - D(i + 1, j + 1)) / dx - v * (D(i, j) - D(i, j + 1)) / dy;
249  } else if (u <= -dx * v / dy and u >= 0.0) { //7
250  tempFD = u * (D(i, j + 1) - D(i - 1, j + 1)) / dx - v * (D(i, j) - D(i, j + 1)) / dy;
251  } else if (u >= -dx * v / dy and v <= 0.0) { //8
252  tempFD = u * (D(i, j) - D(i - 1, j)) / dx - v * (D(i - 1, j) - D(i - 1, j + 1)) / dy;
253  } else {
254  m_log->message(3, "######### missing case of angle %f of %f and %f at %d, %d \n",
255  atan(v / u) / M_PI * 180., u * 3e7, v * 3e7, i, j);
256  }
257  } else {
258  tempFD += u * (u < 0 ? D(i + 1, j) - D(i, j) : D(i, j) - D(i - 1, j)) / dx;
259  tempFD += v * (v < 0 ? D(i, j + 1) - D(i, j) : D(i, j) - D(i, j - 1)) / dy;
260  }
261 
262  D_new(i, j) -= tempFD * dt;
263 
264  //sources /////////////////////////////////////////////////////////////////
265  ///von mises criterion
266 
267  double
268  txx = m_deviatoric_stresses(i, j).xx,
269  tyy = m_deviatoric_stresses(i, j).yy,
270  txy = m_deviatoric_stresses(i, j).xy,
271  T1 = 0.5 * (txx + tyy) + sqrt(0.25 * pow(txx - tyy, 2) + pow(txy, 2)), //Pa
272  T2 = 0.5 * (txx + tyy) - sqrt(0.25 * pow(txx - tyy, 2) + pow(txy, 2)), //Pa
273  sigmat = sqrt(pow(T1, 2) + pow(T2, 2) - T1 * T2);
274 
275 
276  ///max shear stress criterion (more stringent than von mises)
277  if (max_shear_stress) {
278  double maxshear = fabs(T1);
279  maxshear = std::max(maxshear, fabs(T2));
280  maxshear = std::max(maxshear, fabs(T1 - T2));
281 
282  sigmat = maxshear;
283  }
284 
285  ///lefm mixed-mode criterion
286  if (lefm) {
287  double sigmamu = 0.1; //friction coefficient between crack faces
288 
289  double sigmac = 0.64 / M_PI; //initial crack depth 20cm
290 
291  double sigmabetatest, sigmanor, sigmatau, Kone, Ktwo, KSI, KSImax = 0.0, sigmatetanull;
292 
293  for (int l = 46; l <= 90; ++l) { //optimize for various precursor angles beta
294  sigmabetatest = l * M_PI / 180.0;
295 
296  //rist_sammonds99
297  sigmanor = 0.5 * (T1 + T2) - (T1 - T2) * cos(2 * sigmabetatest);
298  sigmatau = 0.5 * (T1 - T2) * sin(2 * sigmabetatest);
299  //shayam_wu90
300  if (sigmamu * sigmanor < 0.0) { //compressive case
301  if (fabs(sigmatau) <= fabs(sigmamu * sigmanor)) {
302  sigmatau = 0.0;
303  } else {
304  if (sigmatau > 0) { //coulomb friction opposing sliding
305  sigmatau += (sigmamu * sigmanor);
306  } else {
307  sigmatau -= (sigmamu * sigmanor);
308  }
309  }
310  }
311 
312  //stress intensity factors
313  Kone = sigmanor * sqrt(M_PI * sigmac); //normal
314  Ktwo = sigmatau * sqrt(M_PI * sigmac); //shear
315 
316  if (Ktwo == 0.0) {
317  sigmatetanull = 0.0;
318  } else { //eq15 in hulbe_ledoux10 or eq15 shayam_wu90
319  sigmatetanull = -2.0 * atan((sqrt(pow(Kone, 2) + 8.0 * pow(Ktwo, 2)) - Kone) / (4.0 * Ktwo));
320  }
321 
322  KSI = cos(0.5 * sigmatetanull) *
323  (Kone * cos(0.5 * sigmatetanull) * cos(0.5 * sigmatetanull) - 0.5 * 3.0 * Ktwo * sin(sigmatetanull));
324  // mode I stress intensity
325 
326  KSImax = std::max(KSI, KSImax);
327  }
328  sigmat = KSImax;
329  }
330 
331  //////////////////////////////////////////////////////////////////////////////
332 
333  // fracture density
334  double fdnew = 0.0;
335  if (borstad_limit) {
336  if (geometry.ice_thickness(i, j) > minH) {
337  // mean parameters from paper
338  double t0 = initThreshold;
339  double kappa = 2.8;
340 
341  // effective strain rate
342  double e1 = m_strain_rates(i, j).eigen1;
343  double e2 = m_strain_rates(i, j).eigen2;
344  double ee = sqrt(pow(e1, 2.0) + pow(e2, 2.0) - e1 * e2);
345 
346  // threshold for unfractured ice
347  double e0 = pow((t0 / hardness(i, j)), glen_exponent);
348 
349  // threshold for fractured ice (exponential law)
350  double ex = exp((e0 - ee) / (e0 * (kappa - 1)));
351 
352  // stress threshold for fractures ice
353  double te = t0 * ex;
354 
355  // actual effective stress
356  double ts = hardness(i, j) * pow(ee, 1.0 / glen_exponent) * (1 - D_new(i, j));
357 
358  // fracture formation if threshold is hit
359  if (ts > te and ee > e0) {
360  // new fracture density:
361  fdnew = 1.0 - (ex * pow((ee / e0), -1 / glen_exponent));
362  D_new(i, j) = fdnew;
363  }
364  }
365  } else {
366  fdnew = gamma * (m_strain_rates(i, j).eigen1 - 0.0) * (1 - D_new(i, j));
367  if (sigmat > initThreshold) {
368  D_new(i, j) += fdnew * dt;
369  }
370  }
371 
372  //healing
373  double fdheal = gammaheal * std::min(0.0, (m_strain_rates(i, j).eigen1 - healThreshold));
374  if (geometry.cell_type.icy(i, j)) {
375  if (constant_healing) {
376  fdheal = gammaheal * (-healThreshold);
377  if (fracture_weighted_healing) {
378  D_new(i, j) += fdheal * dt * (1 - D(i, j));
379  } else {
380  D_new(i, j) += fdheal * dt;
381  }
382  } else if (m_strain_rates(i, j).eigen1 < healThreshold) {
383  if (fracture_weighted_healing) {
384  D_new(i, j) += fdheal * dt * (1 - D(i, j));
385  } else {
386  D_new(i, j) += fdheal * dt;
387  }
388  }
389  }
390 
391  // bounding
392  D_new(i, j) = pism::clip(D_new(i, j), 0.0, 1.0);
393 
394  if (geometry.cell_type.icy(i, j)) {
395  //fracture toughness
396  m_toughness(i, j) = sigmat;
397 
398  // fracture growth rate
399  if (sigmat > initThreshold) {
400  m_growth_rate(i, j) = fdnew;
401  //m_growth_rate(i,j)=gamma*(vPrinStrain1(i,j)-0.0)*(1-D_new(i,j));
402  } else {
403  m_growth_rate(i, j) = 0.0;
404  }
405 
406  // fracture healing rate
407  if (geometry.cell_type.icy(i, j)) {
408  if (constant_healing or (m_strain_rates(i, j).eigen1 < healThreshold)) {
409  if (fracture_weighted_healing) {
410  m_healing_rate(i, j) = fdheal * (1 - D(i, j));
411  } else {
412  m_healing_rate(i, j) = fdheal;
413  }
414  } else {
415  m_healing_rate(i, j) = 0.0;
416  }
417  }
418 
419  // fracture age since fracturing occurred
420  {
421  auto a = A.star(i, j);
422  A_new(i, j) -= dt * u * (u < 0 ? a.e - a.c : a.c - a.w) / dx;
423  A_new(i, j) -= dt * v * (v < 0 ? a.n - a.c : a.c - a.s) / dy;
424  A_new(i, j) += dt;
425  if (sigmat > initThreshold) {
426  A_new(i, j) = 0.0;
427  }
428  }
429 
430  // additional flow enhancement due to fracture softening
431  double softening = pow((1.0 - (1.0 - soft_residual) * D_new(i, j)), -glen_exponent);
432  if (geometry.cell_type.icy(i, j)) {
433  m_flow_enhancement(i, j) = 1.0 / pow(softening, 1 / glen_exponent);
434  } else {
435  m_flow_enhancement(i, j) = 1.0;
436  }
437  }
438 
439  // boundary condition
440  if (geometry.cell_type.grounded(i, j) and not do_fracground) {
441 
442  if (bc_mask(i, j) > 0.5) {
443  D_new(i, j) = fdBoundaryValue;
444 
445  {
446  A_new(i, j) = 0.0;
447  m_growth_rate(i, j) = 0.0;
448  m_healing_rate(i, j) = 0.0;
449  m_flow_enhancement(i, j) = 1.0;
450  m_toughness(i, j) = 0.0;
451  }
452  }
453  }
454 
455  // ice free regions and boundary of computational domain
456  if (geometry.cell_type.ice_free(i, j) or i == 0 or j == 0 or i == Mx - 1 or j == My - 1) {
457 
458  D_new(i, j) = 0.0;
459 
460  {
461  A_new(i, j) = 0.0;
462  m_growth_rate(i, j) = 0.0;
463  m_healing_rate(i, j) = 0.0;
464  m_flow_enhancement(i, j) = 1.0;
465  m_toughness(i, j) = 0.0;
466  }
467  }
468 
469  if (constant_fd) { // no fd evolution
470  D_new(i, j) = D(i, j);
471  }
472  }
473 
474  A.copy_from(A_new);
475  D.copy_from(D_new);
476 }
477 
479  return {{"fracture_density", Diagnostic::wrap(m_density)},
480  {"fracture_growth_rate", Diagnostic::wrap(m_growth_rate)},
481  {"fracture_healing_rate", Diagnostic::wrap(m_healing_rate)},
482  {"fracture_flow_enhancement", Diagnostic::wrap(m_flow_enhancement)},
483  {"fracture_age", Diagnostic::wrap(m_age)},
484  {"fracture_toughness", Diagnostic::wrap(m_toughness)}
485  };
486 }
487 
489  return m_density;
490 }
491 
493  return m_growth_rate;
494 }
495 
497  return m_healing_rate;
498 }
499 
501  return m_flow_enhancement;
502 }
503 
505  return m_age;
506 }
507 
509  return m_toughness;
510 }
511 
512 } // end of namespace pism
const Config::ConstPtr m_config
configuration database used by this component
Definition: Component.hh:158
const Logger::ConstPtr m_log
logger (for easy access)
Definition: Component.hh:162
@ REGRID_WITHOUT_REGRID_VARS
Definition: Component.hh:151
const std::shared_ptr< const Grid > m_grid
grid used by this component
Definition: Component.hh:156
void regrid(const std::string &module_name, array::Array &variable, RegriddingFlag flag=NO_REGRID_WITHOUT_REGRID_VARS)
Definition: Component.cc:159
A class defining a common interface for most PISM sub-models.
Definition: Component.hh:118
static Ptr wrap(const T &input)
Definition: Diagnostic.hh:160
std::string filename() const
Definition: File.cc:307
High-level PISM I/O class.
Definition: File.hh:56
void define_model_state_impl(const File &output) const
The default (empty implementation).
void restart(const File &input_file, int record)
void update(double dt, const Geometry &geometry, const array::Vector &velocity, const array::Scalar &hardness, const array::Scalar &inflow_boundary_mask)
FractureDensity(std::shared_ptr< const Grid > grid, std::shared_ptr< const rheology::FlowLaw > flow_law)
array::Array2D< stressbalance::DeviatoricStresses > m_deviatoric_stresses
components of horizontal stress tensor along axes and shear stress (temporary storage)
array::Scalar m_density_new
const array::Scalar & toughness() const
const array::Scalar & growth_rate() const
array::Array2D< stressbalance::PrincipalStrainRates > m_strain_rates
major and minor principal components of horizontal strain-rate tensor (temporary storage)
const array::Scalar & age() const
array::Scalar m_healing_rate
void bootstrap(const File &input_file)
void write_model_state_impl(const File &output) const
The default (empty implementation).
std::shared_ptr< const rheology::FlowLaw > m_flow_law
array::Scalar1 m_density
array::Scalar m_growth_rate
const array::Scalar & healing_rate() const
const array::Scalar & flow_enhancement() const
DiagnosticList diagnostics_impl() const
array::Scalar m_toughness
array::Scalar m_flow_enhancement
const array::Scalar & density() const
array::Vector1 m_velocity
Ghosted copy of the ice velocity.
array::CellType2 cell_type
Definition: Geometry.hh:55
array::Scalar2 ice_thickness
Definition: Geometry.hh:51
VariableMetadata & long_name(const std::string &input)
VariableMetadata & units(const std::string &input)
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition: Array.hh:65
void copy_from(const Array2D< T > &source)
Definition: Array2D.hh:73
stencils::Star< T > star(int i, int j) const
Definition: Array2D.hh:79
void read(const std::string &filename, unsigned int time)
Definition: Array.cc:809
void define(const File &file, io::Type default_type) const
Define variables corresponding to an Array in a file opened using file.
Definition: Array.cc:540
void write(const std::string &filename) const
Definition: Array.cc:800
void set(double c)
Result: v[j] <- c for all j.
Definition: Array.cc:707
void regrid(const std::string &filename, io::Default default_value)
Definition: Array.cc:814
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata object containing metadata for the compoment N.
Definition: Array.cc:553
bool ice_free(int i, int j) const
Definition: CellType.hh:54
bool grounded(int i, int j) const
Definition: CellType.hh:38
bool icy(int i, int j) const
Definition: CellType.hh:42
double max(const array::Scalar &input)
Finds maximum over all the values in an array::Scalar object. Ignores ghosts.
Definition: Scalar.cc:165
@ WITHOUT_GHOSTS
Definition: Array.hh:62
double min(const array::Scalar &input)
Finds minimum over all the values in an array::Scalar object. Ignores ghosts.
Definition: Scalar.cc:193
@ PISM_DOUBLE
Definition: IO_Flags.hh:52
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.
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.
T clip(T x, T a, T b)
std::map< std::string, Diagnostic::Ptr > DiagnosticList
Definition: Diagnostic.hh:125