New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
sbcblk.F90 in NEMO/trunk/cfgs/SPITZ12/MY_SRC – NEMO

source: NEMO/trunk/cfgs/SPITZ12/MY_SRC/sbcblk.F90 @ 9769

Last change on this file since 9769 was 9769, checked in by clem, 6 years ago

remaining cp_ice_msh to be removed

File size: 70.8 KB
Line 
1MODULE sbcblk
2   !!======================================================================
3   !!                       ***  MODULE  sbcblk  ***
4   !! Ocean forcing:  momentum, heat and freshwater flux formulation
5   !!                         Aerodynamic Bulk Formulas
6   !!                        SUCCESSOR OF "sbcblk_core"
7   !!=====================================================================
8   !! History :  1.0  !  2004-08  (U. Schweckendiek)  Original CORE code
9   !!            2.0  !  2005-04  (L. Brodeau, A.M. Treguier)  improved CORE bulk and its user interface
10   !!            3.0  !  2006-06  (G. Madec)  sbc rewritting
11   !!             -   !  2006-12  (L. Brodeau)  Original code for turb_core
12   !!            3.2  !  2009-04  (B. Lemaire)  Introduce iom_put
13   !!            3.3  !  2010-10  (S. Masson)  add diurnal cycle
14   !!            3.4  !  2011-11  (C. Harris)  Fill arrays required by CICE
15   !!            3.7  !  2014-06  (L. Brodeau)  simplification and optimization of CORE bulk
16   !!            4.0  !  2016-06  (L. Brodeau)  sbcblk_core becomes sbcblk and is not restricted to the CORE algorithm anymore
17   !!                 !                        ==> based on AeroBulk (http://aerobulk.sourceforge.net/)
18   !!            4.0  !  2016-10  (G. Madec)  introduce a sbc_blk_init routine
19   !!            4.0  !  2016-10  (M. Vancoppenolle)  Introduce Jules emulator (M. Vancoppenolle)
20   !!----------------------------------------------------------------------
21
22   !!----------------------------------------------------------------------
23   !!   sbc_blk_init  : initialisation of the chosen bulk formulation as ocean surface boundary condition
24   !!   sbc_blk       : bulk formulation as ocean surface boundary condition
25   !!   blk_oce       : computes momentum, heat and freshwater fluxes over ocean
26   !!   rho_air       : density of (moist) air (depends on T_air, q_air and SLP
27   !!   cp_air        : specific heat of (moist) air (depends spec. hum. q_air)
28   !!   q_sat         : saturation humidity as a function of SLP and temperature
29   !!   L_vap         : latent heat of vaporization of water as a function of temperature
30   !!             sea-ice case only :
31   !!   blk_ice_tau   : provide the air-ice stress
32   !!   blk_ice_flx   : provide the heat and mass fluxes at air-ice interface
33   !!   blk_ice_qcn   : provide ice surface temperature and snow/ice conduction flux (emulating JULES coupler)
34   !!   Cdn10_Lupkes2012 : Lupkes et al. (2012) air-ice drag
35   !!   Cdn10_Lupkes2015 : Lupkes et al. (2015) air-ice drag
36   !!----------------------------------------------------------------------
37   USE oce            ! ocean dynamics and tracers
38   USE dom_oce        ! ocean space and time domain
39   USE phycst         ! physical constants
40   USE fldread        ! read input fields
41   USE sbc_oce        ! Surface boundary condition: ocean fields
42   USE cyclone        ! Cyclone 10m wind form trac of cyclone centres
43   USE sbcdcy         ! surface boundary condition: diurnal cycle
44   USE sbcwave , ONLY :   cdn_wave ! wave module
45   USE sbc_ice        ! Surface boundary condition: ice fields
46   USE lib_fortran    ! to use key_nosignedzero
47#if defined key_si3
48   USE ice     , ONLY :   u_ice, v_ice, jpl, a_i_b, at_i_b, tm_su, rn_cnd_s
49   USE icethd_dh      ! for CALL ice_thd_snwblow
50#endif
51   USE sbcblk_algo_ncar     ! => turb_ncar     : NCAR - CORE (Large & Yeager, 2009)
52   USE sbcblk_algo_coare    ! => turb_coare    : COAREv3.0 (Fairall et al. 2003)
53   USE sbcblk_algo_coare3p5 ! => turb_coare3p5 : COAREv3.5 (Edson et al. 2013)
54   USE sbcblk_algo_ecmwf    ! => turb_ecmwf    : ECMWF (IFS cycle 31)
55   !
56   USE iom            ! I/O manager library
57   USE in_out_manager ! I/O manager
58   USE lib_mpp        ! distribued memory computing library
59   USE lbclnk         ! ocean lateral boundary conditions (or mpp link)
60   USE prtctl         ! Print control
61
62   IMPLICIT NONE
63   PRIVATE
64
65   PUBLIC   sbc_blk_init  ! called in sbcmod
66   PUBLIC   sbc_blk       ! called in sbcmod
67#if defined key_si3
68   PUBLIC   blk_ice_tau   ! routine called in iceforcing
69   PUBLIC   blk_ice_flx   ! routine called in iceforcing
70   PUBLIC   blk_ice_qcn   ! routine called in iceforcing
71#endif 
72
73!!Lolo: should ultimately be moved in the module with all physical constants ?
74!!gm  : In principle, yes.
75   REAL(wp), PARAMETER ::   Cp_dry = 1005.0       !: Specic heat of dry air, constant pressure      [J/K/kg]
76   REAL(wp), PARAMETER ::   Cp_vap = 1860.0       !: Specic heat of water vapor, constant pressure  [J/K/kg]
77   REAL(wp), PARAMETER ::   R_dry = 287.05_wp     !: Specific gas constant for dry air              [J/K/kg]
78   REAL(wp), PARAMETER ::   R_vap = 461.495_wp    !: Specific gas constant for water vapor          [J/K/kg]
79   REAL(wp), PARAMETER ::   reps0 = R_dry/R_vap   !: ratio of gas constant for dry air and water vapor => ~ 0.622
80   REAL(wp), PARAMETER ::   rctv0 = R_vap/R_dry   !: for virtual temperature (== (1-eps)/eps) => ~ 0.608
81
82!!clem   INTEGER , PARAMETER ::   jpfld   =10           ! maximum number of files to read
83   INTEGER , PARAMETER ::   jpfld   = 8           ! maximum number of files to read
84   INTEGER , PARAMETER ::   jp_wndi = 1           ! index of 10m wind velocity (i-component) (m/s)    at T-point
85   INTEGER , PARAMETER ::   jp_wndj = 2           ! index of 10m wind velocity (j-component) (m/s)    at T-point
86   INTEGER , PARAMETER ::   jp_tair = 3           ! index of 10m air temperature             (Kelvin)
87   INTEGER , PARAMETER ::   jp_humi = 4           ! index of specific humidity               ( % )
88   INTEGER , PARAMETER ::   jp_qsr  = 5           ! index of solar heat                      (W/m2)
89   INTEGER , PARAMETER ::   jp_qlw  = 6           ! index of Long wave                       (W/m2)
90   INTEGER , PARAMETER ::   jp_prec = 7           ! index of total precipitation (rain+snow) (Kg/m2/s)
91   INTEGER , PARAMETER ::   jp_snow = 8           ! index of snow (solid prcipitation)       (kg/m2/s)
92   INTEGER , PARAMETER ::   jp_slp  = 9           ! index of sea level pressure              (Pa)
93   INTEGER , PARAMETER ::   jp_tdif =10           ! index of tau diff associated to HF tau   (N/m2)   at T-point
94
95   TYPE(FLD), ALLOCATABLE, DIMENSION(:) ::   sf   ! structure of input fields (file informations, fields read)
96
97   !                                             !!! Bulk parameters
98   REAL(wp), PARAMETER ::   cpa    = 1000.5         ! specific heat of air (only used for ice fluxes now...)
99   REAL(wp), PARAMETER ::   Ls     =    2.839e6     ! latent heat of sublimation
100   REAL(wp), PARAMETER ::   Stef   =    5.67e-8     ! Stefan Boltzmann constant
101   REAL(wp), PARAMETER ::   Cd_ice =    1.4e-3      ! transfer coefficient over ice
102   REAL(wp), PARAMETER ::   albo   =    0.066       ! ocean albedo assumed to be constant
103   !
104   !                           !!* Namelist namsbc_blk : bulk parameters
105   LOGICAL  ::   ln_NCAR        ! "NCAR"      algorithm   (Large and Yeager 2008)
106   LOGICAL  ::   ln_COARE_3p0   ! "COARE 3.0" algorithm   (Fairall et al. 2003)
107   LOGICAL  ::   ln_COARE_3p5   ! "COARE 3.5" algorithm   (Edson et al. 2013)
108   LOGICAL  ::   ln_ECMWF       ! "ECMWF"     algorithm   (IFS cycle 31)
109   !
110   LOGICAL  ::   ln_taudif      ! logical flag to use the "mean of stress module - module of mean stress" data
111   REAL(wp) ::   rn_pfac        ! multiplication factor for precipitation
112   REAL(wp) ::   rn_efac        ! multiplication factor for evaporation
113   REAL(wp) ::   rn_vfac        ! multiplication factor for ice/ocean velocity in the calculation of wind stress
114   REAL(wp) ::   rn_zqt         ! z(q,t) : height of humidity and temperature measurements
115   REAL(wp) ::   rn_zu          ! z(u)   : height of wind measurements
116!!gm ref namelist initialize it so remove the setting to false below
117   LOGICAL  ::   ln_Cd_L12 = .FALSE. !  Modify the drag ice-atm depending on ice concentration (from Lupkes et al. JGR2012)
118   LOGICAL  ::   ln_Cd_L15 = .FALSE. !  Modify the drag ice-atm depending on ice concentration (from Lupkes et al. JGR2015)
119   !
120   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) ::   Cd_atm                    ! transfer coefficient for momentum      (tau)
121   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) ::   Ch_atm                    ! transfer coefficient for sensible heat (Q_sens)
122   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) ::   Ce_atm                    ! tansfert coefficient for evaporation   (Q_lat)
123   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) ::   t_zu                      ! air temperature at wind speed height (needed by Lupkes 2015 bulk scheme)
124   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) ::   q_zu                      ! air spec. hum.  at wind speed height (needed by Lupkes 2015 bulk scheme)
125   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) ::   cdn_oce, chn_oce, cen_oce ! needed by Lupkes 2015 bulk scheme
126
127   INTEGER  ::   nblk           ! choice of the bulk algorithm
128   !                            ! associated indices:
129   INTEGER, PARAMETER ::   np_NCAR      = 1   ! "NCAR" algorithm        (Large and Yeager 2008)
130   INTEGER, PARAMETER ::   np_COARE_3p0 = 2   ! "COARE 3.0" algorithm   (Fairall et al. 2003)
131   INTEGER, PARAMETER ::   np_COARE_3p5 = 3   ! "COARE 3.5" algorithm   (Edson et al. 2013)
132   INTEGER, PARAMETER ::   np_ECMWF     = 4   ! "ECMWF" algorithm       (IFS cycle 31)
133
134   !! * Substitutions
135#  include "vectopt_loop_substitute.h90"
136   !!----------------------------------------------------------------------
137   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
138   !! $Id: sbcblk.F90 6416 2016-04-01 12:22:17Z clem $
139   !! Software governed by the CeCILL licence     (./LICENSE)
140   !!----------------------------------------------------------------------
141CONTAINS
142
143   INTEGER FUNCTION sbc_blk_alloc()
144      !!-------------------------------------------------------------------
145      !!             ***  ROUTINE sbc_blk_alloc ***
146      !!-------------------------------------------------------------------
147      ALLOCATE( Cd_atm (jpi,jpj), Ch_atm (jpi,jpj), Ce_atm (jpi,jpj), t_zu(jpi,jpj), q_zu(jpi,jpj), &
148         &      cdn_oce(jpi,jpj), chn_oce(jpi,jpj), cen_oce(jpi,jpj), STAT=sbc_blk_alloc )
149      !
150      IF( lk_mpp             )   CALL mpp_sum ( sbc_blk_alloc )
151      IF( sbc_blk_alloc /= 0 )   CALL ctl_warn('sbc_blk_alloc: failed to allocate arrays')
152   END FUNCTION sbc_blk_alloc
153
154
155   SUBROUTINE sbc_blk_init
156      !!---------------------------------------------------------------------
157      !!                    ***  ROUTINE sbc_blk_init  ***
158      !!
159      !! ** Purpose :   choose and initialize a bulk formulae formulation
160      !!
161      !! ** Method  :
162      !!
163      !!----------------------------------------------------------------------
164      INTEGER  ::   ifpr, jfld            ! dummy loop indice and argument
165      INTEGER  ::   ios, ierror, ioptio   ! Local integer
166      !!
167      CHARACTER(len=100)            ::   cn_dir                ! Root directory for location of atmospheric forcing files
168      TYPE(FLD_N), DIMENSION(jpfld) ::   slf_i                 ! array of namelist informations on the fields to read
169      TYPE(FLD_N) ::   sn_wndi, sn_wndj, sn_humi, sn_qsr       ! informations about the fields to be read
170      TYPE(FLD_N) ::   sn_qlw , sn_tair, sn_prec, sn_snow      !       "                        "
171      TYPE(FLD_N) ::   sn_slp , sn_tdif                        !       "                        "
172      NAMELIST/namsbc_blk/ sn_wndi, sn_wndj, sn_humi, sn_qsr, sn_qlw ,                &   ! input fields
173         &                 sn_tair, sn_prec, sn_snow, sn_slp, sn_tdif,                &
174         &                 ln_NCAR, ln_COARE_3p0, ln_COARE_3p5, ln_ECMWF,             &   ! bulk algorithm
175         &                 cn_dir , ln_taudif, rn_zqt, rn_zu,                         & 
176         &                 rn_pfac, rn_efac, rn_vfac, ln_Cd_L12, ln_Cd_L15
177      !!---------------------------------------------------------------------
178      !
179      !                                      ! allocate sbc_blk_core array
180      IF( sbc_blk_alloc() /= 0 )   CALL ctl_stop( 'STOP', 'sbc_blk : unable to allocate standard arrays' )
181      !
182      !                             !** read bulk namelist 
183      REWIND( numnam_ref )                !* Namelist namsbc_blk in reference namelist : bulk parameters
184      READ  ( numnam_ref, namsbc_blk, IOSTAT = ios, ERR = 901)
185901   IF( ios /= 0 )   CALL ctl_nam ( ios , 'namsbc_blk in reference namelist', lwp )
186      !
187      REWIND( numnam_cfg )                !* Namelist namsbc_blk in configuration namelist : bulk parameters
188      READ  ( numnam_cfg, namsbc_blk, IOSTAT = ios, ERR = 902 )
189902   IF( ios >  0 )   CALL ctl_nam ( ios , 'namsbc_blk in configuration namelist', lwp )
190      !
191      IF(lwm) WRITE( numond, namsbc_blk )
192      !
193      !                             !** initialization of the chosen bulk formulae (+ check)
194      !                                   !* select the bulk chosen in the namelist and check the choice
195                                                               ioptio = 0
196      IF( ln_NCAR      ) THEN   ;   nblk =  np_NCAR        ;   ioptio = ioptio + 1   ;   ENDIF
197      IF( ln_COARE_3p0 ) THEN   ;   nblk =  np_COARE_3p0   ;   ioptio = ioptio + 1   ;   ENDIF
198      IF( ln_COARE_3p5 ) THEN   ;   nblk =  np_COARE_3p5   ;   ioptio = ioptio + 1   ;   ENDIF
199      IF( ln_ECMWF     ) THEN   ;   nblk =  np_ECMWF       ;   ioptio = ioptio + 1   ;   ENDIF
200      !
201      IF( ioptio /= 1 )   CALL ctl_stop( 'sbc_blk_init: Choose one and only one bulk algorithm' )
202      !
203      IF( ln_dm2dc ) THEN                 !* check: diurnal cycle on Qsr
204         IF( sn_qsr%nfreqh /= 24 )   CALL ctl_stop( 'sbc_blk_init: ln_dm2dc=T only with daily short-wave input' )
205         IF( sn_qsr%ln_tint ) THEN
206            CALL ctl_warn( 'sbc_blk_init: ln_dm2dc=T daily qsr time interpolation done by sbcdcy module',   &
207               &           '              ==> We force time interpolation = .false. for qsr' )
208            sn_qsr%ln_tint = .false.
209         ENDIF
210      ENDIF
211      !                                   !* set the bulk structure
212      !                                      !- store namelist information in an array
213      slf_i(jp_wndi) = sn_wndi   ;   slf_i(jp_wndj) = sn_wndj
214      slf_i(jp_qsr ) = sn_qsr    ;   slf_i(jp_qlw ) = sn_qlw
215      slf_i(jp_tair) = sn_tair   ;   slf_i(jp_humi) = sn_humi
216      slf_i(jp_prec) = sn_prec   ;   slf_i(jp_snow) = sn_snow
217!!clem      slf_i(jp_slp)  = sn_slp    ;   slf_i(jp_tdif) = sn_tdif
218      !
219      lhftau = ln_taudif                     !- add an extra field if HF stress is used
220!!clem      jfld = jpfld - COUNT( (/.NOT.lhftau/) )
221      jfld = jpfld
222      !
223      !                                      !- allocate the bulk structure
224      ALLOCATE( sf(jfld), STAT=ierror )
225      IF( ierror > 0 )   CALL ctl_stop( 'STOP', 'sbc_blk_init: unable to allocate sf structure' )
226      DO ifpr= 1, jfld
227         ALLOCATE( sf(ifpr)%fnow(jpi,jpj,1) )
228         IF( slf_i(ifpr)%ln_tint )   ALLOCATE( sf(ifpr)%fdta(jpi,jpj,1,2) )
229         IF( slf_i(ifpr)%nfreqh > 0. .AND. MOD( 3600. * slf_i(ifpr)%nfreqh , REAL(nn_fsbc) * rdt) /= 0. )   &
230            &  CALL ctl_warn( 'sbc_blk_init: sbcmod timestep rdt*nn_fsbc is NOT a submultiple of atmospheric forcing frequency.',   &
231            &                 '               This is not ideal. You should consider changing either rdt or nn_fsbc value...' )
232
233      END DO
234      !                                      !- fill the bulk structure with namelist informations
235      CALL fld_fill( sf, slf_i, cn_dir, 'sbc_blk_init', 'surface boundary condition -- bulk formulae', 'namsbc_blk' )
236      !
237      IF ( ln_wave ) THEN
238      !Activated wave module but neither drag nor stokes drift activated
239         IF ( .NOT.(ln_cdgw .OR. ln_sdw .OR. ln_tauwoc .OR. ln_stcor ) )   THEN
240            CALL ctl_warn( 'Ask for wave coupling but ln_cdgw=F, ln_sdw=F, ln_tauwoc=F, ln_stcor=F')
241      !drag coefficient read from wave model definable only with mfs bulk formulae and core
242         ELSEIF (ln_cdgw .AND. .NOT. ln_NCAR )       THEN       
243             CALL ctl_stop( 'drag coefficient read from wave model definable only with mfs bulk formulae and core')
244         ELSEIF (ln_stcor .AND. .NOT. ln_sdw)                             THEN
245             CALL ctl_stop( 'Stokes-Coriolis term calculated only if activated Stokes Drift ln_sdw=T')
246         ENDIF
247      ELSE
248      IF ( ln_cdgw .OR. ln_sdw .OR. ln_tauwoc .OR. ln_stcor )                & 
249         &   CALL ctl_stop( 'Not Activated Wave Module (ln_wave=F) but asked coupling ',    &
250         &                  'with drag coefficient (ln_cdgw =T) '  ,                        &
251         &                  'or Stokes Drift (ln_sdw=T) ' ,                                 &
252         &                  'or ocean stress modification due to waves (ln_tauwoc=T) ',      & 
253         &                  'or Stokes-Coriolis term (ln_stcori=T)'  )
254      ENDIF 
255      !
256      !           
257      IF(lwp) THEN                     !** Control print
258         !
259         WRITE(numout,*)                  !* namelist
260         WRITE(numout,*) '   Namelist namsbc_blk (other than data information):'
261         WRITE(numout,*) '      "NCAR"      algorithm   (Large and Yeager 2008)     ln_NCAR      = ', ln_NCAR
262         WRITE(numout,*) '      "COARE 3.0" algorithm   (Fairall et al. 2003)       ln_COARE_3p0 = ', ln_COARE_3p0
263         WRITE(numout,*) '      "COARE 3.5" algorithm   (Edson et al. 2013)         ln_COARE_3p5 = ', ln_COARE_3p0
264         WRITE(numout,*) '      "ECMWF"     algorithm   (IFS cycle 31)              ln_ECMWF     = ', ln_ECMWF
265         WRITE(numout,*) '      add High freq.contribution to the stress module     ln_taudif    = ', ln_taudif
266         WRITE(numout,*) '      Air temperature and humidity reference height (m)   rn_zqt       = ', rn_zqt
267         WRITE(numout,*) '      Wind vector reference height (m)                    rn_zu        = ', rn_zu
268         WRITE(numout,*) '      factor applied on precipitation (total & snow)      rn_pfac      = ', rn_pfac
269         WRITE(numout,*) '      factor applied on evaporation                       rn_efac      = ', rn_efac
270         WRITE(numout,*) '      factor applied on ocean/ice velocity                rn_vfac      = ', rn_vfac
271         WRITE(numout,*) '         (form absolute (=0) to relative winds(=1))'
272         WRITE(numout,*) '      use ice-atm drag from Lupkes2012                    ln_Cd_L12    = ', ln_Cd_L12
273         WRITE(numout,*) '      use ice-atm drag from Lupkes2015                    ln_Cd_L15    = ', ln_Cd_L15
274         !
275         WRITE(numout,*)
276         SELECT CASE( nblk )              !* Print the choice of bulk algorithm
277         CASE( np_NCAR      )   ;   WRITE(numout,*) '   ==>>>   "NCAR" algorithm        (Large and Yeager 2008)'
278         CASE( np_COARE_3p0 )   ;   WRITE(numout,*) '   ==>>>   "COARE 3.0" algorithm   (Fairall et al. 2003)'
279         CASE( np_COARE_3p5 )   ;   WRITE(numout,*) '   ==>>>   "COARE 3.5" algorithm   (Edson et al. 2013)'
280         CASE( np_ECMWF     )   ;   WRITE(numout,*) '   ==>>>   "ECMWF" algorithm       (IFS cycle 31)'
281         END SELECT
282         !
283      ENDIF
284      !
285   END SUBROUTINE sbc_blk_init
286
287
288   SUBROUTINE sbc_blk( kt )
289      !!---------------------------------------------------------------------
290      !!                    ***  ROUTINE sbc_blk  ***
291      !!
292      !! ** Purpose :   provide at each time step the surface ocean fluxes
293      !!              (momentum, heat, freshwater and runoff)
294      !!
295      !! ** Method  : (1) READ each fluxes in NetCDF files:
296      !!      the 10m wind velocity (i-component) (m/s)    at T-point
297      !!      the 10m wind velocity (j-component) (m/s)    at T-point
298      !!      the 10m or 2m specific humidity     ( % )
299      !!      the solar heat                      (W/m2)
300      !!      the Long wave                       (W/m2)
301      !!      the 10m or 2m air temperature       (Kelvin)
302      !!      the total precipitation (rain+snow) (Kg/m2/s)
303      !!      the snow (solid prcipitation)       (kg/m2/s)
304      !!      the tau diff associated to HF tau   (N/m2)   at T-point   (ln_taudif=T)
305      !!              (2) CALL blk_oce
306      !!
307      !!      C A U T I O N : never mask the surface stress fields
308      !!                      the stress is assumed to be in the (i,j) mesh referential
309      !!
310      !! ** Action  :   defined at each time-step at the air-sea interface
311      !!              - utau, vtau  i- and j-component of the wind stress
312      !!              - taum        wind stress module at T-point
313      !!              - wndm        wind speed  module at T-point over free ocean or leads in presence of sea-ice
314      !!              - qns, qsr    non-solar and solar heat fluxes
315      !!              - emp         upward mass flux (evapo. - precip.)
316      !!              - sfx         salt flux due to freezing/melting (non-zero only if ice is present)
317      !!
318      !! ** References :   Large & Yeager, 2004 / Large & Yeager, 2008
319      !!                   Brodeau et al. Ocean Modelling 2010
320      !!----------------------------------------------------------------------
321      INTEGER, INTENT(in) ::   kt   ! ocean time step
322      !!---------------------------------------------------------------------
323      !
324      CALL fld_read( kt, nn_fsbc, sf )             ! input fields provided at the current time-step
325      !
326      !                                            ! compute the surface ocean fluxes using bulk formulea
327      IF( MOD( kt - 1, nn_fsbc ) == 0 )   CALL blk_oce( kt, sf, sst_m, ssu_m, ssv_m )
328
329#if defined key_cice
330      IF( MOD( kt - 1, nn_fsbc ) == 0 )   THEN
331         qlw_ice(:,:,1)   = sf(jp_qlw )%fnow(:,:,1)
332         IF( ln_dm2dc ) THEN ; qsr_ice(:,:,1) = sbc_dcy( sf(jp_qsr)%fnow(:,:,1) )
333         ELSE                ; qsr_ice(:,:,1) =          sf(jp_qsr)%fnow(:,:,1) 
334         ENDIF
335         tatm_ice(:,:)    = sf(jp_tair)%fnow(:,:,1)
336         qatm_ice(:,:)    = sf(jp_humi)%fnow(:,:,1)
337         tprecip(:,:)     = sf(jp_prec)%fnow(:,:,1) * rn_pfac
338         sprecip(:,:)     = sf(jp_snow)%fnow(:,:,1) * rn_pfac
339         wndi_ice(:,:)    = sf(jp_wndi)%fnow(:,:,1)
340         wndj_ice(:,:)    = sf(jp_wndj)%fnow(:,:,1)
341      ENDIF
342#endif
343      !
344   END SUBROUTINE sbc_blk
345
346
347   SUBROUTINE blk_oce( kt, sf, pst, pu, pv )
348      !!---------------------------------------------------------------------
349      !!                     ***  ROUTINE blk_oce  ***
350      !!
351      !! ** Purpose :   provide the momentum, heat and freshwater fluxes at
352      !!      the ocean surface at each time step
353      !!
354      !! ** Method  :   bulk formulea for the ocean using atmospheric
355      !!      fields read in sbc_read
356      !!
357      !! ** Outputs : - utau    : i-component of the stress at U-point  (N/m2)
358      !!              - vtau    : j-component of the stress at V-point  (N/m2)
359      !!              - taum    : Wind stress module at T-point         (N/m2)
360      !!              - wndm    : Wind speed module at T-point          (m/s)
361      !!              - qsr     : Solar heat flux over the ocean        (W/m2)
362      !!              - qns     : Non Solar heat flux over the ocean    (W/m2)
363      !!              - emp     : evaporation minus precipitation       (kg/m2/s)
364      !!
365      !!  ** Nota  :   sf has to be a dummy argument for AGRIF on NEC
366      !!---------------------------------------------------------------------
367      INTEGER  , INTENT(in   )                 ::   kt    ! time step index
368      TYPE(fld), INTENT(inout), DIMENSION(:)   ::   sf    ! input data
369      REAL(wp) , INTENT(in)   , DIMENSION(:,:) ::   pst   ! surface temperature                      [Celcius]
370      REAL(wp) , INTENT(in)   , DIMENSION(:,:) ::   pu    ! surface current at U-point (i-component) [m/s]
371      REAL(wp) , INTENT(in)   , DIMENSION(:,:) ::   pv    ! surface current at V-point (j-component) [m/s]
372      !
373      INTEGER  ::   ji, jj               ! dummy loop indices
374      REAL(wp) ::   zztmp                ! local variable
375      REAL(wp), DIMENSION(jpi,jpj) ::   zwnd_i, zwnd_j    ! wind speed components at T-point
376      REAL(wp), DIMENSION(jpi,jpj) ::   zsq               ! specific humidity at pst
377      REAL(wp), DIMENSION(jpi,jpj) ::   zqlw, zqsb        ! long wave and sensible heat fluxes
378      REAL(wp), DIMENSION(jpi,jpj) ::   zqla, zevap       ! latent heat fluxes and evaporation
379      REAL(wp), DIMENSION(jpi,jpj) ::   zst               ! surface temperature in Kelvin
380      REAL(wp), DIMENSION(jpi,jpj) ::   zU_zu             ! bulk wind speed at height zu  [m/s]
381      REAL(wp), DIMENSION(jpi,jpj) ::   ztpot             ! potential temperature of air at z=rn_zqt [K]
382      REAL(wp), DIMENSION(jpi,jpj) ::   zrhoa             ! density of air   [kg/m^3]
383      !!---------------------------------------------------------------------
384      !
385      ! local scalars ( place there for vector optimisation purposes)
386      zst(:,:) = pst(:,:) + rt0      ! convert SST from Celcius to Kelvin (and set minimum value far above 0 K)
387
388      ! ----------------------------------------------------------------------------- !
389      !      0   Wind components and module at T-point relative to the moving ocean   !
390      ! ----------------------------------------------------------------------------- !
391
392      ! ... components ( U10m - U_oce ) at T-point (unmasked)
393!!gm    move zwnd_i (_j) set to zero  inside the key_cyclone ???
394      zwnd_i(:,:) = 0._wp
395      zwnd_j(:,:) = 0._wp
396#if defined key_cyclone
397      CALL wnd_cyc( kt, zwnd_i, zwnd_j )    ! add analytical tropical cyclone (Vincent et al. JGR 2012)
398      DO jj = 2, jpjm1
399         DO ji = fs_2, fs_jpim1   ! vect. opt.
400            sf(jp_wndi)%fnow(ji,jj,1) = sf(jp_wndi)%fnow(ji,jj,1) + zwnd_i(ji,jj)
401            sf(jp_wndj)%fnow(ji,jj,1) = sf(jp_wndj)%fnow(ji,jj,1) + zwnd_j(ji,jj)
402         END DO
403      END DO
404#endif
405      DO jj = 2, jpjm1
406         DO ji = fs_2, fs_jpim1   ! vect. opt.
407            zwnd_i(ji,jj) = (  sf(jp_wndi)%fnow(ji,jj,1) - rn_vfac * 0.5 * ( pu(ji-1,jj  ) + pu(ji,jj) )  )
408            zwnd_j(ji,jj) = (  sf(jp_wndj)%fnow(ji,jj,1) - rn_vfac * 0.5 * ( pv(ji  ,jj-1) + pv(ji,jj) )  )
409         END DO
410      END DO
411      CALL lbc_lnk_multi( zwnd_i, 'T', -1., zwnd_j, 'T', -1. )
412      ! ... scalar wind ( = | U10m - U_oce | ) at T-point (masked)
413      wndm(:,:) = SQRT(  zwnd_i(:,:) * zwnd_i(:,:)   &
414         &             + zwnd_j(:,:) * zwnd_j(:,:)  ) * tmask(:,:,1)
415
416      ! ----------------------------------------------------------------------------- !
417      !      I   Radiative FLUXES                                                     !
418      ! ----------------------------------------------------------------------------- !
419
420      ! ocean albedo assumed to be constant + modify now Qsr to include the diurnal cycle                    ! Short Wave
421      zztmp = 1. - albo
422      IF( ln_dm2dc ) THEN   ;   qsr(:,:) = zztmp * sbc_dcy( sf(jp_qsr)%fnow(:,:,1) ) * tmask(:,:,1)
423      ELSE                  ;   qsr(:,:) = zztmp *          sf(jp_qsr)%fnow(:,:,1)   * tmask(:,:,1)
424      ENDIF
425
426      zqlw(:,:) = (  sf(jp_qlw)%fnow(:,:,1) - Stef * zst(:,:)*zst(:,:)*zst(:,:)*zst(:,:)  ) * tmask(:,:,1)   ! Long  Wave
427
428      ! ----------------------------------------------------------------------------- !
429      !     II    Turbulent FLUXES                                                    !
430      ! ----------------------------------------------------------------------------- !
431
432      ! ... specific humidity at SST and IST tmask(
433!!clem      zsq(:,:) = 0.98 * q_sat( zst(:,:), sf(jp_slp)%fnow(:,:,1) )
434      zsq(:,:) = 0.98 * q_sat( zst(:,:), 101300. )
435      !!
436      !! Estimate of potential temperature at z=rn_zqt, based on adiabatic lapse-rate
437      !!    (see Josey, Gulev & Yu, 2013) / doi=10.1016/B978-0-12-391851-2.00005-2
438      !!    (since reanalysis products provide T at z, not theta !)
439      ztpot = sf(jp_tair)%fnow(:,:,1) + gamma_moist( sf(jp_tair)%fnow(:,:,1), sf(jp_humi)%fnow(:,:,1) ) * rn_zqt
440
441      SELECT CASE( nblk )        !==  transfer coefficients  ==!   Cd, Ch, Ce at T-point
442      !
443      CASE( np_NCAR      )   ;   CALL turb_ncar    ( rn_zqt, rn_zu, zst, ztpot, zsq, sf(jp_humi)%fnow, wndm,   &  ! NCAR-COREv2
444         &                                           Cd_atm, Ch_atm, Ce_atm, t_zu, q_zu, zU_zu, cdn_oce, chn_oce, cen_oce )
445      CASE( np_COARE_3p0 )   ;   CALL turb_coare   ( rn_zqt, rn_zu, zst, ztpot, zsq, sf(jp_humi)%fnow, wndm,   &  ! COARE v3.0
446         &                                           Cd_atm, Ch_atm, Ce_atm, t_zu, q_zu, zU_zu, cdn_oce, chn_oce, cen_oce )
447      CASE( np_COARE_3p5 )   ;   CALL turb_coare3p5( rn_zqt, rn_zu, zst, ztpot, zsq, sf(jp_humi)%fnow, wndm,   &  ! COARE v3.5
448         &                                           Cd_atm, Ch_atm, Ce_atm, t_zu, q_zu, zU_zu, cdn_oce, chn_oce, cen_oce )
449      CASE( np_ECMWF     )   ;   CALL turb_ecmwf   ( rn_zqt, rn_zu, zst, ztpot, zsq, sf(jp_humi)%fnow, wndm,   &  ! ECMWF
450         &                                           Cd_atm, Ch_atm, Ce_atm, t_zu, q_zu, zU_zu, cdn_oce, chn_oce, cen_oce )
451      CASE DEFAULT
452         CALL ctl_stop( 'STOP', 'sbc_oce: non-existing bulk formula selected' )
453      END SELECT
454
455      !                          ! Compute true air density :
456      IF( ABS(rn_zu - rn_zqt) > 0.01 ) THEN     ! At zu: (probably useless to remove zrho*grav*rn_zu from SLP...)
457!!clem         zrhoa(:,:) = rho_air( t_zu(:,:)              , q_zu(:,:)              , sf(jp_slp)%fnow(:,:,1) )
458         zrhoa(:,:) = rho_air( t_zu(:,:)              , q_zu(:,:)              , 101300. )
459      ELSE                                      ! At zt:
460!!clem         zrhoa(:,:) = rho_air( sf(jp_tair)%fnow(:,:,1), sf(jp_humi)%fnow(:,:,1), sf(jp_slp)%fnow(:,:,1) )
461         zrhoa(:,:) = rho_air( sf(jp_tair)%fnow(:,:,1), sf(jp_humi)%fnow(:,:,1), 101300. )
462      END IF
463
464!!      CALL iom_put( "Cd_oce", Cd_atm)  ! output value of pure ocean-atm. transfer coef.
465!!      CALL iom_put( "Ch_oce", Ch_atm)  ! output value of pure ocean-atm. transfer coef.
466
467      DO jj = 1, jpj             ! tau module, i and j component
468         DO ji = 1, jpi
469            zztmp = zrhoa(ji,jj)  * zU_zu(ji,jj) * Cd_atm(ji,jj)   ! using bulk wind speed
470            taum  (ji,jj) = zztmp * wndm  (ji,jj)
471            zwnd_i(ji,jj) = zztmp * zwnd_i(ji,jj)
472            zwnd_j(ji,jj) = zztmp * zwnd_j(ji,jj)
473         END DO
474      END DO
475
476      !                          ! add the HF tau contribution to the wind stress module
477!!clem      IF( lhftau )   taum(:,:) = taum(:,:) + sf(jp_tdif)%fnow(:,:,1)
478
479      CALL iom_put( "taum_oce", taum )   ! output wind stress module
480
481      ! ... utau, vtau at U- and V_points, resp.
482      !     Note the use of 0.5*(2-umask) in order to unmask the stress along coastlines
483      !     Note the use of MAX(tmask(i,j),tmask(i+1,j) is to mask tau over ice shelves
484      DO jj = 1, jpjm1
485         DO ji = 1, fs_jpim1
486            utau(ji,jj) = 0.5 * ( 2. - umask(ji,jj,1) ) * ( zwnd_i(ji,jj) + zwnd_i(ji+1,jj  ) ) &
487               &          * MAX(tmask(ji,jj,1),tmask(ji+1,jj,1))
488            vtau(ji,jj) = 0.5 * ( 2. - vmask(ji,jj,1) ) * ( zwnd_j(ji,jj) + zwnd_j(ji  ,jj+1) ) &
489               &          * MAX(tmask(ji,jj,1),tmask(ji,jj+1,1))
490         END DO
491      END DO
492      CALL lbc_lnk_multi( utau, 'U', -1., vtau, 'V', -1. )
493
494      !  Turbulent fluxes over ocean
495      ! -----------------------------
496
497      ! zqla used as temporary array, for rho*U (common term of bulk formulae):
498      zqla(:,:) = zrhoa(:,:) * zU_zu(:,:) * tmask(:,:,1)
499
500      IF( ABS( rn_zu - rn_zqt) < 0.01_wp ) THEN
501         !! q_air and t_air are given at 10m (wind reference height)
502         zevap(:,:) = rn_efac*MAX( 0._wp,             zqla(:,:)*Ce_atm(:,:)*(zsq(:,:) - sf(jp_humi)%fnow(:,:,1)) ) ! Evaporation, using bulk wind speed
503         zqsb (:,:) = cp_air(sf(jp_humi)%fnow(:,:,1))*zqla(:,:)*Ch_atm(:,:)*(zst(:,:) - ztpot(:,:)             )   ! Sensible Heat, using bulk wind speed
504      ELSE
505         !! q_air and t_air are not given at 10m (wind reference height)
506         ! Values of temp. and hum. adjusted to height of wind during bulk algorithm iteration must be used!!!
507         zevap(:,:) = rn_efac*MAX( 0._wp,             zqla(:,:)*Ce_atm(:,:)*(zsq(:,:) - q_zu(:,:) ) ) ! Evaporation, using bulk wind speed
508         zqsb (:,:) = cp_air(sf(jp_humi)%fnow(:,:,1))*zqla(:,:)*Ch_atm(:,:)*(zst(:,:) - t_zu(:,:) )   ! Sensible Heat, using bulk wind speed
509      ENDIF
510
511      zqla(:,:) = L_vap(zst(:,:)) * zevap(:,:)     ! Latent Heat flux
512
513
514      IF(ln_ctl) THEN
515         CALL prt_ctl( tab2d_1=zqla  , clinfo1=' blk_oce: zqla   : ', tab2d_2=Ce_atm , clinfo2=' Ce_oce  : ' )
516         CALL prt_ctl( tab2d_1=zqsb  , clinfo1=' blk_oce: zqsb   : ', tab2d_2=Ch_atm , clinfo2=' Ch_oce  : ' )
517         CALL prt_ctl( tab2d_1=zqlw  , clinfo1=' blk_oce: zqlw   : ', tab2d_2=qsr, clinfo2=' qsr : ' )
518         CALL prt_ctl( tab2d_1=zsq   , clinfo1=' blk_oce: zsq    : ', tab2d_2=zst, clinfo2=' zst : ' )
519         CALL prt_ctl( tab2d_1=utau  , clinfo1=' blk_oce: utau   : ', mask1=umask,   &
520            &          tab2d_2=vtau  , clinfo2=           ' vtau : ', mask2=vmask )
521         CALL prt_ctl( tab2d_1=wndm  , clinfo1=' blk_oce: wndm   : ')
522         CALL prt_ctl( tab2d_1=zst   , clinfo1=' blk_oce: zst    : ')
523      ENDIF
524
525      ! ----------------------------------------------------------------------------- !
526      !     III    Total FLUXES                                                       !
527      ! ----------------------------------------------------------------------------- !
528      !
529      emp (:,:) = (  zevap(:,:)                                          &   ! mass flux (evap. - precip.)
530         &         - sf(jp_prec)%fnow(:,:,1) * rn_pfac  ) * tmask(:,:,1)
531      !
532      qns(:,:) = zqlw(:,:) - zqsb(:,:) - zqla(:,:)                                &   ! Downward Non Solar
533         &     - sf(jp_snow)%fnow(:,:,1) * rn_pfac * lfus                         &   ! remove latent melting heat for solid precip
534         &     - zevap(:,:) * pst(:,:) * rcp                                      &   ! remove evap heat content at SST
535         &     + ( sf(jp_prec)%fnow(:,:,1) - sf(jp_snow)%fnow(:,:,1) ) * rn_pfac  &   ! add liquid precip heat content at Tair
536         &     * ( sf(jp_tair)%fnow(:,:,1) - rt0 ) * rcp                          &
537         &     + sf(jp_snow)%fnow(:,:,1) * rn_pfac                                &   ! add solid  precip heat content at min(Tair,Tsnow)
538         &     * ( MIN( sf(jp_tair)%fnow(:,:,1), rt0_snow ) - rt0 ) * cpic
539      qns(:,:) = qns(:,:) * tmask(:,:,1)
540      !
541#if defined key_si3
542      qns_oce(:,:) = zqlw(:,:) - zqsb(:,:) - zqla(:,:)                                ! non solar without emp (only needed by SI3)
543      qsr_oce(:,:) = qsr(:,:)
544#endif
545      !
546      IF ( nn_ice == 0 ) THEN
547         CALL iom_put( "qlw_oce" ,   zqlw )                 ! output downward longwave heat over the ocean
548         CALL iom_put( "qsb_oce" , - zqsb )                 ! output downward sensible heat over the ocean
549         CALL iom_put( "qla_oce" , - zqla )                 ! output downward latent   heat over the ocean
550         CALL iom_put( "qemp_oce",   qns-zqlw+zqsb+zqla )   ! output downward heat content of E-P over the ocean
551         CALL iom_put( "qns_oce" ,   qns  )                 ! output downward non solar heat over the ocean
552         CALL iom_put( "qsr_oce" ,   qsr  )                 ! output downward solar heat over the ocean
553         CALL iom_put( "qt_oce"  ,   qns+qsr )              ! output total downward heat over the ocean
554         tprecip(:,:) = sf(jp_prec)%fnow(:,:,1) * rn_pfac * tmask(:,:,1) ! output total precipitation [kg/m2/s]
555         sprecip(:,:) = sf(jp_snow)%fnow(:,:,1) * rn_pfac * tmask(:,:,1) ! output solid precipitation [kg/m2/s]
556         CALL iom_put( 'snowpre', sprecip )                 ! Snow
557         CALL iom_put( 'precip' , tprecip )                 ! Total precipitation
558      ENDIF
559      !
560      IF(ln_ctl) THEN
561         CALL prt_ctl(tab2d_1=zqsb , clinfo1=' blk_oce: zqsb   : ', tab2d_2=zqlw , clinfo2=' zqlw  : ')
562         CALL prt_ctl(tab2d_1=zqla , clinfo1=' blk_oce: zqla   : ', tab2d_2=qsr  , clinfo2=' qsr   : ')
563         CALL prt_ctl(tab2d_1=pst  , clinfo1=' blk_oce: pst    : ', tab2d_2=emp  , clinfo2=' emp   : ')
564         CALL prt_ctl(tab2d_1=utau , clinfo1=' blk_oce: utau   : ', mask1=umask,   &
565            &         tab2d_2=vtau , clinfo2=              ' vtau  : ' , mask2=vmask )
566      ENDIF
567      !
568   END SUBROUTINE blk_oce
569
570
571
572   FUNCTION rho_air( ptak, pqa, pslp )
573      !!-------------------------------------------------------------------------------
574      !!                           ***  FUNCTION rho_air  ***
575      !!
576      !! ** Purpose : compute density of (moist) air using the eq. of state of the atmosphere
577      !!
578      !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk)
579      !!-------------------------------------------------------------------------------
580      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   ptak      ! air temperature             [K]
581      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   pqa       ! air specific humidity   [kg/kg]
582!!clem      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   pslp      ! pressure in                [Pa]
583      REAL(wp),                     INTENT(in) ::   pslp      ! pressure in                [Pa]
584      REAL(wp), DIMENSION(jpi,jpj)             ::   rho_air   ! density of moist air   [kg/m^3]
585      !!-------------------------------------------------------------------------------
586      !
587      rho_air = pslp / (  R_dry*ptak * ( 1._wp + rctv0*pqa )  )
588      !
589   END FUNCTION rho_air
590
591
592   FUNCTION cp_air( pqa )
593      !!-------------------------------------------------------------------------------
594      !!                           ***  FUNCTION cp_air  ***
595      !!
596      !! ** Purpose : Compute specific heat (Cp) of moist air
597      !!
598      !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk)
599      !!-------------------------------------------------------------------------------
600      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   pqa      ! air specific humidity         [kg/kg]
601      REAL(wp), DIMENSION(jpi,jpj)             ::   cp_air   ! specific heat of moist air   [J/K/kg]
602      !!-------------------------------------------------------------------------------
603      !
604      Cp_air = Cp_dry + Cp_vap * pqa
605      !
606   END FUNCTION cp_air
607
608
609   FUNCTION q_sat( ptak, pslp )
610      !!----------------------------------------------------------------------------------
611      !!                           ***  FUNCTION q_sat  ***
612      !!
613      !! ** Purpose : Specific humidity at saturation in [kg/kg]
614      !!              Based on accurate estimate of "e_sat"
615      !!              aka saturation water vapor (Goff, 1957)
616      !!
617      !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk)
618      !!----------------------------------------------------------------------------------
619      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   ptak    ! air temperature                       [K]
620!!clem      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   pslp    ! sea level atmospheric pressure       [Pa]
621      REAL(wp),                     INTENT(in) ::   pslp    ! sea level atmospheric pressure       [Pa]
622      REAL(wp), DIMENSION(jpi,jpj)             ::   q_sat   ! Specific humidity at saturation   [kg/kg]
623      !
624      INTEGER  ::   ji, jj         ! dummy loop indices
625      REAL(wp) ::   ze_sat, ztmp   ! local scalar
626      !!----------------------------------------------------------------------------------
627      !
628      DO jj = 1, jpj
629         DO ji = 1, jpi
630            !
631            ztmp = rt0 / ptak(ji,jj)
632            !
633            ! Vapour pressure at saturation [hPa] : WMO, (Goff, 1957)
634            ze_sat = 10.**( 10.79574*(1. - ztmp) - 5.028*LOG10(ptak(ji,jj)/rt0)        &
635               &    + 1.50475*10.**(-4)*(1. - 10.**(-8.2969*(ptak(ji,jj)/rt0 - 1.)) )  &
636               &    + 0.42873*10.**(-3)*(10.**(4.76955*(1. - ztmp)) - 1.) + 0.78614  )
637               !
638!!clem            q_sat(ji,jj) = reps0 * ze_sat/( 0.01_wp*pslp(ji,jj) - (1._wp - reps0)*ze_sat )   ! 0.01 because SLP is in [Pa]
639            q_sat(ji,jj) = reps0 * ze_sat/( 0.01_wp*pslp - (1._wp - reps0)*ze_sat )   ! 0.01 because SLP is in [Pa]
640            !
641         END DO
642      END DO
643      !
644   END FUNCTION q_sat
645
646
647   FUNCTION gamma_moist( ptak, pqa )
648      !!----------------------------------------------------------------------------------
649      !!                           ***  FUNCTION gamma_moist  ***
650      !!
651      !! ** Purpose : Compute the moist adiabatic lapse-rate.
652      !!     => http://glossary.ametsoc.org/wiki/Moist-adiabatic_lapse_rate
653      !!     => http://www.geog.ucsb.edu/~joel/g266_s10/lecture_notes/chapt03/oh10_3_01/oh10_3_01.html
654      !!
655      !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk)
656      !!----------------------------------------------------------------------------------
657      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   ptak          ! air temperature       [K]
658      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   pqa           ! specific humidity [kg/kg]
659      REAL(wp), DIMENSION(jpi,jpj)             ::   gamma_moist   ! moist adiabatic lapse-rate
660      !
661      INTEGER  ::   ji, jj         ! dummy loop indices
662      REAL(wp) :: zrv, ziRT        ! local scalar
663      !!----------------------------------------------------------------------------------
664      !
665      DO jj = 1, jpj
666         DO ji = 1, jpi
667            zrv = pqa(ji,jj) / (1. - pqa(ji,jj))
668            ziRT = 1. / (R_dry*ptak(ji,jj))    ! 1/RT
669            gamma_moist(ji,jj) = grav * ( 1. + cevap*zrv*ziRT ) / ( Cp_dry + cevap*cevap*zrv*reps0*ziRT/ptak(ji,jj) )
670         END DO
671      END DO
672      !
673   END FUNCTION gamma_moist
674
675
676   FUNCTION L_vap( psst )
677      !!---------------------------------------------------------------------------------
678      !!                           ***  FUNCTION L_vap  ***
679      !!
680      !! ** Purpose : Compute the latent heat of vaporization of water from temperature
681      !!
682      !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk)
683      !!----------------------------------------------------------------------------------
684      REAL(wp), DIMENSION(jpi,jpj)             ::   L_vap   ! latent heat of vaporization   [J/kg]
685      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   psst   ! water temperature                [K]
686      !!----------------------------------------------------------------------------------
687      !
688      L_vap = (  2.501 - 0.00237 * ( psst(:,:) - rt0)  ) * 1.e6
689      !
690   END FUNCTION L_vap
691
692#if defined key_si3
693   !!----------------------------------------------------------------------
694   !!   'key_si3'                                         SI3 sea-ice model
695   !!----------------------------------------------------------------------
696   !!   blk_ice_tau : provide the air-ice stress
697   !!   blk_ice_flx : provide the heat and mass fluxes at air-ice interface
698   !!   blk_ice_qcn : provide ice surface temperature and snow/ice conduction flux (emulating JULES coupler)
699   !!   Cdn10_Lupkes2012 : Lupkes et al. (2012) air-ice drag
700   !!   Cdn10_Lupkes2015 : Lupkes et al. (2015) air-ice drag
701   !!----------------------------------------------------------------------
702
703   SUBROUTINE blk_ice_tau
704      !!---------------------------------------------------------------------
705      !!                     ***  ROUTINE blk_ice_tau  ***
706      !!
707      !! ** Purpose :   provide the surface boundary condition over sea-ice
708      !!
709      !! ** Method  :   compute momentum using bulk formulation
710      !!                formulea, ice variables and read atmospheric fields.
711      !!                NB: ice drag coefficient is assumed to be a constant
712      !!---------------------------------------------------------------------
713      INTEGER  ::   ji, jj    ! dummy loop indices
714      REAL(wp) ::   zwndi_f , zwndj_f, zwnorm_f   ! relative wind module and components at F-point
715      REAL(wp) ::   zwndi_t , zwndj_t             ! relative wind components at T-point
716      REAL(wp), DIMENSION(jpi,jpj) ::   zrhoa     ! transfer coefficient for momentum      (tau)
717      !!---------------------------------------------------------------------
718      !
719      ! set transfer coefficients to default sea-ice values
720      Cd_atm(:,:) = Cd_ice
721      Ch_atm(:,:) = Cd_ice
722      Ce_atm(:,:) = Cd_ice
723
724      wndm_ice(:,:) = 0._wp      !!gm brutal....
725
726      ! ------------------------------------------------------------ !
727      !    Wind module relative to the moving ice ( U10m - U_ice )   !
728      ! ------------------------------------------------------------ !
729      ! C-grid ice dynamics :   U & V-points (same as ocean)
730      DO jj = 2, jpjm1
731         DO ji = fs_2, fs_jpim1   ! vect. opt.
732            zwndi_t = (  sf(jp_wndi)%fnow(ji,jj,1) - rn_vfac * 0.5 * ( u_ice(ji-1,jj  ) + u_ice(ji,jj) )  )
733            zwndj_t = (  sf(jp_wndj)%fnow(ji,jj,1) - rn_vfac * 0.5 * ( v_ice(ji  ,jj-1) + v_ice(ji,jj) )  )
734            wndm_ice(ji,jj) = SQRT( zwndi_t * zwndi_t + zwndj_t * zwndj_t ) * tmask(ji,jj,1)
735         END DO
736      END DO
737      CALL lbc_lnk( wndm_ice, 'T',  1. )
738      !
739      ! Make ice-atm. drag dependent on ice concentration
740      IF    ( ln_Cd_L12 ) THEN   ! calculate new drag from Lupkes(2012) equations
741         CALL Cdn10_Lupkes2012( Cd_atm )
742         Ch_atm(:,:) = Cd_atm(:,:)       ! momentum and heat transfer coef. are considered identical
743      ELSEIF( ln_Cd_L15 ) THEN   ! calculate new drag from Lupkes(2015) equations
744         CALL Cdn10_Lupkes2015( Cd_atm, Ch_atm ) 
745      ENDIF
746
747!!      CALL iom_put( "Cd_ice", Cd_atm)  ! output value of pure ice-atm. transfer coef.
748!!      CALL iom_put( "Ch_ice", Ch_atm)  ! output value of pure ice-atm. transfer coef.
749
750      ! local scalars ( place there for vector optimisation purposes)
751      ! Computing density of air! Way denser that 1.2 over sea-ice !!!
752!!clem      zrhoa (:,:) =  rho_air(sf(jp_tair)%fnow(:,:,1), sf(jp_humi)%fnow(:,:,1), sf(jp_slp)%fnow(:,:,1))
753      zrhoa (:,:) =  rho_air(sf(jp_tair)%fnow(:,:,1), sf(jp_humi)%fnow(:,:,1), 101300.)
754
755      !!gm brutal....
756      utau_ice  (:,:) = 0._wp
757      vtau_ice  (:,:) = 0._wp
758      !!gm end
759
760      ! ------------------------------------------------------------ !
761      !    Wind stress relative to the moving ice ( U10m - U_ice )   !
762      ! ------------------------------------------------------------ !
763      ! C-grid ice dynamics :   U & V-points (same as ocean)
764      DO jj = 2, jpjm1
765         DO ji = fs_2, fs_jpim1   ! vect. opt.
766            utau_ice(ji,jj) = 0.5 * zrhoa(ji,jj) * Cd_atm(ji,jj) * ( wndm_ice(ji+1,jj  ) + wndm_ice(ji,jj) )            &
767               &          * ( 0.5 * (sf(jp_wndi)%fnow(ji+1,jj,1) + sf(jp_wndi)%fnow(ji,jj,1) ) - rn_vfac * u_ice(ji,jj) )
768            vtau_ice(ji,jj) = 0.5 * zrhoa(ji,jj) * Cd_atm(ji,jj) * ( wndm_ice(ji,jj+1  ) + wndm_ice(ji,jj) )            &
769               &          * ( 0.5 * (sf(jp_wndj)%fnow(ji,jj+1,1) + sf(jp_wndj)%fnow(ji,jj,1) ) - rn_vfac * v_ice(ji,jj) )
770         END DO
771      END DO
772      CALL lbc_lnk_multi( utau_ice, 'U', -1., vtau_ice, 'V', -1. )
773      !
774      IF(ln_ctl) THEN
775         CALL prt_ctl(tab2d_1=utau_ice  , clinfo1=' blk_ice: utau_ice : ', tab2d_2=vtau_ice  , clinfo2=' vtau_ice : ')
776         CALL prt_ctl(tab2d_1=wndm_ice  , clinfo1=' blk_ice: wndm_ice : ')
777      ENDIF
778      !
779   END SUBROUTINE blk_ice_tau
780
781
782   SUBROUTINE blk_ice_flx( ptsu, phs, phi, palb )
783      !!---------------------------------------------------------------------
784      !!                     ***  ROUTINE blk_ice_flx  ***
785      !!
786      !! ** Purpose :   provide the heat and mass fluxes at air-ice interface
787      !!
788      !! ** Method  :   compute heat and freshwater exchanged
789      !!                between atmosphere and sea-ice using bulk formulation
790      !!                formulea, ice variables and read atmmospheric fields.
791      !!
792      !! caution : the net upward water flux has with mm/day unit
793      !!---------------------------------------------------------------------
794      REAL(wp), DIMENSION(:,:,:), INTENT(in)  ::   ptsu   ! sea ice surface temperature
795      REAL(wp), DIMENSION(:,:,:), INTENT(in)  ::   phs    ! snow thickness
796      REAL(wp), DIMENSION(:,:,:), INTENT(in)  ::   phi    ! ice thickness
797      REAL(wp), DIMENSION(:,:,:), INTENT(in)  ::   palb   ! ice albedo (all skies)
798      !!
799      INTEGER  ::   ji, jj, jl               ! dummy loop indices
800      REAL(wp) ::   zst3                     ! local variable
801      REAL(wp) ::   zcoef_dqlw, zcoef_dqla   !   -      -
802      REAL(wp) ::   zztmp, z1_lsub           !   -      -
803      REAL(wp) ::   zfr1, zfr2               ! local variables
804      REAL(wp), DIMENSION(jpi,jpj,jpl) ::   z1_st         ! inverse of surface temperature
805      REAL(wp), DIMENSION(jpi,jpj,jpl) ::   z_qlw         ! long wave heat flux over ice
806      REAL(wp), DIMENSION(jpi,jpj,jpl) ::   z_qsb         ! sensible  heat flux over ice
807      REAL(wp), DIMENSION(jpi,jpj,jpl) ::   z_dqlw        ! long wave heat sensitivity over ice
808      REAL(wp), DIMENSION(jpi,jpj,jpl) ::   z_dqsb        ! sensible  heat sensitivity over ice
809      REAL(wp), DIMENSION(jpi,jpj)     ::   zevap, zsnw   ! evaporation and snw distribution after wind blowing (SI3)
810      REAL(wp), DIMENSION(jpi,jpj)     ::   zrhoa
811      !!---------------------------------------------------------------------
812      !
813      zcoef_dqlw = 4.0 * 0.95 * Stef             ! local scalars
814      zcoef_dqla = -Ls * 11637800. * (-5897.8)
815      !
816!!clem      zrhoa(:,:) = rho_air( sf(jp_tair)%fnow(:,:,1), sf(jp_humi)%fnow(:,:,1), sf(jp_slp)%fnow(:,:,1) )
817      zrhoa(:,:) = rho_air( sf(jp_tair)%fnow(:,:,1), sf(jp_humi)%fnow(:,:,1), 101300. )
818      !
819      zztmp = 1. / ( 1. - albo )
820      WHERE( ptsu(:,:,:) /= 0._wp )   ;   z1_st(:,:,:) = 1._wp / ptsu(:,:,:)
821      ELSEWHERE                       ;   z1_st(:,:,:) = 0._wp
822      END WHERE
823      !                                     ! ========================== !
824      DO jl = 1, jpl                        !  Loop over ice categories  !
825         !                                  ! ========================== !
826         DO jj = 1 , jpj
827            DO ji = 1, jpi
828               ! ----------------------------!
829               !      I   Radiative FLUXES   !
830               ! ----------------------------!
831               zst3 = ptsu(ji,jj,jl) * ptsu(ji,jj,jl) * ptsu(ji,jj,jl)
832               ! Short Wave (sw)
833               qsr_ice(ji,jj,jl) = zztmp * ( 1. - palb(ji,jj,jl) ) * qsr(ji,jj)
834               ! Long  Wave (lw)
835               z_qlw(ji,jj,jl) = 0.95 * ( sf(jp_qlw)%fnow(ji,jj,1) - Stef * ptsu(ji,jj,jl) * zst3 ) * tmask(ji,jj,1)
836               ! lw sensitivity
837               z_dqlw(ji,jj,jl) = zcoef_dqlw * zst3
838
839               ! ----------------------------!
840               !     II    Turbulent FLUXES  !
841               ! ----------------------------!
842
843               ! ... turbulent heat fluxes with Ch_atm recalculated in blk_ice_tau
844               ! Sensible Heat
845               z_qsb(ji,jj,jl) = zrhoa(ji,jj) * cpa * Ch_atm(ji,jj) * wndm_ice(ji,jj) * (ptsu(ji,jj,jl) - sf(jp_tair)%fnow(ji,jj,1))
846               ! Latent Heat
847               qla_ice(ji,jj,jl) = rn_efac * MAX( 0.e0, zrhoa(ji,jj) * Ls  * Ch_atm(ji,jj) * wndm_ice(ji,jj) *  &
848                  &                ( 11637800. * EXP( -5897.8 * z1_st(ji,jj,jl) ) / zrhoa(ji,jj) - sf(jp_humi)%fnow(ji,jj,1) ) )
849               ! Latent heat sensitivity for ice (Dqla/Dt)
850               IF( qla_ice(ji,jj,jl) > 0._wp ) THEN
851                  dqla_ice(ji,jj,jl) = rn_efac * zcoef_dqla * Ch_atm(ji,jj) * wndm_ice(ji,jj) *  &
852                     &                 z1_st(ji,jj,jl)*z1_st(ji,jj,jl) * EXP(-5897.8 * z1_st(ji,jj,jl))
853               ELSE
854                  dqla_ice(ji,jj,jl) = 0._wp
855               ENDIF
856
857               ! Sensible heat sensitivity (Dqsb_ice/Dtn_ice)
858               z_dqsb(ji,jj,jl) = zrhoa(ji,jj) * cpa * Ch_atm(ji,jj) * wndm_ice(ji,jj)
859
860               ! ----------------------------!
861               !     III    Total FLUXES     !
862               ! ----------------------------!
863               ! Downward Non Solar flux
864               qns_ice (ji,jj,jl) =     z_qlw (ji,jj,jl) - z_qsb (ji,jj,jl) - qla_ice (ji,jj,jl)
865               ! Total non solar heat flux sensitivity for ice
866               dqns_ice(ji,jj,jl) = - ( z_dqlw(ji,jj,jl) + z_dqsb(ji,jj,jl) + dqla_ice(ji,jj,jl) )
867            END DO
868            !
869         END DO
870         !
871      END DO
872      !
873      tprecip(:,:) = sf(jp_prec)%fnow(:,:,1) * rn_pfac * tmask(:,:,1)  ! total precipitation [kg/m2/s]
874      sprecip(:,:) = sf(jp_snow)%fnow(:,:,1) * rn_pfac * tmask(:,:,1)  ! solid precipitation [kg/m2/s]
875      CALL iom_put( 'snowpre', sprecip )                    ! Snow precipitation
876      CALL iom_put( 'precip' , tprecip )                    ! Total precipitation
877
878      ! --- evaporation --- !
879      z1_lsub = 1._wp / Lsub
880      evap_ice (:,:,:) = rn_efac * qla_ice (:,:,:) * z1_lsub    ! sublimation
881      devap_ice(:,:,:) = rn_efac * dqla_ice(:,:,:) * z1_lsub    ! d(sublimation)/dT
882      zevap    (:,:)   = rn_efac * ( emp(:,:) + tprecip(:,:) )  ! evaporation over ocean
883
884      ! --- evaporation minus precipitation --- !
885      zsnw(:,:) = 0._wp
886      CALL ice_thd_snwblow( (1.-at_i_b(:,:)), zsnw )  ! snow distribution over ice after wind blowing
887      emp_oce(:,:) = ( 1._wp - at_i_b(:,:) ) * zevap(:,:) - ( tprecip(:,:) - sprecip(:,:) ) - sprecip(:,:) * (1._wp - zsnw )
888      emp_ice(:,:) = SUM( a_i_b(:,:,:) * evap_ice(:,:,:), dim=3 ) - sprecip(:,:) * zsnw
889      emp_tot(:,:) = emp_oce(:,:) + emp_ice(:,:)
890
891      ! --- heat flux associated with emp --- !
892      qemp_oce(:,:) = - ( 1._wp - at_i_b(:,:) ) * zevap(:,:) * sst_m(:,:) * rcp                  & ! evap at sst
893         &          + ( tprecip(:,:) - sprecip(:,:) ) * ( sf(jp_tair)%fnow(:,:,1) - rt0 ) * rcp  & ! liquid precip at Tair
894         &          +   sprecip(:,:) * ( 1._wp - zsnw ) *                                        & ! solid precip at min(Tair,Tsnow)
895         &              ( ( MIN( sf(jp_tair)%fnow(:,:,1), rt0_snow ) - rt0 ) * cpic * tmask(:,:,1) - lfus )
896      qemp_ice(:,:) =   sprecip(:,:) * zsnw *                                                    & ! solid precip (only)
897         &              ( ( MIN( sf(jp_tair)%fnow(:,:,1), rt0_snow ) - rt0 ) * cpic * tmask(:,:,1) - lfus )
898
899      ! --- total solar and non solar fluxes --- !
900      qns_tot(:,:) = ( 1._wp - at_i_b(:,:) ) * qns_oce(:,:) + SUM( a_i_b(:,:,:) * qns_ice(:,:,:), dim=3 )  &
901         &           + qemp_ice(:,:) + qemp_oce(:,:)
902      qsr_tot(:,:) = ( 1._wp - at_i_b(:,:) ) * qsr_oce(:,:) + SUM( a_i_b(:,:,:) * qsr_ice(:,:,:), dim=3 )
903
904      ! --- heat content of precip over ice in J/m3 (to be used in 1D-thermo) --- !
905      qprec_ice(:,:) = rhosn * ( ( MIN( sf(jp_tair)%fnow(:,:,1), rt0_snow ) - rt0 ) * cpic * tmask(:,:,1) - lfus )
906
907      ! --- heat content of evap over ice in W/m2 (to be used in 1D-thermo) ---
908      DO jl = 1, jpl
909         qevap_ice(:,:,jl) = 0._wp ! should be -evap_ice(:,:,jl)*( ( Tice - rt0 ) * cpic * tmask(:,:,1) )
910         !                         ! But we do not have Tice => consider it at 0degC => evap=0
911      END DO
912
913      ! --- shortwave radiation transmitted below the surface (W/m2, see Grenfell Maykut 77) --- !
914      zfr1 = ( 0.18 * ( 1.0 - cldf_ice ) + 0.35 * cldf_ice )            ! transmission when hi>10cm
915      zfr2 = ( 0.82 * ( 1.0 - cldf_ice ) + 0.65 * cldf_ice )            ! zfr2 such that zfr1 + zfr2 to equal 1
916      !
917      WHERE    ( phs(:,:,:) <= 0._wp .AND. phi(:,:,:) <  0.1_wp )       ! linear decrease from hi=0 to 10cm 
918         qsr_ice_tr(:,:,:) = qsr_ice(:,:,:) * ( zfr1 + zfr2 * ( 1._wp - phi(:,:,:) * 10._wp ) )
919      ELSEWHERE( phs(:,:,:) <= 0._wp .AND. phi(:,:,:) >= 0.1_wp )       ! constant (zfr1) when hi>10cm
920         qsr_ice_tr(:,:,:) = qsr_ice(:,:,:) * zfr1
921      ELSEWHERE                                                         ! zero when hs>0
922         qsr_ice_tr(:,:,:) = 0._wp 
923      END WHERE
924      !
925      IF(ln_ctl) THEN
926         CALL prt_ctl(tab3d_1=qla_ice , clinfo1=' blk_ice: qla_ice  : ', tab3d_2=z_qsb   , clinfo2=' z_qsb    : ', kdim=jpl)
927         CALL prt_ctl(tab3d_1=z_qlw   , clinfo1=' blk_ice: z_qlw    : ', tab3d_2=dqla_ice, clinfo2=' dqla_ice : ', kdim=jpl)
928         CALL prt_ctl(tab3d_1=z_dqsb  , clinfo1=' blk_ice: z_dqsb   : ', tab3d_2=z_dqlw  , clinfo2=' z_dqlw   : ', kdim=jpl)
929         CALL prt_ctl(tab3d_1=dqns_ice, clinfo1=' blk_ice: dqns_ice : ', tab3d_2=qsr_ice , clinfo2=' qsr_ice  : ', kdim=jpl)
930         CALL prt_ctl(tab3d_1=ptsu    , clinfo1=' blk_ice: ptsu     : ', tab3d_2=qns_ice , clinfo2=' qns_ice  : ', kdim=jpl)
931         CALL prt_ctl(tab2d_1=tprecip , clinfo1=' blk_ice: tprecip  : ', tab2d_2=sprecip , clinfo2=' sprecip  : ')
932      ENDIF
933      !
934   END SUBROUTINE blk_ice_flx
935   
936
937   SUBROUTINE blk_ice_qcn( k_virtual_itd, ptsu, ptb, phs, phi )
938      !!---------------------------------------------------------------------
939      !!                     ***  ROUTINE blk_ice_qcn  ***
940      !!
941      !! ** Purpose :   Compute surface temperature and snow/ice conduction flux
942      !!                to force sea ice / snow thermodynamics
943      !!                in the case JULES coupler is emulated
944      !!               
945      !! ** Method  :   compute surface energy balance assuming neglecting heat storage
946      !!                following the 0-layer Semtner (1976) approach
947      !!
948      !! ** Outputs : - ptsu    : sea-ice / snow surface temperature (K)
949      !!              - qcn_ice : surface inner conduction flux (W/m2)
950      !!
951      !!---------------------------------------------------------------------
952      INTEGER                   , INTENT(in   ) ::   k_virtual_itd   ! single-category option
953      REAL(wp), DIMENSION(:,:,:), INTENT(inout) ::   ptsu            ! sea ice / snow surface temperature
954      REAL(wp), DIMENSION(:,:)  , INTENT(in   ) ::   ptb             ! sea ice base temperature
955      REAL(wp), DIMENSION(:,:,:), INTENT(in   ) ::   phs             ! snow thickness
956      REAL(wp), DIMENSION(:,:,:), INTENT(in   ) ::   phi             ! sea ice thickness
957      !
958      INTEGER , PARAMETER ::   nit = 10                  ! number of iterations
959      REAL(wp), PARAMETER ::   zepsilon = 0.1_wp         ! characteristic thickness for enhanced conduction
960      !
961      INTEGER  ::   ji, jj, jl           ! dummy loop indices
962      INTEGER  ::   iter                 ! local integer
963      REAL(wp) ::   zfac, zfac2, zfac3   ! local scalars
964      REAL(wp) ::   zkeff_h, ztsu, ztsu0 !
965      REAL(wp) ::   zqc, zqnet           !
966      REAL(wp) ::   zhe, zqa0            !
967      REAL(wp), DIMENSION(jpi,jpj,jpl) ::   zgfac   ! enhanced conduction factor
968      !!---------------------------------------------------------------------
969     
970      ! -------------------------------------!
971      !      I   Enhanced conduction factor  !
972      ! -------------------------------------!
973      ! Emulates the enhancement of conduction by unresolved thin ice (k_virtual_itd = 1/2)
974      ! Fichefet and Morales Maqueda, JGR 1997
975      !
976      zgfac(:,:,:) = 1._wp
977     
978      SELECT CASE ( k_virtual_itd )
979      !
980      CASE ( 1 , 2 )
981         !
982         zfac  = 1._wp /  ( rn_cnd_s + rcdic )
983         zfac2 = EXP(1._wp) * 0.5_wp * zepsilon
984         zfac3 = 2._wp / zepsilon
985         !   
986         DO jl = 1, jpl               
987            DO jj = 1 , jpj
988               DO ji = 1, jpi
989                  zhe = ( rn_cnd_s * phi(ji,jj,jl) + rcdic * phs(ji,jj,jl) ) * zfac                             ! Effective thickness
990                  IF( zhe >=  zfac2 )   zgfac(ji,jj,jl) = MIN( 2._wp, 0.5_wp * ( 1._wp + LOG( zhe * zfac3 ) ) ) ! Enhanced conduction factor
991               END DO
992            END DO
993         END DO
994         !     
995      END SELECT
996     
997      ! -------------------------------------------------------------!
998      !      II   Surface temperature and conduction flux            !
999      ! -------------------------------------------------------------!
1000      !
1001      zfac = rcdic * rn_cnd_s
1002      !
1003      DO jl = 1, jpl
1004         DO jj = 1 , jpj
1005            DO ji = 1, jpi
1006               !                   
1007               zkeff_h = zfac * zgfac(ji,jj,jl) / &                                    ! Effective conductivity of the snow-ice system divided by thickness
1008                  &      ( rcdic * phs(ji,jj,jl) + rn_cnd_s * MAX( 0.01, phi(ji,jj,jl) ) )
1009               ztsu    = ptsu(ji,jj,jl)                                                ! Store current iteration temperature
1010               ztsu0   = ptsu(ji,jj,jl)                                                ! Store initial surface temperature
1011               zqa0    = qsr_ice(ji,jj,jl) - qsr_ice_tr(ji,jj,jl) + qns_ice(ji,jj,jl)  ! Net initial atmospheric heat flux
1012               !
1013               DO iter = 1, nit     ! --- Iterative loop
1014                  zqc   = zkeff_h * ( ztsu - ptb(ji,jj) )                              ! Conduction heat flux through snow-ice system (>0 downwards)
1015                  zqnet = zqa0 + dqns_ice(ji,jj,jl) * ( ztsu - ptsu(ji,jj,jl) ) - zqc  ! Surface energy budget
1016                  ztsu  = ztsu - zqnet / ( dqns_ice(ji,jj,jl) - zkeff_h )              ! Temperature update
1017               END DO
1018               !
1019               ptsu   (ji,jj,jl) = MIN( rt0, ztsu )
1020               qcn_ice(ji,jj,jl) = zkeff_h * ( ptsu(ji,jj,jl) - ptb(ji,jj) )
1021               qns_ice(ji,jj,jl) = qns_ice(ji,jj,jl) + dqns_ice(ji,jj,jl) * ( ptsu(ji,jj,jl) - ztsu0 )
1022               qml_ice(ji,jj,jl) = ( qsr_ice(ji,jj,jl) - qsr_ice_tr(ji,jj,jl) + qns_ice(ji,jj,jl) - qcn_ice(ji,jj,jl) )   &
1023                             &   * MAX( 0._wp , SIGN( 1._wp, ptsu(ji,jj,jl) - rt0 ) )
1024
1025            END DO
1026         END DO
1027         !
1028      END DO 
1029      !     
1030   END SUBROUTINE blk_ice_qcn
1031   
1032
1033   SUBROUTINE Cdn10_Lupkes2012( Cd )
1034      !!----------------------------------------------------------------------
1035      !!                      ***  ROUTINE  Cdn10_Lupkes2012  ***
1036      !!
1037      !! ** Purpose :    Recompute the neutral air-ice drag referenced at 10m
1038      !!                 to make it dependent on edges at leads, melt ponds and flows.
1039      !!                 After some approximations, this can be resumed to a dependency
1040      !!                 on ice concentration.
1041      !!               
1042      !! ** Method :     The parameterization is taken from Lupkes et al. (2012) eq.(50)
1043      !!                 with the highest level of approximation: level4, eq.(59)
1044      !!                 The generic drag over a cell partly covered by ice can be re-written as follows:
1045      !!
1046      !!                 Cd = Cdw * (1-A) + Cdi * A + Ce * (1-A)**(nu+1/(10*beta)) * A**mu
1047      !!
1048      !!                    Ce = 2.23e-3       , as suggested by Lupkes (eq. 59)
1049      !!                    nu = mu = beta = 1 , as suggested by Lupkes (eq. 59)
1050      !!                    A is the concentration of ice minus melt ponds (if any)
1051      !!
1052      !!                 This new drag has a parabolic shape (as a function of A) starting at
1053      !!                 Cdw(say 1.5e-3) for A=0, reaching 1.97e-3 for A~0.5
1054      !!                 and going down to Cdi(say 1.4e-3) for A=1
1055      !!
1056      !!                 It is theoretically applicable to all ice conditions (not only MIZ)
1057      !!                 => see Lupkes et al (2013)
1058      !!
1059      !! ** References : Lupkes et al. JGR 2012 (theory)
1060      !!                 Lupkes et al. GRL 2013 (application to GCM)
1061      !!
1062      !!----------------------------------------------------------------------
1063      REAL(wp), DIMENSION(:,:), INTENT(inout) ::   Cd
1064      REAL(wp), PARAMETER ::   zCe   = 2.23e-03_wp
1065      REAL(wp), PARAMETER ::   znu   = 1._wp
1066      REAL(wp), PARAMETER ::   zmu   = 1._wp
1067      REAL(wp), PARAMETER ::   zbeta = 1._wp
1068      REAL(wp)            ::   zcoef
1069      !!----------------------------------------------------------------------
1070      zcoef = znu + 1._wp / ( 10._wp * zbeta )
1071
1072      ! generic drag over a cell partly covered by ice
1073      !!Cd(:,:) = Cd_oce(:,:) * ( 1._wp - at_i_b(:,:) ) +  &                        ! pure ocean drag
1074      !!   &      Cd_ice      *           at_i_b(:,:)   +  &                        ! pure ice drag
1075      !!   &      zCe         * ( 1._wp - at_i_b(:,:) )**zcoef * at_i_b(:,:)**zmu   ! change due to sea-ice morphology
1076
1077      ! ice-atm drag
1078      Cd(:,:) = Cd_ice +  &                                                         ! pure ice drag
1079         &      zCe    * ( 1._wp - at_i_b(:,:) )**zcoef * at_i_b(:,:)**(zmu-1._wp)  ! change due to sea-ice morphology
1080     
1081   END SUBROUTINE Cdn10_Lupkes2012
1082
1083
1084   SUBROUTINE Cdn10_Lupkes2015( Cd, Ch )
1085      !!----------------------------------------------------------------------
1086      !!                      ***  ROUTINE  Cdn10_Lupkes2015  ***
1087      !!
1088      !! ** pUrpose :    Alternative turbulent transfert coefficients formulation
1089      !!                 between sea-ice and atmosphere with distinct momentum
1090      !!                 and heat coefficients depending on sea-ice concentration
1091      !!                 and atmospheric stability (no meltponds effect for now).
1092      !!               
1093      !! ** Method :     The parameterization is adapted from Lupkes et al. (2015)
1094      !!                 and ECHAM6 atmospheric model. Compared to Lupkes2012 scheme,
1095      !!                 it considers specific skin and form drags (Andreas et al. 2010)
1096      !!                 to compute neutral transfert coefficients for both heat and
1097      !!                 momemtum fluxes. Atmospheric stability effect on transfert
1098      !!                 coefficient is also taken into account following Louis (1979).
1099      !!
1100      !! ** References : Lupkes et al. JGR 2015 (theory)
1101      !!                 Lupkes et al. ECHAM6 documentation 2015 (implementation)
1102      !!
1103      !!----------------------------------------------------------------------
1104      !
1105      REAL(wp), DIMENSION(:,:), INTENT(inout) ::   Cd
1106      REAL(wp), DIMENSION(:,:), INTENT(inout) ::   Ch
1107      REAL(wp), DIMENSION(jpi,jpj)            ::   zst, zqo_sat, zqi_sat
1108      !
1109      ! ECHAM6 constants
1110      REAL(wp), PARAMETER ::   z0_skin_ice  = 0.69e-3_wp  ! Eq. 43 [m]
1111      REAL(wp), PARAMETER ::   z0_form_ice  = 0.57e-3_wp  ! Eq. 42 [m]
1112      REAL(wp), PARAMETER ::   z0_ice       = 1.00e-3_wp  ! Eq. 15 [m]
1113      REAL(wp), PARAMETER ::   zce10        = 2.80e-3_wp  ! Eq. 41
1114      REAL(wp), PARAMETER ::   zbeta        = 1.1_wp      ! Eq. 41
1115      REAL(wp), PARAMETER ::   zc           = 5._wp       ! Eq. 13
1116      REAL(wp), PARAMETER ::   zc2          = zc * zc
1117      REAL(wp), PARAMETER ::   zam          = 2. * zc     ! Eq. 14
1118      REAL(wp), PARAMETER ::   zah          = 3. * zc     ! Eq. 30
1119      REAL(wp), PARAMETER ::   z1_alpha     = 1._wp / 0.2_wp  ! Eq. 51
1120      REAL(wp), PARAMETER ::   z1_alphaf    = z1_alpha    ! Eq. 56
1121      REAL(wp), PARAMETER ::   zbetah       = 1.e-3_wp    ! Eq. 26
1122      REAL(wp), PARAMETER ::   zgamma       = 1.25_wp     ! Eq. 26
1123      REAL(wp), PARAMETER ::   z1_gamma     = 1._wp / zgamma
1124      REAL(wp), PARAMETER ::   r1_3         = 1._wp / 3._wp
1125      !
1126      INTEGER  ::   ji, jj         ! dummy loop indices
1127      REAL(wp) ::   zthetav_os, zthetav_is, zthetav_zu
1128      REAL(wp) ::   zrib_o, zrib_i
1129      REAL(wp) ::   zCdn_skin_ice, zCdn_form_ice, zCdn_ice
1130      REAL(wp) ::   zChn_skin_ice, zChn_form_ice
1131      REAL(wp) ::   z0w, z0i, zfmi, zfmw, zfhi, zfhw
1132      REAL(wp) ::   zCdn_form_tmp
1133      !!----------------------------------------------------------------------
1134
1135      ! Momentum Neutral Transfert Coefficients (should be a constant)
1136      zCdn_form_tmp = zce10 * ( LOG( 10._wp / z0_form_ice + 1._wp ) / LOG( rn_zu / z0_form_ice + 1._wp ) )**2   ! Eq. 40
1137      zCdn_skin_ice = ( vkarmn                                      / LOG( rn_zu / z0_skin_ice + 1._wp ) )**2   ! Eq. 7
1138      zCdn_ice      = zCdn_skin_ice   ! Eq. 7 (cf Lupkes email for details)
1139      !zCdn_ice     = 1.89e-3         ! old ECHAM5 value (cf Eq. 32)
1140
1141      ! Heat Neutral Transfert Coefficients
1142      zChn_skin_ice = vkarmn**2 / ( LOG( rn_zu / z0_ice + 1._wp ) * LOG( rn_zu * z1_alpha / z0_skin_ice + 1._wp ) )   ! Eq. 50 + Eq. 52 (cf Lupkes email for details)
1143     
1144      ! Atmospheric and Surface Variables
1145      zst(:,:)     = sst_m(:,:) + rt0                                       ! convert SST from Celcius to Kelvin
1146!!clem      zqo_sat(:,:) = 0.98_wp * q_sat( zst(:,:)  , sf(jp_slp)%fnow(:,:,1) )  ! saturation humidity over ocean [kg/kg]
1147!!clem      zqi_sat(:,:) = 0.98_wp * q_sat( tm_su(:,:), sf(jp_slp)%fnow(:,:,1) )  ! saturation humidity over ice   [kg/kg]
1148      zqo_sat(:,:) = 0.98_wp * q_sat( zst(:,:)  , 101300. )  ! saturation humidity over ocean [kg/kg]
1149      zqi_sat(:,:) = 0.98_wp * q_sat( tm_su(:,:), 101300. )  ! saturation humidity over ice   [kg/kg]
1150      !
1151      DO jj = 2, jpjm1           ! reduced loop is necessary for reproducibility
1152         DO ji = fs_2, fs_jpim1
1153            ! Virtual potential temperature [K]
1154            zthetav_os = zst(ji,jj)   * ( 1._wp + rctv0 * zqo_sat(ji,jj) )   ! over ocean
1155            zthetav_is = tm_su(ji,jj) * ( 1._wp + rctv0 * zqi_sat(ji,jj) )   ! ocean ice
1156            zthetav_zu = t_zu (ji,jj) * ( 1._wp + rctv0 * q_zu(ji,jj)    )   ! at zu
1157           
1158            ! Bulk Richardson Number (could use Ri_bulk function from aerobulk instead)
1159            zrib_o = grav / zthetav_os * ( zthetav_zu - zthetav_os ) * rn_zu / MAX( 0.5, wndm(ji,jj)     )**2   ! over ocean
1160            zrib_i = grav / zthetav_is * ( zthetav_zu - zthetav_is ) * rn_zu / MAX( 0.5, wndm_ice(ji,jj) )**2   ! over ice
1161           
1162            ! Momentum and Heat Neutral Transfert Coefficients
1163            zCdn_form_ice = zCdn_form_tmp * at_i_b(ji,jj) * ( 1._wp - at_i_b(ji,jj) )**zbeta  ! Eq. 40
1164            zChn_form_ice = zCdn_form_ice / ( 1._wp + ( LOG( z1_alphaf ) / vkarmn ) * SQRT( zCdn_form_ice ) )               ! Eq. 53
1165                       
1166            ! Momentum and Heat Stability functions (possibility to use psi_m_ecmwf instead)
1167            z0w = rn_zu * EXP( -1._wp * vkarmn / SQRT( Cdn_oce(ji,jj) ) ) ! over water
1168            z0i = z0_skin_ice                                             ! over ice (cf Lupkes email for details)
1169            IF( zrib_o <= 0._wp ) THEN
1170               zfmw = 1._wp - zam * zrib_o / ( 1._wp + 3._wp * zc2 * Cdn_oce(ji,jj) * SQRT( -zrib_o * ( rn_zu / z0w + 1._wp ) ) )  ! Eq. 10
1171               zfhw = ( 1._wp + ( zbetah * ( zthetav_os - zthetav_zu )**r1_3 / ( Chn_oce(ji,jj) * MAX(0.01, wndm(ji,jj)) )   &     ! Eq. 26
1172                  &             )**zgamma )**z1_gamma
1173            ELSE
1174               zfmw = 1._wp / ( 1._wp + zam * zrib_o / SQRT( 1._wp + zrib_o ) )   ! Eq. 12
1175               zfhw = 1._wp / ( 1._wp + zah * zrib_o / SQRT( 1._wp + zrib_o ) )   ! Eq. 28
1176            ENDIF
1177           
1178            IF( zrib_i <= 0._wp ) THEN
1179               zfmi = 1._wp - zam * zrib_i / (1._wp + 3._wp * zc2 * zCdn_ice * SQRT( -zrib_i * ( rn_zu / z0i + 1._wp)))   ! Eq.  9
1180               zfhi = 1._wp - zah * zrib_i / (1._wp + 3._wp * zc2 * zCdn_ice * SQRT( -zrib_i * ( rn_zu / z0i + 1._wp)))   ! Eq. 25
1181            ELSE
1182               zfmi = 1._wp / ( 1._wp + zam * zrib_i / SQRT( 1._wp + zrib_i ) )   ! Eq. 11
1183               zfhi = 1._wp / ( 1._wp + zah * zrib_i / SQRT( 1._wp + zrib_i ) )   ! Eq. 27
1184            ENDIF
1185           
1186            ! Momentum Transfert Coefficients (Eq. 38)
1187            Cd(ji,jj) = zCdn_skin_ice *   zfmi +  &
1188               &        zCdn_form_ice * ( zfmi * at_i_b(ji,jj) + zfmw * ( 1._wp - at_i_b(ji,jj) ) ) / MAX( 1.e-06, at_i_b(ji,jj) )
1189           
1190            ! Heat Transfert Coefficients (Eq. 49)
1191            Ch(ji,jj) = zChn_skin_ice *   zfhi +  &
1192               &        zChn_form_ice * ( zfhi * at_i_b(ji,jj) + zfhw * ( 1._wp - at_i_b(ji,jj) ) ) / MAX( 1.e-06, at_i_b(ji,jj) )
1193            !
1194         END DO
1195      END DO
1196      CALL lbc_lnk_multi( Cd, 'T',  1., Ch, 'T', 1. )
1197      !
1198   END SUBROUTINE Cdn10_Lupkes2015
1199
1200#endif
1201
1202   !!======================================================================
1203END MODULE sbcblk
Note: See TracBrowser for help on using the repository browser.