ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_FirePrecip.H
Go to the documentation of this file.
1 #ifndef ERF_FIRE_PRECIP_H
2 #define ERF_FIRE_PRECIP_H
3 
4 #include <AMReX_GpuQualifiers.H>
5 #include <AMReX_MultiFab.H>
6 #include <AMReX_MFIter.H>
7 #include <AMReX_REAL.H>
9 
10 /**
11  * @file ERF_FirePrecip.H
12  * @brief Rain per column for the fuel moisture model from the microphysics
13  * surface precipitation accumulators, for an engine that reads the rain
14  * (FireEngine::wants_surface_precip).
15  *
16  * Every Eulerian microphysics scheme with precipitation keeps a cumulative
17  * surface accumulator per atmospheric column (Kessler's rain_accum, SAM's and
18  * Morrison's rain, snow and graupel accumulations, ...), exposed through
19  * Microphysics::Get_Surface_Precip_Accumulation_Ptrs() with a factor that
20  * turns the scheme's native unit into kg/m2 of liquid water. One kg/m2 of
21  * liquid water is one millimetre of depth, so the change of the accumulation
22  * over a step, divided by the step, is the rain rate in mm/hr that the
23  * time-lag and stick moisture updates take. The fire layer keeps the
24  * accumulation it saw at the end of its previous step (checkpointed) and
25  * forms that difference every step; a fresh start begins at zero, which is
26  * where every scheme starts its accumulators.
27  *
28  * Snow, graupel and hail count with their liquid-water equivalent: the fuel
29  * models have no frozen-precipitation branch. There is no canopy interception.
30  */
31 
32 /**
33  * @brief Rain rate [mm/hr] from the change of the surface accumulation over one step.
34  *
35  * @param[in] accum_now_kgm2 accumulation at the end of the step [kg/m2 == mm]
36  * @param[in] accum_prev_kgm2 accumulation at the end of the previous step [kg/m2]
37  * @param[in] dt_s the step [s]
38  * @return (now - prev) * 3600 / dt; zero for a non-positive step or a non-positive
39  * change (an accumulator that was reset, or round-off), and zero for NaN.
40  */
41 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
43  amrex::Real accum_prev_kgm2,
44  amrex::Real dt_s) noexcept
45 {
46  if (!(dt_s > amrex::Real(0.0))) { return amrex::Real(0.0); }
47  const amrex::Real d = accum_now_kgm2 - accum_prev_kgm2;
48  if (!(d > amrex::Real(0.0))) { return amrex::Real(0.0); }
49  return d * amrex::Real(3600.0) / dt_s;
50 }
51 
52 /**
53  * @brief Total liquid-water-equivalent surface precipitation accumulation [kg/m2]
54  * of every column, from the scheme-native accumulators.
55  *
56  * Fills accum_2d, a one-component MultiFab on the level's boxes coarsened to one
57  * cell in z (box n of accum_2d is box n of the accumulators, with the same
58  * owner), from the k = klo plane of the sources. Schemes that provide a total
59  * give it directly; schemes that provide the species give their sum, so
60  * nothing is counted twice (the same rule as the 2D plotfile precipitation
61  * diagnostics). Without any source the field is zero.
62  */
63 inline void fire_surface_precip_accum_k0 (amrex::MultiFab& accum_2d,
64  const SurfacePrecipAccumulationSources& sources,
65  int klo)
66 {
67  using namespace amrex;
68  accum_2d.setVal(Real(0.0));
69  if (!surface_precip_has_any_source(sources)) { return; }
70 
71  const bool has_total = surface_precip_has_source(sources.total);
72  const bool has_rain = surface_precip_has_source(sources.rain);
73  const bool has_snow = surface_precip_has_source(sources.snow);
74  const bool has_graupel = surface_precip_has_source(sources.graupel);
75  const bool has_hail = surface_precip_has_source(sources.hail);
76  const Real f_total = sources.total.native_to_kg_m2;
77  const Real f_rain = sources.rain.native_to_kg_m2;
78  const Real f_snow = sources.snow.native_to_kg_m2;
79  const Real f_graupel = sources.graupel.native_to_kg_m2;
80  const Real f_hail = sources.hail.native_to_kg_m2;
81 
82  for (MFIter mfi(accum_2d, false); mfi.isValid(); ++mfi) {
83  Array4<Real> a = accum_2d.array(mfi);
84  Array4<const Real> total = has_total ? sources.total.accum->const_array(mfi) : Array4<const Real>{};
85  Array4<const Real> rain = has_rain ? sources.rain.accum->const_array(mfi) : Array4<const Real>{};
86  Array4<const Real> snow = has_snow ? sources.snow.accum->const_array(mfi) : Array4<const Real>{};
87  Array4<const Real> graupel = has_graupel ? sources.graupel.accum->const_array(mfi) : Array4<const Real>{};
88  Array4<const Real> hail = has_hail ? sources.hail.accum->const_array(mfi) : Array4<const Real>{};
89  ParallelFor(mfi.tilebox(), [=] AMREX_GPU_DEVICE (const IntVect& iv) noexcept
90  {
91  const int i = iv[0], j = iv[1];
92  Real v;
93  if (has_total) {
94  v = total(i, j, klo) * f_total;
95  } else {
96  v = Real(0.0);
97  if (has_rain) { v += rain(i, j, klo) * f_rain; }
98  if (has_snow) { v += snow(i, j, klo) * f_snow; }
99  if (has_graupel) { v += graupel(i, j, klo) * f_graupel; }
100  if (has_hail) { v += hail(i, j, klo) * f_hail; }
101  }
102  a(i, j, 0) = v;
103  });
104  }
105 }
106 
107 /**
108  * @brief Rain rate [mm/hr] of every column over the step just taken, and roll
109  * the snapshot forward.
110  *
111  * rate_2d = fire_precip_rate_mm_hr(now, prev, dt) per column when prev_valid,
112  * zero otherwise (a restart from a checkpoint without the snapshot); then
113  * prev_2d = now_2d. All three MultiFabs share boxes and distribution.
114  */
115 inline void fire_precip_rate_from_accum (amrex::MultiFab& rate_2d,
116  amrex::MultiFab& prev_2d,
117  const amrex::MultiFab& now_2d,
118  amrex::Real dt_s,
119  bool prev_valid)
120 {
121  using namespace amrex;
122  for (MFIter mfi(rate_2d, false); mfi.isValid(); ++mfi) {
123  Array4<Real> r = rate_2d.array(mfi);
124  Array4<Real> p = prev_2d.array(mfi);
125  Array4<const Real> n = now_2d.const_array(mfi);
126  ParallelFor(mfi.tilebox(), [=] AMREX_GPU_DEVICE (const IntVect& iv) noexcept
127  {
128  const int i = iv[0], j = iv[1];
129  r(i, j, 0) = prev_valid ? fire_precip_rate_mm_hr(n(i, j, 0), p(i, j, 0), dt_s) : Real(0.0);
130  p(i, j, 0) = n(i, j, 0);
131  });
132  }
133 }
134 
135 #endif // ERF_FIRE_PRECIP_H
void fire_precip_rate_from_accum(amrex::MultiFab &rate_2d, amrex::MultiFab &prev_2d, const amrex::MultiFab &now_2d, amrex::Real dt_s, bool prev_valid)
Rain rate [mm/hr] of every column over the step just taken, and roll the snapshot forward.
Definition: ERF_FirePrecip.H:115
void fire_surface_precip_accum_k0(amrex::MultiFab &accum_2d, const SurfacePrecipAccumulationSources &sources, int klo)
Total liquid-water-equivalent surface precipitation accumulation [kg/m2] of every column,...
Definition: ERF_FirePrecip.H:63
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real fire_precip_rate_mm_hr(amrex::Real accum_now_kgm2, amrex::Real accum_prev_kgm2, amrex::Real dt_s) noexcept
Rain rate [mm/hr] from the change of the surface accumulation over one step.
Definition: ERF_FirePrecip.H:42
const int klo
Definition: ERF_InitCustomPert_KE.H:9
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_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool surface_precip_has_source(const SurfacePrecipAccumulationSource &src) noexcept
Definition: ERF_SurfacePrecipitation.H:43
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool surface_precip_has_any_source(const SurfacePrecipAccumulationSources &src) noexcept
Definition: ERF_SurfacePrecipitation.H:61
@ graupel
Definition: ERF_NOAHMP_Fields.H:140
@ rain
Definition: ERF_NOAHMP_Fields.H:138
@ total
Definition: ERF_NOAHMP_Fields.H:137
@ hail
Definition: ERF_NOAHMP_Fields.H:141
@ snow
Definition: ERF_NOAHMP_Fields.H:139
@ p
Definition: ERF_WSM6.H:301
Definition: ERF_ConsoleIO.cpp:17
const amrex::MultiFab * accum
Definition: ERF_SurfacePrecipitation.H:21
amrex::Real native_to_kg_m2
Definition: ERF_SurfacePrecipitation.H:22
Definition: ERF_SurfacePrecipitation.H:34
SurfacePrecipAccumulationSource rain
Definition: ERF_SurfacePrecipitation.H:36
SurfacePrecipAccumulationSource snow
Definition: ERF_SurfacePrecipitation.H:37
SurfacePrecipAccumulationSource hail
Definition: ERF_SurfacePrecipitation.H:39
SurfacePrecipAccumulationSource total
Definition: ERF_SurfacePrecipitation.H:35
SurfacePrecipAccumulationSource graupel
Definition: ERF_SurfacePrecipitation.H:38