ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_PBLModels.H File Reference
#include <functional>
#include <limits>
#include <memory>
#include <AMReX_MultiFab.H>
#include <AMReX_Periodicity.H>
#include "ERF_Constants.H"
#include "ERF_DataStruct.H"
#include "ERF_MOSTUtils.H"
Include dependency graph for ERF_PBLModels.H:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  PBLDerivativeDzInv
 
struct  PBLSurfaceLayerGradient
 
struct  PBLDerivativeDzInv_N
 Functor for inverse vertical spacings with constant grid spacing. More...
 
struct  PBLDerivativeDzInv_S
 Functor for inverse vertical spacings for stretched grids using a spacing array. More...
 
struct  PBLDerivativeDzInv_T
 Functor for inverse vertical spacings for terrain-following grids using cell-center heights. More...
 

Functions

void ComputeDiffusivityMYJ (double dt, const amrex::MultiFab &xvel, const amrex::MultiFab &yvel, amrex::MultiFab &cons_in, amrex::MultiFab &eddyViscosity, const amrex::Geometry &geom, const TurbChoice &turbChoice, std::unique_ptr< SurfaceLayer > &SurfLayer, bool use_terrain_fitted_coords, bool use_moisture, int level, const amrex::BCRec *bc_ptr, bool, const std::unique_ptr< amrex::MultiFab > &z_phys_nd, const std::unique_ptr< amrex::MultiFab > &z_phys_cc, const MoistureComponentIndices &moisture_indices)
 
void ComputeDiffusivityMYNN25 (const amrex::MultiFab &xvel, const amrex::MultiFab &yvel, const amrex::MultiFab &cons_in, amrex::MultiFab &eddyViscosity, const amrex::Geometry &geom, const TurbChoice &turbChoice, std::unique_ptr< SurfaceLayer > &SurfLayer, bool use_terrain_fitted_coords, bool use_moisture, int level, const amrex::BCRec *bc_ptr, bool, const std::unique_ptr< amrex::MultiFab > &z_phys_nd, const std::unique_ptr< amrex::MultiFab > &z_phys_cc, const MoistureComponentIndices &moisture_indices)
 
void ComputeDiffusivityMYNNEDMF (const amrex::MultiFab &xvel, const amrex::MultiFab &yvel, const amrex::MultiFab &cons_in, amrex::MultiFab &eddyViscosity, const amrex::Geometry &geom, const TurbChoice &turbChoice, std::unique_ptr< SurfaceLayer > &SurfLayer, bool use_terrain_fitted_coords, bool use_moisture, int level, const amrex::BCRec *bc_ptr, bool, const std::unique_ptr< amrex::MultiFab > &z_phys_nd, const std::unique_ptr< amrex::MultiFab > &z_phys_cc, const MoistureComponentIndices &moisture_indices)
 
void ComputeDiffusivityYSU (const amrex::MultiFab &xvel, const amrex::MultiFab &yvel, const amrex::MultiFab &cons_in, amrex::MultiFab &eddyViscosity, const amrex::Geometry &geom, const TurbChoice &turbChoice, std::unique_ptr< SurfaceLayer > &SurfLayer, bool use_terrain_fitted_coords, bool use_moisture, int level, const amrex::BCRec *bc_ptr, bool, const std::unique_ptr< amrex::MultiFab > &z_phys_nd, const std::unique_ptr< amrex::MultiFab > &z_phys_cc, const MoistureComponentIndices &moisture_indices)
 
void ComputeDiffusivityMRF (const amrex::MultiFab &xvel, const amrex::MultiFab &yvel, const amrex::MultiFab &cons_in, amrex::MultiFab &eddyViscosity, const amrex::Geometry &geom, const TurbChoice &turbChoice, std::unique_ptr< SurfaceLayer > &SurfLayer, bool use_terrain_fitted_coords, bool use_moisture, int level, const amrex::BCRec *bc_ptr, bool, const std::unique_ptr< amrex::MultiFab > &z_phys_nd, const std::unique_ptr< amrex::MultiFab > &z_phys_cc, const MoistureComponentIndices &moisture_indices, const amrex::MultiFab *terrain_blank=nullptr)
 
void ComputeDiffusivityYSUNew (const amrex::MultiFab &xvel, const amrex::MultiFab &yvel, const amrex::MultiFab &cons_in, amrex::MultiFab &eddyViscosity, const amrex::Geometry &geom, const TurbChoice &turbChoice, std::unique_ptr< SurfaceLayer > &SurfLayer, bool use_terrain_fitted_coords, bool use_moisture, int level, const amrex::BCRec *bc_ptr, bool, const std::unique_ptr< amrex::MultiFab > &z_phys_nd, const std::unique_ptr< amrex::MultiFab > &z_phys_cc, const MoistureComponentIndices &moisture_indices, const amrex::MultiFab *qheating_rates=nullptr, const amrex::MultiFab *terrain_blank=nullptr)
 
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real GetPBLStratVar (int i, int j, int k, const StratType strat, const amrex::Array4< const amrex::Real > &cell_data, const MoistureComponentIndices &moisture_indices)
 
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void ComputeVerticalDerivativesPBL (int i, int j, int k, const amrex::Array4< const amrex::Real > &uvel, const amrex::Array4< const amrex::Real > &vvel, const amrex::Array4< const amrex::Real > &cell_data, const int izmin, const int izmax, const PBLDerivativeDzInv &dz_inv, const bool c_ext_dir_on_zlo, const bool c_ext_dir_on_zhi, const bool u_ext_dir_on_zlo, const bool u_ext_dir_on_zhi, const bool v_ext_dir_on_zlo, const bool v_ext_dir_on_zhi, amrex::Real &dthetadz, amrex::Real &dudz, amrex::Real &dvdz, const MoistureComponentIndices &moisture_indices, const StratType strat=StratType::thetav)
 
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeVirtualTStarPBL (amrex::Real t_star, amrex::Real q_star, amrex::Real theta, amrex::Real qv, bool use_moisture)
 
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void ApplySurfaceLayerGradientsPBL (const PBLSurfaceLayerGradient &sl, amrex::Real &dthetadz, amrex::Real &dudz, amrex::Real &dvdz)
 
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeQKESourceTerms (int i, int j, int k, const amrex::Array4< const amrex::Real > &uvel, const amrex::Array4< const amrex::Real > &vvel, const amrex::Array4< const amrex::Real > &cell_data, const amrex::Array4< const amrex::Real > &cell_prim, const amrex::Array4< const amrex::Real > &K_turb, const amrex::Box &domain, const PBLDerivativeDzInv dz_inv, amrex::Real pbl_mynn_B1_l, const amrex::Real theta_mean, const MoistureComponentIndices &moisture_indices, bool c_ext_dir_on_zlo, bool c_ext_dir_on_zhi, bool u_ext_dir_on_zlo, bool u_ext_dir_on_zhi, bool v_ext_dir_on_zlo, bool v_ext_dir_on_zhi, const amrex::Array4< const amrex::Real > &tau13, const amrex::Array4< const amrex::Real > &tau23, const amrex::Array4< const amrex::Real > &hfx_z, const amrex::Array4< const amrex::Real > &qfx1_z, bool surface_layer_on_zlo)
 
