Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define isconnection on AnalysisPoint #261

Merged
merged 5 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ V = 1.0
@named ground = Ground()

rc_eqs = [connect(constant.output, source.V)
connect(source.p, resistor.p)
connect(resistor.n, capacitor.p)
connect(capacitor.n, source.n, ground.g)]
connect(source.p, resistor.p)
connect(resistor.n, capacitor.p)
connect(capacitor.n, source.n, ground.g)]

@named rc_model = ODESystem(rc_eqs, t,
systems = [resistor, capacitor, constant, source, ground])
Expand Down
6 changes: 3 additions & 3 deletions docs/pages.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pages = [
"Custom Components" => "tutorials/custom_component.md",
"Thermal Conduction Model" => "tutorials/thermal_model.md",
"DC Motor with Speed Controller" => "tutorials/dc_motor_pi.md",
"SampledData Component" => "tutorials/input_component.md",
"SampledData Component" => "tutorials/input_component.md"
],
"About Acausal Connections" => "connectors/connections.md",
"API" => [
Expand All @@ -15,6 +15,6 @@ pages = [
"Mechanical Components" => "API/mechanical.md",
"Thermal Components" => "API/thermal.md",
"Hydraulic Components" => "API/hydraulic.md",
"Linear Analysis" => "API/linear_analysis.md",
],
"Linear Analysis" => "API/linear_analysis.md"
]
]
2 changes: 1 addition & 1 deletion docs/src/API/linear_analysis.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ using ModelingToolkitStandardLibrary.Blocks, ModelingToolkit
@named C = Gain(-1) # A P controller
t = ModelingToolkit.get_iv(P)
eqs = [connect(P.output, :plant_output, C.input) # Connect with an automatically created analysis point called :plant_output
connect(C.output, :plant_input, P.input)]
connect(C.output, :plant_input, P.input)]
sys = ODESystem(eqs, t, systems = [P, C], name = :feedback_system)

matrices_S = get_sensitivity(sys, :plant_input)[1] # Compute the matrices of a state-space representation of the (input)sensitivity function.
Expand Down
8 changes: 4 additions & 4 deletions docs/src/connectors/connections.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ using Plots
@named ground = Ground()

eqs = [connect(capacitor.p, resistor.p)
connect(resistor.n, ground.g, capacitor.n)]
connect(resistor.n, ground.g, capacitor.n)]

@named model = ODESystem(eqs, t; systems = [resistor, capacitor, ground])

Expand Down Expand Up @@ -139,7 +139,7 @@ const TV = ModelingToolkitStandardLibrary.Mechanical.Translational
@named ground = TV.Fixed()

eqs = [connect(damping.flange_a, body.flange)
connect(ground.flange, damping.flange_b)]
connect(ground.flange, damping.flange_b)]

@named model = ODESystem(eqs, t; systems = [damping, body, ground])

Expand Down Expand Up @@ -172,7 +172,7 @@ const TP = ModelingToolkitStandardLibrary.Mechanical.TranslationalPosition
@named ground = TP.Fixed(s_0 = 0)

eqs = [connect(damping.flange_a, body.flange)
connect(ground.flange, damping.flange_b)]
connect(ground.flange, damping.flange_b)]

@named model = ODESystem(eqs, t; systems = [damping, body, ground])

