难振荡积分的数值积分方法


25

我需要对以下积分进行数值评估:

0sinc(xr)rE(r)dr

其中,和。在这里,是第二种修改的贝塞尔函数。在我的特定情况下,我有,和。X[R+λκν>0ķλ=0.00313κ=0.00825ν=0.33E(r)=r4(λκ2+r2)ν5/2Kν5/2(λκ2+r2)xR+λ,κ,ν>0Kλ=0.00313κ=0.00825ν=0.33

我正在使用MATLAB,并且尝试了内置函数integralquadgk,这给了我很多错误(请参见下文)。我自然也尝试了许多其他事情,例如按部分积分,以及将到积分求和。ķ + 1 X πkxπ(k+1)xπ

那么,对于我接下来应该尝试哪种方法,您有任何建议吗?

更新(添加的问题)
我阅读了@Pedro链接的论文,我认为这太难理解了。但是,我有几个问题:

  • 会是好使用为基础元素描述的,在单变量莱方法?ψ ķxkψk
  • 因为振荡的频率是固定的,我可以只使用Filon方法吗?

范例程式码
>> integral(@(r) sin(x*r).*sqrt(E(r)),0,Inf)
Warning: Reached the limit on the maximum number of intervals in use. Approximate
bound on error is 1.6e+07. The integral may not exist, or it may be difficult to
approximate numerically to the requested accuracy.
> In funfun\private\integralCalc>iterateScalarValued at 372
In funfun\private\integralCalc>vadapt at 133
In funfun\private\integralCalc at 84
In integral at 89

ans =

3.3197e+06


什么是在您的积分?x
Pedro

任何正数,实数。我刚刚更新了我的帖子。
torbonde

如果您可以显示一些代码和错误,则解决它们中的大多数可能并不难。当然,请先尝试仔细阅读该错误,然后看看是否可以自行消失。
丹尼斯·贾赫鲁丁

今天晚些时候,我将对一些代码和错误发表评论。或者明天。
torbonde

好吧,我忘了。但是现在我用一个示例更新了我的帖子(我通过显式计算将积分一分为二)。sinc
torbonde

Answers:


12

我已经编写了自己的积分器,quadcc它的奇异性比Matlab积分器要好得多,并且可以提供更可靠的误差估计。

要将其用于您的问题,我做了以下工作:

>> lambda = 0.00313; kappa = 0.00825; nu = 0.33;
>> x = 10;
>> E = @(r) r.^4.*(lambda*sqrt(kappa^2 + r.^2)).^(-nu-5/2) .* besselk(-nu-5/2,lambda*sqrt(kappa^2 + r.^2));
>> sincp = @(x) cos(x)./x - sin(x)./x.^2;
>> f = @(r) sincp(x*r) .* r .* sqrt( E(r) );

f现在,该功能就是您的被积分。请注意,我刚刚为分配了任何旧值x

为了集成到无限域中,我应用了变量的替换:

>> g = @(x) f ( tan ( pi / 2 * x ) ) .* ( 1 + tan ( pi * x / 2 ).^2 ) * pi / 2;

gfg

然后,我叫自己的积分器,quadcc可以NaN在两端处理s:

>> [ int , err , npoints ] = quadcc( g , 0 , 1 , 1e-6 )
int =
  -1.9552e+06
err =
   1.6933e+07
npoints =
       20761

请注意,误差估计很大,即quadcc对结果没有太大的信心。但是,从函数上看,这并不奇怪,因为它在比实际积分高三个数量级的值上振荡。同样,使用不同的间隔变换可能会产生更好的结果。

您可能还想看看更具体的方法,例如this。它涉及更多,但绝对是解决此类问题的正确方法


非常感谢你。我将看看不同的方法。出于我的目的,该误差不必像eq中的标准误差那样小integral(我认为是1e-10),但是1.7e + 07仍然非常大。正如您所提到的,也许另一个转换会很好。
torbonde

@ cimrg.joe:请注意,误差估计是绝对误差的估计,其中除其他外,其基于被积物的最大绝对值。在某些极端情况下,返回值实际上可能还不错。如果您要寻找十位数的准确性,那么我强烈建议您使用我在文章末尾提到的Levin型方法。
佩德罗(Pedro)

我也许不需要十位数,但我认为至少需要五位数。您的方法可以产生这种结果吗?
torbonde

该方法不能保证积分的精度,因为间隔右端的值比积分本身大几个数量级。
Pedro

11

正如Pedro所指出的那样,Levin型方法是解决此类问题的最佳方法。

您可以使用Mathematica吗?对于此问题,Mathematica将默认检测并使用它们:

In[1]:= e[r_] := 
 r^4 (l Sqrt[k^2 + r^2])^(-v - 5/2) BesselK[-v - 5/2, l Sqrt[k^2 + r^2]]

In[2]:= {l, k, v} = {0.00313, 0.00825, 0.33};

In[3]:= Block[{x = 10}, 
 NIntegrate[Sinc'[x r] r Sqrt[e[r]], {r, 0, \[Infinity]}, 
  PrecisionGoal -> 3]]

Out[3]= -112494.

这是x值范围内的图:

In[4]:= ListLinePlot[
 Table[NIntegrate[Sinc'[x r] r Sqrt[e[r]], {r, 0, \[Infinity]}, 
   PrecisionGoal -> 3], {x, .5, 10, 0.1}]]

从x = 0.5到x = 10的图

您还可以手动指定要应用的特定Levin类型方法,在这种情况下,可以稍微改善性能:

In[5]:= method = {"LevinRule", "Kernel" -> {Cos[r x], Sin[r x]}, 
   "DifferentialMatrix" -> {{0, -x}, {x, 0}}, 
   "Amplitude" -> {(
     3497.878840962873` Sqrt[(
      r^4 BesselK[-2.17`, 
        0.00313` Sqrt[
         0.00006806250000000001` + r^2]])/(0.00006806250000000001` + 
        r^2)^1.415`])/
     x, -((3497.878840962873` Sqrt[(
       r^4 BesselK[-2.17`, 
         0.00313` Sqrt[
          0.00006806250000000001` + r^2]])/(0.00006806250000000001` + 
         r^2)^1.415`])/(r x^2))}, "AdditiveTerm" -> 0};

