utils

Modules

discrete_statespace_system module

class DiscreteStatespaceSystem(A=None, B=None, C=None, D=None, sample_time=1.0, x0=None, state_names=None, E=None, F=None, **kwargs)[source]

Bases: System

A general-purpose discrete state space system for modeling dynamical systems.

This class implements a discrete state-space system that supports both linear and bilinear dynamics through state-input and input-input coupling terms. The system serves as the computational core for various physical models in the Twin4Build framework, including thermal RC networks and mass balance systems.

Parameters:
  • A (Optional[Tensor]) – System dynamics matrix of shape (N, N)

  • B (Optional[Tensor]) – Control input matrix of shape (N, M)

  • C (Optional[Tensor]) – Output matrix of shape (P, N)

  • D (Optional[Tensor]) – Feedthrough matrix of shape (P, M). Optional.

  • sample_time (float) – Sampling time for discretization

  • x0 (Optional[Tensor]) – Initial state vector of shape (N,)

  • state_names (Optional[List[str]]) – Names for system states

  • E (Optional[Tensor]) – Bilinear state-input tensor of shape (M, N, N). Optional.

  • F (Optional[Tensor]) – Input-input coupling tensor of shape (M, M, N). Optional.

  • **kwargs – Additional keyword arguments

Mathematical Formulation:

Continuous-Time State-Space Representation:

The general continuous-time state-space system with bilinear terms is formulated as:

\[\frac{d\mathbf{x}}{dt} = \mathbf{A}\mathbf{x} + \mathbf{B}\mathbf{u} + \sum_{i=1}^{m} \mathbf{E}_i\mathbf{x}u_i + \sum_{i=1}^{m} \mathbf{F}_{i}\mathbf{u} u_i\]
\[\mathbf{y} = \mathbf{C}\mathbf{x} + \mathbf{D}\mathbf{u}\]

where:

  • \(\mathbf{x} \in \mathbb{R}^n\): State vector (internal system variables)

  • \(\mathbf{u} \in \mathbb{R}^m\): Input vector (external driving signals)

  • \(\mathbf{y} \in \mathbb{R}^p\): Output vector (observable quantities)

  • \(\mathbf{A} \in \mathbb{R}^{n \times n}\): State transition matrix

  • \(\mathbf{B} \in \mathbb{R}^{n \times m}\): Input matrix

  • \(\mathbf{C} \in \mathbb{R}^{p \times n}\): Output matrix

  • \(\mathbf{D} \in \mathbb{R}^{p \times m}\): Feedthrough matrix

  • \(\mathbf{E} \in \mathbb{R}^{m \times n \times n}\): State-input coupling tensor, with \(\mathbf{E}_i \in \mathbb{R}^{n \times n}\) being the \(i\)-th slice of the tensor

  • \(\mathbf{F} \in \mathbb{R}^{m \times n \times m}\): Input-input coupling tensor, with \(\mathbf{F}_i \in \mathbb{R}^{n \times m}\) being the \(i\)-th slice of the tensor

Bilinear Extensions:

The bilinear terms extend the basic linear state-space model to handle:

State-Input Coupling (E matrices):
  • Models where inputs affect the dynamics matrix

  • Example: \(\dot{m}_{exh} \times T_{air}\) in thermal systems

  • Formulation: \(\sum_{i=1}^{m} \mathbf{E}_i\mathbf{x}u_i\)

Input-Input Coupling (F matrices):
  • Models where the product of two inputs affects the state derivative

  • Example: \(\dot{m}_{sup} \times T_{sup}\) in thermal systems

  • Formulation: \(\sum_{i=1}^{m} \mathbf{F}_{i}\mathbf{u} u_i\)

Discretization Method:

For numerical simulation, the continuous system is discretized using zero-order hold (ZOH). For a linear system, this would be a one-time operation. However, when bilinear terms (E and F matrices) are present, the effective A and B matrices must be recomputed every time inputs change significantly.

