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.
iceupdate.F90 in NEMO/trunk/src/ICE – NEMO

source: NEMO/trunk/src/ICE/iceupdate.F90

Last change on this file was 15385, checked in by clem, 2 years ago

cleaning some ice routines. No change in sette

  • Property svn:keywords set to Id
File size: 28.2 KB
Line 
1MODULE iceupdate
2   !!======================================================================
3   !!                       ***  MODULE iceupdate   ***
4   !!  Sea-ice :   computation of the flux at the sea ice/ocean interface
5   !!======================================================================
6   !! History :  4.0  !  2018     (many people)      SI3 [aka Sea Ice cube]
7   !!----------------------------------------------------------------------
8#if defined key_si3
9   !!----------------------------------------------------------------------
10   !!   'key_si3'                                       SI3 sea-ice model
11   !!----------------------------------------------------------------------
12   !!   ice_update_alloc : allocate the iceupdate arrays
13   !!   ice_update_init  : initialisation
14   !!   ice_update_flx   : updates mass, heat and salt fluxes at the ocean surface
15   !!   ice_update_tau   : update i- and j-stresses, and its modulus at the ocean surface
16   !!----------------------------------------------------------------------
17   USE phycst         ! physical constants
18   USE dom_oce        ! ocean domain
19   USE ice            ! sea-ice: variables
20   USE sbc_ice        ! Surface boundary condition: ice   fields
21   USE sbc_oce        ! Surface boundary condition: ocean fields
22   USE sbccpl         ! Surface boundary condition: coupled interface
23   USE icealb         ! sea-ice: albedo parameters
24   USE traqsr         ! add penetration of solar flux in the calculation of heat budget
25   USE icectl         ! sea-ice: control prints
26   USE zdfdrg  , ONLY : ln_drgice_imp
27   !
28   USE in_out_manager ! I/O manager
29   USE iom            ! I/O manager library
30   USE lib_mpp        ! MPP library
31   USE lib_fortran    ! fortran utilities (glob_sum + no signed zero)
32   USE lbclnk         ! lateral boundary conditions (or mpp links)
33   USE timing         ! Timing
34
35   IMPLICIT NONE
36   PRIVATE
37
38   PUBLIC   ice_update_init   ! called by ice_init
39   PUBLIC   ice_update_flx    ! called by ice_stp
40   PUBLIC   ice_update_tau    ! called by ice_stp
41
42   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) ::   utau_oce, vtau_oce   ! air-ocean surface i- & j-stress     [N/m2]
43   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) ::   tmod_io              ! modulus of the ice-ocean velocity   [m/s]
44
45   !! * Substitutions
46#  include "do_loop_substitute.h90"
47   !!----------------------------------------------------------------------
48   !! NEMO/ICE 4.0 , NEMO Consortium (2018)
49   !! $Id$
50   !! Software governed by the CeCILL license (see ./LICENSE)
51   !!----------------------------------------------------------------------
52CONTAINS
53
54   INTEGER FUNCTION ice_update_alloc()
55      !!-------------------------------------------------------------------
56      !!             ***  ROUTINE ice_update_alloc ***
57      !!-------------------------------------------------------------------
58      ALLOCATE( utau_oce(jpi,jpj), vtau_oce(jpi,jpj), tmod_io(jpi,jpj), STAT=ice_update_alloc )
59      !
60      CALL mpp_sum( 'iceupdate', ice_update_alloc )
61      IF( ice_update_alloc /= 0 )   CALL ctl_stop( 'STOP', 'ice_update_alloc: failed to allocate arrays' )
62      !
63   END FUNCTION ice_update_alloc
64
65
66   SUBROUTINE ice_update_flx( kt )
67      !!-------------------------------------------------------------------
68      !!                ***  ROUTINE ice_update_flx ***
69      !!
70      !! ** Purpose :   Update the surface ocean boundary condition for heat
71      !!                salt and mass over areas where sea-ice is non-zero
72      !!
73      !! ** Action  : - computes the heat and freshwater/salt fluxes
74      !!                at the ice-ocean interface.
75      !!              - Update the ocean sbc
76      !!
77      !! ** Outputs : - qsr     : sea heat flux:     solar
78      !!              - qns     : sea heat flux: non solar
79      !!              - emp     : freshwater budget: volume flux
80      !!              - sfx     : salt flux
81      !!              - fr_i    : ice fraction
82      !!              - tn_ice  : sea-ice surface temperature
83      !!              - alb_ice : sea-ice albedo (recomputed only for coupled mode)
84      !!
85      !! References : Goosse, H. et al. 1996, Bul. Soc. Roy. Sc. Liege, 65, 87-90.
86      !!              Tartinville et al. 2001 Ocean Modelling, 3, 95-108.
87      !!              These refs are now obsolete since everything has been revised
88      !!              The ref should be Rousset et al., 2015
89      !!---------------------------------------------------------------------
90      INTEGER, INTENT(in) ::   kt   ! number of iteration
91      !
92      INTEGER  ::   ji, jj, jl, jk   ! dummy loop indices
93      REAL(wp) ::   zqsr             ! New solar flux received by the ocean
94      REAL(wp), ALLOCATABLE, DIMENSION(:,:) ::   z2d                  ! 2D workspace
95      !!---------------------------------------------------------------------
96      IF( ln_timing )   CALL timing_start('iceupdate')
97
98      IF( kt == nit000 .AND. lwp ) THEN
99         WRITE(numout,*)
100         WRITE(numout,*)'ice_update_flx: update fluxes (mass, salt and heat) at the ice-ocean interface'
101         WRITE(numout,*)'~~~~~~~~~~~~~~'
102      ENDIF
103
104      ! Net heat flux on top of the ice-ocean (W.m-2)
105      !----------------------------------------------
106      IF( ln_cndflx ) THEN   ! ice-atm interface = conduction (and melting) fluxes
107         qt_atm_oi(:,:) = ( 1._wp - at_i_b(:,:) ) * ( qns_oce(:,:) + qsr_oce(:,:) ) + qemp_oce(:,:) + &
108            &             SUM( a_i_b * ( qcn_ice + qml_ice + qtr_ice_top ), dim=3 ) + qemp_ice(:,:)
109      ELSE                   ! ice-atm interface = solar and non-solar fluxes
110         qt_atm_oi(:,:) = qns_tot(:,:) + qsr_tot(:,:) 
111      ENDIF
112
113      ! --- case we bypass ice thermodynamics --- !
114      IF( .NOT. ln_icethd ) THEN   ! we suppose ice is impermeable => ocean is isolated from atmosphere
115         qt_atm_oi  (:,:)   = ( 1._wp - at_i_b(:,:) ) * ( qns_oce(:,:) + qsr_oce(:,:) ) + qemp_oce(:,:)
116         qt_oce_ai  (:,:)   = ( 1._wp - at_i_b(:,:) ) *   qns_oce(:,:)                  + qemp_oce(:,:)
117         emp_ice    (:,:)   = 0._wp
118         qemp_ice   (:,:)   = 0._wp
119         qevap_ice  (:,:,:) = 0._wp
120      ENDIF
121
122      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
123
124         ! Solar heat flux reaching the ocean (max) = zqsr (W.m-2)
125         !---------------------------------------------------
126         IF( ln_cndflx ) THEN   ! ice-atm interface = conduction (and melting) fluxes
127            zqsr = ( 1._wp - at_i_b(ji,jj) ) * qsr_oce(ji,jj) + SUM( a_i_b (ji,jj,:) * qtr_ice_bot(ji,jj,:) )
128         ELSE                   ! ice-atm interface = solar and non-solar fluxes
129            zqsr = qsr_tot(ji,jj) - SUM( a_i_b(ji,jj,:) * ( qsr_ice(ji,jj,:) - qtr_ice_bot(ji,jj,:) ) )
130         ENDIF
131
132         ! Total heat flux reaching the ocean = qt_oce_ai (W.m-2)
133         !---------------------------------------------------
134         IF( ln_icethd ) THEN
135            qt_oce_ai(ji,jj) = qt_atm_oi(ji,jj) - hfx_sum(ji,jj) - hfx_bom(ji,jj) - hfx_bog(ji,jj) &
136               &                                - hfx_dif(ji,jj) - hfx_opw(ji,jj) - hfx_snw(ji,jj) &
137               &                                + hfx_thd(ji,jj) + hfx_dyn(ji,jj) + hfx_res(ji,jj) &
138               &                                + hfx_sub(ji,jj) - SUM( qevap_ice(ji,jj,:) * a_i_b(ji,jj,:) ) + hfx_spr(ji,jj)
139         ENDIF
140         
141         ! New qsr and qns used to compute the oceanic heat flux at the next time step
142         !----------------------------------------------------------------------------
143         ! if warming and some ice remains, then we suppose that the whole solar flux has been consumed to melt the ice
144         ! else ( cooling or no ice left ), then we suppose that     no    solar flux has been consumed
145         !
146         IF( fhld(ji,jj) > 0._wp .AND. at_i(ji,jj) > 0._wp ) THEN   !-- warming and some ice remains
147            !                                        solar flux transmitted thru the 1st level of the ocean (i.e. not used by sea-ice)
148            qsr(ji,jj) = ( 1._wp - at_i_b(ji,jj) ) * qsr_oce(ji,jj) * ( 1._wp - frq_m(ji,jj) ) &
149               !                                   + solar flux transmitted thru ice and the 1st ocean level (also not used by sea-ice)
150               &             + SUM( a_i_b(ji,jj,:) * qtr_ice_bot(ji,jj,:) ) * ( 1._wp - frq_m(ji,jj) )
151            !
152         ELSE                                                       !-- cooling or no ice left
153            qsr(ji,jj) = zqsr
154         ENDIF
155         !
156         ! the non-solar is simply derived from the solar flux
157         qns(ji,jj) = qt_oce_ai(ji,jj) - qsr(ji,jj)
158
159         ! Mass flux at the atm. surface
160         !-----------------------------------
161         wfx_sub(ji,jj) = wfx_snw_sub(ji,jj) + wfx_ice_sub(ji,jj)
162
163         ! Mass flux at the ocean surface
164         !------------------------------------
165         ! ice-ocean  mass flux
166         wfx_ice(ji,jj) = wfx_bog(ji,jj) + wfx_bom(ji,jj) + wfx_sum(ji,jj) + wfx_sni(ji,jj)   &
167            &           + wfx_opw(ji,jj) + wfx_dyn(ji,jj) + wfx_res(ji,jj) + wfx_lam(ji,jj)
168
169         ! snw-ocean mass flux
170         wfx_snw(ji,jj) = wfx_snw_sni(ji,jj) + wfx_snw_dyn(ji,jj) + wfx_snw_sum(ji,jj)
171
172         ! total mass flux at the ocean/ice interface
173         fmmflx(ji,jj) =                - wfx_ice(ji,jj) - wfx_snw(ji,jj) - wfx_pnd(ji,jj) - wfx_err_sub(ji,jj)   ! ice-ocean mass flux saved at least for biogeochemical model
174         emp   (ji,jj) = emp_oce(ji,jj) - wfx_ice(ji,jj) - wfx_snw(ji,jj) - wfx_pnd(ji,jj) - wfx_err_sub(ji,jj)   ! atm-ocean + ice-ocean mass flux
175
176         ! Salt flux at the ocean surface
177         !------------------------------------------
178         sfx(ji,jj) = sfx_bog(ji,jj) + sfx_bom(ji,jj) + sfx_sum(ji,jj) + sfx_sni(ji,jj) + sfx_opw(ji,jj)   &
179            &       + sfx_res(ji,jj) + sfx_dyn(ji,jj) + sfx_bri(ji,jj) + sfx_sub(ji,jj) + sfx_lam(ji,jj)
180
181         ! Mass of snow and ice per unit area
182         !----------------------------------------
183         snwice_mass_b(ji,jj) = snwice_mass(ji,jj)       ! save mass from the previous ice time step
184         !                                               ! new mass per unit area
185         snwice_mass  (ji,jj) = tmask(ji,jj,1) * ( rhos * vt_s(ji,jj) + rhoi * vt_i(ji,jj) + rhow * (vt_ip(ji,jj) + vt_il(ji,jj)) )
186         !                                               ! time evolution of snow+ice mass
187         snwice_fmass (ji,jj) = ( snwice_mass(ji,jj) - snwice_mass_b(ji,jj) ) * r1_Dt_ice
188
189      END_2D
190
191      ! Storing the transmitted variables
192      !----------------------------------
193      fr_i  (:,:)   = at_i(:,:)             ! Sea-ice fraction
194      tn_ice(:,:,:) = t_su(:,:,:)           ! Ice surface temperature
195
196      ! Snow/ice albedo (only if sent to coupler, useless in forced mode)
197      !------------------------------------------------------------------
198      CALL ice_alb( t_su, h_i, h_s, ln_pnd_alb, a_ip_eff, h_ip, cloud_fra, alb_ice ) ! ice albedo
199
200      !
201      IF( lrst_ice ) THEN                       !* write snwice_mass fields in the restart file
202         CALL update_rst( 'WRITE', kt )
203      ENDIF
204      !
205      ! output all fluxes
206      !------------------
207      !
208      ! --- salt fluxes [kg/m2/s] --- !
209      !                           ! sfxice =  sfxbog + sfxbom + sfxsum + sfxsni + sfxopw + sfxres + sfxdyn + sfxbri + sfxsub + sfxlam
210      IF( iom_use('sfxice'  ) )   CALL iom_put( 'sfxice', sfx     * 1.e-03 )   ! salt flux from total ice growth/melt
211      IF( iom_use('sfxbog'  ) )   CALL iom_put( 'sfxbog', sfx_bog * 1.e-03 )   ! salt flux from bottom growth
212      IF( iom_use('sfxbom'  ) )   CALL iom_put( 'sfxbom', sfx_bom * 1.e-03 )   ! salt flux from bottom melting
213      IF( iom_use('sfxsum'  ) )   CALL iom_put( 'sfxsum', sfx_sum * 1.e-03 )   ! salt flux from surface melting
214      IF( iom_use('sfxlam'  ) )   CALL iom_put( 'sfxlam', sfx_lam * 1.e-03 )   ! salt flux from lateral melting
215      IF( iom_use('sfxsni'  ) )   CALL iom_put( 'sfxsni', sfx_sni * 1.e-03 )   ! salt flux from snow ice formation
216      IF( iom_use('sfxopw'  ) )   CALL iom_put( 'sfxopw', sfx_opw * 1.e-03 )   ! salt flux from open water formation
217      IF( iom_use('sfxdyn'  ) )   CALL iom_put( 'sfxdyn', sfx_dyn * 1.e-03 )   ! salt flux from ridging rafting
218      IF( iom_use('sfxbri'  ) )   CALL iom_put( 'sfxbri', sfx_bri * 1.e-03 )   ! salt flux from brines
219      IF( iom_use('sfxres'  ) )   CALL iom_put( 'sfxres', sfx_res * 1.e-03 )   ! salt flux from undiagnosed processes
220      IF( iom_use('sfxsub'  ) )   CALL iom_put( 'sfxsub', sfx_sub * 1.e-03 )   ! salt flux from sublimation
221
222      ! --- mass fluxes [kg/m2/s] --- !
223      CALL iom_put( 'emp_oce', emp_oce )   ! emp over ocean (taking into account the snow blown away from the ice)
224      CALL iom_put( 'emp_ice', emp_ice )   ! emp over ice   (taking into account the snow blown away from the ice)
225
226      !                           ! vfxice = vfxbog + vfxbom + vfxsum + vfxsni + vfxopw + vfxdyn + vfxres + vfxlam + vfxpnd
227      CALL iom_put( 'vfxice'    , wfx_ice     )   ! mass flux from total ice growth/melt
228      CALL iom_put( 'vfxbog'    , wfx_bog     )   ! mass flux from bottom growth
229      CALL iom_put( 'vfxbom'    , wfx_bom     )   ! mass flux from bottom melt
230      CALL iom_put( 'vfxsum'    , wfx_sum     )   ! mass flux from surface melt
231      CALL iom_put( 'vfxlam'    , wfx_lam     )   ! mass flux from lateral melt
232      CALL iom_put( 'vfxsni'    , wfx_sni     )   ! mass flux from snow-ice formation
233      CALL iom_put( 'vfxopw'    , wfx_opw     )   ! mass flux from growth in open water
234      CALL iom_put( 'vfxdyn'    , wfx_dyn     )   ! mass flux from dynamics (ridging)
235      CALL iom_put( 'vfxres'    , wfx_res     )   ! mass flux from undiagnosed processes
236      CALL iom_put( 'vfxpnd'    , wfx_pnd     )   ! mass flux from melt ponds
237      CALL iom_put( 'vfxsub'    , wfx_ice_sub )   ! mass flux from ice sublimation (ice-atm.)
238      CALL iom_put( 'vfxsub_err', wfx_err_sub )   ! "excess" of sublimation sent to ocean
239
240      IF ( iom_use( 'vfxthin' ) ) THEN   ! mass flux from ice growth in open water + thin ice (<20cm) => comparable to observations
241         ALLOCATE( z2d(jpi,jpj) )
242         WHERE( hm_i(:,:) < 0.2 .AND. hm_i(:,:) > 0. ) ; z2d = wfx_bog
243         ELSEWHERE                                     ; z2d = 0._wp
244         END WHERE
245         CALL iom_put( 'vfxthin', wfx_opw + z2d )
246         DEALLOCATE( z2d )
247      ENDIF
248
249      !                            ! vfxsnw = vfxsnw_sni + vfxsnw_dyn + vfxsnw_sum
250      CALL iom_put( 'vfxsnw'     , wfx_snw     )   ! mass flux from total snow growth/melt
251      CALL iom_put( 'vfxsnw_sum' , wfx_snw_sum )   ! mass flux from snow melt at the surface
252      CALL iom_put( 'vfxsnw_sni' , wfx_snw_sni )   ! mass flux from snow melt during snow-ice formation
253      CALL iom_put( 'vfxsnw_dyn' , wfx_snw_dyn )   ! mass flux from dynamics (ridging)
254      CALL iom_put( 'vfxsnw_sub' , wfx_snw_sub )   ! mass flux from snow sublimation (ice-atm.)
255      CALL iom_put( 'vfxsnw_pre' , wfx_spr     )   ! snow precip
256
257      ! --- heat fluxes [W/m2] --- !
258      !                              ! qt_atm_oi - qt_oce_ai = hfxdhc - ( dihctrp + dshctrp )
259      IF( iom_use('qsr_oce'    ) )   CALL iom_put( 'qsr_oce'    , qsr_oce * ( 1._wp - at_i_b )                               )   !     solar flux at ocean surface
260      IF( iom_use('qns_oce'    ) )   CALL iom_put( 'qns_oce'    , qns_oce * ( 1._wp - at_i_b ) + qemp_oce                    )   ! non-solar flux at ocean surface
261      IF( iom_use('qsr_ice'    ) )   CALL iom_put( 'qsr_ice'    , SUM( qsr_ice * a_i_b, dim=3 )                              )   !     solar flux at ice surface
262      IF( iom_use('qns_ice'    ) )   CALL iom_put( 'qns_ice'    , SUM( qns_ice * a_i_b, dim=3 ) + qemp_ice                   )   ! non-solar flux at ice surface
263      IF( iom_use('qtr_ice_bot') )   CALL iom_put( 'qtr_ice_bot', SUM( qtr_ice_bot * a_i_b, dim=3 )                          )   !     solar flux transmitted thru ice
264      IF( iom_use('qtr_ice_top') )   CALL iom_put( 'qtr_ice_top', SUM( qtr_ice_top * a_i_b, dim=3 )                          )   !     solar flux transmitted thru ice surface
265      IF( iom_use('qt_oce'     ) )   CALL iom_put( 'qt_oce'     ,      ( qsr_oce + qns_oce ) * ( 1._wp - at_i_b ) + qemp_oce )
266      IF( iom_use('qt_ice'     ) )   CALL iom_put( 'qt_ice'     , SUM( ( qns_ice + qsr_ice ) * a_i_b, dim=3 )     + qemp_ice )
267      IF( iom_use('qt_oce_ai'  ) )   CALL iom_put( 'qt_oce_ai'  , qt_oce_ai * tmask(:,:,1)                                   )   ! total heat flux at the ocean   surface: interface oce-(ice+atm)
268      IF( iom_use('qt_atm_oi'  ) )   CALL iom_put( 'qt_atm_oi'  , qt_atm_oi * tmask(:,:,1)                                   )   ! total heat flux at the oce-ice surface: interface atm-(ice+oce)
269      IF( iom_use('qemp_oce'   ) )   CALL iom_put( 'qemp_oce'   , qemp_oce                                                   )   ! Downward Heat Flux from E-P over ocean
270      IF( iom_use('qemp_ice'   ) )   CALL iom_put( 'qemp_ice'   , qemp_ice                                                   )   ! Downward Heat Flux from E-P over ice
271
272      ! heat fluxes from ice transformations
273      !                            ! hfxdhc = hfxbog + hfxbom + hfxsum + hfxopw + hfxdif + hfxsnw - ( hfxthd + hfxdyn + hfxres + hfxsub + hfxspr )
274      CALL iom_put ('hfxbog'     , hfx_bog     )   ! heat flux used for ice bottom growth
275      CALL iom_put ('hfxbom'     , hfx_bom     )   ! heat flux used for ice bottom melt
276      CALL iom_put ('hfxsum'     , hfx_sum     )   ! heat flux used for ice surface melt
277      CALL iom_put ('hfxopw'     , hfx_opw     )   ! heat flux used for ice formation in open water
278      CALL iom_put ('hfxdif'     , hfx_dif     )   ! heat flux used for ice temperature change
279      CALL iom_put ('hfxsnw'     , hfx_snw     )   ! heat flux used for snow melt
280      CALL iom_put ('hfxerr'     , hfx_err_dif )   ! heat flux error after heat diffusion
281
282      ! heat fluxes associated with mass exchange (freeze/melt/precip...)
283      CALL iom_put ('hfxthd'     , hfx_thd     )   !
284      CALL iom_put ('hfxdyn'     , hfx_dyn     )   !
285      CALL iom_put ('hfxres'     , hfx_res     )   !
286      CALL iom_put ('hfxsub'     , hfx_sub     )   !
287      CALL iom_put ('hfxspr'     , hfx_spr     )   ! Heat flux from snow precip heat content
288
289      ! other heat fluxes
290      IF( iom_use('hfxsensib'  ) )   CALL iom_put( 'hfxsensib'  ,      qsb_ice_bot * at_i_b         )   ! Sensible oceanic heat flux
291      IF( iom_use('hfxcndbot'  ) )   CALL iom_put( 'hfxcndbot'  , SUM( qcn_ice_bot * a_i_b, dim=3 ) )   ! Bottom conduction flux
292      IF( iom_use('hfxcndtop'  ) )   CALL iom_put( 'hfxcndtop'  , SUM( qcn_ice_top * a_i_b, dim=3 ) )   ! Surface conduction flux
293      IF( iom_use('hfxmelt'    ) )   CALL iom_put( 'hfxmelt'    , SUM( qml_ice     * a_i_b, dim=3 ) )   ! Surface melt flux
294      IF( iom_use('hfxldmelt'  ) )   CALL iom_put( 'hfxldmelt'  ,      fhld        * at_i_b         )   ! Heat in lead for ice melting
295      IF( iom_use('hfxldgrow'  ) )   CALL iom_put( 'hfxldgrow'  ,      qlead       * r1_Dt_ice      )   ! Heat in lead for ice growth
296
297      ! controls
298      !---------
299#if ! defined key_agrif
300      IF( ln_icediachk      )   CALL ice_cons_final('iceupdate')                                       ! conservation
301#endif
302      IF( ln_icectl         )   CALL ice_prt       (kt, iiceprt, jiceprt, 3, 'Final state ice_update') ! prints
303      IF( sn_cfctl%l_prtctl )   CALL ice_prt3D     ('iceupdate')                                       ! prints
304      IF( ln_timing         )   CALL timing_stop   ('iceupdate')                                       ! timing
305      !
306   END SUBROUTINE ice_update_flx
307
308
309   SUBROUTINE ice_update_tau( kt, pu_oce, pv_oce )
310      !!-------------------------------------------------------------------
311      !!                ***  ROUTINE ice_update_tau ***
312      !!
313      !! ** Purpose : Update the ocean surface stresses due to the ice
314      !!
315      !! ** Action  : * at each ice time step (every nn_fsbc time step):
316      !!                - compute the modulus of ice-ocean relative velocity
317      !!                  (*rho*Cd) at T-point (C-grid) or I-point (B-grid)
318      !!                      tmod_io = rhoco * | U_ice-U_oce |
319      !!                - update the modulus of stress at ocean surface
320      !!                      taum = (1-a) * taum + a * tmod_io * | U_ice-U_oce |
321      !!              * at each ocean time step (every kt):
322      !!                  compute linearized ice-ocean stresses as
323      !!                      Utau = tmod_io * | U_ice - pU_oce |
324      !!                using instantaneous current ocean velocity (usually before)
325      !!
326      !!    NB: - ice-ocean rotation angle no more allowed
327      !!        - here we make an approximation: taum is only computed every ice time step
328      !!          This avoids mutiple average to pass from T -> U,V grids and next from U,V grids
329      !!          to T grid. taum is used in TKE and GLS, which should not be too sensitive to this approximaton...
330      !!
331      !! ** Outputs : - utau, vtau   : surface ocean i- and j-stress (u- & v-pts) updated with ice-ocean fluxes
332      !!              - taum         : modulus of the surface ocean stress (T-point) updated with ice-ocean fluxes
333      !!---------------------------------------------------------------------
334      INTEGER ,                     INTENT(in) ::   kt               ! ocean time-step index
335      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   pu_oce, pv_oce   ! surface ocean currents
336      !
337      INTEGER  ::   ji, jj   ! dummy loop indices
338      REAL(wp) ::   zat_u, zutau_ice, zu_t, zmodt   ! local scalar
339      REAL(wp) ::   zat_v, zvtau_ice, zv_t, zrhoco  !   -      -
340      REAL(wp) ::   zflagi                          !   -      -
341      !!---------------------------------------------------------------------
342      IF( ln_timing )   CALL timing_start('ice_update')
343
344      IF( kt == nit000 .AND. lwp ) THEN
345         WRITE(numout,*)
346         WRITE(numout,*)'ice_update_tau: update stress at the ice-ocean interface'
347         WRITE(numout,*)'~~~~~~~~~~~~~~'
348      ENDIF
349
350      zrhoco = rho0 * rn_cio
351      !
352      IF( MOD( kt-1, nn_fsbc ) == 0 ) THEN     !==  Ice time-step only  ==!   (i.e. surface module time-step)
353         DO_2D( 0, 0, 0, 0 )                          !* update the modulus of stress at ocean surface (T-point)
354            !                                               ! 2*(U_ice-U_oce) at T-point
355            zu_t = u_ice(ji,jj) + u_ice(ji-1,jj) - u_oce(ji,jj) - u_oce(ji-1,jj)
356            zv_t = v_ice(ji,jj) + v_ice(ji,jj-1) - v_oce(ji,jj) - v_oce(ji,jj-1)
357            !                                              ! |U_ice-U_oce|^2
358            zmodt =  0.25_wp * (  zu_t * zu_t + zv_t * zv_t  )
359            !                                               ! update the ocean stress modulus
360            taum(ji,jj) = ( 1._wp - at_i(ji,jj) ) * taum(ji,jj) + at_i(ji,jj) * zrhoco * zmodt
361            tmod_io(ji,jj) = zrhoco * SQRT( zmodt )          ! rhoco * |U_ice-U_oce| at T-point
362         END_2D
363         CALL lbc_lnk( 'iceupdate', taum, 'T', 1.0_wp, tmod_io, 'T', 1.0_wp )
364         !
365         utau_oce(:,:) = utau(:,:)                    !* save the air-ocean stresses at ice time-step
366         vtau_oce(:,:) = vtau(:,:)
367         !
368      ENDIF
369      !
370      !                                      !==  every ocean time-step  ==!
371      IF ( ln_drgice_imp ) THEN
372         ! Save drag with right sign to update top drag in the ocean implicit friction
373         rCdU_ice(:,:) = -r1_rho0 * tmod_io(:,:) * at_i(:,:) * tmask(:,:,1)
374         zflagi = 0._wp
375      ELSE
376         zflagi = 1._wp
377      ENDIF
378      !
379      DO_2D( 0, 0, 0, 0 )                             !* update the stress WITHOUT an ice-ocean rotation angle
380         ! ice area at u and v-points
381         zat_u  = ( at_i(ji,jj) * tmask(ji,jj,1) + at_i (ji+1,jj    ) * tmask(ji+1,jj  ,1) )  &
382            &     / MAX( 1.0_wp , tmask(ji,jj,1) + tmask(ji+1,jj  ,1) )
383         zat_v  = ( at_i(ji,jj) * tmask(ji,jj,1) + at_i (ji  ,jj+1  ) * tmask(ji  ,jj+1,1) )  &
384            &     / MAX( 1.0_wp , tmask(ji,jj,1) + tmask(ji  ,jj+1,1) )
385         !                                                   ! linearized quadratic drag formulation
386         zutau_ice   = 0.5_wp * ( tmod_io(ji,jj) + tmod_io(ji+1,jj) ) * ( u_ice(ji,jj) - pu_oce(ji,jj) )
387         zvtau_ice   = 0.5_wp * ( tmod_io(ji,jj) + tmod_io(ji,jj+1) ) * ( v_ice(ji,jj) - pv_oce(ji,jj) )
388         !                                                   ! stresses at the ocean surface
389         utau(ji,jj) = ( 1._wp - zat_u ) * utau_oce(ji,jj) + zat_u * zutau_ice
390         vtau(ji,jj) = ( 1._wp - zat_v ) * vtau_oce(ji,jj) + zat_v * zvtau_ice
391      END_2D
392      CALL lbc_lnk( 'iceupdate', utau, 'U', -1.0_wp, vtau, 'V', -1.0_wp )   ! lateral boundary condition
393      !
394      IF( ln_timing )   CALL timing_stop('ice_update')
395      !
396   END SUBROUTINE ice_update_tau
397
398
399   SUBROUTINE ice_update_init
400      !!-------------------------------------------------------------------
401      !!                  ***  ROUTINE ice_update_init  ***
402      !!
403      !! ** Purpose :   allocate ice-ocean stress fields and read restarts
404      !!                containing the snow & ice mass
405      !!
406      !!-------------------------------------------------------------------
407      INTEGER  ::   ji, jj, jk               ! dummy loop indices
408      REAL(wp) ::   zcoefu, zcoefv, zcoeff   ! local scalar
409      !!-------------------------------------------------------------------
410      !
411      IF(lwp) WRITE(numout,*)
412      IF(lwp) WRITE(numout,*) 'ice_update_init: ice-ocean stress init'
413      IF(lwp) WRITE(numout,*) '~~~~~~~~~~~~~~~'
414      !
415      !                                      ! allocate ice_update array
416      IF( ice_update_alloc() /= 0 )   CALL ctl_stop( 'STOP', 'ice_update_init : unable to allocate standard arrays' )
417      !
418      CALL update_rst( 'READ' )  !* read or initialize all required files
419      !
420   END SUBROUTINE ice_update_init
421
422
423   SUBROUTINE update_rst( cdrw, kt )
424      !!---------------------------------------------------------------------
425      !!                   ***  ROUTINE rhg_evp_rst  ***
426      !!
427      !! ** Purpose :   Read or write RHG file in restart file
428      !!
429      !! ** Method  :   use of IOM library
430      !!----------------------------------------------------------------------
431      CHARACTER(len=*) , INTENT(in) ::   cdrw   ! 'READ'/'WRITE' flag
432      INTEGER, OPTIONAL, INTENT(in) ::   kt     ! ice time-step
433      !
434      INTEGER  ::   iter   ! local integer
435      INTEGER  ::   id1    ! local integer
436      !!----------------------------------------------------------------------
437      !
438      IF( TRIM(cdrw) == 'READ' ) THEN        ! Read/initialize
439         !                                   ! ---------------
440         IF( ln_rstart ) THEN                   !* Read the restart file
441            !
442            id1 = iom_varid( numrir, 'snwice_mass' , ldstop = .FALSE. )
443            !
444            IF( id1 > 0 ) THEN                       ! fields exist
445               CALL iom_get( numrir, jpdom_auto, 'snwice_mass'  , snwice_mass   )
446               CALL iom_get( numrir, jpdom_auto, 'snwice_mass_b', snwice_mass_b )
447            ELSE                                     ! start from rest
448               IF(lwp) WRITE(numout,*) '   ==>>   previous run without snow-ice mass output then set it'
449               snwice_mass  (:,:) = tmask(:,:,1) * ( rhos * vt_s(:,:) + rhoi * vt_i(:,:) )
450               snwice_mass_b(:,:) = snwice_mass(:,:)
451            ENDIF
452         ELSE                                   !* Start from rest
453            IF(lwp) WRITE(numout,*) '   ==>>   start from rest: set the snow-ice mass'
454            snwice_mass  (:,:) = tmask(:,:,1) * ( rhos * vt_s(:,:) + rhoi * vt_i(:,:) )
455            snwice_mass_b(:,:) = snwice_mass(:,:)
456         ENDIF
457         !
458      ELSEIF( TRIM(cdrw) == 'WRITE' ) THEN   ! Create restart file
459         !                                   ! -------------------
460         IF(lwp) WRITE(numout,*) '---- update-rst ----'
461         iter = kt + nn_fsbc - 1             ! ice restarts are written at kt == nitrst - nn_fsbc + 1
462         !
463         CALL iom_rstput( iter, nitrst, numriw, 'snwice_mass'  , snwice_mass   )
464         CALL iom_rstput( iter, nitrst, numriw, 'snwice_mass_b', snwice_mass_b )
465         !
466      ENDIF
467      !
468   END SUBROUTINE update_rst
469
470#else
471   !!----------------------------------------------------------------------
472   !!   Default option         Dummy module           NO SI3 sea-ice model
473   !!----------------------------------------------------------------------
474#endif
475
476   !!======================================================================
477END MODULE iceupdate
Note: See TracBrowser for help on using the repository browser.