LCOV - code coverage report
Current view: top level - cicecore/cicedyn/infrastructure - ice_domain.F90 (source / functions) Hit Total Coverage
Test: 231018-211459:8916b9ff2c:1:quick Lines: 139 289 48.10 %
Date: 2023-10-18 15:30:36 Functions: 2 2 100.00 %

          Line data    Source code
       1             : #ifdef ncdf
       2             : #define USE_NETCDF
       3             : #endif
       4             : !|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
       5             : 
       6             :  module ice_domain
       7             : 
       8             : !  This module contains the model domain and routines for initializing
       9             : !  the domain.  It also initializes the decompositions and
      10             : !  distributions across processors/threads by calling relevant
      11             : !  routines in the block, distribution modules.
      12             : !
      13             : ! author: Phil Jones, LANL
      14             : ! Oct. 2004: Adapted from POP by William H. Lipscomb, LANL
      15             : ! Feb. 2007: E. Hunke removed NE and SW boundary options (they were buggy
      16             : !  and not used anyhow).
      17             : 
      18             :    use ice_kinds_mod
      19             :    use ice_constants, only: shlat, nhlat
      20             :    use ice_communicate, only: my_task, master_task, get_num_procs, &
      21             :        add_mpi_barriers, ice_barrier
      22             :    use ice_broadcast, only: broadcast_scalar, broadcast_array
      23             :    use ice_blocks, only: block, get_block, create_blocks, nghost, &
      24             :        nblocks_x, nblocks_y, nblocks_tot, nx_block, ny_block, debug_blocks
      25             :    use ice_distribution, only: distrb
      26             :    use ice_boundary, only: ice_halo
      27             :    use ice_exit, only: abort_ice
      28             :    use ice_fileunits, only: nu_nml, nml_filename, nu_diag, &
      29             :        get_fileunit, release_fileunit, flush_fileunit
      30             :    use icepack_intfc, only: icepack_warnings_flush, icepack_warnings_aborted
      31             :    use icepack_intfc, only: icepack_query_parameters
      32             : 
      33             : #ifdef USE_NETCDF
      34             :    use netcdf
      35             : #endif
      36             : 
      37             :    implicit none
      38             :    private
      39             : 
      40             :    public  :: init_domain_blocks ,&
      41             :               init_domain_distribution
      42             : 
      43             :    integer (int_kind), public :: &
      44             :       nblocks         ! actual number of blocks on this processor
      45             : 
      46             :    logical (kind=log_kind), public :: &
      47             :       close_boundaries
      48             : 
      49             :    integer (int_kind), dimension(:), pointer, public :: &
      50             :       blocks_ice => null()        ! block ids for local blocks
      51             : 
      52             :    type (distrb), public :: &
      53             :       distrb_info        ! block distribution info
      54             : 
      55             :    type (ice_halo), public :: &
      56             :       halo_info          ! ghost cell update info
      57             : 
      58             :    character (char_len), public :: &
      59             :       ew_boundary_type, &! type of domain bndy in each logical   ! LCOV_EXCL_LINE
      60             :       ns_boundary_type   !    direction (ew is i, ns is j)
      61             : 
      62             :    logical (kind=log_kind), public :: &
      63             :       maskhalo_dyn   , & ! if true, use masked halo updates for dynamics   ! LCOV_EXCL_LINE
      64             :       maskhalo_remap , & ! if true, use masked halo updates for transport   ! LCOV_EXCL_LINE
      65             :       maskhalo_bound , & ! if true, use masked halo updates for bound_state   ! LCOV_EXCL_LINE
      66             :       halo_dynbundle , & ! if true, bundle halo update in dynamics   ! LCOV_EXCL_LINE
      67             :       landblockelim  , & ! if true, land block elimination is on   ! LCOV_EXCL_LINE
      68             :       orca_halogrid      ! if true, input fields are haloed as defined by orca grid
      69             : 
      70             : !-----------------------------------------------------------------------
      71             : !
      72             : !   module private variables - for the most part these appear as
      73             : !   module variables to facilitate sharing info between init_domain1
      74             : !   and init_domain2.
      75             : !
      76             : !-----------------------------------------------------------------------
      77             : 
      78             :     character (char_len) :: &
      79             :        distribution_type,   &! method to use for distributing blocks   ! LCOV_EXCL_LINE
      80             :                              ! 'cartesian', 'roundrobin', 'sectrobin', 'sectcart'
      81             :                              ! 'rake', 'spacecurve', etc
      82             :        distribution_wght     ! method for weighting work per block
      83             :                              ! 'block' = POP default configuration
      84             :                              ! 'blockall' = no land block elimination
      85             :                              ! 'latitude' = no. ocean points * |lat|
      86             :                              ! 'file' = read distribution_wgth_file
      87             :     character (char_len_long) :: &
      88             :        distribution_wght_file  ! file for distribution_wght=file
      89             : 
      90             :     integer (int_kind) :: &
      91             :        nprocs                ! num of processors
      92             : 
      93             : !***********************************************************************
      94             : 
      95             :  contains
      96             : 
      97             : !***********************************************************************
      98             : 
      99          37 :  subroutine init_domain_blocks
     100             : 
     101             : !  This routine reads in domain information and calls the routine
     102             : !  to set up the block decomposition.
     103             : 
     104             :    use ice_distribution, only: processor_shape
     105             :    use ice_domain_size, only: ncat, nilyr, nslyr, max_blocks, &
     106             :        nx_global, ny_global, block_size_x, block_size_y
     107             :    use ice_fileunits, only: goto_nml
     108             : !----------------------------------------------------------------------
     109             : !
     110             : !  local variables
     111             : !
     112             : !----------------------------------------------------------------------
     113             : 
     114             :    integer (int_kind) :: &
     115             :       nml_error          ! namelist read error flag
     116             : 
     117             :    character(len=char_len)      :: nml_name ! text namelist name
     118             :    character(len=char_len_long) :: tmpstr2 ! for namelist check
     119             : 
     120             :    character(len=*), parameter :: subname = '(init_domain_blocks)'
     121             : 
     122             : !----------------------------------------------------------------------
     123             : !
     124             : !  input namelists
     125             : !
     126             : !----------------------------------------------------------------------
     127             : 
     128             :    namelist /domain_nml/ nprocs, &
     129             :                          max_blocks,   &   ! LCOV_EXCL_LINE
     130             :                          block_size_x, &   ! LCOV_EXCL_LINE
     131             :                          block_size_y, &   ! LCOV_EXCL_LINE
     132             :                          nx_global,    &   ! LCOV_EXCL_LINE
     133             :                          ny_global,    &   ! LCOV_EXCL_LINE
     134             :                          processor_shape,   &   ! LCOV_EXCL_LINE
     135             :                          distribution_type, &   ! LCOV_EXCL_LINE
     136             :                          distribution_wght, &   ! LCOV_EXCL_LINE
     137             :                          distribution_wght_file, &   ! LCOV_EXCL_LINE
     138             :                          ew_boundary_type,  &   ! LCOV_EXCL_LINE
     139             :                          ns_boundary_type,  &   ! LCOV_EXCL_LINE
     140             :                          maskhalo_dyn,      &   ! LCOV_EXCL_LINE
     141             :                          maskhalo_remap,    &   ! LCOV_EXCL_LINE
     142             :                          maskhalo_bound,    &   ! LCOV_EXCL_LINE
     143             :                          add_mpi_barriers,  &   ! LCOV_EXCL_LINE
     144             :                          debug_blocks
     145             : 
     146             : !----------------------------------------------------------------------
     147             : !
     148             : !  read domain information from namelist input
     149             : !
     150             : !----------------------------------------------------------------------
     151             : 
     152          37 :    nprocs = -1
     153          37 :    processor_shape   = 'slenderX2'
     154          37 :    distribution_type = 'cartesian'
     155          37 :    distribution_wght = 'latitude'
     156          37 :    distribution_wght_file = 'unknown'
     157          37 :    ew_boundary_type  = 'cyclic'
     158          37 :    ns_boundary_type  = 'open'
     159          37 :    maskhalo_dyn      = .false.     ! if true, use masked halos for dynamics
     160          37 :    maskhalo_remap    = .false.     ! if true, use masked halos for transport
     161          37 :    maskhalo_bound    = .false.     ! if true, use masked halos for bound_state
     162          37 :    halo_dynbundle    = .true.      ! if true, bundle halo updates in dynamics
     163          37 :    add_mpi_barriers  = .false.     ! if true, throttle communication
     164          37 :    debug_blocks      = .false.     ! if true, print verbose block information
     165          37 :    max_blocks        = -1          ! max number of blocks per processor
     166          37 :    block_size_x      = -1          ! size of block in first horiz dimension
     167          37 :    block_size_y      = -1          ! size of block in second horiz dimension
     168          37 :    nx_global         = -1          ! NXGLOB,  i-axis size
     169          37 :    ny_global         = -1          ! NYGLOB,  j-axis size
     170          37 :    landblockelim     = .true.      ! on by default
     171             : 
     172          37 :    if (my_task == master_task) then
     173           7 :       nml_name = 'domain_nml'
     174           7 :       write(nu_diag,*) subname,' Reading ', trim(nml_name)
     175             : 
     176           7 :       call get_fileunit(nu_nml)
     177           7 :       open (nu_nml, file=trim(nml_filename), status='old',iostat=nml_error)
     178           7 :       if (nml_error /= 0) then
     179             :          call abort_ice(subname//'ERROR: domain_nml open file '// &
     180             :               trim(nml_filename), &   ! LCOV_EXCL_LINE
     181           0 :               file=__FILE__, line=__LINE__)
     182             :       endif
     183             : 
     184           7 :       call goto_nml(nu_nml,trim(nml_name),nml_error)
     185           7 :       if (nml_error /= 0) then
     186             :          call abort_ice(subname//'ERROR: searching for '// trim(nml_name), &
     187           0 :               file=__FILE__, line=__LINE__)
     188             :       endif
     189             : 
     190           7 :       nml_error =  1
     191          14 :       do while (nml_error > 0)
     192           7 :          read(nu_nml, nml=domain_nml,iostat=nml_error)
     193             :          ! check if error
     194           7 :          if (nml_error /= 0) then
     195             :             ! backspace and re-read erroneous line
     196           0 :             backspace(nu_nml)
     197           0 :             read(nu_nml,fmt='(A)') tmpstr2
     198             :             call abort_ice(subname//'ERROR: ' // trim(nml_name) // ' reading ' // &
     199           0 :                  trim(tmpstr2), file=__FILE__, line=__LINE__)
     200             :          endif
     201             :       end do
     202             : 
     203           7 :       close(nu_nml)
     204           7 :       call release_fileunit(nu_nml)
     205             : 
     206             :    endif
     207             : 
     208          37 :    call broadcast_scalar(nprocs,            master_task)
     209          37 :    call broadcast_scalar(processor_shape,   master_task)
     210          37 :    call broadcast_scalar(distribution_type, master_task)
     211          37 :    call broadcast_scalar(distribution_wght, master_task)
     212          37 :    call broadcast_scalar(distribution_wght_file, master_task)
     213          37 :    call broadcast_scalar(ew_boundary_type,  master_task)
     214          37 :    call broadcast_scalar(ns_boundary_type,  master_task)
     215          37 :    call broadcast_scalar(maskhalo_dyn,      master_task)
     216          37 :    call broadcast_scalar(maskhalo_remap,    master_task)
     217          37 :    call broadcast_scalar(maskhalo_bound,    master_task)
     218          37 :    call broadcast_scalar(add_mpi_barriers,  master_task)
     219          37 :    call broadcast_scalar(debug_blocks,      master_task)
     220          37 :    if (my_task == master_task) then
     221           7 :      if (max_blocks < 1) then
     222             :        max_blocks=( ((nx_global-1)/block_size_x + 1) *         &
     223           0 :                     ((ny_global-1)/block_size_y + 1) - 1) / nprocs + 1
     224           0 :        max_blocks=max(1,max_blocks)
     225             :        write(nu_diag,'(/,a52,i6,/)') &
     226           0 :          '(ice_domain): max_block < 1: max_block estimated to ',max_blocks
     227             :      endif
     228             :    endif
     229          37 :    call broadcast_scalar(max_blocks,        master_task)
     230          37 :    call broadcast_scalar(block_size_x,      master_task)
     231          37 :    call broadcast_scalar(block_size_y,      master_task)
     232          37 :    call broadcast_scalar(nx_global,         master_task)
     233          37 :    call broadcast_scalar(ny_global,         master_task)
     234             : 
     235             : !----------------------------------------------------------------------
     236             : !
     237             : !  perform some basic checks on domain
     238             : !
     239             : !----------------------------------------------------------------------
     240             : 
     241          37 :    if (nx_global < 1 .or. ny_global < 1 .or. ncat < 1) then
     242             :       !***
     243             :       !*** domain size zero or negative
     244             :       !***
     245           0 :       call abort_ice(subname//'ERROR: Invalid domain: size < 1') ! no domain
     246          37 :    else if (nprocs /= get_num_procs()) then
     247             :       !***
     248             :       !*** input nprocs does not match system (eg MPI) request
     249             :       !***
     250             : #if (defined CESMCOUPLED)
     251             :       nprocs = get_num_procs()
     252             : #else
     253           0 :       write(nu_diag,*) subname,'ERROR: nprocs, get_num_procs = ',nprocs,get_num_procs()
     254           0 :       call abort_ice(subname//'ERROR: Input nprocs not same as system request')
     255             : #endif
     256             :    else if (nghost < 1) then
     257             :       !***
     258             :       !*** must have at least 1 layer of ghost cells
     259             :       !***
     260             :       call abort_ice(subname//'ERROR: Not enough ghost cells allocated')
     261             :    endif
     262             : 
     263             : !----------------------------------------------------------------------
     264             : !
     265             : !  compute block decomposition and details
     266             : !
     267             : !----------------------------------------------------------------------
     268             : 
     269             :    call create_blocks(nx_global, ny_global, trim(ew_boundary_type), &
     270          37 :                                             trim(ns_boundary_type))
     271             : 
     272             : !----------------------------------------------------------------------
     273             : !
     274             : !  Now we need grid info before proceeding further
     275             : !  Print some domain information
     276             : !
     277             : !----------------------------------------------------------------------
     278             : 
     279          37 :    if (my_task == master_task) then
     280           7 :      write(nu_diag,'(/,a18,/)')'Domain Information'
     281           7 :      write(nu_diag,'(a,i6)')  '  Horizontal domain: nx = ', nx_global
     282           7 :      write(nu_diag,'(a,i6)')  '                     ny = ', ny_global
     283           7 :      write(nu_diag,'(a,i6)')  '  No. of categories: nc = ', ncat
     284           7 :      write(nu_diag,'(a,i6)')  '  No. of ice layers: ni = ', nilyr
     285           7 :      write(nu_diag,'(a,i6)')  '  No. of snow layers:ns = ', nslyr
     286           7 :      write(nu_diag,'(a,i6)')  '  Processors:  total    = ', nprocs
     287           7 :      write(nu_diag,'(a,a)')   '  Processor shape       = ', trim(processor_shape)
     288           7 :      write(nu_diag,'(a,a)')   '  Distribution type     = ', trim(distribution_type)
     289           7 :      write(nu_diag,'(a,a)')   '  Distribution weight   = ', trim(distribution_wght)
     290           7 :      write(nu_diag,'(a,a)')   '  Distribution wght file= ', trim(distribution_wght_file)
     291           7 :      write(nu_diag,'(a,a)')   '  ew_boundary_type      = ', trim(ew_boundary_type)
     292           7 :      write(nu_diag,'(a,a)')   '  ns_boundary_type      = ', trim(ns_boundary_type)
     293           7 :      write(nu_diag,'(a,l6)')  '  maskhalo_dyn          = ', maskhalo_dyn
     294           7 :      write(nu_diag,'(a,l6)')  '  maskhalo_remap        = ', maskhalo_remap
     295           7 :      write(nu_diag,'(a,l6)')  '  maskhalo_bound        = ', maskhalo_bound
     296           7 :      write(nu_diag,'(a,l6)')  '  add_mpi_barriers      = ', add_mpi_barriers
     297           7 :      write(nu_diag,'(a,l6)')  '  debug_blocks          = ', debug_blocks
     298           7 :      write(nu_diag,'(a,2i6)') '  block_size_x,_y       = ', block_size_x, block_size_y
     299           7 :      write(nu_diag,'(a,i6)')  '  max_blocks            = ', max_blocks
     300           7 :      write(nu_diag,'(a,i6,/)')'  Number of ghost cells = ', nghost
     301             :    endif
     302             : 
     303             : !----------------------------------------------------------------------
     304             : 
     305          37 :  end subroutine init_domain_blocks
     306             : 
     307             : !***********************************************************************
     308             : 
     309          37 :  subroutine init_domain_distribution(KMTG,ULATG,grid_ice)
     310             : 
     311             : !  This routine calls appropriate setup routines to distribute blocks
     312             : !  across processors and defines arrays with block ids for any local
     313             : !  blocks. Information about ghost cell update routines is also
     314             : !  initialized here through calls to the appropriate boundary routines.
     315             : 
     316             :    use ice_boundary, only: ice_HaloCreate
     317             :    use ice_distribution, only: create_distribution, create_local_block_ids, ice_distributionGet
     318             :    use ice_domain_size, only: max_blocks, nx_global, ny_global
     319             : 
     320             :    real (dbl_kind), dimension(nx_global,ny_global), intent(in) :: &
     321             :       KMTG           ,&! global topography   ! LCOV_EXCL_LINE
     322             :       ULATG            ! global latitude field (radians)
     323             : 
     324             :    character(len=*), intent(in) :: &
     325             :       grid_ice         ! grid_ice, B, C, CD, etc
     326             : 
     327             : !----------------------------------------------------------------------
     328             : !
     329             : !  local variables
     330             : !
     331             : !----------------------------------------------------------------------
     332             : 
     333             :    integer (int_kind), dimension (nx_global, ny_global) :: &
     334          74 :       flat                 ! latitude-dependent scaling factor
     335             : 
     336             :    character (char_len) :: outstring
     337             : 
     338             :    integer (int_kind), parameter :: &
     339             :       max_work_unit=10    ! quantize the work into values from 1,max
     340             : 
     341             :    integer (int_kind) :: &
     342             :       i,j,n              ,&! dummy loop indices   ! LCOV_EXCL_LINE
     343             :       ig,jg              ,&! global indices   ! LCOV_EXCL_LINE
     344             :       igm1,igp1,jgm1,jgp1,&! global indices   ! LCOV_EXCL_LINE
     345             :       ninfo              ,&! ice_distributionGet check   ! LCOV_EXCL_LINE
     346             :       np, nlb, m         ,&! debug blocks temporaries   ! LCOV_EXCL_LINE
     347             :       work_unit          ,&! size of quantized work unit   ! LCOV_EXCL_LINE
     348             : #ifdef USE_NETCDF
     349             :       fid                ,&! file id
     350             :       varid              ,&! var id   ! LCOV_EXCL_LINE
     351             :       status             ,&! netcdf return code   ! LCOV_EXCL_LINE
     352             : #endif
     353             :       tblocks_tmp        ,&! total number of blocks
     354             :       nblocks_tmp        ,&! temporary value of nblocks   ! LCOV_EXCL_LINE
     355             :       nblocks_max          ! max blocks on proc
     356             : 
     357             :    real (dbl_kind) :: &
     358             :       puny, &              ! puny limit   ! LCOV_EXCL_LINE
     359           8 :       rad_to_deg           ! radians to degrees
     360             : 
     361             :    integer (int_kind), dimension(:), allocatable :: &
     362             :       blkinfo            ,&! ice_distributionGet check   ! LCOV_EXCL_LINE
     363             :       nocn               ,&! number of ocean points per block   ! LCOV_EXCL_LINE
     364          37 :       work_per_block       ! number of work units per block
     365             : 
     366             :    type (block) :: &
     367             :       this_block           ! block information for current block
     368             : 
     369             :    real (dbl_kind), dimension(:,:), allocatable :: &
     370          37 :       wght                 ! wghts from file
     371             : 
     372             :    character(len=*), parameter :: subname = '(init_domain_distribution)'
     373             : 
     374             : !----------------------------------------------------------------------
     375             : !
     376             : !  check that there are at least nghost+1 rows or columns of land cells
     377             : !  for closed boundary conditions (otherwise grid lengths are zero in
     378             : !  cells neighboring ocean points).
     379             : !
     380             : !----------------------------------------------------------------------
     381             : 
     382          37 :    call icepack_query_parameters(puny_out=puny, rad_to_deg_out=rad_to_deg)
     383          37 :    call icepack_warnings_flush(nu_diag)
     384          37 :    if (icepack_warnings_aborted()) call abort_ice(error_message=subname, &
     385           0 :       file=__FILE__, line=__LINE__)
     386             : 
     387          37 :    if (trim(ns_boundary_type) == 'closed') then
     388           0 :       call abort_ice(subname//'ERROR: ns_boundary_type = closed not supported')
     389           0 :       allocate(nocn(nblocks_tot))
     390           0 :       nocn = 0
     391           0 :       do n=1,nblocks_tot
     392           0 :          this_block = get_block(n,n)
     393           0 :          if (this_block%jblock == nblocks_y) then ! north edge
     394           0 :          do j = this_block%jhi-1, this_block%jhi
     395           0 :             if (this_block%j_glob(j) > 0) then
     396           0 :                do i = 1, nx_block
     397           0 :                   if (this_block%i_glob(i) > 0) then
     398           0 :                      ig = this_block%i_glob(i)
     399           0 :                      jg = this_block%j_glob(j)
     400           0 :                      if (KMTG(ig,jg) > puny) nocn(n) = nocn(n) + 1
     401             :                   endif
     402             :                enddo
     403             :             endif
     404             :          enddo
     405             :          endif
     406           0 :          if (this_block%jblock == 1) then ! south edge
     407           0 :          do j = this_block%jlo, this_block%jlo+1
     408           0 :             if (this_block%j_glob(j) > 0) then
     409           0 :                do i = 1, nx_block
     410           0 :                   if (this_block%i_glob(i) > 0) then
     411           0 :                      ig = this_block%i_glob(i)
     412           0 :                      jg = this_block%j_glob(j)
     413           0 :                      if (KMTG(ig,jg) > puny) nocn(n) = nocn(n) + 1
     414             :                   endif
     415             :                enddo
     416             :             endif
     417             :          enddo
     418             :          endif
     419           0 :          if (nocn(n) > 0) then
     420           0 :             write(nu_diag,*) subname,'ns closed, Not enough land cells along ns edge'
     421           0 :             call abort_ice(subname//'ERROR: Not enough land cells along ns edge for ns closed')
     422             :          endif
     423             :       enddo
     424           0 :       deallocate(nocn)
     425             :    endif
     426          37 :    if (trim(ew_boundary_type) == 'closed') then
     427           0 :       call abort_ice(subname//'ERROR: ew_boundary_type = closed not supported')
     428           0 :       allocate(nocn(nblocks_tot))
     429           0 :       nocn = 0
     430           0 :       do n=1,nblocks_tot
     431           0 :          this_block = get_block(n,n)
     432           0 :          if (this_block%iblock == nblocks_x) then ! east edge
     433           0 :          do j = 1, ny_block
     434           0 :             if (this_block%j_glob(j) > 0) then
     435           0 :                do i = this_block%ihi-1, this_block%ihi
     436           0 :                   if (this_block%i_glob(i) > 0) then
     437           0 :                      ig = this_block%i_glob(i)
     438           0 :                      jg = this_block%j_glob(j)
     439           0 :                      if (KMTG(ig,jg) > puny) nocn(n) = nocn(n) + 1
     440             :                   endif
     441             :                enddo
     442             :             endif
     443             :          enddo
     444             :          endif
     445           0 :          if (this_block%iblock == 1) then ! west edge
     446           0 :          do j = 1, ny_block
     447           0 :             if (this_block%j_glob(j) > 0) then
     448           0 :                do i = this_block%ilo, this_block%ilo+1
     449           0 :                   if (this_block%i_glob(i) > 0) then
     450           0 :                      ig = this_block%i_glob(i)
     451           0 :                      jg = this_block%j_glob(j)
     452           0 :                      if (KMTG(ig,jg) > puny) nocn(n) = nocn(n) + 1
     453             :                   endif
     454             :                enddo
     455             :             endif
     456             :          enddo
     457             :          endif
     458           0 :          if (nocn(n) > 0) then
     459           0 :             write(nu_diag,*) subname,'ew closed, Not enough land cells along ew edge'
     460           0 :             call abort_ice(subname//'ERROR: Not enough land cells along ew edge for ew closed')
     461             :          endif
     462             :       enddo
     463           0 :       deallocate(nocn)
     464             :    endif
     465             : 
     466             : !----------------------------------------------------------------------
     467             : !
     468             : !  estimate the amount of work per processor using the topography
     469             : !  and latitude
     470             : !
     471             : !----------------------------------------------------------------------
     472             : 
     473          37 :    if (distribution_wght == 'latitude') then
     474      510265 :        flat = max(NINT(abs(ULATG*rad_to_deg), int_kind),1)  ! linear function
     475             :    else
     476           0 :        flat = 1
     477             :    endif
     478             : 
     479          37 :    if (distribution_wght == 'blockall') landblockelim = .false.
     480             : 
     481          37 :    allocate(nocn(nblocks_tot))
     482             : 
     483          37 :    if (distribution_wght == 'file') then
     484           0 :       allocate(wght(nx_global,ny_global))
     485           0 :       if (my_task == master_task) then
     486             :          ! cannot use ice_read_write due to circular dependency
     487             : #ifdef USE_NETCDF
     488           0 :          status = nf90_open(distribution_wght_file, NF90_NOWRITE, fid)
     489           0 :          if (status /= nf90_noerr) then
     490           0 :             call abort_ice (subname//'ERROR: Cannot open '//trim(distribution_wght_file))
     491             :          endif
     492           0 :          status = nf90_inq_varid(fid, 'wght', varid)
     493           0 :          status = nf90_get_var(fid, varid, wght)
     494           0 :          status = nf90_close(fid)
     495           0 :          write(nu_diag,*) 'read ',trim(distribution_wght_file),minval(wght),maxval(wght)
     496             : #else
     497             :          call abort_ice(subname//'ERROR: USE_NETCDF cpp not defined', &
     498             :              file=__FILE__, line=__LINE__)
     499             : #endif
     500             :       endif
     501           0 :       call broadcast_array(wght, master_task)
     502           0 :       nocn = 0
     503           0 :       do n=1,nblocks_tot
     504           0 :          this_block = get_block(n,n)
     505           0 :          do j=this_block%jlo,this_block%jhi
     506           0 :             if (this_block%j_glob(j) > 0) then
     507           0 :                do i=this_block%ilo,this_block%ihi
     508           0 :                   if (this_block%i_glob(i) > 0) then
     509           0 :                      ig = this_block%i_glob(i)
     510           0 :                      jg = this_block%j_glob(j)
     511             : !                     if (KMTG(ig,jg) > puny) &
     512             : !                        nocn(n) = max(nocn(n),nint(wght(ig,jg)+1.0_dbl_kind))
     513           0 :                      if (KMTG(ig,jg) > puny) then
     514           0 :                         if (wght(ig,jg) > 0.00001_dbl_kind) then
     515           0 :                            nocn(n) = nocn(n)+nint(wght(ig,jg))
     516             :                         else
     517           0 :                            nocn(n) = max(nocn(n),1)
     518             :                         endif
     519             :                      endif
     520             :                   endif
     521             :                end do
     522             :             endif
     523             :          end do
     524             :       enddo
     525           0 :       deallocate(wght)
     526             :    else
     527        1126 :       nocn = 0
     528        1126 :       do n=1,nblocks_tot
     529        1089 :          this_block = get_block(n,n)
     530       33525 :          do j=this_block%jlo,this_block%jhi
     531       33525 :             if (this_block%j_glob(j) > 0) then
     532      538180 :                do i=this_block%ilo,this_block%ihi
     533      538180 :                   if (this_block%i_glob(i) > 0) then
     534      505744 :                      ig = this_block%i_glob(i)
     535      505744 :                      jg = this_block%j_glob(j)
     536      505744 :                      if (grid_ice == 'C' .or. grid_ice == 'CD') then
     537             :                         ! Have to be careful about block elimination with C/CD
     538             :                         ! Use a bigger stencil
     539           0 :                         igm1 = mod(ig-2+nx_global,nx_global)+1
     540           0 :                         igp1 = mod(ig,nx_global)+1
     541           0 :                         jgm1 = max(jg-1,1)
     542           0 :                         jgp1 = min(jg+1,ny_global)
     543           0 :                         if ((KMTG(ig  ,jg  ) > puny .or.                             &
     544             :                              KMTG(igm1,jg  ) > puny .or. KMTG(igp1,jg  ) > puny .or. &   ! LCOV_EXCL_LINE
     545             :                              KMTG(ig  ,jgp1) > puny .or. KMTG(ig  ,jgm1) > puny) .and. &   ! LCOV_EXCL_LINE
     546             :                             (ULATG(ig,jg) < shlat/rad_to_deg .or.          &   ! LCOV_EXCL_LINE
     547             :                              ULATG(ig,jg) > nhlat/rad_to_deg) )            &   ! LCOV_EXCL_LINE
     548           0 :                              nocn(n) = nocn(n) + flat(ig,jg)
     549             :                      else
     550      598544 :                         if (KMTG(ig,jg) > puny .and.                      &
     551             :                            (ULATG(ig,jg) < shlat/rad_to_deg .or.          &   ! LCOV_EXCL_LINE
     552             :                             ULATG(ig,jg) > nhlat/rad_to_deg) )            &   ! LCOV_EXCL_LINE
     553      430270 :                              nocn(n) = nocn(n) + flat(ig,jg)
     554             :                      endif
     555             :                   endif
     556             :                end do
     557             :             endif
     558             :          end do
     559             : 
     560             :          !*** with array syntax, we actually do work on non-ocean
     561             :          !*** points, so where the block is not completely land,
     562             :          !*** reset nocn to be the full size of the block
     563             : 
     564             :          ! use processor_shape = 'square-pop' and distribution_wght = 'block'
     565             :          ! to make CICE and POP decompositions/distributions identical.
     566             : 
     567             : #ifdef CICE_IN_NEMO
     568             :          ! Keep all blocks even the ones only containing land points
     569             :          if (distribution_wght == 'block') nocn(n) = nx_block*ny_block
     570             : #else
     571        1089 :          if (distribution_wght == 'block' .and. nocn(n) > 0) nocn(n) = nx_block*ny_block
     572        1126 :          if (.not. landblockelim) nocn(n) = max(nocn(n),1)
     573             : #endif
     574             :       end do
     575             :    endif  ! distribution_wght = file
     576             : 
     577        1126 :    work_unit = maxval(nocn)/max_work_unit + 1
     578             : 
     579             :    !*** find number of work units per block
     580             : 
     581          37 :    allocate(work_per_block(nblocks_tot))
     582             : 
     583        5514 :    where (nocn > 1)
     584           8 :      work_per_block = nocn/work_unit + 2
     585           8 :    elsewhere (nocn == 1)
     586           8 :      work_per_block = nocn/work_unit + 1
     587             :    elsewhere
     588           8 :      work_per_block = 0
     589             :    end where
     590          37 :    if (my_task == master_task) then
     591           7 :       write(nu_diag,*) 'ice_domain work_unit, max_work_unit = ',work_unit, max_work_unit
     592         490 :       write(nu_diag,*) 'ice_domain nocn = ',minval(nocn),maxval(nocn),sum(nocn)
     593         490 :       write(nu_diag,*) 'ice_domain work_per_block = ',minval(work_per_block),maxval(work_per_block),sum(work_per_block)
     594             :    endif
     595          37 :    deallocate(nocn)
     596             : 
     597             : 
     598             : !----------------------------------------------------------------------
     599             : !
     600             : !  determine the distribution of blocks across processors
     601             : !
     602             : !----------------------------------------------------------------------
     603             : 
     604             :    distrb_info = create_distribution(distribution_type, &
     605          37 :                                      nprocs, work_per_block)
     606             : 
     607          37 :    deallocate(work_per_block)
     608             : 
     609             : !----------------------------------------------------------------------
     610             : !
     611             : !  allocate and determine block id for any local blocks
     612             : !
     613             : !----------------------------------------------------------------------
     614             : 
     615          37 :    call create_local_block_ids(blocks_ice, distrb_info)
     616             : 
     617             :    ! write out block distribution
     618             :    ! internal check of icedistributionGet as part of verification process
     619          37 :    if (debug_blocks) then
     620             : 
     621           0 :       call flush_fileunit(nu_diag)
     622           0 :       call ice_barrier()
     623           0 :       if (my_task == master_task) then
     624           0 :          write(nu_diag,*) ' '
     625           0 :          write(nu_diag,'(2a)') subname, ' Blocks by Proc:'
     626             :       endif
     627           0 :       call ice_distributionGet(distrb_info, nprocs=np, numLocalBlocks=nlb)
     628           0 :       do m = 1, np
     629           0 :          if (m == my_task+1) then
     630           0 :             do n=1,nlb
     631             :                write(nu_diag,'(2a,3i8)') &
     632             :                      subname,' my_task, local block ID, global block ID: ', &   ! LCOV_EXCL_LINE
     633           0 :                      my_task, n, distrb_info%blockGlobalID(n)
     634             :             enddo
     635           0 :             call flush_fileunit(nu_diag)
     636             :          endif
     637           0 :          call ice_barrier()
     638             :       enddo
     639             : 
     640           0 :       if (my_task == master_task) then
     641           0 :          write(nu_diag,*) ' '
     642           0 :          write(nu_diag,'(2a)') subname, ' Blocks by Global Block ID:'
     643           0 :          do m = 1, nblocks_tot
     644             :             write(nu_diag,'(2a,3i8)') &
     645             :                   subname,' global block id, proc, local block ID: ', &   ! LCOV_EXCL_LINE
     646           0 :                   m, distrb_info%blockLocation(m), distrb_info%blockLocalID(m)
     647             :          enddo
     648           0 :          call flush_fileunit(nu_diag)
     649             :       endif
     650           0 :       call ice_barrier()
     651             : 
     652           0 :       call ice_distributionGet(distrb_info, nprocs=ninfo)
     653           0 :       if (ninfo /= distrb_info%nprocs) &
     654           0 :          call abort_ice(subname//' ice_distributionGet nprocs ERROR', file=__FILE__, line=__LINE__)
     655             : 
     656           0 :       call ice_distributionGet(distrb_info, communicator=ninfo)
     657           0 :       if (ninfo /= distrb_info%communicator) &
     658           0 :          call abort_ice(subname//' ice_distributionGet communicator ERROR', file=__FILE__, line=__LINE__)
     659             : 
     660           0 :       call ice_distributionGet(distrb_info, numLocalBlocks=ninfo)
     661           0 :       if (ninfo /= distrb_info%numLocalBlocks) &
     662           0 :          call abort_ice(subname//' ice_distributionGet numLocalBlocks ERROR', file=__FILE__, line=__LINE__)
     663             : 
     664           0 :       allocate(blkinfo(ninfo))
     665             : 
     666           0 :       call ice_distributionGet(distrb_info, blockGlobalID = blkinfo)
     667           0 :       do n = 1, ninfo
     668           0 :          if (blkinfo(n) /= distrb_info%blockGlobalID(n)) &
     669           0 :             call abort_ice(subname//' ice_distributionGet blockGlobalID ERROR', file=__FILE__, line=__LINE__)
     670             :       enddo
     671             : 
     672           0 :       deallocate(blkinfo)
     673           0 :       allocate(blkinfo(nblocks_tot))
     674             : 
     675           0 :       call ice_distributionGet(distrb_info, blockLocation = blkinfo)
     676           0 :       do n = 1, nblocks_tot
     677           0 :          if (blkinfo(n) /= distrb_info%blockLocation(n)) &
     678           0 :             call abort_ice(subname//' ice_distributionGet blockLocation ERROR', file=__FILE__, line=__LINE__)
     679             :       enddo
     680             : 
     681           0 :       call ice_distributionGet(distrb_info, blockLocalID = blkinfo)
     682           0 :       do n = 1, nblocks_tot
     683           0 :          if (blkinfo(n) /= distrb_info%blockLocalID(n)) &
     684           0 :             call abort_ice(subname//' ice_distributionGet blockLocalID ERROR', file=__FILE__, line=__LINE__)
     685             :       enddo
     686             : 
     687           0 :       deallocate(blkinfo)
     688             : 
     689           0 :       if (my_task == master_task) then
     690           0 :          write(nu_diag,*) ' '
     691           0 :          write(nu_diag,'(2a)') subname,' ice_distributionGet checks pass'
     692           0 :          write(nu_diag,*) ' '
     693             :       endif
     694             :    endif
     695             : 
     696          37 :    if (associated(blocks_ice)) then
     697          37 :       nblocks = size(blocks_ice)
     698             :    else
     699           0 :       nblocks = 0
     700             :    endif
     701          37 :    nblocks_max = 0
     702          37 :    tblocks_tmp = 0
     703         278 :    do n=0,distrb_info%nprocs - 1
     704         241 :      nblocks_tmp = nblocks
     705         241 :      call broadcast_scalar(nblocks_tmp, n)
     706         241 :      nblocks_max = max(nblocks_max,nblocks_tmp)
     707         278 :      tblocks_tmp = tblocks_tmp + nblocks_tmp
     708             :    end do
     709             : 
     710          37 :    if (my_task == master_task) then
     711             :       write(nu_diag,*) &
     712           7 :           'ice: total number of blocks is', tblocks_tmp
     713             :    endif
     714             : 
     715          37 :    if (nblocks_max > max_blocks) then
     716             :      write(outstring,*) &
     717           0 :          'ERROR: num blocks exceed max: increase max to', nblocks_max
     718             :      call abort_ice(subname//trim(outstring), &
     719           0 :         file=__FILE__, line=__LINE__)
     720          37 :    else if (nblocks_max < max_blocks) then
     721             :      write(outstring,*) &
     722           0 :          'WARNING: ice no. blocks too large: decrease max to', nblocks_max
     723           0 :      if (my_task == master_task) then
     724           0 :         write(nu_diag,*) ' ********WARNING***********'
     725           0 :         write(nu_diag,*) subname,trim(outstring)
     726           0 :         write(nu_diag,*) ' **************************'
     727           0 :         write(nu_diag,*) ' '
     728             :      endif
     729             :    endif
     730             : 
     731             : !----------------------------------------------------------------------
     732             : !
     733             : !  Set up ghost cell updates for each distribution.
     734             : !  Boundary types are cyclic, closed, tripole or tripoleT.
     735             : !
     736             : !----------------------------------------------------------------------
     737             : 
     738             :    ! update ghost cells on all four boundaries
     739             :    halo_info = ice_HaloCreate(distrb_info,     &
     740             :                         trim(ns_boundary_type),     &   ! LCOV_EXCL_LINE
     741             :                         trim(ew_boundary_type),     &   ! LCOV_EXCL_LINE
     742          37 :                         nx_global)
     743             : 
     744             : !----------------------------------------------------------------------
     745             : 
     746          74 :  end subroutine init_domain_distribution
     747             : 
     748             : !***********************************************************************
     749             : 
     750             :  end module ice_domain
     751             : 
     752             : !|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

Generated by: LCOV version 1.14-6-g40580cd