SpECTRE
v2025.03.17
|
This tutorial will illustrate what is needed to compile the minimal SpECTRE executable that will simply print some useful information about the executable and then exit.
Specifically, this tutorial will introduce:
Metavariables
, a C++ struct that is used to specify the metaprogram that is converted into a C++ executable.Main
, the main parallel component that acts as the main function of a C++ executable.In this tutorial, SPECTRE_ROOT
refers to the directory in which SpECTRE was cloned, and SPECTRE_BUILD_DIR
refers to the directory in which you built SpECTRE.
The first step is to select (or create) a directory (within SPECTRE_ROOT/src
) that will hold the files from which the executable will be created. For this tutorial we created the directory ParallelTutorial
in src/Executables/Examples
. If you create a new directory for the executable, you will need to edit the CMakeLists.txt
file in its parent directory and add (replacing ParallelTutorial
with the appropriate directory name)
The second step is to edit (or create) the CMakeLists.txt
file in the executable directory and add a call to add_spectre_executable
such as:
The add_spectre_executable
just forwards its arguments to CMake's add_executable
. It works just like add_executable
in that you pass it a source file that defines your executable.
Your source file needs a CkRegisterMainModule()
function. This is the "main" function of the Charm++ program:
It just calls Parallel::charmxx::register_main_module<Metavariables>()
. This is where SpECTRE code takes over. SpECTRE programs are defined by the Metavariables
class that is passed to this function.
The metavariables can be thought of as a compile-time input file that defines what the executable will do:
The metavariables struct must define a static constexpr std::array<Parallel::Phase, N> default_phase_order
that is used to define the default order in which phases are executed. In this example the executable will execute the Initialization
phase followed by the Exit
phase.
The metavariables struct must define a type alias component_list
that is a tmpl::list
(a typelist defined in Utilities/TMPL.hpp
) of the parallel components used by the executable. In this example no parallel components are used.
The metavariables struct must define help
, a static constexpr Options::String
that will be printed as part of the help message of the executable. (Options::String
is defined in Options/Options.hpp
.)
Let $EXECUTABLE
be the name of the executable (the first argument passed to the add_spectre_executable
CMake
function, so in this example MinimalExample
). Then the executable can be built by running the following command in $SPECTRE_BUILD_DIR
:
which will produce the executable of the same name in $SPECTRE_BUILD_DIR/bin
.
To run a SpECTRE executable, run the command:
where <options>
must include any required command-line options. In the simple example for this tutorial, no command-line options are required.
On a laptop, we get the following output:
which includes information that will be printed by every SpECTRE executable on startup and exit. First, there is information provided by Charm++
that will depend upon how Charm++
was built. Next you will see information provided by SpECTRE which includes:
On exit, the executable will print that it is Done!
, followed by how the long the executable took to run as timed by the Charm++
wall-clock timer, and the date and time at completion, followed by any information the Charm++
provides upon exiting the program.
Every SpECTRE executable comes with a set of command-line options that can be used to obtain useful information about the executable (and for executables expecting an input file, whether or not the input file can be parsed successfully).
To get a list of available options for a SpECTRE executable, run either of the following commands:
In the middle of the Charm++
startup information will now appear a long list of Charm++
related command-line options which we will ignore for this tutorial. After the SpECTRE startup information, there is now a list of available command-line options:
which we will describe in detail below. This is followed by a description of the expected input-file options, which in this example will simply print the help
string from the metavariables struct, and the statement that there are no options expected:
We will cover input file options in a future tutorial.
As the minimal executable in this tutorial expects no input-file options, running the command:
will print out No options to check!
and exit the program. See a future tutorial for an example of checking input-file options.
In order to aid in reproducibility, all SpECTRE executables contain a copy of $SPECTRE_ROOT
. To obtain the source tree as an archive file, run the command:
which will produce the archive file SpECTRE.tar.gz
which can be expanded with the command:
In addition to dumping the entire source tree there are the following options:
--dump-paths
will print out various paths from when the executable was compiled--dump-environment
will print the results of printenv
(i.e. all of the environment variables) from when the executable was compiled--dump-build-info
will print the contents of SpECTRE's BuildInfo.txt
which will contain the versions of libraries that SpECTRE linked against, as well as various CMake
variablesAlso note that the option --dump-only
can be used to have the SpECTRE executable terminate immediately after dumping the information.
Every Charm++ executable needs a mainchare. All SpECTRE executables use Main
(found in src/Parallel/Main.hpp
) as the mainchare. When a SpECTRE executable is run, the constructor of Main
that is executed takes the command line options as an argument (as type CkArgMsg*
). This constructor performs the following operations:
GlobalCache
(a nodegroup chare) that holds objects created from input file options that are stored once per Charm++ node, as well as proxies to all other parallel components.GlobalCache
as well as any items they request that can be created from input file options.GlobalCache
.Once the list of parallel components is sent to the GlobalCache
on each node, the Main
member function allocate_array_components_and_execute_initial_phase
will be executed. This will allocate the elements of the array parallel components by calling the allocate_array
member function of each component. Then the start_phase
member function is called on each component, which will execute the phase action list for the Initialization
phase for each component. Charm++ will execute each phase until it detects that nothing is happening (quiescence detection). As this represents a global synchronization point, the number of phases should be minimized in order to exploit the power of SpECTRE. After each phase, the execute_next_phase
member function of Main
will be called. This member function first determines what the next phase is. If the next phase is Exit
, then some useful information is printed and the program exits gracefully. Otherwise the execute_next_phase
member function of each parallel component is called.