Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b9ff959
refactor: avoid unnecessary scalarization
AayushSabharwal Nov 12, 2025
1e479d7
build: bump Symbolics compat
AayushSabharwal Nov 17, 2025
868e959
refactor: depend on MTKBase instead of MTK
AayushSabharwal Nov 28, 2025
6d192c4
refactor: use SciCompDSL.jl for `@mtkmodel`
AayushSabharwal Dec 1, 2025
5d56791
refactor: use `@component` syntax instead of `@mtkmodel`
AayushSabharwal Dec 16, 2025
4ad451a
refactor: remove `SciCompDSL` imports
AayushSabharwal Dec 16, 2025
0a7844c
test: import SciCompDSL in test
AayushSabharwal Dec 16, 2025
dc511eb
build: make SciCompDSL test dependency
AayushSabharwal Dec 16, 2025
3174bb8
build: bump DataInterpolations.jl compat
AayushSabharwal Dec 16, 2025
d14fc55
build: add MTK as test dependency
AayushSabharwal Dec 17, 2025
69467e5
build: bump ForwardDiff compat
AayushSabharwal Dec 17, 2025
a43c24b
fix: use new symbolic derivative registration syntax
AayushSabharwal Dec 22, 2025
921ec2e
test: fix some imports in tests
AayushSabharwal Dec 22, 2025
30ceb96
fix: use `bindings` instead of `parameter_dependencies`
AayushSabharwal Dec 22, 2025
fe32c77
fix: allow passing parameters to subcomponents in some cases
AayushSabharwal Dec 22, 2025
b1db94b
fix: fix `SlewRateLimiter`
AayushSabharwal Dec 22, 2025
5903e31
test: unwrap values in tests
AayushSabharwal Dec 22, 2025
d24a2a0
refactor: do not use `defaults`
AayushSabharwal Dec 22, 2025
17ebc85
test: add some missing guesses
AayushSabharwal Dec 22, 2025
ddcb8bc
test: fix access to array components
AayushSabharwal Dec 22, 2025
0e07044
refactor: remove deprecated exports
AayushSabharwal Dec 22, 2025
c3bccde
test: fix initializations for several tests
AayushSabharwal Dec 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
name = "ModelingToolkitStandardLibrary"
uuid = "16a59e39-deab-5bd0-87e4-056b12336739"
authors = ["Chris Rackauckas and Julia Computing"]
version = "2.25.0"
authors = ["Chris Rackauckas and Julia Computing"]

