ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_TwoStreamRadiation.cpp File Reference

TwoStreamRadiation: the two-stream radiation model and its surface state. More...

#include <ERF_TwoStreamRadiation.H>
#include <ERF_RadStruct.H>
#include <AMReX_VisMF.H>
#include <AMReX_PlotFileUtil.H>
#include <AMReX_Utility.H>
#include <AMReX_Math.H>
#include <ERF_RadiationDiagnostics.H>
#include <ERF_TwoStreamColumn.H>
#include <ERF_TwoStreamCanopyForcing.H>
#include <ERF_Constants.H>
#include <ERF_ReadCheckpointMF.H>
#include <ERF_PrognosticCloudFraction.H>
#include <ERF_AerosolOpticalDepth.H>
#include <ERF_SimplifiedSEB.H>
#include <ERF_SurfaceMoisture.H>
#include <ERF_SEBTurbulentFlux.H>
#include <ERF_OrbCosZenith.H>
#include <AMReX_Print.H>
#include <AMReX_ParallelDescriptor.H>
#include <AMReX_Gpu.H>
#include <ERF_IndexDefines.H>
#include <ERF_EOS.H>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <limits>
Include dependency graph for ERF_TwoStreamRadiation.cpp:

Functions

TwoStreamSunDate two_stream_sun_date (const RadChoice &rc, TwoStreamRadiation::OrbitalCache &orbit, double epoch_time)
 The calendar sun of the two-stream model at a UTC epoch time (start_time + t). More...
 
void copy_surface_plane (const MultiFab &src2d, MultiFab &dst)
 

Detailed Description

TwoStreamRadiation: the two-stream radiation model and its surface state.

Computes SW/LW fluxes and per-level heating rates using real per-column vertical sweeps over the atmospheric grid. Reads temperature and density from the state and properly accumulates optical depth through all vertical levels.

Capabilities include:

  • Height-varying optical depth: optional "cloud_layer" tau_profile_type adds cloud_tau_per_layer on top of the clear-sky background within [cloud_base_height_m, cloud_top_height_m].
  • Cloud fraction masking: blends clear-sky and cloudy-column fluxes via F = (1 - cloud_fraction) * F_clear + cloud_fraction) * F_cloudy.
  • Diffuse (scattered) SW flux: two-stream reflectance/transmittance per layer combined with the surface albedo by the adding method, giving upward and downward diffuse streams (see ERF_TwoStreamSW.H).
  • Per-level heating rate output: writes the SW/LW radiative tendencies of potential temperature, (dT/dt)/pi, to a 2-component MultiFab (component 0 = SW, component 1 = LW), mirroring the RRTMGP convention expected by the RhoTheta source term.

Includes support for:

  • Height-varying surface properties (albedo, emissivity, temperature)
  • Dynamic cloud fraction from relative humidity and cloud water
  • Prescribed bulk aerosol optical depth
  • Dynamic solar geometry (time-varying solar position)
  • Surface energy balance diagnostics and prognostic updates

Vertical orientation follows ERF: k = kmin is the surface layer and k = kmax the top layer. SW sweeps downward from kmax to kmin; LW sweeps downward (TOA -> surface) and then upward (surface -> TOA). Layer temperature is obtained from rho*theta through the Exner function.

CSV diagnostics (domain means unless noted): SW_surface is the SW absorbed by the surface, SW_TOA the incident SW at the top of the atmosphere, SW_up_TOA the reflected SW leaving the top, LW_net_surface the net (up - down) LW at the surface, LW_up_TOA the outgoing LW at the top, and heating_rate_max the max(|Q_sw|+|Q_lw|) over the column evaluations.

Function Documentation

◆ copy_surface_plane()

void copy_surface_plane ( const MultiFab &  src2d,
MultiFab &  dst 
)
389 {
390  BoxList flat = dst.boxArray().boxList();
391  for (Box& b : flat) { b.setRange(2, 0); }
393  BoxArray(std::move(flat)) == src2d.boxArray() &&
394  dst.DistributionMap() == src2d.DistributionMap(),
395  "copy_surface_plane: the destination's horizontal grids differ from the source's");
396  for (MFIter mfi(dst); mfi.isValid(); ++mfi) {
397  const Box& fab_box = dst[mfi].box();
398  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(fab_box.smallEnd(2) <= 0 && fab_box.bigEnd(2) >= 0,
399  "copy_surface_plane: the destination must hold the k = 0 plane in its valid or ghost region");
400  const Box plane = makeSlab(mfi.validbox(), 2, 0);
401  dst[mfi].template copy<RunOn::Device>(src2d[mfi], plane, 0, plane, 0, 1);
402  }
403 }
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(axis >=0 &&axis< AMREX_SPACEDIM, "prob.axis must be 0, 1 or 2")

