Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2,111 changes: 2,111 additions & 0 deletions Manifest.toml

Large diffs are not rendered by default.

22 changes: 14 additions & 8 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,33 +1,39 @@
name = "JuliaCon2026Components"
uuid = "cb0cf210-d080-4a98-89fc-0e4ae9a4086e"
authors = [" <>"]
version = "0.1.0"
authors = [" <>"]

[deps]
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
BlockComponents = "1ef5d832-be8e-447f-9f2c-8b5d17d15fd3"
DyadData = "cab12561-e36c-4498-ae70-c9a5e79fef2a"
DyadInterface = "99806f68-afab-45ca-9d8c-ceff6bc61f54"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
Moshi = "2e0e35c7-a2e4-4343-998d-7ef72827ed2d"
OrdinaryDiffEqDefault = "50262376-6c5a-4cf5-baba-aaf4f84d72d7"
PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
RotationalComponents = "824fa3ed-d7dc-4365-8bdf-ac77a1ac2011"
RuntimeGeneratedFunctions = "7e49a35a-f44a-4d26-94aa-eba1b4ca6b47"
TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76"

[compat]
Markdown = "1"
BlockComponents = "4.5.2"
DyadData = "2.0.1"
JSON = "0.21, 1"
Markdown = "1"
RotationalComponents = "2.5.4"
TOML = "1"

[dyad]
kernel = "3.3.0"

[extras]
DyadEcosystemDependencies = "7bc808db-8006-421e-b546-062440d520b7"
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
DyadEcosystemDependencies = "7bc808db-8006-421e-b546-062440d520b7"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["DyadEcosystemDependencies","CSV","DataFrames","Plots","Test"]

[dyad]
kernel = "3.3.0"
test = ["DyadEcosystemDependencies", "CSV", "DataFrames", "Plots", "Test"]
428 changes: 428 additions & 0 deletions agent_resources/docs/analyses.md

Large diffs are not rendered by default.

146 changes: 146 additions & 0 deletions agent_resources/docs/analysis_points.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
---
description: Learn about analysis points in Dyad, their purpose, and how to use them for advanced system analysis.
---

# Analysis Points {#analysis_points}

## What Are Analysis Points?

Analysis points are special constructs in Dyad that allow users to define specific locations in a model where signal connections can be manipulated for analysis purposes. These points act as named connections, enabling model transformations such as adding inputs and outputs, as well as breaking connections.

In control systems, analysis points are particularly useful for studying feedback loops, assessing robustness, and performing frequency-domain analyses. They provide a way to isolate and inspect specific parts of a system without altering its overall behavior during simulation.


## How to Use Analysis Points in Dyad

### Syntax Breakdown

In Dyad, analysis points are declared using the `analysis_point` keyword. The syntax is:

```dyad
u: analysis_point(output_signal, input_signal)
```

Here:
- `u` is the name of the analysis point.
- `output_signal` is a block output, i.e., the causal result of a computation performed by a block. This signal is typically treated as the output variable if the analysis point is marked as an output.
- `input_signal` is a block input. This signal will typically be treated as an input or additively perturbed by a new external input if the analysis point is marked as an input.

In the most common usage, the analysis-point declaration directly mirrors a `connect` statement between an output and an input, e.g., to add an analysis point to the connection
```
connect(controller.y, plant.u)
```
one would add the following relation to the model:
```dyad
u: analysis_point(controller.y, plant.u)
```
Here, the name `u` is chosen to reflect the common convention of naming control inputs with `u`. The choice of the name `u` here is just an example, you can give it any name. An analysis point may be added to connections with more than one receiving input, but the declaration may only contain a single _output_ (signal source).

The fact that the declaration of an analysis point is separated from the formation of a connection allows for addition of analysis points to any lower level in the model hierarchy, i.e., analysis points can be added inside pre-existing components from an outer component.

### Full Example

Below is a simple example of a feedback system with analysis points:

