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,1454 @@
|
|
|
1
|
+
!
|
|
2
|
+
! file sepeli.f90
|
|
3
|
+
!
|
|
4
|
+
! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
5
|
+
! * *
|
|
6
|
+
! * copyright (c) 2005 by UCAR *
|
|
7
|
+
! * *
|
|
8
|
+
! * University Corporation for Atmospheric Research *
|
|
9
|
+
! * *
|
|
10
|
+
! * all rights reserved *
|
|
11
|
+
! * *
|
|
12
|
+
! * Fishpack *
|
|
13
|
+
! * *
|
|
14
|
+
! * A Package of Fortran *
|
|
15
|
+
! * *
|
|
16
|
+
! * Subroutines and Example Programs *
|
|
17
|
+
! * *
|
|
18
|
+
! * for Modeling Geophysical Processes *
|
|
19
|
+
! * *
|
|
20
|
+
! * by *
|
|
21
|
+
! * *
|
|
22
|
+
! * John Adams, Paul Swarztrauber and Roland Sweet *
|
|
23
|
+
! * *
|
|
24
|
+
! * of *
|
|
25
|
+
! * *
|
|
26
|
+
! * the National Center for Atmospheric Research *
|
|
27
|
+
! * *
|
|
28
|
+
! * Boulder, Colorado (80307) U.S.A. *
|
|
29
|
+
! * *
|
|
30
|
+
! * which is sponsored by *
|
|
31
|
+
! * *
|
|
32
|
+
! * the National Science Foundation *
|
|
33
|
+
! * *
|
|
34
|
+
! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
35
|
+
!
|
|
36
|
+
! SUBROUTINE sepeli(intl, iorder, a, b, m, mbdcnd, bda, alpha, bdb, beta, c,
|
|
37
|
+
! d, n, nbdcnd, bdc, gama, bdd, xnu, cofx, cofy, grhs,
|
|
38
|
+
! usol, idmn, workspace, pertrb, ierror)
|
|
39
|
+
!
|
|
40
|
+
! DIMENSION OF bda(n+1), bdb(n+1), bdc(m+1), bdd(m+1),
|
|
41
|
+
! ARGUMENTS usol(idmn, n+1), grhs(idmn, n+1),
|
|
42
|
+
!
|
|
43
|
+
! LATEST REVISION April 2016
|
|
44
|
+
!
|
|
45
|
+
! PURPOSE sepeli solves for either the second-order
|
|
46
|
+
! finite difference approximation or a
|
|
47
|
+
! fourth-order approximation to a separable
|
|
48
|
+
! elliptic equation
|
|
49
|
+
!
|
|
50
|
+
! 2 2
|
|
51
|
+
! af(x)*d u/dx + bf(x)*du/dx + cf(x)*u +
|
|
52
|
+
! 2 2
|
|
53
|
+
! df(y)*d u/dy + ef(y)*du/dy + ff(y)*u
|
|
54
|
+
!
|
|
55
|
+
! = g(x, y)
|
|
56
|
+
!
|
|
57
|
+
! on a rectangle (x greater than or equal to a
|
|
58
|
+
! and less than or equal to b; y greater than
|
|
59
|
+
! or equal to c and less than or equal to d).
|
|
60
|
+
! any combination of periodic or mixed boundary
|
|
61
|
+
! conditions is allowed.
|
|
62
|
+
!
|
|
63
|
+
! The possible boundary conditions are:
|
|
64
|
+
! in the x-direction:
|
|
65
|
+
! (0) periodic, u(x+b-a, y)=u(x, y) for all
|
|
66
|
+
! y, x (1) u(a, y), u(b, y) are specified for
|
|
67
|
+
! all y
|
|
68
|
+
! (2) u(a, y), du(b, y)/dx+beta*u(b, y) are
|
|
69
|
+
! specified for all y
|
|
70
|
+
! (3) du(a, y)/dx+alpha*u(a, y), du(b, y)/dx+
|
|
71
|
+
! beta*u(b, y) are specified for all y
|
|
72
|
+
! (4) du(a, y)/dx+alpha*u(a, y), u(b, y) are
|
|
73
|
+
! specified for all y
|
|
74
|
+
!
|
|
75
|
+
! in the y-direction:
|
|
76
|
+
! (0) periodic, u(x, y+d-c)=u(x, y) for all x, y
|
|
77
|
+
! (1) u(x, c), u(x, d) are specified for all x
|
|
78
|
+
! (2) u(x, c), du(x, d)/dy+xnu*u(x, d) are
|
|
79
|
+
! specified for all x
|
|
80
|
+
! (3) du(x, c)/dy+gama*u(x, c), du(x, d)/dy+
|
|
81
|
+
! xnu*u(x, d) are specified for all x
|
|
82
|
+
! (4) du(x, c)/dy+gama*u(x, c), u(x, d) are
|
|
83
|
+
! specified for all x
|
|
84
|
+
!
|
|
85
|
+
! USAGE call sepeli (intl, iorder, a, b, m, mbdcnd, bda,
|
|
86
|
+
! alpha, bdb, beta, c, d, n, nbdcnd, bdc,
|
|
87
|
+
! gama, bdd, xnu, cofx, cofy, grhs, usol,
|
|
88
|
+
! idmn, w, pertrb, ierror)
|
|
89
|
+
!
|
|
90
|
+
! ARGUMENTS
|
|
91
|
+
! ON INPUT intl
|
|
92
|
+
! = 0 on initial entry to sepeli or if any
|
|
93
|
+
! of the arguments c, d, n, nbdcnd, cofy
|
|
94
|
+
! are changed from a previous call
|
|
95
|
+
! = 1 if c, d, n, nbdcnd, cofy are unchanged
|
|
96
|
+
! from the previous call.
|
|
97
|
+
!
|
|
98
|
+
! iorder
|
|
99
|
+
! = 2 if a second-order approximation
|
|
100
|
+
! is sought
|
|
101
|
+
! = 4 if a fourth-order approximation
|
|
102
|
+
! is sought
|
|
103
|
+
!
|
|
104
|
+
! a, b
|
|
105
|
+
! the range of the x-independent variable,
|
|
106
|
+
! i.e., x is greater than or equal to a
|
|
107
|
+
! and less than or equal to b. a must be
|
|
108
|
+
! less than b.
|
|
109
|
+
!
|
|
110
|
+
! m
|
|
111
|
+
! the number of panels into which the
|
|
112
|
+
! interval [a, b] is subdivided. hence,
|
|
113
|
+
! there will be m+1 grid points in the x-
|
|
114
|
+
! direction given by xi=a+(i-1)*dlx
|
|
115
|
+
! for i=1, 2, ..., m+1 where dlx=(b-a)/m is
|
|
116
|
+
! the panel width. m must be less than
|
|
117
|
+
! idmn and greater than 5.
|
|
118
|
+
!
|
|
119
|
+
! mbdcnd
|
|
120
|
+
! indicates the type of boundary condition
|
|
121
|
+
! at x=a and x=b
|
|
122
|
+
!
|
|
123
|
+
! = 0 if the solution is periodic in x, i.e.,
|
|
124
|
+
! u(x+b-a, y)=u(x, y) for all y, x
|
|
125
|
+
! = 1 if the solution is specified at x=a
|
|
126
|
+
! and x=b, i.e., u(a, y) and u(b, y) are
|
|
127
|
+
! specified for all y
|
|
128
|
+
! = 2 if the solution is specified at x=a and
|
|
129
|
+
! the boundary condition is mixed at x=b,
|
|
130
|
+
! i.e., u(a, y) and du(b, y)/dx+beta*u(b, y)
|
|
131
|
+
! are specified for all y
|
|
132
|
+
! = 3 if the boundary conditions at x=a and
|
|
133
|
+
! x=b are mixed, i.e.,
|
|
134
|
+
! du(a, y)/dx+alpha*u(a, y) and
|
|
135
|
+
! du(b, y)/dx+beta*u(b, y) are specified
|
|
136
|
+
! for all y
|
|
137
|
+
! = 4 if the boundary condition at x=a is
|
|
138
|
+
! mixed and the solution is specified
|
|
139
|
+
! at x=b, i.e., du(a, y)/dx+alpha*u(a, y)
|
|
140
|
+
! and u(b, y) are specified for all y
|
|
141
|
+
!
|
|
142
|
+
! bda
|
|
143
|
+
! a one-dimensional array of length n+1
|
|
144
|
+
! that specifies the values of
|
|
145
|
+
! du(a, y)/dx+ alpha*u(a, y) at x=a, when
|
|
146
|
+
! mbdcnd=3 or 4.
|
|
147
|
+
! bda(j) = du(a, yj)/dx+alpha*u(a, yj),
|
|
148
|
+
! j=1, 2, ..., n+1. when mbdcnd has any other
|
|
149
|
+
! other value, bda is a dummy parameter.
|
|
150
|
+
!
|
|
151
|
+
! alpha
|
|
152
|
+
! the scalar multiplying the solution in
|
|
153
|
+
! case of a mixed boundary condition at x=a
|
|
154
|
+
! (see argument bda). if mbdcnd is not
|
|
155
|
+
! equal to 3 or 4 then alpha is a dummy
|
|
156
|
+
! parameter.
|
|
157
|
+
!
|
|
158
|
+
! bdb
|
|
159
|
+
! a one-dimensional array of length n+1
|
|
160
|
+
! that specifies the values of
|
|
161
|
+
! du(b, y)/dx+ beta*u(b, y) at x=b.
|
|
162
|
+
! when mbdcnd=2 or 3
|
|
163
|
+
! bdb(j) = du(b, yj)/dx+beta*u(b, yj),
|
|
164
|
+
! j=1, 2, ..., n+1. when mbdcnd has any other
|
|
165
|
+
! other value, bdb is a dummy parameter.
|
|
166
|
+
!
|
|
167
|
+
! beta
|
|
168
|
+
! the scalar multiplying the solution in
|
|
169
|
+
! case of a mixed boundary condition at
|
|
170
|
+
! x=b (see argument bdb). if mbdcnd is
|
|
171
|
+
! not equal to 2 or 3 then beta is a dummy
|
|
172
|
+
! parameter.
|
|
173
|
+
!
|
|
174
|
+
! c, d
|
|
175
|
+
! the range of the y-independent variable,
|
|
176
|
+
! i.e., y is greater than or equal to c
|
|
177
|
+
! and less than or equal to d. c must be
|
|
178
|
+
! less than d.
|
|
179
|
+
!
|
|
180
|
+
! n
|
|
181
|
+
! the number of panels into which the
|
|
182
|
+
! interval [c, d] is subdivided.
|
|
183
|
+
! hence, there will be n+1 grid points
|
|
184
|
+
! in the y-direction given by
|
|
185
|
+
! yj=c+(j-1)*dly for j=1, 2, ..., n+1 where
|
|
186
|
+
! dly=(d-c)/n is the panel width.
|
|
187
|
+
! in addition, n must be greater than 4.
|
|
188
|
+
!
|
|
189
|
+
! nbdcnd
|
|
190
|
+
! indicates the types of boundary conditions
|
|
191
|
+
! at y=c and y=d
|
|
192
|
+
!
|
|
193
|
+
! = 0 if the solution is periodic in y,
|
|
194
|
+
! i.e., u(x, y+d-c)=u(x, y) for all x, y
|
|
195
|
+
! = 1 if the solution is specified at y=c
|
|
196
|
+
! and y = d, i.e., u(x, c) and u(x, d)
|
|
197
|
+
! are specified for all x
|
|
198
|
+
! = 2 if the solution is specified at y=c
|
|
199
|
+
! and the boundary condition is mixed
|
|
200
|
+
! at y=d, i.e., u(x, c) and
|
|
201
|
+
! du(x, d)/dy+xnu*u(x, d) are specified
|
|
202
|
+
! for all x
|
|
203
|
+
! = 3 if the boundary conditions are mixed
|
|
204
|
+
! at y=c and y=d, i.e.,
|
|
205
|
+
! du(x, d)/dy+gama*u(x, c) and
|
|
206
|
+
! du(x, d)/dy+xnu*u(x, d) are specified
|
|
207
|
+
! for all x
|
|
208
|
+
! = 4 if the boundary condition is mixed
|
|
209
|
+
! at y=c and the solution is specified
|
|
210
|
+
! at y=d, i.e. du(x, c)/dy+gama*u(x, c)
|
|
211
|
+
! and u(x, d) are specified for all x
|
|
212
|
+
!
|
|
213
|
+
! bdc
|
|
214
|
+
! a one-dimensional array of length m+1
|
|
215
|
+
! that specifies the value of
|
|
216
|
+
! du(x, c)/dy+gama*u(x, c) at y=c.
|
|
217
|
+
! when nbdcnd=3 or 4 bdc(i) = du(xi, c)/dy +
|
|
218
|
+
! gama*u(xi, c), i=1, 2, ..., m+1.
|
|
219
|
+
! when nbdcnd has any other value, bdc
|
|
220
|
+
! is a dummy parameter.
|
|
221
|
+
!
|
|
222
|
+
! gama
|
|
223
|
+
! the scalar multiplying the solution in
|
|
224
|
+
! case of a mixed boundary condition at
|
|
225
|
+
! y=c (see argument bdc). if nbdcnd is
|
|
226
|
+
! not equal to 3 or 4 then gama is a dummy
|
|
227
|
+
! parameter.
|
|
228
|
+
!
|
|
229
|
+
! bdd
|
|
230
|
+
! a one-dimensional array of length m+1
|
|
231
|
+
! that specifies the value of
|
|
232
|
+
! du(x, d)/dy + xnu*u(x, d) at y=c.
|
|
233
|
+
! when nbdcnd=2 or 3 bdd(i) = du(xi, d)/dy +
|
|
234
|
+
! xnu*u(xi, d), i=1, 2, ..., m+1.
|
|
235
|
+
! when nbdcnd has any other value, bdd
|
|
236
|
+
! is a dummy parameter.
|
|
237
|
+
!
|
|
238
|
+
! xnu
|
|
239
|
+
! the scalar multiplying the solution in
|
|
240
|
+
! case of a mixed boundary condition at
|
|
241
|
+
! y=d (see argument bdd). if nbdcnd is
|
|
242
|
+
! not equal to 2 or 3 then xnu is a
|
|
243
|
+
! dummy parameter.
|
|
244
|
+
!
|
|
245
|
+
! cofx
|
|
246
|
+
! a user-supplied subprogram with
|
|
247
|
+
! parameters x, afun, bfun, cfun which
|
|
248
|
+
! returns the values of the x-dependent
|
|
249
|
+
! coefficients af(x), bf(x), cf(x) in the
|
|
250
|
+
! elliptic equation at x.
|
|
251
|
+
!
|
|
252
|
+
! cofy
|
|
253
|
+
! a user-supplied subprogram with parameters
|
|
254
|
+
! y, dfun, efun, ffun which returns the
|
|
255
|
+
! values of the y-dependent coefficients
|
|
256
|
+
! df(y), ef(y), ff(y) in the elliptic
|
|
257
|
+
! equation at y.
|
|
258
|
+
!
|
|
259
|
+
! note: cofx and cofy must be declared
|
|
260
|
+
! external in the calling routine.
|
|
261
|
+
! the values returned in afun and dfun
|
|
262
|
+
! must satisfy afun*dfun greater than 0
|
|
263
|
+
! for a less than x less than b, c less
|
|
264
|
+
! than y less than d (see ierror=10).
|
|
265
|
+
! the coefficients provided may lead to a
|
|
266
|
+
! matrix equation which is not diagonally
|
|
267
|
+
! dominant in which case solution may fail
|
|
268
|
+
! (see ierror=4).
|
|
269
|
+
!
|
|
270
|
+
! grhs
|
|
271
|
+
! a two-dimensional array that specifies the
|
|
272
|
+
! values of the right-hand side of the
|
|
273
|
+
! elliptic equation, i.e.,
|
|
274
|
+
! grhs(i, j)=g(xi, yi), for i=2, ..., m,
|
|
275
|
+
! j=2, ..., n. at the boundaries, grhs is
|
|
276
|
+
! defined by
|
|
277
|
+
!
|
|
278
|
+
! mbdcnd grhs(1, j) grhs(m+1, j)
|
|
279
|
+
! ------ --------- -----------
|
|
280
|
+
! 0 g(a, yj) g(b, yj)
|
|
281
|
+
! 1 * *
|
|
282
|
+
! 2 * g(b, yj) j=1, 2, ..., n+1
|
|
283
|
+
! 3 g(a, yj) g(b, yj)
|
|
284
|
+
! 4 g(a, yj) *
|
|
285
|
+
!
|
|
286
|
+
! nbdcnd grhs(i, 1) grhs(i, n+1)
|
|
287
|
+
! ------ --------- -----------
|
|
288
|
+
! 0 g(xi, c) g(xi, d)
|
|
289
|
+
! 1 * *
|
|
290
|
+
! 2 * g(xi, d) i=1, 2, ..., m+1
|
|
291
|
+
! 3 g(xi, c) g(xi, d)
|
|
292
|
+
! 4 g(xi, c) *
|
|
293
|
+
!
|
|
294
|
+
! where * means these quantities are not used.
|
|
295
|
+
! grhs should be dimensioned idmn by at least
|
|
296
|
+
! n+1 in the calling routine.
|
|
297
|
+
!
|
|
298
|
+
! usol
|
|
299
|
+
! a two-dimensional array that specifies the
|
|
300
|
+
! values of the solution along the boundaries.
|
|
301
|
+
! at the boundaries, usol is defined by
|
|
302
|
+
!
|
|
303
|
+
! mbdcnd usol(1, j) usol(m+1, j)
|
|
304
|
+
! ------ --------- -----------
|
|
305
|
+
! 0 * *
|
|
306
|
+
! 1 u(a, yj) u(b, yj)
|
|
307
|
+
! 2 u(a, yj) * j=1, 2, ..., n+1
|
|
308
|
+
! 3 * *
|
|
309
|
+
! 4 * u(b, yj)
|
|
310
|
+
!
|
|
311
|
+
! nbdcnd usol(i, 1) usol(i, n+1)
|
|
312
|
+
! ------ --------- -----------
|
|
313
|
+
! 0 * *
|
|
314
|
+
! 1 u(xi, c) u(xi, d)
|
|
315
|
+
! 2 u(xi, c) * i=1, 2, ..., m+1
|
|
316
|
+
! 3 * *
|
|
317
|
+
! 4 * u(xi, d)
|
|
318
|
+
!
|
|
319
|
+
! where * means the quantities are not used
|
|
320
|
+
! in the solution.
|
|
321
|
+
!
|
|
322
|
+
! if iorder=2, the user may equivalence grhs
|
|
323
|
+
! and usol to save space. note that in this
|
|
324
|
+
! case the tables specifying the boundaries
|
|
325
|
+
! of the grhs and usol arrays determine the
|
|
326
|
+
! boundaries uniquely except at the corners.
|
|
327
|
+
! if the tables call for both g(x, y) and
|
|
328
|
+
! u(x, y) at a corner then the solution must
|
|
329
|
+
! be chosen. for example, if mbdcnd=2 and
|
|
330
|
+
! nbdcnd=4, then u(a, c), u(a, d), u(b, d) must
|
|
331
|
+
! be chosen at the corners in addition
|
|
332
|
+
! to g(b, c).
|
|
333
|
+
!
|
|
334
|
+
! if iorder=4, then the two arrays, usol and
|
|
335
|
+
! grhs, must be distinct.
|
|
336
|
+
!
|
|
337
|
+
! usol should be dimensioned idmn by at least
|
|
338
|
+
! n+1 in the calling routine.
|
|
339
|
+
!
|
|
340
|
+
! idmn
|
|
341
|
+
! the row (or first) dimension of the arrays
|
|
342
|
+
! grhs and usol as it appears in the program
|
|
343
|
+
! calling sepeli. this parameter is used
|
|
344
|
+
! to specify the variable dimension of grhs
|
|
345
|
+
! and usol. idmn must be at least 7 and
|
|
346
|
+
! greater than or equal to m+1.
|
|
347
|
+
!
|
|
348
|
+
! workspace
|
|
349
|
+
! An object of class(FishpackWorkspace) variable
|
|
350
|
+
! which is used internally in sepeli to dynamically
|
|
351
|
+
! allocate real and complex workspace arrays used
|
|
352
|
+
! in the solver. An error flag (ierror = 20) is
|
|
353
|
+
! set if the required workspace
|
|
354
|
+
! allocation fails (for example if n, m are too large)
|
|
355
|
+
! real and complex values are set in the components
|
|
356
|
+
! of workspace on a initial (intl=0) call to sepeli.
|
|
357
|
+
! These must be preserved on non-initial calls (intl=1)
|
|
358
|
+
! to sepeli. This eliminates redundant calculations
|
|
359
|
+
! and saves compute time.
|
|
360
|
+
!
|
|
361
|
+
! **** IMPORTANT! The user program calling sepeli should
|
|
362
|
+
! include the statement:
|
|
363
|
+
!
|
|
364
|
+
! call workspace%destroy()
|
|
365
|
+
!
|
|
366
|
+
! after the final approximation is generated by
|
|
367
|
+
! sepeli. This will deallocate the real and complex
|
|
368
|
+
! workspace of workspace. Failure to include this statement
|
|
369
|
+
! could result in serious memory leakage.
|
|
370
|
+
!
|
|
371
|
+
! ON OUTPUT usol
|
|
372
|
+
! Contains the approximate solution to the
|
|
373
|
+
! elliptic equation.
|
|
374
|
+
! usol(i, j) is the approximation to u(xi, yj)
|
|
375
|
+
! for i=1, 2..., m+1 and j=1, 2, ..., n+1.
|
|
376
|
+
! the approximation has error
|
|
377
|
+
! o(dlx**2+dly**2) if called with iorder=2
|
|
378
|
+
! and o(dlx**4+dly**4) if called with
|
|
379
|
+
! iorder=4.
|
|
380
|
+
!
|
|
381
|
+
! workwpace
|
|
382
|
+
! The derived type(FishpackWorkspace) variable
|
|
383
|
+
! contains real and complex values that must not
|
|
384
|
+
! be destroyed if sepeli is called again with
|
|
385
|
+
! intl=1.
|
|
386
|
+
!
|
|
387
|
+
! pertrb
|
|
388
|
+
! if a combination of periodic or derivative
|
|
389
|
+
! boundary conditions
|
|
390
|
+
! (i.e., alpha=beta=0 if mbdcnd=3;
|
|
391
|
+
! gama=xnu=0 if nbdcnd=3) is specified
|
|
392
|
+
! and if the coefficients of u(x, y) in the
|
|
393
|
+
! separable elliptic equation are zero
|
|
394
|
+
! (i.e., cf(x)=0 for x greater than or equal
|
|
395
|
+
! to a and less than or equal to b;
|
|
396
|
+
! ff(y)=0 for y greater than or equal to c
|
|
397
|
+
! and less than or equal to d) then a
|
|
398
|
+
! solution may not exist. pertrb is a
|
|
399
|
+
! constant calculated and subtracted from
|
|
400
|
+
! the right-hand side of the matrix equations
|
|
401
|
+
! generated by sepeli which insures that a
|
|
402
|
+
! solution exists. sepeli then computes this
|
|
403
|
+
! solution which is a weighted minimal least
|
|
404
|
+
! squares solution to the original problem.
|
|
405
|
+
!
|
|
406
|
+
! ierror
|
|
407
|
+
! an error flag that indicates invalid input
|
|
408
|
+
! parameters or failure to find a solution
|
|
409
|
+
! = 0 no error
|
|
410
|
+
! = 1 if a greater than b or c greater than d
|
|
411
|
+
! = 2 if mbdcnd less than 0 or mbdcnd greater
|
|
412
|
+
! than 4
|
|
413
|
+
! = 3 if nbdcnd less than 0 or nbdcnd greater
|
|
414
|
+
! than 4
|
|
415
|
+
! = 4 if attempt to find a solution fails.
|
|
416
|
+
! (the linear system generated is not
|
|
417
|
+
! diagonally dominant.)
|
|
418
|
+
! = 5 if idmn is too small
|
|
419
|
+
! (see discussion of idmn)
|
|
420
|
+
! = 6 if m is too small or too large
|
|
421
|
+
! (see discussion of m)
|
|
422
|
+
! = 7 if n is too small (see discussion of n)
|
|
423
|
+
! = 8 if iorder is not 2 or 4
|
|
424
|
+
! = 9 if intl is not 0 or 1
|
|
425
|
+
! = 10 if afun*dfun less than or equal to 0
|
|
426
|
+
! for some interior mesh point (xi, yj)
|
|
427
|
+
! = 20 If the dynamic allocation of real and
|
|
428
|
+
! complex workspace in the derived type
|
|
429
|
+
! (FishpackWorkspace) variable W fails (e.g.,
|
|
430
|
+
! if N, M are too large for the platform used)
|
|
431
|
+
!
|
|
432
|
+
! Note (concerning ierror=4): for the
|
|
433
|
+
! coefficients input through cofx, cofy,
|
|
434
|
+
! the discretization may lead to a block
|
|
435
|
+
! tridiagonal linear system which is not
|
|
436
|
+
! diagonally dominant (for example, this
|
|
437
|
+
! happens if cfun=0 and bfun/(TWO *dlx) greater
|
|
438
|
+
! than afun/dlx**2). in this case solution
|
|
439
|
+
! may fail. this cannot happen in the limit
|
|
440
|
+
! as dlx, dly approach zero. hence, the
|
|
441
|
+
! condition may be remedied by taking larger
|
|
442
|
+
! values for m or n.
|
|
443
|
+
!
|
|
444
|
+
! SPECIAL CONDITIONS See cofx, cofy argument descriptions above.
|
|
445
|
+
!
|
|
446
|
+
! I/O None
|
|
447
|
+
!
|
|
448
|
+
! PRECISION Set by the instrinsic module ISO_Fortran_env to 64-bit double precision
|
|
449
|
+
!
|
|
450
|
+
! REQUIRED FILES blktri.f90, type_SepAux.f90, type_FishpackWorkspace.f90
|
|
451
|
+
!
|
|
452
|
+
! STANDARD Fortran 2008
|
|
453
|
+
!
|
|
454
|
+
! HISTORY Developed at NCAR during 1975-76 by
|
|
455
|
+
! John c. Adams of the scientific computing
|
|
456
|
+
! division. Released on NCAR's public software
|
|
457
|
+
! libraries in January 1980. Revised in June
|
|
458
|
+
! 2004 using Fortan 90 dynamically allocated work
|
|
459
|
+
! space and derived data types to eliminate mixed
|
|
460
|
+
! mode conflicts in the earlier versions. All
|
|
461
|
+
! statement labels, arithmetic if statements and
|
|
462
|
+
! computed go to statements have been removed from
|
|
463
|
+
! the current version of sepeli.
|
|
464
|
+
!
|
|
465
|
+
! ALGORITHM sepeli automatically discretizes the
|
|
466
|
+
! separable elliptic equation which is then
|
|
467
|
+
! solved by a generalized cyclic reduction
|
|
468
|
+
! algorithm in the subroutine, blktri. The
|
|
469
|
+
! fourth-order solution is obtained using
|
|
470
|
+
! 'deferred corrections' which is described
|
|
471
|
+
! and referenced in sections, references and
|
|
472
|
+
! method.
|
|
473
|
+
!
|
|
474
|
+
! TIMING The operational count is proportional to
|
|
475
|
+
! m*n*log2(n).
|
|
476
|
+
!
|
|
477
|
+
! ACCURACY The following accuracy results were obtained
|
|
478
|
+
! using 64 bit floating point arithmetic. note
|
|
479
|
+
! that the fourth-order accuracy is not realized
|
|
480
|
+
! until the mesh is sufficiently refined.
|
|
481
|
+
!
|
|
482
|
+
! second-order fourth-order
|
|
483
|
+
! m n error error
|
|
484
|
+
!
|
|
485
|
+
! 6 6 6.8e-1 1.2e0
|
|
486
|
+
! 14 14 1.4e-1 1.8e-1
|
|
487
|
+
! 30 30 3.2e-2 9.7e-3
|
|
488
|
+
! 62 62 7.5e-3 3.0e-4
|
|
489
|
+
! 126 126 1.8e-3 3.5e-6
|
|
490
|
+
!
|
|
491
|
+
!
|
|
492
|
+
! REFERENCES Keller, H.B., Numerical methods for two-point
|
|
493
|
+
! boundary-value problems, Blaisdel (1968),
|
|
494
|
+
! Waltham, Mass.
|
|
495
|
+
!
|
|
496
|
+
! Swarztrauber, P., and R. Sweet (1975):
|
|
497
|
+
! Efficient FORTRAN subprograms for the
|
|
498
|
+
! solution of elliptic partial differential
|
|
499
|
+
! equations. NCAR Technical note
|
|
500
|
+
! NCAR-TN/IA-109, PP. 135-137.
|
|
501
|
+
!
|
|
502
|
+
module module_sepeli
|
|
503
|
+
|
|
504
|
+
use fishpack_precision, only: &
|
|
505
|
+
wp, & ! Working precision
|
|
506
|
+
ip ! Integer precision
|
|
507
|
+
|
|
508
|
+
use type_FishpackWorkspace, only: &
|
|
509
|
+
FishpackWorkspace
|
|
510
|
+
|
|
511
|
+
use type_GeneralizedCyclicReductionUtility, only: &
|
|
512
|
+
GeneralizedCyclicReductionUtility
|
|
513
|
+
|
|
514
|
+
use type_SepAux, only: &
|
|
515
|
+
SepAux, &
|
|
516
|
+
get_coefficients
|
|
517
|
+
|
|
518
|
+
! Explicit typing only!
|
|
519
|
+
implicit none
|
|
520
|
+
|
|
521
|
+
! Everything is private unless stated otherwise
|
|
522
|
+
private
|
|
523
|
+
public :: sepeli
|
|
524
|
+
|
|
525
|
+
type, private, extends(SepAux) :: SepeliAux
|
|
526
|
+
!---------------------------------------------------------------
|
|
527
|
+
! Type components
|
|
528
|
+
!---------------------------------------------------------------
|
|
529
|
+
type(GeneralizedCyclicReductionUtility), private :: blktri_aux
|
|
530
|
+
!---------------------------------------------------------------
|
|
531
|
+
contains
|
|
532
|
+
!---------------------------------------------------------------
|
|
533
|
+
! Type-bound procedures
|
|
534
|
+
!---------------------------------------------------------------
|
|
535
|
+
procedure, public :: spelip
|
|
536
|
+
procedure, private :: is_PDE_singular
|
|
537
|
+
procedure, private :: defer
|
|
538
|
+
!---------------------------------------------------------------
|
|
539
|
+
end type SepeliAux
|
|
540
|
+
|
|
541
|
+
!---------------------------------------------------------------
|
|
542
|
+
! Parameters confined to the module
|
|
543
|
+
!---------------------------------------------------------------
|
|
544
|
+
real(wp), parameter :: ZERO = 0.0_wp
|
|
545
|
+
real(wp), parameter :: HALF = 0.5_wp
|
|
546
|
+
real(wp), parameter :: TWO = 2.0_wp
|
|
547
|
+
integer(ip), parameter :: IIWK = 12 !! Size of workspace indices
|
|
548
|
+
!---------------------------------------------------------------
|
|
549
|
+
|
|
550
|
+
contains
|
|
551
|
+
|
|
552
|
+
subroutine sepeli(intl, iorder, a, b, m, mbdcnd, bda, alpha, bdb, &
|
|
553
|
+
beta, c, d, n, nbdcnd, bdc, gama, bdd, xnu, cofx, cofy, grhs, &
|
|
554
|
+
usol, idmn, workspace, pertrb, ierror)
|
|
555
|
+
!--------------------------------------------------------------
|
|
556
|
+
! Dummy arguments
|
|
557
|
+
!--------------------------------------------------------------
|
|
558
|
+
integer(ip), intent(in) :: intl
|
|
559
|
+
integer(ip), intent(in) :: iorder
|
|
560
|
+
integer(ip), intent(in) :: m
|
|
561
|
+
integer(ip), intent(in) :: mbdcnd
|
|
562
|
+
integer(ip), intent(in) :: n
|
|
563
|
+
integer(ip), intent(in) :: nbdcnd
|
|
564
|
+
integer(ip), intent(in) :: idmn
|
|
565
|
+
integer(ip), intent(out) :: ierror
|
|
566
|
+
real(wp), intent(in) :: a
|
|
567
|
+
real(wp), intent(in) :: b
|
|
568
|
+
real(wp), intent(in) :: alpha
|
|
569
|
+
real(wp), intent(in) :: beta
|
|
570
|
+
real(wp), intent(in) :: c
|
|
571
|
+
real(wp), intent(in) :: d
|
|
572
|
+
real(wp), intent(in) :: gama
|
|
573
|
+
real(wp), intent(in) :: xnu
|
|
574
|
+
real(wp), intent(out) :: pertrb
|
|
575
|
+
real(wp), intent(in) :: bda(:)
|
|
576
|
+
real(wp), intent(in) :: bdb(:)
|
|
577
|
+
real(wp), intent(in) :: bdc(:)
|
|
578
|
+
real(wp), intent(in) :: bdd(:)
|
|
579
|
+
real(wp), intent(inout) :: grhs(:,:)
|
|
580
|
+
real(wp), intent(inout) :: usol(:,:)
|
|
581
|
+
class(FishpackWorkspace), intent(inout) :: workspace
|
|
582
|
+
procedure(get_coefficients) :: cofx
|
|
583
|
+
procedure(get_coefficients) :: cofy
|
|
584
|
+
!--------------------------------------------------------------
|
|
585
|
+
! Local variables
|
|
586
|
+
!--------------------------------------------------------------
|
|
587
|
+
type(SepeliAux), save :: aux
|
|
588
|
+
!--------------------------------------------------------------
|
|
589
|
+
|
|
590
|
+
!
|
|
591
|
+
! Check input arguments
|
|
592
|
+
!
|
|
593
|
+
call check_input_arguments(intl, iorder, a, b, m, mbdcnd, c, d, n, &
|
|
594
|
+
nbdcnd, cofx, cofy, idmn, ierror)
|
|
595
|
+
|
|
596
|
+
! Check error flag
|
|
597
|
+
if (ierror /= 0) return
|
|
598
|
+
|
|
599
|
+
!
|
|
600
|
+
! allocate workspace arrays on initial call only
|
|
601
|
+
!
|
|
602
|
+
if (intl == 0) call initialize_workspace(n, m, workspace)
|
|
603
|
+
|
|
604
|
+
associate( &
|
|
605
|
+
indx => workspace%workspace_indices, &
|
|
606
|
+
rew => workspace%real_workspace, &
|
|
607
|
+
cxw => workspace%complex_workspace &
|
|
608
|
+
)
|
|
609
|
+
|
|
610
|
+
!
|
|
611
|
+
! Compute 2nd or 4th order solution
|
|
612
|
+
!
|
|
613
|
+
call aux%spelip(intl, iorder, a, b, m, mbdcnd, &
|
|
614
|
+
bda, alpha, bdb, beta, c, d, n, &
|
|
615
|
+
nbdcnd, bdc, gama, bdd, xnu, cofx, cofy, &
|
|
616
|
+
rew(indx(1):), rew(indx(2):), rew(indx(3):), rew(indx(4):), &
|
|
617
|
+
rew(indx(5):), rew(indx(6):), rew(indx(7):), rew(indx(8):), &
|
|
618
|
+
rew(indx(9):), rew(indx(10):), rew(indx(11):), rew(indx(12):), &
|
|
619
|
+
grhs, usol, idmn, rew, cxw, pertrb, ierror)
|
|
620
|
+
|
|
621
|
+
end associate
|
|
622
|
+
|
|
623
|
+
end subroutine sepeli
|
|
624
|
+
|
|
625
|
+
subroutine initialize_workspace(n, m, workspace)
|
|
626
|
+
!-----------------------------------------------
|
|
627
|
+
! Dummy arguments
|
|
628
|
+
!-----------------------------------------------
|
|
629
|
+
integer(ip), intent(in) :: n
|
|
630
|
+
integer(ip), intent(in) :: m
|
|
631
|
+
class(FishpackWorkspace), intent(out) :: workspace
|
|
632
|
+
!-----------------------------------------------
|
|
633
|
+
! Local variables
|
|
634
|
+
!-----------------------------------------------
|
|
635
|
+
integer(ip) :: irwk, icwk, indx(IIWK)
|
|
636
|
+
!-----------------------------------------------
|
|
637
|
+
|
|
638
|
+
! Compute required blktri workspace lengths
|
|
639
|
+
call workspace%compute_blktri_workspace_lengths(n, m, irwk, icwk)
|
|
640
|
+
|
|
641
|
+
! TODO **************
|
|
642
|
+
! Try to eliminate this local variable altogether
|
|
643
|
+
! Compute workspace indices
|
|
644
|
+
indx = get_workspace_indices(irwk, n, m)
|
|
645
|
+
|
|
646
|
+
! Adjust workspace requirements for sepeli
|
|
647
|
+
irwk = indx(12) + m + 1
|
|
648
|
+
icwk = icwk + 3 * (m + 1)
|
|
649
|
+
|
|
650
|
+
! Allocate required memory
|
|
651
|
+
call workspace%create(irwk, icwk, IIWK)
|
|
652
|
+
|
|
653
|
+
! Set workspace indices
|
|
654
|
+
workspace%workspace_indices = indx
|
|
655
|
+
|
|
656
|
+
end subroutine initialize_workspace
|
|
657
|
+
|
|
658
|
+
pure function get_workspace_indices(irwk, n, m) result (return_value)
|
|
659
|
+
!--------------------------------------------------------------
|
|
660
|
+
! Dummy arguments
|
|
661
|
+
!--------------------------------------------------------------
|
|
662
|
+
integer(ip), intent(in) :: irwk
|
|
663
|
+
integer(ip), intent(in) :: n
|
|
664
|
+
integer(ip), intent(in) :: m
|
|
665
|
+
integer(ip) :: return_value(IIWK)
|
|
666
|
+
!--------------------------------------------------------------
|
|
667
|
+
integer(ip) :: j !! Counter
|
|
668
|
+
!--------------------------------------------------------------
|
|
669
|
+
|
|
670
|
+
associate( indx => return_value)
|
|
671
|
+
|
|
672
|
+
indx(1) = irwk + 1
|
|
673
|
+
|
|
674
|
+
do j = 1, 6
|
|
675
|
+
indx(j+1) = indx(j) + n + 1
|
|
676
|
+
end do
|
|
677
|
+
|
|
678
|
+
do j = 7, 11
|
|
679
|
+
indx(j+1) = indx(j) + m + 1
|
|
680
|
+
end do
|
|
681
|
+
|
|
682
|
+
end associate
|
|
683
|
+
|
|
684
|
+
end function get_workspace_indices
|
|
685
|
+
|
|
686
|
+
subroutine spelip(self, intl, iorder, a, b, m, mbdcnd, bda, alpha, bdb, &
|
|
687
|
+
beta, c, d, n, nbdcnd, bdc, gama, bdd, xnu, cofx, cofy, an, bn, &
|
|
688
|
+
cn, dn, un, zn, am, bm, cm, dm, um, zm, grhs, usol, idmn, w, &
|
|
689
|
+
wc, pertrb, ierror)
|
|
690
|
+
!
|
|
691
|
+
! Purpose:
|
|
692
|
+
!
|
|
693
|
+
! spelip sets up vectors and arrays for input to blktri
|
|
694
|
+
! and computes a second order solution in usol. a return jump to
|
|
695
|
+
! sepeli occurrs if iorder=2. if iorder=4 a fourth order
|
|
696
|
+
! solution is generated in usol.
|
|
697
|
+
!
|
|
698
|
+
!--------------------------------------------------------------
|
|
699
|
+
! Dummy arguments
|
|
700
|
+
!--------------------------------------------------------------
|
|
701
|
+
class(SepeliAux), intent(inout) :: self
|
|
702
|
+
integer(ip), intent(in) :: intl
|
|
703
|
+
integer(ip), intent(in) :: iorder
|
|
704
|
+
integer(ip), intent(in) :: m
|
|
705
|
+
integer(ip), intent(in) :: mbdcnd
|
|
706
|
+
integer(ip), intent(in) :: n
|
|
707
|
+
integer(ip), intent(in) :: nbdcnd
|
|
708
|
+
integer(ip), intent(in) :: idmn
|
|
709
|
+
integer(ip), intent(out) :: ierror
|
|
710
|
+
real(wp), intent(in) :: a
|
|
711
|
+
real(wp), intent(in) :: b
|
|
712
|
+
real(wp), intent(in) :: alpha
|
|
713
|
+
real(wp), intent(in) :: beta
|
|
714
|
+
real(wp), intent(in) :: c
|
|
715
|
+
real(wp), intent(in) :: d
|
|
716
|
+
real(wp), intent(in) :: gama
|
|
717
|
+
real(wp), intent(in) :: xnu
|
|
718
|
+
real(wp), intent(out) :: pertrb
|
|
719
|
+
real(wp), intent(in) :: bda(:)
|
|
720
|
+
real(wp), intent(in) :: bdb(:)
|
|
721
|
+
real(wp), intent(in) :: bdc(:)
|
|
722
|
+
real(wp), intent(in) :: bdd(:)
|
|
723
|
+
real(wp), intent(out) :: an(:)
|
|
724
|
+
real(wp), intent(out) :: bn(:)
|
|
725
|
+
real(wp), intent(out) :: cn(:)
|
|
726
|
+
real(wp), intent(out) :: dn(:)
|
|
727
|
+
real(wp), intent(out) :: un(:)
|
|
728
|
+
real(wp), intent(out) :: zn(:)
|
|
729
|
+
real(wp), intent(out) :: am(:)
|
|
730
|
+
real(wp), intent(out) :: bm(:)
|
|
731
|
+
real(wp), intent(out) :: cm(:)
|
|
732
|
+
real(wp), intent(out) :: dm(:)
|
|
733
|
+
real(wp), intent(out) :: um(:)
|
|
734
|
+
real(wp), intent(out) :: zm(:)
|
|
735
|
+
real(wp), intent(inout) :: grhs(:,:)
|
|
736
|
+
real(wp), intent(inout) :: usol(:,:)
|
|
737
|
+
real(wp), intent(out) :: w(:)
|
|
738
|
+
complex(wp), intent(out) :: wc(:)
|
|
739
|
+
procedure(get_coefficients) :: cofx
|
|
740
|
+
procedure(get_coefficients) :: cofy
|
|
741
|
+
!--------------------------------------------------------------
|
|
742
|
+
! Local variables
|
|
743
|
+
!--------------------------------------------------------------
|
|
744
|
+
integer(ip) :: i, j, i1, mp, np
|
|
745
|
+
real(wp) :: xi, ai, bi, ci, axi, bxi, cxi
|
|
746
|
+
real(wp) :: yj, dj, ej, fj, dyj, eyj
|
|
747
|
+
real(wp) :: fyj, ax1, cxm, dy1, fyn, prtrb
|
|
748
|
+
logical :: singular
|
|
749
|
+
!--------------------------------------------------------------
|
|
750
|
+
|
|
751
|
+
! Associate various quantities
|
|
752
|
+
associate( &
|
|
753
|
+
kswx => self%kswx, &
|
|
754
|
+
kswy => self%kswy, &
|
|
755
|
+
k => self%k, &
|
|
756
|
+
l=>self%l, &
|
|
757
|
+
mit=>self%mit, &
|
|
758
|
+
nit=> self%nit, &
|
|
759
|
+
is=> self%is, &
|
|
760
|
+
ms=> self%ms, &
|
|
761
|
+
js=> self%js, &
|
|
762
|
+
ns=> self%ns, &
|
|
763
|
+
ait => self%ait, &
|
|
764
|
+
bit => self%bit, &
|
|
765
|
+
cit => self%cit, &
|
|
766
|
+
dit => self%dit, &
|
|
767
|
+
dlx => self%dlx, &
|
|
768
|
+
dly => self%dly, &
|
|
769
|
+
tdlx3 => self%tdlx3, &
|
|
770
|
+
tdly3 => self%tdly3, &
|
|
771
|
+
dlx4 => self%dlx4, &
|
|
772
|
+
dly4 => self%dly4 &
|
|
773
|
+
)
|
|
774
|
+
|
|
775
|
+
! set parameters internally
|
|
776
|
+
!
|
|
777
|
+
kswx = mbdcnd + 1
|
|
778
|
+
kswy = nbdcnd + 1
|
|
779
|
+
k = m + 1
|
|
780
|
+
l = n + 1
|
|
781
|
+
ait = a
|
|
782
|
+
bit = b
|
|
783
|
+
cit = c
|
|
784
|
+
dit = d
|
|
785
|
+
!
|
|
786
|
+
! set right hand side values from grhs in usol on the interior
|
|
787
|
+
! and non-specified boundaries.
|
|
788
|
+
!
|
|
789
|
+
usol(2:m, 2:n) = grhs(2:m, 2:n)
|
|
790
|
+
|
|
791
|
+
if (kswx /= 2 .and. kswx /= 3) then
|
|
792
|
+
usol(1, 2:n) = grhs(1, 2:n)
|
|
793
|
+
end if
|
|
794
|
+
|
|
795
|
+
if (kswx /= 2 .and. kswx /= 5) then
|
|
796
|
+
usol(k, 2:n) = grhs(k, 2:n)
|
|
797
|
+
end if
|
|
798
|
+
|
|
799
|
+
if (kswy /= 2 .and. kswy /= 3) then
|
|
800
|
+
usol(2:m, 1) = grhs(2:m, 1)
|
|
801
|
+
end if
|
|
802
|
+
|
|
803
|
+
if (kswy /= 2 .and. kswy /= 5) then
|
|
804
|
+
usol(2:m, l) = grhs(2:m, l)
|
|
805
|
+
end if
|
|
806
|
+
|
|
807
|
+
if (kswx/=2 .and. kswx/=3 .and. kswy/=2 .and. kswy/=3) then
|
|
808
|
+
usol(1, 1) = grhs(1, 1)
|
|
809
|
+
end if
|
|
810
|
+
|
|
811
|
+
if (kswx/=2 .and. kswx/=5 .and. kswy/=2 .and. kswy/=3) then
|
|
812
|
+
usol(k, 1) = grhs(k, 1)
|
|
813
|
+
end if
|
|
814
|
+
|
|
815
|
+
if (kswx/=2 .and. kswx/=3 .and. kswy/=2 .and. kswy/=5) then
|
|
816
|
+
usol(1, l) = grhs(1, l)
|
|
817
|
+
end if
|
|
818
|
+
|
|
819
|
+
if (kswx/=2 .and. kswx/=5 .and. kswy/=2 .and. kswy/=5) then
|
|
820
|
+
usol(k, l) = grhs(k, l)
|
|
821
|
+
end if
|
|
822
|
+
|
|
823
|
+
i1 = 1
|
|
824
|
+
!
|
|
825
|
+
! set switches for periodic or non-periodic boundaries
|
|
826
|
+
!
|
|
827
|
+
mp = 1
|
|
828
|
+
np = 1
|
|
829
|
+
|
|
830
|
+
if (kswx == 1) then
|
|
831
|
+
mp = 0
|
|
832
|
+
end if
|
|
833
|
+
|
|
834
|
+
if (kswy == 1) then
|
|
835
|
+
np = 0
|
|
836
|
+
end if
|
|
837
|
+
!
|
|
838
|
+
! set dlx, dly and size of block tri-diagonal system generated
|
|
839
|
+
! in nint, mint
|
|
840
|
+
!
|
|
841
|
+
dlx = (bit - ait)/m
|
|
842
|
+
mit = k - 1
|
|
843
|
+
|
|
844
|
+
select case (kswx)
|
|
845
|
+
case (2)
|
|
846
|
+
mit = k - 2
|
|
847
|
+
case (4)
|
|
848
|
+
mit = k
|
|
849
|
+
end select
|
|
850
|
+
|
|
851
|
+
dly = (dit - cit)/n
|
|
852
|
+
nit = l - 1
|
|
853
|
+
|
|
854
|
+
select case (kswy)
|
|
855
|
+
case (2)
|
|
856
|
+
nit = l - 2
|
|
857
|
+
case (4)
|
|
858
|
+
nit = l
|
|
859
|
+
end select
|
|
860
|
+
|
|
861
|
+
tdlx3 = TWO * (dlx**3)
|
|
862
|
+
dlx4 = dlx**4
|
|
863
|
+
tdly3 = TWO * (dly**3)
|
|
864
|
+
dly4 = dly**4
|
|
865
|
+
!
|
|
866
|
+
! set subscript limits for portion of array to input to blktri
|
|
867
|
+
!
|
|
868
|
+
is = 1
|
|
869
|
+
js = 1
|
|
870
|
+
|
|
871
|
+
if (kswx==2 .or. kswx==3) then
|
|
872
|
+
is = 2
|
|
873
|
+
end if
|
|
874
|
+
|
|
875
|
+
if (kswy==2 .or. kswy==3) then
|
|
876
|
+
js = 2
|
|
877
|
+
end if
|
|
878
|
+
|
|
879
|
+
ns = nit + js - 1
|
|
880
|
+
ms = mit + is - 1
|
|
881
|
+
!
|
|
882
|
+
! set x - direction
|
|
883
|
+
!
|
|
884
|
+
do i = 1, mit
|
|
885
|
+
xi = ait + real(is + i - 2, kind=wp)*dlx
|
|
886
|
+
call cofx(xi, ai, bi, ci)
|
|
887
|
+
axi = (ai/dlx - HALF*bi)/dlx
|
|
888
|
+
bxi = (-TWO*ai/dlx**2) + ci
|
|
889
|
+
cxi = (ai/dlx + HALF*bi)/dlx
|
|
890
|
+
am(i) = axi
|
|
891
|
+
bm(i) = bxi
|
|
892
|
+
cm(i) = cxi
|
|
893
|
+
end do
|
|
894
|
+
!
|
|
895
|
+
! set y direction
|
|
896
|
+
!
|
|
897
|
+
do j = 1, nit
|
|
898
|
+
yj = cit + real(js + j - 2, kind=wp)*dly
|
|
899
|
+
call cofy(yj, dj, ej, fj)
|
|
900
|
+
dyj = (dj/dly - HALF*ej)/dly
|
|
901
|
+
eyj = (-TWO*dj/dly**2) + fj
|
|
902
|
+
fyj = (dj/dly + HALF*ej)/dly
|
|
903
|
+
an(j) = dyj
|
|
904
|
+
bn(j) = eyj
|
|
905
|
+
cn(j) = fyj
|
|
906
|
+
end do
|
|
907
|
+
!
|
|
908
|
+
! adjust edges in x direction unless periodic
|
|
909
|
+
!
|
|
910
|
+
ax1 = am(1)
|
|
911
|
+
cxm = cm(mit)
|
|
912
|
+
select case (kswx)
|
|
913
|
+
case (2)
|
|
914
|
+
!
|
|
915
|
+
! dirichlet-dirichlet in x direction
|
|
916
|
+
!
|
|
917
|
+
am(1) = ZERO
|
|
918
|
+
cm(mit) = ZERO
|
|
919
|
+
case (5)
|
|
920
|
+
!
|
|
921
|
+
! mixed-dirichlet in x direction
|
|
922
|
+
!
|
|
923
|
+
am(1) = ZERO
|
|
924
|
+
bm(1) = bm(1) + TWO*alpha*dlx*ax1
|
|
925
|
+
cm(1) = cm(1) + ax1
|
|
926
|
+
cm(mit) = ZERO
|
|
927
|
+
case (3)
|
|
928
|
+
!
|
|
929
|
+
! dirichlet-mixed in x direction
|
|
930
|
+
!
|
|
931
|
+
am(1) = ZERO
|
|
932
|
+
am(mit) = am(mit) + cxm
|
|
933
|
+
bm(mit) = bm(mit) - TWO*beta*dlx*cxm
|
|
934
|
+
cm(mit) = ZERO
|
|
935
|
+
!
|
|
936
|
+
! mixed - mixed in x direction
|
|
937
|
+
!
|
|
938
|
+
case (4)
|
|
939
|
+
am(1) = ZERO
|
|
940
|
+
bm(1) = bm(1) + TWO*dlx*alpha*ax1
|
|
941
|
+
cm(1) = cm(1) + ax1
|
|
942
|
+
am(mit) = am(mit) + cxm
|
|
943
|
+
bm(mit) = bm(mit) - TWO*dlx*beta*cxm
|
|
944
|
+
cm(mit) = ZERO
|
|
945
|
+
end select
|
|
946
|
+
!
|
|
947
|
+
! adjust in y direction unless periodic
|
|
948
|
+
!
|
|
949
|
+
dy1 = an(1)
|
|
950
|
+
fyn = cn(nit)
|
|
951
|
+
|
|
952
|
+
select case (kswy)
|
|
953
|
+
case (2)
|
|
954
|
+
!
|
|
955
|
+
! dirichlet-dirichlet in y direction
|
|
956
|
+
!
|
|
957
|
+
an(1) = ZERO
|
|
958
|
+
cn(nit) = ZERO
|
|
959
|
+
case (5)
|
|
960
|
+
!
|
|
961
|
+
! mixed-dirichlet in y direction
|
|
962
|
+
!
|
|
963
|
+
an(1) = ZERO
|
|
964
|
+
bn(1) = bn(1) + TWO*dly*gama*dy1
|
|
965
|
+
cn(1) = cn(1) + dy1
|
|
966
|
+
cn(nit) = ZERO
|
|
967
|
+
case (3)
|
|
968
|
+
!
|
|
969
|
+
! dirichlet-mixed in y direction
|
|
970
|
+
!
|
|
971
|
+
an(1) = ZERO
|
|
972
|
+
an(nit) = an(nit) + fyn
|
|
973
|
+
bn(nit) = bn(nit) - TWO*dly*xnu*fyn
|
|
974
|
+
cn(nit) = ZERO
|
|
975
|
+
case (4)
|
|
976
|
+
!
|
|
977
|
+
! mixed - mixed direction in y direction
|
|
978
|
+
!
|
|
979
|
+
an(1) = ZERO
|
|
980
|
+
bn(1) = bn(1) + TWO*dly*gama*dy1
|
|
981
|
+
cn(1) = cn(1) + dy1
|
|
982
|
+
an(nit) = an(nit) + fyn
|
|
983
|
+
bn(nit) = bn(nit) - TWO * dly*xnu*fyn
|
|
984
|
+
cn(nit) = ZERO
|
|
985
|
+
end select
|
|
986
|
+
|
|
987
|
+
if (kswx /= 1) then
|
|
988
|
+
!
|
|
989
|
+
! adjust usol along x edge
|
|
990
|
+
!
|
|
991
|
+
if (kswx==2 .or. kswx==3) then
|
|
992
|
+
if (kswx==2 .or. kswx==5) then
|
|
993
|
+
usol(is, js:ns) = usol(is, js:ns) - ax1*usol(1, js:ns)
|
|
994
|
+
usol(ms, js:ns) = usol(ms, js:ns) - cxm*usol(k, js:ns)
|
|
995
|
+
else
|
|
996
|
+
usol(is, js:ns) = usol(is, js:ns) - ax1*usol(1, js:ns)
|
|
997
|
+
usol(ms, js:ns) = usol(ms, js:ns) - TWO * dlx*cxm*bdb(js:ns)
|
|
998
|
+
end if
|
|
999
|
+
else
|
|
1000
|
+
if (kswx==2 .or. kswx==5) then
|
|
1001
|
+
usol(is, js:ns) = usol(is, js:ns) + TWO * dlx*ax1*bda(js:ns)
|
|
1002
|
+
usol(ms, js:ns) = usol(ms, js:ns) - cxm*usol(k, js:ns)
|
|
1003
|
+
else
|
|
1004
|
+
usol(is, js:ns) = usol(is, js:ns) + TWO * dlx*ax1*bda(js:ns)
|
|
1005
|
+
usol(ms, js:ns) = usol(ms, js:ns) - TWO * dlx*cxm*bdb(js:ns)
|
|
1006
|
+
end if
|
|
1007
|
+
end if
|
|
1008
|
+
end if
|
|
1009
|
+
|
|
1010
|
+
if (kswy /= 1) then
|
|
1011
|
+
!
|
|
1012
|
+
! adjust usol along y edge
|
|
1013
|
+
!
|
|
1014
|
+
if (kswy==2 .or. kswy==3) then
|
|
1015
|
+
if (kswy==2 .or. kswy==5) then
|
|
1016
|
+
usol(is:ms, js) = usol(is:ms, js) - dy1*usol(is:ms, 1)
|
|
1017
|
+
usol(is:ms, ns) = usol(is:ms, ns) - fyn*usol(is:ms, l)
|
|
1018
|
+
else
|
|
1019
|
+
usol(is:ms, js) = usol(is:ms, js) - dy1*usol(is:ms, 1)
|
|
1020
|
+
usol(is:ms, ns) = usol(is:ms, ns) - TWO * dly*fyn*bdd(is:ms)
|
|
1021
|
+
end if
|
|
1022
|
+
else
|
|
1023
|
+
if (kswy==2 .or. kswy==5) then
|
|
1024
|
+
usol(is:ms, js) = usol(is:ms, js) + TWO * dly*dy1*bdc(is:ms)
|
|
1025
|
+
usol(is:ms, ns) = usol(is:ms, ns) - fyn*usol(is:ms, l)
|
|
1026
|
+
else
|
|
1027
|
+
usol(is:ms, js) = usol(is:ms, js) + TWO * dly*dy1*bdc(is:ms)
|
|
1028
|
+
usol(is:ms, ns) = usol(is:ms, ns) - TWO * dly*fyn*bdd(is:ms)
|
|
1029
|
+
end if
|
|
1030
|
+
end if
|
|
1031
|
+
end if
|
|
1032
|
+
!
|
|
1033
|
+
! save adjusted edges in grhs if iorder=4
|
|
1034
|
+
!
|
|
1035
|
+
if (iorder == 4) then
|
|
1036
|
+
grhs(is, js:ns) = usol(is, js:ns)
|
|
1037
|
+
grhs(ms, js:ns) = usol(ms, js:ns)
|
|
1038
|
+
grhs(is:ms, js) = usol(is:ms, js)
|
|
1039
|
+
grhs(is:ms, ns) = usol(is:ms, ns)
|
|
1040
|
+
end if
|
|
1041
|
+
|
|
1042
|
+
! Initialize perturbation
|
|
1043
|
+
pertrb = ZERO
|
|
1044
|
+
!
|
|
1045
|
+
! check if operator is singular
|
|
1046
|
+
!
|
|
1047
|
+
call self%is_PDE_singular(mbdcnd, nbdcnd, alpha, beta, &
|
|
1048
|
+
gama, xnu, cofx, cofy, singular)
|
|
1049
|
+
!
|
|
1050
|
+
! compute non-zero eigenvector in null space of transpose
|
|
1051
|
+
! if singular
|
|
1052
|
+
!
|
|
1053
|
+
if (singular) then
|
|
1054
|
+
call self%septri(mit, am, bm, cm, dm, um, zm)
|
|
1055
|
+
end if
|
|
1056
|
+
|
|
1057
|
+
if (singular) then
|
|
1058
|
+
call self%septri(nit, an, bn, cn, dn, un, zn)
|
|
1059
|
+
end if
|
|
1060
|
+
!
|
|
1061
|
+
! make initialization call to blktrii
|
|
1062
|
+
!
|
|
1063
|
+
if (intl == 0) then
|
|
1064
|
+
call self%blktri_aux%blktrii(intl, np, nit, an, bn, cn, mp, mit, am, bm, cm, &
|
|
1065
|
+
idmn, usol(is:, js:), ierror, w, wc)
|
|
1066
|
+
|
|
1067
|
+
! Check error flag
|
|
1068
|
+
if (ierror /= 0) then
|
|
1069
|
+
return
|
|
1070
|
+
end if
|
|
1071
|
+
end if
|
|
1072
|
+
!
|
|
1073
|
+
! adjust right hand side if necessary
|
|
1074
|
+
!
|
|
1075
|
+
if (singular) then
|
|
1076
|
+
call self%seport(usol, zn, zm, pertrb)
|
|
1077
|
+
end if
|
|
1078
|
+
!
|
|
1079
|
+
! compute solution
|
|
1080
|
+
!
|
|
1081
|
+
call self%blktri_aux%blktrii(i1, np, nit, an, bn, cn, mp, mit, am, bm, cm, idmn, &
|
|
1082
|
+
usol(is:, js:), ierror, w, wc)
|
|
1083
|
+
|
|
1084
|
+
if (ierror /= 0) then
|
|
1085
|
+
return
|
|
1086
|
+
end if
|
|
1087
|
+
!
|
|
1088
|
+
! set periodic boundaries if necessary
|
|
1089
|
+
!
|
|
1090
|
+
if (kswx == 1) then
|
|
1091
|
+
usol(k, :l) = usol(1, :l)
|
|
1092
|
+
end if
|
|
1093
|
+
|
|
1094
|
+
if (kswy == 1) then
|
|
1095
|
+
usol(:k, l) = usol(:k, 1)
|
|
1096
|
+
end if
|
|
1097
|
+
!
|
|
1098
|
+
! minimize solution with respect to weighted least squares
|
|
1099
|
+
! norm if operator is singular
|
|
1100
|
+
!
|
|
1101
|
+
if (singular) then
|
|
1102
|
+
call self%sepmin(usol, zn, zm, prtrb)
|
|
1103
|
+
end if
|
|
1104
|
+
!
|
|
1105
|
+
! return if deferred corrections and a fourth order solution are
|
|
1106
|
+
! not flagged
|
|
1107
|
+
!
|
|
1108
|
+
if (iorder == 2) return
|
|
1109
|
+
!
|
|
1110
|
+
! compute new right hand side for fourth order solution
|
|
1111
|
+
!
|
|
1112
|
+
call self%defer(cofx, cofy, idmn, usol, grhs)
|
|
1113
|
+
|
|
1114
|
+
if (singular) call self%seport(usol, zn, zm, pertrb)
|
|
1115
|
+
!
|
|
1116
|
+
! compute fourth order solution
|
|
1117
|
+
!
|
|
1118
|
+
call self%blktri_aux%blktrii(i1, np, nit, an, bn, cn, mp, mit, am, bm, cm, idmn, &
|
|
1119
|
+
usol(is:, js:), ierror, w, wc)
|
|
1120
|
+
|
|
1121
|
+
if (ierror /= 0) return
|
|
1122
|
+
!
|
|
1123
|
+
! set periodic boundaries if necessary
|
|
1124
|
+
!
|
|
1125
|
+
if (kswx == 1) then
|
|
1126
|
+
usol(k, :l) = usol(1, :l)
|
|
1127
|
+
end if
|
|
1128
|
+
if (kswy == 1) then
|
|
1129
|
+
usol(:k, l) = usol(:k, 1)
|
|
1130
|
+
end if
|
|
1131
|
+
!
|
|
1132
|
+
! minimize solution with respect to weighted least squares
|
|
1133
|
+
! norm if operator is singular
|
|
1134
|
+
!
|
|
1135
|
+
if (singular) call self%sepmin(usol, zn, zm, prtrb)
|
|
1136
|
+
|
|
1137
|
+
end associate
|
|
1138
|
+
|
|
1139
|
+
end subroutine spelip
|
|
1140
|
+
|
|
1141
|
+
subroutine check_input_arguments(intl, iorder, a, b, m, mbdcnd, c, d, n, nbdcnd, &
|
|
1142
|
+
cofx, cofy, idmn, ierror)
|
|
1143
|
+
!--------------------------------------------------------------
|
|
1144
|
+
! Dummy arguments
|
|
1145
|
+
!--------------------------------------------------------------
|
|
1146
|
+
integer(ip), intent(in) :: intl
|
|
1147
|
+
integer(ip), intent(in) :: iorder
|
|
1148
|
+
integer(ip), intent(in) :: m
|
|
1149
|
+
integer(ip), intent(in) :: mbdcnd
|
|
1150
|
+
integer(ip), intent(in) :: n
|
|
1151
|
+
integer(ip), intent(in) :: nbdcnd
|
|
1152
|
+
integer(ip), intent(in) :: idmn
|
|
1153
|
+
integer(ip), intent(out) :: ierror
|
|
1154
|
+
real(wp), intent(in) :: a
|
|
1155
|
+
real(wp), intent(in) :: b
|
|
1156
|
+
real(wp), intent(in) :: c
|
|
1157
|
+
real(wp), intent(in) :: d
|
|
1158
|
+
!--------------------------------------------------------------
|
|
1159
|
+
! Dummy procedure arguments
|
|
1160
|
+
!--------------------------------------------------------------
|
|
1161
|
+
procedure(get_coefficients) :: cofx
|
|
1162
|
+
procedure(get_coefficients) :: cofy
|
|
1163
|
+
!--------------------------------------------------------------
|
|
1164
|
+
! Dummy arguments
|
|
1165
|
+
!--------------------------------------------------------------
|
|
1166
|
+
integer(ip) :: i, j
|
|
1167
|
+
real(wp) :: dlx, dly, xi, ai, bi, ci, yj, dj, ej, fj
|
|
1168
|
+
!-----------------------------------------------
|
|
1169
|
+
|
|
1170
|
+
! check definition of solution region
|
|
1171
|
+
!
|
|
1172
|
+
if (a>=b .or. c>=d) then
|
|
1173
|
+
ierror = 1
|
|
1174
|
+
return
|
|
1175
|
+
end if
|
|
1176
|
+
!
|
|
1177
|
+
! check boundary condition arguments
|
|
1178
|
+
!
|
|
1179
|
+
if (mbdcnd<0 .or. mbdcnd>4) then
|
|
1180
|
+
ierror = 2
|
|
1181
|
+
return
|
|
1182
|
+
end if
|
|
1183
|
+
if (nbdcnd<0 .or. nbdcnd>4) then
|
|
1184
|
+
ierror = 3
|
|
1185
|
+
return
|
|
1186
|
+
end if
|
|
1187
|
+
!
|
|
1188
|
+
! check first dimension in calling routine
|
|
1189
|
+
!
|
|
1190
|
+
if (idmn < 7) then
|
|
1191
|
+
ierror = 5
|
|
1192
|
+
return
|
|
1193
|
+
end if
|
|
1194
|
+
!
|
|
1195
|
+
! check m, n
|
|
1196
|
+
!
|
|
1197
|
+
if (m>idmn - 1 .or. m<6) then
|
|
1198
|
+
ierror = 6
|
|
1199
|
+
return
|
|
1200
|
+
end if
|
|
1201
|
+
if (n < 5) then
|
|
1202
|
+
ierror = 7
|
|
1203
|
+
return
|
|
1204
|
+
end if
|
|
1205
|
+
!
|
|
1206
|
+
! check iorder
|
|
1207
|
+
!
|
|
1208
|
+
if (iorder/=2 .and. iorder/=4) then
|
|
1209
|
+
ierror = 8
|
|
1210
|
+
return
|
|
1211
|
+
end if
|
|
1212
|
+
!
|
|
1213
|
+
! check intl
|
|
1214
|
+
!
|
|
1215
|
+
if (intl/=0 .and. intl/=1) then
|
|
1216
|
+
ierror = 9
|
|
1217
|
+
return
|
|
1218
|
+
end if
|
|
1219
|
+
!
|
|
1220
|
+
! check that equation is elliptic (only on initial call)
|
|
1221
|
+
!
|
|
1222
|
+
if (intl == 0) then
|
|
1223
|
+
dlx = (b - a)/m
|
|
1224
|
+
dly = (d - c)/n
|
|
1225
|
+
outer_loop: do i = 2, m
|
|
1226
|
+
xi = a + real(i - 1)*dlx
|
|
1227
|
+
|
|
1228
|
+
call cofx(xi, ai, bi, ci)
|
|
1229
|
+
|
|
1230
|
+
inner_loop: do j = 2, n
|
|
1231
|
+
yj = c + real(j - 1)*dly
|
|
1232
|
+
call cofy(yj, dj, ej, fj)
|
|
1233
|
+
|
|
1234
|
+
if (ai*dj > ZERO) cycle inner_loop
|
|
1235
|
+
|
|
1236
|
+
ierror = 10
|
|
1237
|
+
return
|
|
1238
|
+
end do inner_loop
|
|
1239
|
+
end do outer_loop
|
|
1240
|
+
end if
|
|
1241
|
+
!
|
|
1242
|
+
! no error found
|
|
1243
|
+
!
|
|
1244
|
+
ierror = 0
|
|
1245
|
+
|
|
1246
|
+
end subroutine check_input_arguments
|
|
1247
|
+
|
|
1248
|
+
subroutine is_PDE_singular(self, mbdcnd, nbdcnd, alpha, beta, gama, xnu, cofx, cofy, singlr)
|
|
1249
|
+
!
|
|
1250
|
+
! Purpose:
|
|
1251
|
+
!
|
|
1252
|
+
! Checks if the PDE that sepeli must solve is a singular operator
|
|
1253
|
+
!
|
|
1254
|
+
!--------------------------------------------------------------
|
|
1255
|
+
! Dummy arguments
|
|
1256
|
+
!--------------------------------------------------------------
|
|
1257
|
+
class(SepeliAux), intent(inout) :: self
|
|
1258
|
+
integer(ip), intent(in) :: mbdcnd
|
|
1259
|
+
integer(ip), intent(in) :: nbdcnd
|
|
1260
|
+
real(wp), intent(in) :: alpha
|
|
1261
|
+
real(wp), intent(in) :: beta
|
|
1262
|
+
real(wp), intent(in) :: gama
|
|
1263
|
+
real(wp), intent(in) :: xnu
|
|
1264
|
+
logical , intent(out) :: singlr
|
|
1265
|
+
procedure(get_coefficients) :: cofx
|
|
1266
|
+
procedure(get_coefficients) :: cofy
|
|
1267
|
+
!--------------------------------------------------------------
|
|
1268
|
+
! Local variables
|
|
1269
|
+
!--------------------------------------------------------------
|
|
1270
|
+
integer(ip) :: i, j
|
|
1271
|
+
real(wp) :: xi, ai, bi, ci, yj, dj, ej, fj
|
|
1272
|
+
!--------------------------------------------------------------
|
|
1273
|
+
|
|
1274
|
+
! Associate various quantities
|
|
1275
|
+
associate( &
|
|
1276
|
+
kswx => self%kswx, &
|
|
1277
|
+
kswy => self%kswy, &
|
|
1278
|
+
k => self%k, &
|
|
1279
|
+
l=>self%l, &
|
|
1280
|
+
mit=>self%mit, &
|
|
1281
|
+
nit=> self%nit, &
|
|
1282
|
+
is=> self%is, &
|
|
1283
|
+
ms=> self%ms, &
|
|
1284
|
+
js=> self%js, &
|
|
1285
|
+
ns=> self%ns, &
|
|
1286
|
+
ait => self%ait, &
|
|
1287
|
+
bit => self%bit, &
|
|
1288
|
+
cit => self%cit, &
|
|
1289
|
+
dit => self%dit, &
|
|
1290
|
+
dlx => self%dlx, &
|
|
1291
|
+
dly => self%dly, &
|
|
1292
|
+
tdlx3 => self%tdlx3, &
|
|
1293
|
+
tdly3 => self%tdly3, &
|
|
1294
|
+
dlx4 => self%dlx4, &
|
|
1295
|
+
dly4 => self%dly4 &
|
|
1296
|
+
)
|
|
1297
|
+
|
|
1298
|
+
! Initialize flag
|
|
1299
|
+
singlr = .false.
|
|
1300
|
+
!
|
|
1301
|
+
! check if the boundary conditions are
|
|
1302
|
+
! entirely periodic and/or mixed
|
|
1303
|
+
!
|
|
1304
|
+
if(mbdcnd/=0.and.mbdcnd/=3.or.nbdcnd/=0.and.nbdcnd/=3) then
|
|
1305
|
+
return
|
|
1306
|
+
end if
|
|
1307
|
+
!
|
|
1308
|
+
! check that mixed conditions are pure neuman
|
|
1309
|
+
!
|
|
1310
|
+
if (mbdcnd == 3) then
|
|
1311
|
+
if (alpha/=ZERO .or. beta/=ZERO) return
|
|
1312
|
+
end if
|
|
1313
|
+
|
|
1314
|
+
if (nbdcnd == 3) then
|
|
1315
|
+
if (gama/=ZERO .or. xnu/=ZERO) return
|
|
1316
|
+
end if
|
|
1317
|
+
!
|
|
1318
|
+
! check that non-derivative coefficient functions
|
|
1319
|
+
! are zero
|
|
1320
|
+
!
|
|
1321
|
+
do i = is, ms
|
|
1322
|
+
xi = ait + real(i - 1, kind=wp)*dlx
|
|
1323
|
+
call cofx(xi, ai, bi, ci)
|
|
1324
|
+
if (ci == ZERO) cycle
|
|
1325
|
+
return
|
|
1326
|
+
end do
|
|
1327
|
+
|
|
1328
|
+
do j = js, ns
|
|
1329
|
+
yj = cit + real(j - 1, kind=wp)*dly
|
|
1330
|
+
call cofy(yj, dj, ej, fj)
|
|
1331
|
+
if (fj == ZERO) cycle
|
|
1332
|
+
return
|
|
1333
|
+
end do
|
|
1334
|
+
!
|
|
1335
|
+
! the operator must be singular if this point is reached
|
|
1336
|
+
!
|
|
1337
|
+
singlr = .true.
|
|
1338
|
+
|
|
1339
|
+
end associate
|
|
1340
|
+
|
|
1341
|
+
end subroutine is_PDE_singular
|
|
1342
|
+
|
|
1343
|
+
subroutine defer(self, cofx, cofy, idmn, usol, grhs)
|
|
1344
|
+
!
|
|
1345
|
+
! Purpose:
|
|
1346
|
+
!
|
|
1347
|
+
! this subroutine first approximates the truncation error given by
|
|
1348
|
+
! trun1(x, y)=dlx**2*tx+dly**2*ty where
|
|
1349
|
+
! tx=afun(x)*uxxxx/12+bfun(x)*uxxx/6 on the interior and
|
|
1350
|
+
! at the boundaries if periodic(here uxxx, uxxxx are the third
|
|
1351
|
+
! and fourth partial derivatives of u with respect to x).
|
|
1352
|
+
! tx is of the form afun(x)/3 * (uxxxx/4 +uxxx/dlx)
|
|
1353
|
+
! at x=a or x=b if the boundary condition there is mixed.
|
|
1354
|
+
! tx=0.0 along specified boundaries. ty has symmetric form
|
|
1355
|
+
! in y with x, afun(x), bfun(x) replaced by y, dfun(y), efun(y).
|
|
1356
|
+
! the second order solution in usol is used to approximate
|
|
1357
|
+
! (via second order finite differencing) the truncation error
|
|
1358
|
+
! and the result is added to the right hand side in grhs
|
|
1359
|
+
! and then transferred to usol to be used as a new right
|
|
1360
|
+
! hand side when calling blktri for a fourth order solution.
|
|
1361
|
+
!
|
|
1362
|
+
!--------------------------------------------------------------
|
|
1363
|
+
! Dummy arguments
|
|
1364
|
+
!--------------------------------------------------------------
|
|
1365
|
+
class(SepeliAux), intent(inout) :: self
|
|
1366
|
+
integer(ip), intent(in) :: idmn
|
|
1367
|
+
real(wp), intent(inout) :: usol(:,:)
|
|
1368
|
+
real(wp), intent(inout) :: grhs(:,:)
|
|
1369
|
+
procedure(get_coefficients) :: cofx
|
|
1370
|
+
procedure(get_coefficients) :: cofy
|
|
1371
|
+
!--------------------------------------------------------------
|
|
1372
|
+
! Local variables
|
|
1373
|
+
!--------------------------------------------------------------
|
|
1374
|
+
integer(ip) :: j, i
|
|
1375
|
+
real(wp) :: yj, dj, ej, fj, xi, ai, bi, ci
|
|
1376
|
+
real(wp) :: uxxx, uxxxx, uyyy, uyyyy, tx, ty
|
|
1377
|
+
!--------------------------------------------------------------
|
|
1378
|
+
|
|
1379
|
+
! Associate various quantities
|
|
1380
|
+
associate( &
|
|
1381
|
+
kswx => self%kswx, &
|
|
1382
|
+
kswy => self%kswy, &
|
|
1383
|
+
k => self%k, &
|
|
1384
|
+
l=>self%l, &
|
|
1385
|
+
mit=>self%mit, &
|
|
1386
|
+
nit=> self%nit, &
|
|
1387
|
+
is=> self%is, &
|
|
1388
|
+
ms=> self%ms, &
|
|
1389
|
+
js=> self%js, &
|
|
1390
|
+
ns=> self%ns, &
|
|
1391
|
+
ait => self%ait, &
|
|
1392
|
+
bit => self%bit, &
|
|
1393
|
+
cit => self%cit, &
|
|
1394
|
+
dit => self%dit, &
|
|
1395
|
+
dlx => self%dlx, &
|
|
1396
|
+
dly => self%dly, &
|
|
1397
|
+
tdlx3 => self%tdlx3, &
|
|
1398
|
+
tdly3 => self%tdly3, &
|
|
1399
|
+
dlx4 => self%dlx4, &
|
|
1400
|
+
dly4 => self%dly4 &
|
|
1401
|
+
)
|
|
1402
|
+
|
|
1403
|
+
!
|
|
1404
|
+
! compute truncation error approximation over the entire mesh
|
|
1405
|
+
!
|
|
1406
|
+
do j = js, ns
|
|
1407
|
+
yj = cit + real(j - 1, kind=wp)*dly
|
|
1408
|
+
call cofy(yj, dj, ej, fj)
|
|
1409
|
+
do i = is, ms
|
|
1410
|
+
xi = ait + real(i - 1, kind=wp)*dlx
|
|
1411
|
+
call cofx(xi, ai, bi, ci)
|
|
1412
|
+
!
|
|
1413
|
+
! compute partial derivative approximations at (xi, yj)
|
|
1414
|
+
!
|
|
1415
|
+
call self%sepdx(usol, i, j, uxxx, uxxxx)
|
|
1416
|
+
call self%sepdy(usol, idmn, i, j, uyyy, uyyyy)
|
|
1417
|
+
tx = ai*uxxxx/12 + bi*uxxx/6
|
|
1418
|
+
ty = dj*uyyyy/12 + ej*uyyy/6
|
|
1419
|
+
!
|
|
1420
|
+
! reset form of truncation if at boundary which is non-periodic
|
|
1421
|
+
!
|
|
1422
|
+
if (kswx/=1 .and. (i==1 .or. i==k)) then
|
|
1423
|
+
tx = (ai/3) * (uxxxx/4 + uxxx/dlx)
|
|
1424
|
+
end if
|
|
1425
|
+
|
|
1426
|
+
if (kswy/=1 .and. (j==1 .or. j==l)) then
|
|
1427
|
+
ty = (dj/3) * (uyyyy/4 + uyyy/dly)
|
|
1428
|
+
end if
|
|
1429
|
+
|
|
1430
|
+
grhs(i, j) = grhs(i, j) + (dlx**2)*tx + (dly**2)*ty
|
|
1431
|
+
end do
|
|
1432
|
+
end do
|
|
1433
|
+
!
|
|
1434
|
+
! reset the right hand side in usol
|
|
1435
|
+
!
|
|
1436
|
+
usol(is:ms, js:ns) = grhs(is:ms, js:ns)
|
|
1437
|
+
|
|
1438
|
+
end associate
|
|
1439
|
+
|
|
1440
|
+
end subroutine defer
|
|
1441
|
+
|
|
1442
|
+
end module module_sepeli
|
|
1443
|
+
!
|
|
1444
|
+
! REVISION HISTORY
|
|
1445
|
+
!
|
|
1446
|
+
! September 1973 Version 1
|
|
1447
|
+
! April 1976 Version 2
|
|
1448
|
+
! January 1978 Version 3
|
|
1449
|
+
! December 1979 Version 3.1
|
|
1450
|
+
! February 1985 Documentation upgrade
|
|
1451
|
+
! November 1988 Version 3.2, FORTRAN 77 changes
|
|
1452
|
+
! June 2004 Version 5.0, fortran 90 changes
|
|
1453
|
+
! May 2016 Fortran 2008 changes
|
|
1454
|
+
!
|