PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
ColumnSystem.hh
Go to the documentation of this file.
1 // Copyright (C) 2009-2011, 2013, 2014, 2015, 2016, 2019, 2021 PISM Authors
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 #ifndef PISM_COLUMNSYSTEM_HH
20 #define PISM_COLUMNSYSTEM_HH
21 
22 #include <string>
23 #include <ostream>
24 #include <vector>
25 
26 namespace pism {
27 
28 namespace array {
29 class Array3D;
30 } // end of namespace array
31 
32 //! Virtual base class. Abstracts a tridiagonal system to solve in a column of ice and/or bedrock.
33 /*!
34  Because both the age evolution and conservation of energy equations require us to set up
35  and solve a tridiagonal system of equations, this is structure is worth abstracting.
36 
37  This base class just holds the tridiagonal system and the ability to
38  solve it, but does not insert entries into the relevant matrix locations.
39  Derived classes will actually set up instances of the system.
40 
41  The sequence requires setting the column-independent (public) data members,
42  calling the initAllColumns() routine, and then setting up and solving
43  the system in each column.
44 
45  The tridiagonal algorithm here comes from Numerical Recipes in C
46  Section 2.4, page 50. It solves the system:
47 
48 @verbatim
49  [b_1 c_1 0 ... ] [ u_1 ] [ r_1 ]
50  [a_2 b_2 c_2 ... ] [ u_2 ] [ r_2 ]
51  [ ... ].[ ... ] = [ ... ]
52  [ ... a_{N-1} b_{N-1} c_{N-1}] [u_{N-1}] [ r_{N-1} ]
53  [ ... 0 a_N b_N ] [ u_N ] [ r_N ]
54 @endverbatim
55 
56  HOWEVER... the version in this code is different from Numerical
57  Recipes in two ways:
58 
59  - Indexing is zero-based
60  - Variables have been renamed.
61 
62 @verbatim
63  NR PISM
64  ==================
65  a L "Lower Diagonal" (L doesn't use index 0)
66  b D "Diagonal"
67  c U "Upper Diagonal"
68  u x
69  r rhs
70  bet b
71  j k
72  n n
73  gam work
74 @endverbatim
75 
76  Therefore... this version of the code solves the following problem:
77 
78 @verbatim
79  [D_0 U_0 0 ... ] [ x_0 ] [ r_0 ]
80  [L_1 D_1 U_1 ... ] [ x_1 ] [ r_1 ]
81  [ ... ].[ ... ] = [ ... ]
82  [ ... L_{N-2} D_{N-2} U_{N-2}] [x_{N-2}] [ r_{N-2} ]
83  [ ... 0 L_{N-1} D_{N-1}] [x_{N-1}] [ r_{N-1} ]
84 @endverbatim
85 */
87 public:
88  TridiagonalSystem(unsigned int max_size, const std::string &prefix);
89 
90  double norm1(unsigned int system_size) const;
91  double ddratio(unsigned int system_size) const;
92  void reset();
93 
94  // uses an output argument to allow re-using storage and avoid
95  // copying
96  void solve(unsigned int system_size, std::vector<double> &result);
97  void solve(unsigned int system_size, double *result);
98 
99  void save_system_with_solution(const std::string &filename,
100  unsigned int system_size,
101  const std::vector<double> &solution);
102 
103  //! Save the system to a stream using the ASCII MATLAB (Octave)
104  //! format. Virtual to allow saving more info in derived classes.
105  void save_system(std::ostream &output,
106  unsigned int system_size) const;
107 
108  void save_matrix(std::ostream &output,
109  unsigned int system_size,
110  const std::string &variable) const;
111 
112  static void save_vector(std::ostream &output,
113  const std::vector<double> &v,
114  unsigned int system_size,
115  const std::string &variable);
116 
117  std::string prefix() const;
118 
119  double& L(size_t i) {
120  return m_L[i];
121  }
122  double& D(size_t i) {
123  return m_D[i];
124  }
125  double& U(size_t i) {
126  return m_U[i];
127  }
128  double& RHS(size_t i) {
129  return m_rhs[i];
130  }
131 private:
132  unsigned int m_max_system_size; // maximum system size
133  std::vector<double> m_L, m_D, m_U, m_rhs, m_work; // vectors for tridiagonal system
134 
135  std::string m_prefix;
136 };
137 
138 class ColumnInterpolation;
139 
140 //! Base class for tridiagonal systems in the ice.
141 /*! Adds data members used in time-dependent systems with advection
142  (dx, dy, dz, dt, velocity components).
143  */
145 public:
146  columnSystemCtx(const std::vector<double>& storage_grid, const std::string &prefix,
147  double dx, double dy, double dt,
148  const array::Array3D &u3, const array::Array3D &v3, const array::Array3D &w3);
150 
151  void save_to_file(const std::vector<double> &x);
152  void save_to_file(const std::string &filename, const std::vector<double> &x);
153 
154  unsigned int ks() const;
155  double dz() const;
156  const std::vector<double>& z() const;
157  void fine_to_coarse(const std::vector<double> &fine, int i, int j,
158  array::Array3D& coarse) const;
159 protected:
161 
163 
164  //! current system size; corresponds to the highest vertical level within the ice
165  unsigned int m_ks;
166  //! current column indexes
167  int m_i, m_j;
168 
169  double m_dx, m_dy, m_dz, m_dt;
170 
171  //! u-component of the ice velocity
172  std::vector<double> m_u;
173  //! v-component of the ice velocity
174  std::vector<double> m_v;
175  //! w-component of the ice velocity
176  std::vector<double> m_w;
177  //! levels of the fine vertical grid
178  std::vector<double> m_z;
179 
180  //! pointers to 3D velocity components
182 
183  void init_column(int i, int j, double ice_thickness);
184 
185  void reportColumnZeroPivotErrorMFile(unsigned int M);
186 
187  void init_fine_grid(const std::vector<double>& storage_grid);
188 
189  void coarse_to_fine(const array::Array3D &coarse, int i, int j, double* fine) const;
190 };
191 
192 } // end of namespace pism
193 
194 #endif /* PISM_COLUMNSYSTEM_HH */
void save_matrix(std::ostream &output, unsigned int system_size, const std::string &variable) const
View the tridiagonal matrix.
void save_system(std::ostream &output, unsigned int system_size) const
View the tridiagonal system A x = b to an output stream, both A as a full matrix and b as a vector.
std::vector< double > m_work
std::string prefix() const
double & RHS(size_t i)
unsigned int m_max_system_size
TridiagonalSystem(unsigned int max_size, const std::string &prefix)
Allocate a tridiagonal system of maximum size max_system_size.
Definition: ColumnSystem.cc:50
void solve(unsigned int system_size, std::vector< double > &result)
double ddratio(unsigned int system_size) const
Compute diagonal-dominance ratio. If this is less than one then the matrix is strictly diagonally-dom...
double norm1(unsigned int system_size) const
Compute 1-norm, which is max sum of absolute values of columns.
Definition: ColumnSystem.cc:75
double & D(size_t i)
double & U(size_t i)
double & L(size_t i)
static void save_vector(std::ostream &output, const std::vector< double > &v, unsigned int system_size, const std::string &variable)
Utility for simple ascii view of a vector (one-dimensional column) quantity.
std::vector< double > m_D
std::vector< double > m_U
void reset()
Zero all entries.
Definition: ColumnSystem.cc:64
std::vector< double > m_L
void save_system_with_solution(const std::string &filename, unsigned int system_size, const std::vector< double > &solution)
std::vector< double > m_rhs
Virtual base class. Abstracts a tridiagonal system to solve in a column of ice and/or bedrock.
Definition: ColumnSystem.hh:86
A virtual class collecting methods common to ice and bedrock 3D fields.
Definition: Array3D.hh:33
const array::Array3D & m_w3
void coarse_to_fine(const array::Array3D &coarse, int i, int j, double *fine) const
const std::vector< double > & z() const
columnSystemCtx(const std::vector< double > &storage_grid, const std::string &prefix, double dx, double dy, double dt, const array::Array3D &u3, const array::Array3D &v3, const array::Array3D &w3)
A column system is a kind of a tridiagonal system.
void reportColumnZeroPivotErrorMFile(unsigned int M)
Write system matrix and right-hand-side into an Python script. The file name contains ZERO_PIVOT_ERRO...
void save_to_file(const std::vector< double > &x)
Write system matrix, right-hand-side, and (provided) solution into Python script. Constructs file nam...
std::vector< double > m_z
levels of the fine vertical grid
unsigned int m_ks
current system size; corresponds to the highest vertical level within the ice
std::vector< double > m_u
u-component of the ice velocity
const array::Array3D & m_u3
pointers to 3D velocity components
void init_column(int i, int j, double ice_thickness)
const array::Array3D & m_v3
unsigned int ks() const
void init_fine_grid(const std::vector< double > &storage_grid)
int m_i
current column indexes
TridiagonalSystem * m_solver
ColumnInterpolation * m_interp
std::vector< double > m_w
w-component of the ice velocity
void fine_to_coarse(const std::vector< double > &fine, int i, int j, array::Array3D &coarse) const
std::vector< double > m_v
v-component of the ice velocity
Base class for tridiagonal systems in the ice.