dsolve/numeric の解のプロシージャにおける効率
|
モデルの説明
|
|
•
|
Maple で常微分方程式 (ODE)の数値解を扱う際の効率に関しては、様々な考察があります。このページは、解の値やプロットの計算時の dsolve/numeric の効率的な使用、および、すべての dsolve/numeric プロシージャ形式の解についての全般的な考察に関する情報の中央保管場所としての役割を果たします。
|
|
|
Digits (桁数)
|
|
•
|
環境変数 Digits の設定は、dsolve/numeric の効率に極めて重要です。Digits が evalhf(Digits) の値(現在、すべての対応プラットフォームで 15)以下に設定されている場合、解の計算はハードウェアの浮動小数点演算を使用して実行し、53 binaryの精度の Digits を使用ます。
|
|
Digits が15以下の場合、計算がハードウェアモードで実行されていると言い、可能な場合には、ハードウェア浮動小数で高速な評価を行うevalhf が使用されます。こうすると効率が大幅に促進され、場合によっては、 程度の因数によって計算を加速することができます。
|
|
さらに、これをサポートする方法としては、ハードウェアモードでの演算中には compile オプションを使用することができます。このオプションにより、 に加えて の因数により、計算を加速することができます。
|
ソフトウェア精度で実行(16 Digit base-10)
>
|
dsn16 := dsolve({diff(y(t),t,t)+y(t),y(0)=0,D(y)(0)=1}, numeric, abserr=1e-12, relerr=1e-12, maxfun=0);
|
| (2.1) |
| (2.2) |
| (2.3) |
ハードウェア精度で実行
>
|
dsn10 := dsolve({diff(y(t),t,t)+y(t),y(0)=0,D(y)(0)=1}, numeric, abserr=1e-12, relerr=1e-12, maxfun=0);
|
| (2.4) |
| (2.5) |
| (2.6) |
比較:
| (2.7) |
ハードウェア精度および compile で実行
>
|
dsn10 := dsolve({diff(y(t),t,t)+y(t),y(0)=0,D(y)(0)=1}, numeric, abserr=1e-12, relerr=1e-12, maxfun=0, compile=true);
|
| (2.8) |
| (2.9) |
| (2.10) |
比較:
| (2.11) |
|
|
プロット
|
|
•
|
dsolve/numeric で出力される大部分のプロシージャは、compute-as-needed となります。すなわち、その系は解の値が要求されたときに、初期点または最後に計算された解の点のいずれから積分されます。
|
|
ここで「大部分」と表現したのは、特定の問題またはオプションは 解の保存を強制したり、暗示したりするためです。これには、BVP 問題の解、 解を事前計算するための range オプションを使用した IVP の解、または、piecewise 出力形式を使用した解が含まれます。
|
|
compute-as-needed 手法で深刻な問題となるのは、IVP 問題の安定性が明らかでないため、積分の方向が反転できないという点でです。
|
|
(とりわけ)こうした理由により、特殊な IVP の解をプロットするルーチンである plots[odeplot] が準備されており、これを使用して ODE の解のプロットを効率的に作成します。plot のような標準のプロットルーチンを使用すると、処理される点の次数に対する制限に関して把握する手段がないため、非効率になる場合があります。さらに、特殊なルーチンを使用すると、ODE 積分用の特殊出力モデルが可能となり、解法とプロット作成との間の強化された(さらには効率化された)結び付きサポートします。
|
>
|
dsn := dsolve({diff(y(t),t,t)+y(t),y(0)=0,D(y)(0)=1}, numeric, abserr=1e-12, relerr=1e-12, maxfun=0, output=listprocedure);
|
| (3.1) |
plot using 特殊な odeplot を使用したプロット
>
|
plots[odeplot](dsn,[t,y(t)],0..50*Pi,numpoints=500);
|
| (3.2) |
一般的な plot を使用したプロット(適応可)
>
|
plot(op([2,2],dsn),0..50*Pi);
|
| (3.3) |
比較:
| (3.4) |
|
|
系の implicit オプション
|
|
•
|
IVP 問題では、入力系は dsolve/numeric/IVP で説明されているように、既に解かれた 1 階形式に変換する必要があります。一部の系においては、この記号解のステップは非常に大きな負担をかける場合があります。これは特に、自動生成される濃密系やホモトピー問題からの系で発生します。
|
|
幸いにも導関数において系が線形の場合 (1 階に変換後)には、implicit オプションを使用することができます。implicit オプションは記号の backsolve (解のプロシージャの作成時に 1 度実行される)を遅延させ、純粋な数値の backsolves (積分中の導関数の各評価において実行される)にします。
|
|
記号式の膨らみや、大きな式であることから発生する関連丸め誤差の発生の防止に加え、この方法には、未知の記号係数に代わって系の係数の局所数値でピボットが行われるため、削除プロセスにおいて変数を解く際により安定した選択が行われるという利点があります。
|
このアイデアを説明するため、1 階の ODE 系を検討します:
>
|
eq1 := cos(t)*diff(x(t),t)+(1/2-sin(t))*diff(y(t),t)=1/2-y(t);
|
| (4.1) |
>
|
eq2 := sin(t)*diff(x(t),t)+cos(t)*diff(y(t),t)=x(t);
|
| (4.2) |
直接的な記号解では、第 1 の式を使用して を解き、第 2 の式を使用して を解く場合がありますが、 がゼロを通過するときに問題となります。ここではいくつかの限定された簡単化がみられますが、dsolve/numeric は実際には backsolve で解を求めるため、この系は実際に問題となることはありません。
implicit オプションは、 および の値が要求される各点において、係数を評価してから解を求めることにより、この種の問題を回避します。
>
|
dsn := dsolve({eq1,eq2,x(0)=0,y(0)=0}, numeric, implicit=true);
|
| (4.3) |
>
|
plots[odeplot](dsn,[x(t),y(t)],0..6*Pi);
|
|
|
他の解に依存する解
|
|
•
|
別の dsolve/numeric の解に依存する ODE 問題の dsolve/numeric の解を計算する必要があることがあります。たとえば、dsolve/numeric 問題から の解を得るとします。その解は次に、強制関数といった別の問題の一部として使用されるとします。
|
|
時間の尺度が同等な場合、2 つの系を単純に組み合わせることにより、遥かに効率よく解を求めることができます。これは、dsolve/numeric の解のプロシージャに依存する系を evalhf (第 1 セクション参照)のもとで積分することができないために、積分の速度が遥かに遅くなるためです。
|
たとえば、以下を別々に解きます。
>
|
sys1 := {diff(x(t),t,t)+x(t)=0, x(0)=0, D(x)(0)=1};
|
| (5.1) |
>
|
sol1 := dsolve(sys1, numeric, output=listprocedure);
|
| (5.2) |
| (5.3) |
>
|
sys2 := {diff(y(t),t,t)=xf(t), y(0)=0, D(y)(0)=1};
|
| (5.4) |
>
|
sol2 := dsolve(sys2, numeric, known={xf});
|
| (5.5) |
| (5.6) |
>
|
t_separate := time()-tt;
|
| (5.7) |
次に組み合わせます。
>
|
sysc := sys1 union eval(sys2,xf(t)=x(t));
|
| (5.8) |
>
|
solc := dsolve(sysc, numeric);
|
| (5.9) |
| (5.10) |
>
|
t_combined := time()-tt;
|
| (5.11) |
比較:
| (5.12) |
|
時間の尺度が異なる場合 (たとえば、第 2 の系が に依存し、このとき が別の ODE 問題の解である場合)、デフォルトの stiff および non-stiff の方法では、所定の範囲では区分形式の出力が可能です。区分解の計算は、第 2 の問題の望ましい積分の制限を十分に超えて実行することが必要となる可能性があることに注意してください。これは、ソルバが積分中に現在の範囲を超えて 進むためです。
|
同じ例から:
>
|
sol1p := dsolve(sys1, numeric, output=piecewise, range=0..110):
|
>
|
type(xp,specfunc(anything,piecewise)), nops(xp);
|
| (5.13) |
>
|
sys2p := {diff(y(t),t,t)=xf, y(0)=0, D(y)(0)=1}:
|
>
|
sol2p := dsolve(sys2p, numeric);
|
| (5.14) |
| (5.15) |
>
|
t_piecewise := time()-tt;
|
| (5.16) |
比較:
>
|
t_separate/t_piecewise;
|
| (5.17) |
|
最後に、必要であれば、(区分的でない)ストレートな range の解を使用することができます。この方法では、少なくとも解の再計算をせずに済みますが、evalhf モードでは実行されないため、選択肢の中では最も非効率な方法になります。
|
|
|
関連項目
|
|
Digits, dsolve/ck45, dsolve/classical, dsolve/dverk78, dsolve/gear, dsolve/lsode, dsolve/numeric, dsolve/numeric/IVP, dsolve/rkf45, dsolve/rosenbrock, evalhf, piecewise, plots[odeplot]
|
|