Note

Last update 20/07/2021

Reference

This reference provides details of the classes within SuperflexPy. This page is limited to the core framework (i.e. content of superflexpy/framework/ and superflexpy/utils/), in order to provide a clear reference for the classes that should be customized to extend SuperflexPy. Particular implementations of components (i.e. the content of superflexpy/implementation/) are not included.

The following diagram follows the standards of UML and shows the organization of the classes composing the framework. All the classes in the diagram can be extended through inheritance to create customized components.

_images/class_uml.png

superflexpy.framework.element

class superflexpy.framework.element.BaseElement(id)[source]

Bases: object

This is the abstract class for the creation of a BaseElement. A BaseElement does not have parameters or states.

_num_downstream = None

Number of downstream elements

_num_upstream = None

Number of upstream elements

input = {}

Dictionary of input fluxes

__init__(id)[source]

This is the initializer of the abstract class BaseElement.

Parameters:

id (str) – Identifier of the element. All the elements of the framework must have an identifier.

set_input(input)[source]

To be implemented by any child class. It populates the self.input dictionary.

Parameters:

input (list(numpy.ndarray)) – List of input fluxes to the element.

get_output(solve=True)[source]

To be implemented by any child class. It solves the element and returns the output fluxes.

Parameters:

solve (bool) – True if the element has to be solved (i.e. calculate the states).

Returns:

List of output fluxes.

Return type:

list(numpy.ndarray)

property num_downstream

Number of downstream elements.

property num_upstream

Number of upstream elements

class superflexpy.framework.element.ParameterizedElement(parameters, id)[source]

Bases: BaseElement

This is the abstract class for the creation of a ParameterizedElement. A ParameterizedElement has parameters but not states.

_prefix_parameters = ''

Prefix applied to the original names of the parameters

__init__(parameters, id)[source]

This is the initializer of the abstract class ParameterizedElement.

Parameters:
  • parameters (dict) – Parameters controlling the element. The parameters can be either a float (constant in time) or a numpy.ndarray of the same length of the input fluxes (time variant parameters).

  • id (str) – Identifier of the element. All the elements of the framework must have an identifier.

get_parameters(names=None)[source]

This method returns the parameters of the element.

Parameters:

names (list(str)) – Names of the parameters to return. The names must be the ones returned by the method get_parameters_name. If None, all the parameters are returned.

Returns:

Parameters of the element.

Return type:

dict

get_parameters_name()[source]

This method returns the names of the parameters of the element.

Returns:

List with the names of the parameters.

Return type:

list(str)

set_parameters(parameters)[source]

This method sets the values of the parameters.

Parameters:

parameters (dict) – Contains the parameters of the element to be set. The keys must be the ones returned by the method get_parameters_name. Only the parameters that have to be changed should be passed.

add_prefix_parameters(prefix)[source]

This method add a prefix to the name of the parameters of the element.

Parameters:

prefix (str) – Prefix to be added. It cannot contain ‘_’.

class superflexpy.framework.element.StateElement(states, id)[source]

Bases: BaseElement

This is the abstract class for the creation of a StateElement. A StateElement has states but not parameters.

_prefix_states = ''

Prefix applied to the original names of the parameters

__init__(states, id)[source]

This is the initializer of the abstract class StateElement.

Parameters:
  • states (dict) – Initial states of the element. Depending on the element the states can be either a float or a numpy.ndarray.

  • id (str) – Identifier of the element. All the elements of the framework must have an id.

get_states(names=None)[source]

This method returns the states of the element.

Parameters:

names (list(str)) – Names of the states to return. The names must be the ones returned by the method get_states_name. If None, all the states are returned.

Returns:

States of the element.

Return type:

dict

get_states_name()[source]

This method returns the names of the states of the element.

Returns:

List with the names of the states.

Return type:

list(str)

set_states(states)[source]

This method sets the values of the states.

Parameters:

states (dict) – Contains the states of the element to be set. The keys must be the ones returned by the method get_states_name. Only the states that have to be changed should be passed.

reset_states()[source]

This method sets the states to the values provided to the __init__ method. If a state was initialized as None, it will not be reset.

add_prefix_states(prefix)[source]

This method add a prefix to the id of the states of the element.

Parameters:

prefix (str) – Prefix to be added. It cannot contain ‘_’.

class superflexpy.framework.element.StateParameterizedElement(parameters, states, id)[source]

Bases: StateElement, ParameterizedElement

This is the abstract class for the creation of a StateParameterizedElement. A StateParameterizedElement has parameters and states.

__init__(parameters, states, id)[source]

This is the initializer of the abstract class StateParameterizedElement.

