Subsystem

class pathsim.subsystem.Interface[source]

Bases: Block

Bare-bone block that serves as a data interface for the ‘Subsystem’ class.

It works like this:

  • Internal blocks of the subsystem are connected to the inputs and outputs of this Interface block via the internal connections.

  • It behaves like a normal block (inherits the main ‘Block’ class methods).

  • It implements some special methods to get and set the inputs and outputs of the blocks, that are used to translate between the internal blocks of the subsystem and the inputs and outputs of the subsystem.

  • Handles data transfer to and from the internal subsystem blocks to and from the inputs and outputs of the subsystem.

register_port_map(port_map_in, port_map_out)[source]

Update the input and output registers of the interface block with port mappings

Parameters:
  • port_map_in (dict[str: int]) – port alias mapping for block inputs

  • port_map_out (dict[str: int]) – port alias mapping for block outputs

class pathsim.subsystem.Subsystem(blocks=None, connections=None, events=None, tolerance_fpi=1e-10, iterations_max=200)[source]

Bases: Block

Subsystem class that holds its own blocks and connecions and can natively interface with the main simulation loop.

IO interface is realized by a special ‘Interface’ block, that has extra methods for setting and getting inputs and outputs and serves as the interface of the internal blocks to the outside.

The subsystem doesnt use its ‘inputs’ and ‘outputs’ dicts directly. It exclusively handles data transfer via the ‘Interface’ block.

This class can be used just like any other block during the simulation, since it implements the required methods ‘update’ for the fixed-point iteration (resolving algebraic loops with instant time blocks), the ‘step’ method that performs timestepping (especially for dynamic blocks with internal states) and the ‘solve’ method for solving the implicit update equation for implicit solvers.

Example

This is how we can wrap up multiple blocks within a subsystem. In this case vanderpol system built from discrete components instead of using an ODE block (in practice you should use a monolithic ODE whenever possible due to performance).

from pathsim import Subsystem, Interface, Connection
from pathsim.blocks import Integrator, Function

#van der Pol parameter
mu = 1000

#blocks in the subsystem
If = Interface() # this is the interface to the outside
I1 = Integrator(2)
I2 = Integrator(0)
Fn = Function(lambda x1, x2: mu*(1 - x1**2)*x2 - x1)

sub_blocks = [If, I1, I2, Fn]

#connections in the subsystem
sub_connections = [
    Connection(I2, I1, Fn[1], If[1]),
    Connection(I1, Fn, If),
    Connection(Fn, I2)
    ]

#the subsystem acts just like a normal block
vdp = Subsystem(sub_blocks, sub_connections)
Parameters:
  • blocks (list[Block] | None) – internal blocks of the subsystem

  • connections (list[Connection] | None) – internal connections of the subsystem

  • events (list[Event] | None)

  • tolerance_fpi (float) – absolute tolerance for convergence of algebraic loops default see ´SIM_TOLERANCE_FPI´ in ´_constants.py´

  • iterations_max (int) – maximum allowed number of iterations for algebraic loop solver, default see ´SIM_ITERATIONS_MAX´ in ´_constants.py´

interface

internal interface block for data transfer to the outside

Type:

Interface

graph

internal graph representation for fast system funcion evluations using DAG with algebraic depths

Type:

Graph

boosters

list of boosters (fixed point accelerators) that wrap algebraic loop closing connections assembled from the system graph

Type:

None | list[ConnectionBooster]

property size

Get size information from subsystem, recursively assembled from internal blocks, including nested subsystems.

Returns:

sizes – size of block (number of all internal blocks) and number of internal states (from internal engines)

Return type:

tuple[int]

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

Plot the simulation results by calling all the blocks that have visualization capabilities such as the ‘Scope’ and ‘Spectrum’.

Parameters:
  • args (tuple) – args for the plot methods

  • kwargs (dict) – kwargs for the plot method

reset()[source]

Reset the subsystem interface and all internal blocks

on()[source]

Activate the subsystem and all internal blocks, sets the boolean evaluation flag to ‘True’.

off()[source]

Deactivate the subsystem and all internal blocks, sets the boolean evaluation flag to ‘False’. Also resets the subsystem.

linearize(t)[source]

Linearize the algebraic and dynamic components of the internal blocks.

This is done by linearizing the internal ‘Operator’ and ‘DynamicOperator’ instances of all the internal blocks of the subsystem in the current system operating point. The operators create 1st order tayler approximations internally and use them on subsequent calls after linarization.

Recursively traverses down the hierarchy for nested subsystems and linearizes all of them.

Parameters:

t (float) – evaluation time

delinearize()[source]

Revert the linearization of the internal blocks.

property events

Recursively collect and return events spawned by the internal blocks of the subsystem, for discrete time blocks such as triggers / comparators, clocks, etc.

property inputs
property outputs
sample(t, dt)[source]

Update the internal connections again and sample data from the internal blocks that implement the ‘sample’ method.

Parameters:
  • t (float) – evaluation time

  • dt (float) – integration timestep

update(t)[source]

Update the instant time components of the internal blocks to evaluate the (distributed) system equation.

Parameters:

t (float) – evaluation time

solve(t, dt)[source]

Advance solution of implicit update equation for internal blocks.

Parameters:
  • t (float) – evaluation time

  • dt (float) – timestep

Returns:

max_error – maximum error of implicit update equaiton

Return type:

float

step(t, dt)[source]

Explicit component of timestep for internal blocks including error propagation.

Notes

This is pretty much an exact copy of the ‘_step’ method from the ‘Simulation’ class.

Parameters:
  • t (float) – evaluation time

  • dt (float) – timestep

Returns:

  • success (bool) – indicator if the timestep was successful

  • max_error (float) – maximum local truncation error from integration

  • scale (float) – rescale factor for timestep

set_solver(Solver, parent, **solver_args)[source]

Initialize all blocks with solver for numerical integration and additional args for the solver such as tolerances, etc.

If blocks already have solvers, change the numerical integrator to the ‘Solver’ class.

Parameters:
  • Solver (Solver) – numerical solver definition

  • parent (Solver) – numerical solver instance as parent

  • solver_args (dict) – args to initialize solver with

revert()[source]

revert the internal blocks to the state of the previous timestep

buffer(dt)[source]

buffer internal states of blocks with internal integration engines

Parameters:

dt (float) – evaluation time for buffering