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/branches/UKMO/NEMO_4.0.4_remade_heat_balance/src/ICE – NEMO

source: NEMO/branches/UKMO/NEMO_4.0.4_remade_heat_balance/src/ICE/iceupdate.F90 @ 14585

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