void ApplyPBLHSmoothing (amrex::FArrayBox &pblh_fab, const amrex::Box &xybx_valid, const amrex::Real weight, const int passes, const amrex::Box &domain, const amrex::Periodicity &periodicity)
 Apply spatial smoothing to PBLH field using 5-point stencil. More...
 
std::unique_ptr< amrex::MultiFab > WidenForPBLH (const amrex::MultiFab &src, const int ng, const std::function< void(amrex::MultiFab &)> &fill)
 

Function Documentation

◆ ApplyPBLHSmoothing()

void ApplyPBLHSmoothing ( amrex::FArrayBox &  pblh_fab,
const amrex::Box &  xybx_valid,
const amrex::Real  weight,
const int  passes,
const amrex::Box &  domain,
const amrex::Periodicity &  periodicity 
)
inline

Apply spatial smoothing to PBLH field using 5-point stencil.

Applies a simple 5-point spatial averaging to reduce grid-to-grid noise in the diagnosed PBLH field. This is standard post-processing practice for discrete Rib-crossing detection as described in Seibert et al. (2000): "Review and intercomparison of operational methods for the determination of the mixing height", Atmospheric Environment, 34, 1001-1027.

Stencil: PBLH_smooth(i,j) = w * PBLH(i,j) + (1-w)/4 * [PBLH(i+-1,j) + PBLH(i,j+-1)]

The stencil reads one column outside the region it writes, so the result on a cell depends on columns that a single tile – or a single box – does not own. The caller therefore names the region it wants smoothed (xybx_valid, normally the planar tile box) inside a work array carrying passes columns of halo around it, filled from the same inputs. Pass p writes the region grown by passes-1-p and reads the one grown by passes-p, so each pass consumes one column of halo and the last lands exactly on xybx_valid. Every read stays inside the array, and the result does not depend on how the domain is divided into boxes or tiles.

At a non-periodic domain edge there is no column to read, so the stencil reuses the cell's own value (reflective/Neumann). Across a periodic edge the halo holds the wrapped columns and is read directly, which is why the periodicity has to be passed in: clamping there would fold an edge into a domain that has none.

Parameters
[in,out]pblh_fabFArrayBox holding the 2D PBLH field (component 0), sized to contain xybx_valid grown by passes in x and y
[in]xybx_validRegion to smooth (x,y indices only)
[in]weightCenter cell weight in stencil (must be in [0,1])
[in]passesNumber of smoothing iterations
[in]domainDomain box, for the reflective edge condition
[in]periodicityDomain periodicity, so periodic edges read the halo
728 {
729  if (passes <= 0) { return; }
730 
731  // The caller must supply the halo the passes will consume; see the note above.
733  pblh_fab.box().contains(amrex::grow(xybx_valid, amrex::IntVect(passes,passes,0))),
734  "ApplyPBLHSmoothing: the PBLH work array needs `passes` columns of halo "
735  "around the region being smoothed");
736 
737  // Use a temporary to hold intermediate results
738  amrex::FArrayBox pblh_temp(pblh_fab.box(), 1, amrex::The_Async_Arena());
739  auto pblh = pblh_fab.array();
740  auto pblh_tmp = pblh_temp.array();
741 
742  const auto& dom_lo = amrex::lbound(domain);
743  const auto& dom_hi = amrex::ubound(domain);
744 
745  const bool per_x = periodicity.isPeriodic(0);
746  const bool per_y = periodicity.isPeriodic(1);
747 
748  const amrex::Real wt_side = (one - weight) / four; // Weight for each of 4 neighbors
749 
750  // Apply smoothing passes
751  for (int pass = 0; pass < passes; ++pass) {
752  const int halo = passes - 1 - pass;
753  const amrex::Box bx = amrex::grow(xybx_valid, amrex::IntVect(halo,halo,0));
754 
755  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int) noexcept
756  {
757  // Reflective (Neumann) at a non-periodic domain edge: reuse the cell's
758  // own value. Everywhere else -- including across a periodic edge, where
759  // the halo holds the wrapped column -- read the neighbour.
760  const int i_xlo = (per_x || i > dom_lo.x) ? (i - 1) : i;
761  const int i_xhi = (per_x || i < dom_hi.x) ? (i + 1) : i;
762  const int j_ylo = (per_y || j > dom_lo.y) ? (j - 1) : j;
763  const int j_yhi = (per_y || j < dom_hi.y) ? (j + 1) : j;
764 
765  // 5-point stencil
766  pblh_tmp(i, j, 0) = weight * pblh(i, j, 0)
767  + wt_side * (pblh(i_xlo, j, 0) + pblh(i_xhi, j, 0) +
768  pblh(i, j_ylo, 0) + pblh(i, j_yhi, 0));
769  });
770 
771  // Copy back only what this pass computed: outside bx the array still holds
772  // the previous pass, which no later pass reads.
773  pblh_fab.copy<amrex::RunOn::Device>(pblh_temp, bx, 0, bx, 0, 1);
774  }
775 }
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(axis >=0 &&axis< AMREX_SPACEDIM, "prob.axis must be 0, 1 or 2")
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);})
constexpr amrex::Real four
Definition: ERF_NumericalConstants.H:40
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:37
amrex::Real Real
Definition: ERF_ShocInterface.H:19