Expand Down Expand Up @@ -267,7 +267,7 @@ Let's define a quick function to simplify and solve the 2 different systems. Not
```@example connections
function simplify_and_solve(damping, spring, body, ground)
eqs = [connect(spring.flange_a, body.flange, damping.flange_a)
connect(spring.flange_b, damping.flange_b, ground.flange)]
connect(spring.flange_b, damping.flange_b, ground.flange)]

@named model = ODESystem(eqs, t; systems = [ground, body, spring, damping])

Expand Down
24 changes: 12 additions & 12 deletions docs/src/tutorials/custom_component.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ function NonlinearResistor(; name, Ga, Gb, Ve)
pars = @parameters Ga=Ga Gb=Gb Ve=Ve
eqs = [
i ~ ifelse(v < -Ve,
Gb * (v + Ve) - Ga * Ve,
ifelse(v > Ve,
Gb * (v - Ve) + Ga * Ve,
Ga * v)),
Gb * (v + Ve) - Ga * Ve,
ifelse(v > Ve,
Gb * (v - Ve) + Ga * Ve,
Ga * v))
]
extend(ODESystem(eqs, t, [], pars; name = name), oneport)
end
Expand Down Expand Up @@ -102,14 +102,14 @@ The final model can now be created with the components from the library and the
@named Gnd = Ground()

connections = [connect(L.p, G.p)
connect(G.n, Nr.p)
connect(Nr.n, Gnd.g)
connect(C1.p, G.n)
connect(L.n, Ro.p)
connect(G.p, C2.p)
connect(C1.n, Gnd.g)
connect(C2.n, Gnd.g)
connect(Ro.n, Gnd.g)]
connect(G.n, Nr.p)
connect(Nr.n, Gnd.g)
connect(C1.p, G.n)
connect(L.n, Ro.p)
connect(G.p, C2.p)
connect(C1.n, Gnd.g)
connect(C2.n, Gnd.g)
connect(Ro.n, Gnd.g)]

@named model = ODESystem(connections, t, systems = [L, Ro, G, C1, C2, Nr, Gnd])
nothing # hide
Expand Down
26 changes: 13 additions & 13 deletions docs/src/tutorials/dc_motor_pi.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,18 @@ The actual model can now be composed.
@named speed_sensor = SpeedSensor()

connections = [connect(fixed.flange, emf.support, friction.flange_b)
connect(emf.flange, friction.flange_a, inertia.flange_a)
connect(inertia.flange_b, load.flange)
connect(inertia.flange_b, speed_sensor.flange)
connect(load_step.output, load.tau)
connect(ref.output, feedback.input1)
connect(speed_sensor.w, :y, feedback.input2)
connect(feedback.output, pi_controller.err_input)
connect(pi_controller.ctr_output, :u, source.V)
connect(source.p, R1.p)
connect(R1.n, L1.p)
connect(L1.n, emf.p)
connect(emf.n, source.n, ground.g)]
connect(emf.flange, friction.flange_a, inertia.flange_a)
connect(inertia.flange_b, load.flange)
connect(inertia.flange_b, speed_sensor.flange)
connect(load_step.output, load.tau)
connect(ref.output, feedback.input1)
connect(speed_sensor.w, :y, feedback.input2)
connect(feedback.output, pi_controller.err_input)
connect(pi_controller.ctr_output, :u, source.V)
connect(source.p, R1.p)
connect(R1.n, L1.p)
connect(L1.n, emf.p)
connect(emf.n, source.n, ground.g)]

@named model = ODESystem(connections, t,
systems = [
Expand All @@ -78,7 +78,7 @@ connections = [connect(fixed.flange, emf.support, friction.flange_b)
load_step,
inertia,
friction,
speed_sensor,
speed_sensor
])
nothing # hide
```
Expand Down
18 changes: 9 additions & 9 deletions docs/src/tutorials/input_component.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ function System(f; name)
pars = @parameters m=10 k=1000 d=1

eqs = [f ~ src.output.u
ddx * 10 ~ k * x + d * dx + f
D(x) ~ dx
D(dx) ~ ddx]
ddx * 10 ~ k * x + d * dx + f
D(x) ~ dx
D(dx) ~ ddx]

ODESystem(eqs, t, vars, pars; systems = [src], name)
end
Expand Down Expand Up @@ -74,9 +74,9 @@ function System(; name)
pars = @parameters m=10 k=1000 d=1

eqs = [f ~ get_sampled_data(t)
ddx * 10 ~ k * x + d * dx + f
D(x) ~ dx
D(dx) ~ ddx]
ddx * 10 ~ k * x + d * dx + f
D(x) ~ dx
D(dx) ~ ddx]

ODESystem(eqs, t, vars, pars; name)
end
Expand Down Expand Up @@ -115,9 +115,9 @@ function System(; name)
pars = @parameters m=10 k=1000 d=1

eqs = [f ~ src.output.u
ddx * 10 ~ k * x + d * dx + f
D(x) ~ dx
D(dx) ~ ddx]
ddx * 10 ~ k * x + d * dx + f
D(x) ~ dx
D(dx) ~ ddx]

ODESystem(eqs, t, vars, pars; systems = [src], name)
end
Expand Down
6 changes: 3 additions & 3 deletions docs/src/tutorials/rc_circuit.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ V = 1.0
@named ground = Ground()

rc_eqs = [connect(constant.output, source.V)
connect(source.p, resistor.p)
connect(resistor.n, capacitor.p)
connect(capacitor.n, source.n, ground.g)]
connect(source.p, resistor.p)
connect(resistor.n, capacitor.p)
connect(capacitor.n, source.n, ground.g)]

@named rc_model = ODESystem(rc_eqs, t,
systems = [resistor, capacitor, constant, source, ground])
Expand Down
2 changes: 1 addition & 1 deletion docs/src/tutorials/thermal_model.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ connections = [
connect(mass1.port, conduction.port_a),
connect(conduction.port_b, mass2.port),
connect(mass1.port, Tsensor1.port),
connect(mass2.port, Tsensor2.port),
connect(mass2.port, Tsensor2.port)
]

