26#include "pism/verification/tests/exactTestH.h"
27#include "pism/verification/tests/exactTestL.hh"
28#include "pism/verification/tests/exactTestsABCD.h"
29#include "pism/verification/tests/exactTestsFG.hh"
31#include "pism/verification/BTU_Verification.hh"
32#include "pism/verification/PSVerification.hh"
33#include "pism/verification/TemperatureModel_Verification.hh"
34#include "pism/verification/iceCompModel.hh"
35#include "pism/coupler/SeaLevel.hh"
36#include "pism/coupler/ocean/Constant.hh"
37#include "pism/earth/BedDef.hh"
38#include "pism/energy/BTU_Minimal.hh"
39#include "pism/rheology/PatersonBuddCold.hh"
40#include "pism/stressbalance/ShallowStressBalance.hh"
41#include "pism/stressbalance/StressBalance.hh"
42#include "pism/stressbalance/sia/SIAFD.hh"
43#include "pism/util/ConfigInterface.hh"
44#include "pism/util/Context.hh"
45#include "pism/util/EnthalpyConverter.hh"
46#include "pism/util/Grid.hh"
47#include "pism/util/Logger.hh"
48#include "pism/util/Mask.hh"
49#include "pism/util/Time.hh"
50#include "pism/util/error_handling.hh"
51#include "pism/util/io/File.hh"
52#include "pism/util/io/io_helpers.hh"
53#include "pism/util/pism_options.hh"
54#include "pism/util/pism_utilities.hh"
63 m_HexactL(m_grid,
"HexactL"),
64 m_strain_heating3_comp(m_grid,
"strain_heating_comp", array::WITHOUT_GHOSTS, m_grid->z()),
65 m_bedrock_is_ice_forK(false) {
70 m_config->set_number(
"stress_balance.sia.enhancement_factor", 1.0);
72 m_config->set_number(
"stress_balance.sia.bed_smoother.range", 0.0);
75 m_config->set_flag(
"geometry.update.enabled",
true);
76 m_config->set_flag(
"geometry.update.use_basal_melt_rate",
false);
86 m_config->set_string(
"stress_balance.sia.flow_law",
"isothermal_glen");
87 const double year = convert(
m_sys, 1.0,
"year",
"seconds");
88 m_config->set_number(
"flow_law.isothermal_Glen.ice_softness", 1.0e-16 / year);
92 m_config->set_string(
"stress_balance.ssa.flow_law",
"isothermal_glen");
93 const double hardness = 1.9e8,
95 pow(hardness, -
m_config->get_number(
"stress_balance.ssa.Glen_exponent"));
96 m_config->set_number(
"flow_law.isothermal_Glen.ice_softness", softness);
104 m_config->set_string(
"stress_balance.sia.flow_law",
"arr");
110 m_config->set_string(
"bed_deformation.model",
"iso");
112 m_config->set_string(
"bed_deformation.model",
"none");
116 m_config->set_string(
"energy.model",
"cold");
119 m_config->set_number(
"energy.minimum_allowed_temperature", 0.0);
120 m_config->set_number(
"energy.max_low_temperature_count", 1000000);
122 m_config->set_string(
"energy.model",
"none");
126 m_config->set_number(
"sea_level.constant.value", -1e4);
130 m_config->set_flag(
"energy.allow_temperature_above_melting",
false);
133 m_config->set_flag(
"energy.allow_temperature_above_melting",
true);
138 m_config->set_flag(
"geometry.update.use_basal_melt_rate",
false);
141 m_config->set_string(
"energy.model",
"none");
144 m_config->set_string(
"stress_balance_model",
"ssa");
147 m_config->set_number(
"sea_level.constant.value", 0.0);
149 m_config->set_flag(
"stress_balance.ssa.dirichlet_bc",
true);
158 .
long_name(
"rate of compensatory strain heating in ice")
169 bool biiSet =
options::Bool(
"-bedrock_is_ice",
"set bedrock properties to those of ice");
172 m_log->message(1,
"setting material properties of bedrock to those of ice in Test K\n");
173 m_config->set_number(
"energy.bedrock_thermal.density",
174 m_config->get_number(
"constants.ice.density"));
175 m_config->set_number(
"energy.bedrock_thermal.conductivity",
176 m_config->get_number(
"constants.ice.thermal_conductivity"));
177 m_config->set_number(
"energy.bedrock_thermal.specific_heat_capacity",
178 m_config->get_number(
"constants.ice.specific_heat_capacity"));
182 1,
"IceCompModel WARNING: option -bedrock_is_ice ignored; only applies to Test K\n");
191 m_config->set_number(
"energy.bedrock_thermal.density",
192 m_config->get_number(
"constants.ice.density"));
193 m_config->set_number(
"energy.bedrock_thermal.conductivity",
194 m_config->get_number(
"constants.ice.thermal_conductivity"));
195 m_config->set_number(
"energy.bedrock_thermal.specific_heat_capacity",
196 m_config->get_number(
"constants.ice.specific_heat_capacity"));
201 if (bed_vertical_grid.Mbz > 1) {
202 m_btu = std::make_shared<energy::BTU_Verification>(
m_grid, bed_vertical_grid,
205 m_btu = std::make_shared<energy::BTU_Minimal>(
m_grid);
217 m_log->message(2,
"# Allocating an energy balance model...\n");
220 bool bedrock_is_ice =
options::Bool(
"-bedrock_is_ice",
"set bedrock properties to those of ice");
222 m_energy_model = std::make_shared<energy::TemperatureModel_Verification>(
234 m_f =
m_config->get_number(
"constants.ice.density") /
m_config->get_number(
"bed_deformation.mantle_density");
236 std::string bed_def_model =
m_config->get_string(
"bed_deformation.model");
238 if ((
m_testname ==
'H') && bed_def_model !=
"iso") {
240 "IceCompModel WARNING: Test H should be run with option\n"
241 " '-bed_def iso' for the reported errors to be correct.\n");
261 "PISM does not support bootstrapping in verification mode.");
265 m_log->message(3,
"initializing Test %c from formulas ...\n",
m_testname);
308 const double time =
m_time->current();
316 for (
auto p =
m_grid->points(); p; p.next()) {
317 const int i = p.i(), j = p.j();
379 m_log->message(2,
"* Initializing ice thickness and bed topography for test L...\n");
385 std::vector<rgrid> rrv(MM);
387 for (
auto p =
m_grid->points(); p; p.next()) {
388 const int i = p.i(), j = p.j();
400 std::vector<double> rr(MM), HH(MM), bb(MM), aa(MM);
402 for (
k = 0;
k < MM;
k++) {
413 for (
k = 0;
k < MM;
k++) {
432 const double LforAE = 750e3;
436 for (
auto p =
m_grid->points(); p; p.next()) {
437 const int i = p.i(), j = p.j();
448 double &gdomeHexact,
double &volerr,
449 double &areaerr,
double &gmaxHerr,
450 double &gavHerr,
double &gmaxetaerr,
451 double ¢erHerr) {
454 const double time =
m_time->current();
474 seawater_density =
m_config->get_number(
"constants.sea_water.density"),
475 ice_density =
m_config->get_number(
"constants.ice.density"),
476 Glen_n =
m_config->get_number(
"stress_balance.sia.Glen_exponent"),
477 standard_gravity =
m_config->get_number(
"constants.standard_gravity");
480 const double a =
m_grid->dx() *
m_grid->dy() * 1e-3 * 1e-3;
481 const double m = (2.0 * Glen_n + 2.0) / Glen_n;
485 for (
auto p =
m_grid->points(); p; p.next()) {
486 const int i = p.i(), j = p.j();
511 std::vector<double> z(1, 0.0);
520 std::vector<double> z(1, 0.0);
538 v0 = convert(
m_sys, 300.0,
"m year-1",
"m second-1"),
541 C = pow(ice_density * standard_gravity * (1.0 - ice_density/seawater_density) / (4 *
B0), 3);
543 Hexact = pow(4 * C / Q0 * xx + 1/pow(
H0, 4), -0.25);
547 throw RuntimeError(
PISM_ERROR_LOCATION,
"test must be A, B, C, D, F, G, H, K, L, or O");
552 volexact += a * Hexact * 1e-3;
554 if (i == ((
int)
m_grid->Mx() - 1)/2 and
555 j == ((
int)
m_grid->My() - 1)/2) {
571 double gvol, garea, gdomeH;
578 volerr = fabs(gvol - gvolexact);
579 areaerr = fabs(garea - gareaexact);
587 centerHerr = fabs(gdomeH - gdomeHexact);
603 const char *units,
const char *long_name,
double value,
607 v[
"long_name"] = long_name;
645 bool no_report =
options::Bool(
"-no_report",
"Don't report numerical errors");
651 double maxbmelterr, minbmelterr, volexact, areaexact, domeHexact,
652 volerr, areaerr, maxHerr, avHerr, maxetaerr, centerHerr;
653 double maxTerr, avTerr, basemaxTerr, baseavTerr, basecenterTerr, maxTberr, avTberr;
654 double max_strain_heating_error, av_strain_heating_error;
655 double maxUerr, avUerr, maxWerr, avWerr;
663 not FlowLawIsPatersonBuddCold(flow_law, *
m_config, EC)) {
665 "WARNING: flow law must be cold part of Paterson-Budd ('-siafd_flow_law arr')\n"
666 " for reported errors in test %c to be meaningful!\n",
671 "NUMERICAL ERRORS evaluated at final time (relative to exact solution):\n");
677 volerr,areaerr,maxHerr,avHerr,maxetaerr,centerHerr);
679 "geometry : prcntVOL maxH avH relmaxETA\n");
680 m_log->message(1,
" %12.6f%12.6f%12.6f%12.6f\n",
681 100*volerr/volexact, maxHerr, avHerr,
682 maxetaerr/pow(domeHexact,m));
691 "temp : maxT avT basemaxT baseavT\n");
692 m_log->message(1,
" %12.6f%12.6f%12.6f%12.6f\n",
693 maxTerr, avTerr, basemaxTerr, baseavTerr);
698 "temp : maxT avT maxTb avTb\n");
699 m_log->message(1,
" %12.6f%12.6f%12.6f%12.6f\n",
700 maxTerr, avTerr, maxTberr, avTberr);
708 "Sigma : maxSig avSig\n");
709 m_log->message(1,
" %12.6f%12.6f\n",
710 max_strain_heating_error*1.0e6, av_strain_heating_error*1.0e6);
717 "surf vels : maxUvec avUvec maxW avW\n");
719 " %12.6f%12.6f%12.6f%12.6f\n",
720 convert(
m_sys, maxUerr,
"m second-1",
"m year-1"),
721 convert(
m_sys, avUerr,
"m second-1",
"m year-1"),
722 convert(
m_sys, maxWerr,
"m second-1",
"m year-1"),
723 convert(
m_sys, avWerr,
"m second-1",
"m year-1"));
729 if (maxbmelterr != minbmelterr) {
731 "IceCompModel WARNING: unexpected Test O situation: max and min of bmelt error\n"
732 " are different: maxbmelterr = %f, minbmelterr = %f\n",
733 convert(
m_sys, maxbmelterr,
"m second-1",
"m year-1"),
734 convert(
m_sys, minbmelterr,
"m second-1",
"m year-1"));
737 "basal melt: max\n");
738 m_log->message(1,
" %11.5f\n",
739 convert(
m_sys, maxbmelterr,
"m second-1",
"m year-1"));
743 m_log->message(1,
"NUM ERRORS DONE\n");
745 options::String report_file(
"-report_file",
"NetCDF error report file");
746 bool append =
options::Bool(
"-append",
"Append the NetCDF error report");
750 if (report_file.
is_set()) {
752 m_log->message(2,
"Also writing errors to '%s'...\n", report_file->c_str());
762 write(
m_sys, file, start,
"N",
"1",
"run number", start + 1);
773 write(
m_sys, file, start,
"relative_volume",
"1",
"relative volume error", 100*volerr/volexact);
774 write(
m_sys, file, start,
"relative_max_eta",
"1",
"relative $\\eta$ error", maxetaerr/pow(domeHexact,m));
775 write(
m_sys, file, start,
"maximum_thickness",
"meters",
"maximum ice thickness error", maxHerr);
776 write(
m_sys, file, start,
"average_thickness",
"meters",
"average ice thickness error", avHerr);
780 write(
m_sys, file, start,
"maximum_temperature",
"kelvin",
"maximum ice temperature error", maxTerr);
781 write(
m_sys, file, start,
"average_temperature",
"kelvin",
"average ice temperature error", avTerr);
782 write(
m_sys, file, start,
"maximum_basal_temperature",
"kelvin",
"maximum basal temperature error", basemaxTerr);
783 write(
m_sys, file, start,
"average_basal_temperature",
"kelvin",
"average basal temperature error", baseavTerr);
787 write(
m_sys, file, start,
"maximum_sigma",
"1e6 J s-1 m-3",
"maximum strain heating error", c(max_strain_heating_error));
788 write(
m_sys, file, start,
"average_sigma",
"1e6 J s-1 m-3",
"average strain heating error", c(av_strain_heating_error));
793 write(
m_sys, file, start,
"maximum_surface_velocity",
"m year-1",
"maximum ice surface horizontal velocity error", c(maxUerr));
794 write(
m_sys, file, start,
"average_surface_velocity",
"m year-1",
"average ice surface horizontal velocity error", c(avUerr));
795 write(
m_sys, file, start,
"maximum_surface_w",
"m year-1",
"maximum ice surface vertical velocity error", c(maxWerr));
796 write(
m_sys, file, start,
"average_surface_w",
"m year-1",
"average ice surface vertical velocity error", c(avWerr));
801 write(
m_sys, file, start,
"maximum_temperature",
"kelvin",
"maximum ice temperature error", maxTerr);
802 write(
m_sys, file, start,
"average_temperature",
"kelvin",
"average ice temperature error", avTerr);
803 write(
m_sys, file, start,
"maximum_bedrock_temperature",
"kelvin",
"maximum bedrock temperature error", maxTberr);
804 write(
m_sys, file, start,
"average_bedrock_temperature",
"kelvin",
"average bedrock temperature error", avTberr);
809 write(
m_sys, file, start,
"maximum_basal_melt_rate",
"m year -1",
"maximum basal melt rate error", c(maxbmelterr));
855 double upstream_velocity = convert(
m_sys, 300.0,
"m year-1",
"m second-1"),
856 upstream_thk = 600.0;
862 for (
auto p =
m_grid->points(); p; p.next()) {
863 const int i = p.i(), j = p.j();
std::shared_ptr< EnthalpyConverter > Ptr
unsigned int dimension_length(const std::string &name) const
Get the length of a dimension.
High-level PISM I/O class.
array::Scalar1 sea_level_elevation
array::CellType2 cell_type
array::Scalar2 ice_thickness
array::Scalar2 bed_elevation
virtual void allocate_bed_deformation()
void compute_strain_heating_errors(double &gmax_strain_heating_err, double &gav_strain_heating_err)
virtual void post_step_hook()
Virtual. Does nothing in IceModel. Derived classes can do more computation in each time step.
void reset_thickness_test_A()
Tests A and E have a thickness B.C. (ice_thickness == 0 outside a circle of radius 750km).
void bootstrap_2d(const File &input_file) __attribute__((noreturn))
virtual void allocate_couplers()
virtual void allocate_bedrock_thermal_unit()
Decide which bedrock thermal unit to use.
array::Array3D m_strain_heating3_comp
void test_V_init()
Initialize test V.
virtual void initialize_2d()
void computeSurfaceVelocityErrors(double &gmaxUerr, double &gavUerr, double &gmaxWerr, double &gavWerr)
bool m_bedrock_is_ice_forK
virtual void allocate_energy_model()
void computeIceBedrockTemperatureErrors(double &gmaxTerr, double &gavTerr, double &gmaxTberr, double &gavTberr)
virtual void allocate_storage()
Allocate all Arrays defined in IceModel.
void computeTemperatureErrors(double &gmaxTerr, double &gavTerr)
void computeGeometryErrors(double &gvolexact, double &gareaexact, double &gdomeHexact, double &volerr, double &areaerr, double &gmaxHerr, double &gavHerr, double &gmaxetaerr, double ¢erHerr)
static const double m_LforFG
virtual void print_summary(bool tempAndAge)
IceCompModel(std::shared_ptr< Grid > g, std::shared_ptr< Context > ctx, int mytest)
void computeBasalMeltRateErrors(double &gmaxbmelterr, double &gminbmelterr)
static const double m_ApforG
void computeBasalTemperatureErrors(double &gmaxTerr, double &gavTerr, double ¢erTerr)
std::map< std::string, const Component * > m_submodels
the list of sub-models, for writing model states and obtaining diagnostics
virtual void allocate_bed_deformation()
std::shared_ptr< stressbalance::StressBalance > m_stress_balance
std::shared_ptr< ocean::OceanModel > m_ocean
std::shared_ptr< surface::SurfaceModel > m_surface
const Time::Ptr m_time
Time manager.
std::shared_ptr< Context > m_ctx
Execution context.
const Logger::Ptr m_log
Logger.
virtual void print_summary(bool tempAndAge)
VariableMetadata m_output_global_attributes
stores global attributes saved in a PISM output file
virtual void allocate_storage()
Allocate all Arrays defined in IceModel.
array::Scalar2 m_velocity_bc_mask
mask to determine Dirichlet boundary locations for the sliding velocity
Config::Ptr m_config
Configuration flags and parameters.
std::shared_ptr< energy::BedThermalUnit > m_btu
array::Scalar1 m_ice_thickness_bc_mask
Mask prescribing locations where ice thickness is held constant.
const units::System::Ptr m_sys
Unit system.
array::Vector2 m_velocity_bc_values
Dirichlet boundary velocities.
std::shared_ptr< ocean::sea_level::SeaLevel > m_sea_level
std::shared_ptr< energy::EnergyModel > m_energy_model
const std::shared_ptr< Grid > m_grid
Computational grid.
std::shared_ptr< bed::BedDef > m_beddef
void failed()
Indicates a failure of a parallel section.
void add(const PetscAccessible &v)
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
void copy_from(const Array2D< T > &source)
void scale(double alpha)
Result: v <- v * alpha. Calls VecScale.
void set(double c)
Result: v[j] <- c for all j.
void update_ghosts()
Updates ghost points.
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata object containing metadata for the compoment N.
A class implementing a constant (in terms of the ocean inputs) ocean model. Uses configuration parame...
Class used initTestL() in generating sorted list for ODE solver.
Climate inputs for verification tests.
std::shared_ptr< System > Ptr
#define PISM_ERROR_LOCATION
struct TestHParameters exactH(const double f, const double t, const double r)
ExactLParameters exactL(const std::vector< double > &r)
struct TestABCDParameters exactB(const double t, const double r)
struct TestABCDParameters exactD(const double t, const double r)
struct TestABCDParameters exactA(double r)
struct TestABCDParameters exactC(const double t, const double r)
double radius(const Grid &grid, int i, int j)
Returns the distance from the point (i,j) to the origin.
@ PISM_READWRITE_MOVE
create a file for writing, move foo.nc to foo.nc~ if present
@ PISM_READWRITE
open an existing file for reading and writing
void write_attributes(const File &file, const VariableMetadata &variable, io::Type nctype)
Write variable attributes to a NetCDF file.
void write_timeseries(const File &file, const VariableMetadata &metadata, size_t t_start, const std::vector< double > &data)
Write a time-series data to a file.
void define_timeseries(const VariableMetadata &var, const std::string &dimension_name, const File &file, io::Type nctype)
Define a NetCDF variable corresponding to a time-series.
bool Bool(const std::string &option, const std::string &description)
double convert(System::Ptr system, double input, const std::string &spec1, const std::string &spec2)
Convert a quantity from unit1 to unit2.
static void write(units::System::Ptr sys, const File &file, size_t start, const char *name, const char *units, const char *long_name, double value, io::Type type=io::PISM_DOUBLE)
void GlobalMax(MPI_Comm comm, double *local, double *result, int count)
TestFGParameters exactFG(double t, double r, const std::vector< double > &z, double Cp)
void GlobalSum(MPI_Comm comm, double *local, double *result, int count)
static BTUGrid FromOptions(std::shared_ptr< const Context > ctx)
bool operator()(rgrid a, rgrid b)
Comparison used initTestL() in generating sorted list for ODE solver.