-
-
Notifications
You must be signed in to change notification settings - Fork 233
Closed
Labels
questionFurther information is requestedFurther information is requested
Description
I think this relates to my previous issues: #3043, and has some relationship to SciML/OrdinaryDiffEq.jl#2441.
- If I solve it without discrete events, it can be solved with the default solver, but if I use Rodas4() it shows "Unstable" and the solution is unsuccessful.
- If I solve it with discrete events, when I use the default solver, I get the error 'ERROR: UndefRefError: access to undefined reference'. Even if you then switch to another solver and run it again, the initialisation error remains. But if you use Rodas4() to solve the problem from the beginning, it will show "Unstable", the solver is not successful either.
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?
- Minimal Reproducible Example 👇
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 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), [description = "rotor speed", guess = 1.0]
vf(t)
tm(t)
p(t)
q(t)
_Id(t), [guess = 0.0]
_Iq(t), [guess = 0.0]
end
@parameters begin
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) ~ 0
D_t(vf) ~ 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, 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)]
# -------initialization of models--------
ini_eqs = [device_list[:syn].omega ~ 1,
device_list[:syn].tm - device_list[:syn].p - device_list[:syn].ra * (device_list[:syn]._Id^2 + device_list[:syn]._Iq^2) ~ 0,
device_list[:syn].bus.va ~ device_list[:syn].va0,
device_list[:syn].bus.vm ~ device_list[:syn].vm0]
# -------change the parameters of models--------
# -------Apply and clear fault in the models--------
u_temp_record = Dict{Int,Vector{Float64}}()
function affect1!(integ, u, p, ctx)
println("apply fault at t = ", integ.t)
if integ.ps[p.u] != ctx
integ.ps[p.u] = ctx
u_temp_record[1] = copy(integ.u[integ.differential_vars.==false])
end
end
function affect2!(integ, u, p, ctx)
println("clear fault at t = ", integ.t)
if integ.ps[p.u] != ctx
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)
# -------format the system to solve--------
prob = ODEProblem(test_system_init_simplify,[], (0,20),[]; guesses = u0_guess, initialization_eqs = ini_eqs, fully_determined = true, jac=true,sparse=true)
# sol = solve(prob, Rodas4(), tstops = [1.0,1.05])
sol = solve(prob, tstops = [1.0,1.05])
plot(sol)Environment (please complete the following information):
- Output of using Pkg; Pkg.status()
[6e4b80f9] BenchmarkTools v1.5.0
[336ed68f] CSV v0.10.14
[a93c6f00] DataFrames v1.7.0
[0c46a032] DifferentialEquations v7.14.0
[5789e2e9] FileIO v1.16.3
[961ee093] ModelingToolkit v9.41.0
[8913a72c] NonlinearSolve v3.14.0
[1dea7af3] OrdinaryDiffEq v6.89.0
[91a5bcdd] Plots v1.40.8
[0bca4576] SciMLBase v2.54.0
[37e2e46d] LinearAlgebra
[56ddb016] Logging
[2f01184e] SparseArrays v1.10.0
What I mean is that solving the problem with discrete event by default solver:
# -------simplify the system--------
test_system_init = ODESystem(eqs, t,[],[]; systems = collect(values(merge(device_list, Bus_Dict))), name = :test_system_init, discrete_events = reflect)
test_system_init_simplify = structural_simplify(test_system_init, fully_determined = true)
# -------format the system to solve--------
prob = ODEProblem(test_system_init_simplify,[], (0,2),[]; guesses = u0_guess, initialization_eqs = ini_eqs, fully_determined = true, jac=true,sparse=true)
sol = solve(prob, tstops = [1.0,1.05])The output:
apply fault at t = 1.0
apply fault at t = 1.0
ERROR: UndefRefError: access to undefined reference
if solving the problem with discrete event by Rodas4() solver:
# -------simplify the system--------
test_system_init = ODESystem(eqs, t,[],[]; systems = collect(values(merge(device_list, Bus_Dict))), name = :test_system_init, discrete_events = reflect)
test_system_init_simplify = structural_simplify(test_system_init, fully_determined = true)
# -------format the system to solve--------
prob = ODEProblem(test_system_init_simplify,[], (0,2),[]; guesses = u0_guess, initialization_eqs = ini_eqs, fully_determined = true, jac=true,sparse=true)
sol = solve(prob, Rodas4(), tstops = [1.0,1.05])The output:
Warning: At t=1.0e-6, dt was forced below floating point epsilon 2.117582368135751e-22, and step error estimate = 6.659475516269642. Aborting. There is either an error in your model specification or the true solution is unstable (or the true solution can not be represented in the precision of Float64).
retcode: Unstable
Interpolation: specialized 3rd order "free" stiffness-aware interpolation
Metadata
Metadata
Assignees
Labels
questionFurther information is requestedFurther information is requested