Parameters:
  • parameters (dict) – Parameters controlling the element. The parameters can be either a float (constant in time) or a numpy.ndarray of the same length of the input fluxes (time variant parameters).

  • states (dict) – Initial states of the element. Depending on the element the states can be either a float or a numpy.ndarray.

  • id (str) – Identifier of the element. All the elements of the framework must have an id.

class superflexpy.framework.element.ODEsElement(parameters, states, approximation, id)[source]

Bases: StateParameterizedElement

This is the abstract class for the creation of a ODEsElement. An ODEsElement is an element with states and parameters that is controlled by an ordinary differential equation, of the form:

dS/dt = input - output

_num_upstream = 1

Number of upstream elements

_num_downstream = 1

Number of downstream elements

_solver_states = []

List of states used by the solver of the differential equation

_fluxes = []

This attribute contains a list of methods (one per differential equation) that calculate the values of the fluxes needed to solve the differential equations that control the element. The single functions must return the fluxes as a list where incoming fluxes are positive and outgoing are negative. Here is a list of the required outputs of the single functions:

list(floats)

Values of the fluxes given states, inputs, and parameters.

float

Minimum value of the state. Used, sometimes, by the numerical solver to search for the solution.

float

Maximum value of the state. Used, sometimes, by the numerical solver to search for the solution.

list(floats)

Values of the derivatives of the fluxes w.r.t. the states.

__init__(parameters, states, approximation, id)[source]

This is the initializer of the abstract class ODEsElement.

Parameters:
  • parameters (dict) – Parameters controlling the element. The parameters can be either a float (constant in time) or a numpy.ndarray of the same length of the input fluxes (time variant parameters).

  • states (dict) – Initial states of the element. Depending on the element the states can be either a float or a numpy.ndarray.

  • approximation (superflexpy.utils.numerical_approximation.NumericalApproximator) – Numerial method used to approximate the differential equation

  • id (str) – Identifier of the element. All the elements of the framework must have an id.

set_timestep(dt)[source]

This method sets the timestep used by the element.

Parameters:

dt (float) – Timestep

get_timestep()[source]

This method returns the timestep used by the element.

Returns:

Timestep

Return type:

float

define_numerical_approximation(approximation)[source]

This method define the solver to use for the differential equation.

Parameters:

solver (superflexpy.utils.root_finder.RootFinder) – Solver used to find the root(s) of the differential equation(s). Child classes may implement their own solver, therefore the type of the solver is not enforced.

_solve_differential_equation(**kwargs)[source]

This method calls the solver of the differential equation(s). When called, it solves the differential equation(s) for all the timesteps and populates self.state_array.

class superflexpy.framework.element.LagElement(parameters, states, id)[source]

Bases: StateParameterizedElement

This is the abstract class for the creation of a LagElement. An LagElement is an element with states and parameters that distributes the incoming fluxes according to a weight array

Parameters must be called:

  • ‘lag-time’: characteristic time of the lag. Its definition depends on the specific implementations of the element. It can be a scalar (it will be applied to all the fluxes) or a list (with length equal to the number of fluxes).

States must be called:

  • lag: initial state of the lag function. If None it will be initialized to zeros. It can be a numpy.ndarray (it will be applied to all the fluxes) of a list on numpy.ndarray (with length equal to the number of fluxes).

_num_upstream = 1

Number of upstream elements

_num_downstream = 1

Number of downstream elements

_build_weight(lag_time)[source]

This method must be implemented by any child class. It calculates the weight array(s) based on the lag_time.

Parameters:

lag_time (float) – Characteristic time of the lag function.

Returns:

List of weight array(s).

Return type:

list(numpy.ndarray)

set_input(input)[source]

This method sets the inputs to the elements. Since the name of the inputs is not important, the fluxes are stored as list.

Parameters:

input (list(numpy.ndarray)) – List of input fluxes.

get_output(solve=True)[source]

This method returns the output of the LagElement. It applies the lag to all the incoming fluxes, according to the weight array(s).

Parameters:

solve (bool) – True if the element has to be solved (i.e. calculate the states).

Returns:

List of output fluxes.

Return type:

list(numpy.ndarray)

reset_states()[source]

This method sets the states to the values provided to the __init__ method. In this case, if a state was initialized as None, it will be set back to None.

static _solve_lag(weight, lag_state, input)[source]

This method distributes the input fluxes according to the weight array and the initial state.

Parameters:
  • weight (list(numpy.ndarray)) – List of weights to use

  • lag_state (list(numpy.ndarray)) – List of the initial states of the lag.

  • input (list(numpy.ndarray)) – List of fluxes