Referenced by ComputeDiffusivityMRF(), and ComputeDiffusivityYSUNew().

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

◆ ApplySurfaceLayerGradientsPBL()

AMREX_GPU_DEVICE AMREX_FORCE_INLINE void ApplySurfaceLayerGradientsPBL ( const PBLSurfaceLayerGradient &  sl,
amrex::Real &  dthetadz,
amrex::Real &  dudz,
amrex::Real &  dvdz 
)

Overwrite the vertical gradients in the first cell above the surface with the MOST profile gradients, |dU/dz| = u_* phi_m(zeta) / (kappa z) dthetav/dz = thetav_* phi_h(zeta) / (kappa z)

With zlo.type = surface_layer the state carries foextrap and the velocities hoextrap at the lower boundary, so the centered stencil in ComputeVerticalDerivativesPBL reads ghost values that hold no surface information there: the potential-temperature gradient comes out half the one-sided value and the velocity gradient has no dependence on the friction velocity at all (ERF #4037). The MOST profile used here is the one the surface stress and heat flux were themselves derived from.

Every PBL scheme that consumes these gradients uses only the shear magnitude dudz^2 + dvdz^2, so that magnitude is carried in dudz and dvdz is left at zero rather than being split by wind direction.

Parameters
[in]slMonin-Obukhov inputs for this column
[out]dthetadzvertical derivative of virtual potential temperature
[out]dudzvertical derivative of x-velocity (carries the shear magnitude)
[out]dvdzvertical derivative of y-velocity (set to zero)
432 {
433  const similarity_funs sfuns{};
434  const amrex::Real inv_kappa_z = one / (KAPPA * sl.zval);
435  dudz = sl.u_star * sfuns.calc_phi_m(sl.zeta) * inv_kappa_z;
436  dvdz = zero;
437  dthetadz = sl.tstar_v * sfuns.calc_phi_h(sl.zeta) * inv_kappa_z;
438 }
constexpr amrex::Real KAPPA
Definition: ERF_Constants.H:71
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:36
amrex::Real tstar_v
virtual temperature scale
Definition: ERF_PBLModels.H:373
amrex::Real zeta
stability coordinate z/L
Definition: ERF_PBLModels.H:375
amrex::Real u_star
friction velocity
Definition: ERF_PBLModels.H:372
amrex::Real zval
height of the cell center above the surface
Definition: ERF_PBLModels.H:374
Definition: ERF_MOSTUtils.H:67

Referenced by ComputeDiffusivityMYJ(), ComputeDiffusivityMYNN25(), ComputeDiffusivityMYNNEDMF(), ComputeDiffusivityYSU(), and ComputeDiffusivityYSUNew().

Here is the caller graph for this function:

◆ ComputeDiffusivityMRF()

void ComputeDiffusivityMRF ( const amrex::MultiFab &  xvel,
const amrex::MultiFab &  yvel,
const amrex::MultiFab &  cons_in,
amrex::MultiFab &  eddyViscosity,
const amrex::Geometry &  geom,
const TurbChoice &  turbChoice,
std::unique_ptr< SurfaceLayer > &  SurfLayer,
bool  use_terrain_fitted_coords,
bool  use_moisture,
int  level,
const amrex::BCRec *  bc_ptr,
bool  ,
const std::unique_ptr< amrex::MultiFab > &  z_phys_nd,
const std::unique_ptr< amrex::MultiFab > &  z_phys_cc,
const MoistureComponentIndices &  moisture_indices,
const amrex::MultiFab *  terrain_blank = nullptr 
)

Compute eddy diffusivities of momentum (eddy viscosity) and heat using the Medium Range Forecast (MRF) boundary layer scheme based on Hong and Pan (1996). Reference: Hong, S. Y., and H.-L. Pan, 1996: Nonlocal Boundary Layer Vertical Diffusion in a Medium-Range Forecast Model. Monthly Weather Review, 124, 2322-2339. https://doi.org/10.1175/1520-0493(1996)124<2322:NBLVDI>2.0.CO;2

Parameters
[in]xvelVelocity in x-dir
[in]yvelVelocity in y-dir
[in]cons_inCell center conserved quantities
[out]eddyViscosityHolds turbulent viscosity
[in]geomProblem geometry
[in]turbChoiceContainer with turbulence parameters
[in]SurfLayerPointer to Monin-Obukhov class if instantiated
[in]use_moistureIf we have microphysics enabled
[in]levelCurrent level
[in]bc_ptrPointer to array with boundary condition info
[in]vert_onlyOnly compute vertical eddy diffusivities
[in]z_phys_ndPhysical location of grid nodes, if terrain (or grid stretching) is enabled
[in]z_phys_ccPhysical location of cell centers

◆ ComputeDiffusivityMYJ()

void ComputeDiffusivityMYJ ( double  dt,
const amrex::MultiFab &  xvel,
const amrex::MultiFab &  yvel,
amrex::MultiFab &  cons_in,
amrex::MultiFab &  eddyViscosity,
const amrex::Geometry &  geom,
const TurbChoice &  turbChoice,
std::unique_ptr< SurfaceLayer > &  SurfLayer,
bool  use_terrain_fitted_coords,
bool  use_moisture,
int  level,
const amrex::BCRec *  bc_ptr,
bool  ,
const std::unique_ptr< amrex::MultiFab > &  z_phys_nd,
const std::unique_ptr< amrex::MultiFab > &  z_phys_cc,
const MoistureComponentIndices &  moisture_indices 
)

Compute eddy diffusivities of momentum (eddy viscosity) and heat using the Mellor-Yamada-Janjić (MYJ) boundary layer scheme. Reference: Janjić, Z. I., 1994: The Step-Mountain Eta Coordinate Model: Further Developments of the Convection, Viscous Sublayer, and Turbulence Closure Schemes. Monthly Weather Review, 122, 927–945. https://doi.org/10.1175/1520-0493(1994)122<0927:TSMECM>2.0.CO;2

Parameters
[in]xvelVelocity in x-dir
[in]yvelVelocity in y-dir
[in]cons_inCell center conserved quantities
[out]eddyViscosityHolds turbulent viscosity
[in]geomProblem geometry
[in]turbChoiceContainer with turbulence parameters
[in]SurfLayerPointer to Monin-Obukhov class if instantiated
[in]use_moistureIf we have microphysics enabled
[in]levelCurrent level
[in]bc_ptrPointer to array with boundary condition info
[in]vert_onlyOnly compute vertical eddy diffusivities
[in]z_phys_ndPhysical location of grid nodes, if terrain (or grid stretching) is enabled
[in]z_phys_ccPhysical location of cell centers

◆ ComputeDiffusivityMYNN25()

void ComputeDiffusivityMYNN25 ( const amrex::MultiFab &  xvel,
const amrex::MultiFab &  yvel,
const amrex::MultiFab &  cons_in,
amrex::MultiFab &  eddyViscosity,
const amrex::Geometry &  geom,
const TurbChoice &  turbChoice,
std::unique_ptr< SurfaceLayer > &  SurfLayer,
bool  use_terrain_fitted_coords,
bool  use_moisture,
int  level,
const amrex::BCRec *  bc_ptr,
bool  ,
const std::unique_ptr< amrex::MultiFab > &  z_phys_nd,
const std::unique_ptr< amrex::MultiFab > &  z_phys_cc,
const MoistureComponentIndices &  moisture_indices 
)

Compute eddy diffusivities of momentum (eddy viscosity) and heat using the Mellor-Yamada-Nakanishi-Niino Level amrex::Real(2.5) PBL scheme

Parameters
[in]xvelVelocity in x-dir
[in]yvelVelocity in y-dir
[in]cons_inCell center conserved quantities
[out]eddyViscosityHolds turbulent viscosity
[in]geomProblem geometry
[in]turbChoiceContainer with turbulence parameters
[in]SurfLayerPointer to Monin-Obukhov class if instantiated
[in]use_moistureIf we have microphysics enabled
[in]levelCurrent level
[in]bc_ptrPointer to array with boundary condition info
[in]vert_onlyOnly compute vertical eddy diffusivities
[in]z_phys_ndPhysical location of grid nodes, if terrain (or grid stretching) is enabled
[in]z_phys_ccPhysical location of cell centers

◆ ComputeDiffusivityMYNNEDMF()

void ComputeDiffusivityMYNNEDMF ( const amrex::MultiFab &  xvel,
const amrex::MultiFab &  yvel,
const amrex::MultiFab &  cons_in,
amrex::MultiFab &  eddyViscosity,
const amrex::Geometry &  geom,
const TurbChoice &  turbChoice,
std::unique_ptr< SurfaceLayer > &  SurfLayer,
bool  use_terrain_fitted_coords,
bool  use_moisture,
int  level,
const amrex::BCRec *  bc_ptr,
bool  ,
const std::unique_ptr< amrex::MultiFab > &  z_phys_nd,
const std::unique_ptr< amrex::MultiFab > &  z_phys_cc,
const MoistureComponentIndices &  moisture_indices 
)

Compute eddy diffusivities of momentum (eddy viscosity) and heat using the Mellor-Yamada-Nakanishi-Niino Level amrex::Real(2.5) PBL scheme

Parameters
[in]xvelVelocity in x-dir
[in]yvelVelocity in y-dir
[in]cons_inCell center conserved quantities
[out]eddyViscosityHolds turbulent viscosity
[in]geomProblem geometry
[in]turbChoiceContainer with turbulence parameters
[in]SurfLayerPointer to Monin-Obukhov class if instantiated
[in]use_moistureIf we have microphysics enabled
[in]levelCurrent level
[in]bc_ptrPointer to array with boundary condition info
[in]vert_onlyOnly compute vertical eddy diffusivities
[in]z_phys_ndPhysical location of grid nodes, if terrain (or grid stretching) is enabled
[in]z_phys_ccPhysical location of cell centers

◆ ComputeDiffusivityYSU()

void ComputeDiffusivityYSU ( const amrex::MultiFab &  xvel,
const amrex::MultiFab &  yvel,
const amrex::MultiFab &  cons_in,
amrex::MultiFab &  eddyViscosity,
const amrex::Geometry &  geom,
const TurbChoice &  turbChoice,
std::unique_ptr< SurfaceLayer > &  SurfLayer,
bool  use_terrain_fitted_coords,
bool  use_moisture,
int  level,
const amrex::BCRec *  bc_ptr,
bool  ,
const std::unique_ptr< amrex::MultiFab > &  z_phys_nd,
const std::unique_ptr< amrex::MultiFab > &  z_phys_cc,
const MoistureComponentIndices &  moisture_indices 
)

Compute eddy diffusivities of momentum (eddy viscosity) and heat using the Yonsei University PBL scheme

Parameters
[in]xvelVelocity in x-dir
[in]yvelVelocity in y-dir
[in]cons_inCell center conserved quantities
[out]eddyViscosityHolds turbulent viscosity
[in]geomProblem geometry
[in]turbChoiceContainer with turbulence parameters
[in]SurfLayerPointer to Monin-Obukhov class if instantiated
[in]use_moistureIf we have microphysics enabled
[in]levelCurrent level
[in]bc_ptrPointer to array with boundary condition info
[in]vert_onlyOnly compute vertical eddy diffusivities
[in]z_phys_ndPhysical location of grid nodes, if terrain (or grid stretching) is enabled
[in]z_phys_ccPhysical location of cell centers

◆ ComputeDiffusivityYSUNew()

void ComputeDiffusivityYSUNew ( const amrex::MultiFab &  xvel,
const amrex::MultiFab &  yvel,
const amrex::MultiFab &  cons_in,
amrex::MultiFab &  eddyViscosity,
const amrex::Geometry &  geom,
const TurbChoice &  turbChoice,
std::unique_ptr< SurfaceLayer > &  SurfLayer,
bool  use_terrain_fitted_coords,
bool  use_moisture,
int  level,
const amrex::BCRec *  bc_ptr,
bool  ,
const std::unique_ptr< amrex::MultiFab > &  z_phys_nd,
const std::unique_ptr< amrex::MultiFab > &  z_phys_cc,
const MoistureComponentIndices &  moisture_indices,
const amrex::MultiFab *  qheating_rates = nullptr,
const amrex::MultiFab *  terrain_blank = nullptr 
)

Compute eddy diffusivities of momentum (eddy viscosity) and heat using the WRF Yonsei University (YSU) PBL scheme.

Based on: Hong, Noh & Dudhia (2006), MWR, https://doi.org/10.1175/MWR3250.1 Hong (2010), QJRMS, https://doi.org/10.1002/qj.665

Features: three-pass bulk-Richardson PBLH diagnosis, nonlocal countergradient fluxes, explicit entrainment at PBL top, and grid-adaptive Richardson-number mixing in free atmosphere.

Parameters
[in]xvelx-direction velocity
[in]yvely-direction velocity
[in]cons_incell-center conserved quantities
[out]eddyViscosityturbulent eddy viscosity
[in]geomproblem geometry
[in]turbChoiceturbulence parameter container
[in]SurfLayerMonin-Obukhov surface layer object
[in]use_terrain_fitted_coordsflag for terrain coordinates
[in]use_moistureflag for moisture active
[in]levelAMR level
[in]bc_ptrboundary condition array
[in]vert_onlycompute vertical diffusivity only
[in]z_phys_ndphysical node heights (terrain)
[in]z_phys_ccphysical cell-center heights
[in]moisture_indicescomponent index mapping for moisture variables
[in]qheating_ratesradiation heating rates (SW, LW components); optional

◆ ComputeQKESourceTerms()

AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeQKESourceTerms ( int  i,
int  j,
int  k,
const amrex::Array4< const amrex::Real > &  uvel,
const amrex::Array4< const amrex::Real > &  vvel,
const amrex::Array4< const amrex::Real > &  cell_data,
const amrex::Array4< const amrex::Real > &  cell_prim,
const amrex::Array4< const amrex::Real > &  K_turb,
const amrex::Box &  domain,
const PBLDerivativeDzInv  dz_inv,
amrex::Real  pbl_mynn_B1_l,
const amrex::Real  theta_mean,
const MoistureComponentIndices &  moisture_indices,
bool  c_ext_dir_on_zlo,
bool  c_ext_dir_on_zhi,
bool  u_ext_dir_on_zlo,
bool  u_ext_dir_on_zhi,
bool  v_ext_dir_on_zlo,
bool  v_ext_dir_on_zhi,
const amrex::Array4< const amrex::Real > &  tau13,
const amrex::Array4< const amrex::Real > &  tau23,
const amrex::Array4< const amrex::Real > &  hfx_z,
const amrex::Array4< const amrex::Real > &  qfx1_z,
bool  surface_layer_on_zlo 
)

Function for computing the QKE source terms (NN09, Eqn. 5).

Parameters
[in]uvelocity in x-dir
[in]vvelocity in y-dir
[in]cell_dataconserved cell center vars
[in]cell_primprimitive cell center vars
[in]K_turbturbulent viscosity
[in]domainbox of the whole domain
[in]dz_invinverse spacings for interior and Dirichlet-boundary differences
[in]pbl_mynn_B1_la parameter
[in]theta_meanaverage theta
[in]moisture_indicesmoisture variable component indices
[in]tau13rho<u'w'> on z-faces; the surface-layer stress at the zlo face
[in]tau23rho<v'w'> on z-faces; the surface-layer stress at the zlo face
[in]hfx_zrho<w'theta'> on z-faces; the surface-layer heat flux at the zlo face
[in]qfx1_zrho<w'qv'> on z-faces; the surface-layer moisture flux at the zlo face
[in]surface_layer_on_zloa SurfaceLayer supplies the fluxes through the zlo face
484 {
485  amrex::Real source_term = zero;
486 
487  int izmin = domain.smallEnd(2);
488  int izmax = domain.bigEnd(2);
489 
490  const amrex::Real rho = cell_data(i,j,k,Rho_comp);
491 
492  // Notes:
493  // - We transport TKE = myhalf*QKE rather than QKE, so the RHS terms do not
494  // have a factor of two.
495  // - Transport terms due to turbulence and pressure are included when
496  // DiffusionSrcForState_* is called from ERF_slow_rhs_post.
497  // - Eddy diffusivities are updated at the beginning of each time step only.
498 
499  const bool use_surface_fluxes = ( surface_layer_on_zlo && (k == izmin) &&
500  tau13 && tau23 && hfx_z );
501 
502  if (use_surface_fluxes)
503  {
504  // The first cell center lies inside the unresolved surface layer. With
505  // zlo.type = surface_layer the state carries foextrap and the velocities
506  // hoextrap at the lower boundary, so the stencil used below reads ghost
507  // values that hold no surface information: the resolved gradients there
508  // are not a discretization of anything (ERF #4037). Build the production
509  // terms from the fluxes the model actually carries instead:
510  //
511  // tau13, tau23 = rho<u'w'>, rho<v'w'> (z-faces, staggered in x,y)
512  // hfx_z, qfx1_z = rho<w'theta'>, rho<w'qv'> (z-faces)
513  //
514  // Two different heights are wanted here, so the two are kept apart:
515  // - u_*, thetav_* and L are surface-layer parameters and have no
516  // cell-centered counterpart, so they come from the zlo face alone;
517  // - the production terms belong at the cell center, so their flux
518  // factors average the two z-faces bounding this cell.
519  // Only the profile shape, phi(zeta_1)/(kappa z_1), ties the two together.
520 
521  const amrex::Real theta = cell_data(i,j,k,RhoTheta_comp) / rho;
522  const amrex::Real qv = (moisture_indices.qv >= 0) ?
523  cell_data(i,j,k,moisture_indices.qv) / rho : zero;
524 
525  // ---- Surface-layer parameters, on the zlo face ----
526 
527  // |tau|/rho = u_*^2
528  const amrex::Real t13_s = myhalf * ( tau13(i,j,k) + tau13(i+1,j,k) );
529  const amrex::Real t23_s = myhalf * ( tau23(i,j,k) + tau23(i,j+1,k) );
530  const amrex::Real tau_s = std::sqrt(t13_s*t13_s + t23_s*t23_s);
531  const amrex::Real ustar2 = tau_s / rho;
532  const amrex::Real ustar = std::sqrt(ustar2);
533 
534  // Surface virtual heat flux rho<w'theta_v'> (Stull Eqn. 4.4.5d)
535  amrex::Real hfxv_s = hfx_z(i,j,k) * (one + epsv*qv);
536  if (qfx1_z) { hfxv_s += epsv * theta * qfx1_z(i,j,k); }
537 
538  // Height of this cell center above the surface. dz_inv.dirichlet_lo is by
539  // construction the inverse of the boundary-to-first-center distance, so it
540  // carries the right height for uniform, stretched and terrain-fitted grids.
541  const amrex::Real z1 = one / dz_inv.dirichlet_lo;
542 
543  // Obukhov length, from the surface fluxes. A vanishing stress (a building
544  // face, say) leaves the shear production zero whatever zeta is, so the
545  // neutral value is the safe one to carry into phi_m there.
546  const amrex::Real thetav = theta * (one + epsv*qv);
548  amrex::Real zeta = zero;
549  if (std::abs(hfxv_s) > eps && ustar > eps) {
550  const amrex::Real l_obukhov = -( thetav * rho * ustar2 * ustar )
551  / ( KAPPA * CONST_GRAV * hfxv_s );
552  zeta = z1 / l_obukhov;
553  }
554 
555  // phi_m, the companion of the psi_m that SurfaceLayer uses
556  const similarity_funs sfuns{};
557  const amrex::Real phi_m = sfuns.calc_phi_m(zeta);
558 
559  // ---- Production terms, at the cell center ----
560 
561  // Cell-centered stress: average the two z-faces bounding this cell
562  const amrex::Real t13_c = fourth * ( tau13(i,j,k ) + tau13(i+1,j,k )
563  + tau13(i,j,k+1) + tau13(i+1,j,k+1) );
564  const amrex::Real t23_c = fourth * ( tau23(i,j ,k) + tau23(i,j ,k+1)
565  + tau23(i,j+1,k) + tau23(i,j+1,k+1) );
566 
567  // Cell-centered virtual heat flux. Both faces are from this stage: the
568  // QKE sources are added after RhoQ1 is diffused (see AddTurbKESources).
569  amrex::Real hfxv_c = myhalf * ( hfx_z(i,j,k) + hfx_z(i,j,k+1) ) * (one + epsv*qv);
570  if (qfx1_z) {
571  hfxv_c += epsv * theta * myhalf * ( qfx1_z(i,j,k) + qfx1_z(i,j,k+1) );
572  }
573 
574  // Shear production, -<u'w'> dU/dz - <v'w'> dV/dz. MOST sets the direction
575  // of the mean shear anti-parallel to the surface stress and its magnitude
576  // to u_* phi_m/(kappa z_1), so the dot product is the cell-centered stress
577  // projected onto the surface stress. This reduces to |tau| u_* phi_m /
578  // (kappa z_1) when the stress does not turn across the cell.
579  if (tau_s > eps) {
580  const amrex::Real tau_proj = (t13_c*t13_s + t23_c*t23_s) / tau_s;
581  source_term += std::max(tau_proj,amrex::Real(0.)) * ustar * phi_m / (KAPPA * z1);
582  }
583 
584  // Buoyancy production, which needs no gradient at all
585  source_term += (CONST_GRAV/theta_mean) * hfxv_c;
586  }
587  else
588  {
589  // Compute some relevant derivatives
590  amrex::Real dthetadz, dudz, dvdz;
592  uvel, vvel, cell_data, izmin, izmax, dz_inv,
593  c_ext_dir_on_zlo, c_ext_dir_on_zhi,
594  u_ext_dir_on_zlo, u_ext_dir_on_zhi,
595  v_ext_dir_on_zlo, v_ext_dir_on_zhi,
596  dthetadz, dudz, dvdz,
597  moisture_indices);
598 
599  // Second-order turbulent fluxes, e.g.:
600  // -<uw> = L q SM dU/dz (NN09, Eqn. 18)
601  // = Kmv/rho dU/dz
602 
603  // Shear Production
604  source_term += K_turb(i,j,k,EddyDiff::Mom_v) * (dudz*dudz + dvdz*dvdz);
605 
606  // Buoyancy Production
607  source_term -= (CONST_GRAV/theta_mean)*K_turb(i,j,k,EddyDiff::Theta_v)*dthetadz;
608  }
609 
610  // Dissipation (NN09, Eqn. 12)
611  amrex::Real qke = two * cell_prim(i,j,k,PrimKE_comp);
612  if (std::abs(qke) > zero) {
613  source_term -= rho * std::pow(qke,amrex::Real(1.5)) /
614  (pbl_mynn_B1_l * K_turb(i,j,k,EddyDiff::Turb_lengthscale));
615  }
616 
617  return source_term;
618 }
constexpr amrex::Real epsv
Definition: ERF_Constants.H:56
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:72
@ tau23
Definition: ERF_DataStruct.H:49
@ tau13
Definition: ERF_DataStruct.H:49
#define Rho_comp
Definition: ERF_IndexDefines.H:53
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:54
#define PrimKE_comp
Definition: ERF_IndexDefines.H:80
constexpr amrex::Real two
Definition: ERF_NumericalConstants.H:38
constexpr amrex::Real fourth
Definition: ERF_NumericalConstants.H:42
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:41
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void ComputeVerticalDerivativesPBL(int i, int j, int k, const amrex::Array4< const amrex::Real > &uvel, const amrex::Array4< const amrex::Real > &vvel, const amrex::Array4< const amrex::Real > &cell_data, const int izmin, const int izmax, const PBLDerivativeDzInv &dz_inv, const bool c_ext_dir_on_zlo, const bool c_ext_dir_on_zhi, const bool u_ext_dir_on_zlo, const bool u_ext_dir_on_zhi, const bool v_ext_dir_on_zlo, const bool v_ext_dir_on_zhi, amrex::Real &dthetadz, amrex::Real &dudz, amrex::Real &dvdz, const MoistureComponentIndices &moisture_indices, const StratType strat=StratType::thetav)
Definition: ERF_PBLModels.H:309
@ Theta_v
Definition: ERF_IndexDefines.H:290
@ Turb_lengthscale
Definition: ERF_IndexDefines.H:294
@ Mom_v
Definition: ERF_IndexDefines.H:289
@ ustar
Definition: ERF_SLM.H:28
@ rho
Definition: ERF_Kessler.H:25
@ theta
Definition: ERF_Kessler.H:26
@ qv
Definition: ERF_Kessler.H:31
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12
int qv
water vapor
Definition: ERF_DataStruct.H:262
amrex::Real dirichlet_lo
Definition: ERF_PBLModels.H:257

