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,1002 @@
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
+
35
+ submodule(centered_helmholtz_solvers) centered_axisymmetric_spherical_solver
36
+
37
+ ! Parameters confined to the submodule
38
+ integer(ip), parameter :: SIZE_OF_WORKSPACE_INDICES = 10
39
+
40
+ contains
41
+
42
+ ! SUBROUTINE hwscsp(intl, ts, tf, m, mbdcnd, bdts, bdtf, rs, rf, n, nbdcnd, &
43
+ ! bdrs, bdrf, elmbda, f, idimf, pertrb, ierror, w)
44
+ !
45
+ !
46
+ ! DIMENSION OF bdts(n+1), bdtf(n+1), bdrs(m+1), bdrf(m+1),
47
+ ! ARGUMENTS f(idimf, n+1)
48
+ !
49
+ !
50
+ ! PURPOSE Solves a finite difference approximation
51
+ ! to the modified helmholtz equation in
52
+ ! spherical coordinates assuming axisymmetry
53
+ ! (no dependence on longitude). the equation
54
+ ! is
55
+ !
56
+ ! (1/r**2)(d/dr)((r**2)(d/dr)u) +
57
+ !
58
+ ! (1/(r**2)sin(theta))(d/dtheta)
59
+ !
60
+ ! (sin(theta)(d/dtheta)u) +
61
+ !
62
+ ! (lambda/(rsin(theta))**2)u = f(theta, r).
63
+ !
64
+ ! this two dimensional modified helmholtz
65
+ ! equation results from the fourier transform
66
+ ! of the three dimensional poisson equation.
67
+ !
68
+ ! USAGE call hwscsp(intl, ts, tf, m, mbdcnd, bdts, bdtf,
69
+ ! rs, rf, n, nbdcnd, bdrs, bdrf, elmbda,
70
+ ! f, idimf, pertrb, ierror, w)
71
+ !
72
+ ! ARGUMENTS
73
+ ! ON INPUT intl
74
+ ! = 0 on initial entry to hwscsp or if any
75
+ ! of the arguments rs, rf, n, nbdcnd
76
+ ! are changed from a previous call.
77
+ ! = 1 if rs, rf, n, nbdcnd are all unchanged
78
+ ! from previous call to hwscsp.
79
+ !
80
+ ! note:
81
+ ! a call with intl=0 takes approximately
82
+ ! 1.5 times as much time as a call with
83
+ ! intl = 1 . once a call with intl = 0
84
+ ! has been made then subsequent solutions
85
+ ! corresponding to different f, bdts, bdtf,
86
+ ! bdrs, bdrf can be obtained faster with
87
+ ! intl = 1 since initialization is not
88
+ ! repeated.
89
+ !
90
+ ! ts, tf
91
+ ! the range of theta (colatitude), i.e.,
92
+ ! ts <= theta <= tf. ts must be less
93
+ ! than tf. ts and tf are in radians. a ts of
94
+ ! zero corresponds to the north pole and a
95
+ ! tf of pi corresponds to the south pole.
96
+ !
97
+ ! **** important ****
98
+ !
99
+ ! if tf is equal to pi then it must be
100
+ ! computed using the statement
101
+ ! tf = pi_mach(dum). this insures that tf
102
+ ! in the user's program is equal to pi in
103
+ ! this program which permits several tests
104
+ ! of the input parameters that otherwise
105
+ ! would not be possible.
106
+ !
107
+ ! m
108
+ ! the number of panels into which the
109
+ ! interval (ts, tf) is subdivided.
110
+ ! hence, there will be m+1 grid points
111
+ ! in the theta-direction given by
112
+ ! theta(k) = (i-1)dtheta+ts for
113
+ ! i = 1, 2, ..., m+1, where dtheta = (tf-ts)/m
114
+ ! is the panel width.
115
+ !
116
+ ! mbdcnd
117
+ ! indicates the type of boundary condition
118
+ ! at theta = ts and theta = tf.
119
+ !
120
+ ! = 1 if the solution is specified at
121
+ ! theta = ts and theta = tf.
122
+ ! = 2 if the solution is specified at
123
+ ! theta = ts and the derivative of the
124
+ ! solution with respect to theta is
125
+ ! specified at theta = tf
126
+ ! (see note 2 below).
127
+ ! = 3 if the derivative of the solution
128
+ ! with respect to theta is specified
129
+ ! at theta = ts and theta = tf
130
+ ! (see notes 1, 2 below).
131
+ ! = 4 if the derivative of the solution
132
+ ! with respect to theta is specified
133
+ ! at theta = ts (see note 1 below) and
134
+ ! solution is specified at theta = tf.
135
+ ! = 5 if the solution is unspecified at
136
+ ! theta = ts = 0 and the solution is
137
+ ! specified at theta = tf.
138
+ ! = 6 if the solution is unspecified at
139
+ ! theta = ts = 0 and the derivative
140
+ ! of the solution with respect to theta
141
+ ! is specified at theta = tf
142
+ ! (see note 2 below).
143
+ ! = 7 if the solution is specified at
144
+ ! theta = ts and the solution is
145
+ ! unspecified at theta = tf = pi.
146
+ ! = 8 if the derivative of the solution
147
+ ! with respect to theta is specified
148
+ ! at theta = ts (see note 1 below)
149
+ ! and the solution is unspecified at
150
+ ! theta = tf = pi.
151
+ ! = 9 if the solution is unspecified at
152
+ ! theta = ts = 0 and theta = tf = pi.
153
+ !
154
+ ! note 1:
155
+ ! if ts = 0, do not use mbdcnd = 3, 4, or 8,
156
+ ! but instead use mbdcnd = 5, 6, or 9 .
157
+ !
158
+ ! note 2:
159
+ ! if tf = pi, do not use mbdcnd = 2, 3, or 6,
160
+ ! but instead use mbdcnd = 7, 8, or 9 .
161
+ !
162
+ ! bdts
163
+ ! a one-dimensional array of length n+1 that
164
+ ! specifies the values of the derivative of
165
+ ! the solution with respect to theta at
166
+ ! theta = ts. when mbdcnd = 3, 4, or 8,
167
+ !
168
+ ! bdts(j) = (d/dtheta)u(ts, r(j)),
169
+ ! j = 1, 2, ..., n+1 .
170
+ !
171
+ ! when mbdcnd has any other value, bdts is
172
+ ! a dummy variable.
173
+ !
174
+ ! bdtf
175
+ ! a one-dimensional array of length n+1 that
176
+ ! specifies the values of the derivative of
177
+ ! the solution with respect to theta at
178
+ ! theta = tf. when mbdcnd = 2, 3, or 6,
179
+ !
180
+ ! bdtf(j) = (d/dtheta)u(tf, r(j)),
181
+ ! j = 1, 2, ..., n+1 .
182
+ !
183
+ ! when mbdcnd has any other value, bdtf is
184
+ ! a dummy variable.
185
+ !
186
+ ! rs, rf
187
+ ! the range of r, i.e., rs <= r < rf.
188
+ ! rs must be less than rf. rs must be
189
+ ! non-negative.
190
+ !
191
+ ! n
192
+ ! the number of panels into which the
193
+ ! interval (rs, rf) is subdivided.
194
+ ! hence, there will be n+1 grid points in the
195
+ ! r-direction given by r(j) = (j-1)dr+rs
196
+ ! for j = 1, 2, ..., n+1, where dr = (rf-rs)/n
197
+ ! is the panel width.
198
+ ! n must be greater than 2
199
+ !
200
+ ! nbdcnd
201
+ ! indicates the type of boundary condition
202
+ ! at r = rs and r = rf.
203
+ !
204
+ ! = 1 if the solution is specified at
205
+ ! r = rs and r = rf.
206
+ ! = 2 if the solution is specified at
207
+ ! r = rs and the derivative
208
+ ! of the solution with respect to r
209
+ ! is specified at r = rf.
210
+ ! = 3 if the derivative of the solution
211
+ ! with respect to r is specified at
212
+ ! r = rs and r = rf.
213
+ ! = 4 if the derivative of the solution
214
+ ! with respect to r is specified at
215
+ ! rs and the solution is specified at
216
+ ! r = rf.
217
+ ! = 5 if the solution is unspecified at
218
+ ! r = rs = 0 (see note below) and the
219
+ ! solution is specified at r = rf.
220
+ ! = 6 if the solution is unspecified at
221
+ ! r = rs = 0 (see note below) and the
222
+ ! derivative of the solution with
223
+ ! respect to r is specified at r = rf.
224
+ !
225
+ ! note:
226
+ ! nbdcnd = 5 or 6 cannot be used with
227
+ ! mbdcnd = 1, 2, 4, 5, or 7. the former
228
+ ! indicates that the solution is unspecified
229
+ ! at r = 0, the latter indicates that the
230
+ ! solution is specified).
231
+ ! use instead nbdcnd = 1 or 2 .
232
+ !
233
+ ! bdrs
234
+ ! a one-dimensional array of length m+1 that
235
+ ! specifies the values of the derivative of
236
+ ! the solution with respect to r at r = rs.
237
+ !
238
+ ! when nbdcnd = 3 or 4,
239
+ ! bdrs(i) = (d/dr)u(theta(i), rs),
240
+ ! i = 1, 2, ..., m+1 .
241
+ !
242
+ ! when nbdcnd has any other value, bdrs is
243
+ ! a dummy variable.
244
+ !
245
+ ! bdrf
246
+ ! a one-dimensional array of length m+1
247
+ ! that specifies the values of the
248
+ ! derivative of the solution with respect
249
+ ! to r at r = rf.
250
+ !
251
+ ! when nbdcnd = 2, 3, or 6,
252
+ ! bdrf(i) = (d/dr)u(theta(i), rf),
253
+ ! i = 1, 2, ..., m+1 .
254
+ !
255
+ ! when nbdcnd has any other value, bdrf is
256
+ ! a dummy variable.
257
+ !
258
+ ! elmbda
259
+ ! the constant lambda in the helmholtz
260
+ ! equation. if lambda > 0, a solution
261
+ ! may not exist. however, hwscsp will
262
+ ! attempt to find a solution. if nbdcnd = 5
263
+ ! or 6 or mbdcnd = 5, 6, 7, 8, or 9, elmbda
264
+ ! must be zero.
265
+ !
266
+ ! f
267
+ ! a two-dimensional array, of dimension at
268
+ ! least (m+1)*(n+1), specifying values of the
269
+ ! right side of the helmholtz equation and
270
+ ! boundary values (if any).
271
+ !
272
+ ! on the interior, f is defined as follows:
273
+ ! for i = 2, 3, ..., m and j = 2, 3, ..., n
274
+ ! f(i, j) = f(theta(i), r(j)).
275
+ !
276
+ ! on the boundaries, f is defined as follows:
277
+ ! for j=1, 2, ..., n+1, i=1, 2, ..., m+1,
278
+ !
279
+ ! mbdcnd f(1, j) f(m+1, j)
280
+ ! ------ ---------- ----------
281
+ !
282
+ ! 1 u(ts, r(j)) u(tf, r(j))
283
+ ! 2 u(ts, r(j)) f(tf, r(j))
284
+ ! 3 f(ts, r(j)) f(tf, r(j))
285
+ ! 4 f(ts, r(j)) u(tf, r(j))
286
+ ! 5 f(0, r(j)) u(tf, r(j))
287
+ ! 6 f(0, r(j)) f(tf, r(j))
288
+ ! 7 u(ts, r(j)) f(pi, r(j))
289
+ ! 8 f(ts, r(j)) f(pi, r(j))
290
+ ! 9 f(0, r(j)) f(pi, r(j))
291
+ !
292
+ ! nbdcnd f(i, 1) f(i, n+1)
293
+ ! ------ -------------- --------------
294
+ !
295
+ ! 1 u(theta(i), rs) u(theta(i), rf)
296
+ ! 2 u(theta(i), rs) f(theta(i), rf)
297
+ ! 3 f(theta(i), rs) f(theta(i), rf)
298
+ ! 4 f(theta(i), rs) u(theta(i), rf)
299
+ ! 5 f(ts, 0) u(theta(i), rf)
300
+ ! 6 f(ts, 0) f(theta(i), rf)
301
+ !
302
+ ! note:
303
+ ! if the table calls for both the solution
304
+ ! u and the right side f at a corner then
305
+ ! the solution must be specified.
306
+ !
307
+ ! idimf
308
+ ! the row (or first) dimension of the array
309
+ ! f as it appears in the program calling
310
+ ! hwscsp. this parameter is used to specify
311
+ ! the variable dimension of f. idimf must
312
+ ! be at least m+1 .
313
+ !
314
+ ! w
315
+ ! A FishpackWorkspace derived data type variable
316
+ ! that must be declared by the user. the first
317
+ ! two declarative statements in the user program
318
+ ! calling sepeli must be:
319
+ !
320
+ ! use type_fishpackworkspace
321
+ ! type(fishpackworkspace) :: w
322
+ !
323
+ ! The first statement makes the fishpack module
324
+ ! defined in the file "type_FishpackWorkspace.f90" available to the
325
+ ! user program calling hwscsp. The second statement
326
+ ! declares a derived type variable (defined in
327
+ ! the module "type_FishpackWorkspace.f90") which is used internally
328
+ ! in hwscsp to dynamically allocate real and complex
329
+ ! workspace used in solution. an error flag
330
+ ! (ierror = 20) is set if the required workspace
331
+ ! allocation fails (for example if n, m are too large)
332
+ ! real and complex values are set in the components
333
+ ! of w on a initial (intl=0) call to hwscsp. these
334
+ ! must be preserved on non-initial calls (intl=1)
335
+ ! to hwscsp. this eliminates redundant calculations
336
+ ! and saves compute time.
337
+ ! **** IMPORTANT! The user program calling hwscsp should
338
+ ! include the statement:
339
+ !
340
+ ! call w%destroy()
341
+ !
342
+ ! after the final approximation is generated by
343
+ ! hwscsp. The will deallocate the real and complex
344
+ ! workspace of W. Failure to include this statement
345
+ ! could result in serious memory leakage.
346
+ !
347
+ !
348
+ ! ON OUTPUT f
349
+ ! contains the solution u(i, j) of the finite
350
+ ! difference approximation for the grid point
351
+ ! (theta(i), r(j)), i = 1, 2, ..., m+1,
352
+ ! j = 1, 2, ..., n+1 .
353
+ !
354
+ ! pertrb
355
+ ! if a combination of periodic or derivative
356
+ ! boundary conditions is specified for a
357
+ ! poisson equation (lambda = 0), a solution
358
+ ! may not exist. pertrb is a constant,
359
+ ! calculated and subtracted from f, which
360
+ ! ensures that a solution exists. hwscsp
361
+ ! then computes this solution, which is a
362
+ ! least squares solution to the original
363
+ ! approximation. this solution is not unique
364
+ ! and is unnormalized. the value of pertrb
365
+ ! should be small compared to the right side
366
+ ! f. otherwise , a solution is obtained to
367
+ ! an essentially different problem. this
368
+ ! comparison should always be made to insure
369
+ ! that a meaningful solution has been obtained.
370
+ !
371
+ ! ierror
372
+ ! an error flag that indicates invalid input
373
+ ! parameters. except for numbers 0 and 10,
374
+ ! a solution is not attempted.
375
+ !
376
+ ! = 1 ts<0. or tf>pi
377
+ ! = 2 ts>=tf
378
+ ! = 3 m<5
379
+ ! = 4 mbdcnd<1 or mbdcnd>9
380
+ ! = 5 rs<0
381
+ ! = 6 rs>=rf
382
+ ! = 7 n<5
383
+ ! = 8 nbdcnd<1 or nbdcnd>6
384
+ ! = 9 elmbda>0
385
+ ! = 10 idimf<m+1
386
+ ! = 11 elmbda/=0 and mbdcnd>=5
387
+ ! = 12 elmbda/=0 and nbdcnd equals 5 or 6
388
+ ! = 13 mbdcnd equals 5, 6 or 9 and ts/=0
389
+ ! = 14 mbdcnd>=7 and tf/=pi
390
+ ! = 15 ts.eq.0 and mbdcnd equals 3, 4 or 8
391
+ ! = 16 tf.eq.pi and mbdcnd equals 2, 3 or 6
392
+ ! = 17 nbdcnd>=5 and rs/=0
393
+ ! = 18 nbdcnd>=5 and mbdcnd equals 1, 2, 4, 5 or
394
+ ! = 20 if the dynamic allocation of real and
395
+ ! complex workspace in the derived type
396
+ ! (fishpackworkspace) variable w fails (e.g.,
397
+ ! if n, m are too large for the platform used)
398
+ !
399
+ ! since this is the only means of indicating
400
+ ! a possliby incorrect call to hwscsp, the
401
+ ! user should test ierror after a call.
402
+ !
403
+ ! w
404
+ ! the derived type(fishpackworkspace) variable w
405
+ ! contains real and complex values that must not
406
+ ! be destroyed if hwscsp is called again with
407
+ ! intl=1.
408
+ !
409
+ !
410
+ ! HISTORY Written by Roland Sweet AT NCAR in the late
411
+ ! 1970'S. Released on NCAR's public software
412
+ ! libraries in January 1980. Revised by John
413
+ ! Adams in June 2004 using Fortran 90 dynamically
414
+ ! allocated workspace and derived datat types
415
+ ! to eliminate mixed mode conflicts in the earlier
416
+ ! versions.
417
+ !
418
+ !
419
+ ! ALGORITHM The routine defines the finite difference
420
+ ! equations, incorporates boundary data, and
421
+ ! adjusts the right side of singular systems
422
+ ! and then calls blktri to solve the system.
423
+ !
424
+ ! REFERENCES Swarztrauber, P. and R. Sweet, "Efficient
425
+ ! FORTRAN subprograms for the solution of
426
+ ! elliptic equations"
427
+ ! NCAR TN/IA-109, July, 1975, 138 pp.
428
+ !
429
+ module subroutine hwscsp(intl, ts, tf, m, mbdcnd, bdts, bdtf, rs, rf, n, &
430
+ nbdcnd, bdrs, bdrf, elmbda, f, idimf, pertrb, ierror, workspace)
431
+
432
+ ! Dummy arguments
433
+ integer(ip), intent(in) :: intl
434
+ integer(ip), intent(in) :: m
435
+ integer(ip), intent(in) :: mbdcnd
436
+ integer(ip), intent(in) :: n
437
+ integer(ip), intent(in) :: nbdcnd
438
+ integer(ip), intent(in) :: idimf
439
+ integer(ip), intent(out) :: ierror
440
+ real(wp), intent(in) :: ts
441
+ real(wp), intent(in) :: tf
442
+ real(wp), intent(in) :: rs
443
+ real(wp), intent(in) :: rf
444
+ real(wp), intent(in) :: elmbda
445
+ real(wp), intent(out) :: pertrb
446
+ real(wp), intent(in) :: bdts(:)
447
+ real(wp), intent(in) :: bdtf(:)
448
+ real(wp), intent(in) :: bdrs(:)
449
+ real(wp), intent(in) :: bdrf(:)
450
+ real(wp), intent(inout) :: f(:,:)
451
+ class(FishpackWorkspace), intent(inout) :: workspace
452
+
453
+ ! Check input arguments
454
+ call hwscsp_check_input_arguments(ts, tf, m, mbdcnd, rs, rf, &
455
+ n, nbdcnd, elmbda, idimf, ierror)
456
+
457
+ ! Check error flag
458
+ if (ierror /= 0) return
459
+
460
+ ! Set up workspace on initial call only
461
+ if (intl == 0) call hwscsp_initialize_workspace(n, m, nbdcnd, workspace)
462
+
463
+ ! Solve system
464
+ associate( &
465
+ indx => workspace%workspace_indices, &
466
+ rew => workspace%real_workspace, &
467
+ cxw => workspace%complex_workspace &
468
+ )
469
+ associate( &
470
+ w => rew, &
471
+ wc => cxw, &
472
+ s => rew(indx(1):), &
473
+ an => rew(indx(2):), &
474
+ bn => rew(indx(3):), &
475
+ cn => rew(indx(4):), &
476
+ r => rew(indx(5):), &
477
+ am => rew(indx(6):), &
478
+ bm => rew(indx(7):), &
479
+ cm => rew(indx(8):), &
480
+ sint => rew(indx(9):), &
481
+ bmh => rew(indx(10):) &
482
+ )
483
+ call hwscsp_lower_routine(intl, ts, tf, m, mbdcnd, bdts, bdtf, rs, rf, n, &
484
+ nbdcnd, bdrs, bdrf, elmbda, f, idimf, pertrb, w, wc, s, an, bn, &
485
+ cn, r, am, bm, cm, sint, bmh, ierror)
486
+ end associate
487
+ end associate
488
+
489
+ end subroutine hwscsp
490
+
491
+ subroutine hwscsp_initialize_workspace(n, m, nbdcnd, workspace)
492
+
493
+ ! Dummy arguments
494
+ integer(ip), intent(in) :: nbdcnd
495
+ integer(ip), intent(in) :: n
496
+ integer(ip), intent(in) :: m
497
+ class(FishpackWorkspace), intent(out) :: workspace
498
+
499
+ ! Local variables
500
+ integer(ip) :: irwk, icwk, indx(SIZE_OF_WORKSPACE_INDICES)
501
+
502
+ ! Compute workspace indices
503
+ indx = hwscsp_get_workspace_indices(n, m, nbdcnd)
504
+
505
+ ! Compute required blktri workspace lengths
506
+ call workspace%compute_blktri_workspace_lengths(n, m, irwk, icwk)
507
+
508
+ ! Adjust workspace requirements for hwscsp
509
+ irwk = indx(10) + m + 1
510
+ icwk = icwk + 3 * m
511
+
512
+ ! Allocate memory
513
+ call workspace%create(irwk, icwk, SIZE_OF_WORKSPACE_INDICES)
514
+
515
+ ! Set workspace indices
516
+ workspace%workspace_indices = indx
517
+
518
+ end subroutine hwscsp_initialize_workspace
519
+
520
+ pure function hwscsp_get_workspace_indices(n, m, nbdcnd) result (return_value)
521
+
522
+ ! Dummy arguments
523
+ integer(ip), intent(in) :: n, m, nbdcnd
524
+ integer(ip) :: return_value(SIZE_OF_WORKSPACE_INDICES)
525
+
526
+ ! Local variables
527
+ integer(ip) :: j, nck, l, k
528
+
529
+ nck = n
530
+
531
+ select case (nbdcnd)
532
+ case (1, 5)
533
+ nck = nck - 1
534
+ case (3)
535
+ nck = nck + 1
536
+ end select
537
+
538
+ k = 1
539
+ l = 4
540
+ k = k + 1
541
+
542
+ do
543
+ if (nck <= l) exit
544
+ l = 2*l
545
+ k = k + 1
546
+ end do
547
+
548
+ l = 2*l
549
+
550
+ associate( indx => return_value)
551
+
552
+ indx(1) = (k - 2)*l + k + max(2*n, 6*m) + 13
553
+
554
+ do j = 1, 5
555
+ indx(j+1) = indx(j) + n + 1
556
+ end do
557
+
558
+ do j = 6, 9
559
+ indx(j+1) = indx(j) + m + 1
560
+ end do
561
+
562
+ end associate
563
+
564
+ end function hwscsp_get_workspace_indices
565
+
566
+ subroutine hwscsp_check_input_arguments(ts, tf, m, mbdcnd, rs, rf, &
567
+ n, nbdcnd, elmbda, idimf, ierror)
568
+
569
+ ! Dummy arguments
570
+ integer(ip), intent(in) :: m
571
+ integer(ip), intent(in) :: mbdcnd
572
+ integer(ip), intent(in) :: n
573
+ integer(ip), intent(in) :: nbdcnd
574
+ integer(ip), intent(in) :: idimf
575
+ integer(ip), intent(out) :: ierror
576
+ real(wp), intent(in) :: ts
577
+ real(wp), intent(in) :: tf
578
+ real(wp), intent(in) :: rs
579
+ real(wp), intent(in) :: rf
580
+ real(wp), intent(in) :: elmbda
581
+
582
+ if (ts < ZERO .or. tf > PI) then
583
+ ierror = 1
584
+ return
585
+ else if (ts >= tf) then
586
+ ierror = 2
587
+ return
588
+ else if (m < 5) then
589
+ ierror = 3
590
+ return
591
+ else if (mbdcnd < 1 .or. mbdcnd > 9) then
592
+ ierror = 4
593
+ return
594
+ else if (rs < ZERO) then
595
+ ierror = 5
596
+ return
597
+ else if (rs >= rf) then
598
+ ierror = 6
599
+ return
600
+ else if (n < 5) then
601
+ ierror = 7
602
+ return
603
+ else if (nbdcnd < 1 .or. nbdcnd > 6) then
604
+ ierror = 8
605
+ return
606
+ else if (elmbda > ZERO) then
607
+ ierror = 9
608
+ return
609
+ else if (idimf < m + 1) then
610
+ ierror = 10
611
+ return
612
+ else if (elmbda /= ZERO .and. mbdcnd >= 5) then
613
+ ierror = 11
614
+ return
615
+ else if (elmbda /= ZERO) then
616
+ select case (nbdcnd)
617
+ case (5, 6)
618
+ ierror = 12
619
+ return
620
+ end select
621
+ else if (ts /= ZERO) then
622
+ select case (mbdcnd)
623
+ case (5, 6, 9)
624
+ ierror = 13
625
+ return
626
+ end select
627
+ else if (mbdcnd >= 7 .and. tf /= PI) then
628
+ ierror = 14
629
+ return
630
+ else if (ts == ZERO) then
631
+ select case (mbdcnd)
632
+ case (3:4, 8)
633
+ ierror = 15
634
+ return
635
+ end select
636
+ else if (tf == PI) then
637
+ select case (mbdcnd)
638
+ case (2, 3, 6)
639
+ ierror = 16
640
+ return
641
+ end select
642
+ else if (nbdcnd >= 5 .and. rs /= ZERO) then
643
+ ierror = 17
644
+ return
645
+ else if (5 <= nbdcnd) then
646
+ select case (mbdcnd)
647
+ case (1:2, 5, 7)
648
+ ierror = 18
649
+ return
650
+ end select
651
+ else
652
+ ierror = 0
653
+ end if
654
+
655
+ end subroutine hwscsp_check_input_arguments
656
+
657
+ subroutine hwscsp_lower_routine(intl, ts, tf, m, mbdcnd, bdts, bdtf, rs, rf, n, &
658
+ nbdcnd, bdrs, bdrf, elmbda, f, idimf, pertrb, w, wc, s, an, bn &
659
+ , cn, r, am, bm, cm, sint, bmh, ierror)
660
+
661
+ ! Dummy arguments
662
+
663
+ integer(ip), intent(in) :: intl
664
+ integer(ip), intent(in) :: m
665
+ integer(ip), intent(in) :: mbdcnd
666
+ integer(ip), intent(in) :: n
667
+ integer(ip), intent(in) :: nbdcnd
668
+ integer(ip), intent(in) :: idimf
669
+ integer(ip), intent(out) :: ierror
670
+ real(wp), intent(in) :: ts
671
+ real(wp), intent(in) :: tf
672
+ real(wp), intent(in) :: rs
673
+ real(wp), intent(in) :: rf
674
+ real(wp), intent(in) :: elmbda
675
+ real(wp), intent(out) :: pertrb
676
+ real(wp), intent(in) :: bdts(:)
677
+ real(wp), intent(in) :: bdtf(:)
678
+ real(wp), intent(in) :: bdrs(:)
679
+ real(wp), intent(in) :: bdrf(:)
680
+ real(wp), intent(inout) :: f(idimf,n + 1)
681
+ real(wp), intent(out) :: w(:)
682
+ real(wp), intent(out) :: s(:)
683
+ real(wp), intent(out) :: an(:)
684
+ real(wp), intent(out) :: bn(:)
685
+ real(wp), intent(out) :: cn(:)
686
+ real(wp), intent(out) :: r(:)
687
+ real(wp), intent(out) :: am(:)
688
+ real(wp), intent(out) :: bm(:)
689
+ real(wp), intent(out) :: cm(:)
690
+ real(wp), intent(out) :: sint(:)
691
+ real(wp), intent(out) :: bmh(:)
692
+ complex(wp), intent(out) :: wc(:)
693
+
694
+ ! Local variables
695
+ integer(ip) :: mp1, i, np1, j, mp, np
696
+ integer(ip) :: its, itf, itsp, itfm, ictr, jrs
697
+ integer(ip) :: l, jrf, jrsp, jrfm, munk, nunk, ising, iflg
698
+ real(wp) :: dth, tdt, hdth, sdts
699
+ real(wp) :: theta, t1, dr, hdr
700
+ real(wp) :: tdr, dr2, czr, at, ct, wts, wtf
701
+ real(wp) :: ar, wtnm, yps, cr, wrs, wrf
702
+ real(wp) :: wrz, summation, r2, hne, yhld
703
+ real(wp) :: rs2, rf2, rsq, xp, yph, xps
704
+ real(wp), parameter :: FOUR = 4.0_wp
705
+ real(wp), parameter :: SIX = 6.0_wp
706
+ type(GeneralizedCyclicReductionUtility) :: util
707
+
708
+
709
+ mp1 = m + 1
710
+ dth = (tf - ts)/m
711
+ tdt = dth + dth
712
+ hdth = dth/2
713
+ sdts = ONE/(dth**2)
714
+
715
+ do i = 1, mp1
716
+ theta = ts + real(i - 1, kind=wp)*dth
717
+ sint(i) = sin(theta)
718
+ if (sint(i) == ZERO) cycle
719
+ t1 = sdts/sint(i)
720
+ am(i) = t1*sin(theta - hdth)
721
+ cm(i) = t1*sin(theta + hdth)
722
+ bm(i) = -(am(i)+cm(i))
723
+ end do
724
+
725
+ np1 = n + 1
726
+ dr = (rf - rs)/n
727
+ hdr = dr/2
728
+ tdr = dr + dr
729
+ dr2 = dr**2
730
+ czr = SIX*dth/(dr2*(cos(ts) - cos(tf)))
731
+
732
+ do j = 1, np1
733
+ r(j) = rs + real(j - 1, kind=wp)*dr
734
+ an(j) = (r(j)-hdr)**2/dr2
735
+ cn(j) = (r(j)+hdr)**2/dr2
736
+ bn(j) = -(an(j)+cn(j))
737
+ end do
738
+
739
+ mp = 1
740
+ np = 1
741
+
742
+ !
743
+ ! Boundary condition at phi=ps
744
+ !
745
+ select case (mbdcnd)
746
+ case (1:2,7)
747
+ at = am(2)
748
+ its = 2
749
+ case (3:4,8)
750
+ at = am(1)
751
+ its = 1
752
+ cm(1) = cm(1) + am(1)
753
+ case (5:6,9)
754
+ its = 1
755
+ bm(1) = -FOUR*sdts
756
+ cm(1) = -bm(1)
757
+ end select
758
+
759
+ !
760
+ ! Boundary condition at phi=pf
761
+ !
762
+ select case (mbdcnd)
763
+ case (1,4:5)
764
+ ct = cm(m)
765
+ itf = m
766
+ case (2:3,6)
767
+ ct = cm(m+1)
768
+ am(m+1) = am(m+1) + cm(m+1)
769
+ itf = m + 1
770
+ case (7:9)
771
+ itf = m + 1
772
+ am(m+1) = FOUR*sdts
773
+ bm(m+1) = -am(m+1)
774
+ end select
775
+
776
+ wts = sint(its+1)*am(its+1)/cm(its)
777
+ wtf = sint(itf-1)*cm(itf-1)/am(itf)
778
+ itsp = its + 1
779
+ itfm = itf - 1
780
+ !
781
+ ! Boundary condition at r=rs
782
+ !
783
+ ictr = 0
784
+ select case (nbdcnd)
785
+ case default
786
+ ar = an(2)
787
+ jrs = 2
788
+ case (3:4)
789
+ ar = an(1)
790
+ jrs = 1
791
+ cn(1) = cn(1) + an(1)
792
+ case (5:6)
793
+ jrs = 2
794
+ ictr = 1
795
+ s(n) = an(n)/bn(n)
796
+ do j = 3, n
797
+ l = n - j + 2
798
+ s(l) = an(l)/(bn(l)-cn(l)*s(l+1))
799
+ end do
800
+ s(2) = -s(2)
801
+ do j = 3, n
802
+ s(j) = -s(j)*s(j-1)
803
+ end do
804
+ wtnm = wts + wtf
805
+ do i = itsp, itfm
806
+ wtnm = wtnm + sint(i)
807
+ end do
808
+ yps = czr*wtnm*(s(2)-ONE)
809
+ end select
810
+
811
+ !
812
+ ! Boundary condition at r=rf
813
+ !
814
+ select case (nbdcnd)
815
+ case (1,4:5)
816
+ cr = cn(n)
817
+ jrf = n
818
+ case (2:3,6)
819
+ cr = cn(n+1)
820
+ an(n+1) = an(n+1) + cn(n+1)
821
+ jrf = n + 1
822
+ end select
823
+
824
+ wrs = an(jrs+1)*r(jrs)**2/cn(jrs)
825
+ wrf = cn(jrf-1)*r(jrf)**2/an(jrf)
826
+ wrz = an(jrs)/czr
827
+ jrsp = jrs + 1
828
+ jrfm = jrf - 1
829
+ munk = itf - its + 1
830
+ nunk = jrf - jrs + 1
831
+ bmh(its:itf) = bm(its:itf)
832
+ ising = 0
833
+
834
+ if (nbdcnd == 3 .or. nbdcnd == 6 ) then
835
+ select case (mbdcnd)
836
+ case (3,6,8:9)
837
+ if (elmbda >= ZERO) then
838
+ ising = 1
839
+ summation = wts*wrs + wts*wrf + wtf*wrs + wtf*wrf
840
+ if (ictr /= 0) then
841
+ summation = summation + wrz
842
+ end if
843
+ do j = jrsp, jrfm
844
+ r2 = r(j)**2
845
+ do i = itsp, itfm
846
+ summation = summation + r2*sint(i)
847
+ end do
848
+ end do
849
+ do j = jrsp, jrfm
850
+ summation = summation + (wts + wtf)*r(j)**2
851
+ end do
852
+ do i = itsp, itfm
853
+ summation = summation + (wrs + wrf)*sint(i)
854
+ end do
855
+ hne = summation
856
+ end if
857
+ end select
858
+ end if
859
+
860
+ select case (mbdcnd)
861
+ case (1:4, 7:8)
862
+ bm(its) = bmh(its) + elmbda/sint(its)**2
863
+ end select
864
+
865
+ select case (mbdcnd)
866
+ case (1:6)
867
+ bm(itf) = bmh(itf) + elmbda/sint(itf)**2
868
+ end select
869
+
870
+ bm(itsp:itfm) = bmh(itsp:itfm) + elmbda/sint(itsp:itfm)**2
871
+
872
+ select case (mbdcnd)
873
+ case (1:2, 7)
874
+ f(2, jrs:jrf) = f(2, jrs:jrf) - at*f(1, jrs:jrf)/r(jrs:jrf)**2
875
+ case (3:4, 8)
876
+ f(1, jrs:jrf) = f(1, jrs:jrf) + tdt*bdts(jrs:jrf)*at/r(jrs:jrf)**2
877
+ end select
878
+
879
+ select case (mbdcnd)
880
+ case (1, 4:5)
881
+ f(m, jrs:jrf) = f(m, jrs:jrf) - ct*f(m+1, jrs:jrf)/r(jrs:jrf)**2
882
+ case (2:3, 6)
883
+ f(m+1, jrs:jrf)=f(m+1, jrs:jrf)-tdt*bdtf(jrs:jrf)*ct/r(jrs:jrf)**2
884
+ end select
885
+
886
+ case_block: block
887
+ select case (nbdcnd)
888
+ case default
889
+ if (mbdcnd /= 3) exit case_block
890
+ yhld = f(its, 1) - czr/tdt*(sin(tf)*bdtf(2)-sin(ts)*bdts(2))
891
+ f(:mp1, 1) = yhld
892
+ case (1:2)
893
+ rs2 = (rs + dr)**2
894
+ f(its:itf, 2) = f(its:itf, 2) - ar*f(its:itf, 1)/rs2
895
+ case (3:4)
896
+ f(its:itf, 1) = f(its:itf, 1) + tdr*bdrs(its:itf)*ar/rs**2
897
+ end select
898
+ end block case_block
899
+
900
+ select case (nbdcnd)
901
+ case (1, 4:5)
902
+ rf2 = (rf - dr)**2
903
+ f(its:itf, n) = f(its:itf, n) - cr*f(its:itf, n+1)/rf2
904
+ case (2:3, 6)
905
+ f(its:itf, n+1) = f(its:itf, n+1) - tdr*bdrf(its:itf)*cr/rf**2
906
+ end select
907
+
908
+ pertrb = ZERO
909
+
910
+ if (ising /= 0) then
911
+ summation = wts*wrs*f(its, jrs) + wts*wrf*f(its, jrf) + wtf*wrs*f(itf, &
912
+ jrs) + wtf*wrf*f(itf, jrf)
913
+
914
+ if (ictr /= 0) summation = summation + wrz*f(its, 1)
915
+
916
+ do j = jrsp, jrfm
917
+ r2 = r(j)**2
918
+ do i = itsp, itfm
919
+ summation = summation + r2*sint(i)*f(i, j)
920
+ end do
921
+ end do
922
+
923
+ summation = summation &
924
+ + dot_product(r(jrsp:jrfm)**2, wts*f(its, jrsp:jrfm)+ &
925
+ wtf*f(itf, jrsp:jrfm))
926
+
927
+ summation = summation &
928
+ + dot_product(sint(itsp:itfm), wrs*f(itsp:itfm, jrs)+ &
929
+ wrf*f(itsp:itfm, jrf))
930
+
931
+ pertrb = summation/hne
932
+
933
+ f(:mp1, :np1) = f(:mp1, :np1) - pertrb
934
+
935
+ end if
936
+
937
+ do j = jrs, jrf
938
+ rsq = r(j)**2
939
+ f(its:itf, j) = rsq*f(its:itf, j)
940
+ end do
941
+
942
+ iflg = intl
943
+
944
+ call util%blktrii(iflg, np, nunk, an(jrs:), bn(jrs:), cn(jrs:), mp, munk, &
945
+ am(its:), bm(its:), cm(its:), idimf, f(its:, jrs:), ierror, w, wc)
946
+
947
+ if (ierror /= 0) then
948
+ error stop 'fishpack library: blktrii call failed in hwscsp_lower_routine'
949
+ end if
950
+
951
+ iflg = iflg + 1
952
+
953
+ do while(iflg == 1)
954
+ !
955
+ ! Iterate solver
956
+ !
957
+ call util%blktrii(iflg, np, nunk, an(jrs:), bn(jrs:), cn(jrs:), mp, &
958
+ munk, am(its:), bm(its:), cm(its:), idimf, f(its:, jrs:), ierror, w, wc)
959
+
960
+ if (ierror /= 0) then
961
+ error stop 'fishpack library: blktrii call failed in hwscsp_lower_routine'
962
+ end if
963
+ !
964
+ ! Increment solver flag
965
+ !
966
+ iflg = iflg + 1
967
+ end do
968
+
969
+ if (nbdcnd == 0) f(:mp1, jrf+1) = f(:mp1, jrs)
970
+
971
+ if (mbdcnd == 0) f(itf+1, :np1) = f(its, :np1)
972
+
973
+ xp = ZERO
974
+
975
+ if (ictr /= 0) then
976
+ if (ising == 0) then
977
+ summation = wts*f(its, 2) + wtf*f(itf, 2)
978
+ summation = summation + dot_product(sint(itsp:itfm), f(itsp:itfm, 2))
979
+ yph = czr*summation
980
+ xp = (f(its, 1)-yph)/yps
981
+ do j = jrs, jrf
982
+ xps = xp*s(j)
983
+ f(its:itf, j) = f(its:itf, j) + xps
984
+ end do
985
+ end if
986
+ f(:mp1, 1) = xp
987
+ end if
988
+
989
+ end subroutine hwscsp_lower_routine
990
+
991
+ end submodule centered_axisymmetric_spherical_solver
992
+ !
993
+ ! REVISION HISTORY
994
+ !
995
+ ! September 1973 Version 1
996
+ ! April 1976 Version 2
997
+ ! January 1978 Version 3
998
+ ! December 1979 Version 3.1
999
+ ! February 1985 Documentation upgrade
1000
+ ! November 1988 Version 3.2, FORTRAN 77 changes
1001
+ ! June 2004 Version 5.0, Fortran 90 changes
1002
+ !