PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
ssa_test_plug.cc
Go to the documentation of this file.
1 // Copyright (C) 2010--2018, 2021, 2022 Ed Bueler, Constantine Khroulev, and David Maxwell
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 /* This file implements a test case for the ssa: plug flow. The geometry
20  consists of a constant surface slope in the positive x-direction, and the
21  ice is pinned on the y-boundaries. There is no basal shear stress, and hence
22  the the only nonzero terms in the SSA are the "p-laplacian" and the driving
23  stress.
24 */
25 
26 static char help[] =
27  "\nSSA_TEST_PLUG\n"
28  " Testing program for the finite element implementation of the SSA.\n"
29  " Does a time-independent calculation. Does not run IceModel or a derived\n"
30  " class thereof.\n\n";
31 
32 #include <cmath>
33 
34 #include "pism/basalstrength/basal_resistance.hh" // IceBasalResistancePlasticLaw
35 #include "pism/stressbalance/ssa/SSAFD.hh"
36 #include "pism/stressbalance/ssa/SSAFEM.hh"
37 #include "pism/stressbalance/ssa/SSATestCase.hh"
38 #include "pism/util/Context.hh"
39 #include "pism/util/VariableMetadata.hh"
40 #include "pism/util/error_handling.hh"
41 #include "pism/util/io/File.hh"
42 #include "pism/util/petscwrappers/PetscInitializer.hh"
43 #include "pism/util/pism_utilities.hh"
44 #include "pism/util/pism_options.hh"
45 #include "pism/verification/tests/exactTestsIJ.h"
46 
47 namespace pism {
48 namespace stressbalance {
49 
51 public:
52  SSATestCasePlug(std::shared_ptr<Context> ctx, int Mx, int My,
53  double n, SSAFactory ssafactory)
54  : SSATestCase(ctx, Mx, My, 50e3, 50e3, grid::CELL_CORNER, grid::NOT_PERIODIC) {
55  H0 = 2000.; // m
56  L = 50.e3; // 50km half-width
57  dhdx = 0.001; // pure number, slope of surface & bed
58  tauc0 = 0.; // No basal shear stress
59 
60  // Pa s^{1/3}; hardness given on p. 239 of Schoof; why so big?
61  B0 = 3.7e8;
62 
63  this->glen_n = n;
64 
65  // Basal sliding law parameters are irrelevant because tauc=0
66 
67  // Enthalpy converter is irrelevant (but still required) for this test.
69 
70  // Use constant hardness
71  m_config->set_string("stress_balance.ssa.flow_law", "isothermal_glen");
72  m_config->set_number("flow_law.isothermal_Glen.ice_softness", pow(B0, -glen_n));
73 
74  m_ssa = ssafactory(m_grid);
75  }
76 
77 protected:
78  virtual void initializeSSACoefficients();
79 
80  virtual void exactSolution(int i, int j,
81  double x, double y, double *u, double *v);
82 
83 
84  double H0; // Thickness
85  double L; // Half-width
86  double dhdx; // surface slope
87  double tauc0; // zero basal shear stress
88  double B0; // hardness
89  double glen_n;
90 
92 
93 };
94 
96 
97  // The finite difference code uses the following flag to treat the non-periodic grid correctly.
98  m_config->set_flag("stress_balance.ssa.compute_surface_gradient_inward", true);
99  m_config->set_number("stress_balance.ssa.epsilon", 0.0);
100 
101  // Ensure we never use the strength extension.
103 
104  // Set constant coefficients.
106  m_tauc.set(tauc0);
107 
108  // Set boundary conditions (Dirichlet all the way around).
109  m_bc_mask.set(0.0);
110 
112 
113  for (auto p = m_grid->points(); p; p.next()) {
114  const int i = p.i(), j = p.j();
115 
116  double myu, myv;
117  const double myx = m_grid->x(i), myy=m_grid->y(j);
118 
119  m_geometry.bed_elevation(i,j) = -myx*(dhdx);
121 
122  bool edge = ((j == 0) || (j == (int)m_grid->My() - 1) ||
123  (i == 0) || (i == (int)m_grid->Mx() - 1));
124  if (edge) {
125  m_bc_mask(i,j) = 1;
126  exactSolution(i,j,myx,myy,&myu,&myv);
127  m_bc_values(i,j).u = myu;
128  m_bc_values(i,j).v = myv;
129  }
130  }
131 
136 }
137 
138 void SSATestCasePlug::exactSolution(int /*i*/, int /*j*/,
139  double /*x*/, double y,
140  double *u, double *v) {
141  double earth_grav = m_config->get_number("constants.standard_gravity"),
142  ice_rho = m_config->get_number("constants.ice.density");
143  double f = ice_rho * earth_grav * H0* dhdx;
144  double ynd = y/L;
145 
146  *u = 0.5*pow(f,3)*pow(L,4)/pow(B0*H0,3)*(1-pow(ynd,4));
147  *v = 0;
148 }
149 
150 } // end of namespace stressbalance
151 } // end of namespace pism
152 
153 int main(int argc, char *argv[]) {
154 
155  using namespace pism;
156  using namespace pism::stressbalance;
157 
158  MPI_Comm com = MPI_COMM_WORLD; // won't be used except for rank,size
159  petsc::Initializer petsc(argc, argv, help);
160 
161  com = PETSC_COMM_WORLD;
162 
163  /* This explicit scoping forces destructors to be called before PetscFinalize() */
164  try {
165  std::shared_ptr<Context> ctx = context_from_options(com, "ssa_test_plug");
166  Config::Ptr config = ctx->config();
167 
168  std::string usage = "\n"
169  "usage of SSA_TEST_PLUG:\n"
170  " run ssa_test_plug -Mx <number> -My <number> -ssa_method <fd|fem>\n"
171  "\n";
172 
173  bool stop = show_usage_check_req_opts(*ctx->log(), "ssa_test_plug", {}, usage);
174 
175  if (stop) {
176  return 0;
177  }
178 
179  // Parameters that can be overridden by command line options
180 
181  unsigned int Mx = config->get_number("grid.Mx");
182  unsigned int My = config->get_number("grid.My");
183 
184  auto method = config->get_string("stress_balance.ssa.method");
185  auto output_file = config->get_string("output.file");
186  auto glen_n = config->get_number("stress_balance.ssa.Glen_exponent");
187 
188  bool write_output = config->get_string("output.size") != "none";
189 
190  // Determine the kind of solver to use.
191  SSAFactory ssafactory = NULL;
192  if (method == "fem") {
193  ssafactory = SSAFEMFactory;
194  } else if (method == "fd") {
195  ssafactory = SSAFDFactory;
196  } else {
197  /* can't happen */
198  }
199 
200  SSATestCasePlug testcase(ctx, Mx, My, glen_n, ssafactory);
201  testcase.init();
202  testcase.run();
203  testcase.report("plug");
204  if (write_output) {
205  testcase.write(output_file);
206  }
207  }
208  catch (...) {
209  handle_fatal_errors(com);
210  return 1;
211  }
212 
213  return 0;
214 }
std::shared_ptr< Config > Ptr
std::shared_ptr< EnthalpyConverter > Ptr
Converts between specific enthalpy and temperature or liquid content.
array::Scalar2 ice_surface_elevation
Definition: Geometry.hh:57
array::Scalar2 ice_thickness
Definition: Geometry.hh:51
array::Scalar2 bed_elevation
Definition: Geometry.hh:47
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition: Array.hh:65
void set(double c)
Result: v[j] <- c for all j.
Definition: Array.cc:707
void update_ghosts()
Updates ghost points.
Definition: Array.cc:693
void set_min_thickness(double my_min_thickness)
Set minimum thickness to trigger use of extension.
Definition: SSA.cc:50
virtual void initializeSSACoefficients()
Set up the coefficient variables as appropriate for the test case.
virtual void exactSolution(int i, int j, double x, double y, double *u, double *v)
SSATestCasePlug(std::shared_ptr< Context > ctx, int Mx, int My, double n, SSAFactory ssafactory)
virtual void init()
Initialize the test case at the start of a run.
Definition: SSATestCase.cc:94
EnthalpyConverter::Ptr m_enthalpyconverter
Definition: SSATestCase.hh:102
std::shared_ptr< Grid > m_grid
Definition: SSATestCase.hh:94
virtual void report(const std::string &testname)
Report on the generated solution.
Definition: SSATestCase.cc:121
virtual void run()
Solve the SSA.
Definition: SSATestCase.cc:103
virtual void write(const std::string &filename)
Save the computation and data to a file.
Definition: SSATestCase.cc:296
SSAStrengthExtension * strength_extension
Definition: SSA.hh:115
#define n
Definition: exactTestM.c:37
@ NOT_PERIODIC
Definition: Grid.hh:51
@ CELL_CORNER
Definition: Grid.hh:53
SSA * SSAFDFactory(std::shared_ptr< const Grid > g)
Constructs a new SSAFD.
Definition: SSAFD.cc:49
SSA *(* SSAFactory)(std::shared_ptr< const Grid >)
Definition: SSA.hh:77
SSA * SSAFEMFactory(std::shared_ptr< const Grid > g)
Factory function for constructing a new SSAFEM.
Definition: SSAFEM.cc:112
Stress balance models and related diagnostics.
Definition: Isochrones.hh:31
std::shared_ptr< Context > context_from_options(MPI_Comm com, const std::string &prefix, bool print)
Create a default context using options.
Definition: Context.cc:170
void handle_fatal_errors(MPI_Comm com)
bool show_usage_check_req_opts(const Logger &log, const std::string &execname, const std::vector< std::string > &required_options, const std::string &usage)
In a single call a driver program can provide a usage string to the user and check if required option...
Definition: pism_options.cc:51
int main(int argc, char *argv[])
static char help[]