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.
limitd_th.F90 in branches/UKMO/restart_datestamp/NEMOGCM/NEMO/LIM_SRC_3 – NEMO

source: branches/UKMO/restart_datestamp/NEMOGCM/NEMO/LIM_SRC_3/limitd_th.F90 @ 5462

Last change on this file since 5462 was 5462, checked in by davestorkey, 9 years ago

Update UKMO/restart_datestamp branch to revision 5442 of trunk. Also clear the SVN keywords again - necessary after the update step.

File size: 35.3 KB
Line 
1MODULE limitd_th
2   !!======================================================================
3   !!                       ***  MODULE limitd_th ***
4   !!   LIM3 ice model : ice thickness distribution: Thermodynamics
5   !!======================================================================
6   !! History :   -   !          (W. H. Lipscomb and E.C. Hunke) CICE (c) original code
7   !!            3.0  ! 2005-12  (M. Vancoppenolle) adaptation to LIM-3
8   !!             -   ! 2006-06  (M. Vancoppenolle) adaptation to include salt, age
9   !!             -   ! 2007-04  (M. Vancoppenolle) Mass conservation checked
10   !!----------------------------------------------------------------------
11#if defined key_lim3
12   !!----------------------------------------------------------------------
13   !!   'key_lim3' :                                   LIM3 sea-ice model
14   !!----------------------------------------------------------------------
15   !!   lim_itd_th_rem   :
16   !!   lim_itd_th_reb   :
17   !!   lim_itd_fitline  :
18   !!   lim_itd_shiftice :
19   !!----------------------------------------------------------------------
20   USE dom_ice          ! LIM-3 domain
21   USE par_oce          ! ocean parameters
22   USE dom_oce          ! ocean domain
23   USE phycst           ! physical constants (ocean directory)
24   USE thd_ice          ! LIM-3 thermodynamic variables
25   USE ice              ! LIM-3 variables
26   USE limvar           ! LIM-3 variables
27   USE prtctl           ! Print control
28   USE in_out_manager   ! I/O manager
29   USE lib_mpp          ! MPP library
30   USE wrk_nemo         ! work arrays
31   USE lib_fortran      ! to use key_nosignedzero
32   USE limcons          ! conservation tests
33
34   IMPLICIT NONE
35   PRIVATE
36
37   PUBLIC   lim_itd_th_rem
38   PUBLIC   lim_itd_th_reb
39
40   !!----------------------------------------------------------------------
41   !! NEMO/LIM3 4.0 , UCL - NEMO Consortium (2010)
42   !! $Id$
43   !! Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
44   !!----------------------------------------------------------------------
45CONTAINS
46
47   SUBROUTINE lim_itd_th_rem( klbnd, kubnd, kt )
48      !!------------------------------------------------------------------
49      !!                ***  ROUTINE lim_itd_th_rem ***
50      !!
51      !! ** Purpose :   computes the redistribution of ice thickness
52      !!              after thermodynamic growth of ice thickness
53      !!
54      !! ** Method  : Linear remapping
55      !!
56      !! References : W.H. Lipscomb, JGR 2001
57      !!------------------------------------------------------------------
58      INTEGER , INTENT (in) ::   klbnd   ! Start thickness category index point
59      INTEGER , INTENT (in) ::   kubnd   ! End point on which the  the computation is applied
60      INTEGER , INTENT (in) ::   kt      ! Ocean time step
61      !
62      INTEGER  ::   ji, jj, jl     ! dummy loop index
63      INTEGER  ::   ii, ij         ! 2D corresponding indices to ji
64      INTEGER  ::   nd             ! local integer
65      REAL(wp) ::   zx1, zwk1, zdh0, zetamin, zdamax   ! local scalars
66      REAL(wp) ::   zx2, zwk2, zda0, zetamax           !   -      -
67      REAL(wp) ::   zx3       
68      CHARACTER (len = 15) :: fieldid
69
70      INTEGER , POINTER, DIMENSION(:,:,:) ::   zdonor   ! donor category index
71
72      REAL(wp), POINTER, DIMENSION(:,:,:) ::   zdhice      ! ice thickness increment
73      REAL(wp), POINTER, DIMENSION(:,:,:) ::   g0          ! coefficients for fitting the line of the ITD
74      REAL(wp), POINTER, DIMENSION(:,:,:) ::   g1          ! coefficients for fitting the line of the ITD
75      REAL(wp), POINTER, DIMENSION(:,:,:) ::   hL          ! left boundary for the ITD for each thickness
76      REAL(wp), POINTER, DIMENSION(:,:,:) ::   hR          ! left boundary for the ITD for each thickness
77      REAL(wp), POINTER, DIMENSION(:,:,:) ::   zht_i_b     ! old ice thickness
78      REAL(wp), POINTER, DIMENSION(:,:,:) ::   dummy_es
79      REAL(wp), POINTER, DIMENSION(:,:,:) ::   zdaice, zdvice          ! local increment of ice area and volume
80      REAL(wp), POINTER, DIMENSION(:)     ::   zvetamin, zvetamax      ! maximum values for etas
81      INTEGER , POINTER, DIMENSION(:)     ::   nind_i, nind_j          ! compressed indices for i/j directions
82      INTEGER                             ::   nbrem                   ! number of cells with ice to transfer
83      REAL(wp)                            ::   zslope                  ! used to compute local thermodynamic "speeds"
84      REAL(wp), POINTER, DIMENSION(:,:)   ::   zhb0, zhb1              ! category boundaries for thinnes categories
85      REAL(wp), POINTER, DIMENSION(:,:)   ::   vt_i_init, vt_i_final   !  ice volume summed over categories
86      REAL(wp), POINTER, DIMENSION(:,:)   ::   vt_s_init, vt_s_final   !  snow volume summed over categories
87      REAL(wp), POINTER, DIMENSION(:,:)   ::   et_i_init, et_i_final   !  ice energy summed over categories
88      REAL(wp), POINTER, DIMENSION(:,:)   ::   et_s_init, et_s_final   !  snow energy summed over categories
89      INTEGER , POINTER, DIMENSION(:,:)   ::   zremap_flag      ! compute remapping or not ????
90      REAL(wp), POINTER, DIMENSION(:,:,:) ::   zhbnew           ! new boundaries of ice categories
91      !!------------------------------------------------------------------
92
93      CALL wrk_alloc( jpi,jpj, zremap_flag )
94      CALL wrk_alloc( jpi,jpj,jpl-1, zdonor )
95      CALL wrk_alloc( jpi,jpj,jpl, zdhice, g0, g1, hL, hR, zht_i_b, dummy_es )
96      CALL wrk_alloc( jpi,jpj,jpl-1, zdaice, zdvice )   
97      CALL wrk_alloc( jpi,jpj,jpl+1, zhbnew, kkstart = 0 )   
98      CALL wrk_alloc( (jpi+1)*(jpj+1), zvetamin, zvetamax )   
99      CALL wrk_alloc( (jpi+1)*(jpj+1), nind_i, nind_j ) 
100      CALL wrk_alloc( jpi,jpj, zhb0,zhb1,vt_i_init,vt_i_final,vt_s_init,vt_s_final,et_i_init,et_i_final,et_s_init,et_s_final )
101
102      !!----------------------------------------------------------------------------------------------
103      !! 0) Conservation checkand changes in each ice category
104      !!----------------------------------------------------------------------------------------------
105      IF( con_i ) THEN
106         CALL lim_column_sum (jpl,   v_i, vt_i_init)
107         CALL lim_column_sum (jpl,   v_s, vt_s_init)
108         CALL lim_column_sum_energy (jpl, nlay_i,   e_i, et_i_init)
109         dummy_es(:,:,:) = e_s(:,:,1,:)
110         CALL lim_column_sum (jpl, dummy_es(:,:,:) , et_s_init)
111      ENDIF
112
113      !!----------------------------------------------------------------------------------------------
114      !! 1) Compute thickness and changes in each ice category
115      !!----------------------------------------------------------------------------------------------
116      IF( kt == nit000 .AND. lwp) THEN
117         WRITE(numout,*)
118         WRITE(numout,*) 'lim_itd_th_rem  : Remapping the ice thickness distribution'
119         WRITE(numout,*) '~~~~~~~~~~~~~~~'
120         WRITE(numout,*) ' klbnd :       ', klbnd
121         WRITE(numout,*) ' kubnd :       ', kubnd
122      ENDIF
123
124      zdhice(:,:,:) = 0._wp
125      DO jl = klbnd, kubnd
126         DO jj = 1, jpj
127            DO ji = 1, jpi
128               rswitch           = MAX( 0.0, SIGN( 1.0, a_i(ji,jj,jl) - epsi10 ) )     !0 if no ice and 1 if yes
129               ht_i(ji,jj,jl)    = v_i(ji,jj,jl) / MAX( a_i(ji,jj,jl), epsi10 ) * rswitch
130               rswitch           = MAX( 0.0, SIGN( 1.0, a_i_b(ji,jj,jl) - epsi10) )
131               zht_i_b(ji,jj,jl) = v_i_b(ji,jj,jl) / MAX( a_i_b(ji,jj,jl), epsi10 ) * rswitch
132               IF( a_i(ji,jj,jl) > epsi10 )   zdhice(ji,jj,jl) = ht_i(ji,jj,jl) - zht_i_b(ji,jj,jl) ! clem: useless IF statement?
133            END DO
134         END DO
135      END DO
136
137      !-----------------------------------------------------------------------------------------------
138      !  2) Compute fractional ice area in each grid cell
139      !-----------------------------------------------------------------------------------------------
140      at_i(:,:) = 0._wp
141      DO jl = klbnd, kubnd
142         at_i(:,:) = at_i(:,:) + a_i(:,:,jl)
143      END DO
144
145      !-----------------------------------------------------------------------------------------------
146      !  3) Identify grid cells with ice
147      !-----------------------------------------------------------------------------------------------
148      nbrem = 0
149      DO jj = 1, jpj
150         DO ji = 1, jpi
151            IF ( at_i(ji,jj) > epsi10 ) THEN
152               nbrem         = nbrem + 1
153               nind_i(nbrem) = ji
154               nind_j(nbrem) = jj
155               zremap_flag(ji,jj) = 1
156            ELSE
157               zremap_flag(ji,jj) = 0
158            ENDIF
159         END DO
160      END DO
161
162      !-----------------------------------------------------------------------------------------------
163      !  4) Compute new category boundaries
164      !-----------------------------------------------------------------------------------------------
165      !- 4.1 Compute category boundaries
166      zhbnew(:,:,:) = 0._wp
167
168      DO jl = klbnd, kubnd - 1
169         DO ji = 1, nbrem
170            ii = nind_i(ji)
171            ij = nind_j(ji)
172            !
173            zhbnew(ii,ij,jl) = hi_max(jl)
174            IF    ( a_i_b(ii,ij,jl) > epsi10 .AND. a_i_b(ii,ij,jl+1) > epsi10 ) THEN
175               !interpolate between adjacent category growth rates
176               zslope           = ( zdhice(ii,ij,jl+1) - zdhice(ii,ij,jl) ) / ( zht_i_b(ii,ij,jl+1) - zht_i_b(ii,ij,jl) )
177               zhbnew(ii,ij,jl) = hi_max(jl) + zdhice(ii,ij,jl) + zslope * ( hi_max(jl) - zht_i_b(ii,ij,jl) )
178            ELSEIF( a_i_b(ii,ij,jl) > epsi10) THEN
179               zhbnew(ii,ij,jl) = hi_max(jl) + zdhice(ii,ij,jl)
180            ELSEIF( a_i_b(ii,ij,jl+1) > epsi10) THEN
181               zhbnew(ii,ij,jl) = hi_max(jl) + zdhice(ii,ij,jl+1)
182            ENDIF
183         END DO
184
185         !- 4.2 Check that each zhbnew lies between adjacent values of ice thickness
186         DO ji = 1, nbrem
187            ii = nind_i(ji)
188            ij = nind_j(ji)
189
190            ! clem: we do not want ht_i to be too close to either HR or HL otherwise a division by nearly 0 is possible
191            ! in lim_itd_fitline in the case (HR-HL) = 3(Hice - HL) or = 3(HR - Hice)
192            IF    ( a_i(ii,ij,jl  ) > epsi10 .AND. ht_i(ii,ij,jl  ) > ( zhbnew(ii,ij,jl) - epsi10 ) ) THEN
193               zremap_flag(ii,ij) = 0
194            ELSEIF( a_i(ii,ij,jl+1) > epsi10 .AND. ht_i(ii,ij,jl+1) < ( zhbnew(ii,ij,jl) + epsi10 ) ) THEN
195               zremap_flag(ii,ij) = 0
196            ENDIF
197
198            !- 4.3 Check that each zhbnew does not exceed maximal values hi_max 
199            IF( zhbnew(ii,ij,jl) < hi_max(jl-1) ) zremap_flag(ii,ij) = 0
200            IF( zhbnew(ii,ij,jl) > hi_max(jl+1) ) zremap_flag(ii,ij) = 0
201            ! clem bug: why is not the following instead?
202            !!IF( zhbnew(ii,ij,jl) < hi_max(jl-1) ) zremap_flag(ii,ij) = 0
203            !!IF( zhbnew(ii,ij,jl) > hi_max(jl  ) ) zremap_flag(ii,ij) = 0
204 
205         END DO
206
207      END DO
208
209      !-----------------------------------------------------------------------------------------------
210      !  5) Identify cells where ITD is to be remapped
211      !-----------------------------------------------------------------------------------------------
212      nbrem = 0
213      DO jj = 1, jpj
214         DO ji = 1, jpi
215            IF( zremap_flag(ji,jj) == 1 ) THEN
216               nbrem         = nbrem + 1
217               nind_i(nbrem) = ji
218               nind_j(nbrem) = jj
219            ENDIF
220         END DO
221      END DO 
222
223      !-----------------------------------------------------------------------------------------------
224      !  6) Fill arrays with lowermost / uppermost boundaries of 'new' categories
225      !-----------------------------------------------------------------------------------------------
226      DO jj = 1, jpj
227         DO ji = 1, jpi
228            zhb0(ji,jj) = hi_max(0)
229            zhb1(ji,jj) = hi_max(1)
230
231            IF( a_i(ji,jj,kubnd) > epsi10 ) THEN
232               zhbnew(ji,jj,kubnd) = MAX( hi_max(kubnd-1), 3._wp * ht_i(ji,jj,kubnd) - 2._wp * zhbnew(ji,jj,kubnd-1) )
233            ELSE
234!clem bug               zhbnew(ji,jj,kubnd) = hi_max(kubnd) 
235               zhbnew(ji,jj,kubnd) = hi_max(kubnd-1) ! not used anyway
236            ENDIF
237
238            ! clem: we do not want ht_i_b to be too close to either HR or HL otherwise a division by nearly 0 is possible
239            ! in lim_itd_fitline in the case (HR-HL) = 3(Hice - HL) or = 3(HR - Hice)
240            IF    ( zht_i_b(ji,jj,klbnd) < ( zhb0(ji,jj) + epsi10 ) )  THEN
241               zremap_flag(ji,jj) = 0
242            ELSEIF( zht_i_b(ji,jj,klbnd) > ( zhb1(ji,jj) - epsi10 ) )  THEN
243               zremap_flag(ji,jj) = 0
244            ENDIF
245
246         END DO
247      END DO
248
249      !-----------------------------------------------------------------------------------------------
250      !  7) Compute g(h)
251      !-----------------------------------------------------------------------------------------------
252      !- 7.1 g(h) for category 1 at start of time step
253      CALL lim_itd_fitline( klbnd, zhb0, zhb1, zht_i_b(:,:,klbnd), g0(:,:,klbnd), g1(:,:,klbnd), hL(:,:,klbnd),   &
254         &                  hR(:,:,klbnd), zremap_flag )
255
256      !- 7.2 Area lost due to melting of thin ice (first category,  klbnd)
257      DO ji = 1, nbrem
258         ii = nind_i(ji) 
259         ij = nind_j(ji) 
260
261         IF( a_i(ii,ij,klbnd) > epsi10 ) THEN
262
263            zdh0 = zdhice(ii,ij,klbnd) !decrease of ice thickness in the lower category
264
265            IF( zdh0 < 0.0 ) THEN      !remove area from category 1
266               zdh0 = MIN( -zdh0, hi_max(klbnd) )
267               !Integrate g(1) from 0 to dh0 to estimate area melted
268               zetamax = MIN( zdh0, hR(ii,ij,klbnd) ) - hL(ii,ij,klbnd)
269
270               IF( zetamax > 0.0 ) THEN
271                  zx1    = zetamax
272                  zx2    = 0.5 * zetamax * zetamax 
273                  zda0   = g1(ii,ij,klbnd) * zx2 + g0(ii,ij,klbnd) * zx1                        ! ice area removed
274                  zdamax = a_i(ii,ij,klbnd) * (1.0 - ht_i(ii,ij,klbnd) / zht_i_b(ii,ij,klbnd) ) ! Constrain new thickness <= ht_i               
275                  zda0   = MIN( zda0, zdamax )                                                  ! ice area lost due to melting
276                                                                                                !     of thin ice (zdamax > 0)
277                  ! Remove area, conserving volume
278                  ht_i(ii,ij,klbnd) = ht_i(ii,ij,klbnd) * a_i(ii,ij,klbnd) / ( a_i(ii,ij,klbnd) - zda0 )
279                  a_i(ii,ij,klbnd)  = a_i(ii,ij,klbnd) - zda0
280                  v_i(ii,ij,klbnd)  = a_i(ii,ij,klbnd) * ht_i(ii,ij,klbnd) ! clem-useless ?
281               ENDIF
282
283            ELSE ! if ice accretion zdh0 > 0
284               ! zhbnew was 0, and is shifted to the right to account for thin ice growth in openwater (F0 = f1)
285               zhbnew(ii,ij,klbnd-1) = MIN( zdh0, hi_max(klbnd) ) 
286            ENDIF
287
288         ENDIF
289
290      END DO
291
292      !- 7.3 g(h) for each thickness category 
293      DO jl = klbnd, kubnd
294         CALL lim_itd_fitline( jl, zhbnew(:,:,jl-1), zhbnew(:,:,jl), ht_i(:,:,jl),  &
295            &                  g0(:,:,jl), g1(:,:,jl), hL(:,:,jl), hR(:,:,jl), zremap_flag )
296      END DO
297
298      !-----------------------------------------------------------------------------------------------
299      !  8) Compute area and volume to be shifted across each boundary
300      !-----------------------------------------------------------------------------------------------
301
302      DO jl = klbnd, kubnd - 1
303         DO jj = 1, jpj
304            DO ji = 1, jpi
305               zdonor(ji,jj,jl) = 0
306               zdaice(ji,jj,jl) = 0.0
307               zdvice(ji,jj,jl) = 0.0
308            END DO
309         END DO
310
311         DO ji = 1, nbrem
312            ii = nind_i(ji)
313            ij = nind_j(ji)
314
315            IF (zhbnew(ii,ij,jl) > hi_max(jl)) THEN ! transfer from jl to jl+1
316               ! left and right integration limits in eta space
317               zvetamin(ji) = MAX( hi_max(jl), hL(ii,ij,jl) ) - hL(ii,ij,jl)
318               zvetamax(ji) = MIN( zhbnew(ii,ij,jl), hR(ii,ij,jl) ) - hL(ii,ij,jl)
319               zdonor(ii,ij,jl) = jl
320
321            ELSE                                    ! zhbnew(jl) <= hi_max(jl) ; transfer from jl+1 to jl
322               ! left and right integration limits in eta space
323               zvetamin(ji) = 0.0
324               zvetamax(ji) = MIN( hi_max(jl), hR(ii,ij,jl+1) ) - hL(ii,ij,jl+1)
325               zdonor(ii,ij,jl) = jl + 1
326
327            ENDIF
328
329            zetamax = MAX( zvetamax(ji), zvetamin(ji) ) ! no transfer if etamax < etamin
330            zetamin = zvetamin(ji)
331
332            zx1  = zetamax - zetamin
333            zwk1 = zetamin * zetamin
334            zwk2 = zetamax * zetamax
335            zx2  = 0.5 * ( zwk2 - zwk1 )
336            zwk1 = zwk1 * zetamin
337            zwk2 = zwk2 * zetamax
338            zx3  = 1.0 / 3.0 * ( zwk2 - zwk1 )
339            nd   = zdonor(ii,ij,jl)
340            zdaice(ii,ij,jl) = g1(ii,ij,nd)*zx2 + g0(ii,ij,nd)*zx1
341            zdvice(ii,ij,jl) = g1(ii,ij,nd)*zx3 + g0(ii,ij,nd)*zx2 + zdaice(ii,ij,jl)*hL(ii,ij,nd)
342
343         END DO
344      END DO
345
346      !!----------------------------------------------------------------------------------------------
347      !! 9) Shift ice between categories
348      !!----------------------------------------------------------------------------------------------
349      CALL lim_itd_shiftice ( klbnd, kubnd, zdonor, zdaice, zdvice )
350
351      !!----------------------------------------------------------------------------------------------
352      !! 10) Make sure ht_i >= minimum ice thickness hi_min
353      !!----------------------------------------------------------------------------------------------
354
355      DO ji = 1, nbrem
356         ii = nind_i(ji)
357         ij = nind_j(ji)
358         IF ( a_i(ii,ij,1) > epsi10 .AND. ht_i(ii,ij,1) < rn_himin ) THEN
359            a_i (ii,ij,1) = a_i(ii,ij,1) * ht_i(ii,ij,1) / rn_himin 
360            ht_i(ii,ij,1) = rn_himin
361         ENDIF
362      END DO
363
364      !!----------------------------------------------------------------------------------------------
365      !! 11) Conservation check
366      !!----------------------------------------------------------------------------------------------
367      IF ( con_i ) THEN
368         CALL lim_column_sum (jpl,   v_i, vt_i_final)
369         fieldid = ' v_i : limitd_th '
370         CALL lim_cons_check (vt_i_init, vt_i_final, 1.0e-6, fieldid) 
371
372         CALL lim_column_sum_energy (jpl, nlay_i,  e_i, et_i_final)
373         fieldid = ' e_i : limitd_th '
374         CALL lim_cons_check (et_i_init, et_i_final, 1.0e-3, fieldid) 
375
376         CALL lim_column_sum (jpl,   v_s, vt_s_final)
377         fieldid = ' v_s : limitd_th '
378         CALL lim_cons_check (vt_s_init, vt_s_final, 1.0e-6, fieldid) 
379
380         dummy_es(:,:,:) = e_s(:,:,1,:)
381         CALL lim_column_sum (jpl, dummy_es(:,:,:) , et_s_final)
382         fieldid = ' e_s : limitd_th '
383         CALL lim_cons_check (et_s_init, et_s_final, 1.0e-3, fieldid) 
384      ENDIF
385
386      CALL wrk_dealloc( jpi,jpj, zremap_flag )
387      CALL wrk_dealloc( jpi,jpj,jpl-1, zdonor )
388      CALL wrk_dealloc( jpi,jpj,jpl, zdhice, g0, g1, hL, hR, zht_i_b, dummy_es )
389      CALL wrk_dealloc( jpi,jpj,jpl-1, zdaice, zdvice )   
390      CALL wrk_dealloc( jpi,jpj,jpl+1, zhbnew, kkstart = 0 )   
391      CALL wrk_dealloc( (jpi+1)*(jpj+1), zvetamin, zvetamax )   
392      CALL wrk_dealloc( (jpi+1)*(jpj+1), nind_i, nind_j ) 
393      CALL wrk_dealloc( jpi,jpj, zhb0,zhb1,vt_i_init,vt_i_final,vt_s_init,vt_s_final,et_i_init,et_i_final,et_s_init,et_s_final )
394
395   END SUBROUTINE lim_itd_th_rem
396
397
398   SUBROUTINE lim_itd_fitline( num_cat, HbL, Hbr, hice, g0, g1, hL, hR, zremap_flag )
399      !!------------------------------------------------------------------
400      !!                ***  ROUTINE lim_itd_fitline ***
401      !!
402      !! ** Purpose :   fit g(h) with a line using area, volume constraints
403      !!
404      !! ** Method  :   Fit g(h) with a line, satisfying area and volume constraints.
405      !!              To reduce roundoff errors caused by large values of g0 and g1,
406      !!              we actually compute g(eta), where eta = h - hL, and hL is the
407      !!              left boundary.
408      !!------------------------------------------------------------------
409      INTEGER                     , INTENT(in   ) ::   num_cat      ! category index
410      REAL(wp), DIMENSION(jpi,jpj), INTENT(in   ) ::   HbL, HbR     ! left and right category boundaries
411      REAL(wp), DIMENSION(jpi,jpj), INTENT(in   ) ::   hice         ! ice thickness
412      REAL(wp), DIMENSION(jpi,jpj), INTENT(  out) ::   g0, g1       ! coefficients in linear equation for g(eta)
413      REAL(wp), DIMENSION(jpi,jpj), INTENT(  out) ::   hL           ! min value of range over which g(h) > 0
414      REAL(wp), DIMENSION(jpi,jpj), INTENT(  out) ::   hR           ! max value of range over which g(h) > 0
415      INTEGER , DIMENSION(jpi,jpj), INTENT(in   ) ::   zremap_flag  !
416      !
417      INTEGER  ::   ji,jj        ! horizontal indices
418      REAL(wp) ::   zh13         ! HbL + 1/3 * (HbR - HbL)
419      REAL(wp) ::   zh23         ! HbL + 2/3 * (HbR - HbL)
420      REAL(wp) ::   zdhr         ! 1 / (hR - hL)
421      REAL(wp) ::   zwk1, zwk2   ! temporary variables
422      !!------------------------------------------------------------------
423      !
424      DO jj = 1, jpj
425         DO ji = 1, jpi
426            !
427            IF( zremap_flag(ji,jj) == 1 .AND. a_i(ji,jj,num_cat) > epsi10   &
428               &                        .AND. hice(ji,jj)        > 0._wp )  THEN
429
430               ! Initialize hL and hR
431               hL(ji,jj) = HbL(ji,jj)
432               hR(ji,jj) = HbR(ji,jj)
433
434               ! Change hL or hR if hice falls outside central third of range
435               zh13 = 1.0 / 3.0 * ( 2.0 * hL(ji,jj) + hR(ji,jj) )
436               zh23 = 1.0 / 3.0 * ( hL(ji,jj) + 2.0 * hR(ji,jj) )
437
438               IF    ( hice(ji,jj) < zh13 ) THEN   ;   hR(ji,jj) = 3._wp * hice(ji,jj) - 2._wp * hL(ji,jj)
439               ELSEIF( hice(ji,jj) > zh23 ) THEN   ;   hL(ji,jj) = 3._wp * hice(ji,jj) - 2._wp * hR(ji,jj)
440               ENDIF
441
442               ! Compute coefficients of g(eta) = g0 + g1*eta
443               zdhr = 1._wp / (hR(ji,jj) - hL(ji,jj))
444               zwk1 = 6._wp * a_i(ji,jj,num_cat) * zdhr
445               zwk2 = ( hice(ji,jj) - hL(ji,jj) ) * zdhr
446               g0(ji,jj) = zwk1 * ( 2._wp / 3._wp - zwk2 )
447               g1(ji,jj) = 2._wp * zdhr * zwk1 * ( zwk2 - 0.5 )
448               !
449            ELSE  ! remap_flag = .false. or a_i < epsi10
450               hL(ji,jj) = 0._wp
451               hR(ji,jj) = 0._wp
452               g0(ji,jj) = 0._wp
453               g1(ji,jj) = 0._wp
454            ENDIF
455            !
456         END DO
457      END DO
458      !
459   END SUBROUTINE lim_itd_fitline
460
461
462   SUBROUTINE lim_itd_shiftice( klbnd, kubnd, zdonor, zdaice, zdvice )
463      !!------------------------------------------------------------------
464      !!                ***  ROUTINE lim_itd_shiftice ***
465      !!
466      !! ** Purpose :   shift ice across category boundaries, conserving everything
467      !!              ( area, volume, energy, age*vol, and mass of salt )
468      !!
469      !! ** Method  :
470      !!------------------------------------------------------------------
471      INTEGER                           , INTENT(in   ) ::   klbnd    ! Start thickness category index point
472      INTEGER                           , INTENT(in   ) ::   kubnd    ! End point on which the  the computation is applied
473      INTEGER , DIMENSION(jpi,jpj,jpl-1), INTENT(in   ) ::   zdonor   ! donor category index
474      REAL(wp), DIMENSION(jpi,jpj,jpl-1), INTENT(inout) ::   zdaice   ! ice area transferred across boundary
475      REAL(wp), DIMENSION(jpi,jpj,jpl-1), INTENT(inout) ::   zdvice   ! ice volume transferred across boundary
476
477      INTEGER ::   ji, jj, jl, jl2, jl1, jk   ! dummy loop indices
478      INTEGER ::   ii, ij                     ! indices when changing from 2D-1D is done
479
480      REAL(wp), POINTER, DIMENSION(:,:,:) ::   zaTsfn
481      REAL(wp), POINTER, DIMENSION(:,:)   ::   zworka            ! temporary array used here
482
483      REAL(wp) ::   zdvsnow, zdesnow   ! snow volume and energy transferred
484      REAL(wp) ::   zdeice             ! ice energy transferred
485      REAL(wp) ::   zdsm_vice          ! ice salinity times volume transferred
486      REAL(wp) ::   zdo_aice           ! ice age times volume transferred
487      REAL(wp) ::   zdaTsf             ! aicen*Tsfcn transferred
488
489      INTEGER, POINTER, DIMENSION(:) ::   nind_i, nind_j   ! compressed indices for i/j directions
490
491      INTEGER  ::   nbrem             ! number of cells with ice to transfer
492      !!------------------------------------------------------------------
493
494      CALL wrk_alloc( jpi,jpj,jpl, zaTsfn )
495      CALL wrk_alloc( jpi,jpj, zworka )
496      CALL wrk_alloc( (jpi+1)*(jpj+1), nind_i, nind_j )
497
498      !----------------------------------------------------------------------------------------------
499      ! 1) Define a variable equal to a_i*T_su
500      !----------------------------------------------------------------------------------------------
501
502      DO jl = klbnd, kubnd
503         zaTsfn(:,:,jl) = a_i(:,:,jl) * t_su(:,:,jl)
504      END DO
505
506      !-------------------------------------------------------------------------------
507      ! 2) Transfer volume and energy between categories
508      !-------------------------------------------------------------------------------
509
510      DO jl = klbnd, kubnd - 1
511         nbrem = 0
512         DO jj = 1, jpj
513            DO ji = 1, jpi
514               IF (zdaice(ji,jj,jl) > 0.0 ) THEN ! daice(n) can be < puny
515                  nbrem = nbrem + 1
516                  nind_i(nbrem) = ji
517                  nind_j(nbrem) = jj
518               ENDIF
519            END DO
520         END DO
521
522         DO ji = 1, nbrem 
523            ii = nind_i(ji)
524            ij = nind_j(ji)
525
526            jl1 = zdonor(ii,ij,jl)
527            rswitch       = MAX( 0._wp , SIGN( 1._wp , v_i(ii,ij,jl1) - epsi10 ) )
528            zworka(ii,ij) = zdvice(ii,ij,jl) / MAX( v_i(ii,ij,jl1), epsi10 ) * rswitch
529            IF( jl1 == jl) THEN   ;   jl2 = jl1+1
530            ELSE                  ;   jl2 = jl 
531            ENDIF
532
533            !--------------
534            ! Ice areas
535            !--------------
536            a_i(ii,ij,jl1) = a_i(ii,ij,jl1) - zdaice(ii,ij,jl)
537            a_i(ii,ij,jl2) = a_i(ii,ij,jl2) + zdaice(ii,ij,jl)
538
539            !--------------
540            ! Ice volumes
541            !--------------
542            v_i(ii,ij,jl1) = v_i(ii,ij,jl1) - zdvice(ii,ij,jl) 
543            v_i(ii,ij,jl2) = v_i(ii,ij,jl2) + zdvice(ii,ij,jl)
544
545            !--------------
546            ! Snow volumes
547            !--------------
548            zdvsnow        = v_s(ii,ij,jl1) * zworka(ii,ij)
549            v_s(ii,ij,jl1) = v_s(ii,ij,jl1) - zdvsnow
550            v_s(ii,ij,jl2) = v_s(ii,ij,jl2) + zdvsnow 
551
552            !--------------------
553            ! Snow heat content 
554            !--------------------
555            zdesnow            = e_s(ii,ij,1,jl1) * zworka(ii,ij)
556            e_s(ii,ij,1,jl1)   = e_s(ii,ij,1,jl1) - zdesnow
557            e_s(ii,ij,1,jl2)   = e_s(ii,ij,1,jl2) + zdesnow
558
559            !--------------
560            ! Ice age
561            !--------------
562            zdo_aice           = oa_i(ii,ij,jl1) * zdaice(ii,ij,jl)
563            oa_i(ii,ij,jl1)    = oa_i(ii,ij,jl1) - zdo_aice
564            oa_i(ii,ij,jl2)    = oa_i(ii,ij,jl2) + zdo_aice
565
566            !--------------
567            ! Ice salinity
568            !--------------
569            zdsm_vice          = smv_i(ii,ij,jl1) * zworka(ii,ij)
570            smv_i(ii,ij,jl1)   = smv_i(ii,ij,jl1) - zdsm_vice
571            smv_i(ii,ij,jl2)   = smv_i(ii,ij,jl2) + zdsm_vice
572
573            !---------------------
574            ! Surface temperature
575            !---------------------
576            zdaTsf             = t_su(ii,ij,jl1) * zdaice(ii,ij,jl)
577            zaTsfn(ii,ij,jl1)  = zaTsfn(ii,ij,jl1) - zdaTsf
578            zaTsfn(ii,ij,jl2)  = zaTsfn(ii,ij,jl2) + zdaTsf 
579
580         END DO
581
582         !------------------
583         ! Ice heat content
584         !------------------
585
586         DO jk = 1, nlay_i
587            DO ji = 1, nbrem
588               ii = nind_i(ji)
589               ij = nind_j(ji)
590
591               jl1 = zdonor(ii,ij,jl)
592               IF (jl1 == jl) THEN
593                  jl2 = jl+1
594               ELSE             ! n1 = n+1
595                  jl2 = jl 
596               ENDIF
597
598               zdeice = e_i(ii,ij,jk,jl1) * zworka(ii,ij)
599               e_i(ii,ij,jk,jl1) =  e_i(ii,ij,jk,jl1) - zdeice
600               e_i(ii,ij,jk,jl2) =  e_i(ii,ij,jk,jl2) + zdeice 
601            END DO
602         END DO
603
604      END DO                   ! boundaries, 1 to ncat-1
605
606      !-----------------------------------------------------------------
607      ! Update ice thickness and temperature
608      !-----------------------------------------------------------------
609
610      DO jl = klbnd, kubnd
611         DO jj = 1, jpj
612            DO ji = 1, jpi 
613               IF ( a_i(ji,jj,jl) > epsi10 ) THEN
614                  ht_i(ji,jj,jl)  =  v_i   (ji,jj,jl) / a_i(ji,jj,jl) 
615                  t_su(ji,jj,jl)  =  zaTsfn(ji,jj,jl) / a_i(ji,jj,jl) 
616               ELSE
617                  ht_i(ji,jj,jl)  = 0._wp
618                  t_su(ji,jj,jl)  = rt0
619               ENDIF
620            END DO
621         END DO
622      END DO
623      !
624      CALL wrk_dealloc( jpi,jpj,jpl, zaTsfn )
625      CALL wrk_dealloc( jpi,jpj, zworka )
626      CALL wrk_dealloc( (jpi+1)*(jpj+1), nind_i, nind_j )
627      !
628   END SUBROUTINE lim_itd_shiftice
629   
630
631   SUBROUTINE lim_itd_th_reb( klbnd, kubnd )
632      !!------------------------------------------------------------------
633      !!                ***  ROUTINE lim_itd_th_reb ***
634      !!
635      !! ** Purpose : rebin - rebins thicknesses into defined categories
636      !!
637      !! ** Method  :
638      !!------------------------------------------------------------------
639      INTEGER , INTENT (in) ::   klbnd   ! Start thickness category index point
640      INTEGER , INTENT (in) ::   kubnd   ! End point on which the  the computation is applied
641      !
642      INTEGER ::   ji,jj, jl   ! dummy loop indices
643      INTEGER ::   zshiftflag          ! = .true. if ice must be shifted
644      CHARACTER (len = 15) :: fieldid
645
646      INTEGER , POINTER, DIMENSION(:,:,:) ::   zdonor           ! donor category index
647      REAL(wp), POINTER, DIMENSION(:,:,:) ::   zdaice, zdvice   ! ice area and volume transferred
648
649      REAL(wp), POINTER, DIMENSION(:,:) ::   vt_i_init, vt_i_final   ! ice volume summed over categories
650      REAL(wp), POINTER, DIMENSION(:,:) ::   vt_s_init, vt_s_final   ! snow volume summed over categories
651      !!------------------------------------------------------------------
652     
653      CALL wrk_alloc( jpi,jpj,jpl, zdonor )   ! interger
654      CALL wrk_alloc( jpi,jpj,jpl, zdaice, zdvice )
655      CALL wrk_alloc( jpi,jpj, vt_i_init, vt_i_final, vt_s_init, vt_s_final )
656      !     
657      IF( con_i ) THEN                 ! conservation check
658         CALL lim_column_sum (jpl,   v_i, vt_i_init)
659         CALL lim_column_sum (jpl,   v_s, vt_s_init)
660      ENDIF
661
662      !
663      !------------------------------------------------------------------------------
664      ! 1) Compute ice thickness.
665      !------------------------------------------------------------------------------
666      DO jl = klbnd, kubnd
667         DO jj = 1, jpj
668            DO ji = 1, jpi 
669               rswitch = MAX( 0._wp , SIGN( 1._wp, a_i(ji,jj,jl) - epsi10 ) )
670               ht_i(ji,jj,jl) = v_i (ji,jj,jl) / MAX( a_i(ji,jj,jl) , epsi10 ) * rswitch
671            END DO
672         END DO
673      END DO
674
675      !------------------------------------------------------------------------------
676      ! 2) If a category thickness is not in bounds, shift the
677      ! entire area, volume, and energy to the neighboring category
678      !------------------------------------------------------------------------------
679      !-------------------------
680      ! Initialize shift arrays
681      !-------------------------
682      DO jl = klbnd, kubnd
683         zdonor(:,:,jl) = 0
684         zdaice(:,:,jl) = 0._wp
685         zdvice(:,:,jl) = 0._wp
686      END DO
687
688      !-------------------------
689      ! Move thin categories up
690      !-------------------------
691
692      DO jl = klbnd, kubnd - 1  ! loop over category boundaries
693
694         !---------------------------------------
695         ! identify thicknesses that are too big
696         !---------------------------------------
697         zshiftflag = 0
698
699         DO jj = 1, jpj 
700            DO ji = 1, jpi 
701               IF( a_i(ji,jj,jl) > epsi10 .AND. ht_i(ji,jj,jl) > hi_max(jl) ) THEN
702                  zshiftflag        = 1
703                  zdonor(ji,jj,jl)  = jl 
704                  ! begin TECLIM change
705                  !zdaice(ji,jj,jl)  = a_i(ji,jj,jl) * 0.5_wp
706                  !zdvice(ji,jj,jl)  = v_i(ji,jj,jl)-zdaice(ji,jj,jl)*(hi_max(jl)+hi_max(jl-1)) * 0.5_wp
707                  ! end TECLIM change
708                  ! clem: how much of a_i you send in cat sup is somewhat arbitrary
709                  zdaice(ji,jj,jl)  = a_i(ji,jj,jl) * ( ht_i(ji,jj,jl) - hi_max(jl) + epsi20 ) / ht_i(ji,jj,jl) 
710                  zdvice(ji,jj,jl)  = v_i(ji,jj,jl) - ( a_i(ji,jj,jl) - zdaice(ji,jj,jl) ) * ( hi_max(jl) - epsi20 )
711               ENDIF
712            END DO
713         END DO
714         IF(lk_mpp)   CALL mpp_max( zshiftflag )
715
716         IF( zshiftflag == 1 ) THEN            ! Shift ice between categories
717            CALL lim_itd_shiftice( klbnd, kubnd, zdonor, zdaice, zdvice )
718            ! Reset shift parameters
719            zdonor(:,:,jl) = 0
720            zdaice(:,:,jl) = 0._wp
721            zdvice(:,:,jl) = 0._wp
722         ENDIF
723         !
724      END DO
725
726      !----------------------------
727      ! Move thick categories down
728      !----------------------------
729
730      DO jl = kubnd - 1, 1, -1       ! loop over category boundaries
731
732         !-----------------------------------------
733         ! Identify thicknesses that are too small
734         !-----------------------------------------
735         zshiftflag = 0
736
737         DO jj = 1, jpj
738            DO ji = 1, jpi
739               IF( a_i(ji,jj,jl+1) > epsi10 .AND. ht_i(ji,jj,jl+1) <= hi_max(jl) ) THEN
740                  !
741                  zshiftflag = 1
742                  zdonor(ji,jj,jl) = jl + 1
743                  zdaice(ji,jj,jl) = a_i(ji,jj,jl+1) 
744                  zdvice(ji,jj,jl) = v_i(ji,jj,jl+1)
745               ENDIF
746            END DO
747         END DO
748
749         IF(lk_mpp)   CALL mpp_max( zshiftflag )
750         
751         IF( zshiftflag == 1 ) THEN            ! Shift ice between categories
752            CALL lim_itd_shiftice( klbnd, kubnd, zdonor, zdaice, zdvice )
753            ! Reset shift parameters
754            zdonor(:,:,jl) = 0
755            zdaice(:,:,jl) = 0._wp
756            zdvice(:,:,jl) = 0._wp
757         ENDIF
758
759      END DO
760
761      !------------------------------------------------------------------------------
762      ! 3) Conservation check
763      !------------------------------------------------------------------------------
764
765      IF( con_i ) THEN
766         CALL lim_column_sum (jpl,   v_i, vt_i_final)
767         fieldid = ' v_i : limitd_reb '
768         CALL lim_cons_check (vt_i_init, vt_i_final, 1.0e-6, fieldid) 
769
770         CALL lim_column_sum (jpl,   v_s, vt_s_final)
771         fieldid = ' v_s : limitd_reb '
772         CALL lim_cons_check (vt_s_init, vt_s_final, 1.0e-6, fieldid) 
773      ENDIF
774      !
775      CALL wrk_dealloc( jpi,jpj,jpl, zdonor )
776      CALL wrk_dealloc( jpi,jpj,jpl, zdaice, zdvice )
777      CALL wrk_dealloc( jpi,jpj, vt_i_init, vt_i_final, vt_s_init, vt_s_final )
778
779   END SUBROUTINE lim_itd_th_reb
780
781#else
782   !!----------------------------------------------------------------------
783   !!   Default option            Dummy module         NO LIM sea-ice model
784   !!----------------------------------------------------------------------
785CONTAINS
786   SUBROUTINE lim_itd_th_rem
787   END SUBROUTINE lim_itd_th_rem
788   SUBROUTINE lim_itd_fitline
789   END SUBROUTINE lim_itd_fitline
790   SUBROUTINE lim_itd_shiftice
791   END SUBROUTINE lim_itd_shiftice
792   SUBROUTINE lim_itd_th_reb
793   END SUBROUTINE lim_itd_th_reb
794#endif
795   !!======================================================================
796END MODULE limitd_th
Note: See TracBrowser for help on using the repository browser.