ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_LatLonMap.cpp File Reference
#include "ERF_LatLonMap.H"
#include "ERF_EarthRelativeWind.H"
#include "ERF_NumericalConstants.H"
#include <algorithm>
#include <AMReX_Arena.H>
#include <AMReX_GpuDevice.H>
#include <AMReX_MFIter.H>
#include <AMReX_ParallelDescriptor.H>
Include dependency graph for ERF_LatLonMap.cpp:

Functions

void pack_latlon (MultiFab &latlon, const MultiFab &lat, const MultiFab &lon)
 
void grid_rotation_from_latlon (const Array4< const Real > &ll, const Box &dom, int i, int j, Real &cos_alpha, Real &sin_alpha)
 
void fill_grid_rotation (MultiFab &cos_alpha, MultiFab &sin_alpha, const MultiFab &lat, const MultiFab &lon, const Geometry &geom)
 
LatLonStatus locate_latlon_on_grid (const Array4< const Real > &ll, const Box &dom, const GpuArray< Real, AMREX_SPACEDIM > &problo, const GpuArray< Real, AMREX_SPACEDIM > &dx, Real req_lat, Real req_lon, LatLonLocation &loc)
 

Function Documentation

◆ fill_grid_rotation()

void fill_grid_rotation ( MultiFab &  cos_alpha,
MultiFab &  sin_alpha,
const MultiFab &  lat,
const MultiFab &  lon,
const Geometry &  geom 
)
84 {
85  const Box& dom = geom.Domain();
86  const int ilo = dom.smallEnd(0);
87  const int ihi = dom.bigEnd(0);
88 
89  // Ghost cells outside the domain are left at zero: the stencil never reads them
90  const IntVect ng(1,1,0);
91  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(lat.nGrowVect().allGE(ng) && lon.nGrowVect().allGE(ng),
92  "fill_grid_rotation: lat/lon need one ghost cell in x and y");
93  MultiFab ll(cos_alpha.boxArray(), cos_alpha.DistributionMap(), 2, ng);
94  ll.setVal(Real(0.0));
95  const Periodicity period(IntVect(geom.isPeriodic(0) ? dom.length(0) : 0,
96  geom.isPeriodic(1) ? dom.length(1) : 0, 0));
97  ll.ParallelCopy(lat, 0, 0, 1, ng, ng, period);
98  ll.ParallelCopy(lon, 0, 1, 1, ng, ng, period);
99 
100  for (MFIter mfi(cos_alpha, TilingIfNotGPU()); mfi.isValid(); ++mfi) {
101  const Box& bx = mfi.tilebox();
102  const Array4<const Real>& ll_arr = ll.const_array(mfi);
103  const Array4<Real>& c_arr = cos_alpha.array(mfi);
104  const Array4<Real>& s_arr = sin_alpha.array(mfi);
105  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
106  {
107  erf_earth_wind::grid_rotation_at(ll_arr, ilo, ihi, i, j, c_arr(i,j,k), s_arr(i,j,k));
108  });
109  }
110 }
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(axis >=0 &&axis< AMREX_SPACEDIM, "prob.axis must be 0, 1 or 2")
ParallelFor(fab_box, [=] AMREX_GPU_DEVICE(int i, int j, int k) { qrcuten_arr(i, j, k)=Real(0);qscuten_arr(i, j, k)=Real(0);qicuten_arr(i, j, k)=Real(0);})
Real sin_alpha
Definition: ERF_Plotfile2DInterpolator.cpp:29
Real cos_alpha
Definition: ERF_Plotfile2DInterpolator.cpp:28
amrex::Real Real
Definition: ERF_ShocInterface.H:19
@ ng
Definition: ERF_Morrison.H:51
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void grid_rotation_at(const amrex::Array4< const amrex::Real > &ll, int ilo, int ihi, int i, int j, amrex::Real &cos_alpha, amrex::Real &sin_alpha) noexcept
Definition: ERF_EarthRelativeWind.H:75

Referenced by ERF::FillPlot2DVars(), and TopographicShading::initialize_geometry().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ grid_rotation_from_latlon()

