ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
RadiationSimple Class Reference

#include <ERF_RadiationSimple.H>

Inheritance diagram for RadiationSimple:
Collaboration diagram for RadiationSimple:

Public Member Functions

 RadiationSimple (const int &, const SolverChoice &sc)
 
 ~RadiationSimple ()=default
 
virtual void Init (const amrex::Geometry &geom, const amrex::BoxArray &ba, amrex::MultiFab *cons_in) override
 
virtual void Run (int &level, int &step, double &time, const double &dt, const amrex::BoxArray &ba, amrex::Geometry &geom, amrex::MultiFab *cons_in, amrex::iMultiFab *lmask, amrex::MultiFab *t_surf, amrex::Vector< amrex::MultiFab * > &lsm_input_ptrs, amrex::Vector< amrex::MultiFab * > &lsm_output_ptrs, amrex::MultiFab *qheating_rates, amrex::MultiFab *rad_fluxes, amrex::MultiFab *z_phys, amrex::MultiFab *lat, amrex::MultiFab *lon, const bool updated_lsm) override
 
virtual void WriteDataLog (const double &time) override
 
const amrex::MultiFab * get_radlwdn ()
 
const amrex::MultiFab * get_radqrlw ()
 
- Public Member Functions inherited from IRadiation
virtual ~IRadiation ()=default
 
virtual amrex::Vector< std::string > get_lsm_input_varnames ()
 
virtual amrex::Vector< std::string > get_lsm_output_varnames ()
 
virtual bool is_nested_patch () const
 
void setupDataLog ()
 
void setDataLogFrequency (const int nstep)
 
bool hasDatalog ()
 

Private Attributes

bool m_have_qv = false
 
bool m_have_qc = false
 
bool m_ice = false
 
int m_qv_comp = -1
 
int m_qc_comp = -1
 
int m_qi_comp = -1
 
amrex::Geometry m_geom
 
amrex::BoxArray m_ba
 
amrex::MultiFab deltaq
 
amrex::MultiFab flux
 
std::unique_ptr< amrex::MultiFab > radlwdn
 
std::unique_ptr< amrex::MultiFab > radqrlw
 

Additional Inherited Members

- Protected Attributes inherited from IRadiation
std::unique_ptr< std::fstream > datalog = nullptr
 
std::string datalogname
 
int datalog_int = -1
 

Constructor & Destructor Documentation

◆ RadiationSimple()

RadiationSimple::RadiationSimple ( const int &  ,
const SolverChoice sc 
)
inline
18  {
19  // Every moist species we read is taken from the configured moisture-component
20  // mapping, so each scheme is indexed by its own layout rather than by an
21  // enumerated model list: every scheme carrying cloud ice (SAM, Morrison, WSM6,
22  // WDM6, ...) is picked up, and the warm-rain schemes are not.
26 
27  m_have_qv = (m_qv_comp >= 0);
28  m_have_qc = (m_qc_comp >= 0);
29  m_ice = (m_qi_comp >= 0);
30  }
int m_qc_comp
Definition: ERF_RadiationSimple.H:66
bool m_ice
Definition: ERF_RadiationSimple.H:64
bool m_have_qc
Definition: ERF_RadiationSimple.H:63
int m_qi_comp
Definition: ERF_RadiationSimple.H:67
int m_qv_comp
Definition: ERF_RadiationSimple.H:65
bool m_have_qv
Definition: ERF_RadiationSimple.H:62
int qi
cloud ice
Definition: ERF_DataStruct.H:236
int qv
water vapor
Definition: ERF_DataStruct.H:234
int qc
cloud liquid water
Definition: ERF_DataStruct.H:235
MoistureComponentIndices moisture_indices
Index map of the moisture data carried by the active scheme: conserved-state components for the speci...
Definition: ERF_DataStruct.H:2263

◆ ~RadiationSimple()

RadiationSimple::~RadiationSimple ( )
default

Member Function Documentation

◆ get_radlwdn()

const amrex::MultiFab* RadiationSimple::get_radlwdn ( )
inline
58 { return radlwdn.get(); }
std::unique_ptr< amrex::MultiFab > radlwdn
Definition: ERF_RadiationSimple.H:73

◆ get_radqrlw()

const amrex::MultiFab* RadiationSimple::get_radqrlw ( )
inline
59 { return radqrlw.get(); }
std::unique_ptr< amrex::MultiFab > radqrlw
Definition: ERF_RadiationSimple.H:74

◆ Init()

void RadiationSimple::Init ( const amrex::Geometry &  geom,
const amrex::BoxArray &  ba,
amrex::MultiFab *  cons_in 
)
overridevirtual

