20#include "pism/energy/TemperatureModel.hh"
21#include "pism/energy/tempSystem.hh"
22#include "pism/energy/utilities.hh"
23#include "pism/util/Vars.hh"
24#include "pism/util/array/CellType.hh"
25#include "pism/util/io/File.hh"
26#include "pism/util/pism_utilities.hh"
27#include "pism/util/Logger.hh"
28#include "pism/util/io/IO_Flags.hh"
34 std::shared_ptr<const Grid> grid,
35 std::shared_ptr<const stressbalance::StressBalance> stress_balance)
37 m_ice_temperature(m_grid,
"temp", array::WITH_GHOSTS, m_grid->z()) {
52 m_log->message(2,
"* Restarting the temperature-based energy balance model from %s...\n",
53 input_file.
name().c_str());
57 const array::Scalar &ice_thickness = *
m_grid->variables().get_2d_scalar(
"land_ice_thickness");
78 m_log->message(2,
"* Bootstrapping the temperature-based energy balance model from %s...\n",
79 input_file.
name().c_str());
102 m_log->message(2,
"* Bootstrapping the temperature-based energy balance model...\n");
179 ice_density =
m_config->get_number(
"constants.ice.density"),
180 ice_c =
m_config->get_number(
"constants.ice.specific_heat_capacity"),
181 L =
m_config->get_number(
"constants.fresh_water.latent_heat_of_fusion"),
182 melting_point_temp =
m_config->get_number(
"constants.fresh_water.melting_point_temperature"),
183 beta_CC_grad =
m_config->get_number(
"constants.ice.beta_Clausius_Clapeyron") * ice_density *
m_config->get_number(
"constants.standard_gravity");
185 const bool allow_above_melting =
m_config->get_flag(
"energy.allow_temperature_above_melting");
189 const double bulge_max =
m_config->get_number(
"energy.enthalpy.cold_bulge_max") / ice_c;
198 const auto &cell_type = *inputs.
cell_type;
210 &cell_type, &basal_heat_flux, &till_water_thickness, &basal_frictional_heating,
218 double dz = system.
dz();
219 const std::vector<double>& z_fine = system.
z();
220 size_t Mz_fine = z_fine.size();
221 std::vector<double> x(Mz_fine);
222 std::vector<double> Tnew(Mz_fine);
225 unsigned int maxLowTempCount =
m_config->get_number(
"energy.max_low_temperature_count");
226 const double T_minimum =
m_config->get_number(
"energy.minimum_allowed_temperature");
228 double margin_threshold =
m_config->get_number(
"energy.margin_ice_thickness_limit");
232 for (
auto p :
m_grid->points()) {
233 const int i = p.i(), j = p.j();
237 const double H = ice_thickness(i, j);
238 const double T_surface = ice_surface_temp(i, j);
241 marginal(ice_thickness, i, j, margin_threshold),
244 const int ks = system.
ks();
248 if (system.
lambda() < 1.0) {
255 shelf_base_temp(i,j),
256 basal_frictional_heating(i,j));
263 double bwatnew = till_water_thickness(i,j);
266 for (
int k=1;
k <= ks;
k++) {
267 if (allow_above_melting) {
271 Tpmp = melting_point_temp - beta_CC_grad * (H - z_fine[
k]);
274 double Texcess = x[
k] - Tpmp;
281 if (Tnew[
k] < T_minimum) {
283 " [[too low (<200) ice segment temp T = %f at %d, %d, %d;"
284 " proc %d; mask=%d; w=%f m year-1]]\n",
285 Tnew[
k], i, j,
k,
m_grid->rank(), mask,
290 if (Tnew[
k] < T_surface - bulge_max) {
291 Tnew[
k] = T_surface - bulge_max;
298 if (allow_above_melting ==
true) {
301 const double Tpmp = melting_point_temp - beta_CC_grad * H;
302 double Texcess = x[0] - Tpmp;
310 Tnew[0] = Tpmp + Texcess;
311 if (Tnew[0] > (Tpmp + 0.00001)) {
315 if (Tnew[0] < T_minimum) {
317 " [[too low (<200) ice/bedrock segment temp T = %f at %d,%d;"
318 " proc %d; mask=%d; w=%f]]\n",
319 Tnew[0],i,j,
m_grid->rank(), mask,
324 if (Tnew[0] < T_surface - bulge_max) {
325 Tnew[0] = T_surface - bulge_max;
331 for (
unsigned int k = ks;
k < Mz_fine;
k++) {
380 const double z,
const double dz,
381 double *Texcess,
double *bwat)
const {
384 darea =
m_grid->cell_area(),
386 dE =
rho * c * (*Texcess) * dvol,
389 if (*Texcess >= 0.0) {
393 const double FRACTION_TO_BASE
394 = (z < 100.0) ? 0.2 * (100.0 - z) / 100.0 : 0.0;
396 *bwat += (FRACTION_TO_BASE * massmelted) / (
rho * darea);
405 const double thicknessToFreezeOn = - massmelted / (
rho * darea);
406 if (thicknessToFreezeOn <= *bwat) {
407 *bwat -= thicknessToFreezeOn;
411 const double dTemp =
L * (*bwat) / (c * dz);
const units::System::Ptr m_sys
unit system used by this component
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)
bool variable_exists(const std::string &short_name) const
Checks if a variable exists.
High-level PISM I/O class.
void message(int threshold, const char format[],...) const __attribute__((format(printf
Print a message to the log.
void failed()
Indicates a failure of a parallel section.
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
void copy_from(const Array2D< T > &source)
void copy_from(const Array3D &input)
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)
VariableMetadata & metadata(unsigned int N=0)
Returns a reference to the VariableMetadata object containing metadata for the compoment N.
const std::vector< double > & z() const
void fine_to_coarse(const std::vector< double > &input, int i, int j, array::Array3D &output) const
unsigned int reduced_accuracy_counter
unsigned int low_temperature_counter
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
const array::Array3D & temperature() const
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)
void write_state_impl(const OutputFile &output) const
The default (empty implementation).
std::set< VariableMetadata > state_impl() const
array::Array3D m_ice_temperature
void restart_impl(const File &input_file, int record)
TemperatureModel(std::shared_ptr< const Grid > grid, std::shared_ptr< const stressbalance::StressBalance > stress_balance)
void column_drainage(const double rho, const double c, const double L, const double z, const double dz, double *Texcess, double *bwat) const
Compute the melt water which should go to the base if is above pressure-melting.
void update_impl(double t, double dt, const Inputs &inputs)
Takes a semi-implicit time-step for the temperature equation.
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)
void initThisColumn(int i, int j, bool is_marginal, MaskValue new_mask, double ice_thickness)
void setSurfaceBoundaryValuesThisColumn(double my_Ts)
void solveThisColumn(std::vector< double > &x)
void setBasalBoundaryValuesThisColumn(double my_G0, double my_Tshelfbase, double my_Rb)
Tridiagonal linear system for vertical column of temperature-based conservation of energy problem.
#define PISM_ERROR_LOCATION
std::set< VariableMetadata > metadata(std::initializer_list< const Array * > vecs)
void bootstrap_ice_temperature(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)
Create a temperature field within the ice from provided ice thickness, surface temperature,...
bool marginal(const array::Scalar1 &thickness, int i, int j, double threshold)
void compute_enthalpy_cold(const array::Array3D &temperature, const array::Scalar &ice_thickness, array::Array3D &result)
Compute ice enthalpy from temperature temperature by assuming the ice has zero liquid fraction.
void compute_temperature(const array::Array3D &enthalpy, const array::Scalar &ice_thickness, array::Array3D &result)
bool ocean(int M)
An ocean cell (floating ice or ice-free).
double convert(System::Ptr system, double input, const std::string &spec1, const std::string &spec2)
Convert a quantity from unit1 to unit2.
void GlobalSum(MPI_Comm comm, double *local, double *result, int count)