diff --git a/Project.toml b/Project.toml index 89dd78f93..cf0643117 100644 --- a/Project.toml +++ b/Project.toml @@ -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" @@ -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" @@ -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"] diff --git a/src/Blocks/Blocks.jl b/src/Blocks/Blocks.jl index be434fba7..9d30d969d 100644 --- a/src/Blocks/Blocks.jl +++ b/src/Blocks/Blocks.jl @@ -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") diff --git a/src/Blocks/continuous.jl b/src/Blocks/continuous.jl index 9f40b7de1..794b9933f 100644 --- a/src/Blocks/continuous.jl +++ b/src/Blocks/continuous.jl @@ -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 """ @@ -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 ``` @@ -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 """ @@ -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 """ @@ -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 """ @@ -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) + @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) 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 """ @@ -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")) @@ -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) diff --git a/src/Blocks/math.jl b/src/Blocks/math.jl index d2ad76fc0..a46ebfe24 100644 --- a/src/Blocks/math.jl +++ b/src/Blocks/math.jl @@ -12,16 +12,28 @@ Output the product of a gain value with the input signal. - `input` - `output` """ -@mtkmodel Gain begin - @extend u, y = siso = SISO() - @parameters begin - k, [description = "Gain"] +@component function Gain(; name, k = nothing) + @named siso = SISO() + @unpack u, y = siso + + pars = @parameters begin + k = k, [description = "Gain"] end - @equations begin - y ~ k * u + + systems = @named begin end + + vars = @variables begin + end + + equations = Equation[ + y ~ k * u + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, siso) end -Gain.f(k; name) = Gain.f(; k, name) +Gain(k; name) = Gain(; k, name) """ MatrixGain(; K::AbstractArray, name) @@ -37,22 +49,27 @@ Output the product of a gain matrix with the input signal vector. - `input` - `output` """ -@mtkmodel MatrixGain begin - @structural_parameters begin - K - end - begin - nout = size(K, 1) - nin = size(K, 2) +@component function MatrixGain(; name, K = nothing) + nout = size(K, 1) + nin = size(K, 2) + + pars = @parameters begin end - @components begin + + systems = @named begin input = RealInput(; nin = nin) output = RealOutput(; nout = nout) end - @equations begin + + vars = @variables begin + end + + equations = Equation[ [output.u[i] ~ sum(K[i, j] * input.u[j] for j in 1:nin) for i in 1:nout]... - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -66,14 +83,23 @@ Input port dimension can be set with `input__nin` - `input` - `output` """ -@mtkmodel Sum begin - @components begin +@component function Sum(; name, nin = nothing) + pars = @parameters begin + end + + systems = @named begin input = RealInput(; nin) output = RealOutput() end - @equations begin - output.u ~ sum(input.u) + + vars = @variables begin end + + equations = Equation[ + output.u ~ sum(input.u) + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -87,15 +113,24 @@ Output difference between reference input (input1) and feedback input (input2). - `input2` - `output` """ -@mtkmodel Feedback begin - @components begin +@component function Feedback(; name) + pars = @parameters begin + end + + systems = @named begin input1 = RealInput() input2 = RealInput() output = RealOutput() end - @equations begin - output.u ~ input1.u - input2.u + + vars = @variables begin end + + equations = Equation[ + output.u ~ input1.u - input2.u + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -114,19 +149,26 @@ Output the sum of the two scalar inputs. - `input2` - `output` """ -@mtkmodel Add begin - @components begin +@component function Add(; name, k1 = 1.0, k2 = 1.0) + pars = @parameters begin + k1 = k1, [description = "Gain of Add input1"] + k2 = k2, [description = "Gain of Add input2"] + end + + systems = @named begin input1 = RealInput() input2 = RealInput() output = RealOutput() end - @parameters begin - k1 = 1.0, [description = "Gain of Add input1"] - k2 = 1.0, [description = "Gain of Add input2"] + + vars = @variables begin end - @equations begin + + equations = Equation[ output.u ~ k1 * input1.u + k2 * input2.u - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -147,21 +189,28 @@ Output the sum of the three scalar inputs. - `input3` - `output` """ -@mtkmodel Add3 begin - @components begin +@component function Add3(; name, k1 = 1.0, k2 = 1.0, k3 = 1.0) + pars = @parameters begin + k1 = k1, [description = "Gain of Add input1"] + k2 = k2, [description = "Gain of Add input2"] + k3 = k3, [description = "Gain of Add input3"] + end + + systems = @named begin input1 = RealInput() input2 = RealInput() input3 = RealInput() output = RealOutput() end - @parameters begin - k1 = 1.0, [description = "Gain of Add input1"] - k2 = 1.0, [description = "Gain of Add input2"] - k3 = 1.0, [description = "Gain of Add input3"] + + vars = @variables begin end - @equations begin + + equations = Equation[ output.u ~ k1 * input1.u + k2 * input2.u + k3 * input3.u - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -175,15 +224,24 @@ Output product of the two inputs. - `input2` - `output` """ -@mtkmodel Product begin - @components begin +@component function Product(; name) + pars = @parameters begin + end + + systems = @named begin input1 = RealInput() input2 = RealInput() output = RealOutput() end - @equations begin - output.u ~ input1.u * input2.u + + vars = @variables begin end + + equations = Equation[ + output.u ~ input1.u * input2.u + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -197,15 +255,24 @@ Output first input divided by second input. - `input2` - `output` """ -@mtkmodel Division begin - @components begin +@component function Division(; name) + pars = @parameters begin + end + + systems = @named begin input1 = RealInput() input2 = RealInput(guess = 1.0) # denominator can not be zero output = RealOutput() end - @equations begin - output.u ~ input1.u / input2.u + + vars = @variables begin end + + equations = Equation[ + output.u ~ input1.u / input2.u + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -219,15 +286,24 @@ Output the exponential with base as the first input and exponent as second input - `exponent` - `output` """ -@mtkmodel Power begin - @components begin +@component function Power(; name) + pars = @parameters begin + end + + systems = @named begin base = RealInput() exponent = RealInput() output = RealOutput() end - @equations begin - output.u ~ base.u^exponent.u + + vars = @variables begin end + + equations = Equation[ + output.u ~ base.u^exponent.u + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -241,15 +317,24 @@ Output the remainder when the first input is divided by second input. - `divisor` - `remainder` """ -@mtkmodel Modulo begin - @components begin +@component function Modulo(; name) + pars = @parameters begin + end + + systems = @named begin dividend = RealInput() divisor = RealInput(guess = 1.0) # denominator can not be zero remainder = RealOutput() end - @equations begin - remainder.u ~ mod(dividend.u, divisor.u) + + vars = @variables begin end + + equations = Equation[ + remainder.u ~ mod(dividend.u, divisor.u) + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -262,14 +347,23 @@ Output the product of -1 and the input. - `input` - `output` """ -@mtkmodel UnaryMinus begin - @components begin +@component function UnaryMinus(; name) + pars = @parameters begin + end + + systems = @named begin input = RealInput() output = RealOutput() end - @equations begin - output.u ~ -(input.u) + + vars = @variables begin end + + equations = Equation[ + output.u ~ -(input.u) + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -282,14 +376,23 @@ Output the floor rounding of the input. - `input` - `output` """ -@mtkmodel Floor begin - @components begin +@component function Floor(; name) + pars = @parameters begin + end + + systems = @named begin input = RealInput() output = RealOutput() end - @equations begin - output.u ~ floor(input.u) + + vars = @variables begin end + + equations = Equation[ + output.u ~ floor(input.u) + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -302,14 +405,23 @@ Output the ceiling rounding of the input. - `input` - `output` """ -@mtkmodel Ceil begin - @components begin +@component function Ceil(; name) + pars = @parameters begin + end + + systems = @named begin input = RealInput() output = RealOutput() end - @equations begin - output.u ~ ceil(input.u) + + vars = @variables begin end + + equations = Equation[ + output.u ~ ceil(input.u) + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -324,16 +436,27 @@ If the given function is not composed of simple core methods (e.g. sin, abs, ... - `input` - `output` """ -@mtkmodel StaticNonLinearity begin - @structural_parameters begin - func +@component function StaticNonLinearity(; name, func = nothing) + @named siso = SISO() + @unpack u, y = siso + + pars = @parameters begin end - @extend u, y = siso = SISO() - @equations begin - y ~ func(u) + + systems = @named begin + end + + vars = @variables begin end + + equations = Equation[ + y ~ func(u) + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, siso) end -StaticNonLinearity.f(func; name) = StaticNonLinearity(; func, name) +StaticNonLinearity(func; name) = StaticNonLinearity(; func, name) """ Abs(; name) @@ -445,15 +568,24 @@ Output the arc tangent of the input. - `input2` - `output` """ -@mtkmodel Atan2 begin - @components begin +@component function Atan2(; name) + pars = @parameters begin + end + + systems = @named begin input1 = RealInput() input2 = RealInput() output = RealOutput() end - @equations begin - output.u ~ atan(input1.u, input2.u) + + vars = @variables begin end + + equations = Equation[ + output.u ~ atan(input1.u, input2.u) + ] + + return System(equations, t, vars, pars; name, systems) end """ diff --git a/src/Blocks/nonlinear.jl b/src/Blocks/nonlinear.jl index b51125c34..e6d539ec8 100644 --- a/src/Blocks/nonlinear.jl +++ b/src/Blocks/nonlinear.jl @@ -15,7 +15,7 @@ Limit the range of a signal. - `input` - `output` """ -@component function Limiter(; name, y_max, y_min = y_max > 0 ? -y_max : -Inf) +@component function Limiter(; name, y_max = nothing, y_min = y_max > 0 ? -y_max : -Inf) @symcheck y_max ≥ y_min || throw(ArgumentError("`y_min` must be smaller than `y_max`")) m = (y_max + y_min) / 2 siso = SISO(u_start = m, y_start = m, name = :siso) # Default signals to center of saturation to minimize risk of saturation while linearizing etc. @@ -56,22 +56,35 @@ If the input is within `u_min` ... `u_max`, the output is zero. Outside of this - `input` - `output` """ -@mtkmodel DeadZone begin - @parameters begin - u_max, [description = "Upper limit of dead zone of DeadZone"] - u_min = -u_max, [description = "Lower limit of dead zone of DeadZone"] +@component function DeadZone(; name, u_max = nothing, u_min = nothing) + # Set default for u_min based on u_max + _u_min = isnothing(u_min) ? (isnothing(u_max) ? nothing : -u_max) : u_min + + # Validation (only if u_max is a concrete value) + if !isnothing(u_max) && !ModelingToolkitBase.isvariable(u_max) + u_max ≥ _u_min || throw(ArgumentError("`u_min` must be smaller than `u_max`")) end - begin - if !ModelingToolkit.isvariable(u_max) - u_max ≥ u_min || throw(ArgumentError("`u_min` must be smaller than `u_max`")) - end + + @named siso = SISO() + @unpack u, y = siso + + pars = @parameters begin + u_max = u_max, [description = "Upper limit of dead zone of DeadZone"] + u_min = _u_min, [description = "Lower limit of dead zone of DeadZone"] end - @extend u, y = siso = SISO() + systems = @named begin + end - @equations begin - y ~ _dead_zone(u, u_min, u_max) + vars = @variables begin end + + equations = Equation[ + y ~ _dead_zone(u, u_min, u_max) + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, siso) end """ diff --git a/src/Blocks/sources.jl b/src/Blocks/sources.jl index 61a2e4116..4840723b5 100644 --- a/src/Blocks/sources.jl +++ b/src/Blocks/sources.jl @@ -75,16 +75,23 @@ Generate constant signal. - `output` """ -@mtkmodel Constant begin - @components begin +@component function Constant(; k = 0.0, name) + pars = @parameters begin + k = k, [description = "Constant output value of block"] + end + + systems = @named begin output = RealOutput() end - @parameters begin - k = 0.0, [description = "Constant output value of block"] + + vars = @variables begin end - @equations begin + + equations = Equation[ output.u ~ k - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -97,18 +104,24 @@ The input variable `t` can be changed by passing a different variable as the key # Connectors: - `output` """ -@mtkmodel TimeVaryingFunction begin - @structural_parameters begin - f +@component function TimeVaryingFunction(; f = nothing, name) + pars = @parameters begin end - @components begin + + systems = @named begin output = RealOutput() end - @equations begin - output.u ~ f(t) + + vars = @variables begin end + + equations = Equation[ + output.u ~ f(t) + ] + + return System(equations, t, vars, pars; name, systems) end -TimeVaryingFunction.f(f; name) = TimeVaryingFunction(; f, name) +TimeVaryingFunction(f; name) = TimeVaryingFunction(; f, name) """ Sine(; name, frequency, amplitude = 1, phase = 0, offset = 0, start_time = 0, @@ -131,7 +144,7 @@ Generate sine signal. - `output` """ @component function Sine(; name, - frequency, + frequency = nothing, amplitude = 1, phase = 0, offset = 0, @@ -173,7 +186,7 @@ Generate cosine signal. - `output` """ @component function Cosine(; name, - frequency, + frequency = nothing, amplitude = 1, phase = 0, offset = 0, @@ -368,7 +381,7 @@ Exponentially damped sine signal. - `output` """ @component function ExpSine(; name, - frequency, + frequency = nothing, amplitude = 1.0, damping = 0.1, phase = 0.0, @@ -655,8 +668,8 @@ data input component. """ @component function SampledData(::Val{SampledDataType.vector_based}; name, - buffer, - sample_time, + buffer = nothing, + sample_time = nothing, circular_buffer = true) T = eltype(buffer) pars = @parameters begin @@ -822,7 +835,7 @@ Base.nameof(::CachedInterpolation) = :CachedInterpolation @register_symbolic (f::CachedInterpolation)(u::AbstractArray, x::AbstractArray, args::Tuple) """ - ParametrizedInterpolation(interp_type, u, x, args...; name, t = ModelingToolkit.t_nounits) + ParametrizedInterpolation(interp_type, u, x, args...; name, t = ModelingToolkitBase.t_nounits) Represent function interpolation symbolically as a block component, with the interpolation data represented parametrically. By default interpolation types from [`DataInterpolations.jl`](https://github.com/SciML/DataInterpolations.jl) are supported, @@ -862,7 +875,7 @@ function ParametrizedInterpolation( eqs = [output.u ~ interpolator(input.u)] - System(eqs, ModelingToolkit.t_nounits, [], + System(eqs, ModelingToolkitBase.t_nounits, [], [data, ts, interpolation_type, interpolator]; parameter_dependencies = [ interpolator ~ build_interpolation(data, ts, args) diff --git a/src/Blocks/utils.jl b/src/Blocks/utils.jl index 61cbb484e..07e643690 100644 --- a/src/Blocks/utils.jl +++ b/src/Blocks/utils.jl @@ -15,9 +15,8 @@ input = true, description = "Inner variable in RealInput $name" ] - u = collect(u) end - System(Equation[], t, [u;], []; name = name, guesses = [(u .=> guess);]) + System(Equation[], t, [u;], []; name = name, guesses = [u => guess]) end @doc """ RealInput(;name, guess) @@ -73,9 +72,8 @@ Connector with an array of input signals of type Real. output = true, description = "Inner variable in RealOutput $name" ] - u = collect(u) end - System(Equation[], t, [u;], []; name = name, guesses = [(u .=> guess);]) + System(Equation[], t, [u;], []; name = name, guesses = [u => guess]) end @doc """ RealOutput(;name, guess) @@ -124,23 +122,28 @@ Single input single output (SISO) continuous system block. - `u_start`: Initial value for the input - `y_start`: Initial value for the output """ -@mtkmodel SISO begin - @parameters begin - u_start = 0.0 - y_start = 0.0 +@component function SISO(; name, u_start = 0.0, y_start = 0.0, u = nothing, y = nothing) + pars = @parameters begin + u_start = u_start + y_start = y_start end - @variables begin - u(t), [guess = u_start, description = "Input of SISO system"] - y(t), [guess = y_start, description = "Output of SISO system"] - end - @components begin + + systems = @named begin input = RealInput(guess = u_start) output = RealOutput(guess = y_start) end - @equations begin - u ~ input.u - y ~ output.u + + vars = @variables begin + u(t) = u, [guess = u_start, description = "Input of SISO system"] + y(t) = y, [guess = y_start, description = "Output of SISO system"] end + + equations = Equation[ + u ~ input.u, + y ~ output.u + ] + + return System(equations, t, vars, pars; name, systems) end """ diff --git a/src/Electrical/Analog/ideal_components.jl b/src/Electrical/Analog/ideal_components.jl index 8ef5b702d..89a47712e 100644 --- a/src/Electrical/Analog/ideal_components.jl +++ b/src/Electrical/Analog/ideal_components.jl @@ -8,13 +8,22 @@ node. - `g` """ -@mtkmodel Ground begin - @components begin +@component function Ground(; name) + pars = @parameters begin + end + + systems = @named begin g = Pin() end - @equations begin - g.v ~ 0 + + vars = @variables begin end + + equations = Equation[ + g.v ~ 0 + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -40,36 +49,48 @@ Generic resistor with optional temperature dependency. - `alpha`: [K⁻¹] Temperature coefficient of resistance - `T_dep`: [bool] Temperature dependency """ -@mtkmodel Resistor begin - @extend v, i = oneport = OnePort() - - @structural_parameters begin - T_dep = false - end - - @parameters begin - R = 1.0, [description = "Reference resistance"] - T_ref = 300.15, [description = "Reference temperature"] - alpha = 0.0, [description = "Temperature coefficient of resistance"] +@component function Resistor(; T_dep = false, R = 1.0, T_ref = 300.15, alpha = 0.0, name) + @named oneport = OnePort() + @unpack v, i = oneport + + pars = @parameters begin + R = R, [description = "Reference resistance"] + T_ref = T_ref, [description = "Reference temperature"] + alpha = alpha, [description = "Temperature coefficient of resistance"] end - if T_dep - @components begin + systems = if T_dep + @named begin heat_port = HeatPort() end + else + @named begin + end + end + + vars = if T_dep @variables begin R_T(t), [description = "Temperature-dependent resistance"] end - @equations begin - R_T ~ R * (1 + alpha * (heat_port.T - T_ref)) # Temperature-dependent resistance - heat_port.Q_flow ~ -v * i # -LossPower - v ~ i * R_T # Ohm's Law - end else - @equations begin - v ~ i * R # Ohm's Law for constant resistance + @variables begin end end + + equations = if T_dep + Equation[ + R_T ~ R * (1 + alpha * (heat_port.T - T_ref)), + heat_port.Q_flow ~ -v * i, + v ~ i * R_T + ] + else + Equation[ + v ~ i * R + ] + end + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, oneport) end """ @@ -90,14 +111,26 @@ See [OnePort](@ref) - `G`: [`S`] Conductance """ -@mtkmodel Conductor begin - @extend v, i = oneport = OnePort() - @parameters begin - G, [description = "Conductance"] +@component function Conductor(; G = nothing, name) + @named oneport = OnePort() + @unpack v, i = oneport + + pars = @parameters begin + G = G, [description = "Conductance"] end - @equations begin - i ~ v * G + + systems = @named begin + end + + vars = @variables begin end + + equations = Equation[ + i ~ v * G + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, oneport) end """ @@ -119,14 +152,26 @@ See [OnePort](@ref) - `C`: [`F`] Capacitance """ -@mtkmodel Capacitor begin - @parameters begin - C, [description = "Capacitance"] +@component function Capacitor(; C = nothing, v = nothing, name) + @named oneport = OnePort(; v) + @unpack v, i = oneport + + pars = @parameters begin + C = C, [description = "Capacitance"] end - @extend v, i = oneport = OnePort(; v) - @equations begin - D(v) ~ i / C + + systems = @named begin end + + vars = @variables begin + end + + equations = Equation[ + D(v) ~ i / C + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, oneport) end """ @@ -148,14 +193,26 @@ See [OnePort](@ref) - `L`: [`H`] Inductance """ -@mtkmodel Inductor begin - @parameters begin - L, [description = "Inductance"] +@component function Inductor(; L = nothing, i = nothing, name) + @named oneport = OnePort(; i) + @unpack v, i = oneport + + pars = @parameters begin + L = L, [description = "Inductance"] end - @extend v, i = oneport = OnePort(; i) - @equations begin - D(i) ~ 1 / L * v + + systems = @named begin + end + + vars = @variables begin end + + equations = Equation[ + D(i) ~ 1 / L * v + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, oneport) end """ @@ -176,12 +233,26 @@ See [TwoPort](@ref) - `n1` Negative pin (left port) - `n2` Negative pin (right port) """ -@mtkmodel IdealOpAmp begin - @extend v1, v2, i1, i2 = twoport = TwoPort() - @equations begin - v1 ~ 0 - i1 ~ 0 +@component function IdealOpAmp(; name) + @named twoport = TwoPort() + @unpack v1, v2, i1, i2 = twoport + + pars = @parameters begin + end + + systems = @named begin end + + vars = @variables begin + end + + equations = Equation[ + v1 ~ 0, + i1 ~ 0 + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, twoport) end """ @@ -198,11 +269,25 @@ See [OnePort](@ref) - `p` Positive pin - `n` Negative pin """ -@mtkmodel Short begin - @extend v, i = oneport = OnePort() - @equations begin - v ~ 0 +@component function Short(; name) + @named oneport = OnePort() + @unpack v, i = oneport + + pars = @parameters begin + end + + systems = @named begin end + + vars = @variables begin + end + + equations = Equation[ + v ~ 0 + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, oneport) end """ @@ -228,26 +313,34 @@ Electromotoric force (electric/mechanic transformer) - `k`: [`N⋅m/A`] Transformation coefficient """ -@mtkmodel EMF begin - @parameters begin - k, [description = "Transformation coefficient"] - end - @variables begin - phi(t), [guess = 0.0, description = "Rotation Angle"] - w(t), [guess = 0.0] +@component function EMF(; k = nothing, name) + @named oneport = OnePort() + @unpack v, i = oneport + + pars = @parameters begin + k = k, [description = "Transformation coefficient"] end - @extend v, i = oneport = OnePort() - @components begin + + systems = @named begin flange = Flange() support = Support() end - @equations begin - phi ~ flange.phi - support.phi - D(phi) ~ w - k * w ~ v - flange.tau ~ -k * i - support.tau ~ -flange.tau + + vars = @variables begin + phi(t), [guess = 0.0, description = "Rotation Angle"] + w(t), [guess = 0.0] end + + equations = Equation[ + phi ~ flange.phi - support.phi, + D(phi) ~ w, + k * w ~ v, + flange.tau ~ -k * i, + support.tau ~ -flange.tau + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, oneport) end """ @@ -272,40 +365,54 @@ Generic diode with optional temperature dependency. - `T`: [K] Constant ambient temperature - only used if T_dep=false - `T_dep`: [bool] Temperature dependency """ -@mtkmodel Diode begin - @constants begin +@component function Diode(; T_dep = false, Is = 1e-6, n = 1, T = 300.15, v = 0.0, name) + consts = @constants begin k = 1.380649e-23 # Boltzmann constant (J/K) q = 1.602176634e-19 # Elementary charge (C) end - @extend v, i = oneport = OnePort(; v = 0.0) - @structural_parameters begin - T_dep = false - end + @named oneport = OnePort(; v) + @unpack v, i = oneport - @parameters begin - Is = 1e-6, [description = "Saturation current (A)"] - n = 1, [description = "Ideality factor"] - T = 300.15, [description = "Ambient temperature"] + pars = @parameters begin + Is = Is, [description = "Saturation current (A)"] + n = n, [description = "Ideality factor"] + T = T, [description = "Ambient temperature"] end + pars = [pars; consts] - if T_dep - @components begin + systems = if T_dep + @named begin port = HeatPort() end + else + @named begin + end + end + + vars = if T_dep @variables begin Vt(t), [description = "Thermal voltage"] end - @equations begin - Vt ~ k * port.T / q # Thermal voltage equation - i ~ Is * (exp(v / (n * Vt)) - 1) # Shockley diode equation with temperature dependence - port.Q_flow ~ -v * i # -LossPower + else + @variables begin end + end + + equations = if T_dep + Equation[ + Vt ~ k * port.T / q, # Thermal voltage equation + i ~ Is * (exp(v / (n * Vt)) - 1), # Shockley diode equation with temperature dependence + port.Q_flow ~ -v * i # -LossPower + ] else - @equations begin + Equation[ i ~ Is * (exp(v * q / (n * k * T)) - 1) # Shockley diode equation - end + ] end + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, oneport) end """ @@ -346,49 +453,58 @@ R = R_const + pos * R_ref * (1 + alpha * (port.T - T_ref)) - `alpha`: [K⁻¹] Temperature coefficient of resistance - `enforce_bounds`: Enforce bounds for the position of the wiper (0-1) """ -@mtkmodel VariableResistor begin - @extend v, i = oneport = OnePort() +@component function VariableResistor(; T_dep = false, enforce_bounds = true, R_ref = 1.0, T_ref = 300.15, R_const = 1e-3, alpha = 1e-3, name) + @named oneport = OnePort() + @unpack v, i = oneport - @structural_parameters begin - T_dep = false - enforce_bounds = true - end - - @parameters begin - R_ref = 1.0, - [description = "Resistance at temperature T_ref when fully closed (pos=1.0) (Ω)"] - T_ref = 300.15, [description = "Reference temperature (K)"] - R_const = 1e-3, [description = "Constant resistance between p and n (Ω)"] + pars = if T_dep + @parameters begin + R_ref = R_ref, [description = "Resistance at temperature T_ref when fully closed (pos=1.0) (Ω)"] + T_ref = T_ref, [description = "Reference temperature (K)"] + R_const = R_const, [description = "Constant resistance between p and n (Ω)"] + alpha = alpha, [description = "Temperature coefficient of resistance (K^-1)"] + end + else + @parameters begin + R_ref = R_ref, [description = "Resistance at temperature T_ref when fully closed (pos=1.0) (Ω)"] + T_ref = T_ref, [description = "Reference temperature (K)"] + R_const = R_const, [description = "Constant resistance between p and n (Ω)"] + end end - @components begin - position = RealInput() + systems = if T_dep + @named begin + position = RealInput() + port = HeatPort() + end + else + @named begin + position = RealInput() + end end - @variables begin + vars = @variables begin pos(t), [description = "Position of the wiper (normally 0-1)"] R(t), [description = "Resistance (Ω)"] end - if T_dep - @parameters begin - alpha = 1e-3, [description = "Temperature coefficient of resistance (K^-1)"] - end - @components begin - port = HeatPort() - end - @equations begin - port.Q_flow ~ -v * i # -LossPower + conditional_eqs = if T_dep + Equation[ + port.Q_flow ~ -v * i, # -LossPower R ~ R_const + pos * R_ref * (1 + alpha * (port.T - T_ref)) - end + ] else - @equations begin + Equation[ R ~ R_const + pos * R_ref - end + ] end - @equations begin + equations = [ + conditional_eqs... pos ~ (enforce_bounds ? clamp(position.u, 0, 1) : position.u) v ~ i * R - end + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, oneport) end diff --git a/src/Electrical/Analog/mosfets.jl b/src/Electrical/Analog/mosfets.jl index 1b12a6afe..2310a8008 100644 --- a/src/Electrical/Analog/mosfets.jl +++ b/src/Electrical/Analog/mosfets.jl @@ -1,14 +1,14 @@ """ NMOS(;name, V_tn, R_DS, lambda) -Creates an N-type MOSFET transistor +Creates an N-type MOSFET transistor # Structural Parameters - `use_transconductance`: If `true` the parameter `k_n` needs to be provided, and is used in the calculation of the current - through the transistor. Otherwise, `mu_n`, `C_ox`, `W`, and `L` need to be provided and are used to calculate the transconductance. + through the transistor. Otherwise, `mu_n`, `C_ox`, `W`, and `L` need to be provided and are used to calculate the transconductance. - - `use_channel_length_modulation`: If `true` the channel length modulation effect is taken in to account. In essence this gives - the drain-source current has a small dependency on the drains-source voltage in the saturation region of operation. + - `use_channel_length_modulation`: If `true` the channel length modulation effect is taken in to account. In essence this gives + the drain-source current has a small dependency on the drains-source voltage in the saturation region of operation. # Connectors - `d` Drain Pin @@ -20,79 +20,75 @@ Creates an N-type MOSFET transistor - `C_ox`: Oxide capacitance (F/m^2) - `W`: Channel width (m) - `L`: Channel length - - `k_n`: MOSFET transconductance parameter + - `k_n`: MOSFET transconductance parameter Based on the MOSFET models in (Sedra, A. S., Smith, K. C., Carusone, T. C., & Gaudet, V. C. (2021). Microelectronic circuits (8th ed.). Oxford University Press.) """ -@mtkmodel NMOS begin - @variables begin - V_GS(t) - V_DS(t) - V_OV(t) +@component function NMOS(; name, + use_transconductance = true, + V_GS = nothing, V_DS = nothing, V_OV = nothing, + V_tn = 0.8, R_DS = 1e7, lambda = 0.04, + mu_n = nothing, C_ox = nothing, W = nothing, L = nothing, + k_n = 20e-3) + pars = @parameters begin + V_tn = V_tn, [description = "Threshold voltage (V)"] + R_DS = R_DS, [description = "Drain to source resistance (Ω)"] + lambda = lambda, [description = "Channel length modulation coefficient (V^(-1))"] end - @components begin - d = Pin() - g = Pin() - s = Pin() + if !use_transconductance + pars = [pars; @parameters(mu_n = mu_n, [description = "Electron mobility"])] + pars = [pars; @parameters(C_ox = C_ox, [description = "Oxide capacitance (F/m^2)"])] + pars = [pars; @parameters(W = W, [description = "Channel width (m)"])] + pars = [pars; @parameters(L = L, [description = "Channel length (m)"])] + else + pars = [pars; @parameters(k_n = k_n, [description = "MOSFET transconductance parameter"])] end - @parameters begin - V_tn = 0.8, [description = "Threshold voltage (V)"] - R_DS = 1e7, [description = "Drain to source resistance (Ω)"] + @named d = Pin() + @named g = Pin() + @named s = Pin() + systems = [d, g, s] - lambda = 0.04, [description = "Channel length modulation coefficient (V^(-1))"] - - if !use_transconductance - mu_n, [description = "Electron mobility"] - C_ox, [description = "Oxide capacitance (F/m^2)"] - W, [description = "Channel width (m)"] - L, [description = "Channel length (m)"] - else - k_n = 20e-3, [description = "MOSFET transconductance parameter"] - end - end - - @structural_parameters begin - use_transconductance = true + # Calculate k_n if using individual parameters + if !use_transconductance + k_n = mu_n * C_ox * (W / L) end - begin - if !use_transconductance - k_n = mu_n * C_ox * (W / L) - end + vars = @variables begin + V_GS(t) = V_GS + V_DS(t) = V_DS + V_OV(t) = V_OV end - @equations begin - V_DS ~ ifelse(d.v < s.v, s.v - d.v, d.v - s.v) - V_GS ~ g.v - ifelse(d.v < s.v, d.v, s.v) - V_OV ~ V_GS - V_tn - + equations = Equation[ + V_DS ~ ifelse(d.v < s.v, s.v - d.v, d.v - s.v), + V_GS ~ g.v - ifelse(d.v < s.v, d.v, s.v), + V_OV ~ V_GS - V_tn, d.i ~ ifelse(d.v < s.v, -1, 1) * ifelse(V_GS < V_tn, V_DS / R_DS, ifelse(V_DS < V_OV, k_n * (1 + lambda * V_DS) * (V_OV - V_DS / 2) * V_DS + V_DS / R_DS, - ((k_n * V_OV^2) / 2) * (1 + lambda * V_DS) + V_DS / R_DS - ) - ) - - g.i ~ 0 + ((k_n * V_OV^2) / 2) * (1 + lambda * V_DS) + V_DS / R_DS)), + g.i ~ 0, s.i ~ -d.i - end + ] + + return System(equations, t, vars, pars; name, systems) end """ PMOS(;name, V_tp, R_DS, lambda) -Creates an N-type MOSFET transistor +Creates an N-type MOSFET transistor # Structural Parameters - `use_transconductance`: If `true` the parameter `k_p` needs to be provided, and is used in the calculation of the current - through the transistor. Otherwise, `mu_n`, `C_ox`, `W`, and `L` need to be provided and are used to calculate the transconductance. + through the transistor. Otherwise, `mu_n`, `C_ox`, `W`, and `L` need to be provided and are used to calculate the transconductance. - - `use_channel_length_modulation`: If `true` the channel length modulation effect is taken in to account. In essence this gives - the drain-source current has a small dependency on the drains-source voltage in the saturation region of operation. + - `use_channel_length_modulation`: If `true` the channel length modulation effect is taken in to account. In essence this gives + the drain-source current has a small dependency on the drains-source voltage in the saturation region of operation. # Connectors - `d` Drain Pin @@ -104,63 +100,59 @@ Creates an N-type MOSFET transistor - `C_ox`: Oxide capacitance (F/m^2) - `W`: Channel width (m) - `L`: Channel length - - `k_p`: MOSFET transconductance parameter + - `k_p`: MOSFET transconductance parameter Based on the MOSFET models in (Sedra, A. S., Smith, K. C., Carusone, T. C., & Gaudet, V. C. (2021). Microelectronic circuits (8th ed.). Oxford University Press.) """ -@mtkmodel PMOS begin - @variables begin - V_GS(t) - V_DS(t) +@component function PMOS(; name, + use_transconductance = true, + V_GS = nothing, V_DS = nothing, + V_tp = -1.5, R_DS = 1e7, lambda = 1 / 25, + mu_p = nothing, C_ox = nothing, W = nothing, L = nothing, + k_p = 20e-3) + pars = @parameters begin + V_tp = V_tp, [description = "Threshold voltage (V)"] + R_DS = R_DS, [description = "Drain-source resistance (Ω)"] + lambda = lambda, [description = "Channel length modulation coefficient (V^(-1))"] end - @components begin - d = Pin() - g = Pin() - s = Pin() + if !use_transconductance + pars = [pars; @parameters(mu_p = mu_p, [description = "Hole mobility"])] + pars = [pars; @parameters(C_ox = C_ox, [description = "Oxide capacitance (F/m^2)"])] + pars = [pars; @parameters(W = W, [description = "Channel width (m)"])] + pars = [pars; @parameters(L = L, [description = "Channel length (m)"])] + else + pars = [pars; @parameters(k_p = k_p, [description = "MOSFET transconductance parameter"])] end - @parameters begin - V_tp = -1.5, [description = "Threshold voltage (V)"] - R_DS = 1e7, [description = "Drain-source resistance (Ω)"] + @named d = Pin() + @named g = Pin() + @named s = Pin() + systems = [d, g, s] - lambda = 1 / 25, [description = "Channel length modulation coefficient (V^(-1))"] - - if !use_transconductance - mu_p, [description = "Hole mobility"] - C_ox, [description = "Oxide capacitance (F/m^2)"] - W, [description = "Channel width (m)"] - L, [description = "Channel length (m)"] - else - k_p = 20e-3 - end - end - - @structural_parameters begin - use_transconductance = true + # Calculate k_p if using individual parameters + if !use_transconductance + k_p = mu_p * C_ox * (W / L) end - begin - if !use_transconductance - k_p = mu_p * C_ox * (W / L) - end + vars = @variables begin + V_GS(t) = V_GS + V_DS(t) = V_DS end - @equations begin - V_DS ~ ifelse(d.v > s.v, s.v - d.v, d.v - s.v) - V_GS ~ g.v - ifelse(d.v > s.v, d.v, s.v) - + equations = Equation[ + V_DS ~ ifelse(d.v > s.v, s.v - d.v, d.v - s.v), + V_GS ~ g.v - ifelse(d.v > s.v, d.v, s.v), d.i ~ -ifelse(d.v > s.v, -1.0, 1.0) * ifelse(V_GS > V_tp, V_DS / R_DS, ifelse(V_DS > (V_GS - V_tp), k_p * (1 + lambda * V_DS) * ((V_GS - V_tp) - V_DS / 2) * V_DS + V_DS / R_DS, - ((k_p * (V_GS - V_tp)^2) / 2) * (1 + lambda * V_DS) + V_DS / R_DS - ) - ) - - g.i ~ 0 + ((k_p * (V_GS - V_tp)^2) / 2) * (1 + lambda * V_DS) + V_DS / R_DS)), + g.i ~ 0, s.i ~ -d.i - end + ] + + return System(equations, t, vars, pars; name, systems) end diff --git a/src/Electrical/Analog/sensors.jl b/src/Electrical/Analog/sensors.jl index 5c6e7f16d..4d1d34a22 100644 --- a/src/Electrical/Analog/sensors.jl +++ b/src/Electrical/Analog/sensors.jl @@ -13,19 +13,26 @@ an ideal ammeter. - `p` Positive pin - `n` Negative pin """ -@mtkmodel CurrentSensor begin - @components begin +@component function CurrentSensor(; name) + pars = @parameters begin + end + + systems = @named begin p = Pin() n = Pin() end - @variables begin + + vars = @variables begin i(t) end - @equations begin - p.v ~ n.v - i ~ p.i + + equations = Equation[ + p.v ~ n.v, + i ~ p.i, i ~ -n.i - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -41,17 +48,24 @@ Creates a circuit component which measures the potential at a pin. - `p` Pin at which potential is to be measured """ -@mtkmodel PotentialSensor begin - @components begin +@component function PotentialSensor(; name) + pars = @parameters begin + end + + systems = @named begin p = Pin() end - @variables begin + + vars = @variables begin phi(t) end - @equations begin - p.i ~ 0 + + equations = Equation[ + p.i ~ 0, phi ~ p.v - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -68,19 +82,26 @@ Creates a circuit component that measures the voltage across it. Analogous to an - `p` Positive pin - `n` Negative pin """ -@mtkmodel VoltageSensor begin - @components begin +@component function VoltageSensor(; name) + pars = @parameters begin + end + + systems = @named begin p = Pin() n = Pin() end - @variables begin + + vars = @variables begin v(t) end - @equations begin - p.i ~ 0 - n.i ~ 0 + + equations = Equation[ + p.i ~ 0, + n.i ~ 0, v ~ p.v - n.v - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -102,8 +123,11 @@ consumed by a circuit. - `pv` Corresponds to the `p` pin of the [`VoltageSensor`](@ref) - `nv` Corresponds to the `n` pin of the [`VoltageSensor`](@ref) """ -@mtkmodel PowerSensor begin - @components begin +@component function PowerSensor(; name) + pars = @parameters begin + end + + systems = @named begin pc = Pin() nc = Pin() pv = Pin() @@ -111,16 +135,20 @@ consumed by a circuit. voltage_sensor = VoltageSensor() current_sensor = CurrentSensor() end - @variables begin + + vars = @variables begin power(t) end - @equations begin - connect(voltage_sensor.p, pv) - connect(voltage_sensor.n, nv) - connect(current_sensor.p, pc) - connect(current_sensor.n, nc) + + equations = Equation[ + connect(voltage_sensor.p, pv), + connect(voltage_sensor.n, nv), + connect(current_sensor.p, pc), + connect(current_sensor.n, nc), power ~ current_sensor.i * voltage_sensor.v - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -140,8 +168,11 @@ Combines a [`VoltageSensor`](@ref) and a [`CurrentSensor`](@ref). - `pv` Corresponds to the `p` pin of the [`VoltageSensor`](@ref) - `nv` Corresponds to the `n` pin of the [`VoltageSensor`](@ref) """ -@mtkmodel MultiSensor begin - @components begin +@component function MultiSensor(; name) + pars = @parameters begin + end + + systems = @named begin pc = Pin() nc = Pin() pv = Pin() @@ -149,16 +180,20 @@ Combines a [`VoltageSensor`](@ref) and a [`CurrentSensor`](@ref). voltage_sensor = VoltageSensor() current_sensor = CurrentSensor() end - @variables begin + + vars = @variables begin i(t) = 1.0 v(t) = 1.0 end - @equations begin - connect(voltage_sensor.p, pv) - connect(voltage_sensor.n, nv) - connect(current_sensor.p, pc) - connect(current_sensor.n, nc) - i ~ current_sensor.i + + equations = Equation[ + connect(voltage_sensor.p, pv), + connect(voltage_sensor.n, nv), + connect(current_sensor.p, pc), + connect(current_sensor.n, nc), + i ~ current_sensor.i, v ~ voltage_sensor.v - end + ] + + return System(equations, t, vars, pars; name, systems) end diff --git a/src/Electrical/Analog/sources.jl b/src/Electrical/Analog/sources.jl index 807fa91f1..a742e0c76 100644 --- a/src/Electrical/Analog/sources.jl +++ b/src/Electrical/Analog/sources.jl @@ -13,14 +13,26 @@ See [OnePort](@ref) - `n` Negative pin - `V` [RealInput](@ref) Input for the voltage control signal, i.e. `V ~ p.v - n.v` """ -@mtkmodel Voltage begin - @extend v, i = oneport = OnePort() - @components begin +@component function Voltage(; name) + @named oneport = OnePort() + @unpack v, i = oneport + + pars = @parameters begin + end + + systems = @named begin V = RealInput() end - @equations begin - v ~ V.u + + vars = @variables begin end + + equations = Equation[ + v ~ V.u + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, oneport) end """ @@ -38,12 +50,24 @@ See [OnePort](@ref) - `n` Negative pin - `I` [RealInput](@ref) Input for the current control signal, i.e. `I ~ p.i """ -@mtkmodel Current begin - @extend v, i = oneport = OnePort() - @components begin +@component function Current(; name) + @named oneport = OnePort() + @unpack v, i = oneport + + pars = @parameters begin + end + + systems = @named begin I = RealInput() end - @equations begin - i ~ I.u + + vars = @variables begin end + + equations = Equation[ + i ~ I.u + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, oneport) end diff --git a/src/Electrical/Analog/transistors.jl b/src/Electrical/Analog/transistors.jl index 3dad46c45..60e214a8e 100644 --- a/src/Electrical/Analog/transistors.jl +++ b/src/Electrical/Analog/transistors.jl @@ -42,127 +42,123 @@ Early voltage effect. - `NF`: Forward emission coefficient - `NR`: Reverse emission coefficient """ -@mtkmodel NPN begin - @variables begin - V_BE(t) - V_BC(t) - ICC(t) - IEC(t) - - C_jC(t) - C_jE(t) - C_DC(t) - C_DE(t) - - I_sub(t) - V_sub(t) - V_CS(t) +@component function NPN(; name, + use_substrate = false, + use_Early = true, + use_advanced_continuation = false, + V_BE = nothing, V_BC = nothing, ICC = nothing, IEC = nothing, + C_jC = nothing, C_jE = nothing, C_DC = nothing, C_DE = nothing, + I_sub = nothing, V_sub = nothing, V_CS = nothing, + B_F = 50.0, B_R = 0.1, Is = 1e-16, V_T = 0.026, + V_A = 0.02, phi_C = 0.8, phi_E = 0.6, + Z_C = 0.1, Z_E = 0.1, + Tau_f = 0.12e-9, Tau_r = 5e-9, + C_jC0 = 0.5e-12, C_jE0 = 0.4e-12, + C_CS = 1e-12, + gamma_C = 0.5, gamma_E = 1.0/3.0, + NF = 1.0, NR = 1.0) + + pars = @parameters begin + B_F = B_F, [description = "Forward beta"] + B_R = B_R, [description = "Reverse beta"] + Is = Is, [description = "Saturation current"] + V_T = V_T, [description = "Thermal voltage at 300K"] + phi_C = phi_C, [description = "Collector junction scaling factor"] + phi_E = phi_E, [description = "Emitter junction scaling factor"] + Tau_f = Tau_f, [description = "Forward transit time"] + Tau_r = Tau_r, [description = "Reverse transit time"] + C_jC0 = C_jC0, [description = "Collector-junction capacitance coefficient"] + C_jE0 = C_jE0, [description = "Emitter-junction capacitance coefficient"] + C_CS = C_CS, [description = "Collector-substrate capacitance"] + gamma_C = gamma_C, [description = "Collector junction exponent"] + gamma_E = gamma_E, [description = "Emitter junction exponent"] + NF = NF, [description = "Forward ideality exponent"] + NR = NR, [description = "Reverse ideality exponent"] end - @structural_parameters begin - use_substrate = false - use_Early = true - use_advanced_continuation = false + if use_Early + pars = [pars; @parameters(V_A = V_A, [description = "Inverse Early voltage"])] end - @components begin - b = Pin() - e = Pin() - c = Pin() - - if use_substrate - s = Pin() - end + if use_advanced_continuation + pars = [pars; @parameters(Z_C = Z_C, [description = "Collector junction offset"])] + pars = [pars; @parameters(Z_E = Z_E, [description = "Emitter junction offset"])] end - @parameters begin - B_F = 50.0, [description = "Forward beta"] - B_R = 0.1, [description = "Reverse beta"] - Is = 1e-16, [description = "Saturation current"] - V_T = 0.026, [description = "Thermal voltage at 300K"] + @named b = Pin() + @named e = Pin() + @named c = Pin() + systems = [b, e, c] - if use_Early - V_A = 0.02, [description = "Inverse Early voltage"] - end + if use_substrate + @named s = Pin() + push!(systems, s) + end - phi_C = 0.8, [description = "Collector junction scaling factor"] - phi_E = 0.6, [description = "Emitter junction scaling factor"] + vars = @variables begin + V_BE(t) = V_BE + V_BC(t) = V_BC + ICC(t) = ICC + IEC(t) = IEC + C_jC(t) = C_jC + C_jE(t) = C_jE + C_DC(t) = C_DC + C_DE(t) = C_DE + I_sub(t) = I_sub + V_sub(t) = V_sub + V_CS(t) = V_CS + end - if use_advanced_continuation - Z_C = 0.1, [description = "Collector junction offset"] - Z_E = 0.1, [description = "Emitter junction offset"] - end + equations = Equation[ + V_BE ~ b.v - e.v, + V_BC ~ b.v - c.v, + ICC ~ Is * (exp(V_BE / V_T) - 1), + IEC ~ Is * (exp(V_BC / V_T) - 1) + ] - Tau_f = 0.12e-9, [description = "Forward transit time"] - Tau_r = 5e-9, [description = "Reverse transit time"] + if !use_advanced_continuation + push!(equations, C_jC ~ ifelse(V_BC / phi_C > 0.0, 1 + gamma_C * V_BC / phi_C, + (C_jC0) / (1 - V_BC / phi_C)^gamma_C)) + push!(equations, C_jE ~ ifelse(V_BE / phi_E > 0.0, 1 + gamma_E * V_BE / phi_E, + (C_jE0) / (1 - V_BE / phi_E)^gamma_E)) + end - C_jC0 = 0.5e-12, [description = "Collector-junction capacitance coefficient"] - C_jE0 = 0.4e-12, [description = "Emitter-junction capacitance coefficient"] + if use_advanced_continuation + push!(equations, C_jC ~ ifelse(V_BC > phi_C - Z_C, + ((C_jC0 * gamma_C * (1 - ((phi_C - Z_C) / phi_C))^(-gamma_C - 1)) / phi_C) * + V_BC - + ((C_jC0 * gamma_C * (1 - ((phi_C - Z_C) / phi_C))^(-gamma_C - 1)) / phi_C) * + (phi_C - Z_C) + (C_jC0) / (1 - (phi_C - Z_C) / phi_C)^gamma_C, + (C_jC0) / (1 - V_BC / phi_C)^gamma_C)) + + push!(equations, C_jE ~ ifelse(V_BE > phi_E - Z_E, + ((C_jE0 * gamma_E * (1 - ((phi_E - Z_E) / phi_E))^(-gamma_E - 1)) / phi_E) * + V_BE - + ((C_jE0 * gamma_E * (1 - ((phi_E - Z_E) / phi_E))^(-gamma_E - 1)) / phi_E) * + (phi_E - Z_E) + (C_jE0) / (1 - (phi_E - Z_E) / phi_E)^gamma_E, + (C_jE0) / (1 - V_BE / phi_E)^gamma_E)) + end - C_CS = 1e-12, [description = "Collector-substrate capacitance"] + push!(equations, C_DE ~ Tau_f * (Is / (NF * V_T)) * exp(V_BE / (NF * V_T))) + push!(equations, C_DC ~ Tau_r * (Is / (NR * V_T)) * exp(V_BC / (NR * V_T))) - gamma_C = 0.5, [description = "Collector junction exponent"] - gamma_E = 1.0 / 3.0, [description = "Emitter junction exponent"] + if use_substrate + push!(equations, s.i ~ I_sub) + push!(equations, s.v ~ V_sub) + push!(equations, V_CS ~ c.v - V_sub) + end - NF = 1.0, [description = "Forward ideality exponent"] - NR = 1.0, [description = "Reverse ideality exponent"] + if !use_substrate + push!(equations, V_sub ~ c.v) end - @equations begin - V_BE ~ b.v - e.v - V_BC ~ b.v - c.v + push!(equations, I_sub ~ ifelse(use_substrate, -C_CS * D(V_CS), -C_CS * D(V_sub))) - ICC ~ Is * (exp(V_BE / V_T) - 1) - IEC ~ Is * (exp(V_BC / V_T) - 1) + push!(equations, c.i ~ (ICC - IEC) * ifelse(use_Early, (1 - V_BC * V_A), 1.0) - IEC / B_R - (C_jC + C_DC) * D(V_BC) - I_sub) + push!(equations, b.i ~ IEC / B_R + ICC / B_F + (C_jC + C_DC) * D(V_BC) + (C_jE + C_DE) * D(V_BE)) + push!(equations, e.i ~ -c.i - b.i - I_sub) - if !use_advanced_continuation - C_jC ~ ifelse(V_BC / phi_C > 0.0, 1 + gamma_C * V_BC / phi_C, - (C_jC0) / (1 - V_BC / phi_C)^gamma_C) - C_jE ~ ifelse(V_BE / phi_E > 0.0, 1 + gamma_E * V_BE / phi_E, - (C_jE0) / (1 - V_BE / phi_E)^gamma_E) - end - - if use_advanced_continuation - C_jC ~ if V_BC > phi_C - Z_C - ((C_jC0 * gamma_C * (1 - ((phi_C - Z_C) / phi_C))^(-gamma_C - 1)) / phi_C) * - V_BC - - ((C_jC0 * gamma_C * (1 - ((phi_C - Z_C) / phi_C))^(-gamma_C - 1)) / phi_C) * - (phi_C - Z_C) + (C_jC0) / (1 - (phi_C - Z_C) / phi_C)^gamma_C - else - (C_jC0) / (1 - V_BC / phi_C)^gamma_C - end - - C_jE ~ if V_BE > phi_E - Z_E - ((C_jE0 * gamma_E * (1 - ((phi_E - Z_E) / phi_E))^(-gamma_E - 1)) / phi_E) * - V_BE - - ((C_jE0 * gamma_E * (1 - ((phi_E - Z_E) / phi_E))^(-gamma_E - 1)) / phi_E) * - (phi_E - Z_E) + (C_jE0) / (1 - (phi_E - Z_E) / phi_E)^gamma_E - else - (C_jE0) / (1 - V_BE / phi_E)^gamma_E - end - end - - C_DE ~ Tau_f * (Is / (NF * V_T)) * exp(V_BE / (NF * V_T)) - C_DC ~ Tau_r * (Is / (NR * V_T)) * exp(V_BC / (NR * V_T)) - - if use_substrate - s.i ~ I_sub - s.v ~ V_sub - V_CS ~ c.v - V_sub - end - - if !use_substrate - V_sub ~ c.v - end - - I_sub ~ ifelse(use_substrate, -C_CS * D(V_CS), -C_CS * D(V_sub)) - - c.i ~ - (ICC - IEC) * ifelse(use_Early, (1 - V_BC * V_A), 1.0) - IEC / B_R - - (C_jC + C_DC) * D(V_BC) - I_sub - b.i ~ IEC / B_R + ICC / B_F + (C_jC + C_DC) * D(V_BC) + (C_jE + C_DE) * D(V_BE) - e.i ~ -c.i - b.i - I_sub - end + return System(equations, t, vars, pars; name, systems) end """ @@ -209,125 +205,121 @@ Early voltage effect. - `NF`: Forward emission coefficient - `NR`: Reverse emission coefficient """ -@mtkmodel PNP begin - @variables begin - V_EB(t) - V_CB(t) - ICC(t) - IEC(t) - - C_jC(t) - C_jE(t) - C_DC(t) - C_DE(t) - - I_sub(t) - V_sub(t) - V_CS(t) +@component function PNP(; name, + use_substrate = false, + use_Early = true, + use_advanced_continuation = false, + V_EB = nothing, V_CB = nothing, ICC = nothing, IEC = nothing, + C_jC = nothing, C_jE = nothing, C_DC = nothing, C_DE = nothing, + I_sub = nothing, V_sub = nothing, V_CS = nothing, + B_F = 50.0, B_R = 0.1, Is = 1e-16, V_T = 0.026, + V_A = 0.02, phi_C = 0.8, phi_E = 0.6, + Z_C = 0.1, Z_E = 0.1, + Tau_f = 0.12e-9, Tau_r = 5e-9, + C_jC0 = 0.5e-12, C_jE0 = 0.4e-12, + C_CS = 1e-12, + gamma_C = 0.5, gamma_E = 1.0/3.0, + NF = 1.0, NR = 1.0) + + pars = @parameters begin + B_F = B_F, [description = "Forward beta"] + B_R = B_R, [description = "Reverse beta"] + Is = Is, [description = "Saturation current"] + V_T = V_T, [description = "Thermal voltage at 300K"] + phi_C = phi_C, [description = "Collector junction scaling factor"] + phi_E = phi_E, [description = "Emitter junction scaling factor"] + Tau_f = Tau_f, [description = "Forward transit time"] + Tau_r = Tau_r, [description = "Reverse transit time"] + C_jC0 = C_jC0, [description = "Collector-junction capacitance coefficient"] + C_jE0 = C_jE0, [description = "Emitter-junction capacitance coefficient"] + C_CS = C_CS, [description = "Collector-substrate capacitance"] + gamma_C = gamma_C, [description = "Collector junction exponent"] + gamma_E = gamma_E, [description = "Emitter junction exponent"] + NF = NF, [description = "Forward ideality exponent"] + NR = NR, [description = "Reverse ideality exponent"] end - @structural_parameters begin - use_substrate = false - use_Early = true - use_advanced_continuation = false + if use_Early + pars = [pars; @parameters(V_A = V_A, [description = "Inverse Early voltage"])] end - @components begin - b = Pin() - e = Pin() - c = Pin() - - if use_substrate - s = Pin() - end + if use_advanced_continuation + pars = [pars; @parameters(Z_C = Z_C, [description = "Collector junction offset"])] + pars = [pars; @parameters(Z_E = Z_E, [description = "Emitter junction offset"])] end - @parameters begin - B_F = 50.0, [description = "Forward beta"] - B_R = 0.1, [description = "Reverse beta"] - Is = 1e-16, [description = "Saturation current"] - V_T = 0.026, [description = "Thermal voltage at 300K"] + @named b = Pin() + @named e = Pin() + @named c = Pin() + systems = [b, e, c] - if use_Early - V_A = 0.02, [description = "Inverse Early voltage"] - end + if use_substrate + @named s = Pin() + push!(systems, s) + end - phi_C = 0.8, [description = "Collector junction scaling factor"] - phi_E = 0.6, [description = "Emitter junction scaling factor"] + vars = @variables begin + V_EB(t) = V_EB + V_CB(t) = V_CB + ICC(t) = ICC + IEC(t) = IEC + C_jC(t) = C_jC + C_jE(t) = C_jE + C_DC(t) = C_DC + C_DE(t) = C_DE + I_sub(t) = I_sub + V_sub(t) = V_sub + V_CS(t) = V_CS + end - if use_advanced_continuation - Z_C = 0.1, [description = "Collector junction offset"] - Z_E = 0.1, [description = "Emitter junction offset"] - end + equations = Equation[ + V_EB ~ e.v - b.v, + V_CB ~ c.v - b.v, + ICC ~ Is * (exp(V_EB / V_T) - 1), + IEC ~ Is * (exp(V_CB / V_T) - 1) + ] - Tau_f = 0.12e-9, [description = "Forward transit time"] - Tau_r = 5e-9, [description = "Reverse transit time"] + if !use_advanced_continuation + push!(equations, C_jC ~ ifelse(V_CB / phi_C > 0.0, 1 + gamma_C * V_CB / phi_C, + (C_jC0) / (1 - V_CB / phi_C)^gamma_C)) + push!(equations, C_jE ~ ifelse(V_EB / phi_E > 0.0, 1 + gamma_E * V_EB / phi_E, + (C_jE0) / (1 - V_EB / phi_E)^gamma_E)) + end - C_jC0 = 0.5e-12, [description = "Collector-junction capacitance coefficient"] - C_jE0 = 0.4e-12, [description = "Emitter-junction capacitance coefficient"] + if use_advanced_continuation + push!(equations, C_jC ~ ifelse(V_CB > phi_C - Z_C, + ((C_jC0 * gamma_C * (1 - ((phi_C - Z_C) / phi_C))^(-gamma_C - 1)) / phi_C) * + V_CB - + ((C_jC0 * gamma_C * (1 - ((phi_C - Z_C) / phi_C))^(-gamma_C - 1)) / phi_C) * + (phi_C - Z_C) + (C_jC0) / (1 - (phi_C - Z_C) / phi_C)^gamma_C, + (C_jC0) / (1 - V_CB / phi_C)^gamma_C)) + + push!(equations, C_jE ~ ifelse(V_EB > phi_E - Z_E, + ((C_jE0 * gamma_E * (1 - ((phi_E - Z_E) / phi_E))^(-gamma_E - 1)) / phi_E) * + V_EB - + ((C_jE0 * gamma_E * (1 - ((phi_E - Z_E) / phi_E))^(-gamma_E - 1)) / phi_E) * + (phi_E - Z_E) + (C_jE0) / (1 - (phi_E - Z_E) / phi_E)^gamma_E, + (C_jE0) / (1 - V_EB / phi_E)^gamma_E)) + end - C_CS = 1e-12, [description = "Collector-substrate capacitance"] + push!(equations, C_DE ~ Tau_f * (Is / (NF * V_T)) * exp(V_EB / (NF * V_T))) + push!(equations, C_DC ~ Tau_r * (Is / (NR * V_T)) * exp(V_CB / (NR * V_T))) - gamma_C = 0.5, [description = "Collector junction exponent"] - gamma_E = 1.0 / 3.0, [description = "Emitter junction exponent"] + if use_substrate + push!(equations, s.i ~ I_sub) + push!(equations, s.v ~ V_sub) + push!(equations, V_CS ~ c.v - V_sub) + end - NF = 1.0, [description = "Forward ideality exponent"] - NR = 1.0, [description = "Reverse ideality exponent"] + if !use_substrate + push!(equations, V_sub ~ c.v) end - @equations begin - V_EB ~ e.v - b.v - V_CB ~ c.v - b.v + push!(equations, I_sub ~ ifelse(use_substrate, -C_CS * D(V_CS), -C_CS * D(V_sub))) - ICC ~ Is * (exp(V_EB / V_T) - 1) - IEC ~ Is * (exp(V_CB / V_T) - 1) + push!(equations, c.i ~ IEC / B_R - (ICC - IEC) * ifelse(use_Early, (1 - V_CB * V_A), 1.0) + (C_jC + C_DC) * D(V_CB) - I_sub) + push!(equations, b.i ~ -IEC / B_R - ICC / B_F - (C_jC + C_DC) * D(V_CB) - (C_jE + C_DE) * D(V_EB)) + push!(equations, e.i ~ -c.i - b.i - I_sub) - if !use_advanced_continuation - C_jC ~ ifelse(V_CB / phi_C > 0.0, 1 + gamma_C * V_CB / phi_C, - (C_jC0) / (1 - V_CB / phi_C)^gamma_C) - C_jE ~ ifelse(V_EB / phi_E > 0.0, 1 + gamma_E * V_EB / phi_E, - (C_jE0) / (1 - V_EB / phi_E)^gamma_E) - end - - if use_advanced_continuation - C_jC ~ if V_CB > phi_C - Z_C - ((C_jC0 * gamma_C * (1 - ((phi_C - Z_C) / phi_C))^(-gamma_C - 1)) / phi_C) * - V_CB - - ((C_jC0 * gamma_C * (1 - ((phi_C - Z_C) / phi_C))^(-gamma_C - 1)) / phi_C) * - (phi_C - Z_C) + (C_jC0) / (1 - (phi_C - Z_C) / phi_C)^gamma_C - else - (C_jC0) / (1 - V_CB / phi_C)^gamma_C - end - - C_jE ~ if V_EB > phi_E - Z_E - ((C_jE0 * gamma_E * (1 - ((phi_E - Z_E) / phi_E))^(-gamma_E - 1)) / phi_E) * - V_EB - - ((C_jE0 * gamma_E * (1 - ((phi_E - Z_E) / phi_E))^(-gamma_E - 1)) / phi_E) * - (phi_E - Z_E) + (C_jE0) / (1 - (phi_E - Z_E) / phi_E)^gamma_E - else - (C_jE0) / (1 - V_EB / phi_E)^gamma_E - end - end - - C_DE ~ Tau_f * (Is / (NF * V_T)) * exp(V_EB / (NF * V_T)) - C_DC ~ Tau_r * (Is / (NR * V_T)) * exp(V_CB / (NR * V_T)) - - if use_substrate - s.i ~ I_sub - s.v ~ V_sub - V_CS ~ c.v - V_sub - end - - if !use_substrate - V_sub ~ c.v - end - - I_sub ~ ifelse(use_substrate, -C_CS * D(V_CS), -C_CS * D(V_sub)) - - c.i ~ - IEC / B_R - (ICC - IEC) * ifelse(use_Early, (1 - V_CB * V_A), 1.0) + - (C_jC + C_DC) * D(V_CB) - I_sub - b.i ~ -IEC / B_R - ICC / B_F - (C_jC + C_DC) * D(V_CB) - (C_jE + C_DE) * D(V_EB) - e.i ~ -c.i - b.i - I_sub - end + return System(equations, t, vars, pars; name, systems) end diff --git a/src/Electrical/Digital/sources.jl b/src/Electrical/Digital/sources.jl index 0e4160b0f..3a90cfe77 100644 --- a/src/Electrical/Digital/sources.jl +++ b/src/Electrical/Digital/sources.jl @@ -16,7 +16,7 @@ PulseDiff(; name, Val = 1, dt = 0.1) function PulseDiff(; name, Val = 1, dt = 0.1) @named d = DigitalPin() @variables val(t) - D = ModelingToolkit.Difference(t; dt = dt) + D = ModelingToolkitBase.Difference(t; dt = dt) eqs = [D(val) ~ Val val ~ d.val] diff --git a/src/Electrical/Electrical.jl b/src/Electrical/Electrical.jl index 712e4b172..9330653f7 100644 --- a/src/Electrical/Electrical.jl +++ b/src/Electrical/Electrical.jl @@ -4,8 +4,8 @@ This library contains electrical components to build up analog circuits. """ module Electrical -using ModelingToolkit, Symbolics, IfElse -using ModelingToolkit: t_nounits as t, D_nounits as D +using ModelingToolkitBase, Symbolics, IfElse +using ModelingToolkitBase: t_nounits as t, D_nounits as D using ..Thermal: HeatPort using ..Mechanical.Rotational: Flange, Support using ..Blocks: RealInput, RealOutput diff --git a/src/Electrical/utils.jl b/src/Electrical/utils.jl index 2fea22c27..a24f35ac8 100644 --- a/src/Electrical/utils.jl +++ b/src/Electrical/utils.jl @@ -1,6 +1,9 @@ -@connector Pin begin - v(t) # Potential at the pin [V] - i(t), [connect = Flow] # Current flowing into the pin [A] +@connector function Pin(; name, v = nothing, i = nothing) + vars = @variables begin + v(t) = v # Potential at the pin [V] + i(t) = i, [connect = Flow] # Current flowing into the pin [A] + end + System(Equation[], t, vars, []; name) end @doc """ Pin(; name) @@ -13,7 +16,7 @@ A pin in an analog circuit. """ Pin """ - OnePort(; name, v = 0.0, i = 0.0) + OnePort(; name, v = nothing, i = nothing) Component with two electrical pins `p` and `n` and current `i` flows from `p` to `n`. @@ -27,24 +30,31 @@ Component with two electrical pins `p` and `n` and current `i` flows from `p` to - `p` Positive pin - `n` Negative pin """ -@mtkmodel OnePort begin - @components begin +@component function OnePort(; v = nothing, i = nothing, name) + pars = @parameters begin + end + + systems = @named begin p = Pin() n = Pin() end - @variables begin - v(t) - i(t) + + vars = @variables begin + v(t) = v + i(t) = i end - @equations begin - v ~ p.v - n.v - 0 ~ p.i + n.i + + equations = Equation[ + v ~ p.v - n.v, + 0 ~ p.i + n.i, i ~ p.i - end + ] + + return System(equations, t, vars, pars; name, systems) end """ - TwoPort(; name, v1 = 0.0, v2 = 0.0, i1 = 0.0, i2 = 0.0) + TwoPort(; name, v1 = nothing, v2 = nothing, i1 = nothing, i2 = nothing) Component with four electrical pins `p1`, `n1`, `p2` and `n2` Current `i1` flows from `p1` to `n1` and `i2` from `p2` to `n2`. @@ -62,27 +72,34 @@ Current `i1` flows from `p1` to `n1` and `i2` from `p2` to `n2`. - `n2` Second Negative pin """ -@mtkmodel TwoPort begin - @components begin +@component function TwoPort(; v1 = nothing, v2 = nothing, i1 = nothing, i2 = nothing, name) + pars = @parameters begin + end + + systems = @named begin p1 = Pin() n1 = Pin() p2 = Pin() n2 = Pin() end - @variables begin - v1(t) - i1(t) - v2(t) - i2(t) + + vars = @variables begin + v1(t) = v1 + i1(t) = i1 + v2(t) = v2 + i2(t) = i2 end - @equations begin - v1 ~ p1.v - n1.v - 0 ~ p1.i + n1.i - i1 ~ p1.i - v2 ~ p2.v - n2.v - 0 ~ p2.i + n2.i + + equations = Equation[ + v1 ~ p1.v - n1.v, + 0 ~ p1.i + n1.i, + i1 ~ p1.i, + v2 ~ p2.v - n2.v, + 0 ~ p2.i + n2.i, i2 ~ p2.i - end + ] + + return System(equations, t, vars, pars; name, systems) end @connector function DigitalPin(; name) diff --git a/src/Hydraulic/Hydraulic.jl b/src/Hydraulic/Hydraulic.jl index cb3cb1deb..c1c072bd4 100644 --- a/src/Hydraulic/Hydraulic.jl +++ b/src/Hydraulic/Hydraulic.jl @@ -3,7 +3,7 @@ Library of hydraulic models. """ module Hydraulic -using ModelingToolkit +using ModelingToolkitBase include("IsothermalCompressible/IsothermalCompressible.jl") diff --git a/src/Hydraulic/IsothermalCompressible/IsothermalCompressible.jl b/src/Hydraulic/IsothermalCompressible/IsothermalCompressible.jl index 3403ee022..fc114b7b8 100644 --- a/src/Hydraulic/IsothermalCompressible/IsothermalCompressible.jl +++ b/src/Hydraulic/IsothermalCompressible/IsothermalCompressible.jl @@ -3,8 +3,8 @@ Library to model iso-thermal compressible liquid fluid flow """ module IsothermalCompressible -using ModelingToolkit, Symbolics -using ModelingToolkit: t_nounits as t, D_nounits as D +using ModelingToolkitBase, Symbolics +using ModelingToolkitBase: t_nounits as t, D_nounits as D using ...Blocks: RealInput, RealOutput using ...Mechanical.Translational: MechanicalPort, Mass diff --git a/src/Hydraulic/IsothermalCompressible/components.jl b/src/Hydraulic/IsothermalCompressible/components.jl index 305e96105..4964afbf3 100644 --- a/src/Hydraulic/IsothermalCompressible/components.jl +++ b/src/Hydraulic/IsothermalCompressible/components.jl @@ -7,19 +7,23 @@ Caps a hydraulic port to prevent mass flow in or out. # Connectors: - `port`: hydraulic port """ -@mtkmodel Cap begin - @variables begin - p(t), [guess = 0] +@component function Cap(; name, p = nothing) + pars = @parameters begin end - @components begin - port = HydraulicPort() + @named port = HydraulicPort() + systems = [port] + + vars = @variables begin + p(t) = p, [guess = 0] end - @equations begin - port.p ~ p + equations = Equation[ + port.p ~ p, port.dm ~ 0 - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -30,20 +34,24 @@ Provides an "open" boundary condition for a hydraulic port such that mass flow ` # Connectors: - `port`: hydraulic port """ -@mtkmodel Open begin - @variables begin - p(t), [guess = 0] - dm(t), [guess = 0] +@component function Open(; name, p = nothing, dm = nothing) + pars = @parameters begin end - @components begin - port = HydraulicPort() + @named port = HydraulicPort() + systems = [port] + + vars = @variables begin + p(t) = p, [guess = 0] + dm(t) = dm, [guess = 0] end - @equations begin - port.p ~ p + equations = Equation[ + port.p ~ p, port.dm ~ dm - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -67,8 +75,8 @@ Variable length internal flow model of the fully developed incompressible flow f - `port_b`: hydraulic port """ @component function TubeBase(add_inertia = true, variable_length = true; - area, - length_int, + area = nothing, + length_int = nothing, head_factor = 1, perimeter = 2 * sqrt(area * pi), shape_factor = 64, @@ -153,9 +161,9 @@ Constant length internal flow model discretized by `N` (`FixedVolume`: `N`, `Tub - `port_a`: hydraulic port - `port_b`: hydraulic port """ -@component function Tube(N, add_inertia = true; area, length, head_factor = 1, +@component function Tube(N, add_inertia = true; area = nothing, length = nothing, head_factor = 1, perimeter = 2 * sqrt(area * pi), - shape_factor = 64, p_int, name) + shape_factor = 64, p_int = nothing, name) @assert(N>0, "the Tube component must be defined with at least 1 segment (i.e. N>0), found N=$N") @@ -215,36 +223,37 @@ Reduces the flow from `port_a` to `port_b` by `n`. Useful for modeling parallel - `port_a`: full flow hydraulic port - `port_b`: part flow hydraulic port """ -@mtkmodel FlowDivider begin +@component function FlowDivider(; name, n = nothing, dm_a = nothing, dm_b = nothing) #TODO: assert n >= 1 - @parameters begin + pars = @parameters begin n = n end - @variables begin - dm_a(t), [guess = 0] - dm_b(t), [guess = 0] - end + @named port_a = HydraulicPort() + @named port_b = HydraulicPort() + @named open = Open() + systems = [port_a, port_b, open] - @components begin - port_a = HydraulicPort() - port_b = HydraulicPort() - open = Open() + vars = @variables begin + dm_a(t) = dm_a, [guess = 0] + dm_b(t) = dm_b, [guess = 0] end - @equations begin - connect(port_a, port_b, open.port) - dm_a ~ port_a.dm - dm_b ~ dm_a / n + equations = Equation[ + connect(port_a, port_b, open.port), + dm_a ~ port_a.dm, + dm_b ~ dm_a / n, open.dm ~ dm_a - dm_b # extra flow dumps into an open port # port_b.dm ~ dm_b # divided flow goes to port_b - end + ] + + return System(equations, t, vars, pars; name, systems) end @component function ValveBase( - reversible = false; minimum_area = 0, Cd, Cd_reverse = Cd, name) + reversible = false; minimum_area = 0, Cd = nothing, Cd_reverse = Cd, name) pars = @parameters begin Cd = Cd Cd_reverse = Cd_reverse @@ -307,7 +316,7 @@ Valve with `area` input and discharge coefficient `Cd` defined by https://en.wik - `area`: real input setting the valve `area`. When `reversible = true`, negative input reverses flow direction, otherwise a floor of `minimum_area` is enforced. """ @component function Valve(reversible = false; - Cd, Cd_reverse = Cd, + Cd = nothing, Cd_reverse = Cd, minimum_area = 0, name) pars = @parameters begin @@ -333,7 +342,7 @@ Valve with `area` input and discharge coefficient `Cd` defined by https://en.wik System(eqs, t, vars, pars; name, systems) end -@component function VolumeBase(; area, dead_volume = 0, p_int, x_int, +@component function VolumeBase(; area = nothing, dead_volume = 0, p_int = nothing, x_int = nothing, name) pars = @parameters begin area = area @@ -381,7 +390,7 @@ Fixed fluid volume. # Connectors: - `port`: hydraulic port """ -@component function FixedVolume(; vol, name, p_int) +@component function FixedVolume(; vol = nothing, name, p_int = nothing) pars = @parameters begin vol = vol p_int = p_int @@ -449,9 +458,9 @@ See also [`FixedVolume`](@ref), [`DynamicVolume`](@ref) """ @component function Volume(; #parameters - area, + area = nothing, direction = +1, - x_int, + x_int = nothing, name) pars = @parameters begin area = area @@ -550,9 +559,9 @@ dm ────► │ │ area - `flange`: mechanical translational port """ @component function DynamicVolume(reversible = false; - area, + area = nothing, x_int = 0, - x_max, + x_max = nothing, x_min = 0, x_damp = x_min, direction = +1, @@ -561,7 +570,7 @@ dm ────► │ │ area perimeter = 2 * sqrt(area * pi), shape_factor = 64, head_factor = 1, - p_int, + p_int = nothing, # Valve Cd = 1e2, @@ -651,7 +660,7 @@ Spool valve with `x` valve opening input as mechanical flange port and `d` diame See [`Valve`](@ref) for more information. """ -@component function SpoolValve(reversible = false; Cd, d, x_int, name) +@component function SpoolValve(reversible = false; Cd = nothing, d = nothing, x_int = nothing, name) pars = @parameters begin d = d Cd = Cd @@ -701,7 +710,7 @@ end See [`SpoolValve`](@ref) for more information. """ -@component function SpoolValve2Way(reversible = false; m, g, Cd, d, x_int, name) +@component function SpoolValve2Way(reversible = false; m = nothing, g = nothing, Cd = nothing, d = nothing, x_int = nothing, name) pars = @parameters begin m = m g = g @@ -814,18 +823,18 @@ Actuator made of two DynamicVolumes connected in opposite direction with body ma - `flange`: mechanical translational port """ @component function Actuator(reversible = false; - area_a, - area_b, + area_a = nothing, + area_b = nothing, perimeter_a = 2 * sqrt(area_a * pi), perimeter_b = 2 * sqrt(area_b * pi), - length_a_int, - length_b_int, + length_a_int = nothing, + length_b_int = nothing, shape_factor_a = 64, shape_factor_b = 64, head_factor_a = 1, head_factor_b = 1, - m, - g, + m = nothing, + g = nothing, x_int = 0, dx_int = 0, minimum_volume_a = 0, @@ -835,8 +844,8 @@ Actuator made of two DynamicVolumes connected in opposite direction with body ma Cd = 1e4, Cd_reverse = Cd, d = 0, - p_a_int, - p_b_int, + p_a_int = nothing, + p_b_int = nothing, name) pars = @parameters begin area_a = area_a @@ -922,20 +931,20 @@ end """ Orifice() -A valve in fixed position, with parameters for area and the discharge coefficient (fitting the form Effective Area = area x Cd) +A valve in fixed position, with parameters for area and the discharge coefficient (fitting the form Effective Area = area x Cd) ``` - ┌ - │ + ┌ + │ ▲ dm ────► effective area ▼ - │ + │ └ ``` # Features: -- +- # Parameters: ## volume @@ -947,22 +956,28 @@ dm ────► effective area - `port_b`: hydraulic port """ -@mtkmodel Orifice begin - @parameters begin - orifice_area = 0.00094 - Cd = 0.6 # TODO Cd here is defined differently from Valve(). +@component function Orifice(; name, orifice_area = 0.00094, Cd = 0.6) + pars = @parameters begin + orifice_area = orifice_area + Cd = Cd # TODO Cd here is defined differently from Valve(). # Here it follows the form Effective Orifice Area = Cd x Physical Orifice Area # The Valve component should be updated too. end - @components begin - area = Constant(k = orifice_area) - valve = Valve(Cd = 1 / (Cd * Cd)) - port_a = HydraulicPort() - port_b = HydraulicPort() + + @named area = Constant(k = orifice_area) + @named valve = Valve(Cd = 1 / (Cd * Cd)) + @named port_a = HydraulicPort() + @named port_b = HydraulicPort() + systems = [area, valve, port_a, port_b] + + vars = @variables begin end - @equations begin - connect(valve.area, area.output) - connect(valve.port_a, port_a) + + equations = Equation[ + connect(valve.area, area.output), + connect(valve.port_a, port_a), connect(valve.port_b, port_b) - end + ] + + return System(equations, t, vars, pars; name, systems) end diff --git a/src/Hydraulic/IsothermalCompressible/sources.jl b/src/Hydraulic/IsothermalCompressible/sources.jl index cb032a109..34234193f 100644 --- a/src/Hydraulic/IsothermalCompressible/sources.jl +++ b/src/Hydraulic/IsothermalCompressible/sources.jl @@ -8,15 +8,22 @@ Hydraulic mass flow input source - `port`: hydraulic port - `dm`: real input """ -@mtkmodel MassFlow begin - @components begin - port = HydraulicPort() - dm = RealInput() +@component function MassFlow(; name) + pars = @parameters begin end - @equations begin - port.dm ~ -dm.u + @named port = HydraulicPort() + @named dm = RealInput() + systems = [port, dm] + + vars = @variables begin end + + equations = Equation[ + port.dm ~ -dm.u + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -30,18 +37,22 @@ Fixed pressure source # Connectors: - `port`: hydraulic port """ -@mtkmodel FixedPressure begin - @parameters begin - p +@component function FixedPressure(; name, p = nothing) + pars = @parameters begin + p = p end - @components begin - port = HydraulicPort() + @named port = HydraulicPort() + systems = [port] + + vars = @variables begin end - @equations begin + equations = Equation[ port.p ~ p - end + ] + + return System(equations, t, vars, pars; name, systems) end @deprecate Source FixedPressure @@ -54,14 +65,21 @@ input pressure source - `port`: hydraulic port - `p`: real input """ -@mtkmodel Pressure begin - @components begin - port = HydraulicPort() - p = RealInput() +@component function Pressure(; name) + pars = @parameters begin end - @equations begin - port.p ~ p.u + @named port = HydraulicPort() + @named p = RealInput() + systems = [port, p] + + vars = @variables begin end + + equations = Equation[ + port.p ~ p.u + ] + + return System(equations, t, vars, pars; name, systems) end @deprecate InputSource Pressure diff --git a/src/Magnetic/FluxTubes/FluxTubes.jl b/src/Magnetic/FluxTubes/FluxTubes.jl index 08dd00120..e91676558 100644 --- a/src/Magnetic/FluxTubes/FluxTubes.jl +++ b/src/Magnetic/FluxTubes/FluxTubes.jl @@ -1,6 +1,6 @@ module FluxTubes -using ModelingToolkit -using ModelingToolkit: t_nounits as t, D_nounits as D +using ModelingToolkitBase +using ModelingToolkitBase: t_nounits as t, D_nounits as D using ...Electrical: Pin export PositiveMagneticPort, NegativeMagneticPort, TwoPort diff --git a/src/Magnetic/FluxTubes/basic.jl b/src/Magnetic/FluxTubes/basic.jl index 3c5c4b0c1..8c65b46b2 100644 --- a/src/Magnetic/FluxTubes/basic.jl +++ b/src/Magnetic/FluxTubes/basic.jl @@ -3,13 +3,22 @@ Zero magnetic potential. """ -@mtkmodel Ground begin - @components begin +@component function Ground(; name) + pars = @parameters begin + end + + systems = @named begin port = PositiveMagneticPort() end - @equations begin - port.V_m ~ 0 + + vars = @variables begin end + + equations = Equation[ + port.V_m ~ 0 + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -17,11 +26,25 @@ end Idle running branch. """ -@mtkmodel Idle begin - @extend (Phi,) = two_port = TwoPort() - @equations begin - Phi ~ 0 +@component function Idle(; name) + @named two_port = TwoPort() + @unpack Phi = two_port + + pars = @parameters begin end + + systems = @named begin + end + + vars = @variables begin + end + + equations = Equation[ + Phi ~ 0 + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, two_port) end """ @@ -29,11 +52,25 @@ end Short cut branch. """ -@mtkmodel Short begin - @extend (V_m,) = two_port = TwoPort() - @equations begin - V_m ~ 0 +@component function Short(; name) + @named two_port = TwoPort() + @unpack V_m = two_port + + pars = @parameters begin + end + + systems = @named begin + end + + vars = @variables begin end + + equations = Equation[ + V_m ~ 0 + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, two_port) end """ @@ -43,17 +80,26 @@ Crossing of two branches. This is a simple crossing of two branches. The ports port_p1 and port_p2 are connected, as well as port_n1 and port_n2. """ -@mtkmodel Crossing begin - @components begin +@component function Crossing(; name) + pars = @parameters begin + end + + systems = @named begin port_p1 = PositiveMagneticPort() port_p2 = PositiveMagneticPort() port_n1 = NegativeMagneticPort() port_n2 = NegativeMagneticPort() end - @equations begin - connect(port_p1, port_p2) - connect(port_n1, port_n2) + + vars = @variables begin end + + equations = Equation[ + connect(port_p1, port_p2), + connect(port_n1, port_n2) + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -65,14 +111,26 @@ Constant permeance. - `G_m`: [H] Magnetic permeance """ -@mtkmodel ConstantPermeance begin - @extend V_m, Phi = two_port = TwoPort() - @parameters begin - G_m = 1.0, [description = "Magnetic permeance"] +@component function ConstantPermeance(; name, G_m = 1.0) + @named two_port = TwoPort() + @unpack V_m, Phi = two_port + + pars = @parameters begin + G_m = G_m, [description = "Magnetic permeance"] end - @equations begin - Phi ~ G_m * V_m + + systems = @named begin + end + + vars = @variables begin end + + equations = Equation[ + Phi ~ G_m * V_m + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, two_port) end """ @@ -84,14 +142,26 @@ Constant reluctance. - `R_m`: [H^-1] Magnetic reluctance """ -@mtkmodel ConstantReluctance begin - @extend V_m, Phi = two_port = TwoPort(; Phi = 0.0) - @parameters begin - R_m = 1.0, [description = "Magnetic reluctance"] +@component function ConstantReluctance(; name, R_m = 1.0) + @named two_port = TwoPort(; Phi = 0.0) + @unpack V_m, Phi = two_port + + pars = @parameters begin + R_m = R_m, [description = "Magnetic reluctance"] end - @equations begin - V_m ~ Phi * R_m + + systems = @named begin + end + + vars = @variables begin end + + equations = Equation[ + V_m ~ Phi * R_m + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, two_port) end """ @@ -109,27 +179,35 @@ Initial magnetic flux flowing into the port_p can be set with `Phi` ([Wb]) - `N`: Number of turns """ -@mtkmodel ElectroMagneticConverter begin - @parameters begin - N, [description = "Number of turns"] - end - @variables begin - v(t) - i(t) +@component function ElectroMagneticConverter(; name, N = nothing, Phi = nothing, v = nothing, i = nothing) + @named two_port = TwoPort(; Phi) + @unpack V_m, Phi = two_port + + pars = @parameters begin + N = N, [description = "Number of turns"] end - @extend V_m, Phi = two_port = TwoPort(; Phi) - @components begin + + systems = @named begin p = Pin() n = Pin() end - @equations begin - v ~ p.v - n.v - 0 ~ p.i + n.i - i ~ p.i + + vars = @variables begin + v(t) = v + i(t) = i + end + + equations = Equation[ + v ~ p.v - n.v, + 0 ~ p.i + n.i, + i ~ p.i, #converter equations: - V_m ~ i * N # Ampere's law + V_m ~ i * N, # Ampere's law D(Phi) ~ -v / N - end + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, two_port) end """ @@ -144,15 +222,29 @@ Initial magnetic flux flowing into the port_p can be set with `Phi` ([`Wb`]) - `l`: [m] Average length of eddy current path - `A`: [m^2] Cross sectional area of eddy current path """ -@mtkmodel EddyCurrent begin - @parameters begin - rho = 0.098e-6, [description = "Resistivity of flux tube material"] - l = 1, [description = "Average length of eddy current path"] - A = 1, [description = "Cross sectional area of eddy current path"] - R = rho * l / A # Electrical resistance of eddy current path +@component function EddyCurrent(; name, Phi = nothing, rho = 0.098e-6, l = 1, A = 1) + @named two_port = TwoPort(; Phi) + @unpack V_m, Phi = two_port + + R = rho * l / A # Electrical resistance of eddy current path + + pars = @parameters begin + rho = rho, [description = "Resistivity of flux tube material"] + l = l, [description = "Average length of eddy current path"] + A = A, [description = "Cross sectional area of eddy current path"] + R = R end - @extend (V_m, Phi) = two_port = TwoPort(; Phi) - @equations begin - D(Phi) ~ V_m * R + + systems = @named begin + end + + vars = @variables begin end + + equations = Equation[ + D(Phi) ~ V_m * R + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, two_port) end diff --git a/src/Magnetic/FluxTubes/sources.jl b/src/Magnetic/FluxTubes/sources.jl index d2c5f8dfe..6ca7f8b9b 100644 --- a/src/Magnetic/FluxTubes/sources.jl +++ b/src/Magnetic/FluxTubes/sources.jl @@ -7,22 +7,27 @@ Parameters: - `V_m`: [A] Magnetic potential difference """ -@mtkmodel ConstantMagneticPotentialDifference begin - @components begin +@component function ConstantMagneticPotentialDifference(; name, V_m = 0.0, Phi = nothing) + pars = @parameters begin + V_m = V_m, [description = "Magnetic potential difference"] + end + + systems = @named begin port_p = PositiveMagneticPort() port_n = NegativeMagneticPort() end - @parameters begin - V_m = 0.0, [description = "Magnetic potential difference"] - end - @variables begin - Phi(t) + + vars = @variables begin + Phi(t) = Phi end - @equations begin - V_m ~ port_p.V_m - port_n.V_m - Phi ~ port_p.Phi + + equations = Equation[ + V_m ~ port_p.V_m - port_n.V_m, + Phi ~ port_p.Phi, 0 ~ port_p.Phi + port_n.Phi - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -34,20 +39,25 @@ Parameters: - `Phi`: [Wb] Magnetic flux """ -@mtkmodel ConstantMagneticFlux begin - @components begin +@component function ConstantMagneticFlux(; name, Phi = 0.0, V_m = nothing) + pars = @parameters begin + Phi = Phi, [description = "Magnetic flux"] + end + + systems = @named begin port_p = PositiveMagneticPort() port_n = NegativeMagneticPort() end - @parameters begin - Phi = 0.0, [description = "Magnetic flux"] - end - @variables begin - V_m(t) + + vars = @variables begin + V_m(t) = V_m end - @equations begin - V_m ~ port_p.V_m - port_n.V_m - Phi ~ port_p.Phi + + equations = Equation[ + V_m ~ port_p.V_m - port_n.V_m, + Phi ~ port_p.Phi, 0 ~ port_p.Phi + port_n.Phi - end + ] + + return System(equations, t, vars, pars; name, systems) end diff --git a/src/Magnetic/FluxTubes/utils.jl b/src/Magnetic/FluxTubes/utils.jl index a7d1027be..d1aaf22c8 100644 --- a/src/Magnetic/FluxTubes/utils.jl +++ b/src/Magnetic/FluxTubes/utils.jl @@ -1,6 +1,9 @@ -@connector MagneticPort begin - V_m(t), [description = "Magnetic potential at the port"] - Phi(t), [connect = Flow, description = "Magnetic flux flowing into the port"] +@connector function MagneticPort(; name, V_m = nothing, Phi = nothing) + vars = @variables begin + V_m(t) = V_m, [description = "Magnetic potential at the port"] + Phi(t) = Phi, [connect = Flow, description = "Magnetic flux flowing into the port"] + end + System(Equation[], t, vars, []; name) end Base.@doc "Port for a Magnetic system." MagneticPort @@ -24,18 +27,25 @@ Partial component with magnetic potential difference between two magnetic ports - `V_m`: Initial magnetic potential difference between both ports - `Phi`: Initial magnetic flux from port_p to port_n """ -@mtkmodel TwoPort begin - @components begin +@component function TwoPort(; name, V_m = nothing, Phi = nothing) + pars = @parameters begin + end + + systems = @named begin port_p = PositiveMagneticPort() port_n = NegativeMagneticPort() end - @variables begin - V_m(t) - Phi(t) + + vars = @variables begin + V_m(t) = V_m + Phi(t) = Phi end - @equations begin - V_m ~ port_p.V_m - port_n.V_m - Phi ~ port_p.Phi + + equations = Equation[ + V_m ~ port_p.V_m - port_n.V_m, + Phi ~ port_p.Phi, 0 ~ port_p.Phi + port_n.Phi - end + ] + + return System(equations, t, vars, pars; name, systems) end diff --git a/src/Magnetic/Magnetic.jl b/src/Magnetic/Magnetic.jl index 4eefda950..65a850c12 100644 --- a/src/Magnetic/Magnetic.jl +++ b/src/Magnetic/Magnetic.jl @@ -1,6 +1,6 @@ module Magnetic -using ModelingToolkit +using ModelingToolkitBase # FluxTubes include("FluxTubes/FluxTubes.jl") diff --git a/src/Mechanical/Mechanical.jl b/src/Mechanical/Mechanical.jl index 95c9e0204..64393d119 100644 --- a/src/Mechanical/Mechanical.jl +++ b/src/Mechanical/Mechanical.jl @@ -3,7 +3,7 @@ Library of mechanical models. """ module Mechanical -using ModelingToolkit +using ModelingToolkitBase include("Rotational/Rotational.jl") include("Translational/Translational.jl") diff --git a/src/Mechanical/MultiBody2D/MultiBody2D.jl b/src/Mechanical/MultiBody2D/MultiBody2D.jl index ab0e3e6c0..bb8495783 100644 --- a/src/Mechanical/MultiBody2D/MultiBody2D.jl +++ b/src/Mechanical/MultiBody2D/MultiBody2D.jl @@ -1,7 +1,7 @@ module MultiBody2D -using ModelingToolkit, Symbolics, IfElse -using ModelingToolkit: t_nounits as t, D_nounits as D +using ModelingToolkitBase, Symbolics, IfElse +using ModelingToolkitBase: t_nounits as t, D_nounits as D using ..TranslationalPosition export Link diff --git a/src/Mechanical/MultiBody2D/components.jl b/src/Mechanical/MultiBody2D/components.jl index 2e45de98f..30d06b0e6 100644 --- a/src/Mechanical/MultiBody2D/components.jl +++ b/src/Mechanical/MultiBody2D/components.jl @@ -1,88 +1,105 @@ -@mtkmodel Link begin - @parameters begin - m - l - I - g - x1_0 = 0.0 - y1_0 = 0.0 +@component function Link(; name, + m = nothing, l = nothing, I = nothing, g = nothing, + x1_0 = 0.0, y1_0 = 0.0, + A = nothing, dA = nothing, ddA = nothing, + fx1 = nothing, fy1 = nothing, + fx2 = nothing, fy2 = nothing, + x1 = nothing, dx1 = nothing, + y1 = nothing, dy1 = nothing, + x2 = nothing, dx2 = nothing, + y2 = nothing, dy2 = nothing, + x_cm = nothing, dx_cm = nothing, ddx_cm = nothing, + y_cm = nothing, dy_cm = nothing, ddy_cm = nothing) + pars = @parameters begin + m = m + l = l + I = I + g = g + x1_0 = x1_0 + y1_0 = y1_0 end - @variables begin - (A(t)), [state_priority = 10] - (dA(t)), [state_priority = 10] - (ddA(t)), [state_priority = 10] + @named TX1 = Flange() + @named TY1 = Flange() + @named TX2 = Flange() + @named TY2 = Flange() + systems = [TX1, TY1, TX2, TY2] - fx1(t) - fy1(t) + # Compute defaults using parameter symbols if not provided + x1_val = x1 === nothing ? x1_0 : x1 + y1_val = y1 === nothing ? y1_0 : y1 + x2_val = x2 === nothing ? l + x1_0 : x2 + x_cm_val = x_cm === nothing ? l / 2 + x1_0 : x_cm - fx2(t) - fy2(t) + vars = @variables begin + A(t) = A, [state_priority = 10] + dA(t) = dA, [state_priority = 10] + ddA(t) = ddA, [state_priority = 10] - x1(t) = x1_0 - dx1(t) + fx1(t) = fx1 + fy1(t) = fy1 - y1(t) = y1_0 - dy1(t) + fx2(t) = fx2 + fy2(t) = fy2 - x2(t) = l + x1_0 - dx2(t) + x1(t) = x1_val + dx1(t) = dx1 - y2(t) - dy2(t) + y1(t) = y1_val + dy1(t) = dy1 - x_cm(t) = l / 2 + x1_0 - dx_cm(t) - ddx_cm(t) + x2(t) = x2_val + dx2(t) = dx2 - y_cm(t) - dy_cm(t) - ddy_cm(t) - end + y2(t) = y2 + dy2(t) = dy2 - @components begin - TX1 = Flange() - TY1 = Flange() + x_cm(t) = x_cm_val + dx_cm(t) = dx_cm + ddx_cm(t) = ddx_cm - TX2 = Flange() - TY2 = Flange() + y_cm(t) = y_cm + dy_cm(t) = dy_cm + ddy_cm(t) = ddy_cm end - @equations begin - D(A) ~ dA - D(dA) ~ ddA - D(x1) ~ dx1 - D(y1) ~ dy1 - D(x2) ~ dx2 - D(y2) ~ dy2 - D(x_cm) ~ dx_cm - D(dx_cm) ~ ddx_cm - D(y_cm) ~ dy_cm - D(dy_cm) ~ ddy_cm + equations = Equation[ + D(A) ~ dA, + D(dA) ~ ddA, + D(x1) ~ dx1, + D(y1) ~ dy1, + D(x2) ~ dx2, + D(y2) ~ dy2, + D(x_cm) ~ dx_cm, + D(dx_cm) ~ ddx_cm, + D(y_cm) ~ dy_cm, + D(dy_cm) ~ ddy_cm, # x forces - m * ddx_cm ~ fx1 + fx2 + m * ddx_cm ~ fx1 + fx2, # y forces - m * ddy_cm ~ m * g + fy1 + fy2 + m * ddy_cm ~ m * g + fy1 + fy2, # torques I * ddA ~ -fy1 * (x2 - x1) / 2 + fy2 * (x2 - x1) / 2 + fx1 * (y2 - y1) / 2 - - fx2 * (y2 - y1) / 2 + fx2 * (y2 - y1) / 2, # geometry - x2 ~ l * cos(A) + x1 - y2 ~ l * sin(A) + y1 - x_cm ~ l * cos(A) / 2 + x1 - y_cm ~ l * sin(A) / 2 + y1 - TX1.f ~ fx1 - TX1.s ~ x1 - TY1.f ~ fy1 - TY1.s ~ y1 - TX2.f ~ fx2 - TX2.s ~ x2 - TY2.f ~ fy2 + x2 ~ l * cos(A) + x1, + y2 ~ l * sin(A) + y1, + x_cm ~ l * cos(A) / 2 + x1, + y_cm ~ l * sin(A) / 2 + y1, + TX1.f ~ fx1, + TX1.s ~ x1, + TY1.f ~ fy1, + TY1.s ~ y1, + TX2.f ~ fx2, + TX2.s ~ x2, + TY2.f ~ fy2, TY2.s ~ y2 - end + ] + + return System(equations, t, vars, pars; name, systems) end diff --git a/src/Mechanical/Rotational/Rotational.jl b/src/Mechanical/Rotational/Rotational.jl index 0483c0654..a26885dd2 100644 --- a/src/Mechanical/Rotational/Rotational.jl +++ b/src/Mechanical/Rotational/Rotational.jl @@ -3,8 +3,8 @@ Library to model 1-dimensional, rotational mechanical systems """ module Rotational -using ModelingToolkit, Symbolics, IfElse -using ModelingToolkit: t_nounits as t, D_nounits as D +using ModelingToolkitBase, Symbolics, IfElse +using ModelingToolkitBase: t_nounits as t, D_nounits as D using ...Blocks: RealInput, RealOutput import ...@symcheck diff --git a/src/Mechanical/Rotational/components.jl b/src/Mechanical/Rotational/components.jl index f734c1862..ab254880d 100644 --- a/src/Mechanical/Rotational/components.jl +++ b/src/Mechanical/Rotational/components.jl @@ -11,20 +11,27 @@ Flange fixed in housing at a given angle. - `phi0`: [`rad`] Fixed offset angle of housing """ -@mtkmodel Fixed begin - @components begin +@component function Fixed(; phi0 = 0.0, name) + pars = @parameters begin + phi0 = phi0, [description = "Fixed offset angle of flange"] + end + + systems = @named begin flange = Flange() end - @parameters begin - phi0 = 0.0, [description = "Fixed offset angle of flange"] + + vars = @variables begin end - @equations begin + + equations = Equation[ flange.phi ~ phi0 - end + ] + + return System(equations, t, vars, pars; name, systems) end """ - Inertia(;name, J, phi = 0.0, w = 0.0, a = 0.0) + Inertia(;name, J, phi = nothing, w = nothing, a = nothing) 1D-rotational component with inertia. @@ -43,29 +50,33 @@ end - `J`: [`kg·m²`] Moment of inertia """ -@mtkmodel Inertia begin - @parameters begin - J, [description = "Moment of inertia"] +@component function Inertia(; J = nothing, phi = nothing, w = nothing, a = nothing, name) + @symcheck J > 0 || throw(ArgumentError("Expected `J` to be positive")) + + pars = @parameters begin + J = J, [description = "Moment of inertia"] end - @components begin + + systems = @named begin flange_a = Flange() flange_b = Flange() end - begin - @symcheck J > 0 || throw(ArgumentError("Expected `J` to be positive")) - end - @variables begin - phi(t), [description = "Absolute rotation angle", guess = 0.0] - w(t), [description = "Absolute angular velocity", guess = 0.0] - a(t), [description = "Absolute angular acceleration", guess = 0.0] + + vars = @variables begin + phi(t) = phi, [description = "Absolute rotation angle", guess = 0.0] + w(t) = w, [description = "Absolute angular velocity", guess = 0.0] + a(t) = a, [description = "Absolute angular acceleration", guess = 0.0] end - @equations begin - phi ~ flange_a.phi - phi ~ flange_b.phi - D(phi) ~ w - D(w) ~ a + + equations = Equation[ + phi ~ flange_a.phi, + phi ~ flange_b.phi, + D(phi) ~ w, + D(w) ~ a, J * a ~ flange_a.tau + flange_b.tau - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -88,18 +99,29 @@ Linear 1D rotational spring - `c`: [`N.m/rad`] Spring constant - `phi_rel0`: [`rad`] Unstretched spring angle. Defaults to 0.0. """ -@mtkmodel Spring begin - @extend phi_rel, tau = partial_comp = PartialCompliant() - begin - @symcheck c > 0 || throw(ArgumentError("Expected `c` to be positive")) +@component function Spring(; c = nothing, phi_rel0 = 0.0, name) + @symcheck c > 0 || throw(ArgumentError("Expected `c` to be positive")) + + @named partial_comp = PartialCompliant() + @unpack phi_rel, tau = partial_comp + + pars = @parameters begin + c = c, [description = "Spring constant"] + phi_rel0 = phi_rel0, [description = "Unstretched spring angle"] end - @parameters begin - c, [description = "Spring constant"] - phi_rel0 = 0.0, [description = "Unstretched spring angle"] + + systems = @named begin end - @equations begin - tau ~ c * (phi_rel - phi_rel0) + + vars = @variables begin end + + equations = Equation[ + tau ~ c * (phi_rel - phi_rel0) + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, partial_comp) end """ @@ -123,17 +145,28 @@ Linear 1D rotational damper - `d`: [`N.m.s/rad`] Damping constant """ -@mtkmodel Damper begin - @extend w_rel, tau = partial_comp = PartialCompliantWithRelativeStates() - begin - @symcheck d > 0 || throw(ArgumentError("Expected `d` to be positive")) +@component function Damper(; d = nothing, name) + @symcheck d > 0 || throw(ArgumentError("Expected `d` to be positive")) + + @named partial_comp = PartialCompliantWithRelativeStates() + @unpack w_rel, tau = partial_comp + + pars = @parameters begin + d = d, [description = "Damping constant"] + end + + systems = @named begin end - @parameters begin - d, [description = "Damping constant"] + + vars = @variables begin end - @equations begin + + equations = Equation[ tau ~ d * w_rel - end + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, partial_comp) end """ SpringDamper(; name, d) @@ -158,22 +191,32 @@ Linear 1D rotational spring and damper - `c`: [`N.m/rad`] Spring constant - `phi_rel0`: [`rad`] Unstretched spring angle. Defaults to 0.0 """ -@mtkmodel SpringDamper begin - @extend phi_rel, w_rel, tau = partial_comp = PartialCompliantWithRelativeStates() - @variables begin - tau_c(t), [description = "Spring torque"] - tau_d(t), [description = "Damper torque"] +@component function SpringDamper(; d = nothing, c = nothing, phi_rel0 = 0.0, tau_c = nothing, tau_d = nothing, name) + @named partial_comp = PartialCompliantWithRelativeStates() + @unpack phi_rel, w_rel, tau = partial_comp + + pars = @parameters begin + d = d, [description = "Damping constant"] + c = c, [description = "Spring constant"] + phi_rel0 = phi_rel0, [description = "Unstretched spring angle"] + end + + systems = @named begin end - @parameters begin - d, [description = "Damping constant"] - c, [description = "Spring constant"] - phi_rel0 = 0.0, [description = "Unstretched spring angle"] + + vars = @variables begin + tau_c(t) = tau_c, [description = "Spring torque"] + tau_d(t) = tau_d, [description = "Damper torque"] end - @equations begin - tau_c ~ c * (phi_rel - phi_rel0) - tau_d ~ d * w_rel + + equations = Equation[ + tau_c ~ c * (phi_rel - phi_rel0), + tau_d ~ d * w_rel, tau ~ tau_c + tau_d - end + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, partial_comp) end """ @@ -199,25 +242,31 @@ This element characterizes any type of gear box which is fixed in the ground and - `ratio`: Transmission ratio (flange_a.phi/flange_b.phi) - `use_support`: If support flange enabled, otherwise implicitly grounded. By default it is `false` """ -@mtkmodel IdealGear begin - @extend phi_support, flange_a, - flange_b = partial_element = PartialElementaryTwoFlangesAndSupport2(; - use_support = false) - @parameters begin - ratio, [description = "Transmission ratio"] +@component function IdealGear(; ratio = nothing, use_support = false, phi_a = nothing, phi_b = nothing, name) + @named partial_element = PartialElementaryTwoFlangesAndSupport2(; use_support) + @unpack phi_support, flange_a, flange_b = partial_element + + pars = @parameters begin + ratio = ratio, [description = "Transmission ratio"] end - @variables begin - phi_a(t), - [description = "Relative angle between shaft a and the support", guess = 0.0] - phi_b(t), - [description = "Relative angle between shaft b and the support", guess = 0.0] + + systems = @named begin end - @equations begin - phi_a ~ flange_a.phi - phi_support - phi_b ~ flange_b.phi - phi_support - phi_a ~ ratio * phi_b - 0 ~ ratio * flange_a.tau + flange_b.tau + + vars = @variables begin + phi_a(t) = phi_a, [description = "Relative angle between shaft a and the support", guess = 0.0] + phi_b(t) = phi_b, [description = "Relative angle between shaft b and the support", guess = 0.0] end + + equations = Equation[ + phi_a ~ flange_a.phi - phi_support, + phi_b ~ flange_b.phi - phi_support, + phi_a ~ ratio * phi_b, + 0 ~ ratio * flange_a.tau + flange_b.tau + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, partial_element) end """ @@ -247,23 +296,33 @@ Friction model: "Armstrong, B. and C.C. de Wit, Friction Modeling and Compensati - `w_brk`: [`rad/s`] Breakaway friction velocity - `tau_brk`: [`N⋅m`] Breakaway friction torque """ -@mtkmodel RotationalFriction begin - @extend w_rel, tau = partial_comp = PartialCompliantWithRelativeStates() - @parameters begin - f, [description = "Viscous friction coefficient"] - tau_c, [description = "Coulomb friction torque"] - w_brk, [description = "Breakaway friction velocity"] - tau_brk, [description = "Breakaway friction torque"] +@component function RotationalFriction(; f = nothing, tau_c = nothing, w_brk = nothing, tau_brk = nothing, name) + @named partial_comp = PartialCompliantWithRelativeStates() + @unpack w_rel, tau = partial_comp + + pars = @parameters begin + f = f, [description = "Viscous friction coefficient"] + tau_c = tau_c, [description = "Coulomb friction torque"] + w_brk = w_brk, [description = "Breakaway friction velocity"] + tau_brk = tau_brk, [description = "Breakaway friction torque"] end - begin - str_scale = sqrt(2 * exp(1)) * (tau_brk - tau_c) - w_st = w_brk * sqrt(2) - w_coul = w_brk / 10 + str_scale = sqrt(2 * exp(1)) * (tau_brk - tau_c) + w_st = w_brk * sqrt(2) + w_coul = w_brk / 10 + + systems = @named begin + end + + vars = @variables begin end - @equations begin + + equations = Equation[ tau ~ str_scale * (exp(-(w_rel / w_st)^2) * w_rel / w_st) + - tau_c * tanh(w_rel / w_coul) + f * w_rel # Stribeck friction + Coulomb friction + Viscous friction - end + tau_c * tanh(w_rel / w_coul) + f * w_rel # Stribeck friction + Coulomb friction + Viscous friction + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, partial_comp) end diff --git a/src/Mechanical/Rotational/sensors.jl b/src/Mechanical/Rotational/sensors.jl index 258552e8d..3e6147a61 100644 --- a/src/Mechanical/Rotational/sensors.jl +++ b/src/Mechanical/Rotational/sensors.jl @@ -8,15 +8,24 @@ Ideal sensor to measure the absolute flange angle - `flange`: [Flange](@ref) Flange of shaft from which sensor information shall be measured - `phi`: [RealOutput](@ref) Absolute angle of flange """ -@mtkmodel AngleSensor begin - @components begin +@component function AngleSensor(; name) + pars = @parameters begin + end + + systems = @named begin flange = Flange() phi = RealOutput() end - @equations begin - phi.u ~ flange.phi - flange.tau ~ 0 + + vars = @variables begin end + + equations = Equation[ + phi.u ~ flange.phi, + flange.tau ~ 0 + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -29,15 +38,24 @@ Ideal sensor to measure the absolute flange angular velocity - `flange`: [Flange](@ref) Flange of shaft from which sensor information shall be measured - `w`: [RealOutput](@ref) Absolute angular velocity of flange """ -@mtkmodel SpeedSensor begin - @components begin +@component function SpeedSensor(; name) + pars = @parameters begin + end + + systems = @named begin flange = Flange() w = RealOutput() end - @equations begin - D(flange.phi) ~ w.u - flange.tau ~ 0 + + vars = @variables begin end + + equations = Equation[ + D(flange.phi) ~ w.u, + flange.tau ~ 0 + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -51,16 +69,25 @@ Ideal sensor to measure the torque between two flanges (`= flange_a.tau`) - `flange_b`: [Flange](@ref) Left flange of shaft - `tau`: [RealOutput](@ref) Torque in flange flange_a and flange_b (`tau = flange_a.tau = -flange_b.tau`) """ -@mtkmodel TorqueSensor begin - @components begin +@component function TorqueSensor(; name) + pars = @parameters begin + end + + systems = @named begin flange_a = Flange() flange_b = Flange() tau = RealOutput() end - @equations begin - flange_a.phi ~ flange_b.phi - tau.u ~ flange_a.tau + + vars = @variables begin end + + equations = Equation[ + flange_a.phi ~ flange_b.phi, + tau.u ~ flange_a.tau + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -74,19 +101,26 @@ Ideal sensor to measure the relative angular velocity - `flange_b`: [Flange](@ref) Flange of shaft from which sensor information shall be measured - `w`: [RealOutput](@ref) Absolute angular velocity of flange """ -@mtkmodel RelSpeedSensor begin - @components begin +@component function RelSpeedSensor(; name, phi_rel = nothing) + pars = @parameters begin + end + + systems = @named begin flange_a = Flange() flange_b = Flange() w_rel = RealOutput() end - @variables begin - phi_rel(t), [guess = 0.0] + + vars = @variables begin + phi_rel(t) = phi_rel, [guess = 0.0] end - @equations begin - 0 ~ flange_a.tau + flange_b.tau - phi_rel ~ flange_b.phi - flange_a.phi - D(phi_rel) ~ w_rel.u + + equations = Equation[ + 0 ~ flange_a.tau + flange_b.tau, + phi_rel ~ flange_b.phi - flange_a.phi, + D(phi_rel) ~ w_rel.u, 0 ~ flange_a.tau - end + ] + + return System(equations, t, vars, pars; name, systems) end diff --git a/src/Mechanical/Rotational/sources.jl b/src/Mechanical/Rotational/sources.jl index a93496292..0f756a6b9 100644 --- a/src/Mechanical/Rotational/sources.jl +++ b/src/Mechanical/Rotational/sources.jl @@ -1,16 +1,23 @@ -@mtkmodel PartialTorque begin - @extend flange, - phi_support = partial_element = PartialElementaryOneFlangeAndSupport2(; - use_support = false) - @variables begin - phi(t), - [ - description = "Angle of flange with respect to support (= flange.phi - support.phi)" - ] +@component function PartialTorque(; use_support = false, name) + @named partial_element = PartialElementaryOneFlangeAndSupport2(; use_support) + @unpack flange, phi_support = partial_element + + pars = @parameters begin end - @equations begin - phi ~ flange.phi - phi_support + + systems = @named begin + end + + vars = @variables begin + phi(t), [description = "Angle of flange with respect to support (= flange.phi - support.phi)"] end + + equations = Equation[ + phi ~ flange.phi - phi_support + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, partial_element) end """ @@ -31,15 +38,26 @@ Input signal acting as external torque on a flange - `use_support` """ -@mtkmodel Torque begin - @extend (flange,) = partial_element = PartialElementaryOneFlangeAndSupport2(; - use_support = false) - @components begin +@component function Torque(; use_support = false, name) + @named partial_element = PartialElementaryOneFlangeAndSupport2(; use_support) + @unpack flange = partial_element + + pars = @parameters begin + end + + systems = @named begin tau = RealInput() end - @equations begin - flange.tau ~ -tau.u + + vars = @variables begin end + + equations = Equation[ + flange.tau ~ -tau.u + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, partial_element) end """ @@ -60,24 +78,30 @@ Constant torque source - `tau_constant`: The constant torque applied by the source - `use_support`: Whether or not an internal support flange is added. By default, it is `false` """ -@mtkmodel ConstantTorque begin - @parameters begin - tau_constant, - [ - description = "Constant torque (if negative, torque is acting as load in positive direction of rotation)" - ] +@component function ConstantTorque(; tau_constant, use_support = false, name) + @named partial_element = PartialTorque(; use_support) + @unpack flange, phi = partial_element + + pars = @parameters begin + tau_constant = tau_constant, [description = "Constant torque (if negative, torque is acting as load in positive direction of rotation)"] end - @extend flange, phi = partial_element = PartialTorque(; use_support = false) - @variables begin + + systems = @named begin + end + + vars = @variables begin tau(t), [description = "Accelerating torque acting at flange (= -flange.tau)"] - w(t), - [description = "Angular velocity of flange with respect to support (= der(phi))"] + w(t), [description = "Angular velocity of flange with respect to support (= der(phi))"] end - @equations begin - w ~ D(phi) - tau ~ -flange.tau + + equations = Equation[ + w ~ D(phi), + tau ~ -flange.tau, tau ~ tau_constant - end + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, partial_element) end """ @@ -101,23 +125,46 @@ Forced movement of a flange according to a reference angular velocity signal - `tau_filt`: [`rad/s`] if exact=false, Time constant of low-pass filter to filter input signal """ @component function Speed(; name, use_support = false, exact = false, tau_filt = 50) - @named partial_element = PartialElementaryOneFlangeAndSupport2(use_support = use_support) + @named partial_element = PartialElementaryOneFlangeAndSupport2(; use_support) @unpack flange, phi_support = partial_element - @named w_ref = RealInput() - @variables phi(t) [guess = 0.0] w(t) [guess = 0.0] a(t) [guess = 0.0] - eqs = [phi ~ flange.phi - phi_support - D(phi) ~ w] - if exact - pars = [] - push!(eqs, w ~ w_ref.u) - push!(eqs, a ~ 0) + + pars = if exact + @parameters begin + end else - pars = @parameters tau_filt = tau_filt - push!(eqs, D(w) ~ a) - push!(eqs, a ~ (w_ref.u - w) * tau_filt) + @parameters begin + tau_filt = tau_filt, [description = "Time constant of low-pass filter to filter input signal"] + end end - return extend(System(eqs, t, [phi, w, a], pars; name = name, systems = [w_ref]), - partial_element) + + systems = @named begin + w_ref = RealInput() + end + + vars = @variables begin + phi(t), [guess = 0.0, description = "Angle of flange with respect to support"] + w(t), [guess = 0.0, description = "Angular velocity of flange with respect to support"] + a(t), [guess = 0.0, description = "Angular acceleration of flange with respect to support"] + end + + equations = if exact + Equation[ + phi ~ flange.phi - phi_support, + D(phi) ~ w, + w ~ w_ref.u, + a ~ 0 + ] + else + Equation[ + phi ~ flange.phi - phi_support, + D(phi) ~ w, + D(w) ~ a, + a ~ (w_ref.u - w) * tau_filt + ] + end + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, partial_element) end """ diff --git a/src/Mechanical/Rotational/utils.jl b/src/Mechanical/Rotational/utils.jl index f3f834275..f9a89886c 100644 --- a/src/Mechanical/Rotational/utils.jl +++ b/src/Mechanical/Rotational/utils.jl @@ -1,6 +1,9 @@ -@connector Flange begin - phi(t), [description = "Rotation angle of flange"] - tau(t), [connect = Flow, description = "Cut torque in flange"] +@connector function Flange(; name, phi = nothing, tau = nothing) + vars = @variables begin + phi(t) = phi, [description = "Rotation angle of flange"] + tau(t) = tau, [connect = Flow, description = "Cut torque in flange"] + end + System(Equation[], t, vars, []; name) end Base.@doc """ @@ -13,9 +16,12 @@ Base.@doc """ - `tau(t)`: [`N.m`] Cut torque in the flange """ Flange -@connector Support begin - phi(t), [description = "Rotation angle of flange"] - tau(t), [connect = Flow, description = "Cut torque in flange"] +@connector function Support(; name, phi = nothing, tau = nothing) + vars = @variables begin + phi(t) = phi, [description = "Rotation angle of flange"] + tau(t) = tau, [connect = Flow, description = "Cut torque in flange"] + end + System(Equation[], t, vars, []; name) end # Base.@doc """ @@ -65,20 +71,27 @@ Partial model for the compliant connection of two rotational 1-dim. shaft flange - `flange_b` [Flange](@ref) """ -@mtkmodel PartialCompliant begin - @components begin +@component function PartialCompliant(; name, phi_rel = nothing, tau = nothing) + pars = @parameters begin + end + + systems = @named begin flange_a = Flange() flange_b = Flange() end - @variables begin - phi_rel(t), [description = "Relative rotation angle between flanges", guess = 0.0] - tau(t), [description = "Torque between flanges", guess = 0.0] + + vars = @variables begin + phi_rel(t) = phi_rel, [description = "Relative rotation angle between flanges", guess = 0.0] + tau(t) = tau, [description = "Torque between flanges", guess = 0.0] end - @equations begin - phi_rel ~ flange_b.phi - flange_a.phi - flange_b.tau ~ tau + + equations = Equation[ + phi_rel ~ flange_b.phi - flange_a.phi, + flange_b.tau ~ tau, flange_a.tau ~ -tau - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -98,25 +111,32 @@ Partial model for the compliant connection of two rotational 1-dim. shaft flange - `flange_a` [Flange](@ref) - `flange_b` [Flange](@ref) """ -@mtkmodel PartialCompliantWithRelativeStates begin - @components begin +@component function PartialCompliantWithRelativeStates(; name, phi_rel = nothing, w_rel = nothing, a_rel = nothing, tau = nothing) + pars = @parameters begin + end + + systems = @named begin flange_a = Flange() flange_b = Flange() end - @variables begin - phi_rel(t), [description = "Relative rotation angle between flanges", guess = 0.0] - w_rel(t), [description = "Relative angular velocity between flanges", guess = 0.0] - a_rel(t), + + vars = @variables begin + phi_rel(t) = phi_rel, [description = "Relative rotation angle between flanges", guess = 0.0] + w_rel(t) = w_rel, [description = "Relative angular velocity between flanges", guess = 0.0] + a_rel(t) = a_rel, [description = "Relative angular acceleration between flanges", guess = 0.0] - tau(t), [description = "Torque between flanges", guess = 0.0] + tau(t) = tau, [description = "Torque between flanges", guess = 0.0] end - @equations begin - phi_rel ~ flange_b.phi - flange_a.phi - D(phi_rel) ~ w_rel - D(w_rel) ~ a_rel - flange_b.tau ~ tau + + equations = Equation[ + phi_rel ~ flange_b.phi - flange_a.phi, + D(phi_rel) ~ w_rel, + D(w_rel) ~ a_rel, + flange_b.tau ~ tau, flange_a.tau ~ -tau - end + ] + + return System(equations, t, vars, pars; name, systems) end """ diff --git a/src/Mechanical/Translational/Translational.jl b/src/Mechanical/Translational/Translational.jl index 4db9168ad..42a5b5f4a 100644 --- a/src/Mechanical/Translational/Translational.jl +++ b/src/Mechanical/Translational/Translational.jl @@ -3,8 +3,8 @@ Library to model 1-dimensional, translational mechanical systems """ module Translational -using ModelingToolkit, Symbolics -using ModelingToolkit: getdefault, t_nounits as t, D_nounits as D +using ModelingToolkitBase, Symbolics +using ModelingToolkitBase: getdefault, t_nounits as t, D_nounits as D using ModelingToolkitStandardLibrary.Blocks: RealInput, RealOutput using IfElse: ifelse diff --git a/src/Mechanical/Translational/components.jl b/src/Mechanical/Translational/components.jl index 0f7551d82..2f4b62f11 100644 --- a/src/Mechanical/Translational/components.jl +++ b/src/Mechanical/Translational/components.jl @@ -7,16 +7,23 @@ Use to close a system that has un-connected `MechanicalPort`'s where the force s - `flange`: 1-dim. translational flange """ -@mtkmodel Free begin - @components begin +@component function Free(; name, f = nothing) + pars = @parameters begin + end + + systems = @named begin flange = MechanicalPort() end - @variables begin - f(t) + + vars = @variables begin + f(t) = f end - @equations begin + + equations = Equation[ flange.f ~ f - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -28,13 +35,22 @@ Fixes a flange position (velocity = 0) - `flange`: 1-dim. translational flange """ -@mtkmodel Fixed begin - @components begin +@component function Fixed(; name) + pars = @parameters begin + end + + systems = @named begin flange = MechanicalPort() end - @equations begin - flange.v ~ 0 + + vars = @variables begin end + + equations = Equation[ + flange.v ~ 0 + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -98,11 +114,11 @@ Linear 1D translational spring - `flange_a`: 1-dim. translational flange on one side of spring - `flange_b`: 1-dim. translational flange on opposite side of spring """ -@component function Spring(; name, k) +@component function Spring(; name, k = nothing) Spring(REL; name, k) end # default -@component function Spring(::Val{:relative}; name, k) +@component function Spring(::Val{:relative}; name, k = nothing) pars = @parameters begin k = k end @@ -124,7 +140,7 @@ end # default end const ABS = Val(:absolute) -@component function Spring(::Val{:absolute}; name, k, l = 0) +@component function Spring(::Val{:absolute}; name, k = nothing, l = 0) pars = @parameters begin k = k l = l @@ -162,24 +178,27 @@ Linear 1D translational damper - `flange_a`: 1-dim. translational flange on one side of damper. Initial value of state `v` is set to 0.0 m/s. - `flange_b`: 1-dim. translational flange on opposite side of damper. Initial value of state `v` is set to 0.0 m/s. """ -@mtkmodel Damper begin - @parameters begin - d - end - @variables begin - v(t), [guess = 0] - f(t), [guess = 0] +@component function Damper(; name, d = nothing, v = nothing, f = nothing) + pars = @parameters begin + d = d end - @components begin + systems = @named begin flange_a = MechanicalPort() flange_b = MechanicalPort() end - @equations begin - v ~ flange_a.v - flange_b.v - f ~ v * d - flange_a.f ~ +f - flange_b.f ~ -f + vars = @variables begin + v(t) = v, [guess = 0] + f(t) = f, [guess = 0] end + + equations = Equation[ + v ~ flange_a.v - flange_b.v, + f ~ v * d, + flange_a.f ~ +f, + flange_b.f ~ -f + ] + + return System(equations, t, vars, pars; name, systems) end diff --git a/src/Mechanical/Translational/sensors.jl b/src/Mechanical/Translational/sensors.jl index 2a61d42db..fceb8efd5 100644 --- a/src/Mechanical/Translational/sensors.jl +++ b/src/Mechanical/Translational/sensors.jl @@ -8,18 +8,26 @@ Linear 1D force sensor, measures the force between two flanges. - `flange`: 1-dim. translational flange - `output`: real output """ -@mtkmodel ForceSensor begin - @components begin +@component function ForceSensor(; name) + pars = @parameters begin + end + + systems = @named begin flange_a = MechanicalPort() flange_b = MechanicalPort() output = RealOutput() end - @equations begin - flange_a.v ~ flange_b.v - flange_a.f + flange_b.f ~ 0.0 - output.u ~ flange_a.f + vars = @variables begin end + + equations = Equation[ + flange_a.v ~ flange_b.v, + flange_a.f + flange_b.f ~ 0.0, + output.u ~ flange_a.f + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -36,21 +44,26 @@ Linear 1D position sensor. - `flange`: 1-dim. translational flange - `output`: real output """ -@mtkmodel PositionSensor begin - @components begin +@component function PositionSensor(; name, s = nothing) + pars = @parameters begin + end + + systems = @named begin flange = MechanicalPort() output = RealOutput() end - @variables begin - s(t) + vars = @variables begin + s(t) = s end - @equations begin - D(s) ~ flange.v - output.u ~ s + equations = Equation[ + D(s) ~ flange.v, + output.u ~ s, flange.f ~ 0.0 - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -67,19 +80,24 @@ Linear 1D acceleration sensor. - `flange`: 1-dim. translational flange - `output`: real output """ -@mtkmodel AccelerationSensor begin - @components begin +@component function AccelerationSensor(; name, a = nothing) + pars = @parameters begin + end + + systems = @named begin flange = MechanicalPort() output = RealOutput() end - @variables begin - a(t) + vars = @variables begin + a(t) = a end - @equations begin - a ~ D(flange.v) - output.u ~ a + equations = Equation[ + a ~ D(flange.v), + output.u ~ a, flange.f ~ 0.0 - end + ] + + return System(equations, t, vars, pars; name, systems) end diff --git a/src/Mechanical/Translational/sources.jl b/src/Mechanical/Translational/sources.jl index 1f1eed02b..00719c410 100644 --- a/src/Mechanical/Translational/sources.jl +++ b/src/Mechanical/Translational/sources.jl @@ -8,15 +8,23 @@ Linear 1D force input source - `flange`: 1-dim. translational flange - `f`: real input """ -@mtkmodel Force begin - @components begin +@component function Force(; name) + pars = @parameters begin + end + + systems = @named begin flange = MechanicalPort(; v = 0.0) f = RealInput() end - @equations begin - flange.f ~ -f.u + vars = @variables begin end + + equations = Equation[ + flange.f ~ -f.u + ] + + return System(equations, t, vars, pars; name, systems) end """ diff --git a/src/Mechanical/Translational/utils.jl b/src/Mechanical/Translational/utils.jl index 012cd2c0d..0e9c65a5a 100644 --- a/src/Mechanical/Translational/utils.jl +++ b/src/Mechanical/Translational/utils.jl @@ -1,6 +1,9 @@ -@connector MechanicalPort begin - v(t) - f(t), [connect = Flow] +@connector function MechanicalPort(; name, v = nothing, f = nothing) + vars = @variables begin + v(t) = v + f(t) = f, [connect = Flow] + end + return System(Equation[], t, vars, []; name) end Base.@doc """ MechanicalPort(;name) diff --git a/src/Mechanical/TranslationalModelica/TranslationalModelica.jl b/src/Mechanical/TranslationalModelica/TranslationalModelica.jl index fd3ad41a1..f13d7a1c1 100644 --- a/src/Mechanical/TranslationalModelica/TranslationalModelica.jl +++ b/src/Mechanical/TranslationalModelica/TranslationalModelica.jl @@ -3,8 +3,8 @@ Library to model 1-dimensional, translational mechanical components. """ module TranslationalModelica -using ModelingToolkit, Symbolics, IfElse -using ModelingToolkit: t_nounits as t, D_nounits as D +using ModelingToolkitBase, Symbolics, IfElse +using ModelingToolkitBase: t_nounits as t, D_nounits as D using ...Blocks: RealInput, RealOutput export Flange diff --git a/src/Mechanical/TranslationalModelica/components.jl b/src/Mechanical/TranslationalModelica/components.jl index e401270ab..cefb0bfca 100644 --- a/src/Mechanical/TranslationalModelica/components.jl +++ b/src/Mechanical/TranslationalModelica/components.jl @@ -11,18 +11,23 @@ Flange fixed in housing at a given position. - `flange: 1-dim. translational flange` """ -@mtkmodel Fixed begin - @parameters begin - s0 = 0 +@component function Fixed(; name, s0 = 0) + pars = @parameters begin + s0 = s0 end - @components begin + systems = @named begin flange = Flange() end - @equations begin - flange.s ~ s0 + vars = @variables begin end + + equations = Equation[ + flange.s ~ s0 + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -43,20 +48,30 @@ Sliding mass with inertia - `flange: 1-dim. translational flange of mass` """ -@mtkmodel Mass begin - @parameters begin - m = 0.0, [description = "Mass of sliding mass [kg]"] +@component function Mass(; name, m = 0.0, s = nothing, v = nothing, a = nothing) + @named pr = PartialRigid(; L = 0.0, s) + @unpack flange_a, flange_b, s = pr + + pars = @parameters begin + m = m, [description = "Mass of sliding mass [kg]"] end - @variables begin - v(t), [description = "Absolute linear velocity of sliding mass [m/s]"] - a(t), [description = "Absolute linear acceleration of sliding mass [m/s^2]"] + + systems = @named begin end - @extend flange_a, flange_b, s = pr = PartialRigid(; L = 0.0, s) - @equations begin - v ~ D(s) - a ~ D(v) - m * a ~ flange_a.f + flange_b.f + + vars = @variables begin + v(t) = v, [description = "Absolute linear velocity of sliding mass [m/s]"] + a(t) = a, [description = "Absolute linear acceleration of sliding mass [m/s^2]"] end + + equations = Equation[ + v ~ D(s), + a ~ D(v), + m * a ~ flange_a.f + flange_b.f + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, pr) end """ @@ -74,16 +89,27 @@ Linear 1D translational spring - `flange_a: 1-dim. translational flange on one side of spring` - `flange_b: 1-dim. translational flange on opposite side of spring` #default function """ -@mtkmodel Spring begin - @extend flange_a, flange_b, s_rel, f = pc = PartialCompliant() - @parameters begin - c = 0.0, [description = "Spring constant [N/m]"] - s_rel0 = 0.0, [description = "Unstretched spring length [m]"] +@component function Spring(; name, c = 0.0, s_rel0 = 0.0) + @named pc = PartialCompliant() + @unpack flange_a, flange_b, s_rel, f = pc + + pars = @parameters begin + c = c, [description = "Spring constant [N/m]"] + s_rel0 = s_rel0, [description = "Unstretched spring length [m]"] end - @equations begin - f ~ c * (s_rel - s_rel0) + systems = @named begin + end + + vars = @variables begin end + + equations = Equation[ + f ~ c * (s_rel - s_rel0) + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, pc) end """ @@ -100,18 +126,28 @@ Linear 1D translational damper - `flange_a: 1-dim. translational flange on one side of damper` - `flange_b: 1-dim. translational flange on opposite side of damper` """ -@mtkmodel Damper begin - @extend flange_a, flange_b, v_rel, f = pc = PartialCompliantWithRelativeStates() - @parameters begin - d = 0.0, [description = "Damping constant [Ns/m]"] +@component function Damper(; name, d = 0.0, lossPower = nothing) + @named pc = PartialCompliantWithRelativeStates() + @unpack flange_a, flange_b, v_rel, f = pc + + pars = @parameters begin + d = d, [description = "Damping constant [Ns/m]"] + end + + systems = @named begin end - @variables begin - lossPower(t), [description = "Power dissipated by the damper [W]"] + + vars = @variables begin + lossPower(t) = lossPower, [description = "Power dissipated by the damper [W]"] end - @equations begin - f ~ d * v_rel + + equations = Equation[ + f ~ d * v_rel, lossPower ~ f * v_rel - end + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, pc) end """ @@ -132,18 +168,28 @@ Linear 1D translational spring and damper in parallel - `lossPower`: [W] Power dissipated by the damper - `f`: [N] Total force """ -@mtkmodel SpringDamper begin - @extend flange_a, flange_b, s_rel, v_rel, f = pc = PartialCompliantWithRelativeStates() - @parameters begin - d = 0.0, [description = "Damping constant [Ns/m]"] - c = 0.0, [description = "Spring constant [N/m]"] - s_rel0 = 0.0, [description = "Unstretched spring length [m]"] +@component function SpringDamper(; name, c = 0.0, d = 0.0, s_rel0 = 0.0, lossPower = nothing) + @named pc = PartialCompliantWithRelativeStates() + @unpack flange_a, flange_b, s_rel, v_rel, f = pc + + pars = @parameters begin + d = d, [description = "Damping constant [Ns/m]"] + c = c, [description = "Spring constant [N/m]"] + s_rel0 = s_rel0, [description = "Unstretched spring length [m]"] end - @variables begin - lossPower(t), [description = "Power dissipated by the damper [W]"] + + systems = @named begin end - @equations begin - f ~ c * (s_rel - s_rel0) + d * v_rel - lossPower ~ d * v_rel^2 + + vars = @variables begin + lossPower(t) = lossPower, [description = "Power dissipated by the damper [W]"] end + + equations = Equation[ + f ~ c * (s_rel - s_rel0) + d * v_rel, + lossPower ~ d * v_rel^2 + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, pc) end diff --git a/src/Mechanical/TranslationalModelica/sources.jl b/src/Mechanical/TranslationalModelica/sources.jl index f3ce5645c..7223f2728 100644 --- a/src/Mechanical/TranslationalModelica/sources.jl +++ b/src/Mechanical/TranslationalModelica/sources.jl @@ -3,15 +3,26 @@ Input signal acting as external force on a flange """ -@mtkmodel Force begin - @extend (flange,) = partial_element = PartialElementaryOneFlangeAndSupport2(; - use_support = false) - @components begin - f = RealInput() # Accelerating force acting at flange (= -flange.tau) +@component function Force(; name, use_support = false) + @named partial_element = PartialElementaryOneFlangeAndSupport2(; use_support) + @unpack flange = partial_element + + pars = @parameters begin end - @equations begin - flange.f ~ -f.u + + systems = @named begin + f = RealInput() + end + + vars = @variables begin end + + equations = Equation[ + flange.f ~ -f.u + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, partial_element) end """ @@ -26,33 +37,41 @@ The input signal `s_ref` defines the reference position in [m]. Flange flange is The input signal can be provided from one of the signal generator blocks of the block library `Blocks.Sources`. """ -@mtkmodel Position begin - @extend (s,) = ptf = PartialElementaryOneFlangeAndSupport2() - @structural_parameters begin - exact = false - end - @parameters begin - f_crit = 50 - end - @variables begin - v(t) - a(t) +@component function Position(; name, exact = false, f_crit = 50, v = nothing, a = nothing) + @named ptf = PartialElementaryOneFlangeAndSupport2() + @unpack s = ptf + + pars = @parameters begin + f_crit = f_crit end - @components begin + + w_crit = 2π * f_crit + af = 1.3617 + bf = 0.6180 + + systems = @named begin s_ref = RealInput() end - begin - w_crit = 2π * f_crit - af = 1.3617 - bf = 0.6180 + + vars = @variables begin + v(t) = v + a(t) = a end - @equations begin - if exact - s ~ s_ref.u - else - a ~ ((s_ref.u - s) * w_crit - af * v) * (w_crit / bf) - end - v ~ D(s) - a ~ D(v) + + equations = if exact + Equation[ + s ~ s_ref.u, + v ~ D(s), + a ~ D(v) + ] + else + Equation[ + a ~ ((s_ref.u - s) * w_crit - af * v) * (w_crit / bf), + v ~ D(s), + a ~ D(v) + ] end + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, ptf) end diff --git a/src/Mechanical/TranslationalModelica/utils.jl b/src/Mechanical/TranslationalModelica/utils.jl index 6911485cf..a649fd65d 100644 --- a/src/Mechanical/TranslationalModelica/utils.jl +++ b/src/Mechanical/TranslationalModelica/utils.jl @@ -1,6 +1,9 @@ -@connector Flange begin - s(t) - f(t), [connect = Flow] +@connector function Flange(; name, s = nothing, f = nothing) + vars = @variables begin + s(t) = s + f(t) = f, [connect = Flow] + end + System(Equation[], t, vars, []; name) end Base.@doc """ Flange(;name) @@ -12,9 +15,12 @@ Base.@doc """ - `f`: [N] Cut force into the flange """ Flange -@connector Support begin - s(t) - f(t), [connect = Flow] +@connector function Support(; name, s = nothing, f = nothing) + vars = @variables begin + s(t) = s + f(t) = f, [connect = Flow] + end + System(Equation[], t, vars, []; name) end Base.@doc """ Support(;name) @@ -26,11 +32,21 @@ Support/housing 1-dim. translational flange. - `f`: [N] Cut force into the flange """ Support -@mtkmodel PartialTwoFlanges begin - @components begin - flange_a = Flange() # (left) driving flange (flange axis directed into cut plane, e. g. from left to right) - flange_b = Flange() # (right) driven flange (flange axis directed out of cut plane) +@component function PartialTwoFlanges(; name) + pars = @parameters begin end + + systems = @named begin + flange_a = Flange() + flange_b = Flange() + end + + vars = @variables begin + end + + equations = Equation[] + + return System(equations, t, vars, pars; name, systems) end """ @@ -43,18 +59,29 @@ Partial model for the compliant connection of two translational 1-dim. flanges. - `s_rel`: [m] Relative distance (= flange_b.s - flange_a.s). It accepts an initial value, which defaults to 0.0. - `f`: [N] Force between flanges (= flange_b.f). It accepts an initial value, which defaults to 0.0. """ -@mtkmodel PartialCompliant begin - @extend (flange_a, flange_b) = pt = PartialTwoFlanges() - @variables begin - s_rel(t), [description = "Relative distance between flanges", guess = 0.0] - f(t), [description = "Force between flanges", guess = 0.0] +@component function PartialCompliant(; name, s_rel = nothing, f = nothing) + @named pt = PartialTwoFlanges() + @unpack flange_a, flange_b = pt + + pars = @parameters begin end - @equations begin - s_rel ~ flange_b.s - flange_a.s - flange_b.f ~ +f - flange_a.f ~ -f + systems = @named begin + end + + vars = @variables begin + s_rel(t) = s_rel, [description = "Relative distance between flanges", guess = 0.0] + f(t) = f, [description = "Force between flanges", guess = 0.0] end + + equations = Equation[ + s_rel ~ flange_b.s - flange_a.s, + flange_b.f ~ +f, + flange_a.f ~ -f + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, pt) end """ @@ -68,20 +95,31 @@ Partial model for the compliant connection of two translational 1-dim. flanges. - `v_rel`: [m/s] Relative linear velocity (= der(s_rel)). It accepts an initial value, which defaults to 0.0. - `f`: [N] Force between flanges (= flange_b.f). It accepts an initial value, which defaults to 0.0. """ -@mtkmodel PartialCompliantWithRelativeStates begin - @extend flange_a, flange_b = pt = PartialTwoFlanges() - @variables begin - s_rel(t), [description = "Relative distance between flanges"] - v_rel(t), [description = "Relative linear velocity))"] - f(t), [description = "Forces between flanges"] - end - - @equations begin - s_rel ~ flange_b.s - flange_a.s - v_rel ~ D(s_rel) - flange_b.f ~ f - flange_a.f ~ -f +@component function PartialCompliantWithRelativeStates(; name, s_rel = nothing, v_rel = nothing, f = nothing) + @named pt = PartialTwoFlanges() + @unpack flange_a, flange_b = pt + + pars = @parameters begin + end + + systems = @named begin + end + + vars = @variables begin + s_rel(t) = s_rel, [description = "Relative distance between flanges"] + v_rel(t) = v_rel, [description = "Relative linear velocity))"] + f(t) = f, [description = "Forces between flanges"] end + + equations = Equation[ + s_rel ~ flange_b.s - flange_a.s, + v_rel ~ D(s_rel), + flange_b.f ~ f, + flange_a.f ~ -f + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, pt) end """ @@ -146,16 +184,26 @@ function PartialElementaryTwoFlangesAndSupport2(; name, use_support = false) end end -@mtkmodel PartialRigid begin - @extend flange_a, flange_b = ptf = PartialTwoFlanges() - @variables begin - s(t), [description = "Absolute position of center of component"] +@component function PartialRigid(; name, L = 0.0, s = nothing) + @named ptf = PartialTwoFlanges() + @unpack flange_a, flange_b = ptf + + pars = @parameters begin + L = L, [description = "Length of component, from left flange to right flange"] end - @parameters begin - L = 0.0, [description = "Length of component, from left flange to right flange"] + + systems = @named begin end - @equations begin - flange_a.s ~ s - L / 2 - flange_b.s ~ s + L / 2 + + vars = @variables begin + s(t) = s, [description = "Absolute position of center of component"] end + + equations = Equation[ + flange_a.s ~ s - L / 2, + flange_b.s ~ s + L / 2 + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, ptf) end diff --git a/src/Mechanical/TranslationalPosition/TranslationalPosition.jl b/src/Mechanical/TranslationalPosition/TranslationalPosition.jl index c304d6cec..d27c082f0 100644 --- a/src/Mechanical/TranslationalPosition/TranslationalPosition.jl +++ b/src/Mechanical/TranslationalPosition/TranslationalPosition.jl @@ -3,8 +3,8 @@ Library to model 1-dimensional, translational mechanical components. """ module TranslationalPosition -using ModelingToolkit, Symbolics, IfElse -using ModelingToolkit: t_nounits as t, D_nounits as D +using ModelingToolkitBase, Symbolics, IfElse +using ModelingToolkitBase: t_nounits as t, D_nounits as D using ...Blocks: RealInput, RealOutput export Flange diff --git a/src/Mechanical/TranslationalPosition/components.jl b/src/Mechanical/TranslationalPosition/components.jl index 4ed4bdf9e..db897264b 100644 --- a/src/Mechanical/TranslationalPosition/components.jl +++ b/src/Mechanical/TranslationalPosition/components.jl @@ -11,16 +11,23 @@ Flange fixed in housing at a given position. - `flange: 1-dim. translational flange` """ -@mtkmodel Fixed begin - @parameters begin - s_0 = 0 +@component function Fixed(; name, s_0 = 0) + pars = @parameters begin + s_0 = s_0 end - @components begin + + systems = @named begin flange = Flange() end - @equations begin - flange.s ~ s_0 + + vars = @variables begin end + + equations = Equation[ + flange.s ~ s_0 + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -43,28 +50,33 @@ Sliding mass with inertia - `flange: 1-dim. translational flange of mass` """ -@mtkmodel Mass begin - @parameters begin - m - end - @variables begin - s(t) - v(t) - f(t) +@component function Mass(; name, m = nothing, s = nothing, v = nothing, f = nothing) + pars = @parameters begin + m = m end - @components begin + + systems = @named begin flange = Flange() end - @equations begin - flange.s ~ s - flange.f ~ f - D(s) ~ v - D(v) ~ f / m + + vars = @variables begin + s(t) = s + v(t) = v + f(t) = f end + + equations = Equation[ + flange.s ~ s, + flange.f ~ f, + D(s) ~ v, + D(v) ~ f / m + ] + + return System(equations, t, vars, pars; name, systems) end const REL = Val(:relative) -@component function Spring(::Val{:relative}; name, k, va = 0.0, vb = 0.0, +@component function Spring(::Val{:relative}; name, k = nothing, va = 0.0, vb = 0.0, delta_s = 0) pars = @parameters begin k = k @@ -109,12 +121,12 @@ Linear 1D translational spring - `flange_a: 1-dim. translational flange on one side of spring` - `flange_b: 1-dim. translational flange on opposite side of spring` #default function """ -function Spring(; name, k, l = 0) +function Spring(; name, k = nothing, l = 0) Spring(ABS; name, k, l) end #default function @component function Spring(::Val{:absolute}; - name, k, l = 0) + name, k = nothing, l = 0) pars = @parameters begin k = k l = l @@ -150,26 +162,29 @@ Linear 1D translational damper - `flange_a: 1-dim. translational flange on one side of damper` - `flange_b: 1-dim. translational flange on opposite side of damper` """ -@mtkmodel Damper begin - @parameters begin - d - end - @variables begin - va(t) - vb(t) - f(t) +@component function Damper(; name, d = nothing, va = nothing, vb = nothing, f = nothing) + pars = @parameters begin + d = d end - @components begin + systems = @named begin flange_a = Flange() flange_b = Flange() end - @equations begin - D(flange_a.s) ~ va - D(flange_b.s) ~ vb - f ~ (va - vb) * d - flange_a.f ~ +f - flange_b.f ~ -f + vars = @variables begin + va(t) = va + vb(t) = vb + f(t) = f end + + equations = Equation[ + D(flange_a.s) ~ va, + D(flange_b.s) ~ vb, + f ~ (va - vb) * d, + flange_a.f ~ +f, + flange_b.f ~ -f + ] + + return System(equations, t, vars, pars; name, systems) end diff --git a/src/Mechanical/TranslationalPosition/sensors.jl b/src/Mechanical/TranslationalPosition/sensors.jl index 8e264dbb1..801340f02 100644 --- a/src/Mechanical/TranslationalPosition/sensors.jl +++ b/src/Mechanical/TranslationalPosition/sensors.jl @@ -9,18 +9,26 @@ Linear 1D force sensor, measures the force between two flanges. - `flange_b`: 1-dim. translational flange - `output`: real output """ -@mtkmodel ForceSensor begin - @components begin +@component function ForceSensor(; name) + pars = @parameters begin + end + + systems = @named begin flange_a = Flange() flange_b = Flange() output = RealOutput() end - @equations begin - flange_a.s ~ flange_b.s - flange_a.f + flange_b.f ~ 0.0 - output.u ~ flange_a.f + vars = @variables begin end + + equations = Equation[ + flange_a.s ~ flange_b.s, + flange_a.f + flange_b.f ~ 0.0, + output.u ~ flange_a.f + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -37,16 +45,24 @@ Linear 1D position sensor. - `flange`: 1-dim. translational flange - `output`: real output """ -@mtkmodel PositionSensor begin - @components begin +@component function PositionSensor(; name) + pars = @parameters begin + end + + systems = @named begin flange = Flange() output = RealOutput() end - @equations begin - output.u ~ flange.s - flange.f ~ 0.0 + vars = @variables begin end + + equations = Equation[ + output.u ~ flange.s, + flange.f ~ 0.0 + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -63,19 +79,24 @@ Linear 1D acceleration sensor. - `flange`: 1-dim. translational flange - `output`: real output """ -@mtkmodel AccelerationSensor begin - @components begin +@component function AccelerationSensor(; name, a = nothing) + pars = @parameters begin + end + + systems = @named begin flange = Flange() output = RealOutput() end - @variables begin - a(t) + vars = @variables begin + a(t) = a end - @equations begin - a ~ D(D(flange.s)) - output.u ~ a + equations = Equation[ + a ~ D(D(flange.s)), + output.u ~ a, flange.f ~ 0.0 - end + ] + + return System(equations, t, vars, pars; name, systems) end diff --git a/src/Mechanical/TranslationalPosition/sources.jl b/src/Mechanical/TranslationalPosition/sources.jl index 7c7dacaa8..f77f873ff 100644 --- a/src/Mechanical/TranslationalPosition/sources.jl +++ b/src/Mechanical/TranslationalPosition/sources.jl @@ -3,16 +3,25 @@ Input signal acting as external force on a flange """ -@mtkmodel Force begin - @extend (flange,) = partial_element = PartialElementaryOneFlangeAndSupport2(; - use_support = false) - @parameters begin - s = 0 +@component function Force(; name, use_support = false, s = 0) + @named partial_element = PartialElementaryOneFlangeAndSupport2(; use_support) + @unpack flange = partial_element + + pars = @parameters begin + s = s end - @components begin + + systems = @named begin f = RealInput() end - @equations begin - flange.f ~ -f.u + + vars = @variables begin end + + equations = Equation[ + flange.f ~ -f.u + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, partial_element) end diff --git a/src/Mechanical/TranslationalPosition/utils.jl b/src/Mechanical/TranslationalPosition/utils.jl index 897a7005f..7736928a6 100644 --- a/src/Mechanical/TranslationalPosition/utils.jl +++ b/src/Mechanical/TranslationalPosition/utils.jl @@ -1,6 +1,9 @@ -@connector Flange begin - s(t) - f(t), [connect = Flow] +@connector function Flange(; name, s = nothing, f = nothing) + vars = @variables begin + s(t) = s + f(t) = f, [connect = Flow] + end + System(Equation[], t, vars, []; name) end Base.@doc """ Flange(;name) @@ -12,9 +15,12 @@ Base.@doc """ - `f`: [N] Cut force into the flange """ Flange -@connector Support begin - s(t) - f(t), [connect = Flow] +@connector function Support(; name, s = nothing, f = nothing) + vars = @variables begin + s(t) = s + f(t) = f, [connect = Flow] + end + System(Equation[], t, vars, []; name) end Base.@doc """ Support(;name) @@ -36,24 +42,31 @@ Partial model for the compliant connection of two translational 1-dim. flanges. - `s_rel`: [m] Relative distance (= flange_b.s - flange_a.s). It accepts an initial value, which defaults to 0.0. - `f`: [N] Force between flanges (= flange_b.f). It accepts an initial value, which defaults to 0.0. """ -@mtkmodel PartialCompliant begin#(; name, s_rel_start = 0.0, f_start = 0.0) - @components begin +@component function PartialCompliant(; name, v_a = nothing, v_b = nothing, s_rel = nothing, f = nothing) + pars = @parameters begin + end + + systems = @named begin flange_a = Flange() flange_b = Flange() end - @variables begin - v_a(t) - v_b(t) - s_rel(t) - f(t) + + vars = @variables begin + v_a(t) = v_a + v_b(t) = v_b + s_rel(t) = s_rel + f(t) = f end - @equations begin - D(flange_a.s) ~ v_a - D(flange_b.s) ~ v_b - D(s_rel) ~ v_b - v_a - flange_b.f ~ +f + + equations = Equation[ + D(flange_a.s) ~ v_a, + D(flange_b.s) ~ v_b, + D(s_rel) ~ v_b - v_a, + flange_b.f ~ +f, flange_a.f ~ -f - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -75,20 +88,27 @@ Partial model for the compliant connection of two translational 1-dim. flanges. - `a_rel`: [m/s²] Relative linear acceleration (= der(v_rel)) - `f`: [N] Force between flanges (= flange_b.f) """ -@mtkmodel PartialCompliantWithRelativeStates begin - @components begin +@component function PartialCompliantWithRelativeStates(; name, delta_s = nothing, f = nothing) + pars = @parameters begin + end + + systems = @named begin flange_a = Flange() flange_b = Flange() end - @variables begin - delta_s(t) - f(t) + + vars = @variables begin + delta_s(t) = delta_s + f(t) = f end - @equations begin - delta_s ~ flange_a.s - flange_b.s - flange_a.f ~ +f + + equations = Equation[ + delta_s ~ flange_a.s - flange_b.s, + flange_a.f ~ +f, flange_b.f ~ -f - end + ] + + return System(equations, t, vars, pars; name, systems) end """ diff --git a/src/Thermal/HeatTransfer/ideal_components.jl b/src/Thermal/HeatTransfer/ideal_components.jl index 890382ca3..7d42e8a1c 100644 --- a/src/Thermal/HeatTransfer/ideal_components.jl +++ b/src/Thermal/HeatTransfer/ideal_components.jl @@ -16,23 +16,27 @@ Lumped thermal element storing heat - `C`: [`J/K`] Heat capacity of element (= cp*m) """ -@mtkmodel HeatCapacitor begin - @components begin - port = HeatPort() +@component function HeatCapacitor(; C = nothing, T = 273.15 + 20, name) + pars = @parameters begin + C = C, [description = "Heat capacity of element"] end - @parameters begin - C, [description = "Heat capacity of element"] + + systems = @named begin + port = HeatPort() end - @variables begin - T(t), [guess = 273.15 + 20] + + vars = @variables begin + T(t) = T, [guess = 273.15 + 20] der_T(t), [guess = 0.0] end - @equations begin - T ~ port.T - der_T ~ port.Q_flow / C + equations = Equation[ + T ~ port.T, + der_T ~ port.Q_flow / C, D(T) ~ der_T - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -53,14 +57,26 @@ see [`Element1D`](@ref) - `G`: [`W/K`] Constant thermal conductance of material """ -@mtkmodel ThermalConductor begin - @extend Q_flow, dT = element1d = Element1D() - @parameters begin - G +@component function ThermalConductor(; G = nothing, name) + @named element1d = Element1D() + @unpack Q_flow, dT = element1d + + pars = @parameters begin + G = G end - @equations begin - Q_flow ~ G * dT + + systems = @named begin + end + + vars = @variables begin end + + equations = Equation[ + Q_flow ~ G * dT + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, element1d) end """ @@ -82,14 +98,26 @@ Lumped thermal element transporting heat without storing it. - `R`: [`K/W`] Constant thermal resistance of material """ -@mtkmodel ThermalResistor begin - @extend Q_flow, dT = element1d = Element1D() - @parameters begin - R +@component function ThermalResistor(; R = nothing, name) + @named element1d = Element1D() + @unpack Q_flow, dT = element1d + + pars = @parameters begin + R = R end - @equations begin - dT ~ R * Q_flow + + systems = @named begin + end + + vars = @variables begin end + + equations = Equation[ + dT ~ R * Q_flow + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, element1d) end """ @@ -111,14 +139,26 @@ Lumped thermal element for heat convection. - `G`: [W/K] Convective thermal conductance """ -@mtkmodel ConvectiveConductor begin - @extend Q_flow, dT = convective_element1d = ConvectiveElement1D() - @parameters begin - G +@component function ConvectiveConductor(; G = nothing, name) + @named convective_element1d = ConvectiveElement1D() + @unpack Q_flow, dT = convective_element1d + + pars = @parameters begin + G = G end - @equations begin - Q_flow ~ G * dT + + systems = @named begin end + + vars = @variables begin + end + + equations = Equation[ + Q_flow ~ G * dT + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, convective_element1d) end """ @@ -140,14 +180,26 @@ Lumped thermal element for heat convection. - `R`: [`K/W`] Constant thermal resistance of material """ -@mtkmodel ConvectiveResistor begin - @extend Q_flow, dT = convective_element1d = ConvectiveElement1D() - @parameters begin - R +@component function ConvectiveResistor(; R = nothing, name) + @named convective_element1d = ConvectiveElement1D() + @unpack Q_flow, dT = convective_element1d + + pars = @parameters begin + R = R end - @equations begin - dT ~ R * Q_flow + + systems = @named begin + end + + vars = @variables begin end + + equations = Equation[ + dT ~ R * Q_flow + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, convective_element1d) end """ @@ -169,18 +221,28 @@ Lumped thermal element for radiation heat transfer. - `G`: [m^2] Net radiation conductance between two surfaces # Stefan-Boltzmann constant TODO: extract into physical constants module or use existing one """ -@mtkmodel BodyRadiation begin - begin - sigma = 5.6703744191844294e-8 # Stefan-Boltzmann constant TODO: extract into physical constants module or use existing one +@component function BodyRadiation(; G = nothing, name) + sigma = 5.6703744191844294e-8 # Stefan-Boltzmann constant TODO: extract into physical constants module or use existing one + + @named element1d = Element1D() + @unpack Q_flow, dT, port_a, port_b = element1d + + pars = @parameters begin + G = G end - @extend Q_flow, dT, port_a, port_b = element1d = Element1D() - @parameters begin - G + systems = @named begin end - @equations begin - Q_flow ~ G * sigma * (port_a.T^4 - port_b.T^4) + + vars = @variables begin end + + equations = Equation[ + Q_flow ~ G * sigma * (port_a.T^4 - port_b.T^4) + ] + + sys = System(equations, t, vars, pars; name, systems) + return extend(sys, element1d) end """ @@ -201,19 +263,27 @@ This is a model to collect the heat flows from `m` heatports to one single heatp - `m`: Number of heat ports (e.g. m=2: `port_a1`, `port_a2`) """ -@mtkmodel ThermalCollector begin - @structural_parameters begin - m::Integer = 1 +@component function ThermalCollector(; m::Integer = 1, name) + pars = @parameters begin + end + + port_a = @named begin + port_a[1:m] = HeatPort() end - @components begin - port_a = [HeatPort(name = Symbol(:port_a, i)) for i in 1:m] + systems = @named begin port_b = HeatPort() end + append!(systems, port_a) - @equations begin - port_b.Q_flow + sum(k -> k.Q_flow, port_a) ~ 0 - port_b.T ~ port_a[1].T - [port_a[i].T ~ port_a[i + 1].T for i in 1:(m - 1)] + vars = @variables begin end + + equations = Equation[ + port_b.Q_flow + sum(k -> k.Q_flow, port_a) ~ 0, + port_b.T ~ port_a[1].T, + [port_a[i].T ~ port_a[i + 1].T for i in 1:(m - 1)]... + ] + + return System(equations, t, vars, pars; name, systems) end diff --git a/src/Thermal/HeatTransfer/sensors.jl b/src/Thermal/HeatTransfer/sensors.jl index afc4ed441..7d1067d1a 100644 --- a/src/Thermal/HeatTransfer/sensors.jl +++ b/src/Thermal/HeatTransfer/sensors.jl @@ -12,15 +12,24 @@ lags are associated with this sensor model. - `port`: [HeatPort](@ref) Thermal port from which sensor information shall be measured - `T`: [RealOutput](@ref) [K] Absolute temperature of port """ -@mtkmodel TemperatureSensor begin - @components begin +@component function TemperatureSensor(; name) + pars = @parameters begin + end + + systems = @named begin port = HeatPort() T = RealOutput() end - @equations begin - T.u ~ port.T - port.Q_flow ~ 0 + + vars = @variables begin end + + equations = Equation[ + T.u ~ port.T, + port.Q_flow ~ 0 + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -37,17 +46,26 @@ output signal in kelvin. - `port_b`: [HeatPort](@ref) Thermal port from which sensor information shall be measured - `T`: [RealOutput](@ref) [K] Relative temperature `a.T - b.T` """ -@mtkmodel RelativeTemperatureSensor begin - @components begin +@component function RelativeTemperatureSensor(; name) + pars = @parameters begin + end + + systems = @named begin port_a = HeatPort() port_b = HeatPort() T = RealOutput() end - @equations begin - T.u ~ port_a.T - port_b.T - port_a.Q_flow ~ 0 - port_b.Q_flow ~ 0 + + vars = @variables begin end + + equations = Equation[ + T.u ~ port_a.T - port_b.T, + port_a.Q_flow ~ 0, + port_b.Q_flow ~ 0 + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -66,15 +84,24 @@ The output signal is positive, if the heat flows from `port_a` to `port_b`. - `port_b`: [HeatPort](@ref) Thermal port from which sensor information shall be measured - `Q_flow`: [RealOutput](@ref) [W] Heat flow from `port_a` to `port_b` """ -@mtkmodel HeatFlowSensor begin - @components begin +@component function HeatFlowSensor(; name) + pars = @parameters begin + end + + systems = @named begin port_a = HeatPort() port_b = HeatPort() Q_flow = RealOutput() end - @equations begin - port_a.T ~ port_b.T - port_a.Q_flow + port_b.Q_flow ~ 0 - Q_flow.u ~ port_a.Q_flow + + vars = @variables begin end + + equations = Equation[ + port_a.T ~ port_b.T, + port_a.Q_flow + port_b.Q_flow ~ 0, + Q_flow.u ~ port_a.Q_flow + ] + + return System(equations, t, vars, pars; name, systems) end diff --git a/src/Thermal/HeatTransfer/sources.jl b/src/Thermal/HeatTransfer/sources.jl index cdd279479..9e5a800f2 100644 --- a/src/Thermal/HeatTransfer/sources.jl +++ b/src/Thermal/HeatTransfer/sources.jl @@ -17,21 +17,27 @@ the component FixedHeatFlow is connected, if parameter `Q_flow` is positive. - `T_ref`: [K] Reference temperature - `alpha`: [1/K] Temperature coefficient of heat flow rate """ -@mtkmodel FixedHeatFlow begin - @parameters begin - Q_flow = 1.0, [description = "Fixed heat flow rate at port"] - T_ref = 293.15, [description = "Reference temperature"] - alpha = 0.0, [description = "Temperature coefficient of heat flow rate"] +@component function FixedHeatFlow(; Q_flow = 1.0, T_ref = 293.15, alpha = 0.0, name) + pars = @parameters begin + Q_flow = Q_flow, [description = "Fixed heat flow rate at port"] + T_ref = T_ref, [description = "Reference temperature"] + alpha = alpha, [description = "Temperature coefficient of heat flow rate"] end - @components begin + + systems = @named begin port = HeatPort() end - @equations begin + vars = @variables begin + end + + equations = Equation[ port.Q_flow ~ ifelse(alpha == 0.0, -Q_flow, # Simplified equation when alpha is 0 -Q_flow * (1 + alpha * (port.T - T_ref))) - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -49,16 +55,23 @@ This model defines a fixed temperature `T` at its port in kelvin, i.e., it defin - `T`: [K] Fixed temperature boundary condition """ -@mtkmodel FixedTemperature begin - @components begin +@component function FixedTemperature(; T = nothing, name) + pars = @parameters begin + T = T, [description = "Fixed temperature boundary condition"] + end + + systems = @named begin port = HeatPort() end - @parameters begin - T, [description = "Fixed temperature boundary condition"] + + vars = @variables begin end - @equations begin + + equations = Equation[ port.T ~ T - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -82,18 +95,25 @@ dependent losses (which are given a reference temperature T_ref). - `T_ref`: [K] Reference temperature - `alpha`: [1/K] Temperature coefficient of heat flow rate """ -@mtkmodel PrescribedHeatFlow begin - @parameters begin - T_ref = 293.15, [description = "Reference temperature"] - alpha = 0.0, [description = "Temperature coefficient of heat flow rate"] +@component function PrescribedHeatFlow(; T_ref = 293.15, alpha = 0.0, name) + pars = @parameters begin + T_ref = T_ref, [description = "Reference temperature"] + alpha = alpha, [description = "Temperature coefficient of heat flow rate"] end - @components begin + + systems = @named begin port = HeatPort() Q_flow = RealInput() end - @equations begin - port.Q_flow ~ -Q_flow.u * (1 + alpha * (port.T - T_ref)) + + vars = @variables begin end + + equations = Equation[ + port.Q_flow ~ -Q_flow.u * (1 + alpha * (port.T - T_ref)) + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -110,12 +130,21 @@ the temperature at the specified value. - `port` - `RealInput` `T` input for the temperature """ -@mtkmodel PrescribedTemperature begin - @components begin +@component function PrescribedTemperature(; name) + pars = @parameters begin + end + + systems = @named begin port = HeatPort() T = RealInput() end - @equations begin - port.T ~ T.u + + vars = @variables begin end + + equations = Equation[ + port.T ~ T.u + ] + + return System(equations, t, vars, pars; name, systems) end diff --git a/src/Thermal/Thermal.jl b/src/Thermal/Thermal.jl index a7ad12c07..8139e5efe 100644 --- a/src/Thermal/Thermal.jl +++ b/src/Thermal/Thermal.jl @@ -2,8 +2,8 @@ Library of thermal system components to model heat transfer. """ module Thermal -using ModelingToolkit, Symbolics, IfElse -using ModelingToolkit: t_nounits as t, D_nounits as D +using ModelingToolkitBase, Symbolics, IfElse +using ModelingToolkitBase: t_nounits as t, D_nounits as D using ...Blocks: RealInput, RealOutput export HeatPort, Element1D diff --git a/src/Thermal/utils.jl b/src/Thermal/utils.jl index 74e9f3b42..8ba3bb6a2 100644 --- a/src/Thermal/utils.jl +++ b/src/Thermal/utils.jl @@ -1,13 +1,14 @@ -@connector HeatPort begin - @parameters begin +@connector function HeatPort(; name, T_guess = 273.15 + 20, Q_flow_guess = 0.0, T = nothing, Q_flow = nothing) + pars = @parameters begin T_guess = 273.15 + 20 Q_flow_guess = 0.0 end - @variables begin - T(t), [guess = T_guess] - Q_flow(t), [guess = Q_flow_guess, connect = Flow] + vars = @variables begin + T(t) = T, [guess = T_guess] + Q_flow(t) = Q_flow, [guess = Q_flow_guess, connect = Flow] end + System(Equation[], t, vars, pars; name) end Base.@doc """ HeatPort(; T = nothing, T_guess = 273.15 + 20, Q_flow = nothing, Q_flow_guess = 0.0, name) @@ -39,20 +40,27 @@ flow rate through the element from `port_a` to `port_b`, `Q_flow`. `port_a` `port_b` """ -@mtkmodel Element1D begin - @components begin +@component function Element1D(; dT = 0.0, Q_flow = 0.0, name) + pars = @parameters begin + end + + systems = @named begin port_a = HeatPort() port_b = HeatPort() end - @variables begin - dT(t), [guess = 0.0] - Q_flow(t), [guess = 0.0] + + vars = @variables begin + dT(t) = dT, [guess = 0.0] + Q_flow(t) = Q_flow, [guess = 0.0] end - @equations begin - dT ~ port_a.T - port_b.T - port_a.Q_flow ~ Q_flow + + equations = Equation[ + dT ~ port_a.T - port_b.T, + port_a.Q_flow ~ Q_flow, port_a.Q_flow + port_b.Q_flow ~ 0 - end + ] + + return System(equations, t, vars, pars; name, systems) end """ @@ -73,18 +81,25 @@ flow rate through the element from `solid` to `fluid`, `Q_flow`. `solid` `fluid` """ -@mtkmodel ConvectiveElement1D begin - @components begin +@component function ConvectiveElement1D(; dT = 0.0, Q_flow = 0.0, name) + pars = @parameters begin + end + + systems = @named begin solid = HeatPort() fluid = HeatPort() end - @variables begin - dT(t), [guess = 0.0] - Q_flow(t), [guess = 0.0] + + vars = @variables begin + dT(t) = dT, [guess = 0.0] + Q_flow(t) = Q_flow, [guess = 0.0] end - @equations begin - dT ~ solid.T - fluid.T - solid.Q_flow ~ Q_flow + + equations = Equation[ + dT ~ solid.T - fluid.T, + solid.Q_flow ~ Q_flow, solid.Q_flow + fluid.Q_flow ~ 0 - end + ] + + return System(equations, t, vars, pars; name, systems) end diff --git a/test/Blocks/continuous.jl b/test/Blocks/continuous.jl index 78b7eff50..b5a550af0 100644 --- a/test/Blocks/continuous.jl +++ b/test/Blocks/continuous.jl @@ -1,4 +1,5 @@ using ModelingToolkit, ModelingToolkitStandardLibrary, OrdinaryDiffEq +using SciCompDSL using ModelingToolkitStandardLibrary.Blocks using ModelingToolkit: t_nounits as t using OrdinaryDiffEq: ReturnCode.Success diff --git a/test/Blocks/math.jl b/test/Blocks/math.jl index f37ebf9cb..608d6f5b8 100644 --- a/test/Blocks/math.jl +++ b/test/Blocks/math.jl @@ -1,4 +1,5 @@ using ModelingToolkitStandardLibrary.Blocks +using SciCompDSL using ModelingToolkit, OrdinaryDiffEq, Test using ModelingToolkitStandardLibrary.Blocks: _clamp, _dead_zone using ModelingToolkit: inputs, unbound_inputs, bound_inputs, t_nounits as t diff --git a/test/Blocks/nonlinear.jl b/test/Blocks/nonlinear.jl index d6fb31283..b164f25da 100644 --- a/test/Blocks/nonlinear.jl +++ b/test/Blocks/nonlinear.jl @@ -1,4 +1,5 @@ using ModelingToolkit, OrdinaryDiffEq +using SciCompDSL using ModelingToolkitStandardLibrary.Blocks using ModelingToolkit: t_nounits as t using ModelingToolkitStandardLibrary.Blocks: _dead_zone diff --git a/test/Blocks/sources.jl b/test/Blocks/sources.jl index 752ad08ab..1742dde89 100644 --- a/test/Blocks/sources.jl +++ b/test/Blocks/sources.jl @@ -1,4 +1,5 @@ using ModelingToolkit, ModelingToolkitStandardLibrary, OrdinaryDiffEq +using SciCompDSL using ModelingToolkitStandardLibrary.Blocks using ModelingToolkit: t_nounits as t, D_nounits as D using ModelingToolkitStandardLibrary.Blocks: smooth_sin, smooth_cos, smooth_damped_sin, diff --git a/test/Blocks/test_analysis_points.jl b/test/Blocks/test_analysis_points.jl index 7244c7e4b..18b00a2e1 100644 --- a/test/Blocks/test_analysis_points.jl +++ b/test/Blocks/test_analysis_points.jl @@ -1,4 +1,5 @@ using Test, LinearAlgebra +using SciCompDSL using ModelingToolkit using ModelingToolkitStandardLibrary.Blocks using OrdinaryDiffEq diff --git a/test/Blocks/utils.jl b/test/Blocks/utils.jl index 9880fe091..84145fe66 100644 --- a/test/Blocks/utils.jl +++ b/test/Blocks/utils.jl @@ -1,4 +1,5 @@ using ModelingToolkitStandardLibrary.Blocks +using SciCompDSL using ModelingToolkit using OrdinaryDiffEq using ModelingToolkit: t_nounits as t, D_nounits as D diff --git a/test/Electrical/analog.jl b/test/Electrical/analog.jl index cac7a1dd7..4951f4451 100644 --- a/test/Electrical/analog.jl +++ b/test/Electrical/analog.jl @@ -1,4 +1,5 @@ using ModelingToolkitStandardLibrary.Electrical, ModelingToolkit, OrdinaryDiffEq, Test +using SciCompDSL using ModelingToolkit: t_nounits as t, D_nounits as D using ModelingToolkitStandardLibrary.Blocks: Step, Constant, Sine, Cosine, ExpSine, Ramp, diff --git a/test/Electrical/digital.jl b/test/Electrical/digital.jl index eae00ae2f..0d8c88049 100644 --- a/test/Electrical/digital.jl +++ b/test/Electrical/digital.jl @@ -1,4 +1,5 @@ using ModelingToolkitStandardLibrary.Electrical, ModelingToolkit, OrdinaryDiffEq, Test +using SciCompDSL using ModelingToolkitStandardLibrary.Electrical: _and, _or, _not, _xor using ModelingToolkitStandardLibrary.Electrical: U, X, F0, F1, Z, W, L, H, DC, Uninitialized using ModelingToolkitStandardLibrary.Electrical: AndTable, OrTable, NotTable, XorTable diff --git a/test/Hydraulic/isothermal_compressible.jl b/test/Hydraulic/isothermal_compressible.jl index 407438a8b..b14e7901a 100644 --- a/test/Hydraulic/isothermal_compressible.jl +++ b/test/Hydraulic/isothermal_compressible.jl @@ -1,4 +1,5 @@ using ModelingToolkit, OrdinaryDiffEq, Test +using SciCompDSL using ModelingToolkit: t_nounits as t, D_nounits as D import ModelingToolkitStandardLibrary.Hydraulic.IsothermalCompressible as IC import ModelingToolkitStandardLibrary.Blocks as B diff --git a/test/Magnetic/magnetic.jl b/test/Magnetic/magnetic.jl index 0b356930a..e6e8da787 100644 --- a/test/Magnetic/magnetic.jl +++ b/test/Magnetic/magnetic.jl @@ -1,4 +1,5 @@ using ModelingToolkitStandardLibrary.Magnetic, ModelingToolkit, OrdinaryDiffEq, Test +using SciCompDSL import ModelingToolkitStandardLibrary.Electrical import ModelingToolkitStandardLibrary.Blocks diff --git a/test/Mechanical/multibody.jl b/test/Mechanical/multibody.jl index 9c1f470c4..991e42a8f 100644 --- a/test/Mechanical/multibody.jl +++ b/test/Mechanical/multibody.jl @@ -1,4 +1,5 @@ using ModelingToolkit +using SciCompDSL using ModelingToolkit: t_nounits as t using ModelingToolkitStandardLibrary.Mechanical.MultiBody2D using ModelingToolkitStandardLibrary.Mechanical.TranslationalPosition diff --git a/test/Mechanical/rotational.jl b/test/Mechanical/rotational.jl index b295e2bf1..dece4bec8 100644 --- a/test/Mechanical/rotational.jl +++ b/test/Mechanical/rotational.jl @@ -1,6 +1,7 @@ using ModelingToolkitStandardLibrary.Mechanical.Rotational, ModelingToolkit, OrdinaryDiffEq, Test +using SciCompDSL using ModelingToolkit: t_nounits as t, D_nounits as D import ModelingToolkitStandardLibrary.Blocks using OrdinaryDiffEq: ReturnCode.Success diff --git a/test/Mechanical/translational.jl b/test/Mechanical/translational.jl index 628ec7127..380bed51f 100644 --- a/test/Mechanical/translational.jl +++ b/test/Mechanical/translational.jl @@ -1,4 +1,5 @@ using ModelingToolkit, OrdinaryDiffEq, Test +using SciCompDSL using ModelingToolkit: t_nounits as t, D_nounits as D using ModelingToolkitStandardLibrary.Blocks diff --git a/test/Mechanical/translational_modelica.jl b/test/Mechanical/translational_modelica.jl index d27902742..9b2115b87 100644 --- a/test/Mechanical/translational_modelica.jl +++ b/test/Mechanical/translational_modelica.jl @@ -1,4 +1,5 @@ using ModelingToolkit, OrdinaryDiffEq, Test +using SciCompDSL using ModelingToolkit: t_nounits as t, D_nounits as D using ModelingToolkitStandardLibrary.Blocks: Sine diff --git a/test/Thermal/demo.jl b/test/Thermal/demo.jl index be81c878e..60d4009e8 100644 --- a/test/Thermal/demo.jl +++ b/test/Thermal/demo.jl @@ -1,4 +1,5 @@ using ModelingToolkitStandardLibrary.Thermal, ModelingToolkit, OrdinaryDiffEq, Test +using SciCompDSL using ModelingToolkit: t_nounits as t, D_nounits as D using OrdinaryDiffEq: ReturnCode.Success diff --git a/test/Thermal/motor.jl b/test/Thermal/motor.jl index 3b84ef51d..580ae6a43 100644 --- a/test/Thermal/motor.jl +++ b/test/Thermal/motor.jl @@ -1,4 +1,5 @@ using ModelingToolkit, Test +using SciCompDSL using ModelingToolkitStandardLibrary.Thermal using ModelingToolkitStandardLibrary.Blocks diff --git a/test/Thermal/piston.jl b/test/Thermal/piston.jl index 25e24a181..0466f8bd1 100644 --- a/test/Thermal/piston.jl +++ b/test/Thermal/piston.jl @@ -1,4 +1,5 @@ using ModelingToolkit, Test +using SciCompDSL using ModelingToolkitStandardLibrary.Thermal using ModelingToolkitStandardLibrary.Blocks diff --git a/test/Thermal/thermal.jl b/test/Thermal/thermal.jl index 665bf9a95..155075916 100644 --- a/test/Thermal/thermal.jl +++ b/test/Thermal/thermal.jl @@ -1,4 +1,5 @@ using ModelingToolkitStandardLibrary.Thermal, ModelingToolkit, OrdinaryDiffEq, Test +using SciCompDSL using ModelingToolkit: t_nounits as t, D_nounits as D using ModelingToolkitStandardLibrary.Blocks: Constant, Step using OrdinaryDiffEq: ReturnCode.Success diff --git a/test/chua_circuit.jl b/test/chua_circuit.jl index 552d88966..3b95b31a3 100644 --- a/test/chua_circuit.jl +++ b/test/chua_circuit.jl @@ -1,4 +1,5 @@ using ModelingToolkit +using SciCompDSL using ModelingToolkit: t_nounits as t using ModelingToolkitStandardLibrary.Electrical using ModelingToolkitStandardLibrary.Electrical: OnePort diff --git a/test/multi_domain.jl b/test/multi_domain.jl index afbd40d72..866b9ea31 100644 --- a/test/multi_domain.jl +++ b/test/multi_domain.jl @@ -1,4 +1,5 @@ using ModelingToolkitStandardLibrary.Electrical +using SciCompDSL using ModelingToolkitStandardLibrary.Mechanical.Rotational using ModelingToolkitStandardLibrary.Blocks using ModelingToolkitStandardLibrary.Thermal