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"
33 std::shared_ptr<const stressbalance::StressBalance> stress_balance)
40 m_log->message(2,
"* Restarting the enthalpy-based energy balance model from %s...\n",
56 m_log->message(2,
"* Bootstrapping the enthalpy-based energy balance model from %s...\n",
79 m_log->message(2,
"* Bootstrapping the enthalpy-based energy balance model...\n");
114 ice_density =
m_config->get_number(
"constants.ice.density"),
115 bulgeEnthMax =
m_config->get_number(
"energy.enthalpy.cold_bulge_max"),
116 target_water_fraction =
m_config->get_number(
"energy.drainage_target_water_fraction");
129 const auto &cell_type = *inputs.
cell_type;
144 const size_t Mz_fine = system.
z().size();
145 const double dz = system.
dz();
146 std::vector<double> Enthnew(Mz_fine);
148 array::AccessScope list{&ice_surface_temp, &shelf_base_temp, &surface_liquid_fraction,
149 &ice_thickness, &basal_frictional_heating, &basal_heat_flux, &till_water_thickness,
153 double margin_threshold =
m_config->get_number(
"energy.margin_ice_thickness_limit");
155 unsigned int liquifiedCount = 0;
159 for (
auto pt =
m_grid->points(); pt; pt.next()) {
160 const int i = pt.i(), j = pt.j();
162 const double H = ice_thickness(i, j);
165 marginal(ice_thickness, i, j, margin_threshold),
170 depth_ks = H - system.
ks() * dz,
171 p_ks = EC->pressure(depth_ks);
173 const double Enth_ks = EC->enthalpy_permissive(ice_surface_temp(i, j),
174 surface_liquid_fraction(i, j), p_ks);
176 const bool ice_free_column = (system.
ks() == 0);
179 if (ice_free_column) {
188 if (system.
lambda() < 1.0) {
193 is_floating = cell_type.ocean(i, j),
194 base_is_warm = system.
Enth(0) >= system.
Enth_s(0),
195 above_base_is_warm = system.
Enth(1) >= system.
Enth_s(1);
207 double Enth0 = EC->enthalpy_permissive(shelf_base_temp(i, j), 0.0, EC->pressure(H));
212 if (base_is_warm && (till_water_thickness(i, j) > 0.0)) {
213 if (above_base_is_warm) {
230 system.
solve(Enthnew);
235 double Hdrainedtotal = 0.0;
239 for (
unsigned int k=0;
k < system.
ks();
k++) {
240 if (Enthnew[
k] > system.
Enth_s(
k)) {
244 p = EC->pressure(depth),
245 T_m = EC->melting_temperature(p),
248 if (Enthnew[
k] >= system.
Enth_s(
k) + 0.5 *
L) {
253 double omega = EC->water_fraction(Enthnew[
k], p);
255 if (omega > target_water_fraction) {
258 fractiondrained =
std::min(fractiondrained,
259 omega - target_water_fraction);
260 Hdrainedtotal += fractiondrained * dz;
261 Enthnew[
k] -= fractiondrained *
L;
267 const double lowerEnthLimit = Enth_ks - bulgeEnthMax;
268 for (
unsigned int k=0;
k < system.
ks();
k++) {
269 if (Enthnew[
k] < lowerEnthLimit) {
273 Enthnew[
k] = lowerEnthLimit;
280 if (till_water_thickness(i, j) > 0.0) {
287 bool base_is_cold = (Enthnew[0] < system.
Enth_s(0)) && (till_water_thickness(i,j) == 0.0);
302 p_0 = EC->pressure(H),
303 p_1 = EC->pressure(H - dz),
304 Tpmp_0 = EC->melting_temperature(p_0);
306 const bool k1_istemperate = EC->is_temperate(Enthnew[1], p_1);
308 if (k1_istemperate) {
310 Tpmp_1 = EC->melting_temperature(p_1);
312 hf_up = -system.
k_from_T(Tpmp_0) * (Tpmp_1 - Tpmp_0) / dz;
314 double T_0 = EC->temperature(Enthnew[0], p_0);
315 const double K_0 = system.
k_from_T(T_0) / EC->c();
317 hf_up = -K_0 * (Enthnew[1] - Enthnew[0]) / dz;
326 m_basal_melt_rate(i, j) = (basal_frictional_heating(i, j) + basal_heat_flux(i, j) - hf_up) / (ice_density * EC->L(Tpmp_0));
const Config::ConstPtr m_config
configuration database used by this component
const Logger::ConstPtr m_log
logger (for easy access)
@ 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< EnthalpyConverter > Ptr
std::string filename() const
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 define(const File &file, io::Type default_type) const
Define variables corresponding to an Array in a file opened using file.
void write(const std::string &filename) 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 > &fine, int i, int j, array::Array3D &coarse) 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_model_state_impl(const File &output) const
The default (empty implementation).
EnthalpyModel(std::shared_ptr< const Grid > grid, std::shared_ptr< const stressbalance::StressBalance > stress_balance)
virtual void define_model_state_impl(const File &output) const
The default (empty implementation).
virtual void update_impl(double t, double dt, const Inputs &inputs)=0
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.
double max(const array::Scalar &input)
Finds maximum over all the values in an array::Scalar object. Ignores ghosts.
double min(const array::Scalar &input)
Finds minimum over all the values in an array::Scalar object. Ignores ghosts.
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)