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 |