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