高度に振動する積分の数値評価


11

複素関数論のアプリケーションでは、この上級コースの演習の高い振動不可欠で1ポイントで

I(λ)=cos(λcosx)sinxxdx

複素平面で点法を使用して、λ大きな値に対して近似する必要があります。

振動性が高いため、この積分は他のほとんどの方法を使用して評価するのは非常に困難です。これらは、異なるスケールでのλ=10被積分関数のグラフの2つのフラグメントです。

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

一次漸近近似は

I1(λ)=cos(λ14π)2πλ

そして、さらに(はるかに小さい)改良が用語を追加します

I2(λ)=18sin(λ14π)2πλ3

λ関数としての近似値のグラフは次のようになります。

I(ラム​​ダ)約

ここで質問が来ます。近似がどれほど良いかを視覚的に見るために、積分の「実際の値」と比較するか、より正確には独立したアルゴリズムを使用して同じ積分の良い近似と比較したいと思います。サブリーディング補正の小ささにより、これは非常に近いものになると予想されます。

λtanh(sinh)

mpmathおおよそ

最後に、実装した重要度サンプルを使用してモンテカルロインテグレーターで運を試しましたが、安定した結果を得ることができませんでした。

λ>1


機能は均等ですか?
ニコグアロ

はい、そうです
doetoe

積分をODEに変えてみましたか?
ニコグアロ

1
x

1
λλxx(cos(λxcosx)sincx)

回答:


12

この積分を評価するには、プランシュレルの定理を使用してください。

f,g

I=f(x)g(x)dx=F(k)G(k)dk

F,Gf,gsinx/xrect(k)cos(λcosx)λ|Jn(x)|n>|x|

πJ0(λ)[0,2π]


おかげで、これは非常に良いアイデアです!
-doetoe

7

πN+π2

漸近

I(λ)2πλ[cos(λπ4)+c1sin(λπ4)λ+c2cos(λπ4)λ2+c3sin(λπ4)λ3+]
c1=18

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=9128,c3=751024,c4=367532768,

説明

簡単な例

S(x)=0xsin(y)ydy.
S()=π2

正弦

S(x)

SN=n=1N(1)nn.
SSN+12(1)N+1N+1.
S(x)0πN+π2sinxxdx
max|S(x)|

あなたの問題

Ix0(λ)=20x0cos(λcos(x))sinc(x)dx
x0=πN+π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

SN=12(SN+SN+1)
SN


いいね!コースの講師はあなたの実際の教授ですか?彼らのコースは素晴らしいですが、非常にタフで速いペースです
-doetoe

@doetoeはい、私はコンスタンチンの学生です。彼はあなたの質問へのリンクを私と共有しました。
デビッドセイキン

6

フーリエ正弦積分のためのOouraの方法はここで機能します。

大浦、卓也、森正武、フーリエ型積分のロバストな二重指数公式。計算および応用数学のジャーナル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では、被積分関数からのsin(x)因子なしでcos(lambda * cos(x))/ xがあります。この要素sin(x)に渡される被積分関数を乗算すると仮定するのはooura_fourier_sinですか?
-doetoe

うまくいきました。それとその依存関係はすべてヘッダーのみであるように見えるので、インストールまたはコンパイルする必要さえありませんでした(実行可能ファイルを除く)。ブーストに含まれることを願っています!
-doetoe

sin(x)

@doetoe:Boost 1.71に統合されました。APIは、この答えが与えるものとは少し異なります。
user14717
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.