NIntegrate :: ncvb:NIntegrateが規定の精度に収束できませんでした

Dec 14 2020

統合は次のとおりです。

NIntegrate[-0.17116940940118283` + 1/(
  9.736942322213501` + 7.789553857770802` Cos[q]) + (
  0.02866566930866079` (0.5` + 1.` Cos[q]) Sin[
    q] (-3.0095696738628313` Sqrt[1.25` + 1.` Cos[q]]
       Cos[0.` + ArcTan[(0.5` Sin[q])/(-1 - 0.5` Cos[q])]] + 
     1.` Sin[q]))/(
  0.9772727272727273` + 1.` Cos[q] - 0.045454545454545456` Cos[2 q] - 
   0.09090909090909091` Cos[3 q]) + ((0.35586923225834494` + 
     0.5931153870972414` Cos[q] + 0.11862307741944829` Cos[2 q]) Sin[
    0.` + ArcTan[(0.5` Sin[q])/(-1 - 0.5` Cos[q])]])/((1.75` + 
     1.` Cos[q] - 0.5` Cos[2 q])^(3/2) Sqrt[
   1 - (1.` Sin[q]^2)/(
    1.75` + 1.` Cos[q] - 0.5000000000000001` Cos[2 q])]), {q, -Pi, 
  Pi}]

。エラーメッセージは

