PyFishPack 0.1.0__cp313-cp313-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- PyFishPack/__init__.py +86 -0
- PyFishPack/__pycache__/__init__.cpython-313.pyc +0 -0
- PyFishPack/__pycache__/apps.cpython-313.pyc +0 -0
- PyFishPack/_dummy.c +23 -0
- PyFishPack/_dummy.cp313-win_amd64.pyd +0 -0
- PyFishPack/apps.py +3640 -0
- PyFishPack/fishpack.cp313-win_amd64.dll.a +0 -0
- PyFishPack/fishpack.cp313-win_amd64.pyd +0 -0
- PyFishPack/meson.build +213 -0
- PyFishPack/src/archive/f77/Makefile +19 -0
- PyFishPack/src/archive/f77/blktri.f +1404 -0
- PyFishPack/src/archive/f77/cblktri.f +1414 -0
- PyFishPack/src/archive/f77/cmgnbn.f +1592 -0
- PyFishPack/src/archive/f77/comf.f +186 -0
- PyFishPack/src/archive/f77/fftpack.f +2968 -0
- PyFishPack/src/archive/f77/genbun.f +1335 -0
- PyFishPack/src/archive/f77/gnbnaux.f +314 -0
- PyFishPack/src/archive/f77/hstcrt.f +443 -0
- PyFishPack/src/archive/f77/hstcsp.f +683 -0
- PyFishPack/src/archive/f77/hstcyl.f +485 -0
- PyFishPack/src/archive/f77/hstplr.f +538 -0
- PyFishPack/src/archive/f77/hstssp.f +634 -0
- PyFishPack/src/archive/f77/hw3crt.f +687 -0
- PyFishPack/src/archive/f77/hwscrt.f +512 -0
- PyFishPack/src/archive/f77/hwscsp.f +728 -0
- PyFishPack/src/archive/f77/hwscyl.f +538 -0
- PyFishPack/src/archive/f77/hwsplr.f +602 -0
- PyFishPack/src/archive/f77/hwsssp.f +780 -0
- PyFishPack/src/archive/f77/pois3d.f +550 -0
- PyFishPack/src/archive/f77/poistg.f +875 -0
- PyFishPack/src/archive/f77/sepaux.f +361 -0
- PyFishPack/src/archive/f77/sepeli.f +1029 -0
- PyFishPack/src/archive/f77/sepx4.f +958 -0
- PyFishPack/src/centered_axisymmetric_spherical_solver.f90 +1002 -0
- PyFishPack/src/centered_cartesian_helmholtz_solver_3d.f90 +819 -0
- PyFishPack/src/centered_cartesian_solver.f90 +583 -0
- PyFishPack/src/centered_cylindrical_solver.f90 +634 -0
- PyFishPack/src/centered_helmholtz_solvers.f90 +156 -0
- PyFishPack/src/centered_polar_solver.f90 +746 -0
- PyFishPack/src/centered_real_linear_systems_solver.f90 +280 -0
- PyFishPack/src/centered_spherical_solver.f90 +928 -0
- PyFishPack/src/complex_block_tridiagonal_linear_systems_solver.f90 +1947 -0
- PyFishPack/src/complex_linear_systems_solver.f90 +1787 -0
- PyFishPack/src/fftpack_c_api.f90 +86 -0
- PyFishPack/src/fishpack.f90 +191 -0
- PyFishPack/src/fishpack.pyf +504 -0
- PyFishPack/src/fishpack_c_api.f90 +365 -0
- PyFishPack/src/fishpack_original.pyf +2119 -0
- PyFishPack/src/fishpack_precision.f90 +53 -0
- PyFishPack/src/general_linear_systems_solver_3d.f90 +296 -0
- PyFishPack/src/iterative_solvers.f90 +969 -0
- PyFishPack/src/main.f90 +10 -0
- PyFishPack/src/pyfishpack_module.c +1302 -0
- PyFishPack/src/real_block_tridiagonal_linear_systems_solver.f90 +319 -0
- PyFishPack/src/sepeli.f90 +1454 -0
- PyFishPack/src/sepx4.f90 +1338 -0
- PyFishPack/src/staggered_axisymmetric_spherical_solver.f90 +908 -0
- PyFishPack/src/staggered_cartesian_solver.f90 +553 -0
- PyFishPack/src/staggered_cylindrical_solver.f90 +630 -0
- PyFishPack/src/staggered_helmholtz_solvers.f90 +172 -0
- PyFishPack/src/staggered_polar_solver.f90 +651 -0
- PyFishPack/src/staggered_real_linear_systems_solver.f90 +258 -0
- PyFishPack/src/staggered_spherical_solver.f90 +758 -0
- PyFishPack/src/three_dimensional_solvers.f90 +602 -0
- PyFishPack/src/type_CenteredCyclicReductionUtility.f90 +1714 -0
- PyFishPack/src/type_CyclicReductionUtility.f90 +472 -0
- PyFishPack/src/type_FishpackWorkspace.f90 +290 -0
- PyFishPack/src/type_GeneralizedCyclicReductionUtility.f90 +1980 -0
- PyFishPack/src/type_PeriodicFastFourierTransform.f90 +3789 -0
- PyFishPack/src/type_SepAux.f90 +586 -0
- PyFishPack/src/type_StaggeredCyclicReductionUtility.f90 +893 -0
- pyfishpack-0.1.0.dist-info/DELVEWHEEL +2 -0
- pyfishpack-0.1.0.dist-info/METADATA +81 -0
- pyfishpack-0.1.0.dist-info/RECORD +81 -0
- pyfishpack-0.1.0.dist-info/WHEEL +5 -0
- pyfishpack-0.1.0.dist-info/licenses/LICENSE +21 -0
- pyfishpack-0.1.0.dist-info/top_level.txt +1 -0
- pyfishpack.libs/libgcc_s_seh-1-25d59ccffa1a9009644065b069829e07.dll +0 -0
- pyfishpack.libs/libgfortran-5-08f2195cfa0d823e13371c5c3186a82a.dll +0 -0
- pyfishpack.libs/libquadmath-0-c5abb9113f1ee64b87a889958e4b7418.dll +0 -0
- pyfishpack.libs/libwinpthread-1-83908d14abfafb8b3bfa38cf51ecee56.dll +0 -0
|
@@ -0,0 +1,1787 @@
|
|
|
1
|
+
!
|
|
2
|
+
! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
3
|
+
! * *
|
|
4
|
+
! * copyright (c) 2005 by UCAR *
|
|
5
|
+
! * *
|
|
6
|
+
! * University Corporation for Atmospheric Research *
|
|
7
|
+
! * *
|
|
8
|
+
! * all rights reserved *
|
|
9
|
+
! * *
|
|
10
|
+
! * Fishpack *
|
|
11
|
+
! * *
|
|
12
|
+
! * A Package of Fortran *
|
|
13
|
+
! * *
|
|
14
|
+
! * Subroutines and Example Programs *
|
|
15
|
+
! * *
|
|
16
|
+
! * for Modeling Geophysical Processes *
|
|
17
|
+
! * *
|
|
18
|
+
! * by *
|
|
19
|
+
! * *
|
|
20
|
+
! * John Adams, Paul Swarztrauber and Roland Sweet *
|
|
21
|
+
! * *
|
|
22
|
+
! * of *
|
|
23
|
+
! * *
|
|
24
|
+
! * the National Center for Atmospheric Research *
|
|
25
|
+
! * *
|
|
26
|
+
! * Boulder, Colorado (80307) U.S.A. *
|
|
27
|
+
! * *
|
|
28
|
+
! * which is sponsored by *
|
|
29
|
+
! * *
|
|
30
|
+
! * the National Science Foundation *
|
|
31
|
+
! * *
|
|
32
|
+
! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
33
|
+
!
|
|
34
|
+
module complex_linear_systems_solver
|
|
35
|
+
|
|
36
|
+
use fishpack_precision, only: &
|
|
37
|
+
wp, & ! Working precision
|
|
38
|
+
ip, & ! Integer precision
|
|
39
|
+
PI
|
|
40
|
+
|
|
41
|
+
use type_FishpackWorkspace, only: &
|
|
42
|
+
FishpackWorkspace
|
|
43
|
+
|
|
44
|
+
! Explicit typing only
|
|
45
|
+
implicit none
|
|
46
|
+
|
|
47
|
+
! Everything is private unless stated otherwise
|
|
48
|
+
private
|
|
49
|
+
public :: cmgnbn
|
|
50
|
+
|
|
51
|
+
! Parameters confined to the module
|
|
52
|
+
real(wp), parameter :: ZERO = 0.0_wp
|
|
53
|
+
real(wp), parameter :: HALF = 0.5_wp
|
|
54
|
+
real(wp), parameter :: ONE = 1.0_wp
|
|
55
|
+
real(wp), parameter :: TWO = 2.0_wp
|
|
56
|
+
real(wp), parameter :: THREE = 3.0_wp
|
|
57
|
+
real(wp), parameter :: FOUR = 4.0_wp
|
|
58
|
+
integer(ip), parameter :: IIWK = 11 ! Size of workspace_indices
|
|
59
|
+
|
|
60
|
+
contains
|
|
61
|
+
!
|
|
62
|
+
! SUBROUTINE cmgnbn(nperod, n, mperod, m, a, b, c, idimy, y, ierror)
|
|
63
|
+
!
|
|
64
|
+
!
|
|
65
|
+
! DIMENSION OF a(m), b(m), c(m), y(idimy, n)
|
|
66
|
+
! ARGUMENTS
|
|
67
|
+
!
|
|
68
|
+
! PURPOSE The name of this package is a mnemonic for the
|
|
69
|
+
! complex generalized Buneman algorithm.
|
|
70
|
+
! it solves the complex linear system of equation
|
|
71
|
+
!
|
|
72
|
+
! a(i)*x(i-1, j) + b(i)*x(i, j) + c(i)*x(i+1, j)
|
|
73
|
+
! + x(i, j-1) - TWO * x(i, j) + x(i, j+1) = y(i, j)
|
|
74
|
+
!
|
|
75
|
+
! for i = 1, 2, ..., m and j = 1, 2, ..., n.
|
|
76
|
+
!
|
|
77
|
+
! indices i+1 and i-1 are evaluated modulo m,
|
|
78
|
+
! i.e., x(0, j) = x(m, j) and x(m+1, j) = x(1, j),
|
|
79
|
+
! and x(i, 0) may equal 0, x(i, 2), or x(i, n),
|
|
80
|
+
! and x(i, n+1) may equal 0, x(i, n-1), or x(i, 1)
|
|
81
|
+
! depending on an input parameter.
|
|
82
|
+
!
|
|
83
|
+
! USAGE call cmgnbn (nperod, n, mperod, m, a, b, c, idimy, y,
|
|
84
|
+
! ierror)
|
|
85
|
+
!
|
|
86
|
+
! ARGUMENTS
|
|
87
|
+
!
|
|
88
|
+
! ON INPUT nperod
|
|
89
|
+
!
|
|
90
|
+
! indicates the values that x(i, 0) and
|
|
91
|
+
! x(i, n+1) are assumed to have.
|
|
92
|
+
!
|
|
93
|
+
! = 0 if x(i, 0) = x(i, n) and x(i, n+1) =
|
|
94
|
+
! x(i, 1).
|
|
95
|
+
! = 1 if x(i, 0) = x(i, n+1) = 0 .
|
|
96
|
+
! = 2 if x(i, 0) = 0 and x(i, n+1) = x(i, n-1).
|
|
97
|
+
! = 3 if x(i, 0) = x(i, 2) and x(i, n+1) =
|
|
98
|
+
! x(i, n-1).
|
|
99
|
+
! = 4 if x(i, 0) = x(i, 2) and x(i, n+1) = 0.
|
|
100
|
+
!
|
|
101
|
+
! n
|
|
102
|
+
! the number of unknowns in the j-direction.
|
|
103
|
+
! n must be greater than 2.
|
|
104
|
+
!
|
|
105
|
+
! mperod
|
|
106
|
+
! = 0 if a(1) and c(m) are not zero
|
|
107
|
+
! = 1 if a(1) = c(m) = 0
|
|
108
|
+
!
|
|
109
|
+
! m
|
|
110
|
+
! the number of unknowns in the i-direction.
|
|
111
|
+
! n must be greater than 2.
|
|
112
|
+
!
|
|
113
|
+
! a, b, c
|
|
114
|
+
! one-dimensional complex arrays of length m
|
|
115
|
+
! that specify the coefficients in the linear
|
|
116
|
+
! equations given above. if mperod = 0
|
|
117
|
+
! the array elements must not depend upon
|
|
118
|
+
! the index i, but must be constant.
|
|
119
|
+
! specifically, the subroutine checks the
|
|
120
|
+
! following condition .
|
|
121
|
+
!
|
|
122
|
+
! a(i) = c(1)
|
|
123
|
+
! c(i) = c(1)
|
|
124
|
+
! b(i) = b(1)
|
|
125
|
+
!
|
|
126
|
+
! for i=1, 2, ..., m.
|
|
127
|
+
!
|
|
128
|
+
! idimy
|
|
129
|
+
! the row (or first) dimension of the
|
|
130
|
+
! two-dimensional array y as it appears
|
|
131
|
+
! in the program calling cmgnbn.
|
|
132
|
+
! this parameter is used to specify the
|
|
133
|
+
! variable dimension of y.
|
|
134
|
+
! idimy must be at least m.
|
|
135
|
+
!
|
|
136
|
+
! y
|
|
137
|
+
! a two-dimensional complex array that
|
|
138
|
+
! specifies the values of the right side
|
|
139
|
+
! of the linear system of equations given
|
|
140
|
+
! above.
|
|
141
|
+
! y must be dimensioned at least m*n.
|
|
142
|
+
!
|
|
143
|
+
!
|
|
144
|
+
! ON OUTPUT y
|
|
145
|
+
!
|
|
146
|
+
! contains the solution x.
|
|
147
|
+
!
|
|
148
|
+
! ierror
|
|
149
|
+
! an error flag which indicates invalid
|
|
150
|
+
! input parameters except for number
|
|
151
|
+
! zero, a solution is not attempted.
|
|
152
|
+
!
|
|
153
|
+
! = 0 no error.
|
|
154
|
+
! = 1 m <= 2 .
|
|
155
|
+
! = 2 n <= 2
|
|
156
|
+
! = 3 idimy < m
|
|
157
|
+
! = 4 nperod < 0 or nperod > 4
|
|
158
|
+
! = 5 mperod < 0 or mperod > 1
|
|
159
|
+
! = 6 a(i) /= c(1) or c(i) /= c(1) or
|
|
160
|
+
! b(i) /= b(1) for
|
|
161
|
+
! some i=1, 2, ..., m.
|
|
162
|
+
! = 7 a(1) /= 0 or c(m) /= 0 and
|
|
163
|
+
! mperod = 1
|
|
164
|
+
! = 20 if the dynamic allocation of real and
|
|
165
|
+
! complex workspace required for solution
|
|
166
|
+
! fails (for example if n, m are too large
|
|
167
|
+
! for your computer)
|
|
168
|
+
!
|
|
169
|
+
! HISTORY Written in 1979 by Roland Sweet of NCAR'S
|
|
170
|
+
! scientific computing division. Made available
|
|
171
|
+
! on NCAR's public libraries in January, 1980.
|
|
172
|
+
! Revised in June 2004 by John Adams using
|
|
173
|
+
! Fortran 90 dynamically allocated workspace.
|
|
174
|
+
!
|
|
175
|
+
! ALGORITHM The linear system is solved by a cyclic
|
|
176
|
+
! reduction algorithm described in the
|
|
177
|
+
! reference below.
|
|
178
|
+
!
|
|
179
|
+
! REFERENCES Sweet, R., 'A cyclic reduction algorithm for
|
|
180
|
+
! solving block tridiagonal systems of arbitrary
|
|
181
|
+
! dimensions, ' SIAM J. on Numer. Anal.,
|
|
182
|
+
! 14(Sept., 1977), pp. 706-720.
|
|
183
|
+
!
|
|
184
|
+
! ACCURACY this test was performed on a platform with
|
|
185
|
+
! 64 bit floating point arithmetic.
|
|
186
|
+
! a uniform random number generator was used
|
|
187
|
+
! to create a solution array x for the system
|
|
188
|
+
! given in the 'purpose' description above
|
|
189
|
+
! with
|
|
190
|
+
! a(i) = c(i) = -0.5 * b(i) = 1, i=1, 2, ..., m
|
|
191
|
+
!
|
|
192
|
+
! and, when mperod = 1
|
|
193
|
+
!
|
|
194
|
+
! a(1) = c(m) = 0
|
|
195
|
+
! a(m) = c(1) = 2.
|
|
196
|
+
!
|
|
197
|
+
! the solution x was substituted into the
|
|
198
|
+
! given system and a right side y was
|
|
199
|
+
! computed. using this array y, subroutine
|
|
200
|
+
! cmgnbn was called to produce approximate
|
|
201
|
+
! solution z. then relative error
|
|
202
|
+
! e = max(abs(z(i, j)-x(i, j)))/
|
|
203
|
+
! max(abs(x(i, j)))
|
|
204
|
+
! was computed, where the two maxima are taken
|
|
205
|
+
! over i=1, 2, ..., m and j=1, ..., n.
|
|
206
|
+
!
|
|
207
|
+
! the value of e is given in the table
|
|
208
|
+
! below for some typical values of m and n.
|
|
209
|
+
!
|
|
210
|
+
! m (=n) mperod nperod e
|
|
211
|
+
! ------ ------ ------ ------
|
|
212
|
+
!
|
|
213
|
+
! 31 0 0 1.e-12
|
|
214
|
+
! 31 1 1 4.e-13
|
|
215
|
+
! 31 1 3 2.e-12
|
|
216
|
+
! 32 0 0 7.e-14
|
|
217
|
+
! 32 1 1 5.e-13
|
|
218
|
+
! 32 1 3 2.e-13
|
|
219
|
+
! 33 0 0 6.e-13
|
|
220
|
+
! 33 1 1 5.e-13
|
|
221
|
+
! 33 1 3 3.e-12
|
|
222
|
+
! 63 0 0 5.e-12
|
|
223
|
+
! 63 1 1 6.e-13
|
|
224
|
+
! 63 1 3 1.e-11
|
|
225
|
+
! 64 0 0 1.e-13
|
|
226
|
+
! 64 1 1 3.e-12
|
|
227
|
+
! 64 1 3 3.e-13
|
|
228
|
+
! 65 0 0 2.e-12
|
|
229
|
+
! 65 1 1 5.e-13
|
|
230
|
+
! 65 1 3 1.e-11
|
|
231
|
+
!
|
|
232
|
+
!
|
|
233
|
+
subroutine cmgnbn(nperod, n, mperod, m, a, b, c, idimy, y, ierror)
|
|
234
|
+
|
|
235
|
+
! Dummy arguments
|
|
236
|
+
integer(ip), intent(in) :: nperod
|
|
237
|
+
integer(ip), intent(in) :: n
|
|
238
|
+
integer(ip), intent(in) :: mperod
|
|
239
|
+
integer(ip), intent(in) :: m
|
|
240
|
+
integer(ip), intent(in) :: idimy
|
|
241
|
+
integer(ip), intent(out) :: ierror
|
|
242
|
+
complex(wp), intent(in) :: a(:)
|
|
243
|
+
complex(wp), intent(in) :: b(:)
|
|
244
|
+
complex(wp), intent(in) :: c(:)
|
|
245
|
+
complex(wp), intent(inout) :: y(:,:)
|
|
246
|
+
|
|
247
|
+
! Local variables
|
|
248
|
+
type(FishpackWorkspace) :: workspace
|
|
249
|
+
|
|
250
|
+
! Check input arguments
|
|
251
|
+
call check_input_arguments(nperod, n, mperod, m, a, b, c, idimy, ierror)
|
|
252
|
+
|
|
253
|
+
! Check error flag
|
|
254
|
+
if (ierror /= 0) return
|
|
255
|
+
|
|
256
|
+
! Allocate memory
|
|
257
|
+
call initialize_workspace(n, m, workspace)
|
|
258
|
+
|
|
259
|
+
! Solve system
|
|
260
|
+
associate( &
|
|
261
|
+
cxw => workspace%complex_workspace, &
|
|
262
|
+
indx => workspace%workspace_indices &
|
|
263
|
+
)
|
|
264
|
+
call cmgnbn_lower_routine(nperod, n, mperod, m, a, b, c, idimy, y, cxw, indx)
|
|
265
|
+
end associate
|
|
266
|
+
|
|
267
|
+
! Release memory
|
|
268
|
+
call workspace%destroy()
|
|
269
|
+
|
|
270
|
+
end subroutine cmgnbn
|
|
271
|
+
|
|
272
|
+
pure subroutine check_input_arguments(nperod, n, mperod, m, a, b, c, idimy, ierror)
|
|
273
|
+
|
|
274
|
+
! Dummy arguments
|
|
275
|
+
integer(ip), intent(in) :: nperod
|
|
276
|
+
integer(ip), intent(in) :: n
|
|
277
|
+
integer(ip), intent(in) :: mperod
|
|
278
|
+
integer(ip), intent(in) :: m
|
|
279
|
+
integer(ip), intent(in) :: idimy
|
|
280
|
+
integer(ip), intent(out) :: ierror
|
|
281
|
+
complex(wp), intent(in) :: a(:)
|
|
282
|
+
complex(wp), intent(in) :: b(:)
|
|
283
|
+
complex(wp), intent(in) :: c(:)
|
|
284
|
+
|
|
285
|
+
if (3 > m) then
|
|
286
|
+
ierror = 1
|
|
287
|
+
return
|
|
288
|
+
else if (3 > n) then
|
|
289
|
+
ierror = 2
|
|
290
|
+
return
|
|
291
|
+
else if (idimy < m) then
|
|
292
|
+
ierror = 3
|
|
293
|
+
return
|
|
294
|
+
else if (nperod < 0 .or. nperod > 4) then
|
|
295
|
+
ierror = 4
|
|
296
|
+
return
|
|
297
|
+
else if (mperod < 0 .or. mperod > 1) then
|
|
298
|
+
ierror = 5
|
|
299
|
+
return
|
|
300
|
+
else if (mperod /= 1) then
|
|
301
|
+
if (any(abs(a(2:m)-c(1)) /= ZERO) .or. &
|
|
302
|
+
any(abs(c(2:m)-c(1)) /= ZERO) .or. &
|
|
303
|
+
any(abs(b(2:m)-b(1)) /= ZERO)) then
|
|
304
|
+
ierror = 6
|
|
305
|
+
return
|
|
306
|
+
end if
|
|
307
|
+
else if (abs(a(1)) /= ZERO .and. abs(c(m)) /= ZERO) then
|
|
308
|
+
ierror = 7
|
|
309
|
+
return
|
|
310
|
+
else
|
|
311
|
+
ierror = 0
|
|
312
|
+
end if
|
|
313
|
+
|
|
314
|
+
end subroutine check_input_arguments
|
|
315
|
+
|
|
316
|
+
subroutine initialize_workspace(n, m, workspace)
|
|
317
|
+
|
|
318
|
+
! Dummy arguments
|
|
319
|
+
integer(ip), intent(in) :: n
|
|
320
|
+
integer(ip), intent(in) :: m
|
|
321
|
+
class(FishpackWorkspace), intent(out) :: workspace
|
|
322
|
+
|
|
323
|
+
! Local variables
|
|
324
|
+
integer(ip) :: irwk, icwk, j
|
|
325
|
+
|
|
326
|
+
! Compute required workspace sizes
|
|
327
|
+
irwk = 0
|
|
328
|
+
icwk = (10 + int(log(real(n, kind=wp))/log(TWO), kind=ip))*m + 4*n
|
|
329
|
+
|
|
330
|
+
! Allocate memory
|
|
331
|
+
call workspace%create(irwk, icwk, IIWK)
|
|
332
|
+
|
|
333
|
+
! Compute workspace indices
|
|
334
|
+
associate( indx => workspace%workspace_indices )
|
|
335
|
+
indx(1) = m + 1
|
|
336
|
+
do j = 1, IIWK - 2
|
|
337
|
+
indx(j + 1) = indx(j) + m
|
|
338
|
+
end do
|
|
339
|
+
indx(IIWK) = indx(IIWK-1) + 4*n
|
|
340
|
+
end associate
|
|
341
|
+
|
|
342
|
+
end subroutine initialize_workspace
|
|
343
|
+
|
|
344
|
+
subroutine cmgnbn_lower_routine(nperod, n, mperod, m, a, b, c, idimy, y, w, workspace_indices)
|
|
345
|
+
|
|
346
|
+
! Dummy arguments
|
|
347
|
+
integer(ip), intent(in) :: nperod
|
|
348
|
+
integer(ip), intent(in) :: n
|
|
349
|
+
integer(ip), intent(in) :: mperod
|
|
350
|
+
integer(ip), intent(in) :: m
|
|
351
|
+
integer(ip), intent(in) :: idimy
|
|
352
|
+
complex(wp), intent(in) :: a(:)
|
|
353
|
+
complex(wp), intent(in) :: b(:)
|
|
354
|
+
complex(wp), intent(in) :: c(:)
|
|
355
|
+
complex(wp), intent(inout) :: y(:,:)
|
|
356
|
+
complex(wp), intent(out) :: w(:)
|
|
357
|
+
integer(ip), intent(in) :: workspace_indices(:)
|
|
358
|
+
|
|
359
|
+
! Local variables
|
|
360
|
+
integer(ip) :: i, k, j, mp, np, ipstor
|
|
361
|
+
integer(ip) :: irev, mh, mhm1, modd, nby2, mskip
|
|
362
|
+
complex(wp) :: temp_save
|
|
363
|
+
|
|
364
|
+
associate( &
|
|
365
|
+
iwba => workspace_indices(1), &
|
|
366
|
+
iwbb => workspace_indices(2), &
|
|
367
|
+
iwbc => workspace_indices(3), &
|
|
368
|
+
iwb2 => workspace_indices(4), &
|
|
369
|
+
iwb3 => workspace_indices(5), &
|
|
370
|
+
iww1 => workspace_indices(6), &
|
|
371
|
+
iww2 => workspace_indices(7), &
|
|
372
|
+
iww3 => workspace_indices(8), &
|
|
373
|
+
iwd => workspace_indices(9), &
|
|
374
|
+
iwtcos => workspace_indices(10), &
|
|
375
|
+
iwp => workspace_indices(11) &
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
do i = 1, m
|
|
379
|
+
k = iwba + i - 1
|
|
380
|
+
w(k) = -a(i)
|
|
381
|
+
k = iwbc + i - 1
|
|
382
|
+
w(k) = -c(i)
|
|
383
|
+
k = iwbb + i - 1
|
|
384
|
+
w(k) = TWO - b(i)
|
|
385
|
+
y(i, :n) = -y(i, :n)
|
|
386
|
+
end do
|
|
387
|
+
|
|
388
|
+
mp = mperod + 1
|
|
389
|
+
np = nperod + 1
|
|
390
|
+
|
|
391
|
+
select case (mp)
|
|
392
|
+
case (1)
|
|
393
|
+
goto 114
|
|
394
|
+
case (2)
|
|
395
|
+
goto 107
|
|
396
|
+
end select
|
|
397
|
+
107 continue
|
|
398
|
+
select case (np)
|
|
399
|
+
case (1)
|
|
400
|
+
goto 108
|
|
401
|
+
case (2)
|
|
402
|
+
goto 109
|
|
403
|
+
case (3)
|
|
404
|
+
goto 110
|
|
405
|
+
case (4)
|
|
406
|
+
goto 111
|
|
407
|
+
case (5)
|
|
408
|
+
goto 123
|
|
409
|
+
end select
|
|
410
|
+
108 continue
|
|
411
|
+
call solve_poisson_periodic(m, n, w(iwba:), w(iwbb:), w(iwbc:), y, idimy, w, &
|
|
412
|
+
w(iwb2:), w(iwb3:), w(iww1:), w(iww2:), w(iww3:), w(iwd:), w(iwtcos:), w(iwp:))
|
|
413
|
+
goto 112
|
|
414
|
+
109 continue
|
|
415
|
+
call solve_poisson_dirichlet(m, n, 1, w(iwba:), w(iwbb:), w(iwbc:), y, idimy, w, &
|
|
416
|
+
w(iww1:), w(iwd:), w(iwtcos:), w(iwp:))
|
|
417
|
+
goto 112
|
|
418
|
+
110 continue
|
|
419
|
+
call solve_poisson_neumann(m, n, 1, 2, w(iwba:), w(iwbb:), w(iwbc:), y, idimy, w, &
|
|
420
|
+
w(iwb2:), w(iwb3:), w(iww1:), w(iww2:), w(iww3:), w(iwd:), w(iwtcos:), w(iwp:))
|
|
421
|
+
goto 112
|
|
422
|
+
111 continue
|
|
423
|
+
call solve_poisson_neumann(m, n, 1, 1, w(iwba:), w(iwbb:), w(iwbc:), y, idimy, w, &
|
|
424
|
+
w(iwb2:), w(iwb3:), w(iww1:), w(iww2:), w(iww3:), w(iwd:), w(iwtcos:), w(iwp:))
|
|
425
|
+
112 continue
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
ipstor = int(w(iww1), kind=ip)
|
|
429
|
+
irev = 2
|
|
430
|
+
|
|
431
|
+
if (nperod == 4) goto 124
|
|
432
|
+
|
|
433
|
+
113 continue
|
|
434
|
+
|
|
435
|
+
select case (mp)
|
|
436
|
+
case (1)
|
|
437
|
+
goto 127
|
|
438
|
+
case (2)
|
|
439
|
+
w(1) = cmplx(real(ipstor + iwp - 1, kind=wp), ZERO, kind=wp)
|
|
440
|
+
return
|
|
441
|
+
end select
|
|
442
|
+
114 continue
|
|
443
|
+
|
|
444
|
+
mh = (m + 1)/2
|
|
445
|
+
mhm1 = mh - 1
|
|
446
|
+
|
|
447
|
+
if (mh*2 == m) then
|
|
448
|
+
modd = 2
|
|
449
|
+
else
|
|
450
|
+
modd = 1
|
|
451
|
+
end if
|
|
452
|
+
|
|
453
|
+
do j = 1, n
|
|
454
|
+
do i = 1, mhm1
|
|
455
|
+
w(i) = y(mh-i, j) - y(i+mh, j)
|
|
456
|
+
w(i+mh) = y(mh-i, j) + y(i+mh, j)
|
|
457
|
+
end do
|
|
458
|
+
w(mh) = TWO * y(mh, j)
|
|
459
|
+
select case (modd)
|
|
460
|
+
case (1)
|
|
461
|
+
y(:m, j) = w(:m)
|
|
462
|
+
case (2)
|
|
463
|
+
w(m) = TWO * y(m, j)
|
|
464
|
+
y(:m, j) = w(:m)
|
|
465
|
+
end select
|
|
466
|
+
end do
|
|
467
|
+
|
|
468
|
+
k = iwbc + mhm1 - 1
|
|
469
|
+
i = iwba + mhm1
|
|
470
|
+
w(k) = ZERO
|
|
471
|
+
w(i) = ZERO
|
|
472
|
+
w(k+1) = TWO * w(k+1)
|
|
473
|
+
|
|
474
|
+
select case (modd)
|
|
475
|
+
case default
|
|
476
|
+
k = iwbb + mhm1 - 1
|
|
477
|
+
w(k) = w(k) - w(i-1)
|
|
478
|
+
w(iwbc-1) = w(iwbc-1) + w(iwbb-1)
|
|
479
|
+
case (2)
|
|
480
|
+
w(iwbb-1) = w(k+1)
|
|
481
|
+
end select
|
|
482
|
+
|
|
483
|
+
goto 107
|
|
484
|
+
!
|
|
485
|
+
! reverse columns when nperod = 4
|
|
486
|
+
!
|
|
487
|
+
|
|
488
|
+
123 continue
|
|
489
|
+
|
|
490
|
+
irev = 1
|
|
491
|
+
nby2 = n/2
|
|
492
|
+
|
|
493
|
+
124 continue
|
|
494
|
+
|
|
495
|
+
do j = 1, nby2
|
|
496
|
+
mskip = n + 1 - j
|
|
497
|
+
do i = 1, m
|
|
498
|
+
temp_save = y(i, j)
|
|
499
|
+
y(i, j) = y(i, mskip)
|
|
500
|
+
y(i, mskip) = temp_save
|
|
501
|
+
end do
|
|
502
|
+
end do
|
|
503
|
+
|
|
504
|
+
select case (irev)
|
|
505
|
+
case (1)
|
|
506
|
+
goto 110
|
|
507
|
+
case (2)
|
|
508
|
+
goto 113
|
|
509
|
+
end select
|
|
510
|
+
|
|
511
|
+
127 continue
|
|
512
|
+
|
|
513
|
+
do j = 1, n
|
|
514
|
+
w(mh-1:mh-mhm1:(-1)) = HALF * (y(mh+1:mhm1+mh, j)+y(:mhm1, j))
|
|
515
|
+
w(mh+1:mhm1+mh) = HALF * (y(mh+1:mhm1+mh, j)-y(:mhm1, j))
|
|
516
|
+
w(mh) = HALF * y(mh, j)
|
|
517
|
+
select case (modd)
|
|
518
|
+
case (1)
|
|
519
|
+
y(:m, j) = w(:m)
|
|
520
|
+
case (2)
|
|
521
|
+
w(m) = HALF * y(m, j)
|
|
522
|
+
y(:m, j) = w(:m)
|
|
523
|
+
end select
|
|
524
|
+
end do
|
|
525
|
+
|
|
526
|
+
w(1) = cmplx(real(ipstor + iwp - 1, kind=wp), ZERO, kind=wp)
|
|
527
|
+
|
|
528
|
+
end associate
|
|
529
|
+
|
|
530
|
+
end subroutine cmgnbn_lower_routine
|
|
531
|
+
|
|
532
|
+
! Purpose:
|
|
533
|
+
!
|
|
534
|
+
! To solve poisson's equation for dirichlet boundary
|
|
535
|
+
! conditions.
|
|
536
|
+
!
|
|
537
|
+
! istag = 1 if the last diagonal block is the matrix a.
|
|
538
|
+
! istag = 2 if the last diagonal block is the matrix a+i.
|
|
539
|
+
!
|
|
540
|
+
subroutine solve_poisson_dirichlet(mr, nr, istag, ba, bb, bc, q, idimq, b, w, d, tcos, p)
|
|
541
|
+
|
|
542
|
+
! Dummy arguments
|
|
543
|
+
integer(ip), intent(in) :: mr
|
|
544
|
+
integer(ip), intent(in) :: nr
|
|
545
|
+
integer(ip), intent(in) :: istag
|
|
546
|
+
integer(ip), intent(in) :: idimq
|
|
547
|
+
complex(wp), intent(in) :: ba(mr)
|
|
548
|
+
complex(wp), intent(in) :: bb(mr)
|
|
549
|
+
complex(wp), intent(in) :: bc(mr)
|
|
550
|
+
complex(wp), intent(inout) :: q(idimq,nr)
|
|
551
|
+
complex(wp), intent(inout) :: b(mr)
|
|
552
|
+
complex(wp), intent(inout) :: w(mr)
|
|
553
|
+
complex(wp), intent(inout) :: d(mr)
|
|
554
|
+
complex(wp), intent(inout) :: tcos(mr)
|
|
555
|
+
complex(wp), intent(inout) :: p(nr*4)
|
|
556
|
+
|
|
557
|
+
! Local variables
|
|
558
|
+
integer(ip) :: m, n, iip, ipstor, jsh, kr, irreg, jstsav, i, lr, nun
|
|
559
|
+
integer(ip) :: jst, jsp, l, nodd, j, jm1, jp1, jm2, jp2, jm3, jp3, noddpr
|
|
560
|
+
integer(ip) :: krpi, ideg, jdeg
|
|
561
|
+
real(wp) :: fi
|
|
562
|
+
complex(wp) :: t
|
|
563
|
+
|
|
564
|
+
m = mr
|
|
565
|
+
n = nr
|
|
566
|
+
fi = ONE/istag
|
|
567
|
+
iip = -m
|
|
568
|
+
ipstor = 0
|
|
569
|
+
jsh = 0
|
|
570
|
+
|
|
571
|
+
select case (istag)
|
|
572
|
+
case default
|
|
573
|
+
kr = 0
|
|
574
|
+
irreg = 1
|
|
575
|
+
if (n > 1) goto 106
|
|
576
|
+
tcos(1) = ZERO
|
|
577
|
+
case (2)
|
|
578
|
+
kr = 1
|
|
579
|
+
jstsav = 1
|
|
580
|
+
irreg = 2
|
|
581
|
+
if (n > 1) goto 106
|
|
582
|
+
tcos(1) = cmplx(-ONE, ZERO, kind=wp)
|
|
583
|
+
end select
|
|
584
|
+
|
|
585
|
+
b(:m) = q(:m, 1)
|
|
586
|
+
call solve_linear_system(1, 0, m, ba, bb, bc, b, tcos, d, w)
|
|
587
|
+
q(:m, 1) = b(:m)
|
|
588
|
+
goto 183
|
|
589
|
+
106 continue
|
|
590
|
+
lr = 0
|
|
591
|
+
p(1:m) = ZERO
|
|
592
|
+
nun = n
|
|
593
|
+
jst = 1
|
|
594
|
+
jsp = n
|
|
595
|
+
!
|
|
596
|
+
! irreg = 1 when no irregularities have occurred, otherwise it is 2.
|
|
597
|
+
!
|
|
598
|
+
108 continue
|
|
599
|
+
l = 2*jst
|
|
600
|
+
nodd = 2 - 2*((nun + 1)/2) + nun
|
|
601
|
+
!
|
|
602
|
+
! nodd = 1 when nun is odd, otherwise it is 2.
|
|
603
|
+
!
|
|
604
|
+
select case (nodd)
|
|
605
|
+
case default
|
|
606
|
+
jsp = jsp - l
|
|
607
|
+
case (1)
|
|
608
|
+
jsp = jsp - jst
|
|
609
|
+
if (irreg /= 1) jsp = jsp - l
|
|
610
|
+
end select
|
|
611
|
+
|
|
612
|
+
call generate_cosines(jst, 1, HALF, ZERO, tcos)
|
|
613
|
+
|
|
614
|
+
if (l <= jsp) then
|
|
615
|
+
do j = l, jsp, l
|
|
616
|
+
jm1 = j - jsh
|
|
617
|
+
jp1 = j + jsh
|
|
618
|
+
jm2 = j - jst
|
|
619
|
+
jp2 = j + jst
|
|
620
|
+
jm3 = jm2 - jsh
|
|
621
|
+
jp3 = jp2 + jsh
|
|
622
|
+
if (jst == 1) then
|
|
623
|
+
b(:m) = TWO * q(:m, j)
|
|
624
|
+
q(:m, j) = q(:m, jm2) + q(:m, jp2)
|
|
625
|
+
else
|
|
626
|
+
do i = 1, m
|
|
627
|
+
t = q(i, j) - q(i, jm1) - q(i, jp1) + q(i, jm2) + q(i, jp2)
|
|
628
|
+
b(i) = t + q(i, j) - q(i, jm3) - q(i, jp3)
|
|
629
|
+
q(i, j) = t
|
|
630
|
+
end do
|
|
631
|
+
end if
|
|
632
|
+
call solve_linear_system(jst, 0, m, ba, bb, bc, b, tcos, d, w)
|
|
633
|
+
q(:m, j) = q(:m, j) + b(:m)
|
|
634
|
+
end do
|
|
635
|
+
end if
|
|
636
|
+
!
|
|
637
|
+
! reduction for last unknown
|
|
638
|
+
!
|
|
639
|
+
select case (nodd)
|
|
640
|
+
case default
|
|
641
|
+
select case (irreg)
|
|
642
|
+
case (1)
|
|
643
|
+
goto 152
|
|
644
|
+
case (2)
|
|
645
|
+
goto 120
|
|
646
|
+
end select
|
|
647
|
+
!
|
|
648
|
+
! odd number of unknowns
|
|
649
|
+
!
|
|
650
|
+
120 continue
|
|
651
|
+
jsp = jsp + l
|
|
652
|
+
j = jsp
|
|
653
|
+
jm1 = j - jsh
|
|
654
|
+
jp1 = j + jsh
|
|
655
|
+
jm2 = j - jst
|
|
656
|
+
jp2 = j + jst
|
|
657
|
+
jm3 = jm2 - jsh
|
|
658
|
+
select case (istag)
|
|
659
|
+
case (1)
|
|
660
|
+
goto 123
|
|
661
|
+
case (2)
|
|
662
|
+
goto 121
|
|
663
|
+
end select
|
|
664
|
+
121 continue
|
|
665
|
+
if (jst /= 1) goto 123
|
|
666
|
+
do i = 1, m
|
|
667
|
+
b(i) = q(i, j)
|
|
668
|
+
q(i, j) = ZERO
|
|
669
|
+
end do
|
|
670
|
+
goto 130
|
|
671
|
+
123 continue
|
|
672
|
+
select case (noddpr)
|
|
673
|
+
case default
|
|
674
|
+
b(:m) = HALF * (q(:m, jm2)-q(:m, jm1)-q(:m, jm3)) + p(iip+1:m+iip) &
|
|
675
|
+
+ q(:m, j)
|
|
676
|
+
case (2)
|
|
677
|
+
b(:m) = HALF * (q(:m, jm2)-q(:m, jm1)-q(:m, jm3)) + q(:m, jp2) - q( &
|
|
678
|
+
:m, jp1) + q(:m, j)
|
|
679
|
+
end select
|
|
680
|
+
|
|
681
|
+
q(:m, j) = HALF * (q(:m, j)-q(:m, jm1)-q(:m, jp1))
|
|
682
|
+
130 continue
|
|
683
|
+
call solve_linear_system(jst, 0, m, ba, bb, bc, b, tcos, d, w)
|
|
684
|
+
iip = iip + m
|
|
685
|
+
ipstor = max(ipstor, iip + m)
|
|
686
|
+
p(iip+1:m+iip) = q(:m, j) + b(:m)
|
|
687
|
+
b(:m) = q(:m, jp2) + p(iip+1:m+iip)
|
|
688
|
+
if (lr == 0) then
|
|
689
|
+
do i = 1, jst
|
|
690
|
+
krpi = kr + i
|
|
691
|
+
tcos(krpi) = tcos(i)
|
|
692
|
+
end do
|
|
693
|
+
else
|
|
694
|
+
call generate_cosines(lr, jstsav, ZERO, fi, tcos(jst+1))
|
|
695
|
+
call merge_tcos(tcos, 0, jst, jst, lr, kr)
|
|
696
|
+
end if
|
|
697
|
+
call generate_cosines(kr, jstsav, ZERO, fi, tcos)
|
|
698
|
+
call solve_linear_system(kr, kr, m, ba, bb, bc, b, tcos, d, w)
|
|
699
|
+
q(:m, j) = q(:m, jm2) + b(:m) + p(iip+1:m+iip)
|
|
700
|
+
lr = kr
|
|
701
|
+
kr = kr + l
|
|
702
|
+
!
|
|
703
|
+
! even number of unknowns
|
|
704
|
+
!
|
|
705
|
+
case (2)
|
|
706
|
+
jsp = jsp + l
|
|
707
|
+
j = jsp
|
|
708
|
+
jm1 = j - jsh
|
|
709
|
+
jp1 = j + jsh
|
|
710
|
+
jm2 = j - jst
|
|
711
|
+
jp2 = j + jst
|
|
712
|
+
jm3 = jm2 - jsh
|
|
713
|
+
select case (irreg)
|
|
714
|
+
case default
|
|
715
|
+
jstsav = jst
|
|
716
|
+
ideg = jst
|
|
717
|
+
kr = l
|
|
718
|
+
case (2)
|
|
719
|
+
call generate_cosines(kr, jstsav, ZERO, fi, tcos)
|
|
720
|
+
call generate_cosines(lr, jstsav, ZERO, fi, tcos(kr+1))
|
|
721
|
+
ideg = kr
|
|
722
|
+
kr = kr + jst
|
|
723
|
+
end select
|
|
724
|
+
|
|
725
|
+
if (jst == 1) then
|
|
726
|
+
irreg = 2
|
|
727
|
+
b(:m) = q(:m, j)
|
|
728
|
+
q(:m, j) = q(:m, jm2)
|
|
729
|
+
else
|
|
730
|
+
b(:m) = q(:m, j) + HALF * (q(:m, jm2)-q(:m, jm1)-q(:m, jm3))
|
|
731
|
+
select case (irreg)
|
|
732
|
+
case default
|
|
733
|
+
q(:m, j) = q(:m, jm2) + HALF * (q(:m, j)-q(:m, jm1)-q(:m, jp1))
|
|
734
|
+
irreg = 2
|
|
735
|
+
case (2)
|
|
736
|
+
select case (noddpr)
|
|
737
|
+
case default
|
|
738
|
+
q(:m, j) = q(:m, jm2) + p(iip+1:m+iip)
|
|
739
|
+
iip = iip - m
|
|
740
|
+
case (2)
|
|
741
|
+
q(:m, j) = q(:m, jm2) + q(:m, j) - q(:m, jm1)
|
|
742
|
+
end select
|
|
743
|
+
end select
|
|
744
|
+
end if
|
|
745
|
+
|
|
746
|
+
call solve_linear_system(ideg, lr, m, ba, bb, bc, b, tcos, d, w)
|
|
747
|
+
q(:m, j) = q(:m, j) + b(:m)
|
|
748
|
+
end select
|
|
749
|
+
152 continue
|
|
750
|
+
nun = nun/2
|
|
751
|
+
noddpr = nodd
|
|
752
|
+
jsh = jst
|
|
753
|
+
jst = 2*jst
|
|
754
|
+
if (nun >= 2) goto 108
|
|
755
|
+
!
|
|
756
|
+
! start solution.
|
|
757
|
+
!
|
|
758
|
+
j = jsp
|
|
759
|
+
b(:m) = q(:m, j)
|
|
760
|
+
select case (irreg)
|
|
761
|
+
case default
|
|
762
|
+
call generate_cosines(jst, 1, HALF, ZERO, tcos)
|
|
763
|
+
ideg = jst
|
|
764
|
+
case (2)
|
|
765
|
+
kr = lr + jst
|
|
766
|
+
call generate_cosines(kr, jstsav, ZERO, fi, tcos)
|
|
767
|
+
call generate_cosines(lr, jstsav, ZERO, fi, tcos(kr+1))
|
|
768
|
+
ideg = kr
|
|
769
|
+
end select
|
|
770
|
+
|
|
771
|
+
call solve_linear_system(ideg, lr, m, ba, bb, bc, b, tcos, d, w)
|
|
772
|
+
jm1 = j - jsh
|
|
773
|
+
jp1 = j + jsh
|
|
774
|
+
select case (irreg)
|
|
775
|
+
case default
|
|
776
|
+
q(:m, j) = HALF * (q(:m, j)-q(:m, jm1)-q(:m, jp1)) + b(:m)
|
|
777
|
+
case (2)
|
|
778
|
+
select case (noddpr)
|
|
779
|
+
case default
|
|
780
|
+
q(:m, j) = p(iip+1:m+iip) + b(:m)
|
|
781
|
+
iip = iip - m
|
|
782
|
+
case (2)
|
|
783
|
+
q(:m, j) = q(:m, j) - q(:m, jm1) + b(:m)
|
|
784
|
+
end select
|
|
785
|
+
end select
|
|
786
|
+
164 continue
|
|
787
|
+
jst = jst/2
|
|
788
|
+
jsh = jst/2
|
|
789
|
+
nun = 2*nun
|
|
790
|
+
if (nun > n) goto 183
|
|
791
|
+
do j = jst, n, l
|
|
792
|
+
jm1 = j - jsh
|
|
793
|
+
jp1 = j + jsh
|
|
794
|
+
jm2 = j - jst
|
|
795
|
+
jp2 = j + jst
|
|
796
|
+
if (j <= jst) then
|
|
797
|
+
b(:m) = q(:m, j) + q(:m, jp2)
|
|
798
|
+
else
|
|
799
|
+
if (jp2 <= n) goto 168
|
|
800
|
+
b(:m) = q(:m, j) + q(:m, jm2)
|
|
801
|
+
if (jst < jstsav) irreg = 1
|
|
802
|
+
select case (irreg)
|
|
803
|
+
case (1)
|
|
804
|
+
goto 170
|
|
805
|
+
case (2)
|
|
806
|
+
goto 171
|
|
807
|
+
end select
|
|
808
|
+
168 continue
|
|
809
|
+
b(:m) = q(:m, j) + q(:m, jm2) + q(:m, jp2)
|
|
810
|
+
end if
|
|
811
|
+
170 continue
|
|
812
|
+
call generate_cosines(jst, 1, HALF, ZERO, tcos)
|
|
813
|
+
ideg = jst
|
|
814
|
+
jdeg = 0
|
|
815
|
+
goto 172
|
|
816
|
+
171 continue
|
|
817
|
+
if (j + l > n) lr = lr - jst
|
|
818
|
+
kr = jst + lr
|
|
819
|
+
call generate_cosines(kr, jstsav, ZERO, fi, tcos)
|
|
820
|
+
call generate_cosines(lr, jstsav, ZERO, fi, tcos(kr+1))
|
|
821
|
+
ideg = kr
|
|
822
|
+
jdeg = lr
|
|
823
|
+
172 continue
|
|
824
|
+
call solve_linear_system(ideg, jdeg, m, ba, bb, bc, b, tcos, d, w)
|
|
825
|
+
if (jst <= 1) then
|
|
826
|
+
q(:m, j) = b(:m)
|
|
827
|
+
else
|
|
828
|
+
if (jp2 > n) goto 177
|
|
829
|
+
175 continue
|
|
830
|
+
q(:m, j) = HALF * (q(:m, j)-q(:m, jm1)-q(:m, jp1)) + b(:m)
|
|
831
|
+
cycle
|
|
832
|
+
177 continue
|
|
833
|
+
select case (irreg)
|
|
834
|
+
case (1)
|
|
835
|
+
goto 175
|
|
836
|
+
case (2)
|
|
837
|
+
goto 178
|
|
838
|
+
end select
|
|
839
|
+
178 continue
|
|
840
|
+
if (j + jsh <= n) then
|
|
841
|
+
q(:m, j) = b(:m) + p(iip+1:m+iip)
|
|
842
|
+
iip = iip - m
|
|
843
|
+
else
|
|
844
|
+
q(:m, j) = b(:m) + q(:m, j) - q(:m, jm1)
|
|
845
|
+
end if
|
|
846
|
+
end if
|
|
847
|
+
end do
|
|
848
|
+
l = l/2
|
|
849
|
+
goto 164
|
|
850
|
+
183 continue
|
|
851
|
+
w(1) = cmplx(real(ipstor, kind=wp), ZERO, kind=wp)
|
|
852
|
+
|
|
853
|
+
end subroutine solve_poisson_dirichlet
|
|
854
|
+
|
|
855
|
+
subroutine solve_poisson_neumann(m, n, istag, mixbnd, a, bb, c, q, idimq, b, b2, &
|
|
856
|
+
b3, w, w2, w3, d, tcos, p)
|
|
857
|
+
!
|
|
858
|
+
! Purpose:
|
|
859
|
+
!
|
|
860
|
+
! subroutine to solve poisson's equation with neumann boundary
|
|
861
|
+
! conditions.
|
|
862
|
+
!
|
|
863
|
+
! istag = 1 if the last diagonal block is a.
|
|
864
|
+
! istag = 2 if the last diagonal block is a-i.
|
|
865
|
+
! mixbnd = 1 if have neumann boundary conditions at both boundaries.
|
|
866
|
+
! mixbnd = 2 if have neumann boundary conditions at bottom and
|
|
867
|
+
! dirichlet condition at top. (for this case, must have istag = 1.)
|
|
868
|
+
!
|
|
869
|
+
|
|
870
|
+
! Dummy arguments
|
|
871
|
+
|
|
872
|
+
integer(ip), intent(in) :: m
|
|
873
|
+
integer(ip), intent(in) :: n
|
|
874
|
+
integer(ip), intent(in) :: istag
|
|
875
|
+
integer(ip), intent(in) :: mixbnd
|
|
876
|
+
integer(ip), intent(in) :: idimq
|
|
877
|
+
complex(wp) :: a(m)
|
|
878
|
+
complex(wp) :: bb(m)
|
|
879
|
+
complex(wp) :: c(m)
|
|
880
|
+
complex(wp), intent(inout) :: q(idimq,n)
|
|
881
|
+
complex(wp) :: b(m)
|
|
882
|
+
complex(wp) :: b2(m)
|
|
883
|
+
complex(wp) :: b3(m)
|
|
884
|
+
complex(wp) :: w(m)
|
|
885
|
+
complex(wp) :: w2(m)
|
|
886
|
+
complex(wp) :: w3(m)
|
|
887
|
+
complex(wp) :: d(m)
|
|
888
|
+
complex(wp) :: tcos(m)
|
|
889
|
+
complex(wp), intent(inout) :: p(n*4)
|
|
890
|
+
|
|
891
|
+
! Local variables
|
|
892
|
+
|
|
893
|
+
integer(ip) :: k(4)
|
|
894
|
+
integer(ip) :: mr, iip
|
|
895
|
+
integer(ip) :: ipstor, i2r, jr, nr, nlast, kr
|
|
896
|
+
integer(ip) :: lr, i, nrod, jstart, jstop, i2rby2, j, jp1, jp2, jp3, jm1
|
|
897
|
+
integer(ip) :: jm2, jm3, nrodpr, ii, i1, i2, jr2, nlastp, jstep
|
|
898
|
+
real(wp) :: fistag, fnum, fden
|
|
899
|
+
complex(wp) :: fi, t
|
|
900
|
+
|
|
901
|
+
|
|
902
|
+
associate( &
|
|
903
|
+
k1 => k(1), &
|
|
904
|
+
k2 => k(2), &
|
|
905
|
+
k3 => k(3), &
|
|
906
|
+
k4 => k(4) &
|
|
907
|
+
)
|
|
908
|
+
|
|
909
|
+
fistag = 3 - istag
|
|
910
|
+
fnum = ONE/istag
|
|
911
|
+
fden = HALF * real(istag - 1, kind=wp)
|
|
912
|
+
mr = m
|
|
913
|
+
iip = -mr
|
|
914
|
+
ipstor = 0
|
|
915
|
+
i2r = 1
|
|
916
|
+
jr = 2
|
|
917
|
+
nr = n
|
|
918
|
+
nlast = n
|
|
919
|
+
kr = 1
|
|
920
|
+
lr = 0
|
|
921
|
+
select case (istag)
|
|
922
|
+
case (1)
|
|
923
|
+
goto 101
|
|
924
|
+
case (2)
|
|
925
|
+
goto 103
|
|
926
|
+
end select
|
|
927
|
+
101 continue
|
|
928
|
+
q(:mr, n) = HALF * q(:mr, n)
|
|
929
|
+
select case (mixbnd)
|
|
930
|
+
case (1)
|
|
931
|
+
goto 103
|
|
932
|
+
case (2)
|
|
933
|
+
goto 104
|
|
934
|
+
end select
|
|
935
|
+
103 continue
|
|
936
|
+
if (n <= 3) goto 155
|
|
937
|
+
104 continue
|
|
938
|
+
jr = 2*i2r
|
|
939
|
+
nrod = 1
|
|
940
|
+
if ((nr/2)*2 == nr) nrod = 0
|
|
941
|
+
select case (mixbnd)
|
|
942
|
+
case default
|
|
943
|
+
jstart = 1
|
|
944
|
+
case (2)
|
|
945
|
+
jstart = jr
|
|
946
|
+
nrod = 1 - nrod
|
|
947
|
+
end select
|
|
948
|
+
|
|
949
|
+
jstop = nlast - jr
|
|
950
|
+
if (nrod == 0) jstop = jstop - i2r
|
|
951
|
+
call generate_cosines(i2r, 1, HALF, ZERO, tcos)
|
|
952
|
+
i2rby2 = i2r/2
|
|
953
|
+
if (jstop < jstart) then
|
|
954
|
+
j = jr
|
|
955
|
+
else
|
|
956
|
+
do j = jstart, jstop, jr
|
|
957
|
+
jp1 = j + i2rby2
|
|
958
|
+
jp2 = j + i2r
|
|
959
|
+
jp3 = jp2 + i2rby2
|
|
960
|
+
jm1 = j - i2rby2
|
|
961
|
+
jm2 = j - i2r
|
|
962
|
+
jm3 = jm2 - i2rby2
|
|
963
|
+
if (j == 1) then
|
|
964
|
+
jm1 = jp1
|
|
965
|
+
jm2 = jp2
|
|
966
|
+
jm3 = jp3
|
|
967
|
+
end if
|
|
968
|
+
if (i2r == 1) then
|
|
969
|
+
if (j == 1) jm2 = jp2
|
|
970
|
+
b(:mr) = TWO * q(:mr, j)
|
|
971
|
+
q(:mr, j) = q(:mr, jm2) + q(:mr, jp2)
|
|
972
|
+
else
|
|
973
|
+
do i = 1, mr
|
|
974
|
+
fi = q(i, j)
|
|
975
|
+
q(i, j)=q(i, j)-q(i, jm1)-q(i, jp1)+q(i, jm2)+q(i, jp2)
|
|
976
|
+
b(i) = fi + q(i, j) - q(i, jm3) - q(i, jp3)
|
|
977
|
+
end do
|
|
978
|
+
end if
|
|
979
|
+
call solve_linear_system(i2r, 0, mr, a, bb, c, b, tcos, d, w)
|
|
980
|
+
q(:mr, j) = q(:mr, j) + b(:mr)
|
|
981
|
+
!
|
|
982
|
+
! end of reduction for regular unknowns.
|
|
983
|
+
!
|
|
984
|
+
end do
|
|
985
|
+
!
|
|
986
|
+
! begin special reduction for last unknown.
|
|
987
|
+
!
|
|
988
|
+
j = jstop + jr
|
|
989
|
+
end if
|
|
990
|
+
nlast = j
|
|
991
|
+
jm1 = j - i2rby2
|
|
992
|
+
jm2 = j - i2r
|
|
993
|
+
jm3 = jm2 - i2rby2
|
|
994
|
+
if (nrod /= 0) then
|
|
995
|
+
!
|
|
996
|
+
! odd number of unknowns
|
|
997
|
+
!
|
|
998
|
+
if (i2r == 1) then
|
|
999
|
+
b(:mr) = fistag*q(:mr, j)
|
|
1000
|
+
q(:mr, j) = q(:mr, jm2)
|
|
1001
|
+
else
|
|
1002
|
+
b(:mr) = q(:mr, j) + HALF * (q(:mr, jm2)-q(:mr, jm1)-q(:mr, jm3))
|
|
1003
|
+
if (nrodpr == 0) then
|
|
1004
|
+
q(:mr, j) = q(:mr, jm2) + p(iip+1:mr+iip)
|
|
1005
|
+
iip = iip - mr
|
|
1006
|
+
else
|
|
1007
|
+
q(:mr, j) = q(:mr, j) - q(:mr, jm1) + q(:mr, jm2)
|
|
1008
|
+
end if
|
|
1009
|
+
if (lr /= 0) then
|
|
1010
|
+
call generate_cosines(lr, 1, HALF, fden, tcos(kr+1))
|
|
1011
|
+
else
|
|
1012
|
+
b(:mr) = fistag*b(:mr)
|
|
1013
|
+
end if
|
|
1014
|
+
end if
|
|
1015
|
+
call generate_cosines(kr, 1, HALF, fden, tcos)
|
|
1016
|
+
call solve_linear_system(kr, lr, mr, a, bb, c, b, tcos, d, w)
|
|
1017
|
+
q(:mr, j) = q(:mr, j) + b(:mr)
|
|
1018
|
+
kr = kr + i2r
|
|
1019
|
+
else
|
|
1020
|
+
jp1 = j + i2rby2
|
|
1021
|
+
jp2 = j + i2r
|
|
1022
|
+
if (i2r == 1) then
|
|
1023
|
+
b(:mr) = q(:mr, j)
|
|
1024
|
+
call solve_linear_system(1, 0, mr, a, bb, c, b, tcos, d, w)
|
|
1025
|
+
iip = 0
|
|
1026
|
+
ipstor = mr
|
|
1027
|
+
select case (istag)
|
|
1028
|
+
case default
|
|
1029
|
+
p(:mr) = b(:mr)
|
|
1030
|
+
b(:mr) = b(:mr) + q(:mr, n)
|
|
1031
|
+
tcos(1) = cmplx(ONE, ZERO, kind=wp)
|
|
1032
|
+
tcos(2) = ZERO
|
|
1033
|
+
call solve_linear_system(1, 1, mr, a, bb, c, b, tcos, d, w)
|
|
1034
|
+
q(:mr, j) = q(:mr, jm2) + p(:mr) + b(:mr)
|
|
1035
|
+
goto 150
|
|
1036
|
+
case (1)
|
|
1037
|
+
p(:mr) = b(:mr)
|
|
1038
|
+
q(:mr, j) = q(:mr, jm2) + TWO * q(:mr, jp2) + THREE*b(:mr)
|
|
1039
|
+
goto 150
|
|
1040
|
+
end select
|
|
1041
|
+
end if
|
|
1042
|
+
b(:mr) = q(:mr, j) + HALF * (q(:mr, jm2)-q(:mr, jm1)-q(:mr, jm3))
|
|
1043
|
+
if (nrodpr == 0) then
|
|
1044
|
+
b(:mr) = b(:mr) + p(iip+1:mr+iip)
|
|
1045
|
+
else
|
|
1046
|
+
b(:mr) = b(:mr) + q(:mr, jp2) - q(:mr, jp1)
|
|
1047
|
+
end if
|
|
1048
|
+
call solve_linear_system(i2r, 0, mr, a, bb, c, b, tcos, d, w)
|
|
1049
|
+
iip = iip + mr
|
|
1050
|
+
ipstor = max(ipstor, iip + mr)
|
|
1051
|
+
p(iip+1:mr+iip) = b(:mr) + HALF * (q(:mr, j)-q(:mr, jm1)-q(:mr, jp1))
|
|
1052
|
+
b(:mr) = p(iip+1:mr+iip) + q(:mr, jp2)
|
|
1053
|
+
if (lr /= 0) then
|
|
1054
|
+
call generate_cosines(lr, 1, HALF, fden, tcos(i2r+1))
|
|
1055
|
+
call merge_tcos(tcos, 0, i2r, i2r, lr, kr)
|
|
1056
|
+
else
|
|
1057
|
+
do i = 1, i2r
|
|
1058
|
+
ii = kr + i
|
|
1059
|
+
tcos(ii) = tcos(i)
|
|
1060
|
+
end do
|
|
1061
|
+
end if
|
|
1062
|
+
call generate_cosines(kr, 1, HALF, fden, tcos)
|
|
1063
|
+
if (lr == 0) then
|
|
1064
|
+
select case (istag)
|
|
1065
|
+
case (1)
|
|
1066
|
+
goto 146
|
|
1067
|
+
case (2)
|
|
1068
|
+
goto 145
|
|
1069
|
+
end select
|
|
1070
|
+
end if
|
|
1071
|
+
145 continue
|
|
1072
|
+
call solve_linear_system(kr, kr, mr, a, bb, c, b, tcos, d, w)
|
|
1073
|
+
goto 148
|
|
1074
|
+
146 continue
|
|
1075
|
+
b(:mr) = fistag*b(:mr)
|
|
1076
|
+
148 continue
|
|
1077
|
+
q(:mr, j) = q(:mr, jm2) + p(iip+1:mr+iip) + b(:mr)
|
|
1078
|
+
150 continue
|
|
1079
|
+
lr = kr
|
|
1080
|
+
kr = kr + jr
|
|
1081
|
+
end if
|
|
1082
|
+
select case (mixbnd)
|
|
1083
|
+
case default
|
|
1084
|
+
nr = (nlast - 1)/jr + 1
|
|
1085
|
+
if (nr <= 3) goto 155
|
|
1086
|
+
case (2)
|
|
1087
|
+
nr = nlast/jr
|
|
1088
|
+
if (nr <= 1) goto 192
|
|
1089
|
+
end select
|
|
1090
|
+
|
|
1091
|
+
i2r = jr
|
|
1092
|
+
nrodpr = nrod
|
|
1093
|
+
goto 104
|
|
1094
|
+
155 continue
|
|
1095
|
+
j = 1 + jr
|
|
1096
|
+
jm1 = j - i2r
|
|
1097
|
+
jp1 = j + i2r
|
|
1098
|
+
jm2 = nlast - i2r
|
|
1099
|
+
if (nr /= 2) then
|
|
1100
|
+
if (lr /= 0) goto 170
|
|
1101
|
+
if (n == 3) then
|
|
1102
|
+
!
|
|
1103
|
+
! case n = 3.
|
|
1104
|
+
!
|
|
1105
|
+
select case (istag)
|
|
1106
|
+
case (1)
|
|
1107
|
+
goto 156
|
|
1108
|
+
case (2)
|
|
1109
|
+
goto 168
|
|
1110
|
+
end select
|
|
1111
|
+
156 continue
|
|
1112
|
+
b(:mr) = q(:mr, 2)
|
|
1113
|
+
tcos(1) = ZERO
|
|
1114
|
+
call solve_linear_system(1, 0, mr, a, bb, c, b, tcos, d, w)
|
|
1115
|
+
q(:mr, 2) = b(:mr)
|
|
1116
|
+
b(:mr) = FOUR*b(:mr) + q(:mr, 1) + TWO * q(:mr, 3)
|
|
1117
|
+
tcos(1) = cmplx(-TWO, ZERO, kind=wp)
|
|
1118
|
+
tcos(2) = cmplx(TWO, ZERO, kind=wp)
|
|
1119
|
+
i1 = 2
|
|
1120
|
+
i2 = 0
|
|
1121
|
+
call solve_linear_system(i1, i2, mr, a, bb, c, b, tcos, d, w)
|
|
1122
|
+
q(:mr, 2) = q(:mr, 2) + b(:mr)
|
|
1123
|
+
b(:mr) = q(:mr, 1) + TWO * q(:mr, 2)
|
|
1124
|
+
tcos(1) = ZERO
|
|
1125
|
+
call solve_linear_system(1, 0, mr, a, bb, c, b, tcos, d, w)
|
|
1126
|
+
q(:mr, 1) = b(:mr)
|
|
1127
|
+
jr = 1
|
|
1128
|
+
i2r = 0
|
|
1129
|
+
goto 194
|
|
1130
|
+
end if
|
|
1131
|
+
!
|
|
1132
|
+
! case n = 2**p+1
|
|
1133
|
+
!
|
|
1134
|
+
select case (istag)
|
|
1135
|
+
case (1)
|
|
1136
|
+
goto 162
|
|
1137
|
+
case (2)
|
|
1138
|
+
goto 170
|
|
1139
|
+
end select
|
|
1140
|
+
162 continue
|
|
1141
|
+
b(:mr) = q(:mr, j) + HALF * q(:mr, 1) - q(:mr, jm1) + q(:mr, nlast) - &
|
|
1142
|
+
q(:mr, jm2)
|
|
1143
|
+
call generate_cosines(jr, 1, HALF, ZERO, tcos)
|
|
1144
|
+
call solve_linear_system(jr, 0, mr, a, bb, c, b, tcos, d, w)
|
|
1145
|
+
q(:mr, j) = HALF * (q(:mr, j)-q(:mr, jm1)-q(:mr, jp1)) + b(:mr)
|
|
1146
|
+
b(:mr) = q(:mr, 1) + TWO * q(:mr, nlast) + FOUR*q(:mr, j)
|
|
1147
|
+
jr2 = 2*jr
|
|
1148
|
+
call generate_cosines(jr, 1, ZERO, ZERO, tcos)
|
|
1149
|
+
tcos(jr+1:jr*2) = -tcos(jr:1:(-1))
|
|
1150
|
+
call solve_linear_system(jr2, 0, mr, a, bb, c, b, tcos, d, w)
|
|
1151
|
+
q(:mr, j) = q(:mr, j) + b(:mr)
|
|
1152
|
+
b(:mr) = q(:mr, 1) + TWO * q(:mr, j)
|
|
1153
|
+
call generate_cosines(jr, 1, HALF, ZERO, tcos)
|
|
1154
|
+
call solve_linear_system(jr, 0, mr, a, bb, c, b, tcos, d, w)
|
|
1155
|
+
q(:mr, 1) = HALF * q(:mr, 1) - q(:mr, jm1) + b(:mr)
|
|
1156
|
+
goto 194
|
|
1157
|
+
!
|
|
1158
|
+
! case of general n with nr = 3 .
|
|
1159
|
+
!
|
|
1160
|
+
168 continue
|
|
1161
|
+
b(:mr) = q(:mr, 2)
|
|
1162
|
+
q(:mr, 2) = ZERO
|
|
1163
|
+
b2(:mr) = q(:mr, 3)
|
|
1164
|
+
b3(:mr) = q(:mr, 1)
|
|
1165
|
+
jr = 1
|
|
1166
|
+
i2r = 0
|
|
1167
|
+
j = 2
|
|
1168
|
+
goto 177
|
|
1169
|
+
170 continue
|
|
1170
|
+
b(:mr) = HALF * q(:mr, 1) - q(:mr, jm1) + q(:mr, j)
|
|
1171
|
+
if (nrod == 0) then
|
|
1172
|
+
b(:mr) = b(:mr) + p(iip+1:mr+iip)
|
|
1173
|
+
else
|
|
1174
|
+
b(:mr) = b(:mr) + q(:mr, nlast) - q(:mr, jm2)
|
|
1175
|
+
end if
|
|
1176
|
+
do i = 1, mr
|
|
1177
|
+
t = HALF * (q(i, j)-q(i, jm1)-q(i, jp1))
|
|
1178
|
+
q(i, j) = t
|
|
1179
|
+
b2(i) = q(i, nlast) + t
|
|
1180
|
+
b3(i) = q(i, 1) + TWO * t
|
|
1181
|
+
end do
|
|
1182
|
+
177 continue
|
|
1183
|
+
k1 = kr + 2*jr - 1
|
|
1184
|
+
k2 = kr + jr
|
|
1185
|
+
tcos(k1+1) = cmplx(-TWO, ZERO, kind=wp)
|
|
1186
|
+
k4 = k1 + 3 - istag
|
|
1187
|
+
call generate_cosines(k2 + istag - 2, 1, ZERO, fnum, tcos(k4))
|
|
1188
|
+
k4 = k1 + k2 + 1
|
|
1189
|
+
call generate_cosines(jr - 1, 1, ZERO, ONE, tcos(k4))
|
|
1190
|
+
call merge_tcos(tcos, k1, k2, k1 + k2, jr - 1, 0)
|
|
1191
|
+
k3 = k1 + k2 + lr
|
|
1192
|
+
call generate_cosines(jr, 1, HALF, ZERO, tcos(k3+1))
|
|
1193
|
+
k4 = k3 + jr + 1
|
|
1194
|
+
call generate_cosines(kr, 1, HALF, fden, tcos(k4))
|
|
1195
|
+
call merge_tcos(tcos, k3, jr, k3 + jr, kr, k1)
|
|
1196
|
+
if (lr /= 0) then
|
|
1197
|
+
call generate_cosines(lr, 1, HALF, fden, tcos(k4))
|
|
1198
|
+
call merge_tcos(tcos, k3, jr, k3 + jr, lr, k3 - lr)
|
|
1199
|
+
call generate_cosines(kr, 1, HALF, fden, tcos(k4))
|
|
1200
|
+
end if
|
|
1201
|
+
k3 = kr
|
|
1202
|
+
k4 = kr
|
|
1203
|
+
call solve_tridiagonal_system(mr, a, bb, c, k, b, b2, b3, tcos, d, w, w2, w3)
|
|
1204
|
+
b(:mr) = b(:mr) + b2(:mr) + b3(:mr)
|
|
1205
|
+
tcos(1) = cmplx(TWO, ZERO, kind=wp)
|
|
1206
|
+
call solve_linear_system(1, 0, mr, a, bb, c, b, tcos, d, w)
|
|
1207
|
+
q(:mr, j) = q(:mr, j) + b(:mr)
|
|
1208
|
+
b(:mr) = q(:mr, 1) + TWO * q(:mr, j)
|
|
1209
|
+
call generate_cosines(jr, 1, HALF, ZERO, tcos)
|
|
1210
|
+
call solve_linear_system(jr, 0, mr, a, bb, c, b, tcos, d, w)
|
|
1211
|
+
if (jr == 1) then
|
|
1212
|
+
q(:mr, 1) = b(:mr)
|
|
1213
|
+
goto 194
|
|
1214
|
+
end if
|
|
1215
|
+
q(:mr, 1) = HALF * q(:mr, 1) - q(:mr, jm1) + b(:mr)
|
|
1216
|
+
goto 194
|
|
1217
|
+
end if
|
|
1218
|
+
if (n == 2) then
|
|
1219
|
+
!
|
|
1220
|
+
! case n = 2
|
|
1221
|
+
!
|
|
1222
|
+
b(:mr) = q(:mr, 1)
|
|
1223
|
+
tcos(1) = ZERO
|
|
1224
|
+
call solve_linear_system(1, 0, mr, a, bb, c, b, tcos, d, w)
|
|
1225
|
+
q(:mr, 1) = b(:mr)
|
|
1226
|
+
b(:mr) = TWO * (q(:mr, 2)+b(:mr))*fistag
|
|
1227
|
+
tcos(1) = cmplx((-fistag), ZERO, kind=wp)
|
|
1228
|
+
tcos(2) = cmplx(TWO, ZERO, kind=wp)
|
|
1229
|
+
call solve_linear_system(2, 0, mr, a, bb, c, b, tcos, d, w)
|
|
1230
|
+
q(:mr, 1) = q(:mr, 1) + b(:mr)
|
|
1231
|
+
jr = 1
|
|
1232
|
+
i2r = 0
|
|
1233
|
+
goto 194
|
|
1234
|
+
end if
|
|
1235
|
+
b3(:mr) = ZERO
|
|
1236
|
+
b(:mr) = q(:mr, 1) + TWO * p(iip+1:mr+iip)
|
|
1237
|
+
q(:mr, 1) = HALF * q(:mr, 1) - q(:mr, jm1)
|
|
1238
|
+
b2(:mr) = TWO * (q(:mr, 1)+q(:mr, nlast))
|
|
1239
|
+
k1 = kr + jr - 1
|
|
1240
|
+
tcos(k1+1) = cmplx(-TWO, ZERO, kind=wp)
|
|
1241
|
+
k4 = k1 + 3 - istag
|
|
1242
|
+
call generate_cosines(kr + istag - 2, 1, ZERO, fnum, tcos(k4))
|
|
1243
|
+
k4 = k1 + kr + 1
|
|
1244
|
+
call generate_cosines(jr - 1, 1, ZERO, ONE, tcos(k4))
|
|
1245
|
+
call merge_tcos(tcos, k1, kr, k1 + kr, jr - 1, 0)
|
|
1246
|
+
call generate_cosines(kr, 1, HALF, fden, tcos(k1+1))
|
|
1247
|
+
k2 = kr
|
|
1248
|
+
k4 = k1 + k2 + 1
|
|
1249
|
+
call generate_cosines(lr, 1, HALF, fden, tcos(k4))
|
|
1250
|
+
k3 = lr
|
|
1251
|
+
k4 = 0
|
|
1252
|
+
call solve_tridiagonal_system(mr, a, bb, c, k, b, b2, b3, tcos, d, w, w2, w3)
|
|
1253
|
+
b(:mr) = b(:mr) + b2(:mr)
|
|
1254
|
+
tcos(1) = cmplx(TWO, ZERO, kind=wp)
|
|
1255
|
+
call solve_linear_system(1, 0, mr, a, bb, c, b, tcos, d, w)
|
|
1256
|
+
q(:mr, 1) = q(:mr, 1) + b(:mr)
|
|
1257
|
+
goto 194
|
|
1258
|
+
192 continue
|
|
1259
|
+
b(:mr) = q(:mr, nlast)
|
|
1260
|
+
goto 196
|
|
1261
|
+
194 continue
|
|
1262
|
+
j = nlast - jr
|
|
1263
|
+
b(:mr) = q(:mr, nlast) + q(:mr, j)
|
|
1264
|
+
196 continue
|
|
1265
|
+
jm2 = nlast - i2r
|
|
1266
|
+
if (jr == 1) then
|
|
1267
|
+
q(:mr, nlast) = ZERO
|
|
1268
|
+
else
|
|
1269
|
+
if (nrod == 0) then
|
|
1270
|
+
q(:mr, nlast) = p(iip+1:mr+iip)
|
|
1271
|
+
iip = iip - mr
|
|
1272
|
+
else
|
|
1273
|
+
q(:mr, nlast) = q(:mr, nlast) - q(:mr, jm2)
|
|
1274
|
+
end if
|
|
1275
|
+
end if
|
|
1276
|
+
call generate_cosines(kr, 1, HALF, fden, tcos)
|
|
1277
|
+
call generate_cosines(lr, 1, HALF, fden, tcos(kr+1))
|
|
1278
|
+
if (lr == 0) then
|
|
1279
|
+
b(:mr) = fistag*b(:mr)
|
|
1280
|
+
end if
|
|
1281
|
+
call solve_linear_system(kr, lr, mr, a, bb, c, b, tcos, d, w)
|
|
1282
|
+
q(:mr, nlast) = q(:mr, nlast) + b(:mr)
|
|
1283
|
+
nlastp = nlast
|
|
1284
|
+
206 continue
|
|
1285
|
+
jstep = jr
|
|
1286
|
+
jr = i2r
|
|
1287
|
+
i2r = i2r/2
|
|
1288
|
+
if (jr == 0) goto 222
|
|
1289
|
+
select case (mixbnd)
|
|
1290
|
+
case default
|
|
1291
|
+
jstart = 1 + jr
|
|
1292
|
+
case (2)
|
|
1293
|
+
jstart = jr
|
|
1294
|
+
end select
|
|
1295
|
+
|
|
1296
|
+
kr = kr - jr
|
|
1297
|
+
if (nlast + jr <= n) then
|
|
1298
|
+
kr = kr - jr
|
|
1299
|
+
nlast = nlast + jr
|
|
1300
|
+
jstop = nlast - jstep
|
|
1301
|
+
else
|
|
1302
|
+
jstop = nlast - jr
|
|
1303
|
+
end if
|
|
1304
|
+
lr = kr - jr
|
|
1305
|
+
call generate_cosines(jr, 1, HALF, ZERO, tcos)
|
|
1306
|
+
do j = jstart, jstop, jstep
|
|
1307
|
+
jm2 = j - jr
|
|
1308
|
+
jp2 = j + jr
|
|
1309
|
+
if (j == jr) then
|
|
1310
|
+
b(:mr) = q(:mr, j) + q(:mr, jp2)
|
|
1311
|
+
else
|
|
1312
|
+
b(:mr) = q(:mr, j) + q(:mr, jm2) + q(:mr, jp2)
|
|
1313
|
+
end if
|
|
1314
|
+
if (jr == 1) then
|
|
1315
|
+
q(:mr, j) = ZERO
|
|
1316
|
+
else
|
|
1317
|
+
jm1 = j - i2r
|
|
1318
|
+
jp1 = j + i2r
|
|
1319
|
+
q(:mr, j) = HALF * (q(:mr, j)-q(:mr, jm1)-q(:mr, jp1))
|
|
1320
|
+
end if
|
|
1321
|
+
call solve_linear_system(jr, 0, mr, a, bb, c, b, tcos, d, w)
|
|
1322
|
+
q(:mr, j) = q(:mr, j) + b(:mr)
|
|
1323
|
+
end do
|
|
1324
|
+
nrod = 1
|
|
1325
|
+
if (nlast + i2r <= n) nrod = 0
|
|
1326
|
+
if (nlastp /= nlast) goto 194
|
|
1327
|
+
goto 206
|
|
1328
|
+
222 continue
|
|
1329
|
+
w(1) = cmplx(real(ipstor, kind=wp), ZERO, kind=wp)
|
|
1330
|
+
|
|
1331
|
+
end associate
|
|
1332
|
+
|
|
1333
|
+
end subroutine solve_poisson_neumann
|
|
1334
|
+
|
|
1335
|
+
! Purpose:
|
|
1336
|
+
!
|
|
1337
|
+
! To solve poisson equation with periodic boundary conditions.
|
|
1338
|
+
!
|
|
1339
|
+
subroutine solve_poisson_periodic(m, n, a, bb, c, q, idimq, b, b2, b3, w, w2, w3, d, tcos, p)
|
|
1340
|
+
|
|
1341
|
+
! Dummy arguments
|
|
1342
|
+
integer(ip), intent(in) :: m
|
|
1343
|
+
integer(ip), intent(in) :: n
|
|
1344
|
+
integer(ip), intent(in) :: idimq
|
|
1345
|
+
complex(wp) :: a(*)
|
|
1346
|
+
complex(wp) :: bb(*)
|
|
1347
|
+
complex(wp) :: c(*)
|
|
1348
|
+
complex(wp) :: q(idimq,n)
|
|
1349
|
+
complex(wp) :: b(*)
|
|
1350
|
+
complex(wp) :: b2(*)
|
|
1351
|
+
complex(wp) :: b3(*)
|
|
1352
|
+
complex(wp) :: w(*)
|
|
1353
|
+
complex(wp) :: w2(*)
|
|
1354
|
+
complex(wp) :: w3(*)
|
|
1355
|
+
complex(wp) :: d(*)
|
|
1356
|
+
complex(wp) :: tcos(*)
|
|
1357
|
+
complex(wp) :: p(n*4)
|
|
1358
|
+
|
|
1359
|
+
! Local variables
|
|
1360
|
+
integer(ip) :: mr, nr, nrm1, j, nrmj, nrpj, i, lh
|
|
1361
|
+
real(wp) :: ipstor
|
|
1362
|
+
complex(wp) :: s, t
|
|
1363
|
+
|
|
1364
|
+
mr = m
|
|
1365
|
+
nr = (n + 1)/2
|
|
1366
|
+
nrm1 = nr - 1
|
|
1367
|
+
|
|
1368
|
+
if ((2*nr) == n) then
|
|
1369
|
+
!
|
|
1370
|
+
! even number of unknowns
|
|
1371
|
+
!
|
|
1372
|
+
do j = 1, nrm1
|
|
1373
|
+
nrmj = nr - j
|
|
1374
|
+
nrpj = nr + j
|
|
1375
|
+
do i = 1, mr
|
|
1376
|
+
s = q(i, nrmj) - q(i, nrpj)
|
|
1377
|
+
t = q(i, nrmj) + q(i, nrpj)
|
|
1378
|
+
q(i, nrmj) = s
|
|
1379
|
+
q(i, nrpj) = t
|
|
1380
|
+
end do
|
|
1381
|
+
end do
|
|
1382
|
+
|
|
1383
|
+
q(:mr, nr) = TWO * q(:mr, nr)
|
|
1384
|
+
q(:mr, n) = TWO * q(:mr, n)
|
|
1385
|
+
|
|
1386
|
+
call solve_poisson_dirichlet (mr, nrm1, 1, a, bb, c, q, idimq, b, w, d, tcos, p)
|
|
1387
|
+
|
|
1388
|
+
ipstor = real(w(1), kind=wp)
|
|
1389
|
+
|
|
1390
|
+
call solve_poisson_neumann(mr, nr + 1, 1, 1, a, bb, c, q(1, nr), idimq, b, b2, &
|
|
1391
|
+
b3, w, w2, w3, d, tcos, p)
|
|
1392
|
+
|
|
1393
|
+
ipstor = max(ipstor, real(w(1), kind=wp))
|
|
1394
|
+
|
|
1395
|
+
do j = 1, nrm1
|
|
1396
|
+
nrmj = nr - j
|
|
1397
|
+
nrpj = nr + j
|
|
1398
|
+
do i = 1, mr
|
|
1399
|
+
s = HALF * (q(i, nrpj)+q(i, nrmj))
|
|
1400
|
+
t = HALF * (q(i, nrpj)-q(i, nrmj))
|
|
1401
|
+
q(i, nrmj) = s
|
|
1402
|
+
q(i, nrpj) = t
|
|
1403
|
+
end do
|
|
1404
|
+
end do
|
|
1405
|
+
|
|
1406
|
+
q(:mr, nr) = HALF * q(:mr, nr)
|
|
1407
|
+
q(:mr, n) = HALF * q(:mr, n)
|
|
1408
|
+
|
|
1409
|
+
else
|
|
1410
|
+
|
|
1411
|
+
do j = 1, nrm1
|
|
1412
|
+
nrpj = n + 1 - j
|
|
1413
|
+
do i = 1, mr
|
|
1414
|
+
s = q(i, j) - q(i, nrpj)
|
|
1415
|
+
t = q(i, j) + q(i, nrpj)
|
|
1416
|
+
q(i, j) = s
|
|
1417
|
+
q(i, nrpj) = t
|
|
1418
|
+
end do
|
|
1419
|
+
end do
|
|
1420
|
+
|
|
1421
|
+
q(:mr, nr) = TWO * q(:mr, nr)
|
|
1422
|
+
lh = nrm1/2
|
|
1423
|
+
|
|
1424
|
+
do j = 1, lh
|
|
1425
|
+
nrmj = nr - j
|
|
1426
|
+
do i = 1, mr
|
|
1427
|
+
s = q(i, j)
|
|
1428
|
+
q(i, j) = q(i, nrmj)
|
|
1429
|
+
q(i, nrmj) = s
|
|
1430
|
+
end do
|
|
1431
|
+
end do
|
|
1432
|
+
|
|
1433
|
+
call solve_poisson_dirichlet(mr, nrm1, 2, a, bb, c, q, idimq, b, w, d, tcos, p)
|
|
1434
|
+
|
|
1435
|
+
ipstor = real(w(1), kind=wp)
|
|
1436
|
+
|
|
1437
|
+
call solve_poisson_neumann(mr, nr, 2, 1, a, bb, c, q(1, nr), idimq, b, b2, b3, &
|
|
1438
|
+
w, w2, w3, d, tcos, p)
|
|
1439
|
+
|
|
1440
|
+
ipstor = max(ipstor, real(w(1), kind=wp))
|
|
1441
|
+
|
|
1442
|
+
do j = 1, nrm1
|
|
1443
|
+
nrpj = nr + j
|
|
1444
|
+
do i = 1, mr
|
|
1445
|
+
s = HALF * (q(i, nrpj)+q(i, j))
|
|
1446
|
+
t = HALF * (q(i, nrpj)-q(i, j))
|
|
1447
|
+
q(i, nrpj) = t
|
|
1448
|
+
q(i, j) = s
|
|
1449
|
+
end do
|
|
1450
|
+
end do
|
|
1451
|
+
|
|
1452
|
+
q(:mr, nr) = HALF * q(:mr, nr)
|
|
1453
|
+
|
|
1454
|
+
do j = 1, lh
|
|
1455
|
+
nrmj = nr - j
|
|
1456
|
+
do i = 1, mr
|
|
1457
|
+
s = q(i, j)
|
|
1458
|
+
q(i, j) = q(i, nrmj)
|
|
1459
|
+
q(i, nrmj) = s
|
|
1460
|
+
end do
|
|
1461
|
+
end do
|
|
1462
|
+
end if
|
|
1463
|
+
|
|
1464
|
+
w(1) = cmplx(ipstor, ZERO, kind=wp)
|
|
1465
|
+
|
|
1466
|
+
end subroutine solve_poisson_periodic
|
|
1467
|
+
|
|
1468
|
+
! Purpose:
|
|
1469
|
+
!
|
|
1470
|
+
! Computes required cosine values in ascending
|
|
1471
|
+
! order. When ijump > 1 the routine computes values
|
|
1472
|
+
!
|
|
1473
|
+
! 2*cos(j*pi/l) , j=1, 2, ..., l and j /= 0(mod n/ijump+1)
|
|
1474
|
+
!
|
|
1475
|
+
! where l = ijump*(n/ijump+1).
|
|
1476
|
+
!
|
|
1477
|
+
!
|
|
1478
|
+
! when ijump = 1 it computes
|
|
1479
|
+
!
|
|
1480
|
+
! 2*cos((j-fnum)*pi/(n+fden)) , j=1, 2, ... , n
|
|
1481
|
+
!
|
|
1482
|
+
! where
|
|
1483
|
+
!
|
|
1484
|
+
! fnum = 0.5, fden = 0.0, for regular reduction values
|
|
1485
|
+
! fnum = 0.0, fden = 1.0, for b-r and c-r when istag = 1
|
|
1486
|
+
! fnum = 0.0, fden = 0.5, for b-r and c-r when istag = 2
|
|
1487
|
+
! fnum = 0.5, fden = 0.5, for b-r and c-r when istag = 2
|
|
1488
|
+
! in solve_poisson_neumann only.
|
|
1489
|
+
!
|
|
1490
|
+
!
|
|
1491
|
+
pure subroutine generate_cosines(n, ijump, fnum, fden, a)
|
|
1492
|
+
|
|
1493
|
+
! Dummy arguments
|
|
1494
|
+
integer(ip), intent(in) :: n
|
|
1495
|
+
integer(ip), intent(in) :: ijump
|
|
1496
|
+
real(wp), intent(in) :: fnum
|
|
1497
|
+
real(wp), intent(in) :: fden
|
|
1498
|
+
complex(wp), intent(out) :: a(*)
|
|
1499
|
+
|
|
1500
|
+
! Local variables
|
|
1501
|
+
integer(ip) :: k3, k4, k, k1, k5, i, k2, np1
|
|
1502
|
+
real(wp) :: pibyn, x, y
|
|
1503
|
+
|
|
1504
|
+
if (n /= 0) then
|
|
1505
|
+
if (ijump /= 1) then
|
|
1506
|
+
k3 = n/ijump + 1
|
|
1507
|
+
k4 = k3 - 1
|
|
1508
|
+
pibyn = PI/(n + ijump)
|
|
1509
|
+
do k = 1, ijump
|
|
1510
|
+
k1 = (k - 1)*k3
|
|
1511
|
+
k5 = (k - 1)*k4
|
|
1512
|
+
do i = 1, k4
|
|
1513
|
+
x = k1 + i
|
|
1514
|
+
k2 = k5 + i
|
|
1515
|
+
a(k2) = cmplx((-TWO * cos(x*pibyn)), ZERO, kind=wp)
|
|
1516
|
+
end do
|
|
1517
|
+
end do
|
|
1518
|
+
else
|
|
1519
|
+
np1 = n + 1
|
|
1520
|
+
y = PI/(real(n, kind=wp) + fden)
|
|
1521
|
+
do i = 1, n
|
|
1522
|
+
x = real(np1 - i, kind=wp) - fnum
|
|
1523
|
+
a(i) = cmplx(TWO * cos(x*y), ZERO, kind=wp)
|
|
1524
|
+
end do
|
|
1525
|
+
end if
|
|
1526
|
+
end if
|
|
1527
|
+
|
|
1528
|
+
end subroutine generate_cosines
|
|
1529
|
+
|
|
1530
|
+
! Purpose:
|
|
1531
|
+
!
|
|
1532
|
+
! Merges two ascending strings of numbers in the
|
|
1533
|
+
! array tcos. The first string is of length m1 and starts at
|
|
1534
|
+
! tcos(i1+1). The second string is of length m2 and starts at
|
|
1535
|
+
! tcos(i2+1). The merged string goes into tcos(i3+1).
|
|
1536
|
+
!
|
|
1537
|
+
subroutine merge_tcos(tcos, i1, m1, i2, m2, i3)
|
|
1538
|
+
|
|
1539
|
+
! Dummy arguments
|
|
1540
|
+
integer(ip), intent(in) :: i1
|
|
1541
|
+
integer(ip), intent(in) :: m1
|
|
1542
|
+
integer(ip), intent(in) :: i2
|
|
1543
|
+
integer(ip), intent(in) :: m2
|
|
1544
|
+
integer(ip), intent(in) :: i3
|
|
1545
|
+
complex(wp), intent(inout) :: tcos(*)
|
|
1546
|
+
|
|
1547
|
+
! Local variables
|
|
1548
|
+
integer(ip) :: j11, j3, j1, j2, j, l, k, m
|
|
1549
|
+
complex(wp) :: x, y
|
|
1550
|
+
|
|
1551
|
+
j1 = 1
|
|
1552
|
+
j2 = 1
|
|
1553
|
+
j = i3
|
|
1554
|
+
|
|
1555
|
+
if_construct: if (m1 /= 0) then
|
|
1556
|
+
if (m2 /= 0) then
|
|
1557
|
+
outer_loop: do
|
|
1558
|
+
j11 = j1
|
|
1559
|
+
j3 = max(m1, j11)
|
|
1560
|
+
block_construct: block
|
|
1561
|
+
do j1 = j11, j3
|
|
1562
|
+
j = j + 1
|
|
1563
|
+
l = j1 + i1
|
|
1564
|
+
x = tcos(l)
|
|
1565
|
+
l = j2 + i2
|
|
1566
|
+
y = tcos(l)
|
|
1567
|
+
if (real(x - y, kind=wp) > ZERO) exit block_construct
|
|
1568
|
+
tcos(j) = x
|
|
1569
|
+
end do
|
|
1570
|
+
if (j2 > m2) return
|
|
1571
|
+
exit if_construct
|
|
1572
|
+
end block block_construct
|
|
1573
|
+
tcos(j) = y
|
|
1574
|
+
j2 = j2 + 1
|
|
1575
|
+
if (j2 > m2) exit outer_loop
|
|
1576
|
+
end do outer_loop
|
|
1577
|
+
if (j1 > m1) return
|
|
1578
|
+
end if
|
|
1579
|
+
k = j - j1 + 1
|
|
1580
|
+
do j = j1, m1
|
|
1581
|
+
m = k + j
|
|
1582
|
+
l = j + i1
|
|
1583
|
+
tcos(m) = tcos(l)
|
|
1584
|
+
end do
|
|
1585
|
+
return
|
|
1586
|
+
end if if_construct
|
|
1587
|
+
|
|
1588
|
+
k = j - j2 + 1
|
|
1589
|
+
|
|
1590
|
+
do j = j2, m2
|
|
1591
|
+
m = k + j
|
|
1592
|
+
l = j + i2
|
|
1593
|
+
tcos(m) = tcos(l)
|
|
1594
|
+
end do
|
|
1595
|
+
|
|
1596
|
+
|
|
1597
|
+
end subroutine merge_tcos
|
|
1598
|
+
|
|
1599
|
+
! Purpose:
|
|
1600
|
+
!
|
|
1601
|
+
! To solve a system of linear equations where the
|
|
1602
|
+
! coefficient matrix is a rational function in the matrix given by
|
|
1603
|
+
! tridiagonal ( . . . , a(i), b(i), c(i), . . . ).
|
|
1604
|
+
!
|
|
1605
|
+
subroutine solve_linear_system(idegbr, idegcr, m, a, b, c, y, tcos, d, w)
|
|
1606
|
+
|
|
1607
|
+
! Dummy arguments
|
|
1608
|
+
integer(ip), intent(in) :: idegbr
|
|
1609
|
+
integer(ip), intent(in) :: idegcr
|
|
1610
|
+
integer(ip), intent(in) :: m
|
|
1611
|
+
complex(wp), intent(in) :: a(m)
|
|
1612
|
+
complex(wp), intent(in) :: b(m)
|
|
1613
|
+
complex(wp), intent(in) :: c(m)
|
|
1614
|
+
complex(wp), intent(inout) :: y(m)
|
|
1615
|
+
complex(wp), intent(in) :: tcos(*)
|
|
1616
|
+
complex(wp), intent(out) :: d(m)
|
|
1617
|
+
complex(wp), intent(out) :: w(m)
|
|
1618
|
+
|
|
1619
|
+
! Local variables
|
|
1620
|
+
integer(ip) :: mm1, ifb, ifc, l, lint, k, i, iip
|
|
1621
|
+
complex(wp) :: x, xx, z
|
|
1622
|
+
|
|
1623
|
+
mm1 = m - 1
|
|
1624
|
+
ifb = idegbr + 1
|
|
1625
|
+
ifc = idegcr + 1
|
|
1626
|
+
l = ifb/ifc
|
|
1627
|
+
lint = 1
|
|
1628
|
+
|
|
1629
|
+
do k = 1, idegbr
|
|
1630
|
+
x = tcos(k)
|
|
1631
|
+
|
|
1632
|
+
if (k == l) then
|
|
1633
|
+
i = idegbr + lint
|
|
1634
|
+
xx = x - tcos(i)
|
|
1635
|
+
w = y
|
|
1636
|
+
y = xx*y
|
|
1637
|
+
end if
|
|
1638
|
+
|
|
1639
|
+
z = ONE/(b(1)-x)
|
|
1640
|
+
d(1) = c(1)*z
|
|
1641
|
+
y(1) = y(1)*z
|
|
1642
|
+
|
|
1643
|
+
do i = 2, mm1
|
|
1644
|
+
z = ONE/(b(i)-x-a(i)*d(i-1))
|
|
1645
|
+
d(i) = c(i)*z
|
|
1646
|
+
y(i) = (y(i)-a(i)*y(i-1))*z
|
|
1647
|
+
end do
|
|
1648
|
+
|
|
1649
|
+
z = b(m) - x - a(m)*d(mm1)
|
|
1650
|
+
|
|
1651
|
+
if (abs(z) == ZERO) then
|
|
1652
|
+
y(m) = ZERO
|
|
1653
|
+
else
|
|
1654
|
+
y(m) = (y(m)-a(m)*y(mm1))/z
|
|
1655
|
+
end if
|
|
1656
|
+
|
|
1657
|
+
do iip = 1, mm1
|
|
1658
|
+
y(m-iip) = y(m-iip) - d(m-iip)*y(m+1-iip)
|
|
1659
|
+
end do
|
|
1660
|
+
|
|
1661
|
+
if (k /= l) cycle
|
|
1662
|
+
|
|
1663
|
+
y = y + w
|
|
1664
|
+
lint = lint + 1
|
|
1665
|
+
l = (lint*ifb)/ifc
|
|
1666
|
+
end do
|
|
1667
|
+
|
|
1668
|
+
end subroutine solve_linear_system
|
|
1669
|
+
|
|
1670
|
+
subroutine solve_tridiagonal_system(m, a, b, c, k, y1, y2, y3, tcos, d, w1, w2, w3)
|
|
1671
|
+
|
|
1672
|
+
! Dummy arguments
|
|
1673
|
+
integer(ip), intent(in) :: m
|
|
1674
|
+
integer(ip), intent(in) :: k(4)
|
|
1675
|
+
complex(wp), intent(in) :: a(m)
|
|
1676
|
+
complex(wp), intent(in) :: b(m)
|
|
1677
|
+
complex(wp), intent(in) :: c(m)
|
|
1678
|
+
complex(wp), intent(inout) :: y1(m)
|
|
1679
|
+
complex(wp), intent(inout) :: y2(m)
|
|
1680
|
+
complex(wp), intent(inout) :: y3(m)
|
|
1681
|
+
complex(wp), intent(in) :: tcos(*)
|
|
1682
|
+
complex(wp), intent(out) :: d(m)
|
|
1683
|
+
complex(wp), intent(out) :: w1(m)
|
|
1684
|
+
complex(wp), intent(out) :: w2(m)
|
|
1685
|
+
complex(wp), intent(out) :: w3(m)
|
|
1686
|
+
|
|
1687
|
+
! Local variables
|
|
1688
|
+
integer(ip) :: mm1, k1, k2, k3, k4
|
|
1689
|
+
integer(ip) :: if1, if2, if3, if4, k2k3k4, l1, l2
|
|
1690
|
+
integer(ip) :: l3, lint1, lint2, lint3
|
|
1691
|
+
integer(ip) :: kint1, kint2, kint3, n, i, iip
|
|
1692
|
+
complex(wp) :: x, xx, z
|
|
1693
|
+
|
|
1694
|
+
mm1 = m - 1
|
|
1695
|
+
k1 = k(1)
|
|
1696
|
+
k2 = k(2)
|
|
1697
|
+
k3 = k(3)
|
|
1698
|
+
k4 = k(4)
|
|
1699
|
+
if1 = k1 + 1
|
|
1700
|
+
if2 = k2 + 1
|
|
1701
|
+
if3 = k3 + 1
|
|
1702
|
+
if4 = k4 + 1
|
|
1703
|
+
k2k3k4 = k2 + k3 + k4
|
|
1704
|
+
|
|
1705
|
+
if (k2k3k4 /= 0) then
|
|
1706
|
+
l1 = if1/if2
|
|
1707
|
+
l2 = if1/if3
|
|
1708
|
+
l3 = if1/if4
|
|
1709
|
+
lint1 = 1
|
|
1710
|
+
lint2 = 1
|
|
1711
|
+
lint3 = 1
|
|
1712
|
+
kint1 = k1
|
|
1713
|
+
kint2 = kint1 + k2
|
|
1714
|
+
kint3 = kint2 + k3
|
|
1715
|
+
end if
|
|
1716
|
+
|
|
1717
|
+
do n = 1, k1
|
|
1718
|
+
x = tcos(n)
|
|
1719
|
+
|
|
1720
|
+
if (k2k3k4 /= 0) then
|
|
1721
|
+
if (n == l1) w1 = y1
|
|
1722
|
+
if (n == l2) w2 = y2
|
|
1723
|
+
if (n == l3) w3 = y3
|
|
1724
|
+
end if
|
|
1725
|
+
|
|
1726
|
+
z = ONE/(b(1)-x)
|
|
1727
|
+
d(1) = c(1)*z
|
|
1728
|
+
y1(1) = y1(1)*z
|
|
1729
|
+
y2(1) = y2(1)*z
|
|
1730
|
+
y3(1) = y3(1)*z
|
|
1731
|
+
|
|
1732
|
+
do i = 2, m
|
|
1733
|
+
z = ONE/(b(i)-x-a(i)*d(i-1))
|
|
1734
|
+
d(i) = c(i)*z
|
|
1735
|
+
y1(i) = (y1(i)-a(i)*y1(i-1))*z
|
|
1736
|
+
y2(i) = (y2(i)-a(i)*y2(i-1))*z
|
|
1737
|
+
y3(i) = (y3(i)-a(i)*y3(i-1))*z
|
|
1738
|
+
end do
|
|
1739
|
+
|
|
1740
|
+
do iip = 1, mm1
|
|
1741
|
+
y1(m-iip) = y1(m-iip) - d(m-iip)*y1(m+1-iip)
|
|
1742
|
+
y2(m-iip) = y2(m-iip) - d(m-iip)*y2(m+1-iip)
|
|
1743
|
+
y3(m-iip) = y3(m-iip) - d(m-iip)*y3(m+1-iip)
|
|
1744
|
+
end do
|
|
1745
|
+
|
|
1746
|
+
if (k2k3k4 == 0) cycle
|
|
1747
|
+
|
|
1748
|
+
if (n == l1) then
|
|
1749
|
+
i = lint1 + kint1
|
|
1750
|
+
xx = x - tcos(i)
|
|
1751
|
+
y1 = xx*y1 + w1
|
|
1752
|
+
lint1 = lint1 + 1
|
|
1753
|
+
l1 = (lint1*if1)/if2
|
|
1754
|
+
end if
|
|
1755
|
+
|
|
1756
|
+
if (n == l2) then
|
|
1757
|
+
i = lint2 + kint2
|
|
1758
|
+
xx = x - tcos(i)
|
|
1759
|
+
y2 = xx*y2 + w2
|
|
1760
|
+
lint2 = lint2 + 1
|
|
1761
|
+
l2 = (lint2*if1)/if3
|
|
1762
|
+
end if
|
|
1763
|
+
|
|
1764
|
+
if (n /= l3) cycle
|
|
1765
|
+
|
|
1766
|
+
i = lint3 + kint3
|
|
1767
|
+
xx = x - tcos(i)
|
|
1768
|
+
y3 = xx*y3 + w3
|
|
1769
|
+
lint3 = lint3 + 1
|
|
1770
|
+
l3 = (lint3*if1)/if4
|
|
1771
|
+
end do
|
|
1772
|
+
|
|
1773
|
+
end subroutine solve_tridiagonal_system
|
|
1774
|
+
|
|
1775
|
+
end module complex_linear_systems_solver
|
|
1776
|
+
!
|
|
1777
|
+
! REVISION HISTORY
|
|
1778
|
+
!
|
|
1779
|
+
! September 1973 Version 1
|
|
1780
|
+
! April 1976 Version 2
|
|
1781
|
+
! January 1978 Version 3
|
|
1782
|
+
! December 1979 Version 3.1
|
|
1783
|
+
! February 1985 Documentation upgrade
|
|
1784
|
+
! November 1988 Version 3.2, FORTRAN 77 changes
|
|
1785
|
+
! June 2004 Version 5.0, Fortran 90 changes
|
|
1786
|
+
! May 2016 Fortran 2008 changes
|
|
1787
|
+
!
|