```dyad
component TestDCMotorLoadControlled
motor = DCMotor()
ground = ElectricalComponents.Analog.Basic.Ground()
source = ElectricalComponents.Analog.Sources.VoltageSource()
fixed = RotationalComponents.Components.Fixed()
load = RotationalComponents.Sources.TorqueSource()
load_source = BlockComponents.Sources.Step(height=tau_load, start_time=load_step_start_time)
speed_reference = BlockComponents.Sources.Constant(k=w_motor)
controller = BlockComponents.Continuous.LimPID(k=k, Ti=Ti, Td=Td, Nd=Nd, y_max=5, y_min=-5)
signal_ff = BlockComponents.Sources.Constant(k=0)
speed_sensor = RotationalComponents.Sensors.VelocitySensor()
# Motor desired speed
parameter w_motor::AngularVelocity = 1
# Amplitude of load torque step
parameter tau_load::Torque = -0.3
# Load step start time
parameter load_step_start_time::Time = 3
# Controller gain
parameter k::Real = 0.5
# Controller time constant of the integrator block
parameter Ti::Time = 0.1
# Controller Time constant of the derivative block
parameter Td::Time = 1e5
parameter Nd::Real = 10
relations
initial motor.L1.i = 0
initial motor.inertia.w = 0
u: analysis_point(controller.y, source.V)
y: analysis_point(speed_sensor.w, controller.u_m)
r: analysis_point(speed_reference.y, controller.u_s)
connect(load_source.y, load.tau)
connect(source.p, motor.p)
connect(motor.n, source.n, ground.g)
connect(motor.shaft, load.spline)
connect(motor.housing, load.support, fixed.spline)
connect(speed_reference.y, controller.u_s)
connect(speed_sensor.w, controller.u_m)
connect(controller.y, source.V)
connect(controller.u_ff, signal_ff.y)
connect(speed_sensor.spline, motor.shaft)
end
```

In this example:
- `u` names the connection from the controller output to the voltage source input.
- `y` names the connection from the speed sensor output to the controller input.
- `r` names the connection from the speed reference to the controller reference input.

The diagram below illustrates the connections and analysis points in this example, abstracting the controller and plant components into blocks `C` and `P` respectively:

```
r ┌─────┐ ┌─────┐
───►│ │ u │ │ y
│ C ├────►│ P ├─┬─►
┌►│ │ │ │ │
│ └─────┘ └─────┘ │
│ │
└─────────────────────┘
```


## Model transformations
To facilitate analysis, ModelingToolkit may, depending on the analysis requested, transform connections and / or add new input variables. This section describes some of the available transformations.

### Linearization
When linearizing a model between two analysis points, ModelingToolkit will automatically add one perturbation input variable to each input analysis point. For example, in the diagram
```
│e₁
│ ┌─────┐
d₁────+──┴──► P ├─────┬──►e₄
│ └─────┘ y│
│u │
│ ┌─────┐ -│
e₂◄──┴─────┤ C ◄──┬──+───d₂
└─────┘ │
│e₃
```
linearization between analysis points `u` and `y` will add the artificial input variable `d₁`, and linearize between `d₁` and `y`. Note, the result of such a linearization is _not_ the transfer function of the system `P` between `u` and `y`, instead it is the _closed-loop transfer function_ $(I + PC)^{-1}P$ that is obtained with all the connections in the diagram intact. If the transfer function of the isolated system `P` is desired, one may make use of the `loop_openings` feature to break the connections `u` and `y` during the linearization, i.e., by passing `loop_openings = ["u", "y"]` to the analysis. Loop openings are discussed in more detail below.

### Sensitivity analysis
When computing the sensitivity function in the signal `y`

```
│e₁
│ ┌─────┐
d₁────+──┴──► P ├─────┬──►e₄
│ └─────┘ y│
│u │
│ ┌─────┐ -│
e₂◄──┴─────┤ C ◄──┬──+───d₂
└─────┘ │
│e₃
```
ModelingToolkit will automatically add the input variable `d₂` and the output variable `e₃`, i.e., the analysis point `y` will be perturbed by an artificial input and the output is taken to be the signal _after_ the perturbation. If, instead, the _complementary_ sensitivity function is requested, ModelingToolkit will add the same input variable `d₂`, but the output will instead be immediately _before_ the perturbation, i.e., the output variable `e₄`.

### Loop openings
All analysis-point transformations may be combined with _loop openings_. A loop opening is requested by passing the name of one or several analysis points to the argument `loop_openings`. For example, if `loop_openings = ["u"]` while linearizing between the analysis points `u` and `y`, the connection labeled `u` in the diagram above will be broken during the analysis. This will in this case result in the transfer function `P` being computed, rather than the closed-loop transfer function $(I + CP)^{-1}P$ that would be obtained if the loop was not opened. In this case, breaking the connection through `y` is not required in order to isolate the system `P`, since the block `C` is downstream of the analysis point `y`.
Loading
Loading