Loading [MathJax]/extensions/tex2jax.js
PISM, A Parallel Ice Sheet Model 2.2.2-d6b3a29ca committed by Constantine Khrulev on 2025-03-28
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
btutest.cc
Go to the documentation of this file.
1// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024 Ed Bueler and Constantine Khroulev
2//
3// This file is part of PISM.
4//
5// PISM is free software; you can redistribute it and/or modify it under the
6// terms of the GNU General Public License as published by the Free Software
7// Foundation; either version 3 of the License, or (at your option) any later
8// version.
9//
10// PISM is distributed in the hope that it will be useful, but WITHOUT ANY
11// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13// details.
14//
15// You should have received a copy of the GNU General Public License
16// along with PISM; if not, write to the Free Software
17// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19#include <petsc.h>
20
21static char help[] =
22 "Tests BedThermalUnit using Test K, without IceModel.\n\n";
23
24#include "pism/util/pism_options.hh"
25#include "pism/util/Grid.hh"
26#include "pism/util/io/File.hh"
27#include "pism/verification/BTU_Verification.hh"
28#include "pism/energy/BTU_Minimal.hh"
29#include "pism/util/Time.hh"
30#include "pism/util/ConfigInterface.hh"
31
32#include "pism/verification/tests/exactTestK.h"
33
34#include "pism/util/petscwrappers/PetscInitializer.hh"
35#include "pism/util/error_handling.hh"
36#include "pism/util/io/io_helpers.hh"
37#include "pism/util/Context.hh"
38#include "pism/util/EnthalpyConverter.hh"
39#include "pism/util/MaxTimestep.hh"
40#include "pism/util/Logger.hh"
41
42//! Allocate the verification context. Uses ColdEnthalpyConverter.
43std::shared_ptr<pism::Context> btutest_context(MPI_Comm com, const std::string &prefix) {
44 using namespace pism;
45
46 // unit system
48
49 // logger
50 Logger::Ptr logger = logger_from_options(com);
51
52 // configuration parameters
53 Config::Ptr config = config_from_options(com, *logger, sys);
54
55 int Mx = 3;
56 double Lx = 1500;
57 // default horizontal grid parameters
58 config->set_number("grid.Mx", Mx);
59 config->set_number("grid.My", Mx);
60 config->set_number("grid.Lx", Lx); // in km
61 config->set_number("grid.Ly", Lx); // in km
62
63 // default vertical grid parameters
64 config->set_number("grid.Mbz", 11);
65 config->set_number("grid.Lbz", 1000); // in m
66
67 // when Grid constructor is called, these settings are used
68 config->set_string("time.start", "0s");
69 config->set_number("time.run_length", 1.0);
70
71 set_config_from_options(sys, *config);
72 config->resolve_filenames();
73
74 print_config(*logger, 3, *config);
75
76 Time::Ptr time = std::make_shared<Time>(com, config, *logger, sys);
77
79
80 return std::shared_ptr<Context>(new Context(com, sys, config, EC, time, logger, prefix));
81}
82
83int main(int argc, char *argv[]) {
84
85 using namespace pism;
86
87 MPI_Comm com = MPI_COMM_WORLD;
88 petsc::Initializer petsc(argc, argv, help);
89
90 com = MPI_COMM_WORLD;
91
92 try {
93 std::shared_ptr<Context> ctx = btutest_context(com, "pism_btutest");
94 Logger::Ptr log = ctx->log();
95
96 std::string usage =
97 " pism_btutest -Mbz NN -Lbz 1000.0 [-o OUT.nc -ys A -ye B -dt C -Mz D -Lz E]\n"
98 "where these are required because they are used in BedThermalUnit:\n"
99 " -Mbz number of bedrock thermal layer levels to use\n"
100 " -Lbz 1000.0 depth of bedrock thermal layer (required; Lbz=1000.0 m in Test K)\n"
101 "and these are allowed:\n"
102 " -o output file name; NetCDF format\n"
103 " -ys start year in using Test K\n"
104 " -ye end year in using Test K\n"
105 " -dt time step B (= positive float) in years\n";
106
107 bool done = show_usage_check_req_opts(*log, "BTUTEST %s (test program for BedThermalUnit)",
108 {"-Mbz"}, usage);
109 if (done) {
110 return 0;
111 }
112
113 log->message(2,
114 " initializing Grid from options ...\n");
115
116 auto config = ctx->config();
117
118 grid::Parameters P(*config);
119
121 P.ownership_ranges_from_options(*ctx->config(), ctx->size());
122
123 // create grid and set defaults
124 std::shared_ptr<Grid> grid(new Grid(ctx, P));
125
126 auto outname = config->get_string("output.file");
127
128 options::Real dt_years(ctx->unit_system(),
129 "-dt", "Time-step, in years", "years", 1.0);
130
131 // allocate tools and Arrays
132 array::Scalar bedtoptemp(grid, "bedtoptemp");
133 bedtoptemp.metadata(0).long_name("temperature at top of bedrock thermal layer").units("kelvin");
134
135 array::Scalar heat_flux_at_ice_base(grid, "upward_heat_flux_at_ice_base");
136 heat_flux_at_ice_base.metadata(0)
137 .long_name("upward geothermal flux at bedrock thermal layer base")
138 .units("W m^-2")
139 .output_units("mW m^-2");
140
141 // initialize BTU object:
142 energy::BTUGrid bedrock_grid = energy::BTUGrid::FromOptions(ctx);
143
145
146 if (bedrock_grid.Mbz > 1) {
147 btu.reset(new energy::BTU_Verification(grid, bedrock_grid, 'K', false));
148 } else {
149 btu.reset(new energy::BTU_Minimal(grid));
150 }
151
152 InputOptions opts = process_input_options(com, config);
153 btu->init(opts);
154
155 double dt_seconds = units::convert(ctx->unit_system(), dt_years, "years", "seconds");
156
157 // worry about time step
158 int N = (int)ceil((ctx->time()->end() - ctx->time()->start()) / dt_seconds);
159 dt_seconds = (ctx->time()->end() - ctx->time()->start()) / (double)N;
160 log->message(2,
161 " user set timestep of %.4f years ...\n"
162 " reset to %.4f years to get integer number of steps ... \n",
163 dt_years.value(), units::convert(ctx->unit_system(), dt_seconds, "seconds", "years"));
164 MaxTimestep max_dt = btu->max_timestep(0.0);
165 log->message(2,
166 " BedThermalUnit reports max timestep of %.4f years ...\n",
167 units::convert(ctx->unit_system(), max_dt.value(), "seconds", "years"));
168
169 // actually do the time-stepping
170 log->message(2," running ...\n");
171 for (int n = 0; n < N; n++) {
172 // time at start of time-step
173 const double time = ctx->time()->start() + dt_seconds * (double)n;
174
175 // compute exact ice temperature at z=0 at time y
176 {
177 array::AccessScope list(bedtoptemp);
178 for (auto p = grid->points(); p; p.next()) {
179 const int i = p.i(), j = p.j();
180
181 bedtoptemp(i,j) = exactK(time, 0.0, 0).T;
182 }
183 }
184 // no need to update ghost values
185
186 // update the temperature inside the thermal layer using bedtoptemp
187 btu->update(bedtoptemp, time, dt_seconds);
188 log->message(2,".");
189 }
190
191 log->message(2, "\n done ...\n");
192
193 // compute final output heat flux G_0 at z=0
194 heat_flux_at_ice_base.copy_from(btu->flux_through_top_surface());
195
196 auto time = ctx->time();
197
198 // get, and tell stdout, the correct answer from Test K
199 const double FF = exactK(time->end(), 0.0, 0).F;
200 log->message(2,
201 " exact Test K reports upward heat flux at z=0, at end time %s, as G_0 = %.7f W m-2;\n",
202 time->date(time->end()).c_str(), FF);
203
204 // compute numerical error
205 heat_flux_at_ice_base.shift(-FF);
206 double max_error = heat_flux_at_ice_base.norm(NORM_INFINITY)[0];
207 double avg_error = heat_flux_at_ice_base.norm(NORM_1)[0];
208 heat_flux_at_ice_base.shift(+FF); // shift it back for writing
209 avg_error /= (grid->Mx() * grid->My());
210 log->message(2,
211 "case dt = %.5f:\n", dt_years.value());
212 log->message(1,
213 "NUMERICAL ERRORS in upward heat flux at z=0 relative to exact solution:\n");
214 log->message(1,
215 "bheatflx0 : max prcntmax av\n");
216 log->message(1,
217 " %11.7f %11.7f %11.7f\n",
218 max_error, 100.0*max_error/FF, avg_error);
219 log->message(1, "NUM ERRORS DONE\n");
220
221 File file(grid->com,
222 outname,
223 string_to_backend(config->get_string("output.format")),
224 io::PISM_READWRITE_MOVE);
225
226 io::define_time(file, *ctx);
227 io::append_time(file, *ctx->config(), ctx->time()->current());
228
229 btu->write_model_state(file);
230
231 bedtoptemp.write(file);
232 heat_flux_at_ice_base.write(file);
233
234 log->message(2, "done.\n");
235 }
236 catch (...) {
237 handle_fatal_errors(com);
238 return 1;
239 }
240
241 return 0;
242}
int main(int argc, char *argv[])
Definition btutest.cc:83
static char help[]
Definition btutest.cc:21
std::shared_ptr< pism::Context > btutest_context(MPI_Comm com, const std::string &prefix)
Allocate the verification context. Uses ColdEnthalpyConverter.
Definition btutest.cc:43
An EnthalpyConverter for use in verification tests.
std::shared_ptr< Config > Ptr
std::shared_ptr< EnthalpyConverter > Ptr
High-level PISM I/O class.
Definition File.hh:55
Describes the PISM grid and the distribution of data across processors.
Definition Grid.hh:290
std::shared_ptr< Logger > Ptr
Definition Logger.hh:45
double value() const
Get the value of the maximum time step.
Combines the max. time step with the flag indicating if a restriction is active. Makes is possible to...
std::shared_ptr< Time > Ptr
Definition Time.hh:62
VariableMetadata & long_name(const std::string &input)
VariableMetadata & units(const std::string &input)
VariableMetadata & output_units(const std::string &input)
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition Array.hh:64
void copy_from(const Array2D< T > &source)
Definition Array2D.hh:73
void shift(double alpha)
Result: v[j] <- v[j] + alpha for all j. Calls VecShift.
Definition Array.cc:216
void write(const std::string &filename) const
Definition Array.cc:722
std::vector< double > norm(int n) const
Computes the norm of all the components of an Array.
Definition Array.cc:668
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata object containing metadata for the compoment N.
Definition Array.cc:476
std::shared_ptr< BedThermalUnit > Ptr
void vertical_grid_from_options(const Config &config)
Process -Mz and -Lz; set z;.
Definition Grid.cc:1326
void ownership_ranges_from_options(const Config &config, unsigned int size)
Re-compute ownership ranges. Uses current values of Mx and My.
Definition Grid.cc:1192
Grid parameters; used to collect defaults before an Grid is allocated.
Definition Grid.hh:123
std::shared_ptr< System > Ptr
Definition Units.hh:47
struct TestKParameters exactK(double t, double z, int bedrock_is_ice)
Definition exactTestK.c:129
#define n
Definition exactTestM.c:37