limhdf_2.F90 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. MODULE limhdf_2
  2. !!======================================================================
  3. !! *** MODULE limhdf_2 ***
  4. !! LIM 2.0 ice model : horizontal diffusion of sea-ice quantities
  5. !!======================================================================
  6. !! History : LIM ! 2000-01 (LIM) Original code
  7. !! - ! 2001-05 (G. Madec, R. Hordoir) opa norm
  8. !! 1.0 ! 2002-08 (C. Ethe) F90, free form
  9. !!----------------------------------------------------------------------
  10. #if defined key_lim2
  11. !!----------------------------------------------------------------------
  12. !! 'key_lim2' LIM 2.0 sea-ice model
  13. !!----------------------------------------------------------------------
  14. !! lim_hdf_2 : diffusion trend on sea-ice variable
  15. !!----------------------------------------------------------------------
  16. USE dom_oce ! ocean domain
  17. USE ice_2 ! LIM-2: ice variables
  18. USE lbclnk ! lateral boundary condition - MPP exchanges
  19. USE lib_mpp ! MPP library
  20. USE wrk_nemo ! work arrays
  21. USE prtctl ! Print control
  22. USE in_out_manager ! I/O manager
  23. USE lib_fortran ! Fortran utilities (allows no signed zero when 'key_nosignedzero' defined)
  24. IMPLICIT NONE
  25. PRIVATE
  26. PUBLIC lim_hdf_2 ! called by limtrp_2.F90
  27. LOGICAL :: linit = .TRUE. ! ! initialization flag (set to flase after the 1st call)
  28. REAL(wp) :: epsi04 = 1e-04 ! constant
  29. REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: efact ! metric coefficient
  30. !! * Substitution
  31. # include "vectopt_loop_substitute.h90"
  32. !!----------------------------------------------------------------------
  33. !! NEMO/LIM2 4.0 , UCL - NEMO Consortium (2010)
  34. !! $Id: limhdf_2.F90 4990 2014-12-15 16:42:49Z timgraham $
  35. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  36. !!----------------------------------------------------------------------
  37. CONTAINS
  38. SUBROUTINE lim_hdf_2( ptab )
  39. !!-------------------------------------------------------------------
  40. !! *** ROUTINE lim_hdf_2 ***
  41. !!
  42. !! ** purpose : Compute and add the diffusive trend on sea-ice variables
  43. !!
  44. !! ** method : Second order diffusive operator evaluated using a
  45. !! Cranck-Nicholson time Scheme.
  46. !!
  47. !! ** Action : update ptab with the diffusive contribution
  48. !!-------------------------------------------------------------------
  49. REAL(wp), DIMENSION(jpi,jpj), INTENT( inout ) :: ptab ! Field on which the diffusion is applied
  50. !
  51. INTEGER :: ji, jj ! dummy loop indices
  52. INTEGER :: its, iter, ierr ! local integers
  53. REAL(wp) :: zalfa, zrlxint, zconv, zeps ! local scalars
  54. REAL(wp), DIMENSION(:,:), POINTER :: zrlx, zflu, zflv, zdiv0, zdiv, ztab0
  55. CHARACTER (len=55) :: charout
  56. !!-------------------------------------------------------------------
  57. CALL wrk_alloc( jpi, jpj, zrlx, zflu, zflv, zdiv0, zdiv, ztab0 )
  58. ! !== Initialisation ==!
  59. !
  60. IF( linit ) THEN ! Metric coefficient (compute at the first call and saved in efact)
  61. ALLOCATE( efact(jpi,jpj) , STAT=ierr )
  62. IF( lk_mpp ) CALL mpp_sum( ierr )
  63. IF( ierr /= 0 ) CALL ctl_stop( 'STOP', 'lim_hdf_2 : unable to allocate standard arrays' )
  64. DO jj = 2, jpjm1
  65. DO ji = fs_2 , fs_jpim1 ! vector opt.
  66. efact(ji,jj) = ( e2u(ji,jj) + e2u(ji-1,jj) + e1v(ji,jj) + e1v(ji,jj-1) ) / ( e1t(ji,jj) * e2t(ji,jj) )
  67. END DO
  68. END DO
  69. linit = .FALSE.
  70. ENDIF
  71. !
  72. ! ! Time integration parameters
  73. zalfa = 0.5_wp ! =1.0/0.5/0.0 = implicit/Cranck-Nicholson/explicit
  74. its = 100 ! Maximum number of iteration
  75. zeps = 2._wp * epsi04
  76. !
  77. ztab0(:, : ) = ptab(:,:) ! Arrays initialization
  78. zdiv0(:, 1 ) = 0._wp
  79. zdiv0(:,jpj) = 0._wp
  80. zflu (jpi,:) = 0._wp
  81. zflv (jpi,:) = 0._wp
  82. zdiv0(1, :) = 0._wp
  83. zdiv0(jpi,:) = 0._wp
  84. zconv = 1._wp !== horizontal diffusion using a Crant-Nicholson scheme ==!
  85. iter = 0
  86. !
  87. DO WHILE ( zconv > zeps .AND. iter <= its ) ! Sub-time step loop
  88. !
  89. iter = iter + 1 ! incrementation of the sub-time step number
  90. !
  91. DO jj = 1, jpjm1 ! diffusive fluxes in U- and V- direction
  92. DO ji = 1 , fs_jpim1 ! vector opt.
  93. zflu(ji,jj) = pahu(ji,jj) * e2u(ji,jj) / e1u(ji,jj) * ( ptab(ji+1,jj) - ptab(ji,jj) )
  94. zflv(ji,jj) = pahv(ji,jj) * e1v(ji,jj) / e2v(ji,jj) * ( ptab(ji,jj+1) - ptab(ji,jj) )
  95. END DO
  96. END DO
  97. !
  98. DO jj= 2, jpjm1 ! diffusive trend : divergence of the fluxes
  99. DO ji = fs_2 , fs_jpim1 ! vector opt.
  100. zdiv (ji,jj) = ( zflu(ji,jj) - zflu(ji-1,jj ) &
  101. & + zflv(ji,jj) - zflv(ji ,jj-1) ) / ( e1t (ji,jj) * e2t (ji,jj) )
  102. END DO
  103. END DO
  104. !
  105. IF( iter == 1 ) zdiv0(:,:) = zdiv(:,:) ! save the 1st evaluation of the diffusive trend in zdiv0
  106. !
  107. DO jj = 2, jpjm1 ! iterative evaluation
  108. DO ji = fs_2 , fs_jpim1 ! vector opt.
  109. zrlxint = ( ztab0(ji,jj) &
  110. & + rdt_ice * ( zalfa * ( zdiv(ji,jj) + efact(ji,jj) * ptab(ji,jj) ) &
  111. & + ( 1.0 - zalfa ) * zdiv0(ji,jj) ) ) &
  112. & / ( 1.0 + zalfa * rdt_ice * efact(ji,jj) )
  113. zrlx(ji,jj) = ptab(ji,jj) + om * ( zrlxint - ptab(ji,jj) )
  114. END DO
  115. END DO
  116. CALL lbc_lnk( zrlx, 'T', 1. ) ! lateral boundary condition
  117. zconv = 0._wp ! convergence test
  118. DO jj = 2, jpjm1
  119. DO ji = 2, jpim1
  120. zconv = MAX( zconv, ABS( zrlx(ji,jj) - ptab(ji,jj) ) )
  121. END DO
  122. END DO
  123. IF( lk_mpp ) CALL mpp_max( zconv ) ! max over the global domain
  124. ptab(:,:) = zrlx(:,:)
  125. !
  126. END DO ! end of sub-time step loop
  127. IF(ln_ctl) THEN
  128. zrlx(:,:) = ptab(:,:) - ztab0(:,:)
  129. WRITE(charout,FMT="(' lim_hdf : zconv =',D23.16, ' iter =',I4,2X)") zconv, iter
  130. CALL prt_ctl( tab2d_1=zrlx, clinfo1=charout )
  131. ENDIF
  132. !
  133. CALL wrk_dealloc( jpi, jpj, zrlx, zflu, zflv, zdiv0, zdiv, ztab0 )
  134. !
  135. END SUBROUTINE lim_hdf_2
  136. #else
  137. !!----------------------------------------------------------------------
  138. !! Default option Dummy module NO LIM 2.0 sea-ice model
  139. !!----------------------------------------------------------------------
  140. CONTAINS
  141. SUBROUTINE lim_hdf_2 ! Empty routine
  142. END SUBROUTINE lim_hdf_2
  143. #endif
  144. !!======================================================================
  145. END MODULE limhdf_2