Implements IRadiation.

12 {
13  m_geom = geom;
14  m_ba = ba;
15 
16  DistributionMapping dm = cons_in->DistributionMap();
17  deltaq.define(ba, dm, 1, 0);
18  flux.define(ba, dm, 1, IntVect(0, 0, 1));
19  radlwdn = std::make_unique<amrex::MultiFab>(ba, dm, 1, 0);
20  radqrlw = std::make_unique<amrex::MultiFab>(ba, dm, 1, 0);
21 
22  deltaq.setVal(zero);
23  flux.setVal(zero);
24  radlwdn->setVal(zero);
25  radqrlw->setVal(zero);
26 }
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:29
amrex::MultiFab deltaq
Definition: ERF_RadiationSimple.H:72
amrex::Geometry m_geom
Definition: ERF_RadiationSimple.H:69
amrex::BoxArray m_ba
Definition: ERF_RadiationSimple.H:70
amrex::MultiFab flux
Definition: ERF_RadiationSimple.H:72

◆ Run()

void RadiationSimple::Run ( int &  level,
int &  step,
double &  time,
const double &  dt,
const amrex::BoxArray &  ba,
amrex::Geometry &  geom,
amrex::MultiFab *  cons_in,
amrex::iMultiFab *  lmask,
amrex::MultiFab *  t_surf,
amrex::Vector< amrex::MultiFab * > &  lsm_input_ptrs,
amrex::Vector< amrex::MultiFab * > &  lsm_output_ptrs,
amrex::MultiFab *  qheating_rates,
amrex::MultiFab *  rad_fluxes,
amrex::MultiFab *  z_phys,
amrex::MultiFab *  lat,
amrex::MultiFab *  lon,
const bool  updated_lsm 
)
overridevirtual

Implements IRadiation.

