API Documentation for C++¶
This page provides full documentation for the C++ API of MUSCLE 3.
Note that in a few places, classes are referred to as
libmuscle::impl::<class>
. This is a bug in the documentation rendering
process, the class is actually available as libmuscle::<class>
and
should be used as such.
Namespace libmuscle¶
-
class Data : public libmuscle::impl::DataConstRef¶
A data object.
This represents a data object, which is what MUSCLE 3 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::impl::ClosePort
Public Functions
-
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] = "MUSCLE 3";
- 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.
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 &operator=(Data const &rhs)¶
-
class DataConstRef¶
A const reference to some kind of data.
This defines a read-only API for variable data objects, which is what MUSCLE 3 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::impl::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.
-
char const *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>
Element const *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.
-
DataConstRef()¶
-
class Instance¶
Represents a compute element 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 compute elements, 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 compute elements, 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).
-
bool reuse_instance(bool apply_overlay = true)¶
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 compute elements must execute the reuse loop in each process in parallel, and call this function at the top of the reuse loop in each process.
- Parameters
apply_overlay – Whether to apply the received settings overlay or to save it. If you’re going to use receive_with_settings() on your F_INIT ports, set this to false. If you don’t know what that means, just call reuse_instance() without specifying this and everything will be fine. If it turns out that you did need to specify false, MUSCLE 3 will tell you about it in an error message and you can add it.
-
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 compute elements 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.
-
::ymmsl::SettingValue get_setting(std::string const &name) const¶
Returns the value of a model setting.
MPI-based compute elements 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.
-
template<typename ValueType>
ValueType get_setting_as(std::string const &name) const¶ Returns the value of a model setting.
MPI-based compute elements 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.
-
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 compute elements 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 compute elements 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 compute elements 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 compute elements 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 compute elements 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 compute element is wired up, so you should check.
MPI-based compute elements 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 compute elements 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 compute elements 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 compute elements 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 compute elements 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 compute elements 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 compute elements 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 compute elements 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 compute elements 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 compute elements 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 compute elements 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 compute elements 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 compute elements 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 compute elements 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 compute elements 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.
-
class Impl¶
-
Instance(int argc, char const *const argv[], MPI_Comm const &communicator = MPI_COMM_WORLD, int root = 0)¶
-
class Message¶
A message to be sent or received.
This class describes a message to be sent or that has been received.
Public Functions
-
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.
-
DataConstRef const &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.
-
::ymmsl::Settings const &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.
-
Message(double timestamp, DataConstRef const &data)¶
-
typedef std::unordered_map<ymmsl::Operator, std::vector<std::string>> libmuscle::impl::PortsDescription¶
A description of which ports a compute element 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¶
-
bool ymmsl::impl::allows_sending(Operator op)¶
Whether the given operator allows sending messages.
- Parameters
op – The operator to check.
- Returns
true If and only if the operator allows sending
-
bool ymmsl::impl::allows_receiving(Operator op)¶
Whether the given operator allows receiving messages.
- Parameters
op – The operator to check.
- Returns
true If and only if the operator allows receiving
-
class Conduit¶
A conduit transports data between compute elements.
A conduit has two endpoints, which are references to a Port on a Compute Element. These references must be of one of the following forms:
submodel.port
namespace.submodel.port (or several namespace prefixes)
sender The sending port that this conduit is connected to. 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 compute element name and the port name.
receiver – The receiving port that this conduit is connected to, including the compute element 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 MUSCLE 3.
- 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 MUSCLE 3.
- Returns
A list of slot indexes.
-
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::impl::operator<<(std::ostream &os, Identifier const &i)¶
-
enum ymmsl::impl::Operator¶
An operator of a Compute Element.
This is a combination of the Submodel Execution Loop operators, and operators for other components such as mappers.
Values:
-
enumerator NONE¶
-
enumerator F_INIT¶
-
enumerator O_I¶
-
enumerator S¶
-
enumerator B¶
-
enumerator O_F¶
-
enumerator NONE¶
-
struct Port¶
A port on a compute element.
Ports are used by compute elements to send or receive messages on. They are connected by conduits to enable communication between compute elements.
Subclassed by libmuscle::impl::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)¶
-
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.
-
ReferencePart const &operator[](int i) const¶
Returns the ReferencePart at the given index.
- Parameters
i – The index to dereference.
- Returns
The ReferencePart at that index.
-
Reference const &operator+=(ReferencePart const &rhs)¶
Append a part to this Reference.
- Parameters
rhs – The part to append.
- Returns
A reference to this (updated) object.
-
Reference const &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.
-
Identifier const &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.
-
ReferencePart(Identifier const &i)¶
-
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
-
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.
-
SettingValue const &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.
-
bool operator==(Settings const &rhs) const¶
-
std::ostream &ymmsl::impl::operator<<(std::ostream &os, ymmsl::impl::Settings const &settings)¶
Outputs a human-readable representation of the Settings to a stream.
This makes it so you can use e.g. std::cout << settings.
-
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(int64_t 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::impl::operator<<(std::ostream &os, ymmsl::impl::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.