Skip to content
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .JuliaFormatter.toml

This file was deleted.

14 changes: 10 additions & 4 deletions .github/workflows/FormatCheck.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
name: "Format Check"
name: format-check

on:
push:
branches:
- 'master'
- 'main'
- 'release-'
tags: '*'
pull_request:

jobs:
format-check:
name: "Format Check"
uses: "SciML/.github/.github/workflows/format-check.yml@v1"
runic:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: fredrikekre/runic-action@v1
with:
version: '1'
24 changes: 16 additions & 8 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ ENV["GKSwstype"] = "100"

include("pages.jl")

makedocs(sitename = "ModelingToolkitStandardLibrary.jl",
makedocs(
sitename = "ModelingToolkitStandardLibrary.jl",
authors = "Julia Computing",
modules = [ModelingToolkit,
modules = [
ModelingToolkit,
ModelingToolkitStandardLibrary,
ModelingToolkitStandardLibrary.Blocks,
ModelingToolkitStandardLibrary.Mechanical,
Expand All @@ -29,13 +31,19 @@ makedocs(sitename = "ModelingToolkitStandardLibrary.jl",
ModelingToolkitStandardLibrary.Electrical,
ModelingToolkitStandardLibrary.Thermal,
ModelingToolkitStandardLibrary.Hydraulic,
ModelingToolkitStandardLibrary.Hydraulic.IsothermalCompressible],
ModelingToolkitStandardLibrary.Hydraulic.IsothermalCompressible,
],
clean = true, doctest = false, linkcheck = true,
linkcheck_ignore = ["https://www.mathworks.com/help/simscape/ug/basic-principles-of-modeling-physical-networks.html#bq89sba-6"],
warnonly = [:docs_block, :missing_docs, :cross_references],
format = Documenter.HTML(assets = ["assets/favicon.ico"],
canonical = "https://docs.sciml.ai/ModelingToolkitStandardLibrary/stable/"),
pages = pages)
format = Documenter.HTML(
assets = ["assets/favicon.ico"],
canonical = "https://docs.sciml.ai/ModelingToolkitStandardLibrary/stable/"
),
pages = pages
)

deploydocs(repo = "github.com/SciML/ModelingToolkitStandardLibrary.jl";
push_preview = true)
deploydocs(
repo = "github.com/SciML/ModelingToolkitStandardLibrary.jl";
push_preview = true
)
8 changes: 4 additions & 4 deletions docs/pages.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ pages = [
"Custom Components" => "tutorials/custom_component.md",
"Thermal Conduction Model" => "tutorials/thermal_model.md",
"DC Motor with Speed Controller" => "tutorials/dc_motor_pi.md",
"SampledData Component" => "tutorials/input_component.md"
"SampledData Component" => "tutorials/input_component.md",
],
"About Acausal Connections" => [
"Theory" => "connectors/connections.md",
"Sign Convention" => "connectors/sign_convention.md"
"Sign Convention" => "connectors/sign_convention.md",
],
"API" => [
"Basic Blocks" => "API/blocks.md",
Expand All @@ -18,6 +18,6 @@ pages = [
"Mechanical Components" => "API/mechanical.md",
"Thermal Components" => "API/thermal.md",
"Hydraulic Components" => "API/hydraulic.md",
"Linear Analysis" => "API/linear_analysis.md"
]
"Linear Analysis" => "API/linear_analysis.md",
],
]
6 changes: 3 additions & 3 deletions src/Blocks/Blocks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ export RealInput, RealInputArray, RealOutput, RealOutputArray, SISO
include("utils.jl")

export Gain, Sum, MatrixGain, Feedback, Add, Add3, Product, Division, Power, Modulo,
UnaryMinus, Floor, Ceil
UnaryMinus, Floor, Ceil
export Abs, Sign, Sqrt, Sin, Cos, Tan, Asin, Acos, Atan, Atan2, Sinh, Cosh, Tanh, Exp
export Log, Log10
include("math.jl")

