20#include "pism/energy/EnthalpyModel.hh"
21#include "pism/energy/DrainageCalculator.hh"
22#include "pism/energy/enthSystem.hh"
23#include "pism/energy/utilities.hh"
24#include "pism/util/Context.hh"
25#include "pism/util/EnthalpyConverter.hh"
26#include "pism/util/array/CellType.hh"
27#include "pism/util/io/File.hh"
28#include "pism/util/Logger.hh"
29#include "pism/util/io/IO_Flags.hh"
35 std::shared_ptr<const stressbalance::StressBalance> stress_balance)
42 m_log->message(2,
"* Restarting the enthalpy-based energy balance model from %s...\n",
43 input_file.
name().c_str());
58 m_log->message(2,
"* Bootstrapping the enthalpy-based energy balance model from %s...\n",
59 input_file.
name().c_str());
81 m_log->message(2,
"* Bootstrapping the enthalpy-based energy balance model...\n");
113 auto EC =
m_grid->ctx()->enthalpy_converter();
116 ice_density =
m_config->get_number(
"constants.ice.density"),
117 bulgeEnthMax =
m_config->get_number(
"energy.enthalpy.cold_bulge_max"),
118 target_water_fraction =
m_config->get_number(
"energy.drainage_target_water_fraction");
131 const auto &cell_type = *inputs.
cell_type;
146 const size_t Mz_fine = system.
z().size();
147 const double dz = system.
dz();
148 std::vector<double> Enthnew(Mz_fine);
150 array::AccessScope list{&ice_surface_temp, &shelf_base_temp, &surface_liquid_fraction,
151 &ice_thickness, &basal_frictional_heating, &basal_heat_flux, &till_water_thickness,
155 double margin_threshold =
m_config->get_number(
"energy.margin_ice_thickness_limit");
157 unsigned int liquifiedCount = 0;
161 for (
auto pt :
m_grid->points()) {
162 const int i = pt.i(), j = pt.j();
164 const double H = ice_thickness(i, j);
167 marginal(ice_thickness, i, j, margin_threshold),
172 depth_ks = H - system.
ks() * dz,
173 p_ks = EC->pressure(depth_ks);
175 const double Enth_ks = EC->enthalpy_permissive(ice_surface_temp(i, j),
176 surface_liquid_fraction(i, j), p_ks);
178 const bool ice_free_column = (system.
ks() == 0);
181 if (ice_free_column) {
190 if (system.
lambda() < 1.0) {
195 is_floating = cell_type.ocean(i, j),
196 base_is_warm = system.
Enth(0) >= system.
Enth_s(0),
197 above_base_is_warm = system.
Enth(1) >= system.
Enth_s(1);
209 double Enth0 = EC->enthalpy_permissive(shelf_base_temp(i, j), 0.0, EC->pressure(H));
214 if (base_is_warm && (till_water_thickness(i, j) > 0.0)) {
215 if (above_base_is_warm) {
232 system.
solve(Enthnew);
237 double Hdrainedtotal = 0.0;
241 for (
unsigned int k=0;
k < system.
ks();
k++) {
242 if (Enthnew[
k] > system.
Enth_s(
k)) {
246 p = EC->pressure(depth),
247 T_m = EC->melting_temperature(p),
250 if (Enthnew[
k] >= system.
Enth_s(
k) + 0.5 *
L) {
255 double omega = EC->water_fraction(Enthnew[
k], p);
257 if (omega > target_water_fraction) {
260 fractiondrained = std::min(fractiondrained,
261 omega - target_water_fraction);
262 Hdrainedtotal += fractiondrained * dz;
263 Enthnew[
k] -= fractiondrained *
L;
269 const double lowerEnthLimit = Enth_ks - bulgeEnthMax;
270 for (
unsigned int k=0;
k < system.
ks();
k++) {
271 if (Enthnew[
k] < lowerEnthLimit) {
275 Enthnew[
k] = lowerEnthLimit;
282 if (till_water_thickness(i, j) > 0.0) {
283 Enthnew[0] = std::max(Enthnew[0], system.
Enth_s(0));
289 bool base_is_cold = (Enthnew[0] < system.
Enth_s(0)) && (till_water_thickness(i,j) == 0.0);
304 p_0 = EC->pressure(H),
305 p_1 = EC->pressure(H - dz),
306 Tpmp_0 = EC->melting_temperature(p_0);
308 const bool k1_istemperate = EC->is_temperate(Enthnew[1], p_1);
310 if (k1_istemperate) {
312 Tpmp_1 = EC->melting_temperature(p_1);
314 hf_up = -system.
k_from_T(Tpmp_0) * (Tpmp_1 - Tpmp_0) / dz;
316 double T_0 = EC->temperature(Enthnew[0], p_0);
317 const double K_0 = system.
k_from_T(T_0) / EC->c();
319 hf_up = -K_0 * (Enthnew[1] - Enthnew[0]) / dz;
328 m_basal_melt_rate(i, j) = (basal_frictional_heating(i, j) + basal_heat_flux(i, j) - hf_up) / (ice_density * EC->L(Tpmp_0));
std::shared_ptr< const Config > m_config
configuration database used by this component
@ REGRID_WITHOUT_REGRID_VARS
const std::shared_ptr< const Grid > m_grid
grid used by this component
void regrid(const std::string &module_name, array::Array &variable, RegriddingFlag flag=NO_REGRID_WITHOUT_REGRID_VARS)
std::shared_ptr< const Logger > m_log
logger (for easy access)
High-level PISM I/O class.
void failed()
Indicates a failure of a parallel section.
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
void copy_from(const Array2D< T > &source)
void set_column(int i, int j, double c)
Set all values of scalar quantity to given a single value in a particular column.
A virtual class collecting methods common to ice and bedrock 3D fields.
void read(const std::string &filename, unsigned int time)
void write(const OutputFile &file) const
int state_counter() const
Get the object state counter.
void regrid(const std::string &filename, io::Default default_value)
const std::vector< double > & z() const
void fine_to_coarse(const std::vector< double > &input, int i, int j, array::Array3D &output) const
virtual double get_drainage_rate(double omega)
Return D(omega), as in figure in [AschwandenBuelerKhroulevBlatter].
Compute the rate of drainage D(omega) for temperate ice.
unsigned int reduced_accuracy_counter
double liquified_ice_volume
unsigned int bulge_counter
void init_enthalpy(const File &input_file, bool regrid, int record)
Initialize enthalpy by reading it from a file, or by reading temperature and liquid water fraction,...
const array::Scalar & basal_melt_rate() const
Basal melt rate in grounded areas. (It is set to zero elsewhere.)
array::Array3D m_ice_enthalpy
array::Scalar m_basal_melt_rate
void regrid_enthalpy()
Regrid enthalpy from the -regrid_file.
virtual void initialize_impl(const array::Scalar &basal_melt_rate, const array::Scalar &ice_thickness, const array::Scalar &surface_temperature, const array::Scalar &climatic_mass_balance, const array::Scalar &basal_heat_flux)
virtual void restart_impl(const File &input_file, int record)
virtual void bootstrap_impl(const File &input_file, const array::Scalar &ice_thickness, const array::Scalar &surface_temperature, const array::Scalar &climatic_mass_balance, const array::Scalar &basal_heat_flux)
virtual void write_state_impl(const OutputFile &output) const
The default (empty implementation).
virtual void update_impl(double t, double dt, const Inputs &inputs)
Update ice enthalpy field based on conservation of energy.
virtual std::set< VariableMetadata > state_impl() const
EnthalpyModel(std::shared_ptr< const Grid > grid, std::shared_ptr< const stressbalance::StressBalance > stress_balance)
double Enth(size_t i) const
double Enth_s(size_t i) const
void init(int i, int j, bool ismarginal, double ice_thickness)
double k_from_T(double T) const
void set_basal_heat_flux(double heat_flux)
Set coefficients in discrete equation for Neumann condition at base of ice.
void solve(std::vector< double > &result)
Solve the tridiagonal system, in a single column, which determines the new values of the ice enthalpy...
void set_basal_dirichlet_bc(double E_basal)
Set coefficients in discrete equation for at base of ice.
void set_surface_dirichlet_bc(double E_surface)
Tridiagonal linear system for conservation of energy in vertical column of ice enthalpy.
std::set< VariableMetadata > metadata(std::initializer_list< const Array * > vecs)
bool marginal(const array::Scalar1 &thickness, int i, int j, double threshold)
void bootstrap_ice_enthalpy(const array::Scalar &ice_thickness, const array::Scalar &ice_surface_temp, const array::Scalar &surface_mass_balance, const array::Scalar &basal_heat_flux, array::Array3D &result)