4 from scipy
import weave
5 from scipy
.weave
import blitz
, inline
, converters
6 from const
import timestep
7 from sweep
import native_sweep
, sweep
10 if not (isinstance(lhs
, np
.ndarray
)
11 and isinstance(rhs
, np
.ndarray
)):
12 raise TypeError("arguments must be arrays")
14 if lhs
.shape
!= rhs
.shape
:
15 raise ValueError("arrays must be the same shape")
17 return np
.max(np
.abs(lhs
- rhs
))
20 class ExplicitSolver(object):
21 '''Represents equation solver with time stepper
24 def __init__(self
, I
, J
, time
, ht
=None, ly
=2e-5, lz
=2e-5, lambda_
=2e-6, C
=3e8
, solver
='inline', debug
=False):
26 if solver
== 'python':
27 self
._step
= self
._python
_step
28 elif solver
== 'blitz':
29 self
._step
= self
._blitz
_step
30 elif solver
== 'inline':
31 self
._step
= self
._inline
_step
33 raise ValueError('incorrect solver: %s' % solver
)
35 self
.solve
= self
._explicit
_solve
39 self
.I
, self
.J
, self
.ly
, self
.lz
, self
.lambda_
= I
, J
, ly
, lz
, lambda_
40 self
.hy
= np
.double(ly
/ I
)
41 self
.hz
= np
.double(lz
/ J
)
43 self
.ht
= timestep(min(self
.hy
, self
.hz
) / (C
* np
.sqrt(2)))
46 self
.K
= int(self
.time
/ self
.ht
)
47 self
.u
= np
.zeros((3, I
+ 1, J
+ 1), 'd')
57 def _debug_print(self
):
58 print "grid: %d x %d" % (self
.I
, self
.J
)
59 print "time:ht:K = %g:%g:%d" % (self
.time
, self
.ht
, self
.K
)
61 print "ly:hy:I = %g:%g:%d" % (self
.ly
, self
.hy
, self
.I
)
62 print "lz:hz:J = %g:%g:%d" % (self
.lz
, self
.hz
, self
.J
)
64 print "u size (in Kbytes):", ((self
.u
.size
* self
.u
.itemsize
) / 1024.)
65 print "extrapolated size (in Mbytes):", (float(self
.I
* self
.J
* self
.K
* self
.u
.itemsize
) / (1024**2))
68 def _init_bc(self
, k
, time
):
69 for i
in xrange(self
.u
.shape
[1]):
70 self
.u
[k
, i
, 0] = np
.sin((np
.pi
* i
) / self
.I
) * np
.sin((2 * np
.pi
* self
.C
* self
.ht
* time
) / self
.lambda_
)
72 def _python_step(self
):
73 g
= (self
.C
**2 * self
.ht
**2) / self
.hy
**2
74 d
= (self
.C
**2 * self
.ht
**2) / self
.hz
**2
75 self
.u
[2, 1:-1, 1:-1] = \
76 g
* (self
.u
[1, 2:, 1:-1] + self
.u
[1, 0:-2, 1:-1]) + \
77 d
* (self
.u
[1, 1:-1, 2:] + self
.u
[1, 1:-1, 0:-2]) + \
78 2 * (1 - g
- d
) * self
.u
[1, 1:-1, 1:-1] - \
81 def _blitz_step(self
):
82 g
= float((self
.C
**2 * self
.ht
**2) / self
.hy
**2)
83 d
= float((self
.C
**2 * self
.ht
**2) / self
.hz
**2)
86 "u[2, 1:-1, 1:-1] = " \
87 "g * (u[1, 2:, 1:-1] + u[1, 0:-2, 1:-1]) + " \
88 "d * (u[1, 1:-1, 2:] + u[1, 1:-1, 0:-2]) + " \
89 "2 * (1 - g - d) * u[1, 1:-1, 1:-1] - " \
91 blitz(expr
, check_size
=0)
93 def _inline_step(self
):
94 g
= float((self
.C
**2 * self
.ht
**2) / self
.hy
**2)
95 d
= float((self
.C
**2 * self
.ht
**2) / self
.hz
**2)
97 I
, J
, K
= self
.I
, self
.J
, self
.K
99 for (int i=1; i < I-1; ++i) {
100 for (int j = 1; j < J-1; ++j) {
101 u(2, i, j) = g * (u(1, i+1, j) + u(1, i-1, j)) +
102 d * (u(1, i, j+1) + u(1, i, j-1)) +
103 2 * (1 - g - d) * u(1, i, j) -
109 ['u', 'g', 'd', 'I', 'J', 'K'],
110 type_converters
=converters
.blitz
,
113 def _explicit_solve(self
):
115 for k
in xrange(2, self
.K
):
117 self
.u
[0] = self
.u
[1].copy()
118 self
.u
[1] = self
.u
[2].copy()
119 self
._init
_bc
(2, k
+ 1)
124 class ImplicitSolver(object):
125 '''Represents equation solver with implicit difference scheme
128 def __init__(self
, I
, J
, time
, ht
=None, ly
=2e-5, lz
=2e-5, lambda_
=2e-6, C
=3e8
, debug
=False):
130 self
.solve
= self
._implicit
_solve
134 self
.I
, self
.J
, self
.ly
, self
.lz
, self
.lambda_
= I
, J
, ly
, lz
, lambda_
135 self
.hy
= np
.double(ly
/ I
)
136 self
.hz
= np
.double(lz
/ J
)
141 self
.ht
= np
.trunc(np
.float64(l
[0])) * np
.power(10, np
.float64(l
[1]))
144 self
.K
= int(self
.time
/ self
.ht
)
145 self
.u
= np
.zeros((3, I
+ 1, J
+ 1), 'd')
155 def _debug_print(self
):
156 print "grid: %d x %d" % (self
.I
, self
.J
)
157 print "time:ht:K = %g:%g:%d" % (self
.time
, self
.ht
, self
.K
)
159 print "ly:hy:I = %g:%g:%d" % (self
.ly
, self
.hy
, self
.I
)
160 print "lz:hz:J = %g:%g:%d" % (self
.lz
, self
.hz
, self
.J
)
162 print "u size (in Kbytes):", ((self
.u
.size
* self
.u
.itemsize
) / 1024.)
163 print "extrapolated size (in Mbytes):", (float(self
.I
* self
.J
* self
.K
* self
.u
.itemsize
) / (1024**2))
165 print "\gamma_y =", (self
.C
**2 * self
.ht
**2) / self
.hy
**2
166 print "\gamma_z =", (self
.C
**2 * self
.ht
**2) / self
.hz
**2
169 def _init_bc(self
, k
, time
):
170 for i
in xrange(self
.u
.shape
[1]):
171 self
.u
[k
, i
, 0] = np
.sin((np
.pi
* i
) / self
.I
) * np
.sin((2 * np
.pi
* self
.C
* self
.ht
* time
) / self
.lambda_
)
173 def _make_system(self
):
174 '''Формирует матрицу системы для прогонки (ее диагонали).
177 d
= (self
.C
**2 * self
.ht
**2) / self
.hz
**2
178 a
= np
.zeros(J
- 2) - d
179 b
= np
.zeros(J
- 1) + (1 + 2 * d
)
183 def _make_rhs(self
, i
, k
):
184 '''Формирует правую часть системы для прогонки для шага i по y
186 g
= (self
.C
**2 * self
.ht
**2) / self
.hy
**2
187 d
= (self
.C
**2 * self
.ht
**2) / self
.hz
**2
189 f
= g
* (u
[1, i
+ 1, 1:-1] + u
[1, i
- 1, 1:-1]) + 2 * (1 - g
) * u
[1, i
, 1:-1] - u
[0, i
, 1:-1]
190 f
[0] += d
* u
[2, i
, 0]
191 f
[-1] += d
* u
[2, i
, self
.J
]
194 def _implicit_solve(self
):
195 # система всегда одна и та же
196 a
, b
, c
= self
._make
_system
()
198 for k
in xrange(2, self
.K
):
200 for i
in xrange(1, self
.I
- 1):
201 f
= self
._make
_rhs
(i
, k
)
202 self
.u
[2, i
, 1:-1] = native_sweep(a
, b
, c
, f
)
203 self
.u
[0] = self
.u
[1].copy()
204 self
.u
[1] = self
.u
[2].copy()