sbcfwb.F90 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. MODULE sbcfwb
  2. !!======================================================================
  3. !! *** MODULE sbcfwb ***
  4. !! Ocean fluxes : domain averaged freshwater budget
  5. !!======================================================================
  6. !! History : OPA ! 2001-02 (E. Durand) Original code
  7. !! NEMO 1.0 ! 2002-06 (G. Madec) F90: Free form and module
  8. !! 3.0 ! 2006-08 (G. Madec) Surface module
  9. !! 3.2 ! 2009-07 (C. Talandier) emp mean s spread over erp area
  10. !! 3.6 ! 2014-11 (P. Mathiot ) add ice shelf melting
  11. !!----------------------------------------------------------------------
  12. !!----------------------------------------------------------------------
  13. !! sbc_fwb : freshwater budget for global ocean configurations
  14. !! in free surface and forced mode
  15. !!----------------------------------------------------------------------
  16. USE oce ! ocean dynamics and tracers
  17. USE dom_oce ! ocean space and time domain
  18. USE sbc_oce ! surface ocean boundary condition
  19. USE phycst ! physical constants
  20. USE sbcrnf ! ocean runoffs
  21. USE sbcisf ! ice shelf melting contribution
  22. USE sbcssr ! SS damping terms
  23. USE in_out_manager ! I/O manager
  24. USE lib_mpp ! distribued memory computing library
  25. USE wrk_nemo ! work arrays
  26. USE timing ! Timing
  27. USE lbclnk ! ocean lateral boundary conditions
  28. USE lib_fortran
  29. IMPLICIT NONE
  30. PRIVATE
  31. PUBLIC sbc_fwb ! routine called by step
  32. REAL(wp) :: a_fwb_b ! annual domain averaged freshwater budget
  33. REAL(wp) :: a_fwb ! for 2 year before (_b) and before year.
  34. REAL(wp) :: fwfold ! fwfold to be suppressed
  35. REAL(wp) :: area ! global mean ocean surface (interior domain)
  36. !! * Substitutions
  37. # include "domzgr_substitute.h90"
  38. # include "vectopt_loop_substitute.h90"
  39. !!----------------------------------------------------------------------
  40. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  41. !! $Id: sbcfwb.F90 5628 2015-07-22 20:26:35Z mathiot $
  42. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  43. !!----------------------------------------------------------------------
  44. CONTAINS
  45. SUBROUTINE sbc_fwb( kt, kn_fwb, kn_fsbc )
  46. !!---------------------------------------------------------------------
  47. !! *** ROUTINE sbc_fwb ***
  48. !!
  49. !! ** Purpose : Control the mean sea surface drift
  50. !!
  51. !! ** Method : several ways depending on kn_fwb
  52. !! =0 no control
  53. !! =1 global mean of emp set to zero at each nn_fsbc time step
  54. !! =2 annual global mean corrected from previous year
  55. !! =3 global mean of emp set to zero at each nn_fsbc time step
  56. !! & spread out over erp area depending its sign
  57. !! Note: if sea ice is embedded it is taken into account when computing the budget
  58. !!----------------------------------------------------------------------
  59. INTEGER, INTENT( in ) :: kt ! ocean time-step index
  60. INTEGER, INTENT( in ) :: kn_fsbc !
  61. INTEGER, INTENT( in ) :: kn_fwb ! ocean time-step index
  62. !
  63. INTEGER :: inum, ikty, iyear ! local integers
  64. REAL(wp) :: z_fwf, z_fwf_nsrf, zsum_fwf, zsum_erp ! local scalars
  65. REAL(wp) :: zsurf_neg, zsurf_pos, zsurf_tospread, zcoef ! - -
  66. REAL(wp), POINTER, DIMENSION(:,:) :: ztmsk_neg, ztmsk_pos, z_wgt ! 2D workspaces
  67. REAL(wp), POINTER, DIMENSION(:,:) :: ztmsk_tospread, zerp_cor ! - -
  68. !!----------------------------------------------------------------------
  69. !
  70. IF( nn_timing == 1 ) CALL timing_start('sbc_fwb')
  71. !
  72. CALL wrk_alloc( jpi,jpj, ztmsk_neg, ztmsk_pos, ztmsk_tospread, z_wgt, zerp_cor )
  73. !
  74. IF( kt == nit000 ) THEN
  75. IF(lwp) THEN
  76. WRITE(numout,*)
  77. WRITE(numout,*) 'sbc_fwb : FreshWater Budget correction'
  78. WRITE(numout,*) '~~~~~~~'
  79. IF( kn_fwb == 1 ) WRITE(numout,*) ' instantaneously set to zero'
  80. IF( kn_fwb == 2 ) WRITE(numout,*) ' adjusted from previous year budget'
  81. IF( kn_fwb == 3 ) WRITE(numout,*) ' fwf set to zero and spread out over erp area'
  82. ENDIF
  83. !
  84. IF( kn_fwb == 3 .AND. nn_sssr /= 2 ) CALL ctl_stop( 'sbc_fwb: nn_fwb = 3 requires nn_sssr = 2, we stop ' )
  85. IF( kn_fwb == 3 .AND. ln_isfcav ) CALL ctl_stop( 'sbc_fwb: nn_fwb = 3 with ln_isfcav = .TRUE. not working, we stop ' )
  86. !
  87. area = glob_sum( e1e2t(:,:) * tmask(:,:,1)) ! interior global domain surface
  88. ! isf cavities are excluded because it can feedback to the melting with generation of inhibition of plumes
  89. ! and in case of no melt, it can generate HSSW.
  90. !
  91. #if ! defined key_lim2 && ! defined key_lim3 && ! defined key_cice
  92. snwice_mass_b(:,:) = 0.e0 ! no sea-ice model is being used : no snow+ice mass
  93. snwice_mass (:,:) = 0.e0
  94. #endif
  95. !
  96. ENDIF
  97. SELECT CASE ( kn_fwb )
  98. !
  99. CASE ( 1 ) !== global mean fwf set to zero ==!
  100. !
  101. IF( MOD( kt-1, kn_fsbc ) == 0 ) THEN
  102. z_fwf = glob_sum( e1e2t(:,:) * ( emp(:,:) - rnf(:,:) + fwfisf(:,:) - snwice_fmass(:,:) ) ) / area ! sum over the global domain
  103. zcoef = z_fwf * rcp
  104. emp(:,:) = emp(:,:) - z_fwf * tmask(:,:,1)
  105. qns(:,:) = qns(:,:) + zcoef * sst_m(:,:) * tmask(:,:,1) ! account for change to the heat budget due to fw correction
  106. ENDIF
  107. !
  108. CASE ( 2 ) !== fwf budget adjusted from the previous year ==!
  109. !
  110. IF( kt == nit000 ) THEN ! initialisation
  111. ! ! Read the corrective factor on precipitations (fwfold)
  112. CALL ctl_opn( inum, 'EMPave_old.dat', 'OLD', 'FORMATTED', 'SEQUENTIAL', -1, numout, .FALSE. )
  113. READ ( inum, "(24X,I8,2ES24.16)" ) iyear, a_fwb_b, a_fwb
  114. CLOSE( inum )
  115. fwfold = a_fwb ! current year freshwater budget correction
  116. ! ! estimate from the previous year budget
  117. IF(lwp)WRITE(numout,*)
  118. IF(lwp)WRITE(numout,*)'sbc_fwb : year = ',iyear , ' freshwater budget correction = ', fwfold
  119. IF(lwp)WRITE(numout,*)' year = ',iyear-1, ' freshwater budget read = ', a_fwb
  120. IF(lwp)WRITE(numout,*)' year = ',iyear-2, ' freshwater budget read = ', a_fwb_b
  121. ENDIF
  122. ! ! Update fwfold if new year start
  123. ikty = 365 * 86400 / rdttra(1) !!bug use of 365 days leap year or 360d year !!!!!!!
  124. IF( MOD( kt, ikty ) == 0 ) THEN
  125. a_fwb_b = a_fwb ! mean sea level taking into account the ice+snow
  126. ! sum over the global domain
  127. a_fwb = glob_sum( e1e2t(:,:) * ( sshn(:,:) + snwice_mass(:,:) * r1_rau0 ) )
  128. a_fwb = a_fwb * 1.e+3 / ( area * rday * 365. ) ! convert in Kg/m3/s = mm/s
  129. !!gm ! !!bug 365d year
  130. fwfold = a_fwb ! current year freshwater budget correction
  131. ! ! estimate from the previous year budget
  132. ENDIF
  133. !
  134. IF( MOD( kt-1, kn_fsbc ) == 0 ) THEN ! correct the freshwater fluxes
  135. zcoef = fwfold * rcp
  136. emp(:,:) = emp(:,:) + fwfold * tmask(:,:,1)
  137. qns(:,:) = qns(:,:) - zcoef * sst_m(:,:) * tmask(:,:,1) ! account for change to the heat budget due to fw correction
  138. ENDIF
  139. !
  140. IF( kt == nitend .AND. lwp ) THEN ! save fwfold value in a file
  141. CALL ctl_opn( inum, 'EMPave.dat', 'REPLACE', 'FORMATTED', 'SEQUENTIAL', -1, numout, .FALSE., narea )
  142. WRITE( inum, "(24X,I8,2ES24.16)" ) nyear, a_fwb_b, a_fwb
  143. CLOSE( inum )
  144. ENDIF
  145. !
  146. CASE ( 3 ) !== global fwf set to zero and spread out over erp area ==!
  147. !
  148. IF( MOD( kt-1, kn_fsbc ) == 0 ) THEN
  149. ztmsk_pos(:,:) = tmask_i(:,:) ! Select <0 and >0 area of erp
  150. WHERE( erp < 0._wp ) ztmsk_pos = 0._wp
  151. ztmsk_neg(:,:) = tmask_i(:,:) - ztmsk_pos(:,:)
  152. !
  153. zsurf_neg = glob_sum( e1e2t(:,:)*ztmsk_neg(:,:) ) ! Area filled by <0 and >0 erp
  154. zsurf_pos = glob_sum( e1e2t(:,:)*ztmsk_pos(:,:) )
  155. ! ! fwf global mean (excluding ocean to ice/snow exchanges)
  156. z_fwf = glob_sum( e1e2t(:,:) * ( emp(:,:) - rnf(:,:) + fwfisf(:,:) - snwice_fmass(:,:) ) ) / area
  157. !
  158. IF( z_fwf < 0._wp ) THEN ! spread out over >0 erp area to increase evaporation
  159. zsurf_tospread = zsurf_pos
  160. ztmsk_tospread(:,:) = ztmsk_pos(:,:)
  161. ELSE ! spread out over <0 erp area to increase precipitation
  162. zsurf_tospread = zsurf_neg
  163. ztmsk_tospread(:,:) = ztmsk_neg(:,:)
  164. ENDIF
  165. !
  166. zsum_fwf = glob_sum( e1e2t(:,:) * z_fwf ) ! fwf global mean over <0 or >0 erp area
  167. !!gm : zsum_fwf = z_fwf * area ??? it is right? I think so....
  168. z_fwf_nsrf = zsum_fwf / ( zsurf_tospread + rsmall )
  169. ! ! weight to respect erp field 2D structure
  170. zsum_erp = glob_sum( ztmsk_tospread(:,:) * erp(:,:) * e1e2t(:,:) )
  171. z_wgt(:,:) = ztmsk_tospread(:,:) * erp(:,:) / ( zsum_erp + rsmall )
  172. ! ! final correction term to apply
  173. zerp_cor(:,:) = -1. * z_fwf_nsrf * zsurf_tospread * z_wgt(:,:)
  174. !
  175. !!gm ===>>>> lbc_lnk should be useless as all the computation is done over the whole domain !
  176. CALL lbc_lnk( zerp_cor, 'T', 1. )
  177. !
  178. emp(:,:) = emp(:,:) + zerp_cor(:,:)
  179. qns(:,:) = qns(:,:) - zerp_cor(:,:) * rcp * sst_m(:,:) ! account for change to the heat budget due to fw correction
  180. erp(:,:) = erp(:,:) + zerp_cor(:,:)
  181. !
  182. IF( nprint == 1 .AND. lwp ) THEN ! control print
  183. IF( z_fwf < 0._wp ) THEN
  184. WRITE(numout,*)' z_fwf < 0'
  185. WRITE(numout,*)' SUM(erp+) = ', SUM( ztmsk_tospread(:,:)*erp(:,:)*e1e2t(:,:) )*1.e-9,' Sv'
  186. ELSE
  187. WRITE(numout,*)' z_fwf >= 0'
  188. WRITE(numout,*)' SUM(erp-) = ', SUM( ztmsk_tospread(:,:)*erp(:,:)*e1e2t(:,:) )*1.e-9,' Sv'
  189. ENDIF
  190. WRITE(numout,*)' SUM(empG) = ', SUM( z_fwf*e1e2t(:,:) )*1.e-9,' Sv'
  191. WRITE(numout,*)' z_fwf = ', z_fwf ,' Kg/m2/s'
  192. WRITE(numout,*)' z_fwf_nsrf = ', z_fwf_nsrf ,' Kg/m2/s'
  193. WRITE(numout,*)' MIN(zerp_cor) = ', MINVAL(zerp_cor)
  194. WRITE(numout,*)' MAX(zerp_cor) = ', MAXVAL(zerp_cor)
  195. ENDIF
  196. ENDIF
  197. !
  198. CASE DEFAULT !== you should never be there ==!
  199. CALL ctl_stop( 'sbc_fwb : wrong nn_fwb value for the FreshWater Budget correction, choose either 1, 2 or 3' )
  200. !
  201. END SELECT
  202. !
  203. CALL wrk_dealloc( jpi,jpj, ztmsk_neg, ztmsk_pos, ztmsk_tospread, z_wgt, zerp_cor )
  204. !
  205. IF( nn_timing == 1 ) CALL timing_stop('sbc_fwb')
  206. !
  207. END SUBROUTINE sbc_fwb
  208. !!======================================================================
  209. END MODULE sbcfwb