在 ODE 问题中使用复数 returns 不精确错误
Using Complex Numbers in ODE Problem returns Inexact Error
我正在尝试使用 Julia 为 n-Machine 系统实现 Swing 方程。
当我 运行 以下代码时,我收到此错误消息:
LoadError: InexactError: Float64(0.0 + 1.0im)
in expression starting at /home/Documents/first_try.jl:61
Swing_Equation(::Array{Float64,1}, ::Array{Float64,1}, ::Array{Float64,1}, ::Float64) at complex.jl:37
ODEFunction at diffeqfunction.jl:219 [inlined]
initialize!
出现问题是因为我使用的 du[3] = (u[3] * u[2]) * im
不能是 Float64
类型。当我删除 im
时代码工作正常 - 但它不再是我想要实现的模型。
有什么方法可以解决我的问题?
using Plots
using DifferentialEquations
inspectdr()
# Constants
P_m0 = 0.3 # constant Mechanical Power
P_emax = 1
H = 1.01 # Inertia constant of the system
θ_0 = asin(P_m0 / P_emax) # angle of the system
ω_0 = 1.0 # initial angular velocity
M = 2 * H / ω_0
D = 0.9 # Damping constant
u02 = [θ_0;ω_0] # Initial Conditions
tspan = (0.0,100.0) # Time span to solve for
p = [M;P_m0;D]
i = 3
function Swing_Equation(du,u,t,p) # u[1] = angle θ
du[1] = u[2] # u[2] = angular velocity ω
P_e = real(u[3] * conj(i))
du[2] = (1 / M) * ( P_m0 - P_e - D * u[2]) # du[2] = angular acceleration
du[3] = (u[3] * u[2]) * im
end
# solving the differential equations
prob2 = ODEProblem(Swing_Equation,u0,tspan,p)
print(prob2)
sol2 = solve(prob2)
# Visualizing the solutoins
plot(sol2; vars = 1, label = "Θ_kura", line = ("red"))
plot!(sol2; vars = 2, label = "ω_kura", line = ("blue"))
gui()
plot(sol2,vars = (1,2),label="Kurmamoto" ,line = ("purple"))
xlabel!("Θ")
ylabel!("ω")
gui()
问题很可能出在您的输入中。
prob2 = ODEProblem(Swing_Equation,u0,tspan,p)
我猜您在这部分中为 u0
提供了一个 Float64
的数组?然后,您的 Swing_Equation
会收到 u
作为 Array{Float64}
类型。我怀疑这也意味着 du
是一样的。
这导致表达式
du[3] = (u[3] * u[2]) * im
失败,因为您正试图将 Complex{Float64}
数字分配给类型为 Float64
的 du[3]
。然后 Julia 将尝试执行
convert(Float64, (u[3] * u[2]) * im)
这将导致不精确的错误,因为您无法将复数转换为浮点数。
解决方案是确保 du
和 u
是复数,从而避免这种转换。解决这个问题的一种快速而肮脏的方法是写:
prob2 = ODEProblem(Swing_Equation, collect(Complex{Float64}, u0),tspan,p)
这将收集 u0
中的所有元素并创建一个新数组,其中每个元素都是 Complex{Float64}
。然而,这假设一个一维数组。我不知道你的情况。我自己不使用 ODE 求解器。
避免此类问题的一般建议
在您的代码中添加更多类型断言,以确保您获得您期望的输入类型。这将有助于捕获此类问题,并让您更轻松地了解正在发生的事情。
function Swing_Equation(du::AbstractArray{T}, u::AbstractArray{T}, t,p) where T<:Complex # u[1] = angle θ
du[1] = u[2] :: Complex{Float64}
P_e = real(u[3] * conj(i))
du[2] = (1 / M) * ( P_m0 - P_e - D * u[2]) # du[2] = angular acceleration
du[3] = (u[3] * u[2]) * im
end
请记住,在匹配类型方面,Julia 比其他动态语言要求更高一些。这就是赋予它性能的原因。
在这种情况下,为什么 Julia 与 Python 不同?
Julia 不会将 Python 之类的类型升级到任何合适的类型。数组是有类型的。它们不能包含 Python 和其他动态语言中的任何内容。如果你例如制作了一个数组,其中每个元素都是一个整数,那么如果不先显式转换为浮点数,就不能为每个元素分配浮点值。否则,Julia 必须通过抛出异常来警告您出现了不准确的错误。
在 Python 中这不是问题,因为数组中的每个元素都可以是不同的类型。如果您希望 Julia 数组中的每个元素都是不同的数字类型,那么您必须将数组创建为 Array{Number}
类型,但这样效率很低。
希望对您有所帮助!
我正在尝试使用 Julia 为 n-Machine 系统实现 Swing 方程。 当我 运行 以下代码时,我收到此错误消息:
LoadError: InexactError: Float64(0.0 + 1.0im)
in expression starting at /home/Documents/first_try.jl:61
Swing_Equation(::Array{Float64,1}, ::Array{Float64,1}, ::Array{Float64,1}, ::Float64) at complex.jl:37
ODEFunction at diffeqfunction.jl:219 [inlined]
initialize!
出现问题是因为我使用的 du[3] = (u[3] * u[2]) * im
不能是 Float64
类型。当我删除 im
时代码工作正常 - 但它不再是我想要实现的模型。
有什么方法可以解决我的问题?
using Plots
using DifferentialEquations
inspectdr()
# Constants
P_m0 = 0.3 # constant Mechanical Power
P_emax = 1
H = 1.01 # Inertia constant of the system
θ_0 = asin(P_m0 / P_emax) # angle of the system
ω_0 = 1.0 # initial angular velocity
M = 2 * H / ω_0
D = 0.9 # Damping constant
u02 = [θ_0;ω_0] # Initial Conditions
tspan = (0.0,100.0) # Time span to solve for
p = [M;P_m0;D]
i = 3
function Swing_Equation(du,u,t,p) # u[1] = angle θ
du[1] = u[2] # u[2] = angular velocity ω
P_e = real(u[3] * conj(i))
du[2] = (1 / M) * ( P_m0 - P_e - D * u[2]) # du[2] = angular acceleration
du[3] = (u[3] * u[2]) * im
end
# solving the differential equations
prob2 = ODEProblem(Swing_Equation,u0,tspan,p)
print(prob2)
sol2 = solve(prob2)
# Visualizing the solutoins
plot(sol2; vars = 1, label = "Θ_kura", line = ("red"))
plot!(sol2; vars = 2, label = "ω_kura", line = ("blue"))
gui()
plot(sol2,vars = (1,2),label="Kurmamoto" ,line = ("purple"))
xlabel!("Θ")
ylabel!("ω")
gui()
问题很可能出在您的输入中。
prob2 = ODEProblem(Swing_Equation,u0,tspan,p)
我猜您在这部分中为 u0
提供了一个 Float64
的数组?然后,您的 Swing_Equation
会收到 u
作为 Array{Float64}
类型。我怀疑这也意味着 du
是一样的。
这导致表达式
du[3] = (u[3] * u[2]) * im
失败,因为您正试图将 Complex{Float64}
数字分配给类型为 Float64
的 du[3]
。然后 Julia 将尝试执行
convert(Float64, (u[3] * u[2]) * im)
这将导致不精确的错误,因为您无法将复数转换为浮点数。
解决方案是确保 du
和 u
是复数,从而避免这种转换。解决这个问题的一种快速而肮脏的方法是写:
prob2 = ODEProblem(Swing_Equation, collect(Complex{Float64}, u0),tspan,p)
这将收集 u0
中的所有元素并创建一个新数组,其中每个元素都是 Complex{Float64}
。然而,这假设一个一维数组。我不知道你的情况。我自己不使用 ODE 求解器。
避免此类问题的一般建议
在您的代码中添加更多类型断言,以确保您获得您期望的输入类型。这将有助于捕获此类问题,并让您更轻松地了解正在发生的事情。
function Swing_Equation(du::AbstractArray{T}, u::AbstractArray{T}, t,p) where T<:Complex # u[1] = angle θ
du[1] = u[2] :: Complex{Float64}
P_e = real(u[3] * conj(i))
du[2] = (1 / M) * ( P_m0 - P_e - D * u[2]) # du[2] = angular acceleration
du[3] = (u[3] * u[2]) * im
end
请记住,在匹配类型方面,Julia 比其他动态语言要求更高一些。这就是赋予它性能的原因。
在这种情况下,为什么 Julia 与 Python 不同?
Julia 不会将 Python 之类的类型升级到任何合适的类型。数组是有类型的。它们不能包含 Python 和其他动态语言中的任何内容。如果你例如制作了一个数组,其中每个元素都是一个整数,那么如果不先显式转换为浮点数,就不能为每个元素分配浮点值。否则,Julia 必须通过抛出异常来警告您出现了不准确的错误。
在 Python 中这不是问题,因为数组中的每个元素都可以是不同的类型。如果您希望 Julia 数组中的每个元素都是不同的数字类型,那么您必须将数组创建为 Array{Number}
类型,但这样效率很低。
希望对您有所帮助!