/[MITgcm]/MITgcm/pkg/diagnostics/diag_cg2d.F
ViewVC logotype

Contents of /MITgcm/pkg/diagnostics/diag_cg2d.F

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.4 - (show annotations) (download)
Wed Aug 24 02:23:41 2011 UTC (12 years, 8 months ago) by jmc
Branch: MAIN
CVS Tags: checkpoint63h, checkpoint63i, checkpoint63j, checkpoint63k, checkpoint63d, checkpoint63e, checkpoint63f, checkpoint63g, checkpoint63b, checkpoint63c
Changes since 1.3: +15 -1 lines
Initialise main diagonal (aC2d) to get valid value in overlap regions
 (in case EXCH call do not fill them all)

1 C $Header: /u/gcmpack/MITgcm/pkg/diagnostics/diag_cg2d.F,v 1.3 2011/08/01 20:40:43 jmc Exp $
2 C $Name: $
3
4 #include "DIAG_OPTIONS.h"
5 #undef DEBUG_DIAG_CG2D
6
7 CBOP
8 C !ROUTINE: DIAG_CG2D
9 C !INTERFACE:
10 SUBROUTINE DIAG_CG2D(
11 I aW2d, aS2d, b2d,
12 I residCriter,
13 O firstResidual, minResidual, lastResidual,
14 U x2d, numIters,
15 O nIterMin,
16 I printResidFrq, myThid )
17 C !DESCRIPTION: \bv
18 C *==========================================================*
19 C | SUBROUTINE CG2D
20 C | o Two-dimensional grid problem conjugate-gradient
21 C | inverter (with preconditioner).
22 C *==========================================================*
23 C | Con. grad is an iterative procedure for solving Ax = b.
24 C | It requires the A be symmetric.
25 C | This implementation assumes A is a five-diagonal
26 C | matrix of the form that arises in the discrete
27 C | representation of the del^2 operator in a
28 C | two-dimensional space.
29 C *==========================================================*
30 C \ev
31
32 C !USES:
33 IMPLICIT NONE
34 C === Global data ===
35 #include "SIZE.h"
36 #include "EEPARAMS.h"
37 #include "PARAMS.h"
38
39 C !INPUT/OUTPUT PARAMETERS:
40 C === Routine arguments ===
41 C b2d :: The source term or "right hand side"
42 C x2d :: The solution
43 C firstResidual :: the initial residual before any iterations
44 C minResidual :: the lowest residual reached
45 C lastResidual :: the actual residual reached
46 C numIters :: Entry: the maximum number of iterations allowed
47 C Exit: the actual number of iterations used
48 C nIterMin :: iteration number corresponding to lowest residual
49 C printResidFrq :: Frequency for printing residual in CG iterations
50 C myThid :: my Thread Id number
51 _RS aW2d(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
52 _RS aS2d(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
53 _RL b2d (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
54 _RL residCriter
55 _RL firstResidual
56 _RL minResidual
57 _RL lastResidual
58 _RL x2d (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
59 INTEGER numIters
60 INTEGER nIterMin
61 INTEGER printResidFrq
62 INTEGER myThid
63
64 C !LOCAL VARIABLES:
65 C === Local variables ====
66 C bi, bj :: tile indices
67 C eta_qrN :: Used in computing search directions
68 C eta_qrNM1 suffix N and NM1 denote current and
69 C cgBeta previous iterations respectively.
70 C alpha
71 C sumRHS :: Sum of right-hand-side. Sometimes this is a
72 C useful debuggin/trouble shooting diagnostic.
73 C For neumann problems sumRHS needs to be ~0.
74 C or they converge at a non-zero residual.
75 C err :: Measure of current residual of Ax - b, usually the norm.
76 C i, j, it2d :: Loop counters ( it2d counts CG iterations )
77 INTEGER bi, bj
78 INTEGER i, j, it2d
79 _RL err, errTile(nSx,nSy)
80 _RL eta_qrN, eta_qrNtile(nSx,nSy)
81 _RL eta_qrNM1
82 _RL cgBeta
83 _RL alpha, alphaTile(nSx,nSy)
84 _RL sumRHS, sumRHStile(nSx,nSy)
85 _RL pW_tmp, pS_tmp
86 _RL diagCG_pcOffDFac
87 CHARACTER*(MAX_LEN_MBUF) msgBuf
88 LOGICAL printResidual
89 CEOP
90 _RS aC2d(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
91 _RS pW (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
92 _RS pS (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
93 _RS pC (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
94 _RL q2d(1-1:sNx+1,1-1:sNy+1,nSx,nSy)
95 #ifdef DEBUG_DIAG_CG2D
96 CHARACTER*(10) sufx
97 _RL r2d(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
98 #else
99 _RL r2d(1-1:sNx+1,1-1:sNy+1,nSx,nSy)
100 #endif
101 _RL s2d(1-1:sNx+1,1-1:sNy+1,nSx,nSy)
102 _RL x2dm(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
103
104 #ifdef ALLOW_DEBUG
105 IF (debugMode) CALL DEBUG_ENTER('DIAG_CG2D',myThid)
106 #endif
107
108 C-- Set matrice main diagnonal:
109 DO bj=myByLo(myThid),myByHi(myThid)
110 DO bi=myBxLo(myThid),myBxHi(myThid)
111 C- Initialise overlap regions (in case EXCH call do not fill them all)
112 DO j = 1-Oly,sNy+Oly
113 DO i = 1-Olx,sNx+Olx
114 aC2d(i,j,bi,bj) = 0.
115 ENDDO
116 ENDDO
117 DO j=1,sNy
118 DO i=1,sNx
119 aC2d(i,j,bi,bj) = -( ( aW2d(i,j,bi,bj)+aW2d(i+1,j,bi,bj) )
120 & +( aS2d(i,j,bi,bj)+aS2d(i,j+1,bi,bj) )
121 & )
122 ENDDO
123 ENDDO
124 ENDDO
125 ENDDO
126 CALL EXCH_XY_RS(aC2d, myThid)
127
128 C-- Initialise preconditioner
129 diagCG_pcOffDFac = cg2dpcOffDFac
130 DO bj=myByLo(myThid),myByHi(myThid)
131 DO bi=myBxLo(myThid),myBxHi(myThid)
132 DO j=1,sNy+1
133 DO i=1,sNx+1
134 IF ( aC2d(i,j,bi,bj) .EQ. 0. ) THEN
135 pC(i,j,bi,bj) = 1. _d 0
136 ELSE
137 pC(i,j,bi,bj) = 1. _d 0 / aC2d(i,j,bi,bj)
138 ENDIF
139 pW_tmp = aC2d(i,j,bi,bj)+aC2d(i-1,j,bi,bj)
140 IF ( pW_tmp .EQ. 0. ) THEN
141 pW(i,j,bi,bj) = 0.
142 ELSE
143 pW(i,j,bi,bj) = -aW2d(i,j,bi,bj)
144 & /( (diagCG_pcOffDFac*pW_tmp)**2 )
145 ENDIF
146 pS_tmp = aC2d(i,j,bi,bj)+aC2d(i,j-1,bi,bj)
147 IF ( pS_tmp .EQ. 0. ) THEN
148 pS(i,j,bi,bj) = 0.
149 ELSE
150 pS(i,j,bi,bj) = -aS2d(i,j,bi,bj)
151 & /( (diagCG_pcOffDFac*pS_tmp)**2 )
152 ENDIF
153 c pC(i,j,bi,bj) = 1.
154 c pW(i,j,bi,bj) = 0.
155 c pS(i,j,bi,bj) = 0.
156 ENDDO
157 ENDDO
158 ENDDO
159 ENDDO
160
161 C-- Initialise inverter
162 eta_qrNM1 = 1. _d 0
163
164 CALL EXCH_XY_RL( x2d, myThid )
165
166 C-- Initial residual calculation
167 DO bj=myByLo(myThid),myByHi(myThid)
168 DO bi=myBxLo(myThid),myBxHi(myThid)
169 DO j=1-1,sNy+1
170 DO i=1-1,sNx+1
171 s2d(i,j,bi,bj) = 0.
172 x2dm(i,j,bi,bj) = x2d(i,j,bi,bj)
173 ENDDO
174 ENDDO
175 sumRHStile(bi,bj) = 0. _d 0
176 errTile(bi,bj) = 0. _d 0
177 DO j=1,sNy
178 DO i=1,sNx
179 r2d(i,j,bi,bj) = b2d(i,j,bi,bj) -
180 & (aW2d(i ,j ,bi,bj)*x2d(i-1,j ,bi,bj)
181 & +aW2d(i+1,j ,bi,bj)*x2d(i+1,j ,bi,bj)
182 & +aS2d(i ,j ,bi,bj)*x2d(i ,j-1,bi,bj)
183 & +aS2d(i ,j+1,bi,bj)*x2d(i ,j+1,bi,bj)
184 & +aC2d(i ,j ,bi,bj)*x2d(i ,j ,bi,bj)
185 & )
186 errTile(bi,bj) = errTile(bi,bj)
187 & + r2d(i,j,bi,bj)*r2d(i,j,bi,bj)
188 sumRHStile(bi,bj) = sumRHStile(bi,bj) + b2d(i,j,bi,bj)
189 ENDDO
190 ENDDO
191 ENDDO
192 ENDDO
193 #ifdef DEBUG_DIAG_CG2D
194 CALL EXCH_XY_RL ( r2d, myThid )
195 #else
196 CALL EXCH_S3D_RL( r2d, 1, myThid )
197 #endif
198 CALL GLOBAL_SUM_TILE_RL( errTile, err, myThid )
199 IF ( printResidFrq.GE.1 )
200 & CALL GLOBAL_SUM_TILE_RL( sumRHStile, sumRHS, myThid )
201 err = SQRT(err)
202 it2d = 0
203 firstResidual = err
204 minResidual = err
205 nIterMin = it2d
206
207 printResidual = .FALSE.
208 IF ( debugLevel .GE. debLevZero ) THEN
209 _BEGIN_MASTER( myThid )
210 printResidual = printResidFrq.GE.1
211 IF ( printResidual ) THEN
212 WRITE(msgBuf,'(2A,I6,A,1PE17.9,A,1PE14.6)')' diag_cg2d:',
213 & ' iter=', it2d, ' ; resid.=', err, ' ; sumRHS=', sumRHS
214 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
215 & SQUEEZE_RIGHT, myThid )
216 ENDIF
217 _END_MASTER( myThid )
218 ENDIF
219 #ifdef DEBUG_DIAG_CG2D
220 IF ( printResidFrq.GE.1 ) THEN
221 WRITE(sufx,'(I10.10)') 0
222 CALL WRITE_FLD_XY_RL( 'r2d.',sufx, r2d, 1, myThid )
223 ENDIF
224 #endif
225
226 IF ( err .LT. residCriter ) GOTO 11
227
228 C >>>>>>>>>>>>>>> BEGIN SOLVER <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
229 DO 10 it2d=1, numIters
230
231 C-- Solve preconditioning equation and update
232 C-- conjugate direction vector "s".
233 DO bj=myByLo(myThid),myByHi(myThid)
234 DO bi=myBxLo(myThid),myBxHi(myThid)
235 eta_qrNtile(bi,bj) = 0. _d 0
236 DO j=1,sNy
237 DO i=1,sNx
238 q2d(i,j,bi,bj) =
239 & pC(i ,j ,bi,bj)*r2d(i ,j ,bi,bj)
240 & +pW(i ,j ,bi,bj)*r2d(i-1,j ,bi,bj)
241 & +pW(i+1,j ,bi,bj)*r2d(i+1,j ,bi,bj)
242 & +pS(i ,j ,bi,bj)*r2d(i ,j-1,bi,bj)
243 & +pS(i ,j+1,bi,bj)*r2d(i ,j+1,bi,bj)
244 eta_qrNtile(bi,bj) = eta_qrNtile(bi,bj)
245 & +q2d(i,j,bi,bj)*r2d(i,j,bi,bj)
246 ENDDO
247 ENDDO
248 ENDDO
249 ENDDO
250
251 CALL GLOBAL_SUM_TILE_RL( eta_qrNtile,eta_qrN,myThid )
252 cgBeta = eta_qrN/eta_qrNM1
253 eta_qrNM1 = eta_qrN
254
255 DO bj=myByLo(myThid),myByHi(myThid)
256 DO bi=myBxLo(myThid),myBxHi(myThid)
257 DO j=1,sNy
258 DO i=1,sNx
259 s2d(i,j,bi,bj) = q2d(i,j,bi,bj)
260 & + cgBeta*s2d(i,j,bi,bj)
261 ENDDO
262 ENDDO
263 ENDDO
264 ENDDO
265
266 C-- Do exchanges that require messages i.e. between processes.
267 CALL EXCH_S3D_RL( s2d, 1, myThid )
268
269 C== Evaluate laplace operator on conjugate gradient vector
270 C== q = A.s
271 DO bj=myByLo(myThid),myByHi(myThid)
272 DO bi=myBxLo(myThid),myBxHi(myThid)
273 alphaTile(bi,bj) = 0. _d 0
274 DO j=1,sNy
275 DO i=1,sNx
276 q2d(i,j,bi,bj) =
277 & aW2d(i ,j ,bi,bj)*s2d(i-1,j ,bi,bj)
278 & +aW2d(i+1,j ,bi,bj)*s2d(i+1,j ,bi,bj)
279 & +aS2d(i ,j ,bi,bj)*s2d(i ,j-1,bi,bj)
280 & +aS2d(i ,j+1,bi,bj)*s2d(i ,j+1,bi,bj)
281 & +aC2d(i ,j ,bi,bj)*s2d(i ,j ,bi,bj)
282 alphaTile(bi,bj) = alphaTile(bi,bj)
283 & + s2d(i,j,bi,bj)*q2d(i,j,bi,bj)
284 ENDDO
285 ENDDO
286 ENDDO
287 ENDDO
288 CALL GLOBAL_SUM_TILE_RL( alphaTile, alpha, myThid )
289 alpha = eta_qrN/alpha
290
291 C== Update solution and residual vectors
292 C Now compute "interior" points.
293 DO bj=myByLo(myThid),myByHi(myThid)
294 DO bi=myBxLo(myThid),myBxHi(myThid)
295 errTile(bi,bj) = 0. _d 0
296 DO j=1,sNy
297 DO i=1,sNx
298 x2d(i,j,bi,bj)=x2d(i,j,bi,bj)+alpha*s2d(i,j,bi,bj)
299 r2d(i,j,bi,bj)=r2d(i,j,bi,bj)-alpha*q2d(i,j,bi,bj)
300 errTile(bi,bj) = errTile(bi,bj)
301 & + r2d(i,j,bi,bj)*r2d(i,j,bi,bj)
302 ENDDO
303 ENDDO
304 ENDDO
305 ENDDO
306
307 CALL GLOBAL_SUM_TILE_RL( errTile, err, myThid )
308 err = SQRT(err)
309 IF ( printResidual ) THEN
310 IF ( MOD( it2d-1, printResidFrq ).EQ.0 ) THEN
311 WRITE(msgBuf,'(A,I6,A,1PE17.9)')
312 & ' diag_cg2d: iter=', it2d, ' ; resid.=', err
313 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
314 & SQUEEZE_RIGHT, myThid )
315 ENDIF
316 ENDIF
317 IF ( err .LT. residCriter ) GOTO 11
318 IF ( err .LT. minResidual ) THEN
319 C- Store lowest residual solution
320 minResidual = err
321 nIterMin = it2d
322 DO bj=myByLo(myThid),myByHi(myThid)
323 DO bi=myBxLo(myThid),myBxHi(myThid)
324 DO j=1,sNy
325 DO i=1,sNx
326 x2dm(i,j,bi,bj) = x2d(i,j,bi,bj)
327 ENDDO
328 ENDDO
329 ENDDO
330 ENDDO
331 ENDIF
332
333 #ifdef DEBUG_DIAG_CG2D
334 CALL EXCH_XY_RL( r2d, myThid )
335 IF ( printResidFrq.GE.1 ) THEN
336 WRITE(sufx,'(I10.10)') it2d
337 CALL WRITE_FLD_XY_RL( 'r2d.',sufx, r2d, 1, myThid )
338 CALL WRITE_FLD_XY_RL( 'x2d.',sufx, x2d, 1, myThid )
339 ENDIF
340 #else
341 CALL EXCH_S3D_RL( r2d, 1, myThid )
342 #endif
343
344 10 CONTINUE
345 it2d = numIters
346 11 CONTINUE
347
348 C-- Return parameters to caller
349 lastResidual = err
350 numIters = it2d
351
352 IF ( err .GT. minResidual ) THEN
353 C- use the lowest residual solution (instead of current one <-> last residual)
354 DO bj=myByLo(myThid),myByHi(myThid)
355 DO bi=myBxLo(myThid),myBxHi(myThid)
356 DO j=1,sNy
357 DO i=1,sNx
358 x2d(i,j,bi,bj) = x2dm(i,j,bi,bj)
359 ENDDO
360 ENDDO
361 ENDDO
362 ENDDO
363 ENDIF
364 c CALL EXCH_XY_RL( x2d, myThid )
365
366 #ifdef ALLOW_DEBUG
367 IF (debugMode) CALL DEBUG_LEAVE('DIAG_CG2D',myThid)
368 #endif
369
370 RETURN
371 END

  ViewVC Help
Powered by ViewVC 1.1.22