-
-
Notifications
You must be signed in to change notification settings - Fork 210
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
solving problem with discrete events #3068
Comments
Is this a bug? using ModelingToolkit, DifferentialEquations, Plots
using ModelingToolkit: t_nounits as t, D_nounits as D_t
# --------system models --------
@connector AcBus begin
@variables begin
vm(t) = 1.0
va(t) = 0.0
pin(t) = 0.0, [connect = Flow]
qin(t) = 0.0, [connect = Flow]
end
end
@mtkmodel Zipload_component begin
@parameters begin
u = 1,[description = "Enable Signal"]
g
b
end
@components begin
bus = AcBus()
end
@equations begin
bus.pin ~ u * ( g * bus.vm ^2)
bus.qin ~ u * (- b * bus.vm ^2)
end
end
@mtkmodel Piline_component begin
@parameters begin
u = 1 ,[description = "Enable Signal"]
rft
xft
g0 = 0.0
b0
tap_ratio = 1.0
gft = rft/(rft^2 + xft^2)
bft = -xft/(rft^2 + xft^2)
m_real = tap_ratio
m2 = tap_ratio^2
end
@components begin
bus_fr = AcBus()
bus_to = AcBus()
end
@equations begin
bus_fr.pin*m2 ~ u*( g0/2*bus_fr.vm^2 + gft*bus_fr.vm^2
- gft*m_real*bus_fr.vm*bus_to.vm*cos(bus_fr.va - bus_to.va)
- bft*m_real*bus_fr.vm*bus_to.vm*sin(bus_fr.va - bus_to.va))
-bus_fr.qin*m2 ~ u*(b0/2*bus_fr.vm^2 + bft*bus_fr.vm^2
- bft*m_real*bus_fr.vm*bus_to.vm*cos(bus_fr.va - bus_to.va)
+ gft*m_real*bus_fr.vm*bus_to.vm*sin(bus_fr.va - bus_to.va))
bus_to.pin*m2 ~ u*( g0/2*m2*bus_to.vm^2 + gft*m2*bus_to.vm^2
- gft*m_real*bus_fr.vm*bus_to.vm*cos(bus_fr.va - bus_to.va)
+ bft*m_real*bus_fr.vm*bus_to.vm*sin(bus_fr.va - bus_to.va))
-bus_to.qin*m2 ~ u*(b0/2*m2*bus_to.vm^2 + bft*m2*bus_to.vm^2
- bft*m_real*bus_fr.vm*bus_to.vm*cos(bus_fr.va - bus_to.va)
- gft*m_real*bus_fr.vm*bus_to.vm*sin(bus_fr.va - bus_to.va))
end
end
@mtkmodel Syn2_component begin
@components begin
bus = AcBus()
end
@variables begin
delta(t), [description = "rotor angle"]
omega(t) = 1.0, [description = "rotor speed"]
vf(t)
tm(t)
p(t)
q(t)
_Id(t) = 0.0
_Iq(t) = 0.0
end
@parameters begin
time_flag
u = 1, [description = "Enable Signal"]
fn
H
Damp
ra
xd1
Kw
Kp
iM = u / (2 * H)
c1 = ra / (ra^2 + xd1^2)
c2 = xd1 / (ra^2 + xd1^2)
c3 = c2
vm0
va0
end
@equations begin
_Id ~ u*(-(bus.vm * sin(delta - bus.va) * c1) - (bus.vm * cos(delta - bus.va) * c3) + c3 * vf)
_Iq ~ u*( (bus.vm * sin(delta - bus.va) * c2) - (bus.vm * cos(delta - bus.va) * c1) + c1 * vf)
p ~ bus.vm * sin(delta - bus.va) * _Id + bus.vm * cos(delta - bus.va) * _Iq
q ~ bus.vm * cos(delta - bus.va) * _Id - bus.vm * sin(delta - bus.va) * _Iq
bus.pin ~ -p # for AcBus
bus.qin ~ -q # for AcBus
D_t(delta) ~ u * 2 * π * fn * (omega - 1)
D_t(omega) ~ iM * (tm - p - ra * (_Id^2 + _Iq^2) - Damp * (omega - 1))
D_t(tm) + (time_flag<0)* (bus.va-va0) ~ 0
D_t(vf) + (time_flag<0)* (bus.vm-vm0) ~ 0
end
end
@mtkmodel Fault_component begin
@parameters begin
u = 0,[description="fault status"]
rf
xf
yg = rf/(rf^2 + xf^2)
yb = -xf/(rf^2 + xf^2)
end
@components begin
bus = AcBus()
end
@equations begin
bus.pin ~ u * yg * bus.vm^2
bus.qin ~ -u * yb * bus.vm^2
end
end
# -------colection of instances of models--------
Bus_Dict = Dict{Symbol,ODESystem}(Symbol(1)=>AcBus(;name = Symbol("Bus 1")),Symbol(2)=>AcBus(;name = Symbol("Bus 2")))
device_list::Dict{Symbol,ODESystem} = Dict(
:line => Piline_component(;name = :line, rft = 0.01,xft = 0.01,g0 = 0,b0 = 0.01,tap_ratio = 1.0),
:syn => Syn2_component(;name = :syn1, time_flag = -1, fn = 50.0, H = 1.0, Damp = 0.8, ra = 0.01, xd1 = 0.1, Kw=1.0, Kp=1.0, va0 = 0.0 , vm0=1.0),
:zipload => Zipload_component(;name = :zipload1, g = 1.0, b = 0.0),
:fault => Fault_component(;name = :fault, rf = 0.0, xf = 0.1)
)
# -------connection of models--------
eqs = [ connect(Bus_Dict[Symbol(1)], device_list[:syn].bus),
connect(Bus_Dict[Symbol(1)], device_list[:line].bus_fr),
connect(Bus_Dict[Symbol(1)], device_list[:fault].bus),
connect(Bus_Dict[Symbol(2)], device_list[:zipload].bus),
connect(Bus_Dict[Symbol(2)], device_list[:line].bus_to)]
# -------Apply and clear fault in the models--------
u_temp_record = Dict{Int,Vector{Float64}}()
function affect1!(integ, u, p, ctx)
if integ.ps[p.u] != ctx
println("apply fault at t = ", integ.t)
integ.ps[p.u] = ctx
u_temp_record[1] = copy(integ.u[integ.differential_vars.==false])
end
end
function affect2!(integ, u, p, ctx)
if integ.ps[p.u] != ctx
println("clear fault at t = ", integ.t)
integ.ps[p.u] = ctx
#offer the initial value of algebraic variables for the reinitialization
integ.u[integ.differential_vars.==false] = u_temp_record[1]
end
end
fault_function = [(t==1.0) => (affect1!, [], [device_list[:fault].u=>:u], [device_list[:fault].u], 1.0),
(t==1.05) => (affect2!, [], [device_list[:fault].u=>:u], [device_list[:fault].u], 0.0)]
# -------set the initial guessvalues of models--------
function set_ini_syn2(; ra, xd1)
pg0 = 1.0
qg0 = 0.0
vm0 = 1.0
va0 = 0.0
V = vm0 .* exp.(va0 .* 1im)
S = pg0 - qg0 .* 1im
I = S ./ conj.(V)
E = V + (ra + xd1 .* 1im) .* I
delta = imag(log.(E ./ abs.(E) + 0im))
delta0 = delta
omega0 = 1.0
# d- and q-axis voltages and currents
vdq = V .* 1im .* exp.(-delta .* 1im)
idq = I .* 1im .* exp.(-delta .* 1im)
vd = real(vdq)
vq = imag(vdq)
Id = real(idq)
Iq = imag(idq)
# mechanical torques/powers
tm0 = (vq + ra .* Iq) .* Iq + (vd + ra .* Id) .* Id
vf0 = vq + ra .* Iq + xd1 .* Id
return delta0, omega0, tm0, vf0, pg0, qg0
end
u0_guess = Dict(zip([device_list[:syn].delta, device_list[:syn].omega, device_list[:syn].tm, device_list[:syn].vf, device_list[:syn].p, device_list[:syn].q], set_ini_syn2(ra = 0.01, xd1 = 0.1)))
# -------simplify the system--------
test_system_init = ODESystem(eqs, t,[],[]; systems = collect(values(merge(device_list, Bus_Dict))), name = :test_system_init, discrete_events = fault_function)
test_system_init_simplify = structural_simplify(test_system_init, fully_determined = true)
test_system_xy0 = SteadyStateProblem(test_system_init_simplify, u0_guess; jac = true, sparse = true)
sol = DifferentialEquations.solve(test_system_xy0)
xy0_sol_dict = Dict{Symbolics.Num, Any}()
for var in unknowns(test_system_xy0.f.sys)
xy0_sol_dict[var] = sol[var]
end
for var in observed(test_system_xy0.f.sys)
xy0_sol_dict[var.lhs] = sol[var.lhs]
end
defaults(test_system_init_simplify)[device_list[:syn].time_flag] = 1
# -------format the system to solve--------
prob = ODEProblem(test_system_init_simplify, xy0_sol_dict, (0,20); fully_determined = true, jac=true,sparse=true)
# sol = solve(prob, Rodas4(), tstops = [1.0,1.05])
sol = solve(prob, dtmax = 0.01, tstops = [1.0,1.05])
plot(sol)
plot(sol.t,sol[device_list[:syn].delta])
plot(sol.t,sol[device_list[:syn].omega])
plot(sol.t,sol[device_list[:zipload].bus.vm]) But this way cannot work in the later version, because the way of initialisation has changed. But I do not know why I can not run my code after I modify that like the top side of this issue. When I run the above codes, the output of Pkg.status()
|
If nobody answers me, I would like to report that as a bug issue and close this one. This question is making me feel crazy. |
There's just a lot of extra things in here so it will take some time to narrow it down before we can give a reasonable response. Is everything in that script actually needed to reproduce the issue? The plotting stuff for example seems unnecessary. If you can simplify the issue you'll get a quicker response, otherwise it will have to wait until I have the time to simplify the issue. |
Thank you so much! Your response gives me the confidence to solve it. |
Yes it will definitely help, since someone has to simplify it. If I have to do it then I'll need to wait until I have a good chunk of time open, but if it's simplified I can pretty say what's going on. My guess from a quick look is that it's the initialization things being fixed in #2922 |
I am trying to simplify the cases above as follows: using ModelingToolkit, DifferentialEquations, Plots
using ModelingToolkit: t_nounits as t, D_nounits as D_t
# --------system models --------
@connector AcBus begin
@variables begin
vm(t), [guess = 1.0]
va(t), [guess = 0.0]
pin(t), [connect = Flow, guess = 0.0]
qin(t), [connect = Flow, guess = 0.0]
end
end
@mtkmodel Sys_component begin
@components begin
bus = AcBus()
end
@variables begin
delta(t), [guess = 0.1]
omega(t), [guess = 1.0]
tm(t),[guess = 1.0]
p(t),[guess = 1.0]
q(t),[guess = 0.0]
end
@parameters begin
fn
H
Damp
xd1
gl
va0
end
@equations begin
p ~ bus.vm * sin(delta - bus.va) * 1.05 / xd1
q ~ bus.vm * cos(delta - bus.va) * 1.05 / xd1 - bus.vm^2/ xd1
D_t(delta) ~ 2 * π * fn * (omega - 1)
D_t(omega) ~ (tm - p - Damp * (omega - 1))/(2 * H)
D_t(tm) ~ 0
bus.pin ~ -p + gl * bus.vm ^2
bus.qin ~ -q
end
end
@mtkmodel Fault_component begin
@parameters begin
u = 0,[description="fault status"]
yf
end
@components begin
bus = AcBus()
end
@equations begin
bus.pin ~ u * yf * bus.vm^2
bus.qin ~ 0
end
end
# -------colection of instances of models--------
Bus_Dict = Dict{Symbol,ODESystem}(Symbol(1)=>AcBus(;name = Symbol("Bus 1")))
device_list::Dict{Symbol,ODESystem} = Dict(
:syn => Sys_component(;name = :syn, fn = 50.0, H = 1.0, Damp = 0.8, xd1 = 0.1, gl = 1.0, va0 = 0.0),
:fault => Fault_component(;name = :fault, yf = 1.0)
)
# -------connection of models--------
eqs = [ connect(Bus_Dict[Symbol(1)], device_list[:syn].bus),
connect(Bus_Dict[Symbol(1)], device_list[:fault].bus)]
# -------initialization of models--------
ini_eqs = [device_list[:syn].omega ~ 1,
device_list[:syn].tm - device_list[:syn].p ~ 0,
device_list[:syn].bus.va ~ device_list[:syn].va0]
# -------Apply and clear fault in the models--------
u_temp_record = Dict{Int,Vector{Float64}}()
function affect1!(integ, u, p, ctx)
if integ.ps[p.u] != ctx
println("apply fault at t = ", integ.t)
integ.ps[p.u] = ctx
u_temp_record[1] = copy(integ.u[integ.differential_vars.==false])
end
end
function affect2!(integ, u, p, ctx)
if integ.ps[p.u] != ctx
println("clear fault at t = ", integ.t)
integ.ps[p.u] = ctx
#offer the initial value of algebraic variables for the reinitialization
integ.u[integ.differential_vars.==false] = u_temp_record[1]
end
end
fault_function = [(t==1.0) => (affect1!, [], [device_list[:fault].u=>:u], [device_list[:fault].u], 1.0),
(t==1.01) => (affect2!, [], [device_list[:fault].u=>:u], [device_list[:fault].u], 0.0)]
# -------simplify the system--------
test_system_init = ODESystem(eqs, t,[],[]; systems = collect(values(merge(device_list, Bus_Dict))), name = :test_system_init, discrete_events = fault_function)
test_system_init_simplify = structural_simplify(test_system_init, fully_determined = true)
# -------format the system to solve--------
prob = ODEProblem(test_system_init_simplify,[], (0,20),[]; initialization_eqs = ini_eqs, fully_determined = true, jac=true,sparse=true)
# sol = solve(prob, Rodas4()) # retcode:success without discrete events
sol = solve(prob, tstops = [1.0,1.01]) # ERROR: UndefRefError: access to undefined reference
# sol = solve(prob, Rodas4(), tstops = [1.0,1.01]) # retcoe: Unstable The output of Pkg.status()
This code can also reproduce the issue above, but it is not simple enough. |
When I am trying to narrow it down further, I face some other problems: using ModelingToolkit, DifferentialEquations, Plots
using ModelingToolkit: t_nounits as t, D_nounits as D_t
# --------system models --------
@mtkmodel Sys_component begin
@variables begin
delta(t), [guess = 0.1]
omega(t), [guess = 1.0]
tm(t), [guess = 1.0]
p(t), [guess = 1.0]
q(t), [guess = 0.0]
bus_vm(t), [guess = 1.0]
bus_va(t), [guess = 0.0]
end
@parameters begin
fn
H
Damp
xd1
gl
va0
u = 0,[description="fault status"]
yf
end
@equations begin
p ~ bus_vm * sin(delta - bus_va) * 1.05 / xd1
q ~ bus_vm * cos(delta - bus_va) * 1.05 / xd1 - bus_vm^2/ xd1
D_t(delta) ~ 2 * π * fn * (omega - 1)
D_t(omega) ~ (tm - p - Damp * (omega - 1))/(2 * H)
D_t(tm) ~ 0
0 ~ -p + gl * bus_vm ^2 + u * yf * bus_vm^2
0 ~ -q
end
@discrete_events begin
(t == 1.00) => [u ~ 1]
(t == 1.01) => [u ~ 0]
end
end
# -------simplify the system--------
sys = Sys_component(;name = :sys, fn = 50.0, H = 1.0, Damp = 0.8, xd1 = 0.1, gl = 1.0, va0 = 0.0, yf = 10.0)
test_system_init_simplify = structural_simplify(sys, fully_determined = true)
# -------initialization of models--------
ini_eqs = [sys.omega ~ 1,
sys.tm - sys.p ~ 0,
sys.bus_va ~ sys.va0]
# -------format the system to solve--------
prob = ODEProblem(test_system_init_simplify,[], (0,20),[]; initialization_eqs = ini_eqs, fully_determined = true, jac=true,sparse=true)
# sol = solve(prob, Rodas4())
sol = solve(prob, tstops = [1.0,1.01])
# sol = solve(prob, Rodas4(), tstops = [1.0,1.01]) After simplifying the system, it shows error in building ODEProblem step:
But there are 7 variables and 7 equations in total, why? |
I just check, this problem has been almost fixed in the latest version. Although I still don't know the reason of my last question, which indicates "The system is unbalanced", I will close this question. |
I think this relates to my previous issues: #3043, and has some relationship to SciML/OrdinaryDiffEq.jl#2441.
I am stuck with this problem for a long time, no matter I use the latest version 9.41.0 or the older version of the ModelingToolkit.
What should I do? Should I modify my codes? Or this is a bug?
Environment (please complete the following information):
What I mean is that solving the problem with discrete event by default solver:
The output:
if solving the problem with discrete event by Rodas4() solver:
The output:
The text was updated successfully, but these errors were encountered: