Skip to content

Commit

Permalink
Merge pull request #261 from SciML/myb/ap
Browse files Browse the repository at this point in the history
Define `isconnection` on AnalysisPoint
  • Loading branch information
YingboMa authored Feb 22, 2024
2 parents f5e0548 + cc61d77 commit 8abd6d7
Show file tree
Hide file tree
Showing 52 changed files with 717 additions and 655 deletions.
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

0 comments on commit 8abd6d7

Please sign in to comment.