ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_FireCoupler.H
Go to the documentation of this file.
1 #ifndef ERF_FIRE_COUPLER_H
2 #define ERF_FIRE_COUPLER_H
3 
4 #include <memory>
5 #include <string>
6 #include <vector>
7 #include <AMReX_MultiFab.H>
8 #include <AMReX_Geometry.H>
9 #include <AMReX_BoxArray.H>
10 #include <ERF_FireCouplingParams.H>
11 #include <ERF_FireEngine.H>
12 #include <ERF_FireGrid.H>
14 
15 class ERF;
16 class SurfaceLayer;
17 
18 /**
19  * @file ERF_FireCoupler.H
20  * @brief The atmosphere side of the fire coupling, shared by every fire engine
21  *
22  * ERF holds one FireCoupler (std::unique_ptr<FireCoupler> m_fire_coupler),
23  * which owns the fire engine selected by erf.fire.engine. The coupler:
24  * - checks the ERF configuration a fire grid needs and builds that grid on
25  * the level it refines (erf.fire.anchor_level);
26  * - each step of that level, hands the engine the atmospheric state
27  * (FireForcing) and advances it; with lagged or synchronous coupling, or
28  * with the smoke tracer, it averages the fluxes the engine reports
29  * (FireFluxes) onto the atmospheric columns, where they wait for the next
30  * step (the one-step explicit lag of WRF-Fire);
31  * - at every Runge-Kutta stage of that next step, injects the lagged heat and
32  * vapour into the cell sources with the WRF-Fire exponential profile
33  * (ERF_FireAtmCoupling.H; lagged and synchronous coupling only) and the
34  * smoke tracer (ERF_FireSmokeEmission.H; erf.fire.smoke_enable);
35  * - holds the lagged fluxes for the boundary-layer scheme and the checkpoint.
36  *
37  * Coarser levels see the fire through average-down, finer levels not at all.
38  */
40 {
41 public:
42  /**
43  * @param[in] params The coupling inputs (FireCouplingParams::read())
44  * @param[in] engine The fire engine erf.fire.engine selects
45  */
46  FireCoupler (const FireCouplingParams& params, std::unique_ptr<FireEngine> engine);
47 
48  /**
49  * @brief Check the configuration, build the fire grid and set the engine up
50  *
51  * Called once from ERF::InitData_post() after every surface layer exists.
52  * Runs the coupling's checks (verify_fire_prerequisites), then the
53  * engine's, builds the fire grid on level lev, allocates the lagged flux
54  * buffers (zero) and initialises the engine.
55  *
56  * @param[in] erf ERF instance (public AmrCore accessors only)
57  * @param[in] lev The level the fire grid refines (fire_anchor_level)
58  * @param[in] surface_layer The bottom surface layer, or nullptr (aborts when
59  * the engine needs one, FireEngine::needs_surface_layer)
60  * @param[in] z_phys_nd_atm Nodal height of level lev [m] (ERF always passes it)
61  */
62  void initialize (const ERF& erf,
63  int lev,
65  const amrex::MultiFab* z_phys_nd_atm);
66 
67  /**
68  * @brief Lay the coupling out on a fire grid: what initialize() does after
69  * its start-up checks and before it sets the engine up
70  *
71  * Takes the fire grid and allocates the lagged flux buffers (zero) on the
72  * k = 0 slabs of ba_atm, with 5 ghost columns. Public so that a test can
73  * drive the coupling with an engine of its own without an ERF object
74  * (Tests/Unit/Fire/ERF_GTestFireCoupler.cpp).
75  *
76  * @param[in] lev The level the fire grid refines
77  * @param[in] fg The fire grid (create_fire_grid)
78  * @param[in] ba_atm The level's boxes
79  * @param[in] dm_atm Their owners
80  * @param[in] geom_atm The level's geometry
81  */
82  void set_fire_grid (int lev, const FireGrid& fg,
83  const amrex::BoxArray& ba_atm,
84  const amrex::DistributionMapping& dm_atm,
85  const amrex::Geometry& geom_atm);
86 
87  /**
88  * @brief Advance the fire one step of its level and refill the lagged fluxes
89  *
90  * Called from ERF::Advance() once per step of the fire grid's level, after
91  * that level's dycore. The air temperature and humidity at k = 0 come from
92  * the state before the dycore; the wind from before the dycore (passive and
93  * lagged coupling) or after it (synchronous).
94  *
95  * @param[in] time Start of the step [s]
96  * @param[in] dt Step of the level [s]
97  * @param[in] S_old Conserved state before the dycore
98  * @param[in] xvel_old, yvel_old Face velocities before the dycore [m/s]
99  * @param[in] xvel_new, yvel_new Face velocities after the dycore [m/s]
100  * @param[in] z_phys_cc Cell-centre height of the level [m]
101  * @param[in] ba2d The level's boxes coarsened to one cell in z
102  * @param[in] geom Geometry of the level
103  * @param[in] precip_sources The microphysics surface precipitation accumulators of the level
104  */
105  void advance (amrex::Real time, amrex::Real dt,
106  const amrex::MultiFab& S_old,
107  const amrex::MultiFab& xvel_old, const amrex::MultiFab& yvel_old,
108  const amrex::MultiFab& xvel_new, const amrex::MultiFab& yvel_new,
109  const amrex::MultiFab& z_phys_cc,
110  const amrex::BoxArray& ba2d,
111  const amrex::Geometry& geom,
112  const SurfacePrecipAccumulationSources& precip_sources);
113 
114  /**
115  * @brief Inject the lagged fire heat, vapour and smoke into the cell sources
116  *
117  * Called from the slow right-hand side at every Runge-Kutta stage on the
118  * fire grid's level, after make_sources has rebuilt cc_source. The lagged
119  * fluxes are fixed over the step, so every stage receives the same
120  * tendency (erf.fire.source_mode decides whether it replaces or adds to the
121  * theta and vapour sources). Heat and vapour only with lagged or
122  * synchronous coupling; smoke with erf.fire.smoke_enable.
123  *
124  * @param[in,out] cc_source Cell-centred sources of the level
125  * @param[in] S_old Conserved state at the start of the step (density)
126  * @param[in] z_phys_cc Cell-centre height [m]
127  * @param[in] z_phys_nd Nodal height [m] (ERF always passes it): the cell
128  * thickness and roof datum of the heat, and the
129  * smoke cell's thickness
130  * @param[in] geom Geometry of the level
131  * @param[in] has_moisture The vapour source exists
132  * @param[in] step Step of the level, for the debug output
133  */
134  void add_sources (amrex::MultiFab& cc_source,
135  const amrex::MultiFab& S_old,
136  const amrex::MultiFab& z_phys_cc,
137  const amrex::MultiFab* z_phys_nd,
138  const amrex::Geometry& geom,
139  bool has_moisture,
140  int step);
141 
142  /**
143  * @brief Write the fire to a checkpoint: the engine's state
144  * (FireEngine::write_checkpoint), then the coupling's lagged fluxes
145  * (FireQAtmPrev and FireQLatAtmPrev) under checkpointname/Level_<lev>/
146  */
147  void write_checkpoint (const std::string& checkpointname) const;
148 
149  /**
150  * @brief Why a checkpoint's lagged fluxes do not belong to this run's fire
151  * grid, or an empty string when they do
152  *
153  * @param[in] chk_lev The level the checkpoint holds them on
154  * @param[in] chk_region The columns they cover (minimal box of their boxes)
155  */
156  std::string checkpoint_mismatch (int chk_lev, const amrex::Box& chk_region) const;
157 
158  /**
159  * @brief Restore the engine's state, then the lagged fluxes, on a restart
160  *
161  * Aborts when the checkpoint holds the lagged fluxes on another level or
162  * over another region than this run's fire grid. A checkpoint without them
163  * (no fire state, or written before they were checkpointed) leaves them at
164  * zero: the first restarted step injects no fire heat.
165  *
166  * @param[in] restart_chkfile The checkpoint directory
167  * @param[in] max_level ERF's max_level
168  * @param[in] step The step count of the fire grid's level at the checkpoint
169  */
170  void read_checkpoint (const std::string& restart_chkfile, int max_level, int step);
171 
172  /// Fire fields the ERF plotfile can carry (FireEngine::plot_var_names(), read at construction,
173  /// before ERF reads erf.plot_vars_*).
174  const std::vector<std::string>& plot_var_names () const { return m_plot_var_names; }
175 
176  /**
177  * @brief Fill component dcomp of an ERF plotfile MultiFab of level lev
178  * with the fire field name
179  *
180  * On the fire grid's level, the k = 0 cell of each column holds the mean
181  * of the engine's field (FireEngine::plot_var) over the fire cells under
182  * it; every other cell, every other level and a field the engine returns
183  * as nullptr hold zero.
184  *
185  * @param[in] name One of plot_var_names()
186  * @param[out] dst Cell-centred MultiFab on the boxes of level lev
187  * @param[in] dcomp Component of dst to fill
188  * @param[in] lev The level dst belongs to
189  */
190  void fill_plot_var (const std::string& name, amrex::MultiFab& dst, int dcomp, int lev) const;
191 
192  /// The level the fire grid refines (erf.fire.anchor_level, resolved at initialize).
193  int level () const { return m_lev; }
194 
195  /// The coupling inputs.
196  const FireCouplingParams& params () const { return m_params; }
197 
198  /// The fire engine.
199  FireEngine& engine () { return *m_engine; }
200  const FireEngine& engine () const { return *m_engine; }
201 
202  /// The fire grid.
203  const FireGrid& fire_grid () const { return m_fg; }
204 
205  /**
206  * @brief Sensible heat flux [W/m2] of the previous fire step on the
207  * atmospheric columns of the fire grid's level, with 5 ghost columns
208  * (for a reader that samples a halo around each tile, such as a
209  * boundary-layer scheme taking the fire's heat into its mixing); zero
210  * outside the fire region. Allocated at initialize, so never null afterwards.
211  */
212  const amrex::MultiFab* get_Q_atm_prev () const { return m_Q_atm_prev.get(); }
213  /// Latent heat flux [W/m2] of the previous fire step, laid out as get_Q_atm_prev().
214  const amrex::MultiFab* get_Q_lat_atm_prev () const { return m_Q_lat_atm_prev.get(); }
215 
216 private:
217  /// Average the engine's fluxes onto the atmospheric columns for the next step.
218  void update_flux_buffer (const amrex::Geometry& geom_atm);
219 
221  std::unique_ptr<FireEngine> m_engine;
223  int m_lev = 0;
224  amrex::Geometry m_geom_atm; ///< geometry of the fire grid's level
225 
226  // The engine's fluxes averaged onto the atmospheric columns of the fire
227  // grid's level (one slab per box of that level), held from the previous
228  // step for injection at every stage of the next (one-step explicit lag).
229  // Their ghost columns hold the neighbouring box's value for a reader that
230  // samples a halo around every tile; outside the refined region of a finer
231  // level they hold zero.
232  std::unique_ptr<amrex::MultiFab> m_Q_atm_prev; ///< sensible [W/m2]
233  std::unique_ptr<amrex::MultiFab> m_Q_lat_atm_prev; ///< latent [W/m2]
234 
235  std::vector<std::string> m_plot_var_names; ///< FireEngine::plot_var_names(), read at construction
236 };
237 
238 #endif
The inputs of the atmosphere side of the fire coupling.
The interface between the fire coupling and a fire engine.
Fire grid data structure and construction.
@ surface_layer
std::string name
Definition: ERF_Plotfile2DCatalog.cpp:116
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Definition: ERF_FireCoupler.H:40
FireGrid m_fg
Definition: ERF_FireCoupler.H:222
const FireCouplingParams & params() const
The coupling inputs.
Definition: ERF_FireCoupler.H:196
const amrex::MultiFab * get_Q_atm_prev() const
Sensible heat flux [W/m2] of the previous fire step on the atmospheric columns of the fire grid's lev...
Definition: ERF_FireCoupler.H:212
void add_sources(amrex::MultiFab &cc_source, const amrex::MultiFab &S_old, const amrex::MultiFab &z_phys_cc, const amrex::MultiFab *z_phys_nd, const amrex::Geometry &geom, bool has_moisture, int step)
Inject the lagged fire heat, vapour and smoke into the cell sources.
Definition: ERF_FireCoupler.cpp:275
std::unique_ptr< FireEngine > m_engine
Definition: ERF_FireCoupler.H:221
void set_fire_grid(int lev, const FireGrid &fg, const amrex::BoxArray &ba_atm, const amrex::DistributionMapping &dm_atm, const amrex::Geometry &geom_atm)
Lay the coupling out on a fire grid: what initialize() does after its start-up checks and before it s...
Definition: ERF_FireCoupler.cpp:112
void initialize(const ERF &erf, int lev, const SurfaceLayer *surface_layer, const amrex::MultiFab *z_phys_nd_atm)
Check the configuration, build the fire grid and set the engine up.
Definition: ERF_FireCoupler.cpp:83
void write_checkpoint(const std::string &checkpointname) const
Write the fire to a checkpoint: the engine's state (FireEngine::write_checkpoint),...
Definition: ERF_FireCoupler.cpp:336
void advance(amrex::Real time, amrex::Real dt, const amrex::MultiFab &S_old, const amrex::MultiFab &xvel_old, const amrex::MultiFab &yvel_old, const amrex::MultiFab &xvel_new, const amrex::MultiFab &yvel_new, const amrex::MultiFab &z_phys_cc, const amrex::BoxArray &ba2d, const amrex::Geometry &geom, const SurfacePrecipAccumulationSources &precip_sources)
Advance the fire one step of its level and refill the lagged fluxes.
Definition: ERF_FireCoupler.cpp:136
std::unique_ptr< amrex::MultiFab > m_Q_lat_atm_prev
latent [W/m2]
Definition: ERF_FireCoupler.H:233
FireCouplingParams m_params
Definition: ERF_FireCoupler.H:220
void fill_plot_var(const std::string &name, amrex::MultiFab &dst, int dcomp, int lev) const
Fill component dcomp of an ERF plotfile MultiFab of level lev with the fire field name.
Definition: ERF_FireCoupler.cpp:200
FireCoupler(const FireCouplingParams &params, std::unique_ptr< FireEngine > engine)
Definition: ERF_FireCoupler.cpp:70
FireEngine & engine()
The fire engine.
Definition: ERF_FireCoupler.H:199
int m_lev
Definition: ERF_FireCoupler.H:223
void update_flux_buffer(const amrex::Geometry &geom_atm)
Average the engine's fluxes onto the atmospheric columns for the next step.
Definition: ERF_FireCoupler.cpp:232
std::vector< std::string > m_plot_var_names
FireEngine::plot_var_names(), read at construction.
Definition: ERF_FireCoupler.H:235
const FireEngine & engine() const
Definition: ERF_FireCoupler.H:200
const amrex::MultiFab * get_Q_lat_atm_prev() const
Latent heat flux [W/m2] of the previous fire step, laid out as get_Q_atm_prev().
Definition: ERF_FireCoupler.H:214
const std::vector< std::string > & plot_var_names() const
Definition: ERF_FireCoupler.H:174
amrex::Geometry m_geom_atm
geometry of the fire grid's level
Definition: ERF_FireCoupler.H:224
int level() const
The level the fire grid refines (erf.fire.anchor_level, resolved at initialize).
Definition: ERF_FireCoupler.H:193
std::unique_ptr< amrex::MultiFab > m_Q_atm_prev
sensible [W/m2]
Definition: ERF_FireCoupler.H:232
void read_checkpoint(const std::string &restart_chkfile, int max_level, int step)
Restore the engine's state, then the lagged fluxes, on a restart.
Definition: ERF_FireCoupler.cpp:368
std::string checkpoint_mismatch(int chk_lev, const amrex::Box &chk_region) const
Why a checkpoint's lagged fluxes do not belong to this run's fire grid, or an empty string when they ...
Definition: ERF_FireCoupler.cpp:353
const FireGrid & fire_grid() const
The fire grid.
Definition: ERF_FireCoupler.H:203
A fire engine behind the shared coupling layer.
Definition: ERF_FireEngine.H:132
Definition: ERF_SurfaceLayer.H:60
Definition: ERF_InterpolationUtils.H:15
@ fg
Definition: ERF_AdvanceMorrison.cpp:111
Definition: ERF_FireCouplingParams.H:18
2D horizontal fire computational grid
Definition: ERF_FireGrid.H:29
Definition: ERF_SurfacePrecipitation.H:34