Keyword: 後退差分公式, 常微分方程式
概要
本サンプルは後退差分公式を用いた常微分方程式を求めるFortranによるサンプルプログラムです。 本サンプルは以下に示される常微分方程式について5つのケースの計算をし、出力します。
※本サンプルはnAG Fortranライブラリに含まれるルーチン d02ejf() のExampleコードです。本サンプル及びルーチンの詳細情報は d02ejf のマニュアルページをご参照ください。
ご相談やお問い合わせはこちらまで
入力データ
(本ルーチンの詳細はd02ejf のマニュアルページを参照)1 2 3 4
このデータをダウンロード |
D02EJF Example Program Data 0.0 10.0 : xinit, xend 1.0, 0.0, 0.0 : yinit 4 : kinit
- 1行目はタイトル行で読み飛ばされます。
- 2行目は独立変数xの初期値(xinit)と最終値(xned)を指定しています。
- 3行目は解の初期値(yinit)を指定しています。
- 4行目は独立変数xの刻み幅の値の数(kinit)を指定しています。
出力結果
(本ルーチンの詳細はd02ejf のマニュアルページを参照)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
この出力例をダウンロード |
D02EJF Example Program Results Case 1: calculating Jacobian internally, intermediate output, root-finding Calculation with TOL = 0.1E-02 X Y(1) Y(2) Y(3) 0.00 1.00000 0.00000 0.00000 2.00 0.94163 0.00003 0.05834 4.00 0.90551 0.00002 0.09447 Root of Y(1)-0.9 at 4.377 Solution is 0.90000 0.00002 0.09998 Calculation with TOL = 0.1E-03 X Y(1) Y(2) Y(3) 0.00 1.00000 0.00000 0.00000 2.00 0.94161 0.00003 0.05837 4.00 0.90551 0.00002 0.09446 Root of Y(1)-0.9 at 4.377 Solution is 0.90000 0.00002 0.09998 Case 2: calculating Jacobian by PEDERV, intermediate output, root-finding Calculation with TOL = 0.1E-02 X Y(1) Y(2) Y(3) 0.00 1.00000 0.00000 0.00000 2.00 0.94163 0.00003 0.05834 4.00 0.90551 0.00002 0.09447 Root of Y(1)-0.9 at 4.377 Solution is 0.90000 0.00002 0.09998 Calculation with TOL = 0.1E-03 X Y(1) Y(2) Y(3) 0.00 1.00000 0.00000 0.00000 2.00 0.94161 0.00003 0.05837 4.00 0.90551 0.00002 0.09446 Root of Y(1)-0.9 at 4.377 Solution is 0.90000 0.00002 0.09998 Case 3: calculating Jacobian internally, no intermediate output, root-finding Calculation with TOL = 0.1E-02 Root of Y(1)-0.9 at 4.377 Solution is 0.90000 0.00002 0.09998 Calculation with TOL = 0.1E-03 Root of Y(1)-0.9 at 4.377 Solution is 0.90000 0.00002 0.09998 Case 4: calculating Jacobian internally, intermediate output, no root-finding Calculation with TOL = 0.1E-02 X Y(1) Y(2) Y(3) 0.00 1.00000 0.00000 0.00000 2.00 0.94163 0.00003 0.05834 4.00 0.90551 0.00002 0.09447 6.00 0.87930 0.00002 0.12068 8.00 0.85858 0.00002 0.14140 10.00 0.84136 0.00002 0.15862 Calculation with TOL = 0.1E-03 X Y(1) Y(2) Y(3) 0.00 1.00000 0.00000 0.00000 2.00 0.94161 0.00003 0.05837 4.00 0.90551 0.00002 0.09446 6.00 0.87926 0.00002 0.12072 8.00 0.85854 0.00002 0.14145 10.00 0.84136 0.00002 0.15863 Case 5: calculating Jacobian internally, no intermediate output, no root-finding (integrate to XEND) Calculation with TOL = 0.1E-02 X Y(1) Y(2) Y(3) 0.00 1.00000 0.00000 0.00000 10.00 0.84136 0.00002 0.15862 Calculation with TOL = 0.1E-03 X Y(1) Y(2) Y(3) 0.00 1.00000 0.00000 0.00000 10.00 0.84136 0.00002 0.15863
- 3~20行目にはケース1の結果が出力されています。ケース1ではy=0.9となるデータ点が見つかるまで 2.0の間隔でx=10.0まで計算を行い、中間結果を出力しています。ヤコビ行列を数値的に計算しています。
- 6~10行目にxの値と許容値 0.1e-002 で計算したyの値が出力されています。
- 11行目にy=0.9となるデータ点が出力されています。
- 12行目に常微分方程式の解が出力されています。
- 14~18行目にxの値と許容値 0.1e-003 で計算したyの値が出力されています。
- 19行目にy=0.9となるデータ点が出力されています。
- 20行目に常微分方程式の解が出力されています。
- 23~40行目にはケース2の結果が出力されています。ケース2ではケース1と同様の計算を行い、中間結果を出力し解が見つかったら終了します。ヤコビ行列を分析的に計算しています。
- 43~52行目にケース3の結果が出力されています。ケース3ではケース1と同様の計算を行いますが、中間結果の出力を行わず、解が見つかったら終了します。
- 55~74行目にケース4の結果が出力されています。ケース4ではケース1と同様の計算を行いますが、中間結果を出力し、x=10.0まで計算を行っています。
- 77~88行目にケース5の結果が出力されています。ケース5ではケース1と同様の計算を行いますが中間結果の出力を行わず、x=10.0まで計算を行っています。
ソースコード
(本ルーチンの詳細はd02ejf のマニュアルページを参照)
※本サンプルソースコードは科学技術・統計計算ライブラリである「nAG Fortranライブラリ」のルーチンを呼び出します。
サンプルのコンパイル及び実行方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
このソースコードをダウンロード |
! D02EJF Example Program Text ! Mark 23 Release. nAG Copyright 2011. MODULE d02ejfe_mod ! Data for D02EJF example program ! .. Use Statements .. USE nag_library, ONLY : nag_wp ! .. Implicit None Statement .. IMPLICIT NONE ! .. Parameters .. REAL (KIND=nag_wp), PARAMETER :: alpha = 0.04_nag_wp REAL (KIND=nag_wp), PARAMETER :: beta = 1.0E4_nag_wp REAL (KIND=nag_wp), PARAMETER :: gamma = 3.0E7_nag_wp REAL (KIND=nag_wp), PARAMETER :: zero = 0.0_nag_wp INTEGER, PARAMETER :: n = 3, nin = 5, nout = 6 ! .. Local Scalars .. REAL (KIND=nag_wp) :: h, xend INTEGER, SAVE :: k CONTAINS SUBROUTINE fcn(x,y,f) ! .. Implicit None Statement .. IMPLICIT NONE ! .. Scalar Arguments .. REAL (KIND=nag_wp), INTENT (IN) :: x ! .. Array Arguments .. REAL (KIND=nag_wp), INTENT (OUT) :: f(*) REAL (KIND=nag_wp), INTENT (IN) :: y(*) ! .. Executable Statements .. f(1) = -alpha*y(1) + beta*y(2)*y(3) f(2) = alpha*y(1) - beta*y(2)*y(3) - gamma*y(2)*y(2) f(3) = gamma*y(2)*y(2) RETURN END SUBROUTINE fcn SUBROUTINE pederv(x,y,pw) ! .. Implicit None Statement .. IMPLICIT NONE ! .. Scalar Arguments .. REAL (KIND=nag_wp), INTENT (IN) :: x ! .. Array Arguments .. REAL (KIND=nag_wp), INTENT (OUT) :: pw(*) REAL (KIND=nag_wp), INTENT (IN) :: y(*) ! .. Executable Statements .. pw(1) = -alpha pw(2) = alpha pw(3) = zero pw(4) = beta*y(3) pw(5) = -beta*y(3) - 2.0_nag_wp*gamma*y(2) pw(6) = 2.0_nag_wp*gamma*y(2) pw(7) = beta*y(2) pw(8) = -beta*y(2) pw(9) = zero RETURN END SUBROUTINE pederv FUNCTION g(x,y) ! .. Implicit None Statement .. IMPLICIT NONE ! .. Function Return Value .. REAL (KIND=nag_wp) :: g ! .. Scalar Arguments .. REAL (KIND=nag_wp), INTENT (IN) :: x ! .. Array Arguments .. REAL (KIND=nag_wp), INTENT (IN) :: y(*) ! .. Executable Statements .. g = y(1) - 0.9E0_nag_wp RETURN END FUNCTION g SUBROUTINE output(xsol,y) ! .. Implicit None Statement .. IMPLICIT NONE ! .. Scalar Arguments .. REAL (KIND=nag_wp), INTENT (INOUT) :: xsol ! .. Array Arguments .. REAL (KIND=nag_wp), INTENT (IN) :: y(*) ! .. Local Scalars .. INTEGER :: j ! .. Intrinsic Functions .. INTRINSIC real ! .. Executable Statements .. WRITE (nout,99999) xsol, (y(j),j=1,n) xsol = xend - real(k,kind=nag_wp)*h k = k - 1 RETURN 99999 FORMAT (1X,F8.2,3F13.5) END SUBROUTINE output END MODULE d02ejfe_mod PROGRAM d02ejfe ! D02EJF Example Main Program ! .. Use Statements .. USE nag_library, ONLY : d02ejf, d02ejw, d02ejx, d02ejy, nag_wp USE d02ejfe_mod, ONLY : fcn, g, h, k, n, nin, nout, output, pederv, xend ! .. Implicit None Statement .. IMPLICIT NONE ! .. Local Scalars .. REAL (KIND=nag_wp) :: tol, x, xinit INTEGER :: i, icase, ifail, iw, j, kinit ! .. Local Arrays .. REAL (KIND=nag_wp), ALLOCATABLE :: w(:), y(:), yinit(:) ! .. Intrinsic Functions .. INTRINSIC real ! .. Executable Statements .. WRITE (nout,*) 'D02EJF Example Program Results' iw = (12+n)*n + 50 ALLOCATE (w(iw),y(n),yinit(n)) ! Skip heading in data file READ (nin,*) ! xinit: initial x value, xend: final x value ! y: initial solution values READ (nin,*) xinit, xend READ (nin,*) yinit(1:n) READ (nin,*) kinit DO icase = 1, 5 IF (icase/=2) THEN WRITE (nout,99995) icase, 'Jacobian internally' ELSE WRITE (nout,99995) icase, 'Jacobian by PEDERV' END IF SELECT CASE (icase) CASE (1,2) WRITE (nout,99994) 'intermediate output, root-finding' CASE (3) WRITE (nout,99994) 'no intermediate output, root-finding' CASE (4) WRITE (nout,99994) 'intermediate output, no root-finding' CASE (5) WRITE (nout,99994) & 'no intermediate output, no root-finding (integrate to XEND)' END SELECT DO j = 3, 4 tol = 10.0E0_nag_wp**(-j) WRITE (nout,99999) ' Calculation with TOL =', tol x = xinit y(1:n) = yinit(1:n) IF (icase/=3) THEN WRITE (nout,*) ' X Y(1) Y(2) Y(3)' k = kinit h = (xend-x)/real(k+1,kind=nag_wp) END IF ifail = 0 SELECT CASE (icase) CASE (1) CALL d02ejf(x,xend,n,y,fcn,d02ejy,tol,'Default',output,g,w,iw, & ifail) WRITE (nout,99998) ' Root of Y(1)-0.9 at', x WRITE (nout,99997) ' Solution is', (y(i),i=1,n) CASE (2) CALL d02ejf(x,xend,n,y,fcn,pederv,tol,'Default',output,g,w,iw, & ifail) WRITE (nout,99998) ' Root of Y(1)-0.9 at', x WRITE (nout,99997) ' Solution is', (y(i),i=1,n) CASE (3) CALL d02ejf(x,xend,n,y,fcn,d02ejy,tol,'Default',d02ejx,g,w,iw, & ifail) WRITE (nout,99998) ' Root of Y(1)-0.9 at', x WRITE (nout,99997) ' Solution is', (y(i),i=1,n) CASE (4) ifail = 0 CALL d02ejf(x,xend,n,y,fcn,d02ejy,tol,'Default',output,d02ejw, & w,iw,ifail) CASE (5) WRITE (nout,99996) x, (y(i),i=1,n) CALL d02ejf(x,xend,n,y,fcn,d02ejy,tol,'Default',d02ejx,d02ejw, & w,iw,ifail) WRITE (nout,99996) x, (y(i),i=1,n) END SELECT IF (tol<0.0E0_nag_wp) WRITE (nout,*) ' Range too short for TOL' END DO IF (icase<5) THEN WRITE (nout,*) END IF END DO 99999 FORMAT (/1X,A,E8.1) 99998 FORMAT (1X,A,F7.3) 99997 FORMAT (1X,A,3F13.5) 99996 FORMAT (1X,F8.2,3F13.5) 99995 FORMAT (/1X,'Case ',I1,': calculating ',A,',') 99994 FORMAT (8X,A) END PROGRAM d02ejfe