Step 1: Compute Equivalent Matrices

We can calculate the textit{equivalent} A and B matrices by factoring out the state and input vectors \(\mathbf{x}\) and \(\mathbf{u}\):

\[\mathbf{A}^*[k] = \mathbf{A} + \sum_{i=1}^{m} \mathbf{E}_i u_i[k]\]
\[\mathbf{B}^*[k] = \mathbf{B} + \sum_{i=1}^{m} \mathbf{F}_i u_i[k]\]

where the effective matrices depend on the current input vector \(\mathbf{u}[k]\).

Step 2: Discretize Effective Matrices

The effective matrices are then discretized using the matrix exponential method:

\[ \begin{align}\begin{aligned}\mathbf{A}_d[k] = e^{\mathbf{A}_{eff}[k] T_s}\\\mathbf{B}_d[k] = \int_0^{T_s} e^{\mathbf{A}_{eff}[k]\tau}d\tau \mathbf{B}_{eff}[k]\end{aligned}\end{align} \]

Step 3: State Update

The discrete-time state update becomes:

\[ \begin{align}\begin{aligned}\mathbf{x}[k+1] = \mathbf{A}_d[k]\mathbf{x}[k] + \mathbf{B}_d[k]\mathbf{u}[k]\\\mathbf{y}[k] = \mathbf{C}\mathbf{x}[k] + \mathbf{D}\mathbf{u}[k]\end{aligned}\end{align} \]

where \(T_s\) is the sampling time. This approach ensures that the bilinear coupling effects are properly incorporated into the discrete-time dynamics while preserving numerical accuracy through the matrix exponential method.

Computational Efficiency:

The effective matrices and their discretization are recomputed only when the input vector changes significantly, providing computational efficiency while maintaining accuracy for time-varying bilinear systems.

Practical Implementation:

In practice, the matrix exponential computation is performed using a block matrix approach for numerical stability:

\[ \begin{align}\begin{aligned}\begin{split}\mathbf{M} = \begin{bmatrix} \mathbf{A}_{eff}[k] T_s & \mathbf{B}_{eff}[k] T_s \\ \mathbf{0} & \mathbf{0} \end{bmatrix}\end{split}\\\begin{split}e^{\mathbf{M}} = \begin{bmatrix} \mathbf{A}_d[k] & \mathbf{B}_d[k] \\ \mathbf{0} & \mathbf{I} \end{bmatrix}\end{split}\end{aligned}\end{align} \]

Physical Interpretation:

In Thermal Systems:
  • States: Temperatures of thermal nodes (air, walls, etc.)

  • Inputs: Weather conditions, HVAC flows, heat gains

  • A matrix: Thermal coupling between nodes via resistances

  • B matrix: External heat inputs and boundary conditions

  • E/F matrices: Flow-dependent heat transfer

In Mass Balance Systems:
  • States: Concentration levels (CO2, humidity, etc.)

  • Inputs: Ventilation flows, generation rates, outdoor conditions

  • A matrix: Dilution and mixing effects

  • B matrix: Source terms and boundary inflows

  • E/F matrices: Flow-dependent transport

Computational Features:

  • Automatic Differentiation: PyTorch tensors enable gradient computation

  • Adaptive Discretization: Matrices updated when inputs change significantly

  • Numerical Stability: Matrix exponential method for accurate discretization

  • Efficient Simulation: Optimized for repeated time-stepping

Examples

Basic linear state-space system:

>>> import torch
>>> import twin4build as tb
>>>
>>> # Define system matrices
>>> A = torch.tensor([[-0.1, 0.05], [0.02, -0.08]], dtype=torch.float64)
>>> B = torch.tensor([[1.0], [0.5]], dtype=torch.float64)
>>> C = torch.tensor([[1.0, 0.0]], dtype=torch.float64)
>>> x0 = torch.tensor([20.0, 18.0], dtype=torch.float64)
>>>
>>> # Create system
>>> system = tb.DiscreteStatespaceSystem(
...     A=A, B=B, C=C, x0=x0, sample_time=3600.0,
...     state_names=["T_air", "T_wall"]
... )

