limthd_ent.F90 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. MODULE limthd_ent
  2. !!======================================================================
  3. !! *** MODULE limthd_ent ***
  4. !! Redistribution of Enthalpy in the ice
  5. !! on the new vertical grid
  6. !! after vertical growth/decay
  7. !!======================================================================
  8. !! History : LIM ! 2003-05 (M. Vancoppenolle) Original code in 1D
  9. !! ! 2005-07 (M. Vancoppenolle) 3D version
  10. !! ! 2006-11 (X. Fettweis) Vectorized
  11. !! 3.0 ! 2008-03 (M. Vancoppenolle) Energy conservation and clean code
  12. !! 3.4 ! 2011-02 (G. Madec) dynamical allocation
  13. !! - ! 2014-05 (C. Rousset) complete rewriting
  14. !!----------------------------------------------------------------------
  15. #if defined key_lim3
  16. !!----------------------------------------------------------------------
  17. !! 'key_lim3' LIM3 sea-ice model
  18. !!----------------------------------------------------------------------
  19. !! lim_thd_ent : ice redistribution of enthalpy
  20. !!----------------------------------------------------------------------
  21. USE par_oce ! ocean parameters
  22. USE dom_oce ! domain variables
  23. USE domain !
  24. USE phycst ! physical constants
  25. USE sbc_oce ! Surface boundary condition: ocean fields
  26. USE ice ! LIM variables
  27. USE thd_ice ! LIM thermodynamics
  28. USE limvar ! LIM variables
  29. USE in_out_manager ! I/O manager
  30. USE lib_mpp ! MPP library
  31. USE wrk_nemo ! work arrays
  32. USE lib_fortran ! Fortran utilities (allows no signed zero when 'key_nosignedzero' defined)
  33. IMPLICIT NONE
  34. PRIVATE
  35. PUBLIC lim_thd_ent ! called by limthd and limthd_lac
  36. !!----------------------------------------------------------------------
  37. !! NEMO/LIM3 4.0 , UCL - NEMO Consortium (2011)
  38. !! $Id: limthd_ent.F90 4990 2014-12-15 16:42:49Z timgraham $
  39. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  40. !!----------------------------------------------------------------------
  41. CONTAINS
  42. SUBROUTINE lim_thd_ent( kideb, kiut, qnew )
  43. !!-------------------------------------------------------------------
  44. !! *** ROUTINE lim_thd_ent ***
  45. !!
  46. !! ** Purpose :
  47. !! This routine computes new vertical grids in the ice,
  48. !! and consistently redistributes temperatures.
  49. !! Redistribution is made so as to ensure to energy conservation
  50. !!
  51. !!
  52. !! ** Method : linear conservative remapping
  53. !!
  54. !! ** Steps : 1) cumulative integrals of old enthalpies/thicknesses
  55. !! 2) linear remapping on the new layers
  56. !!
  57. !! ------------ cum0(0) ------------- cum1(0)
  58. !! NEW -------------
  59. !! ------------ cum0(1) ==> -------------
  60. !! ... -------------
  61. !! ------------ -------------
  62. !! ------------ cum0(nlay_i+2) ------------- cum1(nlay_i)
  63. !!
  64. !!
  65. !! References : Bitz & Lipscomb, JGR 99; Vancoppenolle et al., GRL, 2005
  66. !!-------------------------------------------------------------------
  67. INTEGER , INTENT(in) :: kideb, kiut ! Start/End point on which the the computation is applied
  68. REAL(wp), INTENT(inout), DIMENSION(:,:) :: qnew ! new enthlapies (J.m-3, remapped)
  69. INTEGER :: ji ! dummy loop indices
  70. INTEGER :: jk0, jk1 ! old/new layer indices
  71. !
  72. REAL(wp), POINTER, DIMENSION(:,:) :: zqh_cum0, zh_cum0 ! old cumulative enthlapies and layers interfaces
  73. REAL(wp), POINTER, DIMENSION(:,:) :: zqh_cum1, zh_cum1 ! new cumulative enthlapies and layers interfaces
  74. REAL(wp), POINTER, DIMENSION(:) :: zhnew ! new layers thicknesses
  75. !!-------------------------------------------------------------------
  76. CALL wrk_alloc( jpij, nlay_i+3, zqh_cum0, zh_cum0, kjstart = 0 )
  77. CALL wrk_alloc( jpij, nlay_i+1, zqh_cum1, zh_cum1, kjstart = 0 )
  78. CALL wrk_alloc( jpij, zhnew )
  79. !--------------------------------------------------------------------------
  80. ! 1) Cumulative integral of old enthalpy * thickness and layers interfaces
  81. !--------------------------------------------------------------------------
  82. zqh_cum0(:,0:nlay_i+2) = 0._wp
  83. zh_cum0 (:,0:nlay_i+2) = 0._wp
  84. DO jk0 = 1, nlay_i+2
  85. DO ji = kideb, kiut
  86. zqh_cum0(ji,jk0) = zqh_cum0(ji,jk0-1) + qh_i_old(ji,jk0-1)
  87. zh_cum0 (ji,jk0) = zh_cum0 (ji,jk0-1) + h_i_old (ji,jk0-1)
  88. ENDDO
  89. ENDDO
  90. !------------------------------------
  91. ! 2) Interpolation on the new layers
  92. !------------------------------------
  93. ! new layer thickesses
  94. DO ji = kideb, kiut
  95. zhnew(ji) = SUM( h_i_old(ji,0:nlay_i+1) ) * r1_nlay_i
  96. ENDDO
  97. ! new layers interfaces
  98. zh_cum1(:,0:nlay_i) = 0._wp
  99. DO jk1 = 1, nlay_i
  100. DO ji = kideb, kiut
  101. zh_cum1(ji,jk1) = zh_cum1(ji,jk1-1) + zhnew(ji)
  102. ENDDO
  103. ENDDO
  104. zqh_cum1(:,0:nlay_i) = 0._wp
  105. ! new cumulative q*h => linear interpolation
  106. DO jk0 = 1, nlay_i+1
  107. DO jk1 = 1, nlay_i-1
  108. DO ji = kideb, kiut
  109. IF( zh_cum1(ji,jk1) <= zh_cum0(ji,jk0) .AND. zh_cum1(ji,jk1) > zh_cum0(ji,jk0-1) ) THEN
  110. zqh_cum1(ji,jk1) = ( zqh_cum0(ji,jk0-1) * ( zh_cum0(ji,jk0) - zh_cum1(ji,jk1 ) ) + &
  111. & zqh_cum0(ji,jk0 ) * ( zh_cum1(ji,jk1) - zh_cum0(ji,jk0-1) ) ) &
  112. & / ( zh_cum0(ji,jk0) - zh_cum0(ji,jk0-1) )
  113. ENDIF
  114. ENDDO
  115. ENDDO
  116. ENDDO
  117. ! to ensure that total heat content is strictly conserved, set:
  118. zqh_cum1(:,nlay_i) = zqh_cum0(:,nlay_i+2)
  119. ! new enthalpies
  120. DO jk1 = 1, nlay_i
  121. DO ji = kideb, kiut
  122. rswitch = MAX( 0._wp , SIGN( 1._wp , zhnew(ji) - epsi20 ) )
  123. qnew(ji,jk1) = rswitch * ( zqh_cum1(ji,jk1) - zqh_cum1(ji,jk1-1) ) / MAX( zhnew(ji), epsi20 )
  124. ENDDO
  125. ENDDO
  126. ! --- diag error on heat remapping --- !
  127. ! comment: if input h_i_old and qh_i_old are already multiplied by a_i (as in limthd_lac),
  128. ! then we should not (* a_i) again but not important since this is just to check that remap error is ~0
  129. DO ji = kideb, kiut
  130. hfx_err_rem_1d(ji) = hfx_err_rem_1d(ji) + a_i_1d(ji) * r1_rdtice * &
  131. & ( SUM( qnew(ji,1:nlay_i) ) * zhnew(ji) - SUM( qh_i_old(ji,0:nlay_i+1) ) )
  132. END DO
  133. !
  134. CALL wrk_dealloc( jpij, nlay_i+3, zqh_cum0, zh_cum0, kjstart = 0 )
  135. CALL wrk_dealloc( jpij, nlay_i+1, zqh_cum1, zh_cum1, kjstart = 0 )
  136. CALL wrk_dealloc( jpij, zhnew )
  137. !
  138. END SUBROUTINE lim_thd_ent
  139. #else
  140. !!----------------------------------------------------------------------
  141. !! Default option NO LIM3 sea-ice model
  142. !!----------------------------------------------------------------------
  143. CONTAINS
  144. SUBROUTINE lim_thd_ent ! Empty routine
  145. END SUBROUTINE lim_thd_ent
  146. #endif
  147. !!======================================================================
  148. END MODULE limthd_ent