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