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.
icbthm.F90 in NEMO/branches/2020/tickets_2494_2375/src/OCE/ICB – NEMO

source: NEMO/branches/2020/tickets_2494_2375/src/OCE/ICB/icbthm.F90 @ 13265

Last change on this file since 13265 was 13265, checked in by mathiot, 4 years ago

ticket #2494 and #2375: ticket #2494 changes and part of ticket #2375 (lbc_icb_lnk on extended variable at T point removed), ff_e initialisation and lbc_lnk move in the icbini.F90; tests on possible useless lbc_lnk in icbclv not yet done

  • Property svn:keywords set to Id
File size: 13.4 KB
Line 
1MODULE icbthm
2   !!======================================================================
3   !!                       ***  MODULE  icbthm  ***
4   !! Icebergs:  thermodynamics routines for icebergs
5   !!======================================================================
6   !! History : 3.3.1 !  2010-01  (Martin&Adcroft) Original code
7   !!            -    !  2011-03  (Madec)          Part conversion to NEMO form
8   !!            -    !                            Removal of mapping from another grid
9   !!            -    !  2011-04  (Alderson)       Split into separate modules
10   !!            -    !  2011-05  (Alderson)       Use tmask instead of tmask_i
11   !!----------------------------------------------------------------------
12   !!----------------------------------------------------------------------
13   !!   icb_thm : initialise
14   !!             reference for equations - M = Martin + Adcroft, OM 34, 2010
15   !!----------------------------------------------------------------------
16   USE par_oce        ! NEMO parameters
17   USE dom_oce        ! NEMO domain
18   USE in_out_manager ! NEMO IO routines, numout in particular
19   USE lib_mpp        ! NEMO MPI routines, ctl_stop in particular
20   USE phycst         ! NEMO physical constants
21   USE sbc_oce
22   USE lib_fortran, ONLY : DDPDD
23
24   USE icb_oce        ! define iceberg arrays
25   USE icbutl         ! iceberg utility routines
26   USE icbdia         ! iceberg budget routines
27
28   IMPLICIT NONE
29   PRIVATE
30
31   PUBLIC   icb_thm ! routine called in icbstp.F90 module
32
33   !!----------------------------------------------------------------------
34   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
35   !! $Id$
36   !! Software governed by the CeCILL license (see ./LICENSE)
37   !!----------------------------------------------------------------------
38CONTAINS
39
40   SUBROUTINE icb_thm( kt )
41      !!----------------------------------------------------------------------
42      !!                  ***  ROUTINE icb_thm  ***
43      !!
44      !! ** Purpose :   compute the iceberg thermodynamics.
45      !!
46      !! ** Method  : - See Martin & Adcroft, Ocean Modelling 34, 2010
47      !!----------------------------------------------------------------------
48      INTEGER, INTENT(in) ::   kt   ! timestep number, just passed to icb_utl_print_berg
49      !
50      INTEGER  ::   ii, ij
51      REAL(wp) ::   zM, zT, zW, zL, zSST, zVol, zLn, zWn, zTn, znVol, zIC, zDn
52      REAL(wp) ::   zMv, zMe, zMb, zmelt, zdvo, zdva, zdM, zSs, zdMe, zdMb, zdMv
53      REAL(wp) ::   zMnew, zMnew1, zMnew2, zheat_hcflux, zheat_latent, z1_12
54      REAL(wp) ::   zMbits, znMbits, zdMbitsE, zdMbitsM, zLbits, zAbits, zMbb
55      REAL(wp) ::   zxi, zyj, zff, z1_rday, z1_e1e2, zdt, z1_dt, z1_dt_e1e2
56      TYPE(iceberg), POINTER ::   this, next
57      TYPE(point)  , POINTER ::   pt
58      !
59      COMPLEX(dp), DIMENSION(jpi,jpj) :: cicb_melt, cicb_hflx
60      !!----------------------------------------------------------------------
61      !
62      !! initialiaze cicb_melt and cicb_heat
63      cicb_melt = CMPLX( 0.e0, 0.e0, dp ) 
64      cicb_hflx = CMPLX( 0.e0, 0.e0, dp ) 
65      !
66      z1_rday = 1._wp / rday
67      z1_12   = 1._wp / 12._wp
68      zdt     = berg_dt
69      z1_dt   = 1._wp / zdt
70      !
71      ! we're either going to ignore berg fresh water melt flux and associated heat
72      ! or we pass it into the ocean, so at this point we set them both to zero,
73      ! accumulate the contributions to them from each iceberg in the while loop following
74      ! and then pass them (or not) to the ocean
75      !
76      berg_grid%floating_melt(:,:) = 0._wp
77      ! calving_hflx re-used here as temporary workspace for the heat flux associated with melting
78      berg_grid%calving_hflx(:,:)  = 0._wp
79      !
80      this => first_berg
81      DO WHILE( ASSOCIATED(this) )
82         !
83         pt => this%current_point
84         nknberg = this%number(1)
85         IF ( nn_sample_rate > 0 .AND. MOD(kt-1,nn_sample_rate) == 0 ) THEN
86            CALL icb_utl_interp( pt%xi, pt%yj, pe1=pt%e1, pe2=pt%e2,                 &
87               &                 puo=pt%uo, pui=pt%ui, pua=pt%ua, pssh_i=pt%ssh_x,   &
88               &                 pvo=pt%vo, pvi=pt%vi, pva=pt%va, pssh_j=pt%ssh_y,   &
89               &                 psst=pt%sst, pcn=pt%cn, phi=pt%hi,                  &
90               &                 plat=pt%lat, plon=pt%lon                            )
91         ELSE
92            CALL icb_utl_interp( pt%xi, pt%yj,           &   ! position
93               &                 puo=pt%uo, pua=pt%ua,   &   ! oce/atm velocities
94               &                 pvo=pt%vo, pva=pt%va,   &   ! oce/atm velocities
95               &                 psst=pt%sst, pcn=pt%cn )    ! sst and ice concentration
96               ! preparation Nacho add t3d and uo, vo, to basal
97         END IF
98         !
99         zSST = pt%sst
100         zIC  = MIN( 1._wp, pt%cn + rn_sicn_shift )     ! Shift sea-ice concentration       !!gm ???
101         zM   = pt%mass
102         zT   = pt%thickness                               ! total thickness
103       ! D   = (rn_rho_bergs/pp_rho_seawater)*zT ! draught (keel depth)
104       ! F   = zT - D ! freeboard
105         zW   = pt%width
106         zL   = pt%length
107         zxi  = pt%xi                                      ! position in (i,j) referential
108         zyj  = pt%yj
109         ii  = INT( zxi + 0.5 )                            ! T-cell of the berg
110         ii  = mi1( ii )
111         ij  = INT( zyj + 0.5 )             
112         ij  = mj1( ij )
113         zVol = zT * zW * zL
114
115         ! Environment
116         zdvo = SQRT( (pt%uvel-pt%uo)**2 + (pt%vvel-pt%vo)**2 )
117         zdva = SQRT( (pt%ua  -pt%uo)**2 + (pt%va  -pt%vo)**2 )
118         zSs  = 1.5_wp * SQRT( zdva ) + 0.1_wp * zdva                ! Sea state      (eqn M.A9)
119
120         ! Melt rates in m/s (i.e. division by rday)
121         zMv = MAX( 7.62d-3*zSST+1.29d-3*(zSST**2)                    , 0._wp ) * z1_rday   ! Buoyant convection at sides (eqn M.A10)
122         zMb = MAX( 0.58_wp*(zdvo**0.8_wp)*(zSST+4.0_wp)/(zL**0.2_wp) , 0._wp ) * z1_rday   ! Basal turbulent melting     (eqn M.A7 )
123         zMe = MAX( z1_12*(zSST+2.)*zSs*(1._wp+COS(rpi*(zIC**3)))     , 0._wp ) * z1_rday   ! Wave erosion                (eqn M.A8 )
124
125         IF( ln_operator_splitting ) THEN      ! Operator split update of volume/mass
126            zTn    = MAX( zT - zMb*zdt , 0._wp )         ! new total thickness (m)
127            znVol  = zTn * zW * zL                       ! new volume (m^3)
128            zMnew1 = ( znVol / zVol ) * zM               ! new mass (kg)
129            zdMb   = zM - zMnew1                         ! mass lost to basal melting (>0) (kg)
130            !
131            zLn    = MAX( zL - zMv*zdt , 0._wp )         ! new length (m)
132            zWn    = MAX( zW - zMv*zdt , 0._wp )         ! new width (m)
133            znVol  = zTn * zWn * zLn                     ! new volume (m^3)
134            zMnew2 = ( znVol / zVol ) * zM               ! new mass (kg)
135            zdMv   = zMnew1 - zMnew2                     ! mass lost to buoyant convection (>0) (kg)
136            !
137            zLn    = MAX( zLn - zMe*zdt , 0._wp )        ! new length (m)
138            zWn    = MAX( zWn - zMe*zdt , 0._wp )        ! new width (m)
139            znVol  = zTn * zWn * zLn                     ! new volume (m^3)
140            zMnew  = ( znVol / zVol ) * zM               ! new mass (kg)
141            zdMe   = zMnew2 - zMnew                      ! mass lost to erosion (>0) (kg)
142            zdM    = zM - zMnew                          ! mass lost to all erosion and melting (>0) (kg)
143            !
144         ELSE                                         ! Update dimensions of berg
145            zLn = MAX( zL -(zMv+zMe)*zdt ,0._wp )        ! (m)
146            zWn = MAX( zW -(zMv+zMe)*zdt ,0._wp )        ! (m)
147            zTn = MAX( zT - zMb    *zdt ,0._wp )         ! (m)
148            ! Update volume and mass of berg
149            znVol = zTn*zWn*zLn                          ! (m^3)
150            zMnew = (znVol/zVol)*zM                      ! (kg)
151            zdM   = zM - zMnew                           ! (kg)
152            zdMb = (zM/zVol) * (zW*   zL ) *zMb*zdt      ! approx. mass loss to basal melting (kg)
153            zdMe = (zM/zVol) * (zT*(zW+zL)) *zMe*zdt     ! approx. mass lost to erosion (kg)
154            zdMv = (zM/zVol) * (zT*(zW+zL)) *zMv*zdt     ! approx. mass loss to buoyant convection (kg)
155         ENDIF
156
157         IF( rn_bits_erosion_fraction > 0._wp ) THEN     ! Bergy bits
158            !
159            zMbits   = pt%mass_of_bits                                               ! mass of bergy bits (kg)
160            zdMbitsE = rn_bits_erosion_fraction * zdMe                               ! change in mass of bits (kg)
161            znMbits  = zMbits + zdMbitsE                                             ! add new bergy bits to mass (kg)
162            zLbits   = MIN( zL, zW, zT, 40._wp )                                     ! assume bergy bits are smallest dimension or 40 meters
163            zAbits   = ( zMbits / rn_rho_bergs ) / zLbits                            ! Effective bottom area (assuming T=Lbits)
164            zMbb     = MAX( 0.58_wp*(zdvo**0.8_wp)*(zSST+2._wp) /   &
165               &                              ( zLbits**0.2_wp ) , 0._wp ) * z1_rday ! Basal turbulent melting (for bits)
166            zMbb     = rn_rho_bergs * zAbits * zMbb                                  ! in kg/s
167            zdMbitsM = MIN( zMbb*zdt , znMbits )                                     ! bergy bits mass lost to melting (kg)
168            znMbits  = znMbits-zdMbitsM                                              ! remove mass lost to bergy bits melt
169            IF( zMnew == 0._wp ) THEN                                                ! if parent berg has completely melted then
170               zdMbitsM = zdMbitsM + znMbits                                         ! instantly melt all the bergy bits
171               znMbits  = 0._wp
172            ENDIF
173         ELSE                                                     ! No bergy bits
174            zAbits   = 0._wp
175            zdMbitsE = 0._wp
176            zdMbitsM = 0._wp
177            znMbits  = pt%mass_of_bits                             ! retain previous value incase non-zero
178         ENDIF
179
180         ! use tmask rather than tmask_i when dealing with icebergs
181         IF( tmask(ii,ij,1) /= 0._wp ) THEN    ! Add melting to the grid and field diagnostics
182            z1_e1e2    = r1_e1e2t(ii,ij) * this%mass_scaling
183            z1_dt_e1e2 = z1_dt * z1_e1e2
184            !
185            ! iceberg melt
186            !! the use of DDPDD function for the cumulative sum is needed for reproducibility
187            zmelt    = ( zdM - ( zdMbitsE - zdMbitsM ) ) * z1_dt   ! kg/s
188            CALL DDPDD( CMPLX( zmelt * z1_e1e2, 0.e0, dp ), cicb_melt(ii,ij) )
189            !
190            ! iceberg heat flux
191            !! the use of DDPDD function for the cumulative sum is needed for reproducibility
192            !! NB. The src_calving_hflx field is currently hardwired to zero in icb_stp, which means that the
193            !!     heat density of the icebergs is zero and the heat content flux to the ocean from iceberg
194            !!     melting is always zero. Leaving the term in the code until such a time as this is fixed. DS.
195            zheat_hcflux = zmelt * pt%heat_density       ! heat content flux : kg/s x J/kg = J/s
196            zheat_latent = - zmelt * rLfus               ! latent heat flux:  kg/s x J/kg = J/s
197            CALL DDPDD( CMPLX( ( zheat_hcflux + zheat_latent ) * z1_e1e2, 0.e0, dp ), cicb_hflx(ii,ij) )
198            !
199            ! diagnostics
200            CALL icb_dia_melt( ii, ij, zMnew, zheat_hcflux, zheat_latent, this%mass_scaling,       &
201               &                       zdM, zdMbitsE, zdMbitsM, zdMb, zdMe,   &
202               &                       zdMv, z1_dt_e1e2 )
203         ELSE
204            WRITE(numout,*) 'icb_thm: berg ',this%number(:),' appears to have grounded  at ',narea,ii,ij
205            CALL icb_utl_print_berg( this, kt )
206            WRITE(numout,*) 'msk=',tmask(ii,ij,1), e1e2t(ii,ij)
207            CALL ctl_stop('icb_thm', 'berg appears to have grounded!')
208         ENDIF
209
210         ! Rolling
211         zDn = ( rn_rho_bergs / pp_rho_seawater ) * zTn       ! draught (keel depth)
212         IF( zDn > 0._wp .AND. MAX(zWn,zLn) < SQRT( 0.92*(zDn**2) + 58.32*zDn ) ) THEN
213            zT  = zTn
214            zTn = zWn
215            zWn = zT
216         ENDIF
217
218         ! Store the new state of iceberg (with L>W)
219         pt%mass         = zMnew
220         pt%mass_of_bits = znMbits
221         pt%thickness    = zTn
222         pt%width        = MIN( zWn , zLn )
223         pt%length       = MAX( zWn , zLn )
224
225         next=>this%next
226
227!!gm  add a test to avoid over melting ?
228
229         IF( zMnew <= 0._wp ) THEN       ! Delete the berg if completely melted
230            CALL icb_utl_delete( first_berg, this )
231            !
232         ELSE                            ! Diagnose mass distribution on grid
233            z1_e1e2 = r1_e1e2t(ii,ij) * this%mass_scaling
234            CALL icb_dia_size( ii, ij, zWn, zLn, zAbits,   &
235               &               this%mass_scaling, zMnew, znMbits, z1_e1e2 )
236         ENDIF
237         !
238         this=>next
239         !
240      END DO
241      !
242      berg_grid%floating_melt = REAL(cicb_melt,dp)    ! kg/m2/s
243      berg_grid%calving_hflx  = REAL(cicb_hflx,dp)
244      !
245      ! now use melt and associated heat flux in ocean (or not)
246      !
247      IF(.NOT. ln_passive_mode ) THEN
248         emp (:,:) = emp (:,:) - berg_grid%floating_melt(:,:)
249         qns (:,:) = qns (:,:) + berg_grid%calving_hflx (:,:) 
250      ENDIF
251      !
252   END SUBROUTINE icb_thm
253
254   !!======================================================================
255END MODULE icbthm
Note: See TracBrowser for help on using the repository browser.