Referenced by TwoStreamRadiation::write_land_forcing().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ two_stream_sun_date()

TwoStreamSunDate two_stream_sun_date ( const RadChoice &  rc,
TwoStreamRadiation::OrbitalCache &  orbit,
double  epoch_time 
)

The calendar sun of the two-stream model at a UTC epoch time (start_time + t).

The calendar sun of the two-stream model at a UTC epoch time: the calendar day with the time of day as its fraction, the declination and the Earth-Sun distance factor, from the date as the RRTMGP interface forms it and the orbital code of ERF_OrbCosZenith.H (orbital_params once per year into orbit, with the erf.rad_orbital_* overrides passed to it, then orbital_decl per call). set_solar_state() takes the sun of every sweep from here, and the immersed-boundary balance its erf.ibseb.sun_mode = two_stream sun, so the two cannot drift apart.

103 {
104  // Calendar date of this call (UTC), as the RRTMGP interface forms it.
105  time_t timestamp = time_t(epoch_time);
106  struct tm timeinfo{};
107 #if defined(_WIN32)
108  gmtime_s(&timeinfo, &timestamp);
109 #else
110  gmtime_r(&timestamp, &timeinfo);
111 #endif
112  const int year = (rc.rad_orbital_year >= 0) ? rc.rad_orbital_year : timeinfo.tm_year + 1900;
113  const int mon = timeinfo.tm_mon + 1;
114  const int day = timeinfo.tm_mday;
115  const int sec = timeinfo.tm_hour*3600 + timeinfo.tm_min*60 + timeinfo.tm_sec;
116 
117  // Orbital parameters of the year (Berger 1978) unless overridden: a few
118  // hundred series terms and six vectors, so once per year, not per step.
119  if (orbit.year != year) {
120  int iyear = year;
121  double eccen = rc.rad_orbital_eccentricity;
122  double obliq = rc.rad_orbital_obliquity;
123  double mvelp = rc.rad_orbital_mvelp;
124  double obliqr = 0.0, lambm0 = 0.0, mvelpp = 0.0;
125  orbital_params(iyear, eccen, obliq, mvelp, obliqr, lambm0, mvelpp);
126  orbit.year = year;
127  orbit.eccen = eccen; orbit.obliqr = obliqr; orbit.lambm0 = lambm0; orbit.mvelpp = mvelpp;
128  }
129 
130  // Declination and Earth-Sun distance factor of the day.
131  double calday = orbital_calday(year, mon, day, sec);
132  double eccen = orbit.eccen, mvelpp = orbit.mvelpp, lambm0 = orbit.lambm0, obliqr = orbit.obliqr;
133  double delta = 0.0, eccf = 1.0;
134  orbital_decl(calday, eccen, mvelpp, lambm0, obliqr, delta, eccf);
135 
136  TwoStreamSunDate out;
137  out.calday = calday;
138  out.declin = delta;
139  out.eccf = eccf;
140  return out;
141 }
if(KE_decay_height > 0 &&state_pert.nComp() > RhoKE_comp)
Definition: ERF_InitCustomPert_ABL.H:74
AMREX_GPU_HOST AMREX_FORCE_INLINE double orbital_calday(int year, int mon, int day, int sec)
Definition: ERF_OrbCosZenith.H:485
AMREX_GPU_HOST AMREX_FORCE_INLINE void orbital_decl(double &calday, double &eccen, double &mvelpp, double &lambm0, double &obliqr, double &delta, double &eccf)
Definition: ERF_OrbCosZenith.H:18
AMREX_GPU_HOST AMREX_FORCE_INLINE void orbital_params(int &iyear_AD, double &eccen, double &obliq, double &mvelp, double &obliqr, double &lambm0, double &mvelpp)
Definition: ERF_OrbCosZenith.H:84
constexpr std::array< amrex::Real, num_veg_params > rc
Definition: ERF_SLM_DefaultParams.H:22
double obliqr
Definition: ERF_TwoStreamRadiation.H:297
int year
Definition: ERF_TwoStreamRadiation.H:295
double lambm0
Definition: ERF_TwoStreamRadiation.H:298
double mvelpp
Definition: ERF_TwoStreamRadiation.H:299
double eccen
Definition: ERF_TwoStreamRadiation.H:296
The calendar sun of the two-stream model at one time (see two_stream_sun_date()).
Definition: ERF_TwoStreamRadiation.H:384
double eccf
Earth-Sun distance factor (d0/d)^2.
Definition: ERF_TwoStreamRadiation.H:387
double declin
Solar declination [rad].
Definition: ERF_TwoStreamRadiation.H:386
double calday
Day of the year (1 = 1 January), UTC time of day as the fraction.
Definition: ERF_TwoStreamRadiation.H:385

Referenced by ERF::ibseb_set_two_stream_sun().

Here is the call graph for this function:
Here is the caller graph for this function: