ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_TwoStreamRadiation.H
Go to the documentation of this file.
1 #ifndef ERF_TWO_STREAM_RADIATION_H_
2 #define ERF_TWO_STREAM_RADIATION_H_
3 
4 #include <memory>
5 #include <string>
6 
7 #include <AMReX_BoxArray.H>
8 #include <AMReX_DistributionMapping.H>
9 #include <AMReX_Geometry.H>
10 #include <AMReX_MultiFab.H>
11 #include <AMReX_REAL.H>
12 #include <AMReX_Vector.H>
13 
14 #include <ERF_RadStruct.H>
15 #include <ERF_LandSurface.H>
17 
18 /**
19  * @brief The two-stream radiation model (erf.radiation_model = TwoStream).
20  *
21  * Owns everything the model keeps between steps: the per-level surface
22  * property fields it falls back on when no land-surface model supplies
23  * them, the surface-energy-balance (SEB) fields and force-restore state,
24  * and the domain-mean flux diagnostics of the last column sweep. ERF holds
25  * one instance and calls it only after testing
26  * `solverChoice.rad_type == RadiationType::TwoStream`; every method
27  * here checks the same predicate and returns without acting otherwise.
28  *
29  * Lifecycle:
30  * - resize(nlevs) once at construction (before the inputs are read);
31  * - define_level(lev, radChoice, rdOcp, ba2d, dm) whenever a level is (re)built;
32  * - advance(...) twice per step: "pre_dycore" runs the column sweep on the
33  * old state and writes the heating rates, "post_dycore" reuses that
34  * sweep's flux diagnostics and advances the SEB state by dt_step;
35  * - write_checkpoint / read_checkpoint for the prognostic surface state.
36  *
37  * The heating-rate MultiFab itself stays in ERF, since RRTMGP writes the
38  * same 2-component (SW, LW) array and the RhoTheta source term and the
39  * plotfile read it without caring which model filled it.
40  */
42 {
43 public:
44  TwoStreamRadiation () = default;
45 
46  /** @brief Size the per-level containers; no allocation happens here. */
47  void resize (int nlevs_max);
48 
49  /** @brief True once a level has been defined with the model selected. */
50  [[nodiscard]] bool active () const {
51  return (m_rad != nullptr) && m_rad->enabled;
52  }
53 
54  /**
55  * @brief Allocate the 2D surface fields of one level on the given
56  * horizontal BoxArray and fill them with the scalar defaults. A no-op
57  * unless rad_choice.rad_type == TwoStream.
58  */
59  void define_level (int lev,
60  const RadChoice& rad_choice,
62  const amrex::BoxArray& ba2d,
63  const amrex::DistributionMapping& dm);
64 
65  /**
66  * @brief One radiation call at one level.
67  *
68  * @param lev level
69  * @param nstep step number, used as the diagnostics row index
70  * @param time time logged with the diagnostics row [s]
71  * @param dt_step step size, used by the SEB Euler update [s]
72  * @param call_site "pre_dycore" (column sweep + diagnostics) or
73  * "post_dycore" (cached diagnostics + SEB update)
74  * @param cons_old old-state conserved variables of this level
75  * @param z_phys_nd nodal heights (layer interfaces), or nullptr on a uniform grid
76  * @param geom geometry of this level
77  * @param lsm land-surface model (queried for per-column fields)
78  * @param qheating 2-component (SW, LW) heating-rate MultiFab of this
79  * level, written at the pre-dycore call; may be nullptr
80  * @param rad_fluxes 4-component (SW up, SW down, LW up, LW down) interface
81  * fluxes of this level in RRTMGP's level layout (index k
82  * the lower interface of layer k, the top of the
83  * atmosphere in the z-ghost cell above the top layer),
84  * written at the pre-dycore call; may be nullptr
85  * @param t_surf the surface layer's surface temperature, or nullptr;
86  * used as the longwave boundary condition where no
87  * land-surface field exists, as RRTMGP does
88  * @param lat_m per-column latitude [degrees], or nullptr (then
89  * erf.rad_cons_lat); only the WRF/metgrid inits fill it
90  * @param lon_m per-column longitude [degrees], likewise
91  * @param epoch_time seconds since 1970-01-01 00:00 UTC of this call
92  * (start_time + time), the RRTMGP time base; double, as
93  * RRTMGP keeps it, since a float cannot resolve a time
94  * of day at ~1.7e9 s
95  * @param have_datetime true when start_datetime (or a WRF/metgrid start
96  * date) fixed the calendar; without it a dynamic sun
97  * cannot be placed and the call aborts
98  */
99  void advance (int lev,
100  int nstep,
101  amrex::Real time,
102  amrex::Real dt_step,
103  const std::string& call_site,
104  const amrex::MultiFab& cons_old,
105  const amrex::MultiFab* z_phys_nd,
106  const amrex::Geometry& geom,
107  LandSurface& lsm,
108  amrex::MultiFab* qheating,
109  amrex::MultiFab* rad_fluxes,
110  const amrex::MultiFab* t_surf,
111  const amrex::MultiFab* lat_m,
112  const amrex::MultiFab* lon_m,
113  double epoch_time,
114  bool have_datetime);
115 
116  /** @brief Write the prognostic surface state of one level (SEB on). */
117  void write_checkpoint (int lev, const std::string& checkpointname) const;
118 
119  /** @brief Read it back when the checkpoint carries it; else keep defaults. */
120  void read_checkpoint (int lev, const std::string& restart_chkfile);
121 
122  // Orbital elements of the current year (Berger 1978, or the erf.rad_orbital_*
123  // overrides), computed once per year rather than every step, and the
124  // one-time note about an unscaled irradiance. Public so the file-local
125  // solar-state helper can fill it.
126  struct OrbitalCache {
127  int year = -9999;
128  double eccen = 0.0;
129  double obliqr = 0.0;
130  double lambm0 = 0.0;
131  double mvelpp = 0.0;
132  bool noted_unscaled = false;
133  };
134 
135 private:
136  // Domain-mean flux diagnostics of the last column sweep, per level, so the
137  // post-dycore call can report them without sweeping again.
138  struct FluxDiag {
140  amrex::Real SW_TOA = 0.0; // domain-mean incident SW at the top
145  };
146 
147  const RadChoice* m_rad = nullptr;
150 
151  // CSV / console diagnostics writer, created on the first advance() so its
152  // header and duplicate-row state persist across calls.
153  std::unique_ptr<RadiationDiagnostics> m_diag;
154 
155  // Fallback surface properties when no LSM supplies them (2D: i,j).
156  amrex::Vector<std::unique_ptr<amrex::MultiFab>> m_alb_sw;
157  amrex::Vector<std::unique_ptr<amrex::MultiFab>> m_emiss_lw;
158  amrex::Vector<std::unique_ptr<amrex::MultiFab>> m_t_sfc; // prognostic when the SEB evolves it
159 
160  // Surface-energy-balance fields (2D: i,j), allocated when seb_enable.
161  amrex::Vector<std::unique_ptr<amrex::MultiFab>> m_sw_flux_sfc; // net absorbed shortwave [W/m^2]
162  amrex::Vector<std::unique_ptr<amrex::MultiFab>> m_lw_flux_sfc; // net absorbed longwave [W/m^2]
163  amrex::Vector<std::unique_ptr<amrex::MultiFab>> m_hfx_sfc; // sensible heat flux [W/m^2]
164  amrex::Vector<std::unique_ptr<amrex::MultiFab>> m_lh_sfc; // latent heat flux [W/m^2]
165  amrex::Vector<std::unique_ptr<amrex::MultiFab>> m_grdflx_sfc; // ground heat flux [W/m^2]
166  amrex::Vector<std::unique_ptr<amrex::MultiFab>> m_q_sfc; // surface moisture [kg/kg], prognostic
167  amrex::Vector<std::unique_ptr<amrex::MultiFab>> m_t_deep; // deep-soil temperature [K]
168  amrex::Vector<std::unique_ptr<amrex::MultiFab>> m_q_deep; // deep-soil moisture [kg/kg]
169 
170  amrex::Vector<FluxDiag> m_flux_diag;
171 };
172 
173 #endif // ERF_TWO_STREAM_RADIATION_H_
constexpr amrex::Real RdoCp
Definition: ERF_Constants.H:41
const Real rdOcp
Definition: ERF_InitCustomPert_ABL.H:72
Radiation model type and control parameters.
Radiation module diagnostic output and CSV logging.
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Wrapper class for managing land surface models across AMR levels.
Definition: ERF_LandSurface.H:19
The two-stream radiation model (erf.radiation_model = TwoStream).
Definition: ERF_TwoStreamRadiation.H:42
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_q_sfc
Definition: ERF_TwoStreamRadiation.H:166
TwoStreamRadiation()=default
void read_checkpoint(int lev, const std::string &restart_chkfile)
Read it back when the checkpoint carries it; else keep defaults.
Definition: ERF_TwoStreamRadiation.cpp:279
void define_level(int lev, const RadChoice &rad_choice, amrex::Real rdOcp, const amrex::BoxArray &ba2d, const amrex::DistributionMapping &dm)
Allocate the 2D surface fields of one level on the given horizontal BoxArray and fill them with the s...
Definition: ERF_TwoStreamRadiation.cpp:222
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_grdflx_sfc
Definition: ERF_TwoStreamRadiation.H:165
void write_checkpoint(int lev, const std::string &checkpointname) const
Write the prognostic surface state of one level (SEB on).
Definition: ERF_TwoStreamRadiation.cpp:263
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_lw_flux_sfc
Definition: ERF_TwoStreamRadiation.H:162
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_q_deep
Definition: ERF_TwoStreamRadiation.H:168
amrex::Real m_rdOcp
Definition: ERF_TwoStreamRadiation.H:148
amrex::Vector< FluxDiag > m_flux_diag
Definition: ERF_TwoStreamRadiation.H:170
bool active() const
True once a level has been defined with the model selected.
Definition: ERF_TwoStreamRadiation.H:50
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_emiss_lw
Definition: ERF_TwoStreamRadiation.H:157
void resize(int nlevs_max)
Size the per-level containers; no allocation happens here.
Definition: ERF_TwoStreamRadiation.cpp:205
std::unique_ptr< RadiationDiagnostics > m_diag
Definition: ERF_TwoStreamRadiation.H:153
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_t_sfc
Definition: ERF_TwoStreamRadiation.H:158
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_lh_sfc
Definition: ERF_TwoStreamRadiation.H:164
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_alb_sw
Definition: ERF_TwoStreamRadiation.H:156
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_sw_flux_sfc
Definition: ERF_TwoStreamRadiation.H:161
OrbitalCache m_orbit
Definition: ERF_TwoStreamRadiation.H:149
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_t_deep
Definition: ERF_TwoStreamRadiation.H:167
void advance(int lev, int nstep, amrex::Real time, amrex::Real dt_step, const std::string &call_site, const amrex::MultiFab &cons_old, const amrex::MultiFab *z_phys_nd, const amrex::Geometry &geom, LandSurface &lsm, amrex::MultiFab *qheating, amrex::MultiFab *rad_fluxes, const amrex::MultiFab *t_surf, const amrex::MultiFab *lat_m, const amrex::MultiFab *lon_m, double epoch_time, bool have_datetime)
One radiation call at one level.
Definition: ERF_TwoStreamRadiation.cpp:297
const RadChoice * m_rad
Definition: ERF_TwoStreamRadiation.H:147
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_hfx_sfc
Definition: ERF_TwoStreamRadiation.H:163
Container holding radiation-related choices and parameters.
Definition: ERF_RadStruct.H:70
bool enabled
True when erf.radiation_model = TwoStream. Set by init_params from the model SolverChoice read; the e...
Definition: ERF_RadStruct.H:76
Definition: ERF_TwoStreamRadiation.H:138
amrex::Real LW_net_surface
Definition: ERF_TwoStreamRadiation.H:142
amrex::Real SW_TOA
Definition: ERF_TwoStreamRadiation.H:140
amrex::Real SW_surface
Definition: ERF_TwoStreamRadiation.H:139
amrex::Real heating_rate_max
Definition: ERF_TwoStreamRadiation.H:144
amrex::Real LW_up_TOA
Definition: ERF_TwoStreamRadiation.H:143
amrex::Real SW_up_TOA
Definition: ERF_TwoStreamRadiation.H:141
Definition: ERF_TwoStreamRadiation.H:126
bool noted_unscaled
Definition: ERF_TwoStreamRadiation.H:132
double obliqr
Definition: ERF_TwoStreamRadiation.H:129
int year
Definition: ERF_TwoStreamRadiation.H:127
double lambm0
Definition: ERF_TwoStreamRadiation.H:130
double mvelpp
Definition: ERF_TwoStreamRadiation.H:131
double eccen
Definition: ERF_TwoStreamRadiation.H:128