高振荡积分的数值评估


11

这一高级课程中,复杂函数理论在一次练习中的应用是高度振荡的

一世λ=-cosλcosXXXdX

对于大的λ值,必须使用鞍点法在复平面中进行近似。

由于其高度振荡的性质,使用大多数其他方法很难评估该积分。这是λ=10时不同比例的积分图的两个片段:

cos(10 cos(x))sin(x)/ x

前导渐近逼近为

一世1个λ=cosλ-1个4π2πλ

进一步(小得多)的改进增加了术语

一世2λ=1个8λ-1个4π2πλ3

近似值与λ如下:

I(λ)约

现在是我的问题:为了直观地看到近似值,我想将其与积分的“实际值”进行比较,或更准确地说,是使用独立算法将其与相同积分的近似值进行比较。由于次要修正的规模很小,我希望这确实很接近。

我尝试使用其他算法评估某些λ的积分,但收效甚微:使用默认数值积分器的Mathematica和Matlab未能产生有意义的值(并明确报告此值),而mpmath则同时使用了双指数替换和Gauss-Legendre方法产生非常嘈杂的结果,尽管它确实有轻微的趋势围绕鞍点方法给出的值振荡,如下图所示:

约mmpath

最终,我使用实现的重要性样本与蒙特卡洛积分器进行了碰碰运气,但我也未能获得任何稳定的结果。

有谁知道如何对λ > 1的任何固定值独立地求积分λ>1个左右的?


功能是否均匀?
nicoguaro

是的,甚至
doetoe

您是否尝试过将积分转换为ODE?
nicoguaro

1
不,微分,然后数值求解微分方程。X
nicoguaro

1
您的第一张图似乎显示出与被积函数不同的功能。也就是说,它似乎已经替换为λ X。即,曲线图是函数的X COS λ X COS X 的sinc X λλXXcosλXcosX辛克X
鲁斯兰

Answers:


12

利用 Plancherel定理评估该积分。

基本思想是,对于两个函数FG

一世=-FXGXdX=-FķGķdķ

其中FGFG的傅立叶变换。您的函数在频谱域中的支持都相对较小。这里,X/X直肠ķcosλcosX应具有的分析傅里叶变换(或系列),如雅可比-愤怒膨胀。您可以在大约截断无穷级数λ而言,由于贝塞尔函数的超指数衰减|ĴñX|ñ>|X|。希望这可以帮助。

编辑:实际上,您应该在此处使用傅立叶级数表示法而不是进行变换。变换路径通向推导渐近表示你已经有了(事实证明这仅仅是πĴ0λ)。Plancherel定理上述方法也适用于傅里叶级数与积分域[02π]上的最后一个积分。


谢谢,这是一个非常好的主意!
doetoe

7

评估振荡积分的关键是在正确的位置截断积分。对于此示例,您需要选择表格的上限

πñ+π2
在解释为什么它应该起作用之前,首先让我表明它实际上产生了良好的效果。

渐近性

很容易猜想,渐近级数的形式为

一世λ2πλ[cosλ-π4+C1个λ-π4λ+C2cosλ-π4λ2+C3λ-π4λ3+]
为了数值上检查C1个=1个8足以绘制出积分和前渐近表达之间的差异。

int := NIntegrate[Cos[l*Cos[x]]*Sinc[x], {x, 0, 20.5*Pi}]; 
Plot[{l*(Sqrt[2*l/Pi]*int - Cos[l-Pi/4]), Sin[l-Pi/4]/8}, {l, Pi/4, 20}]

作为输出,您会得到一个很好的正弦,与您上面导出的正弦一致。

18岁

如果要查找以下系数,则需要一些更复杂的代码。以下代码的想法是采用几个较高的上限值并将其结果“平均”。

J[l_?NumericQ] := Block[{n=500},
  f[k_] := NIntegrate[Cos[l*Cos[x]]*Sinc[x], {x,0,(n+k)*Pi+Pi/2},
  Method->{"DoubleExponential"}, AccuracyGoal->14, MaxRecursion->100];
  1/2*((f[0]+f[1])/2+(f[1]+f[2])/2)
]
t = Table[{l, l^2*(Sqrt[2*l/Pi]*J[l] - Cos[l-Pi/4] - 1/8*Sin[l-Pi/4]/l)}, 
    {l, 4*Pi+Pi/4, 12*Pi+Pi/4, Pi/36}];
