Skip to content

Commit 286630f

Browse files
authored
FSD fixes for conservation (#495)
This is a bug fix plus some rearranging for conservation in CICE. This impacts FSD cases as well as non-FSD cases. There are two main aspects to the bug fix: Initial ice and snow volume values at the beginning of the lateral melt routine are now used for updating the snow and ice enthalpy as well other tracers for lateral melting. This is answer changing in all cases! The other fix is to move the computation of vi0new_lat (lateral growth from FSD) outside of the subroutine fsd_lateral_growth and a check to make sure the category vi0new (vin0new) does not exceed the total vi0new. This is a warning and it recomputes to ensure conservation. This is only answer changing in FSD cases. There is also a change in definition of floe_area_c, so that it is precisely half way between floe_area_l and floe_area_h. The original computation of floe_area_c based on floe_rad_c biases the area towards the lower value. Update the fsd subroutine arguments (floe_rad_c, floe_rad_l, floe_binwidth, c_fsd_range) to store static data inside Icepack when computed in Icepack rather than pass them back and forth. Provide an ability to pass out the values from Icepack as optional arguments. Move the computation of rsiden and get rid of fside which is no longer needed. Clean up some comments and indentation Update swccsm3 test, set ktherm=1 Update interface documentation There is an associated CICE tag to go with this.
1 parent 6da5668 commit 286630f

12 files changed

+408
-447
lines changed

columnphysics/icepack_fsd.F90

+82-58
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,19 @@ module icepack_fsd
5555
public :: icepack_init_fsd_bounds, icepack_init_fsd, icepack_cleanup_fsd, &
5656
fsd_lateral_growth, fsd_add_new_ice, fsd_weld_thermo, get_subdt_fsd
5757

58-
real(kind=dbl_kind), dimension(:), allocatable :: &
58+
real(kind=dbl_kind), dimension(:), allocatable, public :: &
5959
floe_rad_h, & ! fsd size higher bound in m (radius)
60+
floe_rad_c, & ! fsd size center in m (radius)
61+
floe_rad_l, & ! fsd size lower bound in m (radius)
62+
floe_binwidth, & ! fsd size binwidth in m (radius)
6063
floe_area_l, & ! fsd area at lower bound (m^2)
6164
floe_area_h, & ! fsd area at higher bound (m^2)
6265
floe_area_c, & ! fsd area at bin centre (m^2)
6366
floe_area_binwidth ! floe area bin width (m^2)
6467

68+
character (len=35), dimension(:), allocatable, public :: &
69+
c_fsd_range ! string for history output
70+
6571
integer(kind=int_kind), dimension(:,:), allocatable, public :: &
6672
iweld ! floe size categories that can combine
6773
! during welding (dimensionless)
@@ -85,22 +91,22 @@ module icepack_fsd
8591
! authors: Lettie Roach, NIWA/VUW and C. M. Bitz, UW
8692

8793
subroutine icepack_init_fsd_bounds( &
88-
floe_rad_l, & ! fsd size lower bound in m (radius)
89-
floe_rad_c, & ! fsd size bin centre in m (radius)
90-
floe_binwidth, & ! fsd size bin width in m (radius)
91-
c_fsd_range, & ! string for history output
92-
write_diags ) ! flag for writing diagnostics
94+
floe_rad_l_out, & ! fsd size lower bound in m (radius)
95+
floe_rad_c_out, & ! fsd size bin centre in m (radius)
96+
floe_binwidth_out, & ! fsd size bin width in m (radius)
97+
c_fsd_range_out, & ! string for history output
98+
write_diags) ! flag for writing diagnostics
9399

94-
real(kind=dbl_kind), dimension(:), intent(inout) :: &
95-
floe_rad_l, & ! fsd size lower bound in m (radius)
96-
floe_rad_c, & ! fsd size bin centre in m (radius)
97-
floe_binwidth ! fsd size bin width in m (radius)
100+
real(kind=dbl_kind), dimension(:), intent(out), optional :: &
101+
floe_rad_l_out, & ! fsd size lower bound in m (radius)
102+
floe_rad_c_out, & ! fsd size bin centre in m (radius)
103+
floe_binwidth_out ! fsd size bin width in m (radius)
98104

99-
character (len=35), intent(out) :: &
100-
c_fsd_range(nfsd) ! string for history output
105+
character (len=35), dimension(:), intent(out), optional :: &
106+
c_fsd_range_out ! string for history output
101107

102108
logical (kind=log_kind), intent(in), optional :: &
103-
write_diags ! write diags flag
109+
write_diags ! write diags flag
104110

105111
!autodocument_end
106112