@named model = ODESystem(connections, t,
Expand Down
4 changes: 2 additions & 2 deletions src/Blocks/Blocks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export Log, Log10
include("math.jl")

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

export Limiter, DeadZone, SlewRateLimiter
Expand All @@ -30,7 +30,7 @@ export PI, LimPI, PID, LimPID
include("continuous.jl")

export AnalysisPoint, get_sensitivity, get_comp_sensitivity,
get_looptransfer, open_loop
get_looptransfer, open_loop
include("analysis_points.jl")

end
40 changes: 25 additions & 15 deletions src/Blocks/analysis_points.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,18 @@ Base.@kwdef mutable struct AnalysisPoint
out = nothing
name::Symbol = :nothing
end
Base.broadcastable(x::AnalysisPoint) = Ref(x)
if Base.isdefined(ModelingToolkit, :isconnection)
ModelingToolkit.isconnection(::AnalysisPoint) = true
end

Base.nameof(ap::AnalysisPoint) = ap.name
function Base.hash(ap::AnalysisPoint, seed::UInt)
h1 = hash(ap.in, seed)
h2 = hash(ap.out, h1)
h3 = hash(ap.name, h2)
h3 ⊻ (0xd29cdc51aa6562d4 % UInt)
end

function ap_var(sys)
if hasproperty(sys, :u)
Expand Down Expand Up @@ -255,7 +265,7 @@ end
const SymOrVec = Union{Symbol, Vector{Symbol}}

function get_sensitivity_function(sys, ap_name::SymOrVec; loop_openings = nothing,
kwargs...)
kwargs...)
find = namespaced_ap_match(ap_name, loop_openings)
t = get_iv(sys)
aps = []
Expand Down Expand Up @@ -284,7 +294,7 @@ function get_sensitivity_function(sys, ap_name::SymOrVec; loop_openings = nothin
end

function get_comp_sensitivity_function(sys, ap_name::SymOrVec; loop_openings = nothing,
kwargs...)
kwargs...)
find = namespaced_ap_match(ap_name, loop_openings)
t = get_iv(sys)
aps = []
Expand Down Expand Up @@ -313,7 +323,7 @@ function get_comp_sensitivity_function(sys, ap_name::SymOrVec; loop_openings = n
end

function get_looptransfer_function(sys, ap_name::SymOrVec; loop_openings = nothing,
kwargs...)
kwargs...)
find = namespaced_ap_match(ap_name, loop_openings)
t = get_iv(sys)
aps = []
Expand Down Expand Up @@ -380,9 +390,9 @@ function open_loop(sys, ap_name::Symbol; ground_input = false, kwargs...)
end

function ModelingToolkit.linearization_function(sys::ModelingToolkit.AbstractSystem,
input_name::SymOrVec, output_name;
loop_openings = nothing,
kwargs...)
input_name::SymOrVec, output_name;
loop_openings = nothing,
kwargs...)
t = get_iv(sys)
@variables u(t)=0 [input = true]
names = [input_name;]
Expand Down Expand Up @@ -417,7 +427,7 @@ function ModelingToolkit.linearization_function(sys::ModelingToolkit.AbstractSys
push!(multiplicities_y, length(yi))
append!(y, yi)
[ap_var(ap.in) .~ yi;
ap_var(ap.out) .~ ap_var(ap.in)], yi
ap_var(ap.out) .~ ap_var(ap.in)], yi
else # loop opening
[ap_var(ap.out) .~ 0;], []
end
Expand All @@ -444,19 +454,19 @@ for f in [:get_sensitivity, :get_comp_sensitivity, :get_looptransfer, :open_loop
end

function ModelingToolkit.linearize(sys, input::AnalysisPoint, output::AnalysisPoint;
kwargs...)
kwargs...)
ModelingToolkit.linearize(sys, nameof(input), nameof(output); kwargs...)
end

# Methods above are implemented in terms of linearization_function, the method below creates wrappers for linearize
for f in [:get_sensitivity, :get_comp_sensitivity, :get_looptransfer]
@eval function $f(sys,
ap,
args...;
loop_openings = nothing,
op = Dict(),
p = DiffEqBase.NullParameters(),
kwargs...)
ap,
args...;
loop_openings = nothing,
op = Dict(),
p = DiffEqBase.NullParameters(),
kwargs...)
lin_fun, ssys = $(Symbol(string(f) * "_function"))(sys, ap, args...; op, p,
loop_openings,
kwargs...)
Expand All @@ -472,7 +482,7 @@ Linearize a system between two analysis points. To get a loop-transfer function,
The output is allowed to be either an analysis-point name, or a vector of symbolic variables like the standard interface to `linearize`. The input must be an analysis-point name.
"""
function ModelingToolkit.linearize(sys, input_name::SymOrVec, output_name;
loop_openings = nothing, kwargs...)
loop_openings = nothing, kwargs...)
lin_fun, ssys = linearization_function(sys, input_name, output_name; loop_openings,
kwargs...)
ModelingToolkit.linearize(ssys, lin_fun; kwargs...), ssys
Expand Down
Loading