45 {
46 
47  constexpr amrex::Real cp_spec = 1015.0;
48  constexpr amrex::Real coef = 70.0;
49  constexpr amrex::Real coef1 = 22.0;
50  constexpr amrex::Real f0=3.75e-6;
51  constexpr amrex::Real xk = 85.0;
52 
53  const Real fixed_dz = geom.CellSize(2);
54  const int nz = geom.Domain().length(2);
55 
56  flux.setVal(zero);
57  deltaq.setVal(zero);
58 
59  const bool have_qv = m_have_qv;
60  const bool have_qc = m_have_qc;
61  const bool ice = m_ice;
62  const int qv_comp = m_qv_comp;
63  const int qc_comp = m_qc_comp;
64  const int qi_comp = m_qi_comp;
65 
66  for (MFIter mfi(*cons_in, TileNoZ()); mfi.isValid(); ++mfi)
67  {
68  Box box = mfi.validbox();
69  box.makeSlab(2, 0);
70 
71  const Array4<const Real>& cons_arr = cons_in->const_array(mfi);
72  const Array4<const Real>& z_nd_arr = (z_phys) ? z_phys->const_array(mfi) : Array4<const Real>{};
73  const Array4<Real>& deltaq_arr = deltaq.array(mfi);
74  const Array4<Real>& flux_arr = flux.array(mfi);
75  const Array4<Real>& radlwdn_arr = radlwdn->array(mfi);
76  const Array4<Real>& radqrlw_arr = radqrlw->array(mfi);
77  const Array4<Real>& qheating_arr = qheating_rates->array(mfi);
78 
79  const Array4<Real>& radfluxes_arr = rad_fluxes->array(mfi);
80 
81  ParallelFor(box, [=] AMREX_GPU_DEVICE (int i, int j, int)
82  {
83  int itop = 0;
84  Real qzinf = 0.0; // holds accumulated optical depth between z and domain top
85  Real qzeroz = 0.0; // holds accumulated optical depth between surface and z
86 
87  for (int k = 0; k < nz; k++)
88  {
89  Real rho = cons_arr(i, j, k, Rho_comp);
90  Real qv = (have_qv) ? cons_arr(i, j, k, qv_comp) / rho : zero;
91  Real qc = (have_qc) ? cons_arr(i, j, k, qc_comp) / rho : zero;
92  Real qi = (ice) ? cons_arr(i, j, k, qi_comp) / rho : zero;
93 
94  Real dz = (z_nd_arr) ? Real(0.25) * ( (z_nd_arr(i ,j ,k+1) - z_nd_arr(i ,j ,k))
95  + (z_nd_arr(i+1,j ,k+1) - z_nd_arr(i+1,j ,k))
96  + (z_nd_arr(i ,j+1,k+1) - z_nd_arr(i ,j+1,k))
97  + (z_nd_arr(i+1,j+1,k+1) - z_nd_arr(i+1,j+1,k)) ) : fixed_dz;
98 
99  // optical depth only includes that due to liquid water
100  if (qc + qi > 0.0)
101  {
102  deltaq_arr(i, j, k) = xk * rho * (qc + qi) * dz;
103  }
104 
105  // inversion height is top of highest layer w/q>8g/kg
106  if (qv + qc + qi > 0.008)
107  {
108  itop = max(itop, k+1); // note zi(k+1) is inversion height
109  }
110 
111  // accumulate optical depth in qzinf
112  qzinf = qzinf + deltaq_arr(i, j, k);
113  }
114 
115  // note: qzinf now holds total optical depth of column (due to cloud)
116  // qzeroz is initialized to zero since first level is at surface
117 
118  // compute net upward longwave flux up to inversion height
119  for (int k = 0; k <= itop; k++)
120  {
121  flux_arr(i, j, k) = coef*exp(-qzinf) + coef1*exp(-qzeroz);
122  qzinf = qzinf - deltaq_arr(i, j, k);
123  qzeroz = qzeroz + deltaq_arr(i, j, k);
124  }
125 
126  // compute net upward longwave flux above inversion height
127  // this includes correction for clearsky fluxes which balances
128  // the prescribed subsidence heating above the inversion
129  Real z_itop = (z_nd_arr) ? z_nd_arr(i, j, itop) : itop * fixed_dz;
130  for (int k = itop + 1; k < nz; k++) {
131  Real rho_nd = 0.5 * (cons_arr(i, j, k - 1, Rho_comp) + cons_arr(i, j, k, Rho_comp)); // rho at interface
132  Real zi = (z_nd_arr) ? z_nd_arr(i, j, k) : k * fixed_dz;
133  flux_arr(i, j, k) = coef * exp(-qzinf) + coef1 * exp(-qzeroz)
134  + cp_spec * rho_nd * f0 * (0.25 * zi + 0.75 * z_itop)
135  * pow(zi - z_itop, 1.0 / 3.0);
136  qzinf = qzinf - deltaq_arr(i, j, k);
137  qzeroz = qzeroz + deltaq_arr(i, j, k);
138  }
139  Real rho_nd = 0.5 * (cons_arr(i, j, nz - 1, Rho_comp) + cons_arr(i, j, nz, Rho_comp));
140  Real zi = (z_nd_arr) ? z_nd_arr(i, j, nz) : nz * fixed_dz;
141  flux_arr(i, j, nz) = coef * exp(-qzinf) + coef1 * exp(-qzeroz)
142  + cp_spec * rho_nd * f0 * (0.25 * zi + 0.75 * z_itop)
143  * pow(zi - z_itop, 1.0 / 3.0);
144 
145  // note that our flux differs from the specification in that it
146  // uses the local density (rather than the interface density) in
147  // computing the correction to the flux above the inversion.
148  // Formulating things in this way ensures a rough balance between
149  // the subsidence heating and radiative cooling above the inversion.
150 
151  // compute radiative heating as divergence of net upward lw flux
152  for (int k = 0; k < nz; k++)
153  {
154  Real dz = (z_nd_arr) ? 0.25 * ( (z_nd_arr(i ,j ,k+1) - z_nd_arr(i ,j ,k))
155  + (z_nd_arr(i+1,j ,k+1) - z_nd_arr(i+1,j ,k))
156  + (z_nd_arr(i ,j+1,k+1) - z_nd_arr(i ,j+1,k))
157  + (z_nd_arr(i+1,j+1,k+1) - z_nd_arr(i+1,j+1,k)) ) : fixed_dz;
158 
159  Real cpmassl = cp_spec * cons_arr(i, j, k, Rho_comp) * dz; // thermal mass
160  Real FTHRL = -(flux_arr(i, j, k+1) - flux_arr(i, j, k)) / cpmassl;
161  // convert heating rate FTHRL for theta_d
162  Real pres = getPgivenRTh(cons_arr(i,j,k,RhoTheta_comp),cons_arr(i,j,k,RhoQ1_comp)/cons_arr(i,j,k,Rho_comp));
163  Real exner = getExnergivenP(pres, R_d/Cp_d);
164  FTHRL *= exner;
165  qheating_arr(i, j, k, 1) = FTHRL; // radiative heating for source term
166  radlwdn_arr(i, j, k) = flux_arr(i, j, k); // net lw flux
167  radqrlw_arr(i, j, k) = FTHRL; // net lw heating
168 
169  // write lw dn to ERF fluxes
170  radfluxes_arr(i, j, k, 3) = flux_arr(i, j, k); // net lw flux
171  }
172  });
173  }
174 }
constexpr amrex::Real Cp_d
Definition: ERF_Constants.H:36
constexpr amrex::Real R_d
Definition: ERF_Constants.H:34
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getExnergivenP(const amrex::Real P, const amrex::Real rdOcp)
Definition: ERF_EOS.H:141
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getPgivenRTh(const amrex::Real rhotheta, const amrex::Real qv=amrex::Real(0))
Definition: ERF_EOS.H:81
#define Rho_comp
Definition: ERF_IndexDefines.H:39
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:40
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:45
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);})
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_FORCE_INLINE amrex::IntVect TileNoZ()
Definition: ERF_TileNoZ.H:11
@ pres
Definition: ERF_Kessler.H:28
@ rho
Definition: ERF_Kessler.H:25
@ qv
Definition: ERF_Kessler.H:31
@ qc
Definition: ERF_SatAdj.H:42
@ qi
Definition: ERF_WDM6.H:28
@ dz
Definition: ERF_AdvanceWDM6.cpp:272
@ zi
Definition: ERF_AdvanceWDM6.cpp:276
Here is the call graph for this function:

