後退差分公式を用いた常微分方程式

Fortranによるサンプルソースコード : 使用ルーチン名:d02ejf

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


関連情報
© 日本ニューメリカルアルゴリズムズグループ株式会社 2025
Privacy Policy  /  Trademarks