1 |
jmc |
1.1 |
C $Header: /u/gcmpack/MITgcm/model/src/solve_tridiagonal.F,v 1.10 2012/03/15 15:25:18 jmc Exp $ |
2 |
|
|
C $Name: $ |
3 |
|
|
|
4 |
|
|
#include "CPP_OPTIONS.h" |
5 |
|
|
|
6 |
|
|
CBOP |
7 |
|
|
C !ROUTINE: SOLVE_UV_TRIDIAGO |
8 |
|
|
C !INTERFACE: |
9 |
|
|
SUBROUTINE SOLVE_UV_TRIDIAGO( |
10 |
|
|
I kSize, ols, solve4u, solve4v, |
11 |
|
|
I aU, bU, cU, rhsU, |
12 |
|
|
I aV, bV, cV, rhsV, |
13 |
|
|
O uFld, vFld, |
14 |
|
|
O errCode, |
15 |
|
|
I subIter, myIter, myThid ) |
16 |
|
|
C !DESCRIPTION: \bv |
17 |
|
|
C *==========================================================* |
18 |
|
|
C | S/R SOLVE_UV_TRIDIAGO |
19 |
|
|
C | o Solve a pair of tri-diagonal system along X and Y lines |
20 |
|
|
C | (in X-dir for uFld and in Y-dir for vFld) |
21 |
|
|
C *==========================================================* |
22 |
|
|
C | o Used, e.g., in linear part of seaice LSR solver |
23 |
|
|
C *==========================================================* |
24 |
|
|
C \ev |
25 |
|
|
|
26 |
|
|
C !USES: |
27 |
|
|
IMPLICIT NONE |
28 |
|
|
C == Global data == |
29 |
|
|
#include "SIZE.h" |
30 |
|
|
#include "EEPARAMS.h" |
31 |
|
|
|
32 |
|
|
C !INPUT/OUTPUT PARAMETERS: |
33 |
|
|
C == Routine Arguments == |
34 |
|
|
C kSize :: size in 3rd dimension |
35 |
|
|
C ols :: size of overlap (of input arg array) |
36 |
|
|
C solve4u :: logical flag, do solve for u-component if true |
37 |
|
|
C solve4v :: logical flag, do solve for v-component if true |
38 |
|
|
C aU,bU,cU :: u-matrix (lower diagonal, main diagonal & upper diagonal) |
39 |
|
|
C rhsU :: RHS vector (u-component) |
40 |
|
|
C aV,bV,cV :: v-matrix (lower diagonal, main diagonal & upper diagonal) |
41 |
|
|
C rhsV :: RHS vector (v-component) |
42 |
|
|
C uFld :: X = solution of: A_u * X = rhsU |
43 |
|
|
C vFld :: X = solution of: A_v * X = rhsV |
44 |
|
|
C errCode :: > 0 if singular matrix |
45 |
|
|
C subIter :: current sub-iteration number |
46 |
|
|
C myIter :: current iteration number |
47 |
|
|
C myThid :: my Thread Id number |
48 |
|
|
INTEGER kSize, ols |
49 |
|
|
LOGICAL solve4u, solve4v |
50 |
|
|
_RL aU (1-ols:sNx+ols,1-ols:sNy+ols,kSize,nSx,nSy) |
51 |
|
|
_RL bU (1-ols:sNx+ols,1-ols:sNy+ols,kSize,nSx,nSy) |
52 |
|
|
_RL cU (1-ols:sNx+ols,1-ols:sNy+ols,kSize,nSx,nSy) |
53 |
|
|
_RL rhsU(1-ols:sNx+ols,1-ols:sNy+ols,kSize,nSx,nSy) |
54 |
|
|
_RL aV (1-ols:sNx+ols,1-ols:sNy+ols,kSize,nSx,nSy) |
55 |
|
|
_RL bV (1-ols:sNx+ols,1-ols:sNy+ols,kSize,nSx,nSy) |
56 |
|
|
_RL cV (1-ols:sNx+ols,1-ols:sNy+ols,kSize,nSx,nSy) |
57 |
|
|
_RL rhsV(1-ols:sNx+ols,1-ols:sNy+ols,kSize,nSx,nSy) |
58 |
|
|
_RL uFld(1-OLx:sNx+OLx,1-OLy:sNy+OLy,kSize,nSx,nSy) |
59 |
|
|
_RL vFld(1-OLx:sNx+OLx,1-OLy:sNy+OLy,kSize,nSx,nSy) |
60 |
|
|
INTEGER errCode |
61 |
|
|
INTEGER subIter, myIter, myThid |
62 |
|
|
|
63 |
|
|
C !SHARED LOCAL VARIABLES: |
64 |
|
|
C aTu, cTu, yTu :: tile edges coeff and RHS for u-component |
65 |
|
|
C aTv, cTv, yTv :: tile edges coeff and RHS for v-component |
66 |
|
|
COMMON /SOLVE_UV_3DIAG_LOCAL/ |
67 |
|
|
& aTu, cTu, yTu, aTv, cTv, yTv |
68 |
|
|
_RL aTu(2,1:sNy,nSx,nSy) |
69 |
|
|
_RL cTu(2,1:sNy,nSx,nSy) |
70 |
|
|
_RL yTu(2,1:sNy,nSx,nSy) |
71 |
|
|
_RL aTv(2,1:sNx,nSx,nSy) |
72 |
|
|
_RL cTv(2,1:sNx,nSx,nSy) |
73 |
|
|
_RL yTv(2,1:sNx,nSx,nSy) |
74 |
|
|
|
75 |
|
|
C !LOCAL VARIABLES: |
76 |
|
|
C == Local variables == |
77 |
|
|
INTEGER bi, bj, bm, bp |
78 |
|
|
INTEGER i,j,k |
79 |
|
|
INTEGER ii, im, ip |
80 |
|
|
INTEGER jj, jm, jp |
81 |
|
|
_RL tmpVar |
82 |
|
|
_RL uTmp1, uTmp2, vTmp1, vTmp2 |
83 |
|
|
_RL alpU(1:sNx,1:sNy,nSx,nSy) |
84 |
|
|
_RL gamU(1:sNx,1:sNy,nSx,nSy) |
85 |
|
|
_RL yy_U(1:sNx,1:sNy,nSx,nSy) |
86 |
|
|
_RL alpV(1:sNx,1:sNy,nSx,nSy) |
87 |
|
|
_RL gamV(1:sNx,1:sNy,nSx,nSy) |
88 |
|
|
_RL yy_V(1:sNx,1:sNy,nSx,nSy) |
89 |
|
|
CEOP |
90 |
|
|
|
91 |
|
|
errCode = 0 |
92 |
|
|
IF ( .NOT.solve4u .AND. .NOT.solve4v ) RETURN |
93 |
|
|
|
94 |
|
|
C-- outside loop on level number k |
95 |
|
|
DO k = 1,kSize |
96 |
|
|
|
97 |
|
|
IF ( solve4u ) THEN |
98 |
|
|
DO bj=myByLo(myThid),myByHi(myThid) |
99 |
|
|
DO bi=myBxLo(myThid),myBxHi(myThid) |
100 |
|
|
|
101 |
|
|
C-- work on local copy: |
102 |
|
|
DO j= 1,sNy |
103 |
|
|
DO i= 1,sNx |
104 |
|
|
alpU(i,j,bi,bj) = aU(i,j,k,bi,bj) |
105 |
|
|
gamU(i,j,bi,bj) = cU(i,j,k,bi,bj) |
106 |
|
|
yy_U(i,j,bi,bj) = rhsU(i,j,k,bi,bj) |
107 |
|
|
ENDDO |
108 |
|
|
ENDDO |
109 |
|
|
|
110 |
|
|
C-- Beginning of forward sweep (i=1) |
111 |
|
|
i = 1 |
112 |
|
|
DO j= 1,sNy |
113 |
|
|
C- normalise row [1] ( 1 on main diagonal) |
114 |
|
|
tmpVar = bU(i,j,k,bi,bj) |
115 |
|
|
IF ( tmpVar.NE.0. _d 0 ) THEN |
116 |
|
|
tmpVar = 1. _d 0 / tmpVar |
117 |
|
|
ELSE |
118 |
|
|
tmpVar = 0. _d 0 |
119 |
|
|
errCode = 1 |
120 |
|
|
ENDIF |
121 |
|
|
gamU(i,j,bi,bj) = gamU(i,j,bi,bj)*tmpVar |
122 |
|
|
alpU(i,j,bi,bj) = alpU(i,j,bi,bj)*tmpVar |
123 |
|
|
yy_U(i,j,bi,bj) = yy_U(i,j,bi,bj)*tmpVar |
124 |
|
|
ENDDO |
125 |
|
|
|
126 |
|
|
C-- Middle of forward sweep (i=2:sNx) |
127 |
|
|
DO j= 1,sNy |
128 |
|
|
DO i= 2,sNx |
129 |
|
|
im = i-1 |
130 |
|
|
C- update row [i] <-- [i] - alp_i * [i-1] and normalise (main diagonal = 1) |
131 |
|
|
tmpVar = bU(i,j,k,bi,bj) - alpU(i,j,bi,bj)*gamU(im,j,bi,bj) |
132 |
|
|
IF ( tmpVar.NE.0. _d 0 ) THEN |
133 |
|
|
tmpVar = 1. _d 0 / tmpVar |
134 |
|
|
ELSE |
135 |
|
|
tmpVar = 0. _d 0 |
136 |
|
|
errCode = 1 |
137 |
|
|
ENDIF |
138 |
|
|
yy_U(i,j,bi,bj) = ( yy_U(i,j,bi,bj) |
139 |
|
|
& - alpU(i,j,bi,bj)*yy_U(im,j,bi,bj) |
140 |
|
|
& )*tmpVar |
141 |
|
|
gamU(i,j,bi,bj) = gamU(i,j,bi,bj)*tmpVar |
142 |
|
|
alpU(i,j,bi,bj) = - alpU(i,j,bi,bj)*alpU(im,j,bi,bj)*tmpVar |
143 |
|
|
ENDDO |
144 |
|
|
ENDDO |
145 |
|
|
|
146 |
|
|
C-- Backward sweep (i=sNx-1:-1:1) |
147 |
|
|
DO j= 1,sNy |
148 |
|
|
DO ii= 1,sNx-1 |
149 |
|
|
i = sNx - ii |
150 |
|
|
ip = i+1 |
151 |
|
|
C- update row [i] <-- [i] - gam_i * [i+1] |
152 |
|
|
yy_U(i,j,bi,bj) = yy_U(i,j,bi,bj) |
153 |
|
|
& - gamU(i,j,bi,bj)*yy_U(ip,j,bi,bj) |
154 |
|
|
alpU(i,j,bi,bj) = alpU(i,j,bi,bj) |
155 |
|
|
& - gamU(i,j,bi,bj)*alpU(ip,j,bi,bj) |
156 |
|
|
gamU(i,j,bi,bj) = -gamU(i,j,bi,bj)*gamU(ip,j,bi,bj) |
157 |
|
|
ENDDO |
158 |
|
|
ENDDO |
159 |
|
|
|
160 |
|
|
C-- At this stage, the 3-diagonal system is reduced to Identity with two |
161 |
|
|
C more columns (alp & gam) corresponding to unknow X(i=0) and X(i=sNx+1): |
162 |
|
|
C X_0 |
163 |
|
|
C alp 1 0 ... 0 0 gam X_1 Y_1 |
164 |
|
|
C alp 0 1 ... 0 0 gam X_2 Y_2 |
165 |
|
|
C |
166 |
|
|
C . . . ... . . . . . |
167 |
|
|
C ( . . . ... . . . )( . ) = ( . ) |
168 |
|
|
C . . . ... . . . . . |
169 |
|
|
C |
170 |
|
|
C alp 0 0 ... 1 0 gam X_n-1 Y_n-1 |
171 |
|
|
C alp 0 0 ... 0 1 gam X_n Y_n |
172 |
|
|
C X_n+1 |
173 |
|
|
C----- |
174 |
|
|
|
175 |
|
|
C-- Store tile edges coeff: (1) <--> i=1 ; (2) <--> i=sNx |
176 |
|
|
DO j= 1,sNy |
177 |
|
|
aTu(1,j,bi,bj) = alpU( 1, j,bi,bj) |
178 |
|
|
cTu(1,j,bi,bj) = gamU( 1, j,bi,bj) |
179 |
|
|
yTu(1,j,bi,bj) = yy_U( 1, j,bi,bj) |
180 |
|
|
aTu(2,j,bi,bj) = alpU(sNx,j,bi,bj) |
181 |
|
|
cTu(2,j,bi,bj) = gamU(sNx,j,bi,bj) |
182 |
|
|
yTu(2,j,bi,bj) = yy_U(sNx,j,bi,bj) |
183 |
|
|
ENDDO |
184 |
|
|
|
185 |
|
|
C end bi,bj-loops |
186 |
|
|
ENDDO |
187 |
|
|
ENDDO |
188 |
|
|
|
189 |
|
|
C-- Solve for tile edges values |
190 |
|
|
IF ( nPx*nPy.GT.1 .OR. useCubedSphereExchange ) THEN |
191 |
|
|
STOP 'ABNORMAL END: S/R SOLVE_UV_TRIDIAGO: missing code' |
192 |
|
|
ENDIF |
193 |
|
|
_BARRIER |
194 |
|
|
_BEGIN_MASTER(myThid) |
195 |
|
|
DO bj=1,nSy |
196 |
|
|
DO j=1,sNy |
197 |
|
|
|
198 |
|
|
DO bi=2,nSx |
199 |
|
|
bm = bi-1 |
200 |
|
|
C- update row [1,bi] <- [1,bi] - a(1,bi)*[2,bi-1] (& normalise diag) |
201 |
|
|
tmpVar = oneRL - aTu(1,j,bi,bj)*cTu(2,j,bm,bj) |
202 |
|
|
IF ( tmpVar.NE.0. _d 0 ) THEN |
203 |
|
|
tmpVar = 1. _d 0 / tmpVar |
204 |
|
|
ELSE |
205 |
|
|
tmpVar = 0. _d 0 |
206 |
|
|
errCode = 1 |
207 |
|
|
ENDIF |
208 |
|
|
yTu(1,j,bi,bj) = ( yTu(1,j,bi,bj) |
209 |
|
|
& - aTu(1,j,bi,bj)*yTu(2,j,bm,bj) |
210 |
|
|
& )*tmpVar |
211 |
|
|
cTu(1,j,bi,bj) = cTu(1,j,bi,bj)*tmpVar |
212 |
|
|
aTu(1,j,bi,bj) = - aTu(1,j,bi,bj)*aTu(2,j,bm,bj)*tmpVar |
213 |
|
|
|
214 |
|
|
C- update row [2,bi] <- [2,bi] - a(2,bi)*[2,bi-1] + a(2,bi)*c(2,bi-1)*[1,bi] |
215 |
|
|
tmpVar = aTu(2,j,bi,bj)*cTu(2,j,bm,bj) |
216 |
|
|
yTu(2,j,bi,bj) = yTu(2,j,bi,bj) |
217 |
|
|
& - aTu(2,j,bi,bj)*yTu(2,j,bm,bj) |
218 |
|
|
& + tmpVar*yTu(1,j,bi,bj) |
219 |
|
|
cTu(2,j,bi,bj) = cTu(2,j,bi,bj) |
220 |
|
|
& + tmpVar*cTu(1,j,bi,bj) |
221 |
|
|
aTu(2,j,bi,bj) = -aTu(2,j,bi,bj)*aTu(2,j,bm,bj) |
222 |
|
|
& + tmpVar*aTu(1,j,bi,bj) |
223 |
|
|
ENDDO |
224 |
|
|
|
225 |
|
|
DO bi=nSx-1,1,-1 |
226 |
|
|
bp = bi+1 |
227 |
|
|
DO i=1,2 |
228 |
|
|
C- update row [1,bi] <- [1,bi] - c(1,bi)*[1,bi+1] |
229 |
|
|
C- update row [2,bi] <- [2,bi] - c(2,bi)*[1,bi+1] |
230 |
|
|
aTu(i,j,bi,bj) = aTu(i,j,bi,bj) |
231 |
|
|
& - cTu(i,j,bi,bj)*aTu(1,j,bp,bj) |
232 |
|
|
yTu(i,j,bi,bj) = yTu(i,j,bi,bj) |
233 |
|
|
& - cTu(i,j,bi,bj)*yTu(1,j,bp,bj) |
234 |
|
|
cTu(i,j,bi,bj) = -cTu(i,j,bi,bj)*cTu(1,j,bp,bj) |
235 |
|
|
ENDDO |
236 |
|
|
ENDDO |
237 |
|
|
|
238 |
|
|
C-- periodic in X: X_0 <=> X_Nx and X_(N+1) <=> X_1 ; |
239 |
|
|
C find the value at the 2 opposite location (i=1 and i=Nx) |
240 |
|
|
bm = 1 |
241 |
|
|
bp = nSx |
242 |
|
|
cTu(1,j,bm,bj) = oneRL + cTu(1,j,bm,bj) |
243 |
|
|
aTu(2,j,bp,bj) = oneRL + aTu(2,j,bp,bj) |
244 |
|
|
tmpVar = cTu(1,j,bm,bj) * aTu(2,j,bp,bj) |
245 |
|
|
& - aTu(1,j,bm,bj) * cTu(2,j,bp,bj) |
246 |
|
|
IF ( tmpVar.NE.0. _d 0 ) THEN |
247 |
|
|
tmpVar = 1. _d 0 / tmpVar |
248 |
|
|
ELSE |
249 |
|
|
tmpVar = 0. _d 0 |
250 |
|
|
errCode = 1 |
251 |
|
|
ENDIF |
252 |
|
|
uTmp1 = ( aTu(2,j,bp,bj) * yTu(1,j,bm,bj) |
253 |
|
|
& - aTu(1,j,bm,bj) * yTu(2,j,bp,bj) |
254 |
|
|
& )*tmpVar |
255 |
|
|
uTmp2 = ( cTu(1,j,bm,bj) * yTu(2,j,bp,bj) |
256 |
|
|
& - cTu(2,j,bp,bj) * yTu(1,j,bm,bj) |
257 |
|
|
& )*tmpVar |
258 |
|
|
|
259 |
|
|
C- finalise tile-edges solution (put into RHS "yTu"): |
260 |
|
|
DO bi=1,nSx |
261 |
|
|
DO i=1,2 |
262 |
|
|
IF ( bi+i .EQ.2 ) THEN |
263 |
|
|
yTu(i,j,bi,bj) = uTmp1 |
264 |
|
|
ELSEIF ( bi+i .EQ. nSx+2 ) THEN |
265 |
|
|
yTu(i,j,bi,bj) = uTmp2 |
266 |
|
|
ELSE |
267 |
|
|
yTu(i,j,bi,bj) = yTu(i,j,bi,bj) |
268 |
|
|
& - aTu(i,j,bi,bj) * uTmp2 |
269 |
|
|
& - cTu(i,j,bi,bj) * uTmp1 |
270 |
|
|
ENDIF |
271 |
|
|
ENDDO |
272 |
|
|
ENDDO |
273 |
|
|
|
274 |
|
|
ENDDO |
275 |
|
|
ENDDO |
276 |
|
|
_END_MASTER(myThid) |
277 |
|
|
_BARRIER |
278 |
|
|
|
279 |
|
|
DO bj=myByLo(myThid),myByHi(myThid) |
280 |
|
|
DO bi=myBxLo(myThid),myBxHi(myThid) |
281 |
|
|
bm = 1 + MOD(bi-2+nSx,nSx) |
282 |
|
|
bp = 1 + MOD(bi-0+nSx,nSx) |
283 |
|
|
DO j= 1,sNy |
284 |
|
|
DO i= 1,sNx |
285 |
|
|
uFld(i,j,k,bi,bj) = yy_U(i,j,bi,bj) |
286 |
|
|
& - alpU(i,j,bi,bj) * yTu(2,j,bm,bj) |
287 |
|
|
& - gamU(i,j,bi,bj) * yTu(1,j,bp,bj) |
288 |
|
|
ENDDO |
289 |
|
|
ENDDO |
290 |
|
|
ENDDO |
291 |
|
|
ENDDO |
292 |
|
|
|
293 |
|
|
C end solve for uFld |
294 |
|
|
ENDIF |
295 |
|
|
|
296 |
|
|
IF ( solve4v ) THEN |
297 |
|
|
DO bj=myByLo(myThid),myByHi(myThid) |
298 |
|
|
DO bi=myBxLo(myThid),myBxHi(myThid) |
299 |
|
|
|
300 |
|
|
C-- work on local copy: |
301 |
|
|
DO j= 1,sNy |
302 |
|
|
DO i= 1,sNx |
303 |
|
|
alpV(i,j,bi,bj) = aV(i,j,k,bi,bj) |
304 |
|
|
gamV(i,j,bi,bj) = cV(i,j,k,bi,bj) |
305 |
|
|
yy_V(i,j,bi,bj) = rhsV(i,j,k,bi,bj) |
306 |
|
|
ENDDO |
307 |
|
|
ENDDO |
308 |
|
|
|
309 |
|
|
C-- Beginning of forward sweep (j=1) |
310 |
|
|
j = 1 |
311 |
|
|
DO i= 1,sNx |
312 |
|
|
C- normalise row [1] ( 1 on main diagonal) |
313 |
|
|
tmpVar = bV(i,j,k,bi,bj) |
314 |
|
|
IF ( tmpVar.NE.0. _d 0 ) THEN |
315 |
|
|
tmpVar = 1. _d 0 / tmpVar |
316 |
|
|
ELSE |
317 |
|
|
tmpVar = 0. _d 0 |
318 |
|
|
errCode = 1 |
319 |
|
|
ENDIF |
320 |
|
|
gamV(i,j,bi,bj) = gamV(i,j,bi,bj)*tmpVar |
321 |
|
|
alpV(i,j,bi,bj) = alpV(i,j,bi,bj)*tmpVar |
322 |
|
|
yy_V(i,j,bi,bj) = yy_V(i,j,bi,bj)*tmpVar |
323 |
|
|
ENDDO |
324 |
|
|
|
325 |
|
|
C-- Middle of forward sweep (j=2:sNy) |
326 |
|
|
DO i= 1,sNx |
327 |
|
|
DO j= 2,sNy |
328 |
|
|
jm = j-1 |
329 |
|
|
C- update row [j] <-- [j] - alp_j * [j-1] and normalise (main diagonal = 1) |
330 |
|
|
tmpVar = bV(i,j,k,bi,bj) - alpV(i,j,bi,bj)*gamV(i,jm,bi,bj) |
331 |
|
|
IF ( tmpVar.NE.0. _d 0 ) THEN |
332 |
|
|
tmpVar = 1. _d 0 / tmpVar |
333 |
|
|
ELSE |
334 |
|
|
tmpVar = 0. _d 0 |
335 |
|
|
errCode = 1 |
336 |
|
|
ENDIF |
337 |
|
|
yy_V(i,j,bi,bj) = ( yy_V(i,j,bi,bj) |
338 |
|
|
& - alpV(i,j,bi,bj)*yy_V(i,jm,bi,bj) |
339 |
|
|
& )*tmpVar |
340 |
|
|
gamV(i,j,bi,bj) = gamV(i,j,bi,bj)*tmpVar |
341 |
|
|
alpV(i,j,bi,bj) = - alpV(i,j,bi,bj)*alpV(i,jm,bi,bj)*tmpVar |
342 |
|
|
ENDDO |
343 |
|
|
ENDDO |
344 |
|
|
|
345 |
|
|
C-- Backward sweep (j=sNy-1:-1:1) |
346 |
|
|
DO i= 1,sNx |
347 |
|
|
DO jj= 1,sNy-1 |
348 |
|
|
j = sNy - jj |
349 |
|
|
jp = j+1 |
350 |
|
|
C- update row [j] <-- [j] - gam_j * [j+1] |
351 |
|
|
yy_V(i,j,bi,bj) = yy_V(i,j,bi,bj) |
352 |
|
|
& - gamV(i,j,bi,bj)*yy_V(i,jp,bi,bj) |
353 |
|
|
alpV(i,j,bi,bj) = alpV(i,j,bi,bj) |
354 |
|
|
& - gamV(i,j,bi,bj)*alpV(i,jp,bi,bj) |
355 |
|
|
gamV(i,j,bi,bj) = -gamV(i,j,bi,bj)*gamV(i,jp,bi,bj) |
356 |
|
|
ENDDO |
357 |
|
|
ENDDO |
358 |
|
|
|
359 |
|
|
C-- At this stage, the 3-diagonal system is reduced to Identity with two |
360 |
|
|
C more columns (alp & gam) corresponding to unknow X(j=0) and X(j=sNy+1) |
361 |
|
|
|
362 |
|
|
C-- Store tile edges coeff: (1) <--> j=1 ; (2) <--> j=sNy |
363 |
|
|
DO i= 1,sNx |
364 |
|
|
aTv(1,i,bi,bj) = alpV(i, 1, bi,bj) |
365 |
|
|
cTv(1,i,bi,bj) = gamV(i, 1, bi,bj) |
366 |
|
|
yTv(1,i,bi,bj) = yy_V(i, 1, bi,bj) |
367 |
|
|
aTv(2,i,bi,bj) = alpV(i,sNy,bi,bj) |
368 |
|
|
cTv(2,i,bi,bj) = gamV(i,sNy,bi,bj) |
369 |
|
|
yTv(2,i,bi,bj) = yy_V(i,sNy,bi,bj) |
370 |
|
|
ENDDO |
371 |
|
|
|
372 |
|
|
C end bi,bj-loops |
373 |
|
|
ENDDO |
374 |
|
|
ENDDO |
375 |
|
|
|
376 |
|
|
C-- Solve for tile edges values |
377 |
|
|
IF ( nPx*nPy.GT.1 .OR. useCubedSphereExchange ) THEN |
378 |
|
|
STOP 'ABNORMAL END: S/R SOLVE_UV_TRIDIAGO: missing code' |
379 |
|
|
ENDIF |
380 |
|
|
_BARRIER |
381 |
|
|
_BEGIN_MASTER(myThid) |
382 |
|
|
DO bi=1,nSx |
383 |
|
|
DO i=1,sNx |
384 |
|
|
|
385 |
|
|
DO bj=2,nSy |
386 |
|
|
bm = bj-1 |
387 |
|
|
C- update row [1,bj] <- [1,bj] - a(1,bj)*[2,bj-1] (& normalise diag) |
388 |
|
|
tmpVar = oneRL - aTv(1,i,bi,bj)*cTv(2,i,bi,bm) |
389 |
|
|
IF ( tmpVar.NE.0. _d 0 ) THEN |
390 |
|
|
tmpVar = 1. _d 0 / tmpVar |
391 |
|
|
ELSE |
392 |
|
|
tmpVar = 0. _d 0 |
393 |
|
|
errCode = 1 |
394 |
|
|
ENDIF |
395 |
|
|
yTv(1,i,bi,bj) = ( yTv(1,i,bi,bj) |
396 |
|
|
& - aTv(1,i,bi,bj)*yTv(2,i,bi,bm) |
397 |
|
|
& )*tmpVar |
398 |
|
|
cTv(1,i,bi,bj) = cTv(1,i,bi,bj)*tmpVar |
399 |
|
|
aTv(1,i,bi,bj) = - aTv(1,i,bi,bj)*aTv(2,i,bi,bm)*tmpVar |
400 |
|
|
|
401 |
|
|
C- update row [2,bj] <- [2,bj] - a(2,bj)*[2,bj-1] + a(2,bj)*c(2,bj-1)*[1,bj] |
402 |
|
|
tmpVar = aTv(2,i,bi,bj)*cTv(2,i,bi,bm) |
403 |
|
|
yTv(2,i,bi,bj) = yTv(2,i,bi,bj) |
404 |
|
|
& - aTv(2,i,bi,bj)*yTv(2,i,bi,bm) |
405 |
|
|
& + tmpVar*yTv(1,i,bi,bj) |
406 |
|
|
cTv(2,i,bi,bj) = cTv(2,i,bi,bj) |
407 |
|
|
& + tmpVar*cTv(1,i,bi,bj) |
408 |
|
|
aTv(2,i,bi,bj) = -aTv(2,i,bi,bj)*aTv(2,i,bi,bm) |
409 |
|
|
& + tmpVar*aTv(1,i,bi,bj) |
410 |
|
|
ENDDO |
411 |
|
|
|
412 |
|
|
DO bj=nSy-1,1,-1 |
413 |
|
|
bp = bj+1 |
414 |
|
|
DO j=1,2 |
415 |
|
|
C- update row [1,bj] <- [1,bj] - c(1,bj)*[1,bj+1] |
416 |
|
|
C- update row [2,bj] <- [2,bj] - c(2,bj)*[1,bj+1] |
417 |
|
|
aTv(j,i,bi,bj) = aTv(j,i,bi,bj) |
418 |
|
|
& - cTv(j,i,bi,bj)*aTv(1,i,bi,bp) |
419 |
|
|
yTv(j,i,bi,bj) = yTv(j,i,bi,bj) |
420 |
|
|
& - cTv(j,i,bi,bj)*yTv(1,i,bi,bp) |
421 |
|
|
cTv(j,i,bi,bj) = -cTv(j,i,bi,bj)*cTv(1,i,bi,bp) |
422 |
|
|
ENDDO |
423 |
|
|
ENDDO |
424 |
|
|
|
425 |
|
|
C-- periodic in Y: X_0 <=> X_Ny and X_(N+1) <=> X_1 ; |
426 |
|
|
C find the value at the 2 opposite location (j=1 and j=Ny) |
427 |
|
|
bm = 1 |
428 |
|
|
bp = nSy |
429 |
|
|
cTv(1,i,bi,bm) = oneRL + cTv(1,i,bi,bm) |
430 |
|
|
aTv(2,i,bi,bp) = oneRL + aTv(2,i,bi,bp) |
431 |
|
|
tmpVar = cTv(1,i,bi,bm) * aTv(2,i,bi,bp) |
432 |
|
|
& - aTv(1,i,bi,bm) * cTv(2,i,bi,bp) |
433 |
|
|
IF ( tmpVar.NE.0. _d 0 ) THEN |
434 |
|
|
tmpVar = 1. _d 0 / tmpVar |
435 |
|
|
ELSE |
436 |
|
|
tmpVar = 0. _d 0 |
437 |
|
|
errCode = 1 |
438 |
|
|
ENDIF |
439 |
|
|
vTmp1 = ( aTv(2,i,bi,bp) * yTv(1,i,bi,bm) |
440 |
|
|
& - aTv(1,i,bi,bm) * yTv(2,i,bi,bp) |
441 |
|
|
& )*tmpVar |
442 |
|
|
vTmp2 = ( cTv(1,i,bi,bm) * yTv(2,i,bi,bp) |
443 |
|
|
& - cTv(2,i,bi,bp) * yTv(1,i,bi,bm) |
444 |
|
|
& )*tmpVar |
445 |
|
|
|
446 |
|
|
C- finalise tile-edges solution (put into RHS "yTv"): |
447 |
|
|
DO bj=1,nSy |
448 |
|
|
DO j=1,2 |
449 |
|
|
IF ( bj+j .EQ.2 ) THEN |
450 |
|
|
yTv(j,i,bi,bj) = vTmp1 |
451 |
|
|
ELSEIF ( bj+j .EQ. nSy+2 ) THEN |
452 |
|
|
yTv(j,i,bi,bj) = vTmp2 |
453 |
|
|
ELSE |
454 |
|
|
yTv(j,i,bi,bj) = yTv(j,i,bi,bj) |
455 |
|
|
& - aTv(j,i,bi,bj) * vTmp2 |
456 |
|
|
& - cTv(j,i,bi,bj) * vTmp1 |
457 |
|
|
ENDIF |
458 |
|
|
ENDDO |
459 |
|
|
ENDDO |
460 |
|
|
|
461 |
|
|
ENDDO |
462 |
|
|
ENDDO |
463 |
|
|
_END_MASTER(myThid) |
464 |
|
|
_BARRIER |
465 |
|
|
|
466 |
|
|
DO bj=myByLo(myThid),myByHi(myThid) |
467 |
|
|
DO bi=myBxLo(myThid),myBxHi(myThid) |
468 |
|
|
bm = 1 + MOD(bj-2+nSy,nSy) |
469 |
|
|
bp = 1 + MOD(bj-0+nSy,nSy) |
470 |
|
|
DO j= 1,sNy |
471 |
|
|
DO i= 1,sNx |
472 |
|
|
vFld(i,j,k,bi,bj) = yy_V(i,j,bi,bj) |
473 |
|
|
& - alpV(i,j,bi,bj) * yTv(2,i,bi,bm) |
474 |
|
|
& - gamV(i,j,bi,bj) * yTv(1,i,bi,bp) |
475 |
|
|
ENDDO |
476 |
|
|
ENDDO |
477 |
|
|
ENDDO |
478 |
|
|
ENDDO |
479 |
|
|
|
480 |
|
|
C end solve for vFld |
481 |
|
|
ENDIF |
482 |
|
|
|
483 |
|
|
C end k-loop |
484 |
|
|
ENDDO |
485 |
|
|
|
486 |
|
|
RETURN |
487 |
|
|
END |