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"
32 std::shared_ptr<const Grid> grid,
33 std::shared_ptr<const stressbalance::StressBalance> stress_balance)
35 m_ice_temperature(m_grid,
"temp", array::
WITH_GHOSTS, m_grid->z()) {
50 m_log->message(2,
"* Restarting the temperature-based energy balance model from %s...\n",
55 const array::Scalar &ice_thickness = *
m_grid->variables().get_2d_scalar(
"land_ice_thickness");
76 m_log->message(2,
"* Bootstrapping the temperature-based energy balance model from %s...\n",
100 m_log->message(2,
"* Bootstrapping the temperature-based energy balance model...\n");
177 ice_density =
m_config->get_number(
"constants.ice.density"),
178 ice_c =
m_config->get_number(
"constants.ice.specific_heat_capacity"),
179 L =
m_config->get_number(
"constants.fresh_water.latent_heat_of_fusion"),
180 melting_point_temp =
m_config->get_number(
"constants.fresh_water.melting_point_temperature"),
181 beta_CC_grad =
m_config->get_number(
"constants.ice.beta_Clausius_Clapeyron") * ice_density *
m_config->get_number(
"constants.standard_gravity");
183 const bool allow_above_melting =
m_config->get_flag(
"energy.allow_temperature_above_melting");
187 const double bulge_max =
m_config->get_number(
"energy.enthalpy.cold_bulge_max") / ice_c;
196 const auto &cell_type = *inputs.
cell_type;
208 &cell_type, &basal_heat_flux, &till_water_thickness, &basal_frictional_heating,
216 double dz = system.
dz();
217 const std::vector<double>& z_fine = system.
z();
218 size_t Mz_fine = z_fine.size();
219 std::vector<double> x(Mz_fine);
220 std::vector<double> Tnew(Mz_fine);
223 unsigned int maxLowTempCount =
m_config->get_number(
"energy.max_low_temperature_count");
224 const double T_minimum =
m_config->get_number(
"energy.minimum_allowed_temperature");
226 double margin_threshold =
m_config->get_number(
"energy.margin_ice_thickness_limit");
230 for (
auto p =
m_grid->points(); p; p.next()) {
231 const int i = p.i(), j = p.j();
235 const double H = ice_thickness(i, j);
236 const double T_surface = ice_surface_temp(i, j);
239 marginal(ice_thickness, i, j, margin_threshold),
242 const int ks = system.
ks();
246 if (system.
lambda() < 1.0) {
253 shelf_base_temp(i,j),
254 basal_frictional_heating(i,j));
261 double bwatnew = till_water_thickness(i,j);
264 for (
int k=1;
k <= ks;
k++) {
265 if (allow_above_melting) {
269 Tpmp = melting_point_temp - beta_CC_grad * (H - z_fine[
k]);
272 double Texcess = x[
k] - Tpmp;
279 if (Tnew[
k] < T_minimum) {
281 " [[too low (<200) ice segment temp T = %f at %d, %d, %d;"
282 " proc %d; mask=%d; w=%f m year-1]]\n",
283 Tnew[
k], i, j,
k,
m_grid->rank(), mask,
288 if (Tnew[
k] < T_surface - bulge_max) {
289 Tnew[
k] = T_surface - bulge_max;
296 if (allow_above_melting ==
true) {
299 const double Tpmp = melting_point_temp - beta_CC_grad * H;
300 double Texcess = x[0] - Tpmp;
308 Tnew[0] = Tpmp + Texcess;
309 if (Tnew[0] > (Tpmp + 0.00001)) {
313 if (Tnew[0] < T_minimum) {
315 " [[too low (<200) ice/bedrock segment temp T = %f at %d,%d;"
316 " proc %d; mask=%d; w=%f]]\n",
317 Tnew[0],i,j,
m_grid->rank(), mask,
322 if (Tnew[0] < T_surface - bulge_max) {
323 Tnew[0] = T_surface - bulge_max;
329 for (
unsigned int k = ks;
k < Mz_fine;
k++) {
379 const double z,
const double dz,
380 double *Texcess,
double *bwat)
const {
383 darea =
m_grid->cell_area(),
385 dE =
rho * c * (*Texcess) * dvol,
388 if (*Texcess >= 0.0) {
392 const double FRACTION_TO_BASE
393 = (z < 100.0) ? 0.2 * (100.0 - z) / 100.0 : 0.0;
395 *bwat += (FRACTION_TO_BASE * massmelted) / (
rho * darea);
401 throw RuntimeError(
PISM_ERROR_LOCATION,
"excessToBasalMeltLayer() called with z not at base and negative Texcess");
404 const double thicknessToFreezeOn = - massmelted / (
rho * darea);
405 if (thicknessToFreezeOn <= *bwat) {
406 *bwat -= thicknessToFreezeOn;
410 const double dTemp =
L * (*bwat) / (c * dz);
const units::System::Ptr m_sys
unit system used by this component
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)
VariableLookupData find_variable(const std::string &short_name, const std::string &std_name) const
Find a variable using its standard name and/or short name.
std::string filename() const
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 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)
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata object containing metadata for the compoment N.
const std::vector< double > & z() const
void fine_to_coarse(const std::vector< double > &fine, int i, int j, array::Array3D &coarse) 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
void write_model_state_impl(const File &output) const
The default (empty implementation).
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 define_model_state_impl(const File &output) const
The default (empty implementation).
array::Array3D m_ice_temperature
void restart_impl(const File &input_file, int record)
virtual void update_impl(double t, double dt, const Inputs &inputs)=0
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
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
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)