Skip to content

Commit 52cb686

Browse files
authored
Update halo and interior restoring (CICE-Consortium#1110)
This is a significant refactor of the restoring implementation. Separated the exterior halo boundary update and the interior restoring capability. Added namelist set_boundary_flds to set exterior halo values. Added namelist restore_data, restore_flds, restore_mask, restore_width, and restore_timescale which work when restore_ice is on to computed interior restoring terms. Calls to initialize and execute the boundary and interior restoring were updated in the code. In summary, several model defined fields can be restored (controlled by set_boundary_flds and restore_flds) in ice_restoring.F90. The restoring dataset is specified with restore_data. Exterior halo values are set with set_boundary_flds. Interior restoring is turned on with restore_ice and the restoring strength is specified with restore_mask, restore_width, and restore_timescale. The implementation provides some basic options and a framework for adding new fields, new masks, and new datasets by application users as needed. The current restore_data options are - defined, internally defined state at all time - initial, uses the initial model state at all time - restartfiles, reads in extended restart files at each timestep, filenames are somewhat hardcoded into the implementation The fields (set_boundary_flds, restore_flds) currently supported are - aicen, restore ice concentration in all categories - state, restore aicen, vicen, vsnon, and trcrn - trcrn, restore all tracers in all categories - vicen, restore ice thickness in all categories - vsnon, restore snow thickness in all categories - velocity, restore uvel and vvel The interior restoring strength is set as follows. The interior mask (restore_mask) specifies a mask that is applied to interior points based on restore_width (the number of gridcells around the exterior to restore) and restore_timescale (the restoring time in days) as follows - all, sets all interior points with full restoring value (restore_timescale) - none, no interior restoring is carried out - constant, restores restore_width gridpoints on the exterior of the domain with full restoring value (restore_timescale) - linear, restores restore_width gridpoints on the exterior of the domain with a linearly decreasing restoring value moving from the exterior (set to restore_timescale) to the interior. The boundary and interior restoring uses the same internal arrays to hold the restoring data. The boundary updates always just set the values on the exterior halo to the restoring values. The interior restoring updates the interior fields with a forcing strength proportional to the model timestep (dt) over the restoring time (restore_timescale). It's important not to do interior restoring more than once per model timestep for each field. The halo updates are done via subroutine ice_restoring_halo while the interior restoring is done via calls to subroutine ice_restoring_interior. A new timer was added, timer_restore, to track restoring time. Documentation was updated, and several tests were added or updated. There is a new script, configuration/scripts/tests/full2nest.sh, that provides a basis for extracting a smaller (nest) regional grid from a (full) run and generating the extended restart files to force the boundary and interior for the nest testcase. The full2nest.sh script describes how to setup that test. All results are bit-for-bit except the boxrestore test case which was modified to produce new results. There are still several issues to investigate - Can the exterior halo values for grid and technical fields (like the advection metrics) be computed directly and exactly for a regional grid rather than by a "zero_gradient" type implementation? Up to now, the only time these values were needed on the halo was in cyclic cases and those halo values can be set by the cyclic bc exactly. - Can/should we be able to mix "zero_gradient" and "linear_extrapolation" for regional bcs in a model run depending on fields (maybe velocity should be extrapolated and concentration should not?) - We should implement restoring for aice, vice, vsno, tracers (not defined by category but then distributed across categories) and maybe subsets of tracer fields (instead of all or none). - Will the regional grids work better with 2 or 3 ghost cells? We need to validate the model with ghost cells greater than 1 and test whether extending the halo and specifying the halo values will improve the regional solutions. - Are the restoring calls in the best place in the code? For instance, can we implement interior restoring in dynamics subcycling (ndtd or ndte) while preserving the restoring forcing strength somehow? Several other minor modifications were made - bound_state was separated from ice_state into it's own module due to some circular dependencies created by adding ice_restoring_halo calls to bound_state to update the exterior halo when required. Also added an optional argument that turns off any restoring in bound_state, needed during initialization. - deprecated restore_bgc feature - maxval_spval in runtime_diagnostics was updated to better reflect the implementation - the restoring calculation for restore_ocn and restore_bgc was maintained but updated to reduce flops - added some memory allocation checks - updated some abort_ice calls - cleaned up indentation in ice_forcing_bgc.F90 - updated restoring calls in all drivers including unit test drivers as needed - removed a couple of unused variables - updated the Boreas port
1 parent 3c20646 commit 52cb686

56 files changed

Lines changed: 1970 additions & 1199 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎cicecore/cicedyn/analysis/ice_diagnostics.F90‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,11 @@ subroutine runtime_diags (dt)
207207
work1, work2 ! temporary
208208

209209
real (kind=dbl_kind), parameter :: &
210-
maxval_spval = -0.9_dbl_kind*HUGE(0.0_dbl_kind) ! spval to detect
210+
maxval_spval = -0.9_dbl_kind*1.0e36_dbl_kind ! spval to detect
211211
! undefined values returned from global_maxval. if global_maxval
212212
! is applied to a region that does not exist (for instance
213213
! southern hemisphere in box cases), global_maxval
214-
! returns -HUGE which we want to avoid writing. The
214+
! returns -1.0e36 which we want to avoid writing. The
215215
! return value is checked against maxval_spval before writing.
216216

217217
character(len=*), parameter :: subname = '(runtime_diags)'

‎cicecore/cicedyn/dynamics/ice_dyn_eap.F90‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ subroutine eap (dt)
121121
use ice_grid, only: tmask, umask, dxT, dyT, dxU, dyU, &
122122
tarear, uarear, grid_average_X2Y, &
123123
grid_atm_dynu, grid_atm_dynv, grid_ocn_dynu, grid_ocn_dynv
124+
use ice_restoring, only: ice_restoring_halo
124125
use ice_state, only: aice, aiU, vice, vsno, uvel, vvel, divu, shear, vort, &
125126
aice_init, aice0, aicen, vicen, strength
126127
use ice_timers, only: timer_dynamics, timer_bound, &
@@ -520,6 +521,8 @@ subroutine eap (dt)
520521
call ice_timer_stop(timer_bound)
521522
call unstack_fields(fld2, uvel, vvel)
522523

524+
call ice_restoring_halo(setfld='velocity')
525+
523526
enddo ! subcycling
524527

525528
if (maskhalo_dyn) call ice_HaloDestroy(halo_info_mask)

‎cicecore/cicedyn/dynamics/ice_dyn_evp.F90‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ subroutine evp (dt)
285285
dxE, dxN, dxT, dxU, dyE, dyN, dyT, dyU, &
286286
tarear, uarear, earear, narear, grid_average_X2Y, uarea, &
287287
grid_ice, grid_atm_dynu, grid_atm_dynv, grid_ocn_dynu, grid_ocn_dynv
288+
use ice_restoring, only: ice_restoring_halo
288289
use ice_state, only: aice, aiU, vice, vsno, uvel, vvel, uvelN, vvelN, &
289290
uvelE, vvelE, divu, shear, vort, &
290291
aice_init, aice0, aicen, vicen, strength
@@ -907,6 +908,7 @@ subroutine evp (dt)
907908
call dyn_haloUpdate (halo_info, halo_info_mask, &
908909
field_loc_NEcorner, field_type_vector, &
909910
uvel, vvel)
911+
call ice_restoring_halo(setfld='velocity')
910912

911913
enddo ! sub cycling
912914
endif ! evp algorithm
@@ -1094,6 +1096,7 @@ subroutine evp (dt)
10941096
call dyn_haloUpdate (halo_info, halo_info_mask, &
10951097
field_loc_NEcorner, field_type_vector, &
10961098
uvel, vvel)
1099+
call ice_restoring_halo(setfld='velocity')
10971100

10981101
enddo ! subcycling
10991102

@@ -1285,6 +1288,7 @@ subroutine evp (dt)
12851288
call dyn_haloUpdate (halo_info, halo_info_mask, &
12861289
field_loc_NEcorner, field_type_vector, &
12871290
uvel, vvel)
1291+
call ice_restoring_halo(setfld='velocity')
12881292

12891293
enddo ! subcycling
12901294

‎cicecore/cicedyn/dynamics/ice_dyn_vp.F90‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,7 @@ subroutine anderson_solver (icellT , icellU , &
682682
use ice_grid, only: dxT, dyT, uarear
683683
use ice_dyn_shared, only: DminTarea, dxhy, dyhx, cxp, cyp, cxm, cym
684684
use ice_state, only: uvel, vvel, strength
685+
use ice_restoring, only: ice_restoring_halo
685686
use ice_timers, only: ice_timer_start, ice_timer_stop, timer_bound
686687

687688
integer (kind=int_kind), intent(in) :: &
@@ -1092,6 +1093,8 @@ subroutine anderson_solver (icellT , icellU , &
10921093
call ice_timer_stop(timer_bound)
10931094
call unstack_fields(fld2, uvel, vvel)
10941095

1096+
call ice_restoring_halo(setfld='velocity')
1097+
10951098
! Compute "progress" residual norm
10961099
!$OMP PARALLEL DO PRIVATE(iblk)
10971100
do iblk = 1, nblocks

‎cicecore/cicedyn/dynamics/ice_transport_driver.F90‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,8 @@ subroutine transport_remap (dt)
258258
use ice_domain_size, only: ncat, max_blocks
259259
use ice_blocks, only: nx_block, ny_block, block, get_block, nghost
260260
use ice_state, only: aice0, aicen, vicen, vsnon, trcrn, &
261-
uvel, vvel, bound_state, uvelE, vvelN
261+
uvel, vvel, uvelE, vvelN
262+
use ice_bound_state, only: bound_state
262263
use ice_grid, only: tarea, grid_ice
263264
use ice_calendar, only: istep1
264265
use ice_timers, only: ice_timer_start, ice_timer_stop, &
@@ -706,13 +707,15 @@ end subroutine transport_remap
706707

707708
subroutine transport_upwind (dt)
708709

709-
use ice_boundary, only: ice_HaloUpdate
710+
use ice_boundary, only: ice_HaloUpdate, ice_HaloExtrapolate
710711
use ice_blocks, only: nx_block, ny_block, block, get_block, nx_block, ny_block
711-
use ice_domain, only: blocks_ice, halo_info, nblocks
712+
use ice_domain, only: blocks_ice, halo_info, nblocks, distrb_info, &
713+
ew_boundary_type, ns_boundary_type
712714
use ice_domain_size, only: ncat, max_blocks
713715
use ice_state, only: aice0, aicen, vicen, vsnon, trcrn, &
714-
uvel, vvel, trcr_depend, bound_state, trcr_base, &
716+
uvel, vvel, trcr_depend, trcr_base, &
715717
n_trcr_strata, nt_strata, uvelE, vvelN
718+
use ice_bound_state, only: bound_state
716719
use ice_flux, only: Tf
717720
use ice_grid, only: HTE, HTN, tarea, tmask, grid_ice
718721
use ice_timers, only: ice_timer_start, ice_timer_stop, &
@@ -793,6 +796,10 @@ subroutine transport_upwind (dt)
793796
!$OMP END PARALLEL DO
794797

795798
call ice_timer_start(timer_bound)
799+
call ice_HaloExtrapolate(uee, distrb_info, &
800+
ew_boundary_type, ns_boundary_type)
801+
call ice_HaloExtrapolate(vnn, distrb_info, &
802+
ew_boundary_type, ns_boundary_type)
796803
call ice_HaloUpdate (uee, halo_info, &
797804
field_loc_Eface, field_type_vector)
798805
call ice_HaloUpdate (vnn, halo_info, &
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
!=======================================================================
2+
!
3+
! Primary state variables in various configurations
4+
! Note: other state variables are at the end of this...
5+
! The primary state variable names are:
6+
!-------------------------------------------------------------------
7+
! for each category aggregated over units
8+
! categories
9+
!-------------------------------------------------------------------
10+
! aicen(i,j,n) aice(i,j) ---
11+
! vicen(i,j,n) vice(i,j) m
12+
! vsnon(i,j,n) vsno(i,j) m
13+
! trcrn(i,j,it,n) trcr(i,j,it)
14+
!
15+
! Area is dimensionless because aice is the fractional area
16+
! (normalized so that the sum over all categories, including open
17+
! water, is 1.0). That is why vice/vsno have units of m instead of m^3.
18+
!
19+
! Variable names follow these rules:
20+
!
21+
! (1) For 3D variables (indices i,j,n), write 'ice' or 'sno' or
22+
! 'sfc' and put an 'n' at the end.
23+
! (2) For 2D variables (indices i,j) aggregated over all categories,
24+
! write 'ice' or 'sno' or 'sfc' without the 'n'.
25+
! (3) For 2D variables (indices i,j) associated with an individual
26+
! category, write 'i' or 's' instead of 'ice' or 'sno' and put an 'n'
27+
! at the end: e.g. hin, hsn. These are not declared here
28+
! but in individual modules (e.g., icepack_therm_vertical).
29+
!
30+
! authors C. M. Bitz, UW
31+
! Elizabeth C. Hunke and William H. Lipscomb, LANL
32+
!
33+
! 2004: Block structure added by William Lipscomb
34+
! 2006: Converted to free form source (F90) by Elizabeth Hunke
35+
36+
module ice_bound_state
37+
38+
use ice_kinds_mod
39+
use ice_constants, only: field_loc_center, field_type_scalar, c0
40+
use ice_exit, only: abort_ice
41+
use ice_fileunits, only: nu_diag
42+
! use icepack_intfc, only: icepack_query_tracer_sizes
43+
! use icepack_intfc, only: icepack_warnings_flush, icepack_warnings_aborted
44+
45+
implicit none
46+
private
47+
public :: bound_state
48+
49+
!=======================================================================
50+
51+
contains
52+
53+
!=======================================================================
54+
!
55+
! Get ghost cell values for ice state variables in each thickness category.
56+
! NOTE: This subroutine cannot be called from inside a block loop!
57+
!
58+
! author: William H. Lipscomb, LANL
59+
60+
subroutine bound_state (aicen, &
61+
vicen, vsnon, &
62+
ntrcr, trcrn, &
63+
restore)
64+
65+
use ice_boundary, only: ice_halo, ice_HaloMask, ice_HaloUpdate, &
66+
ice_HaloDestroy
67+
use ice_domain_size, only: max_blocks, ncat
68+
use ice_blocks, only: nx_block, ny_block
69+
use ice_domain, only: halo_info, maskhalo_bound, nblocks
70+
use ice_restoring, only: ice_restoring_halo
71+
72+
integer (kind=int_kind), intent(in) :: &
73+
ntrcr ! number of tracers in use
74+
75+
real (kind=dbl_kind), dimension(nx_block,ny_block,ncat,max_blocks), intent(inout) :: &
76+
aicen , & ! fractional ice area
77+
vicen , & ! volume per unit area of ice (m)
78+
vsnon ! volume per unit area of snow (m)
79+
80+
real (kind=dbl_kind), intent(inout), dimension(:,:,:,:,:) :: & ! (nx_block,ny_block,ntrcr,ncat,max_blocks)
81+
trcrn ! ice tracers
82+
83+
logical (kind=log_kind), intent(in), optional :: &
84+
restore
85+
86+
! local variables
87+
88+
integer (kind=int_kind) :: i, j, n, iblk
89+
90+
integer (kind=int_kind), &
91+
dimension(nx_block,ny_block,max_blocks) :: halomask
92+
93+
type (ice_halo) :: halo_info_aicemask ! halo mask
94+
95+
logical (kind=log_kind) :: lrestore ! local restart flag
96+
97+
character(len=*), parameter :: subname = '(bound_state)'
98+
99+
if (present(restore)) then
100+
lrestore = restore
101+
else
102+
lrestore = .true.
103+
endif
104+
105+
call ice_HaloUpdate (aicen, halo_info, &
106+
field_loc_center, field_type_scalar)
107+
108+
if (maskhalo_bound) then
109+
halomask(:,:,:) = 0
110+
111+
!$OMP PARALLEL DO PRIVATE(iblk,n,i,j)
112+
do iblk = 1, nblocks
113+
do n = 1, ncat
114+
do j = 1, ny_block
115+
do i = 1, nx_block
116+
if (aicen(i,j,n,iblk) > c0) halomask(i,j,iblk) = 1
117+
enddo
118+
enddo
119+
enddo
120+
enddo
121+
!$OMP END PARALLEL DO
122+
123+
call ice_HaloMask(halo_info_aicemask, halo_info, halomask)
124+
125+
call ice_HaloUpdate (trcrn(:,:,:,:,:), halo_info_aicemask, &
126+
field_loc_center, field_type_scalar)
127+
call ice_HaloUpdate (vicen, halo_info_aicemask, &
128+
field_loc_center, field_type_scalar)
129+
call ice_HaloUpdate (vsnon, halo_info_aicemask, &
130+
field_loc_center, field_type_scalar)
131+
call ice_HaloDestroy(halo_info_aicemask)
132+
133+
else
134+
call ice_HaloUpdate (trcrn(:,:,:,:,:), halo_info, &
135+
field_loc_center, field_type_scalar)
136+
call ice_HaloUpdate (vicen, halo_info, &
137+
field_loc_center, field_type_scalar)
138+
call ice_HaloUpdate (vsnon, halo_info, &
139+
field_loc_center, field_type_scalar)
140+
endif
141+
142+
if (lrestore) then
143+
call ice_restoring_halo(setfld='state')
144+
endif
145+
146+
end subroutine bound_state
147+
148+
!=======================================================================
149+
150+
end module ice_bound_state
151+
152+
!=======================================================================

‎cicecore/cicedyn/general/ice_forcing.F90‎

100755100644
Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
module ice_forcing
2020

2121
use ice_kinds_mod
22-
use ice_boundary, only: ice_HaloUpdate
2322
use ice_blocks, only: nx_block, ny_block
2423
use ice_domain, only: halo_info
2524
use ice_domain_size, only: ncat, max_blocks, nx_global, ny_global, nfreq
@@ -34,7 +33,7 @@ module ice_forcing
3433
ice_open_nc, ice_read_nc, ice_close_nc
3534
use ice_timers, only: ice_timer_start, ice_timer_stop, timer_readwrite, &
3635
timer_bound, timer_forcing
37-
use ice_arrays_column, only: oceanmixed_ice, restore_bgc
36+
use ice_arrays_column, only: oceanmixed_ice
3837
use ice_constants, only: c0, c1, c2, c3, c4, c5, c8, c10, c12, c15, c20, &
3938
c180, c360, c365, c1000, c3600
4039
use ice_constants, only: p001, p01, p1, p2, p25, p5, p6
@@ -160,11 +159,8 @@ module ice_forcing
160159
logical (kind=log_kind), public :: &
161160
restore_ocn ! restore sst if true
162161

163-
integer (kind=int_kind), public :: &
164-
trestore ! restoring time scale (days)
165-
166162
real (kind=dbl_kind), public :: &
167-
trest ! restoring time scale (sec)
163+
trestore ! restoring time scale (days)
168164

169165
logical (kind=log_kind), public :: &
170166
debug_forcing ! prints forcing debugging output if true
@@ -188,6 +184,9 @@ module ice_forcing
188184

189185
! PRIVATE:
190186

187+
real (dbl_kind) :: &
188+
frestore ! restoring value based on trestore (0.-1.)
189+
191190
real (dbl_kind), parameter :: &
192191
mixed_layer_depth_default = c20 ! default mixed layer depth in m
193192

@@ -411,11 +410,11 @@ subroutine init_forcing_ocn(dt)
411410

412411
nbits = 64 ! double precision data
413412

414-
if (restore_ocn .or. restore_bgc) then
415-
if (trestore == 0) then
416-
trest = dt ! use data instantaneously
413+
if (restore_ocn) then
414+
if (trestore == c0) then
415+
frestore = c1 ! use data instantaneously
417416
else
418-
trest = real(trestore,kind=dbl_kind) * secday ! seconds
417+
frestore = max(dt/(trestore*secday),c1)
419418
endif
420419
endif
421420

@@ -731,17 +730,6 @@ subroutine get_forcing_atmo
731730
enddo ! iblk
732731
!$OMP END PARALLEL DO
733732

734-
call ice_timer_start(timer_bound)
735-
call ice_HaloUpdate (swvdr, halo_info, &
736-
field_loc_center, field_type_scalar, fillvalue=c0)
737-
call ice_HaloUpdate (swvdf, halo_info, &
738-
field_loc_center, field_type_scalar, fillvalue=c0)
739-
call ice_HaloUpdate (swidr, halo_info, &
740-
field_loc_center, field_type_scalar, fillvalue=c0)
741-
call ice_HaloUpdate (swidf, halo_info, &
742-
field_loc_center, field_type_scalar, fillvalue=c0)
743-
call ice_timer_stop(timer_bound)
744-
745733
call ice_timer_stop(timer_forcing)
746734

747735
end subroutine get_forcing_atmo
@@ -3629,7 +3617,7 @@ subroutine ocn_data_clim (dt)
36293617
do j = 1, ny_block
36303618
do i = 1, nx_block
36313619
sst(i,j,iblk) = sst(i,j,iblk) &
3632-
+ (sstdat(i,j,iblk)-sst(i,j,iblk))*dt/trest
3620+
+ (sstdat(i,j,iblk)-sst(i,j,iblk))*frestore
36333621
enddo
36343622
enddo
36353623
enddo
@@ -4085,7 +4073,7 @@ subroutine ocn_data_ncar(dt)
40854073
if (restore_ocn) then
40864074
do j = 1, ny_block
40874075
do i = 1, nx_block
4088-
sst(i,j,:) = sst(i,j,:) + (work1(i,j,:)-sst(i,j,:))*dt/trest
4076+
sst(i,j,:) = sst(i,j,:) + (work1(i,j,:)-sst(i,j,:))*frestore
40894077
enddo
40904078
enddo
40914079
! else sst is only updated in ice_ocean.F
@@ -4288,7 +4276,7 @@ subroutine ocn_data_hadgem(dt)
42884276
do j = 1, ny_block
42894277
do i = 1, nx_block
42904278
sst(i,j,iblk) = sst(i,j,iblk) &
4291-
+ (sstdat(i,j,iblk)-sst(i,j,iblk))*dt/trest
4279+
+ (sstdat(i,j,iblk)-sst(i,j,iblk))*frestore
42924280
enddo
42934281
enddo
42944282
enddo

0 commit comments

Comments
 (0)