19#include "pism/stressbalance/ssa/SSATestCase.hh"
20#include "pism/stressbalance/ssa/SSAFD_SNES.hh"
21#include "pism/stressbalance/StressBalance.hh"
22#include "pism/util/Context.hh"
23#include "pism/util/Interpolation1D.hh"
24#include "pism/util/io/File.hh"
25#include "pism/util/io/io_helpers.hh"
26#include "pism/util/pism_options.hh"
27#include "pism/util/pism_utilities.hh"
29#include "pism/stressbalance/ssa/SSAFD.hh"
30#include "pism/stressbalance/ssa/SSAFEM.hh"
33namespace stressbalance {
36 : m_grid(ssa->grid()),
38 m_config(m_ctx->config()),
39 m_sys(m_ctx->unit_system()),
40 m_tauc(m_grid,
"tauc"),
41 m_ice_enthalpy(m_grid,
"enthalpy", array::WITH_GHOSTS, m_grid->z(), 1),
42 m_bc_values(m_grid,
"_bc"),
43 m_bc_mask(m_grid,
"bc_mask"),
51 .
long_name(
"yield stress for basal till (plastic or pseudo-plastic model)")
56 .
long_name(
"ice enthalpy (includes sensible heat, latent heat, pressure)")
61 .
long_name(
"X-component of the SSA velocity boundary conditions")
65 .
long_name(
"Y-component of the SSA velocity boundary conditions")
91 if (method ==
"fem") {
92 return std::make_shared<SSAFEM>(grid);
95 return std::make_shared<SSAFD>(grid,
false);
97 return std::make_shared<SSAFD_SNES>(grid,
false);
111 m_ctx->log()->message(2,
"* Solving the SSA stress balance ...\n");
123 bool full_update =
true;
124 m_ssa->update(inputs, full_update);
130 m_ctx->log()->message(3,
m_ssa->stdout_report());
132 double maxvecerr = 0.0, avvecerr = 0.0, avuerr = 0.0, avverr = 0.0, maxuerr = 0.0, maxverr = 0.0;
133 double gmaxvecerr = 0.0, gavvecerr = 0.0, gavuerr = 0.0, gavverr = 0.0, gmaxuerr = 0.0,
136 if (
m_config->get_flag(
"basal_resistance.pseudo_plastic.enabled") &&
137 m_config->get_number(
"basal_resistance.pseudo_plastic.q") != 1.0) {
138 m_ctx->log()->message(1,
"WARNING: numerical errors not valid for pseudo-plastic till\n");
140 m_ctx->log()->message(1,
"NUMERICAL ERRORS in velocity relative to exact solution:\n");
146 double exactvelmax = 0, gexactvelmax = 0;
147 for (
auto p =
m_grid->points(); p; p.next()) {
148 const int i = p.i(), j = p.j();
150 double uexact, vexact;
155 double exactnormsq = sqrt(uexact * uexact + vexact * vexact);
156 exactvelmax = std::max(exactnormsq, exactvelmax);
159 const double uerr = fabs(vel_ssa(i, j).u - uexact);
160 const double verr = fabs(vel_ssa(i, j).v - vexact);
161 avuerr = avuerr + uerr;
162 avverr = avverr + verr;
163 maxuerr = std::max(maxuerr, uerr);
164 maxverr = std::max(maxverr, verr);
165 const double vecerr = sqrt(uerr * uerr + verr * verr);
166 maxvecerr = std::max(maxvecerr, vecerr);
167 avvecerr = avvecerr + vecerr;
176 gavuerr = gavuerr / N;
178 gavverr = gavverr / N;
181 gavvecerr = gavvecerr / N;
185 m_ctx->log()->message(
186 1,
"velocity : maxvector prcntavvec maxu maxv avu avv\n");
187 m_ctx->log()->message(1,
" %11.4f%13.5f%10.4f%10.4f%10.4f%10.4f\n",
188 convert(
m_sys, gmaxvecerr,
"m second-1",
"m year-1"),
189 (gavvecerr / gexactvelmax) * 100.0,
190 convert(
m_sys, gmaxuerr,
"m second-1",
"m year-1"),
191 convert(
m_sys, gmaxverr,
"m second-1",
"m year-1"),
192 convert(
m_sys, gavuerr,
"m second-1",
"m year-1"),
193 convert(
m_sys, gavverr,
"m second-1",
"m year-1"));
195 m_ctx->log()->message(1,
"NUM ERRORS DONE\n");
198 (gavvecerr / gexactvelmax) * 100.0,
199 convert(
m_sys, gmaxuerr,
"m second-1",
"m year-1"),
200 convert(
m_sys, gmaxverr,
"m second-1",
"m year-1"),
201 convert(
m_sys, gavuerr,
"m second-1",
"m year-1"),
202 convert(
m_sys, gavverr,
"m second-1",
"m year-1"));
206 double max_u,
double max_v,
double avg_u,
double avg_v) {
207 auto sys =
m_grid->ctx()->unit_system();
213 if (not filename.
is_set()) {
217 m_ctx->log()->message(2,
"Also writing errors to '%s'...\n", filename->c_str());
219 bool append =
options::Bool(
"-append",
"Append the NetCDF error report");
226 global_attributes[
"source"] = std::string(
"PISM ") + pism::revision;
259 max_velocity.
long_name(
"maximum ice velocity magnitude error").
units(
"m year^-1");
265 rel_velocity.
long_name(
"relative ice velocity magnitude error").
units(
"percent");
271 maximum_u.
long_name(
"maximum error in the X-component of the ice velocity").
units(
"m year^-1");
277 maximum_v.
long_name(
"maximum error in the Y-component of the ice velocity").
units(
"m year^-1");
283 average_u.
long_name(
"average error in the X-component of the ice velocity").
units(
"m year^-1");
289 average_v.
long_name(
"average error in the Y-component of the ice velocity").
units(
"m year^-1");
318 m_ssa->velocity().write(file);
322 auto diagnostics =
m_ssa->diagnostics();
324 for (
auto &p : diagnostics) {
326 p.second->compute()->write(file);
335 .
long_name(
"X-component of the SSA exact solution")
338 .
long_name(
"Y-component of the SSA exact solution")
342 for (
auto p =
m_grid->points(); p; p.next()) {
343 const int i = p.i(), j = p.j();
346 &(tmp(i,j).u), &(tmp(i,j).v));
352 .
long_name(
"X-component of the error (exact - computed)")
356 .
long_name(
"Y-component of the error (exact - computed)")
365 error_mag.
write(file);
unsigned int dimension_length(const std::string &name) const
Get the length of a dimension.
High-level PISM I/O class.
void ensure_consistency(double ice_free_thickness_threshold)
array::Scalar2 ice_surface_elevation
array::Scalar2 ice_thickness
array::Scalar2 bed_elevation
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
void add(double alpha, const Array2D< T > &x)
void set_interpolation_type(InterpolationType type)
void write(const std::string &filename) const
void set(double c)
Result: v[j] <- c for all j.
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata object containing metadata for the compoment N.
std::shared_ptr< const pism::Grid > m_grid
virtual void init()
Initialize the test case at the start of a run.
const units::System::Ptr m_sys
array::Array3D m_ice_enthalpy
virtual void initializeSSACoefficients()=0
Set up the coefficient variables as appropriate for the test case.
void report_netcdf(const std::string &testname, double max_vector, double rel_vector, double max_u, double max_v, double avg_u, double avg_v)
array::Vector2 m_bc_values
virtual void exactSolution(int i, int j, double x, double y, double *u, double *v)
static std::shared_ptr< SSA > solver(std::shared_ptr< Grid > grid, const std::string &method)
virtual void report(const std::string &testname)
Report on the generated solution.
virtual void run()
Solve the SSA.
SSATestCase(std::shared_ptr< SSA > ssa)
const Config::ConstPtr m_config
std::shared_ptr< SSA > m_ssa
virtual void write(const std::string &filename)
Save the computation and data to a file.
const std::shared_ptr< const Context > m_ctx
std::shared_ptr< System > Ptr
void compute_magnitude(const array::Vector &input, array::Scalar &result)
void append_time(const File &file, const Config &config, double time_seconds)
Prepare a file for output.
@ 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_time(const File &file, const Context &ctx)
Prepare a file for output.
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.
void GlobalMax(MPI_Comm comm, double *local, double *result, int count)
void GlobalSum(MPI_Comm comm, double *local, double *result, int count)