Module runge_kutta_45_functional
|
|
1
2 """
3 B{Course:} TKP4106 Process Modelling\012
4 B{Task:} Implementing a 4th order Runge-Kutta integrator
5
6 @author: Tore Haug-Warberg
7 @contact: haugwarb@nt.ntnu.no
8 @organization: Department of Chemical Engineering, NTNU, Norway
9 @license: TKP4106 Process Modelling (demo code)
10 @since: 2015-09-24
11 @change: 2015-09-24 started (v1.0)
12 @change: 2015-10-13 implemented "execfile" for loading code from external
13 source (v1.1)
14 @version: 1.1
15 @todo:
16 @requires: Python v2.7 (not tested in v3.0)
17 @requires: runge_kutta_45_function_execfile_1.py (student's task)
18 @see: U{Seven Topics in Python<http://www.nt.ntnu.no/
19 users/haugwarb/TKP4106/Tore/Syllabus/topic_00/TeX/
20 seven_topics.pdf>}
21 @note:
22 """
23
24
25 import getopt
26 import sys
27 import math
28
29
30 -def rk45(ydot=[lambda x,y: y[0]], y0=[1.0], x0=0.0, x1=1.0, nx=20):
31 """
32 1.
33 Numerical integration of a list of ODEs using a 4th order Runge-Kutta scheme::
34
35 h
36 y_{i+1} = y_i + - ( k1 + 2*k2 + 2*k3 + k4 )
37 6
38
39 where::
40
41 k1 = f(x_i , y_i )
42 k2 = f(x_i+h/2, y_i+k1*h/2)
43 k3 = f(x_i+h/2, y_i+k2*h/2)
44 k4 = f(x_i+h , y_i+k3 )
45
46 2.
47 Application Programming Interface (API):
48
49 @param ydot: a list of ODEs provided as C{ydot[k] = lambda x,y: fun_k(x,y)}
50 @param y0: a list of starting values for y
51 @param x0: start of integration domain
52 @param x1: end of integration domain
53 @param nx: number of integration steps in addition to x0
54
55 @return: Integration history "y" defined by [ y0, y1, ... ynx ]
56
57 @type ydot: [ lambda, lambda, ... ]
58 @type y0: [ float, float, ... ]
59 @type x0: float
60 @type x1: float
61 @type nx: int
62
63 @rtype: [ list, list, ... ]
64
65 """
66
67 execfile('runge_kutta_45_functional_execfile_1.py', globals(), locals())
68 return locals()['y']
69
70
71
72
73
74 if __name__ == '__main__':
75
76
77 print '\n0. Integration of default problem:\n'
78 print '{:19s}'.format(' y')
79
80 for yk in rk45():
81 print '{:19.16f}'.format(*yk)
82
83 print ''
84
85
86 N = 12
87
88 t0 = 0.0
89 t1 = 2*3.141592653589793
90
91 y0 = [ 2.0, 0.0 ]
92
93 ydot = [lambda x,y:-y[1], \
94 lambda x,y: y[0]]
95
96 print '\n1. Integration along circle in t-range [{:f}, {:f}]:\n'.format(t0,t1)
97 print '{:19s}, {:19s}'.format(' x',' y')
98
99 for yk in rk45(ydot, y0, t0, t1, N):
100 print '{:19.16f}, {:19.16f}'.format(*yk)
101
102 print ''
103
104
105
106 N = 20
107
108 t0 = 0.0
109 t1 = 0.4*math.pi
110
111 n = 5
112 y0 = [1.0] + [0.0]*n
113
114 a = 0.1
115 u = lambda x: math.sin(x)
116
117 ydot = [lambda x,y: -a*y[0] + u(x)] + [None for i in range(n)]
118
119
120
121 ydot[1] = lambda x,y: -a*y[1] + a*y[0]
122 ydot[2] = lambda x,y: -a*y[2] + a*y[1]
123 ydot[3] = lambda x,y: -a*y[3] + a*y[2]
124 ydot[4] = lambda x,y: -a*y[4] + a*y[3]
125 ydot[5] = lambda x,y: -a*y[5] + a*y[4]
126
127
128
129 i0 = 0
130 ydot[i0+1] = lambda x,y: -a*y[i0+1] + a*y[i0]
131 i1 = 1
132 ydot[i1+1] = lambda x,y: -a*y[i1+1] + a*y[i1]
133 i2 = 2
134 ydot[i2+1] = lambda x,y: -a*y[i2+1] + a*y[i2]
135 i3 = 3
136 ydot[i3+1] = lambda x,y: -a*y[i3+1] + a*y[i3]
137 i4 = 4
138 ydot[i4+1] = lambda x,y: -a*y[i4+1] + a*y[i4]
139
140
141
142 for i in range(n):
143 ydot[i+1] = lambda x,y: -a*y[i+1] + a*y[i]
144
145
146 for i in range(n):
147 ydot[i+1] = lambda x,y,j=i: -a*y[j+1] + a*y[j]
148
149
150
151 for i in range(n):
152 ydot[i+1] = (lambda j: lambda x,y: -a*y[j+1] + a*y[j])(i)
153
154
155 for i in range(n):
156 ydot[i+1] = (lambda j=i: lambda x,y: -a*y[j+1] + a*y[j])()
157
158
159
160 for i in range(n):
161 exec('ydot[{:n}] = lambda x,y: -a*y[{:n}] + a*y[{:n}]'.format(i+1,i+1,i))
162
163 print '\n2. Linearly coupled differential equations:\n'
164 print(', '.join('{:8s}'.format(' y'+str(i)) for i in range(n+1)))
165
166 for yk in rk45(ydot, y0, t0, t1, N):
167 print(', '.join('{:8.5f}'.format(yki) for yki in yk))
168
169 print ''
170
171
172 N = 20
173
174 t0 = 0.0
175 t1 = 0.4*math.pi
176
177 n = 5
178 y0 = [1.0] + [0.0]*n
179
180 a = 0.1
181 u = lambda x: math.sin(x)
182
183 ydot = [lambda x,y: -a*y[0] + u(x)] + [None for i in range(n)]
184
185 for i in range(n):
186 ydot[i+1] = (lambda j=i: lambda x,y: -a*y[j+1] + ydot[j](x,y))()
187
188 print '\n3. Non-linearly coupled differential equations:\n'
189 print(', '.join('{:8s}'.format(' y'+str(i)) for i in range(n+1)))
190
191 for yk in rk45(ydot, y0, t0, t1, N):
192 print(', '.join('{:8.5f}'.format(yki) for yki in yk))
193
194 print ''
195