API Documentation for C++
This page provides full documentation for the C++ API of MUSCLE3.
Namespace libmuscle
Data
-
class Data : public libmuscle::DataConstRef
A data object.
This represents a data object, which is what MUSCLE3 sends and receives.
Data objects refer to a simple value of a basic type, or refer to a dictionary or list. They model a reference, so if you copy a Data object to a new Data object, you’ll have two Data objects referring to the same data item. If you assign to a Data object, you modify the referred-to item, which will be visible also via any existing copies of the Data object.
With respect to memory management, this is like a shared_ptr, in that it will automatically manage any referenced memory, and only remove any actual items once all Data objects referring to them have been destructed.
Note that this publicly derives from DataConstRef, so see that class for the constructors and read-only member functions; they work on Data as well.
See the C++ tutorial for examples of how to use this.
Subclassed by libmuscle::ClosePort
Public Functions
-
Data(Data const&) = default
Copy-construct a Data object.
Explicit default avoids a compiler warning on some compilers.
-
Data(Data&&) = default
Move-construct a Data object.
Explicit default avoids a compiler warning on some compilers.
-
Data &operator=(Data const &rhs)
Copy-assign the given value to this Data object.
If the argument is a basic type, then the value will be copied. If it is a list or a dict, then this Data object will refer to the same list or dict as the argument.
- Parameters:
rhs – The object to copy from.
-
Data operator[](std::string const &key)
Access a dictionary value by key.
Returns a Data object referring to the value for the given key. Assign to that object to modify a value, as in
mydict["stress"] = 12.4;
If no key with the given name exists, a new entry is added to the dictionary with the given key and a nil value, and a reference to it is then returned. This way new key/value pairs can be added to a dictionary.
- Parameters:
key – The key to search for.
- Throws:
std::runtime_error – if the object is not a dictionary.
- Returns:
A writable reference to the requested value.
-
Data value(std::size_t i) const
Access a value in a dictionary by index.
Use only if is_a_dict() returns true.
Indices match those of key(), so value(i) will give you the value corresponding to key(i).
See also
- Parameters:
i – The index of the value to retrieve.
- Throws:
std::runtime_error – if the object is not a map.
std::domain_error – if the index is out of bounds.
-
Data operator[](std::size_t index)
Access a list entry by index.
Returns a Data object referring to the value at the given index. Assign to that object to modify a value, as in
mylist[3] = 12.4; mylist[4] = "MUSCLE3";
- Parameters:
index – The index to refer to.
- Throws:
std::runtime_error – if the object is not a list.
std::out_of_range – if the index is beyond the end of the list.
- Returns:
A writable reference to the requested value.
-
char *as_byte_array()
Access a byte array.
Use is_a_byte_array() to check whether this object represents a byte array. Use size() to get the size in bytes.
The returned buffer will remain valid and accessible at least until this Data goes out of scope.
- Throws:
std::runtime_error – if this is not a byte array.
- Returns:
A pointer to a the first byte of a consecutive buffer.
-
DataConstRef()
Create a Data object representing nil.
Nil is a special “no data” value, like nullptr or None in Python.
-
DataConstRef(bool value)
Create a DataConstRef object representing a boolean value.
- Parameters:
value – The value to represent.
-
DataConstRef(char const *const value)
Create a DataConstRef object representing a string value.
- Parameters:
value – The value to represent, a null-terminated C string.
-
DataConstRef(std::string const &value)
Create a DataConstRef object representing a string value.
- Parameters:
value – The value to represent.
-
DataConstRef(int value)
Create a DataConstRef object representing an integer value.
- Parameters:
value – The value to represent.
-
DataConstRef(long int value)
Create a DataConstRef object representing an integer value.
- Parameters:
value – The value to represent.
-
DataConstRef(long long int value)
Create a DataConstRef object representing an integer value.
- Parameters:
value – The value to represent.
-
DataConstRef(unsigned int value)
Create a DataConstRef object representing an unsigned integer value.
- Parameters:
value – The value to represent.
-
DataConstRef(unsigned long int value)
Create a DataConstRef object representing an unsigned integer value.
- Parameters:
value – The value to represent.
-
DataConstRef(unsigned long long int value)
Create a DataConstRef object representing an unsigned integer value.
- Parameters:
value – The value to represent.
-
DataConstRef(float value)
Create a DataConstRef object representing a 32-bit floating point value.
- Parameters:
value – The value to represent.
-
DataConstRef(double value)
Create a DataConstRef object representing a 64-bit floating point value.
- Parameters:
value – The value to represent.
-
DataConstRef(::ymmsl::SettingValue const &value)
Create a DataConstRef object from a SettingValue’s value.
Note that this will decode to whichever type is stored in the SettingValue, not to a SettingValue object.
- Parameters:
value – The value to represent.
-
DataConstRef(::ymmsl::Settings const &settings)
Create a DataConstRef object representing a Settings object.
- Parameters:
value – The value to represent.
-
DataConstRef(DataConstRef const&) = default
Copy-construct a DataConstRef object.
-
DataConstRef(DataConstRef&&) = default
Move-construct a DataConstRef object.
Public Static Functions
-
template<typename Element>
static Data grid(Element const *const data, std::vector<std::size_t> const &shape, std::vector<std::string> const &indexes = {}, StorageOrder storage_order = StorageOrder::last_adjacent) Create a Data object containing a grid object.
This creates a DataConstRef that represents a grid or array of a given element type.
Supported types are
std::int32_t
,std::int64_t
,float
,double
andbool
. Note that unless you have exotic hardware,int
,long
andlong long
will be aliased as eitherint32_t
orint64_t
, and will therefore work as well. Unsigned integer types are not supported.Besides a type, arrays have a shape. This is a list of sizes, one for each dimension of the array.
They also have a storage order, which specifies in which order the elements are arranged in memory. StorageOrder::first_adjacent means that array items who only differ by one in their first index are adjacent in memory, while StorageOrder::last_adjacent means that array items which only differ by one in their last index are adjacent in memory. Last adjacent is the standard in C and C++, and is also known as column-major, while first adjacent is the standard in Fortran, and is also known as row-major.
The data argument should be a pointer to a contiguous array of elements of the given type.
Finally, the optional index_names argument may be used to specify the names of the indices. For a Cartesian grid, these may be
x
andy
, while for for example a polar grid you may haverho
andphi
. These names are optional, but help to make it easier to interpret the data, and so adding them is very much recommended.- Template Parameters:
Element – The type of the elements.
- Parameters:
data – Pointer to the array data.
shape – The shape of the array.
indexes – Names of the array’s indexes.
storage_order – The storage order of the array data.
-
static Data dict()
Create a Data containing an empty dictionary.
- Returns:
A Data containing an empty dictionary.
-
template<typename ...Args>
static Data dict(Args const&... args) Create a Data containing a dictionary with the given keys and values.
An even number of arguments must be given. The even arguments must be strings, and are the keys, while the odd arguments are the values. These are Data objects, so you can pass those, or a value of any type representable by Data.
Example:
auto mydict = Data::dict( "id", "element1", "stress", 12.3, "strain", 1.23);
- Returns:
A Data containing a dictionary with the given keys and values.
-
static Data list()
Create a Data containing an empty list.
- Returns:
A Data containing an empty list.
-
static Data nils(std::size_t size)
Create a Data containing a list of the given size.
The items in the list will be initialised to the nil value.
- Parameters:
size – The size of the new list.
- Returns:
A Data containing a list of nil values of length size.
-
template<typename ...Args>
static Data list(Args const&... args) Create a Data containing a list of the given items.
Each argument must be either a Data object, or an object of a type representable by a Data object.
-
static Data byte_array(uint32_t size)
Create a byte array of a given size.
The buffer will be owned by this Data object. Use as_byte_array() to get a pointer to put data into it.
-
static Data byte_array(char const *buffer, uint32_t size)
Create a Data referencing a byte array.
The buffer passed will not be copied! This creates a Data object that refers to your buffer, and you need to make sure that that buffer exists for as long as the Data object (and/or any copies of it) is used.
- Parameters:
buffer – A pointer to the beginning of the buffer.
size – The size of the buffer.
-
Data(Data const&) = default
DataConstRef
-
class DataConstRef
A const reference to some kind of data.
This defines a read-only API for variable data objects, which is what MUSCLE3 sends and receives.
As a user, you should be creating Data objects, not DataConstRef objects. Data objects have the same interface as DataConstRef objects, but have additional member functions for modification.
This class models a const reference. You can create it and access the referenced data, but you cannot assign to this because that would change the referenced data, and this is a const reference.
With respect to memory management, this is like a shared_ptr, in that it will automatically manage referenced memory, even if you copy the object.
Subclassed by libmuscle::Data
Public Functions
-
DataConstRef()
Create a Data object representing nil.
Nil is a special “no data” value, like nullptr or None in Python.
-
DataConstRef(bool value)
Create a DataConstRef object representing a boolean value.
- Parameters:
value – The value to represent.
-
DataConstRef(char const *const value)
Create a DataConstRef object representing a string value.
- Parameters:
value – The value to represent, a null-terminated C string.
-
DataConstRef(std::string const &value)
Create a DataConstRef object representing a string value.
- Parameters:
value – The value to represent.
-
DataConstRef(int value)
Create a DataConstRef object representing an integer value.
- Parameters:
value – The value to represent.
-
DataConstRef(long int value)
Create a DataConstRef object representing an integer value.
- Parameters:
value – The value to represent.
-
DataConstRef(long long int value)
Create a DataConstRef object representing an integer value.
- Parameters:
value – The value to represent.
-
DataConstRef(unsigned int value)
Create a DataConstRef object representing an unsigned integer value.
- Parameters:
value – The value to represent.
-
DataConstRef(unsigned long int value)
Create a DataConstRef object representing an unsigned integer value.
- Parameters:
value – The value to represent.
-
DataConstRef(unsigned long long int value)
Create a DataConstRef object representing an unsigned integer value.
- Parameters:
value – The value to represent.
-
DataConstRef(float value)
Create a DataConstRef object representing a 32-bit floating point value.
- Parameters:
value – The value to represent.
-
DataConstRef(double value)
Create a DataConstRef object representing a 64-bit floating point value.
- Parameters:
value – The value to represent.
-
DataConstRef(::ymmsl::SettingValue const &value)
Create a DataConstRef object from a SettingValue’s value.
Note that this will decode to whichever type is stored in the SettingValue, not to a SettingValue object.
- Parameters:
value – The value to represent.
-
DataConstRef(::ymmsl::Settings const &settings)
Create a DataConstRef object representing a Settings object.
- Parameters:
value – The value to represent.
-
DataConstRef(DataConstRef const&) = default
Copy-construct a DataConstRef object.
-
DataConstRef(DataConstRef&&) = default
Move-construct a DataConstRef object.
-
DataConstRef &operator=(DataConstRef const&) = delete
Assignment is forbidden, this models a const reference.
-
DataConstRef &operator=(DataConstRef&&) = delete
Assignment is forbidden, this models a const reference.
-
void reseat(DataConstRef const &target)
Reseat the reference.
This makes this DataConstRef object refer to the object referred to by the argument.
- Parameters:
target – The object to refer to.
-
template<typename T>
bool is_a() const Determine the type of the referenced data.
This works for the following types:
bool
std::string
char (checks for integer, not for string!)
short int
int
long int
long long int
unsigned char
unsigned short int
unsigned int
unsigned long int
unsigned long long int
float
double
ymmsl::SettingValue
ymmsl::Settings
For checking nil, list and dict, see is_nil(), is_a_list() and is_a_dict().
- Template Parameters:
T – The type to check.
-
bool is_nil() const
Return whether this references a nil value.
- Returns:
True iff this references a nil value.
-
bool is_a_dict() const
Return whether this references a dict value.
If so, operator[key] can be used to obtain values.
- Returns:
True iff this references a dict.
-
bool is_a_list() const
Return whether this references a list value.
If so, operator[index] can be used to obtain values.
- Returns:
True iff this references a list.
-
template<typename Element>
bool is_a_grid_of() const Return whether this references a grid of the given element type.
Supported element types are
std::int32_t
,std::int64_t
,float
,double
, andbool
. Unless you’re on some exotic machine,int
,long
, andlong long
are aliases forint32_t
orint64_t
, and so will also work. Unsigned types are not supported.- Template Parameters:
Element – The type of the elements of the array.
-
bool is_a_byte_array() const
Return whether this references a byte array.
If so, as_byte_array() can be used to obtain values, and size() to get the number of bytes in the array.
- Returns:
True iff this references a byte array.
-
std::size_t size() const
Returns the size of a list, dict, grid or byte array.
- Returns:
The number of items in a referenced list or dict value, the number of elements in a grid, or the number of bytes in a byte array.
-
template<typename T>
T as() const Access a referenced scalar value.
Use is_a* first to check whether the type is what you expect. If the type mismatches, an exception will be thrown.
The following types can be used:
bool
std::string
char (accesses as integer, not as string!)
short int
int
long int
long long int
unsigned char
unsigned short int
unsigned int
unsigned long int
unsigned long long int
float
double
ymmsl::SettingValue
ymmsl::Settings
- Template Parameters:
T – The type to access, as above.
- Throws:
std::runtime_error – if the type does not match.
- Returns:
The referenced value, as the given type.
-
const char *as_byte_array() const
Access a byte array.
Use is_a_byte_array() to check whether this object represents a byte array. Use size() to get the size.
The returned buffer will remain valid and accessible at least until this DataConstRef goes out of scope.
- Throws:
std::runtime_error – if this is not a byte array.
- Returns:
A pointer to a the first byte of a consecutive buffer.
-
DataConstRef operator[](std::string const &key) const
Access an item in a dictionary by key.
Use only if is_a_dict() returns true.
- Parameters:
key – The key whose value to retrieve.
- Throws:
std::runtime_error – if the object is not a map.
std::domain_error – if the key does not exist.
-
std::string key(std::size_t i) const
Access a key in a dictionary by index.
Use only if is_a_dict() returns true.
Indices match those of value(), so value(i) will give you the value corresponding to key(i).
See also
- Parameters:
i – The index of the key to retrieve.
- Throws:
std::runtime_error – if the object is not a map.
std::domain_error – if the index is out of bounds.
-
DataConstRef value(std::size_t i) const
Access a value in a dictionary by index.
Use only if is_a_dict() returns true.
Indices match those of key(), so value(i) will give you the value corresponding to key(i).
See also
- Parameters:
i – The index of the value to retrieve.
- Throws:
std::runtime_error – if the object is not a map.
std::domain_error – if the index is out of bounds.
-
DataConstRef operator[](std::size_t index) const
Access an item in a list.
Use only if is_a_list() returns true.
Indexes are zero-based, use size() to find the valid range.
- Parameters:
index – The index at which to retrieve a value.
- Throws:
std::runtime_error – if the object is not a list.
std::domain_error – if the index is out of range.
-
std::vector<std::size_t> shape() const
Get the shape of a grid.
Use only if is_a_grid_of() returns true.
The shape of an array is a list of sizes of the array, one for each of its dimensions.
- Throws:
std::runtime_error – if the object is not a grid.
- Returns:
The shape of the contained grid.
-
StorageOrder storage_order() const
Get the storage order of the grid.
Use only if is_a_grid_of() returns true.
The storage order is either StorageOrder::first_adjacent or StorageOrder::last_adjacent. StorageOrder::first_adjacent means that array items who only differ by one in their first index are adjacent in memory, while StorageOrder::last_adjacent means that array items which only differ by one in their last index are adjacent in memory. Last adjacent is the standard in C and C++, and is also known as column-major, while first adjacent is the standard in Fortran, and is also known as row-major.
- Throws:
std::runtime_error – if the object is not a grid.
- Returns:
The storage order of the grid.
-
bool has_indexes() const
Return whether a grid has index names.
Use only if is_a_grid_of() returns true.
This function determines whether the grid has named indexes. If so, you can access them through indexes().
- Throws:
std::runtime_Error – if the object is not a grid.
- Returns:
True iff the grid has named indexes.
-
std::vector<std::string> indexes() const
Get the index names of the grid.
Use only if is_a_grid_of() returns true and has_indexes() returns true.
The optional index names returned by this function specify which index refers to what. For a 2D Cartesian grid, these may be
'x'
and'y'
for example, or for a polar grid,'phi'
and'rho'
. They’re intended to help annotate and use the data, and may be absent if the sender of a message did not include them.- Throws:
std::runtime_error – if the object is not a grid.
- Returns:
The indexes.
-
template<typename Element>
const Element *elements() const Get the elements (data values) of a grid.
Use only if is_a_grid_of<Element>() returns true.
This returns a pointer to the specified type which points to a block of memory containing the grid’s element values. They are contiguous in memory in the order specified by storage_order().
The returned pointer is valid at least as long as this object exists.
- Template Parameters:
Element – The type of the data stored in the grid.
- Throws:
std::runtime_error – if the object is not a grid of this type.
- Returns:
A pointer to the data, as specified above.
Public Static Functions
-
template<typename Element>
static DataConstRef grid(Element const *const data, std::vector<std::size_t> const &shape, std::vector<std::string> const &indexes = {}, StorageOrder storage_order = StorageOrder::last_adjacent) Create a DataConstRef object containing a grid object.
This creates a DataConstRef that represents a grid or array of a given element type.
Supported types are
std::int32_t
,std::int64_t
,float
,double
andbool
. Note that unless you have exotic hardware,int
,long
andlong long
will be aliased as eitherint32_t
orint64_t
, and will therefore work as well. Unsigned integer types are not supported.Besides a type, arrays have a shape. This is a list of sizes, one for each dimension of the array.
They also have a storage order, which specifies in which order the elements are arranged in memory. StorageOrder::first_adjacent means that array items who only differ by one in their first index are adjacent in memory, while StorageOrder::last_adjacent means that array items which only differ by one in their last index are adjacent in memory. Last adjacent is the standard in C and C++, and is also known as column-major, while first adjacent is the standard in Fortran, and is also known as row-major.
The data argument should be a pointer to a contiguous array of elements of the given type.
Finally, the optional index_names argument may be used to specify the names of the indices. For a Cartesian grid, these may be
x
andy
, while for for example a polar grid you may haverho
andphi
. These names are optional, but help to make it easier to interpret the data, and so adding them is very much recommended.- Template Parameters:
Element – The type of the elements.
- Parameters:
data – Pointer to the array data.
shape – The shape of the array.
indexes – Names of the array’s indexes.
storage_order – The storage order of the array data.
-
static DataConstRef dict()
Create a DataConstRef containing an empty dictionary.
- Returns:
A DataConstRef containing an empty dictionary.
-
template<typename ...Args>
static DataConstRef dict(Args const&... args) Create a DataConstRef of a dictionary with the given keys and values.
An even number of arguments must be given. The even arguments must be strings, and are the keys, while the odd arguments are the values. These are DataConstRef objects, so you can pass those, or a value of any type representable by DataConstRef.
Example:
auto mydict = Data::dict( "id", "element1", "stress", 12.3, "strain", 1.23);
- Returns:
A DataConstRef containing a dictionary with the given keys and values.
-
static DataConstRef list()
Create a DataConstRef containing an empty list.
- Returns:
A DataConstRef containing an empty list.
-
static DataConstRef nils(std::size_t size)
Create a DataConstRef containing a list of the given size.
The items in the list will be initialised to the nil value.
- Parameters:
size – The size of the new list.
- Returns:
A DataConstRef containing a list of nil values of length size.
-
template<typename ...Args>
static DataConstRef list(Args const&... args) Create a DataConstRef containing a list of the given items.
Each argument must be either a DataConstRef object, or an object of a type representable by a DataConstRef object.
-
DataConstRef()
Instance
-
class Instance
Represents a component instance in a MUSCLE3 simulation.
This class provides a low-level send/receive API for the instance to use.
Public Functions
-
Instance(int argc, char const *const argv[], MPI_Comm const &communicator = MPI_COMM_WORLD, int root = 0)
Create an Instance.
For MPI-based components, creating an Instance is a collective operation, so it must be done in all processes simultaneously, with the same communicator and the same root.
- Parameters:
argc – The number of command-line arguments.
argv – Command line arguments.
communicator – MPI communicator containing all processes in this instance (MPI only).
root – The designated root process (MPI only).
-
Instance(int argc, char const *const argv[], PortsDescription const &ports, MPI_Comm const &communicator = MPI_COMM_WORLD, int root = 0)
Create an instance.
A PortsDescription can be written like this:
PortsDescription ports({ {Operator::F_INIT, {“port1”, “port2”}}, {Operator::O_F, {“port3[]”}} });
For MPI-based components, creating an Instance is a collective operation, so it must be done in all processes simultaneously, with the same communicator and the same root.
- Parameters:
argc – The number of command-line arguments.
argv – Command line arguments.
ports – A description of the ports that this instance has.
communicator – MPI communicator containing all processes in this instance (MPI only).
root – The designated root process (MPI only).
-
Instance(int argc, char const *const argv[], InstanceFlags flags, MPI_Comm const &communicator = MPI_COMM_WORLD, int root = 0)
Create an Instance.
For MPI-based components, creating an Instance is a collective operation, so it must be done in all processes simultaneously, with the same communicator and the same root.
- Parameters:
argc – The number of command-line arguments.
argv – Command line arguments.
flags – InstanceFlags for this instance.
communicator – MPI communicator containing all processes in this instance (MPI only).
root – The designated root process (MPI only).
-
Instance(int argc, char const *const argv[], PortsDescription const &ports, InstanceFlags flags, MPI_Comm const &communicator = MPI_COMM_WORLD, int root = 0)
Create an instance.
A PortsDescription can be written like this:
PortsDescription ports({ {Operator::F_INIT, {“port1”, “port2”}}, {Operator::O_F, {“port3[]”}} });
For MPI-based components, creating an Instance is a collective operation, so it must be done in all processes simultaneously, with the same communicator and the same root.
- Parameters:
argc – The number of command-line arguments.
argv – Command line arguments.
ports – A description of the ports that this instance has.
flags – InstanceFlags for this instance.
communicator – MPI communicator containing all processes in this instance (MPI only).
root – The designated root process (MPI only).
-
bool reuse_instance()
Decide whether to run this instance again.
In a multiscale simulation, instances get reused all the time. For example, in a macro-micro simulation, the micromodel does a complete run for every timestep of the macromodel. Rather than starting up a new instance of the micromodel, which could be expensive, we reuse a single instance many times.
This may bring other advantages, such as faster convergence when starting from the previous final state, and in some cases may be necessary if micromodel state needs to be preserved from one macro timestep to the next.
So in MUSCLE, submodels run in a reuse loop, which runs them over and over again until their work is done and they should be shut down. Whether to do another F_INIT, O_I, S, O_F cycle is decided by this method.
This method must be called at the beginning of the reuse loop, i.e. before the F_INIT operator, and its return value should decide whether to enter that loop again.
MPI-based components must execute the reuse loop in each process in parallel, and call this function at the top of the reuse loop in each process.
-
void error_shutdown(std::string const &message)
Logs an error and shuts down the Instance.
If you detect that something is wrong (invalid input, invalid settings, simulation diverged, or anything else really), you should call this method before calling exit() or raising an exception that you don’t expect to catch.
If you do so, the Instance will tell the rest of the simulation that it encountered an error and will shut down. That makes it easier to debug the situation (the message will be logged), and it reduces the chance that other parts of the simulation will sit around waiting forever for a message that this instance was supposed to send.
MPI-based components may either call this function in all processes, or only in the root process (as passed to the constructor).
- Parameters:
message – An error message describing the problem.
-
std::vector<std::string> list_settings() const
List settings by name.
This function returns a list of names of the available settings.
- Returns:
A list of setting names.
-
::ymmsl::SettingValue get_setting(std::string const &name) const
Returns the value of a model setting.
MPI-based components may call this function at any time within the reuse loop, in any or all processes, simultaneously or not.
- Parameters:
name – The name of the setting, without any instance prefix.
- Throws:
std::out_of_range – if no setting with the given name exists.
- Returns:
The value of the setting as a generic SettingValue.
-
template<typename ValueType>
ValueType get_setting_as(std::string const &name) const Returns the value of a model setting.
MPI-based components may call this function at any time within the reuse loop, in any or all processes, simultaneously or not.
- Template Parameters:
ValueType – The (expected) type of the setting. Needs to match exactly or an exception will be thrown, this will not convert e.g. an integer into a string.
- Parameters:
name – The name of the setting, without any instance prefix.
- Throws:
std::out_of_range – if no setting with the given name exists.
std::bad_cast – if the value is not of the specified type.
- Returns:
The value of the setting as a ValueType
-
std::unordered_map<::ymmsl::Operator, std::vector<std::string>> list_ports() const
Returns a description of the ports that this CE has.
This keeps Doxygen from getting confused.
Note that the result has almost the same format as the port declarations you pass when making an Instance. The only difference is that the port names never have
[]
at the end, even if the port is a vector port.MPI-based components may call this function only in the root process.
- Returns:
A map, indexed by operator, containing lists of port names. Operators with no associated ports are not included.
-
bool is_connected(std::string const &port) const
Returns whether the given port is connected.
MPI-based components may call this function only in the root process.
- Parameters:
port – The name of the port to inspect.
- Returns:
true if there is a conduit attached to this port, false if not.
-
bool is_vector_port(std::string const &port) const
Returns whether a port is a vector or scalar port.
If a port has been declared to be a vector port (i.e. the name passed when creating this Instance had ‘[]’ at the end), then you can pass a ‘slot’ argument when sending or receiving. It’s like the port is a vector of slots on which you can send or receive messages.
MPI-based components may call this function only in the root process.
This function returns True if the given port is a vector port, and False if it is a scalar port.
- Parameters:
port – The port to check this property of.
-
bool is_resizable(std::string const &port) const
Returns whether the given port is resizable.
Scalar ports are never resizable. Whether a vector port is resizable depends on what it is connected to.
MPI-based components may call this function only in the root process.
- Parameters:
port – Name of the port to inspect.
- Returns:
: true if the port can be resized, false if not.
-
int get_port_length(std::string const &port) const
Returns the current length of the port.
MPI-based components may call this function only in the root process.
- Parameters:
port – The name of the port to measure.
- Throws:
std::runtime_error – if this is a scalar port.
-
void set_port_length(std::string const &port, int length)
Resizes the port to the given length.
You should check whether the port is resizable using is_resizable() first; whether it is depends on how this component is wired up, so you should check.
MPI-based components may call this function only in the root process.
- Parameters:
port – Name of the port to resize.
length – The new length.
- Throws:
std::runtime_error – if the port is not resizable.
-
void send(std::string const &port_name, Message const &message)
Send a message to the outside world.
Sending is non-blocking, a copy of the message will be made and stored until the receiver is ready to receive it.
MPI-based components may call this function either in all processes, or only in the root process. In both cases, the message given by the root process will be sent, the others ignored.
- Parameters:
port_name – The port on which this message is to be sent.
message – The message to be sent.
-
void send(std::string const &port_name, Message const &message, int slot)
Send a message to the outside world.
Sending is non-blocking, a copy of the message will be made and stored until the receiver is ready to receive it.
MPI-based components may call this function either in all processes, or only in the root process. In both cases, the message given by the root process will be sent, the others ignored. You may want to do a gather operation first to collect all the information that is to be sent in the root process.
- Parameters:
port_name – The port on which this message is to be sent.
message – The message to be sent.
slot – The slot to send the message on.
-
Message receive(std::string const &port_name)
Receive a message from the outside world.
Receiving is a blocking operation. This function will contact the sender, wait for a message to be available, and receive and return it.
If the port you are receiving on is not connected, an exception will be thrown.
MPI-based components must call this function in all processes simultaneously. The received message will be returned in the root process, all other processes will receive a dummy message. It is therefore up to the model code to scatter or broadcast the received message to the non-root processes, if necessary.
- Parameters:
port_name – The endpoint on which a message is to be received.
- Throws:
std::runtime_error – if the given port is not connected.
- Returns:
The received message. The settings attribute of the received message will not be set.
-
Message receive(std::string const &port_name, Message const &default_msg)
Receive a message from the outside world.
Receiving is a blocking operation. This function will contact the sender, wait for a message to be available, and receive and return it.
If the port you are receiving on is not connected, the default value you specified will be returned exactly as you passed it.
MPI-based components must call this function in all processes simultaneously. The received message will be returned in the root process, all other processes will receive a dummy message. It is therefore up to the model code to scatter or broadcast the received message to the non-root processes, if necessary.
- Parameters:
port_name – The endpoint on which a message is to be received.
default_msg – A default value to return if this port is not connected.
- Throws:
std::runtime_error – if the given port is not connected and no default value was given.
- Returns:
The received message. The settings attribute of the received message will not be set.
-
Message receive(std::string const &port_name, int slot)
Receive a message from the outside world.
Receiving is a blocking operation. This function will contact the sender, wait for a message to be available, and receive and return it.
If the port you are receiving on is not connected, an exception will be thrown.
MPI-based components must call this function in all processes simultaneously. The received message will be returned in the root process, all other processes will receive a dummy message. It is therefore up to the model code to scatter or broadcast the received message to the non-root processes, if necessary.
- Parameters:
port_name – The endpoint on which a message is to be received.
slot – The slot to receive the message, on, if any.
- Throws:
std::runtime_error – if the given port is not connected and no default value was given.
- Returns:
The received message. The settings attribute of the received message will not be set.
-
Message receive(std::string const &port_name, int slot, Message const &default_msg)
Receive a message from the outside world.
Receiving is a blocking operation. This function will contact the sender, wait for a message to be available, and receive and return it.
If the port you are receiving on is not connected, the default value you specified will be returned exactly as you passed it. If you didn’t specify a default value (e.g. because there is no reasonable default, you really need the outside input) and the port is not connected, you’ll get a std::runtime_error thrown.
MPI-based components must call this function in all processes simultaneously. The received message will be returned in the root process, all other processes will receive a dummy message. It is therefore up to the model code to scatter or broadcast the received message to the non-root processes, if necessary.
- Parameters:
port_name – The endpoint on which a message is to be received.
slot – The slot to receive the message, on, if any.
default_msg – A default value to return if this port is not connected.
- Throws:
std::runtime_error – if the given port is not connected and no default value was given.
- Returns:
The received message. The settings attribute of the received message will not be set.
-
Message receive_with_settings(std::string const &port_name)
Receive a message with attached settings overlay.
This function should not be used in submodels. It is intended for use by special components that are ensemble-aware and have to pass on overlay settings explicitly.
Receiving is a blocking operation. This function will contact the sender, wait for a message to be available, and receive and return it.
If the port you are receiving on is not connected, an exception will be thrown.
MPI-based components must call this function in all processes simultaneously. The received message will be returned in the root process, all other processes will receive a dummy message. It is therefore up to the model code to scatter or broadcast the received message to the non-root processes, if necessary.
- Parameters:
port_name – The port on which a message is to be received.
- Throws:
std::runtime_error – if the given port is not connected.
- Returns:
The received message. The settings attribute of the received message will contain the received settings.
-
Message receive_with_settings(std::string const &port_name, int slot)
Receive a message with attached settings overlay.
This function should not be used in submodels. It is intended for use by special components that are ensemble-aware and have to pass on overlay settings explicitly.
Receiving is a blocking operation. This function will contact the sender, wait for a message to be available, and receive and return it.
If the port you are receiving on is not connected, an exception will be thrown.
MPI-based components must call this function in all processes simultaneously. The received message will be returned in the root process, all other processes will receive a dummy message. It is therefore up to the model code to scatter or broadcast the received message to the non-root processes, if necessary.
- Parameters:
port_name – The endpoint on which a message is to be received.
slot – The slot to receive the message, on, if any.
- Throws:
std::runtime_error – if the given port is not connected.
- Returns:
The received message. The settings attribute of the received message will contain the received settings.
-
Message receive_with_settings(std::string const &port_name, Message const &default_msg)
Receive a message with attached settings overlay.
This function should not be used in submodels. It is intended for use by special components that are ensemble-aware and have to pass on overlay settings explicitly.
Receiving is a blocking operation. This function will contact the sender, wait for a message to be available, and receive and return it.
If the port you are receiving on is not connected, the default value you specified will be returned exactly as you passed it. If you didn’t specify a default value (e.g. because there is no reasonable default, you really need the outside input) and the port is not connected, you’ll get a std::runtime_error thrown.
MPI-based components must call this function in all processes simultaneously. The received message will be returned in the root process, all other processes will receive a dummy message. It is therefore up to the model code to scatter or broadcast the received message to the non-root processes, if necessary.
- Parameters:
port_name – The endpoint on which a message is to be received.
default_msg – A default value to return if this port is not connected.
- Throws:
std::runtime_error – if the given port is not connected and no default value was given.
- Returns:
The received message. The settings attribute of the received message will contain the received settings.
-
Message receive_with_settings(std::string const &port_name, int slot, Message const &default_msg)
Receive a message with attached settings overlay.
This function should not be used in submodels. It is intended for use by special components that are ensemble-aware and have to pass on overlay settings explicitly.
Receiving is a blocking operation. This function will contact the sender, wait for a message to be available, and receive and return it.
If the port you are receiving on is not connected, the default value you specified will be returned exactly as you passed it. If you didn’t specify a default value (e.g. because there is no reasonable default, you really need the outside input) and the port is not connected, you’ll get a std::runtime_error thrown.
MPI-based components must call this function in all processes simultaneously. The received message will be returned in the root process, all other processes will receive a dummy message. It is therefore up to the model code to scatter or broadcast the received message to the non-root processes, if necessary.
- Parameters:
port_name – The endpoint on which a message is to be received.
slot – The slot to receive the message, on, if any.
default_msg – A default value to return if this port is not connected.
- Throws:
std::runtime_error – if the given port is not connected and no default value was given.
- Returns:
The received message. The settings attribute of the received message will contain the received settings.
-
bool resuming()
Check if this instance is resuming from a snapshot.
Must be used by submodels that implement the checkpointing API. You’ll get a RuntimeError if you don’t call this method in an iteration of the reuse loop.
This method returns True for the first iteration of the reuse loop after resuming from a previously taken snapshot. When resuming from a snapshot, the submodel must load its state from the snapshot returned by Instance::load_snapshot.
MPI-based components must call this function in all processes simultaneously.
- Returns:
true iff the submodel must resume from a snapshot.
-
bool should_init()
Check if this instance should initialize.
Must be used by submodels that implement the checkpointing API.
When resuming from a previous snapshot, instances need not always execute the F_INIT phase of the submodel execution loop. Use this method before attempting to receive data on F_INIT ports.
MPI-based components must call this function in all processes simultaneously.
- Returns:
true if the submodel must execute the F_INIT step.
- Returns:
false otherwise.
-
Message load_snapshot()
Load a snapshot.
Must only be called when Instance::resuming returns True.
MPI-based components may only call this from the root process. An error is raised when attempting to call this method in any other process. It is therefore up to the model code to scatter or broadcast the snapshot state to the non-root processes, if necessary.
- Returns:
Message containing the state as saved in a previous run through Instance::save_snapshot or Instance::save_final_snapshot.
-
bool should_save_snapshot(double timestamp)
Check if a snapshot should be saved after the S Operator of the submodel.
This method checks if a snapshot should be saved right now, based on the provided timestamp and elapsed wallclock time.
If this method returns true, then the submodel must also save a snapshot through Instance::save_snapshot. A std::runtime_error will be generated if this is not done.
See also Instance::should_save_final_snapshot for the variant that must be called at the end of the reuse loop.
MPI-based components must call this function in all processes simultaneously.
- Parameters:
timestamp – current timestamp of the submodel.
- Returns:
true iff a snapshot should be taken by the submodel according to the checkpoint rules provided in the ymmsl configuration.
-
void save_snapshot(Message message)
Save a snapshot after the S Operator of the submodel.
Before saving a snapshot, you should check using Instance::should_save_snapshot if a snapshot should be saved according to the checkpoint rules specified in the ymmsl configuration. You should use the same timestamp in the provided Message object as used to query Instance::should_save_snapshot.
MPI-based components may only call this from the root process. An error is raised when attempting to call this method in any other process. It is therefore up to the model code to gather the necessary state from the non-root processes before saving the snapshot.
- Parameters:
message – Message object that is saved as snapshot. The message timestamp attribute should be the same as passed to Instance::should_save_snapshot. The data attribute can be used to store the internal state of the submodel.
-
bool should_save_final_snapshot()
Check if a snapshot should be saved at the end of the reuse loop.
This method checks if a snapshot should be saved at the end of the reuse loop. All your communication on O_F ports must be finished before calling this method, otherwise your simulation may deadlock.
When this method returns true, the submodel must also save a snapshot through Instance::save_final_snapshot. A std::runtime_error will be generated if this is not done.
See also Instance::should_save_snapshot for the variant that may be called inside of a time-integration loop of the submodel.
MPI-based components must call this function in all processes simultaneously.
Note
This method will block until it can determine whether a final snapshot should be taken, because it must determine if this instance is reused.
- Returns:
true iff a final snapshot should be taken by the submodel according to the checkpoint rules provided in the ymmsl configuration.
-
void save_final_snapshot(Message message)
Save a snapshot at the end of the reuse loop.
Before saving a snapshot, you should check using Instance::should_save_final_snapshot if a snapshot should be saved according to the checkpoint rules specified in the ymmsl configuration.
See also Instance::save_snapshot for the variant that may be called after each S Operator of the submodel.
MPI-based components may only call this from the root process. An error is raised when attempting to call this method in any other process. It is therefore up to the model code to gather the necessary state from the non-root processes before saving the snapshot.
- Parameters:
message – Message object that is saved as snapshot. The data attribute can be used to store the internal state of the submodel.
-
Instance(int argc, char const *const argv[], MPI_Comm const &communicator = MPI_COMM_WORLD, int root = 0)
InstanceFlags
-
enum class libmuscle::InstanceFlags : int
Enumeration of properties that an instance may have.
You may combine multiple flags using the bitwise OR operator
|
. For example:auto flags = InstanceFlags::DONT_APPLY_OVERLAY | InstanceFlags::USES_CHECKPOINT_API; Instance instance(argc, argv, flags);
Values:
-
enumerator NONE
-
enumerator DONT_APPLY_OVERLAY
Do not apply the received settings overlay during prereceive of F_INIT messages.
If you’re going to use Instance.receive_with_settings on your F_INIT ports, you need to set this flag when creating an Instance.
If you don’t know what that means, do not specify this flag and everything will be fine. If it turns out that you did need to specify the flag, MUSCLE3 will tell you about it in an error message and you can add it still.
-
enumerator USES_CHECKPOINT_API
Indicate that this instance supports checkpointing.
You may not use any checkpointing API calls when this flag is not supplied.
-
enumerator KEEPS_NO_STATE_FOR_NEXT_USE
Indicate this instance does not carry state between iterations of the reuse loop.
Specifying this flag is equivalent to
ymmsl.KeepsStateForNextUse.NO
.By default, (if neither KEEPS_NO_STATE_FOR_NEXT_USE nor STATE_NOT_REQUIRED_FOR_NEXT_USE are provided), the instance is assumed to keep state between reuses, and to require that state (equivalent to
ymmsl.KeepsStateForNextUse.NECESSARY
).
-
enumerator STATE_NOT_REQUIRED_FOR_NEXT_USE
Indicate this instance carries state between iterations of the reuse loop, however this state is not required for restarting.
Specifying this flag is equivalent to
ymmsl.KeepsStateForNextUse.HELPFUL
.By default, (if neither KEEPS_NO_STATE_FOR_NEXT_USE nor STATE_NOT_REQUIRED_FOR_NEXT_USE are provided), the instance is assumed to keep state between reuses, and to require that state (equivalent to
ymmsl.KeepsStateForNextUse.NECESSARY
).
-
enumerator NONE
Message
-
class Message
A message to be sent or received.
This class describes a message to be sent or that has been received.
Public Functions
-
explicit Message(double timestamp)
Create an empty Message.
- Parameters:
timestamp – Simulation time for which this data is valid.
-
Message(double timestamp, DataConstRef const &data)
Create a Message.
- Parameters:
timestamp – Simulation time for which this data is valid.
data – An object to send or that was received.
-
Message(double timestamp, double next_timestamp, DataConstRef const &data)
Create a Message.
- Parameters:
timestamp – Simulation time for which this data is valid.
next_timestamp – Simulation time for the next message to be transmitted through this port.
data – An object to send or that was received.
-
Message(double timestamp, DataConstRef const &data, ymmsl::Settings const &settings)
Create a Message.
- Parameters:
timestamp – Simulation time for which this data is valid.
data – An object to send or that was received.
settings – Overlay settings to send or that were received.
-
Message(double timestamp, double next_timestamp, DataConstRef const &data, ymmsl::Settings const &settings)
Create a Message.
- Parameters:
timestamp – Simulation time for which this data is valid.
next_timestamp – Simulation time for the next message to be transmitted through this port.
data – An object to send or that was received.
settings – Overlay settings to send or that were received.
-
double timestamp() const
Returns the timestamp of the message.
-
void set_timestamp(double timestamp)
Sets the timestamp of the message.
- Parameters:
timestamp – The new value.
-
bool has_next_timestamp() const
Returns whether the message has a next timestamp.
-
double next_timestamp() const
Returns the next timestamp of the message.
Only call if has_next_timestamp() returns true.
- Throws:
std::logic_error – if the next timestamp is not set.
-
void set_next_timestamp(double next_timestamp)
Sets the next timestamp of the message.
- Parameters:
next_timestamp – The new value.
-
void unset_next_timestamp()
Unsets the next timestamp of the message.
-
const DataConstRef &data() const
Returns the data of the message.
-
void set_data(DataConstRef const &data)
Sets data to the given value.
- Parameters:
data – The new data to set.
-
bool has_settings() const
Returns whether the message carries settings.
-
const ::ymmsl::Settings &settings() const
Returns the settings carried by the message.
Only call if has_settings() returns true.
-
void set_settings(::ymmsl::Settings const &settings)
Sets settings to the given value.
This overwrites the entire Settings object, not a single value.
- Parameters:
settings – The new settings to use.
-
void unset_settings()
Unsets the settings of the message.
-
explicit Message(double timestamp)
PortsDescription
-
using libmuscle::PortsDescription = std::unordered_map<ymmsl::Operator, std::vector<std::string>>
A description of which ports a component has.
You can create one like this:
PortsDescription ports({ {Operator::F_INIT, {"port1", "port2"}}, {Operator::O_F, {"port3[]"}} });
and access elements as
ports[Operator::F_INIT][0] == "port1";
or for a const reference to a PortsDescription
ports.at(Operator::F_INIT)[1] == "port2";
Namespace ymmsl
allows_sending
allows_receiving
Conduit
-
class Conduit
A conduit transports data between simulation components.
A conduit has two endpoints, which are references to a Port on a Component. These references must be of one of the following forms:
submodel.port
namespace.submodel.port (or several namespace prefixes)
@attribute sender The sending port that this conduit is connected to. @attribute receiver The receiving port that this conduit is connected to.
Public Functions
-
Conduit(std::string const &sender, std::string const &receiver)
Create a Conduit.
- Parameters:
sender – The sending port that this conduit is connected to, including the component name and the port name.
receiver – The receiving port that this conduit is connected to, including the component name and the port name.
-
explicit operator std::string() const
Convert to string.
-
bool operator==(Conduit const &rhs) const
Compare two conduits for equality.
- Parameters:
rhs – The other conduit to compare with.
- Returns:
true iff the two conduits are identical.
-
Identifier sending_port() const
Returns the identity of the sending port.
-
std::vector<int> sending_slot() const
Returns the slot on the sending port.
If no slot was given, an empty list is returned.
Note that conduits connected to specific slots are currently not supported by MUSCLE3.
- Returns:
A list of slot indexes.
-
Identifier receiving_port() const
Returns the identity of the receiving port.
-
std::vector<int> receiving_slot() const
Returns the slot on the receiving port.
If no slot was given, an empty list is returned.
Note that conduits connected to specific slots are currently not supported by MUSCLE3.
- Returns:
A list of slot indexes.
Identifier
-
class Identifier
A custom string type that represents an identifier.
An identifier may consist of upper- and lowercase characters, digits, and underscores.
Public Functions
-
Identifier(std::string const &contents)
Create an Identifier.
This creates a new identifier object, using the given string.
- Parameters:
contents – The contents of the identifier.
- Throws:
std::invalid_argument – if contents is not a valid identifier.
-
Identifier(char const *const contents)
Create an Identifier.
This creates a new identifier object, using the given C-style string.
- Parameters:
contents – The contents of the identifier.
- Throws:
std::invalid_argument – if contents is not a valid identifier.
-
operator std::string() const
Implicit conversion to std::string.
This is a custom string class, so that’s appropriate.
- Returns:
The string representation of this Identifier.
-
bool operator==(Identifier const &rhs) const
Compare for equality.
- Parameters:
rhs – The Identifier to compare against.
- Returns:
True iff both Identifiers are equal.
-
bool operator==(std::string const &rhs) const
Compare for equality against a string.
- Parameters:
rhs – The string to compare against.
- Returns:
True iff the Identifier matches the string.
-
bool operator==(char const *const rhs) const
Compare for equality against a C-style string.
- Parameters:
rhs – The string to compare against.
- Returns:
True iff the Identifier matches the string.
-
bool operator!=(Identifier const &rhs) const
Compare for inequality.
- Parameters:
rhs – The Identifier to compare against.
- Returns:
True iff both Identifiers are different.
-
bool operator!=(std::string const &rhs) const
Compare for inequality against a string.
- Parameters:
rhs – The string to compare against.
- Returns:
True iff the Identifier is different from the string.
-
bool operator!=(char const *const rhs) const
Compare for inequality against a C-style string.
- Parameters:
rhs – The string to compare against.
- Returns:
True iff the Identifier is different from the string.
-
Identifier(std::string const &contents)
-
std::ostream &ymmsl::operator<<(std::ostream &os, Identifier const &i)
Operator
Port
-
struct Port
A port on a component.
Ports are used by components to send or receive messages on. They are connected by conduits to enable communication between components.
Subclassed by libmuscle::Port
Public Functions
-
Port(Identifier const &name, Operator oper)
The MMSL operator in which this port is used.
Create a Port.
- Parameters:
name – The name of the port.
oper – The MMSL operator in which this port is used.
-
Port(Identifier const &name, Operator oper)
Reference
-
class Reference
A reference to an object in the MMSL execution model.
References in string form are written as either:
an Identifier,
a Reference followed by a period and an Identifier, or
a Reference followed by an integer enclosed in square brackets.
In object form, they consist of a list of Identifiers and ints. The first list item is always an Identifier. For the rest of the list, an Identifier represents a period operator with that argument, while an int represents the indexing operator with that argument.
Reference objects act like a list of Identifiers and ints, you can get their length using length(), iterate through the parts using cbegin() and cend(), and get individual items using []. Note that the sublist has to be a valid Reference, so it cannot start with an int.
References can be compared for equality to each other or to a plain string, and they can be used as dictionary keys. Reference objects are immutable (or they’re supposed to be anyway), so do not try to change any of the elements. Instead, make a new Reference. Especially References that are used as dictionary keys must not be modified, this will get your dictionary in a very confused state.
Public Types
-
typedef std::vector<ReferencePart>::const_iterator const_iterator
Random access iterator type for a Reference.
Public Functions
-
Reference(std::string const &content)
Create a Reference from a string.
Creates a Reference from a string, which will be parsed.
- Parameters:
content – A string to parse.
- Throws:
std::invalid_argument – if the argument does not define a valid Reference.
-
Reference(char const *content)
Create a Reference from a C string.
Creates a Reference from a C string, which will be parsed.
- Parameters:
content – A string to parse.
- Throws:
std::invalid_argument – if the argument does not define a valid Reference.
-
template<class ForwardIt>
Reference(ForwardIt begin, ForwardIt end) Create a Reference from a ReferencePart range.
*begin and *end must be of type ReferencePart.
- Parameters:
begin – An iterator to the start of the range.
end – An iterator to the end of the range.
-
explicit operator std::string() const
Conversion to std::string.
- Returns:
The string representation of this Identifier.
-
bool operator==(Reference const &rhs) const
Compares for equality.
Will compare part-by-part.
- Parameters:
rhs – The Reference to compare with.
- Returns:
True iff the two References are equal.
-
bool operator==(std::string const &rhs) const
Compares for equality.
Compares string representations.
- Parameters:
rhs – The string to compare with.
- Returns:
True iff this Reference matches the given string.
-
bool operator==(char const *rhs) const
Compares for equality.
Compares string representations.
- Parameters:
rhs – The string to compare with.
- Returns:
True iff this Reference matches the given string.
-
bool operator!=(Reference const &rhs) const
Compares for inequality.
Will compare part-by-part.
- Parameters:
rhs – The Reference to compare with.
- Returns:
True iff the two References are different.
-
bool operator!=(std::string const &rhs) const
Compares for inequality.
Compares string representations.
- Parameters:
rhs – The string to compare with.
- Returns:
True iff this Reference does not match the given string.
-
bool operator!=(char const *rhs) const
Compares for inequality.
Compares string representations.
- Parameters:
rhs – The string to compare with.
- Returns:
True iff this Reference does not match the given string.
-
const_iterator cbegin() const
Returns a const_iterator to the beginning of the Reference.
-
const_iterator cend() const
Returns a const_iterator to one-past-the-end of the Reference.
-
const_iterator begin() const
Returns a const_iterator to the beginning of the Reference.
-
const_iterator end() const
Returns a const_iterator to one-past-the-end of the Reference.
-
const ReferencePart &operator[](int i) const
Returns the ReferencePart at the given index.
- Parameters:
i – The index to dereference.
- Returns:
The ReferencePart at that index.
-
const Reference &operator+=(ReferencePart const &rhs)
Append a part to this Reference.
- Parameters:
rhs – The part to append.
- Returns:
A reference to this (updated) object.
-
const Reference &operator+=(std::vector<int> const &rhs)
Append a list of indexes to this Reference.
- Parameters:
rhs – The indexes to append.
- Returns:
A reference to this (updated) object.
-
Reference operator+(ReferencePart const &rhs) const
Append a ReferencePart to this Reference to create a new one.
- Parameters:
rhs – The ReferencePart to append to this one to produce the new Reference.
-
class ReferencePart
An item in a Reference.
Public Functions
-
ReferencePart(Identifier const &i)
Create a ReferencePart containing an Identifier.
This is implicit, so that you can give an Identifier wherever a ReferencePart is required.
- Parameters:
i – The Identifier to store.
-
ReferencePart(int index)
Create a ReferencePart containing an index.
This is implicit, so that you can give an int wherever a ReferencePart is required.
- Parameters:
index – The index to store.
-
bool is_identifier() const
Returns whether this Part holds an Identifier.
- Returns:
True iff this holds an Identifier.
-
bool is_index() const
Returns whether this Part holds an index.
- Returns:
True iff this holds an index.
-
const Identifier &identifier() const
Returns the Identifier value.
- Throws:
std::runtime_error – if this object does not hold an Identifier.
- Returns:
The identifier value.
-
int index() const
Returns the index value.
- Throws:
std::runtime_error – if this object does not hold an index.
- Returns:
The index value.
-
bool operator==(ReferencePart const &rhs) const
Compares for equality.
- Parameters:
rhs – The ReferencePart to compare with.
- Returns:
True if both type and value match.
-
bool operator!=(ReferencePart const &rhs) const
Compares for inequality.
- Parameters:
rhs – The ReferencePart to compare with.
- Returns:
True if type or value mismatch.
-
ReferencePart(Identifier const &i)
Settings
-
class Settings
Settings for doing an experiment.
An experiment is done by running a model with particular settings, e.g. the submodel scales, model parameters, and any other settings.
Public Functions
-
Settings(std::initializer_list<MapType_::value_type> const &init)
Create a Settings object with the given settings.
- Parameters:
init – An initializer list with pairs of {Reference, SettingValue}
-
bool operator==(Settings const &rhs) const
Compare Settings objects for equality.
- Returns:
True iff the Settings are equal.
-
bool operator!=(Settings const &rhs) const
Compare Settings objects for inequality.
- Returns:
True iff the Settings are not equal.
-
std::size_t size() const
Return the number of settings in this object.
-
bool empty() const
Return true iff this object has no settings.
-
bool contains(Reference const &setting) const
Return true iff a setting with this name exists here.
- Parameters:
setting – Name of the setting to check for.
- Returns:
true iff it exists.
-
const SettingValue &at(Reference const &setting) const
Get the value of a given setting.
- Parameters:
setting – The name of the setting to read.
- Throws:
std::out_of_range – if there is no setting with that name.
- Returns:
The value of that setting.
-
SettingValue &operator[](Reference const &setting)
Set the value of a given setting.
Adds the setting first if it does not exist.
- Parameters:
setting – The name of the setting to read.
- Returns:
A reference to the setting’s value that can be modified.
-
std::size_t erase(std::string const &setting)
Removes setting with the given key.
- Parameters:
setting – Key of the setting to remove.
- Returns:
The number of settings removed (0u or 1u).
-
void clear()
Removes all settings.
-
const_iterator begin() const
Return an iterator to the first setting.
The iterator dereferences to a std::pair<Reference, SettingValue>.
-
const_iterator end() const
Return an iterator past the last setting.
-
Settings(std::initializer_list<MapType_::value_type> const &init)
SettingValue
-
class SettingValue
Holds the value of a setting.
This is a discriminated union that can contain a std::string, an int64_t, a double, a bool, a std::vector<double> or a std::vector<std::vector<double>>.
Values of these types will be automatically converted wherever a SettingValue is required.
Public Functions
-
SettingValue()
Create an empty (and invalid) SettingValue.
-
SettingValue(std::string const &value)
Create a SettingValue containing a string.
- Parameters:
value – The string value to hold.
-
SettingValue(char const *value)
Create a SettingValue containing a string.
- Parameters:
value – The string value to hold.
-
SettingValue(int value)
Create a SettingValue containing an int64_t.
- Parameters:
value – The value to hold.
-
SettingValue(long int value)
Create a SettingValue containing an int64_t.
- Parameters:
value – The value to hold.
-
SettingValue(long long int value)
Create a SettingValue containing an int64_t.
- Parameters:
value – The value to hold.
-
SettingValue(double value)
Create a SettingValue containing a double.
- Parameters:
value – The value to hold.
-
SettingValue(bool value)
Create a SettingValue containing a bool.
- Parameters:
value – The value to hold.
-
SettingValue(std::initializer_list<double> value)
Create a SettingValue containing a std::vector<double>.
This covers SettingValue({1.0, 2.0, 3.0});
- Parameters:
value – The value to hold.
-
SettingValue(std::vector<double> const &value)
Create a SettingValue containing a std::vector<double>.
- Parameters:
value – The value to hold.
-
SettingValue(std::initializer_list<std::vector<double>> const &value)
Create a SettingValue containing a std::vector<std::vector<double>>.
This covers SettingValue({{1.0, 2.0}, {3.0, 4.0}});
- Parameters:
value – The value to hold.
-
SettingValue(std::vector<std::vector<double>> const &value)
Create a SettingValue containing a std::vector<std::vector<double>>.
- Parameters:
value – The value to hold.
-
SettingValue(SettingValue const &other)
Copy-constructs a SettingValue.
-
SettingValue(SettingValue &&other)
Move-constructs a SettingValue.
-
SettingValue &operator=(SettingValue const &other)
Copy-assigns a SettingValue.
-
SettingValue &operator=(SettingValue &&other)
Move-assigns a SettingValue.
-
~SettingValue()
Destructs a SettingValue.
-
bool operator==(SettingValue const &rhs) const
Compare against another SettingValue.
Returns true iff both type and value are the same.
- Parameters:
rhs – The value to compare with.
-
bool operator!=(SettingValue const &rhs) const
Compare against another SettingValue.
Returns true iff both type and value are the same.
- Parameters:
rhs – The value to compare with.
-
template<typename T>
bool is_a() const Return whether this SettingValue holds a value of the given type.
Note that for int32_t, this function will return true only if the value is integer and fits in an int32_t. For double, it will return true if the value is integer, even if converting it to a double would reduce precision.
Since int and long are usually equivalent to int32_t or int64_t, you can use those values too.
- Parameters:
T – A valid type, being one of std::string, int32_t, int64_t, double, bool, std::vector<double>, or std::vector<std::vector<double>>.
-
template<typename T>
T as() const Return the value as the given type.
Only call if is_a<T>() returns true.
- Parameters:
T – A valid type, being one of std::string, int32_t, int64_t, double, bool, std::vector<double>, or std::vector<std::vector<double>>.
- Throws:
std::bad_cast – if the type of this value does not match the template parameter.
-
SettingValue()
-
std::ostream &ymmsl::operator<<(std::ostream &os, ymmsl::SettingValue const &val)
Outputs a human-readable representation of the SettingValue to a stream.
This makes it so you can use e.g. std::cout << setting_value.