43std::shared_ptr<pism::Context>
btutest_context(MPI_Comm com,
const std::string &prefix) {
53 Config::Ptr config = config_from_options(com, *logger, sys);
58 config->set_number(
"grid.Mx", Mx);
59 config->set_number(
"grid.My", Mx);
60 config->set_number(
"grid.Lx", Lx);
61 config->set_number(
"grid.Ly", Lx);
64 config->set_number(
"grid.Mbz", 11);
65 config->set_number(
"grid.Lbz", 1000);
68 config->set_string(
"time.start",
"0s");
69 config->set_number(
"time.run_length", 1.0);
71 set_config_from_options(sys, *config);
72 config->resolve_filenames();
74 print_config(*logger, 3, *config);
76 Time::Ptr time = std::make_shared<Time>(com, config, *logger, sys);
80 return std::shared_ptr<Context>(
new Context(com, sys, config, EC, time, logger, prefix));
83int main(
int argc,
char *argv[]) {
87 MPI_Comm com = MPI_COMM_WORLD;
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";
107 bool done = show_usage_check_req_opts(*log,
"BTUTEST %s (test program for BedThermalUnit)",
114 " initializing Grid from options ...\n");
116 auto config = ctx->config();
124 std::shared_ptr<Grid> grid(
new Grid(ctx, P));
126 auto outname = config->get_string(
"output.file");
129 "-dt",
"Time-step, in years",
"years", 1.0);
135 array::Scalar heat_flux_at_ice_base(grid,
"upward_heat_flux_at_ice_base");
137 .
long_name(
"upward geothermal flux at bedrock thermal layer base")
146 if (bedrock_grid.
Mbz > 1) {
155 double dt_seconds = units::convert(ctx->unit_system(), dt_years,
"years",
"seconds");
158 int N = (
int)ceil((ctx->time()->end() - ctx->time()->start()) / dt_seconds);
159 dt_seconds = (ctx->time()->end() - ctx->time()->start()) / (
double)N;
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"));
166 " BedThermalUnit reports max timestep of %.4f years ...\n",
167 units::convert(ctx->unit_system(), max_dt.
value(),
"seconds",
"years"));
170 log->message(2,
" running ...\n");
171 for (
int n = 0;
n < N;
n++) {
173 const double time = ctx->time()->start() + dt_seconds * (
double)
n;
178 for (
auto p = grid->points(); p; p.next()) {
179 const int i = p.i(), j = p.j();
181 bedtoptemp(i,j) =
exactK(time, 0.0, 0).
T;
187 btu->update(bedtoptemp, time, dt_seconds);
191 log->message(2,
"\n done ...\n");
194 heat_flux_at_ice_base.
copy_from(btu->flux_through_top_surface());
196 auto time = ctx->time();
199 const double FF =
exactK(time->end(), 0.0, 0).
F;
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);
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);
209 avg_error /= (grid->Mx() * grid->My());
211 "case dt = %.5f:\n", dt_years.
value());
213 "NUMERICAL ERRORS in upward heat flux at z=0 relative to exact solution:\n");
215 "bheatflx0 : max prcntmax av\n");
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");
223 string_to_backend(config->get_string(
"output.format")),
224 io::PISM_READWRITE_MOVE);
226 io::define_time(file, *ctx);
227 io::append_time(file, *ctx->config(), ctx->time()->current());
229 btu->write_model_state(file);
231 bedtoptemp.
write(file);
232 heat_flux_at_ice_base.
write(file);
234 log->message(2,
"done.\n");
237 handle_fatal_errors(com);