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.
sbcisf.F90 in NEMO/branches/UKMO/NEMO_4.0.1_icesheet_and_river_coupling/src/OCE/SBC – NEMO

source: NEMO/branches/UKMO/NEMO_4.0.1_icesheet_and_river_coupling/src/OCE/SBC/sbcisf.F90 @ 12675

Last change on this file since 12675 was 12675, checked in by dancopsey, 4 years ago

Fix compile errors.

File size: 50.5 KB
Line 
1MODULE sbcisf
2   !!======================================================================
3   !!                       ***  MODULE  sbcisf  ***
4   !! Surface module :  update surface ocean boundary condition under ice
5   !!                   shelf
6   !!======================================================================
7   !! History :  3.2  !  2011-02  (C.Harris  ) Original code isf cav
8   !!            X.X  !  2006-02  (C. Wang   ) Original code bg03
9   !!            3.4  !  2013-03  (P. Mathiot) Merging + parametrization
10   !!----------------------------------------------------------------------
11
12   !!----------------------------------------------------------------------
13   !!   sbc_isf       : update sbc under ice shelf
14   !!----------------------------------------------------------------------
15   USE oce            ! ocean dynamics and tracers
16   USE dom_oce        ! ocean space and time domain
17   USE phycst         ! physical constants
18   USE eosbn2         ! equation of state
19   USE sbc_oce        ! surface boundary condition: ocean fields
20   USE zdfdrg         ! vertical physics: top/bottom drag coef.
21   !
22   USE in_out_manager ! I/O manager
23   USE iom            ! I/O library
24   USE fldread        ! read input field at current time step
25   USE lbclnk         !
26   USE lib_fortran    ! glob_sum
27
28   IMPLICIT NONE
29   PRIVATE
30
31   PUBLIC   sbc_isf, sbc_isf_init, sbc_isf_div, sbc_isf_alloc  ! routine called in sbcmod and divhor
32
33   ! public in order to be able to output then
34
35   REAL(wp), PUBLIC ::   rn_hisf_tbl                 !: thickness of top boundary layer [m]
36   INTEGER , PUBLIC ::   nn_isf                      !: flag to choose between explicit/param/specified 
37   INTEGER , PUBLIC ::   nn_isfblk                   !: flag to choose the bulk formulation to compute the ice shelf melting
38   INTEGER , PUBLIC ::   nn_gammablk                 !: flag to choose how the exchange coefficient is computed
39   REAL(wp), PUBLIC ::   rn_gammat0                  !: temperature exchange coeficient []
40   REAL(wp), PUBLIC ::   rn_gammas0                  !: salinity    exchange coeficient []
41
42   INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:)   ::   misfkt   , misfkb        !: Level of ice shelf base
43   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:)   ::   rzisf_tbl                !: depth of calving front (shallowest point) nn_isf ==2/3
44   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:)   ::   rhisf_tbl, rhisf_tbl_0   !: thickness of tbl  [m]
45   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:)   ::   r1_hisf_tbl              !: 1/thickness of tbl
46   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:)   ::   ralpha                   !: proportion of bottom cell influenced by tbl
47   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:)   ::   risfLeff                 !: effective length (Leff) BG03 nn_isf==2
48   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:)   ::   ttbl, stbl, utbl, vtbl   !: top boundary layer variable at T point
49   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:)   ::   qisf                     !: net heat flux from ice shelf      [W/m2]
50   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:,:) ::   risf_tsc_b, risf_tsc     !: before and now T & S isf contents [K.m/s & PSU.m/s] 
51
52   LOGICAL, PUBLIC ::   l_isfcpl = .false.       !: isf recieved from oasis
53
54   REAL(wp), PUBLIC, SAVE ::   rcpisf   = 2000.0_wp     !: specific heat of ice shelf             [J/kg/K]
55   REAL(wp), PUBLIC, SAVE ::   rkappa   = 1.54e-6_wp    !: heat diffusivity through the ice-shelf [m2/s]
56   REAL(wp), PUBLIC, SAVE ::   rhoisf   = 920.0_wp      !: volumic mass of ice shelf              [kg/m3]
57   REAL(wp), PUBLIC, SAVE ::   tsurf    = -20.0_wp      !: air temperature on top of ice shelf    [C]
58   REAL(wp), PUBLIC, SAVE ::   rLfusisf = 0.334e6_wp    !: latent heat of fusion of ice shelf     [J/kg]
59
60!: Variable used in fldread to read the forcing file (nn_isf == 4 .OR. nn_isf == 3)
61   CHARACTER(len=100), PUBLIC           :: cn_dirisf  = './' !: Root directory for location of ssr files
62   TYPE(FLD_N)       , PUBLIC           :: sn_fwfisf         !: information about the isf melting file to be read
63   TYPE(FLD), ALLOCATABLE, DIMENSION(:) :: sf_fwfisf
64   TYPE(FLD_N)       , PUBLIC           :: sn_rnfisf         !: information about the isf melting param.   file to be read
65   TYPE(FLD), ALLOCATABLE, DIMENSION(:) :: sf_rnfisf           
66   TYPE(FLD_N)       , PUBLIC           :: sn_depmax_isf     !: information about the grounding line depth file to be read
67   TYPE(FLD_N)       , PUBLIC           :: sn_depmin_isf     !: information about the calving   line depth file to be read
68   TYPE(FLD_N)       , PUBLIC           :: sn_Leff_isf       !: information about the effective length     file to be read
69   
70   !!----------------------------------------------------------------------
71   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
72   !! $Id$
73   !! Software governed by the CeCILL license (see ./LICENSE)
74   !!----------------------------------------------------------------------
75CONTAINS
76 
77  SUBROUTINE sbc_isf( kt )
78      !!---------------------------------------------------------------------
79      !!                  ***  ROUTINE sbc_isf  ***
80      !!
81      !! ** Purpose : Compute Salt and Heat fluxes related to ice_shelf
82      !!              melting and freezing
83      !!
84      !! ** Method  :  4 parameterizations are available according to nn_isf
85      !!               nn_isf = 1 : Realistic ice_shelf formulation
86      !!                        2 : Beckmann & Goose parameterization
87      !!                        3 : Specified runoff in deptht (Mathiot & al. )
88      !!                        4 : specified fwf and heat flux forcing beneath the ice shelf
89      !!----------------------------------------------------------------------
90      INTEGER, INTENT(in) ::   kt   ! ocean time step
91      !
92      INTEGER ::   ji, jj, jk   ! loop index
93      INTEGER ::   ikt, ikb     ! local integers
94      REAL(wp)                     ::   zgreenland_fwfisf_sum, zantarctica_fwfisf_sum 
95      REAL(wp), DIMENSION(jpi,jpj) ::   zt_frz, zdep   ! freezing temperature (zt_frz) at depth (zdep)
96      REAL(wp), DIMENSION(:,:)  , ALLOCATABLE ::   zqhcisf2d
97      REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::   zfwfisf3d, zqhcisf3d, zqlatisf3d
98      LOGICAL :: ll_wrtstp
99      !!---------------------------------------------------------------------
100      !
101      ll_wrtstp  = ( MOD( kt, sn_cfctl%ptimincr ) == 0 ) .OR. ( kt == nitend )
102      IF( MOD( kt-1, nn_fsbc) == 0 ) THEN    ! compute salt and heat flux
103         !
104         SELECT CASE ( nn_isf )
105         CASE ( 1 )    ! realistic ice shelf formulation
106            ! compute T/S/U/V for the top boundary layer
107            CALL sbc_isf_tbl(tsn(:,:,:,jp_tem),ttbl(:,:),'T')
108            CALL sbc_isf_tbl(tsn(:,:,:,jp_sal),stbl(:,:),'T')
109            CALL sbc_isf_tbl(un(:,:,:)        ,utbl(:,:),'U')
110            CALL sbc_isf_tbl(vn(:,:,:)        ,vtbl(:,:),'V')
111            ! iom print
112            CALL iom_put('ttbl',ttbl(:,:))
113            CALL iom_put('stbl',stbl(:,:))
114            CALL iom_put('utbl',utbl(:,:) * (1._wp - tmask(:,:,1)) * ssmask(:,:))
115            CALL iom_put('vtbl',vtbl(:,:) * (1._wp - tmask(:,:,1)) * ssmask(:,:))
116            ! compute fwf and heat flux
117            ! compute fwf and heat flux
118            IF( .NOT.l_isfcpl ) THEN    ;   CALL sbc_isf_cav (kt)
119            ELSE                        ;   qisf(:,:)  = fwfisf(:,:) * rLfusisf  ! heat        flux
120            ENDIF
121            !
122         CASE ( 2 )    ! Beckmann and Goosse parametrisation
123            stbl(:,:)   = soce
124            CALL sbc_isf_bg03(kt)
125            !
126         CASE ( 3 )    ! specified runoff in depth (Mathiot et al., XXXX in preparation)
127            ! specified runoff in depth (Mathiot et al., XXXX in preparation)
128            IF( .NOT.l_isfcpl ) THEN
129               CALL fld_read ( kt, nn_fsbc, sf_rnfisf   )
130               fwfisf(:,:) = - sf_rnfisf(1)%fnow(:,:,1)         ! fresh water flux from the isf (fwfisf <0 mean melting)
131            ENDIF
132
133            IF( lk_oasis) THEN
134              ! nn_coupled_iceshelf_fluxes uninitialised unless lk_oasis=true
135              IF( nn_coupled_iceshelf_fluxes .gt. 0 ) THEN
136
137                ! Adjust total iceshelf melt rates so that sum of iceberg calving and iceshelf melting in the northern
138                ! and southern hemispheres equals rate of increase of mass of greenland and antarctic ice sheets
139                ! to preserve total freshwater conservation in coupled models without an active ice sheet model.
140
141                ! All related global sums must be done bit reproducibly
142                 zgreenland_fwfisf_sum = glob_sum( 'sbcisf', fwfisf(:,:) * e1t(:,:) * e2t(:,:) * greenland_icesheet_mask(:,:) )
143
144                 ! use ABS function because we need to preserve the sign of fwfisf
145                 WHERE( greenland_icesheet_mask(:,:) == 1.0 )                                                                  &
146                &    fwfisf(:,:) = fwfisf(:,:)  * ABS( greenland_icesheet_mass_rate_of_change * (1.0-rn_greenland_calving_fraction) &
147                &                           / ( zgreenland_fwfisf_sum + 1.0e-10_wp ) )
148
149                 ! check
150                 IF(lwp .AND. ll_wrtstp) WRITE(numout, *) 'Greenland iceshelf melting climatology (kg/s) : ',zgreenland_fwfisf_sum
151
152                 zgreenland_fwfisf_sum = glob_sum( 'sbcisf', fwfisf(:,:) * e1t(:,:) * e2t(:,:) * greenland_icesheet_mask(:,:) )
153
154                 IF(lwp .AND. ll_wrtstp) WRITE(numout, *) 'Greenland iceshelf melting adjusted value (kg/s) : ',zgreenland_fwfisf_sum
155
156                 zantarctica_fwfisf_sum = glob_sum( 'sbcisf', fwfisf(:,:) * e1t(:,:) * e2t(:,:) * antarctica_icesheet_mask(:,:) )
157
158                 ! use ABS function because we need to preserve the sign of fwfisf
159                 WHERE( antarctica_icesheet_mask(:,:) == 1.0 ) &
160                &    fwfisf(:,:) = fwfisf(:,:)  * ABS( antarctica_icesheet_mass_rate_of_change * (1.0-rn_antarctica_calving_fraction) &
161                &                           / ( zantarctica_fwfisf_sum + 1.0e-10_wp ) )
162
163                 ! check
164                 IF(lwp .AND. ll_wrtstp) WRITE(numout, *) 'Antarctica iceshelf melting climatology (kg/s) : ',zantarctica_fwfisf_sum
165
166                 zantarctica_fwfisf_sum = glob_sum( 'sbcisf', fwfisf(:,:) * e1t(:,:) * e2t(:,:) * antarctica_icesheet_mask(:,:) )
167
168                 IF(lwp .AND. ll_wrtstp) WRITE(numout, *) 'Antarctica iceshelf melting adjusted value (kg/s) : ',zantarctica_fwfisf_sum
169
170              ENDIF
171            ENDIF
172
173            qisf(:,:)   = fwfisf(:,:) * rLfusisf             ! heat flux
174            stbl(:,:)   = soce
175            !
176         CASE ( 4 )    ! specified fwf and heat flux forcing beneath the ice shelf
177            !          ! specified fwf and heat flux forcing beneath the ice shelf
178            IF( .NOT.l_isfcpl ) THEN
179               CALL fld_read ( kt, nn_fsbc, sf_fwfisf   )
180               !CALL fld_read ( kt, nn_fsbc, sf_qisf   )
181               fwfisf(:,:) = -sf_fwfisf(1)%fnow(:,:,1)            ! fwf
182            ENDIF
183
184            IF( lk_oasis) THEN
185              ! nn_coupled_iceshelf_fluxes uninitialised unless lk_oasis=true
186              IF( nn_coupled_iceshelf_fluxes .gt. 0 ) THEN
187
188                ! Adjust total iceshelf melt rates so that sum of iceberg calving and iceshelf melting in the northern
189                ! and southern hemispheres equals rate of increase of mass of greenland and antarctic ice sheets
190                ! to preserve total freshwater conservation in coupled models without an active ice sheet model.
191
192                ! All related global sums must be done bit reproducibly
193                 zgreenland_fwfisf_sum = glob_sum( 'sbcisf', fwfisf(:,:) * e1t(:,:) * e2t(:,:) * greenland_icesheet_mask(:,:) )
194
195                 ! use ABS function because we need to preserve the sign of fwfisf
196                 WHERE( greenland_icesheet_mask(:,:) == 1.0 )                                                                  &
197                &    fwfisf(:,:) = fwfisf(:,:)  * ABS( greenland_icesheet_mass_rate_of_change * (1.0-rn_greenland_calving_fraction) &
198                &                           / ( zgreenland_fwfisf_sum + 1.0e-10_wp ) )
199
200                 ! check
201                 IF(lwp .AND. ll_wrtstp) WRITE(numout, *) 'Greenland iceshelf melting climatology (kg/s) : ',zgreenland_fwfisf_sum
202
203                 zgreenland_fwfisf_sum = glob_sum( 'sbcisf', fwfisf(:,:) * e1t(:,:) * e2t(:,:) * greenland_icesheet_mask(:,:) )
204
205                 IF(lwp .AND. ll_wrtstp) WRITE(numout, *) 'Greenland iceshelf melting adjusted value (kg/s) : ',zgreenland_fwfisf_sum
206
207                 zantarctica_fwfisf_sum = glob_sum( 'sbcisf', fwfisf(:,:) * e1t(:,:) * e2t(:,:) * antarctica_icesheet_mask(:,:) )
208
209                 ! use ABS function because we need to preserve the sign of fwfisf
210                 WHERE( antarctica_icesheet_mask(:,:) == 1.0 ) &
211                &    fwfisf(:,:) = fwfisf(:,:)  * ABS( antarctica_icesheet_mass_rate_of_change * (1.0-rn_antarctica_calving_fraction) &
212                &                           / ( zantarctica_fwfisf_sum + 1.0e-10_wp ) )
213
214                 ! check
215                 IF(lwp .AND. ll_wrtstp) WRITE(numout, *) 'Antarctica iceshelf melting climatology (kg/s) : ',zantarctica_fwfisf_sum
216
217                 zantarctica_fwfisf_sum = glob_sum( 'sbcisf', fwfisf(:,:) * e1t(:,:) * e2t(:,:) * antarctica_icesheet_mask(:,:) )
218
219                 IF(lwp .AND. ll_wrtstp) WRITE(numout, *) 'Antarctica iceshelf melting adjusted value (kg/s) : ',zantarctica_fwfisf_sum
220
221              ENDIF
222            ENDIF
223
224            qisf(:,:)   = fwfisf(:,:) * rLfusisf               ! heat flux
225            stbl(:,:)   = soce
226            !
227         END SELECT
228
229         ! compute tsc due to isf
230         ! isf melting implemented as a volume flux and we assume that melt water is at 0 PSU.
231         ! WARNING water add at temp = 0C, need to add a correction term (fwfisf * tfreez / rau0).
232         ! compute freezing point beneath ice shelf (or top cell if nn_isf = 3)
233         DO jj = 1,jpj
234            DO ji = 1,jpi
235               zdep(ji,jj)=gdepw_n(ji,jj,misfkt(ji,jj))
236            END DO
237         END DO
238         CALL eos_fzp( stbl(:,:), zt_frz(:,:), zdep(:,:) )
239         
240         risf_tsc(:,:,jp_tem) = qisf(:,:) * r1_rau0_rcp - fwfisf(:,:) * zt_frz(:,:) * r1_rau0 !
241         risf_tsc(:,:,jp_sal) = 0.0_wp
242
243         ! lbclnk
244         CALL lbc_lnk_multi( 'sbcisf', risf_tsc(:,:,jp_tem), 'T', 1., risf_tsc(:,:,jp_sal), 'T', 1., fwfisf,'T', 1., qisf, 'T', 1.)
245         ! output
246         IF( iom_use('iceshelf_cea') )   CALL iom_put( 'iceshelf_cea', -fwfisf(:,:)                      )   ! isf mass flux
247         IF( iom_use('hflx_isf_cea') )   CALL iom_put( 'hflx_isf_cea', risf_tsc(:,:,jp_tem) * rau0 * rcp )   ! isf sensible+latent heat (W/m2)
248         IF( iom_use('qlatisf' ) )       CALL iom_put( 'qlatisf'     , qisf(:,:)                         )   ! isf latent heat
249         IF( iom_use('fwfisf'  ) )       CALL iom_put( 'fwfisf'      , fwfisf(:,:)                       )   ! isf mass flux (opposite sign)
250
251         ! Diagnostics
252         IF( iom_use('fwfisf3d') .OR. iom_use('qlatisf3d') .OR. iom_use('qhcisf3d') .OR. iom_use('qhcisf')) THEN
253            ALLOCATE( zfwfisf3d(jpi,jpj,jpk) , zqhcisf3d(jpi,jpj,jpk) , zqlatisf3d(jpi,jpj,jpk) )
254            ALLOCATE( zqhcisf2d(jpi,jpj) )
255            !
256            zfwfisf3d (:,:,:) = 0._wp                         ! 3d ice shelf melting (kg/m2/s)
257            zqhcisf3d (:,:,:) = 0._wp                         ! 3d heat content flux (W/m2)
258            zqlatisf3d(:,:,:) = 0._wp                         ! 3d ice shelf melting latent heat flux (W/m2)
259            zqhcisf2d (:,:)   = fwfisf(:,:) * zt_frz * rcp    ! 2d heat content flux (W/m2)
260            !
261            DO jj = 1,jpj
262               DO ji = 1,jpi
263                  ikt = misfkt(ji,jj)
264                  ikb = misfkb(ji,jj)
265                  DO jk = ikt, ikb - 1
266                     zfwfisf3d (ji,jj,jk) = zfwfisf3d (ji,jj,jk) + fwfisf   (ji,jj) * r1_hisf_tbl(ji,jj) * e3t_n(ji,jj,jk)
267                     zqhcisf3d (ji,jj,jk) = zqhcisf3d (ji,jj,jk) + zqhcisf2d(ji,jj) * r1_hisf_tbl(ji,jj) * e3t_n(ji,jj,jk)
268                     zqlatisf3d(ji,jj,jk) = zqlatisf3d(ji,jj,jk) + qisf     (ji,jj) * r1_hisf_tbl(ji,jj) * e3t_n(ji,jj,jk)
269                  END DO
270                  zfwfisf3d (ji,jj,jk) = zfwfisf3d (ji,jj,jk) + fwfisf   (ji,jj) * r1_hisf_tbl(ji,jj)   & 
271                     &                                                                   * ralpha(ji,jj) * e3t_n(ji,jj,jk)
272                  zqhcisf3d (ji,jj,jk) = zqhcisf3d (ji,jj,jk) + zqhcisf2d(ji,jj) * r1_hisf_tbl(ji,jj)   & 
273                     &                                                                   * ralpha(ji,jj) * e3t_n(ji,jj,jk)
274                  zqlatisf3d(ji,jj,jk) = zqlatisf3d(ji,jj,jk) + qisf     (ji,jj) * r1_hisf_tbl(ji,jj)   & 
275                     &                                                                   * ralpha(ji,jj) * e3t_n(ji,jj,jk)
276               END DO
277            END DO
278            !
279            CALL iom_put('fwfisf3d' , zfwfisf3d (:,:,:))
280            CALL iom_put('qlatisf3d', zqlatisf3d(:,:,:))
281            CALL iom_put('qhcisf3d' , zqhcisf3d (:,:,:))
282            CALL iom_put('qhcisf'   , zqhcisf2d (:,:  ))
283            !
284            DEALLOCATE( zfwfisf3d, zqhcisf3d, zqlatisf3d )
285            DEALLOCATE( zqhcisf2d )
286         ENDIF
287         !
288      ENDIF
289
290      IF( kt == nit000 ) THEN                         !   set the forcing field at nit000 - 1    !
291         IF( ln_rstart .AND.    &                     ! Restart: read in restart file
292            &   iom_varid( numror, 'fwf_isf_b', ldstop = .FALSE. ) > 0 ) THEN
293            IF(lwp) WRITE(numout,*) '          nit000-1 isf tracer content forcing fields read in the restart file'
294            CALL iom_get( numror, jpdom_autoglo, 'fwf_isf_b', fwfisf_b(:,:)         , ldxios = lrxios )   ! before salt content isf_tsc trend
295            CALL iom_get( numror, jpdom_autoglo, 'isf_sc_b' , risf_tsc_b(:,:,jp_sal), ldxios = lrxios )   ! before salt content isf_tsc trend
296            CALL iom_get( numror, jpdom_autoglo, 'isf_hc_b' , risf_tsc_b(:,:,jp_tem), ldxios = lrxios )   ! before salt content isf_tsc trend
297         ELSE
298            fwfisf_b(:,:)    = fwfisf(:,:)
299            risf_tsc_b(:,:,:)= risf_tsc(:,:,:)
300         ENDIF
301      ENDIF
302      !
303      IF( lrst_oce ) THEN
304         IF(lwp) WRITE(numout,*)
305         IF(lwp) WRITE(numout,*) 'sbc : isf surface tracer content forcing fields written in ocean restart file ',   &
306            &                    'at it= ', kt,' date= ', ndastp
307         IF(lwp) WRITE(numout,*) '~~~~'
308         IF( lwxios ) CALL iom_swap(      cwxios_context          )
309         CALL iom_rstput( kt, nitrst, numrow, 'fwf_isf_b', fwfisf(:,:)         , ldxios = lwxios )
310         CALL iom_rstput( kt, nitrst, numrow, 'isf_hc_b' , risf_tsc(:,:,jp_tem), ldxios = lwxios )
311         CALL iom_rstput( kt, nitrst, numrow, 'isf_sc_b' , risf_tsc(:,:,jp_sal), ldxios = lwxios )
312         IF( lwxios ) CALL iom_swap(      cxios_context          )
313      ENDIF
314      !
315   END SUBROUTINE sbc_isf
316
317
318   INTEGER FUNCTION sbc_isf_alloc()
319      !!----------------------------------------------------------------------
320      !!               ***  FUNCTION sbc_isf_rnf_alloc  ***
321      !!----------------------------------------------------------------------
322      sbc_isf_alloc = 0       ! set to zero if no array to be allocated
323      IF( .NOT. ALLOCATED( qisf ) ) THEN
324         ALLOCATE(  risf_tsc(jpi,jpj,jpts), risf_tsc_b(jpi,jpj,jpts), qisf(jpi,jpj)   , &
325               &    rhisf_tbl(jpi,jpj)    , r1_hisf_tbl(jpi,jpj), rzisf_tbl(jpi,jpj)  , &
326               &    ttbl(jpi,jpj)         , stbl(jpi,jpj)       , utbl(jpi,jpj)       , &
327               &    vtbl(jpi, jpj)        , risfLeff(jpi,jpj)   , rhisf_tbl_0(jpi,jpj), &
328               &    ralpha(jpi,jpj)       , misfkt(jpi,jpj)     , misfkb(jpi,jpj)     , &
329               &    STAT= sbc_isf_alloc )
330         !
331         CALL mpp_sum ( 'sbcisf', sbc_isf_alloc )
332         IF( sbc_isf_alloc /= 0 )   CALL ctl_stop( 'STOP', 'sbc_isf_alloc: failed to allocate arrays.' )
333         !
334      ENDIF
335   END FUNCTION
336
337
338  SUBROUTINE sbc_isf_init
339      !!---------------------------------------------------------------------
340      !!                  ***  ROUTINE sbc_isf_init  ***
341      !!
342      !! ** Purpose : Initialisation of variables for iceshelf fluxes formulation
343      !!
344      !! ** Method  :  4 parameterizations are available according to nn_isf
345      !!               nn_isf = 1 : Realistic ice_shelf formulation
346      !!                        2 : Beckmann & Goose parameterization
347      !!                        3 : Specified runoff in deptht (Mathiot & al. )
348      !!                        4 : specified fwf and heat flux forcing beneath the ice shelf
349      !!----------------------------------------------------------------------
350      INTEGER               :: ji, jj, jk           ! loop index
351      INTEGER               :: ik                   ! current level index
352      INTEGER               :: ikt, ikb             ! top and bottom level of the isf boundary layer
353      INTEGER               :: inum, ierror
354      INTEGER               :: ios                  ! Local integer output status for namelist read
355      REAL(wp)              :: zhk
356      CHARACTER(len=256)    :: cvarzisf, cvarhisf   ! name for isf file
357      CHARACTER(LEN=32 )    :: cvarLeff             ! variable name for efficient Length scale
358      !!----------------------------------------------------------------------
359      NAMELIST/namsbc_isf/ nn_isfblk, rn_hisf_tbl, rn_gammat0, rn_gammas0, nn_gammablk, nn_isf, &
360                         & sn_fwfisf, sn_rnfisf, sn_depmax_isf, sn_depmin_isf, sn_Leff_isf
361      !!----------------------------------------------------------------------
362
363      REWIND( numnam_ref )              ! Namelist namsbc_rnf in reference namelist : Runoffs
364      READ  ( numnam_ref, namsbc_isf, IOSTAT = ios, ERR = 901)
365901   IF( ios /= 0 )   CALL ctl_nam ( ios , 'namsbc_isf in reference namelist' )
366
367      REWIND( numnam_cfg )              ! Namelist namsbc_rnf in configuration namelist : Runoffs
368      READ  ( numnam_cfg, namsbc_isf, IOSTAT = ios, ERR = 902 )
369902   IF( ios >  0 )   CALL ctl_nam ( ios , 'namsbc_isf in configuration namelist' )
370      IF(lwm) WRITE ( numond, namsbc_isf )
371
372      IF(lwp) WRITE(numout,*)
373      IF(lwp) WRITE(numout,*) 'sbc_isf_init : heat flux of the ice shelf'
374      IF(lwp) WRITE(numout,*) '~~~~~~~~~~~~'
375      IF(lwp) WRITE(numout,*) '   Namelist namsbc_isf :'
376      IF(lwp) WRITE(numout,*) '      type ice shelf melting/freezing         nn_isf      = ', nn_isf
377      IF(lwp) WRITE(numout,*) '      bulk formulation (nn_isf=1 only)        nn_isfblk   = ', nn_isfblk
378      IF(lwp) WRITE(numout,*) '      thickness of the top boundary layer     rn_hisf_tbl = ', rn_hisf_tbl
379      IF(lwp) WRITE(numout,*) '      gamma formulation                       nn_gammablk = ', nn_gammablk 
380      IF(lwp) WRITE(numout,*) '      gammat coefficient                      rn_gammat0  = ', rn_gammat0 
381      IF(lwp) WRITE(numout,*) '      gammas coefficient                      rn_gammas0  = ', rn_gammas0 
382      IF(lwp) WRITE(numout,*) '      top drag coef. used (from namdrg_top)   rn_Cd0      = ', r_Cdmin_top 
383
384
385                           !  1 = presence of ISF    2 = bg03 parametrisation
386                           !  3 = rnf file for isf   4 = ISF fwf specified
387                           !  option 1 and 4 need ln_isfcav = .true. (domzgr)
388      !
389      ! Allocate public variable
390      IF ( sbc_isf_alloc()  /= 0 )         CALL ctl_stop( 'STOP', 'sbc_isf : unable to allocate arrays' )
391      !
392      ! initialisation
393      qisf    (:,:)    = 0._wp   ;   fwfisf  (:,:) = 0._wp
394      risf_tsc(:,:,:)  = 0._wp   ;   fwfisf_b(:,:) = 0._wp
395      !
396      ! define isf tbl tickness, top and bottom indice
397      SELECT CASE ( nn_isf )
398      CASE ( 1 ) 
399         IF(lwp) WRITE(numout,*)
400         IF(lwp) WRITE(numout,*) '      ==>>>   presence of under iceshelf seas (nn_isf = 1)'
401         rhisf_tbl(:,:) = rn_hisf_tbl
402         misfkt   (:,:) = mikt(:,:)         ! same indice for bg03 et cav => used in isfdiv
403         !
404      CASE ( 2 , 3 )
405         IF( .NOT.l_isfcpl ) THEN
406             ALLOCATE( sf_rnfisf(1), STAT=ierror )
407             ALLOCATE( sf_rnfisf(1)%fnow(jpi,jpj,1), sf_rnfisf(1)%fdta(jpi,jpj,1,2) )
408             CALL fld_fill( sf_rnfisf, (/ sn_rnfisf /), cn_dirisf, 'sbc_isf_init', 'read fresh water flux isf data', 'namsbc_isf' )
409          ENDIF
410          !  read effective lenght (BG03)
411          IF( nn_isf == 2 ) THEN
412            IF(lwp) WRITE(numout,*)
413            IF(lwp) WRITE(numout,*) '      ==>>>   bg03 parametrisation (nn_isf = 2)'
414            CALL iom_open( sn_Leff_isf%clname, inum )
415            cvarLeff = TRIM(sn_Leff_isf%clvar)
416            CALL iom_get( inum, jpdom_data, cvarLeff, risfLeff , 1)
417            CALL iom_close(inum)
418            !
419            risfLeff = risfLeff*1000.0_wp           !: convertion in m
420         ELSE
421            IF(lwp) WRITE(numout,*)
422            IF(lwp) WRITE(numout,*) '      ==>>>   rnf file for isf (nn_isf = 3)'
423         ENDIF
424         ! read depth of the top and bottom of the isf top boundary layer (in this case, isf front depth and grounding line depth)
425         CALL iom_open( sn_depmax_isf%clname, inum )
426         cvarhisf = TRIM(sn_depmax_isf%clvar)
427         CALL iom_get( inum, jpdom_data, cvarhisf, rhisf_tbl, 1) !: depth of deepest point of the ice shelf base
428         CALL iom_close(inum)
429         !
430         CALL iom_open( sn_depmin_isf%clname, inum )
431         cvarzisf = TRIM(sn_depmin_isf%clvar)
432         CALL iom_get( inum, jpdom_data, cvarzisf, rzisf_tbl, 1) !: depth of shallowest point of the ice shelves base
433         CALL iom_close(inum)
434         !
435         rhisf_tbl(:,:) = rhisf_tbl(:,:) - rzisf_tbl(:,:)        !: tickness isf boundary layer
436
437         !! compute first level of the top boundary layer
438         DO ji = 1, jpi
439            DO jj = 1, jpj
440                ik = 2
441!!gm potential bug: use gdepw_0 not _n
442                DO WHILE ( ik <= mbkt(ji,jj) .AND. gdepw_n(ji,jj,ik) < rzisf_tbl(ji,jj) ) ;  ik = ik + 1 ;  END DO
443                misfkt(ji,jj) = ik-1
444            END DO
445         END DO
446         !
447      CASE ( 4 ) 
448         IF(lwp) WRITE(numout,*)
449         IF(lwp) WRITE(numout,*) '      ==>>>   specified fresh water flux in ISF (nn_isf = 4)'
450         ! as in nn_isf == 1
451         rhisf_tbl(:,:) = rn_hisf_tbl
452         misfkt   (:,:) = mikt(:,:)         ! same indice for bg03 et cav => used in isfdiv
453         !
454         ! load variable used in fldread (use for temporal interpolation of isf fwf forcing)
455         IF( .NOT.l_isfcpl ) THEN
456           ALLOCATE( sf_fwfisf(1), STAT=ierror )
457           ALLOCATE( sf_fwfisf(1)%fnow(jpi,jpj,1), sf_fwfisf(1)%fdta(jpi,jpj,1,2) )
458           CALL fld_fill( sf_fwfisf, (/ sn_fwfisf /), cn_dirisf, 'sbc_isf_init', 'read fresh water flux isf data', 'namsbc_isf' )
459         ENDIF
460         !
461      CASE DEFAULT
462         CALL ctl_stop( 'sbc_isf_init: wrong value of nn_isf' )
463      END SELECT
464         
465      rhisf_tbl_0(:,:) = rhisf_tbl(:,:)
466
467      ! compute bottom level of isf tbl and thickness of tbl below the ice shelf
468      DO jj = 1,jpj
469         DO ji = 1,jpi
470            ikt = misfkt(ji,jj)
471            ikb = misfkt(ji,jj)
472            ! thickness of boundary layer at least the top level thickness
473            rhisf_tbl(ji,jj) = MAX(rhisf_tbl_0(ji,jj), e3t_n(ji,jj,ikt))
474
475            ! determine the deepest level influenced by the boundary layer
476            DO jk = ikt+1, mbkt(ji,jj)
477               IF( (SUM(e3t_n(ji,jj,ikt:jk-1)) < rhisf_tbl(ji,jj)) .AND. (tmask(ji,jj,jk) == 1) )   ikb = jk
478            END DO
479            rhisf_tbl(ji,jj) = MIN(rhisf_tbl(ji,jj), SUM(e3t_n(ji,jj,ikt:ikb))) ! limit the tbl to water thickness.
480            misfkb(ji,jj) = ikb                                                   ! last wet level of the tbl
481            r1_hisf_tbl(ji,jj) = 1._wp / rhisf_tbl(ji,jj)
482
483            zhk           = SUM( e3t_n(ji, jj, ikt:ikb - 1)) * r1_hisf_tbl(ji,jj) ! proportion of tbl cover by cell from ikt to ikb - 1
484            ralpha(ji,jj) = rhisf_tbl(ji,jj) * (1._wp - zhk ) / e3t_n(ji,jj,ikb)  ! proportion of bottom cell influenced by boundary layer
485         END DO
486      END DO
487
488      IF( lwxios ) THEN
489          CALL iom_set_rstw_var_active('fwf_isf_b')
490          CALL iom_set_rstw_var_active('isf_hc_b')
491          CALL iom_set_rstw_var_active('isf_sc_b')
492      ENDIF
493
494
495  END SUBROUTINE sbc_isf_init
496
497
498  SUBROUTINE sbc_isf_bg03(kt)
499      !!---------------------------------------------------------------------
500      !!                  ***  ROUTINE sbc_isf_bg03  ***
501      !!
502      !! ** Purpose : add net heat and fresh water flux from ice shelf melting
503      !!          into the adjacent ocean
504      !!
505      !! ** Method  :   See reference
506      !!
507      !! ** Reference : Beckmann and Goosse (2003), "A parameterization of ice shelf-ocean
508      !!         interaction for climate models", Ocean Modelling 5(2003) 157-170.
509      !!         (hereafter BG)
510      !! History :  06-02  (C. Wang) Original code
511      !!----------------------------------------------------------------------
512      INTEGER, INTENT ( in ) :: kt
513      !
514      INTEGER  :: ji, jj, jk ! dummy loop index
515      INTEGER  :: ik         ! current level
516      REAL(wp) :: zt_sum     ! sum of the temperature between 200m and 600m
517      REAL(wp) :: zt_ave     ! averaged temperature between 200m and 600m
518      REAL(wp) :: zt_frz     ! freezing point temperature at depth z
519      REAL(wp) :: zpress     ! pressure to compute the freezing point in depth
520      !!----------------------------------------------------------------------
521      !
522      DO ji = 1, jpi
523         DO jj = 1, jpj
524            ik = misfkt(ji,jj)
525            !! Initialize arrays to 0 (each step)
526            zt_sum = 0.e0_wp
527            IF ( ik > 1 ) THEN
528               ! 1. -----------the average temperature between 200m and 600m ---------------------
529               DO jk = misfkt(ji,jj),misfkb(ji,jj)
530                  ! Calculate freezing temperature
531                  zpress = grav*rau0*gdept_n(ji,jj,ik)*1.e-04
532                  CALL eos_fzp(stbl(ji,jj), zt_frz, zpress) 
533                  zt_sum = zt_sum + (tsn(ji,jj,jk,jp_tem)-zt_frz) * e3t_n(ji,jj,jk) * tmask(ji,jj,jk)  ! sum temp
534               END DO
535               zt_ave = zt_sum/rhisf_tbl(ji,jj) ! calcul mean value
536               ! 2. ------------Net heat flux and fresh water flux due to the ice shelf
537               ! For those corresponding to zonal boundary   
538               qisf(ji,jj) = - rau0 * rcp * rn_gammat0 * risfLeff(ji,jj) * e1t(ji,jj) * zt_ave  &
539                           & * r1_e1e2t(ji,jj) * tmask(ji,jj,jk)
540             
541               fwfisf(ji,jj) = qisf(ji,jj) / rLfusisf          !fresh water flux kg/(m2s)                 
542               fwfisf(ji,jj) = fwfisf(ji,jj) * ( soce / stbl(ji,jj) )
543               !add to salinity trend
544            ELSE
545               qisf(ji,jj) = 0._wp   ;   fwfisf(ji,jj) = 0._wp
546            END IF
547         END DO
548      END DO
549      !
550  END SUBROUTINE sbc_isf_bg03
551
552
553  SUBROUTINE sbc_isf_cav( kt )
554      !!---------------------------------------------------------------------
555      !!                     ***  ROUTINE sbc_isf_cav  ***
556      !!
557      !! ** Purpose :   handle surface boundary condition under ice shelf
558      !!
559      !! ** Method  : -
560      !!
561      !! ** Action  :   utau, vtau : remain unchanged
562      !!                taum, wndm : remain unchanged
563      !!                qns        : update heat flux below ice shelf
564      !!                emp, emps  : update freshwater flux below ice shelf
565      !!---------------------------------------------------------------------
566      INTEGER, INTENT(in) ::   kt   ! ocean time step
567      !
568      INTEGER  ::   ji, jj     ! dummy loop indices
569      INTEGER  ::   nit
570      LOGICAL  ::   lit
571      REAL(wp) ::   zlamb1, zlamb2, zlamb3
572      REAL(wp) ::   zeps1,zeps2,zeps3,zeps4,zeps6,zeps7
573      REAL(wp) ::   zaqe,zbqe,zcqe,zaqer,zdis,zsfrz,zcfac
574      REAL(wp) ::   zeps = 1.e-20_wp       
575      REAL(wp) ::   zerr
576      REAL(wp), DIMENSION(jpi,jpj) ::   zfrz
577      REAL(wp), DIMENSION(jpi,jpj) ::   zgammat, zgammas 
578      REAL(wp), DIMENSION(jpi,jpj) ::   zfwflx, zhtflx, zhtflx_b
579      !!---------------------------------------------------------------------
580      !
581      ! coeficient for linearisation of potential tfreez
582      ! Crude approximation for pressure (but commonly used)
583      IF ( l_useCT ) THEN   ! linearisation from Jourdain et al. (2017)
584         zlamb1 =-0.0564_wp
585         zlamb2 = 0.0773_wp
586         zlamb3 =-7.8633e-8 * grav * rau0
587      ELSE                  ! linearisation from table 4 (Asay-Davis et al., 2015)
588         zlamb1 =-0.0573_wp
589         zlamb2 = 0.0832_wp
590         zlamb3 =-7.53e-8 * grav * rau0
591      ENDIF
592      !
593      ! initialisation
594      zgammat(:,:) = rn_gammat0 ; zgammas (:,:) = rn_gammas0
595      zhtflx (:,:) = 0.0_wp     ; zhtflx_b(:,:) = 0.0_wp   
596      zfwflx (:,:) = 0.0_wp
597
598      ! compute ice shelf melting
599      nit = 1 ; lit = .TRUE.
600      DO WHILE ( lit )    ! maybe just a constant number of iteration as in blk_core is fine
601         SELECT CASE ( nn_isfblk )
602         CASE ( 1 )   !  ISOMIP formulation (2 equations) for volume flux (Hunter et al., 2006)
603            ! Calculate freezing temperature
604            CALL eos_fzp( stbl(:,:), zfrz(:,:), risfdep(:,:) )
605
606            ! compute gammat every where (2d)
607            CALL sbc_isf_gammats(zgammat, zgammas, zhtflx, zfwflx)
608           
609            ! compute upward heat flux zhtflx and upward water flux zwflx
610            DO jj = 1, jpj
611               DO ji = 1, jpi
612                  zhtflx(ji,jj) =   zgammat(ji,jj)*rcp*rau0*(ttbl(ji,jj)-zfrz(ji,jj))
613                  zfwflx(ji,jj) = - zhtflx(ji,jj)/rLfusisf
614               END DO
615            END DO
616
617            ! Compute heat flux and upward fresh water flux
618            qisf  (:,:) = - zhtflx(:,:) * (1._wp - tmask(:,:,1)) * ssmask(:,:)
619            fwfisf(:,:) =   zfwflx(:,:) * (1._wp - tmask(:,:,1)) * ssmask(:,:)
620
621         CASE ( 2 )  ! ISOMIP+ formulation (3 equations) for volume flux (Asay-Davis et al., 2015)
622            ! compute gammat every where (2d)
623            CALL sbc_isf_gammats(zgammat, zgammas, zhtflx, zfwflx)
624
625            ! compute upward heat flux zhtflx and upward water flux zwflx
626            ! Resolution of a 2d equation from equation 21, 22 and 23 to find Sb (Asay-Davis et al., 2015)
627            DO jj = 1, jpj
628               DO ji = 1, jpi
629                  ! compute coeficient to solve the 2nd order equation
630                  zeps1 = rcp*rau0*zgammat(ji,jj)
631                  zeps2 = rLfusisf*rau0*zgammas(ji,jj)
632                  zeps3 = rhoisf*rcpisf*rkappa/MAX(risfdep(ji,jj),zeps)
633                  zeps4 = zlamb2+zlamb3*risfdep(ji,jj)
634                  zeps6 = zeps4-ttbl(ji,jj)
635                  zeps7 = zeps4-tsurf
636                  zaqe  = zlamb1 * (zeps1 + zeps3)
637                  zaqer = 0.5_wp/MIN(zaqe,-zeps)
638                  zbqe  = zeps1*zeps6+zeps3*zeps7-zeps2
639                  zcqe  = zeps2*stbl(ji,jj)
640                  zdis  = zbqe*zbqe-4.0_wp*zaqe*zcqe               
641
642                  ! Presumably zdis can never be negative because gammas is very small compared to gammat
643                  ! compute s freeze
644                  zsfrz=(-zbqe-SQRT(zdis))*zaqer
645                  IF ( zsfrz < 0.0_wp ) zsfrz=(-zbqe+SQRT(zdis))*zaqer
646
647                  ! compute t freeze (eq. 22)
648                  zfrz(ji,jj)=zeps4+zlamb1*zsfrz
649 
650                  ! zfwflx is upward water flux
651                  ! zhtflx is upward heat flux (out of ocean)
652                  ! compute the upward water and heat flux (eq. 28 and eq. 29)
653                  zfwflx(ji,jj) = rau0 * zgammas(ji,jj) * (zsfrz-stbl(ji,jj)) / MAX(zsfrz,zeps)
654                  zhtflx(ji,jj) = zgammat(ji,jj) * rau0 * rcp * (ttbl(ji,jj) - zfrz(ji,jj) ) 
655               END DO
656            END DO
657
658            ! compute heat and water flux
659            qisf  (:,:) = - zhtflx(:,:) * (1._wp - tmask(:,:,1)) * ssmask(:,:)
660            fwfisf(:,:) =   zfwflx(:,:) * (1._wp - tmask(:,:,1)) * ssmask(:,:)
661
662         END SELECT
663
664         ! define if we need to iterate (nn_gammablk 0/1 do not need iteration)
665         IF ( nn_gammablk <  2 ) THEN ; lit = .FALSE.
666         ELSE                           
667            ! check total number of iteration
668            IF (nit >= 100) THEN ; CALL ctl_stop( 'STOP', 'sbc_isf_hol99 : too many iteration ...' )
669            ELSE                 ; nit = nit + 1
670            END IF
671
672            ! compute error between 2 iterations
673            ! if needed save gammat and compute zhtflx_b for next iteration
674            zerr = MAXVAL(ABS(zhtflx-zhtflx_b))
675            IF ( zerr <= 0.01_wp ) THEN ; lit = .FALSE.
676            ELSE                        ; zhtflx_b(:,:) = zhtflx(:,:)
677            END IF
678         END IF
679      END DO
680      !
681      CALL iom_put('isfgammat', zgammat)
682      CALL iom_put('isfgammas', zgammas)
683      !
684   END SUBROUTINE sbc_isf_cav
685
686
687   SUBROUTINE sbc_isf_gammats(pgt, pgs, pqhisf, pqwisf )
688      !!----------------------------------------------------------------------
689      !! ** Purpose    : compute the coefficient echange for heat flux
690      !!
691      !! ** Method     : gamma assume constant or depends of u* and stability
692      !!
693      !! ** References : Holland and Jenkins, 1999, JPO, p1787-1800, eq 14
694      !!                Jenkins et al., 2010, JPO, p2298-2312
695      !!---------------------------------------------------------------------
696      REAL(wp), DIMENSION(:,:), INTENT(  out) ::   pgt   , pgs      !
697      REAL(wp), DIMENSION(:,:), INTENT(in   ) ::   pqhisf, pqwisf   !
698      !
699      INTEGER  :: ji, jj                     ! loop index
700      INTEGER  :: ikt                        ! local integer
701      REAL(wp) :: zdku, zdkv                 ! U, V shear
702      REAL(wp) :: zPr, zSc, zRc              ! Prandtl, Scmidth and Richardson number
703      REAL(wp) :: zmob, zmols                ! Monin Obukov length, coriolis factor at T point
704      REAL(wp) :: zbuofdep, zhnu             ! Bouyancy length scale, sublayer tickness
705      REAL(wp) :: zhmax                      ! limitation of mol
706      REAL(wp) :: zetastar                   ! stability parameter
707      REAL(wp) :: zgmolet, zgmoles, zgturb   ! contribution of modelecular sublayer and turbulence
708      REAL(wp) :: zcoef                      ! temporary coef
709      REAL(wp) :: zdep
710      REAL(wp) :: zeps = 1.0e-20_wp   
711      REAL(wp), PARAMETER :: zxsiN = 0.052_wp   ! dimensionless constant
712      REAL(wp), PARAMETER :: znu   = 1.95e-6_wp ! kinamatic viscosity of sea water (m2.s-1)
713      REAL(wp), DIMENSION(2) :: zts, zab
714      REAL(wp), DIMENSION(jpi,jpj) :: zustar   ! U, V at T point and friction velocity
715      !!---------------------------------------------------------------------
716      !
717      SELECT CASE ( nn_gammablk )
718      CASE ( 0 ) ! gamma is constant (specified in namelist)
719         !! ISOMIP formulation (Hunter et al, 2006)
720         pgt(:,:) = rn_gammat0
721         pgs(:,:) = rn_gammas0
722
723      CASE ( 1 ) ! gamma is assume to be proportional to u*
724         !! Jenkins et al., 2010, JPO, p2298-2312
725         !! Adopted by Asay-Davis et al. (2015)
726         !! compute ustar (eq. 24)
727!!gm  NB  use pCdU here so that it will incorporate local boost of Cd0 and log layer case :
728!!         zustar(:,:) = SQRT( rCdU_top(:,:) * SQRT(utbl(:,:) * utbl(:,:) + vtbl(:,:) * vtbl(:,:) + r_ke0_top) )
729!! or better :  compute ustar in zdfdrg  and use it here as well as in TKE, GLS and Co
730!!
731!!     ===>>>>    GM  to be done this chrismas
732!!         
733!!gm end
734         zustar(:,:) = SQRT( r_Cdmin_top * (utbl(:,:) * utbl(:,:) + vtbl(:,:) * vtbl(:,:) + r_ke0_top) )
735
736         !! Compute gammats
737         pgt(:,:) = zustar(:,:) * rn_gammat0
738         pgs(:,:) = zustar(:,:) * rn_gammas0
739     
740      CASE ( 2 ) ! gamma depends of stability of boundary layer
741         !! Holland and Jenkins, 1999, JPO, p1787-1800, eq 14
742         !! as MOL depends of flux and flux depends of MOL, best will be iteration (TO DO)
743         !! compute ustar
744         zustar(:,:) = SQRT( r_Cdmin_top * (utbl(:,:) * utbl(:,:) + vtbl(:,:) * vtbl(:,:) + r_ke0_top) )
745
746         !! compute Pr and Sc number (can be improved)
747         zPr =   13.8_wp
748         zSc = 2432.0_wp
749
750         !! compute gamma mole
751         zgmolet = 12.5_wp * zPr ** (2.0/3.0) - 6.0_wp
752         zgmoles = 12.5_wp * zSc ** (2.0/3.0) - 6.0_wp
753
754         !! compute gamma
755         DO ji = 2, jpi
756            DO jj = 2, jpj
757               ikt = mikt(ji,jj)
758
759               IF( zustar(ji,jj) == 0._wp ) THEN           ! only for kt = 1 I think
760                  pgt = rn_gammat0
761                  pgs = rn_gammas0
762               ELSE
763                  !! compute Rc number (as done in zdfric.F90)
764!!gm better to do it like in the new zdfric.F90   i.e. avm weighted Ri computation
765!!gm moreover, use Max(rn2,0) to take care of static instabilities....
766                  zcoef = 0.5_wp / e3w_n(ji,jj,ikt+1)
767                  !                                            ! shear of horizontal velocity
768                  zdku = zcoef * (  un(ji-1,jj  ,ikt  ) + un(ji,jj,ikt  )  &
769                     &             -un(ji-1,jj  ,ikt+1) - un(ji,jj,ikt+1)  )
770                  zdkv = zcoef * (  vn(ji  ,jj-1,ikt  ) + vn(ji,jj,ikt  )  &
771                     &             -vn(ji  ,jj-1,ikt+1) - vn(ji,jj,ikt+1)  )
772                  !                                            ! richardson number (minimum value set to zero)
773                  zRc = rn2(ji,jj,ikt+1) / MAX( zdku*zdku + zdkv*zdkv, zeps )
774
775                  !! compute bouyancy
776                  zts(jp_tem) = ttbl(ji,jj)
777                  zts(jp_sal) = stbl(ji,jj)
778                  zdep        = gdepw_n(ji,jj,ikt)
779                  !
780                  CALL eos_rab( zts, zdep, zab )
781                  !
782                  !! compute length scale
783                  zbuofdep = grav * ( zab(jp_tem) * pqhisf(ji,jj) - zab(jp_sal) * pqwisf(ji,jj) )  !!!!!!!!!!!!!!!!!!!!!!!!!!!!
784
785                  !! compute Monin Obukov Length
786                  ! Maximum boundary layer depth
787                  zhmax = gdept_n(ji,jj,mbkt(ji,jj)) - gdepw_n(ji,jj,mikt(ji,jj)) -0.001_wp
788                  ! Compute Monin obukhov length scale at the surface and Ekman depth:
789                  zmob   = zustar(ji,jj) ** 3 / (vkarmn * (zbuofdep + zeps))
790                  zmols  = SIGN(1._wp, zmob) * MIN(ABS(zmob), zhmax) * tmask(ji,jj,ikt)
791
792                  !! compute eta* (stability parameter)
793                  zetastar = 1._wp / ( SQRT(1._wp + MAX(zxsiN * zustar(ji,jj) / ( ABS(ff_f(ji,jj)) * zmols * zRc ), 0._wp)))
794
795                  !! compute the sublayer thickness
796                  zhnu = 5 * znu / zustar(ji,jj)
797
798                  !! compute gamma turb
799                  zgturb = 1._wp / vkarmn * LOG(zustar(ji,jj) * zxsiN * zetastar * zetastar / ( ABS(ff_f(ji,jj)) * zhnu )) &
800                  &      + 1._wp / ( 2 * zxsiN * zetastar ) - 1._wp / vkarmn
801
802                  !! compute gammats
803                  pgt(ji,jj) = zustar(ji,jj) / (zgturb + zgmolet)
804                  pgs(ji,jj) = zustar(ji,jj) / (zgturb + zgmoles)
805               END IF
806            END DO
807         END DO
808         CALL lbc_lnk_multi( 'sbcisf', pgt, 'T', 1., pgs, 'T', 1.)
809      END SELECT
810      !
811   END SUBROUTINE sbc_isf_gammats
812
813
814   SUBROUTINE sbc_isf_tbl( pvarin, pvarout, cd_ptin )
815      !!----------------------------------------------------------------------
816      !!                  ***  SUBROUTINE sbc_isf_tbl  ***
817      !!
818      !! ** Purpose : compute mean T/S/U/V in the boundary layer at T- point
819      !!
820      !!----------------------------------------------------------------------
821      REAL(wp), DIMENSION(:,:,:), INTENT(in   ) :: pvarin
822      REAL(wp), DIMENSION(:,:)  , INTENT(  out) :: pvarout
823      CHARACTER(len=1),           INTENT(in   ) :: cd_ptin ! point of variable in/out
824      !
825      INTEGER ::   ji, jj, jk                ! loop index
826      INTEGER ::   ikt, ikb                    ! top and bottom index of the tbl
827      REAL(wp) ::   ze3, zhk
828      REAL(wp), DIMENSION(jpi,jpj) :: zhisf_tbl ! thickness of the tbl
829      !!----------------------------------------------------------------------
830     
831      ! initialisation
832      pvarout(:,:)=0._wp
833   
834      SELECT CASE ( cd_ptin )
835      CASE ( 'U' ) ! compute U in the top boundary layer at T- point
836         DO jj = 1,jpj
837            DO ji = 1,jpi
838               ikt = miku(ji,jj) ; ikb = miku(ji,jj)
839               ! thickness of boundary layer at least the top level thickness
840               zhisf_tbl(ji,jj) = MAX( rhisf_tbl_0(ji,jj) , e3u_n(ji,jj,ikt) )
841
842               ! determine the deepest level influenced by the boundary layer
843               DO jk = ikt+1, mbku(ji,jj)
844                  IF ( (SUM(e3u_n(ji,jj,ikt:jk-1)) < zhisf_tbl(ji,jj)) .AND. (umask(ji,jj,jk) == 1) ) ikb = jk
845               END DO
846               zhisf_tbl(ji,jj) = MIN(zhisf_tbl(ji,jj), SUM(e3u_n(ji,jj,ikt:ikb)))  ! limit the tbl to water thickness.
847
848               ! level fully include in the ice shelf boundary layer
849               DO jk = ikt, ikb - 1
850                  ze3 = e3u_n(ji,jj,jk)
851                  pvarout(ji,jj) = pvarout(ji,jj) + pvarin(ji,jj,jk) / zhisf_tbl(ji,jj) * ze3
852               END DO
853
854               ! level partially include in ice shelf boundary layer
855               zhk = SUM( e3u_n(ji, jj, ikt:ikb - 1)) / zhisf_tbl(ji,jj)
856               pvarout(ji,jj) = pvarout(ji,jj) + pvarin(ji,jj,ikb) * (1._wp - zhk)
857            END DO
858         END DO
859         DO jj = 2, jpj
860            DO ji = 2, jpi
861!!gm a wet-point only average should be used here !!!
862               pvarout(ji,jj) = 0.5_wp * (pvarout(ji,jj) + pvarout(ji-1,jj))
863            END DO
864         END DO
865         CALL lbc_lnk('sbcisf', pvarout,'T',-1.)
866     
867      CASE ( 'V' ) ! compute V in the top boundary layer at T- point
868         DO jj = 1,jpj
869            DO ji = 1,jpi
870               ikt = mikv(ji,jj) ; ikb = mikv(ji,jj)
871               ! thickness of boundary layer at least the top level thickness
872               zhisf_tbl(ji,jj) = MAX(rhisf_tbl_0(ji,jj), e3v_n(ji,jj,ikt))
873
874               ! determine the deepest level influenced by the boundary layer
875               DO jk = ikt+1, mbkv(ji,jj)
876                  IF ( (SUM(e3v_n(ji,jj,ikt:jk-1)) < zhisf_tbl(ji,jj)) .AND. (vmask(ji,jj,jk) == 1) ) ikb = jk
877               END DO
878               zhisf_tbl(ji,jj) = MIN(zhisf_tbl(ji,jj), SUM(e3v_n(ji,jj,ikt:ikb)))  ! limit the tbl to water thickness.
879
880               ! level fully include in the ice shelf boundary layer
881               DO jk = ikt, ikb - 1
882                  ze3 = e3v_n(ji,jj,jk)
883                  pvarout(ji,jj) = pvarout(ji,jj) + pvarin(ji,jj,jk) / zhisf_tbl(ji,jj) * ze3
884               END DO
885
886               ! level partially include in ice shelf boundary layer
887               zhk = SUM( e3v_n(ji, jj, ikt:ikb - 1)) / zhisf_tbl(ji,jj)
888               pvarout(ji,jj) = pvarout(ji,jj) + pvarin(ji,jj,ikb) * (1._wp - zhk)
889            END DO
890         END DO
891         DO jj = 2, jpj
892            DO ji = 2, jpi
893!!gm a wet-point only average should be used here !!!
894               pvarout(ji,jj) = 0.5_wp * (pvarout(ji,jj) + pvarout(ji,jj-1))
895            END DO
896         END DO
897         CALL lbc_lnk('sbcisf', pvarout,'T',-1.)
898
899      CASE ( 'T' ) ! compute T in the top boundary layer at T- point
900         DO jj = 1,jpj
901            DO ji = 1,jpi
902               ikt = misfkt(ji,jj)
903               ikb = misfkb(ji,jj)
904
905               ! level fully include in the ice shelf boundary layer
906               DO jk = ikt, ikb - 1
907                  ze3 = e3t_n(ji,jj,jk)
908                  pvarout(ji,jj) = pvarout(ji,jj) + pvarin(ji,jj,jk) * r1_hisf_tbl(ji,jj) * ze3
909               END DO
910
911               ! level partially include in ice shelf boundary layer
912               zhk = SUM( e3t_n(ji, jj, ikt:ikb - 1)) * r1_hisf_tbl(ji,jj)
913               pvarout(ji,jj) = pvarout(ji,jj) + pvarin(ji,jj,ikb) * (1._wp - zhk)
914            END DO
915         END DO
916      END SELECT
917      !
918      ! mask mean tbl value
919      pvarout(:,:) = pvarout(:,:) * ssmask(:,:)
920      !
921   END SUBROUTINE sbc_isf_tbl
922     
923
924   SUBROUTINE sbc_isf_div( phdivn )
925      !!----------------------------------------------------------------------
926      !!                  ***  SUBROUTINE sbc_isf_div  ***
927      !!       
928      !! ** Purpose :   update the horizontal divergence with the runoff inflow
929      !!
930      !! ** Method  :   
931      !!                CAUTION : risf_tsc(:,:,jp_sal) is negative (outflow) increase the
932      !!                          divergence and expressed in m/s
933      !!
934      !! ** Action  :   phdivn   decreased by the runoff inflow
935      !!----------------------------------------------------------------------
936      REAL(wp), DIMENSION(:,:,:), INTENT( inout ) ::   phdivn   ! horizontal divergence
937      !
938      INTEGER  ::   ji, jj, jk   ! dummy loop indices
939      INTEGER  ::   ikt, ikb 
940      REAL(wp) ::   zhk
941      REAL(wp) ::   zfact     ! local scalar
942      !!----------------------------------------------------------------------
943      !
944      zfact   = 0.5_wp
945      !
946      IF(.NOT.ln_linssh ) THEN     ! need to re compute level distribution of isf fresh water
947         DO jj = 1,jpj
948            DO ji = 1,jpi
949               ikt = misfkt(ji,jj)
950               ikb = misfkt(ji,jj)
951               ! thickness of boundary layer at least the top level thickness
952               rhisf_tbl(ji,jj) = MAX(rhisf_tbl_0(ji,jj), e3t_n(ji,jj,ikt))
953
954               ! determine the deepest level influenced by the boundary layer
955               DO jk = ikt, mbkt(ji,jj)
956                  IF ( (SUM(e3t_n(ji,jj,ikt:jk-1)) .LT. rhisf_tbl(ji,jj)) .AND. (tmask(ji,jj,jk) == 1) ) ikb = jk
957               END DO
958               rhisf_tbl(ji,jj) = MIN(rhisf_tbl(ji,jj), SUM(e3t_n(ji,jj,ikt:ikb)))  ! limit the tbl to water thickness.
959               misfkb(ji,jj) = ikb                                                  ! last wet level of the tbl
960               r1_hisf_tbl(ji,jj) = 1._wp / rhisf_tbl(ji,jj)
961
962               zhk           = SUM( e3t_n(ji, jj, ikt:ikb - 1)) * r1_hisf_tbl(ji,jj)  ! proportion of tbl cover by cell from ikt to ikb - 1
963               ralpha(ji,jj) = rhisf_tbl(ji,jj) * (1._wp - zhk ) / e3t_n(ji,jj,ikb)  ! proportion of bottom cell influenced by boundary layer
964            END DO
965         END DO
966      END IF 
967      !
968      !==   ice shelf melting distributed over several levels   ==!
969      DO jj = 1,jpj
970         DO ji = 1,jpi
971               ikt = misfkt(ji,jj)
972               ikb = misfkb(ji,jj)
973               ! level fully include in the ice shelf boundary layer
974               DO jk = ikt, ikb - 1
975                  phdivn(ji,jj,jk) = phdivn(ji,jj,jk) + ( fwfisf(ji,jj) + fwfisf_b(ji,jj) ) &
976                    &              * r1_hisf_tbl(ji,jj) * r1_rau0 * zfact
977               END DO
978               ! level partially include in ice shelf boundary layer
979               phdivn(ji,jj,ikb) = phdivn(ji,jj,ikb) + ( fwfisf(ji,jj) &
980                    &            + fwfisf_b(ji,jj) ) * r1_hisf_tbl(ji,jj) * r1_rau0 * zfact * ralpha(ji,jj) 
981         END DO
982      END DO
983      !
984   END SUBROUTINE sbc_isf_div
985
986   !!======================================================================
987END MODULE sbcisf
Note: See TracBrowser for help on using the repository browser.