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, const amrex::Vector< const amrex::MultiFab * > &lsm_input_ptrs, const 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, amrex::Real &declin, amrex::Real &calday) 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 bool radiation_updated () const
 Reports whether the last radiation call updated its outputs. More...
 
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:68
bool m_ice
Definition: ERF_RadiationSimple.H:66
bool m_have_qc
Definition: ERF_RadiationSimple.H:65
int m_qi_comp
Definition: ERF_RadiationSimple.H:69
int m_qv_comp
Definition: ERF_RadiationSimple.H:67
bool m_have_qv
Definition: ERF_RadiationSimple.H:64
int qi
cloud ice
Definition: ERF_DataStruct.H:251
int qv
water vapor
Definition: ERF_DataStruct.H:249
int qc
cloud liquid water
Definition: ERF_DataStruct.H:250
MoistureComponentIndices moisture_indices
Index map of the moisture data carried by the active scheme: conserved-state components for the speci...
Definition: ERF_DataStruct.H:2575

◆ ~RadiationSimple()

RadiationSimple::~RadiationSimple ( )
default

Member Function Documentation

◆ get_radlwdn()

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

◆ get_radqrlw()

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

◆ 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:36
amrex::MultiFab deltaq
Definition: ERF_RadiationSimple.H:74
amrex::Geometry m_geom
Definition: ERF_RadiationSimple.H:71
amrex::BoxArray m_ba
Definition: ERF_RadiationSimple.H:72
amrex::MultiFab flux
Definition: ERF_RadiationSimple.H:74

◆ 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,
const amrex::Vector< const amrex::MultiFab * > &  lsm_input_ptrs,
const 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,
amrex::Real &  declin,
amrex::Real &  calday 
)
overridevirtual

Implements IRadiation.

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

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

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: