PISM, A Parallel Ice Sheet Model 2.3.0-79cae578d committed by Constantine Khrulev on 2026-03-22
Loading...
Searching...
No Matches
LocalInterpCtx.cc
Go to the documentation of this file.
1// Copyright (C) 2007-2020, 2023, 2024, 2025 Jed Brown, Ed Bueler and Constantine Khroulev
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#include <cstddef> // size_t
20#include <cstring>
21#include <cstdlib>
22#include <algorithm> // std::min
23#include <gsl/gsl_interp.h>
24#include <memory>
25#include <vector>
26
27#include "IO_Flags.hh"
28#include "pism/util/io/LocalInterpCtx.hh"
29#include "pism/util/Grid.hh"
30
31#include "pism/util/error_handling.hh"
32#include "pism/util/Interpolation1D.hh"
33
34namespace pism {
35
36//! Compute start and count for getting a subset of x.
37/*! Given a grid `x` we find `x_start` and `x_count` so that `[subset_x_min, subset_x_max]` is in
38 * `[x[x_start], x[x_start + x_count]]`.
39 *
40 * `x_start` and `x_count` define the smallest subset of `x` with this property.
41 *
42 * Note that `x_start + x_count <= x.size()` as long as `x` is strictly increasing.
43 *
44 * @param[in] x input grid (defined interpolation domain)
45 * @param[in] subset_x_min minimum `x` of a subset (interpolation range)
46 * @param[in] subset_x_max maxumum `x` of a subset (interpolation range)
47 * @param[out] x_start starting index
48 * @param[out] x_count number of elements required
49 */
50static void subset_start_and_count(const std::vector<double> &x, double subset_x_min,
51 double subset_x_max, int &x_start, int &x_count) {
52 auto x_size = (int)x.size();
53
54 x_start = (int)gsl_interp_bsearch(x.data(), subset_x_min, 0, x_size - 1);
55
56 auto x_end = (int)gsl_interp_bsearch(x.data(), subset_x_max, 0, x_size - 1) + 1;
57
58 x_end = std::min(x_size - 1, x_end);
59
60 x_count = x_end - x_start + 1;
61}
62
63//! Construct a local interpolation context.
64/*!
65 The essential quantities to compute are where each processor should start within the NetCDF file grid
66 (`start[]`) and how many grid points, from the starting place, the processor has. The resulting
67 portion of the grid is stored in array `a` (a field of the `LocalInterpCtx`).
68
69 We make conservative choices about `start[]` and `count[]`. In particular, the portions owned by
70 processors \e must overlap at one point in the NetCDF file grid, but they \e may overlap more than that
71 (as computed here).
72
73 Note this constructor doesn't extract new information from the NetCDF file or
74 do communication. The information from the NetCDF file must already be
75 extracted, validly stored in a grid_info structure `input`.
76
77 The `Grid` is used to determine what ranges of the target arrays (i.e. \c
78 Vecs into which NetCDF information will be interpolated) are owned by each
79 processor.
80*/
82 const grid::DistributedGridInfo &internal_grid,
83 const std::vector<double> &z_internal, InterpolationType type)
84 : LocalInterpCtx(input_grid, internal_grid, type) {
85
86 // Z
87 start[Z_AXIS] = 0; // always start at the base
88 count[Z_AXIS] = std::max((int)input_grid.z.size(), 1); // read at least one level
89
90 if (type == LINEAR or type == NEAREST) {
91 z.reset(new Interpolation1D(type, input_grid.z, z_internal));
92 } else {
93 throw RuntimeError(PISM_ERROR_LOCATION, "invalid interpolation type in LocalInterpCtx");
94 }
95}
96
97/*!
98 * The two-dimensional version of the interpolation context.
99 */
101 InterpolationType type) {
102
103 const auto &xx = internal_grid.x;
104 const auto &yy = internal_grid.y;
105
106 // limits of the processor's part of the target computational domain
107 const double x_min_proc = xx[internal_grid.xs],
108 x_max_proc = xx[internal_grid.xs + internal_grid.xm - 1],
109 y_min_proc = yy[internal_grid.ys],
110 y_max_proc = yy[internal_grid.ys + internal_grid.ym - 1];
111
112 // T
113 start[T_AXIS] = (int)input_grid.t_len - 1; // use the latest time.
114 count[T_AXIS] = 1; // read only one record
115
116 // X
117 subset_start_and_count(input_grid.x, x_min_proc, x_max_proc, start[X_AXIS], count[X_AXIS]);
118
119 // Y
120 subset_start_and_count(input_grid.y, y_min_proc, y_max_proc, start[Y_AXIS], count[Y_AXIS]);
121
122 // Z
123 start[Z_AXIS] = 0;
124 count[Z_AXIS] = 1;
125
126 if (type == LINEAR or type == NEAREST) {
127 x = std::make_shared<Interpolation1D>(type, &input_grid.x[start[X_AXIS]], count[X_AXIS],
128 &xx[internal_grid.xs], internal_grid.xm);
129
130 y = std::make_shared<Interpolation1D>(type, &input_grid.y[start[Y_AXIS]], count[Y_AXIS],
131 &yy[internal_grid.ys], internal_grid.ym);
132
133 std::vector<double> zz = {0.0};
134 z = std::make_shared<Interpolation1D>(type, zz, zz);
135 } else {
136 throw RuntimeError(PISM_ERROR_LOCATION, "invalid interpolation type in LocalInterpCtx");
137 }
138}
139
140
142 return count[X_AXIS] * count[Y_AXIS] * std::max(count[Z_AXIS], 1);
143}
144
145
146} // end of namespace pism
std::array< int, 4 > count
std::shared_ptr< Interpolation1D > z
std::array< int, 4 > start
std::shared_ptr< Interpolation1D > x
LocalInterpCtx(const grid::InputGridInfo &input_grid, const grid::DistributedGridInfo &internal_grid, InterpolationType type)
std::shared_ptr< Interpolation1D > y
unsigned int ys
Starting index of the patch owned by the current MPI rank (X direction)
Definition GridInfo.hh:76
unsigned int xs
Starting index (in the X direction) of the patch owned by the current MPI rank.
Definition GridInfo.hh:71
std::vector< double > y
y coordinates
Definition GridInfo.hh:53
std::vector< double > x
x coordinates
Definition GridInfo.hh:51
unsigned int t_len
Definition Grid.hh:68
std::vector< double > z
z coordinates: input grids may be 3-dimensional
Definition Grid.hh:82
#define PISM_ERROR_LOCATION
@ T_AXIS
Definition IO_Flags.hh:34
@ X_AXIS
Definition IO_Flags.hh:34
@ Z_AXIS
Definition IO_Flags.hh:34
@ Y_AXIS
Definition IO_Flags.hh:34
static void subset_start_and_count(const std::vector< double > &x, double subset_x_min, double subset_x_max, int &x_start, int &x_count)
Compute start and count for getting a subset of x.