Fit[t, Table[Cos[l-Pi/4+Pi/2*n]/l^n, {n, 0, 10}], l]

C2=-9128C3=-751024C4=367532768

说明

简单的例子

小号X=0Xÿÿdÿ
小号=π2

正弦

小号X

小号ñ=ñ=1个ñ-1个ññ
小号小号ñ+1个2-1个ñ+1个ñ+1个
小号X0πñ+π2XXdX
最大值|小号X|

你的问题

一世X0λ=20X0cosλcosX辛克XdX
X0=πñ+π2λ=12π

tab = Table[{x0, 2*NIntegrate[Cos[12*Pi*Cos[x]]*Sinc[x], {x, 0, x0}, 
     Method->{"DoubleExponential"}, AccuracyGoal->12, MaxRecursion->100]},
    {x0, 10*Pi+Pi/2, 30*Pi+Pi/2, Pi}];
tab1 = Table[(tab[[i]] + tab[[i+1]])/2, {i,1,Length[tab]-1}];
ListPlot[{tab, tab1}]

acc

小号ñ=1个2小号ñ+小号ñ+1个
小号ñ


真好!该课程的讲师是您的真实教授吗?他们的历程很棒,虽然非常艰难而且节奏很快
doetoe

@doetoe是的,我是康斯坦丁的学生。他与我分享了您的问题链接。
大卫·赛金

6

Ooura的傅里叶正弦积分方法在这里有效,请参见:

Ooura,Takuy​​a和Masatake Mori,傅立叶型积分的鲁棒双指数公式。计算与应用数学学报112.1-2(1999):229-241。

我编写该算法的实现,但从未投入工作以使其快速(通过缓存节点/权重),但是尽管如此,我在浮动精度之外的所有方面都得到了一致的结果:

float     = 0.0154244
double    = 0.943661538060268
long dbl  = 0.943661538066058702
quad      = 0.943661538066060288748574485677942
oct       = 0.943661538066060288748574485680878906503533004997613278231689169604876
asymptotic= 0.944029734

这是代码:

#include <iostream>
#include <boost/math/quadrature/ooura_fourier_integrals.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/multiprecision/float128.hpp>
#include <boost/multiprecision/cpp_bin_float.hpp>

template<class Real>
Real asymptotic(Real lambda) {
    using std::sin;
    using std::cos;
    using boost::math::constants::pi;
    Real I1 = cos(lambda - pi<Real>()/4)*sqrt(2*pi<Real>()/lambda);
    Real I2 = sin(lambda - pi<Real>()/4)*sqrt(2*pi<Real>()/(lambda*lambda*lambda))/8;
    return I1 + I2;
}

template<class Real>
Real osc(Real lambda) {
    using std::cos;
    using boost::math::quadrature::ooura_fourier_sin;
    auto f = [&lambda](Real x)->Real { return cos(lambda*cos(x))/x; };
    Real omega = 1;
    Real Is = ooura_fourier_sin<decltype(f), Real>(f, omega);
    return 2*Is;
}

template<class Real>
void print(Real val) {
   std::cout << std::defaultfloat;
   std::cout << std::setprecision(std::numeric_limits<Real>::digits10);
   std::cout <<  val <<  " = " << std::hexfloat << val;
}

int main() {
    using boost::multiprecision::float128;
    float128  s = 7;
    std::cout << "Asymptotic = " << std::setprecision(std::numeric_limits<float128>::digits10) << asymptotic(s) << "\n";
    std::cout << "float precision = ";
    print(osc(7.0f));
    std::cout << "\n";
    std::cout << "double precision= ";
    print(osc(7.0));
    std::cout << "\n";
    std::cout << "long double     = ";
    print(osc(7.0L));
    std::cout << "\n";
    print(osc(s));

    print(osc(boost::multiprecision::cpp_bin_float_oct(7)));
    std::cout << "\n";
}

λ0在此处输入图片说明


谢谢,这真的很好!我尚未使它工作,我的增强安装不兼容,但是我现在正在下载最新版本。
doetoe

可以肯定的是:在23中,您有cos(lambda * cos(x))/ x,而没有被积数的sin(x)因子。是ooura_fourier_sin假设这个因子sin(x)乘以传递给它的被积数吗?
doetoe

我知道了 它及其依赖项似乎都只是标头,因此我什至不必安装或编译(可执行文件除外)。我希望它会被包含进来!
doetoe

X

@doetoe:它已合并到Boost 1.71中。API与此答案给出的有点不同。
user14717
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.