このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
質量行列ソルバーを使用した DAE の求解
MATLAB® で使用可能な質量行列ソルバーの 1 つを使用して微分代数方程式を解きます。このワークフローを使用するには、はじめに微分代数方程式 (DAE) の求解の手順 1、2、および 3 を完了してください。その後、ode15i
の代わりに質量行列ソルバーを使用します。
この例では、ode15s
または ode23t
の使用方法を示します。他のソルバーの詳細については、ODE ソルバーの選択を参照してこのページのワークフローを適用してください。
手順 1. DAE の関数ハンドルへの変換
reduceDAEIndex
の出力により、方程式のベクトル DAEs
と変数のベクトル DAEvars
が得られました。ode15s
または ode23t
を使用するには、2 つの関数ハンドルが必要です。1 つは DAE 系の質量行列を、もう 1 つは質量行列方程式の右辺を表します。これらの関数ハンドルは ODE 系の質量行列の等価な表現です。ここで M(t,y(t))y’(t) = f(t,y(t)) です。
massMatrixForm
を使用してこれらの関数ハンドルを求め、質量行列 M
と右辺 F
を得ます。
[M,f] = massMatrixForm(DAEs,DAEvars)
M = [ 0, 0, 0, 0, 0, 0, 0] [ 0, 0, 0, 0, 0, 0, 0] [ 0, 0, 0, 0, 0, 0, 0] [ 0, 0, 0, 0, 0, 0, 0] [ 0, 0, 0, 0, 0, 0, 0] [ 0, 0, 0, 0, -1, 0, 0] [ 0, -1, 0, 0, 0, 0, 0] f = (T(t)*x(t) - m*r*Dxtt(t))/r -(g*m*r - T(t)*y(t) + m*r*Dytt(t))/r r^2 - y(t)^2 - x(t)^2 - 2*Dxt(t)*x(t) - 2*Dyt(t)*y(t) - 2*Dxtt(t)*x(t) - 2*Dytt(t)*y(t) - 2*Dxt(t)^2 - 2*Dyt(t)^2 -Dytt(t) -Dyt(t)
DAEs
の方程式には変数のベクトル DAEvars
で指定されていないシンボリック パラメーターが含まれても構いません。DAEs
および DAEvars
から得られた symvar
の出力に対して setdiff
を使用して、これらのパラメーターを求めます。
pDAEs = symvar(DAEs); pDAEvars = symvar(DAEvars); extraParams = setdiff(pDAEs, pDAEvars)
extraParams = [ g, m, r]
質量行列 M
にはこれらの余分なパラメーターはありません。したがって、odeFunction
を使用して M
を関数ハンドルに直接変換します。
M = odeFunction(M, DAEvars);
f
を関数ハンドルに変換します。odeFunction
への追加の入力としてパラメーターを別途指定します。
f = odeFunction(f, DAEvars, g, m, r);
以降のワークフローは純粋に数値的です。パラメーター値を設定して関数ハンドルを作成します。
g = 9.81; m = 1; r = 1; F = @(t, Y) f(t, Y, g, m, r);
手順 2. 初期条件を求める
ソルバーは関数ハンドル内のあらゆる変数に対して初期値を必要とします。MATLAB decic
関数を使用して、方程式を充足する初期値を求めます。decic
は推測された (方程式を満たさない可能性のある) 初期条件も取り扱うことができ、それらの推測を使用して充足する初期条件を求めようとします。decic
は失敗することもあり、そのような場合は問題に対し整合性のある初期値を手動で設定する必要があります。
はじめに、DAEvars
の変数をチェックします。
DAEvars
DAEvars = x(t) y(t) T(t) Dxt(t) Dyt(t) Dytt(t) Dxtt(t)
ここで、Dxt(t)
は x(t)
の 1 次導関数、Dytt(t)
は y(t)
の 2 次導関数、以下同様です。7
× 1
ベクトルには 7 個の変数が含まれます。したがって、変数の初期値とその導関数の推測も 7
× 1
ベクトルでなければなりません。
振子の初期角変位が 30° つまり pi/6
、座標の原点が振子のつり下げ点にあるとします。半径 r
は 1
であるため、初期水平位置 x(t)
は r*sin(pi/6)
です。初期垂直位置 y(t)
は -r*cos(pi/6)
です。ベクトル y0est
におけるこれらの変数の初期値を指定します。
残りの変数の初期値を任意に設定し、その導関数を 0
に設定します。これらは良い推測ではありません。しかしながら、この問題を充足します。問題において decic
エラーが発生した場合は、より良い推測を与えてから decic
のページを参照してください。
y0est = [r*sin(pi/6); -r*cos(pi/6); 0; 0; 0; 0; 0]; yp0est = zeros(7,1);
質量行列 M
と初期の推測 yp0est
を含むオプションセットを作成し、数値検索の数値許容誤差を指定するオプション セットを指定します。
opt = odeset('Mass', M, 'InitialSlope', yp0est,... 'RelTol', 10.0^(-7), 'AbsTol' , 10.0^(-7));
MATLAB 関数 decic
を使用して、変数とその導関数で整合性のある初期値を求めます。decic
の最初の引数は、DAE を f(t,y,yp) = f(t,y,y') = 0
と記述した関数ハンドルでなければなりません。M
および F
の観点からすると、これは f(t,y,yp) = M(t,y)*yp - F(t,y)
を意味します。
implicitDAE = @(t,y,yp) M(t,y)*yp - F(t,y); [y0, yp0] = decic(implicitDAE, 0, y0est, [], yp0est, [], opt)
y0 = 0.4771 -0.8788 -8.6214 0 0.0000 -2.2333 -4.1135 yp0 = 0 0.0000 0 0 -2.2333 0 0
ここで、系の質量行列 M
および、導関数に対して整合性のある初期値のベクトル yp0
を含むオプション セットを作成します。系を解くときにこのオプションを使用します。
opt = odeset(opt, 'InitialSlope', yp0);
手順 3. DAE 系の求解
系を時間範囲 0
≤ t
≤ 0.5
で積分して求解します。プロットにグリッド ラインと凡例を追加します。コードでは ode15s
を使用します。代わりに、ode15s
を ode23s
に置き換えて ode23s
を使用することもできます。
[tSol,ySol] = ode15s(F, [0, 0.5], y0, opt); plot(tSol,ySol(:,1:origVars),'-o') for k = 1:origVars S{k} = char(DAEvars(k)); end legend(S, 'Location', 'Best') grid on
新しい変数を設定し、関数ハンドルと初期条件を再生成することで、異なるパラメーター値で系を解きます。
r
に 2
を設定して、関数ハンドルと初期条件を再生成します。
r = 2; F = @(t, Y) f(t, Y, g, m, r); y0est = [r*sin(pi/6); -r*cos(pi/6); 0; 0; 0; 0; 0]; implicitDAE = @(t,y,yp) M(t,y)*yp - F(t,y); [y0, yp0] = decic(implicitDAE, 0, y0est, [], yp0est, [], opt); opt = odeset(opt, 'InitialSlope', yp0);
新しいパラメーター値で系を解きます。
[tSol,ySol] = ode15s(F, [0, 0.5], y0, opt); plot(tSol,ySol(:,1:origVars),'-o') for k = 1:origVars S{k} = char(DAEvars(k)); end legend(S, 'Location', 'Best') grid on