export Constant, TimeVaryingFunction, Sine, Cosine, ContinuousClock, Ramp, Step, ExpSine,
Square, Triangular, Parameter, SampledData,
Interpolation, ParametrizedInterpolation
Square, Triangular, Parameter, SampledData,
Interpolation, ParametrizedInterpolation
include("sources.jl")

export Limiter, DeadZone, SlewRateLimiter
Expand Down
106 changes: 59 additions & 47 deletions src/Blocks/continuous.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Initial value of integrator state ``x`` can be set with `x`

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

sys = System(equations, t, vars, pars; name, systems)
Expand Down Expand Up @@ -74,7 +74,7 @@ Initial value of the state ``x`` can be set with `x`.
"""
@component function Derivative(; name, k = 1, T = nothing, x = 0.0)
@symcheck T > 0 ||
throw(ArgumentError("Time constant `T` has to be strictly positive"))
throw(ArgumentError("Time constant `T` has to be strictly positive"))

@named siso = SISO()
@unpack u, y = siso
Expand All @@ -93,7 +93,7 @@ Initial value of the state ``x`` can be set with `x`.

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

sys = System(equations, t, vars, pars; name, systems)
Expand Down Expand Up @@ -137,7 +137,7 @@ See also [`SecondOrder`](@ref)
"""
@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"))
throw(ArgumentError("Time constant `T` has to be strictly positive"))

@named siso = SISO()
@unpack u, y = siso
Expand All @@ -156,7 +156,7 @@ See also [`SecondOrder`](@ref)

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

sys = System(equations, t, vars, pars; name, systems)
Expand Down Expand Up @@ -211,7 +211,7 @@ Initial value of the state `x` can be set with `x`, and of derivative state `xd`
equations = Equation[
D(x) ~ xd,
D(xd) ~ w * (w * (k * u - x) - 2 * d * xd),
y ~ x
y ~ x,
]

sys = System(equations, t, vars, pars; name, systems)
Expand Down Expand Up @@ -243,7 +243,7 @@ See also [`LimPI`](@ref)
"""
@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"))
throw(ArgumentError("Time constant `T` has to be strictly positive"))

pars = @parameters begin
k = k, [description = "Proportional gain"]
Expand All @@ -266,7 +266,7 @@ See also [`LimPI`](@ref)
connect(addPI.output, gainPI.input),
connect(gainPI.output, ctr_output),
connect(err_input, int.input),
connect(int.output, addPI.input2)
connect(int.output, addPI.input2),
]

return System(equations, t, vars, pars; name, systems)
Expand All @@ -293,18 +293,20 @@ Text-book version of a PID-controller without actuator saturation and anti-windu

See also [`LimPID`](@ref)
"""
@component function PID(; name, k = 1, Ti = false, Td = false, Nd = 10, int__x = 0,
der__x = 0)
@component function PID(;
name, k = 1, Ti = false, Td = false, Nd = 10, int__x = 0,
der__x = 0
)
with_I = !isequal(Ti, false)
with_D = !isequal(Td, false)
@named err_input = RealInput() # control error
@named ctr_output = RealOutput() # control signal
@symcheck Ti ≥ 0 ||
throw(ArgumentError("Ti out of bounds, got $(Ti) but expected Ti ≥ 0"))
throw(ArgumentError("Ti out of bounds, got $(Ti) but expected Ti ≥ 0"))
@symcheck Td ≥ 0 ||
throw(ArgumentError("Td out of bounds, got $(Td) but expected Td ≥ 0"))
throw(ArgumentError("Td out of bounds, got $(Td) but expected Td ≥ 0"))
@symcheck Nd > 0 ||
throw(ArgumentError("Nd out of bounds, got $(Nd) but expected Nd > 0"))
throw(ArgumentError("Nd out of bounds, got $(Nd) but expected Nd > 0"))

