44std::shared_ptr<pism::Context>
btutest_context(MPI_Comm com,
const std::string &prefix) {
51 auto logger = std::make_shared<Logger>(com, 1);
53 auto config = config_from_options(com, sys);
55 logger->set_threshold(
static_cast<int>(config->get_number(
"output.runtime.verbosity")));
60 config->set_number(
"grid.Mx", Mx);
61 config->set_number(
"grid.My", Mx);
62 config->set_number(
"grid.Lx", Lx);
63 config->set_number(
"grid.Ly", Lx);
66 config->set_number(
"grid.Mbz", 11);
67 config->set_number(
"grid.Lbz", 1000);
70 config->set_string(
"time.start",
"0s");
71 config->set_number(
"time.run_length", 1.0);
73 set_config_from_options(*config);
74 config->resolve_filenames();
76 print_config(*logger, 3, *config);
78 auto time = std::make_shared<Time>(com, config, *logger, sys);
82 return std::shared_ptr<Context>(
new Context(com, sys, config, EC, time, logger, prefix));
85int main(
int argc,
char *argv[]) {
89 MPI_Comm com = MPI_COMM_WORLD;
96 auto log = ctx->log();
99 " pism_btutest -Mbz NN -Lbz 1000.0 [-o OUT.nc -ys A -ye B -dt C -Mz D -Lz E]\n"
100 "where these are required because they are used in BedThermalUnit:\n"
101 " -Mbz number of bedrock thermal layer levels to use\n"
102 " -Lbz 1000.0 depth of bedrock thermal layer (required; Lbz=1000.0 m in Test K)\n"
103 "and these are allowed:\n"
104 " -o output file name; NetCDF format\n"
105 " -ys start year in using Test K\n"
106 " -ye end year in using Test K\n"
107 " -dt time step B (= positive float) in years\n";
109 bool done = maybe_show_usage(*log,
"BTUTEST %s (test program for BedThermalUnit)", usage);
115 " initializing Grid from options ...\n");
117 auto config = ctx->config();
125 std::shared_ptr<Grid> grid(
new Grid(ctx, P));
127 auto outname = config->get_string(
"output.file");
130 "-dt",
"Time-step, in years",
"years", 1.0);
136 array::Scalar heat_flux_at_ice_base(grid,
"upward_heat_flux_at_ice_base");
138 .
long_name(
"upward geothermal flux at bedrock thermal layer base")
145 std::shared_ptr<energy::BedThermalUnit> btu;
147 if (bedrock_grid.
Mbz > 1) {
156 double dt_seconds = units::convert(ctx->unit_system(), dt_years,
"years",
"seconds");
159 int N = (
int)ceil((ctx->time()->end() - ctx->time()->start()) / dt_seconds);
160 dt_seconds = (ctx->time()->end() - ctx->time()->start()) / (
double)N;
162 " user set timestep of %.4f years ...\n"
163 " reset to %.4f years to get integer number of steps ... \n",
164 dt_years.
value(), units::convert(ctx->unit_system(), dt_seconds,
"seconds",
"years"));
167 " BedThermalUnit reports max timestep of %.4f years ...\n",
168 units::convert(ctx->unit_system(), max_dt.
value(),
"seconds",
"years"));
171 log->message(2,
" running ...\n");
172 for (
int n = 0;
n < N;
n++) {
174 const double time = ctx->time()->start() + dt_seconds * (
double)
n;
179 for (
auto p : grid->points()) {
180 const int i = p.i(), j = p.j();
182 bedtoptemp(i,j) =
exactK(time, 0.0, 0).
T;
188 btu->update(bedtoptemp, time, dt_seconds);
192 log->message(2,
"\n done ...\n");
195 heat_flux_at_ice_base.
copy_from(btu->flux_through_top_surface());
197 auto time = ctx->time();
200 const double FF =
exactK(time->end(), 0.0, 0).
F;
202 " exact Test K reports upward heat flux at z=0, at end time %s, as G_0 = %.7f W m-2;\n",
203 time->date(time->end()).c_str(), FF);
206 heat_flux_at_ice_base.
shift(-FF);
207 double max_error = heat_flux_at_ice_base.
norm(NORM_INFINITY)[0];
208 double avg_error = heat_flux_at_ice_base.
norm(NORM_1)[0];
209 heat_flux_at_ice_base.
shift(+FF);
210 avg_error /= (grid->Mx() * grid->My());
212 "case dt = %.5f:\n", dt_years.
value());
214 "NUMERICAL ERRORS in upward heat flux at z=0 relative to exact solution:\n");
216 "bheatflx0 : max prcntmax av\n");
218 " %11.7f %11.7f %11.7f\n",
219 max_error, 100.0*max_error/FF, avg_error);
220 log->message(1,
"NUM ERRORS DONE\n");
222 auto writer = std::make_shared<SynchronousOutputWriter>(grid->com, *config);
223 writer->initialize({},
true);
232 pism::combine(btu->state(), array::metadata({ &bedtoptemp, &heat_flux_at_ice_base }));
234 for (
const auto &v : variables) {
238 btu->write_state(file);
239 bedtoptemp.
write(file);
240 heat_flux_at_ice_base.
write(file);
242 log->message(2,
"done.\n");
245 handle_fatal_errors(com);