PISM, A Parallel Ice Sheet Model 2.2.1-cd005eec8 committed by Constantine Khrulev on 2025-03-07
Loading...
Searching...
No Matches
grid_hierarchy.cc
Go to the documentation of this file.
1/* Copyright (C) 2020, 2021, 2022, 2023 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
20#include "pism/stressbalance/blatter/util/grid_hierarchy.hh"
21
22namespace pism {
23
24/*!
25 * z coordinates of the nodes
26 *
27 * @param[in] b surface elevation of the bottom of the domain
28 * @param[in] H domain thickness
29 * @param[in] Mz number of grid points in each vertical column
30 * @param[in] k node index in the z direction
31 */
32double grid_z(double b, double H, int Mz, int k) {
33 return b + H * k / (Mz - 1.0);
34}
35
36/* Transpose a DMDALocalInfo structure to map from PETSc's ordering to PISM's order needed
37 to ensure that vertical columns are stored contiguously in RAM.
38
39 (What a pain.)
40
41 Map from PETSc to PISM order:
42
43 | PETSc | PISM |
44 |-------+------|
45 | x | z |
46 | y | x |
47 | z | y |
48
49 Assuming that i, j, k indexes correspond to x, y, and z PETSc's indexing order is
50 [k][j][i]. After this transpose we have to use [j][i][k].
51
52 Note that this indexing order is compatible with the PETSc-standard indexing for 2D
53 Vecs: [j][i].
54
55 All the lines changed to implement this transpose are marked with STORAGE_ORDER: that
56 way you can use grep to find them.
57 */
58DMDALocalInfo grid_transpose(const DMDALocalInfo &input) {
59 DMDALocalInfo result = input;
60
61 result.mx = input.my;
62 result.my = input.mz;
63 result.mz = input.mx;
64
65 result.xs = input.ys;
66 result.ys = input.zs;
67 result.zs = input.xs;
68
69 result.xm = input.ym;
70 result.ym = input.zm;
71 result.zm = input.xm;
72
73 result.gxs = input.gys;
74 result.gys = input.gzs;
75 result.gzs = input.gxs;
76
77 result.gxm = input.gym;
78 result.gym = input.gzm;
79 result.gzm = input.gxm;
80
81 result.bx = input.by;
82 result.by = input.bz;
83 result.bz = input.bx;
84
85 return result;
86}
87
88
89/*!
90 * Set up storage for 3D data inputs (DMDAs and Vecs)
91 */
92PetscErrorCode setup_level(DM dm, int mg_levels) {
93 PetscErrorCode ierr;
94
95 // Create a 3D DMDA and a global Vec, then stash them in dm.
96 {
97 DM da;
98 Vec parameters;
99 int dof = 1;
100#if PETSC_VERSION_LT(3,10,0)
101 ierr = DMDAGetReducedDMDA(dm, dof, &da); CHKERRQ(ierr);
102#else
103 ierr = DMDACreateCompatibleDMDA(dm, dof, &da); CHKERRQ(ierr);
104#endif
105
106 ierr = DMSetUp(da); CHKERRQ(ierr);
107
108 ierr = DMCreateGlobalVector(da, &parameters); CHKERRQ(ierr);
109
110 ierr = PetscObjectCompose((PetscObject)dm, "3D_DM", (PetscObject)da); CHKERRQ(ierr);
111 ierr = PetscObjectCompose((PetscObject)dm, "3D_DM_data", (PetscObject)parameters); CHKERRQ(ierr);
112
113 ierr = DMDestroy(&da); CHKERRQ(ierr);
114
115 ierr = VecDestroy(&parameters); CHKERRQ(ierr);
116 }
117
118 // get coarsening level
119 PetscInt level = 0;
120 ierr = DMGetCoarsenLevel(dm, &level); CHKERRQ(ierr);
121
122 // report
123 {
124 MPI_Comm comm;
125 ierr = PetscObjectGetComm((PetscObject)dm, &comm); CHKERRQ(ierr);
126
127 DMDALocalInfo info;
128 ierr = DMDAGetLocalInfo(dm, &info); CHKERRQ(ierr);
129 info = grid_transpose(info);
130
131 int
132 Mx = info.mx,
133 My = info.my,
134 Mz = info.mz;
135 ierr = PetscPrintf(comm,
136 "Blatter grid level %d: %3d x %3d x %3d (%8d) nodes\n",
137 (mg_levels - 1) - static_cast<int>(level),
138 Mx, My, Mz, Mx * My * Mz); CHKERRQ(ierr);
139 }
140 return 0;
141}
142
143/*! @brief Create the restriction matrix.
144 *
145 * The result of this call is attached to `dm_fine` under `mat_name`.
146 *
147 * @param[in] fine DM corresponding to the fine grid
148 * @param[in] coarse DM corresponding to the coarse grid
149 * @param[in] dm_name name of the DM for 2D or 3D parameters
150 * @param[in] mat_name name to use when attaching the restriction matrix to `fine`
151 */
152PetscErrorCode create_restriction(DM fine, DM coarse, const char *dm_name) {
153 PetscErrorCode ierr;
154 DM da_fine, da_coarse;
155 Mat mat;
156 Vec scale;
157
158 std::string
159 prefix = dm_name,
160 mat_name = prefix + "_restriction",
161 vec_name = prefix + "_scaling";
162
163 /* Get the DM for parameters from the fine grid DM */
164 ierr = PetscObjectQuery((PetscObject)fine, dm_name, (PetscObject *)&da_fine); CHKERRQ(ierr);
165 if (!da_fine) {
166#if PETSC_VERSION_LT(3,17,0)
167 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No %s composed with given DMDA", dm_name); // LCOV_EXCL_LINE
168#else
169 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No %s composed with given DMDA", dm_name); // LCOV_EXCL_LINE
170#endif
171 }
172
173 /* Get the DM for parameters from the coarse grid DM */
174 ierr = PetscObjectQuery((PetscObject)coarse, dm_name, (PetscObject *)&da_coarse); CHKERRQ(ierr);
175 if (!da_coarse) {
176#if PETSC_VERSION_LT(3,17,0)
177 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No %s composed with given DMDA", dm_name); // LCOV_EXCL_LINE
178#else
179 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No %s composed with given DMDA", dm_name); // LCOV_EXCL_LINE
180#endif
181 }
182
183 /* call DMCreateInterpolation */
184 ierr = DMCreateInterpolation(da_coarse, da_fine, &mat, &scale); CHKERRQ(ierr);
185
186 /* attach to the fine grid DM */
187 ierr = PetscObjectCompose((PetscObject)fine, vec_name.c_str(), (PetscObject)scale); CHKERRQ(ierr);
188 ierr = VecDestroy(&scale); CHKERRQ(ierr);
189
190 ierr = PetscObjectCompose((PetscObject)fine, mat_name.c_str(), (PetscObject)mat); CHKERRQ(ierr);
191 ierr = MatDestroy(&mat); CHKERRQ(ierr);
192
193 return 0;
194}
195
196
197/*! @brief Restrict model parameters from the `fine` grid onto the `coarse` grid.
198 *
199 * This function uses the restriction matrix created by coarsening_hook().
200 */
201PetscErrorCode restrict_data(DM fine, DM coarse, const char *dm_name) {
202 PetscErrorCode ierr;
203 Vec X_fine, X_coarse, scaling;
204 DM da_fine, da_coarse;
205 Mat mat;
206
207 std::string
208 prefix = dm_name,
209 mat_name = prefix + "_restriction",
210 scaling_name = prefix + "_scaling",
211 vec_name = prefix + "_data";
212
213 /* get the restriction matrix from the fine grid DM */
214 ierr = PetscObjectQuery((PetscObject)fine, mat_name.c_str(), (PetscObject *)&mat); CHKERRQ(ierr);
215 if (!mat) {
216 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Failed to get the restriction matrix"); // LCOV_EXCL_LINE
217 }
218
219 /* get the scaling vector from the fine grid DM */
220 ierr = PetscObjectQuery((PetscObject)fine, scaling_name.c_str(), (PetscObject *)&scaling); CHKERRQ(ierr);
221 if (!scaling) {
222 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Failed to get the scaling vector"); // LCOV_EXCL_LINE
223 }
224
225 /* get the DMDA from the fine grid DM */
226 ierr = PetscObjectQuery((PetscObject)fine, dm_name, (PetscObject *)&da_fine); CHKERRQ(ierr);
227 if (!da_fine) {
228 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Failed to get the fine grid DM"); // LCOV_EXCL_LINE
229 }
230
231 /* get the storage vector from the fine grid DM */
232 ierr = PetscObjectQuery((PetscObject)fine, vec_name.c_str(), (PetscObject *)&X_fine); CHKERRQ(ierr);
233 if (!X_fine) {
234 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Failed to get the fine grid Vec"); // LCOV_EXCL_LINE
235 }
236
237 /* get the DMDA from the coarse grid DM */
238 ierr = PetscObjectQuery((PetscObject)coarse, dm_name, (PetscObject *)&da_coarse); CHKERRQ(ierr);
239 if (!da_coarse) {
240 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Failed to get the coarse grid DM"); // LCOV_EXCL_LINE
241 }
242
243 /* get the storage vector from the coarse grid DM */
244 ierr = PetscObjectQuery((PetscObject)coarse, vec_name.c_str(), (PetscObject *)&X_coarse); CHKERRQ(ierr);
245 if (!X_coarse) {
246 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Failed to get the coarse grid Vec"); // LCOV_EXCL_LINE
247 }
248
249 ierr = MatRestrict(mat, X_fine, X_coarse); CHKERRQ(ierr);
250
251 ierr = VecPointwiseMult(X_coarse, X_coarse, scaling); CHKERRQ(ierr);
252
253 return 0;
254}
255
256} // end of namespace pism
double grid_z(double b, double H, int Mz, int k)
PetscErrorCode setup_level(DM dm, int mg_levels)
DMDALocalInfo grid_transpose(const DMDALocalInfo &input)
static const double k
Definition exactTestP.cc:42
PetscErrorCode restrict_data(DM fine, DM coarse, const char *dm_name)
Restrict model parameters from the fine grid onto the coarse grid.
PetscErrorCode create_restriction(DM fine, DM coarse, const char *dm_name)
Create the restriction matrix.