Returns:

3D array (dimensions: number of timesteps, number of fluxes, max lag length) that stores all the states of the lag in time

Return type:

numpy.ndarray

_init_lag_state(lag_time)[source]

This method sets the initial state of the lag to arrays of proper length.

Parameters:

lag_time (list(float)) – List of lag times

Returns:

List of the initial states of the lag.

Return type:

list(numpy.ndarray)

superflexpy.utils.generic_component

class superflexpy.utils.generic_component.GenericComponent[source]

Bases: object

This is the abstract class for the creation of the components Unit, Node, and Network. It defines a series of methods that are common among the components.

_content_pointer = {}

Dictionary that maps the id of the components to their location

_content = []

List (or dictionary) of the component contained

_local_parameters = {}

Dictionary that contains the parameters that are specific to the component

_local_states = {}

Dictionary that contains the states that are specific to the component

_init_local_states = {}

Dictionary that contains the value of the states, which that are specific to the component, at initialization.

_prefix_local_parameters = ''

Prefix applied to local parameters

_prefix_local_states = ''

Prefix applied to local states

get_parameters(names=None)[source]

This method returns the parameters of the component and of the ones contained.

Parameters:

names (list(str)) – Names of the parameters to return. The names must be the ones returned by the method get_parameters_name. If None, all the parameters are returned.

Returns:

Parameters of the element.

Return type:

dict

get_parameters_name()[source]

This method returns the names of the parameters of the component and of the ones contained.

Returns:

List with the names of the parameters.

Return type:

list(str)

_find_content_from_name(name)[source]

This method finds a component using the name of the parameter or the state.

Parameters:

name (str) – Name to use for the search

Returns:

Index of the component in self._content

Return type:

int or tuple

set_parameters(parameters)[source]

This method sets the values of the parameters.

Parameters:

parameters (dict) – Contains the parameters of the element to be set. The keys must be the ones returned by the method get_parameters_name. Only the parameters that have to be changed should be passed.

get_states(names=None)[source]

This method returns the states of the component and of the ones contained.

Parameters:

names (list(str)) – Names of the states to return. The names must be the ones returned by the method get_states_name. If None, all the states are returned.

Returns:

States of the element.

Return type:

dict

get_states_name()[source]

This method returns the names of the states of the component and of the ones contained.

Returns:

List with the names of the states.

Return type:

list(str)

set_states(states)[source]

This method sets the values of the states.

Parameters:

states (dict) – Contains the states of the element to be set. The keys must be the ones returned by the method get_states_name. Only the states that have to be changed should be passed.

reset_states(id=None)[source]

This method sets the states to the values provided to the __init__ method. If a state was initialized as None, it will not be reset.

Parameters:

id (list(str)) – List of element’s id where the method is applied.

get_timestep()[source]

This method returns the timestep used by the element.

Returns:

Timestep

Return type:

float

set_timestep(dt)[source]

This method sets the timestep used by the element.

Parameters:

dt (float) – Timestep

define_solver(solver)[source]

This method define the solver to use for the differential equation.

Parameters:

solver (superflexpy.utils.root_finder.RootFinder) – Solver used to find the root(s) of the differential equation(s). Child classes may implement their own solver, therefore the tipe of the solver is not enforced.

superflexpy.framework.unit

class superflexpy.framework.unit.Unit(layers, id, parameters=None, states=None, copy_pars=True)[source]

Bases: GenericComponent

This class defines a Unit. A unit can be part of a node and it is a collection of elements. It’s task is to build the basic structure, connecting different elements. Mathematically, it is a directed acyclic graph.

__init__(layers, id, parameters=None, states=None, copy_pars=True)[source]

This is the initializer of the class Unit.

Parameters:
  • layers (list(list(superflexpy.framework.element.BaseElement))) – This list defines the structure of the unit. The elements are arranged in layers (upstream to downstream) and each layer can contain multiple elements.

  • id (str) – Identifier of the unit. All the units of the framework must have an identifier.

  • copy_pars (bool) – True if the parameters of the elements are copied instead of being shared among the different Units.

set_input(input)[source]

This method sets the inputs to the unit.

Parameters:

input (list(numpy.ndarray)) – List of input fluxes.

get_output(solve=True)[source]

This method solves the Unit, solving each Element and putting together their outputs according to the structure.

Parameters:

solve (bool) – True if the elements have to be solved (i.e. calculate the states).

Returns:

List containing the output fluxes of the unit.

Return type:

list(numpy.ndarray)

append_layer(layer)[source]

This method appends a layer to the structure.

Parameters:

