source: branches/2015/dev_r5151_UKMO_ISF/NEMOGCM/NEMO/OPA_SRC/SBC/sbcisf.F90 @ 5905

Last change on this file since 5905 was 5905, checked in by mathiot, 5 years ago

ISF: based on N. Jourdain comments, compute fwf from potential temp instead of insitu, extra comment + rm useless line

  • Property svn:keywords set to Id
File size: 39.0 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 lbclnk          !
21   USE iom             ! I/O manager library
22   USE in_out_manager  ! I/O manager
23   USE wrk_nemo        ! Memory allocation
24   USE timing          ! Timing
25   USE lib_fortran     ! glob_sum
26   USE zdfbfr
27   USE fldread         ! read input field at current time step
28
29
30
31   IMPLICIT NONE
32   PRIVATE
33
34   PUBLIC   sbc_isf, sbc_isf_div, sbc_isf_alloc  ! routine called in sbcmod and divcur
35
36   ! public in order to be able to output then
37
38   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:,:) ::   risf_tsc_b, risf_tsc   
39   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:)   ::   qisf              !: net heat flux from ice shelf
40   REAL(wp), PUBLIC ::   rn_hisf_tbl                 !: thickness of top boundary layer [m]
41   INTEGER , PUBLIC ::   nn_isf                      !: flag to choose between explicit/param/specified 
42   INTEGER , PUBLIC ::   nn_isfblk                   !:
43   INTEGER , PUBLIC ::   nn_gammablk                 !:
44   REAL(wp), PUBLIC ::   rn_gammat0                  !: temperature exchange coeficient
45   REAL(wp), PUBLIC ::   rn_gammas0                  !: salinity    exchange coeficient
46
47   REAL(wp)   , PUBLIC, ALLOCATABLE, SAVE, DIMENSION (:,:)     ::  rzisf_tbl              !:depth of calving front (shallowest point) nn_isf ==2/3
48   REAL(wp)   , PUBLIC, ALLOCATABLE, SAVE, DIMENSION (:,:)     ::  rhisf_tbl, rhisf_tbl_0 !:thickness of tbl
49   REAL(wp)   , PUBLIC, ALLOCATABLE, SAVE, DIMENSION (:,:)     ::  r1_hisf_tbl            !:1/thickness of tbl
50   REAL(wp)   , PUBLIC, ALLOCATABLE, SAVE, DIMENSION (:,:)     ::  ralpha                 !:proportion of bottom cell influenced by tbl
51   REAL(wp)   , PUBLIC, ALLOCATABLE, SAVE, DIMENSION (:,:)     ::  risfLeff               !:effective length (Leff) BG03 nn_isf==2
52   REAL(wp)   , PUBLIC, ALLOCATABLE, SAVE, DIMENSION (:,:)     ::  ttbl, stbl, utbl, vtbl !:top boundary layer variable at T point
53#if defined key_agrif
54   ! AGRIF can not handle these arrays as integers. The reason is a mystery but problems avoided by declaring them as reals
55   REAL(wp),    PUBLIC, ALLOCATABLE, SAVE, DIMENSION (:,:)     ::  misfkt, misfkb         !:Level of ice shelf base
56                                                                                          !: (first wet level and last level include in the tbl)
57#else
58   INTEGER,    PUBLIC, ALLOCATABLE, SAVE, DIMENSION (:,:)     ::  misfkt, misfkb         !:Level of ice shelf base
59#endif
60
61
62   REAL(wp), PUBLIC, SAVE ::   rcpi   = 2000.0_wp     ! phycst ?
63   REAL(wp), PUBLIC, SAVE ::   kappa  = 1.54e-6_wp    ! phycst ?
64   REAL(wp), PUBLIC, SAVE ::   rhoisf = 920.0_wp      ! phycst ?
65   REAL(wp), PUBLIC, SAVE ::   tsurf  = -20.0_wp      ! phycst ?
66   REAL(wp), PUBLIC, SAVE ::   lfusisf= 0.334e6_wp    ! phycst ?
67
68!: Variable used in fldread to read the forcing file (nn_isf == 4 .OR. nn_isf == 3)
69   CHARACTER(len=100), PUBLIC ::   cn_dirisf  = './'    !: Root directory for location of ssr files
70   TYPE(FLD_N)       , PUBLIC ::   sn_fwfisf            !: information about the isf file to be read
71   TYPE(FLD), ALLOCATABLE, DIMENSION(:) ::  sf_fwfisf
72   TYPE(FLD_N)       , PUBLIC ::   sn_rnfisf              !: information about the runoff file to be read
73   TYPE(FLD), ALLOCATABLE, DIMENSION(:) ::   sf_rnfisf           
74   TYPE(FLD_N)       , PUBLIC ::   sn_depmax_isf, sn_depmin_isf, sn_Leff_isf     !: information about the runoff file to be read
75   
76   !! * Substitutions
77#  include "domzgr_substitute.h90"
78   !!----------------------------------------------------------------------
79   !! NEMO/OPA 3.0 , LOCEAN-IPSL (2008)
80   !! $Id$
81   !! Software governed by the CeCILL licence (modipsl/doc/NEMO_CeCILL.txt)
82   !!----------------------------------------------------------------------
83
84CONTAINS
85 
86  SUBROUTINE sbc_isf(kt)
87    INTEGER, INTENT(in) :: kt                   ! ocean time step
88    INTEGER             :: ji, jj, jk           ! loop index
89    INTEGER             :: ikt, ikb             ! top and bottom level of the isf boundary layer
90    INTEGER             :: inum, ierror
91    INTEGER             :: ios                  ! Local integer output status for namelist read
92    REAL(wp)            :: zhk
93    REAL(wp), DIMENSION (:,:), POINTER :: zt_frz, zdep ! freezing temperature (zt_frz) at depth (zdep)
94    CHARACTER(len=256)  :: cvarzisf, cvarhisf   ! name for isf file
95    CHARACTER(LEN=32 )  :: cvarLeff             ! variable name for efficient Length scale
96      !
97      !!---------------------------------------------------------------------
98      NAMELIST/namsbc_isf/ nn_isfblk, rn_hisf_tbl, rn_gammat0, rn_gammas0, nn_gammablk, nn_isf      , &
99                         & sn_fwfisf, sn_rnfisf, sn_depmax_isf, sn_depmin_isf, sn_Leff_isf
100      !
101      ! allocation
102      CALL wrk_alloc( jpi,jpj, zt_frz, zdep  )
103      !
104      !                                         ! ====================== !
105      IF( kt == nit000 ) THEN                   !  First call kt=nit000  !
106         !                                      ! ====================== !
107         REWIND( numnam_ref )              ! Namelist namsbc_rnf in reference namelist : Runoffs
108         READ  ( numnam_ref, namsbc_isf, IOSTAT = ios, ERR = 901)
109901      IF( ios /= 0 ) CALL ctl_nam ( ios , 'namsbc_isf in reference namelist', lwp )
110
111         REWIND( numnam_cfg )              ! Namelist namsbc_rnf in configuration namelist : Runoffs
112         READ  ( numnam_cfg, namsbc_isf, IOSTAT = ios, ERR = 902 )
113902      IF( ios /= 0 ) CALL ctl_nam ( ios , 'namsbc_isf in configuration namelist', lwp )
114         IF(lwm) WRITE ( numond, namsbc_isf )
115
116
117         IF ( lwp ) WRITE(numout,*)
118         IF ( lwp ) WRITE(numout,*) 'sbc_isf: heat flux of the ice shelf'
119         IF ( lwp ) WRITE(numout,*) '~~~~~~~~~'
120         IF ( lwp ) WRITE(numout,*) 'sbcisf :' 
121         IF ( lwp ) WRITE(numout,*) '~~~~~~~~'
122         IF ( lwp ) WRITE(numout,*) '        nn_isf      = ', nn_isf
123         IF ( lwp ) WRITE(numout,*) '        nn_isfblk   = ', nn_isfblk
124         IF ( lwp ) WRITE(numout,*) '        rn_hisf_tbl = ', rn_hisf_tbl
125         IF ( lwp ) WRITE(numout,*) '        nn_gammablk = ', nn_gammablk 
126         IF ( lwp ) WRITE(numout,*) '        rn_gammat0  = ', rn_gammat0 
127         IF ( lwp ) WRITE(numout,*) '        rn_gammas0  = ', rn_gammas0 
128         IF ( lwp ) WRITE(numout,*) '        rn_tfri2    = ', rn_tfri2 
129         !
130         ! Allocate public variable
131         IF ( sbc_isf_alloc()  /= 0 )         CALL ctl_stop( 'STOP', 'sbc_isf : unable to allocate arrays' )
132         !
133         ! initialisation
134         qisf(:,:)        = 0._wp  ; fwfisf  (:,:) = 0._wp
135         risf_tsc(:,:,:)  = 0._wp  ; fwfisf_b(:,:) = 0._wp
136         !
137         ! define isf tbl tickness, top and bottom indice
138         IF      (nn_isf == 1) THEN
139            rhisf_tbl(:,:) = rn_hisf_tbl
140            misfkt(:,:)    = mikt(:,:)         ! same indice for bg03 et cav => used in isfdiv
141         ELSE IF ((nn_isf == 3) .OR. (nn_isf == 2)) THEN
142            ALLOCATE( sf_rnfisf(1), STAT=ierror )
143            ALLOCATE( sf_rnfisf(1)%fnow(jpi,jpj,1), sf_rnfisf(1)%fdta(jpi,jpj,1,2) )
144            CALL fld_fill( sf_rnfisf, (/ sn_rnfisf /), cn_dirisf, 'sbc_isf_init', 'read fresh water flux isf data', 'namsbc_isf' )
145
146            !: read effective lenght (BG03)
147            IF (nn_isf == 2) THEN
148               cvarLeff = 'soLeff' 
149               CALL iom_open( sn_Leff_isf%clname, inum )
150               CALL iom_get( inum, jpdom_data, cvarLeff, risfLeff , 1)
151               CALL iom_close(inum)
152               !
153               risfLeff = risfLeff*1000.0_wp           !: convertion in m
154            END IF
155
156           ! read depth of the top and bottom of the isf top boundary layer (in this case, isf front depth and grounding line depth)
157            CALL iom_open( sn_depmax_isf%clname, inum )
158            cvarhisf = TRIM(sn_depmax_isf%clvar)
159            CALL iom_get( inum, jpdom_data, cvarhisf, rhisf_tbl, 1) !: depth of deepest point of the ice shelf base
160            CALL iom_close(inum)
161            !
162            CALL iom_open( sn_depmin_isf%clname, inum )
163            cvarzisf = TRIM(sn_depmin_isf%clvar)
164            CALL iom_get( inum, jpdom_data, cvarzisf, rzisf_tbl, 1) !: depth of shallowest point of the ice shelves base
165            CALL iom_close(inum)
166            !
167            rhisf_tbl(:,:) = rhisf_tbl(:,:) - rzisf_tbl(:,:)        !: tickness isf boundary layer
168
169           !! compute first level of the top boundary layer
170           DO ji = 1, jpi
171              DO jj = 1, jpj
172                  jk = 2
173                  DO WHILE ( jk .LE. mbkt(ji,jj) .AND. fsdepw(ji,jj,jk) < rzisf_tbl(ji,jj) ) ;  jk = jk + 1 ;  END DO
174                  misfkt(ji,jj) = jk-1
175               END DO
176            END DO
177
178         ELSE IF ( nn_isf == 4 ) THEN
179            ! as in nn_isf == 1
180            rhisf_tbl(:,:) = rn_hisf_tbl
181            misfkt(:,:)    = mikt(:,:)         ! same indice for bg03 et cav => used in isfdiv
182           
183            ! load variable used in fldread (use for temporal interpolation of isf fwf forcing)
184            ALLOCATE( sf_fwfisf(1), STAT=ierror )
185            ALLOCATE( sf_fwfisf(1)%fnow(jpi,jpj,1), sf_fwfisf(1)%fdta(jpi,jpj,1,2) )
186            CALL fld_fill( sf_fwfisf, (/ sn_fwfisf /), cn_dirisf, 'sbc_isf_init', 'read fresh water flux isf data', 'namsbc_isf' )
187         END IF
188         
189         rhisf_tbl_0(:,:) = rhisf_tbl(:,:)
190
191         ! compute bottom level of isf tbl and thickness of tbl below the ice shelf
192         DO jj = 1,jpj
193            DO ji = 1,jpi
194               ikt = misfkt(ji,jj)
195               ikb = misfkt(ji,jj)
196               ! thickness of boundary layer at least the top level thickness
197               rhisf_tbl(ji,jj) = MAX(rhisf_tbl_0(ji,jj), fse3t_n(ji,jj,ikt))
198
199               ! determine the deepest level influenced by the boundary layer
200               DO jk = ikt+1, mbkt(ji,jj)
201                  IF ( (SUM(fse3t_n(ji,jj,ikt:jk-1)) .LT. rhisf_tbl(ji,jj)) .AND. (tmask(ji,jj,jk) == 1) ) ikb = jk
202               END DO
203               rhisf_tbl(ji,jj) = MIN(rhisf_tbl(ji,jj), SUM(fse3t_n(ji,jj,ikt:ikb)))  ! limit the tbl to water thickness.
204               misfkb(ji,jj) = ikb                                                  ! last wet level of the tbl
205               r1_hisf_tbl(ji,jj) = 1._wp / rhisf_tbl(ji,jj)
206
207               zhk           = SUM( fse3t(ji, jj, ikt:ikb - 1)) * r1_hisf_tbl(ji,jj)  ! proportion of tbl cover by cell from ikt to ikb - 1
208               ralpha(ji,jj) = rhisf_tbl(ji,jj) * (1._wp - zhk ) / fse3t(ji,jj,ikb)  ! proportion of bottom cell influenced by boundary layer
209            END DO
210         END DO
211         
212      END IF
213
214      !                                            ! ---------------------------------------- !
215      IF( kt /= nit000 ) THEN                      !          Swap of forcing fields          !
216         !                                         ! ---------------------------------------- !
217         fwfisf_b  (:,:  ) = fwfisf  (:,:  )               ! Swap the ocean forcing fields except at nit000
218         risf_tsc_b(:,:,:) = risf_tsc(:,:,:)               ! where before fields are set at the end of the routine
219         !
220      ENDIF
221
222      IF( MOD( kt-1, nn_fsbc) == 0 ) THEN
223
224
225         ! compute salf and heat flux
226         IF (nn_isf == 1) THEN
227            ! realistic ice shelf formulation
228            ! compute T/S/U/V for the top boundary layer
229            CALL sbc_isf_tbl(tsn(:,:,:,jp_tem),ttbl(:,:),'T')
230            CALL sbc_isf_tbl(tsn(:,:,:,jp_sal),stbl(:,:),'T')
231            CALL sbc_isf_tbl(un(:,:,:)        ,utbl(:,:),'U')
232            CALL sbc_isf_tbl(vn(:,:,:)        ,vtbl(:,:),'V')
233            ! iom print
234            CALL iom_put('ttbl',ttbl(:,:))
235            CALL iom_put('stbl',stbl(:,:))
236            CALL iom_put('utbl',utbl(:,:))
237            CALL iom_put('vtbl',vtbl(:,:))
238            ! compute fwf and heat flux
239            CALL sbc_isf_cav (kt)
240
241         ELSE IF (nn_isf == 2) THEN
242            ! Beckmann and Goosse parametrisation
243            stbl(:,:)   = soce
244            CALL sbc_isf_bg03(kt)
245
246         ELSE IF (nn_isf == 3) THEN
247            ! specified runoff in depth (Mathiot et al., XXXX in preparation)
248            CALL fld_read ( kt, nn_fsbc, sf_rnfisf   )
249            fwfisf(:,:) = - sf_rnfisf(1)%fnow(:,:,1)         ! fwf  flux from the isf (fwfisf <0 mean melting)
250            qisf(:,:)   = fwfisf(:,:) * lfusisf              ! heat flux
251            stbl(:,:)   = soce
252
253         ELSE IF (nn_isf == 4) THEN
254            ! specified fwf and heat flux forcing beneath the ice shelf
255            CALL fld_read ( kt, nn_fsbc, sf_fwfisf   )
256            fwfisf(:,:) = - sf_fwfisf(1)%fnow(:,:,1)           ! fwf  flux from the isf (fwfisf <0 mean melting)
257            qisf(:,:)   = fwfisf(:,:) * lfusisf                ! heat flux
258            stbl(:,:)   = soce
259         END IF
260
261         ! compute tsc due to isf
262         ! isf melting implemented as a volume flux and we assume that melt water is at 0 PSU.
263         ! WARNING water add at temp = 0C, need to add a correction term (fwfisf * tfreez / rau0).
264         ! compute freezing point beneath ice shelf (or top cell if nn_isf = 3)
265         DO jj = 1,jpj
266            DO ji = 1,jpi
267               zdep(ji,jj)=fsdepw_n(ji,jj,misfkt(ji,jj))
268            END DO
269         END DO
270         CALL eos_fzp( stbl(:,:), zt_frz(:,:), zdep(:,:) )
271         
272         risf_tsc(:,:,jp_tem) = qisf(:,:) * r1_rau0_rcp - fwfisf(:,:) * zt_frz(:,:) * r1_rau0 !
273         risf_tsc(:,:,jp_sal) = 0.0_wp
274
275         ! lbclnk
276         CALL lbc_lnk(risf_tsc(:,:,jp_tem),'T',1.)
277         CALL lbc_lnk(risf_tsc(:,:,jp_sal),'T',1.)
278         CALL lbc_lnk(fwfisf(:,:)   ,'T',1.)
279         CALL lbc_lnk(qisf(:,:)     ,'T',1.)
280
281         IF( kt == nit000 ) THEN                         !   set the forcing field at nit000 - 1    !
282            IF( ln_rstart .AND.    &                     ! Restart: read in restart file
283                 & iom_varid( numror, 'fwf_isf_b', ldstop = .FALSE. ) > 0 ) THEN
284               IF(lwp) WRITE(numout,*) '          nit000-1 isf tracer content forcing fields read in the restart file'
285               CALL iom_get( numror, jpdom_autoglo, 'fwf_isf_b', fwfisf_b(:,:) )   ! before salt content isf_tsc trend
286               CALL iom_get( numror, jpdom_autoglo, 'isf_sc_b', risf_tsc_b(:,:,jp_sal) )   ! before salt content isf_tsc trend
287               CALL iom_get( numror, jpdom_autoglo, 'isf_hc_b', risf_tsc_b(:,:,jp_tem) )   ! before salt content isf_tsc trend
288            ELSE
289               fwfisf_b(:,:)    = fwfisf(:,:)
290               risf_tsc_b(:,:,:)= risf_tsc(:,:,:)
291            END IF
292         ENDIF
293         !
294         ! output
295         IF( iom_use('qisf'  ) )   CALL iom_put('qisf'  , qisf)
296         IF( iom_use('fwfisf') )   CALL iom_put('fwfisf', fwfisf)
297      END IF
298
299      ! deallocation
300      CALL wrk_dealloc( jpi,jpj, zt_frz, zdep  )
301 
302  END SUBROUTINE sbc_isf
303
304  INTEGER FUNCTION sbc_isf_alloc()
305      !!----------------------------------------------------------------------
306      !!               ***  FUNCTION sbc_isf_rnf_alloc  ***
307      !!----------------------------------------------------------------------
308      sbc_isf_alloc = 0       ! set to zero if no array to be allocated
309      IF( .NOT. ALLOCATED( qisf ) ) THEN
310         ALLOCATE(  risf_tsc(jpi,jpj,jpts), risf_tsc_b(jpi,jpj,jpts), qisf(jpi,jpj)   , &
311               &    rhisf_tbl(jpi,jpj)    , r1_hisf_tbl(jpi,jpj), rzisf_tbl(jpi,jpj)  , &
312               &    ttbl(jpi,jpj)         , stbl(jpi,jpj)       , utbl(jpi,jpj)       , &
313               &    vtbl(jpi, jpj)        , risfLeff(jpi,jpj)   , rhisf_tbl_0(jpi,jpj), &
314               &    ralpha(jpi,jpj)       , misfkt(jpi,jpj)     , misfkb(jpi,jpj)     , &
315               &    STAT= sbc_isf_alloc )
316         !
317         IF( lk_mpp                  )   CALL mpp_sum ( sbc_isf_alloc )
318         IF( sbc_isf_alloc /= 0 )   CALL ctl_warn('sbc_isf_alloc: failed to allocate arrays.')
319         !
320      ENDIF
321  END FUNCTION
322
323  SUBROUTINE sbc_isf_bg03(kt)
324   !!==========================================================================
325   !!                 *** SUBROUTINE sbcisf_bg03  ***
326   !! add net heat and fresh water flux from ice shelf melting
327   !! into the adjacent ocean using the parameterisation by
328   !! Beckmann and Goosse (2003), "A parameterization of ice shelf-ocean
329   !!     interaction for climate models", Ocean Modelling 5(2003) 157-170.
330   !!  (hereafter BG)
331   !!==========================================================================
332   !!----------------------------------------------------------------------
333   !!   sbc_isf_bg03      : routine called from sbcmod
334   !!----------------------------------------------------------------------
335   !!
336   !! ** Purpose   :   Add heat and fresh water fluxes due to ice shelf melting
337   !! ** Reference :   Beckmann et Goosse, 2003, Ocean Modelling
338   !!
339   !! History :
340   !!      !  06-02  (C. Wang) Original code
341   !!----------------------------------------------------------------------
342
343    INTEGER, INTENT ( in ) :: kt
344
345    INTEGER :: ji, jj, jk !temporary integer
346
347    REAL(wp) :: zt_sum    ! sum of the temperature between 200m and 600m
348    REAL(wp) :: zt_ave    ! averaged temperature between 200m and 600m
349    REAL(wp) :: zt_frz    ! freezing point temperature at depth z
350    REAL(wp) :: zpress    ! pressure to compute the freezing point in depth
351   
352    !!----------------------------------------------------------------------
353    IF ( nn_timing == 1 ) CALL timing_start('sbc_isf_bg03')
354     !
355
356    ! This test is false only in the very first time step of a run (JMM ???- Initialy build to skip 1rst year of run )
357    DO ji = 1, jpi
358       DO jj = 1, jpj
359          jk = misfkt(ji,jj)
360          !! Initialize arrays to 0 (each step)
361          zt_sum = 0.e0_wp
362          IF ( jk .GT. 1 ) THEN
363    ! 1. -----------the average temperature between 200m and 600m ---------------------
364             DO jk = misfkt(ji,jj),misfkb(ji,jj)
365             ! freezing point temperature  at ice shelf base BG eq. 2 (JMM sign pb ??? +7.64e-4 !!!)
366             ! after verif with UNESCO, wrong sign in BG eq. 2
367             ! Calculate freezing temperature
368                CALL eos_fzp(stbl(ji,jj), zt_frz, zpress) 
369                zt_sum = zt_sum + (tsn(ji,jj,jk,jp_tem)-zt_frz) * fse3t(ji,jj,jk) * tmask(ji,jj,jk)  ! sum temp
370             ENDDO
371             zt_ave = zt_sum/rhisf_tbl(ji,jj) ! calcul mean value
372   
373    ! 2. ------------Net heat flux and fresh water flux due to the ice shelf
374          ! For those corresponding to zonal boundary   
375             qisf(ji,jj) = - rau0 * rcp * rn_gammat0 * risfLeff(ji,jj) * e1t(ji,jj) * zt_ave  &
376                         & / (e1t(ji,jj) * e2t(ji,jj)) * tmask(ji,jj,jk) 
377             
378             fwfisf(ji,jj) = qisf(ji,jj) / lfusisf          !fresh water flux kg/(m2s)                 
379             fwfisf(ji,jj) = fwfisf(ji,jj) * ( soce / stbl(ji,jj) )
380             !add to salinity trend
381          ELSE
382             qisf(ji,jj) = 0._wp ; fwfisf(ji,jj) = 0._wp
383          END IF
384       ENDDO
385    ENDDO
386    !
387    IF( nn_timing == 1 )  CALL timing_stop('sbc_isf_bg03')
388  END SUBROUTINE sbc_isf_bg03
389
390   SUBROUTINE sbc_isf_cav( kt )
391      !!---------------------------------------------------------------------
392      !!                     ***  ROUTINE sbc_isf_cav  ***
393      !!
394      !! ** Purpose :   handle surface boundary condition under ice shelf
395      !!
396      !! ** Method  : -
397      !!
398      !! ** Action  :   utau, vtau : remain unchanged
399      !!                taum, wndm : remain unchanged
400      !!                qns        : update heat flux below ice shelf
401      !!                emp, emps  : update freshwater flux below ice shelf
402      !!---------------------------------------------------------------------
403      INTEGER, INTENT(in)          ::   kt         ! ocean time step
404      !
405      REAL(wp), DIMENSION(:,:), POINTER ::   zfrz
406      REAL(wp), DIMENSION(:,:), POINTER ::   zgammat, zgammas 
407      REAL(wp), DIMENSION(:,:), POINTER ::   zfwflx, zhtflx, zhtflx_b
408      REAL(wp) ::   zlamb1, zlamb2, zlamb3
409      REAL(wp) ::   zeps1,zeps2,zeps3,zeps4,zeps6,zeps7
410      REAL(wp) ::   zaqe,zbqe,zcqe,zaqer,zdis,zsfrz,zcfac
411      REAL(wp) ::   zeps = 1.e-20_wp       
412      REAL(wp) ::   zerr
413      INTEGER  ::   ji, jj     ! dummy loop indices
414      INTEGER  ::   nit
415      LOGICAL  ::   lit
416      !!---------------------------------------------------------------------
417      !
418      ! coeficient for linearisation of potential tfreez
419      ! Crude approximation for pressure (but commonly used)
420      zlamb1=-0.0573_wp
421      zlamb2= 0.0832_wp
422      zlamb3=-7.53e-08 * grav * rau0
423      IF( nn_timing == 1 )  CALL timing_start('sbc_isf_cav')
424      !
425      CALL wrk_alloc( jpi,jpj, zfrz  , zgammat, zgammas  )
426      CALL wrk_alloc( jpi,jpj, zfwflx, zhtflx , zhtflx_b )
427
428      ! initialisation
429      zgammat(:,:)=rn_gammat0 ; zgammas (:,:)=rn_gammas0;
430      zhtflx (:,:)=0.0_wp     ; zhtflx_b(:,:)=0.0_wp    ;
431      zfwflx (:,:)=0.0_wp
432
433      ! compute ice shelf melting
434      nit = 1 ; lit = .TRUE.
435      DO WHILE ( lit )    ! maybe just a constant number of iteration as in blk_core is fine
436         IF (nn_isfblk == 1) THEN 
437            ! ISOMIP formulation (2 equations) for volume flux (Hunter et al., 2006)
438            ! Calculate freezing temperature
439            CALL eos_fzp( stbl(:,:), zfrz(:,:), risfdep(:,:) )
440
441            ! compute gammat every where (2d)
442            CALL sbc_isf_gammats(zgammat, zgammas, zhtflx, zfwflx)
443           
444            ! compute upward heat flux zhtflx and upward water flux zwflx
445            DO jj = 1, jpj
446               DO ji = 1, jpi
447                  zhtflx(ji,jj) =   zgammat(ji,jj)*rcp*rau0*(ttbl(ji,jj)-zfrz(ji,jj))
448                  zfwflx(ji,jj) = - zhtflx(ji,jj)/lfusisf
449               END DO
450            END DO
451
452            ! Compute heat flux and upward fresh water flux
453            qisf  (:,:) = - zhtflx(:,:) * (1._wp - tmask(:,:,1)) * ssmask(:,:)
454            fwfisf(:,:) =   zfwflx(:,:) * (1._wp - tmask(:,:,1)) * ssmask(:,:)
455
456         ELSE IF (nn_isfblk == 2 ) THEN
457            ! ISOMIP+ formulation (3 equations) for volume flux (Asay-Davis et al., 2015)
458            ! compute gammat every where (2d)
459            CALL sbc_isf_gammats(zgammat, zgammas, zhtflx, zfwflx)
460
461            ! compute upward heat flux zhtflx and upward water flux zwflx
462            ! Resolution of a 2d equation from equation 21, 22 and 23 to find Sb (Asay-Davis et al., 2015)
463            DO jj = 1, jpj
464               DO ji = 1, jpi
465                  ! compute coeficient to solve the 2nd order equation
466                  zeps1=rcp*rau0*zgammat(ji,jj)
467                  zeps2=lfusisf*rau0*zgammas(ji,jj)
468                  zeps3=rhoisf*rcpi*kappa/MAX(risfdep(ji,jj),zeps)
469                  zeps4=zlamb2+zlamb3*risfdep(ji,jj)
470                  zeps6=zeps4-ttbl(ji,jj)
471                  zeps7=zeps4-tsurf
472                  zaqe=zlamb1 * (zeps1 + zeps3)
473                  zaqer=0.5/MIN(zaqe,-zeps)
474                  zbqe=zeps1*zeps6+zeps3*zeps7-zeps2
475                  zcqe=zeps2*stbl(ji,jj)
476                  zdis=zbqe*zbqe-4.0*zaqe*zcqe               
477
478                  ! Presumably zdis can never be negative because gammas is very small compared to gammat
479                  ! compute s freeze
480                  zsfrz=(-zbqe-SQRT(zdis))*zaqer
481                  IF ( zsfrz .LT. 0.0_wp ) zsfrz=(-zbqe+SQRT(zdis))*zaqer
482
483                  ! compute t freeze (eq. 22)
484                  zfrz(ji,jj)=zeps4+zlamb1*zsfrz
485 
486                  ! zfwflx is upward water flux
487                  ! zhtflx is upward heat flux (out of ocean)
488                  ! compute the upward water and heat flux (eq. 28 and eq. 29)
489                  zfwflx(ji,jj) = rau0 * zgammas(ji,jj) * (zsfrz-stbl(ji,jj)) / MAX(zsfrz,zeps)
490                  zhtflx(ji,jj) = zgammat(ji,jj) * rau0 * rcp * (ttbl(ji,jj) - zfrz(ji,jj) ) 
491               END DO
492            END DO
493
494            ! compute heat and water flux
495            qisf  (:,:) = - zhtflx(:,:) * (1._wp - tmask(:,:,1)) * ssmask(:,:)
496            fwfisf(:,:) =   zfwflx(:,:) * (1._wp - tmask(:,:,1)) * ssmask(:,:)
497
498         ENDIF
499
500         ! define if we need to iterate (nn_gammablk 0/1 do not need iteration)
501         IF ( nn_gammablk .LT. 2 ) THEN ; lit = .FALSE.
502         ELSE                           
503            ! check total number of iteration
504            IF (nit .GE. 100) THEN ; CALL ctl_stop( 'STOP', 'sbc_isf_hol99 : too many iteration ...' )
505            ELSE                   ; nit = nit + 1
506            ENDIF
507
508            ! compute error between 2 iterations
509            ! if needed save gammat and compute zhtflx_b for next iteration
510            zerr = MAXVAL(ABS(zhtflx-zhtflx_b))
511            IF ( zerr .LE. 0.01 ) THEN ; lit = .FALSE.
512            ELSE                       ; zhtflx_b(:,:) = zhtflx(:,:)
513            ENDIF
514         END IF
515      END DO
516      !
517      ! output
518      IF( iom_use('isfgammat') ) CALL iom_put('isfgammat', zgammat)
519      IF( iom_use('isfgammas') ) CALL iom_put('isfgammas', zgammas)
520      !
521      CALL wrk_dealloc( jpi,jpj, zfrz  , zgammat, zgammas  )
522      CALL wrk_dealloc( jpi,jpj, zfwflx, zhtflx , zhtflx_b )
523      !
524      IF( nn_timing == 1 )  CALL timing_stop('sbc_isf_cav')
525
526   END SUBROUTINE sbc_isf_cav
527
528   SUBROUTINE sbc_isf_gammats(gt, gs, zqhisf, zqwisf )
529      !!----------------------------------------------------------------------
530      !! ** Purpose    : compute the coefficient echange for heat flux
531      !!
532      !! ** Method     : gamma assume constant or depends of u* and stability
533      !!
534      !! ** References : Holland and Jenkins, 1999, JPO, p1787-1800, eq 14
535      !!                Jenkins et al., 2010, JPO, p2298-2312
536      !!---------------------------------------------------------------------
537      REAL(wp), DIMENSION(:,:), INTENT(out) :: gt, gs
538      REAL(wp), DIMENSION(:,:), INTENT(in ) :: zqhisf, zqwisf
539
540      INTEGER  :: ikt                       
541      INTEGER  :: ji,jj                      ! loop index
542      REAL(wp), DIMENSION(:,:), POINTER :: zustar           ! U, V at T point and friction velocity
543      REAL(wp) :: zdku, zdkv                 ! U, V shear
544      REAL(wp) :: zPr, zSc, zRc              ! Prandtl, Scmidth and Richardson number
545      REAL(wp) :: zmob, zmols                ! Monin Obukov length, coriolis factor at T point
546      REAL(wp) :: zbuofdep, zhnu             ! Bouyancy length scale, sublayer tickness
547      REAL(wp) :: zhmax                      ! limitation of mol
548      REAL(wp) :: zetastar                   ! stability parameter
549      REAL(wp) :: zgmolet, zgmoles, zgturb   ! contribution of modelecular sublayer and turbulence
550      REAL(wp) :: zcoef                      ! temporary coef
551      REAL(wp) :: zdep
552      REAL(wp) :: zeps = 1.0e-20_wp   
553      REAL(wp), PARAMETER :: zxsiN = 0.052   ! dimensionless constant
554      REAL(wp), PARAMETER :: znu   = 1.95e-6 ! kinamatic viscosity of sea water (m2.s-1)
555      REAL(wp), DIMENSION(2) :: zts, zab
556      !!---------------------------------------------------------------------
557      CALL wrk_alloc( jpi,jpj, zustar )
558      !
559      IF      ( nn_gammablk == 0 ) THEN
560      !! gamma is constant (specified in namelist)
561      !! ISOMIP formulation (Hunter et al, 2006)
562         gt(:,:) = rn_gammat0
563         gs(:,:) = rn_gammas0
564
565      ELSE IF ( nn_gammablk == 1 ) THEN
566      !! gamma is assume to be proportional to u*
567      !! Jenkins et al., 2010, JPO, p2298-2312
568      !! Adopted by Asay-Davis et al. (2015)
569
570      !! compute ustar (eq. 24)
571         zustar(:,:) = SQRT( rn_tfri2 * (utbl(:,:) * utbl(:,:) + vtbl(:,:) * vtbl(:,:) + rn_tfeb2) )
572
573      !! Compute gammats
574         gt(:,:) = zustar(:,:) * rn_gammat0
575         gs(:,:) = zustar(:,:) * rn_gammas0
576     
577      ELSE IF ( nn_gammablk == 2 ) THEN
578      !! gamma depends of stability of boundary layer
579      !! Holland and Jenkins, 1999, JPO, p1787-1800, eq 14
580      !! as MOL depends of flux and flux depends of MOL, best will be iteration (TO DO)
581      !! compute ustar
582         zustar(:,:) = SQRT( rn_tfri2 * (utbl(:,:) * utbl(:,:) + vtbl(:,:) * vtbl(:,:) + rn_tfeb2) )
583
584      !! compute Pr and Sc number (can be improved)
585         zPr =   13.8
586         zSc = 2432.0
587
588      !! compute gamma mole
589         zgmolet = 12.5 * zPr ** (2.0/3.0) - 6.0
590         zgmoles = 12.5 * zSc ** (2.0/3.0) -6.0
591
592      !! compute gamma
593         DO ji=2,jpi
594            DO jj=2,jpj
595               ikt = mikt(ji,jj)
596
597               IF (zustar(ji,jj) == 0._wp) THEN           ! only for kt = 1 I think
598                  gt = rn_gammat0
599                  gs = rn_gammas0
600               ELSE
601      !! compute Rc number (as done in zdfric.F90)
602                  zcoef = 0.5 / fse3w(ji,jj,ikt)
603                  !                                            ! shear of horizontal velocity
604                  zdku = zcoef * (  un(ji-1,jj  ,ikt  ) + un(ji,jj,ikt  )  &
605                     &             -un(ji-1,jj  ,ikt+1) - un(ji,jj,ikt+1)  )
606                  zdkv = zcoef * (  vn(ji  ,jj-1,ikt  ) + vn(ji,jj,ikt  )  &
607                     &             -vn(ji  ,jj-1,ikt+1) - vn(ji,jj,ikt+1)  )
608                  !                                            ! richardson number (minimum value set to zero)
609                  zRc = rn2(ji,jj,ikt+1) / MAX( zdku*zdku + zdkv*zdkv, zeps )
610
611      !! compute bouyancy
612                  zts(jp_tem) = ttbl(ji,jj)
613                  zts(jp_sal) = stbl(ji,jj)
614                  zdep        = fsdepw(ji,jj,ikt)
615                  !
616                  CALL eos_rab( zts, zdep, zab )
617                  !
618      !! compute length scale
619                  zbuofdep = grav * ( zab(jp_tem) * zqhisf(ji,jj) - zab(jp_sal) * zqwisf(ji,jj) )  !!!!!!!!!!!!!!!!!!!!!!!!!!!!
620
621      !! compute Monin Obukov Length
622                  ! Maximum boundary layer depth
623                  zhmax = fsdept(ji,jj,mbkt(ji,jj)) - fsdepw(ji,jj,mikt(ji,jj)) - 0.001_wp
624                  ! Compute Monin obukhov length scale at the surface and Ekman depth:
625                  zmob   = zustar(ji,jj) ** 3 / (vkarmn * (zbuofdep + zeps))
626                  zmols  = SIGN(1._wp, zmob) * MIN(ABS(zmob), zhmax) * tmask(ji,jj,ikt)
627
628      !! compute eta* (stability parameter)
629                  zetastar = 1._wp / ( SQRT(1._wp + MAX(zxsiN * zustar(ji,jj) / ( ABS(ff(ji,jj)) * zmols * zRc ), 0.0_wp)))
630
631      !! compute the sublayer thickness
632                  zhnu = 5 * znu / zustar(ji,jj)
633
634      !! compute gamma turb
635                  zgturb = 1._wp / vkarmn * LOG(zustar(ji,jj) * zxsiN * zetastar * zetastar / ( ABS(ff(ji,jj)) * zhnu )) &
636                  &      + 1._wp / ( 2 * zxsiN * zetastar ) - 1._wp / vkarmn
637
638      !! compute gammats
639                  gt(ji,jj) = zustar(ji,jj) / (zgturb + zgmolet)
640                  gs(ji,jj) = zustar(ji,jj) / (zgturb + zgmoles)
641               END IF
642            END DO
643         END DO
644         CALL lbc_lnk(gt(:,:),'T',1.)
645         CALL lbc_lnk(gs(:,:),'T',1.)
646      END IF
647      CALL wrk_dealloc( jpi,jpj, zustar )
648
649   END SUBROUTINE
650
651   SUBROUTINE sbc_isf_tbl( varin, varout, cptin )
652      !!----------------------------------------------------------------------
653      !!                  ***  SUBROUTINE sbc_isf_tbl  ***
654      !!
655      !! ** Purpose : compute mean T/S/U/V in the boundary layer at T- point
656      !!
657      !!----------------------------------------------------------------------
658      REAL(wp), DIMENSION(:,:,:), INTENT(in) :: varin
659      REAL(wp), DIMENSION(:,:)  , INTENT(out):: varout
660     
661      CHARACTER(len=1), INTENT(in) :: cptin ! point of variable in/out
662
663      REAL(wp) :: ze3, zhk
664      REAL(wp), DIMENSION(:,:), POINTER :: zhisf_tbl ! thickness of the tbl
665
666      INTEGER :: ji,jj,jk                   ! loop index
667      INTEGER :: ikt,ikb                    ! top and bottom index of the tbl
668 
669      ! allocation
670      CALL wrk_alloc( jpi,jpj, zhisf_tbl)
671     
672      ! initialisation
673      varout(:,:)=0._wp
674   
675      ! compute U in the top boundary layer at T- point
676      IF (cptin == 'U') THEN
677         DO jj = 1,jpj
678            DO ji = 1,jpi
679               ikt = miku(ji,jj) ; ikb = miku(ji,jj)
680            ! thickness of boundary layer at least the top level thickness
681               zhisf_tbl(ji,jj) = MAX(rhisf_tbl_0(ji,jj), fse3u_n(ji,jj,ikt))
682
683            ! determine the deepest level influenced by the boundary layer
684               DO jk = ikt+1, mbku(ji,jj)
685                  IF ( (SUM(fse3u_n(ji,jj,ikt:jk-1)) .LT. zhisf_tbl(ji,jj)) .AND. (umask(ji,jj,jk) == 1) ) ikb = jk
686               END DO
687               zhisf_tbl(ji,jj) = MIN(zhisf_tbl(ji,jj), SUM(fse3u_n(ji,jj,ikt:ikb)))  ! limit the tbl to water thickness.
688
689            ! level fully include in the ice shelf boundary layer
690               DO jk = ikt, ikb - 1
691                  ze3 = fse3u_n(ji,jj,jk)
692                  varout(ji,jj) = varout(ji,jj) + varin(ji,jj,jk) / zhisf_tbl(ji,jj) * ze3
693               END DO
694
695            ! level partially include in ice shelf boundary layer
696               zhk = SUM( fse3u_n(ji, jj, ikt:ikb - 1)) / zhisf_tbl(ji,jj)
697               varout(ji,jj) = varout(ji,jj) + varin(ji,jj,ikb) * (1._wp - zhk)
698            END DO
699         END DO
700         DO jj = 2,jpj
701            DO ji = 2,jpi
702               varout(ji,jj) = 0.5_wp * (varout(ji,jj) + varout(ji-1,jj))
703            END DO
704         END DO
705         CALL lbc_lnk(varout,'T',-1.)
706      END IF
707
708      ! compute V in the top boundary layer at T- point
709      IF (cptin == 'V') THEN
710         DO jj = 1,jpj
711            DO ji = 1,jpi
712               ikt = mikv(ji,jj) ; ikb = mikv(ji,jj)
713           ! thickness of boundary layer at least the top level thickness
714               zhisf_tbl(ji,jj) = MAX(rhisf_tbl_0(ji,jj), fse3v_n(ji,jj,ikt))
715
716            ! determine the deepest level influenced by the boundary layer
717               DO jk = ikt+1, mbkv(ji,jj)
718                  IF ( (SUM(fse3v_n(ji,jj,ikt:jk-1)) .LT. zhisf_tbl(ji,jj)) .AND. (vmask(ji,jj,jk) == 1) ) ikb = jk
719               END DO
720               zhisf_tbl(ji,jj) = MIN(zhisf_tbl(ji,jj), SUM(fse3v_n(ji,jj,ikt:ikb)))  ! limit the tbl to water thickness.
721
722            ! level fully include in the ice shelf boundary layer
723               DO jk = ikt, ikb - 1
724                  ze3 = fse3v_n(ji,jj,jk)
725                  varout(ji,jj) = varout(ji,jj) + varin(ji,jj,jk) / zhisf_tbl(ji,jj) * ze3
726               END DO
727
728            ! level partially include in ice shelf boundary layer
729               zhk = SUM( fse3v_n(ji, jj, ikt:ikb - 1)) / zhisf_tbl(ji,jj)
730               varout(ji,jj) = varout(ji,jj) + varin(ji,jj,ikb) * (1._wp - zhk)
731            END DO
732         END DO
733         DO jj = 2,jpj
734            DO ji = 2,jpi
735               varout(ji,jj) = 0.5_wp * (varout(ji,jj) + varout(ji,jj-1))
736            END DO
737         END DO
738         CALL lbc_lnk(varout,'T',-1.)
739      END IF
740
741      ! compute T in the top boundary layer at T- point
742      IF (cptin == 'T') THEN
743         DO jj = 1,jpj
744            DO ji = 1,jpi
745               ikt = misfkt(ji,jj)
746               ikb = misfkb(ji,jj)
747
748            ! level fully include in the ice shelf boundary layer
749               DO jk = ikt, ikb - 1
750                  ze3 = fse3t_n(ji,jj,jk)
751                  varout(ji,jj) = varout(ji,jj) + varin(ji,jj,jk) * r1_hisf_tbl(ji,jj) * ze3
752               END DO
753
754            ! level partially include in ice shelf boundary layer
755               zhk = SUM( fse3t_n(ji, jj, ikt:ikb - 1)) * r1_hisf_tbl(ji,jj)
756               varout(ji,jj) = varout(ji,jj) + varin(ji,jj,ikb) * (1._wp - zhk)
757            END DO
758         END DO
759      END IF
760
761      ! mask mean tbl value
762      varout(:,:) = varout(:,:) * ssmask(:,:)
763
764      ! deallocation
765      CALL wrk_dealloc( jpi,jpj, zhisf_tbl )     
766
767   END SUBROUTINE sbc_isf_tbl
768     
769
770   SUBROUTINE sbc_isf_div( phdivn )
771      !!----------------------------------------------------------------------
772      !!                  ***  SUBROUTINE sbc_isf_div  ***
773      !!       
774      !! ** Purpose :   update the horizontal divergence with the runoff inflow
775      !!
776      !! ** Method  :   
777      !!                CAUTION : risf_tsc(:,:,jp_sal) is negative (outflow) increase the
778      !!                          divergence and expressed in m/s
779      !!
780      !! ** Action  :   phdivn   decreased by the runoff inflow
781      !!----------------------------------------------------------------------
782      REAL(wp), DIMENSION(:,:,:), INTENT(inout) ::   phdivn   ! horizontal divergence
783      !!
784      INTEGER  ::   ji, jj, jk   ! dummy loop indices
785      INTEGER  ::   ikt, ikb 
786      REAL(wp) ::   zhk
787      REAL(wp) ::   zfact     ! local scalar
788      !!----------------------------------------------------------------------
789      !
790      zfact   = 0.5_wp
791      !
792      IF (lk_vvl) THEN     ! need to re compute level distribution of isf fresh water
793         DO jj = 1,jpj
794            DO ji = 1,jpi
795               ikt = misfkt(ji,jj)
796               ikb = misfkt(ji,jj)
797               ! thickness of boundary layer at least the top level thickness
798               rhisf_tbl(ji,jj) = MAX(rhisf_tbl_0(ji,jj), fse3t(ji,jj,ikt))
799
800               ! determine the deepest level influenced by the boundary layer
801               DO jk = ikt+1, mbkt(ji,jj)
802                  IF ( (SUM(fse3t(ji,jj,ikt:jk-1)) .LT. rhisf_tbl(ji,jj)) .AND. (tmask(ji,jj,jk) == 1) ) ikb = jk
803               END DO
804               rhisf_tbl(ji,jj) = MIN(rhisf_tbl(ji,jj), SUM(fse3t(ji,jj,ikt:ikb)))  ! limit the tbl to water thickness.
805               misfkb(ji,jj) = ikb                                                  ! last wet level of the tbl
806               r1_hisf_tbl(ji,jj) = 1._wp / rhisf_tbl(ji,jj)
807
808               zhk           = SUM( fse3t(ji, jj, ikt:ikb - 1)) * r1_hisf_tbl(ji,jj) ! proportion of tbl cover by cell from ikt to ikb - 1
809               ralpha(ji,jj) = rhisf_tbl(ji,jj) * (1._wp - zhk ) / fse3t(ji,jj,ikb)  ! proportion of bottom cell influenced by boundary layer
810            END DO
811         END DO
812      END IF 
813      !
814      !==   ice shelf melting distributed over several levels   ==!
815      DO jj = 1,jpj
816         DO ji = 1,jpi
817               ikt = misfkt(ji,jj)
818               ikb = misfkb(ji,jj)
819               ! level fully include in the ice shelf boundary layer
820               DO jk = ikt, ikb - 1
821                  phdivn(ji,jj,jk) = phdivn(ji,jj,jk) + ( fwfisf(ji,jj) + fwfisf_b(ji,jj) ) &
822                    &               * r1_hisf_tbl(ji,jj) * r1_rau0 * zfact
823               END DO
824               ! level partially include in ice shelf boundary layer
825               phdivn(ji,jj,ikb) = phdivn(ji,jj,ikb) + ( fwfisf(ji,jj) &
826                  &             + fwfisf_b(ji,jj) ) * r1_hisf_tbl(ji,jj) * r1_rau0 * zfact * ralpha(ji,jj) 
827         END DO
828      END DO
829      !
830   END SUBROUTINE sbc_isf_div
831   !!======================================================================
832END MODULE sbcisf
Note: See TracBrowser for help on using the repository browser.