Loading [MathJax]/extensions/tex2jax.js
PISM, A Parallel Ice Sheet Model 2.2.2-d6b3a29ca committed by Constantine Khrulev on 2025-03-28
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
LocalInterpCtx.cc
Go to the documentation of this file.
1// Copyright (C) 2007-2020, 2023, 2024 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*/
81LocalInterpCtx::LocalInterpCtx(const grid::InputGridInfo &input_grid, const Grid &internal_grid,
82 const std::vector<double> &z_internal, InterpolationType type)
83 : LocalInterpCtx(input_grid, internal_grid, type) {
84
85 // Z
86 start[Z_AXIS] = 0; // always start at the base
87 count[Z_AXIS] = std::max((int)input_grid.z.size(), 1); // read at least one level
88
89 if (type == LINEAR or type == NEAREST) {
90 z.reset(new Interpolation1D(type, input_grid.z, z_internal));
91 } else {
92 throw RuntimeError(PISM_ERROR_LOCATION, "invalid interpolation type in LocalInterpCtx");
93 }
94}
95
96/*!
97 * The two-dimensional version of the interpolation context.
98 */
99LocalInterpCtx::LocalInterpCtx(const grid::InputGridInfo &input_grid, const Grid &internal_grid,
100 InterpolationType type) {
101
102 // limits of the processor's part of the target computational domain
103 const double x_min_proc = internal_grid.x(internal_grid.xs()),
104 x_max_proc = internal_grid.x(internal_grid.xs() + internal_grid.xm() - 1),
105 y_min_proc = internal_grid.y(internal_grid.ys()),
106 y_max_proc = internal_grid.y(internal_grid.ys() + internal_grid.ym() - 1);
107
108 // T
109 start[T_AXIS] = (int)input_grid.t_len - 1; // use the latest time.
110 count[T_AXIS] = 1; // read only one record
111
112 // X
113 subset_start_and_count(input_grid.x, x_min_proc, x_max_proc, start[X_AXIS], count[X_AXIS]);
114
115 // Y
116 subset_start_and_count(input_grid.y, y_min_proc, y_max_proc, start[Y_AXIS], count[Y_AXIS]);
117
118 // Z
119 start[Z_AXIS] = 0;
120 count[Z_AXIS] = 1;
121
122 if (type == LINEAR or type == NEAREST) {
123 x = std::make_shared<Interpolation1D>(type, &input_grid.x[start[X_AXIS]], count[X_AXIS],
124 &internal_grid.x()[internal_grid.xs()], internal_grid.xm());
125
126 y = std::make_shared<Interpolation1D>(type, &input_grid.y[start[Y_AXIS]], count[Y_AXIS],
127 &internal_grid.y()[internal_grid.ys()], internal_grid.ym());
128
129 std::vector<double> zz = {0.0};
130 z = std::make_shared<Interpolation1D>(type, zz, zz);
131 } else {
132 throw RuntimeError(PISM_ERROR_LOCATION, "invalid interpolation type in LocalInterpCtx");
133 }
134}
135
136
138 return count[X_AXIS] * count[Y_AXIS] * std::max(count[Z_AXIS], 1);
139}
140
141
142} // end of namespace pism
const std::vector< double > & x() const
X-coordinates.
Definition Grid.cc:623
const std::vector< double > & y() const
Y-coordinates.
Definition Grid.cc:633
int ys() const
Global starting index of this processor's subset.
Definition Grid.cc:593
int xs() const
Global starting index of this processor's subset.
Definition Grid.cc:588
int xm() const
Width of this processor's sub-domain.
Definition Grid.cc:598
int ym() const
Width of this processor's sub-domain.
Definition Grid.cc:603
Describes the PISM grid and the distribution of data across processors.
Definition Grid.hh:290
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 &internal_grid, InterpolationType type)
std::shared_ptr< Interpolation1D > y
std::vector< double > y
y coordinates
Definition Grid.hh:93
unsigned int t_len
Definition Grid.hh:76
std::vector< double > z
z coordinates
Definition Grid.hh:95
std::vector< double > x
x coordinates
Definition Grid.hh:91
Contains parameters of an input file grid.
Definition Grid.hh:68
#define PISM_ERROR_LOCATION
@ T_AXIS
Definition IO_Flags.hh:33
@ X_AXIS
Definition IO_Flags.hh:33
@ Z_AXIS
Definition IO_Flags.hh:33
@ Y_AXIS
Definition IO_Flags.hh:33
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.