ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_RRTMGP_Utils.H
Go to the documentation of this file.
1 #ifndef ERF_RRTMGP_UTILS_H
2 #define ERF_RRTMGP_UTILS_H
3 
4 #include "rrtmgp_const.h"
5 //#include "rrtmgp_conversion.h"
6 
7 #include "YAKL.h"
8 #include "YAKL_Bounds_fortran.h"
9 
10 #include "ERF_Constants.H"
11 
12 namespace rrtmgp {
13 
14 // Things we need from YAKL
15 using yakl::intrinsics::maxval;
16 using yakl::intrinsics::minval;
17 using yakl::intrinsics::count;
18 using yakl::intrinsics::sum;
19 
20 
21 template<class T, int myMem, int myStyle>
22 void
23 mixing_ratio_to_cloud_mass (yakl::Array<T,2,myMem,myStyle> const &mixing_ratio,
24  yakl::Array<T,2,myMem,myStyle> const &cloud_fraction,
25  yakl::Array<T,2,myMem,myStyle> const &dp,
26  yakl::Array<T,2,myMem,myStyle> &cloud_mass)
27 {
28  int ncol = mixing_ratio.dimension[0];
29  int nlay = mixing_ratio.dimension[1];
30  yakl::fortran::parallel_for(yakl::fortran::SimpleBounds<2>(nlay, ncol), YAKL_LAMBDA(int ilay, int icol)
31  {
32  // Compute in-cloud mixing ratio (mixing ratio of the cloudy part of the layer)
33  // NOTE: these thresholds (from E3SM) seem arbitrary, but included here for consistency
34  // This limits in-cloud mixing ratio to 0.005 kg/kg. According to note in cloud_diagnostics
35  // in EAM, this is consistent with limits in MG2. Is this true for P3?
36  if (cloud_fraction(icol,ilay) > 0) {
37  // Compute layer-integrated cloud mass (per unit area)
38  auto incloud_mixing_ratio = std::min(mixing_ratio(icol,ilay) / std::max(0.0001, cloud_fraction(icol,ilay)), 0.005);
39  cloud_mass(icol,ilay) = incloud_mixing_ratio * dp(icol,ilay) / CONST_GRAV;
40  } else {
41  cloud_mass(icol,ilay) = 0;
42  }
43  });
44 }
45 
46 
47 template<class S, class T>
48 void
49 limit_to_bounds (S const &arr_in,
50  T const lower,
51  T const upper,
52  S &arr_out)
53 {
54  yakl::c::parallel_for(arr_in.totElems(), YAKL_LAMBDA(int i)
55  {
56  arr_out.data()[i] = std::min(std::max(arr_in.data()[i], lower), upper);
57  });
58 }
59 
60 
61 // Provide a routine to compute heating due to radiative fluxes. This is
62 // computed as net flux into a layer, converted to a heating rate. It is
63 // the responsibility of the user to ensure fields are passed with the
64 // proper units. I.e., pressure at level interfaces should be in Pa,
65 // fluxes in W m-2, Cpair in J kg-1 K-1, gravit in m s-2. This will give
66 // heating in units of K s-1.
67 // TODO: we should probably update this to use the pseudo-density pdel instead
68 // of approximating pdel by differencing the level interface pressures.
69 // We are leaving this for the time being for consistency with SCREAMv0,
70 // from which this code was directly ported.
71 template <class T, int myMem, int myStyle>
72 void
73 compute_heating_rate (yakl::Array<T,2,myMem,myStyle> const &flux_up,
74  yakl::Array<T,2,myMem,myStyle> const &flux_dn,
75  yakl::Array<T,2,myMem,myStyle> const &rho ,
76  yakl::Array<T,2,myMem,myStyle> const &dz ,
77  yakl::Array<T,2,myMem,myStyle> &heating_rate)
78 {
79  auto ncol = flux_up.dimension[0];
80  auto nlay = flux_up.dimension[1]-1;
81  yakl::fortran::parallel_for(yakl::fortran::SimpleBounds<2>(nlay,ncol), YAKL_LAMBDA(int ilay, int icol)
82  {
83  heating_rate(icol,ilay) = ( flux_up(icol,ilay+1) - flux_up(icol,ilay)
84  - flux_dn(icol,ilay+1) + flux_dn(icol,ilay) )
85  / (Cp_d * rho(icol,ilay) * dz(icol,ilay));
86 
87  /*
88  if (icol == 1) {
89  printf("Heating Rate %i %e %e %e %e %e %e\n",ilay,
90  flux_up(icol,ilay+1), flux_up(icol,ilay),
91  flux_dn(icol,ilay+1), flux_dn(icol,ilay),
92  rho(icol,ilay), dz(icol,ilay));
93  }
94  */
95  });
96 }
97 
98 
99 inline
100 bool
101 radiation_do (const int irad,
102  const int nstep)
103 {
104  // If irad == 0, then never do radiation;
105  // Otherwise, we always call radiation at the first step,
106  // and afterwards we do radiation if the timestep is divisible
107  // by irad
108  if (irad == 0) {
109  return false;
110  } else {
111  return ( (nstep == 0) || (nstep % irad == 0) );
112  }
113 }
114 
115 } // namespace rrtmgp
116 #endif
constexpr amrex::Real Cp_d
Definition: ERF_Constants.H:12
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:21
@ rho
Definition: ERF_Kessler.H:30
@ T
Definition: ERF_IndexDefines.H:99
Definition: ERF_RRTMGP_Interface.cpp:15
bool radiation_do(const int irad, const int nstep)
Definition: ERF_RRTMGP_Utils.H:101
void compute_heating_rate(yakl::Array< T, 2, myMem, myStyle > const &flux_up, yakl::Array< T, 2, myMem, myStyle > const &flux_dn, yakl::Array< T, 2, myMem, myStyle > const &rho, yakl::Array< T, 2, myMem, myStyle > const &dz, yakl::Array< T, 2, myMem, myStyle > &heating_rate)
Definition: ERF_RRTMGP_Utils.H:73
void limit_to_bounds(S const &arr_in, T const lower, T const upper, S &arr_out)
Definition: ERF_RRTMGP_Utils.H:49
void mixing_ratio_to_cloud_mass(yakl::Array< T, 2, myMem, myStyle > const &mixing_ratio, yakl::Array< T, 2, myMem, myStyle > const &cloud_fraction, yakl::Array< T, 2, myMem, myStyle > const &dp, yakl::Array< T, 2, myMem, myStyle > &cloud_mass)
Definition: ERF_RRTMGP_Utils.H:23