20 #include "pism/util/Poisson.hh"
21 #include "pism/util/error_handling.hh"
22 #include "pism/util/Context.hh"
23 #include "pism/util/petscwrappers/DM.hh"
24 #include "pism/util/petscwrappers/Vec.hh"
25 #include "pism/util/interpolation.hh"
31 m_log(grid->ctx()->log()),
32 m_b(grid,
"poisson_rhs"),
33 m_x(grid,
"poisson_x"),
34 m_mask(grid,
"poisson_mask") {
42 ierr = DMSetMatType(*
m_da, MATAIJ);
51 ierr = KSPSetOptionsPrefix(
m_KSP,
"poisson_");
52 PISM_CHK(ierr,
"KSPSetOptionsPrefix");
55 ierr = KSPSetFromOptions(
m_KSP);
79 ierr = KSPSetInitialGuessNonzero(
m_KSP, PETSC_TRUE);
80 PISM_CHK(ierr,
"KSPSetInitialGuessNonzero");
82 ierr = KSPSetInitialGuessNonzero(
m_KSP, PETSC_FALSE);
83 PISM_CHK(ierr,
"KSPSetInitialGuessNonzero");
98 KSPConvergedReason reason;
99 ierr = KSPGetConvergedReason(
m_KSP, &reason);
100 PISM_CHK(ierr,
"KSPGetConvergedReason");
105 "PISM ERROR: KSP iteration failed while solving the Poisson equation\n"
106 " reason = %d = '%s'\n",
107 reason, KSPConvergedReasons[reason]);
110 KSPConvergedReasons[reason]);
114 PetscInt ksp_iterations = 0;
115 ierr = KSPGetIterationNumber(
m_KSP, &ksp_iterations);
116 PISM_CHK(ierr,
"KSPGetIterationNumber");
118 return ksp_iterations;
160 PetscErrorCode ierr = 0;
165 C_x = 1.0 / (dx * dx),
166 C_y = 1.0 / (dy * dy);
174 ierr = MatZeroEntries(A);
PISM_CHK(ierr,
"MatZeroEntries");
181 MatStencil
row, col[ncol];
184 for (
int m = 0; m < ncol; m++) {
188 for (
auto p =
m_grid->points(); p; p.next()) {
189 const int i = p.i(), j = p.j();
200 const int I[] = {i, i - 1, i, i + 1, i};
203 const int J[] = {j + 1, j, j, j, j - 1};
208 for (
int m = 0; m < ncol; m++) {
213 auto M = mask.
star(i, j);
220 N = M.n == 2 ? 0.0 : 1.0,
221 E = M.e == 2 ? 0.0 : 1.0,
222 W = M.w == 2 ? 0.0 : 1.0,
223 S = M.s == 2 ? 0.0 : 1.0;
227 N = j == My - 1 ? 0.0 : N;
228 E = i == Mx - 1 ? 0.0 : E;
229 W = i == 0 ? 0.0 : W;
230 S = j == 0 ? 0.0 :
S;
234 double L[ncol] = {- N * C_y,
235 - W * C_x, (W + E) * C_x + (N +
S) * C_y, - E * C_x,
238 ierr = MatSetValuesStencil(A, nrow, &
row, ncol, col,
L, INSERT_VALUES);
239 PISM_CHK(ierr,
"MatSetValuesStencil");
243 double D[ncol] = {0.0,
247 ierr = MatSetValuesStencil(A, nrow, &
row, ncol, col,
D, INSERT_VALUES);
248 PISM_CHK(ierr,
"MatSetValuesStencil");
257 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);
PISM_CHK(ierr,
"MatAssemblyBegin");
258 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);
PISM_CHK(ierr,
"MatAssemblyif");
261 ierr = MatSetOption(A, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE);
273 for (
auto p =
m_grid->points(); p; p.next()) {
274 const int i = p.i(), j = p.j();
276 if (mask.
as_int(i, j) == 1) {
void failed()
Indicates a failure of a parallel section.
int solve(const array::Scalar &mask, const array::Scalar &bc, double rhs, bool reuse_matrix=false)
void assemble_matrix(const array::Scalar1 &mask, Mat A)
std::shared_ptr< const Grid > m_grid
const array::Scalar & solution() const
std::shared_ptr< petsc::DM > m_da
void assemble_rhs(double rhs, const array::Scalar &mask, const array::Scalar &bc, array::Scalar &b)
Poisson(std::shared_ptr< const Grid > grid)
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
void copy_from(const Array2D< T > &source)
stencils::Star< T > star(int i, int j) const
void set_interpolation_type(InterpolationType type)
std::shared_ptr< petsc::DM > dm() const
int as_int(int i, int j) const
#define PISM_CHK(errcode, name)
#define PISM_ERROR_LOCATION
static Vector3 row(const double A[3][3], size_t k)
static double S(unsigned n)