REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_apply_clim_nudg.cpp
Go to the documentation of this file.
1#include <REMORA.H>
2
3using namespace amrex;
4
5/**
6 * @param[in ] bx box to apply climatology on
7 * @param[in ] ioff offset in x-direction
8 * @param[in ] joff offset in y-direction
9 * @param[inout] var variable to update
10 * @param[in ] var_old variable to compare against for nudging
11 * @param[in ] var_clim climatology value to nudge towards
12 * @param[in ] clim_coeff nudging time scale (1/s)
13 * @param[in ] Hz vertical cell height
14 * @param[in ] pm 1/dx
15 * @param[in ] pn 1/dy
16 * @param[in ] dt_lev time step
17 */
18void
20 int ioff, int joff,
21 const Array4<Real >& var,
28 const Real dt_lev)
29{
30 BL_PROFILE("REMORA::apply_clim_nudg()");
31 ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
32 {
33 Real cff = Real(0.5) * (clim_coeff(i-ioff,j-joff,k) + clim_coeff(i,j,k));
34 if (ioff==1 || joff==1) {
35 Real om = two / (pm(i-ioff,j-joff,0)+pm(i,j,0));
36 Real on = two / (pn(i-ioff,j-joff,0)+pn(i,j,0));
37 cff *= Real(0.5) * (Hz(i-ioff,j-joff,k) + Hz(i,j,k)) * om * on;
38 } else {
39 cff *= dt_lev;
40 }
41 var(i,j,k) += cff * (var_clim(i,j,k) - var_old(i,j,k));
42 });
43}
44
45/**
46 * @param[in ] nodal_bx box from MFIter::nodaltilebox(dir)
47 * @param[in ] dir direction the box is nodal in (0 for u, 1 for v)
48 * @param[in ] domain cell-centered problem domain at this level
49 * @param[in ] is_periodic whether dir is periodic
50 */
51Box
53 const int dir,
54 const Box& domain,
55 const bool is_periodic)
56{
57 Box bx(nodal_bx);
58
59 // ROMS sets IstrU=Istr (JstrV=Jstr) under EW_PERIODIC (NS_PERIODIC), so a periodic
60 // direction keeps every face.
61 if (is_periodic) {
62 return bx;
63 }
64
65 // MFIter::nodaltilebox calls surroundingNodes(dir) and only strips the high node when the
66 // tile stops short of the valid high end, so a box on the domain high edge legitimately
67 // ends at domain.bigEnd(dir)+1 -- the same convention as bx_xhi_face.setSmall(0,dom_hi.x+1)
68 // in the boundary conditions. Comparing against the cell-centered domain.bigEnd(dir) would
69 // never match there, and would wrongly match a box whose last cell is domain hi minus one.
70 const int nodal_lo = domain.smallEnd(dir);
71 const int nodal_hi = domain.bigEnd(dir) + 1;
72
73 // Independent tests, not else-if: a box spanning the domain in dir sheds both edge faces.
74 if (bx.smallEnd(dir) == nodal_lo) {
75 bx.growLo(dir,-1);
76 }
77 if (bx.bigEnd(dir) == nodal_hi) {
78 bx.growHi(dir,-1);
79 }
80
81 return bx;
82}
constexpr amrex::Real two
mf_h setVal(geomdata.ProbHi(2))
static amrex::Box clim_nudg_momentum_box(const amrex::Box &nodal_bx, int dir, const amrex::Box &domain, bool is_periodic)
Shrink an x- or y-nodal momentum tilebox to the faces ROMS nudges.
void apply_clim_nudg(const amrex::Box &bx, int ioff, int joff, const amrex::Array4< amrex::Real > &var, const amrex::Array4< amrex::Real const > &var_old, const amrex::Array4< amrex::Real const > &var_clim, const amrex::Array4< amrex::Real const > &clim_coeff, const amrex::Array4< amrex::Real const > &Hz, const amrex::Array4< amrex::Real const > &pm, const amrex::Array4< amrex::Real const > &pn, const amrex::Real dt_lev=zero)
Apply climatology nudging.