layer (list(superflexpy.framework.elements.BaseElement)) – Layer to be appended.

insert_layer(layer, position)[source]

This method inserts a layer in the unit structure.

Parameters:
  • layer (list(superflexpy.framework.elements.BaseElement)) – Layer to be inserted.

  • position (int) – Position where the layer is inserted.

get_internal(id, attribute)[source]

This method allows to inspect attributes of the objects that belong to the unit.

Parameters:
  • id (str) – Id of the object.

  • attribute (str) – Name of the attribute to expose.

Returns:

Attribute exposed

Return type:

Unknown

call_internal(id, method, **kwargs)[source]

This method allows to call methods of the objects that belong to the unit.

Parameters:
  • id (str) – Id of the object.

  • method (str) – Name of the method to call.

Returns:

Output of the called method.

Return type:

Unknown

add_prefix_parameters(id)[source]

This method adds the prefix to the parameters of the elements that are contained in the unit.

Parameters:

id (str) – Prefix to add.

add_prefix_states(id)[source]

This method adds the prefix to the states of the elements that are contained in the unit.

Parameters:

id (str) – Prefix to add.

_construct_dictionary()[source]

This method populates the self._content_pointer dictionary.

_find_attribute_from_name(id, function)[source]

This method is used to find the attributes or methods of the components contained for post-run inspection.

Parameters:
  • id (str) – Identifier of the component

  • function (str) – Name of the attribute or method

Returns:

Attribute or method to inspect

Return type:

Unknown

_check_layers()[source]

This method controls if the layers respect all the rules in terms of number of upstream/downstream elements.

superflexpy.framework.node

class superflexpy.framework.node.Node(units, weights, area, id, parameters=None, states=None, shared_parameters=True)[source]

Bases: GenericComponent

This class defines a Node. A node can be part of a network and it is a collection of Units. It’s task is to sum the outputs of the Units, applying, if present, a routing.

__init__(units, weights, area, id, parameters=None, states=None, shared_parameters=True)[source]

This is the initializer of the class Node.

Parameters:
  • units (list(superflexpy.framework.unit.Unit)) – List of Units contained in the Node.

  • weights (list) – List of weights to be applied to the Units when putting together their outputs. The order must be the same used in the units list. If a weight is a list, then different fluxes coming from the same unit have a different weight.

  • area (float) – Influence area of the node. It is the net value: if a node has other nodes upstream, their area is not counted.

  • id (str) – Identifier of the node. All the nodes of the framework must have an identifier.

  • shared_parameters (bool) – True if the parameters of the Units are shared among the different Nodes.

set_input(input)[source]

This method sets the inputs to the node.

Parameters:

input (list(numpy.ndarray)) – List of input fluxes.

get_output(solve=True)[source]

This method solves the Node, solving each Unit and putting together their outputs according to the weight.

Parameters:

solve (bool) – True if the elements have to be solved (i.e. calculate the states).

Returns:

List containig the output fluxes of the node.

Return type:

list(numpy.ndarray)

get_internal(id, attribute)[source]

This method allows to inspect attributes of the objects that belong to the node.

Parameters:
  • id (str) – Id of the object. If it is not a unit, it must contain the ids of the object containing it. If, for example it is an element, the id will be idUnit_idElement.

  • attribute (str) – Name of the attribute to expose.

Returns:

Attribute exposed

Return type:

Unknown

call_internal(id, method, **kwargs)[source]

This method allows to call methods of the objects that belong to the node.

Parameters:
  • id (str) – Id of the object. If it is not a unit, it must contain the ids of the object containing it. If, for example it is an element, the id will be idUnit_idElement.

  • method (str) – Name of the method to call.

Returns:

Output of the called method.

Return type:

Unknown

add_prefix_parameters(id, shared_parameters)[source]

This method adds the prefix to the parameters of the elements that are contained in the node.

Parameters:

id (str) – Prefix to add.

add_prefix_states(id)[source]

This method adds the prefix to the states of the elements that are contained in the node.

Parameters:

id (str) – Prefix to add.

external_routing(flux)[source]

This methods applies the external routing to the fluxes. External routing is the one that affects the fluxes moving from the outflow of this node to the outflow of the one downstream. This function is used by the Network.

Parameters:

flux (list(numpy.ndarray)) – List of fluxes on which the routing has to be applied.

_find_attribute_from_name(id)[source]

This method is used to find the attributes or methods of the components contained for post-run inspection.

Parameters:

id (str) – Identifier of the component

Returns:

Index of the component to look for and indication if it is an element (True) or not.

Return type:

int, bool

_internal_routing(flux)[source]