@@ -111,11 +117,8 @@ subroutine icepack_init_fsd_bounds( &
111117

112118
real (kind=dbl_kind) :: test
113119

114-
real (kind=dbl_kind), dimension (0:nfsd) :: &
115-
floe_rad
116-
117120
real (kind=dbl_kind), dimension(:), allocatable :: &
118-
lims
121+
lims, floe_rad
119122

120123
character(len=8) :: c_fsd1,c_fsd2
121124
character(len=2) :: c_nf
@@ -169,10 +172,15 @@ subroutine icepack_init_fsd_bounds( &
169172

170173
allocate( &
171174
floe_rad_h (nfsd), & ! fsd size higher bound in m (radius)
175+
floe_rad_l (nfsd), & ! fsd size lower bound in m (radius)
176+
floe_rad_c (nfsd), & ! fsd size center in m (radius)
177+
floe_rad (0:nfsd), & ! fsd bounds in m (radius)
172178
floe_area_l (nfsd), & ! fsd area at lower bound (m^2)
173179
floe_area_h (nfsd), & ! fsd area at higher bound (m^2)
174180
floe_area_c (nfsd), & ! fsd area at bin centre (m^2)
175181
floe_area_binwidth (nfsd), & ! floe area bin width (m^2)
182+
floe_binwidth (nfsd), & ! floe bin width (m)
183+
c_fsd_range (nfsd), & !
176184
iweld (nfsd, nfsd), & ! fsd categories that can weld
177185
stat=ierr)
178186
if (ierr/=0) then
@@ -186,8 +194,11 @@ subroutine icepack_init_fsd_bounds( &
186194
floe_rad_c = (floe_rad_h+floe_rad_l)/c2
187195

188196
floe_area_l = c4*floeshape*floe_rad_l**2
189-
floe_area_c = c4*floeshape*floe_rad_c**2
190197
floe_area_h = c4*floeshape*floe_rad_h**2
198+
! floe_area_c = c4*floeshape*floe_rad_c**2
199+
! This is exactly in the middle of floe_area_h and floe_area_l
200+
! Whereas the above calculation is closer to floe_area_l.
201+
floe_area_c = (floe_area_h+floe_area_l)/c2
191202

192203
floe_binwidth = floe_rad_h - floe_rad_l
193204

@@ -220,20 +231,56 @@ subroutine icepack_init_fsd_bounds( &
220231
enddo
221232

222233
if (present(write_diags)) then
223-
if (write_diags) then
224-
write(warnstr,*) ' '
225-
call icepack_warnings_add(warnstr)
226-
write(warnstr,*) subname
227-
call icepack_warnings_add(warnstr)
228-
write(warnstr,*) 'floe_rad(n-1) < fsd Cat n < floe_rad(n)'
229-
call icepack_warnings_add(warnstr)
230-
do n = 1, nfsd
231-
write(warnstr,*) floe_rad(n-1),' < fsd Cat ',n, ' < ',floe_rad(n)
234+
if (write_diags) then
235+
write(warnstr,*) ' '
232236
call icepack_warnings_add(warnstr)
233-
enddo
234-
write(warnstr,*) ' '
235-
call icepack_warnings_add(warnstr)
237+
write(warnstr,*) subname
238+
call icepack_warnings_add(warnstr)
239+
write(warnstr,*) 'floe_rad(n-1) < fsd Cat n < floe_rad(n)'
240+
call icepack_warnings_add(warnstr)
241+
do n = 1, nfsd
242+
write(warnstr,*) floe_rad(n-1),' < fsd Cat ',n, ' < ',floe_rad(n)
243+
call icepack_warnings_add(warnstr)
244+
enddo
245+
write(warnstr,*) ' '
246+
call icepack_warnings_add(warnstr)
247+
endif
248+
endif
249+
250+
if (present(floe_rad_l_out)) then
251+
if (size(floe_rad_l_out) /= size(floe_rad_l)) then
252+
call icepack_warnings_add(subname//' floe_rad_l_out incorrect size')
253+
call icepack_warnings_setabort(.true.,__FILE__,__LINE__)
254+
return
255+
endif
256+
floe_rad_l_out(:) = floe_rad_l(:)
257+
endif
258+
259+
if (present(floe_rad_c_out)) then
260+
if (size(floe_rad_c_out) /= size(floe_rad_c)) then
261+
call icepack_warnings_add(subname//' floe_rad_c_out incorrect size')
262+
call icepack_warnings_setabort(.true.,__FILE__,__LINE__)
263+
return
264+
endif
265+
floe_rad_c_out(:) = floe_rad_c(:)
236266
endif
267+
268+
if (present(floe_binwidth_out)) then
269+
if (size(floe_binwidth_out) /= size(floe_binwidth)) then
270+
call icepack_warnings_add(subname//' floe_binwidth_out incorrect size')
271+
call icepack_warnings_setabort(.true.,__FILE__,__LINE__)
272+
return
273+
endif
274+
floe_binwidth_out(:) = floe_binwidth(:)
275+
endif
276+
277+
if (present(c_fsd_range_out)) then
278+
if (size(c_fsd_range_out) /= size(c_fsd_range)) then
279+
call icepack_warnings_add(subname//' c_fsd_range_out incorrect size')
280+
call icepack_warnings_setabort(.true.,__FILE__,__LINE__)
281+
return
282+
endif
283+
c_fsd_range_out(:) = c_fsd_range(:)
237284
endif
238285

239286
end subroutine icepack_init_fsd_bounds
@@ -256,18 +303,11 @@ end subroutine icepack_init_fsd_bounds
256303
!
257304
! authors: Lettie Roach, NIWA/VUW
258305

259-
subroutine icepack_init_fsd(ice_ic, &
260-
floe_rad_c, & ! fsd size bin centre in m (radius)
261-
floe_binwidth, & ! fsd size bin width in m (radius)
262-
afsd) ! floe size distribution tracer
306+
subroutine icepack_init_fsd(ice_ic, afsd) ! floe size distribution tracer
263307

264308
character(len=char_len_long), intent(in) :: &
265309
ice_ic ! method of ice cover initialization
266310

267-
real(kind=dbl_kind), dimension(:), intent(inout) :: &
268-
floe_rad_c, & ! fsd size bin centre in m (radius)
269-
floe_binwidth ! fsd size bin width in m (radius)
270-
271311
real (kind=dbl_kind), dimension (:), intent(inout) :: &
272312
afsd ! floe size tracer: fraction distribution of floes
273313

@@ -323,7 +363,6 @@ subroutine icepack_cleanup_fsd (afsdn)
323363

324364
character(len=*), parameter :: subname='(icepack_cleanup_fsd)'
325365

326-
327366
if (tr_fsd) then
328367

329368
do n = 1, ncat
@@ -378,14 +417,11 @@ end subroutine icepack_cleanup_fsdn
378417
!
379418
! authors: Lettie Roach, NIWA/VUW
380419

381-
subroutine partition_area (floe_rad_c, aice, &
420+
subroutine partition_area (aice, &
382421
aicen, vicen, &
383422
afsdn, lead_area, &
384423
latsurf_area)
385424

386-
real (kind=dbl_kind), dimension(:), intent(in) :: &
387-
floe_rad_c ! fsd size bin centre in m (radius)
388-
389425
real (kind=dbl_kind), intent(in) :: &
390426
aice ! ice concentration
391427

@@ -476,7 +512,7 @@ end subroutine partition_area
476512
subroutine fsd_lateral_growth (dt, aice, &
477513
aicen, vicen, &
478514
vi0new, &
479-
frazil, floe_rad_c, &
515+
frazil, &
480516
afsdn, &
481517
lead_area, latsurf_area, &
482518
G_radial, d_an_latg, &
@@ -497,10 +533,6 @@ subroutine fsd_lateral_growth (dt, aice, &
497533
vi0new , & ! volume of new ice added to cat 1 (m)
498534
frazil ! frazil ice growth (m/step-->cm/day)
499535

500-
! floe size distribution
501-
real (kind=dbl_kind), dimension (:), intent(in) :: &
502-
floe_rad_c ! fsd size bin centre in m (radius)
503-
504536
real (kind=dbl_kind), dimension(ncat), intent(out) :: &
505537
d_an_latg ! change in aicen occuring due to lateral growth
506538

@@ -529,7 +561,7 @@ subroutine fsd_lateral_growth (dt, aice, &
529561
d_an_latg = c0
530562

531563
! partition volume into lateral growth and frazil
532-
call partition_area (floe_rad_c, aice, &
564+
call partition_area (aice, &
533565
aicen, vicen, &
534566
afsdn, lead_area, &
535567
latsurf_area)
@@ -540,9 +572,6 @@ subroutine fsd_lateral_growth (dt, aice, &
540572
vi0new_lat = vi0new * lead_area / (c1 + aice/latsurf_area)
541573
end if
542574

543-
! for history/diagnostics
544-
frazil = vi0new - vi0new_lat
545-
546575
! lateral growth increment
547576
if (vi0new_lat > puny) then
548577
G_radial = vi0new_lat/dt
@@ -563,8 +592,6 @@ subroutine fsd_lateral_growth (dt, aice, &
563592
endif ! vi0new_lat > 0
564593

565594
! Use remaining ice volume as in standard model,
566-
! but ice cannot grow into the area that has grown laterally
567-
vi0new = vi0new - vi0new_lat
568595
tot_latg = SUM(d_an_latg(:))
569596

570597
end subroutine fsd_lateral_growth
@@ -589,7 +616,6 @@ end subroutine fsd_lateral_growth
589616
subroutine fsd_add_new_ice (n, &
590617
dt, ai0new, &
591618
d_an_latg, d_an_newi, &
592-
floe_rad_c, floe_binwidth, &
593619
G_radial, area2, &
594620
wave_sig_ht, &
595621
wave_spectrum, &
@@ -623,9 +649,7 @@ subroutine fsd_add_new_ice (n, &
623649

624650
real (kind=dbl_kind), dimension (:), intent(in) :: &
625651
aicen_init , & ! fractional area of ice
626-
aicen , & ! after update
627-
floe_rad_c , & ! fsd size bin centre in m (radius)
628-
floe_binwidth ! fsd size bin width in m (radius)
652+
aicen ! after update
629653

630654
real (kind=dbl_kind), dimension (:,:), intent(in) :: &
631655
afsdn ! floe size distribution tracer

0 commit comments

Comments
 (0)