ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_FireEngineRegistry.H File Reference

The fire engines compiled into this executable. More...

#include <ERF_FireCouplingParams.H>
#include <ERF_FireEngine.H>
#include <AMReX.H>
#include <functional>
#include <memory>
#include <string>
#include <type_traits>
#include <vector>
Include dependency graph for ERF_FireEngineRegistry.H:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define ERF_FIRE_ENGINE_CONCAT_(a, b)   a##b
 
#define ERF_FIRE_ENGINE_CONCAT(a, b)   ERF_FIRE_ENGINE_CONCAT_(a, b)
 
#define ERF_REGISTER_FIRE_ENGINE(Class, name)
 Register engine class Class under name: erf.fire.engine = name selects it. Class is constructed from the coupling inputs, Class(const FireCouplingParams&), or default-constructed when it has no such constructor. More...
 

Typedefs

using FireEngineCreator = std::function< std::unique_ptr< FireEngine >(const FireCouplingParams &)>
 Creates an engine from the coupling inputs. More...
 

Functions

bool register_fire_engine (const std::string &name, FireEngineCreator creator)
 Add an engine to the registry; aborts on a name registered twice. More...
 
std::vector< std::string > fire_engine_names ()
 Names erf.fire.engine accepts, sorted; empty when no engine is compiled in. More...
 
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. More...
 

Detailed Description

The fire engines compiled into this executable.

ERF lists no engine itself. Each engine registers itself from its own .cpp with

ERF_REGISTER_FIRE_ENGINE(MyEngine, "myengine")

at namespace scope, and erf.fire.engine then selects it by that name. The engine's directory (FIRE_HOME in GNU make, ERF_FIRE_ENGINE_DIRS in CMake) adds that .cpp to the build, so adding an engine changes no file of ERF.

The registration runs during static initialisation, so the .cpp that holds it must be linked as an object file: inside a static archive (.a) that nothing else references, the linker drops it and the engine is missing. ERF's CMake build compiles engines into its OBJECT library, and GNU make links every object, so both keep it; an engine that ships a prebuilt library keeps its registering .cpp as source (LSFIRE's wrapper does).

Macro Definition Documentation

◆ ERF_FIRE_ENGINE_CONCAT

#define ERF_FIRE_ENGINE_CONCAT (   a,
  b 
)    ERF_FIRE_ENGINE_CONCAT_(a, b)

◆ ERF_FIRE_ENGINE_CONCAT_

#define ERF_FIRE_ENGINE_CONCAT_ (   a,
  b 
)    a##b

◆ ERF_REGISTER_FIRE_ENGINE

#define ERF_REGISTER_FIRE_ENGINE (   Class,
  name 
)
Value:
namespace { \
[[maybe_unused]] const bool ERF_FIRE_ENGINE_CONCAT(erf_fire_engine_registered_, __LINE__) = \
register_fire_engine((name), [](const FireCouplingParams& p) -> std::unique_ptr<FireEngine> { \
if constexpr (std::is_constructible_v<Class, const FireCouplingParams&>) { \
return std::make_unique<Class>(p); \
} else { \
amrex::ignore_unused(p); \
return std::make_unique<Class>(); \
} \
}); \
}
#define ERF_FIRE_ENGINE_CONCAT(a, b)
Definition: ERF_FireEngineRegistry.H:53
std::string name
Definition: ERF_Plotfile2DCatalog.cpp:116
@ p
Definition: ERF_WSM6.H:301
Definition: ERF_FireCouplingParams.H:18

Register engine class Class under name: erf.fire.engine = name selects it. Class is constructed from the coupling inputs, Class(const FireCouplingParams&), or default-constructed when it has no such constructor.

Typedef Documentation

◆ FireEngineCreator

using FireEngineCreator = std::function<std::unique_ptr<FireEngine>(const FireCouplingParams&)>

Creates an engine from the coupling inputs.

Function Documentation

◆ fire_engine_names()

std::vector<std::string> fire_engine_names ( )

Names erf.fire.engine accepts, sorted; empty when no engine is compiled in.

35 {
36  std::vector<std::string> names;
37  for (const auto& kv : fire_engine_registry()) { names.push_back(kv.first); }
38  return names; // std::map keeps them sorted
39 }

Referenced by FireCouplingParams::read().

Here is the caller graph for this function:

◆ make_fire_engine()

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.

43 {
44  const auto& registry = fire_engine_registry();
45  const auto it = registry.find(name);
46  if (it == registry.end()) { return nullptr; }
47  return it->second(params);
48 }

Referenced by ERF::initializeFire().

Here is the caller graph for this function:

◆ register_fire_engine()

bool register_fire_engine ( const std::string &  name,
FireEngineCreator  creator 
)

Add an engine to the registry; aborts on a name registered twice.

Called by ERF_REGISTER_FIRE_ENGINE; returns true so the macro can hold the result in a static variable.

20 {
21  auto& registry = fire_engine_registry();
22  if (name.empty()) {
23  amrex::Abort("[FIRE] ERF_REGISTER_FIRE_ENGINE: an engine registered an empty name");
24  }
25  if (registry.count(name) > 0) {
26  amrex::Abort("[FIRE] ERF_REGISTER_FIRE_ENGINE: two engines registered the name \"" + name
27  + "\"; each engine directory in the build must use its own name");
28  }
29  registry.emplace(name, std::move(creator));
30  return true;
31 }