Interfaces#

FINAM is primarily a collection of interfaces that allows different models and other components to communicate.

For all interfaces, FINAM also provides abstract or concrete implementations to speed up component development.

Class diagram#

The following figure shows a diagram of FINAM’s core interfaces and classes. Arrows indicate inheritance. The properties and methods are those typically used or implemented by developers.

FINAM interfaces class diagramFINAM interfaces class diagram

Figure 1: FINAM interfaces class diagram.

Components#

Components represent linkable entities like models. There are two interfaces for components: IComponent and ITimeComponent.

IComponent#

IComponent serves for pull-based components without an explicit time step. It provides all the basic methods required for component communication and execution.

These methods are called by the scheduler in the given order (and repeatedly for IComponent.update()), each for all components, before proceeding to the next method.

To access a component’s input and output slots, there are the properties:

The abstract class Component provides a basic implementation for IComponent. Classes extending Component must override methods named of the first block, with underscore, like Component._initialize(). Component.inputs, Component.outputs and Component.status are provided as basic implementations.

ITimeComponent#

ITimeComponent extends IComponent and serves for components with explicit time step, like simulation models. In addition to IComponent, it adds one property:

As ITimeComponent extends IComponent, only ITimeComponent needs to be implemented.

The abstract class TimeComponent provides a basic implementation for ITimeComponent. It is basically identical to Component, and in addition provides a basic implementation for TimeComponent.time.

Inputs and Outputs#

Interfaces IInput and IOutput define coupling slots.

The classes Input and Output are provided as implementations for IInput and IOutput, respectively. They should suffice most use cases.

IInput#

IInput represents a data exchange input slot, with the following methods:

Components usually only use IInput.pull_data() in their Component._update() method. All other methods are only used under the hood.

All these methods are implemented in Input, so there is normally no need to write an own implementation for IInput.

Another implementation is provided by CallbackInput, for use in push-based components without a time step. They can connect to IInput.source_updated() by providing a callback function.

Other classes derived from Input can overwrite the method Input.source_updated().

IOutput#

IOutput represents a data exchange output slot, with the following methods:

Components usually only use IOutput.push_data() in their Component._update() method. During coupling setups, IOutput.chain() or it’s synonym operator >> are used. All other methods are only used under the hood.

All these methods are implemented in Output, so there is normally no need to write an own implementation for IOutput.

Other classes derived from Output can overwrite the method Output.get_data().

Adapters#

Adapters serve for data transformations between outputs and inputs of different components.

IAdapter#

The interface IAdapter serves for implementing adapters. It simply combines IInput and IOutput, so it is both at the same time. IAdapter provides all the methods of IInput and IOutput, but most of them are only used under the hood.

Classes implementing IAdapter can extend Adapter, which provides default implementations for IInput and IOutput methods.

Time-independent/one-shot adapters need to override Adapter._get_data(). Inside this method, they get their input via self.pull_data(time), transform it, and return the result.

Time-aware adapters, e.g. for temporal interpolation, usually override Adapter._source_updated() and Adapter._get_data(). In Adapter._source_updated(), incoming data is collected (and potentially aggregated), while in Adapter._get_data() the result is returned.

For details, see chapter Writing adapters.

NoBranchAdapter#

Some time-aware adapters may not allow for branching in the subsequent adapter chain. I.e. they do not support multiple target components. For these cases, NoBranchAdapter is provided as a marker interface without any methods.