Referenced by AddTurbKESources().

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

◆ ComputeVerticalDerivativesPBL()

AMREX_GPU_DEVICE AMREX_FORCE_INLINE void ComputeVerticalDerivativesPBL ( int  i,
int  j,
int  k,
const amrex::Array4< const amrex::Real > &  uvel,
const amrex::Array4< const amrex::Real > &  vvel,
const amrex::Array4< const amrex::Real > &  cell_data,
const int  izmin,
const int  izmax,
const PBLDerivativeDzInv &  dz_inv,
const bool  c_ext_dir_on_zlo,
const bool  c_ext_dir_on_zhi,
const bool  u_ext_dir_on_zlo,
const bool  u_ext_dir_on_zhi,
const bool  v_ext_dir_on_zlo,
const bool  v_ext_dir_on_zhi,
amrex::Real &  dthetadz,
amrex::Real &  dudz,
amrex::Real &  dvdz,
const MoistureComponentIndices &  moisture_indices,
const StratType  strat = StratType::thetav 
)
327 {
328  // ext_dir ghost values hold the value at the physical boundary, which is
329  // half a ghost-center spacing from the adjacent cell center. Use a
330  // two-point, first-order boundary-to-center difference with inverse
331  // distance 2/dz.
332  if ( k==izmax && c_ext_dir_on_zhi ) {
333  dthetadz = ( GetPBLStratVar(i,j,k+1,strat,cell_data,moisture_indices)
334  -GetPBLStratVar(i,j,k ,strat,cell_data,moisture_indices) )*dz_inv.dirichlet_hi;
335  } else if ( k==izmin && c_ext_dir_on_zlo ) {
336  dthetadz = ( GetPBLStratVar(i,j,k ,strat,cell_data,moisture_indices)
337  -GetPBLStratVar(i,j,k-1,strat,cell_data,moisture_indices) )*dz_inv.dirichlet_lo;
338  } else {
339  dthetadz = ( GetPBLStratVar(i,j,k+1,strat,cell_data,moisture_indices)
340  -GetPBLStratVar(i,j,k-1,strat,cell_data,moisture_indices) )*dz_inv.interior;
341  }
342 
343  if ( k==izmax && u_ext_dir_on_zhi ) {
344  dudz = myhalf*( uvel(i ,j,k+1) - uvel(i ,j,k)
345  +uvel(i+1,j,k+1) - uvel(i+1,j,k) )*dz_inv.dirichlet_hi;
346  } else if ( k==izmin && u_ext_dir_on_zlo ) {
347  dudz = myhalf*( uvel(i ,j,k) - uvel(i ,j,k-1)
348  +uvel(i+1,j,k) - uvel(i+1,j,k-1) )*dz_inv.dirichlet_lo;
349  } else {
350  dudz = myhalf*( uvel(i ,j,k+1) - uvel(i ,j,k-1)
351  +uvel(i+1,j,k+1) - uvel(i+1,j,k-1) )*dz_inv.interior;
352  }
353 
354  if ( k==izmax && v_ext_dir_on_zhi ) {
355  dvdz = myhalf*( vvel(i,j ,k+1) - vvel(i,j ,k)
356  +vvel(i,j+1,k+1) - vvel(i,j+1,k) )*dz_inv.dirichlet_hi;
357  } else if ( k==izmin && v_ext_dir_on_zlo ) {
358  dvdz = myhalf*( vvel(i,j ,k) - vvel(i,j ,k-1)
359  +vvel(i,j+1,k) - vvel(i,j+1,k-1) )*dz_inv.dirichlet_lo;
360  } else {
361  dvdz = myhalf*( vvel(i,j ,k+1) - vvel(i,j ,k-1)
362  +vvel(i,j+1,k+1) - vvel(i,j+1,k-1) )*dz_inv.interior;
363  }
364 }
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real GetPBLStratVar(int i, int j, int k, const StratType strat, const amrex::Array4< const amrex::Real > &cell_data, const MoistureComponentIndices &moisture_indices)
Definition: ERF_PBLModels.H:293
amrex::Real dirichlet_hi
Definition: ERF_PBLModels.H:258
amrex::Real interior
Definition: ERF_PBLModels.H:256

