19#include "pism/stressbalance/ssa/tests/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/pism_options.hh"
26#include "pism/util/pism_utilities.hh"
28#include "pism/stressbalance/ssa/SSAFD.hh"
29#include "pism/stressbalance/ssa/SSAFEM.hh"
30#include "pism/util/Logger.hh"
31#include "pism/util/Time.hh"
32#include "pism/util/io/SynchronousOutputWriter.hh"
33#include "pism/util/io/IO_Flags.hh"
34#include "pism/util/io/io_helpers.hh"
38namespace stressbalance {
41 : m_grid(ssa->grid()),
43 m_config(m_ctx->config()),
44 m_sys(m_ctx->unit_system()),
45 m_tauc(m_grid,
"tauc"),
46 m_ice_enthalpy(m_grid,
"enthalpy", array::WITH_GHOSTS, m_grid->z(), 1),
47 m_bc_values(m_grid,
"_bc"),
48 m_bc_mask(m_grid,
"bc_mask"),
56 .
long_name(
"yield stress for basal till (plastic or pseudo-plastic model)")
61 .
long_name(
"ice enthalpy (includes sensible heat, latent heat, pressure)")
66 .
long_name(
"X-component of the SSA velocity boundary conditions")
70 .
long_name(
"Y-component of the SSA velocity boundary conditions")
96 if (method ==
"fem") {
97 return std::make_shared<SSAFEM>(grid);
100 return std::make_shared<SSAFD>(grid,
false);
102 return std::make_shared<SSAFD_SNES>(grid,
false);
116 m_ctx->log()->message(2,
"* Solving the SSA stress balance ...\n");
128 bool full_update =
true;
129 m_ssa->update(inputs, full_update);
135 m_ctx->log()->message(3,
m_ssa->stdout_report());
137 double maxvecerr = 0.0, avvecerr = 0.0, avuerr = 0.0, avverr = 0.0, maxuerr = 0.0, maxverr = 0.0;
138 double gmaxvecerr = 0.0, gavvecerr = 0.0, gavuerr = 0.0, gavverr = 0.0, gmaxuerr = 0.0,
141 if (
m_config->get_flag(
"basal_resistance.pseudo_plastic.enabled") &&
142 m_config->get_number(
"basal_resistance.pseudo_plastic.q") != 1.0) {
143 m_ctx->log()->message(1,
"WARNING: numerical errors not valid for pseudo-plastic till\n");
145 m_ctx->log()->message(1,
"NUMERICAL ERRORS in velocity relative to exact solution:\n");
151 double exactvelmax = 0, gexactvelmax = 0;
152 for (
auto p :
m_grid->points()) {
153 const int i = p.i(), j = p.j();
155 double uexact, vexact;
160 double exactnormsq = sqrt(uexact * uexact + vexact * vexact);
161 exactvelmax = std::max(exactnormsq, exactvelmax);
164 const double uerr = fabs(vel_ssa(i, j).u - uexact);
165 const double verr = fabs(vel_ssa(i, j).v - vexact);
166 avuerr = avuerr + uerr;
167 avverr = avverr + verr;
168 maxuerr = std::max(maxuerr, uerr);
169 maxverr = std::max(maxverr, verr);
170 const double vecerr = sqrt(uerr * uerr + verr * verr);
171 maxvecerr = std::max(maxvecerr, vecerr);
172 avvecerr = avvecerr + vecerr;
181 gavuerr = gavuerr / N;
183 gavverr = gavverr / N;
186 gavvecerr = gavvecerr / N;
190 m_ctx->log()->message(
191 1,
"velocity : maxvector prcntavvec maxu maxv avu avv\n");
192 m_ctx->log()->message(1,
" %11.4f%13.5f%10.4f%10.4f%10.4f%10.4f\n",
193 convert(
m_sys, gmaxvecerr,
"m second-1",
"m year-1"),
194 (gavvecerr / gexactvelmax) * 100.0,
195 convert(
m_sys, gmaxuerr,
"m second-1",
"m year-1"),
196 convert(
m_sys, gmaxverr,
"m second-1",
"m year-1"),
197 convert(
m_sys, gavuerr,
"m second-1",
"m year-1"),
198 convert(
m_sys, gavverr,
"m second-1",
"m year-1"));
200 m_ctx->log()->message(1,
"NUM ERRORS DONE\n");
203 (gavvecerr / gexactvelmax) * 100.0,
204 convert(
m_sys, gmaxuerr,
"m second-1",
"m year-1"),
205 convert(
m_sys, gmaxverr,
"m second-1",
"m year-1"),
206 convert(
m_sys, gavuerr,
"m second-1",
"m year-1"),
207 convert(
m_sys, gavverr,
"m second-1",
"m year-1"));
213 const char *long_name,
214 unsigned int start,
double value,
225 double max_u,
double max_v,
double avg_u,
double avg_v) {
226 auto sys =
m_grid->ctx()->unit_system();
229 global_attributes[
"source"] = std::string(
"PISM ") + pism::revision;
233 if (not filename.
is_set()) {
237 m_ctx->log()->message(2,
"Also writing errors to '%s'...\n", filename->c_str());
239 bool append =
options::Bool(
"-append",
"Append the NetCDF error report");
250 for (
const auto &arg : global_attributes.
all_strings()) {
262 details::write(file,
"max_velocity",
"m year^-1",
"maximum ice velocity magnitude error", start,
265 details::write(file,
"relative_velocity",
"percent",
"relative ice velocity magnitude error",
269 "maximum error in the X-component of the ice velocity", start, max_u);
272 "maximum error in the Y-component of the ice velocity", start, max_v);
275 "average error in the X-component of the ice velocity", start, avg_u);
278 "average error in the Y-component of the ice velocity", start, avg_v);
291 auto writer = std::make_shared<SynchronousOutputWriter>(
m_grid->com, *
m_config);
292 writer->initialize({},
true);
307 for (
const auto *v : variables) {
308 for (
const auto &m : v->all_metadata()) {
314 for (
const auto *v : variables) {
320 std::vector<std::shared_ptr<array::Array>> vecs;
321 for (
auto &pair :
m_ssa->spatial_diagnostics()) {
323 vecs.push_back(pair.second->compute());
330 for (
auto &v : vecs) {
331 for (
auto &m : v->all_metadata()) {
337 for (
auto &v : vecs) {
344 .
long_name(
"X-component of the SSA exact solution")
347 .
long_name(
"Y-component of the SSA exact solution")
351 for (
auto p :
m_grid->points()) {
352 const int i = p.i(), j = p.j();
355 &(tmp(i,j).u), &(tmp(i,j).v));
367 .
long_name(
"X-component of the error (exact - computed)")
371 .
long_name(
"Y-component of the error (exact - computed)")
390 error_mag.
write(file);
void define_dimension(const std::string &name, size_t length) const
void write_variable(const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, const double *op) const
void define_variable(const std::string &name, io::Type nctype, const std::vector< std::string > &dims) const
Define a variable.
void write_attribute(const std::string &var_name, const std::string &att_name, io::Type nctype, const std::vector< double > &values) const
Write a multiple-valued double attribute.
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
void append_time(double time_seconds) const
void define_variable(const VariableMetadata &variable) const
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 OutputFile &file) const
void set(double c)
Result: v[j] <- c for all j.
std::vector< VariableMetadata > all_metadata() const
VariableMetadata & metadata(unsigned int N=0)
Returns a reference to the VariableMetadata object containing metadata for the compoment N.
Abstract class for reading, writing, allocating, and accessing a DA-based PETSc Vec (2D and 3D fields...
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
const std::shared_ptr< const Config > m_config
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)
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)
@ 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
bool Bool(const std::string &option, const std::string &description)
static void write(const File &file, const char *name, const char *units, const char *long_name, unsigned int start, double value, io::Type type=io::PISM_DOUBLE)
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)