◆ WriteDataLog()

void RadiationSimple::WriteDataLog ( const double &  time)
overridevirtual

Implements IRadiation.

177 {
178  constexpr int datwidth = 14;
179  constexpr int datprecision = 9;
180  constexpr int timeprecision = 13;
181 
182  Gpu::HostVector<Real> h_avg_radlwdn, h_avg_radqrlw;
183 
184  auto domain = m_geom.Domain();
185  h_avg_radlwdn = sumToLine(*radlwdn, 0, 1, domain, 2);
186  h_avg_radqrlw = sumToLine(*radqrlw, 0, 1, domain, 2);
187 
188  Real area_z = static_cast<Real>(domain.length(0)*domain.length(1));
189  int nz = domain.length(2);
190  for (int k = 0; k < nz; k++) {
191  h_avg_radlwdn[k] /= area_z;
192  h_avg_radqrlw[k] /= area_z;
193  }
194 
195  if (ParallelDescriptor::IOProcessor()) {
196  std::ostream& log = *datalog;
197 
198  if (log.good()) {
199  for (int k = 0; k < nz; k++)
200  {
201  Real z = k * m_geom.CellSize(2);
202  log << std::setw(datwidth) << std::setprecision(timeprecision) << time << " "
203  << std::setw(datwidth) << std::setprecision(datprecision) << z << " "
204  << h_avg_radlwdn[k] << " "
205  << h_avg_radqrlw[k] << std::endl;
206  }
207  // Write top face values
208  Real z = nz * m_geom.CellSize(2);
209  log << std::setw(datwidth) << std::setprecision(timeprecision) << time << " "
210  << std::setw(datwidth) << std::setprecision(datprecision) << z << " "
211  << 0.0 << " "
212  << 0.0 << std::endl;
213  }
214  }
215 }
std::unique_ptr< std::fstream > datalog
Definition: ERF_RadiationInterface.H:94

Member Data Documentation

◆ deltaq

amrex::MultiFab RadiationSimple::deltaq
private

◆ flux

amrex::MultiFab RadiationSimple::flux
private

◆ m_ba

amrex::BoxArray RadiationSimple::m_ba
private

◆ m_geom

amrex::Geometry RadiationSimple::m_geom
private

◆ m_have_qc

bool RadiationSimple::m_have_qc = false
private

Referenced by RadiationSimple().

◆ m_have_qv

bool RadiationSimple::m_have_qv = false
private

Referenced by RadiationSimple().

◆ m_ice

bool RadiationSimple::m_ice = false
private

Referenced by RadiationSimple().

◆ m_qc_comp

int RadiationSimple::m_qc_comp = -1
private

Referenced by RadiationSimple().

◆ m_qi_comp

int RadiationSimple::m_qi_comp = -1
private

Referenced by RadiationSimple().

◆ m_qv_comp

int RadiationSimple::m_qv_comp = -1
private

Referenced by RadiationSimple().

◆ radlwdn

std::unique_ptr<amrex::MultiFab> RadiationSimple::radlwdn
private

Referenced by get_radlwdn().

◆ radqrlw

std::unique_ptr<amrex::MultiFab> RadiationSimple::radqrlw
private

Referenced by get_radqrlw().


The documentation for this class was generated from the following files: