首页 > 解决方案 > Julia:如何更改 Bessel 函数中参数的类型?

问题描述

这是我的代码:

using Plots
using SpecialFunctions
using QuadGK

kappa = 1
B = 1
xi = (kappa/B)^4

function correlation(x)
    quadgk(q -> q * SpecialFunctions.besselj0(x*q)/(q^4 + xi), 0, 1e6)[1]/kappa 
end

r = range(-20, 20, length = 1001)

plot(r, correlation(r))

我在 Bessel 函数上遇到错误。我知道参数是问题所在,它的格式应该是::BigFloat, ::Float16, or ::Float32,但我不知道该怎么做。我尝试改写x .* q,但问题仍然存在,我收到错误:

ERROR: MethodError: no method matching besselj0(::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}})

另外,我正在寻找一种方法来编写 +infinity 而不是1e6.

标签: julia

解决方案


只需在您的代码中替换correlation(r)correlation.(r)使用广播,如此处所述

您的问题的核心是 Julia 函数默认情况下不可广播 - 您通常必须选择加入它(尤其是当您使用数字代码时)。这是一个基本示例:

julia> sin(1)
0.8414709848078965

julia> sin([1])
ERROR: MethodError: no method matching sin(::Array{Int64,1})
Closest candidates are:
  sin(::BigFloat) at mpfr.jl:727
  sin(::Missing) at math.jl:1197
  sin(::Complex{Float16}) at math.jl:1145
  ...
Stacktrace:
 [1] top-level scope at REPL[2]:1

julia> sin.([1])
1-element Array{Float64,1}:
 0.8414709848078965

但是,在您的情况下,该correlation功能非常昂贵。在这种情况下,我通常使用 ProgressMeter.jl 来监控计算的进度(它显示了计算可以完成多长时间)。所以你可以写:

using ProgressMeter
result = @showprogress map(correlation, r)

并使用该map函数将correlation函数应用于所有元素r(在这种情况下,结果将与广播相同)。

最后,如果您不在quadgk. 最好将kappaxi作为参数传递给函数,如下所示:

function correlation(x, kappa, xi)
    quadgk(q -> q * SpecialFunctions.besselj0(x*q)/(q^4 + xi), 0, 1e6)[1]/kappa 
end

result = @showprogress map(x -> correlation(x, kappa, xi), r)

推荐阅读