[deps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e"
IfElse = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
ModelingToolkitBase = "7771a370-6774-4173-bd38-47e70ca0b839"
PreallocationTools = "d236fae5-4411-538c-8e31-a6e3d9e00b46"
Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"

Expand All @@ -18,19 +18,21 @@ Aqua = "0.8"
ChainRulesCore = "1.24"
ControlSystemsBase = "1.4"
DataFrames = "1.7"
DataInterpolations = "6"
DataInterpolations = "8"
DiffEqBase = "6.152"
ForwardDiff = "0.10"
ForwardDiff = "0.10, 1"
IfElse = "0.1"
LinearAlgebra = "1.10"
ModelingToolkit = "10"
ModelingToolkit = "11"
ModelingToolkitBase = "1"
OrdinaryDiffEq = "6.87"
OrdinaryDiffEqDefault = "1.1"
PreallocationTools = "0.4.23"
SafeTestsets = "0.1"
SciCompDSL = "1"
SciMLStructures = "1.4.2"
SymbolicIndexingInterface = "0.3.28"
Symbolics = "6.14"
Symbolics = "7"
Test = "1"
julia = "1.10"

Expand All @@ -42,12 +44,14 @@ DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
DataInterpolations = "82cc6244-b520-54b8-b5a6-8a565e85f1d0"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
OrdinaryDiffEqDefault = "50262376-6c5a-4cf5-baba-aaf4f84d72d7"
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
SciCompDSL = "91a8cdf1-4ca6-467b-a780-87fda3fff15e"
SciMLStructures = "53ae85a6-f571-4167-b2af-e1d143709226"
SymbolicIndexingInterface = "2efcf032-c050-4f8e-a9bb-153293bab1f5"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["ADTypes", "Aqua", "LinearAlgebra", "OrdinaryDiffEqDefault", "OrdinaryDiffEq", "SafeTestsets", "Test", "ControlSystemsBase", "DataFrames", "DataInterpolations", "SciMLStructures", "SymbolicIndexingInterface", "ForwardDiff"]
test = ["ADTypes", "Aqua", "LinearAlgebra", "OrdinaryDiffEqDefault", "OrdinaryDiffEq", "SafeTestsets", "Test", "ControlSystemsBase", "DataFrames", "DataInterpolations", "SciMLStructures", "SymbolicIndexingInterface", "ForwardDiff", "SciCompDSL", "ModelingToolkit"]
7 changes: 2 additions & 5 deletions src/Blocks/Blocks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
The module `Blocks` contains common input-output components, referred to as blocks.
"""
module Blocks
using ModelingToolkit, Symbolics
using ModelingToolkitBase, Symbolics
import IfElse: ifelse
import ..@symcheck
using ModelingToolkit: getdefault, t_nounits as t, D_nounits as D
using ModelingToolkitBase: getdefault, t_nounits as t, D_nounits as D

export RealInput, RealInputArray, RealOutput, RealOutputArray, SISO
include("utils.jl")
Expand All @@ -28,7 +28,4 @@ export Integrator, Derivative, FirstOrder, SecondOrder, StateSpace, TransferFunc
export PI, LimPI, PID, LimPID
include("continuous.jl")

export AnalysisPoint, get_sensitivity, get_comp_sensitivity,
get_looptransfer, open_loop

end
183 changes: 112 additions & 71 deletions src/Blocks/continuous.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,28 @@ Initial value of integrator state ``x`` can be set with `x`

- `x`: State of Integrator. Defaults to 0.0.
"""
@mtkmodel Integrator begin
@extend u, y = siso = SISO()
@variables begin
x(t) = 0.0, [description = "State of Integrator"]
@component function Integrator(; name, k = 1, x = 0.0)
@named siso = SISO()
@unpack u, y = siso

pars = @parameters begin
k = k, [description = "Gain"]
end
@parameters begin
k = 1, [description = "Gain"]

systems = @named begin
end
@equations begin
D(x) ~ k * u
y ~ x

vars = @variables begin
x(t) = x, [description = "State of Integrator"]
end

equations = Equation[
D(x) ~ k * u,
y ~ x
]

sys = System(equations, t, vars, pars; name, systems)
return extend(sys, siso)
end

"""
Expand All @@ -37,8 +47,8 @@ end
Outputs an approximate derivative of the input. The transfer function of this block is

```
k k ks
─ - ─────── = ──────
k k ks
─ - ─────── = ──────
T sT² + T sT + 1
```

Expand All @@ -62,23 +72,32 @@ Initial value of the state ``x`` can be set with `x`.
- `input`
- `output`
"""
@mtkmodel Derivative begin
@extend u, y = siso = SISO()
@variables begin
x(t) = 0.0, [description = "Derivative-filter state"]
end
@parameters begin
@component function Derivative(; name, k = 1, T = nothing, x = 0.0)
@symcheck T > 0 ||
throw(ArgumentError("Time constant `T` has to be strictly positive"))

@named siso = SISO()
@unpack u, y = siso

pars = @parameters begin
T = T, [description = "Time constant"]
k = 1, [description = "Gain"]
k = k, [description = "Gain"]
end
begin
@symcheck T > 0 ||
throw(ArgumentError("Time constant `T` has to be strictly positive"))

systems = @named begin
end
@equations begin
D(x) ~ (u - x) / T
y ~ (k / T) * (u - x)

vars = @variables begin
x(t) = x, [description = "Derivative-filter state"]
end

equations = Equation[
D(x) ~ (u - x) / T,
y ~ (k / T) * (u - x)
]

sys = System(equations, t, vars, pars; name, systems)
return extend(sys, siso)
end

"""
Expand Down Expand Up @@ -116,26 +135,32 @@ Initial value of the state `x` can be set with `x`

See also [`SecondOrder`](@ref)
"""
@mtkmodel FirstOrder begin
@extend u, y = siso = SISO()
@structural_parameters begin
lowpass = true
end
@variables begin
x(t) = 0.0, [description = "State of FirstOrder filter"]
end
@parameters begin
@component function FirstOrder(; name, lowpass = true, T = nothing, k = 1.0, x = 0.0)
@symcheck T > 0 ||
throw(ArgumentError("Time constant `T` has to be strictly positive"))

@named siso = SISO()
@unpack u, y = siso

pars = @parameters begin
T = T, [description = "Time constant"]
k = 1.0, [description = "Gain"]
k = k, [description = "Gain"]
end
begin
@symcheck T > 0 ||
throw(ArgumentError("Time constant `T` has to be strictly positive"))

systems = @named begin
end
@equations begin
D(x) ~ (k * u - x) / T
lowpass ? y ~ x : y ~ k * u - x

vars = @variables begin
x(t) = x, [description = "State of FirstOrder filter"]
end

equations = Equation[
D(x) ~ (k * u - x) / T,
lowpass ? (y ~ x) : (y ~ k * u - x)
]

sys = System(equations, t, vars, pars; name, systems)
return extend(sys, siso)
end

"""
Expand Down Expand Up @@ -165,22 +190,32 @@ Initial value of the state `x` can be set with `x`, and of derivative state `xd`
- `input`
- `output`
"""
@mtkmodel SecondOrder begin
@extend u, y = siso = SISO()
@variables begin
x(t), [description = "State of SecondOrder filter", guess = 0.0]
xd(t), [description = "Derivative state of SecondOrder filter", guess = 0.0]
@component function SecondOrder(; name, k = 1.0, w = 1.0, d = 1.0, x = nothing, xd = nothing)
@named siso = SISO()
@unpack u, y = siso

pars = @parameters begin
k = k, [description = "Gain"]
w = w, [description = "Bandwidth (angular frequency)"]
d = d, [description = "Relative damping"]
end
@parameters begin
k = 1.0, [description = "Gain"]
w = 1.0, [description = "Bandwidth (angular frequency)"]
d = 1.0, [description = "Relative damping"]

systems = @named begin
end
@equations begin
D(x) ~ xd
D(xd) ~ w * (w * (k * u - x) - 2 * d * xd)
y ~ x

vars = @variables begin
x(t) = x, [description = "State of SecondOrder filter", guess = 0.0]
xd(t) = xd, [description = "Derivative state of SecondOrder filter", guess = 0.0]
end

equations = Equation[
D(x) ~ xd,
D(xd) ~ w * (w * (k * u - x) - 2 * d * xd),
y ~ x
]

sys = System(equations, t, vars, pars; name, systems)
return extend(sys, siso)
end

"""
Expand All @@ -206,29 +241,35 @@ U(s) = k (1 + \\dfrac{1}{sT}) E(S)

See also [`LimPI`](@ref)
"""
@mtkmodel PI begin
@parameters begin
k = 1.0, [description = "Proportional gain"]
T = 1.0, [description = "Integrator time constant"]
end
begin
@symcheck T > 0 ||
throw(ArgumentError("Time constant `T` has to be strictly positive"))
@component function PI(; name, k = 1.0, T = 1.0, gainPI__k = nothing)
@symcheck T > 0 ||
throw(ArgumentError("Time constant `T` has to be strictly positive"))

pars = @parameters begin
k = k, [description = "Proportional gain"]
T = T, [description = "Integrator time constant"]
end
@components begin

systems = @named begin
err_input = RealInput() # control error
ctr_output = RealOutput() # control signal
gainPI = Gain(; k)
gainPI = Gain(; k = gainPI__k)
addPI = Add()
int = Integrator(k = 1 / T, x = 0.0)
end
@equations begin
connect(err_input, addPI.input1)
connect(addPI.output, gainPI.input)
connect(gainPI.output, ctr_output)
connect(err_input, int.input)
connect(int.output, addPI.input2)

vars = @variables begin
end

equations = Equation[
connect(err_input, addPI.input1),
connect(addPI.output, gainPI.input),
connect(gainPI.output, ctr_output),
connect(err_input, int.input),
connect(int.output, addPI.input2)
]

return System(equations, t, vars, pars; name, systems)
end

"""
Expand Down Expand Up @@ -337,7 +378,7 @@ The simplified expression above is given without the anti-windup protection.
- `err_input`
- `ctr_output`
"""
@component function LimPI(; name, k = 1, T, u_max, u_min = -u_max, Ta, int__x = 0.0)
@component function LimPI(; name, k = 1, T = nothing, u_max = nothing, u_min = -u_max, Ta = nothing, int__x = 0.0)
@symcheck Ta > 0 ||
throw(ArgumentError("Time constant `Ta` has to be strictly positive"))
@symcheck T > 0 || throw(ArgumentError("Time constant `T` has to be strictly positive"))
Expand Down Expand Up @@ -610,7 +651,7 @@ To set the initial state, it's recommended to set the initial condition for `x`,
- `input`
- `output`

See also [`StateSpace`](@ref) which handles MIMO systems, as well as [ControlSystemsMTK.jl](https://juliacontrol.github.io/ControlSystemsMTK.jl/stable/) for an interface between [ControlSystems.jl](https://juliacontrol.github.io/ControlSystems.jl/stable/) and ModelingToolkit.jl for advanced manipulation of transfer functions and linear statespace systems. For linearization, see [`linearize`](@ref) and [Linear Analysis](https://docs.sciml.ai/ModelingToolkitStandardLibrary/stable/API/linear_analysis/).
See also [`StateSpace`](@ref) which handles MIMO systems, as well as [ControlSystemsMTK.jl](https://juliacontrol.github.io/ControlSystemsMTK.jl/stable/) for an interface between [ControlSystems.jl](https://juliacontrol.github.io/ControlSystems.jl/stable/) and ModelingToolkitBase.jl for advanced manipulation of transfer functions and linear statespace systems. For linearization, see [`linearize`](@ref) and [Linear Analysis](https://docs.sciml.ai/ModelingToolkitStandardLibrary/stable/API/linear_analysis/).
"""
@component function TransferFunction(; b = [1], a = [1, 1], name)
nb = length(b)
Expand Down
Loading
Loading