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 branches/2015/dev_r5803_NOC_WAD/NEMOGCM/NEMO/OPA_SRC/ICB – NEMO

source: branches/2015/dev_r5803_NOC_WAD/NEMOGCM/NEMO/OPA_SRC/ICB/icbthm.F90 @ 5870

Last change on this file since 5870 was 5870, checked in by acc, 8 years ago

Branch 2015/dev_r5803_NOC_WAD. Merge in trunk changes from 5803 to 5869 in preparation for merge. Also tidied and reorganised some wetting and drying code. Renamed wadlmt.F90 to wetdry.F90. Wetting drying code changes restricted to domzgr.F90, domvvl.F90 nemogcm.F90 sshwzv.F90, dynspg_ts.F90, wetdry.F90 and dynhpg.F90. Code passes full SETTE tests with ln_wd=.false.. Still awaiting test case for checking with ln_wd=.false.

  • Property svn:keywords set to Id
File size: 11.1 KB
Line 
1MODULE icbthm
2
3   !!======================================================================
4   !!                       ***  MODULE  icbthm  ***
5   !! Icebergs:  thermodynamics routines for icebergs
6   !!======================================================================
7   !! History : 3.3.1 !  2010-01  (Martin&Adcroft) Original code
8   !!            -    !  2011-03  (Madec)          Part conversion to NEMO form
9   !!            -    !                            Removal of mapping from another grid
10   !!            -    !  2011-04  (Alderson)       Split into separate modules
11   !!            -    !  2011-05  (Alderson)       Use tmask instead of tmask_i
12   !!----------------------------------------------------------------------
13   !!----------------------------------------------------------------------
14   !!   icb_thm : initialise
15   !!             reference for equations - M = Martin + Adcroft, OM 34, 2010
16   !!----------------------------------------------------------------------
17   USE par_oce        ! NEMO parameters
18   USE dom_oce        ! NEMO domain
19   USE in_out_manager ! NEMO IO routines, numout in particular
20   USE lib_mpp        ! NEMO MPI routines, ctl_stop in particular
21   USE phycst         ! NEMO physical constants
22   USE sbc_oce
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   !! $Id$
34CONTAINS
35
36   SUBROUTINE icb_thm( kt )
37      !!----------------------------------------------------------------------
38      !!                  ***  ROUTINE icb_thm  ***
39      !!
40      !! ** Purpose :   compute the iceberg thermodynamics.
41      !!
42      !! ** Method  : - See Martin & Adcroft, Ocean Modelling 34, 2010
43      !!----------------------------------------------------------------------
44      INTEGER, INTENT(in) ::   kt   ! timestep number, just passed to icb_utl_print_berg
45      !
46      INTEGER  ::   ii, ij
47      REAL(wp) ::   zM, zT, zW, zL, zSST, zVol, zLn, zWn, zTn, znVol, zIC, zDn
48      REAL(wp) ::   zMv, zMe, zMb, zmelt, zdvo, zdva, zdM, zSs, zdMe, zdMb, zdMv
49      REAL(wp) ::   zMnew, zMnew1, zMnew2, zheat
50      REAL(wp) ::   zMbits, znMbits, zdMbitsE, zdMbitsM, zLbits, zAbits, zMbb
51      REAL(wp) ::   zxi, zyj, zff, z1_rday, z1_e1e2, zdt, z1_dt, z1_dt_e1e2
52      TYPE(iceberg), POINTER ::   this, next
53      TYPE(point)  , POINTER ::   pt
54      !!----------------------------------------------------------------------
55      !
56      z1_rday = 1._wp / rday
57     
58      ! we're either going to ignore berg fresh water melt flux and associated heat
59      ! or we pass it into the ocean, so at this point we set them both to zero,
60      ! accumulate the contributions to them from each iceberg in the while loop following
61      ! and then pass them (or not) to the ocean
62      !
63      berg_grid%floating_melt(:,:) = 0._wp
64      berg_grid%calving_hflx(:,:)  = 0._wp
65   
66      this => first_berg
67      DO WHILE( associated(this) )
68         !
69         pt => this%current_point
70         nknberg = this%number(1)
71         CALL icb_utl_interp( pt%xi, pt%e1, pt%uo, pt%ui, pt%ua, pt%ssh_x, &
72         &                    pt%yj, pt%e2, pt%vo, pt%vi, pt%va, pt%ssh_y, &
73         &                 pt%sst, pt%cn, pt%hi, zff )
74         !
75         zSST = pt%sst
76         zIC  = MIN( 1._wp, pt%cn + rn_sicn_shift )     ! Shift sea-ice concentration       !!gm ???
77         zM   = pt%mass
78         zT   = pt%thickness                               ! total thickness
79       ! D   = (rn_rho_bergs/pp_rho_seawater)*zT ! draught (keel depth)
80       ! F   = zT - D ! freeboard
81         zW   = pt%width
82         zL   = pt%length
83         zxi  = pt%xi                                      ! position in (i,j) referential
84         zyj  = pt%yj
85         ii  = INT( zxi + 0.5 )                            ! T-cell of the berg
86         ii  = mi1( ii )
87         ij  = INT( zyj + 0.5 )             
88         ij  = mj1( ij )
89         zVol = zT * zW * zL
90         zdt = berg_dt   ;   z1_dt = 1._wp / zdt
91
92         ! Environment
93         zdvo = SQRT( (pt%uvel-pt%uo)**2 + (pt%vvel-pt%vo)**2 )
94         zdva = SQRT( (pt%ua  -pt%uo)**2 + (pt%va  -pt%vo)**2 )
95         zSs  = 1.5 * SQRT( zdva ) + 0.1 * zdva                ! Sea state      (eqn M.A9)
96
97         ! Melt rates in m/s (i.e. division by rday)
98         zMv = MAX( 7.62e-3*zSST+1.29e-3*(zSST**2)            , 0._wp ) * z1_rday   ! Buoyant convection at sides (eqn M.A10)
99         zMb = MAX( 0.58*(zdvo**0.8)*(zSST+4.0)/(zL**0.2)      , 0._wp ) * z1_rday   ! Basal turbulent melting     (eqn M.A7 )
100         zMe = MAX( 1./12.*(zSST+2.)*zSs*(1+cos(rpi*(zIC**3))) , 0._wp ) * z1_rday   ! Wave erosion                (eqn M.A8 )
101
102         IF( ln_operator_splitting ) THEN      ! Operator split update of volume/mass
103            zTn    = MAX( zT - zMb*zdt , 0._wp )         ! new total thickness (m)
104            znVol  = zTn * zW * zL                        ! new volume (m^3)
105            zMnew1 = (znVol/zVol) * zM                    ! new mass (kg)
106            zdMb   = zM - zMnew1                         ! mass lost to basal melting (>0) (kg)
107            !
108            zLn    = MAX( zL - zMv*zdt , 0._wp )         ! new length (m)
109            zWn    = MAX( zW - zMv*zdt , 0._wp )         ! new width (m)
110            znVol  = zTn * zWn * zLn                      ! new volume (m^3)
111            zMnew2 = (znVol/zVol) * zM                    ! new mass (kg)
112            zdMv   = zMnew1 - zMnew2                     ! mass lost to buoyant convection (>0) (kg)
113            !
114            zLn    = MAX( zLn - zMe*zdt , 0._wp )        ! new length (m)
115            zWn    = MAX( zWn - zMe*zdt , 0._wp )        ! new width (m)
116            znVol  = zTn * zWn * zLn                      ! new volume (m^3)
117            zMnew  = ( znVol / zVol ) * zM                ! new mass (kg)
118            zdMe   = zMnew2 - zMnew                      ! mass lost to erosion (>0) (kg)
119            zdM    = zM - zMnew                          ! mass lost to all erosion and melting (>0) (kg)
120            !
121         ELSE                                         ! Update dimensions of berg
122            zLn = MAX( zL -(zMv+zMe)*zdt ,0._wp )         ! (m)
123            zWn = MAX( zW -(zMv+zMe)*zdt ,0._wp )         ! (m)
124            zTn = MAX( zT - zMb    *zdt ,0._wp )         ! (m)
125            ! Update volume and mass of berg
126            znVol = zTn*zWn*zLn                           ! (m^3)
127            zMnew = (znVol/zVol)*zM                       ! (kg)
128            zdM   = zM - zMnew                           ! (kg)
129            zdMb = (zM/zVol) * (zW*   zL ) *zMb*zdt         ! approx. mass loss to basal melting (kg)
130            zdMe = (zM/zVol) * (zT*(zW+zL)) *zMe*zdt         ! approx. mass lost to erosion (kg)
131            zdMv = (zM/zVol) * (zT*(zW+zL)) *zMv*zdt         ! approx. mass loss to buoyant convection (kg)
132         ENDIF
133
134         IF( rn_bits_erosion_fraction > 0._wp ) THEN      ! Bergy bits
135            !
136            zMbits   = pt%mass_of_bits                                               ! mass of bergy bits (kg)
137            zdMbitsE = rn_bits_erosion_fraction * zdMe                        ! change in mass of bits (kg)
138            znMbits  = zMbits + zdMbitsE                                               ! add new bergy bits to mass (kg)
139            zLbits   = MIN( zL, zW, zT, 40._wp )                                        ! assume bergy bits are smallest dimension or 40 meters
140            zAbits   = ( zMbits / rn_rho_bergs ) / zLbits                           ! Effective bottom area (assuming T=Lbits)
141            zMbb     = MAX( 0.58*(zdvo**0.8)*(zSST+2.0)/(zLbits**0.2), 0.) * z1_rday    ! Basal turbulent melting (for bits)
142            zMbb     = rn_rho_bergs * zAbits * zMbb                                 ! in kg/s
143            zdMbitsM = MIN( zMbb*zdt , znMbits )                                       ! bergy bits mass lost to melting (kg)
144            znMbits  = znMbits-zdMbitsM                                                ! remove mass lost to bergy bits melt
145            IF( zMnew == 0._wp ) THEN                                                ! if parent berg has completely melted then
146               zdMbitsM = zdMbitsM + znMbits                                           ! instantly melt all the bergy bits
147               znMbits  = 0._wp
148            ENDIF
149         ELSE                                                     ! No bergy bits
150            zAbits   = 0._wp
151            zdMbitsE = 0._wp
152            zdMbitsM = 0._wp
153            znMbits  = pt%mass_of_bits                             ! retain previous value incase non-zero
154         ENDIF
155
156         ! use tmask rather than tmask_i when dealing with icebergs
157         IF( tmask(ii,ij,1) /= 0._wp ) THEN    ! Add melting to the grid and field diagnostics
158            z1_e1e2    = r1_e1e2t(ii,ij) * this%mass_scaling
159            z1_dt_e1e2 = z1_dt * z1_e1e2
160            zmelt    = ( zdM - ( zdMbitsE - zdMbitsM ) ) * z1_dt   ! kg/s
161            berg_grid%floating_melt(ii,ij) = berg_grid%floating_melt(ii,ij) + zmelt    * z1_e1e2    ! kg/m2/s
162            zheat = zmelt * pt%heat_density              ! kg/s x J/kg = J/s
163            berg_grid%calving_hflx (ii,ij) = berg_grid%calving_hflx (ii,ij) + zheat    * z1_e1e2    ! W/m2
164            CALL icb_dia_melt( ii, ij, zMnew, zheat, this%mass_scaling,       &
165            &                          zdM, zdMbitsE, zdMbitsM, zdMb, zdMe,   &
166            &                          zdMv, z1_dt_e1e2 )
167         ELSE
168            WRITE(numout,*) 'icb_thm: berg ',this%number(:),' appears to have grounded  at ',narea,ii,ij
169            CALL icb_utl_print_berg( this, kt )
170            WRITE(numout,*) 'msk=',tmask(ii,ij,1), e1e2t(ii,ij)
171            CALL ctl_stop('icb_thm', 'berg appears to have grounded!')
172         ENDIF
173
174         ! Rolling
175         zDn = ( rn_rho_bergs / pp_rho_seawater ) * zTn       ! draught (keel depth)
176         IF( zDn > 0._wp .AND. MAX(zWn,zLn) < SQRT( 0.92*(zDn**2) + 58.32*zDn ) ) THEN
177            zT  = zTn
178            zTn = zWn
179            zWn = zT
180         endif
181
182         ! Store the new state of iceberg (with L>W)
183         pt%mass         = zMnew
184         pt%mass_of_bits = znMbits
185         pt%thickness    = zTn
186         pt%width        = min(zWn,zLn)
187         pt%length       = max(zWn,zLn)
188
189         next=>this%next
190
191!!gm  add a test to avoid over melting ?
192
193         IF( zMnew <= 0._wp ) THEN       ! Delete the berg if completely melted
194            CALL icb_utl_delete( first_berg, this )
195            !
196         ELSE                            ! Diagnose mass distribution on grid
197            z1_e1e2 = r1_e1e2t(ii,ij) * this%mass_scaling
198            CALL icb_dia_size( ii, ij, zWn, zLn, zAbits,   &
199            &                  this%mass_scaling, zMnew, znMbits, z1_e1e2)
200         ENDIF
201         !
202         this=>next
203         !
204      END DO
205     
206      ! now use melt and associated heat flux in ocean (or not)
207      !
208      IF(.NOT. ln_passive_mode ) THEN
209         emp (:,:) = emp (:,:) - berg_grid%floating_melt(:,:)
210!!       qns (:,:) = qns (:,:) + berg_grid%calving_hflx (:,:)  !!gm heat flux not yet properly coded ==>> need it, SOLVE that!
211      ENDIF
212      !
213   END SUBROUTINE icb_thm
214
215   !!======================================================================
216END MODULE icbthm
Note: See TracBrowser for help on using the repository browser.