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