pathsim.subsystem
- class pathsim.subsystem.Interface[source]
Bases:
BlockBare-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.
- class pathsim.subsystem.Subsystem(blocks=None, connections=None, tolerance_fpi=1e-10, iterations_max=200)[source]
Bases:
BlockSubsystem 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:
connections (list[Connection]) – internal connections of the subsystem
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´
- 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]
- size()[source]
Get size information from subsystem, recursively assembled from internal blocks, including nested subsystems.
- plot(*args, **kwargs)[source]
Plot the simulation results by calling all the blocks that have visualization capabilities such as the ‘Scope’ and ‘Spectrum’.
- 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
- get_events()[source]
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)[source]
Update the internal connections again and sample data from the internal blocks that implement the ‘sample’ method.
- Parameters:
t (float) – evaluation time
- update(t)[source]
Update the instant time components of the internal blocks to evaluate the (distributed) system equation.
- Parameters:
t (float) – evaluation time
- 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.