pars = @parameters begin
k = k, [description = "Proportional gain"]
Expand Down Expand Up @@ -339,7 +341,7 @@ See also [`LimPID`](@ref)
eqs = [
connect(err_input, addPID.input1),
connect(addPID.output, gainPID.input),
connect(gainPID.output, ctr_output)
connect(gainPID.output, ctr_output),
]
if with_I
push!(eqs, connect(err_input, int.input))
Expand Down Expand Up @@ -380,7 +382,7 @@ The simplified expression above is given without the anti-windup protection.
"""
@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"))
throw(ArgumentError("Time constant `Ta` has to be strictly positive"))
@symcheck T > 0 || throw(ArgumentError("Time constant `T` has to be strictly positive"))
@symcheck u_max ≥ u_min || throw(ArgumentError("u_min must be smaller than u_max"))
pars = @parameters begin
Expand Down Expand Up @@ -411,7 +413,7 @@ The simplified expression above is given without the anti-windup protection.
connect(err_input, addTrack.input1),
connect(gainTrack.output, addTrack.input2),
connect(addTrack.output, int.input),
connect(int.output, addPI.input2)
connect(int.output, addPI.input2),
]
System(eqs, t, [], pars; name = name, systems = sys)
end
Expand Down Expand Up @@ -449,14 +451,16 @@ where the transfer function for the derivative includes additional filtering, se
- `measurement`
- `ctr_output`
"""
@component function LimPID(; name, k = 1, Ti = false, Td = false, wp = 1, wd = 1,
Ni = Ti == 0 ? Inf : √(max(Td / Ti, 1e-6)),
@component function LimPID(;
name, k = 1, Ti = false, Td = false, wp = 1, wd = 1,
Ni = Ti == 0 ? Inf : √(max(Td / Ti, 1.0e-6)),
Nd = 10,
u_max = Inf,
u_min = u_max > 0 ? -u_max : -Inf,
gains = false,
int__x = 0.0,
der__x = 0.0)
der__x = 0.0
)
with_I = !isequal(Ti, false)
with_D = !isequal(Td, false)
with_AWM = Ni != Inf
Expand All @@ -465,12 +469,12 @@ where the transfer function for the derivative includes additional filtering, se
Td = Td / k
end
@symcheck Ti ≥ 0 ||
throw(ArgumentError("Ti out of bounds, got $(Ti) but expected Ti ≥ 0"))
throw(ArgumentError("Ti out of bounds, got $(Ti) but expected Ti ≥ 0"))
@symcheck Td ≥ 0 ||
throw(ArgumentError("Td out of bounds, got $(Td) but expected Td ≥ 0"))
throw(ArgumentError("Td out of bounds, got $(Td) but expected Td ≥ 0"))
@symcheck u_max ≥ u_min || throw(ArgumentError("u_min must be smaller than u_max"))
@symcheck Nd > 0 ||
throw(ArgumentError("Nd out of bounds, got $(Nd) but expected Nd > 0"))
throw(ArgumentError("Nd out of bounds, got $(Nd) but expected Nd > 0"))

pars = @parameters begin
k = k, [description = "Proportional gain"]
Expand Down Expand Up @@ -530,7 +534,7 @@ where the transfer function for the derivative includes additional filtering, se
connect(addP.output, addPID.input1),
connect(addPID.output, gainPID.input),
connect(gainPID.output, limiter.input),
connect(limiter.output, ctr_output)
connect(limiter.output, ctr_output),
]
if with_I
push!(eqs, connect(reference, addI.input1))
Expand Down Expand Up @@ -592,8 +596,10 @@ y &= h(x, u)