In[6]:= Block[{x = 10}, 
 NIntegrate[Sinc'[x r] r Sqrt[e[r]], {r, 0, \[Infinity]}, 
  PrecisionGoal -> 3, Method -> method]]

Out[6]= -112495.

有关Mathematica中Levin型方法的详细信息,请参见文档。


不幸的是,我无权访问Mathematica-只有MATLAB。我将使用与链接到@Pedro的论文有关的其他一些问题来更新我的问题。
torbonde

好的,正如您所说,您必须使用Matlab。我将为此添加另一个答案。
Andrew Moylan

5

如果您无权使用Mathematica,则可以按照Pedro的建议在Matlab中编写Levin型(或其他专门的振荡方法)。

您是否为Matlab 使用chebfun库?我刚刚得知它包含了一个基本的莱型方法的实现在这里。该实现由Olver(振荡正交领域的专家之一)编写。它不涉及奇异性,自适应细分等,但是可能正是您入门所需的内容。


我曾考虑过自己实施Levin方法,但不确定是否要迎接挑战。我想我需要更好地了解该方法。也许我可以和我的顾问谈谈。无论如何,我问有关Filon方法的原因是,它们似乎更易于实现。而且因为我并不需要极高的精度,但是这是我的硕士论文的一部分,困难重英寸
torbonde

我看了一下chebfun库(令人印象深刻)和Levin集成示例。但是我无法运行它。我实际上已经在这里发布了一个关于它的问题。
torbonde

0

佩德罗(Pedro)建议的转型是一个好主意。您是否尝试过使用Matlab的“ quadgk”函数中的参数?例如,使用Pedro变换,您可以执行以下操作:
quadgk(f, 0.0+eps, 1.0-eps, 'AbsTol', eps, 'MaxIntervalCount', 100000)
使用该解决方案,我得到了:
-2184689.50220729
并且仅需0.8秒(使用上述值:x = 10)
Walter Gander和Walter Gautschi撰写了一篇有关Matlab自适应正交的论文您也可以使用的代码(在此处链接)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.