diff --git a/Project.toml b/Project.toml index f0b0f9e7..32d4d243 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "ModelingToolkitStandardLibrary" uuid = "16a59e39-deab-5bd0-87e4-056b12336739" -version = "2.29.5" +version = "2.29.6" authors = ["Chris Rackauckas and Julia Computing"] [deps] @@ -34,7 +34,7 @@ SafeTestsets = "0.1" SciCompDSL = "1" SciMLBase = "2, 3" SciMLStructures = "1.7.0" -SciMLTesting = "2.1" +SciMLTesting = "2.4" SymbolicIndexingInterface = "0.3.39" SymbolicUtils = "4.38.1" Symbolics = "7.4.1" diff --git a/docs/make.jl b/docs/make.jl index a2fb0ddf..37009647 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -21,7 +21,6 @@ makedocs( sitename = "ModelingToolkitStandardLibrary.jl", authors = "Julia Computing", modules = [ - ModelingToolkit, ModelingToolkitStandardLibrary, ModelingToolkitStandardLibrary.Blocks, ModelingToolkitStandardLibrary.Mechanical, @@ -33,9 +32,10 @@ makedocs( ModelingToolkitStandardLibrary.Hydraulic, ModelingToolkitStandardLibrary.Hydraulic.IsothermalCompressible, ], - clean = true, doctest = false, linkcheck = true, - linkcheck_ignore = ["https://www.mathworks.com/help/simscape/ug/basic-principles-of-modeling-physical-networks.html#bq89sba-6"], - warnonly = [:docs_block, :missing_docs, :cross_references], + clean = true, + checkdocs = :exports, + doctest = true, + linkcheck = true, format = Documenter.HTML( assets = ["assets/favicon.ico"], canonical = "https://docs.sciml.ai/ModelingToolkitStandardLibrary/stable/" diff --git a/docs/pages.jl b/docs/pages.jl index 00bcb942..fb010d48 100644 --- a/docs/pages.jl +++ b/docs/pages.jl @@ -19,5 +19,7 @@ pages = [ "Thermal Components" => "API/thermal.md", "Hydraulic Components" => "API/hydraulic.md", "Linear Analysis" => "API/linear_analysis.md", + "API Reference" => "API/reference.md", + "Domain API Reference" => "API/domain_reference.md", ], ] diff --git a/docs/src/API/domain_reference.md b/docs/src/API/domain_reference.md new file mode 100644 index 00000000..ccd1b38e --- /dev/null +++ b/docs/src/API/domain_reference.md @@ -0,0 +1,15 @@ +# Domain API Reference + +```@autodocs +Modules = [ + ModelingToolkitStandardLibrary.Mechanical.Rotational, + ModelingToolkitStandardLibrary.Mechanical.Translational, + ModelingToolkitStandardLibrary.Mechanical.TranslationalModelica, + ModelingToolkitStandardLibrary.Mechanical.TranslationalPosition, + ModelingToolkitStandardLibrary.Mechanical.MultiBody2D, + ModelingToolkitStandardLibrary.Thermal, + ModelingToolkitStandardLibrary.Electrical, + ModelingToolkitStandardLibrary.Hydraulic.IsothermalCompressible, +] +Private = false +``` diff --git a/docs/src/API/electrical.md b/docs/src/API/electrical.md index 788796ab..91ccde15 100644 --- a/docs/src/API/electrical.md +++ b/docs/src/API/electrical.md @@ -32,7 +32,6 @@ Capacitor Inductor IdealOpAmp Diode -HeatingDiode VariableResistor NMOS PMOS @@ -56,35 +55,3 @@ MultiSensor Voltage Current ``` - -## Digital Gates - -```@docs -Not -And -Nand -Or -Nor -Xor -Xnor -``` - -## Digital Components - -```@docs -HalfAdder -FullAdder -MUX -DEMUX -Encoder -Decoder -``` - -## Digital Sources - -```@docs -PulseDiff -Set -Reset -Pulse -``` diff --git a/docs/src/API/hydraulic.md b/docs/src/API/hydraulic.md index f1063548..12b35a90 100644 --- a/docs/src/API/hydraulic.md +++ b/docs/src/API/hydraulic.md @@ -1,5 +1,9 @@ # [ModelingToolkit Standard Library: Hydraulic Components](@id hydraulic) +```@docs +ModelingToolkitStandardLibrary.Hydraulic +``` + ```@contents Pages = ["hydraulic.md"] Depth = 3 diff --git a/docs/src/API/linear_analysis.md b/docs/src/API/linear_analysis.md index af2369be..ec500c82 100644 --- a/docs/src/API/linear_analysis.md +++ b/docs/src/API/linear_analysis.md @@ -4,15 +4,15 @@ The interface described here is currently experimental and at any time subject to breaking changes not respecting semantic versioning. -Linear analysis refers to the process of linearizing a nonlinear model and analysing the resulting linear dynamical system. To facilitate linear analysis, ModelingToolkitStandardLibrary provides the concept of an [`AnalysisPoint`](@ref), which can be inserted in-between two causal blocks (such as those from the `Blocks` sub module). Once a model containing analysis points is built, several operations are available: +Linear analysis refers to the process of linearizing a nonlinear model and analysing the resulting linear dynamical system. To facilitate linear analysis, ModelingToolkitStandardLibrary provides the concept of an `AnalysisPoint`, which can be inserted in-between two causal blocks (such as those from the `Blocks` sub module). Once a model containing analysis points is built, several operations are available: - - [`get_sensitivity`](@ref) get the [sensitivity function (wiki)](https://en.wikipedia.org/wiki/Sensitivity_(control_systems)), $S(s)$, as defined in the field of control theory. - - [`get_comp_sensitivity`](@ref) get the complementary sensitivity function $T(s) : S(s)+T(s)=1$. - - [`get_looptransfer`](@ref) get the (open) loop-transfer function where the loop starts and ends in the analysis point. For a typical simple feedback connection with a plant $P(s)$ and a controller $C(s)$, the loop-transfer function at the plant output is $P(s)C(s)$. - - [`linearize`](@ref) can be called with two analysis points denoting the input and output of the linearized system. - - [`open_loop`](@ref) return a new (nonlinear) system where the loop has been broken in the analysis point, i.e., the connection the analysis point usually implies has been removed. + - `get_sensitivity` gets the [sensitivity function (wiki)](https://en.wikipedia.org/wiki/Sensitivity_(control_systems)), $S(s)$, as defined in the field of control theory. + - `get_comp_sensitivity` gets the complementary sensitivity function $T(s) : S(s)+T(s)=1$. + - `get_looptransfer` gets the (open) loop-transfer function where the loop starts and ends in the analysis point. For a typical simple feedback connection with a plant $P$ and a controller $C$, the loop-transfer function at the plant output is $P(s)C(s)$. + - `linearize` can be called with two analysis points denoting the input and output of the linearized system. + - `open_loop` returns a new nonlinear system where the loop has been broken at the analysis point. -An analysis point can be created explicitly using the constructor [`AnalysisPoint`](@ref), or automatically when connecting two causal components using `connect`: +An analysis point can be created explicitly using the `AnalysisPoint` constructor, or automatically when connecting two causal components using `connect`: ```julia connect(comp1.output, :analysis_point_name, comp2.input) @@ -34,7 +34,7 @@ The directionality of an analysis point can be thought of as an arrow in a block This is signified by the name being the middle argument to `connect`. -Of the above mentioned functions, all except for [`open_loop`](@ref) return the output of [`ModelingToolkit.linearize`](@ref), which is +Of the above mentioned functions, all except for `open_loop` return the output of `ModelingToolkit.linearize`, which is ```julia matrices, simplified_sys = linearize(...) @@ -148,7 +148,3 @@ Pages = ["Blocks/analysis_points.jl"] Order = [:function, :type] Private = false ``` - -```@docs -ModelingToolkit.linearize -``` diff --git a/docs/src/API/mechanical.md b/docs/src/API/mechanical.md index ac0cddaf..8f41cfd4 100644 --- a/docs/src/API/mechanical.md +++ b/docs/src/API/mechanical.md @@ -1,5 +1,9 @@ # ModelingToolkit Standard Library: Mechanical Components +```@docs +ModelingToolkitStandardLibrary.Mechanical +``` + ```@contents Pages = ["mechanical.md"] Depth = 3 diff --git a/docs/src/API/reference.md b/docs/src/API/reference.md new file mode 100644 index 00000000..bb09ff65 --- /dev/null +++ b/docs/src/API/reference.md @@ -0,0 +1,8 @@ +# API Reference + +```@autodocs +Modules = [ + ModelingToolkitStandardLibrary.Blocks, +] +Private = false +``` diff --git a/docs/src/connectors/connections.md b/docs/src/connectors/connections.md index 1e079d46..0f113160 100644 --- a/docs/src/connectors/connections.md +++ b/docs/src/connectors/connections.md @@ -3,7 +3,7 @@ In Physical Network Acausal modeling, each physical domain must define a **connector** to combine model components. Each physical domain **connector** defines a minimum of 2 variables, one which is called a *Through* variable, and one which is called an *Across* variable. Both Modelica and SimScape define these variables in the same way: - [Modelica Connectors](https://mbe.modelica.university/components/connectors/#acausal-connection) - - [SimScape Connectors](https://www.mathworks.com/help/simscape/ug/basic-principles-of-modeling-physical-networks.html#bq89sba-6) + - Simscape connector documentation However, the standard libraries differ on the selection of the Across variable for the Mechanical Translation and Rotation libraries, Modelica choosing position and angle and SimScape choosing velocity and angular velocity, respectively for Translation and Rotation. Modelica describes their decision [here](https://mbe.modelica.university/components/connectors/simple_domains/). In summary, they would like to provide less integration in the model to avoid lossy numerical behavior, but this decision assumes the lowest order derivative is needed by the model. Numerically it is possible to define the connector either way, but there are some consequences of this decision, and therefore we will study them in detail here as they relate to ModelingToolkit. diff --git a/docs/src/index.md b/docs/src/index.md index b0319ca6..68b7c141 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -33,7 +33,7 @@ The following are the constituent libraries of the ModelingToolkit Standard Libr ## Contributing - Please refer to the - [SciML ColPrac: Contributor's Guide on Collaborative Practices for Community Packages](https://github.com/SciML/ColPrac/blob/master/README.md) + SciML ColPrac: Contributor's Guide on Collaborative Practices for Community Packages for guidance on PRs, issues, and other matters relating to contributing to SciML. - See the [SciML Style Guide](https://github.com/SciML/SciMLStyle) for common coding practices and other style decisions. diff --git a/src/Blocks/Blocks.jl b/src/Blocks/Blocks.jl index e07ec5e8..f6aa3b65 100644 --- a/src/Blocks/Blocks.jl +++ b/src/Blocks/Blocks.jl @@ -5,7 +5,7 @@ module Blocks using ModelingToolkitBase: ModelingToolkitBase, @component, @connector, @named, @parameters, @unpack, System, compose, connect, extend, getdefault, t_nounits as t, D_nounits as D -using SymbolicUtils: @syms, symtype +using SymbolicUtils: @syms, symtype, BasicSymbolic, SymReal using Symbolics: Symbolics, @register_symbolic, @variables, Differential, Equation import Base: ifelse import ..@symcheck diff --git a/src/Blocks/continuous.jl b/src/Blocks/continuous.jl index a30f838c..f7c2116b 100644 --- a/src/Blocks/continuous.jl +++ b/src/Blocks/continuous.jl @@ -661,7 +661,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 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/). +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 `ModelingToolkit.linearize` 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/nonlinear.jl b/src/Blocks/nonlinear.jl index 5aaf7087..d801f359 100644 --- a/src/Blocks/nonlinear.jl +++ b/src/Blocks/nonlinear.jl @@ -61,7 +61,7 @@ If the input is within `u_min` ... `u_max`, the output is zero. Outside of this _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) + if !isnothing(u_max) && !(u_max isa Symbolics.Num) u_max ≥ _u_min || throw(ArgumentError("`u_min` must be smaller than `u_max`")) end diff --git a/src/Blocks/sources.jl b/src/Blocks/sources.jl index e7463a5d..63378087 100644 --- a/src/Blocks/sources.jl +++ b/src/Blocks/sources.jl @@ -492,6 +492,9 @@ struct Parameter{T <: Real} circular_buffer::Bool end +Parameter(data::Symbolics.Arr, ref, circular_buffer) = + Symbolics.term(Parameter, data, ref, circular_buffer) + Parameter(data::Vector{T}, ref::T) where {T <: Real} = Parameter(data, ref, true) Parameter(x::Parameter) = x function Parameter(x::T; tofloat = true) where {T <: Real} @@ -565,7 +568,6 @@ end get_sample_time(memory::Parameter) = memory.ref Symbolics.@register_symbolic get_sample_time(memory::Parameter) -Base.convert(::Type{T}, x::Parameter{T}) where {T <: Real} = x.ref function Base.convert(::Type{<:Parameter{T}}, x::Number) where {T <: Real} return Parameter{T}(T[], x, true) end @@ -647,18 +649,44 @@ end function get_sampled_data(t, buffer) return get_sampled_data(t, buffer.data, buffer.ref, buffer.circular_buffer) end -Symbolics.@register_symbolic Parameter(data::Vector, ref, circular_buffer::Bool) Symbolics.@register_symbolic get_sampled_data(t, buffer::Parameter) Symbolics.@register_symbolic get_sampled_data(t, buffer::Vector, dt, circular_buffer) false + +for (t_type, circular_buffer_type) in ( + (Real, Real), + (Real, Symbolics.Num), + (Real, BasicSymbolic{SymReal}), + (Symbolics.Num, Real), + (Symbolics.Num, Symbolics.Num), + (Symbolics.Num, BasicSymbolic{SymReal}), + (BasicSymbolic{SymReal}, Real), + (BasicSymbolic{SymReal}, Symbolics.Num), + (BasicSymbolic{SymReal}, BasicSymbolic{SymReal}), + ) + @eval function get_sampled_data( + t::$(t_type), buffer::Vector{T}, dt::Symbolics.Num, + circular_buffer::$(circular_buffer_type) + ) where {T <: Real} + return invoke( + get_sampled_data, + Tuple{typeof(t), Vector, Symbolics.Num, typeof(circular_buffer)}, + t, + buffer, + dt, + circular_buffer, + ) + end +end + Symbolics.@register_derivative get_sampled_data(t, buffer) 1 first_order_backwards_difference(t, buffer) -function ChainRulesCore.frule((_, ẋ, _), ::typeof(get_sampled_data), t, buffer) +function ChainRulesCore.frule((_, ẋ, _)::Tuple, ::typeof(get_sampled_data), t, buffer) return first_order_backwards_difference(t, buffer) * ẋ end Symbolics.@register_derivative get_sampled_data(t, buffer, dt, circular_buffer) 1 begin first_order_backwards_difference(t, buffer, dt, circular_buffer) end function ChainRulesCore.frule( - (_, ẋ, _), + (_, ẋ, _)::Tuple, ::typeof(get_sampled_data), t, buffer, diff --git a/src/Blocks/utils.jl b/src/Blocks/utils.jl index 872e685b..6e5ca3bf 100644 --- a/src/Blocks/utils.jl +++ b/src/Blocks/utils.jl @@ -1,3 +1,14 @@ +""" + RealInput(; name, guess) + +Connector with one input signal of type Real. + +# Parameters: +- `guess=0`: Guess value for `u`. + +# States: +- `u`: Value of the connector which is a scalar. +""" @connector function RealInput(; name, nin = 1, u_start = nothing, guess = nin > 1 ? zeros(nin) : 0.0 ) @@ -20,18 +31,19 @@ end System(Equation[], t, [u;], []; name = name, guesses = [u => guess]) end -@doc """ - RealInput(;name, guess) -Connector with one input signal of type Real. +""" + RealInputArray(; name, nin, guess) + +Connector with an array of input signals of type Real. # Parameters: -- `guess=0`: Guess value for `u`. +- `nin`: Number of inputs. +- `guess=zeros(nin)`: Guess value for `u`. # States: -- `u`: Value of the connector which is a scalar. -""" RealInput - +- `u`: Value of the connector which is an array. +""" @connector function RealInputArray(; name, nin, u_start = nothing, guess = zeros(nin)) if u_start !== nothing Base.depwarn( @@ -45,19 +57,18 @@ Connector with one input signal of type Real. ] System(Equation[], t, [u], []; name = name, guesses = [u => guess]) end -@doc """ - RealInputArray(;name, nin, guess) -Connector with an array of input signals of type Real. +""" + RealOutput(; name, guess) + +Connector with one output signal of type Real. # Parameters: -- `nin`: Number of inputs. -- `guess=zeros(nin)`: Guess value for `u`. +- `guess=0`: Guess value for `u`. # States: -- `u`: Value of the connector which is an array. -""" RealInputArray - +- `u`: Value of the connector which is a scalar. +""" @connector function RealOutput(; name, nout = 1, u_start = nothing, guess = nout > 1 ? zeros(nout) : 0.0 ) @@ -80,18 +91,19 @@ Connector with an array of input signals of type Real. end System(Equation[], t, [u;], []; name = name, guesses = [u => guess]) end -@doc """ - RealOutput(;name, guess) -Connector with one output signal of type Real. +""" + RealOutputArray(; name, nout, guess) + +Connector with an array of output signals of type Real. # Parameters: -- `guess=0`: Guess value for `u`. +- `nout`: Number of outputs. +- `guess=zeros(nout)`: Guess value for `u`. # States: -- `u`: Value of the connector which is a scalar. -""" RealOutput - +- `u`: Value of the connector which is an array. +""" @connector function RealOutputArray(; name, nout, u_start = nothing, guess = zeros(nout)) if u_start !== nothing Base.depwarn( @@ -105,18 +117,6 @@ Connector with one output signal of type Real. ] System(Equation[], t, [u], []; name = name, guesses = [u => guess]) end -@doc """ - RealOutputArray(;name, nout, guess) - -Connector with an array of output signals of type Real. - -# Parameters: -- `nout`: Number of outputs. -- `guess=zeros(nout)`: Guess value for `u`. - -# States: -- `u`: Value of the connector which is an array. -""" RealOutputArray """ SISO(;name, u_start = 0.0, y_start = 0.0) diff --git a/src/Electrical/Analog/ideal_components.jl b/src/Electrical/Analog/ideal_components.jl index fed4501a..a537753e 100644 --- a/src/Electrical/Analog/ideal_components.jl +++ b/src/Electrical/Analog/ideal_components.jl @@ -224,7 +224,7 @@ At the right port both any voltage `v2` and any current `i2` are possible (norat # States: -See [TwoPort](@ref) +See `ModelingToolkitStandardLibrary.Magnetic.FluxTubes.TwoPort`. # Connectors: diff --git a/src/Electrical/utils.jl b/src/Electrical/utils.jl index 34b7ef42..d9e3d287 100644 --- a/src/Electrical/utils.jl +++ b/src/Electrical/utils.jl @@ -1,11 +1,4 @@ -@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) A pin in an analog circuit. @@ -13,7 +6,14 @@ A pin in an analog circuit. # States: - `v(t)`: [`V`] The voltage at this pin - `i(t)`: [`A`] The current passing through this pin -""" Pin +""" +@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 """ OnePort(; name, v = nothing, i = nothing) @@ -102,6 +102,17 @@ Current `i1` flows from `p1` to `n1` and `i2` from `p2` to `n2`. return System(equations, t, vars, pars; name, systems) end +""" + DigitalPin(; name) + +A pin in a digital circuit. + +# States: +- `v(t)`: [`V`] The voltage at this pin +- `i(t)`: [`A`] The current passing through this pin +- `val(t)`: The binary value of the pin at this point. A voltage from `0V` to `0.8V` is a binary value of `0`. +A voltage in the range `2.0V` to `5.0V` is `1`. Any other value is `X`. +""" @connector function DigitalPin(; name) @variables val(t) v(t) i(t) eqs = [ @@ -115,14 +126,3 @@ end name = name ) end -@doc """ - DigitalPin(; name) - -A pin in a digital circuit. - -# States: -- `v(t)`: [`V`] The voltage at this pin -- `i(t)`: [`A`] The current passing through this pin -- `val(t)`: The binary value of the pin at this point. A voltage from `0V` to `0.8V` is a binary value of `0`. -A voltage in the range `2.0V` to `5.0V` is `1`. Any other value is `X`. -""" DigitalPin diff --git a/src/Hydraulic/IsothermalCompressible/utils.jl b/src/Hydraulic/IsothermalCompressible/utils.jl index 53947055..94804752 100644 --- a/src/Hydraulic/IsothermalCompressible/utils.jl +++ b/src/Hydraulic/IsothermalCompressible/utils.jl @@ -123,8 +123,8 @@ function friction_factor(dm, area, d_h, viscosity, shape_factor) end end @register_symbolic friction_factor(dm, area, d_h, viscosity, shape_factor) -@register_derivative friction_factor(dm, area, d_h, viscosity, shape_factor) 1 Symbolics.SConst(0) -@register_derivative friction_factor(dm, area, d_h, viscosity, shape_factor) 4 Symbolics.SConst(0) +@register_derivative friction_factor(dm, area, d_h, viscosity, shape_factor) 1 0 +@register_derivative friction_factor(dm, area, d_h, viscosity, shape_factor) 4 0 density_ref(port) = port.ρ density_exp(port) = port.n diff --git a/src/Magnetic/FluxTubes/utils.jl b/src/Magnetic/FluxTubes/utils.jl index 920305b2..79195f15 100644 --- a/src/Magnetic/FluxTubes/utils.jl +++ b/src/Magnetic/FluxTubes/utils.jl @@ -1,3 +1,12 @@ +""" + MagneticPort(; name, V_m = nothing, Phi = nothing) + +Port for a magnetic system. + +# States +- `V_m(t)`: Magnetic potential at the port. +- `Phi(t)`: 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"] @@ -5,7 +14,6 @@ end System(Equation[], t, vars, []; name) end -Base.@doc "Port for a Magnetic system." MagneticPort """ Positive magnetic port diff --git a/src/Mechanical/Rotational/utils.jl b/src/Mechanical/Rotational/utils.jl index 9f2d1fdb..14de3d71 100644 --- a/src/Mechanical/Rotational/utils.jl +++ b/src/Mechanical/Rotational/utils.jl @@ -1,3 +1,12 @@ +""" + Flange(; name) + +One-dimensional rotational flange of a shaft. + +# States +- `phi(t)`: [`rad`] Absolute rotation angle of the flange. +- `tau(t)`: [`N.m`] Cut torque in the flange. +""" @connector function Flange(; name, phi = nothing, tau = nothing) vars = @variables begin phi(t) = phi, [description = "Rotation angle of flange"] @@ -6,16 +15,15 @@ System(Equation[], t, vars, []; name) end -Base.@doc """ - Support(;name) - -1-dim. rotational flange of a shaft. +""" + Support(; name) -# States: -- `phi(t)`: [`rad`] Absolute rotation angle of flange -- `tau(t)`: [`N.m`] Cut torque in the flange -""" Flange +Support or housing of a one-dimensional rotational shaft. +# States +- `phi(t)`: [`rad`] Absolute rotation angle of the support or housing. +- `tau(t)`: [`N.m`] Cut torque in the support or housing. +""" @connector function Support(; name, phi = nothing, tau = nothing) vars = @variables begin phi(t) = phi, [description = "Rotation angle of flange"] @@ -24,18 +32,6 @@ Base.@doc """ System(Equation[], t, vars, []; name) end -# Base.@doc """ -# InternalSupport(;name, tau) - -# 1-dim. rotational flange of a shaft. - -# - `tau`: External support torque (must be computed via torque balance in model where InternalSupport is used; = flange.tau) - -# # States: -# - `phi(t)`: [`rad`] Absolute rotation angle of flange -# - `tau(t)`: [`N.m`] Cut torque in the flange -# """ Flange - # @connector function InternalSupport(; name, tau) # @named flange = Flange() # @variables phi(t)=0 [description = "Rotation angle of support $name"] @@ -45,16 +41,6 @@ end # System(equations, t, [phi], [], name = name, systems = [flange]) # NOTE: tau not included since it belongs elsewhere # end -Base.@doc """ - Support(;name) - -Support/housing of a 1-dim. rotational shaft - -# States: -- `phi(t)`: [`rad`] Absolute rotation angle of the support/housing -- `tau(t)`: [`N.m`] Cut torque in the support/housing -""" Support - """ PartialCompliant(; name, phi_rel = 0.0, tau = 0.0) diff --git a/src/Mechanical/Translational/utils.jl b/src/Mechanical/Translational/utils.jl index 0e9c65a5..d048d0ec 100644 --- a/src/Mechanical/Translational/utils.jl +++ b/src/Mechanical/Translational/utils.jl @@ -1,3 +1,12 @@ +""" + MechanicalPort(; name) + +One-dimensional translational mechanical port. + +# States +- `v(t)`: [`m/s`] Velocity of the node. +- `f(t)`: [`N`] Force entering the node. +""" @connector function MechanicalPort(; name, v = nothing, f = nothing) vars = @variables begin v(t) = v @@ -5,12 +14,3 @@ end return System(Equation[], t, vars, []; name) end -Base.@doc """ - MechanicalPort(;name) - -1-dim. rotational flange of a shaft. - -# States: -- `v`: [m/s] velocity of the node -- `f`: [N] force entering the node -""" MechanicalPort diff --git a/src/Mechanical/TranslationalModelica/utils.jl b/src/Mechanical/TranslationalModelica/utils.jl index 0faaf137..6d052e49 100644 --- a/src/Mechanical/TranslationalModelica/utils.jl +++ b/src/Mechanical/TranslationalModelica/utils.jl @@ -1,3 +1,12 @@ +""" + Flange(; name) + +One-dimensional translational flange. + +# States +- `s(t)`: [`m`] Absolute position of the flange. +- `f(t)`: [`N`] Cut force into the flange. +""" @connector function Flange(; name, s = nothing, f = nothing) vars = @variables begin s(t) = s @@ -5,16 +14,16 @@ end System(Equation[], t, vars, []; name) end -Base.@doc """ - Flange(;name) -1-dim. translational flange. +""" + Support(; name) -# States: -- `s`: [m] Absolute position of flange -- `f`: [N] Cut force into the flange -""" Flange +Support or housing of a one-dimensional translational flange. +# States +- `s(t)`: [`m`] Absolute position of the support or housing. +- `f(t)`: [`N`] Cut force into the flange. +""" @connector function Support(; name, s = nothing, f = nothing) vars = @variables begin s(t) = s @@ -22,15 +31,6 @@ Base.@doc """ end System(Equation[], t, vars, []; name) end -Base.@doc """ - Support(;name) - -Support/housing 1-dim. translational flange. - -# States: -- `s`: [m] Absolute position of the support/housing -- `f`: [N] Cut force into the flange -""" Support @component function PartialTwoFlanges(; name) pars = @parameters begin diff --git a/src/Mechanical/TranslationalPosition/utils.jl b/src/Mechanical/TranslationalPosition/utils.jl index 37fb92ed..9113abbe 100644 --- a/src/Mechanical/TranslationalPosition/utils.jl +++ b/src/Mechanical/TranslationalPosition/utils.jl @@ -1,3 +1,12 @@ +""" + Flange(; name) + +One-dimensional translational flange. + +# States +- `s(t)`: [`m`] Absolute position of the flange. +- `f(t)`: [`N`] Cut force into the flange. +""" @connector function Flange(; name, s = nothing, f = nothing) vars = @variables begin s(t) = s @@ -5,16 +14,16 @@ end System(Equation[], t, vars, []; name) end -Base.@doc """ - Flange(;name) -1-dim. translational flange. +""" + Support(; name) -# States: -- `s`: [m] Absolute position of flange -- `f`: [N] Cut force into the flange -""" Flange +Support or housing of a one-dimensional translational flange. +# States +- `s(t)`: [`m`] Absolute position of the support or housing. +- `f(t)`: [`N`] Cut force into the flange. +""" @connector function Support(; name, s = nothing, f = nothing) vars = @variables begin s(t) = s @@ -22,15 +31,6 @@ Base.@doc """ end System(Equation[], t, vars, []; name) end -Base.@doc """ - Support(;name) - -Support/housing 1-dim. translational flange. - -# States: -- `s`: [m] Absolute position of the support/housing -- `f`: [N] Cut force into the flange -""" Support """ PartialCompliant(;name, s_rel_start=0.0, f_start=0.0) diff --git a/src/Thermal/utils.jl b/src/Thermal/utils.jl index 3aac54ef..3fa969df 100644 --- a/src/Thermal/utils.jl +++ b/src/Thermal/utils.jl @@ -1,3 +1,14 @@ +""" + HeatPort(; name, T = nothing, T_guess = 293.15, Q_flow = nothing, Q_flow_guess = 0.0) + +Port for a thermal system. + +# Keyword Arguments +- `T_guess`: [`K`] Initial temperature guess. +- `Q_flow_guess`: [`W`] Initial heat-flow guess. +- `T`: Default value for the temperature state. +- `Q_flow`: Default value for the heat-flow state. +""" @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 @@ -10,18 +21,6 @@ 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) - -Port for a thermal system. -# Parameters: -- `T_guess`: [K] Initial guess for the temperature of the port (set to 273.15 + 20). -- `Q_flow_guess`: [W] Initial guess for the heat flow rate at the port (set to 0.0). - -# States: -- `T`: [K] Temperature of the port. Guess set to `T_guess`. Passing a value for `T` will set its default. -- `Q_flow`: [W] Heat flow rate at the port. Guess set to `Q_flow_guess`. Passing a value for `Q_flow` will set its default. -""" HeatPort """ Element1D(; name, dT_guess = 0.0, Q_flow_guess = 0.0) diff --git a/test/qa/Project.toml b/test/qa/Project.toml index 756af262..3ec88f01 100644 --- a/test/qa/Project.toml +++ b/test/qa/Project.toml @@ -8,6 +8,6 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [compat] Aqua = "0.8" SafeTestsets = "0.1" -SciMLTesting = "2.1" +SciMLTesting = "2.4" Test = "1" julia = "1.10" diff --git a/test/qa/qa.jl b/test/qa/qa.jl index d918dd82..06b1c559 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -1,15 +1,3 @@ -using SciMLTesting, ModelingToolkitStandardLibrary, Test +using SciMLTesting, ModelingToolkitStandardLibrary -run_qa( - ModelingToolkitStandardLibrary; - explicit_imports = true, - api_docs_kwargs = (; rendered = true), - aqua_kwargs = (; ambiguities = (; recursive = false)), - ei_kwargs = (; - # `ifelse` is IfElse's sole export but it is not declared public in IfElse. - all_explicit_imports_are_public = (; ignore = (:ifelse,)), - # Names accessed qualified but not declared public in their source package: - # ifelse -> IfElse, SConst -> Symbolics, isvariable -> ModelingToolkitBase - all_qualified_accesses_are_public = (; ignore = (:ifelse, :SConst, :isvariable)), - ), -) +run_qa(ModelingToolkitStandardLibrary) diff --git a/test/test_analysis_points.jl b/test/test_analysis_points.jl index 34bf8fbb..61d38b2b 100644 --- a/test/test_analysis_points.jl +++ b/test/test_analysis_points.jl @@ -268,7 +268,13 @@ P_not_broken, _ = linearize(sys_inner, :u, :y) @test P_not_broken.A[] == -2 P_broken, _ = linearize(sys_inner, :u, :y, loop_openings = [:u]) @test P_broken.A[] == -1 -P_broken, _ = linearize(sys_inner, :u, :y, loop_openings = [:y]) +P_broken, _ = linearize( + sys_inner, + :u, + :y, + loop_openings = [:y], + op = Dict(feedback.input2.u => 0.0), +) @test P_broken.A[] == -1 Sinner = sminreal(ss(get_sensitivity(sys_inner, :u)[1]...)) @@ -298,7 +304,10 @@ Souter = sminreal(ss(get_sensitivity(sys_outer, sys_outer.sys_inner.u)[1]...)) Sinner2 = sminreal( ss( get_sensitivity( - sys_outer, sys_outer.sys_inner.u, loop_openings = [:y2] + sys_outer, + sys_outer.sys_inner.u, + loop_openings = [:y2], + op = Dict(P_outer.input.u => 0.0), )[1]... ) )