File indexing completed on 2023-08-04 05:10:47 UTC
view on githubraw file Latest commit 45315406 on 2023-08-03 16:50:12 UTC
c1615e0916 Mart*0001 #include "SEAICE_OPTIONS.h"
0002 #ifdef ALLOW_AUTODIFF
0003 # include "AUTODIFF_OPTIONS.h"
0004 #endif
0005
0006
0007
0008
0009
0010
0011 SUBROUTINE SEAICE_KRYLOV( myTime, myIter, myThid )
0012
0013
0014
0015
0016
ec0d7df165 Mart*0017
0018
c1615e0916 Mart*0019
0020
0021
0022
0023
0024
0025
0026 IMPLICIT NONE
0027
0028
0029 #include "SIZE.h"
0030 #include "EEPARAMS.h"
0031 #include "PARAMS.h"
0032 #include "DYNVARS.h"
0033 #include "GRID.h"
0034 #include "SEAICE_SIZE.h"
0035 #include "SEAICE_PARAMS.h"
0036 #include "SEAICE.h"
0037
0038
0039
0040
0041
0042
0043 _RL myTime
0044 INTEGER myIter
0045 INTEGER myThid
0046
45315406aa Mart*0047 #if ( defined SEAICE_CGRID && defined SEAICE_ALLOW_KRYLOV )
c1615e0916 Mart*0048
0049 LOGICAL DIFFERENT_MULTIPLE
0050 EXTERNAL DIFFERENT_MULTIPLE
0051
0052
0053
0054
0055 INTEGER i,j,bi,bj
0056
0057 INTEGER picardIter
0058 INTEGER krylovIter, krylovFails
0059 INTEGER krylovIterMax, picardIterMax
0060 INTEGER totalKrylovItersLoc, totalPicardItersLoc
0061
0062
0063
0064 INTEGER im
0065 PARAMETER ( im = 50 )
0066 INTEGER ifgmres
0067
0068 INTEGER iOutFGMRES
0069
0070 INTEGER iCode
0071 _RL picardResidual
0072 _RL picardResidualKm1
0073
0074 _RL krylovLinTol
0075 _RL FGMRESeps
0076 _RL picardTol
0077
0078 _RL bdfFac, bdfAlpha
0079
0080 _RL recip_deltaT
0081 LOGICAL picardConverged, krylovConverged
0082 LOGICAL writeNow
0083 CHARACTER*(MAX_LEN_MBUF) msgBuf
ec0d7df165 Mart*0084
c1615e0916 Mart*0085 _RL uIceLin(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
0086 _RL vIceLin(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
0087
0088 _RL duIcNm1(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
0089 _RL dvIcNm1(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
0090
0091 _RL uWork (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
0092 _RL vWork (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
0093
0094 _RL uIceLHS(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
0095 _RL vIceLHS(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
0096
0097 _RL uIceRHS(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
0098 _RL vIceRHS(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy)
0099
0100 _RL resTmp (nVec,1,nSx,nSy)
0101
0102 _RL rhs(nVec,nSx,nSy), sol(nVec,nSx,nSy)
0103 _RL vv(nVec,im+1,nSx,nSy), w(nVec,im,nSx,nSy)
0104 _RL wk1(nVec,nSx,nSy), wk2(nVec,nSx,nSy)
0105
0106
0107
0108 picardIter = 0
0109 krylovFails = 0
0110 totalKrylovItersLoc = 0
0111 picardConverged = .FALSE.
0112 picardTol = 0. _d 0
0113 picardResidual = 0. _d 0
0114 picardResidualKm1 = 0. _d 0
0115 FGMRESeps = 0. _d 0
0116 recip_deltaT = 1. _d 0 / SEAICE_deltaTdyn
0117
0118 krylovIterMax = SEAICElinearIterMax
0119 picardIterMax = SEAICEnonLinIterMax
0120 IF ( SEAICEusePicardAsPrecon ) THEN
0121 krylovIterMax = SEAICEpreconlinIter
0122 picardIterMax = SEAICEpreconNL_Iter
0123 ENDIF
0124
0125 iOutFGMRES=0
0126
ec0d7df165 Mart*0127 IF ( debugLevel.GE.debLevC .AND.
c1615e0916 Mart*0128 & .NOT.SEAICEusePicardAsPrecon .AND.
0129 & DIFFERENT_MULTIPLE( SEAICE_monFreq, myTime, deltaTClock ) )
0130 & iOutFGMRES=1
0131
0132
0133 bdfFac = 0. _d 0
0134 IF ( SEAICEuseBDF2 ) THEN
0135 IF ( myIter.EQ.nIter0 .AND. SEAICEmomStartBDF.EQ.0 ) THEN
0136 bdfFac = 0. _d 0
0137 ELSE
0138 bdfFac = 0.5 _d 0
0139 ENDIF
0140 ENDIF
ec0d7df165 Mart*0141 bdfAlpha = 1. _d 0 + bdfFac
c1615e0916 Mart*0142
0143 DO bj=myByLo(myThid),myByHi(myThid)
0144 DO bi=myBxLo(myThid),myBxHi(myThid)
0145 DO J=1-OLy,sNy+OLy
0146 DO I=1-OLx,sNx+OLx
0147 uIceLHS(I,J,bi,bj) = 0. _d 0
0148 vIceLHS(I,J,bi,bj) = 0. _d 0
0149 uIceRHS(I,J,bi,bj) = 0. _d 0
0150 vIceRHS(I,J,bi,bj) = 0. _d 0
0151 ENDDO
0152 ENDDO
0153
0154 DO J=1-OLy,sNy+OLy
0155 DO I=1-OLx,sNx+OLx
ec0d7df165 Mart*0156 duIcNm1(I,J,bi,bj) = uIce(I,J,bi,bj) * bdfAlpha
c1615e0916 Mart*0157 & + ( uIce(I,J,bi,bj) - uIceNm1(I,J,bi,bj) ) * bdfFac
ec0d7df165 Mart*0158 dvIcNm1(I,J,bi,bj) = vIce(I,J,bi,bj) * bdfAlpha
c1615e0916 Mart*0159 & + ( vIce(I,J,bi,bj) - vIceNm1(I,J,bi,bj) ) * bdfFac
0160 uIceNm1(I,J,bi,bj) = uIce(I,J,bi,bj)
0161 vIceNm1(I,J,bi,bj) = vIce(I,J,bi,bj)
0162 uIceLin(I,J,bi,bj) = uIce(I,J,bi,bj)
0163 vIceLin(I,J,bi,bj) = vIce(I,J,bi,bj)
0164 ENDDO
0165 ENDDO
0166
0167
0168
0169 DO J=1-OLy,sNy+OLy
0170 DO I=1-OLx,sNx+OLx
0171 FORCEX(I,J,bi,bj) = FORCEX0(I,J,bi,bj)
0172 & + seaiceMassU(I,J,bi,bj)*duIcNm1(I,J,bi,bj)*recip_deltaT
0173 FORCEY(I,J,bi,bj) = FORCEY0(I,J,bi,bj)
0174 & + seaiceMassV(I,J,bi,bj)*dvIcNm1(I,J,bi,bj)*recip_deltaT
0175 ENDDO
0176 ENDDO
0177
0178 ENDDO
0179 ENDDO
0180
0181 DO WHILE ( picardIter.LT.picardIterMax .AND.
0182 & .NOT.picardConverged )
0183 picardIter = picardIter + 1
0184
ec0d7df165 Mart*0185
c1615e0916 Mart*0186 DO bj=myByLo(myThid),myByHi(myThid)
0187 DO bi=myBxLo(myThid),myBxHi(myThid)
0188 DO j=1-OLy,sNy+OLy
0189 DO i=1-OLx,sNx+OLx
0190 uIceLin(I,J,bi,bj) = 0.5 _d 0 *
0191 & (uIce(I,J,bi,bj) + uIceLin(I,J,bi,bj))
ec0d7df165 Mart*0192 vIceLin(I,J,bi,bj) = 0.5 _d 0 *
c1615e0916 Mart*0193 & (vIce(I,J,bi,bj) + vIceLin(I,J,bi,bj))
0194 ENDDO
0195 ENDDO
0196 ENDDO
0197 ENDDO
ec0d7df165 Mart*0198
c1615e0916 Mart*0199
0200
0201 CALL SEAICE_OCEANDRAG_COEFFS(
ec0d7df165 Mart*0202 I uIceLin, vIceLin, HEFFM,
c1615e0916 Mart*0203 O DWATN,
0204 I 0, myTime, myIter, myThid )
df1dac8b7b Mart*0205 #ifdef SEAICE_ALLOW_BOTTOMDRAG
d5254b4e3d Mart*0206 CALL SEAICE_BOTTOMDRAG_COEFFS(
ec0d7df165 Mart*0207 I uIceLin, vIceLin, HEFFM,
df1dac8b7b Mart*0208 #ifdef SEAICE_ITD
0209 I HEFFITD, AREAITD, AREA,
0210 #else
0211 I HEFF, AREA,
ec0d7df165 Mart*0212 #endif
df1dac8b7b Mart*0213 O CbotC,
0214 I 0, myTime, myIter, myThid )
0215 #endif /* SEAICE_ALLOW_BOTTOMDRAG */
c1615e0916 Mart*0216 CALL SEAICE_CALC_STRAINRATES(
0217 I uIceLin, vIceLin,
0218 O e11, e22, e12,
0219 I 0, myTime, myIter, myThid )
0220 CALL SEAICE_CALC_VISCOSITIES(
8e32c48b8f Mart*0221 I e11, e22, e12, SEAICE_zMin, SEAICE_zMax, HEFFM, press0,
0222 I tensileStrFac,
c1615e0916 Mart*0223 O eta, etaZ, zeta, zetaZ, press, deltaC,
0224 I 0, myTime, myIter, myThid )
0225
0226 CALL SEAICE_CALC_RHS(
0227 O uIceRHS, vIceRHS,
0228 I picardIter, 0, myTime, myIter, myThid )
0229
0230 CALL SEAICE_CALC_LHS(
0231 I uIce, vIce,
0232 O uIceLHS, vIceLHS,
0233 I picardIter, myTime, myIter, myThid )
0234
0235 DO bj=myByLo(myThid),myByHi(myThid)
0236 DO bi=myBxLo(myThid),myBxHi(myThid)
0237 DO J=1,sNy
0238 DO I=1,sNx
0239 uIceLHS(I,J,bi,bj) = uIceLHS(I,J,bi,bj) - uIceRHS(I,J,bi,bj)
0240 vIceLHS(I,J,bi,bj) = vIceLHS(I,J,bi,bj) - vIceRHS(I,J,bi,bj)
0241
0242
0243
0244 ENDDO
0245 ENDDO
0246 ENDDO
0247 ENDDO
0248
0249
0250 CALL SEAICE_MAP2VEC(nVec,uIceLHS,vIceLHS,resTmp,.TRUE.,myThid)
0251 CALL SEAICE_SCALPROD(nVec,1,1,1,resTmp,resTmp,
0252 & picardResidual,myThid)
0253 picardResidual = SQRT(picardResidual)
0254
0255
0256 krylovLinTol = JFNKgamma_lin_max
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280 picardResidualKm1 = picardResidual
0281
0282
0283
0284
0285
0286
0287 krylovIter = 0
0288 iCode = 0
0289
0290 picardConverged = picardResidual.LT.picardTol
0d02be7d13 Mart*0291 & .OR.picardResidual.EQ.0. _d 0
c1615e0916 Mart*0292
0293
0294
0295 IF ( .NOT.picardConverged ) THEN
0296
0297
0298
0299 krylovConverged = .FALSE.
0300 FGMRESeps = krylovLinTol * picardResidual
0301 CALL SEAICE_MAP2VEC(nVec,uIce,vIce,sol,.TRUE.,myThid)
0302 CALL SEAICE_MAP2VEC(nVec,uIceRHS,vIceRHS,rhs,.TRUE.,myThid)
0303 DO bj=myByLo(myThid),myByHi(myThid)
0304 DO bi=myBxLo(myThid),myBxHi(myThid)
0305 DO j=1-OLy,sNy+OLy
0306 DO i=1-OLx,sNx+OLx
0307 uWork(i,j,bi,bj) = 0. _d 0
0308 vWork(i,j,bi,bj) = 0. _d 0
0309 ENDDO
0310 ENDDO
0311 ENDDO
0312 ENDDO
0313 DO WHILE ( .NOT.krylovConverged )
0314
0315
0316
0317
0318
0319 CALL SEAICE_MAP2VEC(nVec,uWork,vWork,wk2,.TRUE.,myThid)
0320
0321 CALL SEAICE_FGMRES (nVec,im,rhs,sol,ifgmres,krylovIter,
0322 U vv,w,wk1,wk2,
0323 I FGMRESeps,krylovIterMax,iOutFGMRES,
0324 U iCode,
0325 I myThid)
0326
0327 IF ( iCode .EQ. 0 ) THEN
0328
0329 CALL SEAICE_MAP2VEC(nVec,uIce,vIce,sol,.FALSE.,myThid)
0330 CALL EXCH_UV_XY_RL( uIce, vIce,.TRUE.,myThid)
0331 ELSE
0332
0333
0334 CALL SEAICE_MAP2VEC(nVec,uWork,vWork,wk1,.FALSE.,myThid)
0335 CALL EXCH_UV_XY_RL( uWork, vWork,.TRUE.,myThid)
0336 ENDIF
0337
0338
0339
0340
0341 IF (iCode.EQ.1) THEN
0342
0343 IF ( SEAICEpreconLinIter .GT. 0 )
0344 & CALL SEAICE_PRECONDITIONER(
0345 U uWork, vWork,
0346 I zeta, eta, etaZ, zetaZ, dwatn,
0347 I picardIter, krylovIter, myTime, myIter, myThid )
0348 ELSEIF (iCode.GE.2) THEN
0349
0350 CALL SEAICE_CALC_STRAINRATES(
0351 I uWork, vWork,
0352 O e11, e22, e12,
0353 I krylovIter, myTime, myIter, myThid )
0354 CALL SEAICE_CALC_LHS(
0355 I uWork, vWork,
0356 O uIceLHS, vIceLHS,
0357 I picardIter, myTime, myIter, myThid )
0358 DO bj=myByLo(myThid),myByHi(myThid)
0359 DO bi=myBxLo(myThid),myBxHi(myThid)
0360 DO j=1-OLy,sNy+OLy
0361 DO i=1-OLx,sNx+OLx
0362 uWork(i,j,bi,bj) = uIceLHS(i,j,bi,bj)
0363 vWork(i,j,bi,bj) = vIceLHS(i,j,bi,bj)
0364 ENDDO
0365 ENDDO
0366 ENDDO
0367 ENDDO
0368 ENDIF
0369 krylovConverged = iCode.EQ.0
0370
0371 ENDDO
0372 totalKrylovItersLoc = totalKrylovItersLoc + krylovIter
0373
0374 IF ( debugLevel.GE.debLevA
0375 & .AND. .NOT.SEAICEusePicardAsPrecon ) THEN
0376 _BEGIN_MASTER( myThid )
0377 totalPicardItersLoc =
0378 & picardIterMax*(myIter-nIter0)+picardIter
0379 WRITE(msgBuf,'(2A,2(1XI6),2E12.5)')
0380 & ' S/R SEAICE_KRYLOV: Picard iterate / total, ',
0381 & 'KRYLOVgamma_lin, initial norm = ',
0382 & picardIter, totalPicardItersLoc,
0383 & krylovLinTol,picardResidual
0384 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
0385 & SQUEEZE_RIGHT, myThid )
0386 WRITE(msgBuf,'(3(A,I6))')
0387 & ' S/R SEAICE_KRYLOV: Picard iterate / total = ',
0388 & picardIter, ' / ', totalPicardItersLoc,
0389 & ', Nb. of FGMRES iterations = ', krylovIter
0390 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
0391 & SQUEEZE_RIGHT, myThid )
0392 _END_MASTER( myThid )
0393 ENDIF
0394 IF ( krylovIter.EQ.krylovIterMax ) THEN
0395 krylovFails = krylovFails + 1
0396 ENDIF
0397
0398
0399 IF ( picardIter .EQ. 1 ) THEN
0400 picardTol=SEAICEnonLinTol*picardResidual
0401 IF ( JFNKres_tFac .NE. UNSET_RL )
0402 & JFNKres_t = picardResidual * JFNKres_tFac
0403 ENDIF
0404 ENDIF
0405
0406 ENDDO
0407
0408
0409
0410 IF ( SEAICE_monFreq .GT. 0. _d 0 ) THEN
c512e371cc drin*0411
0412 _BEGIN_MASTER(myThid)
0413
c1615e0916 Mart*0414 totalJFNKtimeSteps = totalJFNKtimeSteps + 1
0415 totalNewtonIters = totalNewtonIters + picardIter
0416 totalKrylovIters = totalKrylovIters + totalKrylovItersLoc
0417
0418 totalKrylovFails = totalKrylovFails + krylovFails
0419 IF ( picardIter .EQ. picardIterMax ) THEN
0420 totalNewtonfails = totalNewtonfails + 1
0421 ENDIF
c512e371cc drin*0422 _END_MASTER( myThid )
c1615e0916 Mart*0423 ENDIF
0424
0425 writeNow = DIFFERENT_MULTIPLE(SEAICE_monFreq,
0426 & myTime+deltaTClock, deltaTClock)
0427 #ifdef ALLOW_CAL
0428 IF ( useCAL ) THEN
0429 CALL CAL_TIME2DUMP(
0430 I zeroRL, SEAICE_monFreq, deltaTClock,
0431 U writeNow,
ec0d7df165 Mart*0432 I myTime+deltaTClock, myIter+1, myThid )
c1615e0916 Mart*0433 ENDIF
0434 #endif
0435 IF ( writeNow ) THEN
0436 _BEGIN_MASTER( myThid )
0437 WRITE(msgBuf,'(A)')
0438 &' // ======================================================='
0439 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
0440 & SQUEEZE_RIGHT, myThid )
0441 WRITE(msgBuf,'(A)') ' // Begin KRYLOV statistics'
0442 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
0443 & SQUEEZE_RIGHT, myThid )
0444 WRITE(msgBuf,'(A)')
0445 &' // ======================================================='
0446 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
0447 & SQUEEZE_RIGHT, myThid )
0448 WRITE(msgBuf,'(A,I10)')
0449 & ' %KRYLOV_MON: time step = ', myIter+1
0450 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
0451 & SQUEEZE_RIGHT, myThid )
0452 WRITE(msgBuf,'(A,I10)')
ec0d7df165 Mart*0453 & ' %KRYLOV_MON: Nb. of time steps = ',
c1615e0916 Mart*0454 & totalJFNKtimeSteps
0455 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
0456 & SQUEEZE_RIGHT, myThid )
0457 WRITE(msgBuf,'(A,I10)')
0458 & ' %KRYLOV_MON: Nb. of Picard steps = ', totalNewtonIters
0459 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
0460 & SQUEEZE_RIGHT, myThid )
0461 WRITE(msgBuf,'(A,I10)')
0462 & ' %KRYLOV_MON: Nb. of Krylov steps = ', totalKrylovIters
0463 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
0464 & SQUEEZE_RIGHT, myThid )
0465 WRITE(msgBuf,'(A,I10)')
0466 & ' %KRYLOV_MON: Nb. of Picard failures = ', totalNewtonfails
0467 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
0468 & SQUEEZE_RIGHT, myThid )
0469 WRITE(msgBuf,'(A,I10)')
0470 & ' %KRYLOV_MON: Nb. of Krylov failures = ', totalKrylovFails
0471 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
0472 & SQUEEZE_RIGHT, myThid )
0473 WRITE(msgBuf,'(A)')
0474 &' // ======================================================='
0475 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
0476 & SQUEEZE_RIGHT, myThid )
0477 WRITE(msgBuf,'(A)') ' // End KRYLOV statistics'
0478 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
0479 & SQUEEZE_RIGHT, myThid )
0480 WRITE(msgBuf,'(A)')
0481 &' // ======================================================='
0482 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
0483 & SQUEEZE_RIGHT, myThid )
c512e371cc drin*0484
c1615e0916 Mart*0485 totalJFNKtimeSteps = 0
0486 totalNewtonIters = 0
0487 totalKrylovIters = 0
0488 totalKrylovFails = 0
0489 totalNewtonfails = 0
c512e371cc drin*0490 _END_MASTER( myThid )
c1615e0916 Mart*0491 ENDIF
0492
0493
ec0d7df165 Mart*0494 IF ( debugLevel.GE.debLevA
c1615e0916 Mart*0495 & .AND. .NOT.SEAICEusePicardAsPrecon ) THEN
0496 IF ( picardIter .EQ. picardIterMax ) THEN
0497 _BEGIN_MASTER( myThid )
0498 WRITE(msgBuf,'(A,I10)')
0499 & ' S/R SEAICE_KRYLOV: Solver did not converge in timestep ',
0500 & myIter+1
0501 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
0502 & SQUEEZE_RIGHT, myThid )
0503 _END_MASTER( myThid )
0504 ENDIF
0505 IF ( krylovFails .GT. 0 ) THEN
0506 _BEGIN_MASTER( myThid )
0507 WRITE(msgBuf,'(A,I4,A,I10)')
0508 & ' S/R SEAICE_KRYLOV: FGMRES did not converge ',
0509 & krylovFails, ' times in timestep ', myIter+1
0510 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
0511 & SQUEEZE_RIGHT, myThid )
0512 _END_MASTER( myThid )
0513 ENDIF
0514 _BEGIN_MASTER( myThid )
0515 WRITE(msgBuf,'(A,I6,A,I10)')
0516 & ' S/R SEAICE_KRYLOV: Total number FGMRES iterations = ',
0517 & totalKrylovItersLoc, ' in timestep ', myIter+1
0518 CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
0519 & SQUEEZE_RIGHT, myThid )
0520 _END_MASTER( myThid )
0521 ENDIF
0522
45315406aa Mart*0523 #endif /* SEAICE_CGRID and SEAICE_ALLOW_KRYLOV */
c1615e0916 Mart*0524
0525 RETURN
0526 END