REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_LatLonRegrid.H
Go to the documentation of this file.
1#ifndef REMORA_LATLONREGRID_H_
2#define REMORA_LATLONREGRID_H_
3
4#ifdef REMORA_USE_NETCDF
5
6#include <string>
7#include <vector>
8
9#include <AMReX_MultiFab.H>
10#include <AMReX_iMultiFab.H>
11
12/** \brief How a NetCDF forcing field on a lat-lon grid is interpolated onto the model grid
13 *
14 * Set from remora.frc_regrid, remora.frc_lon_varname, remora.frc_lat_varname and
15 * remora.frc_fill_max_rings.
16 */
18{
19 /** Interpolate a field whose shape is not the model grid's (remora.frc_regrid = auto);
20 * when false (off) such a field is an error */
21 bool enabled = true;
22 /** Name of the longitude variable; empty to take it from the field's coordinates attribute */
23 std::string lon_name;
24 /** Name of the latitude variable; empty to take it from the field's coordinates attribute */
25 std::string lat_name;
26 /** How many source cells out to look for a valid value when every corner of a target
27 * point's cell is missing data */
29 /** Rotate interpolated winds and stresses, given east and north, onto the model grid's
30 * xi and eta axes (remora.frc_rotate = auto); off when the file is already rotated */
31 bool rotate = true;
32};
33
34/**
35 * \brief Bilinear interpolation of a 2D field from a rectilinear lat-lon grid onto
36 * REMORA's rho points, the way ROMS's regrid does for forcing.
37 *
38 * The source grid is given by 1D longitude and latitude axes, each strictly monotone in
39 * either direction; the longitude may be in [-180, 180) or [0, 360), may cross the branch
40 * cut, and may cover the globe, in which case it is treated as periodic. The target points
41 * are the model's lon_rho and lat_rho on level 0 over the domain and its one-cell ring, the
42 * cells a file on the model grid fills.
43 *
44 * The interpolation weights are computed once, in define(), and stored per target cell in
45 * the layout the coupling remap uses: up to four weights, and the (i, j, k) source index of
46 * each. apply() reads one record of the field, sets aside source values equal to the
47 * variable's _FillValue or missing_value (or not finite), unpacks the rest with its
48 * scale_factor and add_offset, renormalizes the remaining weights, and gives a target point
49 * whose four corners are all missing the nearest valid source value within
50 * LatLonRegridOptions::fill_max_rings cells.
51 */
53{
54public:
55 /**
56 * \brief Find the source grid of a variable and build the weights. Collective.
57 *
58 * @param[in] file_name file holding the variable
59 * @param[in] field_name the variable, dimensioned (time, lat, lon)
60 * @param[in] field_shape its shape, from the IO rank
61 * @param[in] target_lon rho-point longitude on level 0, degrees east
62 * @param[in] target_lat rho-point latitude on level 0, degrees north
63 * @param[in] like the forcing MultiFab the field fills, for the layout
64 * @param[in] domain level 0 domain
65 * @param[in] options remora.frc_* settings
66 * @param[in] context appended to an error finding the source axes, to say what the
67 * file would need to be read on the model grid instead
68 */
69 void define (const std::string& file_name, const std::string& field_name,
70 const std::vector<long long>& field_shape,
71 const amrex::MultiFab& target_lon, const amrex::MultiFab& target_lat,
72 const amrex::MultiFab& like, const amrex::Box& domain,
73 const LatLonRegridOptions& options, const std::string& context);
74
75 /** \brief Whether a variable's last two dimensions are CF longitude and latitude
76 * coordinates (1D variables of the dimensions' own names, in degrees east and
77 * north), which marks it as on a lat-lon grid even when its shape happens to be
78 * the model grid's. Collective. */
79 static bool has_latlon_axes (const std::string& file_name, const std::string& field_name);
80
81 /** \brief Whether another file's variable lies on the same source grid. Collective. */
82 bool same_source_grid (const std::string& file_name, const std::string& field_name,
83 const std::vector<long long>& field_shape) const;
84
85 /** \brief Read record itime of the variable and interpolate it into dst, over the domain
86 * and its one-cell ring. Collective. */
87 void apply (const std::string& file_name, const std::string& field_name, int itime,
88 amrex::MultiFab& dst) const;
89
90 /** \brief One line describing the source grid, for the log */
91 std::string summary () const;
92
93 /** \brief The cells filled: the valid box of mfi grown by the ring, inside the ring */
94 amrex::Box target_box (const amrex::MFIter& mfi) const;
95
96 // Kernels. Public because CUDA does not allow a device lambda in a private member.
97 void build_weights (const amrex::MultiFab& lon, const amrex::MultiFab& lat);
98 void interpolate (const amrex::FArrayBox& src, amrex::MultiFab& dst) const;
99
100 /** \brief Number of stencil points per target cell */
101 static constexpr int stencil_size = 4;
102
103private:
104 /** Axes as read and the source shape, for comparing files */
105 std::vector<double> lon_file, lat_file;
106 int nlon = 0, nlat = 0;
107
108 /** Axes put in increasing order and, for longitude, made continuous */
109 std::vector<double> lon_inc, lat_inc;
110 bool flip_lon = false, flip_lat = false;
111 bool periodic_lon = false;
112
113 /** Missing-data markers, in the stored (packed) values, and the packing */
114 bool has_fill = false, has_missing = false;
115 double fill_value = 0.0, missing_value = 0.0;
116 double scale_factor = 1.0, add_offset = 0.0;
117
118 std::string lon_name, lat_name;
120 amrex::Box domain;
121
122 /** Weights and the (i, j, k) source index of each, per target cell */
123 amrex::MultiFab weights;
124 amrex::iMultiFab indices;
125};
126
127#endif // REMORA_USE_NETCDF
128#endif // REMORA_LATLONREGRID_H_
Bilinear interpolation of a 2D field from a rectilinear lat-lon grid onto REMORA's rho points,...
void define(const std::string &file_name, const std::string &field_name, const std::vector< long long > &field_shape, const amrex::MultiFab &target_lon, const amrex::MultiFab &target_lat, const amrex::MultiFab &like, const amrex::Box &domain, const LatLonRegridOptions &options, const std::string &context)
Find the source grid of a variable and build the weights. Collective.
void interpolate(const amrex::FArrayBox &src, amrex::MultiFab &dst) const
std::vector< double > lon_inc
void build_weights(const amrex::MultiFab &lon, const amrex::MultiFab &lat)
std::vector< double > lat_inc
amrex::MultiFab weights
std::vector< double > lon_file
void apply(const std::string &file_name, const std::string &field_name, int itime, amrex::MultiFab &dst) const
Read record itime of the variable and interpolate it into dst, over the domain and its one-cell ring....
static constexpr int stencil_size
Number of stencil points per target cell.
amrex::iMultiFab indices
static bool has_latlon_axes(const std::string &file_name, const std::string &field_name)
Whether a variable's last two dimensions are CF longitude and latitude coordinates (1D variables of t...
bool same_source_grid(const std::string &file_name, const std::string &field_name, const std::vector< long long > &field_shape) const
Whether another file's variable lies on the same source grid. Collective.
std::string summary() const
One line describing the source grid, for the log.
amrex::Box target_box(const amrex::MFIter &mfi) const
The cells filled: the valid box of mfi grown by the ring, inside the ring.
std::vector< double > lat_file
How a NetCDF forcing field on a lat-lon grid is interpolated onto the model grid.