Referenced by ComputeDiffusivityMRF(), ComputeDiffusivityMYJ(), ComputeDiffusivityMYNN25(), ComputeDiffusivityMYNNEDMF(), ComputeDiffusivityYSU(), ComputeDiffusivityYSUNew(), and ComputeQKESourceTerms().

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

◆ ComputeVirtualTStarPBL()

AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real ComputeVirtualTStarPBL ( amrex::Real  t_star,
amrex::Real  q_star,
amrex::Real  theta,
amrex::Real  qv,
bool  use_moisture 
)

Virtual temperature scale, thetav_* = theta_*(1 + epsv qv) + epsv theta q_*. The surface virtual heat flux is <w'thetav'> = -u_* thetav_*.

Parameters
[in]t_startemperature scale
[in]q_starmoisture scale
[in]thetapotential temperature
[in]qvwater vapor mixing ratio
[in]use_moisturewhether the moisture term is active
396 {
397  amrex::Real tstar_v = t_star * (one + epsv*qv);
398  if (use_moisture) { tstar_v += epsv * theta * q_star; }
399  return tstar_v;
400 }
const bool use_moisture
Definition: ERF_InitCustomPert_ABL.H:71

Referenced by ComputeDiffusivityMYJ(), ComputeDiffusivityMYNN25(), ComputeDiffusivityMYNNEDMF(), ComputeDiffusivityYSU(), and ComputeDiffusivityYSUNew().

