PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
Grid_Regional.cc
Go to the documentation of this file.
1 /* Copyright (C) 2015, 2016, 2017, 2018, 2019, 2020, 2021, 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 <vector>
21 #include <cassert>
22 
23 #include <gsl/gsl_interp.h>
24 
25 #include "pism/util/pism_options.hh"
26 #include "pism/util/error_handling.hh"
27 #include "pism/util/Grid.hh"
28 #include "pism/util/io/File.hh"
29 #include "pism/util/Component.hh" // process_input_options
30 #include "pism/util/Context.hh"
31 
32 namespace pism {
33 
34 static void validate_range(const std::string &axis,
35  const std::vector<double> &x,
36  double x_min, double x_max) {
37  if (x_min >= x_max) {
38  throw RuntimeError::formatted(PISM_ERROR_LOCATION, "invalid -%s_range: %s_min >= %s_max (%f >= %f).",
39  axis.c_str(), axis.c_str(), axis.c_str(),
40  x_min, x_max);
41  }
42 
43  if (x_min >= x.back()) {
44  throw RuntimeError::formatted(PISM_ERROR_LOCATION, "invalid -%s_range: %s_min >= max(%s) (%f >= %f).",
45  axis.c_str(), axis.c_str(), axis.c_str(),
46  x_min, x.back());
47  }
48 
49  if (x_max <= x.front()) {
50  throw RuntimeError::formatted(PISM_ERROR_LOCATION, "invalid -%s-range: %s_max <= min(%s) (%f <= %f).",
51  axis.c_str(), axis.c_str(), axis.c_str(),
52  x_max, x.front());
53  }
54 }
55 
56 static void subset_extent(const std::string& axis,
57  const std::vector<double> &x,
58  double x_min, double x_max,
59  double &x0, double &Lx, unsigned int &Mx) {
60 
61  validate_range(axis, x, x_min, x_max);
62 
63  size_t x_start = gsl_interp_bsearch(x.data(), x_min, 0, x.size() - 1);
64  // include one more point if we can
65  if (x_start > 0) {
66  x_start -= 1;
67  }
68 
69  size_t x_end = gsl_interp_bsearch(x.data(), x_max, 0, x.size() - 1);
70  // include one more point if we can
71  x_end = std::min(x.size() - 1, x_end + 1);
72 
73  // NOTE: this assumes the CELL_CORNER grid registration
74  Lx = (x[x_end] - x[x_start]) / 2.0;
75 
76  x0 = (x[x_start] + x[x_end]) / 2.0;
77 
78  assert(x_end + 1 >= x_start);
79  Mx = x_end + 1 - x_start;
80 }
81 
82 //! Create a grid using command-line options and (possibly) an input file.
83 /** Processes options -i, -bootstrap, -Mx, -My, -Mz, -Lx, -Ly, -Lz, -x_range, -y_range.
84  */
85 std::shared_ptr<Grid> regional_grid_from_options(std::shared_ptr<Context> ctx) {
86 
87  auto options = process_input_options(ctx->com(), ctx->config());
88 
89  const options::RealList x_range("-x_range",
90  "range of X coordinates in the selected subset", {});
91  const options::RealList y_range("-y_range",
92  "range of Y coordinates in the selected subset", {});
93 
94  const options::Integer refinement_factor("-refinement_factor",
95  "Grid refinement factor (applies to the horizontal grid)", 1);
96 
97  if (options.type == INIT_BOOTSTRAP and x_range.is_set() and y_range.is_set()) {
98  // bootstrapping; get domain size defaults from an input file, allow overriding all grid
99  // parameters using command-line options
100 
101  if (x_range->size() != 2) {
102  throw RuntimeError(PISM_ERROR_LOCATION, "invalid -x_range argument: need 2 numbers.");
103  }
104 
105  if (y_range->size() != 2) {
106  throw RuntimeError(PISM_ERROR_LOCATION, "invalid -y_range argument: need 2 numbers.");
107  }
108 
109  grid::Parameters input_grid(*ctx->config());
110 
111  std::vector<std::string> names = {"enthalpy", "temp", "land_ice_thickness",
112  "bedrock_altitude", "thk", "topg"};
113  bool grid_info_found = false;
114 
115  File file(ctx->com(), options.filename, io::PISM_NETCDF3, io::PISM_READONLY);
116  for (const auto& name : names) {
117 
118  grid_info_found = file.find_variable(name);
119  if (not grid_info_found) {
120  // Failed to find using a short name. Try using name as a
121  // standard name...
122  grid_info_found = file.find_variable("unlikely_name", name).exists;
123  }
124 
125  if (grid_info_found) {
126  input_grid = grid::Parameters(*ctx, file, name, grid::CELL_CORNER);
127 
128  auto full_grid = grid::InputGridInfo(file, name, ctx->unit_system(), grid::CELL_CORNER);
129 
130  // x direction
131  subset_extent("x", full_grid.x, x_range[0], x_range[1],
132  input_grid.x0, input_grid.Lx, input_grid.Mx);
133  // y direction
134  subset_extent("y", full_grid.y, y_range[0], y_range[1],
135  input_grid.y0, input_grid.Ly, input_grid.My);
136 
137  // Set registration to "CELL_CORNER" so that Grid computes
138  // coordinates correctly.
139  input_grid.registration = grid::CELL_CORNER;
140 
141  break;
142  }
143  }
144 
145  if (not grid_info_found) {
147  "no geometry information found in '%s'",
148  options.filename.c_str());
149  }
150 
151  if (refinement_factor > 1) {
152  input_grid.Mx = (input_grid.Mx - 1) * refinement_factor + 1;
153  input_grid.My = (input_grid.My - 1) * refinement_factor + 1;
154  }
155 
156  // process options controlling vertical grid parameters, overriding values read from a file
157  input_grid.vertical_grid_from_options(ctx->config());
158 
159  // process options controlling ownership ranges
160  input_grid.ownership_ranges_from_options(ctx->size());
161 
162  return std::make_shared<Grid>(ctx, input_grid);
163  }
164 
165  if (x_range.is_set() ^ y_range.is_set()) {
166  throw RuntimeError(PISM_ERROR_LOCATION, "Please set both -x_range and -y_range.");
167  }
168 
169  return Grid::FromOptions(ctx);
170 }
171 
172 
173 } // end of namespace pism
VariableLookupData find_variable(const std::string &short_name, const std::string &std_name) const
Find a variable using its standard name and/or short name.
Definition: File.cc:361
High-level PISM I/O class.
Definition: File.hh:56
static std::shared_ptr< Grid > FromOptions(std::shared_ptr< const Context > ctx)
Create a grid using command-line options and (possibly) an input file.
Definition: Grid.cc:1263
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
Contains parameters of an input file grid.
Definition: Grid.hh:65
void vertical_grid_from_options(std::shared_ptr< const Config > config)
Process -Mz and -Lz; set z;.
Definition: Grid.cc:1209
double y0
Domain center in the Y direction.
Definition: Grid.hh:148
double x0
Domain center in the X direction.
Definition: Grid.hh:146
void ownership_ranges_from_options(unsigned int size)
Re-compute ownership ranges. Uses current values of Mx and My.
Definition: Grid.cc:1142
Registration registration
Grid registration.
Definition: Grid.hh:154
unsigned int Mx
Number of grid points in the X direction.
Definition: Grid.hh:150
double Ly
Domain half-width in the Y direction.
Definition: Grid.hh:144
double Lx
Domain half-width in the X direction.
Definition: Grid.hh:142
unsigned int My
Number of grid points in the Y direction.
Definition: Grid.hh:152
Grid parameters; used to collect defaults before an Grid is allocated.
Definition: Grid.hh:117
#define PISM_ERROR_LOCATION
double min(const array::Scalar &input)
Finds minimum over all the values in an array::Scalar object. Ignores ghosts.
Definition: Scalar.cc:193
@ CELL_CORNER
Definition: Grid.hh:53
@ PISM_NETCDF3
Definition: IO_Flags.hh:57
@ PISM_READONLY
open an existing file for reading only
Definition: IO_Flags.hh:72
std::shared_ptr< Grid > regional_grid_from_options(std::shared_ptr< Context > ctx)
Create a grid using command-line options and (possibly) an input file.
InputOptions process_input_options(MPI_Comm com, Config::ConstPtr config)
Definition: Component.cc:43
@ INIT_BOOTSTRAP
Definition: Component.hh:56
static void validate_range(const std::string &axis, const std::vector< double > &x, double x_min, double x_max)
static void subset_extent(const std::string &axis, const std::vector< double > &x, double x_min, double x_max, double &x0, double &Lx, unsigned int &Mx)