困難な振動積分の数値積分の方法


25

以下の積分を数値的に評価する必要があります。

0sinc(xr)rE(r)dr

ここで、、と。ここで、は第2種の修正ベッセル関数です。私の特定のケースでは、、およびです。のxR+λκν>0Kλ=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を使用していますが、組み込み関数integralおよびを試してみましたがquadgk、これにより多くのエラーが発生します(以下を参照)。私は当然、部品ごとの積分やからへの積分の加算など、他にも多くのことを試しました。K + 1 のx πkxπ(k+1)xπ

だから、次に試すべき方法について何か提案はありますか?

更新(追加の質問)
@Pedroのリンク先の論文を読みましたが、理解するのが難しいとは思いません。ただし、いくつか質問があります。

  • 説明した単変量レビン法でを基底要素として使用しても大丈夫でしょうか?ψ Kxkψ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
ペドロ

正の実数。投稿を更新しました。
torbonde

いくつかのコードとエラーを表示できれば、おそらくそれらのほとんどを解決するのはそれほど難しくありません。もちろん、最初にエラーを注意深く読んでみて、それを自分で消すことができるかどうかを確認してください。
デニスジャエルディン

本日後半に、いくつかのコードとエラーについてコメントします。または明日。
torbonde

さて、忘れてしまいました。しかし、今、私は例を使って投稿を更新しました(明示的に計算することで積分を2つに分割しました)。sinc
-torbonde

回答:


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

次に、両端のsをquadcc処理できる独自のインテグレーターを呼び出しNaNます。

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

誤差の見積もりは膨大であることに注意してください。つまりquadcc、結果にあまり自信がないことに注意してください。ただし、関数を見ると、実際の積分値の3桁上の値で振動するため、これは驚くことではありません。繰り返しますが、異なる間隔変換を使用すると、より良い結果が得られる場合があります。

また、このようなより具体的なメソッドを参照することもできます。それはもう少し複雑ですが、間違いなくこのタイプの問題には正しい方法です。


どうもありがとうございました。さまざまな方法を見ていきます。私の目的では、エラーはeqの標準integral(1e-10と思う)ほど小さくする必要はありませんが、1.7e + 07はまだ本当に大きいです。あなたが言及したように、おそらく別の変換がうまくいくでしょう。
-torbonde

@ cimrg.joe:エラー推定値は、とりわけ被積分関数の最大絶対値に基づいた絶対誤差の推定値であることに注意してください。極端な場合、返される値は実際にはまったく問題ない場合があります。10桁の精度をお探しの場合は、投稿の最後で述べたレビン型の方法を使用することを強くお勧めします。
ペドロ

10桁の精度は必要ないかもしれませんが、少なくとも5桁は必要だと思います。メソッドはそれを生成できますか?
-torbonde

区間の右端の値は積分自体よりも数桁大きいため、この方法では積分の種類の精度を保証できません。
ペドロ

11

ペドロが指摘しているように、レビン型の方法は、この種の問題に対して最も確立された方法です。

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までのプロット

また、適用する特定のレビン型の方法を手動で指定することもできます。この場合、パフォーマンスがわずかに向上します。

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のレビン型メソッドの詳細については、ドキュメントを参照してください


残念ながら、私はMathematicaにアクセスできません-MATLABのみです。@Pedroにリンクされている論文に関する質問をいくつか追加して、質問を更新します。
-torbonde

あなたが言うように、Matlabで間に合わせる必要があります。それについて別の答えを追加します。
アンドリューモイラン

5

Mathematicaにアクセスできない場合は、Pedroが示唆するように、Matlabでレビン型(または他の特殊な振動)メソッドを書くことができます。

Matlabにchebfunライブラリを使用していますか?ここに、基本的なレビン型メソッドの実装が含まれていることを学びました。実装は、Olver(振動求積法分野の専門家の1人)によって書かれています。それは特異点、適応細分化などを扱いませんが、始めるために必要なものだけかもしれません。


私は自分でレビン法を実装することを考えましたが、私はまだ挑戦に立ち上がっているかどうかわかりません。この方法をもう少しよく理解する必要があると思います。たぶん私はそれについて私の顧問に話すことができました。とにかく、私がFilonメソッドについて尋ねた理由は、それらが実装しやすいように見えることです。私は非常に高い精度を必要としないが、これは私の修士論文の一部であるので、難易度は中重量を量る。
torbonde

私はchebfunライブラリー(これは印象的です)とLevin統合の例を見てきました。しかし、私はそれを実行させることはできません。私は実際にそれに関する質問をここに投稿しました
-torbonde

0

Pedroが推奨する変換は素晴らしいアイデアです。Matlabの「quadgk」関数のパラメーターをいじってみましたか?たとえば、ペドロの変換を使用して、次の操作を行うことができ
quadgk(f, 0.0+eps, 1.0-eps, 'AbsTol', eps, 'MaxIntervalCount', 100000)
、これを使用すると、私の解決策を与える:
-2184689.50220729
とわずか0.8秒かかります(上記の値を使用します。x = 10)
ウォルター・ガンダーとウォルター・ガウツシーは、MATLABに適応直角に紙を持っています同様に使用できるコード(リンクはこちら

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.