Here is the caller graph for this function:

◆ GetPBLStratVar()

AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real GetPBLStratVar ( int  i,
int  j,
int  k,
const StratType  strat,
const amrex::Array4< const amrex::Real > &  cell_data,
const MoistureComponentIndices &  moisture_indices 
)

Compute vertical derivatives of potential temperature and velocity for PBL models.

Parameters
ix-index
jy-index
kz-index
[in]uvelx-velocity
[in]vvely-velocity
[in]cell_dataconserved cell-center variables
[in]izminlower z-index limit
[in]izmaxupper z-index limit
[in]dz_invinverse physical distance spacings
[in]c_ext_dir_on_zloDirichlet condition on z-low face for cell data
[in]c_ext_dir_on_zhiDirichlet condition on z-high face for cell data
[in]u_ext_dir_on_zloDirichlet condition on z-low face for u-velocity
[in]u_ext_dir_on_zhiDirichlet condition on z-high face for u-velocity
[in]v_ext_dir_on_zloDirichlet condition on z-low face for v-velocity
[in]v_ext_dir_on_zhiDirichlet condition on z-high face for v-velocity
[out]dthetadzcomputed vertical derivative of potential temperature
[out]dudzcomputed vertical derivative of x-velocity
[out]dvdzcomputed vertical derivative of y-velocity
[in]moisture_indicesmoisture variable component indices Thermodynamic variable whose vertical gradient the PBL schemes use for buoyancy, selected by erf.thermal_stratification.
[in]stratstratification variable to return
297 {
298  if (strat == StratType::theta) {
299  return cell_data(i,j,k,RhoTheta_comp) / cell_data(i,j,k,Rho_comp);
300  } else if (strat == StratType::thetal) {
301  return GetThetal(i,j,k,cell_data,moisture_indices);
302  }
303  return GetThetav(i,j,k,cell_data,moisture_indices);
304 }
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real GetThetav(const int &i, const int &j, const int &k, const amrex::Array4< amrex::Real const > &cell_data, const MoistureComponentIndices &moisture_indices)
Definition: ERF_MoistUtils.H:93
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real GetThetal(const int &i, const int &j, const int &k, const amrex::Array4< amrex::Real const > &cell_data, const MoistureComponentIndices &moisture_indices)
Definition: ERF_MoistUtils.H:127

