Material classes

This section describes the classes required to generate Material objects. This is done by a factory class called MaterialDefinition. The latter accumulates three pieces of information:

  • The ThermoFrame object, representing the thermodynamic model itself,

  • the InitialState object, defining the default initialisation of the object, and

  • the ThermoParameterStore object, being the source for thermodynamic parameters.

Once the MaterialDefinition object is created, it can fabricate Material objects according to its definition.

A ThermoParameterStore instance administers any number of AbstractThermoSource implementations, the actual sources of data that can be represented by parsed data files or adapters to databases. We provide some basic implementations by NestedDictThermoSource and StringDictThermoSource.

ThermoParameterStore

class simu.ThermoParameterStore

This class connects both to the thermodynamic model instances by providing the parameters, and to the model’s numerical interface by providing the symbols and values of all used parameters, allowing those to be altered dynamically and optimised on.

The important aspect here is that a process model can have hundreds of thermodynamic model instances, and while they do not need to, most of them usually share the same parameters.

Adapted to the SiMu data flow, the initial queries by the models to fetch parameters are of symbolic nature, using get_symbols() and get_all_symbols(). This happens during the model definition and assures that multiple model instances that ask for the same parameter receive the same symbol, such that parameter optimisation tasks can be accomplished easily.

In the (numerical) evaluation phase, the store is asked for the actual values via get_all_values(). In most cases these are used as constants in the calculations, but parameter estimation is possible by keeping selected parameters as free variables.

__init__(name: str = None)
get_symbols(
parameter_struct: NestedMap[str],
) NestedMap[Quantity]

Query the nested structure of parameter symbols from the store. The parameter_struct parameter is a nested dictionary with leaf entries being the unit of measurement of the thermodynamic parameters defined by the path of keys to address them.

The method returns a dictionary of the same structure, but with symbolic quantities as leaf values.

With multiple calls to this method with varying parameter structs, previously defined symbols will be reused, and a DimensionalityError is raised if such previously defined symbol is incompatible with respect to the physical dimension.

get_all_symbols() NestedMap[Quantity]

This method returns all previously prepared symbols, cf. get_symbols(), as a nested dictionary of symbolic quantities

get_all_values() NestedMap[Quantity]

This method seeks in connected data sources for all previously prepared symbols.

A KeyError is thrown if not all required parameters are available. Use get_missing_symbols() to get the structure of missing parameters.

The sources are queried sequentially in the reverse sequence of them being added, i.e. latest added Sources supersede previous values of same parameters.

get_values(
parameter_struct: NestedMap[str],
) NestedMap[Quantity]

Query a specific substructure of values from the connected data sources.

get_missing_symbols() NestedMap[str]

This method tries to collect values for all previously prepared symbols and returns a nested dictionary of quantities with those not found.

get_sources() NestedMap[str]

This method returns the name of the data source in which the individual values are found

add_source(
name: str,
source: AbstractThermoSource,
)

Add a given source of thermodynamic parameters to the store.

AbstractThermoSource

class simu.AbstractThermoSource

Any source of thermodynamic parameters is to return a Quantity object if the path describes an available property.

Implementations of this class can be added to the ThermoParameterStore to represent a source of thermodynamic parameters. It is advisable to arrange source objects by bibliographic sources.

Note

We would have loved to download large databases of thermodynamic properties and to publish them with this software. Unfortunate for this particular aspect, there are terms like copyright and license that prohibit this.

While it is completely legal to obtain thermodynamic parameters for free from many sources for the sake of working with them, re-publishing compiled databases under the LGPL license is another thing.

abstractmethod __getitem__(
path: Iterable[str],
) Quantity

This operator is used to extract a value from the source, addressed by a sequence of keys to navigate into the nested data structure:

>>> struct = {"T": {"H2O": "100 K", "NH3": "200 K"},
...           "p": {"H2O": "10 bar", "NH3": "20 atm"}}
>>> source = StringDictThermoSource(struct)
>>> print(source["T", "H2O"])
100 kelvin

A KeyError is raised if either a key does not exist or if the final key still has sub-keys.