void grid_rotation_from_latlon ( const Array4< const Real > &  ll,
const Box &  dom,
int  i,
int  j,
Real &  cos_alpha,
Real &  sin_alpha 
)
65 {
66  erf_earth_wind::grid_rotation_at(ll, dom.smallEnd(0), dom.bigEnd(0), i, j,
68 }

Referenced by locate_latlon_on_grid(), and LatLonMap::rotation_at().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ locate_latlon_on_grid()

LatLonStatus locate_latlon_on_grid ( const Array4< const Real > &  ll,
const Box &  dom,
const GpuArray< Real, AMREX_SPACEDIM > &  problo,
const GpuArray< Real, AMREX_SPACEDIM > &  dx,
Real  req_lat,
Real  req_lon,
LatLonLocation &  loc 
)
117 {
118  const int ilo = dom.smallEnd(0), ihi = dom.bigEnd(0);
119  const int jlo = dom.smallEnd(1), jhi = dom.bigEnd(1);
120 
121  const Real cosfac = std::cos(req_lat * PI / Real(180.0));
122  auto dist2 = [&](int i, int j) {
123  const Real dlat = ll(i,j,0,0) - req_lat;
124  const Real dlon = wrap_longitude_difference(ll(i,j,0,1) - req_lon) * cosfac;
125  return dlat*dlat + dlon*dlon;
126  };
127 
128  int bi = ilo, bj = jlo;
129  Real best = dist2(ilo,jlo);
130  for (int j = jlo; j <= jhi; ++j) {
131  for (int i = ilo; i <= ihi; ++i) {
132  const Real d = dist2(i,j);
133  if (d < best) { best = d; bi = i; bj = j; }
134  }
135  }
136 
137  loc.near_lat = ll(bi,bj,0,0);
138  loc.near_lon = ll(bi,bj,0,1);
139 
140  // One linear solve in index space inverts the map: over a cell the
141  // projection is linear to well below a cell width.
142  const GradientStencil s = gradient_stencil(dom, bi, bj);
143 
144  const Real dlat_di = (ll(s.ip,bj,0,0) - ll(s.im,bj,0,0)) * s.inv_di;
145  const Real dlon_di = wrap_longitude_difference(ll(s.ip,bj,0,1) - ll(s.im,bj,0,1)) * s.inv_di;
146  const Real dlat_dj = (ll(bi,s.jp,0,0) - ll(bi,s.jm,0,0)) * s.inv_dj;
147  const Real dlon_dj = wrap_longitude_difference(ll(bi,s.jp,0,1) - ll(bi,s.jm,0,1)) * s.inv_dj;
148 
149  const Real rlat = req_lat - ll(bi,bj,0,0);
150  const Real rlon = wrap_longitude_difference(req_lon - ll(bi,bj,0,1));
151  Real di = Real(0.0), dj = Real(0.0);
152  if (!invert_latlon_offset(rlat, rlon, dlat_di, dlon_di, dlat_dj, dlon_dj, di, dj)) {
154  }
155 
156  // The solve places the point relative to the nearest grid point, so more
157  // than a cell away means the request cannot be trusted: either it is
158  // outside the domain, or the map is too poorly conditioned near it for one
159  // linear solve.
160  if (std::abs(di) > Real(1.0) || std::abs(dj) > Real(1.0)) {
161  return LatLonStatus::TooFar;
162  }
163 
164  loc.x = problo[0] + (Real(bi) + Real(0.5) + di) * dx[0];
165  loc.y = problo[1] + (Real(bj) + Real(0.5) + dj) * dx[1];
166  loc.lat = ll(bi,bj,0,0) + dlat_di*di + dlat_dj*dj;
167  // Resolving a point from a nearest grid point on the other side of the
168  // antimeridian steps the longitude just past +-180; report the longitude
169  // that names the place, not the one that runs off the end of the range
170  loc.lon = wrap_longitude_difference(ll(bi,bj,0,1) + dlon_di*di + dlon_dj*dj);
171 
172  grid_rotation_from_latlon(ll, dom, bi, bj, loc.cos_alpha, loc.sin_alpha);
173 
174  return LatLonStatus::Ok;
175 }
auto problo
Definition: ERF_InitCustomPertVels_ABL.H:36
const Real dx
Definition: ERF_InitCustomPert_ABL.H:44
amrex::Real wrap_longitude_difference(amrex::Real dlon)
Definition: ERF_LatLonMap.H:75
bool invert_latlon_offset(amrex::Real dlat, amrex::Real dlon, amrex::Real dlat_di, amrex::Real dlon_di, amrex::Real dlat_dj, amrex::Real dlon_dj, amrex::Real &di, amrex::Real &dj)
Definition: ERF_LatLonMap.H:52
void grid_rotation_from_latlon(const Array4< const Real > &ll, const Box &dom, int i, int j, Real &cos_alpha, Real &sin_alpha)
Definition: ERF_LatLonMap.cpp:63
constexpr amrex::Real PI
Definition: ERF_NumericalConstants.H:46
real(c_double), private bi
Definition: ERF_module_mp_morr_two_moment.F90:182
real(c_double), private di
Definition: ERF_module_mp_morr_two_moment.F90:203
amrex::Real cos_alpha
Definition: ERF_LatLonMap.H:101
amrex::Real lat
Definition: ERF_LatLonMap.H:93
amrex::Real x
Definition: ERF_LatLonMap.H:88
amrex::Real near_lat
Definition: ERF_LatLonMap.H:97
amrex::Real y
Definition: ERF_LatLonMap.H:89
amrex::Real sin_alpha
Definition: ERF_LatLonMap.H:102
amrex::Real near_lon
Definition: ERF_LatLonMap.H:98
amrex::Real lon
Definition: ERF_LatLonMap.H:94

Referenced by LatLonMap::locate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pack_latlon()

void pack_latlon ( MultiFab &  latlon,
const MultiFab &  lat,
const MultiFab &  lon 
)
48 {
49  for (MFIter mfi(latlon, TilingIfNotGPU()); mfi.isValid(); ++mfi) {
50  const Box& bx = mfi.tilebox();
51  const Array4<Real>& ll = latlon.array(mfi);
52  const Array4<const Real>& lat_arr = lat.const_array(mfi);
53  const Array4<const Real>& lon_arr = lon.const_array(mfi);
54  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
55  {
56  ll(i,j,k,0) = lat_arr(i,j,0);
57  ll(i,j,k,1) = lon_arr(i,j,0);
58  });
59  }
60 }

Referenced by LatLonMap::LatLonMap().

Here is the call graph for this function:
Here is the caller graph for this function: