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