Bilinear system with state-input coupling:

>>> # Define bilinear coupling matrices
>>> E = torch.zeros((1, 2, 2), dtype=torch.float64)
>>> E[0, 0, 1] = 0.001  # Input 0 affects coupling between states 0 and 1
>>>
>>> # Create bilinear system
>>> bilinear_system = tb.DiscreteStatespaceSystem(
...     A=A, B=B, C=C, E=E, x0=x0, sample_time=3600.0,
...     state_names=["T_air", "T_wall"]
... )

System with input-input coupling:

>>> # Define input-input coupling
>>> F = torch.zeros((2, 2, 2), dtype=torch.float64)
>>> F[0, 1, 0] = 0.1  # Product of inputs 0 and 1 affects state 0
>>>
>>> # Create system with F matrices
>>> coupled_system = tb.DiscreteStatespaceSystem(
...     A=A, B=B, C=C, F=F, x0=x0, sample_time=3600.0,
...     state_names=["T_air", "T_wall"]
... )
discretize_system()[source]

Discretize the continuous-time state space model while maintaining the computational graph.

Uses the matrix exponential method to compute Ad and Bd efficiently. The implementation ensures that gradients can flow back through the discretization process.

Return type:

None

do_step(secondTime, dateTime, step_size, stepIndex)[source]

Perform one step of the state space model simulation. Now supports bilinear (state-input coupled) terms using the trapezoidal (average of old and new states) method for the E and F terms. Ad and Bd are only computed in discretize_system for efficiency.

Return type:

None

classmethod from_matrices(A, B, C, D=None, sample_time=1.0, **kwargs)[source]

Create a DiscreteStatespaceSystem from continuous-time matrices.

Parameters:
  • A – System dynamics matrix

  • B – Control input matrix

  • C – Output matrix

  • D – Feedthrough matrix (optional)

  • sample_time – Sampling time for discretization

  • **kwargs – Additional arguments to pass to constructor

Returns:

Initialized system

Return type:

DiscreteStatespaceSystem

classmethod from_transfer_function(num, den, sample_time=1.0, **kwargs)[source]

Create a DiscreteStatespaceSystem from a transfer function.

Parameters:
  • num – Transfer function numerator polynomial coefficients

  • den – Transfer function denominator polynomial coefficients

  • sample_time – Sampling time for discretization

  • **kwargs – Additional arguments to pass to constructor

Returns:

Initialized system

Return type:

DiscreteStatespaceSystem

get_state()[source]

Get the current state vector.

Return type:

Tensor

initialize(start_time, end_time, step_size, simulator)[source]

Initialize the discrete state space model by computing discretized matrices.

Parameters:
  • start_time (datetime) – Simulation start time.

  • end_time (datetime) – Simulation end time.

  • step_size (int) – Simulation step size.

  • model – Reference to the simulation model.

Return type:

None

set_state(x)[source]

Set the current state vector.

Parameters:

x (Tensor) – New state vector

Return type:

None

property config

Get the configuration parameters of the discrete state-space system.

Returns:

Configuration parameters including all system matrices.

Return type:

dict

property input: dict

Get the input ports of the discrete state-space system.

Returns:

Dictionary containing input ports:
  • ”u”: Input vector of size n_inputs

Return type:

dict

property output: dict

Get the output ports of the discrete state-space system.

Returns:

Dictionary containing output ports:
  • ”y”: Output vector of size n_outputs

Return type:

dict

fmu_system module

class fmuSystem(fmu_path=None, unzipdir=None, **kwargs)[source]

Bases: System

FMU System.

This class implements a FMU system for a given system.

Parameters:
  • fmu_path (Optional[str]) – Path to the FMU file

  • unzipdir (Optional[str]) – Path to the unzip directory

