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,1947 @@
|
|
|
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_block_tridiagonal_linear_systems_solver
|
|
35
|
+
|
|
36
|
+
use fishpack_precision, only: &
|
|
37
|
+
wp, & ! Working precision
|
|
38
|
+
ip, & ! Integer precision
|
|
39
|
+
MACHINE_EPSILON
|
|
40
|
+
|
|
41
|
+
use type_GeneralizedCyclicReductionUtility, only: &
|
|
42
|
+
psgf, &
|
|
43
|
+
ppspf, &
|
|
44
|
+
ppsgf, &
|
|
45
|
+
comf_interface, &
|
|
46
|
+
GeneralizedCyclicReductionUtility
|
|
47
|
+
|
|
48
|
+
use type_FishpackWorkspace, only: &
|
|
49
|
+
FishpackWorkspace
|
|
50
|
+
|
|
51
|
+
! Explicit typing only
|
|
52
|
+
implicit none
|
|
53
|
+
|
|
54
|
+
! Everything is private unless stated otherwise
|
|
55
|
+
private
|
|
56
|
+
public :: cblktri
|
|
57
|
+
|
|
58
|
+
! Parameters confined to the module
|
|
59
|
+
real(wp), parameter :: ZERO = 0.0_wp
|
|
60
|
+
real(wp), parameter :: HALF = 0.5_wp
|
|
61
|
+
real(wp), parameter :: ONE = 1.0_wp
|
|
62
|
+
real(wp), parameter :: TWO = 2.0_wp
|
|
63
|
+
|
|
64
|
+
type, private, extends(GeneralizedCyclicReductionUtility) :: ComplexGeneralizedCyclicReductionUtility
|
|
65
|
+
contains
|
|
66
|
+
! Public type-bound procedures
|
|
67
|
+
procedure, public :: cblktri_lower_routine
|
|
68
|
+
! Private type-bound procedures
|
|
69
|
+
procedure, private :: cblktri_bsrh
|
|
70
|
+
procedure, private :: cblktri_compute_roots_of_b_polynomials
|
|
71
|
+
procedure, private :: cblktri_compute_eigenvalues
|
|
72
|
+
procedure, private :: cblktri_tevls
|
|
73
|
+
procedure, private :: cblktri_compute_index_a_coeff
|
|
74
|
+
procedure, private :: cblktri_compute_index_b_coeff
|
|
75
|
+
procedure, private :: cblktri_compute_index_c_coeff
|
|
76
|
+
end type ComplexGeneralizedCyclicReductionUtility
|
|
77
|
+
|
|
78
|
+
contains
|
|
79
|
+
|
|
80
|
+
! PURPOSE cblktri solves a system of linear equations
|
|
81
|
+
! of the form
|
|
82
|
+
!
|
|
83
|
+
! an(j)*x(i, j-1) + am(i)*x(i-1, j) +
|
|
84
|
+
! (bn(j)+bm(i))*x(i, j) + cn(j)*x(i, j+1) +
|
|
85
|
+
! cm(i)*x(i+1, j) = y(i, j)
|
|
86
|
+
!
|
|
87
|
+
! for i = 1, 2, ..., m and j = 1, 2, ..., n.
|
|
88
|
+
!
|
|
89
|
+
! i+1 and i-1 are evaluated modulo m and
|
|
90
|
+
! j+1 and j-1 modulo n, i.e.,
|
|
91
|
+
!
|
|
92
|
+
! x(i, 0) = x(i, n), x(i, n+1) = x(i, 1),
|
|
93
|
+
! x(0, j) = x(m, j), x(m+1, j) = x(1, j).
|
|
94
|
+
!
|
|
95
|
+
! these equations usually result from the
|
|
96
|
+
! discretization of separable elliptic
|
|
97
|
+
! equations. boundary conditions may be
|
|
98
|
+
! dirichlet, neumann, or periodic.
|
|
99
|
+
!
|
|
100
|
+
! cblktri is a complex version of package
|
|
101
|
+
! blktri on ulib.
|
|
102
|
+
!
|
|
103
|
+
! USAGE call cblktri(iflg, np, n, an, bn, cn, mp, m, am, bm,
|
|
104
|
+
! cm, idimy, y, ierror, w)
|
|
105
|
+
!
|
|
106
|
+
!
|
|
107
|
+
! DIMENSION OF an(n), bn(n), cn(n), am(m), bm(m), cm(m), y(idimy, n)
|
|
108
|
+
! ARGUMENTS
|
|
109
|
+
!
|
|
110
|
+
! ARGUMENTS
|
|
111
|
+
!
|
|
112
|
+
! ON INPUT iflg
|
|
113
|
+
!
|
|
114
|
+
! = 0 initialization only.
|
|
115
|
+
! certain quantities that depend on np,
|
|
116
|
+
! n, an, bn, and cn are computed and
|
|
117
|
+
! stored in the derived data type w
|
|
118
|
+
!
|
|
119
|
+
! = 1 the quantities that were computed
|
|
120
|
+
! in the initialization are used
|
|
121
|
+
! to obtain the solution x(i, j).
|
|
122
|
+
!
|
|
123
|
+
! note:
|
|
124
|
+
! a call with iflg=0 takes
|
|
125
|
+
! approximately one half the time
|
|
126
|
+
! as a call with iflg = 1.
|
|
127
|
+
! however, the initialization does
|
|
128
|
+
! not have to be repeated unless np,
|
|
129
|
+
! n, an, bn, or cn change.
|
|
130
|
+
!
|
|
131
|
+
! np
|
|
132
|
+
! = 0 if an(1) and cn(n) are not zero,
|
|
133
|
+
! which corresponds to periodic
|
|
134
|
+
! bounary conditions.
|
|
135
|
+
!
|
|
136
|
+
! = 1 if an(1) and cn(n) are zero.
|
|
137
|
+
!
|
|
138
|
+
! n
|
|
139
|
+
! the number of unknowns in the j-direction.
|
|
140
|
+
! n must be greater than 4.
|
|
141
|
+
! the operation count is proportional to
|
|
142
|
+
! mnlog2(n), hence n should be selected
|
|
143
|
+
! less than or equal to m.
|
|
144
|
+
!
|
|
145
|
+
! an, bn, cn
|
|
146
|
+
! one-dimensional arrays of length n
|
|
147
|
+
! that specify the coefficients in the
|
|
148
|
+
! linear equations given above.
|
|
149
|
+
!
|
|
150
|
+
! mp
|
|
151
|
+
! = 0 if am(1) and cm(m) are not zero,
|
|
152
|
+
! which corresponds to periodic
|
|
153
|
+
! boundary conditions.
|
|
154
|
+
!
|
|
155
|
+
! = 1 if am(1) = cm(m) = 0 .
|
|
156
|
+
!
|
|
157
|
+
! m
|
|
158
|
+
! the number of unknowns in the i-direction.
|
|
159
|
+
! m must be greater than 4.
|
|
160
|
+
!
|
|
161
|
+
! am, bm, cm
|
|
162
|
+
! complex one-dimensional arrays of length m
|
|
163
|
+
! that specify the coefficients in the linear
|
|
164
|
+
! equations given above.
|
|
165
|
+
!
|
|
166
|
+
! idimy
|
|
167
|
+
! the row (or first) dimension of the
|
|
168
|
+
! two-dimensional array y as it appears
|
|
169
|
+
! in the program calling cblktri.
|
|
170
|
+
! this parameter is used to specify the
|
|
171
|
+
! variable dimension of y.
|
|
172
|
+
! idimy must be at least m.
|
|
173
|
+
!
|
|
174
|
+
! y
|
|
175
|
+
! a complex two-dimensional array that
|
|
176
|
+
! specifies the values of the right side of
|
|
177
|
+
! the linear system of equations given above.
|
|
178
|
+
! y must be dimensioned y(idimy, n) with
|
|
179
|
+
! idimy >= m.
|
|
180
|
+
!
|
|
181
|
+
! w
|
|
182
|
+
! A FishpackWorkspace derived data type variable
|
|
183
|
+
! which is used internally in cblktri to
|
|
184
|
+
! dynamically allocate real and complex workspace
|
|
185
|
+
! arrays used in solution. An error flag
|
|
186
|
+
! (ierror = 20) is set if the required workspace
|
|
187
|
+
! allocation fails (for example if n, m are too large)
|
|
188
|
+
! real and complex values are set in the components
|
|
189
|
+
! of w on a initial (iflg=0) call to cblktri. These
|
|
190
|
+
! must be preserved on non-initial calls (iflg=1)
|
|
191
|
+
! to cblktri. This eliminates redundant calculations
|
|
192
|
+
! and saves compute time.
|
|
193
|
+
! **** IMPORTANT! the user program calling cblktri should
|
|
194
|
+
! include the statement:
|
|
195
|
+
!
|
|
196
|
+
! call w%destroy()
|
|
197
|
+
!
|
|
198
|
+
! after the final approximation is generated by
|
|
199
|
+
! cblktri. The will deallocate the real and complex
|
|
200
|
+
! workspace arrays of w. Tailure to include this statement
|
|
201
|
+
! could result in serious memory leakage.
|
|
202
|
+
!
|
|
203
|
+
!
|
|
204
|
+
! ARGUMENTS
|
|
205
|
+
!
|
|
206
|
+
! ON OUTPUT y
|
|
207
|
+
! contains the solution x.
|
|
208
|
+
!
|
|
209
|
+
! ierror
|
|
210
|
+
! an error flag that indicates invalid
|
|
211
|
+
! input parameters. except for number zer0,
|
|
212
|
+
! a solution is not attempted.
|
|
213
|
+
!
|
|
214
|
+
! = 0 no error.
|
|
215
|
+
! = 1 m < 5
|
|
216
|
+
! = 2 n < 5
|
|
217
|
+
! = 3 idimy < m.
|
|
218
|
+
! = 4 cblktri failed while computing results
|
|
219
|
+
! that depend on the coefficient arrays
|
|
220
|
+
! an, bn, cn. check these arrays.
|
|
221
|
+
! = 5 an(j)*cn(j-1) is less than 0 for some j.
|
|
222
|
+
!
|
|
223
|
+
! possible reasons for this condition are
|
|
224
|
+
! 1. the arrays an and cn are not correct
|
|
225
|
+
! 2. too large a grid spacing was used
|
|
226
|
+
! in the discretization of the elliptic
|
|
227
|
+
! equation.
|
|
228
|
+
! 3. the linear equations resulted from a
|
|
229
|
+
! partial differential equation which
|
|
230
|
+
! was not elliptic.
|
|
231
|
+
!
|
|
232
|
+
! = 20 if the dynamic allocation of real and
|
|
233
|
+
! complex workspace in the derived type
|
|
234
|
+
! (FishpackWorkspace) variable w fails (e.g.,
|
|
235
|
+
! if n, m are too large for the platform used)
|
|
236
|
+
!
|
|
237
|
+
!
|
|
238
|
+
!
|
|
239
|
+
! SPECIAL CONDITIONS The algorithm may fail if
|
|
240
|
+
!
|
|
241
|
+
! abs(bm(i)+bn(j)) < abs(am(i))+abs(an(j)) +
|
|
242
|
+
! abs(cm(i))+abs(cn(j))
|
|
243
|
+
!
|
|
244
|
+
! for some i and j. the algorithm will also
|
|
245
|
+
! fail if an(j)*cn(j-1) < 0 zero for some j.
|
|
246
|
+
! see the description of the output parameter
|
|
247
|
+
! ierror.
|
|
248
|
+
!
|
|
249
|
+
!
|
|
250
|
+
! HISTORY * Written by Paul Swarztrauber at NCAR in
|
|
251
|
+
! the early 1970's. Rewritten an released
|
|
252
|
+
! on NCAR's public software libraries in
|
|
253
|
+
! January, 1980.
|
|
254
|
+
! * Revised in June 2004 by John Adams using
|
|
255
|
+
! Fortran 90 dynamically allocated workspace
|
|
256
|
+
! and derived data types to eliminate mixed
|
|
257
|
+
! mode conflicts in the earlier versions.
|
|
258
|
+
!
|
|
259
|
+
! ALGORITHM Generalized cyclic reduction
|
|
260
|
+
! (see reference below)
|
|
261
|
+
!
|
|
262
|
+
! PORTABILITY The approximate machine accuracy is computed
|
|
263
|
+
! by calling the intrinsic function epsilon
|
|
264
|
+
!
|
|
265
|
+
! REFERENCES Swarztrauber, P. and R. Sweet, 'Efficient
|
|
266
|
+
! FORTRAN subprograms for the solution of
|
|
267
|
+
! elliptic equations'
|
|
268
|
+
! NCAR TN/IA-109, July, 1975, 138 pp.
|
|
269
|
+
!
|
|
270
|
+
! Swarztrauber P. N., A direct method for
|
|
271
|
+
! the discrete solution of separable
|
|
272
|
+
! elliptic equations, S.I.A.M.
|
|
273
|
+
! J. Numer. Anal., 11(1974) pp. 1136-1150.
|
|
274
|
+
!
|
|
275
|
+
subroutine cblktri(iflg, np, n, an, bn, cn, mp, m, am, bm, cm, &
|
|
276
|
+
idimy, y, ierror, w)
|
|
277
|
+
|
|
278
|
+
! Dummy arguments
|
|
279
|
+
integer(ip), intent(in) :: iflg
|
|
280
|
+
integer(ip), intent(in) :: np
|
|
281
|
+
integer(ip), intent(in) :: n
|
|
282
|
+
integer(ip), intent(in) :: mp
|
|
283
|
+
integer(ip), intent(in) :: m
|
|
284
|
+
integer(ip), intent(in) :: idimy
|
|
285
|
+
integer(ip), intent(out) :: ierror
|
|
286
|
+
real(wp), intent(in) :: an(:)
|
|
287
|
+
real(wp), intent(in) :: bn(:)
|
|
288
|
+
real(wp), intent(in) :: cn(:)
|
|
289
|
+
complex(wp), intent(in) :: am(:)
|
|
290
|
+
complex(wp), intent(in) :: bm(:)
|
|
291
|
+
complex(wp), intent(in) :: cm(:)
|
|
292
|
+
complex(wp), intent(inout) :: y(:,:)
|
|
293
|
+
class(FishpackWorkspace), intent(inout) :: w
|
|
294
|
+
|
|
295
|
+
! Local variables
|
|
296
|
+
type(ComplexGeneralizedCyclicReductionUtility) :: util
|
|
297
|
+
integer(ip) :: m2, nh, nl, iwah, iw1, iwbh
|
|
298
|
+
integer(ip) :: iw2, iw3, iwd, iww, iwu
|
|
299
|
+
integer(ip) :: irwk, icwk
|
|
300
|
+
|
|
301
|
+
common_variables: associate( &
|
|
302
|
+
npp => util%npp, &
|
|
303
|
+
k => util%k, &
|
|
304
|
+
nm => util%nm, &
|
|
305
|
+
ncmplx=> util%ncmplx, &
|
|
306
|
+
ik => util%ik, &
|
|
307
|
+
cnv => util%cnv &
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
! Test m and n for the proper form
|
|
311
|
+
nm = n
|
|
312
|
+
m2 = 2*m
|
|
313
|
+
|
|
314
|
+
! Check input arguments
|
|
315
|
+
if (m < 5) then
|
|
316
|
+
ierror = 1
|
|
317
|
+
return
|
|
318
|
+
else if (nm < 3) then
|
|
319
|
+
ierror = 2
|
|
320
|
+
return
|
|
321
|
+
else if (idimy < m) then
|
|
322
|
+
ierror = 3
|
|
323
|
+
return
|
|
324
|
+
else
|
|
325
|
+
ierror = 0
|
|
326
|
+
end if
|
|
327
|
+
|
|
328
|
+
! Compute workspace indices
|
|
329
|
+
nh = n
|
|
330
|
+
npp = np
|
|
331
|
+
|
|
332
|
+
if (npp /= 0) nh = nh + 1
|
|
333
|
+
|
|
334
|
+
ik = 4
|
|
335
|
+
k = 3
|
|
336
|
+
|
|
337
|
+
do
|
|
338
|
+
if (nh <= ik) exit
|
|
339
|
+
ik = 2*ik
|
|
340
|
+
k = k + 1
|
|
341
|
+
end do
|
|
342
|
+
|
|
343
|
+
nl = ik
|
|
344
|
+
ik = 2*ik
|
|
345
|
+
nl = nl - 1
|
|
346
|
+
iwah = (k - 2)*ik + k + 6
|
|
347
|
+
|
|
348
|
+
select case (npp)
|
|
349
|
+
case(0)
|
|
350
|
+
iwbh = iwah + 2*nm
|
|
351
|
+
iw1 = iwbh
|
|
352
|
+
nm = nm - 1
|
|
353
|
+
case default
|
|
354
|
+
iw1 = iwah
|
|
355
|
+
iwbh = iw1 + nm
|
|
356
|
+
end select
|
|
357
|
+
|
|
358
|
+
iw2 = iw1 + m
|
|
359
|
+
iw3 = iw2 + m
|
|
360
|
+
iwd = iw3 + m
|
|
361
|
+
iww = iwd + m
|
|
362
|
+
iwu = iww + m
|
|
363
|
+
|
|
364
|
+
select case (iflg)
|
|
365
|
+
case (0)
|
|
366
|
+
! Initialize solver
|
|
367
|
+
|
|
368
|
+
! Set required workspace sizes
|
|
369
|
+
irwk = iw1 + 2*n
|
|
370
|
+
icwk = iw1 + 6*m
|
|
371
|
+
|
|
372
|
+
! Allocate memory
|
|
373
|
+
call w%create(irwk, icwk)
|
|
374
|
+
|
|
375
|
+
! Check if allocation was successful
|
|
376
|
+
if (ierror == 20) return
|
|
377
|
+
|
|
378
|
+
associate( &
|
|
379
|
+
rew => w%real_workspace, &
|
|
380
|
+
cxw => w%complex_workspace &
|
|
381
|
+
)
|
|
382
|
+
! Compute roots of b polynomials
|
|
383
|
+
call util%cblktri_compute_roots_of_b_polynomials(ierror, an, bn, cn, rew, cxw, rew(iwah:), rew(iwbh:))
|
|
384
|
+
end associate
|
|
385
|
+
case default
|
|
386
|
+
! Solve system
|
|
387
|
+
associate( &
|
|
388
|
+
rew => w%real_workspace, &
|
|
389
|
+
cxw => w%complex_workspace &
|
|
390
|
+
)
|
|
391
|
+
select case (mp)
|
|
392
|
+
case (0)
|
|
393
|
+
call util%cblktri_lower_routine(nl, an, cn, m, am, bm, cm, &
|
|
394
|
+
idimy, y, rew, cxw, &
|
|
395
|
+
cxw(iw1), cxw(iw2), cxw(iw3), cxw(iwd), cxw(iww), &
|
|
396
|
+
cxw(iwu), procp, cprocp)
|
|
397
|
+
case default
|
|
398
|
+
call util%cblktri_lower_routine(nl, an, cn, m, am, bm, cm, &
|
|
399
|
+
idimy, y, rew, cxw, &
|
|
400
|
+
cxw(iw1), cxw(iw2), cxw(iw3), cxw(iwd), cxw(iww), &
|
|
401
|
+
cxw(iwu), proc, cproc)
|
|
402
|
+
end select
|
|
403
|
+
end associate
|
|
404
|
+
end select
|
|
405
|
+
end associate common_variables
|
|
406
|
+
|
|
407
|
+
end subroutine cblktri
|
|
408
|
+
|
|
409
|
+
! Purpose:
|
|
410
|
+
!
|
|
411
|
+
! Solves the linear system
|
|
412
|
+
!
|
|
413
|
+
! Remarks:
|
|
414
|
+
!
|
|
415
|
+
! b contains the roots of all the b polynomials
|
|
416
|
+
! w1, w2, w3, wd, ww, wu are all working arrays
|
|
417
|
+
! prdct is either procp or proc depending on whether the boundary
|
|
418
|
+
! conditions in the m direction are periodic or not
|
|
419
|
+
! cprdct is either cprocp or cproc which are called if some of the zeros
|
|
420
|
+
! of the b polynomials are complex.
|
|
421
|
+
!
|
|
422
|
+
subroutine cblktri_lower_routine(self, n, an, cn, m, am, bm, cm, idimy, y, b, bc, &
|
|
423
|
+
w1, w2, w3, wd, ww, wu, prdct, cprdct)
|
|
424
|
+
|
|
425
|
+
! Dummy arguments
|
|
426
|
+
class(ComplexGeneralizedCyclicReductionUtility), intent(inout) :: self
|
|
427
|
+
integer(ip), intent(in) :: n
|
|
428
|
+
integer(ip), intent(in) :: m
|
|
429
|
+
integer(ip), intent(in) :: idimy
|
|
430
|
+
real(wp), intent(in) :: an(:)
|
|
431
|
+
real(wp), intent(in) :: cn(:)
|
|
432
|
+
complex(wp), intent(in) :: am(:)
|
|
433
|
+
complex(wp), intent(in) :: bm(:)
|
|
434
|
+
complex(wp), intent(in) :: cm(:)
|
|
435
|
+
real(wp), intent(out) :: b(*)
|
|
436
|
+
complex(wp), intent(inout) :: y(idimy,n)
|
|
437
|
+
complex(wp), intent(out) :: bc(*)
|
|
438
|
+
complex(wp), intent(out) :: w1(*)
|
|
439
|
+
complex(wp), intent(out) :: w2(*)
|
|
440
|
+
complex(wp), intent(out) :: w3(*)
|
|
441
|
+
complex(wp), intent(out) :: wd(*)
|
|
442
|
+
complex(wp), intent(out) :: ww(*)
|
|
443
|
+
complex(wp), intent(out) :: wu(*)
|
|
444
|
+
external :: prdct, cprdct
|
|
445
|
+
|
|
446
|
+
! Local variables
|
|
447
|
+
integer(ip) :: kdo, l, ir, i2, i1, i3, i4, irm1, im2, nm2, im3, nm3
|
|
448
|
+
integer(ip) :: im1, nm1, iif, i, ipi1, ipi2, ipi3, idxc, nc, idxa, na, ip2, np2
|
|
449
|
+
integer(ip) :: ip1, np1, ip3, np3, iz, nz, izr, ll, ifd
|
|
450
|
+
integer(ip) :: iip, np, imi1, imi2
|
|
451
|
+
real(wp) :: dummy_variable(1)
|
|
452
|
+
|
|
453
|
+
common_variables: associate( &
|
|
454
|
+
npp => self%npp, &
|
|
455
|
+
k => self%k, &
|
|
456
|
+
nm => self%nm, &
|
|
457
|
+
ncmplx=> self%ncmplx, &
|
|
458
|
+
ik => self%ik, &
|
|
459
|
+
cnv => self%cnv &
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
! begin reduction phase
|
|
463
|
+
kdo = k - 1
|
|
464
|
+
do l = 1, kdo
|
|
465
|
+
ir = l - 1
|
|
466
|
+
i2 = 2**ir
|
|
467
|
+
i1 = i2/2
|
|
468
|
+
i3 = i2 + i1
|
|
469
|
+
i4 = i2 + i2
|
|
470
|
+
irm1 = ir - 1
|
|
471
|
+
call self%cblktri_compute_index_b_coeff(i2, ir, im2, nm2)
|
|
472
|
+
call self%cblktri_compute_index_b_coeff(i1, irm1, im3, nm3)
|
|
473
|
+
call self%cblktri_compute_index_b_coeff(i3, irm1, im1, nm1)
|
|
474
|
+
call prdct(nm2, b(im2), nm3, b(im3), nm1, b(im1), 0, dummy_variable, &
|
|
475
|
+
y(1,i2), w3, m, am, bm, cm, wd, ww, wu)
|
|
476
|
+
iif = 2**k
|
|
477
|
+
do i = i4, iif, i4
|
|
478
|
+
if (i > nm) cycle
|
|
479
|
+
ipi1 = i + i1
|
|
480
|
+
ipi2 = i + i2
|
|
481
|
+
ipi3 = i + i3
|
|
482
|
+
call self%cblktri_compute_index_c_coeff(i, ir, idxc, nc)
|
|
483
|
+
if (iif <= i) cycle
|
|
484
|
+
call self%cblktri_compute_index_a_coeff(i, ir, idxa, na)
|
|
485
|
+
call self%cblktri_compute_index_b_coeff(i - i1, irm1, im1, nm1)
|
|
486
|
+
call self%cblktri_compute_index_b_coeff(ipi2, ir, ip2, np2)
|
|
487
|
+
call self%cblktri_compute_index_b_coeff(ipi1, irm1, ip1, np1)
|
|
488
|
+
call self%cblktri_compute_index_b_coeff(ipi3, irm1, ip3, np3)
|
|
489
|
+
call prdct(nm1, b(im1), 0, dummy_variable, 0, dummy_variable, na, an(idxa), w3, &
|
|
490
|
+
w1, m, am, bm, cm, wd, ww, wu)
|
|
491
|
+
if (ipi2 > nm) then
|
|
492
|
+
w3(:m) = ZERO
|
|
493
|
+
w2(:m) = ZERO
|
|
494
|
+
else
|
|
495
|
+
call prdct(np2, b(ip2), np1, b(ip1), np3, b(ip3), 0, dummy_variable, &
|
|
496
|
+
y(1, ipi2), w3, m, am, bm, cm, wd, ww, wu)
|
|
497
|
+
call prdct(np1, b(ip1), 0, dummy_variable, 0, dummy_variable, nc, cn(idxc), w3, &
|
|
498
|
+
w2, m, am, bm, cm, wd, ww, wu)
|
|
499
|
+
end if
|
|
500
|
+
y(:m, i) = w1(:m) + w2(:m) + y(:m, i)
|
|
501
|
+
end do
|
|
502
|
+
end do
|
|
503
|
+
|
|
504
|
+
if (npp == 0) then
|
|
505
|
+
iif = 2**k
|
|
506
|
+
i = iif/2
|
|
507
|
+
i1 = i/2
|
|
508
|
+
call self%cblktri_compute_index_b_coeff(i - i1, k - 2, im1, nm1)
|
|
509
|
+
call self%cblktri_compute_index_b_coeff(i + i1, k - 2, ip1, np1)
|
|
510
|
+
call self%cblktri_compute_index_b_coeff(i, k - 1, iz, nz)
|
|
511
|
+
call prdct(nz, b(iz), nm1, b(im1), np1, b(ip1), 0, dummy_variable, &
|
|
512
|
+
y(1, i), w1, m, am, bm, cm, wd, ww, wu)
|
|
513
|
+
|
|
514
|
+
izr = i
|
|
515
|
+
w2(:m) = w1(:m)
|
|
516
|
+
|
|
517
|
+
do ll = 2, k
|
|
518
|
+
l = k - ll + 1
|
|
519
|
+
ir = l - 1
|
|
520
|
+
i2 = 2**ir
|
|
521
|
+
i1 = i2/2
|
|
522
|
+
i = i2
|
|
523
|
+
call self%cblktri_compute_index_c_coeff(i, ir, idxc, nc)
|
|
524
|
+
call self%cblktri_compute_index_b_coeff(i, ir, iz, nz)
|
|
525
|
+
call self%cblktri_compute_index_b_coeff(i - i1, ir - 1, im1, nm1)
|
|
526
|
+
call self%cblktri_compute_index_b_coeff(i + i1, ir - 1, ip1, np1)
|
|
527
|
+
call prdct(np1, b(ip1), 0, dummy_variable, 0, dummy_variable, nc, cn(idxc), w1, &
|
|
528
|
+
w1, m, am, bm, cm, wd, ww, wu)
|
|
529
|
+
w1(:m) = y(:m, i) + w1(:m)
|
|
530
|
+
call prdct(nz, b(iz), nm1, b(im1), np1, b(ip1), 0, dummy_variable, w1 &
|
|
531
|
+
, w1, m, am, bm, cm, wd, ww, wu)
|
|
532
|
+
end do
|
|
533
|
+
|
|
534
|
+
loop_118: do ll = 2, k
|
|
535
|
+
l = k - ll + 1
|
|
536
|
+
ir = l - 1
|
|
537
|
+
i2 = 2**ir
|
|
538
|
+
i1 = i2/2
|
|
539
|
+
i4 = i2 + i2
|
|
540
|
+
ifd = iif - i2
|
|
541
|
+
do i = i2, ifd, i4
|
|
542
|
+
|
|
543
|
+
if (i - i2 /= izr) cycle
|
|
544
|
+
|
|
545
|
+
if (i > nm) cycle loop_118
|
|
546
|
+
|
|
547
|
+
call self%cblktri_compute_index_a_coeff(i, ir, idxa, na)
|
|
548
|
+
call self%cblktri_compute_index_b_coeff(i, ir, iz, nz)
|
|
549
|
+
call self%cblktri_compute_index_b_coeff(i - i1, ir - 1, im1, nm1)
|
|
550
|
+
call self%cblktri_compute_index_b_coeff(i + i1, ir - 1, ip1, np1)
|
|
551
|
+
call prdct(nm1, b(im1), 0, dummy_variable, 0, dummy_variable, na, an(idxa), w2 &
|
|
552
|
+
, w2, m, am, bm, cm, wd, ww, wu)
|
|
553
|
+
w2(:m) = y(:m, i) + w2(:m)
|
|
554
|
+
call prdct(nz, b(iz), nm1, b(im1), np1, b(ip1), 0, dummy_variable, &
|
|
555
|
+
w2, w2, m, am, bm, cm, wd, ww, wu)
|
|
556
|
+
izr = i
|
|
557
|
+
if (i == nm) exit loop_118
|
|
558
|
+
end do
|
|
559
|
+
end do loop_118
|
|
560
|
+
|
|
561
|
+
y(:m, nm+1) = y(:m, nm+1) - cn(nm+1)*w1(:m) - an(nm+1)*w2(:m)
|
|
562
|
+
|
|
563
|
+
call self%cblktri_compute_index_b_coeff(iif/2, k - 1, im1, nm1)
|
|
564
|
+
call self%cblktri_compute_index_b_coeff(iif, k - 1, iip, np)
|
|
565
|
+
|
|
566
|
+
select case (ncmplx)
|
|
567
|
+
case (0)
|
|
568
|
+
call prdct(nm + 1, b(iip), nm1, b(im1), 0, dummy_variable, 0, dummy_variable, &
|
|
569
|
+
y(1,nm+1), y(1, nm+1), m, am, bm, cm, wd, ww, wu)
|
|
570
|
+
case default
|
|
571
|
+
call cprdct(nm + 1, bc(iip), nm1, b(im1), 0, dummy_variable, 0, dummy_variable, &
|
|
572
|
+
y(1,nm+1), y(1, nm+1), m, am, bm, cm, w1, w3, ww)
|
|
573
|
+
end select
|
|
574
|
+
|
|
575
|
+
w1(:m) = an(1)*y(:m, nm+1)
|
|
576
|
+
w2(:m) = cn(nm)*y(:m, nm+1)
|
|
577
|
+
y(:m, 1) = y(:m, 1) - w1(:m)
|
|
578
|
+
y(:m, nm) = y(:m, nm) - w2(:m)
|
|
579
|
+
|
|
580
|
+
do l = 1, kdo
|
|
581
|
+
ir = l - 1
|
|
582
|
+
i2 = 2**ir
|
|
583
|
+
i4 = i2 + i2
|
|
584
|
+
i1 = i2/2
|
|
585
|
+
i = i4
|
|
586
|
+
call self%cblktri_compute_index_a_coeff(i, ir, idxa, na)
|
|
587
|
+
call self%cblktri_compute_index_b_coeff(i - i2, ir, im2, nm2)
|
|
588
|
+
call self%cblktri_compute_index_b_coeff(i - i2 - i1, ir - 1, im3, nm3)
|
|
589
|
+
call self%cblktri_compute_index_b_coeff(i - i1, ir - 1, im1, nm1)
|
|
590
|
+
call prdct(nm2, b(im2), nm3, b(im3), nm1, b(im1), 0, dummy_variable, &
|
|
591
|
+
w1, w1, m, am, bm, cm, wd, ww, wu)
|
|
592
|
+
call prdct(nm1, b(im1), 0, dummy_variable, 0, dummy_variable, na, an(idxa), w1, &
|
|
593
|
+
w1, m, am, bm, cm, wd, ww, wu)
|
|
594
|
+
y(:m, i) = y(:m, i) - w1(:m)
|
|
595
|
+
end do
|
|
596
|
+
|
|
597
|
+
izr = nm
|
|
598
|
+
loop_131: do l = 1, kdo
|
|
599
|
+
ir = l - 1
|
|
600
|
+
i2 = 2**ir
|
|
601
|
+
i1 = i2/2
|
|
602
|
+
i3 = i2 + i1
|
|
603
|
+
i4 = i2 + i2
|
|
604
|
+
irm1 = ir - 1
|
|
605
|
+
do i = i4, iif, i4
|
|
606
|
+
ipi1 = i + i1
|
|
607
|
+
ipi2 = i + i2
|
|
608
|
+
ipi3 = i + i3
|
|
609
|
+
|
|
610
|
+
if (ipi2 /= izr) then
|
|
611
|
+
if (i /= izr) cycle
|
|
612
|
+
cycle loop_131
|
|
613
|
+
end if
|
|
614
|
+
|
|
615
|
+
call self%cblktri_compute_index_c_coeff(i, ir, idxc, nc)
|
|
616
|
+
call self%cblktri_compute_index_b_coeff(ipi2, ir, ip2, np2)
|
|
617
|
+
call self%cblktri_compute_index_b_coeff(ipi1, irm1, ip1, np1)
|
|
618
|
+
call self%cblktri_compute_index_b_coeff(ipi3, irm1, ip3, np3)
|
|
619
|
+
call prdct(np2, b(ip2), np1, b(ip1), np3, b(ip3), 0, dummy_variable, &
|
|
620
|
+
w2, w2, m, am, bm, cm, wd, ww, wu)
|
|
621
|
+
call prdct(np1, b(ip1), 0, dummy_variable, 0, dummy_variable, nc, cn(idxc), w2, &
|
|
622
|
+
w2, m, am, bm, cm, wd, ww, wu)
|
|
623
|
+
y(:m, i) = y(:m, i) - w2(:m)
|
|
624
|
+
izr = i
|
|
625
|
+
cycle loop_131
|
|
626
|
+
end do
|
|
627
|
+
end do loop_131
|
|
628
|
+
end if
|
|
629
|
+
|
|
630
|
+
! begin back substitution phase
|
|
631
|
+
do ll = 1, k
|
|
632
|
+
l = k - ll + 1
|
|
633
|
+
ir = l - 1
|
|
634
|
+
irm1 = ir - 1
|
|
635
|
+
i2 = 2**ir
|
|
636
|
+
i1 = i2/2
|
|
637
|
+
i4 = i2 + i2
|
|
638
|
+
ifd = iif - i2
|
|
639
|
+
do i = i2, ifd, i4
|
|
640
|
+
if (i > nm) cycle
|
|
641
|
+
imi1 = i - i1
|
|
642
|
+
imi2 = i - i2
|
|
643
|
+
ipi1 = i + i1
|
|
644
|
+
ipi2 = i + i2
|
|
645
|
+
call self%cblktri_compute_index_a_coeff(i, ir, idxa, na)
|
|
646
|
+
call self%cblktri_compute_index_c_coeff(i, ir, idxc, nc)
|
|
647
|
+
call self%cblktri_compute_index_b_coeff(i, ir, iz, nz)
|
|
648
|
+
call self%cblktri_compute_index_b_coeff(imi1, irm1, im1, nm1)
|
|
649
|
+
call self%cblktri_compute_index_b_coeff(ipi1, irm1, ip1, np1)
|
|
650
|
+
|
|
651
|
+
if (i <= i2) then
|
|
652
|
+
w1(:m) = ZERO
|
|
653
|
+
else
|
|
654
|
+
call prdct(nm1, b(im1), 0, dummy_variable, 0, dummy_variable, na, an(idxa), &
|
|
655
|
+
y(1,imi2), w1, m, am, bm, cm, wd, ww, wu)
|
|
656
|
+
end if
|
|
657
|
+
|
|
658
|
+
if (ipi2 > nm) then
|
|
659
|
+
w2(:m) = ZERO
|
|
660
|
+
else
|
|
661
|
+
call prdct(np1, b(ip1), 0, dummy_variable, 0, dummy_variable, nc, cn(idxc), y( &
|
|
662
|
+
1, ipi2), w2, m, am, bm, cm, wd, ww, wu)
|
|
663
|
+
end if
|
|
664
|
+
w1(:m) = y(:m, i) + w1(:m) + w2(:m)
|
|
665
|
+
call prdct(nz, b(iz), nm1, b(im1), np1, b(ip1), 0, dummy_variable, w1, &
|
|
666
|
+
y(1, i), m, am, bm, cm, wd, ww, wu)
|
|
667
|
+
end do
|
|
668
|
+
end do
|
|
669
|
+
|
|
670
|
+
end associate common_variables
|
|
671
|
+
|
|
672
|
+
end subroutine cblktri_lower_routine
|
|
673
|
+
|
|
674
|
+
function cblktri_bsrh(self, xll, xrr, iz, c, a, bh, f, sgn) &
|
|
675
|
+
result(return_value)
|
|
676
|
+
|
|
677
|
+
! Dummy arguments
|
|
678
|
+
class(ComplexGeneralizedCyclicReductionUtility), intent(inout) :: self
|
|
679
|
+
integer(ip) :: iz
|
|
680
|
+
real(wp), intent(in) :: xll
|
|
681
|
+
real(wp), intent(in) :: xrr
|
|
682
|
+
real(wp) :: c(*)
|
|
683
|
+
real(wp) :: a(*)
|
|
684
|
+
real(wp) :: bh(*)
|
|
685
|
+
procedure(comf_interface) :: f
|
|
686
|
+
real(wp), intent(in) :: sgn
|
|
687
|
+
real(wp) :: return_value
|
|
688
|
+
|
|
689
|
+
! Local variables
|
|
690
|
+
real(wp) :: r1, xl, xr, dx, x
|
|
691
|
+
|
|
692
|
+
common_variables: associate( &
|
|
693
|
+
npp => self%npp, &
|
|
694
|
+
k => self%k, &
|
|
695
|
+
nm => self%nm, &
|
|
696
|
+
ncmplx=> self%ncmplx, &
|
|
697
|
+
ik => self%ik, &
|
|
698
|
+
cnv => self%cnv &
|
|
699
|
+
)
|
|
700
|
+
|
|
701
|
+
xl = xll
|
|
702
|
+
xr = xrr
|
|
703
|
+
dx = HALF*abs(xr - xl)
|
|
704
|
+
x = HALF*(xl + xr)
|
|
705
|
+
r1 = sgn*f(x, iz, c, a, bh)
|
|
706
|
+
|
|
707
|
+
if (r1 >= ZERO) then
|
|
708
|
+
if (r1 == ZERO) then
|
|
709
|
+
return_value = HALF*(xl + xr)
|
|
710
|
+
return
|
|
711
|
+
end if
|
|
712
|
+
xr = x
|
|
713
|
+
else
|
|
714
|
+
xl = x
|
|
715
|
+
end if
|
|
716
|
+
|
|
717
|
+
dx = HALF * dx
|
|
718
|
+
|
|
719
|
+
do
|
|
720
|
+
if (dx <= cnv) exit
|
|
721
|
+
x = HALF*(xl + xr)
|
|
722
|
+
r1 = sgn*f(x, iz, c, a, bh)
|
|
723
|
+
if (r1 >= ZERO) then
|
|
724
|
+
if (r1 == ZERO) then
|
|
725
|
+
return_value = HALF*(xl + xr)
|
|
726
|
+
return
|
|
727
|
+
end if
|
|
728
|
+
xr = x
|
|
729
|
+
else
|
|
730
|
+
xl = x
|
|
731
|
+
end if
|
|
732
|
+
dx = HALF*dx
|
|
733
|
+
end do
|
|
734
|
+
|
|
735
|
+
return_value = HALF*(xl + xr)
|
|
736
|
+
|
|
737
|
+
end associate common_variables
|
|
738
|
+
|
|
739
|
+
end function cblktri_bsrh
|
|
740
|
+
|
|
741
|
+
! Purpose:
|
|
742
|
+
!
|
|
743
|
+
! Computes the roots of the b polynomials using subroutine
|
|
744
|
+
! cblktri_tevls which is a modification the eispack program tqlrat.
|
|
745
|
+
! ierror is set to 4 if either cblktri_tevls fails or if a(j+1)*c(j) is
|
|
746
|
+
! less than zero for some j. ah, bh are temporary work arrays.
|
|
747
|
+
!
|
|
748
|
+
subroutine cblktri_compute_roots_of_b_polynomials(self, ierror, an, bn, cn, b, bc, ah, bh)
|
|
749
|
+
|
|
750
|
+
! Dummy arguments
|
|
751
|
+
class(ComplexGeneralizedCyclicReductionUtility), intent(inout) :: self
|
|
752
|
+
integer(ip), intent(out) :: ierror
|
|
753
|
+
real(wp), intent(in) :: an(:)
|
|
754
|
+
real(wp), intent(in) :: bn(:)
|
|
755
|
+
real(wp), intent(in) :: cn(:)
|
|
756
|
+
real(wp), target, contiguous, intent(inout) :: b(:)
|
|
757
|
+
real(wp), intent(inout) :: ah(:)
|
|
758
|
+
real(wp), intent(inout) :: bh(:)
|
|
759
|
+
complex(wp), intent(inout) :: bc(:)
|
|
760
|
+
|
|
761
|
+
! Local variables
|
|
762
|
+
integer(ip) :: j, iif, kdo, l, ir, i2, i4
|
|
763
|
+
integer(ip) :: ipl, ifd, i, ib, nb, js, jf
|
|
764
|
+
integer(ip) :: ls, lh, nmp, l1, l2, j2, j1, n2m2
|
|
765
|
+
real(wp) :: bnorm, arg, d1, d2, d3
|
|
766
|
+
|
|
767
|
+
common_variables: associate( &
|
|
768
|
+
npp => self%npp, &
|
|
769
|
+
k => self%k, &
|
|
770
|
+
nm => self%nm, &
|
|
771
|
+
ncmplx=> self%ncmplx, &
|
|
772
|
+
ik => self%ik, &
|
|
773
|
+
cnv => self%cnv &
|
|
774
|
+
)
|
|
775
|
+
|
|
776
|
+
bnorm = abs(bn(1))
|
|
777
|
+
|
|
778
|
+
do j = 2, nm
|
|
779
|
+
bnorm = max(bnorm, abs(bn(j)))
|
|
780
|
+
arg = an(j)*cn(j-1)
|
|
781
|
+
if (arg < ZERO) then
|
|
782
|
+
ierror = 5
|
|
783
|
+
return
|
|
784
|
+
end if
|
|
785
|
+
b(j) = sign(sqrt(arg), an(j))
|
|
786
|
+
end do
|
|
787
|
+
|
|
788
|
+
cnv = MACHINE_EPSILON*bnorm
|
|
789
|
+
iif = 2**k
|
|
790
|
+
kdo = k - 1
|
|
791
|
+
|
|
792
|
+
outer_loop: do l = 1, kdo
|
|
793
|
+
|
|
794
|
+
ir = l - 1
|
|
795
|
+
i2 = 2**ir
|
|
796
|
+
i4 = i2 + i2
|
|
797
|
+
ipl = i4 - 1
|
|
798
|
+
ifd = iif - i4
|
|
799
|
+
|
|
800
|
+
do i = i4, ifd, i4
|
|
801
|
+
|
|
802
|
+
call self%cblktri_compute_index_b_coeff(i, l, ib, nb)
|
|
803
|
+
|
|
804
|
+
if (nb <= 0) cycle outer_loop
|
|
805
|
+
|
|
806
|
+
js = i - ipl
|
|
807
|
+
jf = js + nb - 1
|
|
808
|
+
ls = 0
|
|
809
|
+
bh(:jf-js+1) = bn(js:jf)
|
|
810
|
+
ah(:jf-js+1) = b(js:jf)
|
|
811
|
+
|
|
812
|
+
call self%cblktri_tevls(bh(1:nb), ah(1:nb), ierror)
|
|
813
|
+
|
|
814
|
+
if (ierror /= 0) then
|
|
815
|
+
ierror = 4
|
|
816
|
+
return
|
|
817
|
+
end if
|
|
818
|
+
|
|
819
|
+
lh = ib - 1
|
|
820
|
+
|
|
821
|
+
if (nb > 0) then
|
|
822
|
+
b(lh+1:nb+lh) = -bh(:nb)
|
|
823
|
+
lh = nb + lh
|
|
824
|
+
end if
|
|
825
|
+
|
|
826
|
+
end do
|
|
827
|
+
end do outer_loop
|
|
828
|
+
|
|
829
|
+
b(:nm) = -bn(:nm)
|
|
830
|
+
|
|
831
|
+
if (npp == 0) then
|
|
832
|
+
nmp = nm + 1
|
|
833
|
+
nb = nm + nmp
|
|
834
|
+
do j = 1, nb
|
|
835
|
+
l1 = mod(j - 1, nmp) + 1
|
|
836
|
+
l2 = mod(j + nm - 1, nmp) + 1
|
|
837
|
+
arg = an(l1)*cn(l2)
|
|
838
|
+
|
|
839
|
+
if (arg < ZERO) then
|
|
840
|
+
ierror = 5
|
|
841
|
+
return
|
|
842
|
+
end if
|
|
843
|
+
|
|
844
|
+
bh(j) = sign(sqrt(arg), (-an(l1)))
|
|
845
|
+
ah(j) = -bn(l1)
|
|
846
|
+
end do
|
|
847
|
+
|
|
848
|
+
call self%cblktri_tevls(ah(1:nb), bh(1:nb), ierror)
|
|
849
|
+
|
|
850
|
+
if (ierror /= 0) then
|
|
851
|
+
ierror = 4
|
|
852
|
+
return
|
|
853
|
+
end if
|
|
854
|
+
|
|
855
|
+
call self%cblktri_compute_index_b_coeff(iif, k - 1, j2, lh)
|
|
856
|
+
call self%cblktri_compute_index_b_coeff(iif/2, k - 1, j1, lh)
|
|
857
|
+
|
|
858
|
+
j2 = j2 + 1
|
|
859
|
+
lh = j2
|
|
860
|
+
n2m2 = j2 + 2*nm - 2
|
|
861
|
+
|
|
862
|
+
iteration: do
|
|
863
|
+
|
|
864
|
+
d1 = abs(b(j1)-b(j2-1))
|
|
865
|
+
d2 = abs(b(j1)-b(j2))
|
|
866
|
+
d3 = abs(b(j1)-b(j2+1))
|
|
867
|
+
|
|
868
|
+
if (d1 <= d2 .or. d3 <= d2) then
|
|
869
|
+
b(lh) = b(j2)
|
|
870
|
+
j2 = j2 + 1
|
|
871
|
+
lh = lh + 1
|
|
872
|
+
if (j2 <= n2m2) cycle iteration
|
|
873
|
+
else
|
|
874
|
+
j2 = j2 + 1
|
|
875
|
+
j1 = j1 + 1
|
|
876
|
+
if (j2 <= n2m2) cycle iteration
|
|
877
|
+
end if
|
|
878
|
+
exit iteration
|
|
879
|
+
end do iteration
|
|
880
|
+
|
|
881
|
+
b(lh) = b(n2m2+1)
|
|
882
|
+
|
|
883
|
+
call self%cblktri_compute_index_b_coeff(iif, k - 1, j1, j2)
|
|
884
|
+
|
|
885
|
+
j2 = j1 + nmp + nmp
|
|
886
|
+
|
|
887
|
+
! Compute eigenvalues of the periodic tridiagonal
|
|
888
|
+
block
|
|
889
|
+
complex(wp) :: cbp_arg(1)
|
|
890
|
+
real(wp) :: bp_arg(1)
|
|
891
|
+
real(wp), contiguous, pointer :: bh_arg(:) => null()
|
|
892
|
+
|
|
893
|
+
! Associate arguments
|
|
894
|
+
cbp_arg = cmplx(b(j1), kind=wp)
|
|
895
|
+
bp_arg = real(bc(j1), kind=wp)
|
|
896
|
+
bh_arg(1:) => b(j2:)
|
|
897
|
+
|
|
898
|
+
! Call solver
|
|
899
|
+
call self%cblktri_compute_eigenvalues(nm + 1, ierror, an, cn, cbp_arg, bp_arg, bh_arg)
|
|
900
|
+
|
|
901
|
+
! Terminate association
|
|
902
|
+
nullify(bh_arg)
|
|
903
|
+
end block
|
|
904
|
+
end if
|
|
905
|
+
|
|
906
|
+
end associate common_variables
|
|
907
|
+
|
|
908
|
+
end subroutine cblktri_compute_roots_of_b_polynomials
|
|
909
|
+
|
|
910
|
+
! Purpose:
|
|
911
|
+
!
|
|
912
|
+
! Applies a sequence of matrix operations to the vector x and
|
|
913
|
+
! stores the result in y
|
|
914
|
+
! aa array containing scalar multipliers of the vector x
|
|
915
|
+
! nd, nm1, nm2 are the lengths of the arrays bd, bm1, bm2 respectively
|
|
916
|
+
! bd, bm1, bm2 are arrays containing roots of certian b polynomials
|
|
917
|
+
! na is the length of the array aa
|
|
918
|
+
! x, y the matrix operations are applied to x and the result is y
|
|
919
|
+
! a, b, c are arrays which contain the tridiagonal matrix
|
|
920
|
+
! m is the order of the matrix
|
|
921
|
+
! d, w are work arrays
|
|
922
|
+
! isgn determines whether or not a change in sign is made
|
|
923
|
+
!
|
|
924
|
+
pure subroutine cproc(nd, bd, nm1, bm1, nm2, bm2, na, aa, x, y, m, a, b, c, d, w, yy)
|
|
925
|
+
|
|
926
|
+
! Dummy arguments
|
|
927
|
+
integer(ip), intent(in) :: nd
|
|
928
|
+
integer(ip), intent(in) :: nm1
|
|
929
|
+
integer(ip), intent(in) :: nm2
|
|
930
|
+
integer(ip), intent(in) :: na
|
|
931
|
+
integer(ip), intent(in) :: m
|
|
932
|
+
real(wp), intent(in) :: bm1(nm1)
|
|
933
|
+
real(wp), intent(in) :: bm2(nm2)
|
|
934
|
+
real(wp), intent(in) :: aa(na)
|
|
935
|
+
real(wp), intent(in) :: x(m)
|
|
936
|
+
real(wp), intent(out) :: yy(m)
|
|
937
|
+
real(wp), intent(in) :: a(m)
|
|
938
|
+
real(wp), intent(in) :: b(m)
|
|
939
|
+
real(wp), intent(in) :: c(m)
|
|
940
|
+
complex(wp), intent(in) :: bd(nd)
|
|
941
|
+
complex(wp), intent(out) :: d(m)
|
|
942
|
+
complex(wp), intent(out) :: w(m)
|
|
943
|
+
complex(wp), intent(out) :: y(m)
|
|
944
|
+
|
|
945
|
+
! Local variables
|
|
946
|
+
integer(ip) :: j, mm, id, m1, m2, ia, iflg, k
|
|
947
|
+
real(wp) :: rt
|
|
948
|
+
complex(wp) :: crt, den, y1, y2
|
|
949
|
+
|
|
950
|
+
y(:m) = x(:m)
|
|
951
|
+
mm = m - 1
|
|
952
|
+
id = nd
|
|
953
|
+
m1 = nm1
|
|
954
|
+
m2 = nm2
|
|
955
|
+
ia = na
|
|
956
|
+
|
|
957
|
+
main_loop: do
|
|
958
|
+
|
|
959
|
+
iflg = 0
|
|
960
|
+
if (id > 0) then
|
|
961
|
+
crt = bd(id)
|
|
962
|
+
id = id - 1
|
|
963
|
+
|
|
964
|
+
! begin solution to system
|
|
965
|
+
d(m) = a(m)/(b(m)-crt)
|
|
966
|
+
w(m) = y(m)/(b(m)-crt)
|
|
967
|
+
|
|
968
|
+
do j = 2, mm
|
|
969
|
+
k = m - j
|
|
970
|
+
den = b(k+1) - crt - c(k+1)*d(k+2)
|
|
971
|
+
d(k+1) = a(k+1)/den
|
|
972
|
+
w(k+1) = (y(k+1)-c(k+1)*w(k+2))/den
|
|
973
|
+
end do
|
|
974
|
+
|
|
975
|
+
den = b(1) - crt - c(1)*d(2)
|
|
976
|
+
|
|
977
|
+
if (abs(den) /= ZERO) then
|
|
978
|
+
y(1) = (y(1)-c(1)*w(2))/den
|
|
979
|
+
else
|
|
980
|
+
y(1) = cmplx(ONE, ZERO, kind=wp)
|
|
981
|
+
end if
|
|
982
|
+
|
|
983
|
+
do j = 2, m
|
|
984
|
+
y(j) = w(j) - d(j)*y(j-1)
|
|
985
|
+
end do
|
|
986
|
+
|
|
987
|
+
end if
|
|
988
|
+
|
|
989
|
+
if (.not.(m1 <= 0 .and. m2 <= 0)) then
|
|
990
|
+
if (m1 <= 0) then
|
|
991
|
+
rt = bm2(m2)
|
|
992
|
+
m2 = m2 - 1
|
|
993
|
+
else
|
|
994
|
+
if (m2 <= 0) then
|
|
995
|
+
rt = bm1(m1)
|
|
996
|
+
m1 = m1 - 1
|
|
997
|
+
else
|
|
998
|
+
if (abs(bm1(m1)) - abs(bm2(m2)) > ZERO) then
|
|
999
|
+
rt = bm1(m1)
|
|
1000
|
+
m1 = m1 - 1
|
|
1001
|
+
else
|
|
1002
|
+
rt = bm2(m2)
|
|
1003
|
+
m2 = m2 - 1
|
|
1004
|
+
end if
|
|
1005
|
+
end if
|
|
1006
|
+
end if
|
|
1007
|
+
|
|
1008
|
+
y1 = (b(1)-rt)*y(1) + c(1)*y(2)
|
|
1009
|
+
|
|
1010
|
+
if (mm >= 2) then
|
|
1011
|
+
do j = 2, mm
|
|
1012
|
+
y2 = a(j)*y(j-1) + (b(j)-rt)*y(j) + c(j)*y(j+1)
|
|
1013
|
+
y(j-1) = y1
|
|
1014
|
+
y1 = y2
|
|
1015
|
+
end do
|
|
1016
|
+
end if
|
|
1017
|
+
|
|
1018
|
+
y(m) = a(m)*y(m-1) + (b(m)-rt)*y(m)
|
|
1019
|
+
y(m-1) = y1
|
|
1020
|
+
iflg = 1
|
|
1021
|
+
|
|
1022
|
+
cycle main_loop
|
|
1023
|
+
|
|
1024
|
+
end if
|
|
1025
|
+
|
|
1026
|
+
if (ia > 0) then
|
|
1027
|
+
rt = aa(ia)
|
|
1028
|
+
ia = ia - 1
|
|
1029
|
+
iflg = 1
|
|
1030
|
+
|
|
1031
|
+
! scalar multiplication
|
|
1032
|
+
y(:m) = rt*y(:m)
|
|
1033
|
+
end if
|
|
1034
|
+
|
|
1035
|
+
if (iflg <= 0) exit main_loop
|
|
1036
|
+
|
|
1037
|
+
end do main_loop
|
|
1038
|
+
|
|
1039
|
+
end subroutine cproc
|
|
1040
|
+
|
|
1041
|
+
! Purpose:
|
|
1042
|
+
!
|
|
1043
|
+
! cprocp applies a sequence of matrix operations to the vector x and
|
|
1044
|
+
! stores the result in y
|
|
1045
|
+
!
|
|
1046
|
+
! bd, bm1, bm2 are arrays containing roots of certian b polynomials
|
|
1047
|
+
! nd, nm1, nm2 are the lengths of the arrays bd, bm1, bm2 respectively
|
|
1048
|
+
! aa array containing scalar multipliers of the vector x
|
|
1049
|
+
! na is the length of the array aa
|
|
1050
|
+
! x, y the matrix operations are applied to x and the result is y
|
|
1051
|
+
! a, b, c are arrays which contain the tridiagonal matrix
|
|
1052
|
+
! m is the order of the matrix
|
|
1053
|
+
! d, u are work arrays
|
|
1054
|
+
! isgn determines whether or not a change in sign is made
|
|
1055
|
+
!
|
|
1056
|
+
pure subroutine cprocp(nd, bd, nm1, bm1, nm2, bm2, na, aa, x, y, m, a, b, c, d, u, yy)
|
|
1057
|
+
|
|
1058
|
+
! Dummy arguments
|
|
1059
|
+
integer(ip), intent(in) :: nd
|
|
1060
|
+
integer(ip), intent(in) :: nm1
|
|
1061
|
+
integer(ip), intent(in) :: nm2
|
|
1062
|
+
integer(ip), intent(in) :: na
|
|
1063
|
+
integer(ip), intent(in) :: m
|
|
1064
|
+
real(wp), intent(in) :: bm1(nm1)
|
|
1065
|
+
real(wp), intent(in) :: bm2(nm2)
|
|
1066
|
+
real(wp), intent(in) :: aa(na)
|
|
1067
|
+
real(wp), intent(in) :: x(m)
|
|
1068
|
+
real(wp), intent(out) :: yy(m)
|
|
1069
|
+
real(wp), intent(in) :: a(m)
|
|
1070
|
+
real(wp), intent(in) :: b(m)
|
|
1071
|
+
real(wp), intent(in) :: c(m)
|
|
1072
|
+
complex(wp), intent(in) :: bd(nd)
|
|
1073
|
+
complex(wp), intent(out) :: d(m)
|
|
1074
|
+
complex(wp), intent(out) :: u(m)
|
|
1075
|
+
complex(wp), intent(out) :: y(m)
|
|
1076
|
+
|
|
1077
|
+
! Local variables
|
|
1078
|
+
integer(ip) :: j, mm, mm2, id, m1, m2, ia, iflg, k
|
|
1079
|
+
real(wp) :: rt
|
|
1080
|
+
complex(wp) :: v, den, bh, ym, am, y1, y2, yh, crt
|
|
1081
|
+
|
|
1082
|
+
y(:m) = x(:m)
|
|
1083
|
+
mm = m - 1
|
|
1084
|
+
mm2 = m - 2
|
|
1085
|
+
id = nd
|
|
1086
|
+
m1 = nm1
|
|
1087
|
+
m2 = nm2
|
|
1088
|
+
ia = na
|
|
1089
|
+
|
|
1090
|
+
main_loop: do
|
|
1091
|
+
|
|
1092
|
+
iflg = 0
|
|
1093
|
+
if (id > 0) then
|
|
1094
|
+
crt = bd(id)
|
|
1095
|
+
id = id - 1
|
|
1096
|
+
iflg = 1
|
|
1097
|
+
|
|
1098
|
+
! begin solution to system
|
|
1099
|
+
bh = b(m) - crt
|
|
1100
|
+
ym = y(m)
|
|
1101
|
+
den = b(1) - crt
|
|
1102
|
+
d(1) = c(1)/den
|
|
1103
|
+
u(1) = a(1)/den
|
|
1104
|
+
y(1) = y(1)/den
|
|
1105
|
+
v = c(m)
|
|
1106
|
+
if (mm2 >= 2) then
|
|
1107
|
+
do j = 2, mm2
|
|
1108
|
+
den = b(j) - crt - a(j)*d(j-1)
|
|
1109
|
+
d(j) = c(j)/den
|
|
1110
|
+
u(j) = -a(j)*u(j-1)/den
|
|
1111
|
+
y(j) = (y(j)-a(j)*y(j-1))/den
|
|
1112
|
+
bh = bh - v*u(j-1)
|
|
1113
|
+
ym = ym - v*y(j-1)
|
|
1114
|
+
v = -v*d(j-1)
|
|
1115
|
+
end do
|
|
1116
|
+
end if
|
|
1117
|
+
den = b(m-1) - crt - a(m-1)*d(m-2)
|
|
1118
|
+
d(m-1) = (c(m-1)-a(m-1)*u(m-2))/den
|
|
1119
|
+
y(m-1) = (y(m-1)-a(m-1)*y(m-2))/den
|
|
1120
|
+
am = a(m) - v*d(m-2)
|
|
1121
|
+
bh = bh - v*u(m-2)
|
|
1122
|
+
ym = ym - v*y(m-2)
|
|
1123
|
+
den = bh - am*d(m-1)
|
|
1124
|
+
if (abs(den) /= ZERO) then
|
|
1125
|
+
y(m) = (ym - am*y(m-1))/den
|
|
1126
|
+
else
|
|
1127
|
+
y(m) = cmplx(ONE, ZERO, kind=wp)
|
|
1128
|
+
end if
|
|
1129
|
+
y(m-1) = y(m-1) - d(m-1)*y(m)
|
|
1130
|
+
do j = 2, mm
|
|
1131
|
+
k = m - j
|
|
1132
|
+
y(k) = y(k) - d(k)*y(k+1) - u(k)*y(m)
|
|
1133
|
+
end do
|
|
1134
|
+
end if
|
|
1135
|
+
|
|
1136
|
+
if (.not.(m1 <= 0 .and. m2 <= 0)) then
|
|
1137
|
+
if (m1 <= 0) then
|
|
1138
|
+
rt = bm2(m2)
|
|
1139
|
+
m2 = m2 - 1
|
|
1140
|
+
else
|
|
1141
|
+
if (m2 <= 0) then
|
|
1142
|
+
rt = bm1(m1)
|
|
1143
|
+
m1 = m1 - 1
|
|
1144
|
+
else
|
|
1145
|
+
if (abs(bm1(m1)) > abs(bm2(m2))) then
|
|
1146
|
+
rt = bm1(m1)
|
|
1147
|
+
m1 = m1 - 1
|
|
1148
|
+
else
|
|
1149
|
+
rt = bm2(m2)
|
|
1150
|
+
m2 = m2 - 1
|
|
1151
|
+
|
|
1152
|
+
! matrix multiplication
|
|
1153
|
+
end if
|
|
1154
|
+
end if
|
|
1155
|
+
end if
|
|
1156
|
+
|
|
1157
|
+
yh = y(1)
|
|
1158
|
+
y1 = (b(1)-rt)*y(1) + c(1)*y(2) + a(1)*y(m)
|
|
1159
|
+
|
|
1160
|
+
if (mm >= 2) then
|
|
1161
|
+
do j = 2, mm
|
|
1162
|
+
y2 = a(j)*y(j-1) + (b(j)-rt)*y(j) + c(j)*y(j+1)
|
|
1163
|
+
y(j-1) = y1
|
|
1164
|
+
y1 = y2
|
|
1165
|
+
end do
|
|
1166
|
+
end if
|
|
1167
|
+
|
|
1168
|
+
y(m) = a(m)*y(m-1) + (b(m)-rt)*y(m) + c(m)*yh
|
|
1169
|
+
y(m-1) = y1
|
|
1170
|
+
iflg = 1
|
|
1171
|
+
|
|
1172
|
+
cycle main_loop
|
|
1173
|
+
end if
|
|
1174
|
+
|
|
1175
|
+
if (ia > 0) then
|
|
1176
|
+
rt = aa(ia)
|
|
1177
|
+
ia = ia - 1
|
|
1178
|
+
iflg = 1
|
|
1179
|
+
|
|
1180
|
+
! scalar multiplication
|
|
1181
|
+
y(:m) = rt*y(:m)
|
|
1182
|
+
end if
|
|
1183
|
+
|
|
1184
|
+
if (iflg <= 0) exit main_loop
|
|
1185
|
+
|
|
1186
|
+
end do main_loop
|
|
1187
|
+
|
|
1188
|
+
end subroutine cprocp
|
|
1189
|
+
|
|
1190
|
+
subroutine cblktri_compute_index_a_coeff(self, i, ir, idxa, na)
|
|
1191
|
+
|
|
1192
|
+
! Dummy arguments
|
|
1193
|
+
class(ComplexGeneralizedCyclicReductionUtility), intent(inout) :: self
|
|
1194
|
+
integer(ip), intent(in) :: i
|
|
1195
|
+
integer(ip), intent(in) :: ir
|
|
1196
|
+
integer(ip), intent(out) :: idxa
|
|
1197
|
+
integer(ip), intent(out) :: na
|
|
1198
|
+
|
|
1199
|
+
associate( nm => self%nm )
|
|
1200
|
+
na = 2**ir
|
|
1201
|
+
idxa = i - na + 1
|
|
1202
|
+
if (i > nm) na = 0
|
|
1203
|
+
end associate
|
|
1204
|
+
|
|
1205
|
+
end subroutine cblktri_compute_index_a_coeff
|
|
1206
|
+
|
|
1207
|
+
subroutine cblktri_compute_index_b_coeff(self, i, ir, idx, idp)
|
|
1208
|
+
|
|
1209
|
+
! Dummy arguments
|
|
1210
|
+
class(ComplexGeneralizedCyclicReductionUtility), intent(inout) :: self
|
|
1211
|
+
integer(ip), intent(in) :: i
|
|
1212
|
+
integer(ip), intent(in) :: ir
|
|
1213
|
+
integer(ip), intent(out) :: idx
|
|
1214
|
+
integer(ip), intent(out) :: idp
|
|
1215
|
+
|
|
1216
|
+
! Local variables
|
|
1217
|
+
integer(ip) :: izh, id, ipl
|
|
1218
|
+
|
|
1219
|
+
common_variables: associate( &
|
|
1220
|
+
npp => self%npp, &
|
|
1221
|
+
k => self%k, &
|
|
1222
|
+
nm => self%nm, &
|
|
1223
|
+
ncmplx=> self%ncmplx, &
|
|
1224
|
+
ik => self%ik, &
|
|
1225
|
+
cnv => self%cnv &
|
|
1226
|
+
)
|
|
1227
|
+
|
|
1228
|
+
! b(idx) is the location of the first root of the b(i, ir) polynomial
|
|
1229
|
+
idp = 0
|
|
1230
|
+
if (ir >= 0) then
|
|
1231
|
+
if (ir <= 0) then
|
|
1232
|
+
|
|
1233
|
+
if (i > nm) return
|
|
1234
|
+
|
|
1235
|
+
idx = i
|
|
1236
|
+
idp = 1
|
|
1237
|
+
return
|
|
1238
|
+
end if
|
|
1239
|
+
izh = 2**ir
|
|
1240
|
+
id = i - 2*izh
|
|
1241
|
+
idx = 2*id + (ir - 1)*ik + ir + (ik - i)/izh + 4
|
|
1242
|
+
ipl = izh - 1
|
|
1243
|
+
idp = 2*izh - 1
|
|
1244
|
+
|
|
1245
|
+
if (i - ipl > nm) then
|
|
1246
|
+
idp = 0
|
|
1247
|
+
return
|
|
1248
|
+
end if
|
|
1249
|
+
|
|
1250
|
+
if (i + ipl > nm) idp = nm + ipl - i + 1
|
|
1251
|
+
|
|
1252
|
+
end if
|
|
1253
|
+
|
|
1254
|
+
end associate common_variables
|
|
1255
|
+
|
|
1256
|
+
end subroutine cblktri_compute_index_b_coeff
|
|
1257
|
+
|
|
1258
|
+
subroutine cblktri_compute_index_c_coeff(self, i, ir, idxc, nc)
|
|
1259
|
+
|
|
1260
|
+
! Dummy arguments
|
|
1261
|
+
class(ComplexGeneralizedCyclicReductionUtility), intent(inout) :: self
|
|
1262
|
+
integer(ip), intent(in) :: i
|
|
1263
|
+
integer(ip), intent(in) :: ir
|
|
1264
|
+
integer(ip), intent(out) :: idxc
|
|
1265
|
+
integer(ip), intent(out) :: nc
|
|
1266
|
+
|
|
1267
|
+
associate( nm => self%nm )
|
|
1268
|
+
nc = 2**ir
|
|
1269
|
+
idxc = i
|
|
1270
|
+
if (idxc + nc - 1 > nm) nc = 0
|
|
1271
|
+
end associate
|
|
1272
|
+
|
|
1273
|
+
end subroutine cblktri_compute_index_c_coeff
|
|
1274
|
+
|
|
1275
|
+
! Purpose:
|
|
1276
|
+
!
|
|
1277
|
+
! Computes the eigenvalues of the periodic tridiagonal
|
|
1278
|
+
! matrix with coefficients an, bn, cn
|
|
1279
|
+
!
|
|
1280
|
+
! n is the order of the bh and bp polynomials
|
|
1281
|
+
! on output bp contains the eigenvalues
|
|
1282
|
+
! cbp is the same as bp except type complex
|
|
1283
|
+
! bh is used to temporarily store the roots of the b hat polynomial
|
|
1284
|
+
! which enters through bp
|
|
1285
|
+
subroutine cblktri_compute_eigenvalues(self, n, ierror, a, c, cbp, bp, bh)
|
|
1286
|
+
|
|
1287
|
+
! Dummy arguments
|
|
1288
|
+
class(ComplexGeneralizedCyclicReductionUtility), intent(inout) :: self
|
|
1289
|
+
integer(ip), intent(in) :: n
|
|
1290
|
+
integer(ip), intent(out) :: ierror
|
|
1291
|
+
real(wp), intent(in) :: a(:)
|
|
1292
|
+
real(wp), intent(in) :: c(:)
|
|
1293
|
+
complex(wp) :: cbp(:)
|
|
1294
|
+
real(wp) :: bp(:)
|
|
1295
|
+
real(wp) :: bh(:)
|
|
1296
|
+
|
|
1297
|
+
! Local variables
|
|
1298
|
+
integer(ip) :: iz, izm, izm2, j, nt, modiz
|
|
1299
|
+
integer(ip) :: iis, iif, ig, it, icv, i3, i2, nhalf
|
|
1300
|
+
real(wp) :: r4, r5, r6, scnv, xl, db, sgn, xr, xm, psg
|
|
1301
|
+
real(wp) :: temp
|
|
1302
|
+
complex(wp) :: cx, fsg, hsg, dd, f, fp, fpp, cdis, r1, r2, r3
|
|
1303
|
+
|
|
1304
|
+
common_variables: associate( &
|
|
1305
|
+
npp => self%npp, &
|
|
1306
|
+
k => self%k, &
|
|
1307
|
+
nm => self%nm, &
|
|
1308
|
+
ncmplx=> self%ncmplx, &
|
|
1309
|
+
ik => self%ik, &
|
|
1310
|
+
cnv => self%cnv &
|
|
1311
|
+
)
|
|
1312
|
+
|
|
1313
|
+
scnv = sqrt(cnv)
|
|
1314
|
+
iz = n
|
|
1315
|
+
izm = iz - 1
|
|
1316
|
+
izm2 = iz - 2
|
|
1317
|
+
|
|
1318
|
+
main_block: block
|
|
1319
|
+
|
|
1320
|
+
if (bp(n) <= bp(1)) then
|
|
1321
|
+
if (bp(n) == bp(1)) exit main_block
|
|
1322
|
+
bh(:n) = bp(n:1:(-1))
|
|
1323
|
+
else
|
|
1324
|
+
bh(:n) = bp(:n)
|
|
1325
|
+
end if
|
|
1326
|
+
|
|
1327
|
+
ncmplx = 0
|
|
1328
|
+
modiz = mod(iz, 2)
|
|
1329
|
+
iis = 1
|
|
1330
|
+
|
|
1331
|
+
block_110: block
|
|
1332
|
+
if (modiz /= 0) then
|
|
1333
|
+
if (a(1) < ZERO) exit block_110
|
|
1334
|
+
if (a(1) == ZERO) exit main_block
|
|
1335
|
+
end if
|
|
1336
|
+
xl = bh(1)
|
|
1337
|
+
db = bh(3) - bh(1)
|
|
1338
|
+
xl = xl - db
|
|
1339
|
+
r4 = psgf(xl, iz, c, a, bh)
|
|
1340
|
+
do while (r4 <= ZERO)
|
|
1341
|
+
xl = xl - db
|
|
1342
|
+
r4 = psgf(xl, iz, c, a, bh)
|
|
1343
|
+
end do
|
|
1344
|
+
sgn = -ONE
|
|
1345
|
+
temp = self%cblktri_bsrh(xl, bh(1), iz, c, a, bh, psgf, sgn)
|
|
1346
|
+
cbp(1) = cmplx(temp, ZERO, kind=wp)
|
|
1347
|
+
iis = 2
|
|
1348
|
+
end block block_110
|
|
1349
|
+
|
|
1350
|
+
iif = iz - 1
|
|
1351
|
+
|
|
1352
|
+
block_115: block
|
|
1353
|
+
if (modiz /= 0) then
|
|
1354
|
+
if (a(1) > ZERO) exit block_115
|
|
1355
|
+
if (a(1) == ZERO) exit main_block
|
|
1356
|
+
end if
|
|
1357
|
+
xr = bh(iz)
|
|
1358
|
+
db = bh(iz) - bh(iz-2)
|
|
1359
|
+
xr = xr + db
|
|
1360
|
+
r5 = psgf(xr, iz, c, a, bh)
|
|
1361
|
+
do while (r5 < ZERO)
|
|
1362
|
+
xr = xr + db
|
|
1363
|
+
r5 = psgf(xr, iz, c, a, bh)
|
|
1364
|
+
end do
|
|
1365
|
+
sgn = ONE
|
|
1366
|
+
temp = self%cblktri_bsrh(bh(iz), xr, iz, c, a, bh, psgf, sgn)
|
|
1367
|
+
cbp(iz) = cmplx(temp, ZERO, kind=wp)
|
|
1368
|
+
iif = iz - 2
|
|
1369
|
+
end block block_115
|
|
1370
|
+
|
|
1371
|
+
main_loop: do ig = iis, iif, 2
|
|
1372
|
+
xl = bh(ig)
|
|
1373
|
+
xr = bh(ig+1)
|
|
1374
|
+
sgn = -1.
|
|
1375
|
+
xm = self%cblktri_bsrh(xl, xr, iz, c, a, bh, ppspf, sgn)
|
|
1376
|
+
psg = psgf(xm, iz, c, a, bh)
|
|
1377
|
+
|
|
1378
|
+
if_block: block
|
|
1379
|
+
if (abs(psg) > MACHINE_EPSILON) then
|
|
1380
|
+
r6 = psg*ppsgf(xm, iz, c, a, bh)
|
|
1381
|
+
if (r6 > ZERO) exit if_block
|
|
1382
|
+
if (r6 /= ZERO) then
|
|
1383
|
+
sgn = ONE
|
|
1384
|
+
cbp(ig) = cmplx(self%cblktri_bsrh(bh(ig), xm, iz, c, a, bh, psgf, sgn), ZERO, kind=wp)
|
|
1385
|
+
sgn = -ONE
|
|
1386
|
+
cbp(ig+1) = cmplx(self%cblktri_bsrh(xm, bh(ig+1), iz, c, a, bh, psgf, sgn), ZERO, kind=wp)
|
|
1387
|
+
cycle main_loop
|
|
1388
|
+
|
|
1389
|
+
! case of a multiple zero
|
|
1390
|
+
end if
|
|
1391
|
+
end if
|
|
1392
|
+
cbp(ig) = cmplx(xm, ZERO, kind=wp)
|
|
1393
|
+
cbp(ig+1) = cmplx(xm, ZERO, kind=wp)
|
|
1394
|
+
cycle main_loop
|
|
1395
|
+
|
|
1396
|
+
! case of a complex zero
|
|
1397
|
+
end block if_block
|
|
1398
|
+
|
|
1399
|
+
it = 0
|
|
1400
|
+
icv = 0
|
|
1401
|
+
cx = cmplx(xm, ZERO, kind=wp)
|
|
1402
|
+
|
|
1403
|
+
loop_120: do
|
|
1404
|
+
fsg = cmplx(ONE, ZERO, kind=wp)
|
|
1405
|
+
hsg = cmplx(ONE, ZERO, kind=wp)
|
|
1406
|
+
fp = ZERO
|
|
1407
|
+
fpp = ZERO
|
|
1408
|
+
|
|
1409
|
+
do j = 1, iz
|
|
1410
|
+
dd = ONE /(cx - bh(j))
|
|
1411
|
+
fsg = fsg*a(j)*dd
|
|
1412
|
+
hsg = hsg*c(j)*dd
|
|
1413
|
+
fp = fp + dd
|
|
1414
|
+
fpp = fpp - dd*dd
|
|
1415
|
+
end do
|
|
1416
|
+
|
|
1417
|
+
if (modiz == 0) then
|
|
1418
|
+
f = cmplx(ONE, ZERO, kind=wp) - fsg - hsg
|
|
1419
|
+
else
|
|
1420
|
+
f = cmplx(ONE, ZERO, kind=wp) + fsg + hsg
|
|
1421
|
+
end if
|
|
1422
|
+
|
|
1423
|
+
i3 = 0
|
|
1424
|
+
|
|
1425
|
+
if (abs(fp) > ZERO) then
|
|
1426
|
+
i3 = 1
|
|
1427
|
+
r3 = -f/fp
|
|
1428
|
+
end if
|
|
1429
|
+
|
|
1430
|
+
i2 = 0
|
|
1431
|
+
|
|
1432
|
+
if (abs(fpp) > ZERO) then
|
|
1433
|
+
i2 = 1
|
|
1434
|
+
cdis = sqrt(fp**2 - TWO*f*fpp)
|
|
1435
|
+
r1 = cdis - fp
|
|
1436
|
+
r2 = (-fp) - cdis
|
|
1437
|
+
if (abs(r1) - abs(r2) > ZERO) then
|
|
1438
|
+
r1 = r1/fpp
|
|
1439
|
+
else
|
|
1440
|
+
r1 = r2/fpp
|
|
1441
|
+
end if
|
|
1442
|
+
r2 = TWO*f/fpp/r1
|
|
1443
|
+
if (abs(r2) < abs(r1)) r1 = r2
|
|
1444
|
+
if (i3 > 0) then
|
|
1445
|
+
if (abs(r3) < abs(r1)) r1 = r3
|
|
1446
|
+
end if
|
|
1447
|
+
else
|
|
1448
|
+
r1 = r3
|
|
1449
|
+
end if
|
|
1450
|
+
|
|
1451
|
+
cx = cx + r1
|
|
1452
|
+
it = it + 1
|
|
1453
|
+
if (it > 50) exit main_block
|
|
1454
|
+
if (abs(r1) > scnv) cycle loop_120
|
|
1455
|
+
if (icv > 0) exit loop_120
|
|
1456
|
+
icv = 1
|
|
1457
|
+
end do loop_120
|
|
1458
|
+
|
|
1459
|
+
cbp(ig) = cx
|
|
1460
|
+
cbp(ig+1) = conjg(cx)
|
|
1461
|
+
end do main_loop
|
|
1462
|
+
|
|
1463
|
+
if (abs(cbp(n)) - abs(cbp(1)) <= ZERO) then
|
|
1464
|
+
if (abs(cbp(n)) - abs(cbp(1)) == ZERO) exit main_block
|
|
1465
|
+
nhalf = n/2
|
|
1466
|
+
do j = 1, nhalf
|
|
1467
|
+
nt = n - j
|
|
1468
|
+
cx = cbp(j)
|
|
1469
|
+
cbp(j) = cbp(nt+1)
|
|
1470
|
+
cbp(nt+1) = cx
|
|
1471
|
+
end do
|
|
1472
|
+
end if
|
|
1473
|
+
|
|
1474
|
+
ncmplx = 1
|
|
1475
|
+
|
|
1476
|
+
do j = 2, iz
|
|
1477
|
+
if (aimag(cbp(j)) /= ZERO) return
|
|
1478
|
+
end do
|
|
1479
|
+
|
|
1480
|
+
ncmplx = 0
|
|
1481
|
+
|
|
1482
|
+
do j = 2, iz
|
|
1483
|
+
bp(j) = real(cbp(j), kind=wp)
|
|
1484
|
+
end do
|
|
1485
|
+
|
|
1486
|
+
return
|
|
1487
|
+
end block main_block
|
|
1488
|
+
!
|
|
1489
|
+
! Procedure failed
|
|
1490
|
+
!
|
|
1491
|
+
ierror = 4
|
|
1492
|
+
|
|
1493
|
+
end associate common_variables
|
|
1494
|
+
|
|
1495
|
+
end subroutine cblktri_compute_eigenvalues
|
|
1496
|
+
|
|
1497
|
+
! Purpose:
|
|
1498
|
+
!
|
|
1499
|
+
! proc applies a sequence of matrix operations to the vector x and
|
|
1500
|
+
! stores the result in y
|
|
1501
|
+
! bd, bm1, bm2 are arrays containing roots of certian b polynomials
|
|
1502
|
+
! nd, nm1, nm2 are the lengths of the arrays bd, bm1, bm2 respectively
|
|
1503
|
+
! aa array containing scalar multipliers of the vector x
|
|
1504
|
+
! na is the length of the array aa
|
|
1505
|
+
! x, y the matrix operations are applied to x and the result is y
|
|
1506
|
+
! a, b, c are arrays which contain the tridiagonal matrix
|
|
1507
|
+
! m is the order of the matrix
|
|
1508
|
+
! d, w, u are working arrays
|
|
1509
|
+
! is determines whether or not a change in sign is made
|
|
1510
|
+
!
|
|
1511
|
+
pure subroutine proc(nd, bd, nm1, bm1, nm2, bm2, na, aa, x, y, m, a, b, c, d, w, u)
|
|
1512
|
+
|
|
1513
|
+
! Dummy arguments
|
|
1514
|
+
integer(ip), intent(in) :: nd
|
|
1515
|
+
integer(ip), intent(in) :: nm1
|
|
1516
|
+
integer(ip), intent(in) :: nm2
|
|
1517
|
+
integer(ip), intent(in) :: na
|
|
1518
|
+
integer(ip), intent(in) :: m
|
|
1519
|
+
real(wp), intent(in) :: bd(nd)
|
|
1520
|
+
real(wp), intent(in) :: bm1(nm1)
|
|
1521
|
+
real(wp), intent(in) :: bm2(nm2)
|
|
1522
|
+
real(wp), intent(in) :: aa(na)
|
|
1523
|
+
complex(wp), intent(in) :: x(m)
|
|
1524
|
+
complex(wp), intent(out) :: y(m)
|
|
1525
|
+
complex(wp), intent(in) :: a(m)
|
|
1526
|
+
complex(wp), intent(in) :: b(m)
|
|
1527
|
+
complex(wp), intent(in) :: c(m)
|
|
1528
|
+
complex(wp), intent(out) :: d(m)
|
|
1529
|
+
complex(wp), intent(out) :: w(m)
|
|
1530
|
+
complex(wp), intent(out) :: u(m)
|
|
1531
|
+
|
|
1532
|
+
! Local variables
|
|
1533
|
+
integer(ip) :: j, mm, id, ibr, m1, m2, ia, k
|
|
1534
|
+
real(wp) :: rt
|
|
1535
|
+
complex(wp) :: den
|
|
1536
|
+
|
|
1537
|
+
w = x
|
|
1538
|
+
y = w
|
|
1539
|
+
mm = m - 1
|
|
1540
|
+
id = nd
|
|
1541
|
+
ibr = 0
|
|
1542
|
+
m1 = nm1
|
|
1543
|
+
m2 = nm2
|
|
1544
|
+
ia = na
|
|
1545
|
+
|
|
1546
|
+
main_loop: do
|
|
1547
|
+
if (ia > 0) then
|
|
1548
|
+
if (nd == 0) then
|
|
1549
|
+
rt = -aa(ia)
|
|
1550
|
+
else
|
|
1551
|
+
rt = aa(ia)
|
|
1552
|
+
end if
|
|
1553
|
+
ia = ia - 1
|
|
1554
|
+
|
|
1555
|
+
! scalar multiplication
|
|
1556
|
+
y = rt*w
|
|
1557
|
+
end if
|
|
1558
|
+
|
|
1559
|
+
if (id <= 0) return
|
|
1560
|
+
|
|
1561
|
+
rt = bd(id)
|
|
1562
|
+
id = id - 1
|
|
1563
|
+
|
|
1564
|
+
if (id == 0) ibr = 1
|
|
1565
|
+
|
|
1566
|
+
! begin solution to system
|
|
1567
|
+
d(m) = a(m)/(b(m)-rt)
|
|
1568
|
+
w(m) = y(m)/(b(m)-rt)
|
|
1569
|
+
|
|
1570
|
+
do j = 2, mm
|
|
1571
|
+
k = m - j
|
|
1572
|
+
den = b(k+1) - rt - c(k+1)*d(k+2)
|
|
1573
|
+
d(k+1) = a(k+1)/den
|
|
1574
|
+
w(k+1) = (y(k+1)-c(k+1)*w(k+2))/den
|
|
1575
|
+
end do
|
|
1576
|
+
|
|
1577
|
+
den = b(1) - rt - c(1)*d(2)
|
|
1578
|
+
w(1) = cmplx(ONE, ZERO, kind=wp)
|
|
1579
|
+
|
|
1580
|
+
if (abs(den) /= ZERO) then
|
|
1581
|
+
w(1) = (y(1)-c(1)*w(2))/den
|
|
1582
|
+
end if
|
|
1583
|
+
|
|
1584
|
+
do j = 2, m
|
|
1585
|
+
w(j) = w(j) - d(j)*w(j-1)
|
|
1586
|
+
end do
|
|
1587
|
+
|
|
1588
|
+
if (na > 0) cycle main_loop
|
|
1589
|
+
|
|
1590
|
+
if (m1 <= 0) then
|
|
1591
|
+
if (m2 <= 0) then
|
|
1592
|
+
y = w
|
|
1593
|
+
ibr = 1
|
|
1594
|
+
cycle main_loop
|
|
1595
|
+
end if
|
|
1596
|
+
else
|
|
1597
|
+
if (.not.(m2 > 0 .and. abs(bm1(m1)) <= abs(bm2(m2)))) then
|
|
1598
|
+
if (ibr <= 0 .and. abs(bm1(m1)-bd(id)) < abs(bm1(m1)-rt)) then
|
|
1599
|
+
y = w
|
|
1600
|
+
ibr = 1
|
|
1601
|
+
cycle main_loop
|
|
1602
|
+
end if
|
|
1603
|
+
end if
|
|
1604
|
+
rt = rt - bm1(m1)
|
|
1605
|
+
m1 = m1 - 1
|
|
1606
|
+
y = y + rt*w
|
|
1607
|
+
cycle main_loop
|
|
1608
|
+
end if
|
|
1609
|
+
|
|
1610
|
+
if (ibr <= 0 .and. abs(bm2(m2)-bd(id)) < abs(bm2(m2)-rt)) then
|
|
1611
|
+
y = w
|
|
1612
|
+
ibr = 1
|
|
1613
|
+
cycle main_loop
|
|
1614
|
+
end if
|
|
1615
|
+
|
|
1616
|
+
rt = rt - bm2(m2)
|
|
1617
|
+
m2 = m2 - 1
|
|
1618
|
+
y = y + rt*w
|
|
1619
|
+
|
|
1620
|
+
end do main_loop
|
|
1621
|
+
|
|
1622
|
+
end subroutine proc
|
|
1623
|
+
|
|
1624
|
+
! Purpose:
|
|
1625
|
+
!
|
|
1626
|
+
! procp applies a sequence of matrix operations to the vector x and
|
|
1627
|
+
! stores the result in y periodic boundary conditions
|
|
1628
|
+
!
|
|
1629
|
+
! bd, bm1, bm2 are arrays containing roots of certian b polynomials
|
|
1630
|
+
! nd, nm1, nm2 are the lengths of the arrays bd, bm1, bm2 respectively
|
|
1631
|
+
! aa array containing scalar multipliers of the vector x
|
|
1632
|
+
! na is the length of the array aa
|
|
1633
|
+
! x, y the matrix operations are applied to x and the result is y
|
|
1634
|
+
! a, b, c are arrays which contain the tridiagonal matrix
|
|
1635
|
+
! m is the order of the matrix
|
|
1636
|
+
! d, u, w are working arrays
|
|
1637
|
+
! is determines whether or not a change in sign is made
|
|
1638
|
+
!
|
|
1639
|
+
pure subroutine procp(nd, bd, nm1, bm1, nm2, bm2, na, aa, x, y, m, a, b, c, d, u, w)
|
|
1640
|
+
|
|
1641
|
+
! Dummy arguments
|
|
1642
|
+
integer(ip), intent(in) :: nd
|
|
1643
|
+
integer(ip), intent(in) :: nm1
|
|
1644
|
+
integer(ip), intent(in) :: nm2
|
|
1645
|
+
integer(ip), intent(in) :: na
|
|
1646
|
+
integer(ip), intent(in) :: m
|
|
1647
|
+
real(wp), intent(in) :: bd(nd)
|
|
1648
|
+
real(wp), intent(in) :: bm1(nm1)
|
|
1649
|
+
real(wp), intent(in) :: bm2(nm2)
|
|
1650
|
+
real(wp), intent(in) :: aa(na)
|
|
1651
|
+
complex(wp), intent(in) :: x(m)
|
|
1652
|
+
complex(wp), intent(out) :: y(m)
|
|
1653
|
+
complex(wp), intent(in) :: a(m)
|
|
1654
|
+
complex(wp), intent(in) :: b(m)
|
|
1655
|
+
complex(wp), intent(in) :: c(m)
|
|
1656
|
+
complex(wp), intent(out) :: d(m)
|
|
1657
|
+
complex(wp), intent(out) :: u(m)
|
|
1658
|
+
complex(wp), intent(out) :: w(m)
|
|
1659
|
+
|
|
1660
|
+
! Local variables
|
|
1661
|
+
integer(ip) :: j, mm, mm2, id, ibr, m1, m2, ia, k
|
|
1662
|
+
real(wp) :: rt
|
|
1663
|
+
complex(wp) :: den, ym, v, bh, am
|
|
1664
|
+
|
|
1665
|
+
y = x
|
|
1666
|
+
w = y
|
|
1667
|
+
mm = m - 1
|
|
1668
|
+
mm2 = m - 2
|
|
1669
|
+
id = nd
|
|
1670
|
+
ibr = 0
|
|
1671
|
+
m1 = nm1
|
|
1672
|
+
m2 = nm2
|
|
1673
|
+
ia = na
|
|
1674
|
+
|
|
1675
|
+
main_loop: do
|
|
1676
|
+
|
|
1677
|
+
if (ia > 0) then
|
|
1678
|
+
if (nd == 0) then
|
|
1679
|
+
rt = -aa(ia)
|
|
1680
|
+
else
|
|
1681
|
+
rt = aa(ia)
|
|
1682
|
+
end if
|
|
1683
|
+
ia = ia - 1
|
|
1684
|
+
y = rt*w
|
|
1685
|
+
end if
|
|
1686
|
+
|
|
1687
|
+
if (id <= 0) return
|
|
1688
|
+
|
|
1689
|
+
rt = bd(id)
|
|
1690
|
+
id = id - 1
|
|
1691
|
+
|
|
1692
|
+
if (id == 0) ibr = 1
|
|
1693
|
+
|
|
1694
|
+
! begin solution to system
|
|
1695
|
+
bh = b(m) - rt
|
|
1696
|
+
ym = y(m)
|
|
1697
|
+
den = b(1) - rt
|
|
1698
|
+
d(1) = c(1)/den
|
|
1699
|
+
u(1) = a(1)/den
|
|
1700
|
+
w(1) = y(1)/den
|
|
1701
|
+
v = c(m)
|
|
1702
|
+
|
|
1703
|
+
if (mm2 >= 2) then
|
|
1704
|
+
do j = 2, mm2
|
|
1705
|
+
den = b(j) - rt - a(j)*d(j-1)
|
|
1706
|
+
d(j) = c(j)/den
|
|
1707
|
+
u(j) = -a(j)*u(j-1)/den
|
|
1708
|
+
w(j) = (y(j)-a(j)*w(j-1))/den
|
|
1709
|
+
bh = bh - v*u(j-1)
|
|
1710
|
+
ym = ym - v*w(j-1)
|
|
1711
|
+
v = -v*d(j-1)
|
|
1712
|
+
end do
|
|
1713
|
+
end if
|
|
1714
|
+
|
|
1715
|
+
den = b(m-1) - rt - a(m-1)*d(m-2)
|
|
1716
|
+
d(m-1) = (c(m-1)-a(m-1)*u(m-2))/den
|
|
1717
|
+
w(m-1) = (y(m-1)-a(m-1)*w(m-2))/den
|
|
1718
|
+
am = a(m) - v*d(m-2)
|
|
1719
|
+
bh = bh - v*u(m-2)
|
|
1720
|
+
ym = ym - v*w(m-2)
|
|
1721
|
+
den = bh - am*d(m-1)
|
|
1722
|
+
|
|
1723
|
+
if (abs(den) /= ZERO) then
|
|
1724
|
+
w(m) = (ym - am*w(m-1))/den
|
|
1725
|
+
else
|
|
1726
|
+
w(m) = cmplx(ONE, ZERO, kind=wp)
|
|
1727
|
+
end if
|
|
1728
|
+
|
|
1729
|
+
w(m-1) = w(m-1) - d(m-1)*w(m)
|
|
1730
|
+
|
|
1731
|
+
do j = 2, mm
|
|
1732
|
+
k = m - j
|
|
1733
|
+
w(k) = w(k) - d(k)*w(k+1) - u(k)*w(m)
|
|
1734
|
+
end do
|
|
1735
|
+
|
|
1736
|
+
if (na > 0) cycle main_loop
|
|
1737
|
+
|
|
1738
|
+
if (m1 <= 0) then
|
|
1739
|
+
if (m2 <= 0) then
|
|
1740
|
+
y = w
|
|
1741
|
+
ibr = 1
|
|
1742
|
+
cycle main_loop
|
|
1743
|
+
end if
|
|
1744
|
+
else
|
|
1745
|
+
if (.not.(m2 > 0 .and. abs(bm1(m1)) <= abs(bm2(m2)))) then
|
|
1746
|
+
if (ibr <= 0 .and. abs(bm1(m1)-bd(id)) < abs(bm1(m1)-rt)) then
|
|
1747
|
+
y = w
|
|
1748
|
+
ibr = 1
|
|
1749
|
+
cycle main_loop
|
|
1750
|
+
end if
|
|
1751
|
+
rt = rt - bm1(m1)
|
|
1752
|
+
m1 = m1 - 1
|
|
1753
|
+
y = y + rt*w
|
|
1754
|
+
cycle main_loop
|
|
1755
|
+
end if
|
|
1756
|
+
end if
|
|
1757
|
+
|
|
1758
|
+
if (ibr <= 0 .and. abs(bm2(m2)-bd(id)) < abs(bm2(m2)-rt)) then
|
|
1759
|
+
y = w
|
|
1760
|
+
ibr = 1
|
|
1761
|
+
cycle main_loop
|
|
1762
|
+
end if
|
|
1763
|
+
|
|
1764
|
+
rt = rt - bm2(m2)
|
|
1765
|
+
m2 = m2 - 1
|
|
1766
|
+
y = y + rt*w
|
|
1767
|
+
|
|
1768
|
+
end do main_loop
|
|
1769
|
+
|
|
1770
|
+
end subroutine procp
|
|
1771
|
+
|
|
1772
|
+
! Purpose:
|
|
1773
|
+
!
|
|
1774
|
+
! Finds the eigenvalues of a symmetric
|
|
1775
|
+
! tridiagonal matrix by the rational ql method.
|
|
1776
|
+
! This subroutine is a modification of the eispack subroutine tqlrat
|
|
1777
|
+
! algorithm 464, comm. acm 16, 689(1973) by reinsch.
|
|
1778
|
+
!
|
|
1779
|
+
! on input-
|
|
1780
|
+
!
|
|
1781
|
+
! n is the order of the matrix,
|
|
1782
|
+
!
|
|
1783
|
+
! d contains the diagonal elements of the input matrix,
|
|
1784
|
+
!
|
|
1785
|
+
! e2 contains the subdiagonal elements of the
|
|
1786
|
+
! input matrix in its last n-1 positions. e2(1) is arbitrary.
|
|
1787
|
+
!
|
|
1788
|
+
! on output-
|
|
1789
|
+
!
|
|
1790
|
+
! d contains the eigenvalues in ascending order. if an
|
|
1791
|
+
! error exit is made, the eigenvalues are correct and
|
|
1792
|
+
! ordered for indices 1, 2, ...ierr-1, but may not be
|
|
1793
|
+
! the smallest eigenvalues,
|
|
1794
|
+
!
|
|
1795
|
+
! e2 has been destroyed,
|
|
1796
|
+
!
|
|
1797
|
+
! ierr is set to
|
|
1798
|
+
! zero for normal return,
|
|
1799
|
+
! j if the j-th eigenvalue has not been
|
|
1800
|
+
! determined after 30 iterations.
|
|
1801
|
+
!
|
|
1802
|
+
! questions and comments should be directed to b. s. garbow,
|
|
1803
|
+
! applied mathematics division, argonne national laboratory
|
|
1804
|
+
!
|
|
1805
|
+
!
|
|
1806
|
+
! eps is a machine dependent parameter specifying
|
|
1807
|
+
! the relative precision of floating point arithmetic.
|
|
1808
|
+
!
|
|
1809
|
+
!
|
|
1810
|
+
subroutine cblktri_tevls(self, diagonal, subdiagonal, error_flag)
|
|
1811
|
+
|
|
1812
|
+
! Dummy arguments
|
|
1813
|
+
class(ComplexGeneralizedCyclicReductionUtility), intent(inout) :: self
|
|
1814
|
+
real(wp), intent(inout) :: diagonal(:)
|
|
1815
|
+
real(wp), intent(inout) :: subdiagonal(:)
|
|
1816
|
+
integer(ip), intent(out) :: error_flag
|
|
1817
|
+
|
|
1818
|
+
! Local variables
|
|
1819
|
+
integer(ip) :: i, j, l, m, ii, l1, mml, nhalf, ntop
|
|
1820
|
+
real(wp) :: b, c, f, g, h, p, r, s, dhold
|
|
1821
|
+
|
|
1822
|
+
associate( &
|
|
1823
|
+
n => size(diagonal), &
|
|
1824
|
+
d => diagonal, &
|
|
1825
|
+
e2 => subdiagonal &
|
|
1826
|
+
)
|
|
1827
|
+
|
|
1828
|
+
error_flag = 0
|
|
1829
|
+
if (n /= 1) then
|
|
1830
|
+
|
|
1831
|
+
e2(:n-1) = e2(2:n)*e2(2:n)
|
|
1832
|
+
f = ZERO
|
|
1833
|
+
b = ZERO
|
|
1834
|
+
e2(n) = ZERO
|
|
1835
|
+
|
|
1836
|
+
main_loop: do l = 1, n
|
|
1837
|
+
j = 0
|
|
1838
|
+
h = MACHINE_EPSILON*(abs(d(l))+sqrt(e2(l)))
|
|
1839
|
+
|
|
1840
|
+
if (b <= h) then
|
|
1841
|
+
b = h
|
|
1842
|
+
c = b*b
|
|
1843
|
+
end if
|
|
1844
|
+
|
|
1845
|
+
! look for small squared sub-diagonal element
|
|
1846
|
+
do m = l, n
|
|
1847
|
+
if (e2(m) > c) cycle
|
|
1848
|
+
exit
|
|
1849
|
+
|
|
1850
|
+
! 2(n) is always zero, so there is no exit
|
|
1851
|
+
! through the bottom of the loop
|
|
1852
|
+
end do
|
|
1853
|
+
|
|
1854
|
+
if_block: block
|
|
1855
|
+
if (m /= l) then
|
|
1856
|
+
loop_105: do
|
|
1857
|
+
if (j == 30) then
|
|
1858
|
+
|
|
1859
|
+
! set error no convergence to an
|
|
1860
|
+
! eigenvalue after 30 iterations
|
|
1861
|
+
error_flag = l
|
|
1862
|
+
return
|
|
1863
|
+
end if
|
|
1864
|
+
|
|
1865
|
+
j = j + 1
|
|
1866
|
+
|
|
1867
|
+
! form shift
|
|
1868
|
+
l1 = l + 1
|
|
1869
|
+
s = sqrt(e2(l))
|
|
1870
|
+
g = d(l)
|
|
1871
|
+
p = (d(l1)-g)/(TWO*s)
|
|
1872
|
+
r = sqrt(p**2 + ONE)
|
|
1873
|
+
d(l) = s/(p + sign(r, p))
|
|
1874
|
+
h = g - d(l)
|
|
1875
|
+
d(l1:n) = d(l1:n) - h
|
|
1876
|
+
f = f + h
|
|
1877
|
+
|
|
1878
|
+
! rational ql transformation
|
|
1879
|
+
g = d(m)
|
|
1880
|
+
|
|
1881
|
+
if (g == ZERO) g = b
|
|
1882
|
+
|
|
1883
|
+
h = g
|
|
1884
|
+
s = ZERO
|
|
1885
|
+
mml = m - l
|
|
1886
|
+
|
|
1887
|
+
! for i=m-1 step -1 until l do
|
|
1888
|
+
do ii = 1, mml
|
|
1889
|
+
i = m - ii
|
|
1890
|
+
p = g*h
|
|
1891
|
+
r = p + e2(i)
|
|
1892
|
+
e2(i+1) = s*r
|
|
1893
|
+
s = e2(i)/r
|
|
1894
|
+
d(i+1) = h + s*(h + d(i))
|
|
1895
|
+
g = d(i) - e2(i)/g
|
|
1896
|
+
if (g == ZERO) g = b
|
|
1897
|
+
h = g*p/r
|
|
1898
|
+
end do
|
|
1899
|
+
|
|
1900
|
+
e2(l) = s*g
|
|
1901
|
+
d(l) = h
|
|
1902
|
+
|
|
1903
|
+
! guard against underflowed h
|
|
1904
|
+
if (h == ZERO .or. abs(e2(l)) <= abs(c/h)) exit if_block
|
|
1905
|
+
|
|
1906
|
+
e2(l) = h*e2(l)
|
|
1907
|
+
|
|
1908
|
+
if (e2(l) == ZERO) exit loop_105
|
|
1909
|
+
end do loop_105
|
|
1910
|
+
end if
|
|
1911
|
+
end block if_block
|
|
1912
|
+
|
|
1913
|
+
p = d(l) + f
|
|
1914
|
+
|
|
1915
|
+
! order eigenvalues
|
|
1916
|
+
if (l /= 1) then
|
|
1917
|
+
|
|
1918
|
+
! for i=l step -1 until 2 do
|
|
1919
|
+
do ii = 2, l
|
|
1920
|
+
i = l + 2 - ii
|
|
1921
|
+
if (p >= d(i-1)) then
|
|
1922
|
+
d(i) = p
|
|
1923
|
+
cycle main_loop
|
|
1924
|
+
end if
|
|
1925
|
+
d(i) = d(i-1)
|
|
1926
|
+
end do
|
|
1927
|
+
end if
|
|
1928
|
+
i = 1
|
|
1929
|
+
d(i) = p
|
|
1930
|
+
end do main_loop
|
|
1931
|
+
|
|
1932
|
+
if (abs(d(n)) >= abs(d(1))) return
|
|
1933
|
+
|
|
1934
|
+
nhalf = n/2
|
|
1935
|
+
|
|
1936
|
+
do i = 1, nhalf
|
|
1937
|
+
ntop = n - i
|
|
1938
|
+
dhold = d(i)
|
|
1939
|
+
d(i) = d(ntop+1)
|
|
1940
|
+
d(ntop+1) = dhold
|
|
1941
|
+
end do
|
|
1942
|
+
end if
|
|
1943
|
+
end associate
|
|
1944
|
+
|
|
1945
|
+
end subroutine cblktri_tevls
|
|
1946
|
+
|
|
1947
|
+
end module complex_block_tridiagonal_linear_systems_solver
|