NIntegrate :: ncvb:{q} = {-3.14159254089972008785892145083358745552559732061581598827615380287}の近くのqで9回の再帰的二分法を実行した後、NIntegrateは規定の精度に収束できませんでした。NIntegrateは、積分および誤差の推定値として-1.249 10 ^ -16および4.588053980254483` ^ -13を取得しました。**

実際の統合値を取得するにはどうすればよいですか?

回答

6 MarcoB Dec 14 2020 at 23:17

実際にある積分の値を計算する問題を解決するには $0$、Andrew Moylanがこの前の質問で述べたようにAccuracyGoal、デフォルト値(Infinity)よりも低い値を設定できます。「積分の真の値がゼロの場合、デフォルトは決して満たされません。そのような場合は有限を設定する必要があります。"。PrecisionGoalAccuracyGoal

expr明確にするために被積分関数を定義すると、以下はエラーを返しません。

NIntegrate[expr, {q, -Pi, Pi}, AccuracyGoal -> 10]

(* Out: 1.66533*10^-16 *)

参照:

  • 答えがゼロのときはいつでも数値積分に時間がかかりすぎる
  • NIntegrateをFindRootに収束するためのエラー
  • 統合の問題
4 UlrichNeumann Dec 14 2020 at 14:30

またNDSolve、回避策として次のように評価されます~0

expr = -0.17116940940118283` +1/(9.736942322213501` +7.789553857770802` Cos[q]) + (0.02866566930866079` (0.5` + 1.` Cos[q]) Sin[q] (-3.0095696738628313` Sqrt[1.25` + 1.` Cos[q]] Cos[0.` + ArcTan[(0.5` Sin[q])/(-1 - 0.5` Cos[q])]] +1.` Sin[q]))/(0.9772727272727273` + 1.` Cos[q] -0.045454545454545456` Cos[2 q] -0.09090909090909091` Cos[3 q]) + ((0.35586923225834494` +0.5931153870972414` Cos[q] +0.11862307741944829` Cos[2 q]) Sin[0.` + ArcTan[(0.5` Sin[q])/(-1 - 0.5` Cos[q])]])/((1.75` +1.` Cos[q] - 0.5` Cos[2 q])^(3/2) Sqrt[1 - (1.` Sin[q]^2)/(1.75` + 1.` Cos[q] -0.5000000000000001` Cos[2 q])]) 
// Rationalize;

NDSolveValue[{int'[q] == expr, int[-Pi] == 0}, int[Pi], {q, -Pi, Pi},AccuracyGoal -> 15]
(*-3.79922*10^-8*)

ゼロの整数値を示します!

3 Andreas Dec 14 2020 at 22:33

積分の真の値がゼロの場合、NIntegrateで問題が発生する可能性があります。エラーメッセージは、これを収束問題の考えられる理由として引用しています。回避策として、被積分関数に1を加算し、最後に2Piを減算することができます。

NIntegrate[-0.17116940940118283 + 
1/(9.736942322213501 + 7.789553857770802*Cos[q]) + 
   (0.02866566930866079*(0.5 + 1.*Cos[q])*
  Sin[q]*(-3.0095696738628313*Sqrt[1.25 + 1.*Cos[q]]*
     Cos[0. + ArcTan[(0.5*Sin[q])/(-1 - 0.5*Cos[q])]] + 
           1.*Sin[q]))/(0.9772727272727273 + 1.*Cos[q] - 
  0.045454545454545456*Cos[2*q] - 
  0.09090909090909091*Cos[3*q]) + 
   ((0.35586923225834494 + 0.5931153870972414*Cos[q] + 
    0.11862307741944829*Cos[2*q])*
  Sin[0. + ArcTan[(0.5*Sin[q])/(-1 - 0.5*Cos[q])]])/
     ((1.75 + 1.*Cos[q] - 0.5*Cos[2*q])^(3/2)*
  Sqrt[1 - (1.*Sin[q]^2)/(1.75 + 1.*Cos[q] - 
       0.5000000000000001*Cos[2*q])]) + 1, {q, -Pi, Pi}] - 2*Pi

編集:私はすべての数値を合理化し、WorkingPrecisionをより高い値に設定できるようになりました:

NIntegrate[-(17116940940118283/100000000000000000) + 
 1/(9736942322213501/
  1000000000000000 + (7789553857770802/1000000000000000)*Cos[q]) + 
 ((2866566930866079/100000000000000000)*(1/2 + Cos[q])*Sin[q]*
      ((-(30095696738628313/10000000000000000))*Sqrt[5/4 + Cos[q]]*
           Cos[ArcTan[((1/2)*Sin[q])/(-1 - (1/2)*Cos[q])]] + 
   Sin[q]))/
   (43/44 + Cos[q] - (1/22)*Cos[2*q] - (1/11)*Cos[3*q]) + 
 ((35586923225834494/
    100000000000000000 + (5931153870972414/10000000000000000)*
           Cos[q] + (11862307741944829/100000000000000000)*
    Cos[2*q])*
      Sin[ArcTan[((1/2)*Sin[q])/(-1 - (1/2)*Cos[q])]])/
   ((7/4 + Cos[q] - (1/2)*Cos[2*q])^(3/2)*
   Sqrt[1 - Sin[q]^2/(7/4 + Cos[q] - (1/2)*Cos[2*q])]), {q, -Pi, Pi}, 
WorkingPrecision -> 30]

これで、計算の精度が高くなり(15桁?)、文句なしに完了します。したがって、OPによって与えられる積分の実際の値は次のようになります。

3.28296365*10^-16
2 MichaelE2 Dec 15 2020 at 00:09

私はおそらく私が前もって言うことを変えるべきです:

おそらく驚くべきことに、完全なエラーメッセージは、心配することは何もない、そして修正は必要ないということです。

これは、特にメッセージが「失敗」という単語で始まる場合、私のものを含むエラーメッセージに対するほとんどの人の反応の反対です。重要なのは、エラーメッセージのこの部分について考えることです。

NIntegrate得られ-1.24910*^-16かつ4.588053980254483*^-13不可欠と誤差の推定値のため。

つまりNIntegrate、積分が区間内にあるように計算されたということです

{-4.586804880254483`*^-13, 4.589303080254483`*^-13} 

さて、それは十分な答えですか?

おそらく、(他の理由で、たとえば、値が表すことに基づいて)信じない限り、積分はゼロではなく、よりも小さいと考えられ10^-13ます。おそらく、何もする必要はありません。答えを受け入れるだけです。一方、の不確実性4.6*10^-13が許容できない場合は、以下で説明する方法のいずれもそれを修正しません。彼らはただ問題を隠します。

OPの方法はNDSolve、この間隔のかなり外側にありAccuracyGoal、約のそれに対応する方法よりも優れています8

OPの方法は、技術的な理由からNIntegrate、積分1 + integrandと減算によって得られる答えよりも優れてい2 Piます。デフォルトの精度目標は約です6。これは、積分値の誤差がによって制限されることを意味します。2 Pi 10*^-6これは、よりもはるかに大きくなり4.6*10^-13ます。さらに、この方法の積分の値(マイナス2 Pi)は区間内にありますが、OPの積分の値よりもはるかに大きくなります。

OPの方法は下げるよりも優れていAccuracyGoalます。この設定AccuracyGoal -> aは、絶対誤差が、未満の場合10^-aNIntegrate結果を受け入れることを大まかに意味します。を下げることによりAccuracyGoal、実際にNIntegrateはより悪い結果を受け入れるように指示しています。これを行う正当な理由は、@ MarcoBにリンクされた回答の1つに示されています。NIntegrate積分が(ほぼ)ゼロの場合、設定を低くすると、精度の低い結果を計算しやすくなるため、速度が上がります。

これらの他の方法には何も悪いことはありません。小数点以下8桁を超える精度が必要な場合を除いて、ここではほぼ間違いなくそうではありませんが、問題はありませんが、OPの方法よりも優れているわけではありません。この場合のエラーメッセージは、実際、答えがどれだけ優れているかを示しています。他の場合には、それは答えがどれほど悪いかを示しているかもしれません。