Program options service¶
A Program Options service is provided, encapsulated in a singleton object (an instantiation of the Options
class).
The Options
class member variables are private, and public getter functions have been created for the program options currently
used in the code.
The Options service can be accessed by referring to the Options::Instance()
object. For example, to retrieve the value of
the --quiet
program option, call the Options::Quiet()
getter function:
bool quiet = Options::Instance()→Quiet();
Since that could become unwieldy, there is a convenience macro to access the Options service. The macro just defines "OPTIONS" as
"Options::Instance()", so retrieving the value of the --quiet
program option can be written as:
bool quiet = OPTIONS→Quiet();
The Options service must be initialised before use. Initialise the Options service by calling the Options::Initialise()
function:
COMMANDLINE_STATUS programStatus = OPTIONS→Initialise(argc, argv);
(see constants.h
for details of the COMMANDLINE_STATUS
type)
See Program option list and default values for a full list of available program options and their default valaues.
Adding new program options¶
To add a new program option, take the following steps (these are duplicated at the top of the Options.cpp
source file):
Decide on a string for the option - this is the string the user will use on the commandline or in the grid file (e.g. "random-seed"). The convention is hyphenated lower case. Try to be consistent with existing option names. For example, if you are adding a new prescription for something, make sure the option name ends with "-prescription", or if you are adding a new distribution for something, make sure the option name ends with "-distribution". */
Decide on a class member variable name for the option (e.g. m_RandomSeed).
Decide on a default value for the option.
Add the class member variable to the PRIVATE area of the OptionValues class in
Options.h
.Add a getter for the class member variable to the PUBLIC area of the Options class in
Options.h
.Decide if the getter should always retrieve the value specified on the commandline, or whether it should retrieve the grid line value if one was specified by the user, and only retrieve the commandline value if the user did not specify a grid line value - see the
OPT_VALUE
macro defined inOptions.h
.Add the class member variable initialisation (to the default value) to the
Options::OptionValues::Initialise()
function inOptions.cpp
.Add the option to the Options::AddOptions() function in Options.cpp. This is where we tell Boost about the option - the option string, the variable in which the user-specified value should be stored, the default value to use if the user does not specify a value, and the (text) description of the option.
Options::AddOptions()
is a bit of a beast - there's no easy, short way to specify the details of as many options as we have. I have tried to make it semi-readable, but it is, and always will be, just long... The best we can do is keep it neat so it doesn't become too hard to read.When adding options to
Options::AddOptions()
, the convention I have used is that the option string (e.g. "random-seed") is predominantly in lower case - that's not strictly required, but I think it's easier for users to remember the option names if they don't have to remember a mixture of upper and lower case. I have configuredBoost
to perform a case-insensitive match, so option strings can have mixed case if necessary (e.g.--muller-mandel-kick-multiplier-BH
).Where appropriate, use
AllowedOptionValuesFormatted()
to format the allowed values for an option - doing so ensures all allowed values are included, and will keep the format consistent.Add any sanity checks: constraint/range/dependency checks etc. for the new option, and any affected existing options, to
Options::OptionValues::CheckAndSetOptions()
inOptions.cpp
. It is also here you can set any final values that, perhaps due to dependencies on options that had not yet been parsed, could not be set directly byBoost
when the options were parsed (also seeSetCalculatedOptionDefaults()
; viz.m_KickPhi1
etc.).If the option is a string option with multiple-choices - in that the user can select from a list of possible values recorded in
typedefs.h
orLogTypedefs.h
in anENUM CLASS
and correspondingCOMPASUnorderedMap
labels map - then add the option to the functionAllowedOptionValues()
here so that we can easily extract the allowed values for that option.Add the new option to one or more of the following vectors in
Options.h
, as required:m_ShorthandAllowed
: options for which shorthand notation is allowedm_GridLineExcluded
: option strings that may not be specified on a grid linem_SSEOnly
: option strings that apply to SSE onlym_BSEOnly
: option strings that apply to BSE onlym_RangeExcluded
: option strings for which a range may not be specifiedm_SetExcluded
: option strings for which a set may not be specifiedRead the explanations for each of the vectors in
Options.h
to get a better idea of what they are for and where the new option should go.Add the new option to the following structures in
LogTypedefs.h
(only required if the option is required to be available for printing in the logfiles):enum class PROGRAM_OPTION
const COMPASUnorderedMap<PROGRAM_OPTION, std::string> PROGRAM_OPTION_LABEL
const std::map<PROGRAM_OPTION, PROPERTY_DETAILS> PROGRAM_OPTION_DETAIL
Add the new option to
Options::OptionValue()
- this enables selection of the option value for printing in the output (log) files. Only required if the option is required to be available for printing in the logfiles.Add the new option to the default YAML file template in
yaml.h
if required. While this is not mandatory, it does help to keep the YAML file ordered and consequently relatively easy to read and search for options.