25 #include "pism/util/pism_utilities.hh"
26 #include "pism/util/array/Array3D.hh"
27 #include "pism/util/ColumnSystem.hh"
29 #include "pism/util/error_handling.hh"
30 #include "pism/util/ColumnInterpolation.hh"
51 const std::string &prefix)
52 : m_max_system_size(max_size), m_prefix(prefix) {
53 const unsigned int huge = 1e6;
54 assert(max_size >= 1 && max_size < huge);
77 if (system_size == 1) {
80 double z = fabs(
m_D[0]) + fabs(
m_L[1]);
81 for (
unsigned int k = 1;
k < system_size;
k++) {
84 z =
std::max(z, fabs(
m_U[system_size-2]) + fabs(
m_D[system_size-1]));
105 const double eps = 1.0e-12;
106 const double scale =
norm1(system_size);
108 if ((fabs(
m_D[0]) / scale) < eps) {
111 double z = fabs(
m_U[0]) / fabs(
m_D[0]);
113 for (
unsigned int k = 1;
k < system_size - 1;
k++) {
114 if ((fabs(
m_D[
k]) / scale) < eps) {
117 const double s = fabs(
m_L[
k]) + fabs(
m_U[
k]);
121 if ((fabs(
m_D[system_size - 1]) / scale) < eps) {
124 z =
std::max(z, fabs(
m_L[system_size - 1]) / fabs(
m_D[system_size - 1]));
140 const std::vector<double> &v,
141 unsigned int system_size,
142 const std::string &variable) {
143 assert(system_size >= 1);
145 output << variable <<
" = numpy.array([";
146 for (
unsigned int k = 0;
k < system_size;
k++) {
147 output << v[
k] <<
", ";
149 output <<
"])" << std::endl;
155 unsigned int system_size,
156 const std::string &variable)
const {
158 if (system_size < 2) {
159 std::cout <<
"\n\n<nmax >= 2 required to view tri-diagonal matrix " << variable
160 <<
" ... skipping view" << std::endl;
169 output << variable <<
"_diagonals = ["
170 << variable <<
"_L[1:], "
171 << variable <<
"_D, "
172 << variable <<
"_U[:-1]]" << std::endl;
173 output <<
"import scipy.sparse" << std::endl;
174 output << variable <<
" = scipy.sparse.diags(" << variable <<
"_diagonals, [-1, 0, 1])" << std::endl;
180 unsigned int system_size)
const {
188 unsigned int system_size,
189 const std::vector<double> &solution) {
190 std::ofstream output(filename.c_str());
191 output <<
"import numpy" << std::endl;
192 output <<
"# system has 1-norm = " <<
norm1(system_size)
193 <<
" and diagonal-dominance ratio = " <<
ddratio(system_size) << std::endl;
203 solve(system_size, result.data());
216 assert(system_size >= 1);
225 result[0] =
m_rhs[0] / b;
226 for (
unsigned int k = 1;
k < system_size; ++
k) {
238 for (
int k =
static_cast<int>(system_size) - 2;
k >= 0; --
k) {
239 result[
k] -=
m_work[
k + 1] * result[
k + 1];
249 const std::string &prefix,
250 double dx,
double dy,
double dt,
254 : m_dx(dx), m_dy(dy), m_dt(dt), m_u3(u3), m_v3(v3), m_w3(w3) {
293 double* output)
const {
300 unsigned int Mz = storage_grid.size();
301 double Lz = storage_grid.back();
303 for (
unsigned int k = 1;
k < Mz; ++
k) {
307 size_t Mz_fine =
static_cast<size_t>(ceil(Lz /
m_dz) + 1);
308 m_dz = Lz /
static_cast<double>(Mz_fine - 1);
312 for (
unsigned int k = 0;
k < Mz_fine; ++
k) {
319 double ice_thickness) {
322 m_ks =
static_cast<unsigned int>(floor(ice_thickness /
m_dz));
336 "possibly because of invalid ice thickness (%f meters) or dz (%f meters).",
345 auto filename =
pism::printf(
"%s_i%d_j%d_ZERO_PIVOT_ERROR.py",
348 std::ofstream output(filename);
350 <<
" and diagonal-dominance ratio = " <<
m_solver->
ddratio(M) << std::endl;
362 std::cout <<
"saving "
364 <<
" = (" <<
m_i <<
"," <<
m_j <<
") to " << filename <<
" ...\n" << std::endl;
370 const std::vector<double> &x) {
void coarse_to_fine(const double *input, unsigned int ks, double *result) const
void fine_to_coarse(const double *input, double *result) const
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
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
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.
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.
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.
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.
double * get_column(int i, int j)
A virtual class collecting methods common to ice and bedrock 3D fields.
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
void init_column(int i, int j, double ice_thickness)
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
#define PISM_ERROR_LOCATION
double max(const array::Scalar &input)
Finds maximum over all the values in an array::Scalar object. Ignores ghosts.
double min(const array::Scalar &input)
Finds minimum over all the values in an array::Scalar object. Ignores ghosts.
std::string printf(const char *format,...)