ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_FireEngineRegistry.H
Go to the documentation of this file.
1 #ifndef ERF_FIRE_ENGINE_REGISTRY_H
2 #define ERF_FIRE_ENGINE_REGISTRY_H
3 
5 #include <ERF_FireEngine.H>
6 #include <AMReX.H>
7 
8 #include <functional>
9 #include <memory>
10 #include <string>
11 #include <type_traits>
12 #include <vector>
13 
14 /**
15  * @file ERF_FireEngineRegistry.H
16  * @brief The fire engines compiled into this executable
17  *
18  * ERF lists no engine itself. Each engine registers itself from its own .cpp
19  * with
20  *
21  * ERF_REGISTER_FIRE_ENGINE(MyEngine, "myengine")
22  *
23  * at namespace scope, and erf.fire.engine then selects it by that name. The
24  * engine's directory (FIRE_HOME in GNU make, ERF_FIRE_ENGINE_DIRS in CMake)
25  * adds that .cpp to the build, so adding an engine changes no file of ERF.
26  *
27  * The registration runs during static initialisation, so the .cpp that holds
28  * it must be linked as an object file: inside a static archive (.a) that
29  * nothing else references, the linker drops it and the engine is missing.
30  * ERF's CMake build compiles engines into its OBJECT library, and GNU make
31  * links every object, so both keep it; an engine that ships a prebuilt
32  * library keeps its registering .cpp as source (LSFIRE's wrapper does).
33  */
34 
35 /// Creates an engine from the coupling inputs.
36 using FireEngineCreator = std::function<std::unique_ptr<FireEngine>(const FireCouplingParams&)>;
37 
38 /**
39  * @brief Add an engine to the registry; aborts on a name registered twice
40  *
41  * Called by ERF_REGISTER_FIRE_ENGINE; returns true so the macro can hold the
42  * result in a static variable.
43  */
44 bool register_fire_engine (const std::string& name, FireEngineCreator creator);
45 
46 /// Names erf.fire.engine accepts, sorted; empty when no engine is compiled in.
47 std::vector<std::string> fire_engine_names ();
48 
49 /// The engine erf.fire.engine names, or nullptr when no engine has that name.
50 std::unique_ptr<FireEngine> make_fire_engine (const std::string& name, const FireCouplingParams& params);
51 
52 #define ERF_FIRE_ENGINE_CONCAT_(a, b) a##b
53 #define ERF_FIRE_ENGINE_CONCAT(a, b) ERF_FIRE_ENGINE_CONCAT_(a, b)
54 
55 /**
56  * @brief Register engine class Class under name: erf.fire.engine = name
57  * selects it. Class is constructed from the coupling inputs,
58  * Class(const FireCouplingParams&), or default-constructed when it has
59  * no such constructor.
60  */
61 #define ERF_REGISTER_FIRE_ENGINE(Class, name) \
62  namespace { \
63  [[maybe_unused]] const bool ERF_FIRE_ENGINE_CONCAT(erf_fire_engine_registered_, __LINE__) = \
64  register_fire_engine((name), [](const FireCouplingParams& p) -> std::unique_ptr<FireEngine> { \
65  if constexpr (std::is_constructible_v<Class, const FireCouplingParams&>) { \
66  return std::make_unique<Class>(p); \
67  } else { \
68  amrex::ignore_unused(p); \
69  return std::make_unique<Class>(); \
70  } \
71  }); \
72  }
73 
74 #endif
The inputs of the atmosphere side of the fire coupling.
bool register_fire_engine(const std::string &name, FireEngineCreator creator)
Add an engine to the registry; aborts on a name registered twice.
Definition: ERF_FireEngineRegistry.cpp:19
std::unique_ptr< FireEngine > make_fire_engine(const std::string &name, const FireCouplingParams &params)
The engine erf.fire.engine names, or nullptr when no engine has that name.
Definition: ERF_FireEngineRegistry.cpp:42
std::vector< std::string > fire_engine_names()
Names erf.fire.engine accepts, sorted; empty when no engine is compiled in.
Definition: ERF_FireEngineRegistry.cpp:34
std::function< std::unique_ptr< FireEngine >(const FireCouplingParams &)> FireEngineCreator
Creates an engine from the coupling inputs.
Definition: ERF_FireEngineRegistry.H:36
The interface between the fire coupling and a fire engine.
std::string name
Definition: ERF_Plotfile2DCatalog.cpp:116
Definition: ERF_FireCouplingParams.H:18