4

問題:

私はこの微分方程式を解こうとしています:

K[x_, x1_] := 1;
NDSolve[{A''[x] == Integrate[K[x, x1] A[x1], {x1, 0, 1}], 
         A[0] == 0, A'[1] == 1}, A[x], x]

エラー(Function::slotnおよびNDSolve::ndnum)が発生
します(に等しい数値関数を返す必要があります3/16 x^2 + 5/8 x

この微分方程式を解く方法を探しています。NDSolveが理解できるように、より良い形式で書く方法はありますか?役立つ別の関数またはパッケージはありますか?

注1:私の完全な問題でK[x, x1]は、は1ではありません-それは(複雑な方法で)とに依存しxますx1
注2:積分限界が明確であるため、に関する方程式の2つの側面を単純に導出することxはできません。

私の第一印象:

Mathematicaは私がポイントを参照するのを好まないようです-A[x]この簡略化されたバージョンを実行しているときに同じエラーが発生します:

NDSolve[{A''[x] == A[0.5], A[0] == 0, A'[1] == 1}, A[x], x]

(と等しい数値関数を返す必要があります2/11 x^2 + 7/11 x

この場合、解析的に解いA''[x] == cてからを見つけることでこの問題を回避できますcが、私の最初の問題ではうまくいかないようです-微分方程式を積分方程式に変換するだけで、(N)DSolveは後で解きません。

4

3 に答える 3

7

方程式を積分方程式に縮小する方法を提案できます。これは、そのカーネルを行列で近似することで数値的に解くことができ、それによって積分を行列乗算に減らします。

xまず、方程式をから1までx、次に から0までで2 回積分できることは明らかです。したがって、次のxようになります。

ここに画像の説明を入力

この方程式を離散化して、等距離グリッドに置くことができます。

ここに画像の説明を入力

ここで、 はA[x]ベクトルになり、統合されたカーネルiniIntKは行列になり、統合は行列の乗算に置き換えられます。次に、問題は線形方程式系に縮小されます。

最も簡単なケース (ここで検討します) は、カーネルiniIntKを分析的に導出できる場合です。この場合、この方法は非常に高速です。統合カーネルを純粋な関数として生成する関数は次のとおりです。

Clear[computeDoubleIntK]
computeDoubleIntK[kernelF_] :=
  Block[{x, x1},
   Function[
    Evaluate[
      Integrate[
         Integrate[kernelF[y, x1], {y, 1, x}] /. x -> y, {y, 0, x}] /. 
         {x -> #1, x1 -> #2}]]];

私たちの場合には:

In[99]:= K[x_,x1_]:=1;

In[100]:= kernel = computeDoubleIntK[K]
Out[100]= -#1+#1^2/2&

カーネル行列と rh,s ベクトルを生成する関数は次のとおりです。

 computeDiscreteKernelMatrixAndRHS[intkernel_, a0_, aprime1_ , 
    delta_, interval : {_, _}] :=
  Module[{grid, rhs, matrix},
    grid = Range[Sequence @@ interval, delta];
    rhs = a0 + aprime1*grid; (* constant plus a linear term *)
    matrix = 
      IdentityMatrix[Length[grid]] - delta*Outer[intkernel, grid, grid];
    {matrix, rhs}]

これがどのように見えるかを非常に大まかに説明するには (ここでは を使用しますdelta = 1/2):

In[101]:= computeDiscreteKernelMatrixAndRHS[kernel,0,1,1/2,{0,1}]

Out[101]= {{{1,0,0},{3/16,19/16,3/16},{1/4,1/4,5/4}},{0,1/2,1}}

次に、線形方程式を解き、結果を補間する必要があります。これは、次の関数によって行われます。

Clear[computeSolution];
computeSolution[intkernel_, a0_, aprime1_ , delta_, interval : {_, _}] :=
With[{grid = Range[Sequence @@ interval, delta]},
  Interpolation@Transpose[{
    grid,
    LinearSolve @@ 
      computeDiscreteKernelMatrixAndRHS[intkernel, a0, aprime1, delta,interval]
  }]]

ここでは、次のように呼び出しますdelta = 0.1

In[90]:= solA = computeSolution[kernel,0,1,0.1,{0,1}]
Out[90]= InterpolatingFunction[{{0.,1.}},<>] 

結果と@Sashaが見つけた正確な分析解、およびエラーをプロットします。

ここに画像の説明を入力

エラーが見えるように、意図的にdelta十分な大きさを選択しました。deltasayを選択した場合0.01、プロットは視覚的に同一になります。もちろん、小さくすることの代償として、deltaより大きな行列を作成して解く必要があります。

分析的に取得できるカーネルの場合、主なボトルネックは にありますLinearSolveが、実際にはかなり高速です (行列が大きすぎない場合)。カーネルを分析的に統合できない場合、主なボトルネックは多くの点でカーネルを計算することになります (行列の作成)。逆行列はより大きな漸近的複雑さを持ちますが、これは非常に大きな行列に対して役割を果たし始めます。このアプローチは、反復アプローチと組み合わせることができるためです - 以下を参照してください)。通常、以下を定義します。

intK[x_?NumericQ, x1_?NumericQ] := NIntegrate[K[y, x1], {y, 1, x}]
intIntK[x_?NumericQ, x1_?NumericQ] := NIntegrate[intK[z, x1], {z, 0, x}]

このような場合に高速化する方法として、intKグリッドでカーネルを事前計算してから補間することができますintIntK。ただし、これにより追加のエラーが発生するため、推定 (考慮) する必要があります。

グリッド自体は等間隔である必要はありません (簡単にするために使用しただけです)。

最後の例として、自明ではないが記号的に可積分なカーネルを持つ方程式を考えてみましょう。

In[146]:= sinkern =  computeDoubleIntK[50*Sin[Pi/2*(#1-#2)]&]

Out[146]= (100 (2 Sin[1/2 \[Pi] (-#1+#2)]+Sin[(\[Pi] #2)/2] 
     (-2+\[Pi] #1)))/\[Pi]^2&

In[157]:= solSin = computeSolution[sinkern,0,1,0.01,{0,1}]
Out[157]= InterpolatingFunction[{{0.,1.}},<>]

ここに画像の説明を入力

ここにいくつかのチェックがあります:

In[163]:= Chop[{solSin[0],solSin'[1]}]
Out[163]= {0,1.}

In[153]:= 
diff[x_?NumericQ]:=
  solSin''[x] - NIntegrate[50*Sin[Pi/2*(#1-#2)]&[x,x1]*solSin[x1],{x1,0,1}];

In[162]:= diff/@Range[0,1,0.1]

Out[162]=  {-0.0675775,-0.0654974,-0.0632056,-0.0593575,-0.0540479,-0.0474074,
   -0.0395995,-0.0308166,-0.0212749,-0.0112093,0.000369261}

結論として、私はこの方法について慎重なエラー - 推定分析を実行する必要があることを強調したいと思いますが、私はそれを行いませんでした。

編集

また、この方法を使用して初期近似解を取得し、FixedPointまたは他の手段を使用して反復的に改善することもできます。この方法では、比較的高速な収束が得られ、膨大な計算を構築して解決する必要なく、必要な精度に到達できます。行列。

于 2011-08-07T23:45:11.373 に答える
4

これは、しし座シフリンのアプローチを補完するものです。開始点で値と一次導関数を補間する線形関数から始めます。これを、指定されたカーネル関数との統合で使用します。次に、次の近似を行うために使用される統合カーネル内の前の各近似を使用して反復できます。

単なる定数関数よりも複雑なカーネルを使用した例を以下に示します。2 回繰り返して、相違点の表を示します。

kernel[x_, y_] := Sqrt[x]/(y^2 + 1/5)*Sin[x^2 + y]
intkern[x_?NumericQ, aa_] := 
 NIntegrate[kernel[x, y]*aa[y], {y, 0, 1}, MinRecursion -> 2, 
  AccuracyGoal -> 3]

Clear[a];
a0 = 0;
a1 = 1;
a[0][x_] := a0 + a1*x

soln1 = a[1][x] /. 
   First[NDSolve[{(a[1]^\[Prime]\[Prime])[x] == intkern[x, a[0], y], 
      a[1][0] == a0, a[1][1] == a1}, a[1][x], {x, 0, 1}]];
a[1][x_] = soln1;

In[283]:= Table[a[1]''[x] - intkern[x, a[1]], {x, 0., 1, .1}]

Out[283]= {4.336808689942018*10^-19, 0.01145100326794241, \
0.01721655945379122, 0.02313249302884235, 0.02990900241909161, \
0.03778448183557359, 0.04676409320217928, 0.05657128568058478, \
0.06665818935524814, 0.07624149919589895, 0.08412643746245929}

In[285]:= 
soln2 = a[2][x] /. 
   First[NDSolve[{(a[2]^\[Prime]\[Prime])[x] == intkern[x, a[1]], 
      a[2][0] == a0, a[2][1] == a1}, a[2][x], {x, 0, 1}]];
a[2][x_] = soln2;

In[287]:= Table[a[2]''[x] - intkern[x, a[2]], {x, 0., 1, .1}]

Out[287]= {-2.168404344971009*10^-19, -0.001009606971360516, \
-0.00152476679745811, -0.002045817184941901, -0.002645356229312557, \
-0.003343218015068372, -0.004121109614310836, -0.004977453722712966, \
-0.005846840469889258, -0.006731367269472544, -0.007404971586975062}

したがって、この段階での誤差は 0.01 未満です。悪くない。1 つの欠点は、2 番目の近似を取得するのにかなり時間がかかることです。それを改善するためにNDSolveを調整する方法があるかもしれません.

これは、2 つの理由でしし座の方法を補完します。

(1) 最初の線形近似が真の結果に十分に近くなかったためにこれがうまく収束しなかった場合は、代わりに、有限差分スキームによって検出された近似から始めることができます。それは彼がしたことと似ているでしょう。

(2) 彼は、彼に倣って洗練を生み出す可能性のある方法として、これをほとんど彼自身に示しました。

ダニエル・リヒトブラウ

于 2011-08-08T17:24:06.637 に答える
0

あなたの方程式が現在書かれている方法はA''[x] == const、定数よりも独立していxます。したがって、解は常に二次多項式の形式になります。あなたの問題は、不定係数の解決に縮小されます。

In[13]:= A[x_] := a2 x^2 + a1 x + a0;

In[14]:= K[x_, x1_] := 1;

In[16]:= Solve[{A''[x] == Integrate[K[x, x1] A[x1], {x1, 0, 1}], 
  A[0] == 0, A'[1] == 1}, {a2, a1, a0}]

Out[16]= {{a2 -> 3/16, a1 -> 5/8, a0 -> 0}}

In[17]:= A[x] /. First[%]

Out[17]= (5 x)/8 + (3 x^2)/16
于 2011-08-07T19:49:37.323 に答える