Option Parsing

SpECTRE can read YAML configuration files at runtime to set parameters and choose between classes implementing an interface. Options are parsed during code initialization and can be used to construct objects placed in the Parallel::ConstGlobalCache and options passed to the parallel components. The types necessary to mark objects for parsing are declared in Options/Options.hpp.

General option format

An option is defined by an "option struct". At minimum, the struct must declare the type of the object to be parsed and provide a brief description of the meaning. The name of the option in the input file defaults to the name of the struct (excluding any template parameters and scope information), but can be overridden by providing a static name() function. Several other pieces of information, such as defaults and limits, may be provided if desired. This information is all included in the generated help output.


struct Bounded {
using type = int;
static constexpr OptionString help = {
"Option with bounds and a default value"};
// These are optional
static type default_value() noexcept { return 3; }
static type lower_bound() noexcept { return 2; }
static type upper_bound() noexcept { return 10; }
struct VectorOption {
using type = std::vector<int>;
static constexpr OptionString help = {"A vector with length limits"};
// These are optional
static std::string name() noexcept {
return "Vector"; // defaults to "VectorOption"
static size_t lower_bound_on_size() { return 2; }
static size_t upper_bound_on_size() { return 5; }

The option type can be any type understood natively by yaml-cpp (fundamentals, std::string, and std::map, std::vector, std::list, std::array, and std::pair of parsable types) and types SpECTRE adds support for. SpECTRE adds std::unordered_map (but only with ordered keys), and various classes marked as constructible in their declarations.

Constructible classes

A class that defines static constexpr OptionString help and a typelist of option structs options can be created by the option parser. When the class is requested, the option parser will parse each of the options in the options list, and then supply them to the constructor of the class. (See Custom parsing below for more general creation mechanisms.)

Unlike option descriptions, which should be brief, the class help string has no length limits and should give a description of the class and any necessary discussion of its options beyond what can be described in their individual help strings.

Creatable classes must be default constructible and move assignable.


template <typename>
class CreateFromOptions;
struct CFO {
using type = CreateFromOptions<int>;
static constexpr OptionString help = {"help"};
template <typename T>
class CreateFromOptions {
struct Option {
using type = std::string;
static constexpr OptionString help = {"Option help text"};
using options = tmpl::list<Option>;
static constexpr OptionString help = {"Class help text"};
CreateFromOptions() = default;
// The OptionContext argument can be left off if unneeded.
CreateFromOptions(std::string str, const OptionContext& context)
: str_(std::move(str)) {
if (str_[0] != 'f') {
PARSE_ERROR(context, "Option must start with an f");
const char* const input_file_text = R"(
Option: foo


The factory interface creates an object of type std::unique_ptr<Base> containing a pointer to some class derived from Base. The base class must define a type alias listing the derived classes that can be created.

using creatable_classes = tmpl::list<Derived1, ...>;

The requested derived class is created in the same way as an explicitly constructible class.

Custom parsing

Occasionally, the requirements imposed by the default creation mechanism are too stringent. In these cases, the construction algorithm can be overridden by providing a specialization of the struct

template <typename T>
static T create(const Option& options);

The create function can perform any operations required to construct the object.

Example of using a specialization to parse an enum:

namespace {
enum class CreateFromOptionsAnimal { Cat, Dog };
struct CFOAnimal {
using type = CreateFromOptionsAnimal;
static constexpr OptionString help = {"Option help text"};
} // namespace
template <>
struct create_from_yaml<CreateFromOptionsAnimal> {
static CreateFromOptionsAnimal create(const Option& options) {
const std::string animal = options.parse_as<std::string>();
if (animal == "Cat") {
return CreateFromOptionsAnimal::Cat;
if (animal == "Dog") {
return CreateFromOptionsAnimal::Dog;
"CreateFromOptionsAnimal must be 'Cat' or 'Dog'");