ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_MicrophysicsColumns.H
Go to the documentation of this file.
1 /*! @file ERF_MicrophysicsColumns.H
2  * \brief Full-column layout for the column microphysics schemes (Morrison, WSM6, WDM6)
3  */
4 
5 #ifndef ERF_MICROPHYSICSCOLUMNS_H
6 #define ERF_MICROPHYSICSCOLUMNS_H
7 
8 #include <array>
9 #include <memory>
10 
11 #include <AMReX_BoxArray.H>
12 #include <AMReX_DistributionMapping.H>
13 #include <AMReX_MultiFab.H>
14 #include <AMReX_iMultiFab.H>
15 
16 /**
17  * Morrison, WSM6 and WDM6 sediment each column inside one per-column kernel over the
18  * k range of the box they are handed: the box top is treated as the top of the column
19  * (no inflow) and the box bottom as its ground (outflow booked as surface precipitation).
20  * That is only right when no column is split between boxes.
21  *
22  * This class records, for one level's grids, whether any column is split between boxes
23  * stacked in z, and if so builds a "column layout": a BoxArray covering exactly the same
24  * cells in which every contiguous vertical run of covered cells lies inside one box. A
25  * scheme then copies its fields onto that layout, runs its unchanged column kernels, and
26  * copies the result back. The kernels only read and write their own column, so this gives
27  * the same arithmetic as a run whose grids were never split in z.
28  *
29  * A run that does not reach the domain bottom (e.g. a refined patch aloft) has no ground,
30  * so the schemes accumulate surface precipitation only where klo is the domain bottom.
31  */
33 {
34 public:
35  using FabPtr = std::shared_ptr<amrex::MultiFab>;
36 
37  //! Build from a level's grids; call from the scheme's Init (which also runs on regrid)
38  void define (const amrex::BoxArray& ba, const amrex::Box& domain);
39 
40  //! True when some column is split between boxes, so the fields must be gathered
41  [[nodiscard]] bool needs_gather () const { return m_needs_gather; }
42 
43  //! True when every box spans the domain in z (required by the Fortran bridges)
44  [[nodiscard]] bool boxes_span_domain () const { return m_boxes_span_domain; }
45 
46  //! Swap each non-null field for a copy on the column layout; the originals go to saved
47  template <std::size_t N>
48  void gather (std::array<FabPtr,N>& vars, std::array<FabPtr,N>& saved) const
49  {
50  for (std::size_t n = 0; n < N; ++n) {
51  saved[n] = vars[n];
52  if (vars[n]) { vars[n] = gather_one(*vars[n]); }
53  }
54  }
55 
56  //! Copy the column-layout fields back into the originals and restore them
57  template <std::size_t N>
58  void scatter (std::array<FabPtr,N>& vars, std::array<FabPtr,N>& saved) const
59  {
60  for (std::size_t n = 0; n < N; ++n) {
61  if (saved[n]) { saved[n]->ParallelCopy(*vars[n], 0, 0, vars[n]->nComp()); }
62  vars[n] = saved[n];
63  saved[n].reset();
64  }
65  }
66 
67  //! Copy of a field (cell-centered or z-face; with its ghost cells) on the column layout
68  [[nodiscard]] FabPtr gather_one (const amrex::MultiFab& src) const;
69 
70  //! Copy of a nodal field (e.g. z_phys_nd) on the column layout, or null for null input
71  [[nodiscard]] std::unique_ptr<amrex::MultiFab> gather_nodal (const amrex::MultiFab* src) const;
72 
73  //! Copy of a 2D (z-flattened) integer field (e.g. lmask) on the column layout, or null
74  [[nodiscard]] std::unique_ptr<amrex::iMultiFab> gather_2d (const amrex::iMultiFab* src) const;
75 
76 private:
77  bool m_needs_gather = false;
78  bool m_boxes_span_domain = true;
79  amrex::BoxArray m_col_ba;
80  amrex::DistributionMapping m_col_dm;
81 };
82 
83 #endif
Definition: ERF_MicrophysicsColumns.H:33
bool boxes_span_domain() const
True when every box spans the domain in z (required by the Fortran bridges)
Definition: ERF_MicrophysicsColumns.H:44
void gather(std::array< FabPtr, N > &vars, std::array< FabPtr, N > &saved) const
Swap each non-null field for a copy on the column layout; the originals go to saved.
Definition: ERF_MicrophysicsColumns.H:48
bool m_boxes_span_domain
Definition: ERF_MicrophysicsColumns.H:78
FabPtr gather_one(const amrex::MultiFab &src) const
Copy of a field (cell-centered or z-face; with its ghost cells) on the column layout.
Definition: ERF_MicrophysicsColumns.cpp:100
bool m_needs_gather
Definition: ERF_MicrophysicsColumns.H:77
void scatter(std::array< FabPtr, N > &vars, std::array< FabPtr, N > &saved) const
Copy the column-layout fields back into the originals and restore them.
Definition: ERF_MicrophysicsColumns.H:58
std::unique_ptr< amrex::MultiFab > gather_nodal(const amrex::MultiFab *src) const
Copy of a nodal field (e.g. z_phys_nd) on the column layout, or null for null input.
Definition: ERF_MicrophysicsColumns.cpp:116
std::shared_ptr< amrex::MultiFab > FabPtr
Definition: ERF_MicrophysicsColumns.H:35
bool needs_gather() const
True when some column is split between boxes, so the fields must be gathered.
Definition: ERF_MicrophysicsColumns.H:41
amrex::BoxArray m_col_ba
Definition: ERF_MicrophysicsColumns.H:79
std::unique_ptr< amrex::iMultiFab > gather_2d(const amrex::iMultiFab *src) const
Copy of a 2D (z-flattened) integer field (e.g. lmask) on the column layout, or null.
Definition: ERF_MicrophysicsColumns.cpp:128
amrex::DistributionMapping m_col_dm
Definition: ERF_MicrophysicsColumns.H:80
void define(const amrex::BoxArray &ba, const amrex::Box &domain)
Build from a level's grids; call from the scheme's Init (which also runs on regrid)
Definition: ERF_MicrophysicsColumns.cpp:9