linearized around the operating point `x₀, u₀`, we have `y0, u0 = h(x₀, u₀), u₀`.
"""
@component function StateSpace(; A, B, C, D = nothing, x = zeros(size(A, 1)), name,
u0 = zeros(size(B, 2)), y0 = zeros(size(C, 1)))
@component function StateSpace(;
A, B, C, D = nothing, x = zeros(size(A, 1)), name,
u0 = zeros(size(B, 2)), y0 = zeros(size(C, 1))
)
nx, nu, ny = size(A, 1), size(B, 2), size(C, 1)
size(A, 2) == nx || error("`A` has to be a square matrix.")
size(B, 1) == nx || error("`B` has to be of dimension ($nx x $nu).")
Expand All @@ -608,19 +614,23 @@ linearized around the operating point `x₀, u₀`, we have `y0, u0 = h(x₀, u
end
@named input = RealInput(nin = nu)
@named output = RealOutput(nout = ny)
@variables x(t)[1:nx]=x [
description = "State variables of StateSpace system $name"
@variables x(t)[1:nx] = x [
description = "State variables of StateSpace system $name",
]
# pars = @parameters A=A B=B C=C D=D # This is buggy
eqs = [ # FIXME: if array equations work
[Differential(t)(x[i]) ~
sum(A[i, k] * x[k] for k in 1:nx) +
sum(B[i, j] * (input.u[j] - u0[j]) for j in 1:nu)
for i in 1:nx]..., # cannot use D here
[output.u[j] ~
sum(C[j, i] * x[i] for i in 1:nx) +
sum(D[j, k] * (input.u[k] - u0[k]) for k in 1:nu) + y0[j]
for j in 1:ny]...
[
Differential(t)(x[i]) ~
sum(A[i, k] * x[k] for k in 1:nx) +
sum(B[i, j] * (input.u[j] - u0[j]) for j in 1:nu)
for i in 1:nx
]..., # cannot use D here
[
output.u[j] ~
sum(C[j, i] * x[i] for i in 1:nx) +
sum(D[j, k] * (input.u[k] - u0[k]) for k in 1:nu) + y0[j]
for j in 1:ny
]...,
]
compose(System(eqs, t, vcat(x...), [], name = name), [input, output])
end
Expand Down Expand Up @@ -668,24 +678,24 @@ See also [`StateSpace`](@ref) which handles MIMO systems, as well as [ControlSys

@parameters begin
b[1:nb] = b,
[
description = "Numerator coefficients of transfer function (e.g., 2s + 3 is specified as [2,3])"
]
[
description = "Numerator coefficients of transfer function (e.g., 2s + 3 is specified as [2,3])",
]
a[1:na] = a,
[
description = "Denominator coefficients of transfer function (e.g., `s² + 2ωs + ω^2` is specified as [1, 2ω, ω^2])"
]
[
description = "Denominator coefficients of transfer function (e.g., `s² + 2ωs + ω^2` is specified as [1, 2ω, ω^2])",
]
bb[1:(nbb + nb)] = [zeros(nbb); b]
end
d = bb[1] / a[1]# , [description = "Direct feedthrough gain"]
d = bb[1] / a[1] # , [description = "Direct feedthrough gain"]

a = collect(a)
a_end = ifelse(a[end] > 100 * symbolic_eps(sqrt(a' * a)), a[end], 1.0)

pars = [collect(b); a; collect(bb)]
@variables begin
x(t)[1:nx] = zeros(nx),
[description = "State of transfer function on controller canonical form"]
[description = "State of transfer function on controller canonical form"]
x_scaled(t)[1:nx] = collect(x) * a_end, [description = "Scaled vector x"]
u(t), [description = "Input of transfer function"]
y(t), [description = "Output of transfer function"]
Expand All @@ -700,10 +710,12 @@ See also [`StateSpace`](@ref) which handles MIMO systems, as well as [ControlSys
if nx == 0
eqs = [y ~ d * u]
else
eqs = Equation[D(x_scaled[1]) ~ (-a[2:na]'x_scaled + a_end * u) / a[1]
D.(x_scaled[2:nx]) .~ x_scaled[1:(nx - 1)]
y ~ ((bb[2:na] - d * a[2:na])'x_scaled) / a_end + d * u
x .~ x_scaled ./ a_end]
eqs = Equation[
D(x_scaled[1]) ~ (-a[2:na]'x_scaled + a_end * u) / a[1]
D.(x_scaled[2:nx]) .~ x_scaled[1:(nx - 1)]
y ~ ((bb[2:na] - d * a[2:na])'x_scaled) / a_end + d * u
x .~ x_scaled ./ a_end
]
end
push!(eqs, input.u ~ u)
push!(eqs, output.u ~ y)
Expand Down
Loading
Loading