Internal routing is the one that affects the flux coming to the Units and reaching the outflow of the node. This function is internally used by the node.

superflexpy.framework.network

class superflexpy.framework.network.Network(nodes, topology)[source]

Bases: GenericComponent

This class defines a Network. A network is a collection of Nodes and it is used to route the fluxes from upstream to downstream. A network must be a tree.

__init__(nodes, topology)[source]

This is the initializer of the class Network.

Parameters:
  • nodes (list(superflexpy.framework.node.Node)) – List of nodes that belongs to the network. The order is not important.

  • topology (dict(str : str)) – Topology of the network. Keys are the id of the nodes and values are the id of the downstream node the key. Since the network must be a tree, each key has only one downstream element

get_output(solve=True)[source]

This method solves the network, solving each node and putting together their outputs according to the topology of the network.

Parameters:

solve (bool) – True if the elements have to be solved (i.e. calculate the states).

Returns:

Dictionary containig the output fluxes of all the nodes.

Return type:

dict(str : list(numpy.ndarray))

get_internal(id, attribute)[source]

This method allows to inspect attributes of the objects that belong to the network.

Parameters:
  • id (str) – Id of the object. If it is not a node, it must contain the ids of the object containing it. If, for example it is a unit, the id will be idNode_idUnit.

  • attribute (str) – Name of the attribute to expose.

Returns:

Attribute exposed

Return type:

Unknown

call_internal(id, method, **kwargs)[source]

This method allows to call methods of the objects that belong to the the network.

Parameters:
  • id (str) – Id of the object. If it is not a node, it must contain the ids of the object containing it. If, for example it is a unit, the id will be idNode_idUnit.

  • method (str) – Name of the method to call.

Returns:

Output of the called method.

Return type:

Unknown

_build_network()[source]

This method constructs all the structures needed to solve the network

_find_attribute_from_name(id)[source]

This method is used to find the attributes or methods of the components contained for post-run inspection.

Parameters:

id (str) – Identifier of the component

Returns:

Index of the component to look for and indication if it is an element or a unit (True) or not.

Return type:

int, bool

superflexpy.utils.root_finder

class superflexpy.utils.root_finder.RootFinder(tol_F=1e-08, tol_x=1e-08, iter_max=10)[source]

Bases: object

This is the abstract class for the creation of a RootFinder. It defines how the solver of the differential equation must be implemented.

architecture = None

Implementation required to increase the performance (e.g. numba)

__init__(tol_F=1e-08, tol_x=1e-08, iter_max=10)[source]

The constructor of the subclass must accept the parameters of the solver.

Parameters:
  • tol_F (float) – Tolerance on the y axis (distance from 0) that stops the solver

  • tol_x (float) – Tolerance on the x axis (distance between two roots) that stops the solver

  • iter_max (int) – Maximum number of iteration of the solver. After this value it raises a runtime error

get_settings()[source]

This method returns the settings of the root finder.

Returns:

  • float – Function tollerance (tol_F)

  • float – X tollerance (tol_x)

  • int – Maximum number of iterations (iter_max)

solve(*args, **kwargs)[source]

To be implemented by any child class. This method finds the root of the numerical approximation of the differential equation. It can operate over the whole time series.

superflexpy.utils.numerical_approximator

class superflexpy.utils.numerical_approximator.NumericalApproximator(root_finder)[source]

Bases: object

This is the abstract class for the creation of a NumericalApproximator. It defines how the approximator of the differential equation must be implemented to fit in the framework

architecture = None

Defines if the element is implemented using some pre-compiled libraries (e.g. numba)

__init__(root_finder)[source]

The constructor of the subclass must accept the parameters of the approximator.

Parameters:

root_finder (superflexpy.utils.root_finder.RootFinder) – Solver used to find the root(s) of the differential equation(s).

solve(fun, S0, **kwargs)[source]

This method solves an approximation of the ODE.

Parameters:
  • fun (list(function)) –

    List of functions to calculate the fluxes of the ODEs. One equation for ODE. The function must accept:

    • State, called S, used to evaluate the fluxes

    • Initial state of the element, called S0, used to calculate the mainimum and maximum possible state of the reservoir

    • Other parameters (**kwargs) needed to calculate the fluxes

    The function must return:

    • list of fluxes with positive sign if incoming and negative if outgoing

    • minimum possible value of the state

    • maximum possible value of the state

  • S0 (list(float)) – Initial states used for the ODEs. One value per fun

  • **kwargs – Additional arguments needed by fun. It must also contain dt.

Returns:

Array of solutions of the ODEs. It is a 2D array with dimensions (#timesteps, #functions)

Return type:

numpy.ndarray