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