Referenced by ComputeVerticalDerivativesPBL().

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

◆ WidenForPBLH()

std::unique_ptr<amrex::MultiFab> WidenForPBLH ( const amrex::MultiFab &  src,
const int  ng,
const std::function< void(amrex::MultiFab &)> &  fill 
)
inline

Copy of a field read by the PBLH passes, widened to ng horizontal ghost cells.

With erf.pblh_smoothing_passes = n the PBLH passes read their inputs n columns outside the tile (see ApplyPBLHSmoothing), but some of those inputs carry fewer ghost cells: the surface-layer fields have one on the bottom surface. The PBL schemes read such fields from a copy made here instead.

The valid cells and the field's own ghost cells are copied unchanged, so a run that needs no more halo than the field has gives the same answer as reading the field itself. fill then fills the new ghost cells that a box of the level covers, inside the domain or across a periodic edge, the same way the field's owner fills its own (for a surface-layer field, SurfaceLayer::fill_planar_boundary). Ghost cells no box covers – outside a non-periodic domain edge, or next to a coarser level – take the value of the nearest cell of the field's original halo. The smoothing never reads a column outside a non-periodic edge; next to a coarser level this is a zeroth-order extrapolation of the surface scales, while the state there is the interpolated one.

Parameters
[in]srcField to widen
[in]ngGhost cells wanted in x and y; z keeps those of src
[in]fillCallable taking the widened MultiFab& and filling its ghost cells from the valid cells of the other boxes of the level

