<?xml version="1.0" encoding="UTF-8"?>
<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns5="http://www.w3.org/1999/xhtml" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" xml:id="ode" xml:lang="ja">
    <refnamediv>
        <refname>ode</refname>
        <refpurpose>常微分方程式ソルバ</refpurpose>
    </refnamediv>
    <refsynopsisdiv>
        <title>呼び出し手順</title>
        <synopsis>
            y = ode(y0, t0, t, f)
            [y, w, iw] = ode([type,] y0, t0, t [,rtol [,atol]], f [,jac] [,w, iw])
            [y, rd, w, iw] = ode("root", y0, t0, t [,rtol [,atol]], f [,jac],ng, g [,w,iw])
            y = ode("discrete", y0, k0, kvect, f)
        </synopsis>
    </refsynopsisdiv>
    <refsection role="parameters">
        <title>引数</title>
        <variablelist>
            <varlistentry>
                <term>y0</term>
                <listitem>
                    <para>実数ベクトルまたは行列 (初期条件).</para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>t0</term>
                <listitem>
                    <para>実数スカラー (初期時間).</para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>t</term>
                <listitem>
                    <para>実数ベクトル (解を計算する時間).</para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>f</term>
                <listitem>
                    <para>関数, 外部 ,文字列またはリスト, 微分方程式の右辺.</para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>type</term>
                <listitem>
                    <para>
                        文字列,使用するソルバ. 利用可能なソルバ:
                        <literal>"adams"</literal>,
                        <literal>"stiff"</literal>, <literal>"rk"</literal>,
                        <literal>"rkf"</literal>, <literal>"fix"</literal>,
                        <literal>"discrete"</literal>, <literal>"root"</literal>.
                    </para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>atol, rtol</term>
                <listitem>
                    <para>
                        absolute and relative tolerances on the final solution
                        <varname>y</varname> (decimal numbers). If each is a
                        single value, it applies
                        to each component of <varname>y</varname>. Otherwise,
                        it must be a vector of same size as size(y), and
                        is applied element-wise to <varname>y</varname>.
                    </para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>jac</term>
                <listitem>
                    <para>
                        関数, 外部 文字列またはリスト, 関数<varname>f</varname>の
                        ヤコビアン.
                    </para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>ng</term>
                <listitem>
                    <para>整数.</para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>g</term>
                <listitem>
                    <para>外部 (関数または文字列またはリスト).</para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>k0</term>
                <listitem>
                    <para>整数 (初期時間).</para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>kvect</term>
                <listitem>
                    <para>整数ベクトル.</para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>y</term>
                <listitem>
                    <para>実数のベクトルまたは行列. (出力)</para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>rd</term>
                <listitem>
                    <para>実数ベクトル. (出力)</para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>w, iw</term>
                <listitem>
                    <para>実数ベクトル. (入力/出力)
                        See <link linkend="ode_optional_output">ode() optional output</link>
                    </para>
                </listitem>
            </varlistentry>
        </variablelist>
    </refsection>
    <refsection role="description">
        <title>説明</title>
        <para>
            <function>ode</function>は,以下の陽の
            常微分方程式を解きます:
        </para>
        <para>
            <latex>
                \begin{eqnarray}
                \begin{array}{l}
                \dfrac{dy}{dt} = f(t,y)\\
                y(t_0)=y_0
                \end{array}
                \end{eqnarray}
            </latex>
        </para>
        <para>
            この関数は種々のソルバ, 特にODEPACKへのインターフェイスです.
        </para>
        <para>
            このヘルプでは,
            標準の陽のODEシステム用に<function>ode</function>の使用方法のみを
            説明します.
        </para>
        <para>
            <function>ode</function>の最も簡単なコールは以下のようになります:
            <literal>y = ode(y0,t0,t,f)</literal>
            ただし,<literal>y0</literal> は初期条件ベクトル,
            <literal>t0</literal> は初期時間,
            <literal>t</literal> は解 <varname>y</varname>を計算する時間ベクトル,
            そして,<varname>y</varname>は解ベクトルの行列
            <literal>y=[y(t(1)),y(t(2)),...]</literal>です.
        </para>
        <para>
            入力ベクトル<varname>f</varname>は1次微分方程式の右辺を
            定義します.
            この引数は特定のヘッダを有する関数です.
        </para>
        <itemizedlist>
            <listitem>
                <para>
                    <varname>f</varname> が Scilab 関数の場合,
                    その呼び出し手順は以下のようにします
                </para>
                <screen><![CDATA[
ydot = f(t,y)
]]></screen>
                <para>
                    ただし,<literal>t</literal>は実数スカラー(時間),
                    <varname>y</varname> は実数ベクトル (状態量),
                    <literal>ydot</literal>は実数ベクトル (1次微分dy/dt)です.
                </para>
            </listitem>
            <listitem>
                <para>
                    <varname>f</varname> が文字列の場合,
                    FortranサブルーチンまたはC関数の名前が参照されます.
                    例えば,<literal>ode(y0,t0,t,"fex")</literal>をコールすると,
                    サブルーチン<literal>fex</literal>がコールされます.
                </para>
                <para>
                    Fortranルーチンは以下のようなヘッダを有する必要があります:
                </para>
                <screen><![CDATA[
fex(n,t,y,ydot)
]]></screen>
                <para>
                    ただし,<literal>n</literal>は整数, <literal>t</literal>は
                    倍精度スカラー, <varname>y</varname> および
                    <literal>ydot</literal> は倍精度ベクトルです.
                </para>
                <para>
                    C関数は以下のようなヘッダを有する必要があります:
                </para>
                <screen><![CDATA[
fex(int *n,double *t,double *y,double *ydot)
]]></screen>
                <para>
                    ただし,<literal>t</literal>は時間, <varname>y</varname>は
                    状態量, <literal>ydot</literal>は状態量の微分
                    (dy/dt)です.
                </para>
                <para>
                    この外部ルーチンは,
                    <link linkend="ilib_for_link">ilib_for_link</link>により
                    OSと独立した方法で構築でき,
                    <link linkend="link">link</link>
                    関数によりScilabに動的にリンクできます.
                </para>
            </listitem>
            <listitem>
                <para>
                    シミュレータ<varname>f</varname>が他の引数を
                    必要とする場合も起こりえます.
                    この場合, 以下の機能を使用可能です.
                    <varname>f</varname>の引数を
                    リスト<literal>lst=list(simuf,u1,u2,...un)</literal>とすることも
                    できます.
                    ただし,<literal>simuf</literal>は以下の構造を有するScilab関数です:
                    <literal>ydot = f(t,y,u1,u2,...,un)</literal>
                    ただし,<literal>u1</literal>, <literal>u2</literal>, ...,
                    <literal>un</literal>は,
                    シミュレータ<literal>simuf</literal>に自動的に指定される
                    外部引数です.
                </para>
            </listitem>
        </itemizedlist>
        <para>
            関数<varname>f</varname>は,ベクトルではなく
            p行q列の行列を返すことができます.
            この行列表記により,
            <literal>n=p+q</literal>次のODEシステム<literal>dY/dt=F(t,Y)</literal>
            を解きます.
            ただし, <literal>Y</literal>は <literal>p x q</literal>の行列です.
            初期条件 <literal>Y0</literal>も<literal>p x q</literal>の行列
            である必要があり, <function>ode</function>の結果は
            <literal>p行q(T+1)列</literal>
            の行列 <literal>[Y(t_0),Y(t_1),...,Y(t_T)]</literal>
            となります.
        </para>
        <para>
            許容誤差<varname>rtol</varname> および <varname>atol</varname> は
            相対および絶対推定誤差の閾値です.
            <literal>y(i)</literal>の指定誤差は次のようになります:
            <literal>rtol(i)*abs(y(i))+atol(i)</literal>
            そして,状態量の全ての要素に関してこの誤差が小さい場合,
            積分が行われます.
            <varname>rtol</varname>または<varname>atol</varname>が定数の場合,
            <literal>rtol(i)</literal>または<literal>atol(i)</literal>
            はこの定数値に設定されます.
            <varname>rtol</varname> および <varname>atol</varname>のデフォルト値は
            多くのソルバではそれぞれ<literal>rtol=1.d-5</literal> および
            <literal>atol=1.d-7</literal>,
            <literal>"rfk"</literal> および <literal>"fix"</literal>では
            <literal>rtol=1.d-3</literal> および <literal>atol=1.d-4</literal>です.
        </para>
        <para>
            スティッフな問題の場合, RHS関数のヤコビアンを
            オプションの引数 <varname>jac</varname>として
            指定する方が良いでしょう.
            ヤコビアンは,外部,すなわち,指定された構文を有する関数,
            または指定した呼び出し手順を有するFortranサブルーチンまたは
            C関数の名前(文字列),またはリストです.
        </para>
        <itemizedlist>
            <listitem>
                <para>
                    <varname>jac</varname> が関数の場合,
                    構文は
                    <literal>J=jac(t,y)</literal>とする必要があります.
                    ただし, <literal>t</literal> は実数スカラー (時間),
                    <varname>y</varname>は実数ベクトル (状態量)です.
                    結果の行列
                    <literal>J</literal> は df/dx を評価する必要があります.
                    ただし, <literal>J(k,i) =dfk/dxi</literal> で
                    <literal>fk</literal> は<varname>f</varname>の
                    <literal>k</literal>番目の要素です.
                </para>
            </listitem>
            <listitem>
                <para>
                    <varname>jac</varname>が文字列の場合,
                    FortranサブルーチンまたはC関数の名前を指します.
                </para>
                <para>
                    このFortranルーチンは以下のようなヘッダを有する必要があります:
                </para>
                <screen><![CDATA[
subroutine fex(n,t,y,ml,mu,J,nrpd)
integer n,ml,mu,nrpd
double precision t,y(*),J(*)
]]></screen>
                <para>
                    このC関数は以下のようなヘッダを有する必要があります:
                </para>
                <screen><![CDATA[
void fex(int *n,double *t,double *y,int *ml,int *mu,double *J,int *nrpd,)
]]></screen>
                <para>
                    多くの場合,
                    <literal>ml</literal>, <literal>mu</literal> および
                    <literal>nrpd</literal>を参照する必要はありません.
                </para>
            </listitem>
            <listitem>
                <para>
                    <varname>jac</varname>がリストの場合,
                    <varname>f</varname>と同様の表記となります.
                </para>
            </listitem>
        </itemizedlist>
        <para>
            オプション引数<varname>w</varname>および
            <varname>iw</varname>は,
            積分ルーチンにより返される情報を
            保存するベクトルです(詳細は<link linkend="ode_optional_output">ode_optional_output</link> 参照).
            これらのベクトルが <function>ode</function>のRHSで提供される場合,
            積分は前回の停止時と同じパラメータで再開されます.
        </para>
        <para>
            より多くのオプションを<literal>%ODEOPTIONS</literal>変数
            によりODEPACKソルバに指定することができます.
            <link linkend="odeoptions">odeoptions</link>を参照ください.
        </para>
    </refsection>
    <refsection>
        <title>ソルバ</title>
        <para>
            解く問題の型と使用する手法は最初のオプション引数
            <varname>type</varname>の値に依存します.
            この値には以下の文字列の一つを指定できます:
        </para>
        <variablelist>
            <varlistentry>
                <term>&lt;not given&gt;:</term>
                <listitem>
                    <para>
                        ODEPACKパッケージの<literal>lsoda</literal> ソルバが
                        デフォルトでコールされます.
                        このソルバは非スティッフな問題用の予測子/修正子 Adams 法と
                        スティッフな問題用の後退差分法(BDF)を自動的に選択します.
                        まず非スティッフな手法が使用され,使用する手法を
                        決定するためにデータを動的にモニタします.
                    </para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>"adams":</term>
                <listitem>
                    <para>
                        これは非スティッフな問題用です. ODEPACKパッケージの
                        <literal>lsode</literal> ソルバがコールされ, この関数は
                        Adams法を使用します.
                    </para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>"stiff":</term>
                <listitem>
                    <para>
                        これはスティッフな問題用です. ODEPACKパッケージの
                        <literal>lsode</literal> ソルバがコールされ, BDF法が使用されます.
                    </para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>"rk":</term>
                <listitem>
                    <para>4次の適応型 Runge-Kutta (RK4) 法.</para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>"rkf":</term>
                <listitem>
                    <para>
                        Fehlbergの4次と5次の Runge-Kutta法に基づくShampine および Wattsのプログラム
                        (RKF45) が使用されます.
                        この方法は非スティッフおよびややスティッフな問題用で,
                        微係数の評価コストが低い場合に適しています.
                        この手法は一般にユーザが高い精度を望む場合には使用するべきではありません.
                    </para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>"fix":</term>
                <listitem>
                    <para>
                        <literal>"rkf"</literal>と同じソルバですがユーザインターフェイスが
                        非常にシンプルで,
                        <varname>rtol</varname> および <varname>atol</varname>パラメータのみを
                        ソルバに指定することが可能です.
                        この手法は使用できる中で最も簡単な手法です.
                    </para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>"root":</term>
                <listitem>
                    <para>
                        解を得る機能を有するODE ソルバ. ODEPACKパッケージの
                        <literal>lsodar</literal> ソルバが使用されます.
                        使用されているのは<literal>lsoda</literal> ソルバを改変したもので,
                        指定したベクトル関数の根を見つけることができます.
                        詳細は <link linkend="ode_root">ode_root</link> のヘルプを参照してください.
                    </para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>"discrete":</term>
                <listitem>
                    <para>
                        離散時間シミュレーション.
                        詳細は <link linkend="ode_discrete">ode_discrete</link>
                        のヘルプを参照してください.
                    </para>
                </listitem>
            </varlistentry>
        </variablelist>
    </refsection>
    <refsection>
        <title>例</title>
        <para>
            以下の例では,初期条件<literal>y(0)=0</literal>で,常微分方程式
            <literal>dy/dt=y^2-y*sin(t)+cos(t)</literal>を解きます.
            デフォルトのソルバを使用します.
        </para>
        <programlisting role="example"><![CDATA[
function ydot = f(t,y)
    ydot = y^2 - y*sin(t) + cos(t)
endfunction
y0 = 0;
t0 = 0;
t = 0:0.1:%pi;
y = ode(y0, t0, t, f);
plot(t,y)
     ]]></programlisting>
        <scilab:image>
            function ydot=f(t,y)
            ydot=y^2-y*sin(t)+cos(t)
            endfunction
            y0=0;
            t0=0;
            t=0:0.1:%pi;
            y = ode(y0,t0,t,f);
            plot(t,y)
        </scilab:image>
        <para>
            以下の例では,方程式<literal>dy/dt=A*y</literal>を解きます.
            正確な解は<literal>y(t)=expm(A*t)*y(0)</literal>です,
            ただし
            <literal>expm</literal> は行列指数関数です.
            未知量は2行1列の行列 y(t) です.
        </para>
        <programlisting role="example"><![CDATA[
function ydot = f(t,y)
    ydot = A*y
endfunction
function J = Jacobian(t,y)
    J = A
endfunction
A = [10,0 ; 0,-1];
y0 = [0;1];
t0 = 0;
t = 1;
ode("stiff", y0, t0, t, f, Jacobian)
// Compare with exact solution:
expm(A*t)*y0
     ]]></programlisting>
        <para>
            以下の例では,<literal>u(t)=sin(omega*t)</literal>として,
            ODE <literal>dx/dt = A x(t) + B u(t)</literal>を解きます.
            外部引数 <varname>f</varname>に関する注記:
            <literal>A</literal>, <literal>u</literal>, <literal>B</literal>,
            <literal>omega</literal>が関数<varname>f</varname>にリストとして
            指定されます.
        </para>
        <programlisting role="example"><![CDATA[
function xdot = linear(t,x,A,u,B,omega)
    xdot = A*x+B*u(t,omega)
endfunction
function ut = u(t,omega)
    ut = sin(omega*t)
endfunction
A = [1 1 ; 0 2];
B = [1;1];
omega = 5;
y0 = [1;0];
t0 = 0;
t = [0.1, 0.2, 0.5, 1];
ode(y0, t0, t, list(linear,A,u,B,omega))
     ]]></programlisting>
        <para>
            以下の例では,リカッチ微分方程式
            <literal>dX/dt=A'*X + X*A - X'*B*X + C</literal>を解きます.
            ただし,初期条件<literal>X(0)</literal>は2行2列の単位行列です.
        </para>
        <programlisting role="example"><![CDATA[
function Xdot = ric(t,X,A,B,C)
    Xdot = A'*X + X*A - X'*B*X + C
endfunction
A = [1,1 ; 0,2];
B = [1,0 ; 0,1];
C = [1,0 ; 0,1];
y0 = eye(A);
t0 = 0;
t = 0:0.1:%pi;
X = ode(y0, t0, t, list(ric,A,B,C))
     ]]></programlisting>
        <para>
            以下の例では,微分方程式
            <literal>dY/dt=A*Y</literal>を解きます.
            ただし,未知量<literal>Y(t)</literal>は2行2列の行列です.
            厳密解は <literal>Y(t)=expm(A*t)</literal>です.
            ただし,
            <literal>expm</literal>は行列指数関数です.
        </para>
        <programlisting role="example"><![CDATA[
function ydot = f(t,y,A)
    ydot = A*y;
endfunction
A = [1,1 ; 0,2];
y0 = eye(A);
t0 = 0;
t = 1;
ode(y0, t0, t, list(f,A))
// Compare with the exact solution:
expm(A*t)
ode("adams", y0, t0, t, f)
     ]]></programlisting>
    </refsection>
    <refsection role="examples">
        <title>コンパイラを使用</title>
        <para>
            以下の例はCコンパイラを必要とします.
        </para>
        <programlisting role="example"><![CDATA[
// ---------- Simple one dimension ODE (C coded external)
ccode=['#include <math.h>'
       'void myode(int *n,double *t,double *y,double *ydot)'
       '{'
       '  ydot[0]=y[0]*y[0]-y[0]*sin(*t)+cos(*t);'
       '}']
mputl(ccode, TMPDIR+'/myode.c') //create the C file

// Compile
cd TMPDIR
ilib_for_link('myode','myode.c',[],'c',[],'loader.sce');
exec('loader.sce') //incremental linking
y0 = 0;
t0 = 0;
t = 0:0.1:%pi;
y = ode(y0, t0, t, 'myode');
     ]]></programlisting>
    </refsection>
    <refsection role="bibliography">
        <title>参考文献</title>
        <para>
            Alan C. Hindmarsh, "lsode and lsodi, two new initial value ordinary
            differential equation solvers", ACM-Signum newsletter, vol. 15, no. 4
            (1980), pp. 10-11.
        </para>
    </refsection>
    <refsection role="references">
        <title>使用される関数</title>
        <para>
            関連する関数は SCI/modules/differential_equations/src/fortran
            ディレクトリにあります:
            lsode.f lsoda.f lsodar.f
        </para>
    </refsection>
    <refsection role="see also">
        <title>参照</title>
        <simplelist type="inline">
            <member>
                <link linkend="odeoptions">odeoptions</link>
            </member>
            <member>
                <link linkend="ode_optional_output">ode_optional_output</link>
            </member>
            <member>
                <link linkend="ode_root">ode_root</link>
            </member>
            <member>
                <link linkend="ode_discrete">ode_discrete</link>
            </member>
            <member>
                <link linkend="dassl">dassl</link>
            </member>
            <member>
                <link linkend="impl">impl</link>
            </member>
            <member>
                <link linkend="odedc">odedc</link>
            </member>
            <member>
                <link linkend="csim">csim</link>
            </member>
            <member>
                <link linkend="ltitr">ltitr</link>
            </member>
            <member>
                <link linkend="rtitr">rtitr</link>
            </member>
            <member>
                <link linkend="intg">intg</link>
            </member>
        </simplelist>
    </refsection>
</refentry>