do_step(secondTime, dateTime, step_size, stepIndex)[source]

Do a single step of the system.

Parameters:
  • secondTime (float) – The current time in seconds.

  • dateTime (datetime.datetime) – The current date and time.

  • step_size (int) – The step size of the simulation in seconds.

  • stepIndex (int) – The current step index.

Return type:

None

initialize_fmu()[source]
reset()[source]
set_parameters(parameters=None)[source]
unzip_fmu(fmu_path=None, unzipdir=None)[source]

max_system module

class MaxSystem(**kwargs)[source]

Bases: System

Max System.

This class implements a max system for a given system.

Parameters:

**kwargs – Additional keyword arguments

do_step(secondTime, dateTime, step_size, stepIndex)[source]

Do a single step of the system.

Parameters:
  • secondTime (float) – The current time in seconds.

  • dateTime (datetime.datetime) – The current date and time.

  • step_size (int) – The step size of the simulation in seconds.

  • stepIndex (int) – The current step index.

Return type:

None

initialize(start_time, end_time, step_size, simulator)[source]

Initialize the system.

Parameters:
  • start_time (datetime.datetime) – The start time of the simulation.

  • end_time (datetime.datetime) – The end time of the simulation.

  • step_size (int) – The step size of the simulation in seconds.

  • simulator (core.Simulator) – The simulator.

Return type:

None

on_off_system module

class OnOffSystem(threshold=None, is_on_value=None, is_off_value=None, **kwargs)[source]

Bases: System

On-Off System.

If value>=threshold set to on_value else set to off_value

Parameters:
  • threshold (Optional[float]) – Threshold value

  • is_on_value (Optional[float]) – Value to set when value>=threshold

  • is_off_value (Optional[float]) – Value to set when value<threshold

  • **kwargs – Additional keyword arguments

do_step(secondTime, dateTime, step_size, stepIndex)[source]

Do a single step of the system.

Parameters:
  • secondTime (float) – The current time in seconds.

  • dateTime (datetime.datetime) – The current date and time.

  • step_size (int) – The step size of the simulation in seconds.

  • stepIndex (int) – The current step index.

Return type:

None

initialize(start_time, end_time, step_size, simulator)[source]

Initialize the system.

Parameters:
  • start_time (datetime.datetime) – The start time of the simulation.

  • end_time (datetime.datetime) – The end time of the simulation.

  • step_size (int) – The step size of the simulation in seconds.

  • simulator (core.Simulator) – The simulator.

Return type:

None

pass_input_to_output module

class PassInputToOutput(**kwargs)[source]

Bases: System

Pass Input to Output System.

This component simply passes inputs to outputs during simulation.

Parameters:

**kwargs – Additional keyword arguments

do_step(secondTime, dateTime, step_size, stepIndex)[source]

Do a single step of the system.

Parameters:
  • secondTime (float) – The current time in seconds.

  • dateTime (datetime.datetime) – The current date and time.

  • step_size (int) – The step size of the simulation in seconds.

  • stepIndex (int) – The current step index.

Return type:

None

initialize(start_time, end_time, step_size, simulator)[source]

Initialize the system.

Parameters:
  • start_time (datetime.datetime) – The start time of the simulation.

  • end_time (datetime.datetime) – The end time of the simulation.

  • step_size (int) – The step size of the simulation in seconds.

  • simulator (core.Simulator) – The simulator.

Return type:

None

property config

piecewise_linear_system module

class PiecewiseLinearSystem(X=None, Y=None, **kwargs)[source]

Bases: System

A system implementing piecewise linear interpolation functionality.

This class provides core functionality for systems that need to perform piecewise linear interpolation between data points. It supports both direct point-to-point interpolation and fitting of piecewise linear functions to data.

Parameters:
  • X (Optional[ndarray]) – X coordinates

  • Y (Optional[ndarray]) – Y coordinates

  • **kwargs – Additional keyword arguments