fill is a std::function, not a template parameter: nvcc does not accept the device lambda below inside a function template instantiated with a lambda local to the caller.

807 {
808  const amrex::IntVect ng_src = src.nGrowVect();
809  const amrex::IntVect ng_dst(ng, ng, ng_src[2]);
810  const int ncomp = src.nComp();
811 
812  // A value no field holds, marking the cells nothing below fills
813  constexpr amrex::Real unset = std::numeric_limits<amrex::Real>::max();
814 
815  auto dst = std::make_unique<amrex::MultiFab>(src.boxArray(), src.DistributionMap(),
816  ncomp, ng_dst);
817  dst->setVal(unset);
818  amrex::MultiFab::Copy(*dst, src, 0, 0, ncomp, ng_src);
819  fill(*dst);
820 
821  for (amrex::MFIter mfi(*dst); mfi.isValid(); ++mfi) {
822  // The cells holding src's own data; never written below, so they can be read
823  const amrex::Box have = amrex::grow(mfi.validbox(), ng_src);
824  const auto lo = amrex::lbound(have);
825  const auto hi = amrex::ubound(have);
826  auto a = dst->array(mfi);
827  amrex::ParallelFor(mfi.fabbox(), [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
828  {
829  if (have.contains(i, j, k)) { return; }
830  const int ic = amrex::min(amrex::max(i, lo.x), hi.x);
831  const int jc = amrex::min(amrex::max(j, lo.y), hi.y);
832  for (int n = 0; n < ncomp; ++n) {
833  if (a(i, j, k, n) == unset) { a(i, j, k, n) = a(ic, jc, k, n); }
834  }
835  });
836  }
837  return dst;
838 }
for(int i=0;i< m_num_species;i++)
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:52
@ ng
Definition: ERF_Morrison.H:51
void fill(MultiFab &dst, int temperature_comp, int mixing_ratio_comp, int source_comp, const Sources &sources, Real missing_value)
Definition: ERF_NearSurfaceDiagnostics.cpp:42

Referenced by ComputeDiffusivityMRF(), and ComputeDiffusivityYSUNew().

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