LCOV - code coverage report
Current view: top level - cicecore/cicedyn/infrastructure - ice_grid.F90 (source / functions) Hit Total Coverage
Test: 231018-211459:8916b9ff2c:1:quick Lines: 897 1703 52.67 %
Date: 2023-10-18 15:30:36 Functions: 18 30 60.00 %

          Line data    Source code
       1             : #ifdef ncdf
       2             : #define USE_NETCDF
       3             : #endif
       4             : !=======================================================================
       5             : 
       6             : ! Spatial grids, masks, and boundary conditions
       7             : !
       8             : ! authors: Elizabeth C. Hunke and William H. Lipscomb, LANL
       9             : !          Tony Craig, NCAR
      10             : !
      11             : ! 2004: Block structure added by William Lipscomb
      12             : !       init_grid split into two parts as in POP 2.0
      13             : !       Boundary update routines replaced by POP versions
      14             : ! 2006: Converted to free source form (F90) by Elizabeth Hunke
      15             : ! 2007: Option to read from netcdf files (A. Keen, Met Office)
      16             : !       Grid reading routines reworked by E. Hunke for boundary values
      17             : ! 2021: Add N (center of north face) and E (center of east face) grids
      18             : !       to support C and CD solvers.  Defining T at center of cells, U at
      19             : !       NE corner, N at center of top face, E at center of right face.
      20             : !       All cells are quadrilaterals with NE, E, and N associated with
      21             : !       directions relative to logical grid.
      22             : 
      23             :       module ice_grid
      24             : 
      25             :       use ice_kinds_mod
      26             :       use ice_broadcast, only: broadcast_scalar, broadcast_array
      27             :       use ice_boundary, only: ice_HaloUpdate, ice_HaloExtrapolate, &
      28             :           primary_grid_lengths_global_ext
      29             :       use ice_communicate, only: my_task, master_task
      30             :       use ice_blocks, only: block, get_block, nx_block, ny_block, nghost
      31             :       use ice_domain_size, only: nx_global, ny_global, max_blocks
      32             :       use ice_domain, only: blocks_ice, nblocks, halo_info, distrb_info, &
      33             :           ew_boundary_type, ns_boundary_type, init_domain_distribution
      34             :       use ice_fileunits, only: nu_diag, nu_grid, nu_kmt, &
      35             :           get_fileunit, release_fileunit, flush_fileunit
      36             :       use ice_gather_scatter, only: gather_global, scatter_global
      37             :       use ice_read_write, only: ice_read, ice_read_nc, ice_read_global, &
      38             :           ice_read_global_nc, ice_open, ice_open_nc, ice_close_nc
      39             :       use ice_timers, only: timer_bound, ice_timer_start, ice_timer_stop
      40             :       use ice_exit, only: abort_ice
      41             :       use ice_global_reductions, only: global_minval, global_maxval
      42             :       use icepack_intfc, only: icepack_warnings_flush, icepack_warnings_aborted
      43             :       use icepack_intfc, only: icepack_query_parameters, icepack_init_parameters
      44             : 
      45             :       implicit none
      46             :       private
      47             :       public :: init_grid1, init_grid2, grid_average_X2Y, &
      48             :                 alloc_grid, makemask, grid_neighbor_min, grid_neighbor_max
      49             : 
      50             :       character (len=char_len_long), public :: &
      51             :          grid_format  , & ! file format ('bin'=binary or 'nc'=netcdf)   ! LCOV_EXCL_LINE
      52             :          gridcpl_file , & !  input file for POP coupling grid info   ! LCOV_EXCL_LINE
      53             :          grid_file    , & !  input file for POP grid info   ! LCOV_EXCL_LINE
      54             :          kmt_file     , & !  input file for POP grid info   ! LCOV_EXCL_LINE
      55             :          kmt_type     , & !  options are file, default, boxislands   ! LCOV_EXCL_LINE
      56             :          bathymetry_file, & !  input bathymetry for seabed stress   ! LCOV_EXCL_LINE
      57             :          bathymetry_format, & ! bathymetry file format (default or pop)   ! LCOV_EXCL_LINE
      58             :          grid_spacing , & !  default of 30.e3m or set by user in namelist   ! LCOV_EXCL_LINE
      59             :          grid_ice  , & !  Underlying model grid structure (A, B, C, CD)   ! LCOV_EXCL_LINE
      60             :          grid_ice_thrm, & !  ocean forcing grid for thermo fields (T, U, N, E)   ! LCOV_EXCL_LINE
      61             :          grid_ice_dynu, & !  ocean forcing grid for dyn U fields  (T, U, N, E)   ! LCOV_EXCL_LINE
      62             :          grid_ice_dynv, & !  ocean forcing grid for dyn V fields  (T, U, N, E)   ! LCOV_EXCL_LINE
      63             :          grid_atm     , & !  atmos forcing grid structure (A, B, C, CD)   ! LCOV_EXCL_LINE
      64             :          grid_atm_thrm, & !  atmos forcing grid for thermo fields (T, U, N, E)   ! LCOV_EXCL_LINE
      65             :          grid_atm_dynu, & !  atmos forcing grid for dyn U fields  (T, U, N, E)   ! LCOV_EXCL_LINE
      66             :          grid_atm_dynv, & !  atmos forcing grid for dyn V fields  (T, U, N, E)   ! LCOV_EXCL_LINE
      67             :          grid_ocn     , & !  ocean forcing grid structure (A B, C, CD)   ! LCOV_EXCL_LINE
      68             :          grid_ocn_thrm, & !  ocean forcing grid for thermo fields (T, U, N, E)   ! LCOV_EXCL_LINE
      69             :          grid_ocn_dynu, & !  ocean forcing grid for dyn U fields  (T, U, N, E)   ! LCOV_EXCL_LINE
      70             :          grid_ocn_dynv, & !  ocean forcing grid for dyn V fields  (T, U, N, E)   ! LCOV_EXCL_LINE
      71             :          grid_type        !  current options are rectangular (default),
      72             :                           !  displaced_pole, tripole, regional
      73             : 
      74             :       real (kind=dbl_kind), dimension (:,:,:), allocatable, public :: &
      75             :          dxT    , & ! width of T-cell through the middle (m)   ! LCOV_EXCL_LINE
      76             :          dyT    , & ! height of T-cell through the middle (m)   ! LCOV_EXCL_LINE
      77             :          dxU    , & ! width of U-cell through the middle (m)   ! LCOV_EXCL_LINE
      78             :          dyU    , & ! height of U-cell through the middle (m)   ! LCOV_EXCL_LINE
      79             :          dxN    , & ! width of N-cell through the middle (m)   ! LCOV_EXCL_LINE
      80             :          dyN    , & ! height of N-cell through the middle (m)   ! LCOV_EXCL_LINE
      81             :          dxE    , & ! width of E-cell through the middle (m)   ! LCOV_EXCL_LINE
      82             :          dyE    , & ! height of E-cell through the middle (m)   ! LCOV_EXCL_LINE
      83             :          HTE    , & ! length of eastern edge of T-cell (m)   ! LCOV_EXCL_LINE
      84             :          HTN    , & ! length of northern edge of T-cell (m)   ! LCOV_EXCL_LINE
      85             :          tarea  , & ! area of T-cell (m^2), valid in halo   ! LCOV_EXCL_LINE
      86             :          uarea  , & ! area of U-cell (m^2), valid in halo   ! LCOV_EXCL_LINE
      87             :          narea  , & ! area of N-cell (m^2), valid in halo   ! LCOV_EXCL_LINE
      88             :          earea  , & ! area of E-cell (m^2), valid in halo   ! LCOV_EXCL_LINE
      89             :          tarear , & ! 1/tarea, valid in halo   ! LCOV_EXCL_LINE
      90             :          uarear , & ! 1/uarea, valid in halo   ! LCOV_EXCL_LINE
      91             :          narear , & ! 1/narea, valid in halo   ! LCOV_EXCL_LINE
      92             :          earear , & ! 1/earea, valid in halo   ! LCOV_EXCL_LINE
      93             :          tarean , & ! area of NH T-cells   ! LCOV_EXCL_LINE
      94             :          tareas , & ! area of SH T-cells   ! LCOV_EXCL_LINE
      95             :          ULON   , & ! longitude of velocity pts, NE corner of T pts (radians)   ! LCOV_EXCL_LINE
      96             :          ULAT   , & ! latitude of velocity pts, NE corner of T pts (radians)   ! LCOV_EXCL_LINE
      97             :          TLON   , & ! longitude of temp (T) pts (radians)   ! LCOV_EXCL_LINE
      98             :          TLAT   , & ! latitude of temp (T) pts (radians)   ! LCOV_EXCL_LINE
      99             :          NLON   , & ! longitude of center of north face of T pts (radians)   ! LCOV_EXCL_LINE
     100             :          NLAT   , & ! latitude of center of north face of T pts (radians)   ! LCOV_EXCL_LINE
     101             :          ELON   , & ! longitude of center of east face of T pts (radians)   ! LCOV_EXCL_LINE
     102             :          ELAT   , & ! latitude of center of east face of T pts (radians)   ! LCOV_EXCL_LINE
     103             :          ANGLE  , & ! for conversions between POP grid and lat/lon   ! LCOV_EXCL_LINE
     104             :          ANGLET , & ! ANGLE converted to T-cells, valid in halo   ! LCOV_EXCL_LINE
     105             :          bathymetry      , & ! ocean depth, for grounding keels and bergs (m)   ! LCOV_EXCL_LINE
     106             :          ocn_gridcell_frac   ! only relevant for lat-lon grids
     107             :                              ! gridcell value of [1 - (land fraction)] (T-cell)
     108             : 
     109             :       real (kind=dbl_kind), dimension (:,:), allocatable, public :: &
     110             :          G_HTE  , & ! length of eastern edge of T-cell (global ext.)   ! LCOV_EXCL_LINE
     111             :          G_HTN      ! length of northern edge of T-cell (global ext.)
     112             : 
     113             :       real (kind=dbl_kind), dimension (:,:,:), allocatable, public :: &
     114             :          cyp    , & ! 1.5*HTE(i,j)-0.5*HTW(i,j) = 1.5*HTE(i,j)-0.5*HTE(i-1,j)   ! LCOV_EXCL_LINE
     115             :          cxp    , & ! 1.5*HTN(i,j)-0.5*HTS(i,j) = 1.5*HTN(i,j)-0.5*HTN(i,j-1)   ! LCOV_EXCL_LINE
     116             :          cym    , & ! 0.5*HTE(i,j)-1.5*HTW(i,j) = 0.5*HTE(i,j)-1.5*HTE(i-1,j)   ! LCOV_EXCL_LINE
     117             :          cxm    , & ! 0.5*HTN(i,j)-1.5*HTS(i,j) = 0.5*HTN(i,j)-1.5*HTN(i,j-1)   ! LCOV_EXCL_LINE
     118             :          dxhy   , & ! 0.5*(HTE(i,j) - HTW(i,j)) = 0.5*(HTE(i,j) - HTE(i-1,j))   ! LCOV_EXCL_LINE
     119             :          dyhx       ! 0.5*(HTN(i,j) - HTS(i,j)) = 0.5*(HTN(i,j) - HTN(i,j-1))
     120             : 
     121             :       real (kind=dbl_kind), dimension (:,:,:), allocatable, public :: &
     122             :          ratiodxN    , & ! - dxN(i+1,j)   / dxN(i,j)   ! LCOV_EXCL_LINE
     123             :          ratiodyE    , & ! - dyE(i  ,j+1) / dyE(i,j)   ! LCOV_EXCL_LINE
     124             :          ratiodxNr   , & !   1 / ratiodxN   ! LCOV_EXCL_LINE
     125             :          ratiodyEr       !   1 / ratiodyE
     126             : 
     127             :       ! grid dimensions for rectangular grid
     128             :       real (kind=dbl_kind), public ::  &
     129             :          dxrect, & !  user_specified spacing (cm) in x-direction (uniform HTN)   ! LCOV_EXCL_LINE
     130             :          dyrect    !  user_specified spacing (cm) in y-direction (uniform HTE)
     131             : 
     132             :       ! growth factor for variable spaced grid
     133             :       real (kind=dbl_kind), public ::  &
     134             :          dxscale, & !  scale factor for grid spacing in x direction (e.g., 1.02)   ! LCOV_EXCL_LINE
     135             :          dyscale    !  scale factor for gird spacing in y direction (e.g., 1.02)
     136             : 
     137             :       real (kind=dbl_kind), public :: &
     138             :          lonrefrect, & ! lower left lon for rectgrid   ! LCOV_EXCL_LINE
     139             :          latrefrect    ! lower left lat for rectgrid
     140             : 
     141             :       ! Corners of grid boxes for history output
     142             :       real (kind=dbl_kind), dimension (:,:,:,:), allocatable, public :: &
     143             :          lont_bounds, & ! longitude of gridbox corners for T point   ! LCOV_EXCL_LINE
     144             :          latt_bounds, & ! latitude of gridbox corners for T point   ! LCOV_EXCL_LINE
     145             :          lonu_bounds, & ! longitude of gridbox corners for U point   ! LCOV_EXCL_LINE
     146             :          latu_bounds, & ! latitude of gridbox corners for U point   ! LCOV_EXCL_LINE
     147             :          lonn_bounds, & ! longitude of gridbox corners for N point   ! LCOV_EXCL_LINE
     148             :          latn_bounds, & ! latitude of gridbox corners for N point   ! LCOV_EXCL_LINE
     149             :          lone_bounds, & ! longitude of gridbox corners for E point   ! LCOV_EXCL_LINE
     150             :          late_bounds    ! latitude of gridbox corners for E point
     151             : 
     152             :       ! geometric quantities used for remapping transport
     153             :       real (kind=dbl_kind), dimension (:,:,:), allocatable, public :: &
     154             :          xav  , & ! mean T-cell value of x   ! LCOV_EXCL_LINE
     155             :          yav  , & ! mean T-cell value of y   ! LCOV_EXCL_LINE
     156             :          xxav , & ! mean T-cell value of xx   ! LCOV_EXCL_LINE
     157             : !         xyav , & ! mean T-cell value of xy   ! LCOV_EXCL_LINE
     158             : !         yyav , & ! mean T-cell value of yy   ! LCOV_EXCL_LINE
     159             :          yyav     ! mean T-cell value of yy
     160             : !         xxxav, & ! mean T-cell value of xxx
     161             : !         xxyav, & ! mean T-cell value of xxy   ! LCOV_EXCL_LINE
     162             : !         xyyav, & ! mean T-cell value of xyy   ! LCOV_EXCL_LINE
     163             : !         yyyav    ! mean T-cell value of yyy
     164             : 
     165             :       real (kind=dbl_kind), &
     166             :          dimension (:,:,:,:,:), allocatable, public :: &   ! LCOV_EXCL_LINE
     167             :          mne, & ! matrices used for coordinate transformations in remapping   ! LCOV_EXCL_LINE
     168             :          mnw, & ! ne = northeast corner, nw = northwest, etc.   ! LCOV_EXCL_LINE
     169             :          mse, &   ! LCOV_EXCL_LINE
     170             :          msw
     171             : 
     172             :       ! masks
     173             :       real (kind=dbl_kind), dimension (:,:,:), allocatable, public :: &
     174             :          hm     , & ! land/boundary mask, thickness (T-cell)   ! LCOV_EXCL_LINE
     175             :          bm     , & ! task/block id   ! LCOV_EXCL_LINE
     176             :          uvm    , & ! land/boundary mask (U-cell)   ! LCOV_EXCL_LINE
     177             :          npm    , & ! land/boundary mask (N-cell)   ! LCOV_EXCL_LINE
     178             :          epm    , & ! land/boundary mask (E-cell)   ! LCOV_EXCL_LINE
     179             :          kmt        ! ocean topography mask for bathymetry (T-cell)
     180             : 
     181             :       logical (kind=log_kind), public :: &
     182             :          use_bathymetry, & ! flag for reading in bathymetry_file   ! LCOV_EXCL_LINE
     183             :          pgl_global_ext, & ! flag for init primary grid lengths (global ext.)   ! LCOV_EXCL_LINE
     184             :          scale_dxdy        ! flag to apply scale factor to vary dx/dy in rectgrid
     185             : 
     186             :       logical (kind=log_kind), dimension (:,:,:), allocatable, public :: &
     187             :          tmask  , & ! land/boundary mask, thickness (T-cell)   ! LCOV_EXCL_LINE
     188             :          umask  , & ! land/boundary mask  (U-cell) (1 if all surrounding T cells are ocean)   ! LCOV_EXCL_LINE
     189             :          umaskCD, & ! land/boundary mask  (U-cell) (1 if at least two surrounding T cells are ocean)   ! LCOV_EXCL_LINE
     190             :          nmask  , & ! land/boundary mask, (N-cell)   ! LCOV_EXCL_LINE
     191             :          emask  , & ! land/boundary mask, (E-cell)   ! LCOV_EXCL_LINE
     192             :          lmask_n, & ! northern hemisphere mask   ! LCOV_EXCL_LINE
     193             :          lmask_s    ! southern hemisphere mask
     194             : 
     195             :       real (kind=dbl_kind), dimension (:,:,:), allocatable, public :: &
     196             :          rndex_global       ! global index for local subdomain (dbl)
     197             : 
     198             :       logical (kind=log_kind), private :: &
     199             :          l_readCenter ! If anglet exist in grid file read it otherwise calculate it
     200             : 
     201             :       interface grid_average_X2Y
     202             :          module procedure grid_average_X2Y_base , &
     203             :                           grid_average_X2Y_userwghts, &   ! LCOV_EXCL_LINE
     204             :                           grid_average_X2Y_NEversion
     205             :       end interface
     206             : 
     207             : !=======================================================================
     208             : 
     209             :       contains
     210             : 
     211             : !=======================================================================
     212             : !
     213             : ! Allocate space for all variables
     214             : !
     215          37 :       subroutine alloc_grid
     216             : 
     217             :       integer (int_kind) :: ierr
     218             : 
     219             :       character(len=*), parameter :: subname = '(alloc_grid)'
     220             : 
     221             :       allocate( &
     222             :          dxT      (nx_block,ny_block,max_blocks), & ! width of T-cell through the middle (m)   ! LCOV_EXCL_LINE
     223             :          dyT      (nx_block,ny_block,max_blocks), & ! height of T-cell through the middle (m)   ! LCOV_EXCL_LINE
     224             :          dxU      (nx_block,ny_block,max_blocks), & ! width of U-cell through the middle (m)   ! LCOV_EXCL_LINE
     225             :          dyU      (nx_block,ny_block,max_blocks), & ! height of U-cell through the middle (m)   ! LCOV_EXCL_LINE
     226             :          dxN      (nx_block,ny_block,max_blocks), & ! width of N-cell through the middle (m)   ! LCOV_EXCL_LINE
     227             :          dyN      (nx_block,ny_block,max_blocks), & ! height of N-cell through the middle (m)   ! LCOV_EXCL_LINE
     228             :          dxE      (nx_block,ny_block,max_blocks), & ! width of E-cell through the middle (m)   ! LCOV_EXCL_LINE
     229             :          dyE      (nx_block,ny_block,max_blocks), & ! height of E-cell through the middle (m)   ! LCOV_EXCL_LINE
     230             :          HTE      (nx_block,ny_block,max_blocks), & ! length of eastern edge of T-cell (m)   ! LCOV_EXCL_LINE
     231             :          HTN      (nx_block,ny_block,max_blocks), & ! length of northern edge of T-cell (m)   ! LCOV_EXCL_LINE
     232             :          tarea    (nx_block,ny_block,max_blocks), & ! area of T-cell (m^2)   ! LCOV_EXCL_LINE
     233             :          uarea    (nx_block,ny_block,max_blocks), & ! area of U-cell (m^2)   ! LCOV_EXCL_LINE
     234             :          narea    (nx_block,ny_block,max_blocks), & ! area of N-cell (m^2)   ! LCOV_EXCL_LINE
     235             :          earea    (nx_block,ny_block,max_blocks), & ! area of E-cell (m^2)   ! LCOV_EXCL_LINE
     236             :          tarear   (nx_block,ny_block,max_blocks), & ! 1/tarea   ! LCOV_EXCL_LINE
     237             :          uarear   (nx_block,ny_block,max_blocks), & ! 1/uarea   ! LCOV_EXCL_LINE
     238             :          narear   (nx_block,ny_block,max_blocks), & ! 1/narea   ! LCOV_EXCL_LINE
     239             :          earear   (nx_block,ny_block,max_blocks), & ! 1/earea   ! LCOV_EXCL_LINE
     240             :          tarean   (nx_block,ny_block,max_blocks), & ! area of NH T-cells   ! LCOV_EXCL_LINE
     241             :          tareas   (nx_block,ny_block,max_blocks), & ! area of SH T-cells   ! LCOV_EXCL_LINE
     242             :          ULON     (nx_block,ny_block,max_blocks), & ! longitude of U pts, NE corner (radians)   ! LCOV_EXCL_LINE
     243             :          ULAT     (nx_block,ny_block,max_blocks), & ! latitude of U pts, NE corner (radians)   ! LCOV_EXCL_LINE
     244             :          TLON     (nx_block,ny_block,max_blocks), & ! longitude of T pts (radians)   ! LCOV_EXCL_LINE
     245             :          TLAT     (nx_block,ny_block,max_blocks), & ! latitude of T pts (radians)   ! LCOV_EXCL_LINE
     246             :          NLON     (nx_block,ny_block,max_blocks), & ! longitude of N pts, N face (radians)   ! LCOV_EXCL_LINE
     247             :          NLAT     (nx_block,ny_block,max_blocks), & ! latitude of N pts, N face (radians)   ! LCOV_EXCL_LINE
     248             :          ELON     (nx_block,ny_block,max_blocks), & ! longitude of E pts, E face (radians)   ! LCOV_EXCL_LINE
     249             :          ELAT     (nx_block,ny_block,max_blocks), & ! latitude of E pts, E face (radians)   ! LCOV_EXCL_LINE
     250             :          ANGLE    (nx_block,ny_block,max_blocks), & ! for conversions between POP grid and lat/lon   ! LCOV_EXCL_LINE
     251             :          ANGLET   (nx_block,ny_block,max_blocks), & ! ANGLE converted to T-cells   ! LCOV_EXCL_LINE
     252             :          bathymetry(nx_block,ny_block,max_blocks),& ! ocean depth, for grounding keels and bergs (m)   ! LCOV_EXCL_LINE
     253             :          ocn_gridcell_frac(nx_block,ny_block,max_blocks),& ! only relevant for lat-lon grids   ! LCOV_EXCL_LINE
     254             :          cyp      (nx_block,ny_block,max_blocks), & ! 1.5*HTE - 0.5*HTW   ! LCOV_EXCL_LINE
     255             :          cxp      (nx_block,ny_block,max_blocks), & ! 1.5*HTN - 0.5*HTS   ! LCOV_EXCL_LINE
     256             :          cym      (nx_block,ny_block,max_blocks), & ! 0.5*HTE - 1.5*HTW   ! LCOV_EXCL_LINE
     257             :          cxm      (nx_block,ny_block,max_blocks), & ! 0.5*HTN - 1.5*HTS   ! LCOV_EXCL_LINE
     258             :          dxhy     (nx_block,ny_block,max_blocks), & ! 0.5*(HTE - HTW)   ! LCOV_EXCL_LINE
     259             :          dyhx     (nx_block,ny_block,max_blocks), & ! 0.5*(HTN - HTS)   ! LCOV_EXCL_LINE
     260             :          xav      (nx_block,ny_block,max_blocks), & ! mean T-cell value of x   ! LCOV_EXCL_LINE
     261             :          yav      (nx_block,ny_block,max_blocks), & ! mean T-cell value of y   ! LCOV_EXCL_LINE
     262             :          xxav     (nx_block,ny_block,max_blocks), & ! mean T-cell value of xx   ! LCOV_EXCL_LINE
     263             :          yyav     (nx_block,ny_block,max_blocks), & ! mean T-cell value of yy   ! LCOV_EXCL_LINE
     264             :          hm       (nx_block,ny_block,max_blocks), & ! land/boundary mask, thickness (T-cell)   ! LCOV_EXCL_LINE
     265             :          bm       (nx_block,ny_block,max_blocks), & ! task/block id   ! LCOV_EXCL_LINE
     266             :          uvm      (nx_block,ny_block,max_blocks), & ! land/boundary mask, velocity (U-cell) - water in case of all water point   ! LCOV_EXCL_LINE
     267             :          npm      (nx_block,ny_block,max_blocks), & ! land/boundary mask (N-cell)   ! LCOV_EXCL_LINE
     268             :          epm      (nx_block,ny_block,max_blocks), & ! land/boundary mask (E-cell)   ! LCOV_EXCL_LINE
     269             :          kmt      (nx_block,ny_block,max_blocks), & ! ocean topography mask for bathymetry (T-cell)   ! LCOV_EXCL_LINE
     270             :          tmask    (nx_block,ny_block,max_blocks), & ! land/boundary mask, thickness (T-cell)   ! LCOV_EXCL_LINE
     271             :          umask    (nx_block,ny_block,max_blocks), & ! land/boundary mask, velocity (U-cell)   ! LCOV_EXCL_LINE
     272             :          umaskCD  (nx_block,ny_block,max_blocks), & ! land/boundary mask, velocity (U-cell)   ! LCOV_EXCL_LINE
     273             :          nmask    (nx_block,ny_block,max_blocks), & ! land/boundary mask (N-cell)   ! LCOV_EXCL_LINE
     274             :          emask    (nx_block,ny_block,max_blocks), & ! land/boundary mask (E-cell)   ! LCOV_EXCL_LINE
     275             :          lmask_n  (nx_block,ny_block,max_blocks), & ! northern hemisphere mask   ! LCOV_EXCL_LINE
     276             :          lmask_s  (nx_block,ny_block,max_blocks), & ! southern hemisphere mask   ! LCOV_EXCL_LINE
     277             :          rndex_global(nx_block,ny_block,max_blocks), & ! global index for local subdomain (dbl)   ! LCOV_EXCL_LINE
     278             :          lont_bounds(4,nx_block,ny_block,max_blocks), & ! longitude of gridbox corners for T point   ! LCOV_EXCL_LINE
     279             :          latt_bounds(4,nx_block,ny_block,max_blocks), & ! latitude of gridbox corners for T point   ! LCOV_EXCL_LINE
     280             :          lonu_bounds(4,nx_block,ny_block,max_blocks), & ! longitude of gridbox corners for U point   ! LCOV_EXCL_LINE
     281             :          latu_bounds(4,nx_block,ny_block,max_blocks), & ! latitude of gridbox corners for U point   ! LCOV_EXCL_LINE
     282             :          lonn_bounds(4,nx_block,ny_block,max_blocks), & ! longitude of gridbox corners for N point   ! LCOV_EXCL_LINE
     283             :          latn_bounds(4,nx_block,ny_block,max_blocks), & ! latitude of gridbox corners for N point   ! LCOV_EXCL_LINE
     284             :          lone_bounds(4,nx_block,ny_block,max_blocks), & ! longitude of gridbox corners for E point   ! LCOV_EXCL_LINE
     285             :          late_bounds(4,nx_block,ny_block,max_blocks), & ! latitude of gridbox corners for E point   ! LCOV_EXCL_LINE
     286             :          mne  (2,2,nx_block,ny_block,max_blocks), & ! matrices used for coordinate transformations in remapping   ! LCOV_EXCL_LINE
     287             :          mnw  (2,2,nx_block,ny_block,max_blocks), & ! ne = northeast corner, nw = northwest, etc.   ! LCOV_EXCL_LINE
     288             :          mse  (2,2,nx_block,ny_block,max_blocks), &   ! LCOV_EXCL_LINE
     289             :          msw  (2,2,nx_block,ny_block,max_blocks), &   ! LCOV_EXCL_LINE
     290          37 :          stat=ierr)
     291          37 :       if (ierr/=0) call abort_ice(subname//'ERROR: Out of memory')
     292             : 
     293          37 :       if (grid_ice == 'CD' .or. grid_ice == 'C') then
     294             :          allocate( &
     295             :             ratiodxN (nx_block,ny_block,max_blocks), &   ! LCOV_EXCL_LINE
     296             :             ratiodyE (nx_block,ny_block,max_blocks), &   ! LCOV_EXCL_LINE
     297             :             ratiodxNr(nx_block,ny_block,max_blocks), &   ! LCOV_EXCL_LINE
     298             :             ratiodyEr(nx_block,ny_block,max_blocks), &   ! LCOV_EXCL_LINE
     299           0 :             stat=ierr)
     300           0 :          if (ierr/=0) call abort_ice(subname//'ERROR: Out of memory')
     301             :       endif
     302             : 
     303          37 :       if (pgl_global_ext) then
     304             :          allocate( &
     305             :             G_HTE(nx_global+2*nghost, ny_global+2*nghost), & ! length of eastern edge of T-cell (global ext.)   ! LCOV_EXCL_LINE
     306             :             G_HTN(nx_global+2*nghost, ny_global+2*nghost), & ! length of northern edge of T-cell (global ext.)   ! LCOV_EXCL_LINE
     307           0 :             stat=ierr)
     308           0 :          if (ierr/=0) call abort_ice(subname//'ERROR: Out of memory')
     309             :       endif
     310             : 
     311          37 :       end subroutine alloc_grid
     312             : 
     313             : !=======================================================================
     314             : 
     315             : ! Distribute blocks across processors.  The distribution is optimized
     316             : ! based on latitude and topography, contained in the ULAT and KMT arrays.
     317             : !
     318             : ! authors: William Lipscomb and Phil Jones, LANL
     319             : 
     320          37 :       subroutine init_grid1
     321             : 
     322             :       use ice_blocks, only: nx_block, ny_block
     323             :       use ice_broadcast, only: broadcast_array
     324             :       use ice_constants, only: c1
     325             : 
     326             :       integer (kind=int_kind) :: &
     327             :          fid_grid, &     ! file id for netCDF grid file   ! LCOV_EXCL_LINE
     328             :          fid_kmt         ! file id for netCDF kmt file
     329             : 
     330             :       character (char_len) :: &
     331             :          fieldname       ! field name in netCDF file
     332             : 
     333             :       real (kind=dbl_kind), dimension(:,:), allocatable :: &
     334          37 :          work_g1, work_g2
     335             : 
     336             :       real (kind=dbl_kind) :: &
     337           8 :          rad_to_deg
     338             : 
     339             :       character(len=*), parameter :: subname = '(init_grid1)'
     340             : 
     341             :       !-----------------------------------------------------------------
     342             :       ! Get global ULAT and KMT arrays used for block decomposition.
     343             :       !-----------------------------------------------------------------
     344             : 
     345          37 :       call icepack_query_parameters(rad_to_deg_out=rad_to_deg)
     346          37 :       call icepack_warnings_flush(nu_diag)
     347          37 :       if (icepack_warnings_aborted()) call abort_ice(error_message=subname, &
     348           0 :          file=__FILE__, line=__LINE__)
     349             : 
     350          37 :       allocate(work_g1(nx_global,ny_global))
     351          37 :       allocate(work_g2(nx_global,ny_global))
     352             : 
     353             :       ! check tripole flags here
     354             :       ! can't check in init_data because ns_boundary_type is not yet read
     355             :       ! can't check in init_domain_blocks because grid_type is not accessible due to circular logic
     356             : 
     357          37 :       if (grid_type == 'tripole' .and. ns_boundary_type /= 'tripole' .and. &
     358             :           ns_boundary_type /= 'tripoleT') then
     359             :          call abort_ice(subname//'ERROR: grid_type tripole needs tripole ns_boundary_type', &
     360           0 :                         file=__FILE__, line=__LINE__)
     361             :       endif
     362             : 
     363          37 :       if (grid_type == 'tripole' .and. (mod(nx_global,2)/=0)) then
     364             :          call abort_ice(subname//'ERROR: grid_type tripole requires even nx_global number', &
     365           0 :                         file=__FILE__, line=__LINE__)
     366             :       endif
     367             : 
     368             :       if (trim(grid_type) == 'displaced_pole' .or. &
     369             :           trim(grid_type) == 'tripole' .or. &   ! LCOV_EXCL_LINE
     370             :           trim(grid_type) == 'regional'     ) then
     371             : 
     372          21 :          if (trim(grid_format) == 'nc') then
     373             : 
     374           0 :             call ice_open_nc(grid_file,fid_grid)
     375           0 :             call ice_open_nc(kmt_file,fid_kmt)
     376             : 
     377           0 :             fieldname='ulat'
     378           0 :             call ice_read_global_nc(fid_grid,1,fieldname,work_g1,.true.)
     379           0 :             fieldname='kmt'
     380           0 :             call ice_read_global_nc(fid_kmt,1,fieldname,work_g2,.true.)
     381             : 
     382           0 :             if (my_task == master_task) then
     383           0 :                call ice_close_nc(fid_grid)
     384           0 :                call ice_close_nc(fid_kmt)
     385             :             endif
     386             : 
     387             :          else
     388             : 
     389          21 :             call ice_open(nu_grid,grid_file,64) ! ULAT
     390          21 :             call ice_open(nu_kmt, kmt_file, 32) ! KMT
     391             : 
     392          21 :             call ice_read_global(nu_grid,1,work_g1,'rda8',.true.)  ! ULAT
     393          21 :             call ice_read_global(nu_kmt, 1,work_g2,'ida4',.true.)  ! KMT
     394             : 
     395          21 :             if (my_task == master_task) then
     396           5 :                close (nu_grid)
     397           5 :                close (nu_kmt)
     398             :             endif
     399             : 
     400             :          endif
     401             : 
     402             :       else   ! rectangular grid
     403             : 
     404      264208 :          work_g1(:,:) = 75._dbl_kind/rad_to_deg  ! arbitrary polar latitude
     405      264208 :          work_g2(:,:) = c1
     406             : 
     407             :       endif
     408             : 
     409          37 :       call broadcast_array(work_g1, master_task)   ! ULAT
     410          37 :       call broadcast_array(work_g2, master_task)   ! KMT
     411             : 
     412             :       !-----------------------------------------------------------------
     413             :       ! distribute blocks among processors
     414             :       !-----------------------------------------------------------------
     415             : 
     416          37 :       call init_domain_distribution(work_g2, work_g1, grid_ice)  ! KMT, ULAT
     417             : 
     418          37 :       deallocate(work_g1)
     419          37 :       deallocate(work_g2)
     420             : 
     421             :       !-----------------------------------------------------------------
     422             :       ! write additional domain information
     423             :       !-----------------------------------------------------------------
     424             : 
     425          37 :       if (my_task == master_task) then
     426           7 :         write(nu_diag,'(a26,i6)') '  Block size:  nx_block = ',nx_block
     427           7 :         write(nu_diag,'(a26,i6)') '               ny_block = ',ny_block
     428             :       endif
     429             : 
     430          74 :       end subroutine init_grid1
     431             : 
     432             : !=======================================================================
     433             : 
     434             : ! Horizontal grid initialization:
     435             : !
     436             : !     U{LAT,LONG} = true {latitude,longitude} of U points
     437             : !     HT{N,E} = cell widths on {N,E} sides of T cell
     438             : !     ANGLE = angle between local x direction and true east
     439             : !     hm = land mask (c1 for ocean points, c0 for land points)
     440             : !     D{X,Y}{T,U} = {x,y} spacing centered at {T,U} points
     441             : !     T-grid and ghost cell values
     442             : !     Various grid quantities needed for dynamics and transport
     443             : !
     444             : ! author: Elizabeth C. Hunke, LANL
     445             : 
     446          37 :       subroutine init_grid2
     447             : 
     448             :       use ice_blocks, only: get_block, block, nx_block, ny_block
     449             :       use ice_constants, only: c0, c1, c2, p5, p25, c1p5, &
     450             :           field_loc_center, field_loc_NEcorner, field_loc_Nface, field_loc_Eface, &   ! LCOV_EXCL_LINE
     451             :           field_type_scalar, field_type_vector, field_type_angle
     452             :       use ice_domain_size, only: max_blocks
     453             : #if defined (_OPENMP)
     454             :       use OMP_LIB
     455             : #endif
     456             : 
     457             :       integer (kind=int_kind) :: &
     458             :          i, j, iblk, &   ! LCOV_EXCL_LINE
     459             :          ilo,ihi,jlo,jhi      ! beginning and end of physical domain
     460             : 
     461             :       real (kind=dbl_kind) :: &
     462             :          angle_0, angle_w, angle_s, angle_sw, &   ! LCOV_EXCL_LINE
     463           8 :          pi, pi2, puny
     464             : 
     465             :       logical (kind=log_kind), dimension(nx_block,ny_block,max_blocks):: &
     466          74 :          out_of_range
     467             : 
     468             :       real (kind=dbl_kind), dimension(:,:), allocatable :: &
     469          37 :          work_g1
     470             : 
     471             :       type (block) :: &
     472             :          this_block           ! block information for current block
     473             : 
     474             : #if defined (_OPENMP)
     475             :       integer(kind=omp_sched_kind) :: ompsk  ! openmp schedule
     476             :       integer(kind=int_kind) :: ompcs        ! openmp schedule count
     477             : #endif
     478             : 
     479             :       character(len=*), parameter :: subname = '(init_grid2)'
     480             : 
     481             :       !-----------------------------------------------------------------
     482             :       ! lat, lon, cell widths, angle, land mask
     483             :       !-----------------------------------------------------------------
     484             : 
     485          37 :       l_readCenter = .false.
     486             : 
     487          37 :       call icepack_query_parameters(pi_out=pi, pi2_out=pi2, puny_out=puny)
     488          37 :       call icepack_warnings_flush(nu_diag)
     489          37 :       if (icepack_warnings_aborted()) call abort_ice(error_message=subname, &
     490           0 :          file=__FILE__, line=__LINE__)
     491             : 
     492             :       if (trim(grid_type) == 'displaced_pole' .or. &
     493             :           trim(grid_type) == 'tripole' .or. &   ! LCOV_EXCL_LINE
     494             :           trim(grid_type) == 'regional'      ) then
     495          21 :          if (trim(grid_format) == 'nc') then
     496           0 :             call popgrid_nc     ! read POP grid lengths from nc file
     497             :          else
     498          21 :             call popgrid        ! read POP grid lengths directly
     499             :          endif
     500             : #ifdef CESMCOUPLED
     501             :       elseif (trim(grid_type) == 'latlon') then
     502             :          call latlongrid        ! lat lon grid for sequential CESM (CAM mode)
     503             :          return
     504             : #endif
     505          16 :       elseif (trim(grid_type) == 'cpom_grid') then
     506           0 :          call cpomgrid          ! cpom model orca1 type grid
     507             :       else
     508          16 :          call rectgrid          ! regular rectangular grid
     509             :       endif
     510             : 
     511             :       !-----------------------------------------------------------------
     512             :       ! Diagnose OpenMP thread schedule, force order in output
     513             :       !-----------------------------------------------------------------
     514             : 
     515             : #if defined (_OPENMP)
     516          20 :        !$OMP PARALLEL DO ORDERED PRIVATE(iblk) SCHEDULE(runtime)
     517             :        do iblk = 1, nblocks
     518             :           if (my_task == master_task) then
     519             :              !$OMP ORDERED
     520             :              if (iblk == 1) then
     521             :                 call omp_get_schedule(ompsk,ompcs)
     522             : !               write(nu_diag,*) ''
     523             :                 write(nu_diag,*) subname,' OpenMP runtime thread schedule:'
     524             :                 write(nu_diag,*) subname,'  omp schedule = ',ompsk,ompcs
     525             :              endif
     526             :              write(nu_diag,*) subname,' block, thread = ',iblk,OMP_GET_THREAD_NUM()
     527             :              !$OMP END ORDERED
     528             :           endif
     529             :        enddo
     530             :        !$OMP END PARALLEL DO
     531          20 :        call flush_fileunit(nu_diag)
     532             : #endif
     533             : 
     534             :       !-----------------------------------------------------------------
     535             :       ! T-grid cell and U-grid cell quantities
     536             :       ! Fill halo data locally where possible to avoid missing
     537             :       ! data associated with land block elimination
     538             :       ! Note: HTN, HTE, dx*, dy* are all defined from global arrays
     539             :       ! at halos.
     540             :       !-----------------------------------------------------------------
     541             : 
     542          20 :       !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
     543          50 :       do iblk = 1, nblocks
     544          33 :          this_block = get_block(blocks_ice(iblk),iblk)
     545          33 :          ilo = this_block%ilo
     546          33 :          ihi = this_block%ihi
     547          33 :          jlo = this_block%jlo
     548          33 :          jhi = this_block%jhi
     549             : 
     550        1239 :          do j = 1,ny_block
     551       50267 :          do i = 1,nx_block
     552       49028 :             tarea(i,j,iblk) = dxT(i,j,iblk)*dyT(i,j,iblk)
     553       49028 :             uarea(i,j,iblk) = dxU(i,j,iblk)*dyU(i,j,iblk)
     554       49028 :             narea(i,j,iblk) = dxN(i,j,iblk)*dyN(i,j,iblk)
     555       49028 :             earea(i,j,iblk) = dxE(i,j,iblk)*dyE(i,j,iblk)
     556             : 
     557       49028 :             if (tarea(i,j,iblk) > c0) then
     558       49028 :                tarear(i,j,iblk) = c1/tarea(i,j,iblk)
     559             :             else
     560           0 :                tarear(i,j,iblk) = c0 ! possible on boundaries
     561             :             endif
     562       49028 :             if (uarea(i,j,iblk) > c0) then
     563       49028 :                uarear(i,j,iblk) = c1/uarea(i,j,iblk)
     564             :             else
     565           0 :                uarear(i,j,iblk) = c0 ! possible on boundaries
     566             :             endif
     567       49028 :             if (narea(i,j,iblk) > c0) then
     568       49028 :                narear(i,j,iblk) = c1/narea(i,j,iblk)
     569             :             else
     570           0 :                narear(i,j,iblk) = c0 ! possible on boundaries
     571             :             endif
     572       50234 :             if (earea(i,j,iblk) > c0) then
     573       49028 :                earear(i,j,iblk) = c1/earea(i,j,iblk)
     574             :             else
     575           0 :                earear(i,j,iblk) = c0 ! possible on boundaries
     576             :             endif
     577             : 
     578             :          enddo
     579             :          enddo
     580             : 
     581        1173 :          do j = jlo, jhi
     582       45541 :          do i = ilo, ihi
     583       44368 :             dxhy(i,j,iblk) = p5*(HTE(i,j,iblk) - HTE(i-1,j,iblk))
     584       45508 :             dyhx(i,j,iblk) = p5*(HTN(i,j,iblk) - HTN(i,j-1,iblk))
     585             :          enddo
     586             :          enddo
     587             : 
     588        1206 :          do j = jlo, jhi+1
     589       47871 :          do i = ilo, ihi+1
     590       46665 :             cyp(i,j,iblk) = (c1p5*HTE(i,j,iblk) - p5*HTE(i-1,j,iblk))
     591       46665 :             cxp(i,j,iblk) = (c1p5*HTN(i,j,iblk) - p5*HTN(i,j-1,iblk))
     592             :             ! match order of operations in cyp, cxp for tripole grids
     593       46665 :             cym(i,j,iblk) = -(c1p5*HTE(i-1,j,iblk) - p5*HTE(i,j,iblk))
     594       47838 :             cxm(i,j,iblk) = -(c1p5*HTN(i,j-1,iblk) - p5*HTN(i,j,iblk))
     595             :          enddo
     596             :          enddo
     597             : 
     598          70 :          if (grid_ice == 'CD' .or. grid_ice == 'C') then
     599           0 :             do j = jlo, jhi
     600           0 :             do i = ilo, ihi
     601           0 :                ratiodxN (i,j,iblk) = - dxN(i+1,j  ,iblk) / dxN(i,j,iblk)
     602           0 :                ratiodyE (i,j,iblk) = - dyE(i  ,j+1,iblk) / dyE(i,j,iblk)
     603           0 :                ratiodxNr(i,j,iblk) =   c1 / ratiodxN(i,j,iblk)
     604           0 :                ratiodyEr(i,j,iblk) =   c1 / ratiodyE(i,j,iblk)
     605             :             enddo
     606             :             enddo
     607             :          endif
     608             : 
     609             :       enddo                     ! iblk
     610             :       !$OMP END PARALLEL DO
     611             : 
     612             :       !-----------------------------------------------------------------
     613             :       ! Ghost cell updates
     614             :       ! On the tripole grid, one must be careful with updates of
     615             :       !  quantities that involve a difference of cell lengths.
     616             :       ! For example, dyhx and dxhy are cell-centered vector components.
     617             :       ! Also note that on the tripole grid, cxp and cxm would swap places,
     618             :       !  as would cyp and cym.  These quantities are computed only
     619             :       !  in north and east ghost cells (above), not south and west.
     620             :       !-----------------------------------------------------------------
     621             : 
     622          37 :       call ice_timer_start(timer_bound)
     623             : 
     624             :       call ice_HaloUpdate (dxhy,               halo_info, &
     625             :                            field_loc_center,   field_type_vector, &   ! LCOV_EXCL_LINE
     626          37 :                            fillValue=c1)
     627             :       call ice_HaloUpdate (dyhx,               halo_info, &
     628             :                            field_loc_center,   field_type_vector, &   ! LCOV_EXCL_LINE
     629          37 :                            fillValue=c1)
     630             : 
     631             :       ! Update just on the tripole seam to ensure bit-for-bit symmetry across seam
     632             :       call ice_HaloUpdate (tarea,              halo_info, &
     633             :                            field_loc_center,   field_type_scalar, &   ! LCOV_EXCL_LINE
     634          37 :                            fillValue=c1,       tripoleOnly=.true.)
     635             :       call ice_HaloUpdate (uarea,              halo_info, &
     636             :                            field_loc_NEcorner, field_type_scalar, &   ! LCOV_EXCL_LINE
     637          37 :                            fillValue=c1,       tripoleOnly=.true.)
     638             :       call ice_HaloUpdate (narea,              halo_info, &
     639             :                            field_loc_Nface,    field_type_scalar, &   ! LCOV_EXCL_LINE
     640          37 :                            fillValue=c1,       tripoleOnly=.true.)
     641             :       call ice_HaloUpdate (earea,              halo_info, &
     642             :                            field_loc_Eface,    field_type_scalar, &   ! LCOV_EXCL_LINE
     643          37 :                            fillValue=c1,       tripoleOnly=.true.)
     644             :       call ice_HaloUpdate (tarear,             halo_info, &
     645             :                            field_loc_center,   field_type_scalar, &   ! LCOV_EXCL_LINE
     646          37 :                            fillValue=c1,       tripoleOnly=.true.)
     647             :       call ice_HaloUpdate (uarear,             halo_info, &
     648             :                            field_loc_NEcorner, field_type_scalar, &   ! LCOV_EXCL_LINE
     649          37 :                            fillValue=c1,       tripoleOnly=.true.)
     650             :       call ice_HaloUpdate (narear,             halo_info, &
     651             :                            field_loc_Nface,    field_type_scalar, &   ! LCOV_EXCL_LINE
     652          37 :                            fillValue=c1,       tripoleOnly=.true.)
     653             :       call ice_HaloUpdate (earear,             halo_info, &
     654             :                            field_loc_Eface,    field_type_scalar, &   ! LCOV_EXCL_LINE
     655          37 :                            fillValue=c1,       tripoleOnly=.true.)
     656             : 
     657          37 :       call ice_timer_stop(timer_bound)
     658             : 
     659             :       !-----------------------------------------------------------------
     660             :       ! Calculate ANGLET to be compatible with POP ocean model
     661             :       ! First, ensure that -pi <= ANGLE <= pi
     662             :       !-----------------------------------------------------------------
     663             : 
     664      111936 :       out_of_range = .false.
     665      111936 :       where (ANGLE < -pi .or. ANGLE > pi) out_of_range = .true.
     666      111936 :       if (count(out_of_range) > 0) then
     667           0 :          write(nu_diag,*) subname,' angle = ',minval(ANGLE),maxval(ANGLE),count(out_of_range)
     668             :          call abort_ice (subname//' ANGLE out of expected range', &
     669           0 :              file=__FILE__, line=__LINE__)
     670             :       endif
     671             : 
     672             :       !-----------------------------------------------------------------
     673             :       ! Compute ANGLE on T-grid
     674             :       !-----------------------------------------------------------------
     675          37 :       if (trim(grid_type) == 'cpom_grid') then
     676           0 :          ANGLET(:,:,:) = ANGLE(:,:,:)
     677          37 :       else if (.not. (l_readCenter)) then
     678      111936 :           ANGLET = c0
     679             : 
     680             :       !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block, &
     681          20 :       !$OMP                     angle_0,angle_w,angle_s,angle_sw)
     682          50 :       do iblk = 1, nblocks
     683          33 :          this_block = get_block(blocks_ice(iblk),iblk)
     684          33 :          ilo = this_block%ilo
     685          33 :          ihi = this_block%ihi
     686          33 :          jlo = this_block%jlo
     687          33 :          jhi = this_block%jhi
     688             : 
     689        1210 :          do j = jlo, jhi
     690       45541 :          do i = ilo, ihi
     691       44368 :             angle_0  = ANGLE(i  ,j  ,iblk) !   w----0
     692       44368 :             angle_w  = ANGLE(i-1,j  ,iblk) !   |    |
     693       44368 :             angle_s  = ANGLE(i,  j-1,iblk) !   |    |
     694       44368 :             angle_sw = ANGLE(i-1,j-1,iblk) !   sw---s
     695             :             ANGLET(i,j,iblk) = atan2(p25*(sin(angle_0)+ &
     696             :                                           sin(angle_w)+ &   ! LCOV_EXCL_LINE
     697             :                                           sin(angle_s)+ &   ! LCOV_EXCL_LINE
     698             :                                           sin(angle_sw)),&   ! LCOV_EXCL_LINE
     699             :                                      p25*(cos(angle_0)+ &   ! LCOV_EXCL_LINE
     700             :                                           cos(angle_w)+ &   ! LCOV_EXCL_LINE
     701             :                                           cos(angle_s)+ &   ! LCOV_EXCL_LINE
     702       45508 :                                           cos(angle_sw)))
     703             :          enddo
     704             :          enddo
     705             :       enddo
     706             :       !$OMP END PARALLEL DO
     707             :       endif ! cpom_grid
     708          37 :       if (trim(grid_type) == 'regional' .and. &
     709             :           (.not. (l_readCenter))) then
     710             :          ! for W boundary extrapolate from interior
     711           0 :          !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
     712           0 :          do iblk = 1, nblocks
     713           0 :             this_block = get_block(blocks_ice(iblk),iblk)
     714           0 :             ilo = this_block%ilo
     715           0 :             ihi = this_block%ihi
     716           0 :             jlo = this_block%jlo
     717           0 :             jhi = this_block%jhi
     718             : 
     719           0 :             i = ilo
     720           0 :             if (this_block%i_glob(i) == 1) then
     721           0 :                do j = jlo, jhi
     722           0 :                   ANGLET(i,j,iblk) = c2*ANGLET(i+1,j,iblk)-ANGLET(i+2,j,iblk)
     723             :                enddo
     724             :             endif
     725             :          enddo
     726             :          !$OMP END PARALLEL DO
     727             :       endif  ! regional
     728             : 
     729          37 :       call ice_timer_start(timer_bound)
     730             :       call ice_HaloUpdate (ANGLET,           halo_info, &
     731             :                            field_loc_center, field_type_angle, &   ! LCOV_EXCL_LINE
     732          37 :                            fillValue=c1)
     733          37 :       call ice_timer_stop(timer_bound)
     734             : 
     735          37 :       call makemask          ! velocity mask, hemisphere masks
     736          37 :       if (.not. (l_readCenter)) then
     737          37 :          call Tlatlon           ! get lat, lon on the T grid
     738             :       endif
     739             :       !-----------------------------------------------------------------
     740             :       ! bathymetry
     741             :       !-----------------------------------------------------------------
     742             : 
     743          37 :       if (trim(bathymetry_format) == 'default') then
     744          37 :          call get_bathymetry
     745           0 :       elseif (trim(bathymetry_format) == 'pop') then
     746           0 :          call get_bathymetry_popfile
     747             :       else
     748             :          call abort_ice(subname//'ERROR: bathymetry_format value must be default or pop', &
     749           0 :             file=__FILE__, line=__LINE__)
     750             :       endif
     751             : 
     752             :       !----------------------------------------------------------------
     753             :       ! Corner coordinates for CF compliant history files
     754             :       !----------------------------------------------------------------
     755             : 
     756          37 :       call gridbox_corners
     757          37 :       call gridbox_edges
     758             : 
     759             :       !-----------------------------------------------------------------
     760             :       ! Compute global index (used for unpacking messages from coupler)
     761             :       !-----------------------------------------------------------------
     762             : 
     763          37 :       if (my_task==master_task) then
     764           7 :          allocate(work_g1(nx_global,ny_global))
     765         843 :          do j=1,ny_global
     766       91611 :          do i=1,nx_global
     767       91604 :             work_g1(i,j) = real((j-1)*nx_global + i,kind=dbl_kind)
     768             :          enddo
     769             :          enddo
     770             :       else
     771          30 :          allocate(work_g1(1,1)) ! to save memory
     772             :       endif
     773             : 
     774             :       call scatter_global(rndex_global, work_g1,  &
     775             :                           master_task,  distrb_info, &   ! LCOV_EXCL_LINE
     776          37 :                           field_loc_center, field_type_scalar)
     777             : 
     778          37 :       deallocate(work_g1)
     779             : 
     780          37 :       end subroutine init_grid2
     781             : 
     782             : !=======================================================================
     783             : 
     784             : ! POP displaced pole grid and land mask (or tripole).
     785             : ! Grid record number, field and units are: \\
     786             : ! (1) ULAT  (radians)    \\
     787             : ! (2) ULON  (radians)    \\
     788             : ! (3) HTN   (cm)         \\
     789             : ! (4) HTE   (cm)         \\
     790             : ! (5) HUS   (cm)         \\
     791             : ! (6) HUW   (cm)         \\
     792             : ! (7) ANGLE (radians)
     793             : !
     794             : ! Land mask record number and field is (1) KMT.
     795             : !
     796             : ! author: Elizabeth C. Hunke, LANL
     797             : 
     798          21 :       subroutine popgrid
     799             : 
     800             :       use ice_blocks, only: nx_block, ny_block
     801             :       use ice_constants, only: c0, c1, p5, &
     802             :           field_loc_center, field_loc_NEcorner, &   ! LCOV_EXCL_LINE
     803             :           field_type_scalar, field_type_angle
     804             :       use ice_domain_size, only: max_blocks
     805             : 
     806             :       integer (kind=int_kind) :: &
     807             :          i, j, iblk, &   ! LCOV_EXCL_LINE
     808             :          ilo,ihi,jlo,jhi      ! beginning and end of physical domain
     809             : 
     810             :       logical (kind=log_kind) :: diag
     811             : 
     812             :       real (kind=dbl_kind), dimension(:,:), allocatable :: &
     813          21 :          work_g1
     814             : 
     815             :       real (kind=dbl_kind), dimension (nx_block,ny_block,max_blocks) :: &
     816       27842 :          work1
     817             : 
     818             :       type (block) :: &
     819             :          this_block           ! block information for current block
     820             : 
     821             :       character(len=*), parameter :: subname = '(popgrid)'
     822             : 
     823          21 :       call ice_open(nu_grid,grid_file,64)
     824          21 :       call ice_open(nu_kmt,kmt_file,32)
     825             : 
     826          21 :       diag = .true.       ! write diagnostic info
     827             : 
     828             :       !-----------------------------------------------------------------
     829             :       ! topography
     830             :       !-----------------------------------------------------------------
     831             : 
     832             :       call ice_read(nu_kmt,1,work1,'ida4',diag, &
     833             :                     field_loc=field_loc_center, &   ! LCOV_EXCL_LINE
     834          21 :                     field_type=field_type_scalar)
     835             : 
     836       73808 :       hm (:,:,:) = c0
     837       73808 :       kmt(:,:,:) = c0
     838          20 :       !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
     839           2 :       do iblk = 1, nblocks
     840           1 :          this_block = get_block(blocks_ice(iblk),iblk)
     841           1 :          ilo = this_block%ilo
     842           1 :          ihi = this_block%ihi
     843           1 :          jlo = this_block%jlo
     844           1 :          jhi = this_block%jhi
     845             : 
     846         138 :          do j = jlo, jhi
     847       11717 :          do i = ilo, ihi
     848       11600 :             kmt(i,j,iblk) = work1(i,j,iblk)
     849       11716 :             if (kmt(i,j,iblk) >= p5) hm(i,j,iblk) = c1
     850             :          enddo
     851             :          enddo
     852             :       enddo
     853             :       !$OMP END PARALLEL DO
     854             : 
     855             :       !-----------------------------------------------------------------
     856             :       ! lat, lon, angle
     857             :       !-----------------------------------------------------------------
     858             : 
     859          21 :       allocate(work_g1(nx_global,ny_global))
     860             : 
     861          21 :       call ice_read_global(nu_grid,1,work_g1,'rda8',.true.)   ! ULAT
     862          21 :       call gridbox_verts(work_g1,latt_bounds)
     863             :       call scatter_global(ULAT, work_g1, master_task, distrb_info, &
     864          21 :                           field_loc_NEcorner, field_type_scalar)
     865             :       call ice_HaloExtrapolate(ULAT, distrb_info, &
     866          21 :                                ew_boundary_type, ns_boundary_type)
     867             : 
     868          21 :       call ice_read_global(nu_grid,2,work_g1,'rda8',.true.)   ! ULON
     869          21 :       call gridbox_verts(work_g1,lont_bounds)
     870             :       call scatter_global(ULON, work_g1, master_task, distrb_info, &
     871          21 :                           field_loc_NEcorner, field_type_scalar)
     872             :       call ice_HaloExtrapolate(ULON, distrb_info, &
     873          21 :                                ew_boundary_type, ns_boundary_type)
     874             : 
     875          21 :       call ice_read_global(nu_grid,7,work_g1,'rda8',.true.)   ! ANGLE
     876             :       call scatter_global(ANGLE, work_g1, master_task, distrb_info, &
     877          21 :                           field_loc_NEcorner, field_type_angle)
     878             : 
     879             :       !-----------------------------------------------------------------
     880             :       ! cell dimensions
     881             :       ! calculate derived quantities from global arrays to preserve
     882             :       ! information on boundaries
     883             :       !-----------------------------------------------------------------
     884             : 
     885          21 :       call ice_read_global(nu_grid,3,work_g1,'rda8',.true.)   ! HTN
     886          21 :       call primary_grid_lengths_HTN(work_g1)                  ! dxU, dxT, dxN, dxE
     887             : 
     888          21 :       call ice_read_global(nu_grid,4,work_g1,'rda8',.true.)   ! HTE
     889          21 :       call primary_grid_lengths_HTE(work_g1)                  ! dyU, dyT, dyN, dyE
     890             : 
     891          21 :       deallocate(work_g1)
     892             : 
     893          21 :       if (my_task == master_task) then
     894           5 :          close (nu_grid)
     895           5 :          close (nu_kmt)
     896             :       endif
     897             : 
     898          21 :       end subroutine popgrid
     899             : 
     900             : !=======================================================================
     901             : 
     902             : ! POP displaced pole grid and land mask.
     903             : ! Grid record number, field and units are: \\
     904             : ! (1) ULAT  (radians)    \\
     905             : ! (2) ULON  (radians)    \\
     906             : ! (3) HTN   (cm)         \\
     907             : ! (4) HTE   (cm)         \\
     908             : ! (5) HUS   (cm)         \\
     909             : ! (6) HUW   (cm)         \\
     910             : ! (7) ANGLE (radians)
     911             : !
     912             : ! Land mask record number and field is (1) KMT.
     913             : !
     914             : ! author: Elizabeth C. Hunke, LANL
     915             : ! Revised for netcdf input: Ann Keen, Met Office, May 2007
     916             : 
     917           0 :       subroutine popgrid_nc
     918             : 
     919             :       use ice_blocks, only: nx_block, ny_block
     920             :       use ice_constants, only: c0, c1, &
     921             :           field_loc_center, field_loc_NEcorner, &   ! LCOV_EXCL_LINE
     922             :           field_type_scalar, field_type_angle
     923             :       use ice_domain_size, only: max_blocks
     924             : #ifdef USE_NETCDF
     925             :       use netcdf
     926             : #endif
     927             : 
     928             :       integer (kind=int_kind) :: &
     929             :          i, j, iblk, &   ! LCOV_EXCL_LINE
     930             :          ilo,ihi,jlo,jhi, &     ! beginning and end of physical domain   ! LCOV_EXCL_LINE
     931             :          fid_grid, &            ! file id for netCDF grid file   ! LCOV_EXCL_LINE
     932             :          fid_kmt                ! file id for netCDF kmt file
     933             : 
     934             :       logical (kind=log_kind) :: diag
     935             : 
     936             :       character (char_len) :: &
     937             :          fieldname              ! field name in netCDF file
     938             : 
     939             :       real (kind=dbl_kind) :: &
     940           0 :          pi
     941             : 
     942             :       real (kind=dbl_kind), dimension(:,:), allocatable :: &
     943           0 :          work_g1
     944             : 
     945             :       real (kind=dbl_kind), dimension (nx_block,ny_block,max_blocks) :: &
     946           0 :          work1
     947             : 
     948             :       type (block) :: &
     949             :          this_block           ! block information for current block
     950             : 
     951             :       integer(kind=int_kind) :: &
     952             :          varid
     953             :       integer (kind=int_kind) :: &
     954             :          status                ! status flag
     955             : 
     956             : 
     957             :       character(len=*), parameter :: subname = '(popgrid_nc)'
     958             : 
     959             : #ifdef USE_NETCDF
     960           0 :       call icepack_query_parameters(pi_out=pi)
     961           0 :       call icepack_warnings_flush(nu_diag)
     962           0 :       if (icepack_warnings_aborted()) call abort_ice(error_message=subname, &
     963           0 :          file=__FILE__, line=__LINE__)
     964             : 
     965           0 :       call ice_open_nc(grid_file,fid_grid)
     966           0 :       call ice_open_nc(kmt_file,fid_kmt)
     967             : 
     968           0 :       diag = .true.       ! write diagnostic info
     969             :       !-----------------------------------------------------------------
     970             :       ! topography
     971             :       !-----------------------------------------------------------------
     972             : 
     973           0 :       fieldname='kmt'
     974             :       call ice_read_nc(fid_kmt,1,fieldname,work1,diag, &
     975             :                        field_loc=field_loc_center, &   ! LCOV_EXCL_LINE
     976           0 :                        field_type=field_type_scalar)
     977             : 
     978           0 :       hm (:,:,:) = c0
     979           0 :       kmt(:,:,:) = c0
     980           0 :       !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
     981           0 :       do iblk = 1, nblocks
     982           0 :          this_block = get_block(blocks_ice(iblk),iblk)
     983           0 :          ilo = this_block%ilo
     984           0 :          ihi = this_block%ihi
     985           0 :          jlo = this_block%jlo
     986           0 :          jhi = this_block%jhi
     987             : 
     988           0 :          do j = jlo, jhi
     989           0 :          do i = ilo, ihi
     990           0 :             kmt(i,j,iblk) = work1(i,j,iblk)
     991           0 :             if (kmt(i,j,iblk) >= c1) hm(i,j,iblk) = c1
     992             :          enddo
     993             :          enddo
     994             :       enddo
     995             :       !$OMP END PARALLEL DO
     996             : 
     997             :       !-----------------------------------------------------------------
     998             :       ! lat, lon, angle
     999             :       !-----------------------------------------------------------------
    1000             : 
    1001           0 :       allocate(work_g1(nx_global,ny_global))
    1002             : 
    1003           0 :       fieldname='ulat'
    1004           0 :       call ice_read_global_nc(fid_grid,1,fieldname,work_g1,diag) ! ULAT
    1005           0 :       call gridbox_verts(work_g1,latt_bounds)
    1006             :       call scatter_global(ULAT, work_g1, master_task, distrb_info, &
    1007           0 :                           field_loc_NEcorner, field_type_scalar)
    1008             :       call ice_HaloExtrapolate(ULAT, distrb_info, &
    1009           0 :                                ew_boundary_type, ns_boundary_type)
    1010             : 
    1011           0 :       fieldname='ulon'
    1012           0 :       call ice_read_global_nc(fid_grid,1,fieldname,work_g1,diag) ! ULON
    1013           0 :       call gridbox_verts(work_g1,lont_bounds)
    1014             :       call scatter_global(ULON, work_g1, master_task, distrb_info, &
    1015           0 :                           field_loc_NEcorner, field_type_scalar)
    1016             :       call ice_HaloExtrapolate(ULON, distrb_info, &
    1017           0 :                                ew_boundary_type, ns_boundary_type)
    1018             : 
    1019           0 :       fieldname='angle'
    1020           0 :       call ice_read_global_nc(fid_grid,1,fieldname,work_g1,diag) ! ANGLE
    1021             :       call scatter_global(ANGLE, work_g1, master_task, distrb_info, &
    1022           0 :                           field_loc_NEcorner, field_type_angle)
    1023             :       ! fix ANGLE: roundoff error due to single precision
    1024           0 :       where (ANGLE >  pi) ANGLE =  pi
    1025           0 :       where (ANGLE < -pi) ANGLE = -pi
    1026             : 
    1027             :       ! if grid file includes anglet then read instead
    1028           0 :       fieldname='anglet'
    1029           0 :       if (my_task == master_task) then
    1030           0 :          status = nf90_inq_varid(fid_grid, trim(fieldname) , varid)
    1031           0 :          if (status /= nf90_noerr) then
    1032           0 :             write(nu_diag,*) subname//' CICE will calculate angleT, TLON and TLAT'
    1033             :          else
    1034           0 :             write(nu_diag,*) subname//' angleT, TLON and TLAT is read from grid file'
    1035           0 :             l_readCenter = .true.
    1036             :          endif
    1037             :       endif
    1038           0 :       call broadcast_scalar(l_readCenter,master_task)
    1039           0 :       if (l_readCenter) then
    1040           0 :          call ice_read_global_nc(fid_grid,1,fieldname,work_g1,diag)
    1041             :          call scatter_global(ANGLET, work_g1, master_task, distrb_info, &
    1042           0 :                              field_loc_center, field_type_angle)
    1043           0 :          where (ANGLET >  pi) ANGLET =  pi
    1044           0 :          where (ANGLET < -pi) ANGLET = -pi
    1045           0 :          fieldname="tlon"
    1046           0 :          call ice_read_global_nc(fid_grid,1,fieldname,work_g1,diag)
    1047             :          call scatter_global(TLON, work_g1, master_task, distrb_info, &
    1048           0 :                              field_loc_center, field_type_scalar)
    1049           0 :          fieldname="tlat"
    1050           0 :          call ice_read_global_nc(fid_grid,1,fieldname,work_g1,diag)
    1051             :          call scatter_global(TLAT, work_g1, master_task, distrb_info, &
    1052           0 :                              field_loc_center, field_type_scalar)
    1053             :       endif
    1054             :       !-----------------------------------------------------------------
    1055             :       ! cell dimensions
    1056             :       ! calculate derived quantities from global arrays to preserve
    1057             :       ! information on boundaries
    1058             :       !-----------------------------------------------------------------
    1059             : 
    1060           0 :       fieldname='htn'
    1061           0 :       call ice_read_global_nc(fid_grid,1,fieldname,work_g1,diag) ! HTN
    1062           0 :       call primary_grid_lengths_HTN(work_g1)                  ! dxU, dxT, dxN, dxE
    1063           0 :       fieldname='hte'
    1064           0 :       call ice_read_global_nc(fid_grid,1,fieldname,work_g1,diag) ! HTE
    1065           0 :       call primary_grid_lengths_HTE(work_g1)                  ! dyU, dyT, dyN, dyE
    1066             : 
    1067           0 :       deallocate(work_g1)
    1068             : 
    1069           0 :       if (my_task == master_task) then
    1070           0 :          call ice_close_nc(fid_grid)
    1071           0 :          call ice_close_nc(fid_kmt)
    1072             :       endif
    1073             : #else
    1074             :       call abort_ice(subname//'ERROR: USE_NETCDF cpp not defined', &
    1075             :           file=__FILE__, line=__LINE__)
    1076             : #endif
    1077             : 
    1078           0 :       end subroutine popgrid_nc
    1079             : 
    1080             : #ifdef CESMCOUPLED
    1081             : !=======================================================================
    1082             : 
    1083             : ! Read in kmt file that matches CAM lat-lon grid and has single column
    1084             : ! functionality
    1085             : ! author: Mariana Vertenstein
    1086             : ! 2007: Elizabeth Hunke upgraded to netcdf90 and cice ncdf calls
    1087             : 
    1088             :       subroutine latlongrid
    1089             : 
    1090             : !     use ice_boundary
    1091             :       use ice_domain_size
    1092             :       use ice_scam, only : scmlat, scmlon, single_column
    1093             :       use ice_constants, only: c0, c1, p5, p25, &
    1094             :           field_loc_center, field_type_scalar, radius
    1095             : #ifdef USE_NETCDF
    1096             :       use netcdf
    1097             : #endif
    1098             : 
    1099             :       integer (kind=int_kind) :: &
    1100             :          i, j, iblk
    1101             : 
    1102             :       integer (kind=int_kind) :: &
    1103             :          ni, nj, ncid, dimid, varid, ier
    1104             : 
    1105             :       type (block) :: &
    1106             :          this_block           ! block information for current block
    1107             : 
    1108             :       integer (kind=int_kind) :: &
    1109             :          ilo,ihi,jlo,jhi      ! beginning and end of physical domain
    1110             : 
    1111             :       real (kind=dbl_kind) :: &
    1112             :            closelat, &        ! Single-column latitude value   ! LCOV_EXCL_LINE
    1113             :            closelon, &        ! Single-column longitude value   ! LCOV_EXCL_LINE
    1114             :            closelatidx, &     ! Single-column latitude index to retrieve   ! LCOV_EXCL_LINE
    1115             :            closelonidx        ! Single-column longitude index to retrieve
    1116             : 
    1117             :       integer (kind=int_kind) :: &
    1118             :            start(2), &        ! Start index to read in   ! LCOV_EXCL_LINE
    1119             :            count(2)           ! Number of points to read in
    1120             : 
    1121             :       integer (kind=int_kind) :: &
    1122             :            start3(3), &        ! Start index to read in   ! LCOV_EXCL_LINE
    1123             :            count3(3)           ! Number of points to read in
    1124             : 
    1125             :       integer (kind=int_kind) :: &
    1126             :         status                ! status flag
    1127             : 
    1128             :       real (kind=dbl_kind), allocatable :: &
    1129             :            lats(:),lons(:),pos_lons(:), glob_grid(:,:)  ! temporaries
    1130             : 
    1131             :       real (kind=dbl_kind) :: &
    1132             :          pos_scmlon,&         ! temporary   ! LCOV_EXCL_LINE
    1133             :          pi, &   ! LCOV_EXCL_LINE
    1134             :          puny, &   ! LCOV_EXCL_LINE
    1135             :          scamdata             ! temporary
    1136             : 
    1137             :       character(len=*), parameter :: subname = '(lonlatgrid)'
    1138             : 
    1139             : #ifdef USE_NETCDF
    1140             :       !-----------------------------------------------------------------
    1141             :       ! - kmt file is actually clm fractional land file
    1142             :       ! - Determine consistency of dimensions
    1143             :       ! - Read in lon/lat centers in degrees from kmt file
    1144             :       ! - Read in ocean from "kmt" file (1 for ocean, 0 for land)
    1145             :       !-----------------------------------------------------------------
    1146             : 
    1147             :       call icepack_query_parameters(pi_out=pi, puny_out=puny)
    1148             :       call icepack_warnings_flush(nu_diag)
    1149             :       if (icepack_warnings_aborted()) call abort_ice(error_message=subname, &
    1150             :          file=__FILE__, line=__LINE__)
    1151             : 
    1152             :       ! Determine dimension of domain file and check for consistency
    1153             : 
    1154             :       if (my_task == master_task) then
    1155             :          call ice_open_nc(kmt_file, ncid)
    1156             : 
    1157             :          status = nf90_inq_dimid (ncid, 'ni', dimid)
    1158             :          status = nf90_inquire_dimension(ncid, dimid, len=ni)
    1159             :          status = nf90_inq_dimid (ncid, 'nj', dimid)
    1160             :          status = nf90_inquire_dimension(ncid, dimid, len=nj)
    1161             :       end if
    1162             : 
    1163             :       ! Determine start/count to read in for either single column or global lat-lon grid
    1164             :       ! If single_column, then assume that only master_task is used since there is only one task
    1165             : 
    1166             :       if (single_column) then
    1167             :          ! Check for consistency
    1168             :          if (my_task == master_task) then
    1169             :             if ((nx_global /= 1).or. (ny_global /= 1)) then
    1170             :                write(nu_diag,*) 'Because you have selected the column model flag'
    1171             :                write(nu_diag,*) 'Please set nx_global=ny_global=1 in file'
    1172             :                write(nu_diag,*) 'ice_domain_size.F and recompile'
    1173             :                call abort_ice (subname//'ERROR: check nx_global, ny_global')
    1174             :             endif
    1175             :          end if
    1176             : 
    1177             :          ! Read in domain file for single column
    1178             :          allocate(lats(nj))
    1179             :          allocate(lons(ni))
    1180             :          allocate(pos_lons(ni))
    1181             :          allocate(glob_grid(ni,nj))
    1182             : 
    1183             :          start3=(/1,1,1/)
    1184             :          count3=(/ni,nj,1/)
    1185             :          status = nf90_inq_varid(ncid, 'xc' , varid)
    1186             :          if (status /= nf90_noerr) call abort_ice (subname//' inq_varid xc')
    1187             :          status = nf90_get_var(ncid, varid, glob_grid, start3, count3)
    1188             :          if (status /= nf90_noerr) call abort_ice (subname//' get_var xc')
    1189             :          do i = 1,ni
    1190             :             lons(i) = glob_grid(i,1)
    1191             :          end do
    1192             : 
    1193             :          status = nf90_inq_varid(ncid, 'yc' , varid)
    1194             :          if (status /= nf90_noerr) call abort_ice (subname//' inq_varid yc')
    1195             :          status = nf90_get_var(ncid, varid, glob_grid, start3, count3)
    1196             :          if (status /= nf90_noerr) call abort_ice (subname//' get_var yc')
    1197             :          do j = 1,nj
    1198             :             lats(j) = glob_grid(1,j)
    1199             :          end do
    1200             : 
    1201             :          ! convert lons array and scmlon to 0,360 and find index of value closest to 0
    1202             :          ! and obtain single-column longitude/latitude indices to retrieve
    1203             : 
    1204             :          pos_lons(:)= mod(lons(:) + 360._dbl_kind,360._dbl_kind)
    1205             :          pos_scmlon = mod(scmlon  + 360._dbl_kind,360._dbl_kind)
    1206             :          start(1) = (MINLOC(abs(pos_lons-pos_scmlon),dim=1))
    1207             :          start(2) = (MINLOC(abs(lats    -scmlat    ),dim=1))
    1208             : 
    1209             :          deallocate(lats)
    1210             :          deallocate(lons)
    1211             :          deallocate(pos_lons)
    1212             :          deallocate(glob_grid)
    1213             : 
    1214             :          status = nf90_inq_varid(ncid, 'xc' , varid)
    1215             :          if (status /= nf90_noerr) call abort_ice (subname//' inq_varid xc')
    1216             :          status = nf90_get_var(ncid, varid, scamdata, start)
    1217             :          if (status /= nf90_noerr) call abort_ice (subname//' get_var xc')
    1218             :          TLON = scamdata
    1219             :          status = nf90_inq_varid(ncid, 'yc' , varid)
    1220             :          if (status /= nf90_noerr) call abort_ice (subname//' inq_varid yc')
    1221             :          status = nf90_get_var(ncid, varid, scamdata, start)
    1222             :          if (status /= nf90_noerr) call abort_ice (subname//' get_var yc')
    1223             :          TLAT = scamdata
    1224             :          status = nf90_inq_varid(ncid, 'area' , varid)
    1225             :          if (status /= nf90_noerr) call abort_ice (subname//' inq_varid area')
    1226             :          status = nf90_get_var(ncid, varid, scamdata, start)
    1227             :          if (status /= nf90_noerr) call abort_ice (subname//' get_var are')
    1228             :          tarea = scamdata
    1229             :          status = nf90_inq_varid(ncid, 'mask' , varid)
    1230             :          if (status /= nf90_noerr) call abort_ice (subname//' inq_varid mask')
    1231             :          status = nf90_get_var(ncid, varid, scamdata, start)
    1232             :          if (status /= nf90_noerr) call abort_ice (subname//' get_var mask')
    1233             :          hm = scamdata
    1234             :          status = nf90_inq_varid(ncid, 'frac' , varid)
    1235             :          if (status /= nf90_noerr) call abort_ice (subname//' inq_varid frac')
    1236             :          status = nf90_get_var(ncid, varid, scamdata, start)
    1237             :          if (status /= nf90_noerr) call abort_ice (subname//' get_var frac')
    1238             :          ocn_gridcell_frac = scamdata
    1239             :       else
    1240             :          ! Check for consistency
    1241             :          if (my_task == master_task) then
    1242             :             if (nx_global /= ni .and. ny_global /= nj) then
    1243             :               write(nu_diag,*) 'latlongrid: ni,nj = ',ni,nj
    1244             :               write(nu_diag,*) 'latlongrid: nx_g,ny_g = ',nx_global, ny_global
    1245             :               call abort_ice (subname//'ERROR: ni,nj not equal to nx_global,ny_global')
    1246             :             end if
    1247             :          end if
    1248             : 
    1249             :          ! Read in domain file for global lat-lon grid
    1250             :          call ice_read_nc(ncid, 1, 'xc'  , TLON             , diag=.true.)
    1251             :          call ice_read_nc(ncid, 1, 'yc'  , TLAT             , diag=.true.)
    1252             :          call ice_read_nc(ncid, 1, 'area', tarea            , diag=.true., &
    1253             :             field_loc=field_loc_center,field_type=field_type_scalar)
    1254             :          call ice_read_nc(ncid, 1, 'mask', hm               , diag=.true.)
    1255             :          call ice_read_nc(ncid, 1, 'frac', ocn_gridcell_frac, diag=.true.)
    1256             :       end if
    1257             : 
    1258             :       if (my_task == master_task) then
    1259             :          call ice_close_nc(ncid)
    1260             :       end if
    1261             : 
    1262             :      !$OMP PARALLEL DO PRIVATE(iblk,this_block,ilo,ihi,jlo,jhi,i,j)
    1263             :       do iblk = 1, nblocks
    1264             :          this_block = get_block(blocks_ice(iblk),iblk)
    1265             :          ilo = this_block%ilo
    1266             :          ihi = this_block%ihi
    1267             :          jlo = this_block%jlo
    1268             :          jhi = this_block%jhi
    1269             : 
    1270             :          do j = jlo, jhi
    1271             :          do i = ilo, ihi
    1272             :             ! Convert from degrees to radians
    1273             :             TLON(i,j,iblk) = pi*TLON(i,j,iblk)/180._dbl_kind
    1274             : 
    1275             :             ! Convert from degrees to radians
    1276             :             TLAT(i,j,iblk) = pi*TLAT(i,j,iblk)/180._dbl_kind
    1277             : 
    1278             :             ! Convert from radians^2 to m^2
    1279             :             ! (area in domain file is in radians^2 and tarea is in m^2)
    1280             :             tarea(i,j,iblk) = tarea(i,j,iblk) * (radius*radius)
    1281             :          end do
    1282             :          end do
    1283             :       end do
    1284             :       !$OMP END PARALLEL DO
    1285             : 
    1286             :       !-----------------------------------------------------------------
    1287             :       ! Calculate various geometric 2d arrays
    1288             :       ! The U grid (velocity) is not used when run with sequential CAM
    1289             :       ! because we only use thermodynamic sea ice.  However, ULAT is used
    1290             :       ! in the default initialization of CICE so we calculate it here as
    1291             :       ! a "dummy" so that CICE will initialize with ice.  If a no ice
    1292             :       ! initialization is OK (or desired) this can be commented out and
    1293             :       ! ULAT will remain 0 as specified above.  ULAT is located at the
    1294             :       ! NE corner of the grid cell, TLAT at the center, so here ULAT is
    1295             :       ! hacked by adding half the latitudinal spacing (in radians) to
    1296             :       ! TLAT.
    1297             :       !-----------------------------------------------------------------
    1298             : 
    1299             :      !$OMP PARALLEL DO PRIVATE(iblk,this_block,ilo,ihi,jlo,jhi,i,j)
    1300             :       do iblk = 1, nblocks
    1301             :          this_block = get_block(blocks_ice(iblk),iblk)
    1302             :          ilo = this_block%ilo
    1303             :          ihi = this_block%ihi
    1304             :          jlo = this_block%jlo
    1305             :          jhi = this_block%jhi
    1306             : 
    1307             :          do j = jlo, jhi
    1308             :          do i = ilo, ihi
    1309             : 
    1310             :             if (ny_global == 1) then
    1311             :                uarea(i,j,iblk)  = tarea(i,j,  iblk)
    1312             :             else
    1313             :                uarea(i,j,iblk)  = p25*  &
    1314             :                                  (tarea(i,j,  iblk) + tarea(i+1,j,  iblk) &   ! LCOV_EXCL_LINE
    1315             :                                 + tarea(i,j+1,iblk) + tarea(i+1,j+1,iblk))
    1316             :             endif
    1317             :             tarear(i,j,iblk)   = c1/tarea(i,j,iblk)
    1318             :             uarear(i,j,iblk)   = c1/uarea(i,j,iblk)
    1319             : 
    1320             :             if (single_column) then
    1321             :                ULAT  (i,j,iblk) = TLAT(i,j,iblk)+(pi/nj)
    1322             :             else
    1323             :                if (ny_global == 1) then
    1324             :                   ULAT  (i,j,iblk) = TLAT(i,j,iblk)
    1325             :                else
    1326             :                   ULAT  (i,j,iblk) = TLAT(i,j,iblk)+(pi/ny_global)
    1327             :                endif
    1328             :             endif
    1329             :             ULON  (i,j,iblk) = c0
    1330             :             NLON  (i,j,iblk) = c0
    1331             :             NLAT  (i,j,iblk) = c0
    1332             :             ELON  (i,j,iblk) = c0
    1333             :             ELAT  (i,j,iblk) = c0
    1334             :             ANGLE (i,j,iblk) = c0
    1335             : 
    1336             :             ANGLET(i,j,iblk) = c0
    1337             :             HTN   (i,j,iblk) = 1.e36_dbl_kind
    1338             :             HTE   (i,j,iblk) = 1.e36_dbl_kind
    1339             :             dxT   (i,j,iblk) = 1.e36_dbl_kind
    1340             :             dyT   (i,j,iblk) = 1.e36_dbl_kind
    1341             :             dxU   (i,j,iblk) = 1.e36_dbl_kind
    1342             :             dyU   (i,j,iblk) = 1.e36_dbl_kind
    1343             :             dxN   (i,j,iblk) = 1.e36_dbl_kind
    1344             :             dyN   (i,j,iblk) = 1.e36_dbl_kind
    1345             :             dxE   (i,j,iblk) = 1.e36_dbl_kind
    1346             :             dyE   (i,j,iblk) = 1.e36_dbl_kind
    1347             :             dxhy  (i,j,iblk) = 1.e36_dbl_kind
    1348             :             dyhx  (i,j,iblk) = 1.e36_dbl_kind
    1349             :             cyp   (i,j,iblk) = 1.e36_dbl_kind
    1350             :             cxp   (i,j,iblk) = 1.e36_dbl_kind
    1351             :             cym   (i,j,iblk) = 1.e36_dbl_kind
    1352             :             cxm   (i,j,iblk) = 1.e36_dbl_kind
    1353             :          enddo
    1354             :          enddo
    1355             :       enddo
    1356             :       !$OMP END PARALLEL DO
    1357             : 
    1358             :       call makemask
    1359             : #else
    1360             :       call abort_ice(subname//'ERROR: USE_NETCDF cpp not defined', &
    1361             :           file=__FILE__, line=__LINE__)
    1362             : #endif
    1363             : 
    1364             :       end subroutine latlongrid
    1365             : #endif
    1366             : !=======================================================================
    1367             : 
    1368             : ! Regular rectangular grid and mask
    1369             : !
    1370             : ! author: Elizabeth C. Hunke, LANL
    1371             : 
    1372          16 :       subroutine rectgrid
    1373             : 
    1374             :       use ice_constants, only: c0, c1, c2, radius, cm_to_m, &
    1375             :           field_loc_center, field_loc_NEcorner, field_type_scalar
    1376             :       use ice_domain, only: close_boundaries
    1377             : 
    1378             :       integer (kind=int_kind) :: &
    1379             :          i, j, &   ! LCOV_EXCL_LINE
    1380             :          imid, jmid
    1381             : 
    1382             :       real (kind=dbl_kind) :: &
    1383             :          length,  &   ! LCOV_EXCL_LINE
    1384           0 :          rad_to_deg
    1385             : 
    1386             :       real (kind=dbl_kind), dimension(:,:), allocatable :: &
    1387          16 :          work_g1
    1388             : 
    1389             :       character(len=*), parameter :: subname = '(rectgrid)'
    1390             : 
    1391             :       !-----------------------------------------------------------------
    1392             :       ! Calculate various geometric 2d arrays
    1393             :       !-----------------------------------------------------------------
    1394             : 
    1395          16 :       call icepack_query_parameters(rad_to_deg_out=rad_to_deg)
    1396          16 :       call icepack_warnings_flush(nu_diag)
    1397          16 :       if (icepack_warnings_aborted()) call abort_ice(error_message=subname, &
    1398           0 :          file=__FILE__, line=__LINE__)
    1399             : 
    1400       38128 :       hm (:,:,:) = c0
    1401       38128 :       kmt(:,:,:) = c0
    1402       38128 :       angle(:,:,:) = c0   ! "square with the world"
    1403             : 
    1404          16 :       allocate(work_g1(nx_global,ny_global))
    1405             : 
    1406          16 :       if (scale_dxdy) then
    1407             :          ! scale grid spacing from center outward.
    1408             :          ! this different than original method in it
    1409             :          ! needs to define grid spacing before lat/lon.
    1410             :          ! original rectgrid defines latlon first
    1411           0 :          call rectgrid_scale_dxdy
    1412             :       else
    1413             :          ! rectgrid no grid spacing.
    1414             :          ! original method with addition to use namelist lat/lon reference
    1415             : 
    1416          16 :          if (my_task == master_task) then
    1417       33026 :             work_g1 = c0
    1418           2 :             length = dxrect*cm_to_m/radius*rad_to_deg
    1419             : 
    1420         258 :             work_g1(1,:) = lonrefrect ! reference lon from namelist
    1421             : 
    1422         258 :             do j = 1, ny_global
    1423       32770 :             do i = 2, nx_global
    1424       32768 :                work_g1(i,j) = work_g1(i-1,j) + length   ! ULON
    1425             :             enddo
    1426             :             enddo
    1427       33026 :             work_g1(:,:) = work_g1(:,:) / rad_to_deg
    1428             :          endif
    1429             :          call scatter_global(ULON, work_g1, master_task, distrb_info, &
    1430          16 :                              field_loc_NEcorner, field_type_scalar)
    1431             :          call ice_HaloExtrapolate(ULON, distrb_info, &
    1432          16 :                                   ew_boundary_type, ns_boundary_type)
    1433             : 
    1434          16 :          if (my_task == master_task) then
    1435       33026 :             work_g1 = c0
    1436           2 :             length = dyrect*cm_to_m/radius*rad_to_deg
    1437             : 
    1438         258 :             work_g1(:,1) = latrefrect ! reference latitude from namelist
    1439             : 
    1440         258 :             do i = 1, nx_global
    1441       32770 :             do j = 2, ny_global
    1442       32768 :                work_g1(i,j) = work_g1(i,j-1) + length   ! ULAT
    1443             :             enddo
    1444             :             enddo
    1445       33026 :             work_g1(:,:) = work_g1(:,:) / rad_to_deg
    1446             :          endif
    1447             :          call scatter_global(ULAT, work_g1, master_task, distrb_info, &
    1448          16 :                              field_loc_NEcorner, field_type_scalar)
    1449             :          call ice_HaloExtrapolate(ULAT, distrb_info, &
    1450          16 :                                   ew_boundary_type, ns_boundary_type)
    1451             : 
    1452          16 :          if (my_task == master_task) then
    1453         258 :             do j = 1, ny_global
    1454       33026 :             do i = 1, nx_global
    1455       33024 :                work_g1(i,j) = dxrect             ! HTN
    1456             :             enddo
    1457             :             enddo
    1458             :          endif
    1459          16 :          call primary_grid_lengths_HTN(work_g1)  ! dxU, dxT, dxN, dxE
    1460             : 
    1461          16 :          if (my_task == master_task) then
    1462         258 :             do j = 1, ny_global
    1463       33026 :             do i = 1, nx_global
    1464       33024 :                work_g1(i,j) = dyrect             ! HTE
    1465             :             enddo
    1466             :             enddo
    1467             :          endif
    1468          16 :          call primary_grid_lengths_HTE(work_g1)  ! dyU, dyT, dyN, dyE
    1469             : 
    1470             :       endif ! scale_dxdy
    1471             : 
    1472             :       !-----------------------------------------------------------------
    1473             :       ! Construct T-cell land mask
    1474             :       ! Keyed on ew_boundary_type; ns_boundary_type should be 'open'.
    1475             :       !-----------------------------------------------------------------
    1476             : 
    1477          16 :       if (my_task == master_task) then
    1478       33026 :          work_g1(:,:) = c0      ! initialize hm as land
    1479             : 
    1480           2 :          if (trim(kmt_type) == 'boxislands') then
    1481             : 
    1482           0 :             call grid_boxislands_kmt(work_g1)
    1483             : 
    1484           2 :          elseif (trim(kmt_type) == 'channel') then
    1485             : 
    1486           0 :             do j = 3,ny_global-2     ! closed top and bottom
    1487           0 :             do i = 1,nx_global       ! open sides
    1488           0 :                work_g1(i,j) = c1     ! NOTE nx_global > 5
    1489             :             enddo
    1490             :             enddo
    1491             : 
    1492           2 :          elseif (trim(kmt_type) == 'channel_oneeast') then
    1493             : 
    1494           0 :             do j = ny_global/2,ny_global/2    ! one channel wide
    1495           0 :             do i = 1,nx_global       ! open sides
    1496           0 :                work_g1(i,j) = c1     ! NOTE nx_global > 5
    1497             :             enddo
    1498             :             enddo
    1499             : 
    1500           2 :          elseif (trim(kmt_type) == 'channel_onenorth') then
    1501             : 
    1502           0 :             do j = 1,ny_global       ! open sides
    1503           0 :             do i = nx_global/2,nx_global/2    ! one channel wide
    1504           0 :                work_g1(i,j) = c1     ! NOTE nx_global > 5
    1505             :             enddo
    1506             :             enddo
    1507             : 
    1508           2 :          elseif (trim(kmt_type) == 'wall') then
    1509             : 
    1510           0 :             do j = 1,ny_global       ! open except
    1511           0 :             do i = 1,nx_global-2     ! closed east edge
    1512           0 :                work_g1(i,j) = c1
    1513             :             enddo
    1514             :             enddo
    1515             : 
    1516           2 :          elseif (trim(kmt_type) == 'default') then
    1517             : 
    1518             :             ! land in the upper left and lower right corners,
    1519             :             ! otherwise open boundaries
    1520           2 :             imid = nint(aint(real(nx_global)/c2))
    1521           2 :             jmid = nint(aint(real(ny_global)/c2))
    1522             : 
    1523         250 :             do j = 3,ny_global-2
    1524       31002 :             do i = 3,nx_global-2
    1525       31000 :                work_g1(i,j) = c1    ! open central domain
    1526             :             enddo
    1527             :             enddo
    1528             : 
    1529           2 :             if (nx_global > 5 .and. ny_global > 5) then
    1530             : 
    1531         134 :                do j = 1, jmid+2
    1532        8846 :                do i = 1, imid+2
    1533        8844 :                   work_g1(i,j) = c1    ! open lower left corner
    1534             :                enddo
    1535             :                enddo
    1536             : 
    1537         136 :                do j = max(jmid-2,1), ny_global
    1538        9114 :                do i = max(imid-2,1), nx_global
    1539        9112 :                   work_g1(i,j) = c1    ! open upper right corner
    1540             :                enddo
    1541             :                enddo
    1542             : 
    1543             :             endif ! > 5x5 grid
    1544             : 
    1545             :          else
    1546             : 
    1547           0 :             call abort_ice(subname//'ERROR: unknown kmt_type '//trim(kmt_type))
    1548             : 
    1549             :          endif ! kmt_type
    1550             : 
    1551           2 :          if (close_boundaries) then
    1552           0 :             work_g1(:, 1:2) = c0
    1553           0 :             work_g1(:, ny_global-1:ny_global) = c0
    1554           0 :             work_g1(1:2, :) = c0
    1555           0 :             work_g1(nx_global-1:nx_global, :) = c0
    1556             :          endif
    1557             : 
    1558             :       endif
    1559             : 
    1560             :       call scatter_global(hm, work_g1, master_task, distrb_info, &
    1561          16 :                           field_loc_center, field_type_scalar)
    1562             : 
    1563          16 :       deallocate(work_g1)
    1564             : 
    1565          32 :       end subroutine rectgrid
    1566             : 
    1567             : !=======================================================================
    1568             : 
    1569           0 :       subroutine rectgrid_scale_dxdy
    1570             : 
    1571             :         ! generate a variable spaced rectangluar grid.
    1572             :         ! extend spacing from center of grid outward.
    1573             :         use ice_constants, only: c0, c1, c2, radius, cm_to_m, &
    1574             :              field_loc_center, field_loc_NEcorner, field_type_scalar
    1575             : 
    1576             :         integer (kind=int_kind) :: &
    1577             :              i, j, iblk, &   ! LCOV_EXCL_LINE
    1578             :              imid, jmid, &   ! LCOV_EXCL_LINE
    1579             :              center1, center2 ! array centers for expanding dx, dy
    1580             : 
    1581             :         real (kind=dbl_kind) :: &
    1582             :              length,  &   ! LCOV_EXCL_LINE
    1583           0 :              rad_to_deg
    1584             : 
    1585             :         real (kind=dbl_kind), dimension(:,:), allocatable :: &
    1586           0 :              work_g1
    1587             : 
    1588             :         character(len=*), parameter :: subname = '(rectgrid_scale_dxdy)'
    1589             : 
    1590           0 :         call icepack_query_parameters(rad_to_deg_out=rad_to_deg)
    1591             : 
    1592           0 :         allocate(work_g1(nx_global,ny_global))
    1593             : 
    1594             :         ! determine dx spacing
    1595             :         ! strategy: initialize with dxrect.
    1596             :         ! if want to scale the grid, work from center outwards,
    1597             :         ! multplying neighbor cell by scale factor.
    1598             :         ! this assumes dx varies in x direction only.
    1599             :         ! (i.e, dx is the same across same y location)
    1600           0 :         if (my_task == master_task) then
    1601             : 
    1602             :            ! initialize with initial dxrect
    1603           0 :            work_g1(:,:) = dxrect
    1604             : 
    1605             :            ! check if nx is even or odd
    1606             :            ! if even, middle 2 columns are center
    1607             :            ! of odd,  middle 1 column is center
    1608           0 :            if (mod(nx_global,2) == 0) then ! nx_global is even
    1609             : 
    1610             :               ! with even number of x locatons,
    1611             :               ! the center two y columns are center
    1612           0 :               center1 = nx_global/2  ! integer math
    1613           0 :               center2 = center1 + 1  ! integer math
    1614             : 
    1615             :            else ! nx_global = odd
    1616             :               ! only one center index. set center2=center1
    1617           0 :               center1 = ceiling(real(nx_global/2),int_kind)
    1618           0 :               center2 = center1
    1619             :            endif
    1620             : 
    1621             :            ! note loop over only half the x grid points (center1)-1
    1622             :            ! working from the center outward.
    1623           0 :            do j = 1, ny_global
    1624           0 :            do i = 1, center1-1
    1625             :               ! work from center1 to left
    1626           0 :               work_g1(center1-i,j) = dxscale*work_g1(center1-i+1,j)
    1627             : 
    1628             :               ! work from center2 to right
    1629           0 :               work_g1(center2+i,j) = dxscale*work_g1(center2+i-1,j)
    1630             :            enddo ! i
    1631             :            enddo ! j
    1632             : 
    1633             :         endif       ! my_task == master_task
    1634             : 
    1635             : 
    1636             :         ! note work_g1 is converted to meters in primary_grid_lengths_HTN
    1637           0 :         call primary_grid_lengths_HTN(work_g1)  ! dxU, dxT, dxN, dxE
    1638             : 
    1639             :         ! make ULON array
    1640           0 :         if (my_task == master_task) then
    1641             : 
    1642             :            ! make first column reference lon in radians.
    1643             :            ! the remaining work_g1 is still dx in meters
    1644           0 :            work_g1(1,:) = lonrefrect/rad_to_deg ! radians
    1645             : 
    1646             :            ! loop over remaining points and add spacing to successive
    1647             :            ! x locations
    1648           0 :            do j = 1, ny_global
    1649           0 :            do i = 2, nx_global ! start from i=2. i=1 is lonrefrect
    1650           0 :               length = work_g1(i,j)/radius             ! grid spacing in radians
    1651           0 :               work_g1(i,j) = work_g1(i-1,j) + length   ! ULON
    1652             :            enddo ! i
    1653             :            enddo ! j
    1654             :         endif    ! mytask == master_task
    1655             :         call scatter_global(ULON, work_g1, master_task, distrb_info, &
    1656           0 :                             field_loc_NEcorner, field_type_scalar)
    1657             :         call ice_HaloExtrapolate(ULON, distrb_info, &
    1658           0 :                                  ew_boundary_type, ns_boundary_type)
    1659             : 
    1660             :         ! determine dy spacing
    1661             :         ! strategy: initialize with dyrect.
    1662             :         ! if want to scale the grid, work from center outwards,
    1663             :         ! multplying neighbor cell by scale factor.
    1664             :         ! this assumes dy varies in y direction only.
    1665             :         ! (i.e, dy is the same across same x location)
    1666           0 :         if (my_task == master_task) then
    1667             : 
    1668             :            ! initialize with initial dxrect
    1669           0 :            work_g1(:,:) = dyrect
    1670             : 
    1671             :            ! check if ny is even or odd
    1672             :            ! if even, middle 2 rows are center
    1673             :            ! of odd,  middle 1 row is center
    1674           0 :            if (mod(ny_global,2) == 0) then ! ny_global is even
    1675             : 
    1676             :               ! with even number of x locatons,
    1677             :               ! the center two y columns are center
    1678           0 :               center1 = ny_global/2  ! integer math
    1679           0 :               center2 = center1 + 1  ! integer math
    1680             : 
    1681             :            else ! ny_global = odd
    1682             :               ! only one center index. set center2=center1
    1683           0 :               center1 = ceiling(real(ny_global/2),int_kind)
    1684           0 :               center2 = center1
    1685             :            endif
    1686             : 
    1687             :            ! note loop over only half the y grid points (center1)-1
    1688             :            ! working from the center outward.
    1689           0 :            do i = 1, nx_global
    1690           0 :            do j = 1, center1-1
    1691             :               ! work from center1 to bottom
    1692           0 :               work_g1(i,center1-j) = dyscale*work_g1(i,center1-j+1)
    1693             : 
    1694             :               ! work from center2 to top
    1695           0 :               work_g1(i,center2+j) = dyscale*work_g1(i,center2+j-1)
    1696             :            enddo ! i
    1697             :            enddo ! j
    1698             :         endif    ! mytask == master_task
    1699             :         ! note work_g1 is converted to meters primary_grid_lengths_HTE
    1700           0 :         call primary_grid_lengths_HTE(work_g1)  ! dyU, dyT, dyN, dyE
    1701             : 
    1702             :         ! make ULAT array
    1703           0 :         if (my_task == master_task) then
    1704             : 
    1705             :            ! make first row reference lat in radians.
    1706             :            ! the remaining work_g1 is still dy in meters
    1707           0 :            work_g1(:,1) = latrefrect/rad_to_deg ! radians
    1708             : 
    1709             : 
    1710             :            ! loop over remaining points and add spacing to successive
    1711             :            ! x locations
    1712           0 :            do j = 2, ny_global ! start from j=2. j=1 is latrefrect
    1713           0 :            do i = 1, nx_global
    1714           0 :               length = work_g1(i,j)/radius             ! grid spacing in radians
    1715           0 :               work_g1(i,j) = work_g1(i,j-1) + length   ! ULAT
    1716             :            enddo ! i
    1717             :            enddo ! j
    1718             :         endif    ! mytask == master_task
    1719             :         call scatter_global(ULAT, work_g1, master_task, distrb_info, &
    1720           0 :                             field_loc_NEcorner, field_type_scalar)
    1721             :         call ice_HaloExtrapolate(ULAT, distrb_info, &
    1722           0 :                                  ew_boundary_type, ns_boundary_type)
    1723             : 
    1724             : 
    1725           0 :         deallocate(work_g1)
    1726             : 
    1727           0 :       end subroutine rectgrid_scale_dxdy
    1728             : 
    1729             : !=======================================================================
    1730             : 
    1731             :       ! Complex land mask for testing box cases
    1732             :       ! Requires nx_global, ny_global > 20
    1733             :       ! Assumes work array has been initialized to 1 (ocean) and north and
    1734             :       ! south land boundaries have been applied (ew_boundary_type='cyclic')
    1735             : 
    1736           0 :       subroutine grid_boxislands_kmt (work)
    1737             : 
    1738             :       use ice_constants, only: c0, c1, c20
    1739             : 
    1740             :       real (kind=dbl_kind), dimension(:,:), intent(inout) :: work
    1741             : 
    1742             :       integer (kind=int_kind) :: &
    1743             :          i, j, k, & ! indices   ! LCOV_EXCL_LINE
    1744             :          nxb, nyb   ! convenient cell-block sizes for building the mask
    1745             : 
    1746             :       character(len=*), parameter :: subname = '(grid_boxislands_kmt)'
    1747             : 
    1748             :       ! number of cells in 5% of global grid x and y lengths
    1749           0 :       nxb = int(real(nx_global, dbl_kind) / c20, int_kind)
    1750           0 :       nyb = int(real(ny_global, dbl_kind) / c20, int_kind)
    1751             : 
    1752           0 :       if (nxb < 1 .or. nyb < 1) &
    1753           0 :          call abort_ice(subname//'ERROR: requires larger grid size')
    1754             : 
    1755             :       ! initialize work area as all ocean (c1).
    1756           0 :       work(:,:) = c1
    1757             : 
    1758             :       ! now add land points (c0)
    1759             :       ! northeast triangle
    1760           0 :       k = 0
    1761           0 :       do j = ny_global, ny_global-3*nyb, -1
    1762           0 :          k = k+1
    1763           0 :          do i = nx_global-3*nxb+k, nx_global
    1764           0 :             work(i,j) = c0
    1765             :          enddo
    1766             :       enddo
    1767             : 
    1768             :       ! northwest docks
    1769           0 :       do j = ny_global-3*nyb, ny_global
    1770           0 :          do i = 1, 1
    1771           0 :             work(i,j) = c0
    1772             :          enddo
    1773             :       enddo
    1774           0 :       do i = 1, 2*nxb
    1775           0 :          do j = ny_global-3*nyb, ny_global-nyb-2
    1776           0 :             work(i,j) = c0
    1777             :          enddo
    1778           0 :          do j = ny_global-nyb, ny_global-nyb+1
    1779           0 :             work(i,j) = c0
    1780             :          enddo
    1781             :       enddo
    1782             : 
    1783             :       ! southwest docks
    1784           0 :       do j = 2*nyb, 3*nyb
    1785           0 :          do i = 1, 1
    1786           0 :             work(i,j) = c0
    1787             :          enddo
    1788             :       enddo
    1789           0 :       do j = 1, 2*nyb
    1790           0 :          do i = 2, nxb
    1791           0 :             work(i,j) = c0
    1792             :          enddo
    1793           0 :          do i = 2*nxb-1, 2*nxb
    1794           0 :             work(i,j) = c0
    1795             :          enddo
    1796           0 :          do i = 2*nxb+2,4*nxb
    1797           0 :             work(i,j) = c0
    1798             :          enddo
    1799             :       enddo
    1800             : 
    1801             :       ! tiny island
    1802           0 :       do j = 14*nyb, 14*nyb+1
    1803           0 :          do i = 14*nxb, 14*nxb+1
    1804           0 :             work(i,j) = c0
    1805             :          enddo
    1806             :       enddo
    1807             : 
    1808             :       ! X islands
    1809             :       ! left triangle
    1810           0 :       k = 0
    1811           0 :       do i = 2*nxb, 4*nxb
    1812           0 :          k=k+1
    1813           0 :          do j = 10*nyb+k, 14*nyb-k
    1814           0 :             work(i,j) = c0
    1815             :          enddo
    1816             :       enddo
    1817             :       ! upper triangle
    1818           0 :       k = 0
    1819           0 :       do j = 14*nyb, 12*nyb, -1
    1820           0 :          k=k+1
    1821           0 :          do i = 2*nxb+2+k, 6*nxb-2-k
    1822           0 :             work(i,j) = c0
    1823             :          enddo
    1824             :       enddo
    1825             :       ! diagonal
    1826           0 :       k = 0
    1827           0 :       do j = 10*nyb, 14*nyb
    1828           0 :          k=k+1
    1829           0 :          do i = 2*nxb+4+k, 2*nxb+6+k
    1830           0 :             work(i,j) = c0
    1831             :          enddo
    1832             :       enddo
    1833             :       ! lower right triangle
    1834           0 :       k = 0
    1835           0 :       do j = 12*nyb, 10*nyb, -1
    1836           0 :          k=k+1
    1837           0 :          do i = 5*nxb+k, 8*nxb
    1838           0 :             work(i,j) = c0
    1839             :          enddo
    1840             :       enddo
    1841             : 
    1842             :       ! bar islands
    1843           0 :       do i = 10*nxb, 16*nxb
    1844           0 :          do j = 4*nyb, 5*nyb
    1845           0 :             work(i,j) = c0
    1846             :          enddo
    1847           0 :          do j = 6*nyb+2, 8*nyb
    1848           0 :             work(i,j) = c0
    1849             :          enddo
    1850           0 :          do j = 8*nyb+2, 8*nyb+3
    1851           0 :             work(i,j) = c0
    1852             :          enddo
    1853             :       enddo
    1854             : 
    1855           0 :       end subroutine grid_boxislands_kmt
    1856             : 
    1857             : !=======================================================================
    1858             : 
    1859             : ! CPOM displaced pole grid and land mask. \\
    1860             : ! Grid record number, field and units are: \\
    1861             : ! (1) ULAT  (degrees)    \\
    1862             : ! (2) ULON  (degrees)    \\
    1863             : ! (3) HTN   (m)          \\
    1864             : ! (4) HTE   (m)          \\
    1865             : ! (7) ANGLE (radians)    \\
    1866             : !
    1867             : ! Land mask record number and field is (1) KMT.
    1868             : !
    1869             : ! author: Adrian K. Turner, CPOM, UCL, 09/08/06
    1870             : 
    1871           0 :       subroutine cpomgrid
    1872             : 
    1873             :       use ice_blocks, only: nx_block, ny_block
    1874             :       use ice_constants, only: c0, c1, m_to_cm, &
    1875             :           field_loc_NEcorner, field_type_scalar
    1876             :       use ice_domain_size, only: max_blocks
    1877             : 
    1878             :       integer (kind=int_kind) :: &
    1879             :            i, j, iblk,           &   ! LCOV_EXCL_LINE
    1880             :            ilo,ihi,jlo,jhi      ! beginning and end of physical domain
    1881             : 
    1882             :       logical (kind=log_kind) :: diag
    1883             : 
    1884             :       real (kind=dbl_kind), dimension(:,:), allocatable :: &
    1885           0 :          work_g1
    1886             : 
    1887             :       real (kind=dbl_kind), dimension (nx_block,ny_block,max_blocks) :: &
    1888           0 :          work1
    1889             : 
    1890             :       real (kind=dbl_kind) :: &
    1891           0 :          rad_to_deg
    1892             : 
    1893             :       type (block) :: &
    1894             :            this_block           ! block information for current block
    1895             : 
    1896             :       character(len=*), parameter :: subname = '(cpomgrid)'
    1897             : 
    1898           0 :       call icepack_query_parameters(rad_to_deg_out=rad_to_deg)
    1899           0 :       call icepack_warnings_flush(nu_diag)
    1900           0 :       if (icepack_warnings_aborted()) call abort_ice(error_message=subname, &
    1901           0 :          file=__FILE__, line=__LINE__)
    1902             : 
    1903           0 :       call ice_open(nu_grid,grid_file,64)
    1904           0 :       call ice_open(nu_kmt,kmt_file,32)
    1905             : 
    1906           0 :       diag = .true.       ! write diagnostic info
    1907             : 
    1908             :       ! topography
    1909           0 :       call ice_read(nu_kmt,1,work1,'ida4',diag)
    1910             : 
    1911           0 :       hm (:,:,:) = c0
    1912           0 :       kmt(:,:,:) = c0
    1913           0 :       !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
    1914           0 :       do iblk = 1, nblocks
    1915           0 :          this_block = get_block(blocks_ice(iblk),iblk)
    1916           0 :          ilo = this_block%ilo
    1917           0 :          ihi = this_block%ihi
    1918           0 :          jlo = this_block%jlo
    1919           0 :          jhi = this_block%jhi
    1920             : 
    1921           0 :          do j = jlo, jhi
    1922           0 :          do i = ilo, ihi
    1923           0 :             kmt(i,j,iblk) = work1(i,j,iblk)
    1924           0 :             if (kmt(i,j,iblk) >= c1) hm(i,j,iblk) = c1
    1925             :          enddo
    1926             :          enddo
    1927             :       enddo
    1928             :       !$OMP END PARALLEL DO
    1929             : 
    1930           0 :       allocate(work_g1(nx_global,ny_global))
    1931             : 
    1932             :       ! lat, lon, cell dimensions, angles
    1933           0 :       call ice_read_global(nu_grid,1,work_g1, 'rda8',diag)
    1934             :       call scatter_global(ULAT, work_g1, master_task, distrb_info, &
    1935           0 :                           field_loc_NEcorner, field_type_scalar)
    1936             : 
    1937           0 :       call ice_read_global(nu_grid,2,work_g1, 'rda8',diag)
    1938             :       call scatter_global(ULON, work_g1, master_task, distrb_info, &
    1939           0 :                           field_loc_NEcorner, field_type_scalar)
    1940             : 
    1941           0 :       call ice_read_global(nu_grid,3,work_g1,  'rda8',diag)
    1942           0 :       work_g1 = work_g1 * m_to_cm
    1943           0 :       call primary_grid_lengths_HTN(work_g1)  ! dxU, dxT, dxN, dxE
    1944             : 
    1945           0 :       call ice_read_global(nu_grid,4,work_g1,  'rda8',diag)
    1946           0 :       work_g1 = work_g1 * m_to_cm
    1947           0 :       call primary_grid_lengths_HTE(work_g1)  ! dyU, dyT, dyN, dyE
    1948             : 
    1949           0 :       call ice_read_global(nu_grid,7,work_g1,'rda8',diag)
    1950             :       call scatter_global(ANGLE, work_g1, master_task, distrb_info, &
    1951           0 :                           field_loc_NEcorner, field_type_scalar)
    1952             : 
    1953             :       ! fix units
    1954           0 :       ULAT  = ULAT  / rad_to_deg
    1955           0 :       ULON  = ULON  / rad_to_deg
    1956             : 
    1957           0 :       deallocate(work_g1)
    1958             : 
    1959           0 :       if (my_task == master_task) then
    1960           0 :          close (nu_grid)
    1961           0 :          close (nu_kmt)
    1962             :       endif
    1963             : 
    1964           0 :       write(nu_diag,*) "min/max HTN: ", minval(HTN), maxval(HTN)
    1965           0 :       write(nu_diag,*) "min/max HTE: ", minval(HTE), maxval(HTE)
    1966             : 
    1967           0 :       end subroutine cpomgrid
    1968             : 
    1969             : !=======================================================================
    1970             : 
    1971             : ! Calculate dxU and dxT from HTN on the global grid, to preserve
    1972             : ! ghost cell and/or land values that might otherwise be lost. Scatter
    1973             : ! dxU, dxT and HTN to all processors.
    1974             : !
    1975             : ! author: Elizabeth C. Hunke, LANL
    1976             : 
    1977          37 :       subroutine primary_grid_lengths_HTN(work_g)
    1978             : 
    1979             :       use ice_constants, only: p25, p5, c2, cm_to_m, &
    1980             :           field_loc_center, field_loc_NEcorner, &   ! LCOV_EXCL_LINE
    1981             :           field_loc_Nface, field_type_scalar
    1982             : 
    1983             :       real (kind=dbl_kind), dimension(:,:) :: work_g ! global array holding HTN
    1984             : 
    1985             :       ! local variables
    1986             : 
    1987             :       integer (kind=int_kind) :: &
    1988             :          i, j, &   ! LCOV_EXCL_LINE
    1989             :          ip1     ! i+1
    1990             : 
    1991             :       real (kind=dbl_kind), dimension(:,:), allocatable :: &
    1992          37 :          work_g2
    1993             : 
    1994             :       character(len=*), parameter :: subname = '(primary_grid_lengths_HTN)'
    1995             : 
    1996          37 :       if (my_task == master_task) then
    1997           7 :          allocate(work_g2(nx_global,ny_global))
    1998             :       else
    1999          30 :          allocate(work_g2(1,1))
    2000             :       endif
    2001             : 
    2002             :       ! HTN, dxU = average of 2 neighbor HTNs in i
    2003             : 
    2004          37 :       if (my_task == master_task) then
    2005         843 :          do j = 1, ny_global
    2006       91611 :          do i = 1, nx_global
    2007       91604 :             work_g(i,j) = work_g(i,j) * cm_to_m                ! HTN
    2008             :          enddo
    2009             :          enddo
    2010         843 :          do j = 1, ny_global
    2011       91611 :          do i = 1, nx_global
    2012             :             ! assume cyclic; noncyclic will be handled during scatter
    2013       90768 :             ip1 = i+1
    2014       90768 :             if (i == nx_global) ip1 = 1
    2015       91604 :             work_g2(i,j) = p5*(work_g(i,j) + work_g(ip1,j))    ! dxU
    2016             :          enddo
    2017             :          enddo
    2018             :       endif
    2019          37 :       if (pgl_global_ext) then
    2020             :          call primary_grid_lengths_global_ext( &
    2021           0 :             G_HTN, work_g, ew_boundary_type, ns_boundary_type)
    2022             :       endif
    2023           0 :       call scatter_global(HTN, work_g, master_task, distrb_info, &
    2024          37 :                           field_loc_Nface, field_type_scalar)
    2025             :       call scatter_global(dxU, work_g2, master_task, distrb_info, &
    2026          37 :                           field_loc_NEcorner, field_type_scalar)
    2027             : 
    2028             :       ! dxT = average of 2 neighbor HTNs in j
    2029             : 
    2030          37 :       if (my_task == master_task) then
    2031         836 :          do j = 2, ny_global
    2032       90848 :          do i = 1, nx_global
    2033       90841 :             work_g2(i,j) = p5*(work_g(i,j) + work_g(i,j-1)) ! dxT
    2034             :          enddo
    2035             :          enddo
    2036             :          ! extrapolate to obtain dxT along j=1
    2037         763 :          do i = 1, nx_global
    2038         763 :             work_g2(i,1) = c2*work_g(i,2) - work_g(i,3) ! dxT
    2039             :          enddo
    2040             :       endif
    2041             :       call scatter_global(dxT, work_g2, master_task, distrb_info, &
    2042          37 :                           field_loc_center, field_type_scalar)
    2043             : 
    2044             :       ! dxN = HTN
    2045             : 
    2046      111936 :       dxN(:,:,:) = HTN(:,:,:)   ! dxN
    2047             : 
    2048             :       ! dxE = average of 4 surrounding HTNs
    2049             : 
    2050          37 :       if (my_task == master_task) then
    2051         836 :          do j = 2, ny_global
    2052       90848 :          do i = 1, nx_global
    2053             :             ! assume cyclic; noncyclic will be handled during scatter
    2054       90012 :             ip1 = i+1
    2055       90012 :             if (i == nx_global) ip1 = 1
    2056       90841 :             work_g2(i,j) = p25*(work_g(i,j)+work_g(ip1,j)+work_g(i,j-1)+work_g(ip1,j-1))   ! dxE
    2057             :          enddo
    2058             :          enddo
    2059             :          ! extrapolate to obtain dxT along j=1
    2060         763 :          do i = 1, nx_global
    2061             :             ! assume cyclic; noncyclic will be handled during scatter
    2062         756 :             ip1 = i+1
    2063         756 :             if (i == nx_global) ip1 = 1
    2064         200 :             work_g2(i,1) = p5*(c2*work_g(i  ,2) - work_g(i  ,3) + &
    2065         963 :                                c2*work_g(ip1,2) - work_g(ip1,3))      ! dxE
    2066             :          enddo
    2067             :       endif
    2068             :       call scatter_global(dxE, work_g2, master_task, distrb_info, &
    2069          37 :                           field_loc_center, field_type_scalar)
    2070             : 
    2071          37 :       deallocate(work_g2)
    2072             : 
    2073          37 :       end subroutine primary_grid_lengths_HTN
    2074             : 
    2075             : !=======================================================================
    2076             : ! Calculate dyU and dyT from HTE on the global grid, to preserve
    2077             : ! ghost cell and/or land values that might otherwise be lost. Scatter
    2078             : ! dyU, dyT and HTE to all processors.
    2079             : !
    2080             : ! author: Elizabeth C. Hunke, LANL
    2081             : 
    2082          37 :       subroutine primary_grid_lengths_HTE(work_g)
    2083             : 
    2084             :       use ice_constants, only: p25, p5, c2, cm_to_m, &
    2085             :           field_loc_center, field_loc_NEcorner, &   ! LCOV_EXCL_LINE
    2086             :           field_loc_Eface, field_type_scalar
    2087             : 
    2088             :       real (kind=dbl_kind), dimension(:,:) :: work_g ! global array holding HTE
    2089             : 
    2090             :       ! local variables
    2091             : 
    2092             :       integer (kind=int_kind) :: &
    2093             :          i, j, &   ! LCOV_EXCL_LINE
    2094             :          im1     ! i-1
    2095             : 
    2096             :       real (kind=dbl_kind), dimension(:,:), allocatable :: &
    2097          37 :          work_g2
    2098             : 
    2099             :       character(len=*), parameter :: subname = '(primary_grid_lengths_HTE)'
    2100             : 
    2101          37 :       if (my_task == master_task) then
    2102           7 :          allocate(work_g2(nx_global,ny_global))
    2103             :       else
    2104          30 :          allocate(work_g2(1,1))
    2105             :       endif
    2106             : 
    2107             :       ! HTE, dyU = average of 2 neighbor HTE in j
    2108             : 
    2109          37 :       if (my_task == master_task) then
    2110         843 :          do j = 1, ny_global
    2111       91611 :          do i = 1, nx_global
    2112       91604 :             work_g(i,j) = work_g(i,j) * cm_to_m                ! HTE
    2113             :          enddo
    2114             :          enddo
    2115         836 :          do j = 1, ny_global-1
    2116       90848 :          do i = 1, nx_global
    2117       90841 :             work_g2(i,j) = p5*(work_g(i,j) + work_g(i,j+1)) ! dyU
    2118             :          enddo
    2119             :          enddo
    2120             :          ! extrapolate to obtain dyU along j=ny_global
    2121           7 :          if (ny_global > 1) then
    2122         763 :             do i = 1, nx_global
    2123         763 :                work_g2(i,ny_global) = c2*work_g(i,ny_global-1) - work_g(i,ny_global-2)  ! dyU
    2124             :             enddo
    2125             :          endif
    2126             :       endif
    2127          37 :       if (pgl_global_ext) then
    2128             :          call primary_grid_lengths_global_ext( &
    2129           0 :             G_HTE, work_g, ew_boundary_type, ns_boundary_type)
    2130             :       endif
    2131           0 :       call scatter_global(HTE, work_g, master_task, distrb_info, &
    2132          37 :                           field_loc_Eface, field_type_scalar)
    2133             :       call scatter_global(dyU, work_g2, master_task, distrb_info, &
    2134          37 :                           field_loc_NEcorner, field_type_scalar)
    2135             : 
    2136             :       ! dyT = average of 2 neighbor HTE in i
    2137             : 
    2138          37 :       if (my_task == master_task) then
    2139         843 :          do j = 1, ny_global
    2140       91611 :          do i = 1, nx_global
    2141             :             ! assume cyclic; noncyclic will be handled during scatter
    2142       90768 :             im1 = i-1
    2143       90768 :             if (i == 1) im1 = nx_global
    2144       91604 :             work_g2(i,j) = p5*(work_g(i,j) + work_g(im1,j))    ! dyT
    2145             :          enddo
    2146             :          enddo
    2147             :       endif
    2148             :       call scatter_global(dyT, work_g2, master_task, distrb_info, &
    2149          37 :                           field_loc_center, field_type_scalar)
    2150             : 
    2151             :       ! dyN = average of 4 neighbor HTEs
    2152             : 
    2153          37 :       if (my_task == master_task) then
    2154         836 :          do j = 1, ny_global-1
    2155       90848 :          do i = 1, nx_global
    2156             :             ! assume cyclic; noncyclic will be handled during scatter
    2157       90012 :             im1 = i-1
    2158       90012 :             if (i == 1) im1 = nx_global
    2159       90841 :             work_g2(i,j) = p25*(work_g(i,j) + work_g(im1,j) + work_g(i,j+1) + work_g(im1,j+1))   ! dyN
    2160             :          enddo
    2161             :          enddo
    2162             :          ! extrapolate to obtain dyN along j=ny_global
    2163           7 :          if (ny_global > 1) then
    2164         763 :             do i = 1, nx_global
    2165             :                ! assume cyclic; noncyclic will be handled during scatter
    2166         756 :                im1 = i-1
    2167         756 :                if (i == 1) im1 = nx_global
    2168         400 :                work_g2(i,ny_global) = p5*(c2*work_g(i  ,ny_global-1) - work_g(i  ,ny_global-2) + &
    2169        1163 :                                           c2*work_g(im1,ny_global-1) - work_g(im1,ny_global-2))     ! dyN
    2170             :             enddo
    2171             :          endif
    2172             :       endif
    2173             :       call scatter_global(dyN, work_g2, master_task, distrb_info, &
    2174          37 :                           field_loc_center, field_type_scalar)
    2175             : 
    2176             :       ! dyE = HTE
    2177             : 
    2178      111936 :       dyE(:,:,:) = HTE(:,:,:)
    2179             : 
    2180          37 :       deallocate(work_g2)
    2181             : 
    2182          37 :       end subroutine primary_grid_lengths_HTE
    2183             : 
    2184             : !=======================================================================
    2185             : 
    2186             : ! Sets the boundary values for the T cell land mask (hm) and
    2187             : ! makes the logical land masks for T and U cells (tmask, umask)
    2188             : ! and N and E cells (nmask, emask).
    2189             : ! Also creates hemisphere masks (mask-n northern, mask-s southern)
    2190             : !
    2191             : ! author: Elizabeth C. Hunke, LANL
    2192             : 
    2193          37 :       subroutine makemask
    2194             : 
    2195             :       use ice_constants, only: c0, p5, c1p5, &
    2196             :           field_loc_center, field_loc_NEcorner, field_type_scalar, &   ! LCOV_EXCL_LINE
    2197             :           field_loc_Nface, field_loc_Eface
    2198             : 
    2199             :       integer (kind=int_kind) :: &
    2200             :          i, j, iblk, &   ! LCOV_EXCL_LINE
    2201             :          ilo,ihi,jlo,jhi      ! beginning and end of physical domain
    2202             : 
    2203             :       real (kind=dbl_kind) :: &
    2204           8 :          puny
    2205             : 
    2206             :       real (kind=dbl_kind), dimension(:,:,:), allocatable :: &
    2207          37 :             uvmCD
    2208             : 
    2209             :       type (block) :: &
    2210             :          this_block           ! block information for current block
    2211             : 
    2212             :       character(len=*), parameter :: subname = '(makemask)'
    2213             : 
    2214          37 :       call icepack_query_parameters(puny_out=puny)
    2215          37 :       call icepack_warnings_flush(nu_diag)
    2216          37 :       if (icepack_warnings_aborted()) call abort_ice(error_message=subname, &
    2217           0 :          file=__FILE__, line=__LINE__)
    2218             : 
    2219          37 :       call ice_timer_start(timer_bound)
    2220             :       call ice_HaloUpdate (kmt,              halo_info, &
    2221          37 :                            field_loc_center, field_type_scalar)
    2222             :       call ice_HaloUpdate (hm,               halo_info, &
    2223          37 :                            field_loc_center, field_type_scalar)
    2224          37 :       call ice_timer_stop(timer_bound)
    2225             : 
    2226             :       !-----------------------------------------------------------------
    2227             :       ! construct T-cell and U-cell masks
    2228             :       !-----------------------------------------------------------------
    2229             : 
    2230      111936 :       bm = c0
    2231          37 :       allocate(uvmCD(nx_block,ny_block,max_blocks))
    2232             : 
    2233          20 :       !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
    2234          50 :       do iblk = 1, nblocks
    2235          33 :          this_block = get_block(blocks_ice(iblk),iblk)
    2236          33 :          ilo = this_block%ilo
    2237          33 :          ihi = this_block%ihi
    2238          33 :          jlo = this_block%jlo
    2239          33 :          jhi = this_block%jhi
    2240             : 
    2241        1210 :          do j = jlo, jhi
    2242       45541 :          do i = ilo, ihi
    2243             :             uvm(i,j,iblk) = min (hm(i,j,  iblk), hm(i+1,j,  iblk), &
    2244       44368 :                                  hm(i,j+1,iblk), hm(i+1,j+1,iblk))
    2245       44368 :             npm(i,j,iblk) = min (hm(i,j,  iblk), hm(i,j+1,iblk))
    2246       44368 :             epm(i,j,iblk) = min (hm(i,j,  iblk), hm(i+1,j,iblk))
    2247       44368 :             bm(i,j,iblk) = my_task + iblk/100.0_dbl_kind
    2248             :             uvmCD(i,j,iblk) = (hm(i,j,  iblk)+hm(i+1,j,  iblk) &
    2249       45508 :                             +  hm(i,j+1,iblk)+hm(i+1,j+1,iblk))
    2250             :          enddo
    2251             :          enddo
    2252             :       enddo
    2253             :       !$OMP END PARALLEL DO
    2254             : 
    2255          37 :       call ice_timer_start(timer_bound)
    2256             :       call ice_HaloUpdate (uvm,                halo_info, &
    2257          37 :                            field_loc_NEcorner, field_type_scalar)
    2258             :       call ice_HaloUpdate (uvmCD,              halo_info, &
    2259          37 :                            field_loc_NEcorner, field_type_scalar)
    2260             :       call ice_HaloUpdate (npm,                halo_info, &
    2261          37 :                            field_loc_Nface,    field_type_scalar)
    2262             :       call ice_HaloUpdate (epm,                halo_info, &
    2263          37 :                            field_loc_Eface,    field_type_scalar)
    2264             :       call ice_HaloUpdate (bm,                 halo_info, &
    2265          37 :                            field_loc_center,   field_type_scalar)
    2266          37 :       call ice_timer_stop(timer_bound)
    2267             : 
    2268          20 :       !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
    2269          50 :       do iblk = 1, nblocks
    2270          33 :          this_block = get_block(blocks_ice(iblk),iblk)
    2271          33 :          ilo = this_block%ilo
    2272          33 :          ihi = this_block%ihi
    2273          33 :          jlo = this_block%jlo
    2274          33 :          jhi = this_block%jhi
    2275             : 
    2276             :          ! needs to cover halo (no halo update for logicals)
    2277       50267 :          tmask(:,:,iblk)   = .false.
    2278       50267 :          umask(:,:,iblk)   = .false.
    2279       50267 :          umaskCD(:,:,iblk) = .false.
    2280       50267 :          nmask(:,:,iblk)   = .false.
    2281       50267 :          emask(:,:,iblk)   = .false.
    2282        1276 :          do j = jlo-nghost, jhi+nghost
    2283       50267 :          do i = ilo-nghost, ihi+nghost
    2284       49028 :             if ( hm(i,j,iblk)   > p5  ) tmask  (i,j,iblk)   = .true.
    2285       49028 :             if (uvm(i,j,iblk)   > p5  ) umask  (i,j,iblk)   = .true.
    2286       49028 :             if (uvmCD(i,j,iblk) > c1p5) umaskCD(i,j,iblk)   = .true.
    2287       49028 :             if (npm(i,j,iblk)   > p5  ) nmask  (i,j,iblk)   = .true.
    2288       50234 :             if (epm(i,j,iblk)   > p5  ) emask  (i,j,iblk)   = .true.
    2289             :          enddo
    2290             :          enddo
    2291             : 
    2292             :       enddo
    2293             :       !$OMP END PARALLEL DO
    2294             : 
    2295          20 :       !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
    2296          50 :       do iblk = 1, nblocks
    2297          33 :          this_block = get_block(blocks_ice(iblk),iblk)
    2298          33 :          ilo = this_block%ilo
    2299          33 :          ihi = this_block%ihi
    2300          33 :          jlo = this_block%jlo
    2301          33 :          jhi = this_block%jhi
    2302             : 
    2303             :       !-----------------------------------------------------------------
    2304             :       ! create hemisphere masks
    2305             :       !-----------------------------------------------------------------
    2306             : 
    2307       50267 :          lmask_n(:,:,iblk) = .false.
    2308       50267 :          lmask_s(:,:,iblk) = .false.
    2309             : 
    2310       50267 :          tarean(:,:,iblk) = c0
    2311       50267 :          tareas(:,:,iblk) = c0
    2312             : 
    2313        1210 :          do j = jlo,jhi
    2314       45541 :          do i = ilo,ihi
    2315             : 
    2316       44368 :             if (ULAT(i,j,iblk) >= -puny) then
    2317       38968 :                lmask_n(i,j,iblk) = .true. ! N. Hem.
    2318             :             else
    2319        5400 :                lmask_s(i,j,iblk) = .true. ! S. Hem.
    2320             :             endif
    2321             : 
    2322             :             ! N hemisphere area mask (m^2)
    2323       44368 :             if (lmask_n(i,j,iblk)) tarean(i,j,iblk) = tarea(i,j,iblk) &
    2324       38968 :                                                     * hm(i,j,iblk)
    2325             : 
    2326             :             ! S hemisphere area mask (m^2)
    2327       44368 :             if (lmask_s(i,j,iblk)) tareas(i,j,iblk) = tarea(i,j,iblk) &
    2328        6540 :                                                     * hm(i,j,iblk)
    2329             : 
    2330             :          enddo
    2331             :          enddo
    2332             : 
    2333             :       enddo  ! iblk
    2334             :       !$OMP END PARALLEL DO
    2335             : 
    2336          37 :       deallocate(uvmCD)
    2337             : 
    2338          74 :       end subroutine makemask
    2339             : 
    2340             : !=======================================================================
    2341             : 
    2342             : ! Initializes latitude and longitude on T grid
    2343             : !
    2344             : ! author: Elizabeth C. Hunke, LANL; code originally based on POP grid
    2345             : ! generation routine
    2346             : 
    2347          37 :       subroutine Tlatlon
    2348             : 
    2349             :       use ice_constants, only: c0, c1, c1p5, c2, c4, p5, &
    2350             :           field_loc_center, field_loc_Nface, field_loc_Eface, &   ! LCOV_EXCL_LINE
    2351             :           field_type_scalar
    2352             : 
    2353             :       integer (kind=int_kind) :: &
    2354             :            i, j, iblk       , & ! horizontal indices   ! LCOV_EXCL_LINE
    2355             :            ilo,ihi,jlo,jhi      ! beginning and end of physical domain
    2356             : 
    2357             :       real (kind=dbl_kind) :: &
    2358             :            z1,x1,y1,z2,x2,y2,z3,x3,y3,z4,x4,y4,tx,ty,tz,da, &   ! LCOV_EXCL_LINE
    2359           8 :            rad_to_deg
    2360             : 
    2361             :       type (block) :: &
    2362             :            this_block           ! block information for current block
    2363             : 
    2364             :       character(len=*), parameter :: subname = '(Tlatlon)'
    2365             : 
    2366          37 :       call icepack_query_parameters(rad_to_deg_out=rad_to_deg)
    2367          37 :       call icepack_warnings_flush(nu_diag)
    2368          37 :       if (icepack_warnings_aborted()) call abort_ice(error_message=subname, &
    2369           0 :          file=__FILE__, line=__LINE__)
    2370             : 
    2371      111936 :       TLAT(:,:,:) = c0
    2372      111936 :       TLON(:,:,:) = c0
    2373      111936 :       NLAT(:,:,:) = c0
    2374      111936 :       NLON(:,:,:) = c0
    2375      111936 :       ELAT(:,:,:) = c0
    2376      111936 :       ELON(:,:,:) = c0
    2377             : 
    2378             :       !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block, &
    2379             :       !$OMP                     x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4, &   ! LCOV_EXCL_LINE
    2380          20 :       !$OMP                     tx,ty,tz,da)
    2381          50 :       do iblk = 1, nblocks
    2382          33 :          this_block = get_block(blocks_ice(iblk),iblk)
    2383          33 :          ilo = this_block%ilo
    2384          33 :          ihi = this_block%ihi
    2385          33 :          jlo = this_block%jlo
    2386          33 :          jhi = this_block%jhi
    2387             : 
    2388        1210 :          do j = jlo, jhi
    2389       45541 :          do i = ilo, ihi
    2390             : 
    2391       44368 :             z1 = cos(ULAT(i-1,j-1,iblk))
    2392       44368 :             x1 = cos(ULON(i-1,j-1,iblk))*z1
    2393       44368 :             y1 = sin(ULON(i-1,j-1,iblk))*z1
    2394       44368 :             z1 = sin(ULAT(i-1,j-1,iblk))
    2395             : 
    2396       44368 :             z2 = cos(ULAT(i,j-1,iblk))
    2397       44368 :             x2 = cos(ULON(i,j-1,iblk))*z2
    2398       44368 :             y2 = sin(ULON(i,j-1,iblk))*z2
    2399       44368 :             z2 = sin(ULAT(i,j-1,iblk))
    2400             : 
    2401       44368 :             z3 = cos(ULAT(i-1,j,iblk))
    2402       44368 :             x3 = cos(ULON(i-1,j,iblk))*z3
    2403       44368 :             y3 = sin(ULON(i-1,j,iblk))*z3
    2404       44368 :             z3 = sin(ULAT(i-1,j,iblk))
    2405             : 
    2406       44368 :             z4 = cos(ULAT(i,j,iblk))
    2407       44368 :             x4 = cos(ULON(i,j,iblk))*z4
    2408       44368 :             y4 = sin(ULON(i,j,iblk))*z4
    2409       44368 :             z4 = sin(ULAT(i,j,iblk))
    2410             : 
    2411             :             ! ---------
    2412             :             ! TLON/TLAT 4 pt computation (pts 1, 2, 3, 4)
    2413             :             ! ---------
    2414             : 
    2415       44368 :             tx = (x1+x2+x3+x4)/c4
    2416       44368 :             ty = (y1+y2+y3+y4)/c4
    2417       44368 :             tz = (z1+z2+z3+z4)/c4
    2418       44368 :             da = sqrt(tx**2+ty**2+tz**2)
    2419             : 
    2420       44368 :             tz = tz/da
    2421             : 
    2422             :             ! TLON in radians East
    2423       44368 :             TLON(i,j,iblk) = c0
    2424       44368 :             if (tx /= c0 .or. ty /= c0) TLON(i,j,iblk) = atan2(ty,tx)
    2425             : 
    2426             :             ! TLAT in radians North
    2427       45508 :             TLAT(i,j,iblk) = asin(tz)
    2428             : 
    2429             : ! these two loops should be merged to save cos/sin calculations,
    2430             : ! but atan2 is not bit-for-bit. This suggests the result for atan2 depends on
    2431             : ! the prior atan2 call ??? not sure what's going on.
    2432             : #if (1 == 1)
    2433             :          enddo                  ! i
    2434             :          enddo                  ! j
    2435             :       enddo                     ! iblk
    2436             :       !$OMP END PARALLEL DO
    2437             : 
    2438             :       !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block, &
    2439             :       !$OMP                     x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4, &   ! LCOV_EXCL_LINE
    2440          20 :       !$OMP                     tx,ty,tz,da)
    2441          50 :       do iblk = 1, nblocks
    2442          33 :          this_block = get_block(blocks_ice(iblk),iblk)
    2443          33 :          ilo = this_block%ilo
    2444          33 :          ihi = this_block%ihi
    2445          33 :          jlo = this_block%jlo
    2446          33 :          jhi = this_block%jhi
    2447             : 
    2448        1210 :          do j = jlo, jhi
    2449       45541 :          do i = ilo, ihi
    2450             : 
    2451       44368 :             z1 = cos(ULAT(i-1,j-1,iblk))
    2452       44368 :             x1 = cos(ULON(i-1,j-1,iblk))*z1
    2453       44368 :             y1 = sin(ULON(i-1,j-1,iblk))*z1
    2454       44368 :             z1 = sin(ULAT(i-1,j-1,iblk))
    2455             : 
    2456       44368 :             z2 = cos(ULAT(i,j-1,iblk))
    2457       44368 :             x2 = cos(ULON(i,j-1,iblk))*z2
    2458       44368 :             y2 = sin(ULON(i,j-1,iblk))*z2
    2459       44368 :             z2 = sin(ULAT(i,j-1,iblk))
    2460             : 
    2461       44368 :             z3 = cos(ULAT(i-1,j,iblk))
    2462       44368 :             x3 = cos(ULON(i-1,j,iblk))*z3
    2463       44368 :             y3 = sin(ULON(i-1,j,iblk))*z3
    2464       44368 :             z3 = sin(ULAT(i-1,j,iblk))
    2465             : 
    2466       44368 :             z4 = cos(ULAT(i,j,iblk))
    2467       44368 :             x4 = cos(ULON(i,j,iblk))*z4
    2468       44368 :             y4 = sin(ULON(i,j,iblk))*z4
    2469       44368 :             z4 = sin(ULAT(i,j,iblk))
    2470             : #endif
    2471             :             ! ---------
    2472             :             ! NLON/NLAT 2 pt computation (pts 3, 4)
    2473             :             ! ---------
    2474             : 
    2475       44368 :             tx = (x3+x4)/c2
    2476       44368 :             ty = (y3+y4)/c2
    2477       44368 :             tz = (z3+z4)/c2
    2478       44368 :             da = sqrt(tx**2+ty**2+tz**2)
    2479             : 
    2480       44368 :             tz = tz/da
    2481             : 
    2482             :             ! NLON in radians East
    2483       44368 :             NLON(i,j,iblk) = c0
    2484       44368 :             if (tx /= c0 .or. ty /= c0) NLON(i,j,iblk) = atan2(ty,tx)
    2485             : 
    2486             :             ! NLAT in radians North
    2487       44368 :             NLAT(i,j,iblk) = asin(tz)
    2488             : 
    2489             :             ! ---------
    2490             :             ! ELON/ELAT 2 pt computation (pts 2, 4)
    2491             :             ! ---------
    2492             : 
    2493       44368 :             tx = (x2+x4)/c2
    2494       44368 :             ty = (y2+y4)/c2
    2495       44368 :             tz = (z2+z4)/c2
    2496       44368 :             da = sqrt(tx**2+ty**2+tz**2)
    2497             : 
    2498       44368 :             tz = tz/da
    2499             : 
    2500             :             ! ELON in radians East
    2501       44368 :             ELON(i,j,iblk) = c0
    2502       44368 :             if (tx /= c0 .or. ty /= c0) ELON(i,j,iblk) = atan2(ty,tx)
    2503             : 
    2504             :             ! ELAT in radians North
    2505       45508 :             ELAT(i,j,iblk) = asin(tz)
    2506             : 
    2507             :          enddo                  ! i
    2508             :          enddo                  ! j
    2509             :       enddo                     ! iblk
    2510             :       !$OMP END PARALLEL DO
    2511             : 
    2512          37 :       if (trim(grid_type) == 'regional') then
    2513             :          ! for W boundary extrapolate from interior
    2514           0 :          !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
    2515           0 :          do iblk = 1, nblocks
    2516           0 :             this_block = get_block(blocks_ice(iblk),iblk)
    2517           0 :             ilo = this_block%ilo
    2518           0 :             ihi = this_block%ihi
    2519           0 :             jlo = this_block%jlo
    2520           0 :             jhi = this_block%jhi
    2521             : 
    2522           0 :             i = ilo
    2523           0 :             if (this_block%i_glob(i) == 1) then
    2524           0 :                do j = jlo, jhi
    2525             :                   TLON(i,j,iblk) = c2*TLON(i+1,j,iblk) - &
    2526           0 :                                       TLON(i+2,j,iblk)
    2527             :                   TLAT(i,j,iblk) = c2*TLAT(i+1,j,iblk) - &
    2528           0 :                                       TLAT(i+2,j,iblk)
    2529             :                   NLON(i,j,iblk) = c1p5*TLON(i+1,j,iblk) - &
    2530           0 :                                      p5*TLON(i+2,j,iblk)
    2531             :                   NLAT(i,j,iblk) = c1p5*TLAT(i+1,j,iblk) - &
    2532           0 :                                      p5*TLAT(i+2,j,iblk)
    2533             :                enddo
    2534             :             endif
    2535             :          enddo
    2536             :          !$OMP END PARALLEL DO
    2537             :       endif   ! regional
    2538             : 
    2539          37 :       call ice_timer_start(timer_bound)
    2540             :       call ice_HaloUpdate (TLON,             halo_info, &
    2541             :                            field_loc_center, field_type_scalar, &   ! LCOV_EXCL_LINE
    2542          37 :                            fillValue=c1)
    2543             :       call ice_HaloUpdate (TLAT,             halo_info, &
    2544             :                            field_loc_center, field_type_scalar, &   ! LCOV_EXCL_LINE
    2545          37 :                            fillValue=c1)
    2546             :       call ice_HaloUpdate (NLON,             halo_info, &
    2547             :                            field_loc_Nface,  field_type_scalar, &   ! LCOV_EXCL_LINE
    2548          37 :                            fillValue=c1)
    2549             :       call ice_HaloUpdate (NLAT,             halo_info, &
    2550             :                            field_loc_Nface,  field_type_scalar, &   ! LCOV_EXCL_LINE
    2551          37 :                            fillValue=c1)
    2552             :       call ice_HaloUpdate (ELON,             halo_info, &
    2553             :                            field_loc_Eface,  field_type_scalar, &   ! LCOV_EXCL_LINE
    2554          37 :                            fillValue=c1)
    2555             :       call ice_HaloUpdate (ELAT,             halo_info, &
    2556             :                            field_loc_Eface,  field_type_scalar, &   ! LCOV_EXCL_LINE
    2557          37 :                            fillValue=c1)
    2558             :       call ice_HaloExtrapolate(TLON, distrb_info, &
    2559          37 :                                ew_boundary_type, ns_boundary_type)
    2560             :       call ice_HaloExtrapolate(TLAT, distrb_info, &
    2561          37 :                                ew_boundary_type, ns_boundary_type)
    2562             :       call ice_HaloExtrapolate(NLON, distrb_info, &
    2563          37 :                                ew_boundary_type, ns_boundary_type)
    2564             :       call ice_HaloExtrapolate(NLAT, distrb_info, &
    2565          37 :                                ew_boundary_type, ns_boundary_type)
    2566             :       call ice_HaloExtrapolate(ELON, distrb_info, &
    2567          37 :                                ew_boundary_type, ns_boundary_type)
    2568             :       call ice_HaloExtrapolate(ELAT, distrb_info, &
    2569          37 :                                ew_boundary_type, ns_boundary_type)
    2570          37 :       call ice_timer_stop(timer_bound)
    2571             : 
    2572          37 :       x1 = global_minval(TLON, distrb_info, tmask)
    2573          37 :       x2 = global_maxval(TLON, distrb_info, tmask)
    2574          37 :       x3 = global_minval(TLAT, distrb_info, tmask)
    2575          37 :       x4 = global_maxval(TLAT, distrb_info, tmask)
    2576             : 
    2577          37 :       y1 = global_minval(ULON, distrb_info, umask)
    2578          37 :       y2 = global_maxval(ULON, distrb_info, umask)
    2579          37 :       y3 = global_minval(ULAT, distrb_info, umask)
    2580          37 :       y4 = global_maxval(ULAT, distrb_info, umask)
    2581             : 
    2582          37 :       if (my_task==master_task) then
    2583           7 :          write(nu_diag,*) ' '
    2584             : !         if (nx_block > 5+2*nghost .and. ny_block > 5+2*nghost) then
    2585           7 :          write(nu_diag,*) 'min/max ULON:', y1*rad_to_deg, y2*rad_to_deg
    2586           7 :          write(nu_diag,*) 'min/max ULAT:', y3*rad_to_deg, y4*rad_to_deg
    2587             : !         endif
    2588           7 :          write(nu_diag,*) 'min/max TLON:', x1*rad_to_deg, x2*rad_to_deg
    2589           7 :          write(nu_diag,*) 'min/max TLAT:', x3*rad_to_deg, x4*rad_to_deg
    2590             :       endif                     ! my_task
    2591             : 
    2592          37 :       x1 = global_minval(NLON, distrb_info, nmask)
    2593          37 :       x2 = global_maxval(NLON, distrb_info, nmask)
    2594          37 :       x3 = global_minval(NLAT, distrb_info, nmask)
    2595          37 :       x4 = global_maxval(NLAT, distrb_info, nmask)
    2596             : 
    2597          37 :       y1 = global_minval(ELON, distrb_info, emask)
    2598          37 :       y2 = global_maxval(ELON, distrb_info, emask)
    2599          37 :       y3 = global_minval(ELAT, distrb_info, emask)
    2600          37 :       y4 = global_maxval(ELAT, distrb_info, emask)
    2601             : 
    2602          37 :       if (my_task==master_task) then
    2603           7 :          write(nu_diag,*) ' '
    2604             : !         if (nx_block > 5+2*nghost .and. ny_block > 5+2*nghost) then
    2605           7 :          write(nu_diag,*) 'min/max NLON:', x1*rad_to_deg, x2*rad_to_deg
    2606           7 :          write(nu_diag,*) 'min/max NLAT:', x3*rad_to_deg, x4*rad_to_deg
    2607           7 :          write(nu_diag,*) 'min/max ELON:', y1*rad_to_deg, y2*rad_to_deg
    2608           7 :          write(nu_diag,*) 'min/max ELAT:', y3*rad_to_deg, y4*rad_to_deg
    2609             : !         endif
    2610             :       endif                     ! my_task
    2611             : 
    2612          37 :       end subroutine Tlatlon
    2613             : 
    2614             : !=======================================================================
    2615             : 
    2616             : ! Shifts quantities from one grid to another
    2617             : ! Constructs the shift based on the grid
    2618             : ! NOTE: Input array includes ghost cells that must be updated before
    2619             : !       calling this routine.
    2620             : !
    2621             : ! author: T. Craig
    2622             : 
    2623       86760 :       subroutine grid_average_X2Y_base(type,work1,grid1,work2,grid2)
    2624             : 
    2625             :       character(len=*) , intent(in) :: &
    2626             :          type, grid1, grid2
    2627             : 
    2628             :       real (kind=dbl_kind), intent(in) :: &
    2629             :          work1(:,:,:)
    2630             : 
    2631             :       real (kind=dbl_kind), intent(out)   :: &
    2632             :          work2(:,:,:)
    2633             : 
    2634             :       ! local variables
    2635             : 
    2636             :       character(len=16) :: X2Y
    2637             : 
    2638             :       character(len=*), parameter :: subname = '(grid_average_X2Y_base)'
    2639             : 
    2640       86760 :       if (trim(grid1) == trim(grid2)) then
    2641    59896128 :          work2 = work1
    2642             :       else
    2643       63672 :          X2Y = trim(grid1)//'2'//trim(grid2)//trim(type)
    2644       63672 :          call grid_average_X2Y_1(X2Y,work1,work2)
    2645             :       endif
    2646             : 
    2647       86760 :       end subroutine grid_average_X2Y_base
    2648             : 
    2649             : !=======================================================================
    2650             : 
    2651             : ! Shifts quantities from one grid to another
    2652             : ! NOTE: Input array includes ghost cells that must be updated before
    2653             : !       calling this routine.
    2654             : !
    2655             : ! author: T. Craig
    2656             : 
    2657           0 :       subroutine grid_average_X2Y_userwghts(type,work1,grid1,wght1,mask1,work2,grid2)
    2658             : 
    2659             :       character(len=*) , intent(in) :: &
    2660             :          type, grid1, grid2
    2661             : 
    2662             :       real (kind=dbl_kind), intent(in) :: &
    2663             :          work1(:,:,:), &   ! LCOV_EXCL_LINE
    2664             :          wght1(:,:,:), &   ! LCOV_EXCL_LINE
    2665             :          mask1(:,:,:)
    2666             : 
    2667             :       real (kind=dbl_kind), intent(out)   :: &
    2668             :          work2(:,:,:)
    2669             : 
    2670             :       ! local variables
    2671             : 
    2672             :       character(len=16) :: X2Y
    2673             : 
    2674             :       character(len=*), parameter :: subname = '(grid_average_X2Y_userwghts)'
    2675             : 
    2676           0 :       if (trim(grid1) == trim(grid2)) then
    2677           0 :          work2 = work1
    2678             :       else
    2679           0 :          X2Y = trim(grid1)//'2'//trim(grid2)//trim(type)
    2680           0 :          call grid_average_X2Y_1f(X2Y,work1,wght1,mask1,work2)
    2681             :       endif
    2682             : 
    2683           0 :       end subroutine grid_average_X2Y_userwghts
    2684             : 
    2685             : !=======================================================================
    2686             : 
    2687             : ! Shifts quantities from one grid to another
    2688             : ! NOTE: Input array includes ghost cells that must be updated before
    2689             : !       calling this routine.
    2690             : !
    2691             : ! author: T. Craig
    2692             : 
    2693           0 :       subroutine grid_average_X2Y_NEversion(type,work1a,grid1a,work1b,grid1b,work2,grid2)
    2694             : 
    2695             :       character(len=*) , intent(in) :: &
    2696             :          type, grid1a, grid1b, grid2
    2697             : 
    2698             :       real (kind=dbl_kind), intent(in) :: &
    2699             :          work1a(:,:,:), work1b(:,:,:)
    2700             : 
    2701             :       real (kind=dbl_kind), intent(out)   :: &
    2702             :          work2(:,:,:)
    2703             : 
    2704             :       ! local variables
    2705             : 
    2706             :       character(len=16) :: X2Y
    2707             : 
    2708             :       character(len=*), parameter :: subname = '(grid_average_X2Y_NEversion)'
    2709             : 
    2710           0 :       X2Y = trim(grid1a)//trim(grid1b)//'2'//trim(grid2)//trim(type)
    2711             : 
    2712           0 :       select case (trim(X2Y))
    2713             : 
    2714             :          ! state masked
    2715             :          case('NE2US')
    2716           0 :             call grid_average_X2Y_2('NE2US',work1a,narea,npm,work1b,earea,epm,work2)
    2717             :          case('EN2US')
    2718           0 :             call grid_average_X2Y_2('NE2US',work1b,narea,npm,work1a,earea,epm,work2)
    2719             :          case('NE2TS')
    2720           0 :             call grid_average_X2Y_2('NE2TS',work1a,narea,npm,work1b,earea,epm,work2)
    2721             :          case('EN2TS')
    2722           0 :             call grid_average_X2Y_2('NE2TS',work1b,narea,npm,work1a,earea,epm,work2)
    2723             : 
    2724             :          ! state unmasked
    2725             :          case('NE2UA')
    2726           0 :             call grid_average_X2Y_2('NE2UA',work1a,narea,npm,work1b,earea,epm,work2)
    2727             :          case('EN2UA')
    2728           0 :             call grid_average_X2Y_2('NE2UA',work1b,narea,npm,work1a,earea,epm,work2)
    2729             :          case('NE2TA')
    2730           0 :             call grid_average_X2Y_2('NE2TA',work1a,narea,npm,work1b,earea,epm,work2)
    2731             :          case('EN2TA')
    2732           0 :             call grid_average_X2Y_2('NE2TA',work1b,narea,npm,work1a,earea,epm,work2)
    2733             : 
    2734             :          case default
    2735           0 :             call abort_ice(subname//'ERROR: unknown X2Y '//trim(X2Y))
    2736             :       end select
    2737             : 
    2738           0 :       end subroutine grid_average_X2Y_NEversion
    2739             : 
    2740             : !=======================================================================
    2741             : 
    2742             : ! Shifts quantities from one grid to another
    2743             : ! NOTE: Input array includes ghost cells that must be updated before
    2744             : !       calling this routine.
    2745             : !
    2746             : ! author: T. Craig
    2747             : 
    2748       63672 :       subroutine grid_average_X2Y_1(X2Y,work1,work2)
    2749             : 
    2750             :       character(len=*) , intent(in) :: &
    2751             :          X2Y
    2752             : 
    2753             :       real (kind=dbl_kind), intent(in) :: &
    2754             :          work1(:,:,:)
    2755             : 
    2756             :       real (kind=dbl_kind), intent(out)   :: &
    2757             :          work2(:,:,:)
    2758             : 
    2759             :       ! local variables
    2760             : 
    2761             :       character(len=*), parameter :: subname = '(grid_average_X2Y_1)'
    2762             : 
    2763      127344 :       select case (trim(X2Y))
    2764             : 
    2765             :          ! flux unmasked
    2766             :          case('T2UF')
    2767       11568 :             call grid_average_X2YF('NE',work1,tarea,work2,uarea)
    2768             :          case('T2EF')
    2769           0 :             call grid_average_X2YF('E' ,work1,tarea,work2,earea)
    2770             :          case('T2NF')
    2771           0 :             call grid_average_X2YF('N' ,work1,tarea,work2,narea)
    2772             :          case('U2TF')
    2773       11568 :             call grid_average_X2YF('SW',work1,uarea,work2,tarea)
    2774             :          case('U2EF')
    2775           0 :             call grid_average_X2YF('S' ,work1,uarea,work2,earea)
    2776             :          case('U2NF')
    2777           0 :             call grid_average_X2YF('W' ,work1,uarea,work2,narea)
    2778             :          case('E2TF')
    2779           0 :             call grid_average_X2YF('W' ,work1,earea,work2,tarea)
    2780             :          case('E2UF')
    2781           0 :             call grid_average_X2YF('N' ,work1,earea,work2,uarea)
    2782             :          case('E2NF')
    2783           0 :             call grid_average_X2YF('NW',work1,earea,work2,narea)
    2784             :          case('N2TF')
    2785           0 :             call grid_average_X2YF('S' ,work1,narea,work2,tarea)
    2786             :          case('N2UF')
    2787           0 :             call grid_average_X2YF('E' ,work1,narea,work2,uarea)
    2788             :          case('N2EF')
    2789           0 :             call grid_average_X2YF('SE',work1,narea,work2,earea)
    2790             : 
    2791             :          ! state masked
    2792             :          case('T2US')
    2793       28968 :             call grid_average_X2YS('NE',work1,tarea,hm ,work2)
    2794             :          case('T2ES')
    2795           0 :             call grid_average_X2YS('E' ,work1,tarea,hm ,work2)
    2796             :          case('T2NS')
    2797           0 :             call grid_average_X2YS('N' ,work1,tarea,hm ,work2)
    2798             :          case('U2TS')
    2799           0 :             call grid_average_X2YS('SW',work1,uarea,uvm,work2)
    2800             :          case('U2ES')
    2801           0 :             call grid_average_X2YS('S' ,work1,uarea,uvm,work2)
    2802             :          case('U2NS')
    2803           0 :             call grid_average_X2YS('W' ,work1,uarea,uvm,work2)
    2804             :          case('E2TS')
    2805           0 :             call grid_average_X2YS('W' ,work1,earea,epm,work2)
    2806             :          case('E2US')
    2807           0 :             call grid_average_X2YS('N' ,work1,earea,epm,work2)
    2808             :          case('E2NS')
    2809           0 :             call grid_average_X2YS('NW',work1,earea,epm,work2)
    2810             :          case('N2TS')
    2811           0 :             call grid_average_X2YS('S' ,work1,narea,npm,work2)
    2812             :          case('N2US')
    2813           0 :             call grid_average_X2YS('E' ,work1,narea,npm,work2)
    2814             :          case('N2ES')
    2815           0 :             call grid_average_X2YS('SE',work1,narea,npm,work2)
    2816             : 
    2817             :          ! state unmasked
    2818             :          case('T2UA')
    2819           0 :             call grid_average_X2YA('NE',work1,tarea,work2)
    2820             :          case('T2EA')
    2821           0 :             call grid_average_X2YA('E' ,work1,tarea,work2)
    2822             :          case('T2NA')
    2823           0 :             call grid_average_X2YA('N' ,work1,tarea,work2)
    2824             :          case('U2TA')
    2825       11568 :             call grid_average_X2YA('SW',work1,uarea,work2)
    2826             :          case('U2EA')
    2827           0 :             call grid_average_X2YA('S' ,work1,uarea,work2)
    2828             :          case('U2NA')
    2829           0 :             call grid_average_X2YA('W' ,work1,uarea,work2)
    2830             :          case('E2TA')
    2831           0 :             call grid_average_X2YA('W' ,work1,earea,work2)
    2832             :          case('E2UA')
    2833           0 :             call grid_average_X2YA('N' ,work1,earea,work2)
    2834             :          case('E2NA')
    2835           0 :             call grid_average_X2YA('NW',work1,earea,work2)
    2836             :          case('N2TA')
    2837           0 :             call grid_average_X2YA('S' ,work1,narea,work2)
    2838             :          case('N2UA')
    2839           0 :             call grid_average_X2YA('E' ,work1,narea,work2)
    2840             :          case('N2EA')
    2841           0 :             call grid_average_X2YA('SE',work1,narea,work2)
    2842             : 
    2843             :          case default
    2844      127344 :             call abort_ice(subname//'ERROR: unknown X2Y '//trim(X2Y))
    2845             :       end select
    2846             : 
    2847       63672 :       end subroutine grid_average_X2Y_1
    2848             : 
    2849             : !=======================================================================
    2850             : 
    2851             : ! Shifts quantities from one grid to another
    2852             : ! NOTE: Input array includes ghost cells that must be updated before
    2853             : !       calling this routine.
    2854             : !
    2855             : ! author: T. Craig
    2856             : 
    2857           0 :       subroutine grid_average_X2Y_1f(X2Y,work1,wght1,mask1,work2)
    2858             : 
    2859             :       character(len=*) , intent(in) :: &
    2860             :          X2Y
    2861             : 
    2862             :       real (kind=dbl_kind), intent(in) :: &
    2863             :          work1(:,:,:), &   ! LCOV_EXCL_LINE
    2864             :          wght1(:,:,:), &   ! LCOV_EXCL_LINE
    2865             :          mask1(:,:,:)
    2866             : 
    2867             :       real (kind=dbl_kind), intent(out)   :: &
    2868             :          work2(:,:,:)
    2869             : 
    2870             :       ! local variables
    2871             : 
    2872             :       character(len=*), parameter :: subname = '(grid_average_X2Y_1f)'
    2873             : 
    2874           0 :       select case (trim(X2Y))
    2875             : 
    2876             : ! don't support these for now, requires extra destination wght
    2877             : !         ! flux unmasked
    2878             : !         case('T2UF')
    2879             : !            call grid_average_X2YF('NE',work1,tarea,work2,uarea)
    2880             : !         case('T2EF')
    2881             : !            call grid_average_X2YF('E' ,work1,tarea,work2,earea)
    2882             : !         case('T2NF')
    2883             : !            call grid_average_X2YF('N' ,work1,tarea,work2,narea)
    2884             : !         case('U2TF')
    2885             : !            call grid_average_X2YF('SW',work1,uarea,work2,tarea)
    2886             : !         case('U2EF')
    2887             : !            call grid_average_X2YF('S' ,work1,uarea,work2,earea)
    2888             : !         case('U2NF')
    2889             : !            call grid_average_X2YF('W' ,work1,uarea,work2,narea)
    2890             : !         case('E2TF')
    2891             : !            call grid_average_X2YF('W' ,work1,earea,work2,tarea)
    2892             : !         case('E2UF')
    2893             : !            call grid_average_X2YF('N' ,work1,earea,work2,uarea)
    2894             : !         case('E2NF')
    2895             : !            call grid_average_X2YF('NW',work1,earea,work2,narea)
    2896             : !         case('N2TF')
    2897             : !            call grid_average_X2YF('S' ,work1,narea,work2,tarea)
    2898             : !         case('N2UF')
    2899             : !            call grid_average_X2YF('E' ,work1,narea,work2,uarea)
    2900             : !         case('N2EF')
    2901             : !            call grid_average_X2YF('SE',work1,narea,work2,earea)
    2902             : 
    2903             :          ! state masked
    2904             :          case('T2US')
    2905           0 :             call grid_average_X2YS('NE',work1,wght1,mask1,work2)
    2906             :          case('T2ES')
    2907           0 :             call grid_average_X2YS('E' ,work1,wght1,mask1,work2)
    2908             :          case('T2NS')
    2909           0 :             call grid_average_X2YS('N' ,work1,wght1,mask1,work2)
    2910             :          case('U2TS')
    2911           0 :             call grid_average_X2YS('SW',work1,wght1,mask1,work2)
    2912             :          case('U2ES')
    2913           0 :             call grid_average_X2YS('S' ,work1,wght1,mask1,work2)
    2914             :          case('U2NS')
    2915           0 :             call grid_average_X2YS('W' ,work1,wght1,mask1,work2)
    2916             :          case('E2TS')
    2917           0 :             call grid_average_X2YS('W' ,work1,wght1,mask1,work2)
    2918             :          case('E2US')
    2919           0 :             call grid_average_X2YS('N' ,work1,wght1,mask1,work2)
    2920             :          case('E2NS')
    2921           0 :             call grid_average_X2YS('NW',work1,wght1,mask1,work2)
    2922             :          case('N2TS')
    2923           0 :             call grid_average_X2YS('S' ,work1,wght1,mask1,work2)
    2924             :          case('N2US')
    2925           0 :             call grid_average_X2YS('E' ,work1,wght1,mask1,work2)
    2926             :          case('N2ES')
    2927           0 :             call grid_average_X2YS('SE',work1,wght1,mask1,work2)
    2928             : 
    2929             :          ! state unmasked
    2930             :          case('T2UA')
    2931           0 :             call grid_average_X2YA('NE',work1,wght1,work2)
    2932             :          case('T2EA')
    2933           0 :             call grid_average_X2YA('E' ,work1,wght1,work2)
    2934             :          case('T2NA')
    2935           0 :             call grid_average_X2YA('N' ,work1,wght1,work2)
    2936             :          case('U2TA')
    2937           0 :             call grid_average_X2YA('SW',work1,wght1,work2)
    2938             :          case('U2EA')
    2939           0 :             call grid_average_X2YA('S' ,work1,wght1,work2)
    2940             :          case('U2NA')
    2941           0 :             call grid_average_X2YA('W' ,work1,wght1,work2)
    2942             :          case('E2TA')
    2943           0 :             call grid_average_X2YA('W' ,work1,wght1,work2)
    2944             :          case('E2UA')
    2945           0 :             call grid_average_X2YA('N' ,work1,wght1,work2)
    2946             :          case('E2NA')
    2947           0 :             call grid_average_X2YA('NW',work1,wght1,work2)
    2948             :          case('N2TA')
    2949           0 :             call grid_average_X2YA('S' ,work1,wght1,work2)
    2950             :          case('N2UA')
    2951           0 :             call grid_average_X2YA('E' ,work1,wght1,work2)
    2952             :          case('N2EA')
    2953           0 :             call grid_average_X2YA('SE',work1,wght1,work2)
    2954             : 
    2955             :          case default
    2956           0 :             call abort_ice(subname//'ERROR: unknown X2Y '//trim(X2Y))
    2957             :       end select
    2958             : 
    2959           0 :       end subroutine grid_average_X2Y_1f
    2960             : 
    2961             : !=======================================================================
    2962             : ! Shifts quantities from one grid to another
    2963             : ! State masked version, simple area weighted averager
    2964             : ! NOTE: Input array includes ghost cells that must be updated before
    2965             : !       calling this routine.
    2966             : !
    2967             : ! author: T. Craig
    2968             : 
    2969       28968 :       subroutine grid_average_X2YS(dir,work1,wght1,mask1,work2)
    2970             : 
    2971             :       use ice_constants, only: c0
    2972             : 
    2973             :       character(len=*) , intent(in) :: &
    2974             :          dir
    2975             : 
    2976             :       real (kind=dbl_kind), intent(in) :: &
    2977             :          work1(:,:,:), &   ! LCOV_EXCL_LINE
    2978             :          wght1(:,:,:), &   ! LCOV_EXCL_LINE
    2979             :          mask1(:,:,:)
    2980             : 
    2981             :       real (kind=dbl_kind), intent(out) :: &
    2982             :          work2(:,:,:)
    2983             : 
    2984             :       ! local variables
    2985             : 
    2986             :       integer (kind=int_kind) :: &
    2987             :          i, j, iblk, &   ! LCOV_EXCL_LINE
    2988             :          ilo,ihi,jlo,jhi      ! beginning and end of physical domain
    2989             : 
    2990             :       real (kind=dbl_kind) :: &
    2991       10080 :          wtmp
    2992             : 
    2993             :       type (block) :: &
    2994             :          this_block           ! block information for current block
    2995             : 
    2996             :       character(len=*), parameter :: subname = '(grid_average_X2YS)'
    2997             : 
    2998    86101728 :       work2(:,:,:) = c0
    2999             : 
    3000       57936 :       select case (trim(dir))
    3001             : 
    3002             :          case('NE')
    3003       20160 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3004       35064 :             do iblk = 1, nblocks
    3005       17448 :                this_block = get_block(blocks_ice(iblk),iblk)
    3006       17448 :                ilo = this_block%ilo
    3007       17448 :                ihi = this_block%ihi
    3008       17448 :                jlo = this_block%jlo
    3009       17448 :                jhi = this_block%jhi
    3010      618864 :                do j = jlo, jhi
    3011    20233416 :                do i = ilo, ihi
    3012             :                   wtmp = (mask1(i  ,j  ,iblk)*wght1(i  ,j  ,iblk)  &
    3013             :                         + mask1(i+1,j  ,iblk)*wght1(i+1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3014             :                         + mask1(i  ,j+1,iblk)*wght1(i  ,j+1,iblk)  &   ! LCOV_EXCL_LINE
    3015    19643520 :                         + mask1(i+1,j+1,iblk)*wght1(i+1,j+1,iblk))
    3016    19643520 :                   if (wtmp /= c0) &
    3017             :                   work2(i,j,iblk) = (mask1(i  ,j  ,iblk)*work1(i  ,j  ,iblk)*wght1(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3018             :                                    + mask1(i+1,j  ,iblk)*work1(i+1,j  ,iblk)*wght1(i+1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3019             :                                    + mask1(i  ,j+1,iblk)*work1(i  ,j+1,iblk)*wght1(i  ,j+1,iblk)  &   ! LCOV_EXCL_LINE
    3020             :                                    + mask1(i+1,j+1,iblk)*work1(i+1,j+1,iblk)*wght1(i+1,j+1,iblk)) &   ! LCOV_EXCL_LINE
    3021    19403592 :                                    / wtmp
    3022             :                enddo
    3023             :                enddo
    3024             :             enddo
    3025             :             !$OMP END PARALLEL DO
    3026             : 
    3027             :          case('SW')
    3028           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3029           0 :             do iblk = 1, nblocks
    3030           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3031           0 :                ilo = this_block%ilo
    3032           0 :                ihi = this_block%ihi
    3033           0 :                jlo = this_block%jlo
    3034           0 :                jhi = this_block%jhi
    3035           0 :                do j = jlo, jhi
    3036           0 :                do i = ilo, ihi
    3037             :                   wtmp = (mask1(i  ,j  ,iblk)*wght1(i  ,j  ,iblk)  &
    3038             :                         + mask1(i-1,j  ,iblk)*wght1(i-1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3039             :                         + mask1(i  ,j-1,iblk)*wght1(i  ,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3040           0 :                         + mask1(i-1,j-1,iblk)*wght1(i-1,j-1,iblk))
    3041           0 :                   if (wtmp /= c0) &
    3042             :                   work2(i,j,iblk) = (mask1(i  ,j  ,iblk)*work1(i  ,j  ,iblk)*wght1(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3043             :                                    + mask1(i-1,j  ,iblk)*work1(i-1,j  ,iblk)*wght1(i-1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3044             :                                    + mask1(i  ,j-1,iblk)*work1(i  ,j-1,iblk)*wght1(i  ,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3045             :                                    + mask1(i-1,j-1,iblk)*work1(i-1,j-1,iblk)*wght1(i-1,j-1,iblk)) &   ! LCOV_EXCL_LINE
    3046           0 :                                    / wtmp
    3047             :                enddo
    3048             :                enddo
    3049             :             enddo
    3050             :             !$OMP END PARALLEL DO
    3051             : 
    3052             :          case('NW')
    3053           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3054           0 :             do iblk = 1, nblocks
    3055           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3056           0 :                ilo = this_block%ilo
    3057           0 :                ihi = this_block%ihi
    3058           0 :                jlo = this_block%jlo
    3059           0 :                jhi = this_block%jhi
    3060           0 :                do j = jlo, jhi
    3061           0 :                do i = ilo, ihi
    3062             :                   wtmp = (mask1(i-1,j  ,iblk)*wght1(i-1,j  ,iblk)  &
    3063             :                         + mask1(i  ,j  ,iblk)*wght1(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3064             :                         + mask1(i-1,j+1,iblk)*wght1(i-1,j+1,iblk)  &   ! LCOV_EXCL_LINE
    3065           0 :                         + mask1(i  ,j+1,iblk)*wght1(i  ,j+1,iblk))
    3066           0 :                   if (wtmp /= c0) &
    3067             :                   work2(i,j,iblk) = (mask1(i-1,j  ,iblk)*work1(i-1,j  ,iblk)*wght1(i-1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3068             :                                    + mask1(i  ,j  ,iblk)*work1(i  ,j  ,iblk)*wght1(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3069             :                                    + mask1(i-1,j+1,iblk)*work1(i-1,j+1,iblk)*wght1(i-1,j+1,iblk)  &   ! LCOV_EXCL_LINE
    3070             :                                    + mask1(i  ,j+1,iblk)*work1(i  ,j+1,iblk)*wght1(i  ,j+1,iblk)) &   ! LCOV_EXCL_LINE
    3071           0 :                                    / wtmp
    3072             :                enddo
    3073             :                enddo
    3074             :             enddo
    3075             :             !$OMP END PARALLEL DO
    3076             : 
    3077             :          case('SE')
    3078           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3079           0 :             do iblk = 1, nblocks
    3080           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3081           0 :                ilo = this_block%ilo
    3082           0 :                ihi = this_block%ihi
    3083           0 :                jlo = this_block%jlo
    3084           0 :                jhi = this_block%jhi
    3085           0 :                do j = jlo, jhi
    3086           0 :                do i = ilo, ihi
    3087             :                   wtmp = (mask1(i  ,j-1,iblk)*wght1(i  ,j-1,iblk)  &
    3088             :                         + mask1(i+1,j-1,iblk)*wght1(i+1,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3089             :                         + mask1(i  ,j  ,iblk)*wght1(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3090           0 :                         + mask1(i+1,j  ,iblk)*wght1(i+1,j  ,iblk))
    3091           0 :                   if (wtmp /= c0) &
    3092             :                   work2(i,j,iblk) = (mask1(i  ,j-1,iblk)*work1(i  ,j-1,iblk)*wght1(i  ,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3093             :                                    + mask1(i+1,j-1,iblk)*work1(i+1,j-1,iblk)*wght1(i+1,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3094             :                                    + mask1(i  ,j  ,iblk)*work1(i  ,j  ,iblk)*wght1(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3095             :                                    + mask1(i+1,j  ,iblk)*work1(i+1,j  ,iblk)*wght1(i+1,j  ,iblk)) &   ! LCOV_EXCL_LINE
    3096           0 :                                    / wtmp
    3097             :                enddo
    3098             :                enddo
    3099             :             enddo
    3100             :             !$OMP END PARALLEL DO
    3101             : 
    3102             :          case('E')
    3103           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3104           0 :             do iblk = 1, nblocks
    3105           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3106           0 :                ilo = this_block%ilo
    3107           0 :                ihi = this_block%ihi
    3108           0 :                jlo = this_block%jlo
    3109           0 :                jhi = this_block%jhi
    3110           0 :                do j = jlo, jhi
    3111           0 :                do i = ilo, ihi
    3112             :                   wtmp = (mask1(i  ,j,iblk)*wght1(i  ,j,iblk)  &
    3113           0 :                         + mask1(i+1,j,iblk)*wght1(i+1,j,iblk))
    3114           0 :                   if (wtmp /= c0) &
    3115             :                   work2(i,j,iblk) = (mask1(i  ,j,iblk)*work1(i  ,j,iblk)*wght1(i  ,j,iblk)  &   ! LCOV_EXCL_LINE
    3116             :                                    + mask1(i+1,j,iblk)*work1(i+1,j,iblk)*wght1(i+1,j,iblk)) &   ! LCOV_EXCL_LINE
    3117           0 :                                    / wtmp
    3118             :                enddo
    3119             :                enddo
    3120             :             enddo
    3121             :             !$OMP END PARALLEL DO
    3122             : 
    3123             :          case('W')
    3124           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3125           0 :             do iblk = 1, nblocks
    3126           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3127           0 :                ilo = this_block%ilo
    3128           0 :                ihi = this_block%ihi
    3129           0 :                jlo = this_block%jlo
    3130           0 :                jhi = this_block%jhi
    3131           0 :                do j = jlo, jhi
    3132           0 :                do i = ilo, ihi
    3133             :                   wtmp = (mask1(i-1,j,iblk)*wght1(i-1,j,iblk)  &
    3134           0 :                         + mask1(i  ,j,iblk)*wght1(i  ,j,iblk))
    3135           0 :                   if (wtmp /= c0) &
    3136             :                   work2(i,j,iblk) = (mask1(i-1,j,iblk)*work1(i-1,j,iblk)*wght1(i-1,j,iblk)  &   ! LCOV_EXCL_LINE
    3137             :                                    + mask1(i  ,j,iblk)*work1(i  ,j,iblk)*wght1(i  ,j,iblk)) &   ! LCOV_EXCL_LINE
    3138           0 :                                    / wtmp
    3139             :                enddo
    3140             :                enddo
    3141             :             enddo
    3142             :             !$OMP END PARALLEL DO
    3143             : 
    3144             :          case('N')
    3145           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3146           0 :             do iblk = 1, nblocks
    3147           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3148           0 :                ilo = this_block%ilo
    3149           0 :                ihi = this_block%ihi
    3150           0 :                jlo = this_block%jlo
    3151           0 :                jhi = this_block%jhi
    3152           0 :                do j = jlo, jhi
    3153           0 :                do i = ilo, ihi
    3154             :                   wtmp = (mask1(i,j  ,iblk)*wght1(i,j  ,iblk)  &
    3155           0 :                         + mask1(i,j+1,iblk)*wght1(i,j+1,iblk))
    3156           0 :                   if (wtmp /= c0) &
    3157             :                   work2(i,j,iblk) = (mask1(i,j  ,iblk)*work1(i,j  ,iblk)*wght1(i,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3158             :                                    + mask1(i,j+1,iblk)*work1(i,j+1,iblk)*wght1(i,j+1,iblk)) &   ! LCOV_EXCL_LINE
    3159           0 :                                    / wtmp
    3160             :                enddo
    3161             :                enddo
    3162             :             enddo
    3163             :             !$OMP END PARALLEL DO
    3164             : 
    3165             :          case('S')
    3166           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3167           0 :             do iblk = 1, nblocks
    3168           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3169           0 :                ilo = this_block%ilo
    3170           0 :                ihi = this_block%ihi
    3171           0 :                jlo = this_block%jlo
    3172           0 :                jhi = this_block%jhi
    3173           0 :                do j = jlo, jhi
    3174           0 :                do i = ilo, ihi
    3175             :                   wtmp = (mask1(i,j-1,iblk)*wght1(i,j-1,iblk)  &
    3176           0 :                         + mask1(i,j  ,iblk)*wght1(i,j  ,iblk))
    3177           0 :                   if (wtmp /= c0) &
    3178             :                   work2(i,j,iblk) = (mask1(i,j-1,iblk)*work1(i,j-1,iblk)*wght1(i,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3179             :                                    + mask1(i,j  ,iblk)*work1(i,j  ,iblk)*wght1(i,j  ,iblk)) &   ! LCOV_EXCL_LINE
    3180           0 :                                    / wtmp
    3181             :                enddo
    3182             :                enddo
    3183             :             enddo
    3184             :             !$OMP END PARALLEL DO
    3185             : 
    3186             :          case default
    3187       57936 :             call abort_ice(subname//'ERROR: unknown option '//trim(dir))
    3188             :          end select
    3189             : 
    3190       28968 :       end subroutine grid_average_X2YS
    3191             : 
    3192             : !=======================================================================
    3193             : ! Shifts quantities from one grid to another
    3194             : ! State unmasked version, simple weighted averager
    3195             : ! NOTE: Input array includes ghost cells that must be updated before
    3196             : !       calling this routine.
    3197             : !
    3198             : ! author: T. Craig
    3199             : 
    3200       11568 :       subroutine grid_average_X2YA(dir,work1,wght1,work2)
    3201             : 
    3202             :       use ice_constants, only: c0
    3203             : 
    3204             :       character(len=*) , intent(in) :: &
    3205             :          dir
    3206             : 
    3207             :       real (kind=dbl_kind), intent(in) :: &
    3208             :          work1(:,:,:), &   ! LCOV_EXCL_LINE
    3209             :          wght1(:,:,:)
    3210             : 
    3211             :       real (kind=dbl_kind), intent(out) :: &
    3212             :          work2(:,:,:)
    3213             : 
    3214             :       ! local variables
    3215             : 
    3216             :       integer (kind=int_kind) :: &
    3217             :          i, j, iblk, &   ! LCOV_EXCL_LINE
    3218             :          ilo,ihi,jlo,jhi      ! beginning and end of physical domain
    3219             : 
    3220             :       real (kind=dbl_kind) :: &
    3221        2880 :          wtmp
    3222             : 
    3223             :       type (block) :: &
    3224             :          this_block           ! block information for current block
    3225             : 
    3226             :       character(len=*), parameter :: subname = '(grid_average_X2YA)'
    3227             : 
    3228    32443968 :       work2(:,:,:) = c0
    3229             : 
    3230       23136 :       select case (trim(dir))
    3231             : 
    3232             :          case('NE')
    3233        5760 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3234           0 :             do iblk = 1, nblocks
    3235           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3236           0 :                ilo = this_block%ilo
    3237           0 :                ihi = this_block%ihi
    3238           0 :                jlo = this_block%jlo
    3239           0 :                jhi = this_block%jhi
    3240           0 :                do j = jlo, jhi
    3241           0 :                do i = ilo, ihi
    3242             :                   wtmp = (wght1(i  ,j  ,iblk)  &
    3243             :                         + wght1(i+1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3244             :                         + wght1(i  ,j+1,iblk)  &   ! LCOV_EXCL_LINE
    3245           0 :                         + wght1(i+1,j+1,iblk))
    3246           0 :                   if (wtmp /= c0) &
    3247             :                   work2(i,j,iblk) = (work1(i  ,j  ,iblk)*wght1(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3248             :                                    + work1(i+1,j  ,iblk)*wght1(i+1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3249             :                                    + work1(i  ,j+1,iblk)*wght1(i  ,j+1,iblk)  &   ! LCOV_EXCL_LINE
    3250             :                                    + work1(i+1,j+1,iblk)*wght1(i+1,j+1,iblk)) &   ! LCOV_EXCL_LINE
    3251           0 :                                    / wtmp
    3252             :                enddo
    3253             :                enddo
    3254             :             enddo
    3255             :             !$OMP END PARALLEL DO
    3256             : 
    3257             :          case('SW')
    3258        5760 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3259       23184 :             do iblk = 1, nblocks
    3260       11568 :                this_block = get_block(blocks_ice(iblk),iblk)
    3261       11568 :                ilo = this_block%ilo
    3262       11568 :                ihi = this_block%ihi
    3263       11568 :                jlo = this_block%jlo
    3264       11568 :                jhi = this_block%jhi
    3265      397344 :                do j = jlo, jhi
    3266    12739056 :                do i = ilo, ihi
    3267             :                   wtmp = (wght1(i  ,j  ,iblk)  &
    3268             :                         + wght1(i-1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3269             :                         + wght1(i  ,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3270    12353280 :                         + wght1(i-1,j-1,iblk))
    3271    12353280 :                   if (wtmp /= c0) &
    3272             :                   work2(i,j,iblk) = (work1(i  ,j  ,iblk)*wght1(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3273             :                                    + work1(i-1,j  ,iblk)*wght1(i-1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3274             :                                    + work1(i  ,j-1,iblk)*wght1(i  ,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3275             :                                    + work1(i-1,j-1,iblk)*wght1(i-1,j-1,iblk)) &   ! LCOV_EXCL_LINE
    3276    12727488 :                                    / wtmp
    3277             :                enddo
    3278             :                enddo
    3279             :             enddo
    3280             :             !$OMP END PARALLEL DO
    3281             : 
    3282             :          case('NW')
    3283           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3284           0 :             do iblk = 1, nblocks
    3285           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3286           0 :                ilo = this_block%ilo
    3287           0 :                ihi = this_block%ihi
    3288           0 :                jlo = this_block%jlo
    3289           0 :                jhi = this_block%jhi
    3290           0 :                do j = jlo, jhi
    3291           0 :                do i = ilo, ihi
    3292             :                   wtmp = (wght1(i-1,j  ,iblk)  &
    3293             :                         + wght1(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3294             :                         + wght1(i-1,j+1,iblk)  &   ! LCOV_EXCL_LINE
    3295           0 :                         + wght1(i  ,j+1,iblk))
    3296           0 :                   if (wtmp /= c0) &
    3297             :                   work2(i,j,iblk) = (work1(i-1,j  ,iblk)*wght1(i-1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3298             :                                    + work1(i  ,j  ,iblk)*wght1(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3299             :                                    + work1(i-1,j+1,iblk)*wght1(i-1,j+1,iblk)  &   ! LCOV_EXCL_LINE
    3300             :                                    + work1(i  ,j+1,iblk)*wght1(i  ,j+1,iblk)) &   ! LCOV_EXCL_LINE
    3301           0 :                                    / wtmp
    3302             :                enddo
    3303             :                enddo
    3304             :             enddo
    3305             :             !$OMP END PARALLEL DO
    3306             : 
    3307             :          case('SE')
    3308           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3309           0 :             do iblk = 1, nblocks
    3310           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3311           0 :                ilo = this_block%ilo
    3312           0 :                ihi = this_block%ihi
    3313           0 :                jlo = this_block%jlo
    3314           0 :                jhi = this_block%jhi
    3315           0 :                do j = jlo, jhi
    3316           0 :                do i = ilo, ihi
    3317             :                   wtmp = (wght1(i  ,j-1,iblk)  &
    3318             :                         + wght1(i+1,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3319             :                         + wght1(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3320           0 :                         + wght1(i+1,j  ,iblk))
    3321           0 :                   if (wtmp /= c0) &
    3322             :                   work2(i,j,iblk) = (work1(i  ,j-1,iblk)*wght1(i  ,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3323             :                                    + work1(i+1,j-1,iblk)*wght1(i+1,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3324             :                                    + work1(i  ,j  ,iblk)*wght1(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3325             :                                    + work1(i+1,j  ,iblk)*wght1(i+1,j  ,iblk)) &   ! LCOV_EXCL_LINE
    3326           0 :                                    / wtmp
    3327             :                enddo
    3328             :                enddo
    3329             :             enddo
    3330             :             !$OMP END PARALLEL DO
    3331             : 
    3332             :          case('E')
    3333           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3334           0 :             do iblk = 1, nblocks
    3335           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3336           0 :                ilo = this_block%ilo
    3337           0 :                ihi = this_block%ihi
    3338           0 :                jlo = this_block%jlo
    3339           0 :                jhi = this_block%jhi
    3340           0 :                do j = jlo, jhi
    3341           0 :                do i = ilo, ihi
    3342             :                   wtmp = (wght1(i  ,j,iblk)  &
    3343           0 :                         + wght1(i+1,j,iblk))
    3344           0 :                   if (wtmp /= c0) &
    3345             :                   work2(i,j,iblk) = (work1(i  ,j,iblk)*wght1(i  ,j,iblk)  &   ! LCOV_EXCL_LINE
    3346             :                                    + work1(i+1,j,iblk)*wght1(i+1,j,iblk)) &   ! LCOV_EXCL_LINE
    3347           0 :                                    / wtmp
    3348             :                enddo
    3349             :                enddo
    3350             :             enddo
    3351             :             !$OMP END PARALLEL DO
    3352             : 
    3353             :          case('W')
    3354           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3355           0 :             do iblk = 1, nblocks
    3356           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3357           0 :                ilo = this_block%ilo
    3358           0 :                ihi = this_block%ihi
    3359           0 :                jlo = this_block%jlo
    3360           0 :                jhi = this_block%jhi
    3361           0 :                do j = jlo, jhi
    3362           0 :                do i = ilo, ihi
    3363             :                   wtmp = (wght1(i-1,j,iblk)  &
    3364           0 :                         + wght1(i  ,j,iblk))
    3365           0 :                   if (wtmp /= c0) &
    3366             :                   work2(i,j,iblk) = (work1(i-1,j,iblk)*wght1(i-1,j,iblk)  &   ! LCOV_EXCL_LINE
    3367             :                                    + work1(i  ,j,iblk)*wght1(i  ,j,iblk)) &   ! LCOV_EXCL_LINE
    3368           0 :                                    / wtmp
    3369             :                enddo
    3370             :                enddo
    3371             :             enddo
    3372             :             !$OMP END PARALLEL DO
    3373             : 
    3374             :          case('N')
    3375           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3376           0 :             do iblk = 1, nblocks
    3377           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3378           0 :                ilo = this_block%ilo
    3379           0 :                ihi = this_block%ihi
    3380           0 :                jlo = this_block%jlo
    3381           0 :                jhi = this_block%jhi
    3382           0 :                do j = jlo, jhi
    3383           0 :                do i = ilo, ihi
    3384             :                   wtmp = (wght1(i,j  ,iblk)  &
    3385           0 :                         + wght1(i,j+1,iblk))
    3386           0 :                   if (wtmp /= c0) &
    3387             :                   work2(i,j,iblk) = (work1(i,j  ,iblk)*wght1(i,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3388             :                                    + work1(i,j+1,iblk)*wght1(i,j+1,iblk)) &   ! LCOV_EXCL_LINE
    3389           0 :                                    / wtmp
    3390             :                enddo
    3391             :                enddo
    3392             :             enddo
    3393             :             !$OMP END PARALLEL DO
    3394             : 
    3395             :          case('S')
    3396           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3397           0 :             do iblk = 1, nblocks
    3398           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3399           0 :                ilo = this_block%ilo
    3400           0 :                ihi = this_block%ihi
    3401           0 :                jlo = this_block%jlo
    3402           0 :                jhi = this_block%jhi
    3403           0 :                do j = jlo, jhi
    3404           0 :                do i = ilo, ihi
    3405             :                   wtmp = (wght1(i,j-1,iblk)  &
    3406           0 :                         + wght1(i,j  ,iblk))
    3407           0 :                   if (wtmp /= c0) &
    3408             :                   work2(i,j,iblk) = (work1(i,j-1,iblk)*wght1(i,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3409             :                                    + work1(i,j  ,iblk)*wght1(i,j  ,iblk)) &   ! LCOV_EXCL_LINE
    3410           0 :                                    / wtmp
    3411             :                enddo
    3412             :                enddo
    3413             :             enddo
    3414             :             !$OMP END PARALLEL DO
    3415             : 
    3416             :          case default
    3417       23136 :             call abort_ice(subname//'ERROR: unknown option '//trim(dir))
    3418             :          end select
    3419             : 
    3420       11568 :       end subroutine grid_average_X2YA
    3421             : 
    3422             : !=======================================================================
    3423             : ! Shifts quantities from one grid to another
    3424             : ! Flux masked, original implementation based on earlier t2u and u2t versions
    3425             : ! NOTE: Input array includes ghost cells that must be updated before
    3426             : !       calling this routine.
    3427             : !
    3428             : ! author: T. Craig
    3429             : 
    3430       23136 :       subroutine grid_average_X2YF(dir,work1,wght1,work2,wght2)
    3431             : 
    3432             :       use ice_constants, only: c0, p25, p5
    3433             : 
    3434             :       character(len=*) , intent(in) :: &
    3435             :          dir
    3436             : 
    3437             :       real (kind=dbl_kind), intent(in) :: &
    3438             :          work1(:,:,:), &   ! LCOV_EXCL_LINE
    3439             :          wght1(:,:,:), &   ! LCOV_EXCL_LINE
    3440             :          wght2(:,:,:)
    3441             : 
    3442             :       real (kind=dbl_kind), intent(out) :: &
    3443             :          work2(:,:,:)
    3444             : 
    3445             :       ! local variables
    3446             : 
    3447             :       integer (kind=int_kind) :: &
    3448             :          i, j, iblk, &   ! LCOV_EXCL_LINE
    3449             :          ilo,ihi,jlo,jhi      ! beginning and end of physical domain
    3450             : 
    3451             :       type (block) :: &
    3452             :          this_block           ! block information for current block
    3453             : 
    3454             :       character(len=*), parameter :: subname = '(grid_average_X2YF)'
    3455             : 
    3456    64887936 :       work2(:,:,:) = c0
    3457             : 
    3458       46272 :       select case (trim(dir))
    3459             : 
    3460             :          case('NE')
    3461       11520 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
    3462       23184 :             do iblk = 1, nblocks
    3463       11568 :                this_block = get_block(blocks_ice(iblk),iblk)
    3464       11568 :                ilo = this_block%ilo
    3465       11568 :                ihi = this_block%ihi
    3466       11568 :                jlo = this_block%jlo
    3467       11568 :                jhi = this_block%jhi
    3468      397344 :                do j = jlo, jhi
    3469    12739056 :                do i = ilo, ihi
    3470             :                   work2(i,j,iblk) = p25 * &
    3471             :                                     (work1(i  ,j  ,iblk)*wght1(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3472             :                                    + work1(i+1,j  ,iblk)*wght1(i+1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3473             :                                    + work1(i  ,j+1,iblk)*wght1(i  ,j+1,iblk)  &   ! LCOV_EXCL_LINE
    3474             :                                    + work1(i+1,j+1,iblk)*wght1(i+1,j+1,iblk)) &   ! LCOV_EXCL_LINE
    3475    12727488 :                                    / wght2(i  ,j  ,iblk)
    3476             :                enddo
    3477             :                enddo
    3478             :             enddo
    3479             :             !$OMP END PARALLEL DO
    3480             : 
    3481             :          case('SW')
    3482        5760 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
    3483       23184 :             do iblk = 1, nblocks
    3484       11568 :                this_block = get_block(blocks_ice(iblk),iblk)
    3485       11568 :                ilo = this_block%ilo
    3486       11568 :                ihi = this_block%ihi
    3487       11568 :                jlo = this_block%jlo
    3488       11568 :                jhi = this_block%jhi
    3489      397344 :                do j = jlo, jhi
    3490    12739056 :                do i = ilo, ihi
    3491             :                   work2(i,j,iblk) = p25 *  &
    3492             :                                    (work1(i  ,j  ,iblk)*wght1(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3493             :                                   + work1(i-1,j  ,iblk)*wght1(i-1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3494             :                                   + work1(i  ,j-1,iblk)*wght1(i  ,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3495             :                                   + work1(i-1,j-1,iblk)*wght1(i-1,j-1,iblk)) &   ! LCOV_EXCL_LINE
    3496    12727488 :                                   / wght2(i  ,j  ,iblk)
    3497             :                enddo
    3498             :                enddo
    3499             :             enddo
    3500             :             !$OMP END PARALLEL DO
    3501             : 
    3502             :          case('NW')
    3503           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
    3504           0 :             do iblk = 1, nblocks
    3505           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3506           0 :                ilo = this_block%ilo
    3507           0 :                ihi = this_block%ihi
    3508           0 :                jlo = this_block%jlo
    3509           0 :                jhi = this_block%jhi
    3510           0 :                do j = jlo, jhi
    3511           0 :                do i = ilo, ihi
    3512             :                   work2(i,j,iblk) = p25 * &
    3513             :                                     (work1(i-1,j  ,iblk)*wght1(i-1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3514             :                                    + work1(i  ,j  ,iblk)*wght1(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3515             :                                    + work1(i-1,j+1,iblk)*wght1(i-1,j+1,iblk)  &   ! LCOV_EXCL_LINE
    3516             :                                    + work1(i  ,j+1,iblk)*wght1(i  ,j+1,iblk)) &   ! LCOV_EXCL_LINE
    3517           0 :                                    / wght2(i  ,j  ,iblk)
    3518             :                enddo
    3519             :                enddo
    3520             :             enddo
    3521             :             !$OMP END PARALLEL DO
    3522             : 
    3523             :          case('SE')
    3524           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
    3525           0 :             do iblk = 1, nblocks
    3526           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3527           0 :                ilo = this_block%ilo
    3528           0 :                ihi = this_block%ihi
    3529           0 :                jlo = this_block%jlo
    3530           0 :                jhi = this_block%jhi
    3531           0 :                do j = jlo, jhi
    3532           0 :                do i = ilo, ihi
    3533             :                   work2(i,j,iblk) = p25 *  &
    3534             :                                    (work1(i  ,j-1,iblk)*wght1(i  ,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3535             :                                   + work1(i+1,j-1,iblk)*wght1(i+1,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3536             :                                   + work1(i  ,j  ,iblk)*wght1(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3537             :                                   + work1(i+1,j  ,iblk)*wght1(i+1,j  ,iblk)) &   ! LCOV_EXCL_LINE
    3538           0 :                                   / wght2(i  ,j  ,iblk)
    3539             :                enddo
    3540             :                enddo
    3541             :             enddo
    3542             :             !$OMP END PARALLEL DO
    3543             : 
    3544             :          case('E')
    3545           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
    3546           0 :             do iblk = 1, nblocks
    3547           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3548           0 :                ilo = this_block%ilo
    3549           0 :                ihi = this_block%ihi
    3550           0 :                jlo = this_block%jlo
    3551           0 :                jhi = this_block%jhi
    3552           0 :                do j = jlo, jhi
    3553           0 :                do i = ilo, ihi
    3554             :                   work2(i,j,iblk) = p5 * &
    3555             :                                     (work1(i  ,j,iblk)*wght1(i  ,j,iblk)  &   ! LCOV_EXCL_LINE
    3556             :                                    + work1(i+1,j,iblk)*wght1(i+1,j,iblk)) &   ! LCOV_EXCL_LINE
    3557           0 :                                    / wght2(i  ,j,iblk)
    3558             :                enddo
    3559             :                enddo
    3560             :             enddo
    3561             :             !$OMP END PARALLEL DO
    3562             : 
    3563             :          case('W')
    3564           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
    3565           0 :             do iblk = 1, nblocks
    3566           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3567           0 :                ilo = this_block%ilo
    3568           0 :                ihi = this_block%ihi
    3569           0 :                jlo = this_block%jlo
    3570           0 :                jhi = this_block%jhi
    3571           0 :                do j = jlo, jhi
    3572           0 :                do i = ilo, ihi
    3573             :                   work2(i,j,iblk) = p5 * &
    3574             :                                     (work1(i-1,j,iblk)*wght1(i-1,j,iblk)  &   ! LCOV_EXCL_LINE
    3575             :                                    + work1(i  ,j,iblk)*wght1(i  ,j,iblk)) &   ! LCOV_EXCL_LINE
    3576           0 :                                    / wght2(i  ,j,iblk)
    3577             :                enddo
    3578             :                enddo
    3579             :             enddo
    3580             :             !$OMP END PARALLEL DO
    3581             : 
    3582             :          case('N')
    3583           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
    3584           0 :             do iblk = 1, nblocks
    3585           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3586           0 :                ilo = this_block%ilo
    3587           0 :                ihi = this_block%ihi
    3588           0 :                jlo = this_block%jlo
    3589           0 :                jhi = this_block%jhi
    3590           0 :                do j = jlo, jhi
    3591           0 :                do i = ilo, ihi
    3592             :                   work2(i,j,iblk) = p5 * &
    3593             :                                     (work1(i,j  ,iblk)*wght1(i,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3594             :                                    + work1(i,j+1,iblk)*wght1(i,j+1,iblk)) &   ! LCOV_EXCL_LINE
    3595           0 :                                    / wght2(i  ,j,iblk)
    3596             :                enddo
    3597             :                enddo
    3598             :             enddo
    3599             :             !$OMP END PARALLEL DO
    3600             : 
    3601             :          case('S')
    3602           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
    3603           0 :             do iblk = 1, nblocks
    3604           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3605           0 :                ilo = this_block%ilo
    3606           0 :                ihi = this_block%ihi
    3607           0 :                jlo = this_block%jlo
    3608           0 :                jhi = this_block%jhi
    3609           0 :                do j = jlo, jhi
    3610           0 :                do i = ilo, ihi
    3611             :                   work2(i,j,iblk) = p5 * &
    3612             :                                     (work1(i,j-1,iblk)*wght1(i,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3613             :                                    + work1(i,j  ,iblk)*wght1(i,j  ,iblk)) &   ! LCOV_EXCL_LINE
    3614           0 :                                    / wght2(i  ,j,iblk)
    3615             :                enddo
    3616             :                enddo
    3617             :             enddo
    3618             :             !$OMP END PARALLEL DO
    3619             : 
    3620             :          case default
    3621       46272 :             call abort_ice(subname//'ERROR: unknown option '//trim(dir))
    3622             :          end select
    3623             : 
    3624       23136 :       end subroutine grid_average_X2YF
    3625             : 
    3626             : !=======================================================================
    3627             : ! Shifts quantities from one grid to another
    3628             : ! State masked version, simple weighted averager
    3629             : ! NOTE: Input array includes ghost cells that must be updated before
    3630             : !       calling this routine.
    3631             : !
    3632             : ! author: T. Craig
    3633             : 
    3634           0 :       subroutine grid_average_X2Y_2(dir,work1a,wght1a,mask1a,work1b,wght1b,mask1b,work2)
    3635             : 
    3636             :       use ice_constants, only: c0
    3637             : 
    3638             :       character(len=*) , intent(in) :: &
    3639             :          dir
    3640             : 
    3641             :       real (kind=dbl_kind), intent(in) :: &
    3642             :          work1a(:,:,:), work1b(:,:,:), &   ! LCOV_EXCL_LINE
    3643             :          wght1a(:,:,:), wght1b(:,:,:), &   ! LCOV_EXCL_LINE
    3644             :          mask1a(:,:,:), mask1b(:,:,:)
    3645             : 
    3646             :       real (kind=dbl_kind), intent(out) :: &
    3647             :          work2(:,:,:)
    3648             : 
    3649             :       ! local variables
    3650             : 
    3651             :       integer (kind=int_kind) :: &
    3652             :          i, j, iblk, &   ! LCOV_EXCL_LINE
    3653             :          ilo,ihi,jlo,jhi      ! beginning and end of physical domain
    3654             : 
    3655             :       real (kind=dbl_kind) :: &
    3656           0 :          wtmp
    3657             : 
    3658             :       type (block) :: &
    3659             :          this_block           ! block information for current block
    3660             : 
    3661             :       character(len=*), parameter :: subname = '(grid_average_X2Y_2)'
    3662             : 
    3663           0 :       work2(:,:,:) = c0
    3664             : 
    3665           0 :       select case (trim(dir))
    3666             : 
    3667             :          case('NE2US')
    3668           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3669           0 :             do iblk = 1, nblocks
    3670           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3671           0 :                ilo = this_block%ilo
    3672           0 :                ihi = this_block%ihi
    3673           0 :                jlo = this_block%jlo
    3674           0 :                jhi = this_block%jhi
    3675           0 :                do j = jlo, jhi
    3676           0 :                do i = ilo, ihi
    3677             :                   wtmp = (mask1a(i  ,j  ,iblk)*wght1a(i  ,j  ,iblk)  &
    3678             :                         + mask1a(i+1,j  ,iblk)*wght1a(i+1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3679             :                         + mask1b(i  ,j  ,iblk)*wght1b(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3680           0 :                         + mask1b(i  ,j+1,iblk)*wght1b(i  ,j+1,iblk))
    3681           0 :                   if (wtmp /= c0) &
    3682             :                   work2(i,j,iblk) = (mask1a(i  ,j  ,iblk)*work1a(i  ,j  ,iblk)*wght1a(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3683             :                                    + mask1a(i+1,j  ,iblk)*work1a(i+1,j  ,iblk)*wght1a(i+1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3684             :                                    + mask1b(i  ,j  ,iblk)*work1b(i  ,j  ,iblk)*wght1b(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3685             :                                    + mask1b(i  ,j+1,iblk)*work1b(i  ,j+1,iblk)*wght1b(i  ,j+1,iblk)) &   ! LCOV_EXCL_LINE
    3686           0 :                                    / wtmp
    3687             :                enddo
    3688             :                enddo
    3689             :             enddo
    3690             :             !$OMP END PARALLEL DO
    3691             : 
    3692             :          case('NE2TS')
    3693           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3694           0 :             do iblk = 1, nblocks
    3695           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3696           0 :                ilo = this_block%ilo
    3697           0 :                ihi = this_block%ihi
    3698           0 :                jlo = this_block%jlo
    3699           0 :                jhi = this_block%jhi
    3700           0 :                do j = jlo, jhi
    3701           0 :                do i = ilo, ihi
    3702             :                   wtmp = (mask1a(i  ,j-1,iblk)*wght1a(i  ,j-1,iblk)  &
    3703             :                         + mask1a(i  ,j  ,iblk)*wght1a(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3704             :                         + mask1b(i-1,j  ,iblk)*wght1b(i-1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3705           0 :                         + mask1b(i  ,j  ,iblk)*wght1b(i  ,j  ,iblk))
    3706           0 :                   if (wtmp /= c0) &
    3707             :                   work2(i,j,iblk) = (mask1a(i  ,j-1,iblk)*work1a(i  ,j-1,iblk)*wght1a(i  ,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3708             :                                    + mask1a(i  ,j  ,iblk)*work1a(i  ,j  ,iblk)*wght1a(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3709             :                                    + mask1b(i-1,j  ,iblk)*work1b(i-1,j  ,iblk)*wght1b(i-1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3710             :                                    + mask1b(i  ,j  ,iblk)*work1b(i  ,j  ,iblk)*wght1b(i  ,j  ,iblk)) &   ! LCOV_EXCL_LINE
    3711           0 :                                    / wtmp
    3712             :                enddo
    3713             :                enddo
    3714             :             enddo
    3715             :             !$OMP END PARALLEL DO
    3716             : 
    3717             :          case('NE2UA')
    3718           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3719           0 :             do iblk = 1, nblocks
    3720           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3721           0 :                ilo = this_block%ilo
    3722           0 :                ihi = this_block%ihi
    3723           0 :                jlo = this_block%jlo
    3724           0 :                jhi = this_block%jhi
    3725           0 :                do j = jlo, jhi
    3726           0 :                do i = ilo, ihi
    3727             :                   wtmp = (wght1a(i  ,j  ,iblk)  &
    3728             :                         + wght1a(i+1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3729             :                         + wght1b(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3730           0 :                         + wght1b(i  ,j+1,iblk))
    3731           0 :                   if (wtmp /= c0) &
    3732             :                   work2(i,j,iblk) = (work1a(i  ,j  ,iblk)*wght1a(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3733             :                                    + work1a(i+1,j  ,iblk)*wght1a(i+1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3734             :                                    + work1b(i  ,j  ,iblk)*wght1b(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3735             :                                    + work1b(i  ,j+1,iblk)*wght1b(i  ,j+1,iblk)) &   ! LCOV_EXCL_LINE
    3736           0 :                                    / wtmp
    3737             :                enddo
    3738             :                enddo
    3739             :             enddo
    3740             :             !$OMP END PARALLEL DO
    3741             : 
    3742             :          case('NE2TA')
    3743           0 :             !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block,wtmp)
    3744           0 :             do iblk = 1, nblocks
    3745           0 :                this_block = get_block(blocks_ice(iblk),iblk)
    3746           0 :                ilo = this_block%ilo
    3747           0 :                ihi = this_block%ihi
    3748           0 :                jlo = this_block%jlo
    3749           0 :                jhi = this_block%jhi
    3750           0 :                do j = jlo, jhi
    3751           0 :                do i = ilo, ihi
    3752             :                   wtmp = (wght1a(i  ,j-1,iblk)  &
    3753             :                         + wght1a(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3754             :                         + wght1b(i-1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3755           0 :                         + wght1b(i  ,j  ,iblk))
    3756           0 :                   if (wtmp /= c0) &
    3757             :                   work2(i,j,iblk) = (work1a(i  ,j-1,iblk)*wght1a(i  ,j-1,iblk)  &   ! LCOV_EXCL_LINE
    3758             :                                    + work1a(i  ,j  ,iblk)*wght1a(i  ,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3759             :                                    + work1b(i-1,j  ,iblk)*wght1b(i-1,j  ,iblk)  &   ! LCOV_EXCL_LINE
    3760             :                                    + work1b(i  ,j  ,iblk)*wght1b(i  ,j  ,iblk)) &   ! LCOV_EXCL_LINE
    3761           0 :                                    / wtmp
    3762             :                enddo
    3763             :                enddo
    3764             :             enddo
    3765             :             !$OMP END PARALLEL DO
    3766             : 
    3767             :          case default
    3768           0 :             call abort_ice(subname//'ERROR: unknown option '//trim(dir))
    3769             :          end select
    3770             : 
    3771           0 :       end subroutine grid_average_X2Y_2
    3772             : 
    3773             : !=======================================================================
    3774             : ! Compute the minimum of adjacent values of a field at specific indices,
    3775             : ! depending on the grid location (U, E, N)
    3776             : !
    3777           0 :       real(kind=dbl_kind) function grid_neighbor_min(field, i, j, grid_location) result(mini)
    3778             : 
    3779             :       real (kind=dbl_kind), dimension (nx_block,ny_block), intent(in) :: &
    3780             :          field    ! field defined at T point
    3781             : 
    3782             :       integer (kind=int_kind), intent(in) :: &
    3783             :          i, j
    3784             : 
    3785             :       character(len=*), intent(in) :: &
    3786             :          grid_location ! grid location at which to compute the minumum (U, E, N)
    3787             : 
    3788             :       character(len=*), parameter :: subname = '(grid_neighbor_min)'
    3789             : 
    3790           0 :       select case (trim(grid_location))
    3791             :          case('U')
    3792           0 :             mini = min(field(i,j), field(i+1,j), field(i,j+1), field(i+1,j+1))
    3793             :          case('E')
    3794           0 :             mini = min(field(i,j), field(i+1,j))
    3795             :          case('N')
    3796           0 :             mini = min(field(i,j), field(i,j+1))
    3797             :          case default
    3798           0 :             call abort_ice(subname // ' unknown grid_location: ' // grid_location)
    3799             :       end select
    3800             : 
    3801           0 :       end function grid_neighbor_min
    3802             : 
    3803             : !=======================================================================
    3804             : ! Compute the maximum of adjacent values of a field at specific indices,
    3805             : ! depending on the grid location (U, E, N)
    3806             : !
    3807           0 :       real(kind=dbl_kind) function grid_neighbor_max(field, i, j, grid_location) result(maxi)
    3808             : 
    3809             :       real (kind=dbl_kind), dimension (nx_block,ny_block), intent(in) :: &
    3810             :          field    ! field defined at T point
    3811             : 
    3812             :       integer (kind=int_kind), intent(in) :: &
    3813             :          i, j
    3814             : 
    3815             :       character(len=*), intent(in) :: &
    3816             :          grid_location ! grid location at which to compute the maximum (U, E, N)
    3817             : 
    3818             : 
    3819             :       character(len=*), parameter :: subname = '(grid_neighbor_max)'
    3820             : 
    3821           0 :       select case (trim(grid_location))
    3822             :          case('U')
    3823           0 :             maxi = max(field(i,j), field(i+1,j), field(i,j+1), field(i+1,j+1))
    3824             :          case('E')
    3825           0 :             maxi = max(field(i,j), field(i+1,j))
    3826             :          case('N')
    3827           0 :             maxi = max(field(i,j), field(i,j+1))
    3828             :          case default
    3829           0 :             call abort_ice(subname // ' unknown grid_location: ' // grid_location)
    3830             :       end select
    3831             : 
    3832           0 :       end function grid_neighbor_max
    3833             : 
    3834             : !=======================================================================
    3835             : ! The following code is used for obtaining the coordinates of the grid
    3836             : ! vertices for CF-compliant netCDF history output. Approximate!
    3837             : !=======================================================================
    3838             : 
    3839             : ! These fields are only used for netcdf history output, and the
    3840             : ! ghost cell values are not needed.
    3841             : ! NOTE:  Extrapolations were used: these fields are approximate!
    3842             : !
    3843             : ! authors:   A. McLaren, Met Office
    3844             : !            E. Hunke, LANL
    3845             : 
    3846          37 :       subroutine gridbox_corners
    3847             : 
    3848             :       use ice_blocks, only: nx_block, ny_block
    3849             :       use ice_constants, only: c0,  c2, c360, &
    3850             :           field_loc_NEcorner, field_type_scalar
    3851             :       use ice_domain_size, only: max_blocks
    3852             : 
    3853             :       integer (kind=int_kind) :: &
    3854             :           i,j,iblk,icorner,& ! index counters   ! LCOV_EXCL_LINE
    3855             :           ilo,ihi,jlo,jhi    ! beginning and end of physical domain
    3856             : 
    3857             :       real (kind=dbl_kind), dimension(:,:), allocatable :: &
    3858          37 :          work_g2
    3859             : 
    3860             :       real (kind=dbl_kind), dimension (nx_block,ny_block,max_blocks) :: &
    3861       27874 :          work1
    3862             : 
    3863             :       real (kind=dbl_kind) :: &
    3864           8 :          rad_to_deg
    3865             : 
    3866             :       type (block) :: &
    3867             :          this_block           ! block information for current block
    3868             : 
    3869             :       character(len=*), parameter :: subname = '(gridbox_corners)'
    3870             : 
    3871          37 :       call icepack_query_parameters(rad_to_deg_out=rad_to_deg)
    3872          37 :       call icepack_warnings_flush(nu_diag)
    3873          37 :       if (icepack_warnings_aborted()) call abort_ice(error_message=subname, &
    3874           0 :          file=__FILE__, line=__LINE__)
    3875             : 
    3876             :       !-------------------------------------------------------------
    3877             :       ! Get coordinates of grid boxes for each block as follows:
    3878             :       ! (1) SW corner, (2) SE corner, (3) NE corner, (4) NW corner
    3879             :       !-------------------------------------------------------------
    3880             : 
    3881      538192 :       latu_bounds(:,:,:,:) = c0
    3882      538192 :       lonu_bounds(:,:,:,:) = c0
    3883             : 
    3884          20 :       !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
    3885          50 :       do iblk = 1, nblocks
    3886          33 :          this_block = get_block(blocks_ice(iblk),iblk)
    3887          33 :          ilo = this_block%ilo
    3888          33 :          ihi = this_block%ihi
    3889          33 :          jlo = this_block%jlo
    3890          33 :          jhi = this_block%jhi
    3891             : 
    3892        1210 :          do j = jlo, jhi
    3893       45541 :          do i = ilo, ihi
    3894             : 
    3895       44368 :             latu_bounds(1,i,j,iblk)=TLAT(i  ,j  ,iblk)*rad_to_deg
    3896       44368 :             latu_bounds(2,i,j,iblk)=TLAT(i+1,j  ,iblk)*rad_to_deg
    3897       44368 :             latu_bounds(3,i,j,iblk)=TLAT(i+1,j+1,iblk)*rad_to_deg
    3898       44368 :             latu_bounds(4,i,j,iblk)=TLAT(i  ,j+1,iblk)*rad_to_deg
    3899             : 
    3900       44368 :             lonu_bounds(1,i,j,iblk)=TLON(i  ,j  ,iblk)*rad_to_deg
    3901       44368 :             lonu_bounds(2,i,j,iblk)=TLON(i+1,j  ,iblk)*rad_to_deg
    3902       44368 :             lonu_bounds(3,i,j,iblk)=TLON(i+1,j+1,iblk)*rad_to_deg
    3903       45508 :             lonu_bounds(4,i,j,iblk)=TLON(i  ,j+1,iblk)*rad_to_deg
    3904             : 
    3905             :          enddo
    3906             :          enddo
    3907             :       enddo
    3908             :       !$OMP END PARALLEL DO
    3909             : 
    3910             :       !----------------------------------------------------------------
    3911             :       ! extrapolate on global grid to get edge values
    3912             :       !----------------------------------------------------------------
    3913             : 
    3914          37 :       if (my_task == master_task) then
    3915           7 :          allocate(work_g2(nx_global,ny_global))
    3916             :       else
    3917          30 :          allocate(work_g2(1,1))
    3918             :       endif
    3919             : 
    3920      111936 :       work1(:,:,:) = latu_bounds(2,:,:,:)
    3921             : !     work_g2 = c0
    3922             : 
    3923          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    3924          37 :       if (my_task == master_task) then
    3925         843 :          do j = 1, ny_global
    3926           0 :             work_g2(nx_global,j) = c2*work_g2(nx_global-1,j) &
    3927         843 :                                     - work_g2(nx_global-2,j)
    3928             :          enddo
    3929             :       endif
    3930           0 :       call scatter_global(work1, work_g2, &
    3931             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    3932          37 :                           field_loc_NEcorner, field_type_scalar)
    3933      111936 :       latu_bounds(2,:,:,:) = work1(:,:,:)
    3934             : 
    3935      111936 :       work1(:,:,:) = latu_bounds(3,:,:,:)
    3936          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    3937          37 :       if (my_task == master_task) then
    3938         763 :          do i = 1, nx_global
    3939           0 :             work_g2(i,ny_global) = c2*work_g2(i,ny_global-1) &
    3940         763 :                                     - work_g2(i,ny_global-2)
    3941             :          enddo
    3942         843 :          do j = 1, ny_global
    3943           0 :             work_g2(nx_global,j) = c2*work_g2(nx_global-1,j) &
    3944         843 :                                     - work_g2(nx_global-2,j)
    3945             :          enddo
    3946             :       endif
    3947           0 :       call scatter_global(work1, work_g2, &
    3948             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    3949          37 :                           field_loc_NEcorner, field_type_scalar)
    3950      111936 :       latu_bounds(3,:,:,:) = work1(:,:,:)
    3951             : 
    3952      111936 :       work1(:,:,:) = latu_bounds(4,:,:,:)
    3953          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    3954          37 :       if (my_task == master_task) then
    3955         763 :          do i = 1, nx_global
    3956           0 :             work_g2(i,ny_global) = c2*work_g2(i,ny_global-1) &
    3957         763 :                                     - work_g2(i,ny_global-2)
    3958             :          enddo
    3959             :       endif
    3960           0 :       call scatter_global(work1, work_g2, &
    3961             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    3962          37 :                           field_loc_NEcorner, field_type_scalar)
    3963      111936 :       latu_bounds(4,:,:,:) = work1(:,:,:)
    3964             : 
    3965      111936 :       work1(:,:,:) = lonu_bounds(2,:,:,:)
    3966          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    3967          37 :       if (my_task == master_task) then
    3968         843 :          do j = 1, ny_global
    3969           0 :             work_g2(nx_global,j) = c2*work_g2(nx_global-1,j) &
    3970         843 :                                     - work_g2(nx_global-2,j)
    3971             :          enddo
    3972             :       endif
    3973           0 :       call scatter_global(work1, work_g2, &
    3974             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    3975          37 :                           field_loc_NEcorner, field_type_scalar)
    3976      111936 :       lonu_bounds(2,:,:,:) = work1(:,:,:)
    3977             : 
    3978      111936 :       work1(:,:,:) = lonu_bounds(3,:,:,:)
    3979          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    3980          37 :       if (my_task == master_task) then
    3981         763 :          do i = 1, nx_global
    3982           0 :             work_g2(i,ny_global) = c2*work_g2(i,ny_global-1) &
    3983         763 :                                     - work_g2(i,ny_global-2)
    3984             :          enddo
    3985         843 :          do j = 1, ny_global
    3986           0 :             work_g2(nx_global,j) = c2*work_g2(nx_global-1,j) &
    3987         843 :                                     - work_g2(nx_global-2,j)
    3988             :          enddo
    3989             :       endif
    3990           0 :       call scatter_global(work1, work_g2, &
    3991             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    3992          37 :                           field_loc_NEcorner, field_type_scalar)
    3993      111936 :       lonu_bounds(3,:,:,:) = work1(:,:,:)
    3994             : 
    3995      111936 :       work1(:,:,:) = lonu_bounds(4,:,:,:)
    3996          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    3997          37 :       if (my_task == master_task) then
    3998         763 :          do i = 1, nx_global
    3999           0 :             work_g2(i,ny_global) = c2*work_g2(i,ny_global-1) &
    4000         763 :                                     - work_g2(i,ny_global-2)
    4001             :          enddo
    4002             :       endif
    4003           0 :       call scatter_global(work1, work_g2, &
    4004             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    4005          37 :                           field_loc_NEcorner, field_type_scalar)
    4006      111936 :       lonu_bounds(4,:,:,:) = work1(:,:,:)
    4007             : 
    4008          37 :       deallocate(work_g2)
    4009             : 
    4010             :       !----------------------------------------------------------------
    4011             :       ! Convert longitude to Degrees East >0 for history output
    4012             :       !----------------------------------------------------------------
    4013             : 
    4014          37 :       allocate(work_g2(nx_block,ny_block))  ! not used as global here
    4015             :       !OMP fails in this loop
    4016         197 :       do iblk = 1, nblocks
    4017         837 :          do icorner = 1, 4
    4018      446600 :             work_g2(:,:) = lont_bounds(icorner,:,:,iblk) + c360
    4019      446600 :             where (work_g2 > c360) work_g2 = work_g2 - c360
    4020      446600 :             where (work_g2 < c0 )  work_g2 = work_g2 + c360
    4021      446600 :             lont_bounds(icorner,:,:,iblk) = work_g2(:,:)
    4022      446600 :             work_g2(:,:) = lonu_bounds(icorner,:,:,iblk) + c360
    4023      446600 :             where (work_g2 > c360) work_g2 = work_g2 - c360
    4024      446600 :             where (work_g2 < c0 )  work_g2 = work_g2 + c360
    4025      446760 :             lonu_bounds(icorner,:,:,iblk) = work_g2(:,:)
    4026             :          enddo
    4027             :       enddo
    4028          37 :       deallocate(work_g2)
    4029             : 
    4030          74 :       end subroutine gridbox_corners
    4031             : 
    4032             : !=======================================================================
    4033             : ! The following code is used for obtaining the coordinates of the grid
    4034             : ! vertices for CF-compliant netCDF history output. Approximate!
    4035             : !=======================================================================
    4036             : 
    4037             : ! These fields are only used for netcdf history output, and the
    4038             : ! ghost cell values are not needed.
    4039             : ! NOTE:  Extrapolations were used: these fields are approximate!
    4040             : !
    4041             : 
    4042          37 :       subroutine gridbox_edges
    4043             : 
    4044             :       use ice_blocks, only: nx_block, ny_block
    4045             :       use ice_constants, only: c0,  c2, c360, &
    4046             :           field_loc_NEcorner, field_type_scalar
    4047             :       use ice_domain_size, only: max_blocks
    4048             : 
    4049             :       integer (kind=int_kind) :: &
    4050             :           i,j,iblk,icorner,& ! index counters   ! LCOV_EXCL_LINE
    4051             :           ilo,ihi,jlo,jhi    ! beginning and end of physical domain
    4052             : 
    4053             :       real (kind=dbl_kind), dimension(:,:), allocatable :: &
    4054          37 :          work_g2
    4055             : 
    4056             :       real (kind=dbl_kind), dimension (nx_block,ny_block,max_blocks) :: &
    4057       27874 :          work1
    4058             : 
    4059             :       real (kind=dbl_kind) :: &
    4060           8 :          rad_to_deg
    4061             : 
    4062             :       type (block) :: &
    4063             :          this_block           ! block information for current block
    4064             : 
    4065             :       character(len=*), parameter :: subname = '(gridbox_edges)'
    4066             : 
    4067          37 :       call icepack_query_parameters(rad_to_deg_out=rad_to_deg)
    4068          37 :       call icepack_warnings_flush(nu_diag)
    4069          37 :       if (icepack_warnings_aborted()) call abort_ice(error_message=subname, &
    4070           0 :          file=__FILE__, line=__LINE__)
    4071             : 
    4072             :       !-------------------------------------------------------------
    4073             :       ! Get coordinates of grid boxes for each block as follows:
    4074             :       ! for N pt: (1) W edge, (2) E edge, (3) E edge j+1, (4) W edge j+1
    4075             :       ! for E pt: (1) S edge, (2) S edge i+1, (3) N edge, i+1 (4) N edge
    4076             :       !-------------------------------------------------------------
    4077             : 
    4078      538192 :       latn_bounds(:,:,:,:) = c0
    4079      538192 :       lonn_bounds(:,:,:,:) = c0
    4080      538192 :       late_bounds(:,:,:,:) = c0
    4081      538192 :       lone_bounds(:,:,:,:) = c0
    4082             : 
    4083          20 :       !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block)
    4084          50 :       do iblk = 1, nblocks
    4085          33 :          this_block = get_block(blocks_ice(iblk),iblk)
    4086          33 :          ilo = this_block%ilo
    4087          33 :          ihi = this_block%ihi
    4088          33 :          jlo = this_block%jlo
    4089          33 :          jhi = this_block%jhi
    4090             : 
    4091        1210 :          do j = jlo, jhi
    4092       45541 :          do i = ilo, ihi
    4093             : 
    4094       44368 :             latn_bounds(1,i,j,iblk)=ELAT(i-1,j  ,iblk)*rad_to_deg
    4095       44368 :             latn_bounds(2,i,j,iblk)=ELAT(i  ,j  ,iblk)*rad_to_deg
    4096       44368 :             latn_bounds(3,i,j,iblk)=ELAT(i  ,j+1,iblk)*rad_to_deg
    4097       44368 :             latn_bounds(4,i,j,iblk)=ELAT(i-1,j+1,iblk)*rad_to_deg
    4098             : 
    4099       44368 :             lonn_bounds(1,i,j,iblk)=ELON(i-1,j  ,iblk)*rad_to_deg
    4100       44368 :             lonn_bounds(2,i,j,iblk)=ELON(i  ,j  ,iblk)*rad_to_deg
    4101       44368 :             lonn_bounds(3,i,j,iblk)=ELON(i  ,j+1,iblk)*rad_to_deg
    4102       44368 :             lonn_bounds(4,i,j,iblk)=ELON(i-1,j+1,iblk)*rad_to_deg
    4103             : 
    4104       44368 :             late_bounds(1,i,j,iblk)=NLAT(i  ,j-1,iblk)*rad_to_deg
    4105       44368 :             late_bounds(2,i,j,iblk)=NLAT(i+1,j-1,iblk)*rad_to_deg
    4106       44368 :             late_bounds(3,i,j,iblk)=NLAT(i+1,j  ,iblk)*rad_to_deg
    4107       44368 :             late_bounds(4,i,j,iblk)=NLAT(i  ,j  ,iblk)*rad_to_deg
    4108             : 
    4109       44368 :             lone_bounds(1,i,j,iblk)=NLON(i  ,j-1,iblk)*rad_to_deg
    4110       44368 :             lone_bounds(2,i,j,iblk)=NLON(i+1,j-1,iblk)*rad_to_deg
    4111       44368 :             lone_bounds(3,i,j,iblk)=NLON(i+1,j  ,iblk)*rad_to_deg
    4112       45508 :             lone_bounds(4,i,j,iblk)=NLON(i  ,j  ,iblk)*rad_to_deg
    4113             : 
    4114             :          enddo
    4115             :          enddo
    4116             :       enddo
    4117             :       !$OMP END PARALLEL DO
    4118             : 
    4119             :       !----------------------------------------------------------------
    4120             :       ! extrapolate on global grid to get edge values
    4121             :       !----------------------------------------------------------------
    4122             : 
    4123          37 :       if (my_task == master_task) then
    4124           7 :          allocate(work_g2(nx_global,ny_global))
    4125             :       else
    4126          30 :          allocate(work_g2(1,1))
    4127             :       endif
    4128             : 
    4129             :       ! latn_bounds
    4130             : 
    4131      111936 :       work1(:,:,:) = latn_bounds(1,:,:,:)
    4132          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    4133          37 :       if (my_task == master_task) then
    4134         843 :          do j = 1, ny_global
    4135           0 :             work_g2(1,j) = c2*work_g2(2,j) &
    4136         843 :                             - work_g2(3,j)
    4137             :          enddo
    4138             :       endif
    4139           0 :       call scatter_global(work1, work_g2, &
    4140             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    4141          37 :                           field_loc_NEcorner, field_type_scalar)
    4142      111936 :       latn_bounds(1,:,:,:) = work1(:,:,:)
    4143             : 
    4144      111936 :       work1(:,:,:) = latn_bounds(3,:,:,:)
    4145          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    4146          37 :       if (my_task == master_task) then
    4147         763 :          do i = 1, nx_global
    4148           0 :             work_g2(i,ny_global) = c2*work_g2(i,ny_global-1) &
    4149         763 :                                     - work_g2(i,ny_global-2)
    4150             :          enddo
    4151             :       endif
    4152           0 :       call scatter_global(work1, work_g2, &
    4153             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    4154          37 :                           field_loc_NEcorner, field_type_scalar)
    4155      111936 :       latn_bounds(3,:,:,:) = work1(:,:,:)
    4156             : 
    4157      111936 :       work1(:,:,:) = latn_bounds(4,:,:,:)
    4158          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    4159          37 :       if (my_task == master_task) then
    4160         763 :          do i = 1, nx_global
    4161           0 :             work_g2(i,ny_global) = c2*work_g2(i,ny_global-1) &
    4162         763 :                                     - work_g2(i,ny_global-2)
    4163             :          enddo
    4164         843 :          do j = 1, ny_global
    4165           0 :             work_g2(1,j) = c2*work_g2(2,j) &
    4166         843 :                             - work_g2(3,j)
    4167             :          enddo
    4168             :       endif
    4169           0 :       call scatter_global(work1, work_g2, &
    4170             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    4171          37 :                           field_loc_NEcorner, field_type_scalar)
    4172      111936 :       latn_bounds(4,:,:,:) = work1(:,:,:)
    4173             : 
    4174             :       ! lonn_bounds
    4175             : 
    4176      111936 :       work1(:,:,:) = lonn_bounds(1,:,:,:)
    4177          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    4178          37 :       if (my_task == master_task) then
    4179         843 :          do j = 1, ny_global
    4180           0 :             work_g2(1,j) = c2*work_g2(2,j) &
    4181         843 :                             - work_g2(3,j)
    4182             :          enddo
    4183             :       endif
    4184           0 :       call scatter_global(work1, work_g2, &
    4185             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    4186          37 :                           field_loc_NEcorner, field_type_scalar)
    4187      111936 :       lonn_bounds(1,:,:,:) = work1(:,:,:)
    4188             : 
    4189      111936 :       work1(:,:,:) = lonn_bounds(3,:,:,:)
    4190          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    4191          37 :       if (my_task == master_task) then
    4192         763 :          do i = 1, nx_global
    4193           0 :             work_g2(i,ny_global) = c2*work_g2(i,ny_global-1) &
    4194         763 :                                     - work_g2(i,ny_global-2)
    4195             :          enddo
    4196             :       endif
    4197           0 :       call scatter_global(work1, work_g2, &
    4198             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    4199          37 :                           field_loc_NEcorner, field_type_scalar)
    4200      111936 :       lonn_bounds(3,:,:,:) = work1(:,:,:)
    4201             : 
    4202      111936 :       work1(:,:,:) = lonn_bounds(4,:,:,:)
    4203          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    4204          37 :       if (my_task == master_task) then
    4205         763 :          do i = 1, nx_global
    4206           0 :             work_g2(i,ny_global) = c2*work_g2(i,ny_global-1) &
    4207         763 :                                     - work_g2(i,ny_global-2)
    4208             :          enddo
    4209         843 :          do j = 1, ny_global
    4210           0 :             work_g2(1,j) = c2*work_g2(2,j) &
    4211         843 :                             - work_g2(3,j)
    4212             :          enddo
    4213             :       endif
    4214           0 :       call scatter_global(work1, work_g2, &
    4215             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    4216          37 :                           field_loc_NEcorner, field_type_scalar)
    4217      111936 :       lonn_bounds(4,:,:,:) = work1(:,:,:)
    4218             : 
    4219             :       ! late_bounds
    4220             : 
    4221      111936 :       work1(:,:,:) = late_bounds(1,:,:,:)
    4222          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    4223          37 :       if (my_task == master_task) then
    4224         763 :          do i = 1, nx_global
    4225           0 :             work_g2(i,1) = c2*work_g2(i,2) &
    4226         763 :                             - work_g2(i,3)
    4227             :          enddo
    4228             :       endif
    4229           0 :       call scatter_global(work1, work_g2, &
    4230             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    4231          37 :                           field_loc_NEcorner, field_type_scalar)
    4232      111936 :       late_bounds(1,:,:,:) = work1(:,:,:)
    4233             : 
    4234      111936 :       work1(:,:,:) = late_bounds(2,:,:,:)
    4235          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    4236          37 :       if (my_task == master_task) then
    4237         763 :          do i = 1, nx_global
    4238           0 :             work_g2(i,1) = c2*work_g2(i,2) &
    4239         763 :                             - work_g2(i,3)
    4240             :          enddo
    4241         843 :          do j = 1, ny_global
    4242           0 :             work_g2(nx_global,j) = c2*work_g2(nx_global-1,j) &
    4243         843 :                                     - work_g2(nx_global-2,j)
    4244             :          enddo
    4245             :       endif
    4246           0 :       call scatter_global(work1, work_g2, &
    4247             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    4248          37 :                           field_loc_NEcorner, field_type_scalar)
    4249      111936 :       late_bounds(2,:,:,:) = work1(:,:,:)
    4250             : 
    4251      111936 :       work1(:,:,:) = late_bounds(3,:,:,:)
    4252          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    4253          37 :       if (my_task == master_task) then
    4254         843 :          do j = 1, ny_global
    4255           0 :             work_g2(nx_global,j) = c2*work_g2(nx_global-1,j) &
    4256         843 :                                     - work_g2(nx_global-2,j)
    4257             :          enddo
    4258             :       endif
    4259           0 :       call scatter_global(work1, work_g2, &
    4260             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    4261          37 :                           field_loc_NEcorner, field_type_scalar)
    4262      111936 :       late_bounds(3,:,:,:) = work1(:,:,:)
    4263             : 
    4264             :       ! lone_bounds
    4265             : 
    4266      111936 :       work1(:,:,:) = lone_bounds(1,:,:,:)
    4267          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    4268          37 :       if (my_task == master_task) then
    4269         763 :          do i = 1, nx_global
    4270           0 :             work_g2(i,1) = c2*work_g2(i,2) &
    4271         763 :                             - work_g2(i,3)
    4272             :          enddo
    4273             :       endif
    4274           0 :       call scatter_global(work1, work_g2, &
    4275             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    4276          37 :                           field_loc_NEcorner, field_type_scalar)
    4277      111936 :       lone_bounds(1,:,:,:) = work1(:,:,:)
    4278             : 
    4279      111936 :       work1(:,:,:) = lone_bounds(2,:,:,:)
    4280          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    4281          37 :       if (my_task == master_task) then
    4282         763 :          do i = 1, nx_global
    4283           0 :             work_g2(i,1) = c2*work_g2(i,2) &
    4284         763 :                             - work_g2(i,3)
    4285             :          enddo
    4286         843 :          do j = 1, ny_global
    4287           0 :             work_g2(nx_global,j) = c2*work_g2(nx_global-1,j) &
    4288         843 :                                     - work_g2(nx_global-2,j)
    4289             :          enddo
    4290             :       endif
    4291           0 :       call scatter_global(work1, work_g2, &
    4292             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    4293          37 :                           field_loc_NEcorner, field_type_scalar)
    4294      111936 :       lone_bounds(2,:,:,:) = work1(:,:,:)
    4295             : 
    4296      111936 :       work1(:,:,:) = lone_bounds(3,:,:,:)
    4297          37 :       call gather_global(work_g2, work1, master_task, distrb_info)
    4298          37 :       if (my_task == master_task) then
    4299         843 :          do j = 1, ny_global
    4300           0 :             work_g2(nx_global,j) = c2*work_g2(nx_global-1,j) &
    4301         843 :                                     - work_g2(nx_global-2,j)
    4302             :          enddo
    4303             :       endif
    4304           0 :       call scatter_global(work1, work_g2, &
    4305             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    4306          37 :                           field_loc_NEcorner, field_type_scalar)
    4307      111936 :       lone_bounds(3,:,:,:) = work1(:,:,:)
    4308             : 
    4309          37 :       deallocate(work_g2)
    4310             : 
    4311             :       !----------------------------------------------------------------
    4312             :       ! Convert longitude to Degrees East >0 for history output
    4313             :       !----------------------------------------------------------------
    4314             : 
    4315          37 :       allocate(work_g2(nx_block,ny_block))  ! not used as global here
    4316             :       !OMP fails in this loop
    4317         197 :       do iblk = 1, nblocks
    4318         837 :          do icorner = 1, 4
    4319      446600 :             work_g2(:,:) = lonn_bounds(icorner,:,:,iblk) + c360
    4320      446600 :             where (work_g2 > c360) work_g2 = work_g2 - c360
    4321      446600 :             where (work_g2 < c0 )  work_g2 = work_g2 + c360
    4322      446600 :             lonn_bounds(icorner,:,:,iblk) = work_g2(:,:)
    4323      446600 :             work_g2(:,:) = lone_bounds(icorner,:,:,iblk) + c360
    4324      446600 :             where (work_g2 > c360) work_g2 = work_g2 - c360
    4325      446600 :             where (work_g2 < c0 )  work_g2 = work_g2 + c360
    4326      446760 :             lone_bounds(icorner,:,:,iblk) = work_g2(:,:)
    4327             :          enddo
    4328             :       enddo
    4329          37 :       deallocate(work_g2)
    4330             : 
    4331          74 :       end subroutine gridbox_edges
    4332             : 
    4333             : !=======================================================================
    4334             : 
    4335             : ! NOTE:  Boundary conditions for fields on NW, SW, SE corners
    4336             : !        have not been implemented; using NE corner location for all.
    4337             : !        Extrapolations are also used: these fields are approximate!
    4338             : !
    4339             : ! authors:   A. McLaren, Met Office
    4340             : !            E. Hunke, LANL
    4341             : 
    4342          42 :       subroutine gridbox_verts(work_g,vbounds)
    4343             : 
    4344             :       use ice_blocks, only: nx_block, ny_block
    4345             :       use ice_constants, only: c0, c2, &
    4346             :           field_loc_NEcorner, field_type_scalar
    4347             :       use ice_domain_size, only: max_blocks
    4348             : 
    4349             :       real (kind=dbl_kind), dimension(:,:), intent(in) :: &
    4350             :           work_g
    4351             : 
    4352             :       real (kind=dbl_kind), dimension(4,nx_block,ny_block,max_blocks), intent(out) :: &
    4353             :           vbounds
    4354             : 
    4355             :       integer (kind=int_kind) :: &
    4356             :           i,j                 ! index counters
    4357             : 
    4358             :       real (kind=dbl_kind) :: &
    4359          16 :           rad_to_deg
    4360             : 
    4361             :       real (kind=dbl_kind), dimension(:,:), allocatable :: &
    4362          42 :          work_g2
    4363             : 
    4364             :       real (kind=dbl_kind), dimension (nx_block,ny_block,max_blocks) :: &
    4365       55684 :          work1
    4366             : 
    4367             :       character(len=*), parameter :: subname = '(gridbox_verts)'
    4368             : 
    4369          42 :       call icepack_query_parameters(rad_to_deg_out=rad_to_deg)
    4370          42 :       call icepack_warnings_flush(nu_diag)
    4371          42 :       if (icepack_warnings_aborted()) call abort_ice(error_message=subname, &
    4372           0 :          file=__FILE__, line=__LINE__)
    4373             : 
    4374          42 :       if (my_task == master_task) then
    4375          10 :          allocate(work_g2(nx_global,ny_global))
    4376             :       else
    4377          32 :          allocate(work_g2(1,1))
    4378             :       endif
    4379             : 
    4380             :       !-------------------------------------------------------------
    4381             :       ! Get coordinates of grid boxes for each block as follows:
    4382             :       ! (1) SW corner, (2) SE corner, (3) NE corner, (4) NW corner
    4383             :       !-------------------------------------------------------------
    4384             : 
    4385      117266 :       work_g2(:,:) = c0
    4386          42 :       if (my_task == master_task) then
    4387        1160 :          do j = 2, ny_global
    4388      115010 :          do i = 2, nx_global
    4389      115000 :             work_g2(i,j) = work_g(i-1,j-1) * rad_to_deg
    4390             :          enddo
    4391             :          enddo
    4392             :          ! extrapolate
    4393        1170 :          do j = 1, ny_global
    4394        1170 :             work_g2(1,j) = c2*work_g2(2,j) - work_g2(3,j)
    4395             :          enddo
    4396        1010 :          do i = 1, nx_global
    4397        1010 :             work_g2(i,1) = c2*work_g2(i,2) - work_g2(i,3)
    4398             :          enddo
    4399             :       endif
    4400           0 :       call scatter_global(work1, work_g2, &
    4401             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    4402          42 :                           field_loc_NEcorner, field_type_scalar)
    4403      147616 :       vbounds(1,:,:,:) = work1(:,:,:)
    4404             : 
    4405      117266 :       work_g2(:,:) = c0
    4406          42 :       if (my_task == master_task) then
    4407        1160 :          do j = 2, ny_global
    4408      116160 :          do i = 1, nx_global
    4409      116150 :             work_g2(i,j) = work_g(i,j-1) * rad_to_deg
    4410             :          enddo
    4411             :          enddo
    4412             :          ! extrapolate
    4413        1010 :          do i = 1, nx_global
    4414        1010 :             work_g2(i,1) = (c2*work_g2(i,2) - work_g2(i,3))
    4415             :          enddo
    4416             :       endif
    4417           0 :       call scatter_global(work1, work_g2, &
    4418             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    4419          42 :                           field_loc_NEcorner, field_type_scalar)
    4420      147616 :       vbounds(2,:,:,:) = work1(:,:,:)
    4421             : 
    4422      117266 :       work_g2(:,:) = c0
    4423          42 :       if (my_task == master_task) then
    4424        1170 :          do j = 1, ny_global
    4425      117170 :          do i = 1, nx_global
    4426      117160 :             work_g2(i,j) = work_g(i,j) * rad_to_deg
    4427             :          enddo
    4428             :          enddo
    4429             :       endif
    4430           0 :       call scatter_global(work1, work_g2, &
    4431             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    4432          42 :                           field_loc_NEcorner, field_type_scalar)
    4433      147616 :       vbounds(3,:,:,:) = work1(:,:,:)
    4434             : 
    4435      117266 :       work_g2(:,:) = c0
    4436          42 :       if (my_task == master_task) then
    4437        1170 :          do j = 1, ny_global
    4438      116010 :          do i = 2, nx_global
    4439      116000 :             work_g2(i,j) = work_g(i-1,j  ) * rad_to_deg
    4440             :          enddo
    4441             :          enddo
    4442             :          ! extrapolate
    4443        1170 :          do j = 1, ny_global
    4444        1170 :             work_g2(1,j) = c2*work_g2(2,j) - work_g2(3,j)
    4445             :          enddo
    4446             :       endif
    4447           0 :       call scatter_global(work1, work_g2, &
    4448             :                           master_task, distrb_info, &   ! LCOV_EXCL_LINE
    4449          42 :                           field_loc_NEcorner, field_type_scalar)
    4450      147616 :       vbounds(4,:,:,:) = work1(:,:,:)
    4451             : 
    4452          42 :       deallocate (work_g2)
    4453             : 
    4454          42 :       end subroutine gridbox_verts
    4455             : 
    4456             : !=======================================================================
    4457             : ! ocean bathymetry for grounded sea ice (seabed stress) or icebergs
    4458             : ! currently hardwired for 40 levels (gx3, gx1 grids)
    4459             : ! should be read from a file instead (see subroutine read_seabedstress_bathy)
    4460             : 
    4461          37 :       subroutine get_bathymetry
    4462             : 
    4463             :       use ice_constants, only: c0
    4464             : 
    4465             :       integer (kind=int_kind) :: &
    4466             :          i, j, k, iblk      ! loop indices
    4467             : 
    4468             :       integer (kind=int_kind), parameter :: &
    4469             :          nlevel = 40        ! number of layers (gx3 grid)
    4470             : 
    4471             :       real (kind=dbl_kind), dimension(nlevel) :: &
    4472         328 :          depth              ! total depth, m
    4473             : 
    4474             :       real (kind=dbl_kind) :: &
    4475           8 :          puny
    4476             : 
    4477             :       logical (kind=log_kind) :: &
    4478             :          calc_dragio
    4479             : 
    4480             :       real (kind=dbl_kind), dimension(nlevel), parameter :: &
    4481             :          thick  = (/ &                        ! ocean layer thickness, m   ! LCOV_EXCL_LINE
    4482             :             10.01244_dbl_kind,  10.11258_dbl_kind,  10.31682_dbl_kind, &   ! LCOV_EXCL_LINE
    4483             :             10.63330_dbl_kind,  11.07512_dbl_kind,  11.66145_dbl_kind, &   ! LCOV_EXCL_LINE
    4484             :             12.41928_dbl_kind,  13.38612_dbl_kind,  14.61401_dbl_kind, &   ! LCOV_EXCL_LINE
    4485             :             16.17561_dbl_kind,  18.17368_dbl_kind,  20.75558_dbl_kind, &   ! LCOV_EXCL_LINE
    4486             :             24.13680_dbl_kind,  28.63821_dbl_kind,  34.74644_dbl_kind, &   ! LCOV_EXCL_LINE
    4487             :             43.20857_dbl_kind,  55.16812_dbl_kind,  72.30458_dbl_kind, &   ! LCOV_EXCL_LINE
    4488             :             96.74901_dbl_kind,  130.0392_dbl_kind,  170.0489_dbl_kind, &   ! LCOV_EXCL_LINE
    4489             :             207.9933_dbl_kind,  233.5694_dbl_kind,  245.2719_dbl_kind, &   ! LCOV_EXCL_LINE
    4490             :             248.9804_dbl_kind,  249.8322_dbl_kind,  249.9787_dbl_kind, &   ! LCOV_EXCL_LINE
    4491             :             249.9979_dbl_kind,  249.9998_dbl_kind,  250.0000_dbl_kind, &   ! LCOV_EXCL_LINE
    4492             :             250.0000_dbl_kind,  250.0000_dbl_kind,  250.0000_dbl_kind, &   ! LCOV_EXCL_LINE
    4493             :             250.0000_dbl_kind,  250.0000_dbl_kind,  250.0000_dbl_kind, &   ! LCOV_EXCL_LINE
    4494             :             250.0000_dbl_kind,  250.0000_dbl_kind,  250.0000_dbl_kind, &   ! LCOV_EXCL_LINE
    4495             :             250.0000_dbl_kind   /)
    4496             : 
    4497             :       character(len=*), parameter :: subname = '(get_bathymetry)'
    4498             : 
    4499          37 :       call icepack_query_parameters(puny_out=puny, calc_dragio_out=calc_dragio)
    4500          37 :       call icepack_warnings_flush(nu_diag)
    4501          37 :       if (icepack_warnings_aborted()) call abort_ice(error_message=subname, &
    4502           0 :          file=__FILE__, line=__LINE__)
    4503             : 
    4504          37 :       if (use_bathymetry) then
    4505             : 
    4506           0 :          call read_seabedstress_bathy
    4507             : 
    4508             :       else
    4509             : 
    4510             :          ! convert to total depth
    4511          37 :          depth(1) = thick(1)
    4512        1480 :          do k = 2, nlevel
    4513        1480 :             depth(k) = depth(k-1) + thick(k)
    4514             :          enddo
    4515             : 
    4516      111936 :          bathymetry = c0
    4517         197 :          do iblk = 1, nblocks
    4518        5340 :             do j = 1, ny_block
    4519      111650 :             do i = 1, nx_block
    4520      106347 :                k = min(nint(kmt(i,j,iblk)),nlevel)
    4521      106347 :                if (k > nlevel) call abort_ice(subname//' kmt gt nlevel error')
    4522      111490 :                if (k > 0) bathymetry(i,j,iblk) = depth(k)
    4523             :             enddo
    4524             :             enddo
    4525             :          enddo
    4526             : 
    4527             :          ! For consistency, set thickness_ocn_layer1 in Icepack if 'calc_dragio' is active
    4528          37 :          if (calc_dragio) then
    4529           0 :             call icepack_init_parameters(thickness_ocn_layer1_in=thick(1))
    4530           0 :             call icepack_warnings_flush(nu_diag)
    4531           0 :             if (icepack_warnings_aborted()) call abort_ice(error_message=subname, &
    4532           0 :                file=__FILE__, line=__LINE__)
    4533             :          endif
    4534             : 
    4535             :       endif ! bathymetry_file
    4536             : 
    4537          37 :       end subroutine get_bathymetry
    4538             : 
    4539             : !=======================================================================
    4540             : ! with use_bathymetry = false, vertical depth profile generated for max KMT
    4541             : ! with use_bathymetry = true, expects to read in pop vert_grid file
    4542             : 
    4543           0 :       subroutine get_bathymetry_popfile
    4544             : 
    4545             :       integer (kind=int_kind) :: &
    4546             :          i, j, k, iblk      ! loop indices
    4547             : 
    4548             :       integer (kind=int_kind) :: &
    4549             :          ntmp, nlevel   , & ! number of levels (max KMT)   ! LCOV_EXCL_LINE
    4550             :          k1             , & ! levels   ! LCOV_EXCL_LINE
    4551             :          ierr           , & ! error tag   ! LCOV_EXCL_LINE
    4552             :          fid                ! fid unit number
    4553             : 
    4554             :       real (kind=dbl_kind), dimension(:),allocatable :: &
    4555             :          depth          , & ! total depth, m   ! LCOV_EXCL_LINE
    4556           0 :          thick              ! layer thickness, cm -> m
    4557             : 
    4558             :       logical (kind=log_kind) :: &
    4559             :          calc_dragio
    4560             : 
    4561             :       character(len=*), parameter :: subname = '(get_bathymetry_popfile)'
    4562             : 
    4563           0 :       ntmp = maxval(nint(KMT))
    4564           0 :       nlevel = global_maxval(ntmp,distrb_info)
    4565             : 
    4566           0 :       if (my_task==master_task) then
    4567           0 :          write(nu_diag,*) subname,' KMT max = ',nlevel
    4568             :       endif
    4569             : 
    4570           0 :       allocate(depth(nlevel),thick(nlevel))
    4571           0 :       thick = -999999.
    4572           0 :       depth = -999999.
    4573             : 
    4574           0 :       if (use_bathymetry) then
    4575             : 
    4576           0 :          write (nu_diag,*) subname,' Bathymetry file = ', trim(bathymetry_file)
    4577           0 :          if (my_task == master_task) then
    4578           0 :             call get_fileunit(fid)
    4579           0 :             open(fid,file=bathymetry_file,form='formatted',iostat=ierr)
    4580           0 :             if (ierr/=0) call abort_ice(subname//' open error')
    4581           0 :             do k = 1,nlevel
    4582           0 :                read(fid,*,iostat=ierr) thick(k)
    4583           0 :                if (ierr/=0) call abort_ice(subname//' read error')
    4584             :             enddo
    4585           0 :             call release_fileunit(fid)
    4586             :          endif
    4587             : 
    4588           0 :          call broadcast_array(thick,master_task)
    4589             : 
    4590             :       else
    4591             : 
    4592             :          ! create thickness profile
    4593           0 :          k1 = min(5,nlevel)
    4594           0 :          do k = 1,k1
    4595           0 :             thick(k) = max(10000._dbl_kind/float(nlevel),500._dbl_kind)
    4596             :          enddo
    4597           0 :          do k = k1+1,nlevel
    4598           0 :             thick(k) = min(thick(k-1)*1.2_dbl_kind,20000._dbl_kind)
    4599             :          enddo
    4600             : 
    4601             :       endif
    4602             : 
    4603             :       ! convert thick from cm to m
    4604           0 :       thick = thick / 100._dbl_kind
    4605             : 
    4606             :       ! convert to total depth
    4607           0 :       depth(1) = thick(1)
    4608           0 :       do k = 2, nlevel
    4609           0 :          depth(k) = depth(k-1) + thick(k)
    4610           0 :          if (depth(k) < 0.) call abort_ice(subname//' negative depth error')
    4611             :       enddo
    4612             : 
    4613           0 :       if (my_task==master_task) then
    4614           0 :          do k = 1,nlevel
    4615           0 :            write(nu_diag,'(2a,i6,2f13.7)') subname,'   k, thick(m), depth(m) = ',k,thick(k),depth(k)
    4616             :          enddo
    4617             :       endif
    4618             : 
    4619           0 :       bathymetry = 0._dbl_kind
    4620           0 :       do iblk = 1, nblocks
    4621           0 :          do j = 1, ny_block
    4622           0 :          do i = 1, nx_block
    4623           0 :             k = nint(kmt(i,j,iblk))
    4624           0 :             if (k > nlevel) call abort_ice(subname//' kmt gt nlevel error')
    4625           0 :             if (k > 0) bathymetry(i,j,iblk) = depth(k)
    4626             :          enddo
    4627             :          enddo
    4628             :       enddo
    4629             : 
    4630             :       ! For consistency, set thickness_ocn_layer1 in Icepack if 'calc_dragio' is active
    4631           0 :       call icepack_query_parameters(calc_dragio_out=calc_dragio)
    4632           0 :       if (calc_dragio) then
    4633           0 :          call icepack_init_parameters(thickness_ocn_layer1_in=thick(1))
    4634             :       endif
    4635           0 :       call icepack_warnings_flush(nu_diag)
    4636           0 :       if (icepack_warnings_aborted()) call abort_ice(error_message=subname, &
    4637           0 :          file=__FILE__, line=__LINE__)
    4638             : 
    4639           0 :       deallocate(depth,thick)
    4640             : 
    4641           0 :       end subroutine get_bathymetry_popfile
    4642             : 
    4643             : !=======================================================================
    4644             : 
    4645             : ! Read bathymetry data for seabed stress calculation (grounding scheme for
    4646             : ! landfast ice) in CICE stand-alone mode. When CICE is in coupled mode
    4647             : ! (e.g. CICE-NEMO), hwater should be uptated at each time level so that
    4648             : ! it varies with ocean dynamics.
    4649             : !
    4650             : ! author: Fred Dupont, CMC
    4651             : 
    4652           0 :       subroutine read_seabedstress_bathy
    4653             : 
    4654             :       ! use module
    4655             :       use ice_read_write
    4656             :       use ice_constants, only: field_loc_center, field_type_scalar
    4657             : 
    4658             :       ! local variables
    4659             :       integer (kind=int_kind) :: &
    4660             :          fid_init        ! file id for netCDF init file
    4661             : 
    4662             :       character (char_len_long) :: &        ! input data file names
    4663             :          fieldname
    4664             : 
    4665             :       logical (kind=log_kind) :: diag=.true.
    4666             : 
    4667             :       character(len=*), parameter :: subname = '(read_seabedstress_bathy)'
    4668             : 
    4669           0 :       if (my_task == master_task) then
    4670           0 :           write (nu_diag,*) ' '
    4671           0 :           write (nu_diag,*) 'Bathymetry file: ', trim(bathymetry_file)
    4672           0 :           call icepack_warnings_flush(nu_diag)
    4673             :       endif
    4674             : 
    4675           0 :       call ice_open_nc(bathymetry_file,fid_init)
    4676             : 
    4677           0 :       fieldname='Bathymetry'
    4678             : 
    4679           0 :       if (my_task == master_task) then
    4680           0 :          write(nu_diag,*) 'reading ',TRIM(fieldname)
    4681           0 :          call icepack_warnings_flush(nu_diag)
    4682             :       endif
    4683             :       call ice_read_nc(fid_init,1,fieldname,bathymetry,diag, &
    4684             :                     field_loc=field_loc_center, &   ! LCOV_EXCL_LINE
    4685           0 :                     field_type=field_type_scalar)
    4686             : 
    4687           0 :       call ice_close_nc(fid_init)
    4688             : 
    4689           0 :       if (my_task == master_task) then
    4690           0 :          write(nu_diag,*) 'closing file ',TRIM(bathymetry_file)
    4691           0 :          call icepack_warnings_flush(nu_diag)
    4692             :       endif
    4693             : 
    4694           0 :       end subroutine read_seabedstress_bathy
    4695             : 
    4696             : !=======================================================================
    4697             : 
    4698             :       end module ice_grid
    4699             : 
    4700             : !=======================================================================

Generated by: LCOV version 1.14-6-g40580cd