-
Notifications
You must be signed in to change notification settings - Fork 34
Evaluation
At compile
time the block diagram is analysed to create an execution plan. The result is a list of lists of blocks. The index of the outer list is the execution step, and all blocks in the inner list can be executed knowing their inputs have been computed in previous execution steps. The plan can be shown by:
-
bd.plan_print()
as a formatted table -
bd.plan_dotfile()
as a GraphViz graph, for example
This is a data flow graph and arcs represent data dependencies. Each column of this graph represents an execution step. All blocks executed in the same step could be executed in parallel since they are not dependent on each other.
Step 0 of the plan includes all blocks whose output values are already known:
- the outputs of the
Source
blocks such as constants or waveform generators - the outputs of the stateful
Transfer
blocks which are a function of their state
The plan is executed/evaluated by
bd.evaluate_plan(x, t, checkfinite=True, debuglist=[], sinks=True)
where x
is the integrator's state vector, and t
is current simulation time.
Each block, apart from source blocks, has an input
list whose elements correspond to its input ports.
During execution the block's output
method is called and it computes its output as a function of the input
values and time.
The result is a list whose elements correspond to the block's output ports which the method returns.
evaluate_plan
copies the elements of that list to elements of the input
list of the blocks it is connected to, as dictated by the block diagram's wiring network.
By default the scipy Runge-Kutta 45 algorithm is used. This is a variable step integrator which evaluates the state derivative multiple times before it converges on an estimate of x(t). The main steps are:
- Get the initial state vector. Each stateful blocks holds its own initial state, the
getstate0
method of these blocks is called and the values concatenated to createx0
. - The integrator is initialised and it computes the state trajectory by making multiple requests for the derivative of the system state
Each derivative calculation requires evaluating the entire network for a particular state vector provided by the integrator. The steps are:
- Split the state vector across the stateful blocks and tell each block its state value using its
setstate
method - Evaluate the entire block diagram.
- The the state derivative is computed by the values at the inputs to the stateful blocks. Each block returns its state derivative by its
deriv
method.
Although block execution is sequential, as far as the integrator is concerned this is an atomic operation, occurring at a single point in simulation time.
Numerical integration updates a 1D state vector. Each stateful block is concerned with a part of the state vector:
-
before the integration begins the
getstate0
method of eachTransferBlock
subclass block is called to return its initial state vector. This is typically handled by a default method in theTransferBlock
class from the instance variable_x0
. The initial state for the integration is the concatenation of all these individual state vectors. -
for every evaluation the current state from the integrator is transfer to each
TransferBlock
subclass block via itssetstate
method. This method takes the required number of state elements from the left of the passed vector and returns the remainder. This is typically handled by a default method in theTransferBlock
class and the block state is saved in the instance variable_x
.
Copyright (c) Peter Corke 2020-23
- Home
- FAQ
- Changes
- Adding blocks
- Block path
- Connecting blocks
- Subsystems
- Compiling
- Running
- Runtime options
- Discrete-time blocks
- Figures
- Real time control
- PID control
- Coding patterns