PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
DischargeGiven.cc
Go to the documentation of this file.
1 // Copyright (C) 2018, 2019, 2021, 2022, 2023 Andy Aschwanden and Constantine Khroulev
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 #include "pism/coupler/frontalmelt/DischargeGiven.hh"
20 
21 #include "pism/coupler/frontalmelt/FrontalMeltPhysics.hh"
22 #include "pism/coupler/util/options.hh"
23 #include "pism/geometry/Geometry.hh"
24 #include "pism/util/Grid.hh"
25 #include "pism/util/array/Forcing.hh"
26 
27 namespace pism {
28 namespace frontalmelt {
29 
30 DischargeGiven::DischargeGiven(std::shared_ptr<const Grid> grid)
31  : FrontalMelt(grid, nullptr), m_frontal_melt_rate(grid, "frontal_melt_rate") {
32 
34  .long_name("frontal melt rate")
35  .units("m s-1")
36  .output_units("m day-1");
37 
38  m_log->message(2, "* Initializing the frontal melt model\n"
39  " UAF-UT\n");
40 
41  m_theta_ocean = array::Forcing::Constant(grid, "theta_ocean", 0.0);
42 
43  m_subglacial_discharge = array::Forcing::Constant(grid, "subglacial_discharge", 0.0);
44 }
45 
46 void DischargeGiven::init_impl(const Geometry &geometry) {
47  (void)geometry;
48 
49  ForcingOptions opt(*m_grid->ctx(), "frontal_melt.discharge_given");
50 
51  {
52  unsigned int buffer_size = m_config->get_number("input.forcing.buffer_size");
53 
55 
56  m_theta_ocean = std::make_shared<array::Forcing>(m_grid, file, "theta_ocean",
57  "", // no standard name
58  buffer_size, opt.periodic);
59 
60  m_subglacial_discharge = std::make_shared<array::Forcing>(m_grid, file, "subglacial_discharge",
61  "", // no standard name
62  buffer_size, opt.periodic);
63  }
64 
65  m_theta_ocean->metadata(0)
66  .long_name("potential temperature of the adjacent ocean")
67  .units("Celsius");
68 
69  m_theta_ocean->init(opt.filename, opt.periodic);
70 
71  m_subglacial_discharge->metadata(0)
72  .long_name("subglacial discharge")
73  .units("kg m-2 s-1")
74  .output_units("kg m-2 year-1");
75 
77 }
78 
79 /*!
80  * Initialize potential temperature from arrays instead of an input
81  * file (for testing).
82  */
83 void DischargeGiven::initialize(const array::Scalar &theta, const array::Scalar &sgl) {
84  m_theta_ocean->copy_from(theta);
85  m_subglacial_discharge->copy_from(sgl);
86 }
87 
88 void DischargeGiven::update_impl(const FrontalMeltInputs &inputs, double t, double dt) {
89 
90  m_theta_ocean->update(t, dt);
91  m_subglacial_discharge->update(t, dt);
92 
93  m_theta_ocean->average(t, dt);
94  m_subglacial_discharge->average(t, dt);
95 
96  FrontalMeltPhysics physics(*m_config);
97 
98  const auto &cell_type = inputs.geometry->cell_type;
99  const array::Scalar &bed_elevation = inputs.geometry->bed_elevation;
100  const array::Scalar &sea_level_elevation = inputs.geometry->sea_level_elevation;
101 
102  array::AccessScope list{ &bed_elevation,
103  &cell_type,
104  &sea_level_elevation,
105  m_theta_ocean.get(),
108 
109  double water_density = m_config->get_number("constants.fresh_water.density"),
110  seconds_per_day = 86400;
111 
112  for (auto p = m_grid->points(); p; p.next()) {
113  const int i = p.i(), j = p.j();
114 
115  if (cell_type.icy(i, j)) {
116  // Assume for now that thermal forcing is equal to theta_ocean. Also, thermal
117  // forcing is generally not available at the grounding line.
118  double TF = (*m_theta_ocean)(i, j);
119 
120  // Convert subglacial discharge (kg /(m^2 * s)) to an "effective subglacial freshwater
121  // velocity" or volume flux per unit area of ice front in m/day (see Xu et al 2013,
122  // section 2, paragraph 11).
123  //
124  // [flux] = kg / (m^2 * s), so
125  // [flux / water_density] = m / s, so
126  // [flux / water_density * (s / day) ] = m / day
127  double q_sg = ((*m_subglacial_discharge)(i, j) / water_density) * seconds_per_day;
128 
129  double water_depth = sea_level_elevation(i, j) - bed_elevation(i, j);
130 
131  m_frontal_melt_rate(i, j) = physics.frontal_melt_from_undercutting(water_depth, q_sg, TF);
132  // convert from m / day to m / s
133  m_frontal_melt_rate(i, j) /= seconds_per_day;
134  } else {
135  m_frontal_melt_rate(i, j) = 0.0;
136  }
137  } // end of the loop over grid points
138 
139  // Set frontal melt rate *near* grounded termini to the average of grounded icy
140  // neighbors: front retreat code uses values at these locations (the rest is for
141  // visualization).
142 
144 
145  for (auto p = m_grid->points(); p; p.next()) {
146  const int i = p.i(), j = p.j();
147 
148  if (apply(cell_type, i, j) and cell_type.ice_free(i, j)) {
149 
150  auto R = m_frontal_melt_rate.star(i, j);
151  auto M = cell_type.star_int(i, j);
152 
153  int N = 0;
154  double R_sum = 0.0;
155  for (auto d : { North, East, South, West }) {
156  if (mask::grounded_ice(M[d]) or (m_include_floating_ice and mask::icy(M[d]))) {
157  R_sum += R[d];
158  N++;
159  }
160  }
161 
162  if (N > 0) {
163  m_frontal_melt_rate(i, j) = R_sum / N;
164  }
165  }
166  }
167 }
168 
170  return m_frontal_melt_rate;
171 }
172 
174 
175  auto dt = std::min(m_theta_ocean->max_timestep(t), m_subglacial_discharge->max_timestep(t));
176 
177  if (dt.finite()) {
178  return {dt.value(), "frontal_melt discharge_given"};
179  }
180 
181  return {"frontal_melt discharge_given"};
182 }
183 
184 } // end of namespace frontalmelt
185 } // end of namespace pism
std::shared_ptr< const Grid > grid() const
Definition: Component.cc:105
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
const std::shared_ptr< const Grid > m_grid
grid used by this component
Definition: Component.hh:156
High-level PISM I/O class.
Definition: File.hh:56
const Geometry * geometry
Definition: FrontalMelt.hh:32
array::Scalar1 sea_level_elevation
Definition: Geometry.hh:48
array::CellType2 cell_type
Definition: Geometry.hh:55
array::Scalar2 bed_elevation
Definition: Geometry.hh:47
Combines the max. time step with the flag indicating if a restriction is active. Makes is possible to...
Definition: MaxTimestep.hh:31
VariableMetadata & long_name(const std::string &input)
VariableMetadata & output_units(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
stencils::Star< T > star(int i, int j) const
Definition: Array2D.hh:79
void update_ghosts()
Updates ghost points.
Definition: Array.cc:693
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata object containing metadata for the compoment N.
Definition: Array.cc:553
static std::shared_ptr< Forcing > Constant(std::shared_ptr< const Grid > grid, const std::string &short_name, double value)
Definition: Forcing.cc:147
const array::Scalar & frontal_melt_rate_impl() const
MaxTimestep max_timestep_impl(double t) const
void update_impl(const FrontalMeltInputs &inputs, double t, double dt)
std::shared_ptr< array::Forcing > m_subglacial_discharge
DischargeGiven(std::shared_ptr< const Grid > g)
void initialize(const array::Scalar &theta, const array::Scalar &sgl)
std::shared_ptr< array::Forcing > m_theta_ocean
void init_impl(const Geometry &geometry)
double frontal_melt_from_undercutting(double ice_thickness, double discharge_flux, double potential_temperature) const
bool apply(const array::CellType1 &M, int i, int j) const
Definition: FrontalMelt.cc:246
A very rudimentary PISM frontal melt model.
Definition: FrontalMelt.hh:43
double min(const array::Scalar &input)
Finds minimum over all the values in an array::Scalar object. Ignores ghosts.
Definition: Scalar.cc:193
@ PISM_NETCDF3
Definition: IO_Flags.hh:57
@ PISM_READONLY
open an existing file for reading only
Definition: IO_Flags.hh:72
bool icy(int M)
Ice-filled cell (grounded or floating).
Definition: Mask.hh:48
bool grounded_ice(int M)
Definition: Mask.hh:51
@ North
Definition: stencils.hh:24
@ East
Definition: stencils.hh:24
@ South
Definition: stencils.hh:24
@ West
Definition: stencils.hh:24
std::string filename
Definition: options.hh:33