!=======================================================================
!
!BOP
!
! !MODULE: ice_step_mod
!
! !DESCRIPTION:
!
! Contains CICE component driver routines common to all drivers.
!
! !REVISION HISTORY:
! SVN:$Id: $
!
! authors Elizabeth C. Hunke, LANL
! Philip W. Jones, LANL
! William H. Lipscomb, LANL
!
! 2008 ECH: created module by moving subroutines from drivers/cice4/
!
! !INTERFACE:
!
module ice_step_mod 1,23
!
! !USES:
!
use ice_atmo
use ice_calendar
use ice_communicate
use ice_diagnostics
use ice_domain
use ice_dyn_evp
use ice_fileunits
use ice_flux
use ice_grid
use ice_history
use ice_restart
use ice_itd
use ice_kinds_mod
use ice_mechred
use ice_ocean
use ice_orbital
use ice_shortwave
use ice_state
use ice_therm_itd
use ice_therm_vertical
use ice_timers
use ice_transport_driver
use ice_transport_remap
use perf_mod, only: t_startf, t_stopf, t_barrierf
implicit none
private
save
! !PUBLIC MEMBER FUNCTIONS:
public :: step_therm2, step_dynamics, &
prep_radiation, step_radiation
!
!EOP
!
!=======================================================================
contains
!=======================================================================
!BOP
!
! !ROUTINE: prep_radiation - step pre-thermo radiation
!
! !DESCRIPTION:
!
! !REVISION HISTORY:
!
! authors: Mariana Vertenstein, NCAR
!
! !INTERFACE:
subroutine prep_radiation(dt) 1,1
!
! !USES:
!
! !INPUT/OUTPUT PARAMETERS:
!
real (kind=dbl_kind), intent(in) :: &
dt ! time step
!
!EOP
!
integer (kind=int_kind) :: &
i,j,n,iblk ! block index
if (calc_Tsfc) then
!$OMP PARALLEL DO PRIVATE(iblk)
do iblk = 1, nblocks
call prep_radiation_iblk
(dt, iblk)
end do
!$OMP END PARALLEL DO
else ! .not. calc_Tsfc
! Initialize for safety
do iblk = 1, nblocks
do n = 1, ncat
do j = 1, ny_block
do i = 1, nx_block
fswsfcn(i,j,n,iblk) = c0
fswintn(i,j,n,iblk) = c0
fswthrun(i,j,n,iblk) = c0
enddo ! i
enddo ! j
enddo ! ncat
Iswabsn(:,:,:,iblk) = c0
Sswabsn(:,:,:,iblk) = c0
enddo ! iblk
endif ! calc_Tsfc
end subroutine prep_radiation
!=======================================================================
!BOP
!
! !ROUTINE: prep_radiation_iblk - step pre-thermo radiation
!
! !DESCRIPTION:
!
! !REVISION HISTORY:
!
! authors: David A. Bailey, NCAR
!
! !INTERFACE:
subroutine prep_radiation_iblk (dt, iblk) 1,1
!
! !USES:
!
! !INPUT/OUTPUT PARAMETERS:
!
real (kind=dbl_kind), intent(in) :: &
dt ! time step
integer (kind=int_kind), intent(in) :: &
iblk ! block index
!
!EOP
!
integer (kind=int_kind) :: &
i, j, ij , & ! horizontal indices
ilo,ihi,jlo,jhi, & ! beginning and end of physical domain
n , & ! thickness category index
il1, il2 , & ! ice layer indices for eice
sl1, sl2 ! snow layer indices for esno
integer (kind=int_kind) :: &
icells ! number of cells with aicen > puny
integer (kind=int_kind), dimension(nx_block*ny_block) :: &
indxi, indxj ! indirect indices for cells with aicen > puny
! snow variables for Delta-Eddington shortwave
real (kind=dbl_kind), dimension (nx_block,ny_block) :: &
fsn ! snow horizontal fraction
real (kind=dbl_kind), dimension (nx_block,ny_block,nslyr) :: &
rhosnwn , & ! snow density (kg/m3)
rsnwn ! snow grain radius (micro-meters)
! pond variables for Delta-Eddington shortwave
real (kind=dbl_kind), dimension (nx_block,ny_block) :: &
fpn , & ! pond fraction
hpn ! pond depth (m)
real (kind=dbl_kind) :: netsw, netsw_old, ar
type (block) :: &
this_block ! block information for current block
logical (kind=log_kind) :: &
l_stop ! if true, abort the model
integer (kind=int_kind) :: &
istop, jstop ! indices of grid cell where model aborts
l_stop = .false.
fswfac(:,:,iblk) = c1
this_block = get_block
(blocks_ice(iblk),iblk)
ilo = this_block%ilo
ihi = this_block%ihi
jlo = this_block%jlo
jhi = this_block%jhi
!-----------------------------------------------------------------
! Compute netsw scaling factor (new netsw / old netsw)
!-----------------------------------------------------------------
do j = jlo, jhi
do i = ilo, ihi
if (aice(i,j,iblk) > c0 .and. scale_factor(i,j,iblk) > puny) then
netsw = swvdr(i,j,iblk)*(c1 - alvdr_gbm(i,j,iblk)) &
+ swvdf(i,j,iblk)*(c1 - alvdf_gbm(i,j,iblk)) &
+ swidr(i,j,iblk)*(c1 - alidr_gbm(i,j,iblk)) &
+ swidf(i,j,iblk)*(c1 - alidf_gbm(i,j,iblk))
scale_factor(i,j,iblk) = netsw / scale_factor(i,j,iblk)
else
scale_factor(i,j,iblk) = c1
endif
fswfac(i,j,iblk) = scale_factor(i,j,iblk) ! for history
enddo ! i
enddo ! j
do n = 1, ncat
!-----------------------------------------------------------------
! Identify cells with nonzero ice area
!-----------------------------------------------------------------
icells = 0
do j = jlo, jhi
do i = ilo, ihi
if (aicen(i,j,n,iblk) > puny) then
icells = icells + 1
indxi(icells) = i
indxj(icells) = j
endif
enddo ! i
enddo ! j
!-----------------------------------------------------------------
! Scale absorbed solar radiation for change in net shortwave
!-----------------------------------------------------------------
il1 = ilyr1(n)
il2 = ilyrn(n)
sl1 = slyr1(n)
sl2 = slyrn(n)
do ij = 1, icells
i = indxi(ij)
j = indxj(ij)
fswsfcn(i,j,n,iblk) = scale_factor(i,j,iblk)*fswsfcn (i,j,n,iblk)
fswintn(i,j,n,iblk) = scale_factor(i,j,iblk)*fswintn (i,j,n,iblk)
fswthrun(i,j,n,iblk)= scale_factor(i,j,iblk)*fswthrun(i,j,n,iblk)
Sswabsn(i,j,sl1:sl2,iblk) = &
scale_factor(i,j,iblk)*Sswabsn(i,j,sl1:sl2,iblk)
Iswabsn(i,j,il1:il2,iblk) = &
scale_factor(i,j,iblk)*Iswabsn(i,j,il1:il2,iblk)
enddo
enddo ! ncat
end subroutine prep_radiation_iblk
!=======================================================================
!BOP
!
! !ROUTINE: step_therm2 - step post-coupler thermodynamics
!
! !DESCRIPTION:
!
!-----------------------------------------------------------------------
! Wrapper for driver for thermodynamic changes not needed for coupling:
! transport in thickness space, lateral growth and melting. Needed for
! introducing OpenMP threading more simply.
!
! !REVISION HISTORY:
!
! author: Mariana Vertenstein, NCAR
!
! !INTERFACE:
!
subroutine step_therm2 (dt) 1,9
!
! !USES:
!
! !INPUT/OUTPUT PARAMETERS:
!
real (kind=dbl_kind), intent(in) :: &
dt ! time step
!
!EOP
!
integer (kind=int_kind) :: &
iblk, & ! block index
i, j
call ice_timer_start
(timer_column) ! column physics
call ice_timer_start
(timer_thermo) ! thermodynamics
! call ice_timer_start(timer_tmp) ! temporary timer
!$OMP PARALLEL DO PRIVATE(iblk)
do iblk = 1, nblocks
call step_therm2_iblk
(dt, iblk)
end do
!$OMP END PARALLEL DO
!-------------------------------------------------------------------
! Ghost cell updates for state variables.
!-------------------------------------------------------------------
call ice_timer_start
(timer_bound)
call bound_state
(aicen, trcrn, &
vicen, vsnon, &
eicen, esnon)
call ice_timer_stop
(timer_bound)
!$OMP PARALLEL DO PRIVATE(iblk,i,j)
do iblk = 1, nblocks
!-----------------------------------------------------------------
! Aggregate the updated state variables.
!-----------------------------------------------------------------
call aggregate
(nx_block, ny_block, &
aicen(:,:,:,iblk), trcrn(:,:,:,:,iblk), &
vicen(:,:,:,iblk), vsnon(:,:, :,iblk), &
eicen(:,:,:,iblk), esnon(:,:, :,iblk), &
aice (:,:, iblk), trcr (:,:,:, iblk), &
vice (:,:, iblk), vsno (:,:, iblk), &
eice (:,:, iblk), esno (:,:, iblk), &
aice0(:,:, iblk), tmask(:,:, iblk), &
ntrcr, trcr_depend)
!-----------------------------------------------------------------
! Compute thermodynamic area and volume tendencies.
!-----------------------------------------------------------------
do j = 1, ny_block
do i = 1, nx_block
daidtt(i,j,iblk) = (aice(i,j,iblk) - daidtt(i,j,iblk)) / dt
dvidtt(i,j,iblk) = (vice(i,j,iblk) - dvidtt(i,j,iblk)) / dt
enddo
enddo
enddo ! iblk
!$OMP END PARALLEL DO
! call ice_timer_stop(timer_tmp) ! temporary timer
call ice_timer_stop
(timer_thermo) ! column physics
call ice_timer_stop
(timer_column) ! column physics
end subroutine step_therm2
!=======================================================================
!BOP
!
! !ROUTINE: step_therm2_iblk - step post-coupler thermodynamics
!
! !DESCRIPTION:
!
!-----------------------------------------------------------------------
! Driver for thermodynamic changes not needed for coupling:
! transport in thickness space, lateral growth and melting.
!
! NOTE: Ocean fluxes are initialized here.
!
! !REVISION HISTORY:
!
! author: William H. Lipscomb, LANL
!
! !INTERFACE:
subroutine step_therm2_iblk (dt, iblk) 1,11
!
! !USES:
!
!
! !INPUT/OUTPUT PARAMETERS:
!
real (kind=dbl_kind), intent(in) :: &
dt ! time step
integer (kind=int_kind), intent(in) :: &
iblk ! block index
!
!EOP
!
!lipscomb - delete hicen later?
! real (kind=dbl_kind), &
! dimension (nx_block,ny_block,ncat,max_blocks) :: &
! hicen ! ice thickness (m)
integer (kind=int_kind) :: &
ilo,ihi,jlo,jhi, & ! beginning and end of physical domain
i, j, n
integer (kind=int_kind) :: &
icells ! number of ice/ocean cells
integer (kind=int_kind), dimension(nx_block*ny_block) :: &
indxi, indxj ! indirect indices for ice/ocean cells
type (block) :: &
this_block ! block information for current block
logical (kind=log_kind) :: &
l_stop ! if true, abort model
integer (kind=int_kind) :: &
istop, jstop ! indices of grid cell where model aborts
l_stop = .false.
this_block = get_block
(blocks_ice(iblk),iblk)
ilo = this_block%ilo
ihi = this_block%ihi
jlo = this_block%jlo
jhi = this_block%jhi
!-----------------------------------------------------------------
! Let rain drain through to the ocean.
!-----------------------------------------------------------------
do j = 1, ny_block
do i = 1, nx_block
fresh (i,j,iblk) = fresh(i,j,iblk) &
+ frain(i,j,iblk)*aice(i,j,iblk)
enddo
enddo
!-----------------------------------------------------------------
! Given thermodynamic growth rates, transport ice between
! thickness categories.
!-----------------------------------------------------------------
call ice_timer_start
(timer_catconv, iblk) ! category conversions
if (kitd == 1) then
!-----------------------------------------------------------------
! Compute fractional ice area in each grid cell.
!-----------------------------------------------------------------
call aggregate_area
(nx_block, ny_block, &
aicen(:,:,:,iblk), &
aice (:,:, iblk), aice0(:,:,iblk))
!-----------------------------------------------------------------
! Identify grid cells with ice.
!-----------------------------------------------------------------
icells = 0
do j = jlo,jhi
do i = ilo,ihi
if (aice(i,j,iblk) > puny) then
icells = icells + 1
indxi(icells) = i
indxj(icells) = j
endif
enddo
enddo
if (icells > 0) then
call linear_itd
(nx_block, ny_block, &
icells, indxi, indxj, &
ntrcr, trcr_depend, &
aicen_init(:,:,:,iblk), &
vicen_init(:,:,:,iblk), &
aicen (:,:,:,iblk), &
trcrn (:,:,:,:,iblk), &
vicen (:,:,:,iblk), &
vsnon (:,:,:,iblk), &
eicen (:,:,:,iblk), &
esnon (:,:,:,iblk), &
aice (:,:, iblk), &
aice0 (:,:, iblk), &
l_stop, &
istop, jstop)
if (l_stop) then
write (nu_diag,*) 'istep1, my_task, iblk =', &
istep1, my_task, iblk
write (nu_diag,*) 'Global block:', this_block%block_id
if (istop > 0 .and. jstop > 0) &
write(nu_diag,*) 'Global i and j:', &
this_block%i_glob(istop), &
this_block%j_glob(jstop)
call abort_ice
('ice: Linear ITD error')
endif
endif
endif ! kitd
call ice_timer_stop
(timer_catconv, iblk) ! category conversions
!-----------------------------------------------------------------
! Add frazil ice growing in leads.
!-----------------------------------------------------------------
! identify ice-ocean cells
icells = 0
do j = 1, ny_block
do i = 1, nx_block
if (tmask(i,j,iblk)) then
icells = icells + 1
indxi(icells) = i
indxj(icells) = j
endif
enddo ! i
enddo ! j
call add_new_ice
(nx_block, ny_block, &
ntrcr, icells, &
indxi, indxj, &
tmask (:,:, iblk), dt, &
aicen (:,:,:,iblk), &
trcrn (:,:,:,:,iblk), &
vicen (:,:,:,iblk), &
eicen (:,:,:,iblk), &
aice0 (:,:, iblk), &
aice (:,:, iblk), &
frzmlt (:,:, iblk), &
frazil (:,:, iblk), &
frz_onset(:,:, iblk), yday, &
fresh (:,:, iblk), &
fsalt (:,:, iblk), &
Tf (:,:, iblk), l_stop, &
istop, jstop)
if (l_stop) then
write (nu_diag,*) 'istep1, my_task, iblk =', &
istep1, my_task, iblk
write (nu_diag,*) 'Global block:', this_block%block_id
if (istop > 0 .and. jstop > 0) &
write(nu_diag,*) 'Global i and j:', &
this_block%i_glob(istop), &
this_block%j_glob(jstop)
call abort_ice
('ice: add_new_ice error')
endif
!-----------------------------------------------------------------
! Melt ice laterally.
!-----------------------------------------------------------------
call lateral_melt
(nx_block, ny_block, &
ilo, ihi, jlo, jhi, &
dt, &
fresh (:,:, iblk), &
fsalt (:,:, iblk), &
fhocn (:,:, iblk), &
fsoot (:,:,:,iblk), &
rside (:,:, iblk), &
meltl (:,:, iblk), &
aicen (:,:,:,iblk), &
vicen (:,:,:,iblk), &
vsnon (:,:,:,iblk), &
eicen (:,:,:,iblk), &
esnon (:,:,:,iblk), &
trcrn (:,:,:,:,iblk) )
!-----------------------------------------------------------------
! For the special case of a single category, adjust the area and
! volume (assuming that half the volume change decreases the
! thickness, and the other half decreases the area).
!-----------------------------------------------------------------
!NOTE - this does not work - hicen_init is not defined - ECH
! if (ncat==1) &
! call reduce_area (nx_block, ny_block, &
! ilo, ihi, jlo, jhi, &
! tmask (:,:, iblk), &
! aicen (:,:,:,iblk), &
! vicen (:,:,:,iblk), &
! hicen_init(:,:,1,iblk), &
! hicen (:,:,1,iblk))
!-----------------------------------------------------------------
! ITD cleanup: Rebin thickness categories if necessary, and remove
! categories with very small areas.
!-----------------------------------------------------------------
call cleanup_itd
(nx_block, ny_block, &
ilo, ihi, jlo, jhi, &
dt, ntrcr, &
aicen (:,:,:,iblk), trcrn (:,:,:,:,iblk), &
vicen (:,:,:,iblk), vsnon (:,:, :,iblk), &
eicen (:,:,:,iblk), esnon (:,:, :,iblk), &
aice0 (:,:, iblk), aice (:,:,iblk), &
trcr_depend, &
fresh (:,:, iblk), fsalt (:,:, iblk), &
fhocn (:,:, iblk), fsoot (:,:,:,iblk), &
tr_aero, &
heat_capacity, l_stop, &
istop, jstop)
if (l_stop) then
write (nu_diag,*) 'istep1, my_task, iblk =', &
istep1, my_task, iblk
write (nu_diag,*) 'Global block:', this_block%block_id
if (istop > 0 .and. jstop > 0) &
write(nu_diag,*) 'Global i and j:', &
this_block%i_glob(istop), &
this_block%j_glob(jstop)
call abort_ice
('ice: ITD cleanup error')
endif
end subroutine step_therm2_iblk
!=======================================================================
!BOP
!
! !ROUTINE: step_dynamics - step ice dynamics, transport, and ridging
!
! !DESCRIPTION:
!
! Run one time step of dynamics, horizontal transport, and ridging.
! NOTE: The evp and transport modules include boundary updates, so
! they cannot be done inside a single block loop. Ridging
! and cleanup, on the other hand, are single-column operations.
! They are called with argument lists inside block loops
! to increase modularity.
!
! !REVISION HISTORY:
!
! authors: William H. Lipscomb, LANL
!
! !INTERFACE:
subroutine step_dynamics(dt_dyn,dt_thm) 2,19
!
! !USES:
!
! !INPUT/OUTPUT PARAMETERS:
!
real (kind=dbl_kind), intent(in) :: &
dt_dyn , & ! dynamic time step
dt_thm ! thermodynamic time step for diagnostics
!
!EOP
!
type (block) :: &
this_block ! block information for current block
integer (kind=int_kind) :: &
iblk , & ! block index
i,j , & ! horizontal indices
ilo,ihi,jlo,jhi ! beginning and end of physical domain
integer (kind=int_kind) :: &
icells ! number of cells with aicen > puny
integer (kind=int_kind), dimension(nx_block*ny_block) :: &
indxi, indxj ! indirect indices for cells with aicen > puny
logical (kind=log_kind) :: &
l_stop ! if true, abort model
integer (kind=int_kind) :: &
istop, jstop ! indices of grid cell where model aborts
call init_history_dyn
! initialize dynamic history variables
dynCnt = dynCnt + 1
!-----------------------------------------------------------------
! Elastic-viscous-plastic ice dynamics
!-----------------------------------------------------------------
call t_barrierf ('cice_dyn_evp_BARRIER',MPI_COMM_ICE)
call t_startf ('cice_dyn_evp')
if (kdyn == 1) call evp
(dt_dyn)
call t_stopf ('cice_dyn_evp')
!-----------------------------------------------------------------
! Horizontal ice transport
!-----------------------------------------------------------------
call t_barrierf ('cice_dyn_horz_transport_BARRIER',MPI_COMM_ICE)
call t_startf ('cice_dyn_horz_transport')
if (advection == 'upwind') then
call transport_upwind
(dt_dyn) ! upwind
else
call transport_remap
(dt_dyn) ! incremental remapping
endif
call t_stopf ('cice_dyn_horz_transport')
!-----------------------------------------------------------------
! Ridging
!-----------------------------------------------------------------
call ice_timer_start
(timer_column)
call ice_timer_start
(timer_ridge)
call t_barrierf ('cice_dyn_ridge_BARRIER',MPI_COMM_ICE)
call t_startf ('cice_dyn_ridge')
l_stop = .false.
!$OMP PARALLEL DO PRIVATE(iblk,this_block,ilo,ihi,jlo,jhi,&
!$OMP icells,indxi,indxj,l_stop,istop,jstop)
do iblk = 1, nblocks
this_block = get_block
(blocks_ice(iblk), iblk)
ilo = this_block%ilo
ihi = this_block%ihi
jlo = this_block%jlo
jhi = this_block%jhi
!-----------------------------------------------------------------
! Identify ice-ocean cells.
! Note: We can not define icells here using aice>puny because
! aice has not yet been updated since the transport (and
! it may be out of whack, which the ridging helps fix).-ECH
!-----------------------------------------------------------------
icells = 0
do j = jlo, jhi
do i = ilo, ihi
!PERF There is a performance advantage here to only perform the ridging over a limited set of points
!PERF if (tmask(i,j,iblk) .and. aice(i,j,iblk) > c0) then
if (tmask(i,j,iblk)) then
icells = icells + 1
indxi(icells) = i
indxj(icells) = j
endif
enddo ! i
enddo ! j
if (icells > 0) then
call ridge_ice
(nx_block, ny_block, &
dt_dyn, dt_thm, &
ntrcr, icells, &
indxi, indxj, &
!! Delt (:,:, iblk), divu (:,:, iblk), &
rdg_conv(:,:, iblk), rdg_shear (:,:, iblk), &
aicen (:,:,:,iblk), trcrn (:,:,:,:,iblk), &
vicen (:,:,:,iblk), vsnon (:,:,:,iblk), &
eicen (:,:,:,iblk), esnon (:,:,:,iblk), &
aice0 (:,:, iblk), &
trcr_depend, l_stop, &
istop, jstop, &
dardg1dt(:,:,iblk), dardg2dt (:,:,iblk), &
dvirdgdt(:,:,iblk), opening (:,:,iblk), &
fresh (:,:,iblk), fhocn (:,:,iblk), &
fsoot (:,:,:,iblk))
if (l_stop) then
write (nu_diag,*) 'istep1, my_task, iblk =', &
istep1, my_task, iblk
write (nu_diag,*) 'Global block:', this_block%block_id
if (istop > 0 .and. jstop > 0) &
write(nu_diag,*) 'Global i and j:', &
this_block%i_glob(istop), &
this_block%j_glob(jstop)
call abort_ice
('ice: Ridging error')
endif
endif
enddo ! iblk
!$OMP END PARALLEL DO
call ice_timer_stop
(timer_ridge)
call t_stopf ('cice_dyn_ridge')
call t_barrierf ('cice_dyn_column_BARRIER',MPI_COMM_ICE)
call t_startf ('cice_dyn_column')
!$OMP PARALLEL DO PRIVATE(iblk,this_block,ilo,ihi,jlo,jhi,&
!$OMP icells,indxi,indxj,l_stop,istop,jstop)
do iblk = 1, nblocks
this_block = get_block
(blocks_ice(iblk), iblk)
ilo = this_block%ilo
ihi = this_block%ihi
jlo = this_block%jlo
jhi = this_block%jhi
!-----------------------------------------------------------------
! ITD cleanup: Rebin thickness categories if necessary, and remove
! categories with very small areas.
!-----------------------------------------------------------------
call cleanup_itd
(nx_block, ny_block, &
ilo, ihi, jlo, jhi, &
dt_thm, ntrcr, &
aicen (:,:,:,iblk), trcrn (:,:,:,:,iblk), &
vicen (:,:,:,iblk), vsnon (:,:, :,iblk), &
eicen (:,:,:,iblk), esnon (:,:, :,iblk), &
aice0 (:,:, iblk), aice (:,:,iblk), &
trcr_depend, &
fresh (:,:, iblk), fsalt (:,:, iblk), &
fhocn (:,:, iblk), fsoot (:,:,:,iblk), &
tr_aero, &
heat_capacity, l_stop, &
istop, jstop)
if (l_stop) then
write (nu_diag,*) 'istep1, my_task, iblk =', &
istep1, my_task, iblk
write (nu_diag,*) 'Global block:', this_block%block_id
if (istop > 0 .and. jstop > 0) &
write(nu_diag,*) 'Global i and j:', &
this_block%i_glob(istop), &
this_block%j_glob(jstop)
call abort_ice
('ice: ITD cleanup error')
endif
enddo ! iblk
!$OMP END PARALLEL DO
call t_stopf ('cice_dyn_column')
!-------------------------------------------------------------------
! Ghost cell updates for state variables.
!-------------------------------------------------------------------
call t_barrierf ('cice_dyn_bound_BARRIER',MPI_COMM_ICE)
call t_startf ('cice_dyn_bound')
call ice_timer_start
(timer_bound)
call bound_state
(aicen, trcrn, &
vicen, vsnon, &
eicen, esnon)
call ice_timer_stop
(timer_bound)
call t_stopf ('cice_dyn_bound')
call t_barrierf ('cice_dyn_agg_BARRIER',MPI_COMM_ICE)
call t_startf ('cice_dyn_agg')
!$OMP PARALLEL DO PRIVATE(iblk,this_block,ilo,ihi,jlo,jhi,i,j)
do iblk = 1, nblocks
!-----------------------------------------------------------------
! Aggregate the updated state variables.
!-----------------------------------------------------------------
call aggregate
(nx_block, ny_block, &
aicen(:,:,:,iblk), trcrn(:,:,:,:,iblk), &
vicen(:,:,:,iblk), vsnon(:,:, :,iblk), &
eicen(:,:,:,iblk), esnon(:,:, :,iblk), &
aice (:,:, iblk), trcr (:,:,:, iblk), &
vice (:,:, iblk), vsno (:,:, iblk), &
eice (:,:, iblk), esno (:,:, iblk), &
aice0(:,:, iblk), tmask(:,:, iblk), &
ntrcr, trcr_depend)
!-----------------------------------------------------------------
! Compute dynamic area and volume tendencies.
!-----------------------------------------------------------------
this_block = get_block
(blocks_ice(iblk),iblk)
ilo = this_block%ilo
ihi = this_block%ihi
jlo = this_block%jlo
jhi = this_block%jhi
do j = jlo,jhi
do i = ilo,ihi
dvidtd(i,j,iblk) = (vice(i,j,iblk) - dvidtd(i,j,iblk)) /dt_dyn
daidtd(i,j,iblk) = (aice(i,j,iblk) - daidtd(i,j,iblk)) /dt_dyn
enddo
enddo
enddo ! iblk
!$OMP END PARALLEL DO
call t_stopf ('cice_dyn_agg')
call ice_timer_stop
(timer_column)
end subroutine step_dynamics
!=======================================================================
!BOP
!
! !ROUTINE: step_radiation - step pre-coupler radiation
!
! !DESCRIPTION:
!
! !REVISION HISTORY:
!
! authors: Mariana Vertenstein, NCAR
!
! !INTERFACE:
subroutine step_radiation(dt) 1,1
!
! !USES:
!
! !INPUT/OUTPUT PARAMETERS:
!
real (kind=dbl_kind), intent(in) :: &
dt ! time step
!
!EOP
!
integer (kind=int_kind) :: &
i,j,n,iblk ! block index
alvdr(:,:,:) = c0
alvdf(:,:,:) = c0
alidr(:,:,:) = c0
alidf(:,:,:) = c0
Sswabsn(:,:,:,:) = c0
#ifdef AEROFRC
dalvdr_noaero(:,:,:) = c0
dalvdf_noaero(:,:,:) = c0
dalidr_noaero(:,:,:) = c0
dalidf_noaero(:,:,:) = c0
dSswabsn_noaero(:,:,:,:) = c0
#endif
#ifdef PONDFRC
dalvdr_nopond(:,:,:) = c0
dalvdf_nopond(:,:,:) = c0
dalidr_nopond(:,:,:) = c0
dalidf_nopond(:,:,:) = c0
dSswabsn_nopond(:,:,:,:) = c0
#endif
! do iblk = 1,nblocks
! alvdr(:,:,iblk) = c0
! alvdf(:,:,iblk) = c0
! alidr(:,:,iblk) = c0
! alidf(:,:,iblk) = c0
! Sswabsn(:,:,:,iblk) = c0
! enddo
if (calc_Tsfc) then
!$OMP PARALLEL DO PRIVATE(iblk)
do iblk = 1, nblocks
call step_radiation_iblk
(dt, iblk)
end do
!$OMP END PARALLEL DO
else ! .not. calc_Tsfc
! Initialize for safety
do iblk = 1, nblocks
do n = 1, ncat
do j = 1, ny_block
do i = 1, nx_block
alvdrn(i,j,n,iblk) = c0
alidrn(i,j,n,iblk) = c0
alvdfn(i,j,n,iblk) = c0
alidfn(i,j,n,iblk) = c0
fswsfcn(i,j,n,iblk) = c0
fswintn(i,j,n,iblk) = c0
fswthrun(i,j,n,iblk) = c0
enddo ! i
enddo ! j
enddo ! ncat
Iswabsn(:,:,:,iblk) = c0
Sswabsn(:,:,:,iblk) = c0
enddo ! iblk
endif ! calc_Tsfc
end subroutine step_radiation
!=======================================================================
!BOP
!
! !ROUTINE: step_radiation_iblk - step pre-coupler radiation
!
! !DESCRIPTION:
!
! !REVISION HISTORY:
!
! authors: David A. Bailey, NCAR
!
! !INTERFACE:
subroutine step_radiation_iblk (dt, iblk) 1,9
!
! !USES:
!
! !INPUT/OUTPUT PARAMETERS:
!
real (kind=dbl_kind), intent(in) :: &
dt ! time step
integer (kind=int_kind), intent(in) :: &
iblk ! block index
!
!EOP
!
integer (kind=int_kind) :: &
i, j, ij , & ! horizontal indices
ilo,ihi,jlo,jhi, & ! beginning and end of physical domain
n , & ! thickness category index
il1, il2 , & ! ice layer indices for eice
sl1, sl2 ! snow layer indices for esno
integer (kind=int_kind) :: &
icells ! number of cells with aicen > puny
integer (kind=int_kind), dimension(nx_block*ny_block) :: &
indxi, indxj ! indirect indices for cells with aicen > puny
! snow variables for Delta-Eddington shortwave
real (kind=dbl_kind), dimension (nx_block,ny_block) :: &
fsn ! snow horizontal fraction
real (kind=dbl_kind), dimension (nx_block,ny_block,nslyr) :: &
rhosnwn , & ! snow density (kg/m3)
rsnwn ! snow grain radius (micro-meters)
! pond variables for Delta-Eddington shortwave
real (kind=dbl_kind), dimension (nx_block,ny_block) :: &
fpn , & ! pond fraction
hpn ! pond depth (m)
type (block) :: &
this_block ! block information for current block
logical (kind=log_kind) :: &
l_stop ! if true, abort the model
integer (kind=int_kind) :: &
istop, jstop ! indices of grid cell where model aborts
l_stop = .false.
this_block = get_block
(blocks_ice(iblk),iblk)
ilo = this_block%ilo
ihi = this_block%ihi
jlo = this_block%jlo
jhi = this_block%jhi
!-----------------------------------------------------------------
! Compute cosine of solar zenith angle.
! This is used by the delta-Eddington shortwave module.
! Albedos are aggregated in merge_fluxes only for cells w/ coszen > 0.
! For basic shortwave, simply set coszen to a constant between 0 and 1.
!-----------------------------------------------------------------
if (trim(shortwave) == 'dEdd') then ! delta Eddington
! identify ice-ocean cells
icells = 0
do j = 1, ny_block
do i = 1, nx_block
if (tmask(i,j,iblk)) then
icells = icells + 1
indxi(icells) = i
indxj(icells) = j
endif
enddo ! i
enddo ! j
call compute_coszen
(nx_block, ny_block, &
icells, &
indxi, indxj, &
tlat (:,:,iblk), tlon(:,:,iblk), &
coszen(:,:,iblk), dt)
else ! basic (ccsm3) shortwave
coszen(:,:,iblk) = p5 ! sun above the horizon
endif
do n = 1, ncat
!-----------------------------------------------------------------
! Identify cells with nonzero ice area
!-----------------------------------------------------------------
icells = 0
do j = jlo, jhi
do i = ilo, ihi
if (aicen(i,j,n,iblk) > puny) then
icells = icells + 1
indxi(icells) = i
indxj(icells) = j
endif
enddo ! i
enddo ! j
!-----------------------------------------------------------------
! Solar radiation: albedo and absorbed shortwave
!-----------------------------------------------------------------
il1 = ilyr1(n)
il2 = ilyrn(n)
sl1 = slyr1(n)
sl2 = slyrn(n)
if (trim(shortwave) == 'dEdd') then ! delta Eddington
! note that rhoswn, rsnw, fp, hp and Sswabs ARE NOT dimensioned with ncat
! BPB 19 Dec 2006
! set snow properties
call shortwave_dEdd_set_snow
(nx_block, ny_block, &
icells, &
indxi, indxj, &
aicen(:,:,n,iblk), vsnon(:,:,n,iblk), &
trcrn(:,:,nt_Tsfc,n,iblk), fsn, &
rhosnwn, rsnwn)
if (.not. tr_pond) then
! set pond properties
call shortwave_dEdd_set_pond
(nx_block, ny_block, &
icells, &
indxi, indxj, &
aicen(:,:,n,iblk), &
trcrn(:,:,nt_Tsfc,n,iblk), &
fsn, fpn, &
hpn)
else
fpn(:,:) = apondn(:,:,n,iblk)
hpn(:,:) = hpondn(:,:,n,iblk)
endif
#ifdef AEROFRC
! Diagnose aerosol forcing
if (tr_aero) then
tr_aero = .false.
call shortwave_dEdd
(nx_block, ny_block, &
icells, &
indxi, indxj, &
coszen(:,:, iblk), &
aicen(:,:,n,iblk), vicen(:,:,n,iblk), &
vsnon(:,:,n,iblk), fsn, &
rhosnwn, rsnwn, &
fpn, hpn, &
trcrn(:,:,:,n,iblk), tarea(:,:,iblk), &
swvdr(:,:, iblk), swvdf(:,:, iblk), &
swidr(:,:, iblk), swidf(:,:, iblk), &
dalvdrn_noaero(:,:,n,iblk), &
dalvdfn_noaero(:,:,n,iblk), &
dalidrn_noaero(:,:,n,iblk), &
dalidfn_noaero(:,:,n,iblk), &
dfswsfcn_noaero(:,:,n,iblk), &
dfswintn_noaero(:,:,n,iblk), &
dfswthrun_noaero(:,:,n,iblk), &
dSswabsn_noaero(:,:,sl1:sl2,iblk), &
dIswabsn_noaero(:,:,il1:il2,iblk), &
dalbicen_noaero(:,:,n,iblk), &
dalbsnon_noaero(:,:,n,iblk), &
dalbpndn_noaero(:,:,n,iblk))
tr_aero = .true.
endif
#endif
#ifdef PONDFRC
! Diagnose pond forcing
if (tr_pond) then
tr_aero = .false.
fpn(:,:) = c0
hpn(:,:) = c0
call shortwave_dEdd
(nx_block, ny_block, &
icells, &
indxi, indxj, &
coszen(:,:, iblk), &
aicen(:,:,n,iblk), vicen(:,:,n,iblk), &
vsnon(:,:,n,iblk), fsn, &
rhosnwn, rsnwn, &
fpn, hpn, &
trcrn(:,:,:,n,iblk), tarea(:,:,iblk), &
swvdr(:,:, iblk), swvdf(:,:, iblk), &
swidr(:,:, iblk), swidf(:,:, iblk), &
dalvdrn_nopond(:,:,n,iblk), &
dalvdfn_nopond(:,:,n,iblk), &
dalidrn_nopond(:,:,n,iblk), &
dalidfn_nopond(:,:,n,iblk), &
dfswsfcn_nopond(:,:,n,iblk), &
dfswintn_nopond(:,:,n,iblk), &
dfswthrun_nopond(:,:,n,iblk), &
dSswabsn_nopond(:,:,sl1:sl2,iblk), &
dIswabsn_nopond(:,:,il1:il2,iblk), &
dalbicen_nopond(:,:,n,iblk), &
dalbsnon_nopond(:,:,n,iblk), &
dalbpndn_nopond(:,:,n,iblk))
fpn(:,:) = apondn(:,:,n,iblk)
hpn(:,:) = hpondn(:,:,n,iblk)
tr_aero = .true.
endif
#endif
#ifdef CCSM3FRC
call shortwave_ccsm3
(nx_block, ny_block, &
icells, &
indxi, indxj, &
aicen(:,:,n,iblk), vicen(:,:,n,iblk), &
vsnon(:,:,n,iblk), &
trcrn(:,:,nt_Tsfc,n,iblk), &
swvdr(:,:, iblk), swvdf(:,:, iblk), &
swidr(:,:, iblk), swidf(:,:, iblk), &
dalvdrn_ccsm3(:,:,n,iblk), &
dalidrn_ccsm3(:,:,n,iblk), &
dalvdfn_ccsm3(:,:,n,iblk), &
dalidfn_ccsm3(:,:,n,iblk), &
dfswsfcn_ccsm3(:,:,n,iblk), &
dfswintn_ccsm3(:,:,n,iblk), &
dfswthrun_ccsm3(:,:,n,iblk), &
dIswabsn_ccsm3(:,:,il1:il2,iblk), &
dalbicen_ccsm3(:,:,n,iblk), &
dalbsnon_ccsm3(:,:,n,iblk))
#endif
call shortwave_dEdd
(nx_block, ny_block, &
icells, &
indxi, indxj, &
coszen(:,:, iblk), &
aicen(:,:,n,iblk), vicen(:,:,n,iblk), &
vsnon(:,:,n,iblk), fsn, &
rhosnwn, rsnwn, &
fpn, hpn, &
trcrn(:,:,:,n,iblk), tarea(:,:,iblk), &
swvdr(:,:, iblk), swvdf(:,:, iblk), &
swidr(:,:, iblk), swidf(:,:, iblk), &
alvdrn(:,:,n,iblk),alvdfn(:,:,n,iblk), &
alidrn(:,:,n,iblk),alidfn(:,:,n,iblk), &
fswsfcn(:,:,n,iblk),fswintn(:,:,n,iblk),&
fswthrun(:,:,n,iblk), &
Sswabsn(:,:,sl1:sl2,iblk), &
Iswabsn(:,:,il1:il2,iblk), &
albicen(:,:,n,iblk), &
albsnon(:,:,n,iblk),albpndn(:,:,n,iblk))
else
Sswabsn(:,:,sl1:sl2,iblk) = c0
call shortwave_ccsm3
(nx_block, ny_block, &
icells, &
indxi, indxj, &
aicen(:,:,n,iblk), vicen(:,:,n,iblk), &
vsnon(:,:,n,iblk), &
trcrn(:,:,nt_Tsfc,n,iblk), &
swvdr(:,:, iblk), swvdf(:,:, iblk), &
swidr(:,:, iblk), swidf(:,:, iblk), &
alvdrn(:,:,n,iblk),alidrn(:,:,n,iblk), &
alvdfn(:,:,n,iblk),alidfn(:,:,n,iblk), &
fswsfcn(:,:,n,iblk),fswintn(:,:,n,iblk),&
fswthrun(:,:,n,iblk), &
Iswabsn(:,:,il1:il2,iblk), &
albicen(:,:,n,iblk),albsnon(:,:,n,iblk))
endif
#ifdef AEROFRC
dalvdrn_noaero(:,:,n,iblk) = dalvdrn_noaero(:,:,n,iblk)-alvdrn(:,:,n,iblk)
dalvdfn_noaero(:,:,n,iblk) = dalvdfn_noaero(:,:,n,iblk)-alvdfn(:,:,n,iblk)
dalidrn_noaero(:,:,n,iblk) = dalidrn_noaero(:,:,n,iblk)-alidrn(:,:,n,iblk)
dalidfn_noaero(:,:,n,iblk) = dalidfn_noaero(:,:,n,iblk)-alidfn(:,:,n,iblk)
dfswsfcn_noaero(:,:,n,iblk) = dfswsfcn_noaero(:,:,n,iblk)-fswsfcn(:,:,n,iblk)
dfswintn_noaero(:,:,n,iblk) = dfswintn_noaero(:,:,n,iblk)-fswintn(:,:,n,iblk)
dfswthrun_noaero(:,:,n,iblk) = dfswthrun_noaero(:,:,n,iblk)-fswthrun(:,:,n,iblk)
dfswabsn_noaero(:,:,n,iblk) = dfswsfcn_noaero(:,:,n,iblk)+dfswintn_noaero(:,:,n,iblk)+dfswthrun_noaero(:,:,n,iblk)
dalbicen_noaero(:,:,n,iblk) = dalbicen_noaero(:,:,n,iblk)-albicen(:,:,n,iblk)
dalbsnon_noaero(:,:,n,iblk) = dalbsnon_noaero(:,:,n,iblk)-albsnon(:,:,n,iblk)
dalbpndn_noaero(:,:,n,iblk) = dalbpndn_noaero(:,:,n,iblk)-albpndn(:,:,n,iblk)
dSswabsn_noaero(:,:,sl1:sl2,iblk) = dSswabsn_noaero(:,:,sl1:sl2,iblk)-Sswabsn(:,:,sl1:sl2,iblk)
dIswabsn_noaero(:,:,il1:il2,iblk) = dIswabsn_noaero(:,:,il1:il2,iblk)-Iswabsn(:,:,il1:il2,iblk)
#endif
#ifdef CCSM3FRC
dalvdrn_ccsm3(:,:,n,iblk) = dalvdrn_ccsm3(:,:,n,iblk)-alvdrn(:,:,n,iblk)
dalvdfn_ccsm3(:,:,n,iblk) = dalvdfn_ccsm3(:,:,n,iblk)-alvdfn(:,:,n,iblk)
dalidrn_ccsm3(:,:,n,iblk) = dalidrn_ccsm3(:,:,n,iblk)-alidrn(:,:,n,iblk)
dalidfn_ccsm3(:,:,n,iblk) = dalidfn_ccsm3(:,:,n,iblk)-alidfn(:,:,n,iblk)
dfswsfcn_ccsm3(:,:,n,iblk) = dfswsfcn_ccsm3(:,:,n,iblk)-fswsfcn(:,:,n,iblk)
dfswintn_ccsm3(:,:,n,iblk) = dfswintn_ccsm3(:,:,n,iblk)-fswintn(:,:,n,iblk)
dfswthrun_ccsm3(:,:,n,iblk) = dfswthrun_ccsm3(:,:,n,iblk)-fswthrun(:,:,n,iblk)
dfswabsn_ccsm3(:,:,n,iblk) = dfswsfcn_ccsm3(:,:,n,iblk)+dfswintn_ccsm3(:,:,n,iblk)+dfswthrun_ccsm3(:,:,n,iblk)
dalbicen_ccsm3(:,:,n,iblk) = dalbicen_ccsm3(:,:,n,iblk)-albicen(:,:,n,iblk)
dalbsnon_ccsm3(:,:,n,iblk) = dalbsnon_ccsm3(:,:,n,iblk)-albsnon(:,:,n,iblk)
dIswabsn_ccsm3(:,:,il1:il2,iblk) = dIswabsn_ccsm3(:,:,il1:il2,iblk)-Iswabsn(:,:,il1:il2,iblk)
#endif
#ifdef PONDFRC
dalvdrn_nopond(:,:,n,iblk) = dalvdrn_nopond(:,:,n,iblk)-alvdrn(:,:,n,iblk)
dalvdfn_nopond(:,:,n,iblk) = dalvdfn_nopond(:,:,n,iblk)-alvdfn(:,:,n,iblk)
dalidrn_nopond(:,:,n,iblk) = dalidrn_nopond(:,:,n,iblk)-alidrn(:,:,n,iblk)
dalidfn_nopond(:,:,n,iblk) = dalidfn_nopond(:,:,n,iblk)-alidfn(:,:,n,iblk)
dfswsfcn_nopond(:,:,n,iblk) = dfswsfcn_nopond(:,:,n,iblk)-fswsfcn(:,:,n,iblk)
dfswintn_nopond(:,:,n,iblk) = dfswintn_nopond(:,:,n,iblk)-fswintn(:,:,n,iblk)
dfswthrun_nopond(:,:,n,iblk) = dfswthrun_nopond(:,:,n,iblk)-fswthrun(:,:,n,iblk)
dfswabsn_nopond(:,:,n,iblk) = dfswsfcn_nopond(:,:,n,iblk)+dfswintn_nopond(:,:,n,iblk)+dfswthrun_nopond(:,:,n,iblk)
dalbicen_nopond(:,:,n,iblk) = dalbicen_nopond(:,:,n,iblk)-albicen(:,:,n,iblk)
dalbsnon_nopond(:,:,n,iblk) = dalbsnon_nopond(:,:,n,iblk)-albsnon(:,:,n,iblk)
dalbpndn_nopond(:,:,n,iblk) = dalbpndn_nopond(:,:,n,iblk)-albpndn(:,:,n,iblk)
dSswabsn_nopond(:,:,sl1:sl2,iblk) = dSswabsn_nopond(:,:,sl1:sl2,iblk)-Sswabsn(:,:,sl1:sl2,iblk)
dIswabsn_nopond(:,:,il1:il2,iblk) = dIswabsn_nopond(:,:,il1:il2,iblk)-Iswabsn(:,:,il1:il2,iblk)
#endif
enddo ! ncat
end subroutine step_radiation_iblk
!=======================================================================
end module ice_step_mod
!=======================================================================