Note

When X and Y are provided during initialization, the system automatically calculates the piecewise linear coefficients.

do_step(secondTime, dateTime, step_size, stepIndex)[source]

Perform a single interpolation step using new implementation.

Parameters:
  • secondTime (Optional[float], optional) – Current simulation time in seconds. Defaults to None.

  • dateTime (Optional[datetime.datetime], optional) – Current simulation datetime. Defaults to None.

  • step_size (Optional[float], optional) – Time step size in seconds. Defaults to None.

Return type:

None

property X: ndarray | None

Get the X coordinates of the interpolation points.

property Y: ndarray | None

Get the Y coordinates of the interpolation points.

property config: Dict[str, List[str]]

Get the configuration parameters.

Returns:

Dictionary containing configuration parameter names.

Return type:

Dict[str, List[str]]

time_series_input_system module

class TimeSeriesInputSystem(df=None, filename=None, datecolumn=0, valuecolumn=1, useSpreadsheet=False, useDatabase=False, uuid=None, name=None, dbconfig=None, **kwargs)[source]

Bases: System

A system for reading and processing time series data from files or DataFrames.

This component provides functionality to handle time series data inputs, either from CSV files or pandas DataFrames. It supports automatic file path resolution and caching of processed data for improved performance.

Parameters:
  • df (Optional[DataFrame]) – Input dataframe containing time series data. Must have datetime index and value column.

  • filename (Optional[str]) – Path to the CSV file. Can be absolute or relative to cache_root. If relative, will try both current directory and cache_root.

  • datecolumn (int) – Index of the date column (0-based). Defaults to 0.

  • valuecolumn (int) – Index of the value column (0-based). Defaults to 1.

  • useSpreadsheet (bool) – Whether to use a spreadsheet for input. Defaults to False.

  • useDatabase (bool) – Whether to use a database for input. Defaults to False.

  • uuid (Optional[str]) – UUID for database operations.

  • name (Optional[str]) – Name for database operations.

  • dbconfig (Optional[Dict[str, Any]]) – Database configuration parameters.

  • **kwargs – Additional keyword arguments

do_step(secondTime, dateTime, step_size, stepIndex, simulator=None)[source]

Perform a single timestep for the TimeSeriesInputSystem.

Parameters:
  • secondTime (int, optional) – Current simulation time in seconds.

  • dateTime (datetime, optional) – Current simulation time as a datetime object.

  • step_size (int, optional) – Step size for the simulation.

Return type:

None

initialize(start_time, end_time, step_size, simulator)[source]

Initialize the TimeSeriesInputSystem.

Parameters:
  • start_time (datetime.datetime) – Start time for the simulation.

  • end_time (datetime.datetime) – End time for the simulation.

  • step_size (int) – Step size for the simulation.

  • simulator (core.Simulator) – Simulator to be used for initialization.

Return type:

None

property config

Get the configuration of the TimeSeriesInputSystem.

Returns:

The configuration dictionary.

Return type:

dict

property datecolumn: int

Get the index of the date/time column (0-based).

property dbconfig: Dict[str, Any] | None

Get the database configuration parameters.

property df: DataFrame | None

Get the processed input data containing time series values.

property filename: str | None

Get the path to the input CSV file (absolute or relative to root).

property input: dict

Get the input ports of the time series input system.

Returns:

Dictionary containing input ports (empty for leaf systems)

Return type:

dict

property name: str | None

Get the name for database operations.

property output: dict

Get the output ports of the time series input system.

Returns:

Dictionary containing output ports:
  • ”value”: Time series values [units depend on data]

Return type:

dict

property useDatabase: bool

Get whether to use a database for input.

property useSpreadsheet: bool

Get whether to use a spreadsheet for input.

property uuid: str | None

Get the UUID for database operations.

property valuecolumn: int

Get the index of the value column (0-based).