PISM, A Parallel Ice Sheet Model 2.3.0-79cae578d committed by Constantine Khrulev on 2026-03-22
Loading...
Searching...
No Matches
Array.hh
Go to the documentation of this file.
1// Copyright (C) 2008--2023, 2025 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#ifndef PISM_ARRAY_H
20#define PISM_ARRAY_H
21
22#include <initializer_list>
23#include <memory> // shared_ptr, dynamic_pointer_cast
24#include <cstdint> // uint64_t
25#include <set>
26
27#include "pism/util/error_handling.hh" // RuntimeError
28
29namespace pism {
30
32
33namespace io {
34enum Type : int;
35class Default;
36}
37
38class Grid;
39class File;
40class OutputFile;
42
43namespace petsc {
44class DM;
45class Vec;
46class Viewer;
47} // end of namespace petsc
48
49namespace units {
50class System;
51}
52
54public:
55 virtual ~PetscAccessible() = default;
56 virtual void begin_access() const = 0;
57 virtual void end_access() const = 0;
58};
59
60namespace array {
61
62//! What "kind" of a vector to create: with or without ghosts.
64
65//! Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
67public:
69 AccessScope(std::initializer_list<const PetscAccessible *> vecs);
72 void add(const PetscAccessible &v);
73 void add(const std::vector<const PetscAccessible*> &vecs);
74private:
75 std::vector<const PetscAccessible*> m_vecs;
76};
77
78/*!
79 * Interpolation helper. Does not check if points needed for interpolation are within the current
80 * processor's sub-domain.
81 */
82template<class F, typename T>
83T interpolate(const F &field, double x, double y) {
84 auto grid = field.grid();
85
86 int i_left = 0, i_right = 0, j_bottom = 0, j_top = 0;
87 grid->compute_point_neighbors(x, y, i_left, i_right, j_bottom, j_top);
88
89 auto w = grid->compute_interp_weights(x, y);
90
91 return (w[0] * field(i_left, j_bottom) +
92 w[1] * field(i_right, j_bottom) +
93 w[2] * field(i_right, j_top) +
94 w[3] * field(i_left, j_top));
95}
96
97//! \brief Abstract class for reading, writing, allocating, and accessing a
98//! DA-based PETSc Vec (2D and 3D fields) from within IceModel.
99/*!
100 @anchor icemodelvec_use
101
102 This class represents 2D and 3D fields in PISM. Its methods common to all
103 the derived classes can be split (roughly) into six kinds:
104
105 - memory allocation (create)
106 - point-wise access (begin_access(), end_access())
107 - arithmetic (range(), norm(), add(), shift(), scale(), set(), ...)
108 - setting or reading metadata (set_attrs(), metadata())
109 - file input/output (read, write, regrid)
110 - tracking whether a field was updated (get_state_counter(), inc_state_counter())
111
112 ## Memory allocation
113
114 \code
115 array::Scalar var(grid, "var_name", WITH_GHOSTS);
116 // var is ready to use
117 \endcode
118
119 ("WITH_GHOSTS" means "can be used in computations using map-plane neighbors
120 of grid points.)
121
122 It is usually a good idea to set variable metadata right after creating it.
123 The method set_attrs() is used throughout PISM to set commonly used
124 attributes.
125
126 ## Point-wise access
127
128 PETSc performs some pointer arithmetic magic to allow convenient indexing of
129 grid point values. Because of this one needs to surround the code using row,
130 column or level indexes with begin_access() and end_access() calls:
131
132 \code
133 double foo;
134 int i = 0, j = 0;
135 array::Scalar var;
136 // assume that var was allocated
137 ierr = var.begin_access(); CHKERRQ(ierr);
138 foo = var(i,j) * 2;
139 ierr = var.end_access(); CHKERRQ(ierr);
140 \endcode
141
142 Please see [this page](@ref computational_grid) for a discussion of the
143 organization of PISM's computational grid and examples of for-loops you will
144 probably put between begin_access() and end_access().
145
146 To ensure that ghost values are up to date add the following call
147 before the code using ghosts:
148
149 \code
150 ierr = var.update_ghosts(); CHKERRQ(ierr);
151 \endcode
152
153 ## Reading and writing variables
154
155 PISM can read variables either from files with data on a grid matching the
156 current grid (read()) or, using bilinear interpolation, from files
157 containing data on a different (but compatible) grid (regrid()).
158
159 To write a field to a "prepared" NetCDF file, use write(). (A file is prepared
160 if it contains all the necessary dimensions, coordinate variables and global
161 metadata.)
162
163 If you need to "prepare" a file, do:
164 \code
165 File file(grid.com, PISM_NETCDF3);
166 io::prepare_for_output(file, *grid.ctx());
167 \endcode
168
169 A note about NetCDF write performance: due to limitations of the NetCDF
170 (classic, version 3) format, it is significantly faster to
171 \code
172 for (all variables)
173 var.define(...);
174
175 for (all variables)
176 var.write(...);
177 \endcode
178
179 as opposed to
180
181 \code
182 for (all variables) {
183 var.define(...);
184 var.write(...);
185 }
186 \endcode
187
188 array::Array::define() is here so that we can use the first approach.
189
190 ## Tracking if a field changed
191
192 It is possible to track if a certain field changed with the help of
193 get_state_counter() and inc_state_counter() methods.
194
195 For example, PISM's SIA code re-computes the smoothed bed only if the bed
196 deformation code updated it:
197
198 \code
199 if (bed->get_state_counter() > bed_state_counter) {
200 ierr = bed_smoother->preprocess_bed(...); CHKERRQ(ierr);
201 bed_state_counter = bed->get_state_counter();
202 }
203 \endcode
204
205 The state counter is **not** updated automatically. For the code snippet above
206 to work, a bed deformation model has to call inc_state_counter() after an
207 update.
208*/
209class Array : public PetscAccessible {
210public:
211 virtual ~Array();
212
213 std::shared_ptr<const Grid> grid() const;
214 unsigned int ndims() const;
215 std::vector<int> shape() const;
216 //! @brief Returns the number of degrees of freedom per grid point.
217 unsigned int ndof() const;
218 unsigned int stencil_width() const;
219
220 const std::vector<double>& levels() const;
221
222 std::vector<double> norm(int n) const;
223
224 void add(double alpha, const Array &x);
225 void shift(double alpha);
226 void scale(double alpha);
227
228 petsc::Vec& vec() const;
229 std::shared_ptr<petsc::DM> dm() const;
230
231 void set_name(const std::string &name);
232 const std::string& get_name() const;
233
234 void read(const std::string &filename, unsigned int time);
235 void read(const File &file, unsigned int time);
236
237 void write(const OutputFile &file) const;
238
239 void regrid(const std::string &filename, io::Default default_value);
240 void regrid(const File &file, io::Default default_value);
241
242 virtual void begin_access() const;
243 virtual void end_access() const;
244 void update_ghosts();
245
246 std::shared_ptr<petsc::Vec> allocate_proc0_copy() const;
247 void put_on_proc0(petsc::Vec &onp0) const;
248 void get_from_proc0(petsc::Vec &onp0);
249
250 void set(double c);
251
252 VariableMetadata& metadata(unsigned int N = 0);
253
254 const VariableMetadata& metadata(unsigned int N = 0) const;
255
256 std::vector<VariableMetadata> all_metadata() const;
257 int state_counter() const;
258 void inc_state_counter();
259
261
262 void view(std::vector<std::shared_ptr<petsc::Viewer> > viewers) const;
263
264protected:
265 Array(std::shared_ptr<const Grid> grid,
266 const std::string &name,
267 Kind ghostedp,
268 size_t dof,
269 size_t stencil_width,
270 const std::vector<double> &zlevels);
271 struct Impl;
273
274 // will be cast to double**, double***, or Vector2** in derived classes
275 // This is not hidden in m_impl to make it possible to inline operator()
276 mutable void *m_array;
277
278 void set_begin_access_use_dof(bool flag);
279
280 void read_impl(const File &file, unsigned int time);
281 virtual void regrid_impl(const File &file, io::Default default_value);
282 void write_impl(const OutputFile &file) const;
283
284 void checkCompatibility(const char *function, const Array &other) const;
285
286 //! @brief Check array indices and warn if they are out of range.
287 void check_array_indices(int i, int j, unsigned int k) const;
288
289 void copy_to_vec(std::shared_ptr<petsc::DM> destination_da, petsc::Vec &destination) const;
290 void get_dof(std::shared_ptr<petsc::DM> da_result, petsc::Vec &result, unsigned int start,
291 unsigned int count=1) const;
292 void set_dof(std::shared_ptr<petsc::DM> da_source, petsc::Vec &source, unsigned int start,
293 unsigned int count=1);
294private:
295 size_t size() const;
296 // disable copy constructor and the assignment operator:
297 Array(const Array &other);
299public:
300 //! Dump an Array to a file. *This is for debugging only.*
301 //! Uses const char[] to make it easier to call it from gdb.
302 void dump(const char filename[]) const;
303
304 uint64_t fletcher64_serial() const;
305 uint64_t fletcher64() const;
306 std::string checksum(bool serial) const;
307 void print_checksum(const char *prefix = "", bool serial=false) const;
308
309protected:
310 void put_on_proc0(petsc::Vec &parallel, petsc::Vec &onp0) const;
311 void get_from_proc0(petsc::Vec &onp0, petsc::Vec &parallel) const;
312};
313
314//! `std::dynamic_pointer_cast` wrapper that checks if the cast succeeded.
315template <class T>
316static typename std::shared_ptr<T> cast(std::shared_ptr<Array> input) {
317 auto result = std::dynamic_pointer_cast<T, Array>(input);
318
319 if (not result) {
320 throw RuntimeError(PISM_ERROR_LOCATION, "dynamic cast failure");
321 }
322
323 return result;
324}
325
326std::set<VariableMetadata> metadata(std::initializer_list<const Array *> vecs);
327
328} // end of namespace array
329
330/**
331 * Convert a PETSc Vec from the units in `from` into units in `to` (in place).
332 *
333 * @param v data to convert
334 * @param system unit system
335 * @param spec1 source unit specification string
336 * @param spec2 destination unit specification string
337 */
338void convert_vec(petsc::Vec &v, std::shared_ptr<units::System> system,
339 const std::string &spec1, const std::string &spec2);
340
341} // end of namespace pism
342
343#endif /* PISM_ARRAY_H */
High-level PISM I/O class.
Definition File.hh:57
Describes the PISM grid and the distribution of data across processors.
Definition Grid.hh:285
virtual ~PetscAccessible()=default
virtual void begin_access() const =0
virtual void end_access() const =0
void add(const PetscAccessible &v)
Definition Array.cc:917
std::vector< const PetscAccessible * > m_vecs
Definition Array.hh:75
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition Array.hh:66
void read(const std::string &filename, unsigned int time)
Definition Array.cc:753
virtual void end_access() const
Checks if an Array is allocated and calls DAVecRestoreArray.
Definition Array.cc:619
virtual void regrid_impl(const File &file, io::Default default_value)
Gets an Array from a file file, interpolating onto the current grid.
Definition Array.cc:381
void write_impl(const OutputFile &file) const
Writes an Array to a NetCDF file.
Definition Array.cc:482
unsigned int ndof() const
Returns the number of degrees of freedom per grid point.
Definition Array.cc:138
void set_interpolation_type(InterpolationType type)
Definition Array.cc:181
void set_name(const std::string &name)
Sets the variable name to name.
Definition Array.cc:345
void dump(const char filename[]) const
Dumps a variable to a file, overwriting this file's contents (for debugging).
Definition Array.cc:554
Array(const Array &other)
void write(const OutputFile &file) const
Definition Array.cc:859
virtual void begin_access() const
Checks if an Array is allocated and calls DAVecGetArray.
Definition Array.cc:598
void shift(double alpha)
Result: v[j] <- v[j] + alpha for all j. Calls VecShift.
Definition Array.cc:219
const std::vector< double > & levels() const
Definition Array.cc:142
size_t size() const
Return the total number of elements in the owned part of an array.
Definition Array.cc:930
void get_from_proc0(petsc::Vec &onp0)
Gets a local Array2 from processor 0.
Definition Array.cc:1079
void copy_to_vec(std::shared_ptr< petsc::DM > destination_da, petsc::Vec &destination) const
Copies v to a global vector 'destination'. Ghost points are discarded.
Definition Array.cc:241
const std::string & get_name() const
Get the name of an Array object.
Definition Array.cc:357
virtual ~Array()
Definition Array.cc:107
petsc::Vec & vec() const
Definition Array.cc:313
uint64_t fletcher64_serial() const
Definition Array.cc:1096
void get_dof(std::shared_ptr< petsc::DM > da_result, petsc::Vec &result, unsigned int start, unsigned int count=1) const
Definition Array.cc:251
void scale(double alpha)
Result: v <- v * alpha. Calls VecScale.
Definition Array.cc:227
Array & operator=(const Array &)
void print_checksum(const char *prefix="", bool serial=false) const
Definition Array.cc:1182
int state_counter() const
Get the object state counter.
Definition Array.cc:130
std::vector< int > shape() const
Definition Array.cc:162
std::string checksum(bool serial) const
Definition Array.cc:1173
void view(std::vector< std::shared_ptr< petsc::Viewer > > viewers) const
View a 2D vector field using existing PETSc viewers.
Definition Array.cc:1189
std::shared_ptr< const Grid > grid() const
Definition Array.cc:134
void set(double c)
Result: v[j] <- c for all j.
Definition Array.cc:659
void set_dof(std::shared_ptr< petsc::DM > da_source, petsc::Vec &source, unsigned int start, unsigned int count=1)
Definition Array.cc:276
void inc_state_counter()
Increment the object state counter.
Definition Array.cc:153
std::shared_ptr< petsc::DM > dm() const
Definition Array.cc:327
unsigned int ndims() const
Returns the number of spatial dimensions.
Definition Array.cc:158
void regrid(const std::string &filename, io::Default default_value)
Definition Array.cc:758
std::vector< VariableMetadata > all_metadata() const
Definition Array.cc:477
std::shared_ptr< petsc::Vec > allocate_proc0_copy() const
Definition Array.cc:947
uint64_t fletcher64() const
Definition Array.cc:1128
void put_on_proc0(petsc::Vec &onp0) const
Puts a local array::Scalar on processor 0.
Definition Array.cc:1036
void set_begin_access_use_dof(bool flag)
Definition Array.cc:177
void add(double alpha, const Array &x)
Result: v <- v + alpha * x. Calls VecAXPY.
Definition Array.cc:209
std::vector< double > norm(int n) const
Computes the norm of all the components of an Array.
Definition Array.cc:699
void update_ghosts()
Updates ghost points.
Definition Array.cc:645
VariableMetadata & metadata(unsigned int N=0)
Returns a reference to the VariableMetadata object containing metadata for the compoment N.
Definition Array.cc:467
unsigned int stencil_width() const
Get the stencil width of the current Array. Returns 0 if ghosts are not available.
Definition Array.cc:305
void checkCompatibility(const char *function, const Array &other) const
Checks if two Arrays have compatible sizes, dimensions and numbers of degrees of freedom.
Definition Array.cc:575
void read_impl(const File &file, unsigned int time)
Reads appropriate NetCDF variable(s) into an Array.
Definition Array.cc:419
void check_array_indices(int i, int j, unsigned int k) const
Check array indices and warn if they are out of range.
Definition Array.cc:666
Abstract class for reading, writing, allocating, and accessing a DA-based PETSc Vec (2D and 3D fields...
Definition Array.hh:209
#define PISM_ERROR_LOCATION
#define n
Definition exactTestM.c:37
std::set< VariableMetadata > metadata(std::initializer_list< const Array * > vecs)
Definition Array.cc:1244
static std::shared_ptr< T > cast(std::shared_ptr< Array > input)
std::dynamic_pointer_cast wrapper that checks if the cast succeeded.
Definition Array.hh:316
Kind
What "kind" of a vector to create: with or without ghosts.
Definition Array.hh:63
@ WITH_GHOSTS
Definition Array.hh:63
@ WITHOUT_GHOSTS
Definition Array.hh:63
T interpolate(const F &field, double x, double y)
Definition Array.hh:83
static double F(double SL, double B, double H, double alpha)
static const double k
Definition exactTestP.cc:42
void convert_vec(petsc::Vec &v, units::System::Ptr system, const std::string &spec1, const std::string &spec2)
Definition Array.cc:1256
int count
Definition test_cube.c:16