__init__()
classmethod __new__(*args, **kwargs)

NestedDictThermoSource

class simu.NestedDictThermoSource

Bases: AbstractThermoSource

A source of thermodynamic parameters defined by a nested dictionary of Quantities

__init__(
data: NestedMap[Quantity],
)
classmethod __new__(*args, **kwargs)

StringDictThermoSource

class simu.StringDictThermoSource

Bases: NestedDictThermoSource

Source of thermodynamic parameters defined by a nested dictionary. The leaf entries of the nested dictionary are strings representing the quantities, such as “120 K” or “32.1 kJ/(mol*K)”.

__init__(data: NestedMap[str])
classmethod __new__(*args, **kwargs)

MaterialDefinition

class simu.MaterialDefinition

A MaterialDefinition object defines a material type by its

  • frame of thermodynamic contributions,

  • initial state

  • source of thermodynamic parameters

__init__(
frame: ThermoFrame,
initial_state: InitialState,
store: ThermoParameterStore,
)
property spec: MaterialSpec

Return a material spec object that is implemented by this definition

property species: Collection[str]

The species names

Material

class simu.Material

Bases: MutableMapping[str, Quantity | QuantityDict]

This class represents a material

__init__(definition: MaterialDefinition, flow: bool)

Define a material based on the given definition. The flow flag indicates whether a flow or a state is to be generated.

definition: MaterialDefinition

The underlying definition

initial_state: InitialState

The provided initial state

property species: Collection[str]

The species names

property sym_state: Mapping[str, Quantity]

A dictionary of quantities representing the state

property bounds: NestedMap[Quantity]

Return the bounds of the material as a nested mapping. The top level keys will be the names of the original contributions, while the second level keys will be the names of the bounds. The mapping will only have these two levels.

residuals(
normed: bool = False,
) NestedMap[Quantity]

Return the residuals of the material as a nested mapping. The top level keys will be the names of the original contributions, while the second level keys will be the names of the residuals. The mapping will only have these two levels.

If normed is true, return the dimensionless ratio of residual values and their tolerances instead.

__getitem__(key: str) Quantity

Return a (symbolic) property that is calculated by the underlying thermodynamic model or later supplements via __setitem__().

__setitem__(key: str, symbol: Quantity)

Supplement the material with another property. The symbol argument must be a symbolic quantity, and it is highly immoral to supply a symbol that is a function of more than prior material properties.

is_flow()

Return if the material represents a flow (True) or not (False)

It is possible to advise the Material class to export also the properties with leading underscore, thus providing a valuable tool for debugging model contributions. For this purpose:

simu.core.thermo.material.set_export_all_properties(flag: bool)

Set flag whether to export all properties, even those with leading underscore. This affects all material instances built after the call.

Note

Vector properties with leading underscore are exported as a single vector quantity instance, if they are not declared as vector. This is normally acceptable, as these hidden properties are not meant to be input for the process model. If they were, a contribution should be defined to elevate the property to an ordinary one, such as

res["T_c"] = res["_T_c"]

MaterialSpec

class simu.MaterialSpec

Representation of a requirement to a material object.

Objects of this class are used to define the requirements to a material, typically in a material port of a Model. It defines which species are required and whether additional species are allowed.

__init__(
species: Iterable[str] | None = None,
flow: bool = True,
)

Create an instance based on the arguments as follows:

Species:

If None (default), allow any species. If containing a species name *, allow any species, but demand the species that are element of the given iterable. If species does not contain *, lock the specification to the given set of species.

Flow:

True if the material needs to represent a flow, False if a state is to be represented.

class property flow

A generic flow instance, allowing any species

class property state

A generic state instance, allowing any species

property species: set[str]

The set of species that must be provided

property locked: bool

Whether the specification allows other species than the ones listed as species.

is_flow() bool

Whether the specification is a flow (True) or a state (False)

is_compatible(material: Material) bool

Return true if the given material is compatible with this one. That is:

  • none of the specified species are missing in the material

  • if specification locks species set, none of the material species are missing in the specification

  • flows are only compatible with flows, states are only compatible with states.