module ice_probability 2,13
use ice_kinds_mod
use ice_communicate
, only: my_task, master_task, get_num_procs
use ice_constants
, only: pi, puny, c1
use ice_fileunits
, only: nu_timing
use ice_domain_size
, only: nx_global, ny_global, max_blocks
use ice_domain
, only: nblocks, blocks_ice, distrb_info, distribution_wght_file
use ice_blocks
, only: nx_block, ny_block, nblocks_tot, block, get_block
use ice_read_write
, only: ice_open_nc, ice_read_global_nc, ice_close_nc
use ice_broadcast
, only: broadcast_array
use ice_global_reductions
, only: sum_vector_dbl
use ice_timers
, only:
use ice_work
, only: work_gr
use ice_probability_tools
implicit none
integer (int_kind), public, parameter :: & ! types of blocks:
lndType = 0, & ! Land
icefreeType = 1, & ! ice free (ocean only)
iceType = 2 ! sea ice
! include "netcdf.inc"
integer (int_kind), public :: dynCnt ! number of calls to step_dynamic
real (dbl_kind), allocatable :: lnumIceCells(:) ! number of active ice cells
public :: ReadProbabilityFile
public :: CalcWorkPerBlock
! public :: WriteProbabilityStats
public :: init_numIceCells, &
accum_numIceCells, &
accum_numIceCells2, &
print_numIceCells
public :: set_numIceCells,write_numIceCells
contains
subroutine init_numIceCells() 1
dynCnt = 0
! print *,'init_numIceCells: nblocks_tot is: ',nblocks_tot
allocate(lnumIceCells(nblocks_tot))
lnumIceCells = 0.0
end subroutine init_numIceCells
subroutine accum_numIceCells(iblk,icells)
integer (int_kind) :: iblk,icells
lnumIceCells(iblk) = lnumIceCells(iblk) + real(icells,kind=dbl_kind)
end subroutine accum_numIceCells
subroutine accum_numIceCells2(aice) 1,1
real (dbl_kind) :: aice(nx_block,ny_block,max_blocks)
integer (int_kind) :: igblk,iblk
real (dbl_kind) :: tmp
type (block) :: this_block
integer (int_kind) :: i,j,ihi,ilo,jhi,jlo
do iblk = 1,nblocks
igblk = blocks_ice(iblk)
this_block = get_block
(igblk,iblk)
ilo = this_block%ilo
ihi = this_block%ihi
jlo = this_block%jlo
jhi = this_block%jhi
tmp = 0.0
do j = jlo,jhi
do i = ilo,ihi
if(aice(i,j,iblk) > puny) then
tmp = tmp + c1
endif
enddo
enddo
lnumIceCells(igblk) = lnumIceCells(igblk) + tmp
enddo
end subroutine accum_numIceCells2
subroutine set_numIceCells(iblk,ncells)
integer (int_kind) :: iblk
real (dbl_kind) :: ncells
lnumIceCells(iblk) = ncells
end subroutine set_numIceCells
subroutine write_numIceCells 1,1
real (dbl_kind), allocatable :: gnumIceCells(:)
integer :: n
allocate(gnumIceCells(nblocks_tot))
call sum_vector_dbl
(lnumIceCells,gnumIceCells,distrb_info)
gnumIceCells=gnumIceCells/real(dynCnt,kind=dbl_kind)
if(my_task == master_task) then
open(nu_timing,file='numCells2.bin',recl=8*nblocks_tot, &
form = 'unformatted', access = 'direct', status = 'unknown')
write(nu_timing,rec=1) gnumIceCells
close(nu_timing)
endif
end subroutine write_numIceCells
subroutine print_numIceCells,1
real (dbl_kind), allocatable :: gnumIceCells(:)
real (dbl_kind), allocatable :: gnumIceCells2(:)
integer :: ii,n
allocate(gnumIceCells(nblocks_tot))
allocate(gnumIceCells2(nblocks_tot))
call sum_vector_dbl
(lnumIceCells, gnumIceCells, distrb_info)
gnumIceCells = gnumIceCells/real(dynCnt,kind=dbl_kind)
if(my_task == master_task) then
! compress out land blocks
ii =0
do n=1,nblocks_tot
if(nocn(n) > 0) then
ii = ii+1
gnumIceCells2(ii) = gnumIceCells(n)
endif
enddo
open(nu_timing,file='numCells.bin',recl=8*ii, &
form = 'unformatted', access = 'direct', status = 'unknown')
write(nu_timing,rec=1) gnumIceCells2(1:ii)
close(nu_timing)
print *,'numCells: ',gnumIceCells2(1:ii)
endif
deallocate(gnumIceCells,gnumIceCells2)
end subroutine print_numIceCells
subroutine ReadProbabilityFile(distribution_wght_file,Prob) 1,3
character(char_len_long), intent(in) :: distribution_wght_file
real(real_kind), intent(inout) :: Prob(:,:)
type(block) :: this_block
integer(int_kind) :: ilo,ihi
integer(int_kind) :: jlo,jhi
integer(int_kind) :: fid_prob
integer(int_kind) :: amode,ncid,iostat,varid
integer(int_kind) :: i,j,n,ncnt,ierr,ig,jg
real(dbl_kind) :: val,sum,avg
character (char_len) :: &
fieldname ! field name in netCDF file
call ice_open_nc
(distribution_wght_file,fid_prob)
fieldname = 'ice_present'
call ice_read_global_nc
(fid_prob,1,fieldname,Prob,.true.)
if(my_task == master_task) then
call ice_close_nc
(fid_prob)
print *,'MAXVAL(Prob): ',MAXVAL(Prob)
print *,'MINVAL(Prob): ',MINVAL(Prob)
print *,'COUNT(Prob > 0.5): ',COUNT(Prob > 0.5)
endif
! normalize probability [0,1]
! prob=prob/100.0
end subroutine ReadProbabilityFile
!***********************************************************************
!***********************************************************************
subroutine CalcWorkPerBlock(distribution_wght, KMTG,ULATG,work_per_block, prob_per_block,blockType,bStats) 1,15
character (char_len), intent(in) :: distribution_wght
real (dbl_kind), dimension(nx_global,ny_global), intent(in) :: &
KMTG ,&! global topography
ULATG ! global latitude field (radians)
integer (int_kind), intent(inout) :: &
work_per_block(nblocks_tot) ! number of work units per block
real (dbl_kind), intent(inout) :: &
prob_per_block(nblocks_tot) ! probability of sea-ice in block
integer (int_kind), intent(inout) :: &
blockType(nblocks_tot) ! Type of block:
! one of the following
! lnd,ice,icefree
real (dbl_kind), intent(inout) :: bStats(:,:)
type (block) :: &
this_block ! block information for current block
integer (int_kind), parameter :: &
max_work_unit=10 ! quantize the work into values from 1,max
integer(int_kind) :: jg,j,n,ig,i,work_unit
integer(int_kind) :: maxkmt,mkmt,ilo,jlo,ihi,jhi
integer(int_kind) :: activePts
integer(int_kind) :: bid(max_blocks)
integer(int_kind) :: bsize_x,bsize_y
integer(int_kind), allocatable :: iLocation(:)
real(dbl_kind), allocatable, dimension(:) :: prob,work
real(dbl_kind) :: lat
real(dbl_kind), parameter :: w0 = 1., & ! Constants for work blocks:
w1 = 10. ! w0 for all blocks
! w1 for sea-ice blocks
real(dbl_kind) :: maxlat,maxalat
real(dbl_kind) :: shlatT,nhlatT
real(real_kind) :: tmp
integer(int_kind) :: ActiveBlocks,totWork
logical, parameter :: Debug = .FALSE.
integer(int_kind) :: numLnd,numIcefree,numIce
integer(int_kind) :: ierr
!----------------------------------------------------------------------
!
! estimate the amount of work per processor using the topography
! and latitude
!
!----------------------------------------------------------------------
allocate(work_gr(nx_global,ny_global))
allocate(prob(nblocks_tot),work(nblocks_tot))
allocate(nocn(nblocks_tot))
allocate(nice005(nblocks_tot),nice010(nblocks_tot),nice050(nblocks_tot), &
nice100(nblocks_tot),nice250(nblocks_tot),nice500(nblocks_tot))
nocn=0
nice005=0
nice010=0
nice050=0
nice100=0
nice250=0
nice500=0
ActiveBlocks = 0
select case (distribution_wght)
case('file')
call ReadProbabilityFile
(distribution_wght_file,work_gr)
case('erfc')
work_gr = ErfcProbability
(ULATG)
case default
work_gr = ErfcProbability
(ULATG)
end select
!--------------------------------------------------
! It would be nice if we can not find the
! the distribution_wgt_file,
! fall back to erfc weight function.
! However currently the error trapping does not prevent
! such a fault recovery
!-------------------------------------------------------
!if(ierr < 0) then
! print *,'CalcWorkPerBlock: Could not open file: ',trim(distribution_wght_file)
! print *,'CalcWorkPerBlock: Using ERFC probability function instead'
! work_gr = ErfcProbability(ULATG)
!endif
! print *,'IAM: ',my_task,'prod: ',prob
if(my_task == master_task) then
work_per_block=0
do n=1,nblocks_tot
this_block=get_block
(n,n)
ilo = this_block%ilo;ihi = this_block%ihi
jlo = this_block%jlo;jhi = this_block%jhi
!----------------------------------------------------
! calculate the probability of sea-ice in this block
!----------------------------------------------------
tmp = 0.0
do j=jlo,jhi
jg=this_block%j_glob(j)
if(jg>0) then
do i=ilo,ihi
ig = this_block%i_glob(i)
if(ig>0) then
if(KMTG(ig,jg)>puny) then
nocn(n) = nocn(n) + 1
if(work_gr(ig,jg) > 0.005) nice005(n) = nice005(n) + 1
if(work_gr(ig,jg) > 0.010) nice010(n) = nice010(n) + 1
if(work_gr(ig,jg) > 0.050) nice050(n) = nice050(n) + 1
if(work_gr(ig,jg) > 0.100) nice100(n) = nice100(n) + 1
if(work_gr(ig,jg) > 0.250) nice250(n) = nice250(n) + 1
if(work_gr(ig,jg) > 0.500) nice500(n) = nice500(n) + 1
tmp = tmp + work_gr(ig,jg)
endif
endif
enddo
endif
enddo
if(nocn(n) > 0) then
! print *,'n:',n,' tmp:',tmp,' nocn(n): ',nocn(n)
prob_per_block(n) = real(tmp,kind=dbl_kind)/real(nocn(n),kind=dbl_kind)
! print *,'prob_per_block(n):' ,prob_per_block(n)
! print *,' ihi,ilo,(ihi-ilo+1): ',ihi,ilo,(ihi-ilo+1)
! print *,' jhi,jlo,(jhi-jlo+1): ',jhi,jlo,(jhi-jlo+1)
! print *,' w0,w1: ',w0,w1
work_per_block(n) = &
CEILING(w0 + (real(nocn(n),kind=dbl_kind)/real((ihi-ilo+1)*(jhi-jlo+1),kind=dbl_kind)) &
*prob_per_block(n)*w1,kind=int_kind)
else
prob_per_block(n) = 0.0d0
endif
!--------------------------------------------------
! set the type of block (used latter for partition)
!--------------------------------------------------
if(prob_per_block(n) >0.005 .and. nocn(n) > 0) then
blockType(n) = iceType
elseif (nocn(n) > 0) then
blockType(n) = icefreeType
elseif (nocn(n) == 0) then
blockType(n) = lndType
endif
enddo
numIceFree = COUNT(blockType .eq. iceFreeType)
numLnd = COUNT(blockType .eq. lndType)
numIce = COUNT(blockTYpe .eq. iceType)
! print *,'Total blocks:',nblocks_tot,' land blocks: ',numLnd,' Ice blocks: ', &
! numIce,' IceFree blocks: ',numIceFree
write(*,23) nblocks_tot,numIce,numIceFree,numLnd
23 format('CalcWorkPerBlock: Total blocks: ',i5,' Ice blocks: ',i5,' IceFree blocks: ',i5,' Land blocks: ',i5)
endif
!-----------------------------------------------------------------
! distribute blocks among processors
!-----------------------------------------------------------------
call broadcast_array
(work_per_block,master_task)
call broadcast_array
(prob_per_block,master_task)
call broadcast_array
(blockType,master_task)
call broadcast_array
(nocn,master_task)
call broadcast_array
(nice005,master_task)
call broadcast_array
(nice010,master_task)
call broadcast_array
(nice050,master_task)
call broadcast_array
(nice100,master_task)
call broadcast_array
(nice250,master_task)
call broadcast_array
(nice500,master_task)
allocate(iLocation(nblocks_tot))
do i=1,nblocks_tot
iLocation(i) = i
enddo
call BuildProbabilityStats2
(iLocation,bStats)
deallocate(work_gr)
deallocate(iLocation)
!DBG print *,'CalcWorkPerBlock: at the end of the subroutine'
end subroutine CalcWorkPerBlock
function ErfcProbability(lat) result(prob) 2,1
real (kind=dbl_kind), intent(in), &
dimension (nx_global,ny_global) :: lat
real (kind=real_kind), &
dimension (nx_global,ny_global) :: prob
real (kind=dbl_kind) :: ltmp,thetai,sigmai,arg
integer :: i,j
do j=1,ny_global
do i=1,nx_global
ltmp = lat(i,j)
if(ltmp > 0.0d0) then
!---------------------
! northern latitude
!---------------------
!JMD thetai = (70.0_dbl_kind/180.0_dbl_kind)*pi
!JMD For startup lots of random ice at low lattitudes
thetai = (55.0_dbl_kind/180.0_dbl_kind)*pi
sigmai = (5.0_dbl_kind/180.0_dbl_kind)*pi
arg = (thetai-ltmp)/sigmai
else
!---------------------
! southern hemisphere
!---------------------
!JMD thetai = (60.0_dbl_kind/180.0_dbl_kind)*pi
!JMD For startup lots of random ice at low lattitudes
thetai = (60.0_dbl_kind/180.0_dbl_kind)*pi
sigmai = (5.0_dbl_kind/180.0_dbl_kind)*pi
arg = (thetai+ltmp)/sigmai
endif
prob(i,j) = real(erfc06
(arg),kind=real_kind)/2.0_real_kind
enddo
enddo
end function ErfcProbability
function erfc06(x) result(erfc) 1
implicit none
real(dbl_kind), intent(in) :: x
real(dbl_kind) :: erfc
real(dbl_kind) :: t,u
real(dbl_kind), parameter :: pa = 3.97886080735226000e+00_dbl_kind
real(dbl_kind), parameter :: p00 = 2.75374741597376782e-01_dbl_kind
real(dbl_kind), parameter :: p01 = 4.90165080585318424e-01_dbl_kind
real(dbl_kind), parameter :: p02 = 7.74368199119538609e-01_dbl_kind
real(dbl_kind), parameter :: p03 = 1.07925515155856677e+00_dbl_kind
real(dbl_kind), parameter :: p04 = 1.31314653831023098e+00_dbl_kind
real(dbl_kind), parameter :: p05 = 1.37040217682338167e+00_dbl_kind
real(dbl_kind), parameter :: p06 = 1.18902982909273333e+00_dbl_kind
real(dbl_kind), parameter :: p07 = 8.05276408752910567e-01_dbl_kind
real(dbl_kind), parameter :: p08 = 3.57524274449531043e-01_dbl_kind
real(dbl_kind), parameter :: p09 = 1.66207924969367356e-02_dbl_kind
real(dbl_kind), parameter :: p10 = -1.19463959964325415e-01_dbl_kind
real(dbl_kind), parameter :: p11 = -8.38864557023001992e-02_dbl_kind
real(dbl_kind), parameter :: p12 = 2.49367200053503304e-03_dbl_kind
real(dbl_kind), parameter :: p13 = 3.90976845588484035e-02_dbl_kind
real(dbl_kind), parameter :: p14 = 1.61315329733252248e-02_dbl_kind
real(dbl_kind), parameter :: p15 = -1.33823644533460069e-02_dbl_kind
real(dbl_kind), parameter :: p16 = -1.27223813782122755e-02_dbl_kind
real(dbl_kind), parameter :: p17 = 3.83335126264887303e-03_dbl_kind
real(dbl_kind), parameter :: p18 = 7.73672528313526668e-03_dbl_kind
real(dbl_kind), parameter :: p19 = -8.70779635317295828e-04_dbl_kind
real(dbl_kind), parameter :: p20 = -3.96385097360513500e-03_dbl_kind
real(dbl_kind), parameter :: p21 = 1.19314022838340944e-04_dbl_kind
real(dbl_kind), parameter :: p22 = 1.27109764952614092e-03_dbl_kind
t = pa/(pa + abs(x))
u = t - 0.5_dbl_kind
erfc = ((((((((((((((((((((((p22 * u + p21) * u + p20) &
* u + p19) * u + p18) &
* u + p17) * u + p16) &
* u + p15) * u + p14) &
* u + p13) * u + p12) &
* u + p11) * u + p10) &
* u + p09) * u + p08) &
* u + p07) * u + p06) &
* u + p05) * u + p04) &
* u + p03) * u + p02) &
* u + p01) * u + p00) * t * exp(-x**2)
if (x < 0.0_dbl_kind) erfc = 2.0_dbl_kind - erfc
end function erfc06
!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end module ice_probability