From 1cc4372f944a7e726f6db94e239c8aaafc886d54 Mon Sep 17 00:00:00 2001 From: apcraig Date: Fri, 29 Oct 2021 18:35:19 -0600 Subject: [PATCH 01/17] initial implementation of N+E LON/LAT variables --- cicecore/cicedynB/infrastructure/ice_grid.F90 | 175 ++++++++++++++++-- 1 file changed, 162 insertions(+), 13 deletions(-) diff --git a/cicecore/cicedynB/infrastructure/ice_grid.F90 b/cicecore/cicedynB/infrastructure/ice_grid.F90 index 18dbaaefe..04b1fe9b9 100644 --- a/cicecore/cicedynB/infrastructure/ice_grid.F90 +++ b/cicecore/cicedynB/infrastructure/ice_grid.F90 @@ -14,6 +14,12 @@ ! 2006: Converted to free source form (F90) by Elizabeth Hunke ! 2007: Option to read from netcdf files (A. Keen, Met Office) ! Grid reading routines reworked by E. Hunke for boundary values +! 2021: Add N (center of north face) and E (center of east face) grids +! to support CD solvers. Defining T at center of cells, U at +! NE corner, N at center of top face, E at center of right face. +! All cells are quadrilaterals with NE, E, and N associated with +! directions relative to logical grid. E is increasing i (x) and +! N is increasing j (y) direction. module ice_grid @@ -68,10 +74,14 @@ module ice_grid tinyarea,& ! puny*tarea tarean , & ! area of NH T-cells tareas , & ! area of SH T-cells - ULON , & ! longitude of velocity pts (radians) - ULAT , & ! latitude of velocity pts (radians) - TLON , & ! longitude of temp pts (radians) - TLAT , & ! latitude of temp pts (radians) + ULON , & ! longitude of velocity pts, NE corner of T pts (radians) + ULAT , & ! latitude of velocity pts, NE corner of T pts (radians) + TLON , & ! longitude of temp (T) pts (radians) + TLAT , & ! latitude of temp (T) pts (radians) + NLON , & ! longitude of center of north face of T pts (radians) + NLAT , & ! latitude of center of north face of T pts (radians) + ELON , & ! longitude of center of east face of T pts (radians) + ELAT , & ! latitude of center of east face of T pts (radians) ANGLE , & ! for conversions between POP grid and lat/lon ANGLET , & ! ANGLE converted to T-cells bathymetry , & ! ocean depth, for grounding keels and bergs (m) @@ -146,7 +156,6 @@ module ice_grid logical (kind=log_kind), private :: & l_readCenter ! If anglet exist in grid file read it otherwise calculate it - !======================================================================= contains @@ -175,10 +184,14 @@ subroutine alloc_grid tinyarea (nx_block,ny_block,max_blocks), & ! puny*tarea tarean (nx_block,ny_block,max_blocks), & ! area of NH T-cells tareas (nx_block,ny_block,max_blocks), & ! area of SH T-cells - ULON (nx_block,ny_block,max_blocks), & ! longitude of velocity pts (radians) - ULAT (nx_block,ny_block,max_blocks), & ! latitude of velocity pts (radians) - TLON (nx_block,ny_block,max_blocks), & ! longitude of temp pts (radians) - TLAT (nx_block,ny_block,max_blocks), & ! latitude of temp pts (radians) + ULON (nx_block,ny_block,max_blocks), & ! longitude of U pts, NE corner (radians) + ULAT (nx_block,ny_block,max_blocks), & ! latitude of U pts, NE corner (radians) + TLON (nx_block,ny_block,max_blocks), & ! longitude of T pts (radians) + TLAT (nx_block,ny_block,max_blocks), & ! latitude of T pts (radians) + NLON (nx_block,ny_block,max_blocks), & ! longitude of N pts, N face (radians) + NLAT (nx_block,ny_block,max_blocks), & ! latitude of N pts, N face (radians) + ELON (nx_block,ny_block,max_blocks), & ! longitude of E pts, E face (radians) + ELAT (nx_block,ny_block,max_blocks), & ! latitude of E pts, E face (radians) ANGLE (nx_block,ny_block,max_blocks), & ! for conversions between POP grid and lat/lon ANGLET (nx_block,ny_block,max_blocks), & ! ANGLE converted to T-cells bathymetry(nx_block,ny_block,max_blocks),& ! ocean depth, for grounding keels and bergs (m) @@ -1158,6 +1171,10 @@ subroutine latlongrid endif endif ULON (i,j,iblk) = c0 + NLON (i,j,iblk) = c0 + NLAT (i,j,iblk) = c0 + ELON (i,j,iblk) = c0 + ELAT (i,j,iblk) = c0 ANGLE (i,j,iblk) = c0 ANGLET(i,j,iblk) = c0 @@ -1749,8 +1766,9 @@ end subroutine makemask subroutine Tlatlon - use ice_constants, only: c0, c1, c2, c4, & - field_loc_center, field_type_scalar + use ice_constants, only: c0, c1, c1p5, c2, c4, p5, & + field_loc_center, field_loc_Nface, field_loc_Eface, & + field_type_scalar integer (kind=int_kind) :: & i, j, iblk , & ! horizontal indices @@ -1772,6 +1790,10 @@ subroutine Tlatlon TLAT(:,:,:) = c0 TLON(:,:,:) = c0 + NLAT(:,:,:) = c0 + NLON(:,:,:) = c0 + ELAT(:,:,:) = c0 + ELON(:,:,:) = c0 !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block, & !$OMP x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4, & @@ -1806,6 +1828,10 @@ subroutine Tlatlon y4 = sin(ULON(i,j,iblk))*z4 z4 = sin(ULAT(i,j,iblk)) + ! --------- + ! TLON/TLAT 4 pt computation (pts 1, 2, 3, 4) + ! --------- + tx = (x1+x2+x3+x4)/c4 ty = (y1+y2+y3+y4)/c4 tz = (z1+z2+z3+z4)/c4 @@ -1819,11 +1845,90 @@ subroutine Tlatlon ! TLAT in radians North TLAT(i,j,iblk) = asin(tz) + +! these two loops should be merged to save cos/sin calculations, +! but atan2 is not bit-for-bit. This suggests the result for atan2 depends on +! the prior atan2 call ??? not sure what's going on. +#if (1 == 1) + enddo ! i + enddo ! j + enddo ! iblk + !$OMP END PARALLEL DO + + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block, & + !$OMP x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4, & + !$OMP tx,ty,tz,da) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + + do j = jlo, jhi + do i = ilo, ihi + + z1 = cos(ULAT(i-1,j-1,iblk)) + x1 = cos(ULON(i-1,j-1,iblk))*z1 + y1 = sin(ULON(i-1,j-1,iblk))*z1 + z1 = sin(ULAT(i-1,j-1,iblk)) + + z2 = cos(ULAT(i,j-1,iblk)) + x2 = cos(ULON(i,j-1,iblk))*z2 + y2 = sin(ULON(i,j-1,iblk))*z2 + z2 = sin(ULAT(i,j-1,iblk)) + + z3 = cos(ULAT(i-1,j,iblk)) + x3 = cos(ULON(i-1,j,iblk))*z3 + y3 = sin(ULON(i-1,j,iblk))*z3 + z3 = sin(ULAT(i-1,j,iblk)) + + z4 = cos(ULAT(i,j,iblk)) + x4 = cos(ULON(i,j,iblk))*z4 + y4 = sin(ULON(i,j,iblk))*z4 + z4 = sin(ULAT(i,j,iblk)) +#endif + ! --------- + ! NLON/NLAT 2 pt computation (pts 3, 4) + ! --------- + + tx = (x3+x4)/c2 + ty = (y3+y4)/c2 + tz = (z3+z4)/c2 + da = sqrt(tx**2+ty**2+tz**2) + + tz = tz/da + + ! NLON in radians East + NLON(i,j,iblk) = c0 + if (tx /= c0 .or. ty /= c0) NLON(i,j,iblk) = atan2(ty,tx) + + ! NLAT in radians North + NLAT(i,j,iblk) = asin(tz) + + ! --------- + ! ELON/ELAT 2 pt computation (pts 2, 4) + ! --------- + + tx = (x2+x4)/c2 + ty = (y2+y4)/c2 + tz = (z2+z4)/c2 + da = sqrt(tx**2+ty**2+tz**2) + + tz = tz/da + + ! ELON in radians East + ELON(i,j,iblk) = c0 + if (tx /= c0 .or. ty /= c0) ELON(i,j,iblk) = atan2(ty,tx) + + ! ELAT in radians North + ELAT(i,j,iblk) = asin(tz) enddo ! i enddo ! j enddo ! iblk !$OMP END PARALLEL DO + if (trim(grid_type) == 'regional') then ! for W boundary extrapolate from interior !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) @@ -1841,6 +1946,10 @@ subroutine Tlatlon TLON(i+2,j,iblk) TLAT(i,j,iblk) = c2*TLAT(i+1,j,iblk) - & TLAT(i+2,j,iblk) + NLON(i,j,iblk) = c1p5*TLON(i+1,j,iblk) - & + p5*TLON(i+2,j,iblk) + NLAT(i,j,iblk) = c1p5*TLAT(i+1,j,iblk) - & + p5*TLAT(i+2,j,iblk) enddo endif enddo @@ -1854,10 +1963,30 @@ subroutine Tlatlon call ice_HaloUpdate (TLAT, halo_info, & field_loc_center, field_type_scalar, & fillValue=c1) + call ice_HaloUpdate (NLON, halo_info, & + field_loc_Nface, field_type_scalar, & + fillValue=c1) + call ice_HaloUpdate (NLAT, halo_info, & + field_loc_Nface, field_type_scalar, & + fillValue=c1) + call ice_HaloUpdate (ELON, halo_info, & + field_loc_Eface, field_type_scalar, & + fillValue=c1) + call ice_HaloUpdate (ELAT, halo_info, & + field_loc_Eface, field_type_scalar, & + fillValue=c1) call ice_HaloExtrapolate(TLON, distrb_info, & ew_boundary_type, ns_boundary_type) call ice_HaloExtrapolate(TLAT, distrb_info, & ew_boundary_type, ns_boundary_type) + call ice_HaloExtrapolate(NLON, distrb_info, & + ew_boundary_type, ns_boundary_type) + call ice_HaloExtrapolate(NLAT, distrb_info, & + ew_boundary_type, ns_boundary_type) + call ice_HaloExtrapolate(ELON, distrb_info, & + ew_boundary_type, ns_boundary_type) + call ice_HaloExtrapolate(ELAT, distrb_info, & + ew_boundary_type, ns_boundary_type) call ice_timer_stop(timer_bound) x1 = global_minval(TLON, distrb_info, tmask) @@ -1872,14 +2001,34 @@ subroutine Tlatlon if (my_task==master_task) then write(nu_diag,*) ' ' - if (nx_block > 5+2*nghost .and. ny_block > 5+2*nghost) then +! if (nx_block > 5+2*nghost .and. ny_block > 5+2*nghost) then write(nu_diag,*) 'min/max ULON:', y1*rad_to_deg, y2*rad_to_deg write(nu_diag,*) 'min/max ULAT:', y3*rad_to_deg, y4*rad_to_deg - endif +! endif write(nu_diag,*) 'min/max TLON:', x1*rad_to_deg, x2*rad_to_deg write(nu_diag,*) 'min/max TLAT:', x3*rad_to_deg, x4*rad_to_deg endif ! my_task + x1 = global_minval(NLON, distrb_info, tmask) + x2 = global_maxval(NLON, distrb_info, tmask) + x3 = global_minval(NLAT, distrb_info, tmask) + x4 = global_maxval(NLAT, distrb_info, tmask) + + y1 = global_minval(ELON, distrb_info, umask) + y2 = global_maxval(ELON, distrb_info, umask) + y3 = global_minval(ELAT, distrb_info, umask) + y4 = global_maxval(ELAT, distrb_info, umask) + + if (my_task==master_task) then + write(nu_diag,*) ' ' +! if (nx_block > 5+2*nghost .and. ny_block > 5+2*nghost) then + write(nu_diag,*) 'min/max NLON:', x1*rad_to_deg, x2*rad_to_deg + write(nu_diag,*) 'min/max NLAT:', x3*rad_to_deg, x4*rad_to_deg + write(nu_diag,*) 'min/max ELON:', y1*rad_to_deg, y2*rad_to_deg + write(nu_diag,*) 'min/max ELAT:', y3*rad_to_deg, y4*rad_to_deg +! endif + endif ! my_task + end subroutine Tlatlon !======================================================================= From 7f738900f94fcbf67bca48bf555a89ff747a91cb Mon Sep 17 00:00:00 2001 From: apcraig Date: Sat, 30 Oct 2021 20:20:49 -0600 Subject: [PATCH 02/17] add dx,dy,area,mask for N and E and write to history files --- cicecore/cicedynB/analysis/ice_history.F90 | 18 + .../cicedynB/analysis/ice_history_shared.F90 | 81 ++- cicecore/cicedynB/infrastructure/ice_grid.F90 | 532 ++++++++++++++++-- .../io/io_netcdf/ice_history_write.F90 | 346 +++++++----- 4 files changed, 764 insertions(+), 213 deletions(-) diff --git a/cicecore/cicedynB/analysis/ice_history.F90 b/cicecore/cicedynB/analysis/ice_history.F90 index 4b295b54d..a2806b429 100644 --- a/cicecore/cicedynB/analysis/ice_history.F90 +++ b/cicecore/cicedynB/analysis/ice_history.F90 @@ -290,13 +290,22 @@ subroutine init_hist (dt) if (tr_fsd) f_NFSD = .true. call broadcast_scalar (f_tmask, master_task) + call broadcast_scalar (f_umask, master_task) + call broadcast_scalar (f_nmask, master_task) + call broadcast_scalar (f_emask, master_task) call broadcast_scalar (f_blkmask, master_task) call broadcast_scalar (f_tarea, master_task) call broadcast_scalar (f_uarea, master_task) + call broadcast_scalar (f_narea, master_task) + call broadcast_scalar (f_earea, master_task) call broadcast_scalar (f_dxt, master_task) call broadcast_scalar (f_dyt, master_task) call broadcast_scalar (f_dxu, master_task) call broadcast_scalar (f_dyu, master_task) + call broadcast_scalar (f_dxn, master_task) + call broadcast_scalar (f_dyn, master_task) + call broadcast_scalar (f_dxe, master_task) + call broadcast_scalar (f_dye, master_task) call broadcast_scalar (f_HTN, master_task) call broadcast_scalar (f_HTE, master_task) call broadcast_scalar (f_ANGLE, master_task) @@ -1592,13 +1601,22 @@ subroutine init_hist (dt) igrd=.true. igrd(n_tmask ) = f_tmask + igrd(n_umask ) = f_umask + igrd(n_nmask ) = f_nmask + igrd(n_emask ) = f_emask igrd(n_blkmask ) = f_blkmask igrd(n_tarea ) = f_tarea igrd(n_uarea ) = f_uarea + igrd(n_narea ) = f_narea + igrd(n_earea ) = f_earea igrd(n_dxt ) = f_dxt igrd(n_dyt ) = f_dyt igrd(n_dxu ) = f_dxu igrd(n_dyu ) = f_dyu + igrd(n_dxn ) = f_dxn + igrd(n_dyn ) = f_dyn + igrd(n_dxe ) = f_dxe + igrd(n_dye ) = f_dye igrd(n_HTN ) = f_HTN igrd(n_HTE ) = f_HTE igrd(n_ANGLE ) = f_ANGLE diff --git a/cicecore/cicedynB/analysis/ice_history_shared.F90 b/cicecore/cicedynB/analysis/ice_history_shared.F90 index 9b58deeec..1c8823b62 100644 --- a/cicecore/cicedynB/analysis/ice_history_shared.F90 +++ b/cicecore/cicedynB/analysis/ice_history_shared.F90 @@ -120,9 +120,9 @@ module ice_history_shared avail_hist_fields(max_avail_hist_fields) integer (kind=int_kind), parameter, public :: & - nvar = 12 , & ! number of grid fields that can be written + nvar_grd = 21 , & ! number of grid fields that can be written ! excluding grid vertices - nvarz = 6 ! number of category/vertical grid fields written + nvar_grdz = 6 ! number of category/vertical grid fields written integer (kind=int_kind), public :: & ncat_hist , & ! number of thickness categories written <= ncat @@ -152,32 +152,52 @@ module ice_history_shared avgct(max_nstrm) ! average sample counter logical (kind=log_kind), public :: & - igrd (nvar), & ! true if grid field is written to output file - igrdz(nvarz) ! true if category/vertical grid field is written + igrd (nvar_grd), & ! true if grid field is written to output file + igrdz(nvar_grdz) ! true if category/vertical grid field is written character (len=25), public, parameter :: & tcstr = 'area: tarea' , & ! vcellmeas for T cell quantities ucstr = 'area: uarea' , & ! vcellmeas for U cell quantities + ncstr = 'area: narea' , & ! vcellmeas for N cell quantities + ecstr = 'area: earea' , & ! vcellmeas for E cell quantities tstr2D = 'TLON TLAT time' , & ! vcoord for T cell quantities, 2D ustr2D = 'ULON ULAT time' , & ! vcoord for U cell quantities, 2D + nstr2D = 'NLON NLAT time' , & ! vcoord for N cell quantities, 2D + estr2D = 'ELON ELAT time' , & ! vcoord for E cell quantities, 2D tstr3Dz = 'TLON TLAT VGRDi time',& ! vcoord for T cell quantities, 3D ustr3Dz = 'ULON ULAT VGRDi time',& ! vcoord for U cell quantities, 3D + nstr3Dz = 'NLON NLAT VGRDi time',& ! vcoord for N cell quantities, 3D + estr3Dz = 'ELON ELAT VGRDi time',& ! vcoord for E cell quantities, 3D tstr3Dc = 'TLON TLAT NCAT time',& ! vcoord for T cell quantities, 3D ustr3Dc = 'ULON ULAT NCAT time',& ! vcoord for U cell quantities, 3D + nstr3Dc = 'NLON NLAT NCAT time',& ! vcoord for N cell quantities, 3D + estr3Dc = 'ELON ELAT NCAT time',& ! vcoord for E cell quantities, 3D tstr3Db = 'TLON TLAT VGRDb time',& ! vcoord for T cell quantities, 3D ustr3Db = 'ULON ULAT VGRDb time',& ! vcoord for U cell quantities, 3D + nstr3Db = 'NLON NLAT VGRDb time',& ! vcoord for N cell quantities, 3D + estr3Db = 'ELON ELAT VGRDb time',& ! vcoord for E cell quantities, 3D tstr3Da = 'TLON TLAT VGRDa time',& ! vcoord for T cell quantities, 3D ustr3Da = 'ULON ULAT VGRDa time',& ! vcoord for U cell quantities, 3D + nstr3Da = 'NLON NLAT VGRDa time',& ! vcoord for N cell quantities, 3D + estr3Da = 'ELON ELAT VGRDa time',& ! vcoord for E cell quantities, 3D tstr3Df = 'TLON TLAT NFSD time',& ! vcoord for T cell quantities, 3D ustr3Df = 'ULON ULAT NFSD time',& ! vcoord for U cell quantities, 3D + nstr3Df = 'NLON NLAT NFSD time',& ! vcoord for N cell quantities, 3D + estr3Df = 'ELON ELAT NFSD time',& ! vcoord for E cell quantities, 3D !ferret tstr4Di = 'TLON TLAT VGRDi NCAT', & ! vcoord for T cell, 4D, ice ustr4Di = 'ULON ULAT VGRDi NCAT', & ! vcoord for U cell, 4D, ice + nstr4Di = 'NLON NLAT VGRDi NCAT', & ! vcoord for N cell, 4D, ice + estr4Di = 'ELON ELAT VGRDi NCAT', & ! vcoord for E cell, 4D, ice tstr4Ds = 'TLON TLAT VGRDs NCAT', & ! vcoord for T cell, 4D, snow ustr4Ds = 'ULON ULAT VGRDs NCAT', & ! vcoord for U cell, 4D, snow + nstr4Ds = 'NLON NLAT VGRDs NCAT', & ! vcoord for N cell, 4D, snow + estr4Ds = 'ELON ELAT VGRDs NCAT', & ! vcoord for E cell, 4D, snow tstr4Df = 'TLON TLAT NFSD NCAT', & ! vcoord for T cell, 4D, fsd - ustr4Df = 'ULON ULAT NFSD NCAT' ! vcoord for U cell, 4D, fsd + ustr4Df = 'ULON ULAT NFSD NCAT', & ! vcoord for U cell, 4D, fsd + nstr4Df = 'NLON NLAT NFSD NCAT', & ! vcoord for N cell, 4D, fsd + estr4Df = 'ELON ELAT NFSD NCAT' ! vcoord for E cell, 4D, fsd !ferret ! tstr4Di = 'TLON TLAT VGRDi NCAT time', & ! ferret can not handle time ! ustr4Di = 'ULON ULAT VGRDi NCAT time', & ! index on 4D variables. @@ -193,10 +213,15 @@ module ice_history_shared !--------------------------------------------------------------- logical (kind=log_kind), public :: & - f_tmask = .true., f_blkmask = .true., & + f_tmask = .true., f_umask = .true., & + f_nmask = .true., f_emask = .true., & + f_blkmask = .true., & f_tarea = .true., f_uarea = .true., & + f_narea = .true., f_earea = .true., & f_dxt = .true., f_dyt = .true., & f_dxu = .true., f_dyu = .true., & + f_dxn = .true., f_dyn = .true., & + f_dxe = .true., f_dye = .true., & f_HTN = .true., f_HTE = .true., & f_ANGLE = .true., f_ANGLET = .true., & f_bounds = .true., f_NCAT = .true., & @@ -339,10 +364,15 @@ module ice_history_shared !--------------------------------------------------------------- namelist / icefields_nml / & - f_tmask , f_blkmask , & + f_tmask , f_umask , & + f_nmask , f_emask , & + f_blkmask , & f_tarea , f_uarea , & + f_narea , f_earea , & f_dxt , f_dyt , & f_dxu , f_dyu , & + f_dxn , f_dyn , & + f_dxe , f_dye , & f_HTN , f_HTE , & f_ANGLE , f_ANGLET , & f_bounds , f_NCAT , & @@ -484,17 +514,26 @@ module ice_history_shared integer (kind=int_kind), parameter, public :: & n_tmask = 1, & - n_blkmask = 2, & - n_tarea = 3, & - n_uarea = 4, & - n_dxt = 5, & - n_dyt = 6, & - n_dxu = 7, & - n_dyu = 8, & - n_HTN = 9, & - n_HTE = 10, & - n_ANGLE = 11, & - n_ANGLET = 12, & + n_umask = 2, & + n_nmask = 3, & + n_emask = 4, & + n_blkmask = 5, & + n_tarea = 6, & + n_uarea = 7, & + n_narea = 8, & + n_earea = 9, & + n_dxt = 10, & + n_dyt = 11, & + n_dxu = 12, & + n_dyu = 13, & + n_dxn = 14, & + n_dyn = 15, & + n_dxe = 16, & + n_dye = 17, & + n_HTN = 18, & + n_HTE = 19, & + n_ANGLE = 20, & + n_ANGLET = 21, & n_NCAT = 1, & n_VGRDi = 2, & @@ -506,7 +545,11 @@ module ice_history_shared n_lont_bnds = 1, & n_latt_bnds = 2, & n_lonu_bnds = 3, & - n_latu_bnds = 4 + n_latu_bnds = 4, & + n_lonn_bnds = 5, & + n_latn_bnds = 6, & + n_lone_bnds = 7, & + n_late_bnds = 8 integer (kind=int_kind), dimension(max_nstrm), public :: & ! n_example , & diff --git a/cicecore/cicedynB/infrastructure/ice_grid.F90 b/cicecore/cicedynB/infrastructure/ice_grid.F90 index 04b1fe9b9..0b6fba962 100644 --- a/cicecore/cicedynB/infrastructure/ice_grid.F90 +++ b/cicecore/cicedynB/infrastructure/ice_grid.F90 @@ -65,10 +65,16 @@ module ice_grid dyt , & ! height of T-cell through the middle (m) dxu , & ! width of U-cell through the middle (m) dyu , & ! height of U-cell through the middle (m) + dxn , & ! width of N-cell through the middle (m) + dyn , & ! height of N-cell through the middle (m) + dxe , & ! width of E-cell through the middle (m) + dye , & ! height of E-cell through the middle (m) HTE , & ! length of eastern edge of T-cell (m) HTN , & ! length of northern edge of T-cell (m) tarea , & ! area of T-cell (m^2) uarea , & ! area of U-cell (m^2) + narea , & ! area of N-cell (m^2) + earea , & ! area of E-cell (m^2) tarear , & ! 1/tarea uarear , & ! 1/uarea tinyarea,& ! puny*tarea @@ -110,7 +116,11 @@ module ice_grid lont_bounds, & ! longitude of gridbox corners for T point latt_bounds, & ! latitude of gridbox corners for T point lonu_bounds, & ! longitude of gridbox corners for U point - latu_bounds ! latitude of gridbox corners for U point + latu_bounds, & ! latitude of gridbox corners for U point + lonn_bounds, & ! longitude of gridbox corners for N point + latn_bounds, & ! latitude of gridbox corners for N point + lone_bounds, & ! longitude of gridbox corners for E point + late_bounds ! latitude of gridbox corners for E point ! geometric quantities used for remapping transport real (kind=dbl_kind), dimension (:,:,:), allocatable, public :: & @@ -137,6 +147,8 @@ module ice_grid hm , & ! land/boundary mask, thickness (T-cell) bm , & ! task/block id uvm , & ! land/boundary mask, velocity (U-cell) + npm , & ! land/boundary mask (N-cell) + epm , & ! land/boundary mask (E-cell) kmt ! ocean topography mask for bathymetry (T-cell) logical (kind=log_kind), public :: & @@ -147,6 +159,8 @@ module ice_grid dimension (:,:,:), allocatable, public :: & tmask , & ! land/boundary mask, thickness (T-cell) umask , & ! land/boundary mask, velocity (U-cell) + nmask , & ! land/boundary mask, (N-cell) + emask , & ! land/boundary mask, (E-cell) lmask_n, & ! northern hemisphere mask lmask_s ! southern hemisphere mask @@ -175,10 +189,16 @@ subroutine alloc_grid dyt (nx_block,ny_block,max_blocks), & ! height of T-cell through the middle (m) dxu (nx_block,ny_block,max_blocks), & ! width of U-cell through the middle (m) dyu (nx_block,ny_block,max_blocks), & ! height of U-cell through the middle (m) + dxn (nx_block,ny_block,max_blocks), & ! width of N-cell through the middle (m) + dyn (nx_block,ny_block,max_blocks), & ! height of N-cell through the middle (m) + dxe (nx_block,ny_block,max_blocks), & ! width of E-cell through the middle (m) + dye (nx_block,ny_block,max_blocks), & ! height of E-cell through the middle (m) HTE (nx_block,ny_block,max_blocks), & ! length of eastern edge of T-cell (m) HTN (nx_block,ny_block,max_blocks), & ! length of northern edge of T-cell (m) tarea (nx_block,ny_block,max_blocks), & ! area of T-cell (m^2) uarea (nx_block,ny_block,max_blocks), & ! area of U-cell (m^2) + narea (nx_block,ny_block,max_blocks), & ! area of N-cell (m^2) + earea (nx_block,ny_block,max_blocks), & ! area of E-cell (m^2) tarear (nx_block,ny_block,max_blocks), & ! 1/tarea uarear (nx_block,ny_block,max_blocks), & ! 1/uarea tinyarea (nx_block,ny_block,max_blocks), & ! puny*tarea @@ -209,16 +229,24 @@ subroutine alloc_grid hm (nx_block,ny_block,max_blocks), & ! land/boundary mask, thickness (T-cell) bm (nx_block,ny_block,max_blocks), & ! task/block id uvm (nx_block,ny_block,max_blocks), & ! land/boundary mask, velocity (U-cell) + npm (nx_block,ny_block,max_blocks), & ! land/boundary mask (N-cell) + epm (nx_block,ny_block,max_blocks), & ! land/boundary mask (E-cell) kmt (nx_block,ny_block,max_blocks), & ! ocean topography mask for bathymetry (T-cell) tmask (nx_block,ny_block,max_blocks), & ! land/boundary mask, thickness (T-cell) umask (nx_block,ny_block,max_blocks), & ! land/boundary mask, velocity (U-cell) + nmask (nx_block,ny_block,max_blocks), & ! land/boundary mask (N-cell) + emask (nx_block,ny_block,max_blocks), & ! land/boundary mask (E-cell) lmask_n (nx_block,ny_block,max_blocks), & ! northern hemisphere mask lmask_s (nx_block,ny_block,max_blocks), & ! southern hemisphere mask rndex_global(nx_block,ny_block,max_blocks), & ! global index for local subdomain (dbl) lont_bounds(4,nx_block,ny_block,max_blocks), & ! longitude of gridbox corners for T point latt_bounds(4,nx_block,ny_block,max_blocks), & ! latitude of gridbox corners for T point lonu_bounds(4,nx_block,ny_block,max_blocks), & ! longitude of gridbox corners for U point - latu_bounds(4,nx_block,ny_block,max_blocks), & ! latitude of gridbox corners for U point + latu_bounds(4,nx_block,ny_block,max_blocks), & ! latitude of gridbox corners for U point + lonn_bounds(4,nx_block,ny_block,max_blocks), & ! longitude of gridbox corners for N point + latn_bounds(4,nx_block,ny_block,max_blocks), & ! latitude of gridbox corners for N point + lone_bounds(4,nx_block,ny_block,max_blocks), & ! longitude of gridbox corners for E point + late_bounds(4,nx_block,ny_block,max_blocks), & ! latitude of gridbox corners for E point mne (2,2,nx_block,ny_block,max_blocks), & ! matrices used for coordinate transformations in remapping mnw (2,2,nx_block,ny_block,max_blocks), & ! ne = northeast corner, nw = northwest, etc. mse (2,2,nx_block,ny_block,max_blocks), & @@ -368,7 +396,7 @@ subroutine init_grid2 use ice_blocks, only: get_block, block, nx_block, ny_block use ice_constants, only: c0, c1, c2, p5, p25, c1p5, & - field_loc_center, field_loc_NEcorner, & + field_loc_center, field_loc_NEcorner, field_loc_Nface, field_loc_Eface, & field_type_scalar, field_type_vector, field_type_angle use ice_domain_size, only: max_blocks @@ -435,6 +463,9 @@ subroutine init_grid2 do i = ilo, ihi tarea(i,j,iblk) = dxt(i,j,iblk)*dyt(i,j,iblk) uarea(i,j,iblk) = dxu(i,j,iblk)*dyu(i,j,iblk) + narea(i,j,iblk) = dxn(i,j,iblk)*dyn(i,j,iblk) + earea(i,j,iblk) = dxe(i,j,iblk)*dye(i,j,iblk) + if (tarea(i,j,iblk) > c0) then tarear(i,j,iblk) = c1/tarea(i,j,iblk) else @@ -482,6 +513,12 @@ subroutine init_grid2 call ice_HaloUpdate (uarea, halo_info, & field_loc_NEcorner, field_type_scalar, & fillValue=c1) + call ice_HaloUpdate (narea, halo_info, & + field_loc_Nface, field_type_scalar, & + fillValue=c1) + call ice_HaloUpdate (earea, halo_info, & + field_loc_Eface, field_type_scalar, & + fillValue=c1) call ice_HaloUpdate (tarear, halo_info, & field_loc_center, field_type_scalar, & fillValue=c1) @@ -597,6 +634,7 @@ subroutine init_grid2 !---------------------------------------------------------------- call gridbox_corners + call gridbox_edges !----------------------------------------------------------------- ! Compute global index (used for unpacking messages from coupler) @@ -725,10 +763,10 @@ subroutine popgrid !----------------------------------------------------------------- call ice_read_global(nu_grid,3,work_g1,'rda8',.true.) ! HTN - call primary_grid_lengths_HTN(work_g1) ! dxu, dxt + call primary_grid_lengths_HTN(work_g1) ! dxu, dxt, dxn, dxe call ice_read_global(nu_grid,4,work_g1,'rda8',.true.) ! HTE - call primary_grid_lengths_HTE(work_g1) ! dyu, dyt + call primary_grid_lengths_HTE(work_g1) ! dyu, dyt, dyn, dye deallocate(work_g1) @@ -902,10 +940,10 @@ subroutine popgrid_nc fieldname='htn' call ice_read_global_nc(fid_grid,1,fieldname,work_g1,diag) ! HTN - call primary_grid_lengths_HTN(work_g1) ! dxu, dxt + call primary_grid_lengths_HTN(work_g1) ! dxu, dxt, dxn, dxe fieldname='hte' call ice_read_global_nc(fid_grid,1,fieldname,work_g1,diag) ! HTE - call primary_grid_lengths_HTE(work_g1) ! dyu, dyt + call primary_grid_lengths_HTE(work_g1) ! dyu, dyt, dyn, dye deallocate(work_g1) @@ -1184,6 +1222,10 @@ subroutine latlongrid dyt (i,j,iblk) = 1.e36_dbl_kind dxu (i,j,iblk) = 1.e36_dbl_kind dyu (i,j,iblk) = 1.e36_dbl_kind + dxn (i,j,iblk) = 1.e36_dbl_kind + dyn (i,j,iblk) = 1.e36_dbl_kind + dxe (i,j,iblk) = 1.e36_dbl_kind + dye (i,j,iblk) = 1.e36_dbl_kind dxhy (i,j,iblk) = 1.e36_dbl_kind dyhx (i,j,iblk) = 1.e36_dbl_kind cyp (i,j,iblk) = 1.e36_dbl_kind @@ -1295,7 +1337,7 @@ subroutine rectgrid enddo enddo endif - call primary_grid_lengths_HTN(work_g1) ! dxu, dxt + call primary_grid_lengths_HTN(work_g1) ! dxu, dxt, dxn, dxe if (my_task == master_task) then do j = 1, ny_global @@ -1304,7 +1346,7 @@ subroutine rectgrid enddo enddo endif - call primary_grid_lengths_HTE(work_g1) ! dyu, dyt + call primary_grid_lengths_HTE(work_g1) ! dyu, dyt, dyn, dye !----------------------------------------------------------------- ! Construct T-cell land mask @@ -1458,11 +1500,11 @@ subroutine cpomgrid call ice_read_global(nu_grid,3,work_g1, 'rda8',diag) work_g1 = work_g1 * m_to_cm - call primary_grid_lengths_HTN(work_g1) ! dxu, dxt + call primary_grid_lengths_HTN(work_g1) ! dxu, dxt, dxn, dxe call ice_read_global(nu_grid,4,work_g1, 'rda8',diag) work_g1 = work_g1 * m_to_cm - call primary_grid_lengths_HTE(work_g1) ! dyu, dyt + call primary_grid_lengths_HTE(work_g1) ! dyu, dyt, dyn, dye call ice_read_global(nu_grid,7,work_g1,'rda8',diag) call scatter_global(ANGLE, work_g1, master_task, distrb_info, & @@ -1494,7 +1536,7 @@ end subroutine cpomgrid subroutine primary_grid_lengths_HTN(work_g) - use ice_constants, only: p5, c2, cm_to_m, & + use ice_constants, only: p25, p5, c2, cm_to_m, & field_loc_center, field_loc_NEcorner, & field_loc_Nface, field_type_scalar @@ -1517,20 +1559,22 @@ subroutine primary_grid_lengths_HTN(work_g) allocate(work_g2(1,1)) endif + ! HTN, dxu = average of 2 neighbor HTNs in i + if (my_task == master_task) then - do j = 1, ny_global - do i = 1, nx_global - work_g(i,j) = work_g(i,j) * cm_to_m ! HTN - enddo - enddo - do j = 1, ny_global - do i = 1, nx_global - ! assume cyclic; noncyclic will be handled during scatter - ip1 = i+1 - if (i == nx_global) ip1 = 1 - work_g2(i,j) = p5*(work_g(i,j) + work_g(ip1,j)) ! dxu - enddo - enddo + do j = 1, ny_global + do i = 1, nx_global + work_g(i,j) = work_g(i,j) * cm_to_m ! HTN + enddo + enddo + do j = 1, ny_global + do i = 1, nx_global + ! assume cyclic; noncyclic will be handled during scatter + ip1 = i+1 + if (i == nx_global) ip1 = 1 + work_g2(i,j) = p5*(work_g(i,j) + work_g(ip1,j)) ! dxu + enddo + enddo endif if (pgl_global_ext) then call primary_grid_lengths_global_ext( & @@ -1541,20 +1585,49 @@ subroutine primary_grid_lengths_HTN(work_g) call scatter_global(dxu, work_g2, master_task, distrb_info, & field_loc_NEcorner, field_type_scalar) + ! dxt = average of 2 neighbor HTNs in j + if (my_task == master_task) then - do j = 2, ny_global + do j = 2, ny_global do i = 1, nx_global work_g2(i,j) = p5*(work_g(i,j) + work_g(i,j-1)) ! dxt enddo - enddo - ! extrapolate to obtain dxt along j=1 - do i = 1, nx_global - work_g2(i,1) = c2*work_g(i,2) - work_g(i,3) ! dxt - enddo + enddo + ! extrapolate to obtain dxt along j=1 + do i = 1, nx_global + work_g2(i,1) = c2*work_g(i,2) - work_g(i,3) ! dxt + enddo endif call scatter_global(dxt, work_g2, master_task, distrb_info, & field_loc_center, field_type_scalar) + ! dxn = HTN + + dxn(:,:,:) = HTN(:,:,:) ! dxn + + ! dxe = average of 4 surrounding HTNs + + if (my_task == master_task) then + do j = 2, ny_global + do i = 1, nx_global + ! assume cyclic; noncyclic will be handled during scatter + ip1 = i+1 + if (i == nx_global) ip1 = 1 + work_g2(i,j) = p25*(work_g(i,j)+work_g(ip1,j)+work_g(i,j-1)+work_g(ip1,j-1)) ! dxe + enddo + enddo + ! extrapolate to obtain dxt along j=1 + do i = 1, nx_global + ! assume cyclic; noncyclic will be handled during scatter + ip1 = i+1 + if (i == nx_global) ip1 = 1 + work_g2(i,1) = p5*(c2*work_g(i ,2) - work_g(i ,3) + & + c2*work_g(ip1,2) - work_g(ip1,3)) ! dxe + enddo + endif + call scatter_global(dxe, work_g2, master_task, distrb_info, & + field_loc_center, field_type_scalar) + deallocate(work_g2) end subroutine primary_grid_lengths_HTN @@ -1568,7 +1641,7 @@ end subroutine primary_grid_lengths_HTN subroutine primary_grid_lengths_HTE(work_g) - use ice_constants, only: p5, c2, cm_to_m, & + use ice_constants, only: p25, p5, c2, cm_to_m, & field_loc_center, field_loc_NEcorner, & field_loc_Eface, field_type_scalar @@ -1591,6 +1664,8 @@ subroutine primary_grid_lengths_HTE(work_g) allocate(work_g2(1,1)) endif + ! HTE, dyu = average of 2 neighbor HTE in j + if (my_task == master_task) then do j = 1, ny_global do i = 1, nx_global @@ -1605,8 +1680,7 @@ subroutine primary_grid_lengths_HTE(work_g) ! extrapolate to obtain dyu along j=ny_global if (ny_global > 1) then do i = 1, nx_global - work_g2(i,ny_global) = c2*work_g(i,ny_global-1) & - - work_g(i,ny_global-2) ! dyu + work_g2(i,ny_global) = c2*work_g(i,ny_global-1) - work_g(i,ny_global-2) ! dyu enddo endif endif @@ -1619,19 +1693,50 @@ subroutine primary_grid_lengths_HTE(work_g) call scatter_global(dyu, work_g2, master_task, distrb_info, & field_loc_NEcorner, field_type_scalar) + ! dyt = average of 2 neighbor HTE in i + if (my_task == master_task) then - do j = 1, ny_global - do i = 1, nx_global - ! assume cyclic; noncyclic will be handled during scatter - im1 = i-1 - if (i == 1) im1 = nx_global - work_g2(i,j) = p5*(work_g(i,j) + work_g(im1,j)) ! dyt - enddo - enddo + do j = 1, ny_global + do i = 1, nx_global + ! assume cyclic; noncyclic will be handled during scatter + im1 = i-1 + if (i == 1) im1 = nx_global + work_g2(i,j) = p5*(work_g(i,j) + work_g(im1,j)) ! dyt + enddo + enddo endif call scatter_global(dyt, work_g2, master_task, distrb_info, & field_loc_center, field_type_scalar) + ! dyn = average of 4 neighbor HTEs + + if (my_task == master_task) then + do j = 1, ny_global-1 + do i = 1, nx_global + ! assume cyclic; noncyclic will be handled during scatter + im1 = i-1 + if (i == 1) im1 = nx_global + work_g2(i,j) = p25*(work_g(i,j) + work_g(im1,j) + work_g(i,j+1) + work_g(im1,j+1)) ! dyn + enddo + enddo + ! extrapolate to obtain dyn along j=ny_global + if (ny_global > 1) then + do i = 1, nx_global + ! assume cyclic; noncyclic will be handled during scatter + im1 = i-1 + if (i == 1) im1 = nx_global + work_g2(i,ny_global) = p5*(c2*work_g(i ,ny_global-1) - work_g(i ,ny_global-2) + & + c2*work_g(im1,ny_global-1) - work_g(im1,ny_global-2)) ! dyn + enddo + endif + endif + call scatter_global(dyn, work_g2, master_task, distrb_info, & + field_loc_center, field_type_scalar) + + ! dye = HTE + + dye(:,:,:) = HTE(:,:,:) + deallocate(work_g2) end subroutine primary_grid_lengths_HTE @@ -1639,7 +1744,8 @@ end subroutine primary_grid_lengths_HTE !======================================================================= ! Sets the boundary values for the T cell land mask (hm) and -! makes the logical land masks for T and U cells (tmask, umask). +! makes the logical land masks for T and U cells (tmask, umask) +! and N and E cells (nmask, emask). ! Also creates hemisphere masks (mask-n northern, mask-s southern) ! ! author: Elizabeth C. Hunke, LANL @@ -1647,7 +1753,8 @@ end subroutine primary_grid_lengths_HTE subroutine makemask use ice_constants, only: c0, p5, & - field_loc_center, field_loc_NEcorner, field_type_scalar + field_loc_center, field_loc_NEcorner, field_type_scalar, & + field_loc_Nface, field_loc_Eface integer (kind=int_kind) :: & i, j, iblk, & @@ -1667,7 +1774,7 @@ subroutine makemask file=__FILE__, line=__LINE__) call ice_timer_start(timer_bound) - call ice_HaloUpdate (kmt, halo_info, & + call ice_HaloUpdate (kmt, halo_info, & field_loc_center, field_type_scalar) call ice_HaloUpdate (hm, halo_info, & field_loc_center, field_type_scalar) @@ -1691,6 +1798,8 @@ subroutine makemask do i = ilo, ihi uvm(i,j,iblk) = min (hm(i,j, iblk), hm(i+1,j, iblk), & hm(i,j+1,iblk), hm(i+1,j+1,iblk)) + npm(i,j,iblk) = min (hm(i,j, iblk), hm(i,j+1,iblk)) + epm(i,j,iblk) = min (hm(i,j, iblk), hm(i+1,j,iblk)) bm(i,j,iblk) = my_task + iblk/100.0_dbl_kind enddo enddo @@ -1700,8 +1809,12 @@ subroutine makemask call ice_timer_start(timer_bound) call ice_HaloUpdate (uvm, halo_info, & field_loc_NEcorner, field_type_scalar) - call ice_HaloUpdate (bm, halo_info, & - field_loc_center, field_type_scalar) + call ice_HaloUpdate (npm, halo_info, & + field_loc_Nface, field_type_scalar) + call ice_HaloUpdate (epm, halo_info, & + field_loc_Eface, field_type_scalar) + call ice_HaloUpdate (bm, halo_info, & + field_loc_center, field_type_scalar) call ice_timer_stop(timer_bound) !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) @@ -1715,10 +1828,14 @@ subroutine makemask ! needs to cover halo (no halo update for logicals) tmask(:,:,iblk) = .false. umask(:,:,iblk) = .false. + nmask(:,:,iblk) = .false. + emask(:,:,iblk) = .false. do j = jlo-nghost, jhi+nghost do i = ilo-nghost, ihi+nghost if ( hm(i,j,iblk) > p5) tmask(i,j,iblk) = .true. if (uvm(i,j,iblk) > p5) umask(i,j,iblk) = .true. + if (npm(i,j,iblk) > p5) nmask(i,j,iblk) = .true. + if (epm(i,j,iblk) > p5) emask(i,j,iblk) = .true. enddo enddo @@ -2009,15 +2126,15 @@ subroutine Tlatlon write(nu_diag,*) 'min/max TLAT:', x3*rad_to_deg, x4*rad_to_deg endif ! my_task - x1 = global_minval(NLON, distrb_info, tmask) - x2 = global_maxval(NLON, distrb_info, tmask) - x3 = global_minval(NLAT, distrb_info, tmask) - x4 = global_maxval(NLAT, distrb_info, tmask) + x1 = global_minval(NLON, distrb_info, nmask) + x2 = global_maxval(NLON, distrb_info, nmask) + x3 = global_minval(NLAT, distrb_info, nmask) + x4 = global_maxval(NLAT, distrb_info, nmask) - y1 = global_minval(ELON, distrb_info, umask) - y2 = global_maxval(ELON, distrb_info, umask) - y3 = global_minval(ELAT, distrb_info, umask) - y4 = global_maxval(ELAT, distrb_info, umask) + y1 = global_minval(ELON, distrb_info, emask) + y2 = global_maxval(ELON, distrb_info, emask) + y3 = global_minval(ELAT, distrb_info, emask) + y4 = global_maxval(ELAT, distrb_info, emask) if (my_task==master_task) then write(nu_diag,*) ' ' @@ -2268,12 +2385,12 @@ subroutine gridbox_corners latu_bounds(1,i,j,iblk)=TLAT(i ,j ,iblk)*rad_to_deg latu_bounds(2,i,j,iblk)=TLAT(i+1,j ,iblk)*rad_to_deg latu_bounds(3,i,j,iblk)=TLAT(i+1,j+1,iblk)*rad_to_deg - latu_bounds(4,i,j,iblk)=TLAT(i ,j+1,iblk)*rad_to_deg + latu_bounds(4,i,j,iblk)=TLAT(i ,j+1,iblk)*rad_to_deg lonu_bounds(1,i,j,iblk)=TLON(i ,j ,iblk)*rad_to_deg lonu_bounds(2,i,j,iblk)=TLON(i+1,j ,iblk)*rad_to_deg lonu_bounds(3,i,j,iblk)=TLON(i+1,j+1,iblk)*rad_to_deg - lonu_bounds(4,i,j,iblk)=TLON(i ,j+1,iblk)*rad_to_deg + lonu_bounds(4,i,j,iblk)=TLON(i ,j+1,iblk)*rad_to_deg enddo enddo @@ -2402,6 +2519,307 @@ subroutine gridbox_corners end subroutine gridbox_corners +!======================================================================= +! The following code is used for obtaining the coordinates of the grid +! vertices for CF-compliant netCDF history output. Approximate! +!======================================================================= + +! These fields are only used for netcdf history output, and the +! ghost cell values are not needed. +! NOTE: Extrapolations were used: these fields are approximate! +! + + subroutine gridbox_edges + + use ice_blocks, only: nx_block, ny_block + use ice_constants, only: c0, c2, c360, & + field_loc_NEcorner, field_type_scalar + use ice_domain_size, only: max_blocks + + integer (kind=int_kind) :: & + i,j,iblk,icorner,& ! index counters + ilo,ihi,jlo,jhi ! beginning and end of physical domain + + real (kind=dbl_kind), dimension(:,:), allocatable :: & + work_g2 + + real (kind=dbl_kind), dimension (nx_block,ny_block,max_blocks) :: & + work1 + + real (kind=dbl_kind) :: & + rad_to_deg + + type (block) :: & + this_block ! block information for current block + + character(len=*), parameter :: subname = '(gridbox_edges)' + + call icepack_query_parameters(rad_to_deg_out=rad_to_deg) + call icepack_warnings_flush(nu_diag) + if (icepack_warnings_aborted()) call abort_ice(error_message=subname, & + file=__FILE__, line=__LINE__) + + !------------------------------------------------------------- + ! Get coordinates of grid boxes for each block as follows: + ! for N pt: (1) W edge, (2) E edge, (3) E edge j+1, (4) W edge j+1 + ! for E pt: (1) S edge, (2) S edge i+1, (3) N edge, i+1 (4) N edge + !------------------------------------------------------------- + + latn_bounds(:,:,:,:) = c0 + lonn_bounds(:,:,:,:) = c0 + late_bounds(:,:,:,:) = c0 + lone_bounds(:,:,:,:) = c0 + + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + + do j = jlo, jhi + do i = ilo, ihi + + latn_bounds(1,i,j,iblk)=ELAT(i-1,j ,iblk)*rad_to_deg + latn_bounds(2,i,j,iblk)=ELAT(i ,j ,iblk)*rad_to_deg + latn_bounds(3,i,j,iblk)=ELAT(i ,j+1,iblk)*rad_to_deg + latn_bounds(4,i,j,iblk)=ELAT(i-1,j+1,iblk)*rad_to_deg + + lonn_bounds(1,i,j,iblk)=ELON(i-1,j ,iblk)*rad_to_deg + lonn_bounds(2,i,j,iblk)=ELON(i ,j ,iblk)*rad_to_deg + lonn_bounds(3,i,j,iblk)=ELON(i ,j+1,iblk)*rad_to_deg + lonn_bounds(4,i,j,iblk)=ELON(i-1,j+1,iblk)*rad_to_deg + + late_bounds(1,i,j,iblk)=NLAT(i ,j-1,iblk)*rad_to_deg + late_bounds(2,i,j,iblk)=NLAT(i+1,j-1,iblk)*rad_to_deg + late_bounds(3,i,j,iblk)=NLAT(i+1,j ,iblk)*rad_to_deg + late_bounds(4,i,j,iblk)=NLAT(i ,j ,iblk)*rad_to_deg + + lone_bounds(1,i,j,iblk)=NLON(i ,j-1,iblk)*rad_to_deg + lone_bounds(2,i,j,iblk)=NLON(i+1,j-1,iblk)*rad_to_deg + lone_bounds(3,i,j,iblk)=NLON(i+1,j ,iblk)*rad_to_deg + lone_bounds(4,i,j,iblk)=NLON(i ,j ,iblk)*rad_to_deg + + enddo + enddo + enddo + !$OMP END PARALLEL DO + + !---------------------------------------------------------------- + ! extrapolate on global grid to get edge values + !---------------------------------------------------------------- + + if (my_task == master_task) then + allocate(work_g2(nx_global,ny_global)) + else + allocate(work_g2(1,1)) + endif + + ! latn_bounds + + work1(:,:,:) = latn_bounds(1,:,:,:) + call gather_global(work_g2, work1, master_task, distrb_info) + if (my_task == master_task) then + do j = 1, ny_global + work_g2(1,j) = c2*work_g2(2,j) & + - work_g2(3,j) + enddo + endif + call scatter_global(work1, work_g2, & + master_task, distrb_info, & + field_loc_NEcorner, field_type_scalar) + latn_bounds(1,:,:,:) = work1(:,:,:) + + work1(:,:,:) = latn_bounds(3,:,:,:) + call gather_global(work_g2, work1, master_task, distrb_info) + if (my_task == master_task) then + do i = 1, nx_global + work_g2(i,ny_global) = c2*work_g2(i,ny_global-1) & + - work_g2(i,ny_global-2) + enddo + endif + call scatter_global(work1, work_g2, & + master_task, distrb_info, & + field_loc_NEcorner, field_type_scalar) + latn_bounds(3,:,:,:) = work1(:,:,:) + + work1(:,:,:) = latn_bounds(4,:,:,:) + call gather_global(work_g2, work1, master_task, distrb_info) + if (my_task == master_task) then + do i = 1, nx_global + work_g2(i,ny_global) = c2*work_g2(i,ny_global-1) & + - work_g2(i,ny_global-2) + enddo + do j = 1, ny_global + work_g2(1,j) = c2*work_g2(2,j) & + - work_g2(3,j) + enddo + endif + call scatter_global(work1, work_g2, & + master_task, distrb_info, & + field_loc_NEcorner, field_type_scalar) + latn_bounds(4,:,:,:) = work1(:,:,:) + + ! lonn_bounds + + work1(:,:,:) = lonn_bounds(1,:,:,:) + call gather_global(work_g2, work1, master_task, distrb_info) + if (my_task == master_task) then + do j = 1, ny_global + work_g2(1,j) = c2*work_g2(2,j) & + - work_g2(3,j) + enddo + endif + call scatter_global(work1, work_g2, & + master_task, distrb_info, & + field_loc_NEcorner, field_type_scalar) + lonn_bounds(1,:,:,:) = work1(:,:,:) + + work1(:,:,:) = lonn_bounds(3,:,:,:) + call gather_global(work_g2, work1, master_task, distrb_info) + if (my_task == master_task) then + do i = 1, nx_global + work_g2(i,ny_global) = c2*work_g2(i,ny_global-1) & + - work_g2(i,ny_global-2) + enddo + endif + call scatter_global(work1, work_g2, & + master_task, distrb_info, & + field_loc_NEcorner, field_type_scalar) + lonn_bounds(3,:,:,:) = work1(:,:,:) + + work1(:,:,:) = lonn_bounds(4,:,:,:) + call gather_global(work_g2, work1, master_task, distrb_info) + if (my_task == master_task) then + do i = 1, nx_global + work_g2(i,ny_global) = c2*work_g2(i,ny_global-1) & + - work_g2(i,ny_global-2) + enddo + do j = 1, ny_global + work_g2(1,j) = c2*work_g2(2,j) & + - work_g2(3,j) + enddo + endif + call scatter_global(work1, work_g2, & + master_task, distrb_info, & + field_loc_NEcorner, field_type_scalar) + lonn_bounds(4,:,:,:) = work1(:,:,:) + + ! late_bounds + + work1(:,:,:) = late_bounds(1,:,:,:) + call gather_global(work_g2, work1, master_task, distrb_info) + if (my_task == master_task) then + do i = 1, nx_global + work_g2(i,1) = c2*work_g2(i,2) & + - work_g2(i,3) + enddo + endif + call scatter_global(work1, work_g2, & + master_task, distrb_info, & + field_loc_NEcorner, field_type_scalar) + late_bounds(1,:,:,:) = work1(:,:,:) + + work1(:,:,:) = late_bounds(2,:,:,:) + call gather_global(work_g2, work1, master_task, distrb_info) + if (my_task == master_task) then + do i = 1, nx_global + work_g2(i,1) = c2*work_g2(i,2) & + - work_g2(i,3) + enddo + do j = 1, ny_global + work_g2(nx_global,j) = c2*work_g2(nx_global-1,j) & + - work_g2(nx_global-2,j) + enddo + endif + call scatter_global(work1, work_g2, & + master_task, distrb_info, & + field_loc_NEcorner, field_type_scalar) + late_bounds(2,:,:,:) = work1(:,:,:) + + work1(:,:,:) = late_bounds(3,:,:,:) + call gather_global(work_g2, work1, master_task, distrb_info) + if (my_task == master_task) then + do j = 1, ny_global + work_g2(nx_global,j) = c2*work_g2(nx_global-1,j) & + - work_g2(nx_global-2,j) + enddo + endif + call scatter_global(work1, work_g2, & + master_task, distrb_info, & + field_loc_NEcorner, field_type_scalar) + late_bounds(3,:,:,:) = work1(:,:,:) + + ! lone_bounds + + work1(:,:,:) = lone_bounds(1,:,:,:) + call gather_global(work_g2, work1, master_task, distrb_info) + if (my_task == master_task) then + do i = 1, nx_global + work_g2(i,1) = c2*work_g2(i,2) & + - work_g2(i,3) + enddo + endif + call scatter_global(work1, work_g2, & + master_task, distrb_info, & + field_loc_NEcorner, field_type_scalar) + lone_bounds(1,:,:,:) = work1(:,:,:) + + work1(:,:,:) = lone_bounds(2,:,:,:) + call gather_global(work_g2, work1, master_task, distrb_info) + if (my_task == master_task) then + do i = 1, nx_global + work_g2(i,1) = c2*work_g2(i,2) & + - work_g2(i,3) + enddo + do j = 1, ny_global + work_g2(nx_global,j) = c2*work_g2(nx_global-1,j) & + - work_g2(nx_global-2,j) + enddo + endif + call scatter_global(work1, work_g2, & + master_task, distrb_info, & + field_loc_NEcorner, field_type_scalar) + lone_bounds(2,:,:,:) = work1(:,:,:) + + work1(:,:,:) = lone_bounds(3,:,:,:) + call gather_global(work_g2, work1, master_task, distrb_info) + if (my_task == master_task) then + do j = 1, ny_global + work_g2(nx_global,j) = c2*work_g2(nx_global-1,j) & + - work_g2(nx_global-2,j) + enddo + endif + call scatter_global(work1, work_g2, & + master_task, distrb_info, & + field_loc_NEcorner, field_type_scalar) + lone_bounds(3,:,:,:) = work1(:,:,:) + + deallocate(work_g2) + + !---------------------------------------------------------------- + ! Convert longitude to Degrees East >0 for history output + !---------------------------------------------------------------- + + allocate(work_g2(nx_block,ny_block)) ! not used as global here + !OMP fails in this loop + do iblk = 1, nblocks + do icorner = 1, 4 + work_g2(:,:) = lonn_bounds(icorner,:,:,iblk) + c360 + where (work_g2 > c360) work_g2 = work_g2 - c360 + where (work_g2 < c0 ) work_g2 = work_g2 + c360 + lonn_bounds(icorner,:,:,iblk) = work_g2(:,:) + work_g2(:,:) = lone_bounds(icorner,:,:,iblk) + c360 + where (work_g2 > c360) work_g2 = work_g2 - c360 + where (work_g2 < c0 ) work_g2 = work_g2 + c360 + lone_bounds(icorner,:,:,iblk) = work_g2(:,:) + enddo + enddo + deallocate(work_g2) + + end subroutine gridbox_edges + !======================================================================= ! NOTE: Boundary conditions for fields on NW, SW, SE corners diff --git a/cicecore/cicedynB/infrastructure/io/io_netcdf/ice_history_write.F90 b/cicecore/cicedynB/infrastructure/io/io_netcdf/ice_history_write.F90 index 493a91c1e..f48371f8d 100644 --- a/cicecore/cicedynB/infrastructure/io/io_netcdf/ice_history_write.F90 +++ b/cicecore/cicedynB/infrastructure/io/io_netcdf/ice_history_write.F90 @@ -54,9 +54,11 @@ subroutine ice_write_hist (ns) use ice_domain, only: distrb_info use ice_domain_size, only: nx_global, ny_global, max_nstrm, max_blocks use ice_gather_scatter, only: gather_global - use ice_grid, only: TLON, TLAT, ULON, ULAT, hm, bm, tarea, uarea, & - dxu, dxt, dyu, dyt, HTN, HTE, ANGLE, ANGLET, & - lont_bounds, latt_bounds, lonu_bounds, latu_bounds + use ice_grid, only: TLON, TLAT, ULON, ULAT, NLON, NLAT, ELON, ELAT, & + hm, uvm, npm, epm, bm, tarea, uarea, narea, earea, & + dxu, dxt, dyu, dyt, dxn, dyn, dxe, dye, HTN, HTE, ANGLE, ANGLET, & + lont_bounds, latt_bounds, lonu_bounds, latu_bounds, & + lonn_bounds, latn_bounds, lone_bounds, late_bounds use ice_history_shared use ice_restart_shared, only: runid, lcdf64 #ifdef USE_NETCDF @@ -91,15 +93,15 @@ subroutine ice_write_hist (ns) character (char_len) :: start_time,current_date,current_time character (len=8) :: cdate - ! 4 coordinate variables: TLON, TLAT, ULON, ULAT - INTEGER (kind=int_kind), PARAMETER :: ncoord = 4 + ! 8 coordinate variables: TLON, TLAT, ULON, ULAT, NLON, NLAT, ELON, ELAT + INTEGER (kind=int_kind), PARAMETER :: ncoord = 8 - ! 4 vertices in each grid cell - INTEGER (kind=int_kind), PARAMETER :: nverts = 4 + ! 8 vertices in each grid cell + INTEGER (kind=int_kind), PARAMETER :: nverts = 8 - ! 4 variables describe T, U grid boundaries: + ! 8 variables describe T, U grid boundaries: ! lont_bounds, latt_bounds, lonu_bounds, latu_bounds - INTEGER (kind=int_kind), PARAMETER :: nvar_verts = 4 + INTEGER (kind=int_kind), PARAMETER :: nvar_verts = 8 TYPE coord_attributes ! netcdf coordinate attributes character (len=11) :: short_name @@ -112,10 +114,10 @@ subroutine ice_write_hist (ns) character (len=20) :: coordinates END TYPE req_attributes - TYPE(req_attributes), dimension(nvar) :: var - TYPE(coord_attributes), dimension(ncoord) :: coord_var + TYPE(req_attributes), dimension(nvar_grd) :: var_grd + TYPE(coord_attributes), dimension(ncoord) :: var_coord TYPE(coord_attributes), dimension(nvar_verts) :: var_nverts - TYPE(coord_attributes), dimension(nvarz) :: var_nz + TYPE(coord_attributes), dimension(nvar_grdz) :: var_grdz CHARACTER (char_len), dimension(ncoord) :: coord_bounds character(len=*), parameter :: subname = '(ice_write_hist)' @@ -270,65 +272,118 @@ subroutine ice_write_hist (ns) ind = 0 ind = ind + 1 - coord_var(ind) = coord_attributes('TLON', & + var_coord(ind) = coord_attributes('TLON', & 'T grid center longitude', 'degrees_east') coord_bounds(ind) = 'lont_bounds' ind = ind + 1 - coord_var(ind) = coord_attributes('TLAT', & + var_coord(ind) = coord_attributes('TLAT', & 'T grid center latitude', 'degrees_north') coord_bounds(ind) = 'latt_bounds' ind = ind + 1 - coord_var(ind) = coord_attributes('ULON', & + var_coord(ind) = coord_attributes('ULON', & 'U grid center longitude', 'degrees_east') coord_bounds(ind) = 'lonu_bounds' ind = ind + 1 - coord_var(ind) = coord_attributes('ULAT', & + var_coord(ind) = coord_attributes('ULAT', & 'U grid center latitude', 'degrees_north') coord_bounds(ind) = 'latu_bounds' + ind = ind + 1 + var_coord(ind) = coord_attributes('NLON', & + 'N grid center longitude', 'degrees_east') + coord_bounds(ind) = 'lonn_bounds' + ind = ind + 1 + var_coord(ind) = coord_attributes('NLAT', & + 'N grid center latitude', 'degrees_north') + coord_bounds(ind) = 'latn_bounds' + ind = ind + 1 + var_coord(ind) = coord_attributes('ELON', & + 'E grid center longitude', 'degrees_east') + coord_bounds(ind) = 'lone_bounds' + ind = ind + 1 + var_coord(ind) = coord_attributes('ELAT', & + 'E grid center latitude', 'degrees_north') + coord_bounds(ind) = 'late_bounds' - var_nz(1) = coord_attributes('NCAT', 'category maximum thickness', 'm') - var_nz(2) = coord_attributes('VGRDi', 'vertical ice levels', '1') - var_nz(3) = coord_attributes('VGRDs', 'vertical snow levels', '1') - var_nz(4) = coord_attributes('VGRDb', 'vertical ice-bio levels', '1') - var_nz(5) = coord_attributes('VGRDa', 'vertical snow-ice-bio levels', '1') - var_nz(6) = coord_attributes('NFSD', 'category floe size (center)', 'm') + var_grdz(1) = coord_attributes('NCAT', 'category maximum thickness', 'm') + var_grdz(2) = coord_attributes('VGRDi', 'vertical ice levels', '1') + var_grdz(3) = coord_attributes('VGRDs', 'vertical snow levels', '1') + var_grdz(4) = coord_attributes('VGRDb', 'vertical ice-bio levels', '1') + var_grdz(5) = coord_attributes('VGRDa', 'vertical snow-ice-bio levels', '1') + var_grdz(6) = coord_attributes('NFSD', 'category floe size (center)', 'm') !----------------------------------------------------------------- ! define information for optional time-invariant variables !----------------------------------------------------------------- - var(n_tarea)%req = coord_attributes('tarea', & + var_grd(n_tmask)%req = coord_attributes('tmask', & + 'mask of T grid cells, 0 = land, 1 = ocean', 'unitless') + var_grd(n_tmask)%coordinates = 'TLON TLAT' + var_grd(n_umask)%req = coord_attributes('umask', & + 'mask of U grid cells, 0 = land, 1 = ocean', 'unitless') + var_grd(n_umask)%coordinates = 'ULON ULAT' + var_grd(n_nmask)%req = coord_attributes('nmask', & + 'mask of N grid cells, 0 = land, 1 = ocean', 'unitless') + var_grd(n_nmask)%coordinates = 'NLON NLAT' + var_grd(n_emask)%req = coord_attributes('emask', & + 'mask of E grid cells, 0 = land, 1 = ocean', 'unitless') + var_grd(n_emask)%coordinates = 'ELON ELAT' + + var_grd(n_tarea)%req = coord_attributes('tarea', & 'area of T grid cells', 'm^2') - var(n_tarea)%coordinates = 'TLON TLAT' - var(n_uarea)%req = coord_attributes('uarea', & + var_grd(n_tarea)%coordinates = 'TLON TLAT' + var_grd(n_uarea)%req = coord_attributes('uarea', & 'area of U grid cells', 'm^2') - var(n_uarea)%coordinates = 'ULON ULAT' - var(n_dxt)%req = coord_attributes('dxt', & + var_grd(n_uarea)%coordinates = 'ULON ULAT' + var_grd(n_narea)%req = coord_attributes('narea', & + 'area of N grid cells', 'm^2') + var_grd(n_narea)%coordinates = 'NLON NLAT' + var_grd(n_earea)%req = coord_attributes('earea', & + 'area of E grid cells', 'm^2') + var_grd(n_earea)%coordinates = 'ELON ELAT' + + var_grd(n_blkmask)%req = coord_attributes('blkmask', & + 'block id of T grid cells, mytask + iblk/100', 'unitless') + var_grd(n_blkmask)%coordinates = 'TLON TLAT' + + var_grd(n_dxt)%req = coord_attributes('dxt', & 'T cell width through middle', 'm') - var(n_dxt)%coordinates = 'TLON TLAT' - var(n_dyt)%req = coord_attributes('dyt', & + var_grd(n_dxt)%coordinates = 'TLON TLAT' + var_grd(n_dyt)%req = coord_attributes('dyt', & 'T cell height through middle', 'm') - var(n_dyt)%coordinates = 'TLON TLAT' - var(n_dxu)%req = coord_attributes('dxu', & + var_grd(n_dyt)%coordinates = 'TLON TLAT' + var_grd(n_dxu)%req = coord_attributes('dxu', & 'U cell width through middle', 'm') - var(n_dxu)%coordinates = 'ULON ULAT' - var(n_dyu)%req = coord_attributes('dyu', & + var_grd(n_dxu)%coordinates = 'ULON ULAT' + var_grd(n_dyu)%req = coord_attributes('dyu', & 'U cell height through middle', 'm') - var(n_dyu)%coordinates = 'ULON ULAT' - var(n_HTN)%req = coord_attributes('HTN', & + var_grd(n_dyu)%coordinates = 'ULON ULAT' + var_grd(n_dxn)%req = coord_attributes('dxn', & + 'N cell width through middle', 'm') + var_grd(n_dxn)%coordinates = 'NLON NLAT' + var_grd(n_dyn)%req = coord_attributes('dyn', & + 'N cell height through middle', 'm') + var_grd(n_dyn)%coordinates = 'NLON NLAT' + var_grd(n_dxe)%req = coord_attributes('dxe', & + 'E cell width through middle', 'm') + var_grd(n_dxe)%coordinates = 'ELON ELAT' + var_grd(n_dye)%req = coord_attributes('dye', & + 'E cell height through middle', 'm') + var_grd(n_dye)%coordinates = 'ELON ELAT' + + var_grd(n_HTN)%req = coord_attributes('HTN', & 'T cell width on North side','m') - var(n_HTN)%coordinates = 'TLON TLAT' - var(n_HTE)%req = coord_attributes('HTE', & + var_grd(n_HTN)%coordinates = 'TLON TLAT' + var_grd(n_HTE)%req = coord_attributes('HTE', & 'T cell width on East side', 'm') - var(n_HTE)%coordinates = 'TLON TLAT' - var(n_ANGLE)%req = coord_attributes('ANGLE', & + var_grd(n_HTE)%coordinates = 'TLON TLAT' + var_grd(n_ANGLE)%req = coord_attributes('ANGLE', & 'angle grid makes with latitude line on U grid', & 'radians') - var(n_ANGLE)%coordinates = 'ULON ULAT' - var(n_ANGLET)%req = coord_attributes('ANGLET', & + var_grd(n_ANGLE)%coordinates = 'ULON ULAT' + var_grd(n_ANGLET)%req = coord_attributes('ANGLET', & 'angle grid makes with latitude line on T grid', & 'radians') - var(n_ANGLET)%coordinates = 'TLON TLAT' + var_grd(n_ANGLET)%coordinates = 'TLON TLAT' ! These fields are required for CF compliance ! dimensions (nx,ny,nverts) @@ -340,6 +395,14 @@ subroutine ice_write_hist (ns) 'longitude boundaries of U cells', 'degrees_east') var_nverts(n_latu_bnds) = coord_attributes('latu_bounds', & 'latitude boundaries of U cells', 'degrees_north') + var_nverts(n_lonn_bnds) = coord_attributes('lonn_bounds', & + 'longitude boundaries of N cells', 'degrees_east') + var_nverts(n_latn_bnds) = coord_attributes('latn_bounds', & + 'latitude boundaries of N cells', 'degrees_north') + var_nverts(n_lone_bnds) = coord_attributes('lone_bounds', & + 'longitude boundaries of E cells', 'degrees_east') + var_nverts(n_late_bnds) = coord_attributes('late_bounds', & + 'latitude boundaries of E cells', 'degrees_north') !----------------------------------------------------------------- ! define attributes for time-invariant variables @@ -350,28 +413,28 @@ subroutine ice_write_hist (ns) dimid(3) = timid do i = 1, ncoord - status = nf90_def_var(ncid, coord_var(i)%short_name, lprecision, & + status = nf90_def_var(ncid, var_coord(i)%short_name, lprecision, & dimid(1:2), varid) if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining short_name for '//coord_var(i)%short_name) - status = nf90_put_att(ncid,varid,'long_name',coord_var(i)%long_name) + 'ERROR: defining short_name for '//var_coord(i)%short_name) + status = nf90_put_att(ncid,varid,'long_name',var_coord(i)%long_name) if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining long_name for '//coord_var(i)%short_name) - status = nf90_put_att(ncid, varid, 'units', coord_var(i)%units) + 'ERROR: defining long_name for '//var_coord(i)%short_name) + status = nf90_put_att(ncid, varid, 'units', var_coord(i)%units) if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining units for '//coord_var(i)%short_name) - call ice_write_hist_fill(ncid,varid,coord_var(i)%short_name,history_precision) - if (coord_var(i)%short_name == 'ULAT') then + 'ERROR: defining units for '//var_coord(i)%short_name) + call ice_write_hist_fill(ncid,varid,var_coord(i)%short_name,history_precision) + if (var_coord(i)%short_name == 'ULAT') then status = nf90_put_att(ncid,varid,'comment', & 'Latitude of NE corner of T grid cell') if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining comment for '//coord_var(i)%short_name) + 'ERROR: defining comment for '//var_coord(i)%short_name) endif if (f_bounds) then status = nf90_put_att(ncid, varid, 'bounds', coord_bounds(i)) if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining bounds for '//coord_var(i)%short_name) - endif + 'ERROR: defining bounds for '//var_coord(i)%short_name) + endif enddo ! Extra dimensions (NCAT, NZILYR, NZSLYR, NZBLYR, NZALYR, NFSD) @@ -382,62 +445,37 @@ subroutine ice_write_hist (ns) dimidex(5)=kmtida dimidex(6)=fmtid - do i = 1, nvarz + do i = 1, nvar_grdz if (igrdz(i)) then - status = nf90_def_var(ncid, var_nz(i)%short_name, & + status = nf90_def_var(ncid, var_grdz(i)%short_name, & lprecision, dimidex(i), varid) if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining short_name for '//var_nz(i)%short_name) - status = nf90_put_att(ncid,varid,'long_name',var_nz(i)%long_name) + 'ERROR: defining short_name for '//var_grdz(i)%short_name) + status = nf90_put_att(ncid,varid,'long_name',var_grdz(i)%long_name) if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining long_name for '//var_nz(i)%short_name) - status = nf90_put_att(ncid, varid, 'units', var_nz(i)%units) + 'ERROR: defining long_name for '//var_grdz(i)%short_name) + status = nf90_put_att(ncid, varid, 'units', var_grdz(i)%units) if (Status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining units for '//var_nz(i)%short_name) + 'ERROR: defining units for '//var_grdz(i)%short_name) endif enddo - ! Attributes for tmask, blkmask defined separately, since they have no units - if (igrd(n_tmask)) then - status = nf90_def_var(ncid, 'tmask', lprecision, dimid(1:2), varid) - if (status /= nf90_noerr) call abort_ice(subname//'ERROR: defining var tmask') - status = nf90_put_att(ncid,varid, 'long_name', 'ocean grid mask') - if (status /= nf90_noerr) call abort_ice(subname//'ERROR: tmask long_name') - status = nf90_put_att(ncid, varid, 'coordinates', 'TLON TLAT') - if (status /= nf90_noerr) call abort_ice(subname//'ERROR: tmask units') - status = nf90_put_att(ncid,varid,'comment', '0 = land, 1 = ocean') - if (status /= nf90_noerr) call abort_ice(subname//'ERROR: tmask comment') - call ice_write_hist_fill(ncid,varid,'tmask',history_precision) - endif - - if (igrd(n_blkmask)) then - status = nf90_def_var(ncid, 'blkmask', lprecision, dimid(1:2), varid) - if (status /= nf90_noerr) call abort_ice(subname//'ERROR: defining var blkmask') - status = nf90_put_att(ncid,varid, 'long_name', 'ice grid block mask') - if (status /= nf90_noerr) call abort_ice(subname//'ERROR: blkmask long_name') - status = nf90_put_att(ncid, varid, 'coordinates', 'TLON TLAT') - if (status /= nf90_noerr) call abort_ice(subname//'ERROR: blkmask units') - status = nf90_put_att(ncid,varid,'comment', 'mytask + iblk/100') - if (status /= nf90_noerr) call abort_ice(subname//'ERROR: blkmask comment') - call ice_write_hist_fill(ncid,varid,'blkmask',history_precision) - endif - - do i = 3, nvar ! note n_tmask=1, n_blkmask=2 + do i = 1, nvar_grd if (igrd(i)) then - status = nf90_def_var(ncid, var(i)%req%short_name, & + status = nf90_def_var(ncid, var_grd(i)%req%short_name, & lprecision, dimid(1:2), varid) if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining variable '//var(i)%req%short_name) - status = nf90_put_att(ncid,varid, 'long_name', var(i)%req%long_name) + 'ERROR: defining variable '//var_grd(i)%req%short_name) + status = nf90_put_att(ncid,varid, 'long_name', var_grd(i)%req%long_name) if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining long_name for '//var(i)%req%short_name) - status = nf90_put_att(ncid, varid, 'units', var(i)%req%units) + 'ERROR: defining long_name for '//var_grd(i)%req%short_name) + status = nf90_put_att(ncid, varid, 'units', var_grd(i)%req%units) if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining units for '//var(i)%req%short_name) - status = nf90_put_att(ncid, varid, 'coordinates', var(i)%coordinates) + 'ERROR: defining units for '//var_grd(i)%req%short_name) + status = nf90_put_att(ncid, varid, 'coordinates', var_grd(i)%coordinates) if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining coordinates for '//var(i)%req%short_name) - call ice_write_hist_fill(ncid,varid,var(i)%req%short_name,history_precision) + 'ERROR: defining coordinates for '//var_grd(i)%req%short_name) + call ice_write_hist_fill(ncid,varid,var_grd(i)%req%short_name,history_precision) endif enddo @@ -951,8 +989,8 @@ subroutine ice_write_hist (ns) !----------------------------------------------------------------- do i = 1,ncoord - call broadcast_scalar(coord_var(i)%short_name,master_task) - SELECT CASE (coord_var(i)%short_name) + call broadcast_scalar(var_coord(i)%short_name,master_task) + SELECT CASE (var_coord(i)%short_name) CASE ('TLON') ! Convert T grid longitude from -180 -> 180 to 0 to 360 work1 = TLON*rad_to_deg + c360 @@ -968,28 +1006,40 @@ subroutine ice_write_hist (ns) CASE ('ULAT') work1 = ULAT*rad_to_deg call gather_global(work_g1,work1,master_task,distrb_info) + CASE ('NLON') + work1 = NLON*rad_to_deg + call gather_global(work_g1,work1,master_task,distrb_info) + CASE ('NLAT') + work1 = NLAT*rad_to_deg + call gather_global(work_g1,work1,master_task,distrb_info) + CASE ('ELON') + work1 = ELON*rad_to_deg + call gather_global(work_g1,work1,master_task,distrb_info) + CASE ('ELAT') + work1 = ELAT*rad_to_deg + call gather_global(work_g1,work1,master_task,distrb_info) END SELECT if (my_task == master_task) then - status = nf90_inq_varid(ncid, coord_var(i)%short_name, varid) + status = nf90_inq_varid(ncid, var_coord(i)%short_name, varid) if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: getting varid for '//coord_var(i)%short_name) + 'ERROR: getting varid for '//var_coord(i)%short_name) status = nf90_put_var(ncid,varid,work_g1) if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: writing'//coord_var(i)%short_name) + 'ERROR: writing'//var_coord(i)%short_name) endif enddo ! Extra dimensions (NCAT, NFSD, VGRD*) - do i = 1, nvarz + do i = 1, nvar_grdz if (igrdz(i)) then - call broadcast_scalar(var_nz(i)%short_name,master_task) + call broadcast_scalar(var_grdz(i)%short_name,master_task) if (my_task == master_task) then - status = nf90_inq_varid(ncid, var_nz(i)%short_name, varid) + status = nf90_inq_varid(ncid, var_grdz(i)%short_name, varid) if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: getting varid for '//var_nz(i)%short_name) - SELECT CASE (var_nz(i)%short_name) + 'ERROR: getting varid for '//var_grdz(i)%short_name) + SELECT CASE (var_grdz(i)%short_name) CASE ('NCAT') status = nf90_put_var(ncid,varid,hin_max(1:ncat_hist)) CASE ('NFSD') @@ -1004,7 +1054,7 @@ subroutine ice_write_hist (ns) status = nf90_put_var(ncid,varid,(/(k, k=1,nzalyr)/)) END SELECT if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: writing'//var_nz(i)%short_name) + 'ERROR: writing'//var_grdz(i)%short_name) endif endif enddo @@ -1013,38 +1063,28 @@ subroutine ice_write_hist (ns) ! write grid masks, area and rotation angle !----------------------------------------------------------------- - if (igrd(n_tmask)) then - call gather_global(work_g1, hm, master_task, distrb_info) - if (my_task == master_task) then - status = nf90_inq_varid(ncid, 'tmask', varid) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: getting varid for tmask') - status = nf90_put_var(ncid,varid,work_g1) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: writing variable tmask') - endif - endif - - if (igrd(n_blkmask)) then - call gather_global(work_g1, bm, master_task, distrb_info) - if (my_task == master_task) then - status = nf90_inq_varid(ncid, 'blkmask', varid) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: getting varid for blkmask') - status = nf90_put_var(ncid,varid,work_g1) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: writing variable blkmask') - endif - endif - - do i = 3, nvar ! note n_tmask=1, n_blkmask=2 + do i = 1, nvar_grd if (igrd(i)) then - call broadcast_scalar(var(i)%req%short_name,master_task) - SELECT CASE (var(i)%req%short_name) + call broadcast_scalar(var_grd(i)%req%short_name,master_task) + SELECT CASE (var_grd(i)%req%short_name) + CASE ('tmask') + call gather_global(work_g1, hm, master_task, distrb_info) + CASE ('umask') + call gather_global(work_g1, uvm, master_task, distrb_info) + CASE ('nmask') + call gather_global(work_g1, npm, master_task, distrb_info) + CASE ('emask') + call gather_global(work_g1, epm, master_task, distrb_info) CASE ('tarea') call gather_global(work_g1, tarea, master_task, distrb_info) CASE ('uarea') call gather_global(work_g1, uarea, master_task, distrb_info) + CASE ('narea') + call gather_global(work_g1, narea, master_task, distrb_info) + CASE ('earea') + call gather_global(work_g1, earea, master_task, distrb_info) + CASE ('blkmask') + call gather_global(work_g1, bm, master_task, distrb_info) CASE ('dxu') call gather_global(work_g1, dxu, master_task, distrb_info) CASE ('dyu') @@ -1053,6 +1093,14 @@ subroutine ice_write_hist (ns) call gather_global(work_g1, dxt, master_task, distrb_info) CASE ('dyt') call gather_global(work_g1, dyt, master_task, distrb_info) + CASE ('dxn') + call gather_global(work_g1, dxn, master_task, distrb_info) + CASE ('dyn') + call gather_global(work_g1, dyn, master_task, distrb_info) + CASE ('dxe') + call gather_global(work_g1, dxe, master_task, distrb_info) + CASE ('dye') + call gather_global(work_g1, dye, master_task, distrb_info) CASE ('HTN') call gather_global(work_g1, HTN, master_task, distrb_info) CASE ('HTE') @@ -1064,12 +1112,12 @@ subroutine ice_write_hist (ns) END SELECT if (my_task == master_task) then - status = nf90_inq_varid(ncid, var(i)%req%short_name, varid) + status = nf90_inq_varid(ncid, var_grd(i)%req%short_name, varid) if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: getting varid for '//var(i)%req%short_name) + 'ERROR: getting varid for '//var_grd(i)%req%short_name) status = nf90_put_var(ncid,varid,work_g1) if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: writing variable '//var(i)%req%short_name) + 'ERROR: writing variable '//var_grd(i)%req%short_name) endif endif enddo @@ -1086,7 +1134,7 @@ subroutine ice_write_hist (ns) endif work1_3(:,:,:) = c0 - work1 (:,:,:) = c0 + work1 (:,:,:) = c0 do i = 1, nvar_verts call broadcast_scalar(var_nverts(i)%short_name,master_task) @@ -1115,6 +1163,30 @@ subroutine ice_write_hist (ns) call gather_global(work_g1, work1, master_task, distrb_info) if (my_task == master_task) work1_3(ivertex,:,:) = work_g1(:,:) enddo + CASE ('lonn_bounds') + do ivertex = 1, nverts + work1(:,:,:) = lonn_bounds(ivertex,:,:,:) + call gather_global(work_g1, work1, master_task, distrb_info) + if (my_task == master_task) work1_3(ivertex,:,:) = work_g1(:,:) + enddo + CASE ('latn_bounds') + do ivertex = 1, nverts + work1(:,:,:) = latn_bounds(ivertex,:,:,:) + call gather_global(work_g1, work1, master_task, distrb_info) + if (my_task == master_task) work1_3(ivertex,:,:) = work_g1(:,:) + enddo + CASE ('lone_bounds') + do ivertex = 1, nverts + work1(:,:,:) = lone_bounds(ivertex,:,:,:) + call gather_global(work_g1, work1, master_task, distrb_info) + if (my_task == master_task) work1_3(ivertex,:,:) = work_g1(:,:) + enddo + CASE ('late_bounds') + do ivertex = 1, nverts + work1(:,:,:) = late_bounds(ivertex,:,:,:) + call gather_global(work_g1, work1, master_task, distrb_info) + if (my_task == master_task) work1_3(ivertex,:,:) = work_g1(:,:) + enddo END SELECT if (my_task == master_task) then From 87df8d4caa97b5977057ccf3cfc46145edc15d44 Mon Sep 17 00:00:00 2001 From: apcraig Date: Tue, 2 Nov 2021 11:04:20 -0600 Subject: [PATCH 03/17] add grid_average_X2Y method to average fields from one grid to another --- cicecore/cicedynB/dynamics/ice_dyn_eap.F90 | 22 +- cicecore/cicedynB/dynamics/ice_dyn_evp.F90 | 22 +- cicecore/cicedynB/dynamics/ice_dyn_vp.F90 | 23 +- cicecore/cicedynB/general/ice_forcing.F90 | 16 +- cicecore/cicedynB/infrastructure/ice_grid.F90 | 364 +++++++++++------- cicecore/drivers/mct/cesm1/ice_comp_esmf.F90 | 2 +- cicecore/drivers/mct/cesm1/ice_comp_mct.F90 | 2 +- .../drivers/mct/cesm1/ice_import_export.F90 | 14 +- .../drivers/nuopc/cmeps/ice_import_export.F90 | 14 +- cicecore/drivers/nuopc/dmi/cice_cap.info | 15 +- 10 files changed, 312 insertions(+), 182 deletions(-) diff --git a/cicecore/cicedynB/dynamics/ice_dyn_eap.F90 b/cicecore/cicedynB/dynamics/ice_dyn_eap.F90 index 83374d4dd..c550a4b14 100644 --- a/cicecore/cicedynB/dynamics/ice_dyn_eap.F90 +++ b/cicecore/cicedynB/dynamics/ice_dyn_eap.F90 @@ -134,7 +134,7 @@ subroutine eap (dt) stressm_1, stressm_2, stressm_3, stressm_4, & stress12_1, stress12_2, stress12_3, stress12_4 use ice_grid, only: tmask, umask, dxt, dyt, dxhy, dyhx, cxp, cyp, cxm, cym, & - tarear, uarear, to_ugrid, t2ugrid_vector, u2tgrid_vector + tarear, uarear, grid_average_X2Y use ice_state, only: aice, vice, vsno, uvel, vvel, divu, shear, & aice_init, aice0, aicen, vicen, strength ! use ice_timers, only: timer_dynamics, timer_bound, & @@ -254,8 +254,8 @@ subroutine eap (dt) ! convert fields from T to U grid !----------------------------------------------------------------- - call to_ugrid(tmass,umass) - call to_ugrid(aice_init, aiu) + call grid_average_X2Y('T2U',tmass,umass) + call grid_average_X2Y('T2U',aice_init, aiu) !---------------------------------------------------------------- ! Set wind stress to values supplied via NEMO or other forcing @@ -270,8 +270,12 @@ subroutine eap (dt) strairx(:,:,:) = strax(:,:,:) strairy(:,:,:) = stray(:,:,:) else - call t2ugrid_vector(strairx) - call t2ugrid_vector(strairy) + call ice_HaloUpdate (strairx, halo_info, & + field_loc_center, field_type_vector) + call ice_HaloUpdate (strairy, halo_info, & + field_loc_center, field_type_vector) + call grid_average_X2Y('T2U',strairx) + call grid_average_X2Y('T2U',strairy) endif ! tcraig, tcx, turned off this threaded region, in evp, this block and @@ -548,8 +552,12 @@ subroutine eap (dt) enddo !$OMP END PARALLEL DO - call u2tgrid_vector(strocnxT) ! shift - call u2tgrid_vector(strocnyT) + call ice_HaloUpdate (strocnxT, halo_info, & + field_loc_NEcorner, field_type_vector) + call ice_HaloUpdate (strocnyT, halo_info, & + field_loc_NEcorner, field_type_vector) + call grid_average_X2Y('U2T',strocnxT) ! shift + call grid_average_X2Y('U2T',strocnyT) call ice_timer_stop(timer_dynamics) ! dynamics diff --git a/cicecore/cicedynB/dynamics/ice_dyn_evp.F90 b/cicecore/cicedynB/dynamics/ice_dyn_evp.F90 index 8f3fc4910..cf7048e15 100644 --- a/cicecore/cicedynB/dynamics/ice_dyn_evp.F90 +++ b/cicecore/cicedynB/dynamics/ice_dyn_evp.F90 @@ -89,7 +89,7 @@ subroutine evp (dt) stressm_1, stressm_2, stressm_3, stressm_4, & stress12_1, stress12_2, stress12_3, stress12_4 use ice_grid, only: tmask, umask, dxt, dyt, dxhy, dyhx, cxp, cyp, cxm, cym, & - tarear, uarear, tinyarea, to_ugrid, t2ugrid_vector, u2tgrid_vector, & + tarear, uarear, tinyarea, grid_average_X2Y, & grid_type use ice_state, only: aice, vice, vsno, uvel, vvel, divu, shear, & aice_init, aice0, aicen, vicen, strength @@ -219,8 +219,8 @@ subroutine evp (dt) ! convert fields from T to U grid !----------------------------------------------------------------- - call to_ugrid(tmass,umass) - call to_ugrid(aice_init, aiu) + call grid_average_X2Y('T2U',tmass,umass) + call grid_average_X2Y('T2U',aice_init, aiu) !---------------------------------------------------------------- ! Set wind stress to values supplied via NEMO or other forcing @@ -235,8 +235,12 @@ subroutine evp (dt) strairx(:,:,:) = strax(:,:,:) strairy(:,:,:) = stray(:,:,:) else - call t2ugrid_vector(strairx) - call t2ugrid_vector(strairy) + call ice_HaloUpdate (strairx, halo_info, & + field_loc_center, field_type_vector) + call ice_HaloUpdate (strairy, halo_info, & + field_loc_center, field_type_vector) + call grid_average_X2Y('T2U',strairx) + call grid_average_X2Y('T2U',strairy) endif ! tcraig, tcx, threading here leads to some non-reproducbile results and failures in icepack_ice_strength @@ -557,8 +561,12 @@ subroutine evp (dt) enddo !$OMP END PARALLEL DO - call u2tgrid_vector(strocnxT) ! shift - call u2tgrid_vector(strocnyT) + call ice_HaloUpdate (strocnxT, halo_info, & + field_loc_NEcorner, field_type_vector) + call ice_HaloUpdate (strocnyT, halo_info, & + field_loc_NEcorner, field_type_vector) + call grid_average_X2Y('U2T',strocnxT) ! shift + call grid_average_X2Y('U2T',strocnyT) call ice_timer_stop(timer_dynamics) ! dynamics diff --git a/cicecore/cicedynB/dynamics/ice_dyn_vp.F90 b/cicecore/cicedynB/dynamics/ice_dyn_vp.F90 index 1a6c68548..a8bf7be89 100644 --- a/cicecore/cicedynB/dynamics/ice_dyn_vp.F90 +++ b/cicecore/cicedynB/dynamics/ice_dyn_vp.F90 @@ -200,8 +200,7 @@ subroutine implicit_solver (dt) stressm_1, stressm_2, stressm_3, stressm_4, & stress12_1, stress12_2, stress12_3, stress12_4 use ice_grid, only: tmask, umask, dxt, dyt, cxp, cyp, cxm, cym, & - tarear, to_ugrid, t2ugrid_vector, u2tgrid_vector, & - grid_type + tarear, grid_type, grid_average_X2Y use ice_state, only: aice, vice, vsno, uvel, vvel, divu, shear, & aice_init, aice0, aicen, vicen, strength use ice_timers, only: timer_dynamics, timer_bound, & @@ -321,8 +320,8 @@ subroutine implicit_solver (dt) ! convert fields from T to U grid !----------------------------------------------------------------- - call to_ugrid(tmass,umass) - call to_ugrid(aice_init, aiu) + call grid_average_X2Y('T2U',tmass,umass) + call grid_average_X2Y('T2U',aice_init, aiu) !---------------------------------------------------------------- ! Set wind stress to values supplied via NEMO or other forcing @@ -337,8 +336,12 @@ subroutine implicit_solver (dt) strairx(:,:,:) = strax(:,:,:) strairy(:,:,:) = stray(:,:,:) else - call t2ugrid_vector(strairx) - call t2ugrid_vector(strairy) + call ice_HaloUpdate (strairx, halo_info, & + field_loc_center, field_type_vector) + call ice_HaloUpdate (strairy, halo_info, & + field_loc_center, field_type_vector) + call grid_average_X2Y('T2U',strairx) + call grid_average_X2Y('T2U',strairy) endif ! tcraig, tcx, threading here leads to some non-reproducbile results and failures in icepack_ice_strength @@ -648,8 +651,12 @@ subroutine implicit_solver (dt) enddo !$OMP END PARALLEL DO - call u2tgrid_vector(strocnxT) ! shift - call u2tgrid_vector(strocnyT) + call ice_HaloUpdate (strocnxT, halo_info, & + field_loc_NEcorner, field_type_vector) + call ice_HaloUpdate (strocnyT, halo_info, & + field_loc_NEcorner, field_type_vector) + call grid_average_X2Y('U2T',strocnxT) ! shift + call grid_average_X2Y('U2T',strocnyT) call ice_timer_stop(timer_dynamics) ! dynamics diff --git a/cicecore/cicedynB/general/ice_forcing.F90 b/cicecore/cicedynB/general/ice_forcing.F90 index cede58950..a4dd66c67 100755 --- a/cicecore/cicedynB/general/ice_forcing.F90 +++ b/cicecore/cicedynB/general/ice_forcing.F90 @@ -3954,7 +3954,7 @@ subroutine ocn_data_ncar_init_3D use ice_blocks, only: nx_block, ny_block use ice_domain_size, only: max_blocks - use ice_grid, only: to_ugrid, ANGLET + use ice_grid, only: grid_average_X2Y, ANGLET use ice_read_write, only: ice_read_nc_uv #ifdef USE_NETCDF use netcdf @@ -4072,8 +4072,8 @@ subroutine ocn_data_ncar_init_3D work1(:,:,:) = ocn_frc_m(:,:,:,n ,m) work2(:,:,:) = ocn_frc_m(:,:,:,n+1,m) - call to_ugrid(work1,ocn_frc_m(:,:,:,n ,m)) - call to_ugrid(work2,ocn_frc_m(:,:,:,n+1,m)) + call grid_average_X2Y('T2U',work1,ocn_frc_m(:,:,:,n ,m)) + call grid_average_X2Y('T2U',work2,ocn_frc_m(:,:,:,n+1,m)) enddo ! month loop enddo ! field loop @@ -4315,7 +4315,7 @@ subroutine ocn_data_hadgem(dt) use ice_domain, only: nblocks use ice_flux, only: sst, uocn, vocn - use ice_grid, only: t2ugrid_vector, ANGLET + use ice_grid, only: grid_average_X2Y, ANGLET real (kind=dbl_kind), intent(in) :: & dt ! time step @@ -4474,8 +4474,8 @@ subroutine ocn_data_hadgem(dt) ! Interpolate to U grid !----------------------------------------------------------------- - call t2ugrid_vector(uocn) - call t2ugrid_vector(vocn) + call grid_average_X2Y('T2U',uocn) + call grid_average_X2Y('T2U',vocn) endif ! ocn_data_type = hadgem_sst_uvocn @@ -5257,7 +5257,7 @@ subroutine box2001_data use ice_calendar, only: timesecs use ice_blocks, only: nx_block, ny_block, nghost use ice_flux, only: uocn, vocn, uatm, vatm, wind, rhoa, strax, stray - use ice_grid, only: uvm, to_ugrid + use ice_grid, only: uvm, grid_average_X2Y use ice_state, only: aice ! local parameters @@ -5278,7 +5278,7 @@ subroutine box2001_data call icepack_query_parameters(pi_out=pi, pi2_out=pi2, puny_out=puny) call icepack_query_parameters(secday_out=secday) - call to_ugrid(aice, aiu) + call grid_average_X2Y('T2U',aice, aiu) period = c4*secday diff --git a/cicecore/cicedynB/infrastructure/ice_grid.F90 b/cicecore/cicedynB/infrastructure/ice_grid.F90 index 0b6fba962..7a80d963f 100644 --- a/cicecore/cicedynB/infrastructure/ice_grid.F90 +++ b/cicecore/cicedynB/infrastructure/ice_grid.F90 @@ -45,9 +45,8 @@ module ice_grid implicit none private - public :: init_grid1, init_grid2, & - t2ugrid_vector, u2tgrid_vector, & - to_ugrid, to_tgrid, alloc_grid, makemask + public :: init_grid1, init_grid2, grid_average_X2Y, & + alloc_grid, makemask character (len=char_len_long), public :: & grid_format , & ! file format ('bin'=binary or 'nc'=netcdf) @@ -2150,52 +2149,87 @@ end subroutine Tlatlon !======================================================================= -! Transfer vector component from T-cell centers to U-cell centers. +! Shifts quantities from one grid to another +! NOTE: Input array includes ghost cells that must be updated before +! calling this routine. ! -! author: Elizabeth C. Hunke, LANL +! author: T. Craig - subroutine t2ugrid_vector (work) + subroutine grid_average_X2Y(X2Y,work1,work2) - use ice_blocks, only: nx_block, ny_block - use ice_constants, only: field_loc_center, field_type_vector - use ice_domain_size, only: max_blocks + character(len=*) , intent(in) :: & + X2Y + + real (kind=dbl_kind), intent(inout) :: & + work1(nx_block,ny_block,max_blocks) - real (kind=dbl_kind), dimension(nx_block,ny_block,max_blocks), intent(inout) :: & - work + real (kind=dbl_kind), intent(out), optional :: & + work2(nx_block,ny_block,max_blocks) ! local variables real (kind=dbl_kind), dimension (nx_block,ny_block,max_blocks) :: & - work1 - - character(len=*), parameter :: subname = '(t2ugrid_vector)' - - work1(:,:,:) = work(:,:,:) - - call ice_timer_start(timer_bound) - call ice_HaloUpdate (work1, halo_info, & - field_loc_center, field_type_vector) - call ice_timer_stop(timer_bound) - - call to_ugrid(work1,work) + work2tmp + + character(len=*), parameter :: subname = '(grid_average_X2Y)' + + select case (trim(X2Y)) + + case('T2U') + call grid_average_X2Y_compute('NE',work1,tarea,work2tmp,uarea) + case('T2E') + call grid_average_X2Y_compute('E' ,work1,tarea,work2tmp,earea) + case('T2N') + call grid_average_X2Y_compute('N' ,work1,tarea,work2tmp,narea) + case('U2T') + call grid_average_X2Y_compute('SW',work1,uarea,work2tmp,tarea) + case('U2E') + call grid_average_X2Y_compute('S' ,work1,uarea,work2tmp,earea) + case('U2N') + call grid_average_X2Y_compute('W' ,work1,uarea,work2tmp,narea) + case('E2T') + call grid_average_X2Y_compute('W' ,work1,earea,work2tmp,tarea) + case('E2U') + call grid_average_X2Y_compute('N' ,work1,earea,work2tmp,uarea) + case('E2N') + call grid_average_X2Y_compute('NW',work1,earea,work2tmp,narea) + case('N2T') + call grid_average_X2Y_compute('S' ,work1,narea,work2tmp,tarea) + case('N2U') + call grid_average_X2Y_compute('E' ,work1,narea,work2tmp,uarea) + case('N2E') + call grid_average_X2Y_compute('SE',work1,narea,work2tmp,earea) + case default + call abort_ice(subname//'ERROR: unknown X2Y '//trim(X2Y)) + end select + + if (present(work2)) then + work2 = work2tmp + else + work1 = work2tmp + endif - end subroutine t2ugrid_vector + end subroutine grid_average_X2Y !======================================================================= -! Shifts quantities from the T-cell midpoint (work1) to the U-cell -! midpoint (work2) +! Shifts quantities from one grid to another ! NOTE: Input array includes ghost cells that must be updated before ! calling this routine. ! -! author: Elizabeth C. Hunke, LANL +! author: T. Craig - subroutine to_ugrid(work1,work2) + subroutine grid_average_X2Y_compute(dir,work1,area1,work2,area2) - use ice_constants, only: c0, p25 + use ice_constants, only: c0, p25, p5 + + character(len=*) , intent(in) :: & + dir real (kind=dbl_kind), intent(in) :: & - work1(nx_block,ny_block,max_blocks) + work1(nx_block,ny_block,max_blocks), & + area1(nx_block,ny_block,max_blocks), & + area2(nx_block,ny_block,max_blocks) real (kind=dbl_kind), intent(out) :: & work2(nx_block,ny_block,max_blocks) @@ -2203,7 +2237,7 @@ subroutine to_ugrid(work1,work2) type (block) :: & this_block ! block information for current block - character(len=*), parameter :: subname = '(to_ugrid)' + character(len=*), parameter :: subname = '(grid_average_X2Y_compute)' ! local variables @@ -2213,113 +2247,173 @@ subroutine to_ugrid(work1,work2) work2(:,:,:) = c0 - !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) - do iblk = 1, nblocks - this_block = get_block(blocks_ice(iblk),iblk) - ilo = this_block%ilo - ihi = this_block%ihi - jlo = this_block%jlo - jhi = this_block%jhi - - do j = jlo, jhi - do i = ilo, ihi - work2(i,j,iblk) = p25 * & - (work1(i, j, iblk)*tarea(i, j, iblk) & - + work1(i+1,j, iblk)*tarea(i+1,j, iblk) & - + work1(i, j+1,iblk)*tarea(i, j+1,iblk) & - + work1(i+1,j+1,iblk)*tarea(i+1,j+1,iblk)) & - / uarea(i, j, iblk) - enddo - enddo - enddo - !$OMP END PARALLEL DO - - end subroutine to_ugrid - -!======================================================================= - -! Transfer from U-cell centers to T-cell centers. Writes work into -! another array that has ghost cells -! NOTE: Input array is dimensioned only over physical cells. -! -! author: Elizabeth C. Hunke, LANL - - subroutine u2tgrid_vector (work) - - use ice_blocks, only: nx_block, ny_block - use ice_constants, only: field_loc_NEcorner, field_type_vector - use ice_domain_size, only: max_blocks - - real (kind=dbl_kind), dimension (nx_block,ny_block,max_blocks), intent(inout) :: & - work - - ! local variables - - real (kind=dbl_kind), dimension (nx_block,ny_block,max_blocks) :: & - work1 - - character(len=*), parameter :: subname = '(u2tgrid_vector)' - - work1(:,:,:) = work(:,:,:) - - call ice_timer_start(timer_bound) - call ice_HaloUpdate (work1, halo_info, & - field_loc_NEcorner, field_type_vector) - call ice_timer_stop(timer_bound) - - call to_tgrid(work1,work) - - end subroutine u2tgrid_vector - -!======================================================================= - -! Shifts quantities from the U-cell midpoint (work1) to the T-cell -! midpoint (work2) -! NOTE: Input array includes ghost cells that must be updated before -! calling this routine. -! -! author: Elizabeth C. Hunke, LANL - - subroutine to_tgrid(work1, work2) - - use ice_constants, only: p25 - - real (kind=dbl_kind) :: work1(nx_block,ny_block,max_blocks), & - work2(nx_block,ny_block,max_blocks) - - ! local variables - - integer (kind=int_kind) :: & - i, j, iblk, & - ilo,ihi,jlo,jhi ! beginning and end of physical domain - - type (block) :: & - this_block ! block information for current block - - character(len=*), parameter :: subname = '(to_tgrid)' + select case (trim(dir)) - !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) - do iblk = 1, nblocks - this_block = get_block(blocks_ice(iblk),iblk) - ilo = this_block%ilo - ihi = this_block%ihi - jlo = this_block%jlo - jhi = this_block%jhi + case('NE') + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + do j = jlo, jhi + do i = ilo, ihi + work2(i,j,iblk) = p25 * & + (work1(i, j, iblk)*area1(i, j, iblk) & + + work1(i+1,j, iblk)*area1(i+1,j, iblk) & + + work1(i, j+1,iblk)*area1(i, j+1,iblk) & + + work1(i+1,j+1,iblk)*area1(i+1,j+1,iblk)) & + / area2(i, j, iblk) + enddo + enddo + enddo + !$OMP END PARALLEL DO + + case('SW') + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + do j = jlo, jhi + do i = ilo, ihi + work2(i,j,iblk) = p25 * & + (work1(i, j, iblk) * area1(i, j, iblk) & + + work1(i-1,j, iblk) * area1(i-1,j, iblk) & + + work1(i, j-1,iblk) * area1(i, j-1,iblk) & + + work1(i-1,j-1,iblk) * area1(i-1,j-1,iblk)) & + / area2(i, j, iblk) + enddo + enddo + enddo + !$OMP END PARALLEL DO + + case('NW') + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + do j = jlo, jhi + do i = ilo, ihi + work2(i,j,iblk) = p25 * & + (work1(i-1,j, iblk)*area1(i-1,j, iblk) & + + work1(i, j, iblk)*area1(i, j, iblk) & + + work1(i-1,j+1,iblk)*area1(i-1,j+1,iblk) & + + work1(i, j+1,iblk)*area1(i ,j+1,iblk)) & + / area2(i, j, iblk) + enddo + enddo + enddo + !$OMP END PARALLEL DO + + case('SE') + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + do j = jlo, jhi + do i = ilo, ihi + work2(i,j,iblk) = p25 * & + (work1(i ,j-1,iblk) * area1(i ,j-1,iblk)) & + + work1(i+1,j-1,iblk) * area1(i+1,j-1,iblk) & + + work1(i ,j ,iblk) * area1(i ,j, iblk) & + + work1(i+1,j ,iblk) * area1(i+1,j, iblk) & + / area2(i, j, iblk) + enddo + enddo + enddo + !$OMP END PARALLEL DO + + case('E') + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + do j = jlo, jhi + do i = ilo, ihi + work2(i,j,iblk) = p5 * & + (work1(i, j,iblk)*area1(i, j,iblk) & + + work1(i+1,j,iblk)*area1(i+1,j,iblk)) & + / area2(i, j,iblk) + enddo + enddo + enddo + !$OMP END PARALLEL DO + + case('W') + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + do j = jlo, jhi + do i = ilo, ihi + work2(i,j,iblk) = p5 * & + (work1(i-1,j,iblk)*area1(i-1,j,iblk) & + + work1(i, j,iblk)*area1(i, j,iblk)) & + / area2(i, j,iblk) + enddo + enddo + enddo + !$OMP END PARALLEL DO + + case('N') + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + do j = jlo, jhi + do i = ilo, ihi + work2(i,j,iblk) = p5 * & + (work1(i,j, iblk)*area1(i,j, iblk) & + + work1(i,j+1,iblk)*area1(i,j+1,iblk)) & + / area2(i, j,iblk) + enddo + enddo + enddo + !$OMP END PARALLEL DO + + case('S') + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + do j = jlo, jhi + do i = ilo, ihi + work2(i,j,iblk) = p5 * & + (work1(i,j-1,iblk)*area1(i,j-1,iblk) & + + work1(i,j, iblk)*area1(i,j, iblk)) & + / area2(i, j,iblk) + enddo + enddo + enddo + !$OMP END PARALLEL DO - do j = jlo, jhi - do i = ilo, ihi - work2(i,j,iblk) = p25 * & - (work1(i, j ,iblk) * uarea(i, j, iblk) & - + work1(i-1,j ,iblk) * uarea(i-1,j, iblk) & - + work1(i, j-1,iblk) * uarea(i, j-1,iblk) & - + work1(i-1,j-1,iblk) * uarea(i-1,j-1,iblk)) & - / tarea(i, j, iblk) - enddo - enddo - enddo - !$OMP END PARALLEL DO + case default + call abort_ice(subname//'ERROR: unknown dir '//trim(dir)) + end select - end subroutine to_tgrid + end subroutine grid_average_X2Y_compute !======================================================================= ! The following code is used for obtaining the coordinates of the grid diff --git a/cicecore/drivers/mct/cesm1/ice_comp_esmf.F90 b/cicecore/drivers/mct/cesm1/ice_comp_esmf.F90 index 08681d84f..b0a78bfcd 100644 --- a/cicecore/drivers/mct/cesm1/ice_comp_esmf.F90 +++ b/cicecore/drivers/mct/cesm1/ice_comp_esmf.F90 @@ -44,7 +44,7 @@ module ice_comp_esmf use ice_domain, only : nblocks, blocks_ice, halo_info, distrb_info use ice_blocks, only : block, get_block, nx_block, ny_block use ice_grid, only : tlon, tlat, tarea, tmask, anglet, hm, & - grid_type, t2ugrid_vector, gridcpl_file, ocn_gridcell_frac + grid_type, gridcpl_file, ocn_gridcell_frac use ice_constants, only : c0, c1, spval_dbl, rad_to_deg, radius, secday use ice_communicate, only : my_task, master_task, MPI_COMM_ICE use ice_calendar, only : istep, istep1, force_restart_now, write_ic,& diff --git a/cicecore/drivers/mct/cesm1/ice_comp_mct.F90 b/cicecore/drivers/mct/cesm1/ice_comp_mct.F90 index 64dff54e2..d663d0f97 100644 --- a/cicecore/drivers/mct/cesm1/ice_comp_mct.F90 +++ b/cicecore/drivers/mct/cesm1/ice_comp_mct.F90 @@ -42,7 +42,7 @@ module ice_comp_mct use ice_domain, only : nblocks, blocks_ice, halo_info, distrb_info use ice_blocks, only : block, get_block, nx_block, ny_block use ice_grid, only : tlon, tlat, tarea, tmask, anglet, hm, & - grid_type, t2ugrid_vector, gridcpl_file, ocn_gridcell_frac + grid_type, gridcpl_file, ocn_gridcell_frac use ice_constants, only : c0, c1, spval_dbl, radius use ice_constants, only : ice_init_constants use ice_communicate, only : my_task, master_task, MPI_COMM_ICE diff --git a/cicecore/drivers/mct/cesm1/ice_import_export.F90 b/cicecore/drivers/mct/cesm1/ice_import_export.F90 index d42d3f8a1..d0eac5a19 100644 --- a/cicecore/drivers/mct/cesm1/ice_import_export.F90 +++ b/cicecore/drivers/mct/cesm1/ice_import_export.F90 @@ -29,7 +29,7 @@ module ice_import_export use ice_domain , only: nblocks, blocks_ice, halo_info, distrb_info use ice_domain_size , only: nx_global, ny_global, block_size_x, block_size_y, max_blocks use ice_grid , only: tlon, tlat, tarea, tmask, anglet, hm - use ice_grid , only: grid_type, t2ugrid_vector + use ice_grid , only: grid_type, grid_average_X2Y use ice_boundary , only: ice_HaloUpdate use ice_communicate , only: my_task, master_task, MPI_COMM_ICE, get_num_procs use ice_calendar , only: istep, istep1, diagfreq @@ -468,10 +468,14 @@ subroutine ice_import( x2i ) if (.not.prescribed_ice) then call t_startf ('cice_imp_t2u') - call t2ugrid_vector(uocn) - call t2ugrid_vector(vocn) - call t2ugrid_vector(ss_tltx) - call t2ugrid_vector(ss_tlty) + call ice_HaloUpdate(uocn, halo_info, field_loc_center, field_type_scalar) + call ice_HaloUpdate(vocn, halo_info, field_loc_center, field_type_scalar) + call ice_HaloUpdate(ss_tltx, halo_info, field_loc_center, field_type_scalar) + call ice_HaloUpdate(ss_tlty, halo_info, field_loc_center, field_type_scalar) + call grid_average_X2Y('T2U',uocn) + call grid_average_X2Y('T2U',vocn) + call grid_average_X2Y('T2U',ss_tltx) + call grid_average_X2Y('T2U',ss_tlty) call t_stopf ('cice_imp_t2u') end if diff --git a/cicecore/drivers/nuopc/cmeps/ice_import_export.F90 b/cicecore/drivers/nuopc/cmeps/ice_import_export.F90 index 62ff2727d..50cba8883 100644 --- a/cicecore/drivers/nuopc/cmeps/ice_import_export.F90 +++ b/cicecore/drivers/nuopc/cmeps/ice_import_export.F90 @@ -25,7 +25,7 @@ module ice_import_export use ice_flux , only : sss, Tf, wind, fsw use ice_state , only : vice, vsno, aice, aicen_init, trcr use ice_grid , only : tlon, tlat, tarea, tmask, anglet, hm - use ice_grid , only : grid_type, t2ugrid_vector + use ice_grid , only : grid_type, grid_average_X2Y use ice_mesh_mod , only : ocn_gridcell_frac use ice_boundary , only : ice_HaloUpdate use ice_fileunits , only : nu_diag, flush_fileunit @@ -797,10 +797,14 @@ subroutine ice_import( importState, rc ) if (.not.prescribed_ice) then call t_startf ('cice_imp_t2u') - call t2ugrid_vector(uocn) - call t2ugrid_vector(vocn) - call t2ugrid_vector(ss_tltx) - call t2ugrid_vector(ss_tlty) + call ice_HaloUpdate(uocn, halo_info, field_loc_center, field_type_scalar) + call ice_HaloUpdate(vocn, halo_info, field_loc_center, field_type_scalar) + call ice_HaloUpdate(ss_tltx, halo_info, field_loc_center, field_type_scalar) + call ice_HaloUpdate(ss_tlty, halo_info, field_loc_center, field_type_scalar) + call grid_average_X2Y('T2U',uocn) + call grid_average_X2Y('T2U',vocn) + call grid_average_X2Y('T2U',ss_tltx) + call grid_average_X2Y('T2U',ss_tlty) call t_stopf ('cice_imp_t2u') end if diff --git a/cicecore/drivers/nuopc/dmi/cice_cap.info b/cicecore/drivers/nuopc/dmi/cice_cap.info index 49127cc15..d1eee8ae0 100644 --- a/cicecore/drivers/nuopc/dmi/cice_cap.info +++ b/cicecore/drivers/nuopc/dmi/cice_cap.info @@ -18,7 +18,7 @@ module cice_cap use ice_calendar, only: dt use ice_flux use ice_grid, only: TLAT, TLON, ULAT, ULON, hm, tarea, ANGLET, ANGLE, & - dxt, dyt, t2ugrid_vector + dxt, dyt, grid_average_X2Y use ice_state use CICE_RunMod use CICE_InitMod @@ -934,12 +934,17 @@ module cice_cap ss_tlty(i,j,iblk) = ue*sin(AngT_s) + vn*cos(AngT_s) enddo enddo - call t2ugrid_vector(ss_tltx) - call t2ugrid_vector(ss_tlty) - call t2ugrid_vector(uocn) - call t2ugrid_vector(vocn) enddo +! call ice_HaloUpdate(uocn, halo_info, field_loc_center, field_type_scalar) +! call ice_HaloUpdate(vocn, halo_info, field_loc_center, field_type_scalar) +! call ice_HaloUpdate(ss_tltx, halo_info, field_loc_center, field_type_scalar) +! call ice_HaloUpdate(ss_tlty, halo_info, field_loc_center, field_type_scalar) + call grid_average_X2Y('T2U',uocn) + call grid_average_X2Y('T2U',vocn) + call grid_average_X2Y('T2U',ss_tltx) + call grid_average_X2Y('T2U',ss_tlty) + end subroutine subroutine CICE_Export(st,rc) type(ESMF_State) :: st From f37f4fd68b5ecd80cfe7b3d47e3410c77d381ee2 Mon Sep 17 00:00:00 2001 From: apcraig Date: Wed, 3 Nov 2021 18:32:16 -0600 Subject: [PATCH 04/17] add gridavgchk, add blockall, add set_nml.dwblockall --- .../cicedynB/infrastructure/ice_domain.F90 | 1 + cicecore/cicedynB/infrastructure/ice_grid.F90 | 4 +- .../unittest/gridavgchk/CICE_InitMod.F90 | 486 ++++++++++++++++++ .../unittest/gridavgchk/gridavgchk.F90 | 416 +++++++++++++++ configuration/scripts/Makefile | 6 +- .../scripts/options/set_env.gridavgchk | 2 + .../scripts/options/set_nml.dwblockall | 1 + configuration/scripts/tests/unittest_suite.ts | 2 + doc/source/user_guide/ug_case_settings.rst | 3 +- doc/source/user_guide/ug_implementation.rst | 4 +- 10 files changed, 919 insertions(+), 6 deletions(-) create mode 100644 cicecore/drivers/unittest/gridavgchk/CICE_InitMod.F90 create mode 100644 cicecore/drivers/unittest/gridavgchk/gridavgchk.F90 create mode 100644 configuration/scripts/options/set_env.gridavgchk create mode 100644 configuration/scripts/options/set_nml.dwblockall diff --git a/cicecore/cicedynB/infrastructure/ice_domain.F90 b/cicecore/cicedynB/infrastructure/ice_domain.F90 index 1dfdd0428..ae6e83195 100644 --- a/cicecore/cicedynB/infrastructure/ice_domain.F90 +++ b/cicecore/cicedynB/infrastructure/ice_domain.F90 @@ -523,6 +523,7 @@ subroutine init_domain_distribution(KMTG,ULATG) #else if (distribution_wght == 'block' .and. & ! POP style nocn(n) > 0) nocn(n) = nx_block*ny_block + if (distribution_wght == 'blockall') nocn(n) = nx_block*ny_block #endif end do endif ! distribution_wght = file diff --git a/cicecore/cicedynB/infrastructure/ice_grid.F90 b/cicecore/cicedynB/infrastructure/ice_grid.F90 index 7a80d963f..70329bfe7 100644 --- a/cicecore/cicedynB/infrastructure/ice_grid.F90 +++ b/cicecore/cicedynB/infrastructure/ice_grid.F90 @@ -2323,10 +2323,10 @@ subroutine grid_average_X2Y_compute(dir,work1,area1,work2,area2) do j = jlo, jhi do i = ilo, ihi work2(i,j,iblk) = p25 * & - (work1(i ,j-1,iblk) * area1(i ,j-1,iblk)) & + (work1(i ,j-1,iblk) * area1(i ,j-1,iblk) & + work1(i+1,j-1,iblk) * area1(i+1,j-1,iblk) & + work1(i ,j ,iblk) * area1(i ,j, iblk) & - + work1(i+1,j ,iblk) * area1(i+1,j, iblk) & + + work1(i+1,j ,iblk) * area1(i+1,j, iblk)) & / area2(i, j, iblk) enddo enddo diff --git a/cicecore/drivers/unittest/gridavgchk/CICE_InitMod.F90 b/cicecore/drivers/unittest/gridavgchk/CICE_InitMod.F90 new file mode 100644 index 000000000..60f71fa8a --- /dev/null +++ b/cicecore/drivers/unittest/gridavgchk/CICE_InitMod.F90 @@ -0,0 +1,486 @@ +!======================================================================= +! +! This module contains the CICE initialization routine that sets model +! parameters and initializes the grid and CICE state variables. +! +! authors Elizabeth C. Hunke, LANL +! William H. Lipscomb, LANL +! Philip W. Jones, LANL +! +! 2006: Converted to free form source (F90) by Elizabeth Hunke +! 2008: E. Hunke moved ESMF code to its own driver + + module CICE_InitMod + + use ice_kinds_mod + use ice_exit, only: abort_ice + use ice_fileunits, only: init_fileunits, nu_diag + use icepack_intfc, only: icepack_aggregate + use icepack_intfc, only: icepack_init_itd, icepack_init_itd_hist + use icepack_intfc, only: icepack_init_fsd_bounds, icepack_init_wave + use icepack_intfc, only: icepack_configure + use icepack_intfc, only: icepack_warnings_flush, icepack_warnings_aborted + use icepack_intfc, only: icepack_query_parameters, icepack_query_tracer_flags, & + icepack_query_tracer_indices, icepack_query_tracer_sizes + + implicit none + private + public :: CICE_Initialize, cice_init + +!======================================================================= + + contains + +!======================================================================= + +! Initialize the basic state, grid and all necessary parameters for +! running the CICE model. Return the initial state in routine +! export state. +! Note: This initialization driver is designed for standalone and +! CESM-coupled applications. For other +! applications (e.g., standalone CAM), this driver would be +! replaced by a different driver that calls subroutine cice_init, +! where most of the work is done. + + subroutine CICE_Initialize + + character(len=*), parameter :: subname='(CICE_Initialize)' + !-------------------------------------------------------------------- + ! model initialization + !-------------------------------------------------------------------- + + call cice_init + + end subroutine CICE_Initialize + +!======================================================================= +! +! Initialize CICE model. + + subroutine cice_init + + use ice_arrays_column, only: hin_max, c_hi_range, alloc_arrays_column + use ice_arrays_column, only: floe_rad_l, floe_rad_c, & + floe_binwidth, c_fsd_range + use ice_state, only: alloc_state + use ice_flux_bgc, only: alloc_flux_bgc + use ice_calendar, only: dt, dt_dyn, istep, istep1, write_ic, & + init_calendar, advance_timestep, calc_timesteps + use ice_communicate, only: init_communicate, my_task, master_task + use ice_diagnostics, only: init_diags + use ice_domain, only: init_domain_blocks + use ice_domain_size, only: ncat, nfsd + use ice_dyn_eap, only: init_eap, alloc_dyn_eap + use ice_dyn_shared, only: kdyn, init_dyn, alloc_dyn_shared + use ice_dyn_vp, only: init_vp + use ice_flux, only: init_coupler_flux, init_history_therm, & + init_history_dyn, init_flux_atm, init_flux_ocn, alloc_flux + use ice_forcing, only: init_forcing_ocn, init_forcing_atmo, & + get_forcing_atmo, get_forcing_ocn, get_wave_spec + use ice_forcing_bgc, only: get_forcing_bgc, get_atm_bgc, & + faero_default, faero_optics, alloc_forcing_bgc, fiso_default + use ice_grid, only: init_grid1, init_grid2, alloc_grid + use ice_history, only: init_hist, accum_hist + use ice_restart_shared, only: restart, runtype + use ice_init, only: input_data, init_state + use ice_init_column, only: init_thermo_vertical, init_shortwave, init_zbgc, input_zbgc, count_tracers + use ice_kinds_mod + use ice_restoring, only: ice_HaloRestore_init + use ice_timers, only: timer_total, init_ice_timers, ice_timer_start + use ice_transport_driver, only: init_transport + + logical(kind=log_kind) :: tr_aero, tr_zaero, skl_bgc, z_tracers, & + tr_iso, tr_fsd, wave_spec + character(len=*), parameter :: subname = '(cice_init)' + + call init_communicate ! initial setup for message passing + call init_fileunits ! unit numbers + + ! tcx debug, this will create a different logfile for each pe + ! if (my_task /= master_task) nu_diag = 100+my_task + + call icepack_configure() ! initialize icepack + call icepack_warnings_flush(nu_diag) + if (icepack_warnings_aborted()) call abort_ice(trim(subname), & + file=__FILE__,line= __LINE__) + + call input_data ! namelist variables + call input_zbgc ! vertical biogeochemistry namelist + call count_tracers ! count tracers + + call init_domain_blocks ! set up block decomposition + call init_grid1 ! domain distribution + call alloc_grid ! allocate grid arrays + call alloc_arrays_column ! allocate column arrays + call alloc_state ! allocate state arrays + call alloc_dyn_shared ! allocate dyn shared arrays + call alloc_flux_bgc ! allocate flux_bgc arrays + call alloc_flux ! allocate flux arrays + call init_ice_timers ! initialize all timers + call ice_timer_start(timer_total) ! start timing entire run + call init_grid2 ! grid variables + call init_zbgc ! vertical biogeochemistry initialization + call init_calendar ! initialize some calendar stuff + call init_hist (dt) ! initialize output history file + + call init_dyn (dt_dyn) ! define dynamics parameters, variables + if (kdyn == 2) then + call alloc_dyn_eap ! allocate dyn_eap arrays + call init_eap ! define eap dynamics parameters, variables + else if (kdyn == 3) then + call init_vp ! define vp dynamics parameters, variables + endif + + call init_coupler_flux ! initialize fluxes exchanged with coupler + + call init_thermo_vertical ! initialize vertical thermodynamics + + call icepack_init_itd(ncat=ncat, hin_max=hin_max) ! ice thickness distribution + if (my_task == master_task) then + call icepack_init_itd_hist(ncat=ncat, hin_max=hin_max, c_hi_range=c_hi_range) ! output + endif + + call icepack_query_tracer_flags(tr_fsd_out=tr_fsd) + call icepack_warnings_flush(nu_diag) + if (icepack_warnings_aborted()) call abort_ice(trim(subname), & + file=__FILE__,line= __LINE__) + + if (tr_fsd) call icepack_init_fsd_bounds (nfsd, & ! floe size distribution + floe_rad_l, & ! fsd size lower bound in m (radius) + floe_rad_c, & ! fsd size bin centre in m (radius) + floe_binwidth, & ! fsd size bin width in m (radius) + c_fsd_range, & ! string for history output + write_diags=(my_task == master_task)) ! write diag on master only + + call icepack_warnings_flush(nu_diag) + if (icepack_warnings_aborted()) call abort_ice(error_message=subname, & + file=__FILE__, line=__LINE__) + + call init_forcing_ocn(dt) ! initialize sss and sst from data + call init_state ! initialize the ice state + call init_transport ! initialize horizontal transport + call ice_HaloRestore_init ! restored boundary conditions + + call icepack_query_parameters(skl_bgc_out=skl_bgc, z_tracers_out=z_tracers, & + wave_spec_out=wave_spec) + call icepack_warnings_flush(nu_diag) + if (icepack_warnings_aborted()) call abort_ice(trim(subname), & + file=__FILE__,line= __LINE__) + + if (skl_bgc .or. z_tracers) call alloc_forcing_bgc ! allocate biogeochemistry arrays + + call init_restart ! initialize restart variables + call init_diags ! initialize diagnostic output points + call init_history_therm ! initialize thermo history variables + call init_history_dyn ! initialize dynamic history variables + call calc_timesteps ! update timestep counter if not using npt_unit="1" + + call icepack_query_tracer_flags(tr_aero_out=tr_aero, tr_zaero_out=tr_zaero) + call icepack_query_tracer_flags(tr_iso_out=tr_iso) + call icepack_warnings_flush(nu_diag) + if (icepack_warnings_aborted()) call abort_ice(trim(subname), & + file=__FILE__,line= __LINE__) + + if (tr_aero .or. tr_zaero) call faero_optics !initialize aerosol optical + !property tables + + ! Initialize shortwave components using swdn from previous timestep + ! if restarting. These components will be scaled to current forcing + ! in prep_radiation. + if (trim(runtype) == 'continue' .or. restart) & + call init_shortwave ! initialize radiative transfer + +! tcraig, use advance_timestep here +! istep = istep + 1 ! update time step counters +! istep1 = istep1 + 1 +! time = time + dt ! determine the time and date +! call calendar(time) ! at the end of the first timestep + call advance_timestep() + + !-------------------------------------------------------------------- + ! coupler communication or forcing data initialization + !-------------------------------------------------------------------- + + call init_forcing_atmo ! initialize atmospheric forcing (standalone) + + if (tr_fsd .and. wave_spec) call get_wave_spec ! wave spectrum in ice + call get_forcing_atmo ! atmospheric forcing from data + call get_forcing_ocn(dt) ! ocean forcing from data + + ! isotopes + if (tr_iso) call fiso_default ! default values + ! aerosols + ! if (tr_aero) call faero_data ! data file + ! if (tr_zaero) call fzaero_data ! data file (gx1) + if (tr_aero .or. tr_zaero) call faero_default ! default values + if (skl_bgc .or. z_tracers) call get_forcing_bgc ! biogeochemistry + if (z_tracers) call get_atm_bgc ! biogeochemistry + + if (runtype == 'initial' .and. .not. restart) & + call init_shortwave ! initialize radiative transfer using current swdn + + call init_flux_atm ! initialize atmosphere fluxes sent to coupler + call init_flux_ocn ! initialize ocean fluxes sent to coupler + + if (write_ic) call accum_hist(dt) ! write initial conditions + + end subroutine cice_init + +!======================================================================= + + subroutine init_restart + + use ice_arrays_column, only: dhsn + use ice_blocks, only: nx_block, ny_block + use ice_calendar, only: calendar + use ice_constants, only: c0 + use ice_domain, only: nblocks + use ice_domain_size, only: ncat, n_iso, n_aero, nfsd + use ice_dyn_eap, only: read_restart_eap + use ice_dyn_shared, only: kdyn + use ice_grid, only: tmask + use ice_init, only: ice_ic + use ice_init_column, only: init_age, init_FY, init_lvl, & + init_meltponds_cesm, init_meltponds_lvl, init_meltponds_topo, & + init_isotope, init_aerosol, init_hbrine, init_bgc, init_fsd + use ice_restart_column, only: restart_age, read_restart_age, & + restart_FY, read_restart_FY, restart_lvl, read_restart_lvl, & + restart_pond_cesm, read_restart_pond_cesm, & + restart_pond_lvl, read_restart_pond_lvl, & + restart_pond_topo, read_restart_pond_topo, & + restart_fsd, read_restart_fsd, & + restart_iso, read_restart_iso, & + restart_aero, read_restart_aero, & + restart_hbrine, read_restart_hbrine, & + restart_zsal, restart_bgc + use ice_restart_driver, only: restartfile + use ice_restart_shared, only: runtype, restart + use ice_state ! almost everything + + integer(kind=int_kind) :: & + i, j , & ! horizontal indices + iblk ! block index + logical(kind=log_kind) :: & + tr_iage, tr_FY, tr_lvl, tr_pond_cesm, tr_pond_lvl, & + tr_pond_topo, tr_fsd, tr_iso, tr_aero, tr_brine, & + skl_bgc, z_tracers, solve_zsal + integer(kind=int_kind) :: & + ntrcr + integer(kind=int_kind) :: & + nt_alvl, nt_vlvl, nt_apnd, nt_hpnd, nt_ipnd, & + nt_iage, nt_FY, nt_aero, nt_fsd, nt_isosno, nt_isoice + + character(len=*), parameter :: subname = '(init_restart)' + + call icepack_query_tracer_sizes(ntrcr_out=ntrcr) + call icepack_warnings_flush(nu_diag) + if (icepack_warnings_aborted()) call abort_ice(error_message=subname, & + file=__FILE__, line=__LINE__) + + call icepack_query_parameters(skl_bgc_out=skl_bgc, & + z_tracers_out=z_tracers, solve_zsal_out=solve_zsal) + call icepack_query_tracer_flags(tr_iage_out=tr_iage, tr_FY_out=tr_FY, & + tr_lvl_out=tr_lvl, tr_pond_cesm_out=tr_pond_cesm, tr_pond_lvl_out=tr_pond_lvl, & + tr_pond_topo_out=tr_pond_topo, tr_aero_out=tr_aero, tr_brine_out=tr_brine, & + tr_fsd_out=tr_fsd, tr_iso_out=tr_iso) + call icepack_query_tracer_indices(nt_alvl_out=nt_alvl, nt_vlvl_out=nt_vlvl, & + nt_apnd_out=nt_apnd, nt_hpnd_out=nt_hpnd, nt_ipnd_out=nt_ipnd, & + nt_iage_out=nt_iage, nt_FY_out=nt_FY, nt_aero_out=nt_aero, nt_fsd_out=nt_fsd, & + nt_isosno_out=nt_isosno, nt_isoice_out=nt_isoice) + call icepack_warnings_flush(nu_diag) + if (icepack_warnings_aborted()) call abort_ice(error_message=subname, & + file=__FILE__, line=__LINE__) + + if (trim(runtype) == 'continue') then + ! start from core restart file + call restartfile() ! given by pointer in ice_in + call calendar() ! update time parameters + if (kdyn == 2) call read_restart_eap ! EAP + else if (restart) then ! ice_ic = core restart file + call restartfile (ice_ic) ! or 'default' or 'none' + !!! uncomment to create netcdf + ! call restartfile_v4 (ice_ic) ! CICE v4.1 binary restart file + !!! uncomment if EAP restart data exists + ! if (kdyn == 2) call read_restart_eap + endif + + ! tracers + ! ice age tracer + if (tr_iage) then + if (trim(runtype) == 'continue') & + restart_age = .true. + if (restart_age) then + call read_restart_age + else + do iblk = 1, nblocks + call init_age(trcrn(:,:,nt_iage,:,iblk)) + enddo ! iblk + endif + endif + ! first-year area tracer + if (tr_FY) then + if (trim(runtype) == 'continue') restart_FY = .true. + if (restart_FY) then + call read_restart_FY + else + do iblk = 1, nblocks + call init_FY(trcrn(:,:,nt_FY,:,iblk)) + enddo ! iblk + endif + endif + ! level ice tracer + if (tr_lvl) then + if (trim(runtype) == 'continue') restart_lvl = .true. + if (restart_lvl) then + call read_restart_lvl + else + do iblk = 1, nblocks + call init_lvl(iblk,trcrn(:,:,nt_alvl,:,iblk), & + trcrn(:,:,nt_vlvl,:,iblk)) + enddo ! iblk + endif + endif + ! CESM melt ponds + if (tr_pond_cesm) then + if (trim(runtype) == 'continue') & + restart_pond_cesm = .true. + if (restart_pond_cesm) then + call read_restart_pond_cesm + else + do iblk = 1, nblocks + call init_meltponds_cesm(trcrn(:,:,nt_apnd,:,iblk), & + trcrn(:,:,nt_hpnd,:,iblk)) + enddo ! iblk + endif + endif + ! level-ice melt ponds + if (tr_pond_lvl) then + if (trim(runtype) == 'continue') & + restart_pond_lvl = .true. + if (restart_pond_lvl) then + call read_restart_pond_lvl + else + do iblk = 1, nblocks + call init_meltponds_lvl(trcrn(:,:,nt_apnd,:,iblk), & + trcrn(:,:,nt_hpnd,:,iblk), & + trcrn(:,:,nt_ipnd,:,iblk), & + dhsn(:,:,:,iblk)) + enddo ! iblk + endif + endif + ! topographic melt ponds + if (tr_pond_topo) then + if (trim(runtype) == 'continue') & + restart_pond_topo = .true. + if (restart_pond_topo) then + call read_restart_pond_topo + else + do iblk = 1, nblocks + call init_meltponds_topo(trcrn(:,:,nt_apnd,:,iblk), & + trcrn(:,:,nt_hpnd,:,iblk), & + trcrn(:,:,nt_ipnd,:,iblk)) + enddo ! iblk + endif ! .not. restart_pond + endif + ! floe size distribution + if (tr_fsd) then + if (trim(runtype) == 'continue') restart_fsd = .true. + if (restart_fsd) then + call read_restart_fsd + else + call init_fsd(trcrn(:,:,nt_fsd:nt_fsd+nfsd-1,:,:)) + endif + endif + + ! isotopes + if (tr_iso) then + if (trim(runtype) == 'continue') restart_iso = .true. + if (restart_iso) then + call read_restart_iso + else + do iblk = 1, nblocks + call init_isotope(trcrn(:,:,nt_isosno:nt_isosno+n_iso-1,:,iblk), & + trcrn(:,:,nt_isoice:nt_isoice+n_iso-1,:,iblk)) + enddo ! iblk + endif + endif + + if (tr_aero) then ! ice aerosol + if (trim(runtype) == 'continue') restart_aero = .true. + if (restart_aero) then + call read_restart_aero + else + do iblk = 1, nblocks + call init_aerosol(trcrn(:,:,nt_aero:nt_aero+4*n_aero-1,:,iblk)) + enddo ! iblk + endif ! .not. restart_aero + endif + + if (trim(runtype) == 'continue') then + if (tr_brine) & + restart_hbrine = .true. + if (solve_zsal) & + restart_zsal = .true. + if (skl_bgc .or. z_tracers) & + restart_bgc = .true. + endif + + if (tr_brine .or. skl_bgc) then ! brine height tracer + call init_hbrine + if (tr_brine .and. restart_hbrine) call read_restart_hbrine + endif + + if (solve_zsal .or. skl_bgc .or. z_tracers) then ! biogeochemistry + if (tr_fsd) then + write (nu_diag,*) 'FSD implementation incomplete for use with BGC' + call icepack_warnings_flush(nu_diag) + if (icepack_warnings_aborted()) call abort_ice(error_message=subname, & + file=__FILE__, line=__LINE__) + endif + call init_bgc + endif + + !----------------------------------------------------------------- + ! aggregate tracers + !----------------------------------------------------------------- + + !$OMP PARALLEL DO PRIVATE(iblk) + do iblk = 1, nblocks + do j = 1, ny_block + do i = 1, nx_block + if (tmask(i,j,iblk)) then + call icepack_aggregate(ncat = ncat, & + aicen = aicen(i,j,:,iblk), & + trcrn = trcrn(i,j,:,:,iblk), & + vicen = vicen(i,j,:,iblk), & + vsnon = vsnon(i,j,:,iblk), & + aice = aice (i,j, iblk), & + trcr = trcr (i,j,:,iblk), & + vice = vice (i,j, iblk), & + vsno = vsno (i,j, iblk), & + aice0 = aice0(i,j, iblk), & + ntrcr = ntrcr, & + trcr_depend = trcr_depend, & + trcr_base = trcr_base, & + n_trcr_strata = n_trcr_strata, & + nt_strata = nt_strata) + else + ! tcraig, reset all tracer values on land to zero + trcrn(i,j,:,:,iblk) = c0 + endif + enddo + enddo + enddo + !$OMP END PARALLEL DO + + call icepack_warnings_flush(nu_diag) + if (icepack_warnings_aborted()) call abort_ice(error_message=subname, & + file=__FILE__, line=__LINE__) + + end subroutine init_restart + +!======================================================================= + + end module CICE_InitMod + +!======================================================================= diff --git a/cicecore/drivers/unittest/gridavgchk/gridavgchk.F90 b/cicecore/drivers/unittest/gridavgchk/gridavgchk.F90 new file mode 100644 index 000000000..e4c650649 --- /dev/null +++ b/cicecore/drivers/unittest/gridavgchk/gridavgchk.F90 @@ -0,0 +1,416 @@ + + program gridavgchk + + ! This tests the CICE grid_average_X2Y methods by + ! using CICE_InitMod (from the standalone model) to read/initialize + ! a CICE grid/configuration. Then methods in grid_average_X2Y + ! are verified using hardwired inputs with known outputs. + + use CICE_InitMod + use ice_kinds_mod, only: int_kind, dbl_kind + use ice_blocks, only: block, get_block, nx_block, ny_block, nblocks_tot + use ice_boundary, only: ice_HaloUpdate + use ice_constants, only: c0, c1, c2, p25, & + field_loc_center, field_loc_NEcorner, & + field_loc_Nface, field_loc_Eface, field_type_scalar + use ice_communicate, only: my_task, master_task, get_num_procs, MPI_COMM_ICE + use ice_distribution, only: ice_distributionGetBlockID, ice_distributionGet + use ice_domain_size, only: nx_global, ny_global, & + block_size_x, block_size_y, max_blocks + use ice_domain, only: distrb_info, halo_info + use ice_fileunits, only: bfbflag + use ice_exit, only: abort_ice, end_run + use ice_global_reductions, only: global_minval, global_maxval + use ice_grid, only: grid_average_X2Y,tarea,uarea,narea,earea,tmask,umask,nmask,emask + + implicit none + + integer(int_kind) :: i, j, n, ib, ie, jb, je, iblock + integer(int_kind) :: iglob, jglob + integer(int_kind) :: blockID, numBlocks + type (block) :: this_block + + real(dbl_kind) ,allocatable :: array1x(:,:,:), array1y(:,:,:) + real(dbl_kind) ,allocatable :: array2x(:,:,:), array2y(:,:,:) + real(dbl_kind) ,allocatable :: array3x(:,:,:), array3y(:,:,:) + real(dbl_kind) :: amin, amax, errtol, errx, erry + real(dbl_kind) :: deltax0, deltay0, deltax, deltay + + integer(int_kind) :: npes, ierr, ntask, ntest + integer(int_kind), parameter :: maxtest = 36 + integer(int_kind) :: errorflag0,errorflag(maxtest),gflag + character(len=32) :: stringflag(maxtest) + integer(int_kind), parameter :: & + passflag = 0, & + failflag = 1 + integer(int_kind), parameter :: navg = 12 + character(len=8) :: avgname(navg) + logical, allocatable :: dmask(:,:,:,:) + + real(dbl_kind), parameter :: fillval = -1.0e36_dbl_kind + real(dbl_kind), parameter :: testconst = 100._dbl_kind + real(dbl_kind), parameter :: errtolconst = 0.01_dbl_kind ! error tolerance relative to const field + real(dbl_kind), parameter :: errtolijind = 0.65_dbl_kind ! absolute error tolerance for ij index field + real(dbl_kind), parameter :: errtolarea = 0.06_dbl_kind ! relative error tolerance for area field ratio + character(len=*), parameter :: subname='(gridavgchk)' + + !----------------------------------------------------------------- + ! Initialize CICE + !----------------------------------------------------------------- + + call CICE_Initialize + npes = get_num_procs() + + !----------------------------------------------------------------- + ! Testing + !----------------------------------------------------------------- + + if (my_task == master_task) then + write(6,*) ' ' + write(6,*) '==========================================================' + write(6,*) ' ' + write(6,*) 'RunningUnitTest GRIDAVGCHK' + write(6,*) ' ' + write(6,*) ' npes = ',npes + write(6,*) ' my_task = ',my_task + write(6,*) ' nx_global = ',nx_global + write(6,*) ' ny_global = ',ny_global + write(6,*) ' block_size_x = ',block_size_x + write(6,*) ' block_size_y = ',block_size_y + write(6,*) ' nblocks_tot = ',nblocks_tot + write(6,*) ' ' + endif + + errorflag0 = passflag + errorflag = passflag + stringflag = ' ' + + ! --------------------------- + ! TEST GRID AVERAGES + ! --------------------------- + + if (my_task == master_task) write(6,*) ' ' + + allocate(array1x(nx_block,ny_block,max_blocks)) + allocate(array1y(nx_block,ny_block,max_blocks)) + allocate(array2x(nx_block,ny_block,max_blocks)) + allocate(array2y(nx_block,ny_block,max_blocks)) + allocate(array3x(nx_block,ny_block,max_blocks)) + allocate(array3y(nx_block,ny_block,max_blocks)) + + call ice_distributionGet(distrb_info, numLocalBlocks = numBlocks) + + allocate(dmask(nx_block,ny_block,max_blocks,navg)) + avgname(1) = 'T2U'; dmask(:,:,:,1) = umask(:,:,:) + avgname(2) = 'T2N'; dmask(:,:,:,2) = nmask(:,:,:) + avgname(3) = 'T2E'; dmask(:,:,:,3) = emask(:,:,:) + avgname(4) = 'U2T'; dmask(:,:,:,4) = tmask(:,:,:) + avgname(5) = 'U2N'; dmask(:,:,:,5) = nmask(:,:,:) + avgname(6) = 'U2E'; dmask(:,:,:,6) = emask(:,:,:) + avgname(7) = 'N2T'; dmask(:,:,:,7) = tmask(:,:,:) + avgname(8) = 'N2U'; dmask(:,:,:,8) = umask(:,:,:) + avgname(9) = 'N2E'; dmask(:,:,:,9) = emask(:,:,:) + avgname(10) = 'E2T'; dmask(:,:,:,10) = tmask(:,:,:) + avgname(11) = 'E2U'; dmask(:,:,:,11) = umask(:,:,:) + avgname(12) = 'E2N'; dmask(:,:,:,12) = nmask(:,:,:) + + ntest = 0 + + !---------------- + ! Test constant field + !---------------- + + if (my_task == master_task) then + write(6,*) '' + write(6,*) 'TEST constant field' + endif + + array1x = testconst + + do n = 1,navg + ntest = ntest + 1 + + stringflag(ntest) = trim(avgname(n))//' const' + if (my_task == master_task) then + write(6,*) '' + write(6,*) trim(stringflag(ntest)),' test ',ntest + endif + + array2x = c0 + call grid_average_X2Y(trim(avgname(n)),array1x,array2x) + + array3x = c0 + do iblock = 1,numBlocks + call ice_distributionGetBlockID(distrb_info, iblock, blockID) + this_block = get_block(blockID, blockID) + ib = this_block%ilo + ie = this_block%ihi + jb = this_block%jlo + je = this_block%jhi + do j = jb,je + jglob = this_block%j_glob(j) + errtol = errtolconst * testconst + do i = ib,ie + iglob = this_block%i_glob(i) + array3x(i,j,iblock) = array2x(i,j,iblock) - array1x(i,j,iblock) + errx = abs(array3x(i,j,iblock)) + if (dmask(i,j,iblock,n) .and. errx > errtol) then + errorflag(ntest) = failflag + errorflag0 = failflag + write(100+my_task,*) '' + write(100+my_task,100) 'error const '//trim(avgname(n)),my_task,iblock,i,j,iglob,jglob + write(100+my_task,101) 'value, error ',array2x(i,j,iblock),errx + endif + enddo + enddo + enddo + amin = global_minval(array1x, distrb_info) + amax = global_maxval(array1x, distrb_info) + if (my_task == master_task) write(6,102) 'input min/max = ',amin,amax + amin = global_minval(array2x, distrb_info, dmask(:,:,:,n)) + amax = global_maxval(array2x, distrb_info, dmask(:,:,:,n)) + if (my_task == master_task) write(6,102) 'result min/max = ',amin,amax + amin = global_minval(array3x, distrb_info, dmask(:,:,:,n)) + amax = global_maxval(array3x, distrb_info, dmask(:,:,:,n)) + if (my_task == master_task) write(6,102) 'error min/max = ',amin,amax + enddo + + !---------------- + ! Test global i, j fields + !---------------- + + if (my_task == master_task) then + write(6,*) '' + write(6,*) 'TEST global i, j fields' + endif + + do iblock = 1,numBlocks + call ice_distributionGetBlockID(distrb_info, iblock, blockID) + this_block = get_block(blockID, blockID) + ib = this_block%ilo + ie = this_block%ihi + jb = this_block%jlo + je = this_block%jhi +! write(6,*) 'tcx1x ',my_task,iblock,minval(this_block%i_glob(ib:ie)),maxval(this_block%i_glob(ib:ie)) +! write(6,*) 'tcx1y ',my_task,iblock,minval(this_block%j_glob(jb:je)),maxval(this_block%j_glob(jb:je)) + do j = jb,je + do i = ib,ie + array1x(i,j,iblock) = real(this_block%i_glob(i),kind=dbl_kind) + array1y(i,j,iblock) = real(this_block%j_glob(j),kind=dbl_kind) + enddo + enddo + enddo + + call ice_HaloUpdate(array1x, halo_info, field_loc_center, field_type_scalar, fillval) + call ice_HaloUpdate(array1y, halo_info, field_loc_center, field_type_scalar, fillval) + + do n = 1,navg + ntest = ntest + 1 + + stringflag(ntest) = trim(avgname(n))//' ijind' + if (my_task == master_task) then + write(6,*) '' + write(6,*) trim(stringflag(ntest)),' test ',ntest + endif + + deltax0 = 0.0_dbl_kind + deltay0 = 0.0_dbl_kind + if (avgname(n) == 'T2U' .or. & + avgname(n) == 'T2E' .or. & + avgname(n) == 'N2U' .or. & + avgname(n) == 'N2E') then + deltax0 = 0.5_dbl_kind + elseif (avgname(n) == 'U2T' .or. & + avgname(n) == 'U2N' .or. & + avgname(n) == 'E2T' .or. & + avgname(n) == 'E2N') then + deltax0 = -0.5_dbl_kind + endif + if (avgname(n) == 'T2U' .or. & + avgname(n) == 'T2N' .or. & + avgname(n) == 'E2U' .or. & + avgname(n) == 'E2N') then + deltay0 = 0.5_dbl_kind + elseif (avgname(n) == 'U2T' .or. & + avgname(n) == 'U2E' .or. & + avgname(n) == 'N2T' .or. & + avgname(n) == 'N2E') then + deltay0 = -0.5_dbl_kind + endif + + array2x = c0 + array2y = c0 + call grid_average_X2Y(trim(avgname(n)),array1x,array2x) + call grid_average_X2Y(trim(avgname(n)),array1y,array2y) + + array3x = c0 + errtol = errtolijind + do iblock = 1,numBlocks + call ice_distributionGetBlockID(distrb_info, iblock, blockID) + this_block = get_block(blockID, blockID) + ib = this_block%ilo + ie = this_block%ihi + jb = this_block%jlo + je = this_block%jhi + do j = jb,je + jglob = this_block%j_glob(j) + do i = ib,ie + iglob = this_block%i_glob(i) + deltax = deltax0 + deltay = deltay0 + ! adjust deltax at wraparound + if (iglob == 1 .and. deltax < -0.01_dbl_kind) deltax = deltax0 + nx_global/c2 + if (iglob == nx_global .and. deltax > 0.01_dbl_kind) deltax = deltax0 - nx_global/c2 + array3x(i,j,iblock) = array2x(i,j,iblock)-array1x(i,j,iblock)-deltax + errx = abs(array3x(i,j,iblock)) + array3y(i,j,iblock) = array2y(i,j,iblock)-array1y(i,j,iblock)-deltay + erry = abs(array3y(i,j,iblock)) + if (dmask(i,j,iblock,n) .and. (errx > errtol .or. erry > errtol)) then + errorflag(ntest) = failflag + errorflag0 = failflag + write(100+my_task,*) '' + write(100+my_task,100) 'error ijind '//trim(avgname(n)),my_task,iblock,i,j,iglob,jglob + write(100+my_task,101) 'array2x, err',array2x(i,j,iblock),errx + write(100+my_task,101) 'array1x j+1 ',array1x(i-1,j+1,iblock),array1x(i,j+1,iblock),array1x(i+1,j+1,iblock) + write(100+my_task,101) 'array1x j ',array1x(i-1,j ,iblock),array1x(i,j ,iblock),array1x(i+1,j ,iblock) + write(100+my_task,101) 'array1x j-1 ',array1x(i-1,j-1,iblock),array1x(i,j-1,iblock),array1x(i+1,j-1,iblock) + write(100+my_task,101) 'array2y, err',array2y(i,j,iblock),erry + write(100+my_task,101) 'array1y j+1 ',array1y(i-1,j+1,iblock),array1y(i,j+1,iblock),array1y(i+1,j+1,iblock) + write(100+my_task,101) 'array1y j ',array1y(i-1,j ,iblock),array1y(i,j ,iblock),array1y(i+1,j ,iblock) + write(100+my_task,101) 'array1y j-1 ',array1y(i-1,j-1,iblock),array1y(i,j-1,iblock),array1y(i+1,j-1,iblock) +! write(100+my_task,101) 'uarea ',uarea(i,j,iblock) +! write(100+my_task,101) 'tarea j+1 ',tarea (i-1,j+1,iblock),tarea (i,j+1,iblock),tarea (i+1,j+1,iblock) +! write(100+my_task,101) 'tarea j ',tarea (i-1,j ,iblock),tarea (i,j ,iblock),tarea (i+1,j ,iblock) +! write(100+my_task,101) 'tarea j-1 ',tarea (i-1,j-1,iblock),tarea (i,j-1,iblock),tarea (i+1,j-1,iblock) + endif + enddo + enddo + enddo + + amin = global_minval(array1x, distrb_info) + amax = global_maxval(array1x, distrb_info) + if (my_task == master_task) write(6,102) 'i_glob min/max = ',amin,amax + amin = global_minval(array1y, distrb_info) + amax = global_maxval(array1y, distrb_info) + if (my_task == master_task) write(6,102) 'j_glob min/max = ',amin,amax + amin = global_minval(array2x, distrb_info, dmask(:,:,:,n)) + amax = global_maxval(array2x, distrb_info, dmask(:,:,:,n)) + if (my_task == master_task) write(6,102) 'i result min/max = ',amin,amax + amin = global_minval(array2y, distrb_info, dmask(:,:,:,n)) + amax = global_maxval(array2y, distrb_info, dmask(:,:,:,n)) + if (my_task == master_task) write(6,102) 'j result min/max = ',amin,amax + amin = global_minval(array3x, distrb_info, dmask(:,:,:,n)) + amax = global_maxval(array3x, distrb_info, dmask(:,:,:,n)) + if (my_task == master_task) write(6,102) 'i error min/max = ',amin,amax + amin = global_minval(array3y, distrb_info, dmask(:,:,:,n)) + amax = global_maxval(array3y, distrb_info, dmask(:,:,:,n)) + if (my_task == master_task) write(6,102) 'j error min/max = ',amin,amax + + enddo + + !---------------- + ! Test area fields + !---------------- + + if (my_task == master_task) then + write(6,*) '' + write(6,*) 'TEST area fields' + endif + + do n = 1,navg + ntest = ntest + 1 + + stringflag(ntest) = trim(avgname(n))//' area' + if (my_task == master_task) then + write(6,*) '' + write(6,*) trim(stringflag(ntest)),' test ',ntest + endif + + array1x = tarea ! input + array2y = uarea ! result + call ice_HaloUpdate(array1x, halo_info, field_loc_center, field_type_scalar, fillval) + array2x = c0 + call grid_average_X2Y('T2U',array1x,array2x) + + array3x = c1 + array3y = c1 + + do iblock = 1,numBlocks + call ice_distributionGetBlockID(distrb_info, iblock, blockID) + this_block = get_block(blockID, blockID) + ib = this_block%ilo + ie = this_block%ihi + jb = this_block%jlo + je = this_block%jhi + do j = jb,je + jglob = this_block%j_glob(j) + do i = ib,ie + iglob = this_block%i_glob(i) + array3x(i,j,iblock) = array2x(i,j,iblock)/array2y(i,j,iblock) - c1 + errx = abs(array3x(i,j,iblock)) + if (dmask(i,j,iblock,n) .and. errx > errtolarea) then + errorflag(ntest) = failflag + errorflag0 = failflag + write(100+my_task,*) '' + write(100+my_task,100) 'error area '//trim(avgname(n)),my_task,iblock,i,j,iglob,jglob + write(100+my_task,101) 'out,exact,err',array2x(i,j,iblock),array2y(i,j,iblock),array3x(i,j,iblock) + endif + enddo + enddo + enddo + amin = global_minval(array1x, distrb_info) + amax = global_maxval(array1x, distrb_info) + if (my_task == master_task) write(6,103) 'input min/max = ',amin,amax + amin = global_minval(array2x, distrb_info, dmask(:,:,:,n)) + amax = global_maxval(array2x, distrb_info, dmask(:,:,:,n)) + if (my_task == master_task) write(6,103) 'output min/max = ',amin,amax + amin = global_minval(array2y, distrb_info, dmask(:,:,:,n)) + amax = global_maxval(array2y, distrb_info, dmask(:,:,:,n)) + if (my_task == master_task) write(6,103) 'exact min/max = ',amin,amax + amin = global_minval(array3x, distrb_info, dmask(:,:,:,n)) + amax = global_maxval(array3x, distrb_info, dmask(:,:,:,n)) + if (my_task == master_task) write(6,102) 'error min/max = ',amin,amax + enddo + +100 format(a,10i8) +101 format(a,3g16.7) +102 format(a,3f16.7) +103 format(a,2g16.7,f16.7) + + gflag = global_maxval(errorflag0, MPI_COMM_ICE) + errorflag0 = gflag + do n = 1,maxtest + gflag = global_maxval(errorflag(n), MPI_COMM_ICE) + errorflag(n) = gflag + enddo + + if (my_task == master_task) then + write(6,*) ' ' + write(6,*) 'GRIDAVGCHK COMPLETED SUCCESSFULLY' + do n = 1,maxtest + if (errorflag(n) == passflag) then + write(6,*) 'PASS ',trim(stringflag(n)) + else + write(6,*) 'FAIL ',trim(stringflag(n)) + endif + enddo + if (errorflag0 == passflag) then + write(6,*) 'GRIDAVGCHK TEST COMPLETED SUCCESSFULLY' + else + write(6,*) 'GRIDAVGCHK TEST FAILED' + endif + write(6,*) ' ' + write(6,*) '==========================================================' + write(6,*) ' ' + endif + + + !----------------------------------------------------------------- + ! Gracefully end + !----------------------------------------------------------------- + + call end_run() + + end program gridavgchk + +!======================================================================= diff --git a/configuration/scripts/Makefile b/configuration/scripts/Makefile index 51c36cee3..1633b1542 100644 --- a/configuration/scripts/Makefile +++ b/configuration/scripts/Makefile @@ -75,7 +75,7 @@ AR := ar .SUFFIXES: .SUFFIXES: .F90 .F .c .o -.PHONY: all cice libcice targets target db_files db_flags clean realclean helloworld calchk sumchk bcstchk +.PHONY: all cice libcice targets target db_files db_flags clean realclean helloworld calchk sumchk bcstchk gridavgchk all: $(EXEC) cice: $(EXEC) @@ -94,7 +94,7 @@ targets: @echo " " @echo "Supported Makefile Targets are: cice, libcice, makdep, depends, clean, realclean" @echo " Diagnostics: targets, db_files, db_flags" - @echo " Unit Tests : helloworld, calchk, sumchk, bcstchk" + @echo " Unit Tests : helloworld, calchk, sumchk, bcstchk, gridavgchk" target: targets db_files: @@ -150,6 +150,8 @@ sumchk: $(EXEC) bcstchk: $(EXEC) +gridavgchk: $(EXEC) + # this builds just a subset of source code specified explicitly and requires a separate target HWOBJS := helloworld.o diff --git a/configuration/scripts/options/set_env.gridavgchk b/configuration/scripts/options/set_env.gridavgchk new file mode 100644 index 000000000..740d1e9c3 --- /dev/null +++ b/configuration/scripts/options/set_env.gridavgchk @@ -0,0 +1,2 @@ +setenv ICE_DRVOPT unittest/gridavgchk +setenv ICE_TARGET gridavgchk diff --git a/configuration/scripts/options/set_nml.dwblockall b/configuration/scripts/options/set_nml.dwblockall new file mode 100644 index 000000000..161c86b01 --- /dev/null +++ b/configuration/scripts/options/set_nml.dwblockall @@ -0,0 +1 @@ +distribution_wght = 'blockall' diff --git a/configuration/scripts/tests/unittest_suite.ts b/configuration/scripts/tests/unittest_suite.ts index 21810a1e3..3f9a306c8 100644 --- a/configuration/scripts/tests/unittest_suite.ts +++ b/configuration/scripts/tests/unittest_suite.ts @@ -6,3 +6,5 @@ unittest gx3 1x1x25x29x16 sumchk unittest tx1 8x1 sumchk unittest gx3 4x1 bcstchk unittest gx3 1x1 bcstchk +unittest gx3 8x2 gridavgchk,dwblockall +unittest gx3 8x2 gridavgchk diff --git a/doc/source/user_guide/ug_case_settings.rst b/doc/source/user_guide/ug_case_settings.rst index 23e6951fc..9d8e5fbc7 100644 --- a/doc/source/user_guide/ug_case_settings.rst +++ b/doc/source/user_guide/ug_case_settings.rst @@ -278,7 +278,8 @@ domain_nml "", "``spacecurve``", "distribute blocks via space-filling curves", "" "", "``spiralcenter``", "distribute blocks via roundrobin from center of grid outward in a spiral", "" "", "``wghtfile``", "distribute blocks based on weights specified in ``distribution_wght_file``", "" - "``distribution_wght``", "``block``", "full block size distribution weight method", "``latitude``" + "``distribution_wght``", "``block``", "full block weight method with land block elimination", "``latitude``" + "", "``blockall``", "full block weight method without land block elimination", "" "", "``latitude``", "latitude/ocean sets ``work_per_block``", "" "``distribution_wght_file``", "string", "distribution weight file when distribution_type is ``wghtfile``", "'unknown'" "``ew_boundary_type``", "``cyclic``", "periodic boundary conditions in x-direction", "``cyclic``" diff --git a/doc/source/user_guide/ug_implementation.rst b/doc/source/user_guide/ug_implementation.rst index 650d3d6c7..3fb63c11d 100644 --- a/doc/source/user_guide/ug_implementation.rst +++ b/doc/source/user_guide/ug_implementation.rst @@ -452,7 +452,9 @@ block equally. This is useful in POP which always has work in each block and is written with a lot of array syntax requiring calculations over entire blocks (whether or not land is present). This option is provided in CICE as well for -direct-communication compatibility with POP. The ‘latitude’ option +direct-communication compatibility with POP. Block that contain 100% +land grid cells are eliminated with 'block'. The 'blockall' option is identical +to 'block' but does not do land block elimination. The ‘latitude’ option weights the blocks based on latitude and the number of ocean grid cells they contain. Many of the non-cartesian decompositions support automatic land block elimination and provide alternative ways to From 262eb60bbad672ff8b18a3d8a4960e5148e33400 Mon Sep 17 00:00:00 2001 From: apcraig Date: Fri, 5 Nov 2021 09:40:48 -0600 Subject: [PATCH 05/17] add X2YS and update gridavgchk --- .../cicedynB/infrastructure/ice_domain.F90 | 10 +- cicecore/cicedynB/infrastructure/ice_grid.F90 | 341 +++++++++++++++--- .../unittest/gridavgchk/gridavgchk.F90 | 188 +++++++--- .../scripts/machines/env.cheyenne_gnu | 2 +- .../scripts/machines/env.cheyenne_intel | 2 +- .../scripts/machines/env.cheyenne_pgi | 2 +- configuration/scripts/tests/unittest_suite.ts | 5 +- 7 files changed, 445 insertions(+), 105 deletions(-) diff --git a/cicecore/cicedynB/infrastructure/ice_domain.F90 b/cicecore/cicedynB/infrastructure/ice_domain.F90 index ae6e83195..ee7d98b50 100644 --- a/cicecore/cicedynB/infrastructure/ice_domain.F90 +++ b/cicecore/cicedynB/infrastructure/ice_domain.F90 @@ -63,6 +63,7 @@ module ice_domain maskhalo_dyn , & ! if true, use masked halo updates for dynamics maskhalo_remap , & ! if true, use masked halo updates for transport maskhalo_bound , & ! if true, use masked halo updates for bound_state + landblockelim , & ! if true, land block elimination is on orca_halogrid ! if true, input fields are haloed as defined by orca grid !----------------------------------------------------------------------- @@ -79,6 +80,7 @@ module ice_domain ! 'rake', 'spacecurve', etc distribution_wght ! method for weighting work per block ! 'block' = POP default configuration + ! 'blockall' = no land block elimination ! 'latitude' = no. ocean points * |lat| ! 'file' = read distribution_wgth_file character (char_len_long) :: & @@ -155,11 +157,12 @@ subroutine init_domain_blocks maskhalo_bound = .false. ! if true, use masked halos for bound_state add_mpi_barriers = .false. ! if true, throttle communication debug_blocks = .false. ! if true, print verbose block information - max_blocks = -1 ! max number of blocks per processor + max_blocks = -1 ! max number of blocks per processor block_size_x = -1 ! size of block in first horiz dimension block_size_y = -1 ! size of block in second horiz dimension nx_global = -1 ! NXGLOB, i-axis size ny_global = -1 ! NYGLOB, j-axis size + landblockelim = .true. ! on by default call get_fileunit(nu_nml) if (my_task == master_task) then @@ -446,6 +449,8 @@ subroutine init_domain_distribution(KMTG,ULATG) flat = 1 endif + if (distribution_wght == 'blockall') landblockelim = .false. + allocate(nocn(nblocks_tot)) if (distribution_wght == 'file') then @@ -523,7 +528,8 @@ subroutine init_domain_distribution(KMTG,ULATG) #else if (distribution_wght == 'block' .and. & ! POP style nocn(n) > 0) nocn(n) = nx_block*ny_block - if (distribution_wght == 'blockall') nocn(n) = nx_block*ny_block + if (distribution_wght == 'blockall') & + nocn(n) = nx_block*ny_block #endif end do endif ! distribution_wght = file diff --git a/cicecore/cicedynB/infrastructure/ice_grid.F90 b/cicecore/cicedynB/infrastructure/ice_grid.F90 index 70329bfe7..ce5d89dbc 100644 --- a/cicecore/cicedynB/infrastructure/ice_grid.F90 +++ b/cicecore/cicedynB/infrastructure/ice_grid.F90 @@ -677,7 +677,7 @@ end subroutine init_grid2 subroutine popgrid use ice_blocks, only: nx_block, ny_block - use ice_constants, only: c0, c1, & + use ice_constants, only: c0, c1, p5, & field_loc_center, field_loc_NEcorner, & field_type_scalar, field_type_angle use ice_domain_size, only: max_blocks @@ -725,7 +725,7 @@ subroutine popgrid do j = jlo, jhi do i = ilo, ihi kmt(i,j,iblk) = work1(i,j,iblk) - if (kmt(i,j,iblk) >= c1) hm(i,j,iblk) = c1 + if (kmt(i,j,iblk) >= p5) hm(i,j,iblk) = c1 enddo enddo enddo @@ -2175,30 +2175,58 @@ subroutine grid_average_X2Y(X2Y,work1,work2) select case (trim(X2Y)) - case('T2U') - call grid_average_X2Y_compute('NE',work1,tarea,work2tmp,uarea) - case('T2E') - call grid_average_X2Y_compute('E' ,work1,tarea,work2tmp,earea) - case('T2N') - call grid_average_X2Y_compute('N' ,work1,tarea,work2tmp,narea) - case('U2T') - call grid_average_X2Y_compute('SW',work1,uarea,work2tmp,tarea) - case('U2E') - call grid_average_X2Y_compute('S' ,work1,uarea,work2tmp,earea) - case('U2N') - call grid_average_X2Y_compute('W' ,work1,uarea,work2tmp,narea) - case('E2T') - call grid_average_X2Y_compute('W' ,work1,earea,work2tmp,tarea) - case('E2U') - call grid_average_X2Y_compute('N' ,work1,earea,work2tmp,uarea) - case('E2N') - call grid_average_X2Y_compute('NW',work1,earea,work2tmp,narea) - case('N2T') - call grid_average_X2Y_compute('S' ,work1,narea,work2tmp,tarea) - case('N2U') - call grid_average_X2Y_compute('E' ,work1,narea,work2tmp,uarea) - case('N2E') - call grid_average_X2Y_compute('SE',work1,narea,work2tmp,earea) + ! flux unmasked + case('T2UF','T2U') + call grid_average_X2YF('NE',work1,tarea,work2tmp,uarea) + case('T2EF','T2E') + call grid_average_X2YF('E' ,work1,tarea,work2tmp,earea) + case('T2NF','T2N') + call grid_average_X2YF('N' ,work1,tarea,work2tmp,narea) + case('U2TF','U2T') + call grid_average_X2YF('SW',work1,uarea,work2tmp,tarea) + case('U2EF','U2E') + call grid_average_X2YF('S' ,work1,uarea,work2tmp,earea) + case('U2NF','U2N') + call grid_average_X2YF('W' ,work1,uarea,work2tmp,narea) + case('E2TF','E2T') + call grid_average_X2YF('W' ,work1,earea,work2tmp,tarea) + case('E2UF','E2U') + call grid_average_X2YF('N' ,work1,earea,work2tmp,uarea) + case('E2NF','E2N') + call grid_average_X2YF('NW',work1,earea,work2tmp,narea) + case('N2TF','N2T') + call grid_average_X2YF('S' ,work1,narea,work2tmp,tarea) + case('N2UF','N2U') + call grid_average_X2YF('E' ,work1,narea,work2tmp,uarea) + case('N2EF','N2E') + call grid_average_X2YF('SE',work1,narea,work2tmp,earea) + + ! state masked + case('T2US') + call grid_average_X2YS('NE',work1,tarea,hm ,work2tmp) + case('T2ES') + call grid_average_X2YS('E' ,work1,tarea,hm ,work2tmp) + case('T2NS') + call grid_average_X2YS('N' ,work1,tarea,hm ,work2tmp) + case('U2TS') + call grid_average_X2YS('SW',work1,uarea,uvm,work2tmp) + case('U2ES') + call grid_average_X2YS('S' ,work1,uarea,uvm,work2tmp) + case('U2NS') + call grid_average_X2YS('W' ,work1,uarea,uvm,work2tmp) + case('E2TS') + call grid_average_X2YS('W' ,work1,earea,epm,work2tmp) + case('E2US') + call grid_average_X2YS('N' ,work1,earea,epm,work2tmp) + case('E2NS') + call grid_average_X2YS('NW',work1,earea,epm,work2tmp) + case('N2TS') + call grid_average_X2YS('S' ,work1,narea,npm,work2tmp) + case('N2US') + call grid_average_X2YS('E' ,work1,narea,npm,work2tmp) + case('N2ES') + call grid_average_X2YS('SE',work1,narea,npm,work2tmp) + case default call abort_ice(subname//'ERROR: unknown X2Y '//trim(X2Y)) end select @@ -2212,16 +2240,16 @@ subroutine grid_average_X2Y(X2Y,work1,work2) end subroutine grid_average_X2Y !======================================================================= - ! Shifts quantities from one grid to another +! State masked version, simple area weighted averager ! NOTE: Input array includes ghost cells that must be updated before ! calling this routine. ! ! author: T. Craig - subroutine grid_average_X2Y_compute(dir,work1,area1,work2,area2) + subroutine grid_average_X2YS(dir,work1,area1,mask1,work2) - use ice_constants, only: c0, p25, p5 + use ice_constants, only: c0 character(len=*) , intent(in) :: & dir @@ -2229,15 +2257,241 @@ subroutine grid_average_X2Y_compute(dir,work1,area1,work2,area2) real (kind=dbl_kind), intent(in) :: & work1(nx_block,ny_block,max_blocks), & area1(nx_block,ny_block,max_blocks), & - area2(nx_block,ny_block,max_blocks) + mask1(nx_block,ny_block,max_blocks) real (kind=dbl_kind), intent(out) :: & work2(nx_block,ny_block,max_blocks) + ! local variables + + integer (kind=int_kind) :: & + i, j, iblk, & + ilo,ihi,jlo,jhi ! beginning and end of physical domain + + real (kind=dbl_kind) :: & + wtmp + type (block) :: & this_block ! block information for current block - character(len=*), parameter :: subname = '(grid_average_X2Y_compute)' + character(len=*), parameter :: subname = '(grid_average_X2YS)' + + work2(:,:,:) = c0 + + select case (trim(dir)) + + case('NE') + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + do j = jlo, jhi + do i = ilo, ihi + wtmp = (mask1(i, j, iblk)*area1(i, j, iblk) & + + mask1(i+1,j, iblk)*area1(i+1,j, iblk) & + + mask1(i, j+1,iblk)*area1(i, j+1,iblk) & + + mask1(i+1,j+1,iblk)*area1(i+1,j+1,iblk)) + if (wtmp /= c0) & + work2(i,j,iblk) = (mask1(i, j, iblk)*work1(i, j, iblk)*area1(i, j, iblk) & + + mask1(i+1,j, iblk)*work1(i+1,j, iblk)*area1(i+1,j, iblk) & + + mask1(i, j+1,iblk)*work1(i, j+1,iblk)*area1(i, j+1,iblk) & + + mask1(i+1,j+1,iblk)*work1(i+1,j+1,iblk)*area1(i+1,j+1,iblk)) & + / wtmp + enddo + enddo + enddo + !$OMP END PARALLEL DO + + case('SW') + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + do j = jlo, jhi + do i = ilo, ihi + wtmp = (mask1(i, j, iblk)*area1(i, j, iblk) & + + mask1(i-1,j, iblk)*area1(i-1,j, iblk) & + + mask1(i, j-1,iblk)*area1(i, j-1,iblk) & + + mask1(i-1,j-1,iblk)*area1(i-1,j-1,iblk)) + if (wtmp /= c0) & + work2(i,j,iblk) = (mask1(i, j, iblk)*work1(i, j, iblk)*area1(i, j, iblk) & + + mask1(i-1,j, iblk)*work1(i-1,j, iblk)*area1(i-1,j, iblk) & + + mask1(i, j-1,iblk)*work1(i, j-1,iblk)*area1(i, j-1,iblk) & + + mask1(i-1,j-1,iblk)*work1(i-1,j-1,iblk)*area1(i-1,j-1,iblk)) & + / wtmp + enddo + enddo + enddo + !$OMP END PARALLEL DO + + case('NW') + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + do j = jlo, jhi + do i = ilo, ihi + wtmp = (mask1(i-1,j, iblk)*area1(i-1,j, iblk) & + + mask1(i, j, iblk)*area1(i, j, iblk) & + + mask1(i-1,j+1,iblk)*area1(i-1,j+1,iblk) & + + mask1(i, j+1,iblk)*area1(i ,j+1,iblk)) + if (wtmp /= c0) & + work2(i,j,iblk) = (mask1(i-1,j, iblk)*work1(i-1,j, iblk)*area1(i-1,j, iblk) & + + mask1(i, j, iblk)*work1(i, j, iblk)*area1(i, j, iblk) & + + mask1(i-1,j+1,iblk)*work1(i-1,j+1,iblk)*area1(i-1,j+1,iblk) & + + mask1(i, j+1,iblk)*work1(i, j+1,iblk)*area1(i ,j+1,iblk)) & + / wtmp + enddo + enddo + enddo + !$OMP END PARALLEL DO + + case('SE') + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + do j = jlo, jhi + do i = ilo, ihi + wtmp = (mask1(i ,j-1,iblk)*area1(i ,j-1,iblk) & + + mask1(i+1,j-1,iblk)*area1(i+1,j-1,iblk) & + + mask1(i ,j ,iblk)*area1(i ,j, iblk) & + + mask1(i+1,j ,iblk)*area1(i+1,j, iblk)) + if (wtmp /= c0) & + work2(i,j,iblk) = (mask1(i ,j-1,iblk)*work1(i ,j-1,iblk)*area1(i ,j-1,iblk) & + + mask1(i+1,j-1,iblk)*work1(i+1,j-1,iblk)*area1(i+1,j-1,iblk) & + + mask1(i ,j ,iblk)*work1(i ,j ,iblk)*area1(i ,j, iblk) & + + mask1(i+1,j ,iblk)*work1(i+1,j ,iblk)*area1(i+1,j, iblk)) & + / wtmp + enddo + enddo + enddo + !$OMP END PARALLEL DO + + case('E') + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + do j = jlo, jhi + do i = ilo, ihi + wtmp = (mask1(i, j,iblk)*area1(i, j,iblk) & + + mask1(i+1,j,iblk)*area1(i+1,j,iblk)) + if (wtmp /= c0) & + work2(i,j,iblk) = (mask1(i, j,iblk)*work1(i, j,iblk)*area1(i, j,iblk) & + + mask1(i+1,j,iblk)*work1(i+1,j,iblk)*area1(i+1,j,iblk)) & + / wtmp + enddo + enddo + enddo + !$OMP END PARALLEL DO + + case('W') + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + do j = jlo, jhi + do i = ilo, ihi + wtmp = (mask1(i-1,j,iblk)*area1(i-1,j,iblk) & + + mask1(i, j,iblk)*area1(i, j,iblk)) + if (wtmp /= c0) & + work2(i,j,iblk) = (mask1(i-1,j,iblk)*work1(i-1,j,iblk)*area1(i-1,j,iblk) & + + mask1(i, j,iblk)*work1(i, j,iblk)*area1(i, j,iblk)) & + / wtmp + enddo + enddo + enddo + !$OMP END PARALLEL DO + + case('N') + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + do j = jlo, jhi + do i = ilo, ihi + wtmp = (mask1(i,j, iblk)*area1(i,j, iblk) & + + mask1(i,j+1,iblk)*area1(i,j+1,iblk)) + if (wtmp /= c0) & + work2(i,j,iblk) = (mask1(i,j, iblk)*work1(i,j, iblk)*area1(i,j, iblk) & + + mask1(i,j+1,iblk)*work1(i,j+1,iblk)*area1(i,j+1,iblk)) & + / wtmp + enddo + enddo + enddo + !$OMP END PARALLEL DO + + case('S') + !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) + do iblk = 1, nblocks + this_block = get_block(blocks_ice(iblk),iblk) + ilo = this_block%ilo + ihi = this_block%ihi + jlo = this_block%jlo + jhi = this_block%jhi + do j = jlo, jhi + do i = ilo, ihi + wtmp = (mask1(i,j-1,iblk)*area1(i,j-1,iblk) & + + mask1(i,j, iblk)*area1(i,j, iblk)) + if (wtmp /= c0) & + work2(i,j,iblk) = (mask1(i,j-1,iblk)*work1(i,j-1,iblk)*area1(i,j-1,iblk) & + + mask1(i,j, iblk)*work1(i,j, iblk)*area1(i,j, iblk)) & + / wtmp + enddo + enddo + enddo + !$OMP END PARALLEL DO + + case default + call abort_ice(subname//'ERROR: unknown option '//trim(dir)) + end select + + end subroutine grid_average_X2YS + +!======================================================================= +! Shifts quantities from one grid to another +! Flux masked, original implementation based on earlier t2u and u2t versions +! NOTE: Input array includes ghost cells that must be updated before +! calling this routine. +! +! author: T. Craig + + subroutine grid_average_X2YF(dir,work1,area1,work2,area2) + + use ice_constants, only: c0, p25, p5 + + character(len=*) , intent(in) :: & + dir + + real (kind=dbl_kind), intent(in) :: & + work1(nx_block,ny_block,max_blocks), & + area1(nx_block,ny_block,max_blocks), & + area2(nx_block,ny_block,max_blocks) + + real (kind=dbl_kind), intent(out) :: & + work2(nx_block,ny_block,max_blocks) ! local variables @@ -2245,6 +2499,11 @@ subroutine grid_average_X2Y_compute(dir,work1,area1,work2,area2) i, j, iblk, & ilo,ihi,jlo,jhi ! beginning and end of physical domain + type (block) :: & + this_block ! block information for current block + + character(len=*), parameter :: subname = '(grid_average_X2YF)' + work2(:,:,:) = c0 select case (trim(dir)) @@ -2281,10 +2540,10 @@ subroutine grid_average_X2Y_compute(dir,work1,area1,work2,area2) do j = jlo, jhi do i = ilo, ihi work2(i,j,iblk) = p25 * & - (work1(i, j, iblk) * area1(i, j, iblk) & - + work1(i-1,j, iblk) * area1(i-1,j, iblk) & - + work1(i, j-1,iblk) * area1(i, j-1,iblk) & - + work1(i-1,j-1,iblk) * area1(i-1,j-1,iblk)) & + (work1(i, j, iblk)*area1(i, j, iblk) & + + work1(i-1,j, iblk)*area1(i-1,j, iblk) & + + work1(i, j-1,iblk)*area1(i, j-1,iblk) & + + work1(i-1,j-1,iblk)*area1(i-1,j-1,iblk)) & / area2(i, j, iblk) enddo enddo @@ -2323,10 +2582,10 @@ subroutine grid_average_X2Y_compute(dir,work1,area1,work2,area2) do j = jlo, jhi do i = ilo, ihi work2(i,j,iblk) = p25 * & - (work1(i ,j-1,iblk) * area1(i ,j-1,iblk) & - + work1(i+1,j-1,iblk) * area1(i+1,j-1,iblk) & - + work1(i ,j ,iblk) * area1(i ,j, iblk) & - + work1(i+1,j ,iblk) * area1(i+1,j, iblk)) & + (work1(i ,j-1,iblk)*area1(i ,j-1,iblk) & + + work1(i+1,j-1,iblk)*area1(i+1,j-1,iblk) & + + work1(i ,j ,iblk)*area1(i ,j, iblk) & + + work1(i+1,j ,iblk)*area1(i+1,j, iblk)) & / area2(i, j, iblk) enddo enddo @@ -2410,10 +2669,10 @@ subroutine grid_average_X2Y_compute(dir,work1,area1,work2,area2) !$OMP END PARALLEL DO case default - call abort_ice(subname//'ERROR: unknown dir '//trim(dir)) + call abort_ice(subname//'ERROR: unknown option '//trim(dir)) end select - end subroutine grid_average_X2Y_compute + end subroutine grid_average_X2YF !======================================================================= ! The following code is used for obtaining the coordinates of the grid diff --git a/cicecore/drivers/unittest/gridavgchk/gridavgchk.F90 b/cicecore/drivers/unittest/gridavgchk/gridavgchk.F90 index e4c650649..73ff10cad 100644 --- a/cicecore/drivers/unittest/gridavgchk/gridavgchk.F90 +++ b/cicecore/drivers/unittest/gridavgchk/gridavgchk.F90 @@ -5,6 +5,13 @@ program gridavgchk ! using CICE_InitMod (from the standalone model) to read/initialize ! a CICE grid/configuration. Then methods in grid_average_X2Y ! are verified using hardwired inputs with known outputs. + ! There are lots of issues here + ! areas (T, U, N, E) are not locally conservative, affect X2YF + ! X2YF is unmasked which can create havoc in U2T type directions + ! X2YS is masked but there can be no active cells to average (for instance, + ! single gridcell wide channels U2T where resuilt is zero) + ! land block elimination can lead to missing data on halo + ! This test tries to deal with all these things.... use CICE_InitMod use ice_kinds_mod, only: int_kind, dbl_kind @@ -17,11 +24,12 @@ program gridavgchk use ice_distribution, only: ice_distributionGetBlockID, ice_distributionGet use ice_domain_size, only: nx_global, ny_global, & block_size_x, block_size_y, max_blocks - use ice_domain, only: distrb_info, halo_info + use ice_domain, only: distrb_info, halo_info, landblockelim use ice_fileunits, only: bfbflag use ice_exit, only: abort_ice, end_run use ice_global_reductions, only: global_minval, global_maxval - use ice_grid, only: grid_average_X2Y,tarea,uarea,narea,earea,tmask,umask,nmask,emask + use ice_grid, only: grid_average_X2Y,tarea,uarea,narea,earea,tmask,umask,nmask,emask, & + hm,uvm implicit none @@ -36,22 +44,20 @@ program gridavgchk real(dbl_kind) :: amin, amax, errtol, errx, erry real(dbl_kind) :: deltax0, deltay0, deltax, deltay - integer(int_kind) :: npes, ierr, ntask, ntest - integer(int_kind), parameter :: maxtest = 36 - integer(int_kind) :: errorflag0,errorflag(maxtest),gflag - character(len=32) :: stringflag(maxtest) + integer(int_kind) :: npes, ierr, ntask, ntest, maxtest, navg + integer(int_kind), parameter :: maxgroup = 3 + integer(int_kind) :: errorflag0,gflag + integer(int_kind), allocatable :: errorflag(:) + character(len=32), allocatable :: stringflag(:) integer(int_kind), parameter :: & passflag = 0, & failflag = 1 - integer(int_kind), parameter :: navg = 12 - character(len=8) :: avgname(navg) + character(len=8), allocatable :: avgname(:) logical, allocatable :: dmask(:,:,:,:) + real(dbl_kind), allocatable :: errtolconst(:),errtolijind(:),errtolarea(:) real(dbl_kind), parameter :: fillval = -1.0e36_dbl_kind real(dbl_kind), parameter :: testconst = 100._dbl_kind - real(dbl_kind), parameter :: errtolconst = 0.01_dbl_kind ! error tolerance relative to const field - real(dbl_kind), parameter :: errtolijind = 0.65_dbl_kind ! absolute error tolerance for ij index field - real(dbl_kind), parameter :: errtolarea = 0.06_dbl_kind ! relative error tolerance for area field ratio character(len=*), parameter :: subname='(gridavgchk)' !----------------------------------------------------------------- @@ -61,6 +67,57 @@ program gridavgchk call CICE_Initialize npes = get_num_procs() + navg = 12 + if (.not. landblockelim) navg=24 ! no land block elimination, can test F mappings + allocate(avgname(navg)) + allocate(errtolconst(navg)) + allocate(errtolijind(navg)) + allocate(errtolarea(navg)) + maxtest = maxgroup * navg + allocate(errorflag(maxtest)) + allocate(stringflag(maxtest)) + allocate(dmask(nx_block,ny_block,max_blocks,navg)) + + errtolconst(1:12) = 0.0001_dbl_kind + errtolijind(1:12) = 0.51_dbl_kind + errtolarea (1:12) = 0.75_dbl_kind + if (nx_global > 200 .and. ny_global > 200) then + errtolarea (1:12) = 0.20_dbl_kind + endif + avgname(1) = 'T2US'; dmask(:,:,:,1) = umask(:,:,:) + avgname(2) = 'T2NS'; dmask(:,:,:,2) = nmask(:,:,:) + avgname(3) = 'T2ES'; dmask(:,:,:,3) = emask(:,:,:) + avgname(4) = 'U2TS'; dmask(:,:,:,4) = tmask(:,:,:) + avgname(5) = 'U2NS'; dmask(:,:,:,5) = nmask(:,:,:) + avgname(6) = 'U2ES'; dmask(:,:,:,6) = emask(:,:,:) + avgname(7) = 'N2TS'; dmask(:,:,:,7) = tmask(:,:,:) + avgname(8) = 'N2US'; dmask(:,:,:,8) = umask(:,:,:) + avgname(9) = 'N2ES'; dmask(:,:,:,9) = emask(:,:,:) + avgname(10) = 'E2TS'; dmask(:,:,:,10) = tmask(:,:,:) + avgname(11) = 'E2US'; dmask(:,:,:,11) = umask(:,:,:) + avgname(12) = 'E2NS'; dmask(:,:,:,12) = nmask(:,:,:) + if (navg > 12) then + errtolconst(13:24) = 0.008_dbl_kind + errtolijind(13:24) = 0.65_dbl_kind + errtolarea (13:24) = 0.55_dbl_kind + if (nx_global > 200 .and. ny_global > 200) then + errtolijind(13:24) = 0.25_dbl_kind + errtolarea (13:24) = 0.15_dbl_kind + endif + avgname(13) = 'T2UF'; dmask(:,:,:,13) = umask(:,:,:) + avgname(14) = 'T2NF'; dmask(:,:,:,14) = nmask(:,:,:) + avgname(15) = 'T2EF'; dmask(:,:,:,15) = emask(:,:,:) + avgname(16) = 'U2TF'; dmask(:,:,:,16) = tmask(:,:,:) + avgname(17) = 'U2NF'; dmask(:,:,:,17) = nmask(:,:,:) + avgname(18) = 'U2EF'; dmask(:,:,:,18) = emask(:,:,:) + avgname(19) = 'N2TF'; dmask(:,:,:,19) = tmask(:,:,:) + avgname(20) = 'N2UF'; dmask(:,:,:,20) = umask(:,:,:) + avgname(21) = 'N2EF'; dmask(:,:,:,21) = emask(:,:,:) + avgname(22) = 'E2TF'; dmask(:,:,:,22) = tmask(:,:,:) + avgname(23) = 'E2UF'; dmask(:,:,:,23) = umask(:,:,:) + avgname(24) = 'E2NF'; dmask(:,:,:,24) = nmask(:,:,:) + endif + !----------------------------------------------------------------- ! Testing !----------------------------------------------------------------- @@ -78,6 +135,7 @@ program gridavgchk write(6,*) ' block_size_x = ',block_size_x write(6,*) ' block_size_y = ',block_size_y write(6,*) ' nblocks_tot = ',nblocks_tot + write(6,*) ' maxtest = ',maxtest write(6,*) ' ' endif @@ -100,20 +158,6 @@ program gridavgchk call ice_distributionGet(distrb_info, numLocalBlocks = numBlocks) - allocate(dmask(nx_block,ny_block,max_blocks,navg)) - avgname(1) = 'T2U'; dmask(:,:,:,1) = umask(:,:,:) - avgname(2) = 'T2N'; dmask(:,:,:,2) = nmask(:,:,:) - avgname(3) = 'T2E'; dmask(:,:,:,3) = emask(:,:,:) - avgname(4) = 'U2T'; dmask(:,:,:,4) = tmask(:,:,:) - avgname(5) = 'U2N'; dmask(:,:,:,5) = nmask(:,:,:) - avgname(6) = 'U2E'; dmask(:,:,:,6) = emask(:,:,:) - avgname(7) = 'N2T'; dmask(:,:,:,7) = tmask(:,:,:) - avgname(8) = 'N2U'; dmask(:,:,:,8) = umask(:,:,:) - avgname(9) = 'N2E'; dmask(:,:,:,9) = emask(:,:,:) - avgname(10) = 'E2T'; dmask(:,:,:,10) = tmask(:,:,:) - avgname(11) = 'E2U'; dmask(:,:,:,11) = umask(:,:,:) - avgname(12) = 'E2N'; dmask(:,:,:,12) = nmask(:,:,:) - ntest = 0 !---------------- @@ -133,7 +177,7 @@ program gridavgchk stringflag(ntest) = trim(avgname(n))//' const' if (my_task == master_task) then write(6,*) '' - write(6,*) trim(stringflag(ntest)),' test ',ntest + write(6,*) trim(stringflag(ntest)),' test ',ntest,errtolconst(n) endif array2x = c0 @@ -149,12 +193,15 @@ program gridavgchk je = this_block%jhi do j = jb,je jglob = this_block%j_glob(j) - errtol = errtolconst * testconst + errtol = errtolconst(n) * testconst do i = ib,ie iglob = this_block%i_glob(i) array3x(i,j,iblock) = array2x(i,j,iblock) - array1x(i,j,iblock) + ! if array2 is c0, then there are no valid surrounding points and ignore it + if (array2x(i,j,iblock) == c0) array3x(i,j,iblock) = c0 errx = abs(array3x(i,j,iblock)) - if (dmask(i,j,iblock,n) .and. errx > errtol) then + ! flag points that are active and error numerically + if (dmask(i,j,iblock,n) .and. errx > errtol .and. array2x(i,j,iblock) /= c0) then errorflag(ntest) = failflag errorflag0 = failflag write(100+my_task,*) '' @@ -191,8 +238,6 @@ program gridavgchk ie = this_block%ihi jb = this_block%jlo je = this_block%jhi -! write(6,*) 'tcx1x ',my_task,iblock,minval(this_block%i_glob(ib:ie)),maxval(this_block%i_glob(ib:ie)) -! write(6,*) 'tcx1y ',my_task,iblock,minval(this_block%j_glob(jb:je)),maxval(this_block%j_glob(jb:je)) do j = jb,je do i = ib,ie array1x(i,j,iblock) = real(this_block%i_glob(i),kind=dbl_kind) @@ -204,37 +249,53 @@ program gridavgchk call ice_HaloUpdate(array1x, halo_info, field_loc_center, field_type_scalar, fillval) call ice_HaloUpdate(array1y, halo_info, field_loc_center, field_type_scalar, fillval) + ! Overwrite the i wraparound points to deal with i/j index average on wraparound + do iblock = 1,numBlocks + call ice_distributionGetBlockID(distrb_info, iblock, blockID) + this_block = get_block(blockID, blockID) + ib = this_block%ilo + ie = this_block%ihi + jb = this_block%jlo + je = this_block%jhi + do j = 1,ny_block + do i = ib,ie + if (this_block%i_glob(i) == 1 ) array1x(i-1,j,iblock) = 0 + if (this_block%i_glob(i) == nx_global) array1x(i+1,j,iblock) = nx_global+1 + enddo + enddo + enddo + do n = 1,navg ntest = ntest + 1 stringflag(ntest) = trim(avgname(n))//' ijind' if (my_task == master_task) then write(6,*) '' - write(6,*) trim(stringflag(ntest)),' test ',ntest + write(6,*) trim(stringflag(ntest)),' test ',ntest,errtolijind(n) endif deltax0 = 0.0_dbl_kind deltay0 = 0.0_dbl_kind - if (avgname(n) == 'T2U' .or. & - avgname(n) == 'T2E' .or. & - avgname(n) == 'N2U' .or. & - avgname(n) == 'N2E') then + if (avgname(n)(1:3) == 'T2U' .or. & + avgname(n)(1:3) == 'T2E' .or. & + avgname(n)(1:3) == 'N2U' .or. & + avgname(n)(1:3) == 'N2E') then deltax0 = 0.5_dbl_kind - elseif (avgname(n) == 'U2T' .or. & - avgname(n) == 'U2N' .or. & - avgname(n) == 'E2T' .or. & - avgname(n) == 'E2N') then + elseif (avgname(n)(1:3) == 'U2T' .or. & + avgname(n)(1:3) == 'U2N' .or. & + avgname(n)(1:3) == 'E2T' .or. & + avgname(n)(1:3) == 'E2N') then deltax0 = -0.5_dbl_kind endif - if (avgname(n) == 'T2U' .or. & - avgname(n) == 'T2N' .or. & - avgname(n) == 'E2U' .or. & - avgname(n) == 'E2N') then + if (avgname(n)(1:3) == 'T2U' .or. & + avgname(n)(1:3) == 'T2N' .or. & + avgname(n)(1:3) == 'E2U' .or. & + avgname(n)(1:3) == 'E2N') then deltay0 = 0.5_dbl_kind - elseif (avgname(n) == 'U2T' .or. & - avgname(n) == 'U2E' .or. & - avgname(n) == 'N2T' .or. & - avgname(n) == 'N2E') then + elseif (avgname(n)(1:3) == 'U2T' .or. & + avgname(n)(1:3) == 'U2E' .or. & + avgname(n)(1:3) == 'N2T' .or. & + avgname(n)(1:3) == 'N2E') then deltay0 = -0.5_dbl_kind endif @@ -244,7 +305,7 @@ program gridavgchk call grid_average_X2Y(trim(avgname(n)),array1y,array2y) array3x = c0 - errtol = errtolijind + errtol = errtolijind(n) do iblock = 1,numBlocks call ice_distributionGetBlockID(distrb_info, iblock, blockID) this_block = get_block(blockID, blockID) @@ -258,13 +319,15 @@ program gridavgchk iglob = this_block%i_glob(i) deltax = deltax0 deltay = deltay0 - ! adjust deltax at wraparound - if (iglob == 1 .and. deltax < -0.01_dbl_kind) deltax = deltax0 + nx_global/c2 - if (iglob == nx_global .and. deltax > 0.01_dbl_kind) deltax = deltax0 - nx_global/c2 array3x(i,j,iblock) = array2x(i,j,iblock)-array1x(i,j,iblock)-deltax + ! if array2 is c0, then there are no valid surrounding points and ignore it + if (array2x(i,j,iblock) == c0) array3x(i,j,iblock) = c0 errx = abs(array3x(i,j,iblock)) array3y(i,j,iblock) = array2y(i,j,iblock)-array1y(i,j,iblock)-deltay + ! if array2 is c0, then there are no valid surrounding points and ignore it + if (array2y(i,j,iblock) == c0) array3y(i,j,iblock) = c0 erry = abs(array3y(i,j,iblock)) + ! flag points that are active and error numerically if (dmask(i,j,iblock,n) .and. (errx > errtol .or. erry > errtol)) then errorflag(ntest) = failflag errorflag0 = failflag @@ -278,10 +341,16 @@ program gridavgchk write(100+my_task,101) 'array1y j+1 ',array1y(i-1,j+1,iblock),array1y(i,j+1,iblock),array1y(i+1,j+1,iblock) write(100+my_task,101) 'array1y j ',array1y(i-1,j ,iblock),array1y(i,j ,iblock),array1y(i+1,j ,iblock) write(100+my_task,101) 'array1y j-1 ',array1y(i-1,j-1,iblock),array1y(i,j-1,iblock),array1y(i+1,j-1,iblock) -! write(100+my_task,101) 'uarea ',uarea(i,j,iblock) -! write(100+my_task,101) 'tarea j+1 ',tarea (i-1,j+1,iblock),tarea (i,j+1,iblock),tarea (i+1,j+1,iblock) -! write(100+my_task,101) 'tarea j ',tarea (i-1,j ,iblock),tarea (i,j ,iblock),tarea (i+1,j ,iblock) -! write(100+my_task,101) 'tarea j-1 ',tarea (i-1,j-1,iblock),tarea (i,j-1,iblock),tarea (i+1,j-1,iblock) + write(100+my_task,101) 'tarea ',tarea(i,j,iblock) + write(100+my_task,101) 'uarea j+1 ',uarea (i-1,j+1,iblock),uarea (i,j+1,iblock),uarea (i+1,j+1,iblock) + write(100+my_task,101) 'uarea j ',uarea (i-1,j ,iblock),uarea (i,j ,iblock),uarea (i+1,j ,iblock) + write(100+my_task,101) 'uarea j-1 ',uarea (i-1,j-1,iblock),uarea (i,j-1,iblock),uarea (i+1,j-1,iblock) + write(100+my_task,101) 'hm j+1 ',hm (i-1,j+1,iblock),hm (i,j+1,iblock),hm (i+1,j+1,iblock) + write(100+my_task,101) 'hm j ',hm (i-1,j ,iblock),hm (i,j ,iblock),hm (i+1,j ,iblock) + write(100+my_task,101) 'hm j-1 ',hm (i-1,j-1,iblock),hm (i,j-1,iblock),hm (i+1,j-1,iblock) + write(100+my_task,101) 'uvm j+1 ',uvm (i-1,j+1,iblock),uvm (i,j+1,iblock),uvm (i+1,j+1,iblock) + write(100+my_task,101) 'uvm j ',uvm (i-1,j ,iblock),uvm (i,j ,iblock),uvm (i+1,j ,iblock) + write(100+my_task,101) 'uvm j-1 ',uvm (i-1,j-1,iblock),uvm (i,j-1,iblock),uvm (i+1,j-1,iblock) endif enddo enddo @@ -323,14 +392,14 @@ program gridavgchk stringflag(ntest) = trim(avgname(n))//' area' if (my_task == master_task) then write(6,*) '' - write(6,*) trim(stringflag(ntest)),' test ',ntest + write(6,*) trim(stringflag(ntest)),' test ',ntest,errtolarea(n) endif array1x = tarea ! input array2y = uarea ! result call ice_HaloUpdate(array1x, halo_info, field_loc_center, field_type_scalar, fillval) array2x = c0 - call grid_average_X2Y('T2U',array1x,array2x) + call grid_average_X2Y(trim(avgname(n)),array1x,array2x) array3x = c1 array3y = c1 @@ -347,8 +416,11 @@ program gridavgchk do i = ib,ie iglob = this_block%i_glob(i) array3x(i,j,iblock) = array2x(i,j,iblock)/array2y(i,j,iblock) - c1 + ! if array2 is c0, then there are no valid surrounding points and ignore it + if (array2x(i,j,iblock) == c0) array3x(i,j,iblock) = c0 errx = abs(array3x(i,j,iblock)) - if (dmask(i,j,iblock,n) .and. errx > errtolarea) then + ! flag points that are active and error numerically + if (dmask(i,j,iblock,n) .and. errx > errtolarea(n)) then errorflag(ntest) = failflag errorflag0 = failflag write(100+my_task,*) '' diff --git a/configuration/scripts/machines/env.cheyenne_gnu b/configuration/scripts/machines/env.cheyenne_gnu index 8ddc443b1..c68a87d5c 100755 --- a/configuration/scripts/machines/env.cheyenne_gnu +++ b/configuration/scripts/machines/env.cheyenne_gnu @@ -53,7 +53,7 @@ setenv ICE_MACHINE_SUBMIT "qsub" setenv ICE_MACHINE_ACCT P00000000 setenv ICE_MACHINE_QUEUE "regular" setenv ICE_MACHINE_TPNODE 36 -setenv ICE_MACHINE_BLDTHRDS 1 +setenv ICE_MACHINE_BLDTHRDS 8 setenv ICE_MACHINE_QSTAT "qstat " # For lcov diff --git a/configuration/scripts/machines/env.cheyenne_intel b/configuration/scripts/machines/env.cheyenne_intel index 28df6647d..d6eeb67ea 100755 --- a/configuration/scripts/machines/env.cheyenne_intel +++ b/configuration/scripts/machines/env.cheyenne_intel @@ -53,5 +53,5 @@ setenv ICE_MACHINE_SUBMIT "qsub" setenv ICE_MACHINE_ACCT P00000000 setenv ICE_MACHINE_QUEUE "regular" setenv ICE_MACHINE_TPNODE 36 -setenv ICE_MACHINE_BLDTHRDS 1 +setenv ICE_MACHINE_BLDTHRDS 8 setenv ICE_MACHINE_QSTAT "qstat " diff --git a/configuration/scripts/machines/env.cheyenne_pgi b/configuration/scripts/machines/env.cheyenne_pgi index d492129fb..9c559b90c 100755 --- a/configuration/scripts/machines/env.cheyenne_pgi +++ b/configuration/scripts/machines/env.cheyenne_pgi @@ -53,5 +53,5 @@ setenv ICE_MACHINE_SUBMIT "qsub" setenv ICE_MACHINE_ACCT P00000000 setenv ICE_MACHINE_QUEUE "regular" setenv ICE_MACHINE_TPNODE 36 -setenv ICE_MACHINE_BLDTHRDS 1 +setenv ICE_MACHINE_BLDTHRDS 8 setenv ICE_MACHINE_QSTAT "qstat " diff --git a/configuration/scripts/tests/unittest_suite.ts b/configuration/scripts/tests/unittest_suite.ts index 3f9a306c8..76c9f4312 100644 --- a/configuration/scripts/tests/unittest_suite.ts +++ b/configuration/scripts/tests/unittest_suite.ts @@ -7,4 +7,7 @@ unittest tx1 8x1 sumchk unittest gx3 4x1 bcstchk unittest gx3 1x1 bcstchk unittest gx3 8x2 gridavgchk,dwblockall -unittest gx3 8x2 gridavgchk +unittest gx3 12x1 gridavgchk +unittest gx1 28x1 gridavgchk,dwblockall +unittest gx1 16x2 gridavgchk +unittest gbox128 8x2 gridavgchk From 6bffe27a1cb384d5e608fbe3a33800e1c0d5ad5c Mon Sep 17 00:00:00 2001 From: apcraig Date: Fri, 5 Nov 2021 12:19:09 -0600 Subject: [PATCH 06/17] add grid_system namelist, update computation of areas to use local data on halos and avoid halo updates to improve halo values when neighbor cells are land block eliminated --- cicecore/cicedynB/analysis/ice_history.F90 | 11 +++++- cicecore/cicedynB/general/ice_init.F90 | 13 +++++-- cicecore/cicedynB/infrastructure/ice_grid.F90 | 34 ++++++------------- configuration/scripts/ice_in | 1 + 4 files changed, 33 insertions(+), 26 deletions(-) diff --git a/cicecore/cicedynB/analysis/ice_history.F90 b/cicecore/cicedynB/analysis/ice_history.F90 index a2806b429..cf6b470d1 100644 --- a/cicecore/cicedynB/analysis/ice_history.F90 +++ b/cicecore/cicedynB/analysis/ice_history.F90 @@ -68,6 +68,7 @@ subroutine init_hist (dt) use ice_domain_size, only: max_blocks, max_nstrm, nilyr, nslyr, nblyr, ncat, nfsd use ice_dyn_shared, only: kdyn use ice_flux, only: mlt_onset, frz_onset, albcnt, snwcnt + use ice_grid, only: grid_system use ice_history_shared ! everything use ice_history_mechred, only: init_hist_mechred_2D, init_hist_mechred_3Dc use ice_history_pond, only: init_hist_pond_2D, init_hist_pond_3Dc @@ -547,11 +548,19 @@ subroutine init_hist (dt) "snow/ice surface temperature", & "averaged with Tf if no ice is present", c1, c0, & ns1, f_Tsfc) - + +! tcraig, just to test capability, tcx +! if (grid_system == 'CD') then +! call define_hist_field(n_aice,"aice","1",nstr2D, ncstr, & +! "ice area (aggregate)", & +! "none", c1, c0, & +! ns1, f_aice) +! else call define_hist_field(n_aice,"aice","1",tstr2D, tcstr, & "ice area (aggregate)", & "none", c1, c0, & ns1, f_aice) +! endif call define_hist_field(n_uvel,"uvel","m/s",ustr2D, ucstr, & "ice velocity (x)", & diff --git a/cicecore/cicedynB/general/ice_init.F90 b/cicecore/cicedynB/general/ice_init.F90 index 2e67af51c..6754f97db 100644 --- a/cicecore/cicedynB/general/ice_init.F90 +++ b/cicecore/cicedynB/general/ice_init.F90 @@ -99,7 +99,7 @@ subroutine input_data use ice_grid, only: grid_file, gridcpl_file, kmt_file, & bathymetry_file, use_bathymetry, & bathymetry_format, & - grid_type, grid_format, & + grid_type, grid_format, grid_system, & dxrect, dyrect, & pgl_global_ext use ice_dyn_shared, only: ndte, kdyn, revised_evp, yield_curve, & @@ -184,7 +184,7 @@ subroutine input_data bathymetry_file, use_bathymetry, nfsd, bathymetry_format, & ncat, nilyr, nslyr, nblyr, & kcatbound, gridcpl_file, dxrect, dyrect, & - close_boundaries, orca_halogrid + close_boundaries, orca_halogrid, grid_system namelist /tracer_nml/ & tr_iage, restart_age, & @@ -324,6 +324,7 @@ subroutine input_data ice_ic = 'default' ! latitude and sst-dependent grid_format = 'bin' ! file format ('bin'=binary or 'nc'=netcdf) grid_type = 'rectangular' ! define rectangular grid internally + grid_system = 'B' ! underlying grid system grid_file = 'unknown_grid_file' gridcpl_file = 'unknown_gridcpl_file' orca_halogrid = .false. ! orca haloed grid @@ -696,6 +697,7 @@ subroutine input_data call broadcast_scalar(dyrect, master_task) call broadcast_scalar(close_boundaries, master_task) call broadcast_scalar(grid_type, master_task) + call broadcast_scalar(grid_system, master_task) call broadcast_scalar(grid_file, master_task) call broadcast_scalar(gridcpl_file, master_task) call broadcast_scalar(orca_halogrid, master_task) @@ -1356,6 +1358,7 @@ subroutine input_data if (trim(grid_type) == 'displaced_pole') tmpstr2 = ' : user-defined grid with rotated north pole' if (trim(grid_type) == 'tripole') tmpstr2 = ' : user-defined grid with northern hemisphere zipper' write(nu_diag,1030) ' grid_type = ',trim(grid_type),trim(tmpstr2) + write(nu_diag,1030) ' grid_system = ',trim(grid_system) if (trim(grid_type) /= 'rectangular') then if (use_bathymetry) then tmpstr2 = ' : bathymetric input data is used' @@ -2024,6 +2027,12 @@ subroutine input_data abort_list = trim(abort_list)//":20" endif + if (grid_system /= 'B' .and. & + grid_system /= 'CD' ) then + if (my_task == master_task) write(nu_diag,*) subname//' ERROR: unknown grid_system=',trim(grid_system) + abort_list = trim(abort_list)//":26" + endif + if (kdyn == 1 .and. & evp_algorithm /= 'standard_2d' .and. & evp_algorithm /= 'shared_mem_1d') then diff --git a/cicecore/cicedynB/infrastructure/ice_grid.F90 b/cicecore/cicedynB/infrastructure/ice_grid.F90 index ce5d89dbc..8f8c85904 100644 --- a/cicecore/cicedynB/infrastructure/ice_grid.F90 +++ b/cicecore/cicedynB/infrastructure/ice_grid.F90 @@ -56,6 +56,7 @@ module ice_grid bathymetry_file, & ! input bathymetry for seabed stress bathymetry_format, & ! bathymetry file format (default or pop) grid_spacing , & ! default of 30.e3m or set by user in namelist + grid_system , & ! Underlying grid structure (i.e. B, C, CD, etc) grid_type ! current options are rectangular (default), ! displaced_pole, tripole, regional @@ -448,6 +449,10 @@ subroutine init_grid2 !----------------------------------------------------------------- ! T-grid cell and U-grid cell quantities + ! Fill halo data locally where possible to avoid missing + ! data associated with land block elimination + ! Note: HTN, HTE, dx*, dy* are all defined from global arrays + ! at halos. !----------------------------------------------------------------- !$OMP PARALLEL DO PRIVATE(iblk,i,j,ilo,ihi,jlo,jhi,this_block) @@ -458,8 +463,8 @@ subroutine init_grid2 jlo = this_block%jlo jhi = this_block%jhi - do j = jlo, jhi - do i = ilo, ihi + do j = 1,ny_block + do i = 1,nx_block tarea(i,j,iblk) = dxt(i,j,iblk)*dyt(i,j,iblk) uarea(i,j,iblk) = dxu(i,j,iblk)*dyu(i,j,iblk) narea(i,j,iblk) = dxn(i,j,iblk)*dyn(i,j,iblk) @@ -476,7 +481,11 @@ subroutine init_grid2 uarear(i,j,iblk) = c0 ! possible on boundaries endif tinyarea(i,j,iblk) = puny*tarea(i,j,iblk) + enddo + enddo + do j = jlo, jhi + do i = ilo, ihi dxhy(i,j,iblk) = p5*(HTE(i,j,iblk) - HTE(i-1,j,iblk)) dyhx(i,j,iblk) = p5*(HTN(i,j,iblk) - HTN(i,j-1,iblk)) enddo @@ -506,27 +515,6 @@ subroutine init_grid2 !----------------------------------------------------------------- call ice_timer_start(timer_bound) - call ice_HaloUpdate (tarea, halo_info, & - field_loc_center, field_type_scalar, & - fillValue=c1) - call ice_HaloUpdate (uarea, halo_info, & - field_loc_NEcorner, field_type_scalar, & - fillValue=c1) - call ice_HaloUpdate (narea, halo_info, & - field_loc_Nface, field_type_scalar, & - fillValue=c1) - call ice_HaloUpdate (earea, halo_info, & - field_loc_Eface, field_type_scalar, & - fillValue=c1) - call ice_HaloUpdate (tarear, halo_info, & - field_loc_center, field_type_scalar, & - fillValue=c1) - call ice_HaloUpdate (uarear, halo_info, & - field_loc_NEcorner, field_type_scalar, & - fillValue=c1) - call ice_HaloUpdate (tinyarea, halo_info, & - field_loc_center, field_type_scalar, & - fillValue=c1) call ice_HaloUpdate (dxhy, halo_info, & field_loc_center, field_type_vector, & fillValue=c1) diff --git a/configuration/scripts/ice_in b/configuration/scripts/ice_in index 443ff1cbb..11520e36b 100644 --- a/configuration/scripts/ice_in +++ b/configuration/scripts/ice_in @@ -60,6 +60,7 @@ &grid_nml grid_format = 'bin' grid_type = 'displaced_pole' + grid_system = 'B' grid_file = 'grid' kmt_file = 'kmt' bathymetry_file = 'unknown_bathymetry_file' From 5de9a2c886714ad144dd8f6d22792455145f7589 Mon Sep 17 00:00:00 2001 From: apcraig Date: Fri, 5 Nov 2021 13:32:10 -0600 Subject: [PATCH 07/17] update documentation --- doc/source/cice_index.rst | 11 ++++++++- doc/source/user_guide/ug_case_settings.rst | 3 +++ doc/source/user_guide/ug_implementation.rst | 27 ++++++++++++++++++--- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/doc/source/cice_index.rst b/doc/source/cice_index.rst index 12bc8d32e..97afb8016 100644 --- a/doc/source/cice_index.rst +++ b/doc/source/cice_index.rst @@ -184,10 +184,14 @@ either Celsius or Kelvin units). "dumpfreq_n", "restart output frequency", "" "dump_last", "if true, write restart on last time step of simulation", "" "dwavefreq", "widths of wave frequency bins", "1/s" + "dxe", "width of E cell (:math:`\Delta x`) through the middle", "m" "dxhy", "combination of HTE values", "" + "dxn", "width of N cell (:math:`\Delta x`) through the middle", "m" "dxt", "width of T cell (:math:`\Delta x`) through the middle", "m" "dxu", "width of U cell (:math:`\Delta x`) through the middle", "m" + "dye", "height of E cell (:math:`\Delta y`) through the middle", "m" "dyhx", "combination of HTN values", "" + "dyn", "height of N cell (:math:`\Delta y`) through the middle", "m" "dyn_dt", "dynamics and transport time step (:math:`\Delta t_{dyn}`)", "s" "dyt", "height of T cell (:math:`\Delta y`) through the middle", "m" "dyu", "height of U cell (:math:`\Delta y`) through the middle", "m" @@ -196,8 +200,10 @@ either Celsius or Kelvin units). "dvirdg(n)dt", "ice volume ridging rate (category n)", "m/s" "**E**", "", "" "e11, e12, e22", "strain rate tensor components", "" + "earea", "area of E-cell", "m\ :math:`^2`" "ecci", "yield curve minor/major axis ratio, squared", "1/4" "eice(n)", "energy of melting of ice per unit area (in category n)", "J/m\ :math:`^2`" + "emask", "land/boundary mask, T east edge (E-cell)", "" "emissivity", "emissivity of snow and ice", "0.985" "eps13", "a small number", "10\ :math:`^{-13}`" "eps16", "a small number", "10\ :math:`^{-16}`" @@ -277,6 +283,7 @@ either Celsius or Kelvin units). "gravit", "gravitational acceleration", "9.80616 m/s\ :math:`^2`" "grid_file", "input file for grid info", "" "grid_format", "format of grid files", "" + "grid_system", "structure of the grid, ‘B’, ‘CD’, etc", "" "grid_type", "‘rectangular’, ‘displaced_pole’, ‘column’ or ‘regional’", "" "gridcpl_file", "input file for coupling grid info", "" "grow_net", "specific biogeochemistry growth rate per grid cell", "s :math:`^{-1}`" @@ -413,6 +420,7 @@ either Celsius or Kelvin units). "my_task", "task ID for the current processor", "" "**N**", "", "" "n_aero", "number of aerosol species", "" + "narea", "area of N-cell", "m\ :math:`^2`" "natmiter", "number of atmo boundary layer iterations", "5" "nblocks", "number of blocks on current processor", "" "nblocks_tot", "total number of blocks in decomposition", "" @@ -434,6 +442,7 @@ either Celsius or Kelvin units). "nilyr", "number of ice layers in each category", "7" "nit", "nitrate concentration", "mmol/m\ :math:`^3`" "nlt_bgc_[chem]", "ocean sources and sinks for biogeochemistry", "" + "nmask", "land/boundary mask, T north edge (N-cell)", "" "nml_filename", "namelist file name", "" "nprocs", "total number of processors", "" "npt", "total run length values associate with npt_unit", "" @@ -690,7 +699,7 @@ either Celsius or Kelvin units). "uatm", "wind velocity in the x direction", "m/s" "ULAT", "latitude of U-cell centers", "radians" "ULON", "longitude of U-cell centers", "radians" - "umask", "land/boundary mask, velocity (U-cell)", "" + "umask", "land/boundary mask, velocity corner (U-cell)", "" "umax_stab", "ice speed threshold (diagnostics)", "1. m/s" "umin", "min wind speed for turbulent fluxes", "1. m/s" "uocn", "ocean current in the x-direction", "m/s" diff --git a/doc/source/user_guide/ug_case_settings.rst b/doc/source/user_guide/ug_case_settings.rst index 9d8e5fbc7..851f39883 100644 --- a/doc/source/user_guide/ug_case_settings.rst +++ b/doc/source/user_guide/ug_case_settings.rst @@ -239,6 +239,9 @@ grid_nml "``grid_file``", "string", "name of grid file to be read", "'unknown_grid_file'" "``grid_format``", "``bin``", "read direct access grid and kmt files", "``bin``" "", "``nc``", "read grid and kmt files", "" + "``grid_system``", "``B``", "use B grid structure with T at center and U at NE corner, "``B``" + "", "``C``", "use C grid structure with T at center, U at E edge, and V at N edge", "" + "", "``CD``", "use CD grid structure with T at center and U/V at N and E edge", "" "``grid_type``", "``displaced_pole``", "read from file in *popgrid*", "``rectangular``" "", "``rectangular``", "defined in *rectgrid*", "" "", "``regional``", "read from file in *popgrid*", "" diff --git a/doc/source/user_guide/ug_implementation.rst b/doc/source/user_guide/ug_implementation.rst index 3fb63c11d..f855e003b 100644 --- a/doc/source/user_guide/ug_implementation.rst +++ b/doc/source/user_guide/ug_implementation.rst @@ -79,8 +79,8 @@ this tool. Grid, boundary conditions and masks ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The spatial discretization is specialized for a generalized orthogonal -B-grid as in :cite:`Murray96` or +The spatial discretization of the original implementation was specialized +for a generalized orthogonal B-grid as in :cite:`Murray96` or :cite:`Smith95`. Figure :ref:`fig-Bgrid` is a schematic of CICE B-grid. This cell with the tracer point :math:`t(i,j)` in the middle is referred to as T-cell. The ice and snow area, volume and energy are @@ -111,7 +111,23 @@ distribution, http://mitgcm.org/viewvc/MITgcm/MITgcm/pkg/seaice/. Schematic of CICE B-grid. -The user has several choices of grid routines: *popgrid* reads grid +The ability to solve on the CD-grid was added later. With the CD grid, +the u and v velocity points are located on the N and E edges of the T cell +rather than the T cell corners. To support this capability, N and E grids +were added to the existing T and U grids, and the N and E grids are defined +at the northern and eastern edge of the T cell. This is shown in +Figure :ref:`fig-Cgrid`. + +.. _fig-Cgrid: + +.. figure:: ./figures/CICE_Cgrid.pdf + :align: center + :scale: 55% + + Schematic of CICE CD-grid. + + +The user has several ways to initialize the grid: *popgrid* reads grid lengths and other parameters for a nonuniform grid (including tripole and regional grids), and *rectgrid* creates a regular rectangular grid. The input files **global\_gx3.grid** and **global\_gx3.kmt** contain the @@ -122,6 +138,11 @@ and **global\_tx1.kmt** contain the :math:`\left<1^\circ\right>` POP tripole grid and land mask. These are binary unformatted, direct access, Big Endian files. +The input grid file for the B-grid and CD-grid is identical. That file +contains each cells' HTN, HTE, ULON, ULAT, and kmt value. From those +variables, the longitude, latitude, grid lengths (dx and dy), areas, +and masks can be derived for all grids. + In CESM, the sea ice model may exchange coupling fluxes using a different grid than the computational grid. This functionality is activated using the namelist variable ``gridcpl_file``. From e0b1b1916bf8eda6d05d1b1c6898b9794a4aed40 Mon Sep 17 00:00:00 2001 From: apcraig Date: Fri, 5 Nov 2021 13:35:30 -0600 Subject: [PATCH 08/17] add CICE_Cgrid.pdf --- doc/source/user_guide/figures/CICE_Cgrid.pdf | Bin 0 -> 29946 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/source/user_guide/figures/CICE_Cgrid.pdf diff --git a/doc/source/user_guide/figures/CICE_Cgrid.pdf b/doc/source/user_guide/figures/CICE_Cgrid.pdf new file mode 100644 index 0000000000000000000000000000000000000000..dcf0ae479560e268312b44cbfb85950a80fd913c GIT binary patch literal 29946 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 Date: Fri, 5 Nov 2021 13:49:25 -0600 Subject: [PATCH 09/17] update documentation --- doc/source/user_guide/figures/CICE_Cgrid.pdf | Bin 29946 -> 0 bytes doc/source/user_guide/figures/CICE_Cgrid.png | Bin 0 -> 77699 bytes doc/source/user_guide/ug_implementation.rst | 28 +++++++++++++++++-- 3 files changed, 26 insertions(+), 2 deletions(-) delete mode 100644 doc/source/user_guide/figures/CICE_Cgrid.pdf create mode 100644 doc/source/user_guide/figures/CICE_Cgrid.png diff --git a/doc/source/user_guide/figures/CICE_Cgrid.pdf b/doc/source/user_guide/figures/CICE_Cgrid.pdf deleted file mode 100644 index dcf0ae479560e268312b44cbfb85950a80fd913c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29946 zcma&M1yo$kx-E(mBsh%+_r^WAySuwXaCdiicXxLQ&`5B%;O->2=8}K!eb2e$+&Av) z(Nv% z{ULrzyNuh=?{qkwDp+qT(mt$s$@_EuUi5NxiM;j3>?+^qT=e!Zp47f%dCKSV!n9JB zcY#jlci0y7_M-f-r!Fm`#DC3^spF~EEBVZMF*x&P=jQz9Qup=p8L8JAX> znv}X+EFb7F%(vgqv&SMT&2?J-d^RTFpz=c{}c0n-W+Z^DZ|SUcJ9I z?E58}mRwcpSh;I}?O~mds97rW`N_SOf$G%jM0Ll}`dC%U({xKYjKO!rB5s5^j>ULs z8oQ4GFK@|qh1hMGs~CrhV}+ox`h}G-7V)Kio5cgjkC^l4tF!z@?0BfJpq*Rn_+0(^ za+DJvC@!SS`&w-3AP*-=Wgkk2G+9Tf>3o@#kwMxIsfnlkR%Apf4sUHKZjVQ3XOL^K z`C%MvzWe;mcf!*k@Hf=O`H{~~g~VDn(pziBHHHdxL9DBw@X|uwkR7STd0UBM*m1su z?tKL#rn1abNkb78OPxNdsjN1~b#C_8Z`ys6Bj4>&;m%64muFl9-PQ}v-z0zdM^WYO zC|PNa?A6b(!Am+3zBq7txFamfW#>@v{&?K{|F ziq-E$IrVo|%AxRjh-_B=Nkni5@S(li))SRfd z=GJ4Ztkpn?FRhg4Rnk&`7iXJ4jREx(;Edfzi)n`-&p*vxJu<B!^A32th%;-A(Ui)#Fo{QvNj6;HN)3P$E z3YFnH-Q{GfVN4emM*+i6X*Jvz!{P2nM(3xlpI!Lla`Z|*&9dV^P++$}eH0AHfp0pG z<6%eM@1Gw^zmi%+)~{hVn;X zAqE0>ic|^pN$qp4<8N+qoX+cSj@yZMKd~!Gf(*&bQSf9SYN@H4Bj3}VKrR)o7?O3s zuFVcrEe*H425YDBLMSQA-kh*Gr;-GfG}DnF#KU^JiN@lipy$!hS8Ocu&HQ$!W!XiQ zx&6+Yd|V|@S4lzQfKWcSdZz@l=@3sfdRNJjrMjkFNUW~j;`XQ>b;&AThD6pYzNRYx zmic=9h;BF1iuqW^T2jdHz$poTy+o6KjT9eDZk?*6H}+Cc2VKYO3rMqJ(9bNw{PoE$ zK8Lnffs!99@OGOrT-ji0%$omODvJj71XNDhL4HhSC^GXwDIw;@V`L`f>HZ{yCe(D@ zyfck5EOOF0bM%*1`cfq!oXJ2}oD^C4m6UQ_lz`4S2^m{Jso1aXbKOdvZ&I`;B@W9k zs+xQ--zPezM;CD~H6rLHJI}_HMzH$jNOPE1s#za$K`(|=KihKVEO}d&7G;D=$Rn2; zg!`_5?+CVQ6sZ|u?LrE~!R%;GrUUXL13*=1*&*nt1uNqbV0l8%fE!>aNW` zRjqV)eFtgDxjM+3QYErh&c*~*w3Bx0^6x02w!clfSaR0ub4OaeK)}e*%#4J)diC^S zXtRd%qB4^-6{-sPS{M2`R`fTZNs+`?HC~`2-72onEeq9LT91^L*1VLIc4e>iayxa+ z3VN-spb!r^gMd}fa~7dQ)P0rG@9#!Ij#i3tW`Y7I>MI}1>@ha>?qsRJH-tQerC-n8 z0v%$-qe4xW<;&ZL`MndVjJkhSXcy{)YeUD7wGF}?9)8Dkqr1-EYu?@Ry3xZtvqX;l z502h&^o;Tno4aPg@rivmqUMwfwS-1W@`}c36A!vOPF2VkMkMcADUuzT+sbVxmXtuM zdkk1THH#QF>XQ_o1jb%!JvBsju$!rC=6L#eCI3Yjh9oznngFz{#1K*esi}#x5`}IQ z#_sAFG`OabAJ9x^c!6pQ9^^#0jluC2Zv_48G9?^@F<+seK?vZ6?jb5fweiZo8pT#y zI*L&bDZ~lvv4||b2k-Zvm`LDt%LuyTYndu4;OdFpjWmO+e;r_(4M~;2Ce2H< z$DfBK*Ev=0>L16L;s#mMT9WkR`7|TIUs%<_t8bgCD(#xa^jZ_FN5^RU$j8#9$1CyS zxJOv9btBfpPUMMdeIHLvIbb=1MNl97==m4=$Fg8{S4)xTd={jA=F$1gpbb?tku}qv z3kj>CVf| zlvoHkh1q+y-x)3M$Y!AXs}+8NAUfeI3=CuP1xA!~qtf9}OMvzw3s8#Jww`4wE#x4A zYCc6DPIb`AqysDh1F0!D77|jhG~D{fzl?^P z&#juJVKeuNBDGgl_KGTa16tE_*1&i&*Z1;iiE$WA>a`^}k&h=Sh^i84$Zu!qE#7@CbBh_sQ7aJQlxEExtT5y!U^1w4gJ_9ZK$nM!5cf3q zx>suu86~_AI9<>W9iE3eJf3*#%iL>@f79@GR6UpplcJbd~bW zLS3`?S`aK`Yqh2WCUUOVp<-oWEbhodT;UGbbOONCBqK60UuxYPSdhN$`H0#HhN@WR zme~@OvkshQvo1u)Q}5A_Y=5dKFbgRxKw9_!JaW-*nZGCbINIi$NtF$Ldx=v*OTYP= zn2uo8N+$XY!A9GB&gJ5ifKjelbhXyWRie28tQu_bD=W`Xt?h0z%YD&Wu*ooYMWr57 zU#KpCwrZU~K%N(y%r3`?qWA)4jm3$3KSr{;*y%HDDfzE|$Z~ZN1^F`J(L4_({j<;ai5}Mr_3R)ud6h+sdsZ=?n z%K7JYo3ydytg9`%<=Q6UH;PXIa0`al{gb#_`MNZ2YOTafl>u4QWeQvH-w`7tYlC{E ze)}*pan;8t4k#;>K*=1j<+h_>)@x#7xNBGmD<~A#+*a6QYU{**FPN_B@_n}x+j&=D z@uCn%nGU28ZN{ZjWPu)b1>A-|7Lw$0+*eiZf{Q4RCPb`GDM`S0=*Ei+PSAv$fKa}& zIn_owVG8na!lZ{Z0vN{MRRGUBYMhsc4$l*{X9QX!WD{M}nYuwDzcCIm+!J-OnnlJ% z3S9YVwT7)?Qdl%9Djf!=e|7UAC#D-d#P%IC;(NC0vpwp=FPwSIXM4O8-_& zCEM6%Xu2$YKmyyeH;>B2-lCVDcqrfM2S#f{wTjliT;-$&m|8;1sj8H|(wbGOEEnWl;F zy~NV_0hw$c{R2_I*mSF@;EDl4&VCk}NmYhzDzWR>9M05+1ZGxHAV~>MCaNiZ{CJeJ z@&NBz$~7-k4;-zvBpEKcHd`h++ZR7}q1K4v7w~A+h3Yx9vpL5kUfF`5}o56v8th&A>YX8YJW>WL?f8l~)!dw8_g6eR}+ zU%8?{daDqbV^MOF@p6;dY6bM)@hBu{zZjZT#OT3@PBzL*R=rWsA^1S*OG;OETB~=o z*rub$zIlyIVC-e@`uN;~| zUSnkTbq^;If<@Yg&aAXZXMR|0DKO)NXR~9zN-R&gT9?RUZ1KKZ!qZZ}ILa7fQ%FW zFVNxv6Z^B0U6e|Aj)A)fEyv0`g&o)YY09WgV#_TZLu$M9<8-lKx9MFoHCt$hWRUPf zf*6^=@}h|MC+riLw@ zq~J5%w>B(T+;Bj&4u2jbBE#S$KwADDY_ClG8G~NQZ0A)S3|7 z%=Py-Q!#olwSso1&xbUu9%EoE1f$M^lAmm=TWHZ&)3d9J3EeZMv=RgEs1!30@@O&K z>J++#26I-gXety2I?qU3rRE)kqg`RQ==3OH?GVhFjKtd*Sv{;cISbX}sdG*X3U7D| zL(?!L6HPv-MrpRq2SdWZh}93_n;x4AF&<75UR6!(xoo714wxPT1zjD~^+;vTl^6JZ zr2r(tmmGJohkju7na_CT5U^t^WsKh=jfJOVLTehUNy&N;er(3~sas~%9TmhYQ+rF^ zHVcoT2DM`_IIN@{m9~0`w$ZC_&AcA4yB@Ecqqbc5SWSx(m&-kQq|p|#;wBl8R>HTo zvAc~8%`r>h&CoRgPf@J#)tvpCXN(PYCP}QeF;XHa0}?AZEzO-L$qp^|C}kj}rtmn8 zynt~`dT}u`n^R^^iB7DtvS9x=`1uTD2+^zq!y=Jyt@Nt3VB;9=#MJ$bMnCU-YasV1 zw#mcX$kDL3h$%)c8Qs&^AK^u9|+LpsH_L5c{b{ z@j7%*Tp=x(861)G!KfFe5}3JDsObTtpj487mj6w=BxLphvke+qsYDX{xZSYiu z0V1W*%Dr?->imbanIiroO8+7wG`*P}v95xWQjV9}F%CHkIaV1x>ZL@6oWT^{2}etU zcTl0(YFY83Z&-e0GUnMg2b+8wOF7Q_*m!2$fx%YkE*%*{ii<#s16RVM6iVMyFvIr) z)Y1Tmvjm+_!~J<}7QOxqh-oA88-!m7SBvHhdxB)Hg6xsGb-05Ku{s>x zY_0~WI!=R}J-FP3udNL)J3Bew_pq6;f8u%e{@T|3R_@trb$tu=O^f39T=+OeJAB;T zzIG62Q=Kb!nWo`{$U0xZd`-~fPLALLI%jvq5nf!OYbL4(D8G(CjCm8!!FoD(Guh9i zk(eMfwW@LJruvq0+E4l6x(az?iTCw+Fyv2C`PAi(8=<}Q!?o8tP8aO&@w~1PKQC^1 zM-Wj)+KDQGmD8^SgoJBfyR|Pm$620_e~$6SF9Le{?r^$vxK(v#d!&&R)_cr@K<)9S zEt?Q|2UINt+OukVmPf@ztgc00ewK{=LMd{f%-P()xzJo!we>S2pg83^gMbI~tTj-s z7}V6WG(?Xfa}1-*p5ky4#j6L7kU4uC%O4xEea}RdW82Zl>W6DJa0pb4QP1bQ6Vvfr zj6+JUS-KaG{ZoV{iopmB8O3d0a`iR<>dFVgC3jv&4%bN zMgy;If9fY282cv2kVFy5tmOnB^a7Lq3WEJ%!#kJy{+8~Hha`GCAs2icM~_KRQQhvL zQdC9vnmvXVgR+>wfAaooF`F}H!G#6oP~3K9qb;0HH$4);Bb!a>^< zOGQh>-pAw|L(i|*o8G&9Q?88~GY3^L=2|_oFdR-cGG=;-aqZ<@t9=8^%V_3+mkkwc zF@NjYBI&d5iyr$nJwxP%l^o*Eo#z){clVJmUm)c;nSbqq>fC0K2}kW-((s4q^)JO~ zzV_7wadz~dO{ER|$wVqFUBQjfKO$nEZp0gEMY0U|F%C=D9h_t#P8eon*445ixot1TYC6ArqrNMv1LmOY_z0k>CFJXo%BIROs=b1urj zZVoLSpH3q2GzP7%5iSPnl7-?5J1d952%cc*=&8SeW1~o5vOmeDJ-5KFv)CPikQ0~| z5$D4FqNzWd*_v3PZb(L;*doP%re5^RBm=-qPd)>8q4ZeYqFkaKfwW;_?L3c*YxmH| zUt6+Mbax|OHf3U~F zu)Ob7ltx-k&ceSS9C}X)X1>(05_U9-Ur9qB$pFnUaxexd+rO~d))hdJwB}HlSfJV) zF1Kqd5ANI@+4W5$bywR3E_UN@%)Q?VUM7XNIf)jq8~HvPzn6(RCU#y8EjAmKWj zwK-d>XMKA2*<<8+u*%)^>s?s32(uW1e3~hLBQ(18wCL7cEu@7Gki;uc%vY@RPPtjo z+ite8M%8Vuxl4p1hsMDf7e|rxF8s$0PTu;SN+q{f#L1rY>S^cqmPY=9lIx1Q^~DX} zIXj35z)w9b$g$K5efKX=_@@2u?|EC)O6kF=%bwrj-+%G$XtDJ%@51a{i5w1ng_(gmpO62?78Xm1L5TDh*z#- zX#HAU>?hGHL0nK$B7`0sgVTX6%by#aS9YEJ?0(Pc$Nl?^z8v76M?W>`Oci+3ZzlhC zwm-i8^~0I|n=h{7VgF%-D;S#p^X_Q+&6$Y#qgjcFLCMs~&c)H#)QO1oUlqc3-<&_% zorwPW>K_NlnwnS|3fZ|6X)}IQaBwjbu`@C2!haa){~qV>dH?a>6&&r1l}(+Av_A$D z5hG$yF?Dw)(j{ULwzIKwRJJ!XHYNIN(+fK>5wZW%Js;nPS^qKOKh-KK%tV}jtKk_` zR9K0a{tl@0VcGw6?f(8 z#luL9MKKV90*#j8exoQ1e^(R{J=lo0hP$d^yV=Zq8`0caJ!)HCHNWy%?gUeK4TKtS z)&TcsEzrQYJo~PLhCV*@0D+AHj-&zJzhh2N$+pcwGQl4 zpm19HH6~Yss5l?RdAMCfdo35(;KV~t_q zq7UX1!llqI2|H@X3nokoN%oE36T;_A8-)pew71)$CZWzLj@k45=$Q~fC-U2lj39~f z;XPuUi6eO-5T|G>*ycL~T0E?CK0IpxJtG9r;4{8Ii#_Bf5m>Ol1PWv-B)tTLr2tf; zAm0iYydcvGxNDG=J=j8k=M0owAiF(`4wQQTXL|%he{li$(C^ZW;F|%Kp8~H@Fbf4M z;{nCU8A3}acv_!4gas8iF(5(05%DOA0#7p(<=8Yql?B2IytkyzxSgMLgP!wYXNXu~ z-oSl=QPUyj4L`4dwfe8tbK`#!9~j>jamUPt#p++*k!lC7xR`F7t|o(Z$Zm$h67UpQVzk&$szF)J?+V9`niWGgq-GFjpk1HV0J&m#&W(>W z(vP!?Z|~cVt;76{trn^cc{#ev|7`H{4#h9`ZkkPut3c%MPS-}>#J%u-_bk4AzY&Lx%}ILMrC?uj+T6nh>w&HgLo24+D+QtSWQw@f_2JSnisiz@^YG6nm&CV zr9QEr)O+b`JA~qQf$z!zMfGY0Vmr+PydjdJnT07v;YOK85k^6~Y#>GQ?!I8$;{?E|U<`~%#BrXNZ$ z1B?cbEJ`>f(Mi!=(Q!AdhaJ;<)9dVYmU@4>sZ*Y4zR`H6kffNUfTzS&%Bb2cVl3uV z+E&UhFj`Sq8CtDcy)4pK#Y~q?yX8*j=(GOWe+@gW?~L$lf3~_CJmo!2!p+3(#l^u@ z#Z6-!X2Z$+mN}Mrka@&9(rlrH&;q4(pmo%u$C#3FIiX@k-W0`EP*ZzRMmNh>yivtl zV_e>(VO}KHG=;94NUzNy*rwB_>?R~H&7i@cU#ECgz^9m3lULj)-ly&Nqko2I%^*rJ z>w9@YWI>-{u3^!RF==H&)htbsRuT6wr*W%8fDM2?@B*kzcLpTXq}GJi zux&oAe;!;L%Cy!s_8AGa+B0sND&072si~mba_zhD;m*{p-vD&Ubxq$R-IKgfyfDG? zhPj9JAU&)&yHa%p`z)fK9q+VH{fgd$rSzg~n3pWu%F&#np87mhgn)>3jkQ3B?KtbO z(~j?$KyN}Ht?zDMu%No0vZr{lemCl^t(RLoXPS_U^iHqQ%@8%EaC>ay@s_Am^x7BLEU{;*uUR7Ecom`#wOa?&*G zN{@Y)xs!+{%OVfbL};>V+%y+A&HJG^fqHnmpSk~SoM7x`?8TSOjLpr(yw~+T^z}R2 zr8QDb$WpD&dWW2w?)T1}yWX=nTOwPD)$4Jw@fcIQt#6T=3yS%Q^}PlbO;?A*LLEYi zJ3Vw$+DJAa8%&#v4YQ^itMxPzz1cgX@!iN>dGeo$XIq*+>Q5UJ_rVuECHEySZriS( z+!2<@#O`hTPS^{*>O_I1sN)felbGw* z?#LtIRW2gWsz;O8D*V(*3ms49`yEz_^R;Tx?!?9w$=jBy3 zt;)QXOPAXx$EW8a^etxTOIL2H{<*K^Nz0XO&xw80Tk2j-Y%jFW(X;Lg!{&Xb&q3^; z96ZP-O2?*rZnUW{)?5>C$L zALUc>V))&>;a-2cQ`njvZaoCwy!=nL{g=-EWx*fJS5jD5$k55ugox=cSydv^{SSHl zOS%8Ul>dv7JNVNn5-}&(W>{Hm#+0e$${9kn6>EAs6 zzZf*z|DNc-dLv@c(9|Mg;bbLZ}GBK1jWc;lB&49|d(w6K9LR;j?mb5V0__5HT}z!85Zl5;1=y^!zQevwnyYR`!o} zP9jz=P9io&jt|lCUm^c9#(zTjcQz0+7wi9980aQUS`9Ly1Ydc=6RZnguRU2p3@a!> z@ZE-W`haO_!3xqLXmUMXa4XGYc%~1Qt)f;bI@siCnHK>!2a3649qXr{a?7M=fL?ss zls}|!tM*cUXM9P)f*#ml7XPBnA=6kJk__S|aYBsh_F`3@emFU2!$w-lIoLRA7^mC- zy)b-P6_qTsEZzZM=B52pD3&T3TdM`RHEbHPur)NYt7$|^_9HLl*2Mi@%1PmJqL9Ms zbiM-he1gBKo8o!rt5%9^j!5$cYhf)7k%-C#dTjv8>}9+?WbpQBur?8tI{8m<;&zWm z@J~C3wvG=1;TD5%$O50zb)kdfFOt?Fi3?pa@_u#Mc`91HFD3T|`zQW>*nd}ISo(DV z`?jx)thv=}8UKG1p8q`~>t6u*3y%MS!M|W3XK4GO+5QJ$Yz)o+YSDjGq0m3NlaB4< z8q=|SV26pBmGMIsGPCQ#Ge~}*+|pR^o4JkY2T&OVos9pgS}wK^z4v#dzXdvGcCL?2 zWN0s8YH4oaOvKLe(WvZfYOD7542^%)!n3k}j3(%6{twKE*qA@Io2;Sxze-Fj%$)z4 z%136IDKin%-`(?9lKy8)|5NdQLW_xriG%B7JN+l`jPs-P|AyM4w}*R@>hrxv6Nlv* z*~VO{t&-4qVye)%62LMaA-NF~S4Oi-IsZIawjZ8EOEkxUU<8@~bL8tYyD4>hK~UFr z=q?}UUUY0^VQg&BobQ829^a>l>8JO{+N;jPwEHO^{%MaXkB`^yUJ4Lfl@@NWY%_ch zwoY5KS;&kY=}{oeVvX(|DR-5|r#<5sS^zycH=YSH&}MT+;(io1I9zXQK|xu*^%0Jz z8xE;4rC_^PR(iRb(yQ3U!2afU=jQK(<$gI$t)||G=UtzbUQ;${JgVLW$_vaYT+i_o z#>|)OAMb-*fsGbSve+%yIriZ?4Z@$6?Kc=FNylZMp4`MY9LxmI)2~DtMVM~%#Hmy_0pl^?sz zfEpmZX+sFe43MRvGhjp-^%=O-q%mSd7X<)VYgC&xB!b`p8`*NirGK#gJoiZx+_jL4!O z0Hhj-=1kEb1;7*Vw+5miQ@SX9lpxSi!=&j`J@%*(Skyc4xna~OVXTk=fj^25$gJ_G z;jUTSBw?KJV_=XZM3fnUBZ>?V0YuXnY6>^rG1@WNF+d$B2@S~+WktY4ppBve003qH z3V;{@2H*+!3V=tLrA__<*Z@w|KSqG!fO1WbSW$!;uSuW>V6X8nWWZMAV<>1DDA({9 z2}%RXH9iJ{j(~i|zuW+MjgP^gEsfU{&^7kFvn02{Tg`I-u{1^N!|ssY;S+cQA2 zz;7lFkWuvoQlo*4JIo5dDW z`nM*!Xp;G0RI4@8ldqvk#)UeuXl8}e6R$}$6DP7G5ucG-isrkBSVw4;+kDonicm{% zG9|O+p{XX)l536@N=0Ksr;8{~C30k%B`KsR3=xS*STG7^jaQXd5m%8`5mu3H_P5|$ z%o1PHDdZAqil_`95Wzy9B!Nd&MVlnc6jTvp&9T6pRVkzvNs9OpK_SXxiY<&YI}~n? zR{fFkf-28dofvM;T%KMYZo!ihQ{*XFC{)RjdQ4Ktgu#_*fuTw$sUpA{Xu&zlXk|mC z$k&o6&KhjN$d)S28h(0!Vu}tO4ukfY=v00oE^~_HM=|>g+Ec`{!aR-$U*!?G6r~iY z6!~wI5)q|R63sD@ONk$>8j>Or`!Yn4l;-#eQKOQkNQD}X!zil}g%uNGCghQY%m@h? zqZpF8u~m4aW0*vc2_NaDjTj^a33I{=H6c{yqt6k?;)U}n_Y94`M9-A74r8xPmh?xTS!TsW zD9g{~MFd&7vyWg3pkR%p?uPWA+CHRl9XfA!jJO=Zc!AuXM++%vY&rkRiwa%yDG1~i9Dcg zNZ)c7dWBz7tcf~fvAI&VIKs|esN8E8u7~>yJJYJRhg4@pd?V>h`0*`Y%~$r8mZmHB z_-mncge#h^aDsZ$qL?%0Y>EhXcx^b@g2DMZDO^kbctoox8m^%&c_%OtC2$c}vVT(S zBY}(&zd6K$MRiN$?gNZ?0xeCs7`md- z5|K#}>2Lr#U7@F}2ttKHc`nIWxK)Hzcx40tWwK0gx+r&&JX1I*S5{ViHsk}A z%5LVfAwmmMmWMqK0MX+)aj6qMs$I%oSE2 zrGQs3hKztwFn)`8Mm0q>70YIp_KA31Fe9{L3BtWmq}3~Qu1ph4mf9zlB9@BfJS>oP z8)70%#&7_Fk)x5LfY3px9p!;ZG@PS2(ip-fl#!(pc%oWkIHD%R%;*_Za}o(Kj;9gM zBJc^H?uV8<$vchDy3LKwdiVwZe9DG-hu%WIenWr!@`&^Z`?>|Om49x%Qs!Uh&k&Gw z?Fa51+c<6Thu{(85$aKULg-50IJ27&(hvL{(Hm+D?mEvOIRM$957`&l9m^foeZ6nGpP3*b@KtLY(~cl-tB`s=Orz5j#iHs&_fkGTGaMxTlY@?)$5eShE0-j$bZpM(cZ zucQZ@7ojV|g*VbQFI;!{Pxtr(FG>CA{d=>tJ#nISzxi-`*1Q-!V;;a}pwGkn2bC$*gXgvZSPyxTipqve35y;&S5TLFPjeBub}@RwZpnx z!dx}d{n~`~p}ZyNznJM0)ov@O*~+ic-sysF$7zRaM{NgxWIKI>ztFYIIqjMHI_Xv8 zQs7p0$9KiHw6S^dEOT}63~|L?(%;3lfZJK!!{%&h;bbBGau{#hWVC+1s?+$gI6rZQ8g{pR5tq0bYierm_S6f76wE%z(N@A+L^EmbW1^I;OR_Yphv;e#f^{?f?3#M z^E8qwX0R|8sjr%#Db<1=PNt>;YUZpSYNi?^8!P5JHS|Hj*u_DCBs99P=>@tlI=qxH zId->%OYyVP9nxw*Ma6N%HPs%hS70uBuJV_l>+)RTFFmyEpsYeXl&oqDS!uOYO8rc4 z-A2Bpw@7U)XXH`(7+Fv96M0E}a-7{jNl2KKND=Wu2E{z0kyOqSrPvylhWd2(QAXS9 zO%XpeOPfHntZmtu6z`OL9pc+adBxyeuoJrSCUME@)KkJR1pQPv(GEQom>*q0Be4#v z3_fwyS``-a9}fl~n?>gm8lk46U~Y_qwMryWb(MwqyW9=4qd1-6;8Sk0J#6c}5sAn8B0 z**T8c&IkROPgRid)(~q9)ifodneGKpeO1f-sr*DMLaDF6qXtmg4A}IvSQcIx)SvVf z3SSwH_xwDtxS?7l+;!qE9lg^!KCi&*z%)aoL1_C=_ET)58Iab4YamxcEajJTSiunj#PY$*VNdS_+Eg6016ewOo zSTtBD?jOGzkmVQ4B;`X33!Hpen0XpI5QaGHuPKoD-q^3 z7_|WNHcX@FDAHWa=95Cw82z@i^UBY>(OA{`vv019!>^STz+*&pJQVqJfk zGo-nHol>Q?DBmUw6LH*$Q2rJ0vkoOQ?{&GYR&R{gx zpRO6NVYi9%3EWX0d9T6h@!AR7k=wBz3G9*WIqDJG5!%t)A=?Qa>Fn{Y@wU~r0o!KV z6x(9kFx$)hb^d1oXa3d!IsI(?ivoD|nD*rLknIpF^rs^&G-<-NkgX7D;5Gdv{Qv`& zdboC|l}|QcOOR*&EdmJjFdCn$A=Dsf{SW$?4X9@jf#3khD1QnA;+apZV0Qup3J42e zi~SG=e2mEH2ovCDkg5XM?bzwi!TwSP6pWDRNHUP65dY&UM?C-eZT#HVw?0E9ROwEU^?88Y9wtU5G^Q=?RkVk}Ute>FjP zy3~=6t68~5X@uq783nCS(W7P!9d16jWSXN(v0H84QLU2DgC=w+TCE~8c-DswjJVBg z!`hW}LU3M8&nlY~ZFj94J|8}5IpjQ&_uOyaRempwH*WC3r0$^}AbLN)8@F2zAeYV? zUh_nvT!`8w|JCR&$^&^;e*ex>tqwZd{p|4J4fIgF$3C#^s_u=Dh(!nJ zJNmOXo=$=`RGUlaxpeoMpGSq8BE=)X7p%EPTKk<6ecZRVc^6Y{Fi*65W&Wnem%jZ^ zhFgs6#>1^QX0{LLo~=r~MyJ7hb?%Tn3X6@-#-_YZm(g$YCs$L|K*5g;7MfD|tgohy zPsNQ9=u*;=QNwWvfY=_3iDN}l1TjRyRBkHDEqA+s&J~`?hwA^i}iLn*N9@x^EM4Hzu4WFCmYpQ2Ilb5VFZ#O3>+T33Qlk1 zq4aDU{fMoyFVy!hoyn`1hQ~RecbYs;rFmsm+tE2h?&xU5h3k~|tPjgx>4H{KdYQc? zMFs1~gqDEaI-#%pdu9^d*J^eNyyUg5zCz&>ezn=)TEDS!q@4Pd15;HWGfCN=uRSC> zO6Oyv<#XPJ64ugem=$IL( z7I73{AEOq*@%UXy13p`|_O*+Aew=OijbqM`Up_1owzYhpBXIOa*(Xpp{cGXYQzj$! zDj1k7%#%f-T46{x!*PqUH$EEg)6q#wWo1}igK604Q@DhV`u(RsN@Z0ld00CcF`2Yh z$G**-6+g4~ETrM9oGEGmR>tO*FP%3Cu;8o|c85 zXbT`TYRe>aQf{jC-|E50;jg*q1j0VKQ{GG}Dr3Io5u)kI)rqb4K1HWB_Y1~8?9T(a zh-?}mx2jKrpH&@GUy)q;;dGD~Wb)MzjJt?3gP3dvvJ{L#uAZBwX~k8E-R0(G_u`D@Dw(EWye}*m#JJ=u9vA)sfn`hwHTQuu(OHs)+SM&f+sURupW}XOr z-It{MY;i+VrrJblaj)sL3k@>WiFOi~v9qqaLV1?yNaiJoq=*((SFf0dQ1xwL-=2ky+dnTb#iK1V|(@qW?d~=g(GI5*WxB^vF*t`bi}~1 zCCH%3yy!eiI+^w$Wp6fFF8b=4R$a{*Duvd33W?DE(@s|-Gyd#O)8XkaRRSMH0N*w` zNx6s19BmHs5as99IYev#-KG-}l}MGE)eL^7?sCbeNpZnz>cU!SalSCXazcqNRk$Cw z;<9OeB2k-x|FlrATIA&xo~>Yna4J4Vd&2f0|80iet)#(>6{1$4;&+Q2-LT{z)Dito zC=H5{$I)u%k!6s!Mo{*9v?sCU`A7asXdOs2HQ~vrthR3mDQQXj%u)ndA_j-1`v#YYTsH%_63zHeu?5Znb{?RBneKnpnR&KVs zHpFZy{>x2}Kez#tV-2~HFFIbx?s&-OZ)dpV`RLnR> z@O8_-VZNnal@U!#-_eh2(s$MBO2z?I@-|h&xN%h41&!$Ur_833D|edUg^gLKlE#T` zI*>Wvo!{HVi{tk>HopD7q+HIs#_t!yRJFzWy1*5XZ8ILC*LC>Kx@qOl5qvU3)EjVI zjWPbKhc@ImbXg6Denj{8XG)jjQWA)2i=XUcaao!4$`Ht3J#F$3^?g#Jh0@Bb%`^U_ z1_oF@K^vDYJ zqSlzaS*U7dPUN=yW92E}s%a|zLbocaX4@vh?+08V`#3D)@tZ`cx#COr6<>eqS$Z}< zn>NzK!ela5!o<0v&$eQJOZ0Brd705cc6^TVH4H};`cvUP%BjFp{3k1%?H(0*x9IKS zhdHm^u6208Bbp_5J*orpnIBroO8Z*c_iYPrxqV3U?Jcd-kPjCkYbRnrvs5@*Rzs0O zU!Df*%(=7WS>sJMlsJ?;bR_!MFtV(%g3%DAP1Rl9-aHlWX)K2FkcvZ8CohUG;zJ=0 ziDIq_XNm7@vgg%c6duK&c2^~*_1TPk!dR61(8?Nlc77gFuCI@dzb0$5_ z3#tjDt>_U?C%Cg_!@C&c9a-&JIqX^e%^-rpRH&yA%R(Qqb5`-~em~$8<1H~*yZicX zYHZXOXuk6?eVycRehhDTe(iS7`I4}YQo4n%QHC8U| z(&ad8^3`l=44;K+vYI37RxGOHPxvpNA6e4R-PW$9!)OOqi>yI+~XYV}|ywWNA&i!1arRMLGG?JWru{geWEo zdfN3)zfPtHp*6ReQHM1qt2ZTA1C<@q&D#~Cft$Xe zHE-R3G|J5b2dz#laW17j9cm<}2b8FJ(&aZ{-m=fy(Q*z6?fQpRP5L%A-gd*RVt=3g zWhTR{csNmMIMVWMNVv&IVu3e5!zZ0c8K(ovc{qfAn}iD&V@=c}MP8UoTq-BvCyvnq zoylW>Dvoh?r4t#`W8;%)XIzJY@Ryso*_0hHFNSK*Pw43A+1*s8hx?T>N^^ITPnygr z%`)hS+UIc8_o&owukXQ^6kF{o=X%oF%NO^Zz*TCNxo400>>uULJ08M6;Ty4zWaVx< zfd8wxyAFz@@A3s6JV?mkE`t*wxce|baCgn%9^5V1;K5yk1$QS9+zCN~LvVr(5}a@+ z&+fbXy!-Cmy?@>*plVJvzwVwn)x}Vs^KHD%x*mHQ??*RA8AnRdvt2oHf4k00$XuGhgMycr$`4oGPx0`&G%Jfn)shDV6-t zPy7R>4r;bBh_%g3O)lG0ZmN6uletp9YP&pb?a9A$YzU@-bTISWM6w%wgLhNNoJzXhYq*t)-~8Y23VoqZ2%*gU<;%$-iA3L@DAF z-1P%GXK>jfC>%Iv^|L=YJ2$R#OrrTJlkyR7NlP51Y+;pX?J`WizY$ke4!r!J0Cf@MfZY-Gw-e8aNIGd?u143Ol-CA}D0 z*NcBEC10SN57V~d4gv(lDnv`y{3-ywLTSxsMxRdO5*UQj_j&x=3Y=k+@Jd% zW94J70sA~-oytb*`kJf$Cyw1syf0XF1_oqdzioc+1a$FDVh+UudjmnaCZ?0|9>(-y zQUz9zm#6}3nh=B8;!oauUw-pK?=kY^iZk)I4(ePxL1{gK(8~V za!T2ck-2y9CRNfmiy1>uPA@3vlk1WRrpsUz6ic`skdm>G`EW z_BoW3Do_O9?e1Nd{NUJ;w0!&W=VjWNZ#pk9J%pMEUSz9 z!AVy!(@r0ZJxZ=KK)1GEI#FC>*g z!MV6-kzi}(_F|9BEpE05IXksIjIDh;g{t#W|Kl{|8;Qf@K2gf*(7L)uH(;l>u!W&7 z;lyVDw9iYuZ7iJ*m3dlU=Ke}a=dOg=UxT1q_8_b9Qc1ghMP56RtEU+2-K*DB*uh`U zHyVb1mT11z4pqT^D{*>;J|Bk`Tj$@i)cov;+H>NWH)EWf=a{@>mS2nD&dB>)B&tJj z)`rx1k>F6^n-htJ()Vg*b(kvA&aDIZ9(Pt)@7$OzeE_2@BCg<(oYK{3L|McLq+36e zUP}yU5ZCF^*bE8LKj>|}q)mP-wD>|RF z5nKMe47<4I3`MV>Y7pfi`T^o!3?P`YkaKd9T@@s3>ys?uksr<1&D z+v~+DpD~a@$gYEvOc5>(|J#xTe) z19qHB%xEGVT$s5l-BdyNNY$^J!~U;Y?XS^_f3TJRBsy>%^S|OQ>Hj-%;r#m(;FN=b@`^GTLWeK4l>cSDW% zW8)&<6xuV^CP%W^l~DKS>h7qiIh>)`uL&kKMGQ&}Nl~4RNOkhi_I5*C8SSU&^Yf+Y zUoGEgYAT?B`+7?)HHlzAgxRbtQ&34`C?YT_`6T~YSE+7i1Y*&vp9mNqM$2TGBr>B^ zRD*JoSA3*)o0S|YY+FWHxD;T*LCFszKT4L7Nj2J zg>`OEj{I${lACB^%$c$OO;`N`LH?QX`OmKUAK=&Do9X{=`1RLZ(%<3N-+AP}wHh3L z2?)aHqy7QE1bGB_|M%9L^Yzx%l)ds;_4WNowC~tnQ1Hdk9-&DR-%uj9v7V_AQJzdy z&0~7wwWFF8WE=!Zja3>x z`8frh4>>6HC~3`3j`STHz`>(A2euaz<_#u2Tgw~N2Besj^UaV)hI&jdq@-mXUg*UstR&uc+4OlLzWBO1?wPEv*EP{06hP zcAPUK(#X!w9b?<-0_9e=PxTVzT*Yq|=ZRXq9?Pre^Wv{P2mKsLUvh_!=yRHtS#^GT zau^(MdGLF0{ zpa4}8L2>|gp}K7SuYlSZbs(q*a1sD%1B``Q<3Tfe)RomAU|L~Cs2%NlN%^T zu$c$)qv;<4`O)=@hu)|{yD`uBfntEoGC&}~ray2EZ_^04hO_AaT*KW|0>(W*3kTF- zo@D}RFr0OvI-y>A(6mr5HK-J*le+%`B*NI=01~0?pMmE?^(TQufc+++UWU-2Pywd? zk0246{yvZhU4IBjgt{LAco(|B-v0jZ>%xWdM?fSpy18=+5)5bp%|3T-2V8_b$5dnM7Xj{Ks4;`X z0Is3w^x!rCcNh~MBpfgk#zasEhC+Z*KDRS2d47)O!}wIW8MIO>`L4r4!d&JwmCE&# zG)t5ukT6#=J%h+ex+PGfV4@HKFpK7sbbc(D3@TJ+FRFJ4olkUCqH`yGRmq?)-Ixf{ z1~lR2;K(scZo3p(fE~aJk@~dE1J7-M6&YobWeH_)k7JEK4Jp@=ou`4jG0eYcjxuAW z3O++QL#8ZGT3J+CV%d9Z>}mT#J@5{gn|6&WrXa>zre7Fu-mUN(w1r$-u3s2aQ&AJl z6FXX>-UUzt&SinzNTs%_j@AgNO94j{JBXA!Ii zmMlyF(?Y}XEY#r~>|l16qwv|Zs;yA$u*xq#uoP51QXSd}9!c01e4~w>fe zob5Xh&c>1a73TTDCV2kR7AA?mP^LKx zr#>BV7pjchsuZd~#Tf3Opx=`75$2CMmEAc05^l+(zvVB*1lQpxY@edAg?XE;evM8D zS5AaN%9}P(fa+3c+HTt~WuIf31Y*?fVs8(43&g z_*?a_J{L-}mhE4~I3zD@pgrNJoP?4^#JXwsi&8e`Sd(e3%m0G6C9X3+t@$4%)|g<8 zq=q)_Q|LZ>sbBs%+}gc=HB?($&5VWF1qE)|NWf!}scKz(g~hWC+U0AYS;Yh;a4h%* z_}3pZHj{r?W)%%3{FYCoI@9D7WDmaR!TKQ`uv;m(d zg$bL_ShwMpD@On>$A8%*iU z5fUkL8ZKNCCUunrA(vNRt^{yDD8xBdEH1c}!6eYI;go1UFLV{z68KW8_8iQ|vH^#M9FwvKf z3@f)k8d_t;b5q5gWvy!&Ug z%0qv&ATd+%hijyJ)n+1#E|_!>r3A`JgZ`Oa`P2hO6}+svrwwCE<@V#3T1WP$eTQ`U%lc5L(VcCn9rbfXa77SH@M;f150&bv zOQUCocigGEYuG97h5GvI3yROt6TW`JDQ@d+@}Hd|l23&hS4hM`(-begN5v&*8T?XbUSafg5J@<$l7XZ0!F#{LL@xPv7= zw8J(}+F^wcC_lnhF?*YCd4J5{h>Ld%k)Kp!PmR@JOdVHa=xk4+PXz~h1bBOCdwP3W z{*HO4cO3(}eE9Yb9d%0mi1|1Ez@#t-BZ}x-W1A&wr(xgO`xKp_&hqPg9p^#%`@|g_ zXE}8>>BPoY2bDz%Ny!3J3Y3D|Bnj}r)Eo6p6TEK4*?|aL*_c-r=vT;r?>BeN6w-|* zhUT+WbrnS{v-z}5K-3?3CfNqs{2kl26_B!|0UTWz$OBC<^WZp2^*Ykq3vbC3K zwPif!Ba}vWPFqJiTSY8r-`S0cLJg^AKfj%mr&#I7q`xt4q2zl){9@U;eQkmt-b#N6 z`<7X-8`wSi^d9#hP?G9ttYe|C7HnIBJ-WB)nIRnH8q^T1yuoTJTnoox+35BNd`MYA zu|25yNPoewXBEL(J@Td~U$L|QqG1j_>iGoL2${hQ`8d|keg@O`K=QG5ky()mpEXIm zcqha`^&DxgN5u5CDvBl|K@Yhp9|tBAnkAw|50Bx%67(srfh#Zu}XfY_~L58MS9HhetG6;(jgaBk2MB1Pq5)2;@ir`)h9!l^A=^^MP zF=7!Sa}d!R)Wl~mKRl;<=GcSMkEGm#un;UjO<0Sd4Yy#y#68Hw2uS&8ZW?H3)z7%7 z5n^~1U~)(j;xJ4Y_dD_%^c$QTA{Y`(6h;AKgS~+9!U$mWFqC&#H{>^1aHPrzLx*v~ za9}Stq&7}_)`MOKee5v_z7D<)@(lJ2Y6)%$;t!_nA?rEpvFoYmc?(CW78~>%(i;F6 zB1{BE4r7I3!FXW!Fgh4AjA+AogL8u#_UDSj0RzCOVb9(@+ef-Wf?sHYx+K^E2tLmU z{@|}xv{tfx)Dy(tSP$q6NGs?o2rJkRIIS;Q30nWdm9|p0Vz&~uqPCK@VzlBeyf8#~ zKxidz#cIWeJ1-PNEJI{B1R_MDXM0F{2*P?7v&sjCWfVPvJ&O{I?+9xt7EtX`CXt(; zWd$qs$e1F1MW{rZN3aX#?Xfi__~ZW?k*uDL1zSjv)#6*D=m%Nmqgx}B2KoH)fMrO8 za1V$g!KR9ojXjRmE5ZARi2d8!OsI-IjyxJf(&Lto&x8;aOf&yr@>%Jr#k1zByDQ{r z=h5t;?x;V65O3zwOU|@J^$6BOLLt2=AlS)w9ywzi_=<}W~86`9+(|T zj~SniIImcRUF55tWX(()0#F)W-Dd<3aPxWj!4`UQB=W?r=%xs2H{E}mh=yE!VGr24 zhipVi-b>_t85!3%%JL(w@@M(=l5!})&b0Z<*-GkEMBGgEWz$(n@IC5PHdm0m_5fjR zm_1H~*{@23EhkF{dlD{JR68q{1^Eg6$ok^1Rkf+q7|YQmfwB4n+6`LvYz9+83#fio z;l@NwUW=p?C#Ga)O_2_k1`8SXEX#!c>t)`}h33(_tD%XvR9daV;^~1=X|mzqYqPWlaZ|A)OP%_P1>SU`?+s)D zTV47WCPR)8ezQp!sZOtJLrFD6ry*iN!=9=mZFT76yUSweinr*HPj#*wSmV`u%Bp;6*OEbN%P2RVaZM%bK@#TlUu)_72$&*H?#capuRaHkH?= zt{TK9p7KUd`qs{tg}SDjX&Chddnip`Lc&FQu_2}2pB?_{51$8Jn`#F~038>k>ygwD3sp8jX9ySEjQdezrDcJRdj=S=4;Ed3ts- z_`;s^^KbFbmm}j7jwBDx@3uDLN3rH#X>B2#JFXOW9YOrK>dwC_D2Q3kKgPB#tbL(M zmfraB=ybS@>PYs$)wt1_bNIc=sKIA$l;GHk)nvZ8v8lMtd1SL)8k1;tKD1(QqN=*z@u9go$GbB=Q%Gf$I|B zvZZ$UpV18sMerFQCe>NUn5$0Kl7Xzdvb-pbho>S% ziDc zqrHl_d?6au%D9E|0yK1cwFblidRva5xRfbTX9T&q(q*LI)u$vvR03CmKK_ZNz@MB& z%iUI;A6}k;Gc`X+T8Dowh#)r6Cp{gL_J@Ctl{&602QE*McHt0?qR*GRh_VYZ$*;UM z{>Ch?tXcDtx`948@oxV*oG*T9aer#EH)rnijFyqm=wo@J+WNxmU|T^ki)suGOZ*ds05+tv4dCQ&Ut zjU!C86{uXd6ghm0CbZre&-=6raSU_5VPnyES);xRQERde=YNr8;QJWy+S}&Yez>jB zG$Vyj!BdlpTh971sq_VQEG(@NKX3Mn25DGCBUX~7 zcu3MKv+T_1b?JB$i#`sxVoH52&Dej{cVeUft_+2WT+TV*P&M7OD`Z7(BS|)DbeXNPc%BB<-Qe!rhapTnqQ1ypS@XuiJtYKu-nsh(_wfX8-7z=a^jne8 zQWW3MuRltMERwOA`{~NJ4_IoO$rMQXxjK-9p`JNZN~_;&@E$%`KdW}oVcS<5l=~E; zE#aZ6Ie7p6^kUkZ@{ZW4q&$A&g?;bZlyH^NC=@c6YCIn_6Z_L(1ARMs)Osv=(x@|* zaoBE~wuR<&0rw8|8kz5cO}Vqa0rBB->muI!rD;L^QuVsfY}l70))}WRzKPX2i~7eY z0wxoNW%S)DQ);CLU8D>2(h2@Rba7K8Zr^P|=raXU&k3vz)ub6gSpG-T+oIbnJ8%4U z!%xQ+!RweHJjVAooK?JQ7J2=7@~vSm6YqmhU%MZCvRp=Qz#k~~B37hAv0f)><@8%O zIni3?4z>?FBa?dpT(%`~HkM==QnM z*VI8_UMOmc%AKfEW09tJ5Irm7mDExmmj(Ki%e&S!0H6HwKc3sc2(2){rAL_zQ7Gc+Yufu!bSStZnKjjr{i6|6~)Q(R_yU={Z_DRi1bjtm2?hHCws) zSVj3Y))AG}Lb1T;UC~ij*r3tPg#6p5`$zWO%kIE&y$`O6qu!?>*W$H-kA)wp8BasL zixG#cH+CdC+%K!S8=3~*3k=j&7&+sg-xZ`^^?tBlnTwMV3H!256vDoXY=Tvov9ZtD zlt?>K@P&YdEcUgO={}RUq2=IBXXgs@d21a>a6w)DE}3vZFFrlHC$y3}QAESsQDO9l z2_X}~BdWJ={=0zOfHyALW0qgXm?^EUw%zVK!w!;Ui%AJSN=|3R^f4-u>8}}cT{?WE zoy+;~lP4ql6Z(l}MBNjG|IwM#Wt}+D!BXH_6)^+bEAkRUGrkd_kOC(tqs?|vWBsl3 znMV%&+Q}OZk{s+q*rxR3UYmv&8M7mQ)0{Y&=f2~3MAdKrVMm%(7o%W<6D-NNgNN)v z%gHd=f%GXT0{7&p=zFi8M<@ic`FIwv0^1fF!LN6>e1pbal*U~YgC(V&XCAvy&Lt@t zZmaE8`C&b_o!8D;$|V~GMNshSWn+AltFsjRx{nIady@MsLW zR~tS>4yfJZr_CwlbFdy17+N^rx>Sr8Png3mTg_BOY5l#7TW)drzw&L+&X) zM87ewX>)73!pw?-cr&?bQ@LUj{`{;WXKpx8E~dk7@cLj9O)&zGdA8)Fts;Dh$m(A& znmi10wBf@XxZv+V>efat$fiFRKafD!yH`sUa5OEU#n0sRQ65=ZQ ze7uSFRa&WVTExQQhljRZHRp`>q5>_sw_;ieJ^hI0r%l#toKk{gl$gWwB6EkCRgHY|8KCh*;g!i!9y;b*PrK8uahM2@g&XJ zAa8bXe3zR5MXc##Et>j`j11bOc{U>Kek3fijlbFq6ib6wA&;;2Y%8uKZ}1}y_Okk8 zrg<~Tna|D|JARavQHhkS1g)2tZy0(*<9W7Ovg!0XQT*lzU|Kq+L$gd9EOkLD(D!I( zES`fdsPR`cG>n<3wW+AFYH}B}LZvEv5#whz#i{QVYhHVp=M}}nNBWPG+`8%-el>WJ z*6!JGM=~U)tDu<4eD{{JRGaRzJ8`%kkJ)j*ZnjJDeqXzq!&Bj9IY_eqb=p!Hv>8bf z%9cbW=J*{z&aJVHKKepNHY)n`dZxx`!R_pz&y|ebM7@sI-0fCGF2HI$M|wF5(~g0z zZD=wt(?h?EhZ|jR_MrAP|75PXudK?}9okfmu{xbWf6Pzz49~mm!K#8ySAAvII9Ae- zqZ4wG*IEazuv-Vx<&P5|dnKezwIt*=yrq8kEV)hFAL(vG*CPePi{^yWD!TG>J^7Si>c=F^Yn!O0-HTTgM9WvEFWfzYx8smK11W z=5aBXIH!o%EGAq6qCfdT7tbXu+op|_B%8;^-0&h}PBLk6_ubOX^e0b?DJG5fCsBum z$Zx3K$vXQdZ}AqxMC^QJIb^AYg+zH|?t1j~dzL~X2ZxRMcBO_ht;fU&(-UlkQw7Yh zrXrl1ugaXu0P!T=(~tLG@g7KMLrdbDX!$skt%c`v1^R|rz)NaUzKw61sb0lQ;^bV7 z?|x-Ky($!ue?iH);)mpEHi}ICnoVORRVV%EH_k^~g)FI0%UjtGw~(xK3978xW1%gv zTn*?-zO5x9{V7 zZQy-Cdmh0@TW1-7G0<<7W}$y6XW=FG^{GAON5%^)nqvHT0y=A!=tyno4zKcBj~9jW ztK81OoOBaxhapn&AE8LXY20%;=|4HfKigit=e8;)G2-dMb+wGib+JVE;HXr!8jnP2 z;}o$v|AtAnQ^24QQ`oPo__(gc$}C@lK1R{omq#bFG0q}O=(=z$5{B5tp{-p8|SQE$ydIQ zOy>-EA1WJlwonRtjzcvS`1#En4r2P^Vf?%UGTe6tZcdcbdMi>I>N6DTG20|JX>w6h zm!+tNma7G6?v@c#S(zuvW~c$9QL!yQ2|f-mHDMXPRKJ|R(Y5JrWaL{b(ZI6Yl8Dzt zPq^kLl0s5u)#IzorPuQlJtnZSj#(DjU{4R|B{T$yo^PLU2ZfUbx1XElq2G;Y2Io< zOFN_(F=wWd)x{U`D~fq?UR*wacCBzo-}T&^%VopghC+C>lQkut2O_8V_Ub$K+o%1e z(0tLW?};y^OB<($ohF#PL7fZKMegAX;Gr-d13&dn+G*AU4}Foo#H4U~{nx)@DN=GS z3#aYX@$JLZ{Yt+(@e>~f7`pEDP#zdOO0)L3G!dL=-?(Ysm_qpFT)*Os1icu^fVSm}lA6bTJiwcH!Uy0N=KD>U160j}B&?~1;{p}v;Szf$&&RFcxMZdSk$gRgz@ z(|tVJ;Olic#&kTE_fH>&y{S$=;aSZ~em2yt&+s81kM+n9E;Jg9{8$_}_491f*=%PV zD}bG|4ln!L5c93p7J;2#J-6T-!vPVSai=chvIg#|*L+f%$FQ8;n(sx5cGn2?AshCg z>$hB5r#HU2v2|I~1|cV3B~WrV=ys8B#)4Gn7BqjqLMP;HWVbWyIC^?!#_mG---t57 zzkxnY8#j2?7n2m5m5YrzGd$nU#mU^=41T*uCWp6XDjL+<7A~$fPLA-{z1KX{hD;#% zP07ruxj1C_ISrYq)!g5@xcN}SQ>p(7xb|{m#$cCpce8ea|GJx*%Uc^O_=-~SJ43=_ z>ZqAiojfgERGn-b-TqO9FAV+@GR*`Q;^N@q?ox%mHOJwX9}cnsS=t;Z?I{V(SM$9Vkzb-$c~y#Mn0aS3w% z{oLH(yIU!Azq*4l_Jgg9>1 ztqsU2Ok1D28^5(NTftIWcOip!hAyIhpD38q2Tb!XQoz z)HTA;MfSvqqxhp?zW%$H*9!XU?zAYc4_=S&-Mdo!98K772M@UK1F#K~4CqX5WqwJ( z%8api5AHeQTNOU@r%f=)y)t+&VJIyPM+^Im3vHkiYj&cqc9GoDW#2X<+C;06dlz2@80Oy{^%L#BO1_DYb5;BGqGI^Y_(3irl z>@ud5QYHG$90vdQra9O}jKHLa7E18Ys!#Md*l&>JktH#ZF}_ni4~0XS;4GFZ1M`>n z+EE#W#Yh;g@^-j|B!#;6@qy#7E-sV$^xfRS@k0i-1}Kl<5fG6v$OS#&{`rBN!YiL( zBnA7wu6qh933`4Y|JQr3pEiMl%v@~d_vzoC4(kE$!}2e~{+@_FHF-mOKIOw_|J4H# zzxDsj_;wAU37&8i)sZj0{#OqS9sGO$v1(622Lyz`ZM78g|5`U}(WrNe{;O#3cKWZ< zxK*q>^}e;o8ymi}>3@TiJ0SaqH(cU6}W1eB0@$BTDy=6r6$dgZhQ0`^|CaBsgNSgd{UnBX(~Hf`xQ^kydN# zcoV-#YU$cIST|_y0K^} zr4`g-zH9FL3sI6wknJWkRJpr+kGW7V$op{-Hm*Ve8*z>;wdnk0ah&FX29LA@fjLp4 zU{ZkYUg1SbhARl4-KM+(a!{hzyeDLCEe<8`&p-gnx<0+UaIFvcB02l@$gIIeVv0ZKjDe7nHSj{H$&ZFDl})wX{11{8-%Vw{M@ZFysY=pw(;hmolxEJe)ubBl^Eh%+|zyY2$VUpSu&tmRNFRzV@rxk zQnpldUXJoe9%kJR|3N=KySt4&!VZ?lMer-=van?S_yP(W!(Nj*sUPU_)a!lG>59|k zew^;H|5*?R@hdwiVyjcv6vz6R#ZK8o0uP5H_#iFtXTcZ*)-Ll9VW^An=2cL*xWY+iYZmbiEsWe(h!5 z`^x1Nrv*RtXGonU8)_(vJ|XE z!?|wgPisK8jKOuBg-RJLf>k2+7FCK&hI|;xrikgHdV^L13|kr&u$I0=;kMFH6BoB| zBx1f0)9GwtYF43}JCQa*lTJDa>U`4_zp47hek5(b#&m*iA0ipjnmp6iishk!=}TM~ zWhpfZf5t=PwPsXHngpFB87Vp+zL*O>HXBlX6BNZpP@}WE#A4U{*-0N_W)0z?ego3t zBeYy5@WMpIWz-@dgKo>}o%tK=FMqdGZrf-*HX~9j<{GUldbO(Jjyq-t!s!}){8Ni` z=V#~21wEn-)_XaEzNAXX=zA>`rVN!<+nv~zV@iwJnkcyn$i{c!UHsotdiR{Zw_bEEz~IU^mfREe%d@*B0D*WTcf<&(_Q_H!p&) zLtmKhAiPriu0BtSo<6{cw1%HhHjXuOEDr6GeCCem&dC}tCc!kScJo+A(v#puM3TL-Z_ zKe-f8Y^uQQvN!%+3)7*-#?aaREUoYo9$^KUmtW5!SF`-7R>GNJz(c2LQ`5Zxw`$9PRApY- zXnVaLV>O*!vnyNkO*_Azk@P?_mFB9>B#_osc*P=?5pbEI>}kIRf-9MuDC*==XlEK| zh=ISgQ6;0z-8YfM<9MO3*{tuXss&W?6t>j$38V5?d*dOBOp=3xOKE;Ul{NGbA@BRZ zBZe}Heny0Qz9iVGRPlI^*7ye&FA6kkpUY!7E}3^Nc6Rle?L$9`CsQD{NsfbqDSmQVowE=0Z5}N7V`;_J#m+7AY76>o1M8C$2p2t z>BQ-j9`iTJwTO`)iLts=7y_h;%+%e!+MOk!MX<7n?v{Aebfk}|ZyPq9;JmM|bfnMM z82M9{qU^k<)Z-+7BD#32BBZBC;uG;4g5^g-QaUm^ z4pW&geW+Dht#W2f^$>Pw3*8jz-`85p4cl!2dsum)sQ6lWdZ&f(J8B^bSif0Xb)qMn z-q==_>>E!(9+YjCQV;t+!2Rtf8&jb@4D2&5q9L>QmYN-<0=q6(J6Act++Geir>6oJ z^rVR=`Z*y3=`R%=nxBX@k3?yYY=T|xd7WUqKW?phb#XB!nsn(}>IA-a6hil)%|T-q zr7fT$*p^_NZZNr%%|ZHTrhr@dnr4ee0#FmmhESc4c*&f=fCk}^9{;X-C$qqDP(}3N zwq+cz=vXW%i|%$2i%p+U5m>95y)r1`R&DZ7Dju|s>gQ4mdN$x9h)GSCL-N`_K#A*G z=%fW^03eBoo$A(i;iBxdUO+@{Ih~N12XFfLy;IDj!MJ2V^$`AnJl7;~5D=#D$=Y*? z*8P{Rt%bGJ%B{8`hFzNzMpmekfRDt0@o2+xAk4Sp;$LPaW!BRDP&13Hi(ryPB^gw4 z8X#nwa`@UX;2RXY|6rQ{O6n$$O2SfP)qV6OalfrbpbETAhNrz(*0`m73rDe77&>g! z%l0sJKbO$y_vE)e*k95cZ}($y3bCHDlQ7Z>bRNnoGFo9fD<@`gh?{cxCMbqX%w?@; zu$V*TvuiINfL`uukefNY+Y_hwigkQ8XHlJbA(syA|rbz$Z-)+Wru$ zXPUK}exO&t(x%*Y`g1?C`CX=42E_I7!7Mz5 zxwNR^>w@=U6quJ}#sxj(j7i$;M2m4_J78Z-8=nF^$;a<7fHDBg0r8evOKw{{Kokuk z#w=N*_ovK(D)nM+l62wK;m6T|iA^igjvtVo;j!o!?C;mv2KzhK9Vh!Rxk@EtdnNK! zt603Kr(b2t^P?;ffVuxjPW85mra6+0OZcSAxQ?Q!poA<=HO4><4(HbgQq|9g<`PNUNGi3t zM7U|as1SDndzGitW4m9|A8CCR;I$K8F^t=a9jB$$tCS_S+176Le44u0r4p}Di8{GX zRbCPXqZ(VIc_BGAkVS4bOC*P2*VCjbG0PDtRo%}P_H%&2K|x#8O) zHtSI%3Hm-k-)8Z=P-nouVttUTxj0>NspIO>!C<=A?8v2wI(5#@WgF12Z{151zPRLZ zeB#68EJZHqHF-?5*ciZ%Szm4Rw%f@jwoA@%f>PwkFZP`v3ByC%V@V+FpvtpC7ishJ zTpNmB?eo=+_r)LW0ZM$X!_E6`!2toYfR8H&@9u4lxeAiwd0jakHtp9YNd?)PMYi5> zvS1iW=B$j^ZQ)dh#ABqkB@xfKqJ6!BMo~9cW|BrqZfugvVTjK)RT^#D?k`Pcv~)+| zj@BpcTJtU>f7`!23=VFhu0T}d3w$tv%zNgmvN)tNN1UTl5X99tLv&~)pmA1to>{^| z8^tRLHYZT3%xr*(bt$^3tyw9mmab~#6&7RMeOmoE1UxOL57Tx-(nW?nvE~+QBENmE zr=TPvB0j^rVl-I1SN1HFsxQBKA#>j`>0HWfD{idWc`Y83ugY<%b5t3tT^Pox`r7I} zK#oNfn04u0ySducDJ}&8cHTX9OJ{sOCjs>r^L`@|CA_rCNM5Vg!N&7e5@#a|J4gmc>XgN}%O#Z|%0C?$|ceSErn(E4-6EUg)lQw9S`nL-h{a3BqEx7Fszl z0`Y*?I}Ofhv*N!r$UGx&7?&VSm-;pH!f@nhgQ?$N53t2K8Hva1U31?b*lgFSGcAZD zn#+&iB3zT$k+?r(07or1u~9?>9EEP*%!AhJ*r-jpZfC0YrM2PHLRJ)1(s62K#ss1* z-y>|TZKu|^?G@CNC*RzaGp)^^{`upW z{um@g{DevrfG?NO@lllKu4uKO*pW@(i)> zh5w$f{aBi%R&%vj5cq8#b&6mf8RAxW(riiw=Wbr{ru{fCXNE&h@V!yiz>j zQjK-5HQ-;LAy*8$zI^``?|*iH@iuJf-2X}9uTO{F^cEKHe4mE%g}JwXt5qQ&`on(h zlj6tz@594N!5y&cVMOzL|JmW4pyxZbBAFJPN|rv!IOaHj-!NN|S) zckbZM9o%t(J5KQbIx!R%k8rWe#)`2S0!z^yia2?d2H$nvqzg6qKcM?V}p zmM%6`>irdDxG4Egib8h6lKOmaUo!BW5(a&ev(~?(6)#*A4Vwtd?s^+6{i)oTk5LiadrnyQ@wxvlY74~XC?ZCwn6xR=gACnky170kHf(mk#&M>I7Z zXYAFd(vSa)Ve(+nTPbGu>hA`@Lxc^YqPzs1t(j`aT#d@&fnJ6F&`7U)4_Z5@lQga- zz0vvc*AiVV+z!H%0{h%gN{+YUTti<+bc9p4rAKKIf&d`bxGA@4Em`=EW6gL8 zT*VNyrM#W?&tt!moH}L*T~SPPlalJ1NsWU(U7U6ML6A)K`}kX91qB`qUy95tr(Hp{ zEFT&_pAJUVDe`$g-*FWSey6Uku06Zj6SqZH-r_wvItfdIIE_`$D)HHIyQY6IH-8rb zxQ*bra|FwKA%6fYeg|C17l>s>pBSW1*mxi5^~Q5qw~;t12Jmj>mZTWq76NE9a@IVt3VD{m^`>#j@Acs3P>@@1(S;! zm^{w9-j^D`OO4pr_9n8dDXQ9~(>{AkY}Ej(p2_|&oeBFit!`NhgdF`$4fY>M6&tHn zynt@z6a-IMR5P>&5#c=`bF)evD+5bBl;ejCgtUU|uP%0GM8ZLmM%rnTa%iNy6+N#v zNV3?!2yGZSS1k{FT#R|NoUJ9z>CY&`Ch;4kN;L#M2W;rnZyFe|E9O5v$~GcrI~V;J zJ1hWGnH*Q~xrU21kIOYtSIO|R4XJ>tl{JAYX8=aw$^<4%9vT|3}QczFV_% z!*evmr`JZcdE7B~c~Z^^>~P4FoEyGqc)*WAV`s9X+n58?Eu-$QL<;6R8AoU+H5u9* zOK_MpvF;aoFd{H_AOvv+>UV@~ZZde3WkhVOnL&o8!%nPQa8%xm{+e z&wD-CYzn}Vw1+;mZY3~cb5VzkTF%(O9^M*bl&A_W?Wnh`J6qj^lomMF z9VP^oNeI1(eKnOx`Gt-_RgHBaf>AG`F#x+k!+9lw#c_A~6oycfVNIV=3UFB_zQTEN zVE*JOVc5yfLOHRU3&>K)RHk0+<64W)BW0giTbr7@bT~eibz8(Ly1Il~+D{$Xo)IxO3uIc>Uz}_zXN^|5%6&X53(jW0nEKv}UvmlBTH37!1=|_U zmVHWK*gA^8O;sfSjRkzC52Z>UtbINhMwMP=Z+1>6$z4LB$w(>vIKiqBWu$~pP0gl? z<+MA7HD^xFVl%GW9%|C_StYhYa?a_p5w8xT$poWOR?aW+RwQzJh2(jtHoFy$Z?S=DFUXeNeT8wKaJ ziYQOc0)QNC8g3j&Mwa0juhTXdyK1{W|GoL#Ne#gs2^ohmXU#WI#`9KpIE9RW+MDFCN@e}CukZ3vbsHV09&EdXn6 zX2m=kdY^^vGAWj`#Tyr>mjmmEf@+5V?qy~1FeCdCrR8yPyvgVFkg4?0zu1g~-_7Z` zPMT)>iB73)$<9rtYaJVA9x?-lWMRKnwXK0*AO3Mey=Eh0e5W>g&(!h*lv)NbeyR&8ua5eZ27fInwJHXeMNORTOC z+;Yd7X<>2W{cVxt=w4M4Wq)`-5EGO79JAM%3d)87B>)L>yrtsdiS!6}SioZU4|nJe z-r;JGnH@@2W|BL%4BzqaraGu{Em1ToaP#M0WmZ*JKKslIz{X(u$e`tD{AO6b5d7&b0QcVn&t8ki6Vs8-T?Nq|nC94Ugy3WYk84Aw4gc);{F9U=} zlQ3%`jPZ$5d0N*y;A)tnJ;h&SJkj6_4Dvz-n5MOff_G45I_4$i{l~=kMhW)HIkW1mtyDFga*k3639{rfak}TH``6}Vd}^CX@toA-d>`U! zJUlu&N_Makr42hEl%bTA=}Iac%SJ;u%dHeAg9cO`uZw)?k=KQ_<{>KPt)Br*mSgl%)gl{1tA1R4yVKdThBBzQ{x_e}% zpItMJ-4Ar z_1ZJb8F3c=Fp^d?unHrd+5ECbW@)U?%F0mjnaTN~6MYstE23M_qYW%}cJ^b=a*Lxy zT-iY*lZs)ahO9*ErB->d{0uz(UzU^Ijuap3!btzQrFT7QKCPcKO4h5DZX^| z`&;!Y61?`WSY{?R=3OY+4CoPcJv=ZjwYjN%zKHjY>I)&`#=$d_m-Gzw;pS-CmR%?X zbomu26E09NXl`#$9WXt-#<2iYVq}5=+-t8RThoCQks{NPYRiqjV-EF!19gCf zbTNPe=?Pkt&j)*jD_pkevhOyOVZ*9J*{@ZWxHFyNFNys>5At&_`idDGrU8 z>88P)Ius$0?P;0SLSw~l)mH3`^~|ztEGp!nKw$k>R5O8uO)Jl=_W7}1(W_4NJ>~)|u2;ijulk@X1 z_MdP65lq%ZdRy_y!+o`$?7f&4E|Xoyq^aQ6)g{gjY|4{%x`63%h#gHfI$&LRq@&S>TrsMI$P_1lzI~8$FYkr7HE{{yvh+G&$(dVK^essy9YVS6qs2*klw(gHEGP*ZuzV- zL1N{Gkf1WJeYv9j?80P&&y8Dc69yfDM@C%+r+W+EF4H8DcgyG8t$VrFnqgG!>?X2ck_sXd z;D-T`S}kG+3?m4&VKJ^AEbOD#Z2zpX!5|0cB}2CtSzeQV879Vq^}32}sK)uQnC>i) zwfE~$+y7Qx1{-C4_?`xa7}`@!NP5j^k?s4*g+2cF-)XCt?r*a5K#55hvFeGG#OfT((CbA zA21V4Ys0;s1?;F@OEz$zq;LK!Bl`;W{LjA)-oJ{V$)OU-F_%LE!z&#;yl61w;IuD} zEEsmegi*ObQ~RQH#;mG2iG-Drk@sqS+_5=SQ=_46N(m8{UW*`vm!D^q;XUb0^;q+I zt#9i$-(Y|KTGwq_vVpbnFG!>L>SUa=`|r;W%4OTmztCkT*&VJ*v+U2;F7X+WK546U zuGc&rf*MzcHNmvCTOh|ourown)<;OPn zfSVebo(i_O&_QNC#JM}6oL;#gnk-=Lf(3R86ss2U*iV{hv_-+g4G6J4Rq(Ktx682} z+|Pe?-yx#UZYx2y+0o-b5Egcp4Tx>ZJ3Dkvq5Fks+I^C%{1!;f<1Gj~bTq=u2;geG z)vxg<@J2e@UlYNYb}~?!tQKEM#B#@AE^9fu)GC$Y$G+8T?19yrb*Ku@-!K+s%$Gd+)?r zxiY2vL#{@qh-!CHyfhFmcVLHnr*>ntE&#f{CG`QqZlwvpwz zfQsoWyJp5)v5CAN;Rn)W2$Q2kd1KFehBkbo2=#b@5(+0K+4v3r^=nDEp#Zdu3AU+m z9jm69VoLQ|@MV(o7|2vbE$_KHU2P7S6Z{Q4wvCuw0}#2y6S0JdaF1qhHaqX2xt^aDp(9SfbrAXa)?8CwUQa7%W$|8I zn%0H;V?R=gO4E#iPvKOk`nHvv2>eL1XIA0on~5q0Yl&_&bkh`+4>%>2&fv3hEW`7v zyOiYg!iib!KR>5#J${Cr`N9 zS^a`?aQHpNgu05jkadI`(8MEZrCm^m9MQo5kFYC#Wk-|ZY(m?`{L`$k4ithnjAxvF z(0rIwEL5vPDf9Td=VPk+<3Gyfm8xWs0_*oD0%wTkUPg*TXDGT(iJ{-0mDD30tvPiZ zCgFSe?`&P=@n!V^?5X*LBcql!WV7=uU$&`;D^0+wmM_9j z98F+Olx#3eT=bX~UtU}(l|&|mErz|U+|Q5Ffa0Lp#Z?NxR^$nXfQ%Rn2Oro#K&R#p zhj5R+&;TlwiUi4;-IbS^RZjitEbX|`A(mW^$gf%5RiU&Sti*4bm88=*apw2^`&g%A zHE-10L+7V4$fv4;manw6RGC_Q-TNR_35l9%Q4l)$xDlo+r;>t{<){4x2#_CN7Y7MD zW{zW6^xDUIY#q5hv^|OqGYfQ=pE8ppxZHz0xH_rZ?{DJFxs>gZW854LmOq9J-^;!IFQ}9h-6tFw)R$U0Rx0+FL!ond&wTY^I4zG6hcr=a~`1uu_6@8dEW=Yq=NY zV$weUwCIwD^SZ=C-n>$`5krKCH=Ng+UMBA3t7+zE70Hx=Xuh{*tnT`UhX`IFBksFa zcqCT_)FW|N@Fag~&Xb??Cg^n0#!KKJiyhepmA$*&SJcPw2>9N5#2ZKm$Vc7{s6dol z8Iz`v-4lzfCL??ULt^%nsbXxwWC0`}bZKlctDkRLGaOu}#^0r3=P}7W7gFYbZ6*V=2EdQ! zaQ$7_H~X+=DtnUXul_{OD5&T|{q%g>-(kIUQ+dmXa6!*(Ir?fTxT!T^`>f8$MX)+vNPzEis}Kzx~13WQ}JV+Hx&?+t&`D(Z~LMI z05p_a)mzVk*-YZwch?&%hroHU&E^;67rJqn|E=^%o5M?q-dAr8Er|j3o}x zBw@j9RB-gCqN>#(A_2EcWLgOSA7-|nJ`ulMr~pYiDTZkrdsi-6ow|3RX$V1B zi|5zGTuRj+{?4l3U26OMJzv6ZVv4Ts&$*#11H?G+M>Q%5;nt2cYhg+@w((m0He}Rj z!BDl=o10y067Tg>q7N79`x>IQqGr z&M1{gzc)D(anLfr3!E0$Kvm&^ec_-6k{Zp1=o!&PRU-d#>Rl94gbN-f!F9pVM#^8cRJNq^6Bp?wI z#;xq2b98o&@aRMHz2!AE8B%>R+qnXQqYj6||9JOpMmDv)gbYCDyfu%gmFb!pgZwLu8Eyr6KlKf9k*z`&WfIl{_9xJj2*W0eUb4D5!4 z2HENThB8D{oZ5h5RDwpV?MR|GgwHK&zEXWoyUW6<91R414KYAJMJXYlwn_ zN7d$DehPCCd>Bq=D^V+9l8oPQ=#<+VzdUlaLK49!3>LID0p`vWsvJC|4P3Do&503i zlO?14_TJ;O}loy>@2cWPfT%C|12xzmnQBAZ@G%Yy5V&ENcT;c)PeP%s(_ z`*r%U5iyXZV5sQDWl>59k9a?%p3^#NmDW?glmt7XhEp!iyZIB8-_-GyYT z+PP;%8eG_KH2@p$+EXEjdh#(N82&VVacfwfo}6AA;l3T8Spt;cgrC1XFgUa2tnlZ% zJY5Qli!-aK2h~BNzbu3;TrXf<-HVM~Z+%UGUt~1z+?QSxQan5|a{rUKYWIW@KAHTz@Q)452l#-F{uuP{Wi0il8j1u%kD?7I*+7$UM9xov#K{&mB zbQY3Zc_G4h1+2g`!w!A@Xn1TaAn}XP>l;ztXb3XuwHR4sN-=LCQ7{<~fy78VI_l-4 zrtkAOe>Pv=S6ByAr>&4D41W%Qv7Rp2Hi5Ug(%r~R>2x!Zn|pF$(`ka}y?ONH*L<)4 zxjgM3*?v^=(C|YvX3eu}*7A$GT>l%zCHMTWv;V{Xe@(U6>!v4PRMAS9rBJl~_mJzo zFnjd*eYJDxtz(8YdCmSR-P)W?7*#WJTg`iJ&(^BLs&{MLc!Y$T+^c_Iw_rmo0wQxR z7h~zeKUX-EtzUDH(WHY%Wy!D#`{VAZod@W3e30wU!PlD+Gz5S+J!{qfM?k4kp z<$NcZe=6mzjP4|JCz-!V;0|a03t#Ufb0?XP#;^K{gLG*9@J5%3~yItV;Nw96EnU~U6gcdM_~otmIV#G- z$KZ#9qw;h;24-)xu`oF`Tc`)QBh1Y5!+gA%@YlQ*;V51_Z&k_w^2=_XT#8H*20Ujw zwnOQw7>`)nO0GPoGie7XPbwxq(`}Zee7^AB=;En0<}xyCFDI!6?GxIsPnPFpskI}$ zDM5nPdEbBP2>U-o&`)~<*^X4@VCUEHp>kz{{-JVK>}>hvovg9AtKg5aI#n$tc;8RO z_qop2*|;3s!unh*jTqHkIzwGQSQ1mjx(X&LUenFV)bEz*`fnNe(8=q`xAXzq^e9SBhq1! z7>rCa8@1bm5zrv+*Pp!g^VJ1E1U+QtJ?kZ<03|<+J!12G_ipGp_zKFiR3)dhwm3nM zAA@_Ck>1fHSuQDQ7Pn6R03J1|NsQ_*i7@2%8p#(=m;*S!uU@BZVQDA9d6ZIi6&JRu zbemK*Qn!{R4QO21NfTr6bOD;QLKjaZwb&bIb=m64(r)muRPf32#C@3W`Ov)j&lyP-szi8vL#cz$=?;$~6cgBfBA55F8I;gE0&acN_D0YjU5 z4n}Up;JEqtjvx1)rz@cuviv>!=H-c{b6>OpjR5U;YKpuNX|v=?w$Ud(FVe$*S4m7Q z+wrZLW|_6LoN-tzjde}i@sF%WBMvxcrhWc~>ji$X-@tV%yWR^5Kb z_WVPn+8M1-Ps0lpR%U*jS|%R~`iWFjOIUrdaC7Rl%1Krmsx`@$cT9NLia)EUq=Ic+ zchc-(dZHc1a)u<;TbU1eQY2VRA7E9u4Hvv_{AXtMbS#D+a^FWWMKR!K$%g;UA;Z={ z?)k(@Sk(Ks!XbZzuO(Ih^a>1TjE{k{DWqG-Dmu6L7`YjRSCE51_6b#u^U>Cr1c!6^ zRWs;EiFiL~G9~n8yHYp~YmT1z!Fqx>+$jXi z;{3Cm_RFgwzqw8+zcMW)_%(koIBev;3dK*2=nOxG)R>N4uLhU2N`b()k|P`{XYa?!1 z5Xi2S$1b+KKNhr1gB%M#!}+K@m-%br+H(a7S?9g`S7Y+uChYyD;R)4~)O=feQKq(G z`P!!A*)bur9W7va%MYdx-l@Zv1T1y_V3S0x*td_(F=o{~?8db~>)T8$z+Duc3m#Uxf6KPJKY_UvJZ0M3jJ+ko zhmAFV3YYUAxg1$j7s=(i3BAD4m5N@jZdKxZ)=L4a&zW47gQN83wHlDltGvT2l37(i zLq!J->tn8;jszXwFtG@pp%i`4Wdfrb+VA)&{9-4M&H2`Au( z0gW;>2JlhkXR3tdp^UuB#s~ps_&_^$c>VeTpU5f=_NRJ3bNIY3lGBQXIE+-p_1_n= z+-uqff!uj}c()IZ1@MA!FP0Jw10}zIj+Q$!6^mJp8kKO7Pjfv<<{p(aj-g?%<4e{_ zJY36x2BI74oGQfL&g7ThZ%9JuZrICYw5Pa%W@@kgv4;h8!YR)nVB6Fv@Jof%$Yi`E6CyKc0-8GvT1SxkVlZ1Z! zt4|)?RouOouRhU2kL25a)Q8fU#ijw3qy;vfZPdg<3@JFDH&<3xx(>8ktp(!nd8gM* z5@6W$f!C~^?V(qRYWDZU|5x?8cKC3x3KDXIP-@5TX4Ly$U*C;oN#OThpidGWr0>rU zGFIbY4_+bxa%iXKvPR68EWl+)jy!~f>iRp5lqpH;S0Iq|_lkA7j?S+U4+{81cPJMs z+ZxgEf}>s>BSBP5Gn#?u1yPL$_ha}dMOI}k=e|}`?{G#5+00>AQIDO`>WvzVqz82a zxa{D5{%k_U0lVXTACWAfO&!{M%&K_A1y;on>8uw}c<1bz+*3<(F>!zQ%is2f`1)uC z1XRMj4h5qI&IB~$)6qrxQobVFwg=(KGS7lnlVZ8oP`%#(_Z_s; zo1>Xivo8}P`iD+J-dZN@9}bKmX=U#wMC@ z)H53Gp!+NLBJU@ImDC`@F|Id0*;B>q>k}1mx%d8Kyx{QQb(Z{cb2JfCg$>+mKU@m) zy*p)7>4seeX$$jRe3i{gqH{TUMS$?_`JX3c6%UVxyec)`y*KW={0ysx$1kMB;Snxk z*h)}YIEpnhKdD6*4VVr2p=5_a@#5Lc8vAZc56;$z z=t2Qe<`Jgi0s&sN5tMfnJP019dGTC}xVECe`W@M2I5wWeu(C0|<}mHkKX$wVgNfM3 z*h||fn0Uao{j6-+rg19;mb+ovnj9TJn`+9cMp>DEL`mDoviK&>3dA$b&um!>aMWv* zZw`tYb$5qy^7D}M46iN$JNL7%F60@bS*56g1H;LWJzQ)L#`t@1hTM9G6=T>dZOJXR z3s2Jfy7{Yl>>P8w@m5#2hgzSvD;^IGE!XLfyefA%I&$f}q0cvJsf=NKRiH&z>cern zwL6GMhO@!z`~1+nq+xVFd-whPM;uWe8zpX;Qso3h=F&I`#ef8>dKIf}eQlA8#3*7s zs(sVBN40)nUu__h`4I@cWF%@+i4;cgi)T`z;$zuqR7oo@@vVP$JO<@*y&wXACt9)7 z;)JcGaJ{e0!L;9~-k6-!c%+G#{16_u}e(UFOsTp&|40CAk?=&eDcBoiFxX z=u{H&xkKV0+af!q;PcBEhJ$J&j;;VQkRuXPD{9a;ZH?uN!>zi?DuS=;(%@-t32yR{ zxKgg_3tRrWCMr;EmT&Rj5T!v7hA8;rfZd>9(r6&ZL$>)WAy*Mg^8}k7GOqqm-gzK= zS4mPLy{gzdwXG_+$2&C5dG!YyZk`oM+=JcY2VA^k=ayOK+MCp`TA@)rhI}O2M33fd z6CO$@ZgG=-y~k$;d$XI=(kOaesr2so8r9i~c3otBEpRH8iyL{rlbQ>YkoY<0Po}Xp z!`99-+Yx%)2vRrexJjofB^ln%jf>W`2g{?>b?k-&=SwpV)FqA9n`#MNV`Tp2maL6i4!u1)u-|77K7w^^0T z2zUTIWMXXdx$v{1ihTU7z5KGHoJWP9zmJH0J^8Ix7!3#uF;NolA44XmI;3fTcY$5^jgOQub=V#O%}d!AV7$9)lds6=4M#TN3o)KO&5R zBmHAVRf`z4l>zE67EA>K4`pobv)eJh?jv=2+w;j-fllbcYT-qPly%kBaxT5luQf;M$}brCTaxyx+0y}{;5FP4T96JwVn!tY zqer`C6E3U$H6|va%n~7O*+E}y7N!^Sx9l+VCjf`(S(VbdBQLdgHW2q2JfbRqFK^%YEh=yVw+pM3Jk;f8p58X$f8lpu+5oaR;6d0*^t z_=GI zXUaI=Rx^ctvDVt7I34>L!Cj9J98wQ3Eb8pS)XI!MeOF?C8>aT~ZPJkJwl-k*z28Ih zZ*!VlO0kN9LS%6g9t2m5B-9dm3OPkF<(D=WwCvvVovdy6$IpMRgdNetX@*=5&ekaR zz3J}~Cy^_ms+)aB#X1tE$bGSTK-20@Xjlo0roy>_14q_aVSzCZsshg_t1F*W@PlXS z9(FM0aYh<(n=01u<6zJ{rII?5wG4lZy)nVe4XF8p)$>OmfqSn6AtdkHq~g&+CAcI= zuU3Ej7|*GfaInjHqn69=t>V%sOP=B%=&T8DZ1AW2esQ& z(>;1Q4Gnr{XXlGi|Gf`U)w?TorQuupzTRb#E+*~Ht*^Ge5;MZMB6F~MwxjsY$(+P- ztJw%@0F#CaSBhwL@Uc+%l)TbHjKEPl(K@Hg*$=j3#CkK)&#@>U?qk^{I&aU)XmY$o zdTF=UC}qgEiYe+MD$-`w7tJ;N;&PvJM>~+np5$TZdU9Jm|F{vNC~Ol_zALliyPCKa zwQvnRW3Rg)a=D25KZmeL2|RxIn)^> zmFR?i_+hf|TL1$iY&pbjM{rHLT~%Wx1#C6R!g#fh=+Rj>($izRM)564o)BQhI#k6N zRF56X5N1S5*?hg!tyMyz8a1b5=k4QvDlEf4dFDJe##{YNeaEr5 z3ph~a!0RCcHBycm=<<%)C`Rgq#)6zlUU|WO5v$hOl>iMx)u5|j{R;TOWjl%D5C;K z^GkSva#*+hedlYtB2>RQ3r-xUhD$5_I?PZ~f7HYEyP25+l<#>DOJwLnBA23AVE;wp z15zB+6i#bXf>dZh%+oIh$DKcH+gkOT+XdVKpXipbfgiuk3i67W>i{NMHZXU~w42#Y zV{$5f_RF|(S1^)(eqcMok8RXTNJ|+JloIuMlX2##)-T0_o2r(kVz%iGsQyP!fm*!5 zcH4rM3`ig)>TIw?YgNkLVt6;PZ@&SV_o!d^AVB;4wMEUo=o#$&3pD%t-GKzr-{$lG z2S{F2f^Zc5qJbyB69LR{2uMgs`3)lGc_3BvOAD>&$!_&4Vu^>+@ihCklSbN3IbBZ( zsaX`RmKnMt*D`{vEmmj3du7SuUO?K^ZIa&2Gk7p34zW^NoLw$c>`q!<>iMseX>XM3 z4T)TZ=2HGY%zgDkl-={TAP5M8bSWSq9g@-@0s_*F2q@i1cZh-tNXa51-QC@yba#ia zbi>l|o)zoy^Zf(f-^jhsea_6BnQLaQi9g`VNKX#|jcdweF7w#x6jUrMU0OF%;DxKd zTyBlWpe&7vn}QSN5;S5&n_paPm*ttHPLd3U0MZAAYGl@9yK8~%{MT1F*evdK*k6_g`b?p#sH(PtUR@S)&%=c7fJo*i zcij#)V48l9J}Qjbs2MJ zrl-fg9XMWQ9rq$fC?juE>N=X~^qw}#YKM1B-f&}Q|N8O*_HV50BGvc|=4+ ztF_n36PLqT{~(cV&~`{sP*4!l_TqQ{06?Ai(Lu%C?oz+grQW)uF0u9r9nM_UEO`F9 zV6Am!FslY41XwAc#r<--pPHqRj%DI&Yjtw#&RzAbeX?>Z+vZC7Yzi#LxiyPTLYt3b zt9xZGmb}9~2c_yN$w3Wa?J>g~V|RA5IF;yljSj`AzV{y z)Jf7SBhmSpx8GQk9UGL*f5BPA-GBvA@*fcFAFNl9gT|W_g>29nnJOKM6!aZo;dSmm6L!Ekn&+|s*({BnT2zw2o0>IkY8-0wvCRPR)^1MQ_1 z#yiteg)oAGZfcr2IvBaRRM^Lx^uuRM2AcP+ZQ~sR_QxK^S5$~kxqBs57p|GNb}}9; zIXG*)2_z1sB#h+}Blvt@RM2G#CUk=@1kS?KMt*T9shO|mBPm!d3YuI>H#)+{$(_Zn ztFYzPrm8&nLP^6UAhCWAhg$f)SL*3uUpO_b@x?RNJA=AsGeW*k^Z>n1p~I?Ll%QMb zwwrRd8HaL_>(;Y?>y%zcojRk{>+vcogT!vd$!Sfkd-RP4vlCKbA8uL_EaD@yUtb$l zr^XUK3bmN1)U|vx=dQ-iz^>9IQEDoI=5d$$&S{o;N~N0Y?UfL%!D-xM>p)PBU9sYC2Mzny>`2$} z1Sy+p>r3=1^abohL!3o`WN>K6>{Lfi_C1(PQTdp?A6H<<#rK!dvZocflEi;!2d*GI zKI>KJ^L18kIwULRG}N3*ZRk#|wU(PQs>_}*a^r@u5C{zwEo<1vLyWo1I9-=_+V1=J zthj96)Yqe_WTv@#?F)BH>pXiszi|o*z&q3cb-46C#3@B@+SSz5ij8Cu6*HoEmcw9A z(OBl8LE!1^5W2xoVDHson~gwkLZ1WSBRS8DCH|&G$BR;|z-}95UpwOBt@MYmBOyih z=1z{6r2VwiE#Hr*Q1zT&%n#I~eo!B1%Q>iFdEzuL<#2@1I$kAl#+(32P^t58Ov0gd zSu&6!=aNBYdl0Bs6gzt)h+kh0T7OVd8z%4($PqW{g6$mLnP^bT9?2-jJp7g-voOLN z_Ccui&`sZ2B23_H3tz|>Sic*ZzXV6wN3UeBF@}4ce-fT`ab>nSxv0$;+GP%(39)IN zE|V+Gb&()3lL@+@Ggp?+A6CVe65Z!}D?^-9>;341b?JOdMVfs0o2?$5=>YVbOXfbp z0{gLAvGd**Cp#|0+*7>#OVJTtkit{TL}Sb-DHN_fLNjsR=|{E;_L@a^B)bF*Garik zMTt9$>xm$@4Mf%n*PS85zF9>qb=#OushL`udcCYk$CMZ4Rvy0 z=+dEm2Gb;Mm8}_Q^S~qK5+IgBVxsEl>7gDzU(j8djU_o+m=n&L`DWDHU~oGyD~~?( z%jX+S9rLdSm@=|+BM0U+qC&X7vahGz`L%%_2#a4n3|Z6uC| zNJE#Vin}^>Y`}%|P7Pl7K8!UzTg_CZT`XHA+AaJhkqJW0>}j*EMP&6FD-HWy)h|?Y z1}EyQB%)=xW2uoJkL8e;S5~5-N5eyos)4(xdsX#zdD*J%hb65}=5Y~~E8kf*^A2do z&N^4kM8hdG_qS77+CzOryslU84XGD87}u^%9j4w=D4MO54syUR-0r7QdZJ3Fc+a#i z8S$3uTe4ENHR-_Jt9Q0GGMW1ZCK#$}U1ZOMSa!xRhnib_;Lh@M-P~N+x!lox#ZZ4fzvS2p$(>(qlp93f=Ev5^Vu_o)lHw9z6x9 zo7hY0KI^>4j-qDE>8k8UugIk=4Slu;T%Ce?!D?8#nNJ}!)Cm(8@UwZ2p8AW zEt%(QV3sR(6~iB&^-fOiZLaS178y7>+Bu20O4e^8c6KuFu;Sm$W$BK%S|zl;@5$T= zTk(0TZa7wLo?NU~H!u0MmAm9KG`V1TQbz^>=~zq;rtUUq5gKgy@H~hN?M%zeO7t;k?K`bSpQ`xAR zpS5j!WpD^@ucZ+vF(cOC+E8~!G%e`q^Q!8qa}PjBN8jra_-sKRlKng*d(iRFJNk+P z2q-`qN0w0M+_T0QDJUyXU}-SF=o@CYS3j>Ku~xsdE!0KET(f0SPUMLj7QJ61DI%}D zn^1TsVHSza^_>K79onl`;v^0{TztN5f)$E(`Z327DD9uPRtHu*JH9TxB{n>zisy+W zkEU#jC8(+JjU9{%d-37Jf>&Csy|tPyLD}Y$foNB{01;jE$DgB8xMSjyW49E2&`R9R z)akW5^@dD4P+`JXaDK}c;1egRsZRuLFe6X&PCs&96|sKwQNX?sEQ2`O(pCBGdr}6_ zVE8ak*JJf*aBJd`ay9y@sZNu~5XrQT)PX-G==dFu%R&4S@jLYs0$5JC_ zHUlX?{c-|&2HuoV9DJUyBmI;wTAX2q z8XvoBv;&ROX&IE+gTo4vlni^nAbXk+t5Wv3`4~@+F>*yHKeWaef7+*e+>{mw>5U3y z_c}j?cZz!JBAY$oAw|HrO*C|32;*E%>9^nFy-)p^rOG5Bnflw_o>JSL8FiniqE7~c z$91hENvxdQEBpHuWJ232C9D&ubJlO?QiJ!*-O_LUOebH9yMnHOS$i)<5|v_x7NKUX ztK`C^@ZN4>Y38FazsDi^a#d1&lAS8L*VAO|-Te&SN7FWE+9?*8n%%7tW4Ui9kv1b9 zJ>>&=B_fReS-`FOMf0<{g{(8y+7JaUUz7Ry{wm9FY_O;y-On*~OG}qMu{igQXYJpr z)j7d%YbH~$aphEXkNw&~W0r&Z2X~}X7Mp>ukLSpwmT}$OS#Mj&Jpz*N^TM5=A%Lu1 zF<%&olIj68H@aIDYyE5My|gL1DE-CE6t(byMxjugNCB<8oyVbpv9_tyO_Hs;o?e<> zoNs@@_w^LGsI|%|qC>QmaJS=7R&PGvpkz%f%e^e^G0DJ=!m)5ypC36hu_mo_)5lQ> z1+iw@mxH)<{j|ny7ge)N4r_tukHp8z8ijz?yY$;rtmNC z*!16`oT<1Tr_ZINr1Xx=jEsx(-H+rt6Nq9L67$>+NB(Yu{JB6J zTV7611Yj3Yzx((j1!(3B4Xzux`>Y@-h}Lt}{9R4yv!x|mgN}hB!{=&+OdkcMo8I4E zExARDy~OHsIPysI1g4W=9iZMYUozSKQuzj{&%5QVR^r~I3kg|Ll(?yX_zJm6OsLmvVeuBe^GW;UbR;VN8pUsvyapdtNgi>R&c=F> zE*RKVLg&Rs*`1Mo#+1}j#dY-&%FfOkO@)}4l5dvsoLTu+i7FO^7onWHxF~ ztXwuK76&4~G4FiEm2Z*vI#wPhMeMl%z1c9^LFVo@pHth>D(F)wHTf&eX@QE-ts9Ym zMIgEI)LZK)TekBqiJALyNXRFeB!Aj=F(++GDYV|RX}t}TCq8yvyv<8ho?Qzg`Y}aJ zWX>}PM}PtE?s%zXcu2_2)>g)F-Kp(Fyhs%p(XMOsBV}@CjJtzIlbHHgi3w&!^T~T? zO<^=VI=nKN^G5A}R?Na&x;ckxYkf$&Vs@V}CDA$9;&=^B-!wf}D=qSbf8{Ia3n#>! zbK1Tq8MKs1w}?$-18;&XnO1v$x`E{d$(ddcxv1GZu>Eo`$?%ccgm+ocwV$!L$P7Gn zH&KuTMWtY?M;zq3vC}#hv$L?%J-<7+YPca)WVrFR{~_yOQryGw0)77pyKcdq)7@@T zAM~OMd7-1^(|KCqd(%7bMCz{NMXI&uc)800dH~KL-8^OU{N~IXi?GU-4JnlGECS|! z+Ay&ayodMYA6Jgstax|!A%)GP(+?F6&(OI_c=BJsgOBswSO-{|3h2Me^p!Y6O9S3+C&^K>AY zeI8_lD=3ug&E1iT;RI3|8gB$_7Z1K_d$uJ}Sl`T#uMhUzqtdLj&j1~bn)wc#ze++7 z0h^sfd=Sw(NJ+J$RiEy(1A5g+IQf#n?3dSt9w(0aP2T_=pmlKl>rop-qEw{3t28~? zu_4;2M%Xo#?!IfC^xGy9nPWuzAHwgp1hWb%Qc?-{l8_<0_#5k<82!5UP%9kVp&Po){Y&Gn@sd_|;r5sU7{8f{K%KK*LsCJ%xvA^KfPT zvu2aJj(pqRH<;@(bB#fuOWpgt+Kt&?z=DtanN%|-?pacto^HhodK8~!C5F`7a3lb! zZP@9H#c*;Bk;Xx1X7uz;>HWt(PDT5d*$EchYhO~wK@`OAIYFBQjiRt$6eQgVTz z{fn|;9@9A?3MJj&UWU8YiWX+!VBTCZ_9>E&$%G6OQ{^$8XbGuu@Y(J54{lCyzg0Rx zx+Q2>&cx^Pu0#0Q=hXu%VV>ae-}V8OLJtjW1BB=r38*OW6&3MnIIo&MlS@oY1iYIx zeLX!hB~Nx2yCXp`-mJ5G>Y%h~9zU*c>Zt_VFikeRK{8mRisA+44MKgOa)~3xe(u+YxEwx#PE& zqz)R_jN=bd>c;B4E-e>8rPLuqFjsp z-EY?suBdVd=X?v{aP(|1K}15rZ(BTHC+`d}+WIa*6Zx*OcccxTY?V%`rEC&o&uUAj zjDNw)kEqu)j-df2UP(iP4nRCfImdFwIgDG!t9k99&(wpPO+aA6SSSj>9Ny;_gGj81 zmIEfNzkDWd?>c0}ivkHR^dH0yHbjU~QBgaQb*JKv>ti&-I&L{*-r+S!n7*Mhr%YRe z>bk8v(DtCJQ=qyZK7Aq)o(^5XUWyWtH_D#yH~_iE4XVG+1^yx!I^b-4oh+7#5m7Zn z^hWZZ?TqLL6Z-_3=T`cA)^*w6ugo7{6 zz+2Ai?m%^Q&EUx}44>IX|Mt0HVV1Hf*DMuv^`w{e-snqEmnrAD z8^MkOTlH6)0u##1?+5R~aTsL#cqhPaq@=6Mdhg!7-0{W5MHyGu%GI;B2uA2T#$214 z#h)4JU#ST_8_?oSq&+8P4TuW9BT`8O<~yUC#?~S25f-=#e>glmY^;4f^{Og6`!VR% z#jL{I{o=M!k=EbT=gNvvlW-8@G-XOKhwp=c?Yt0WOwGkr(q9wFq)Dm%)Il|E_wyw( z_4}DbpTWCv-EWT2`LUTAk3?Ag?ErIM+em@_)0|9jN9Q~#bG%Mjem(taO>G@Zk}o-5 z4ItZWimbdiT@(&F@IUE(f17_E5E1XV9yMYKTUe~DbA^Ya?uC1o&4>$6ej5J+(f;^K z1Ed%HUSIP~{qfyiPW?cJvf#^W8zrk}WP6dxtaYb_aKdGFqYk1tVNFfV#Ni2HK=l@A z8>#DAQCwPDscw2pK2|`p>;4=@@GhfTHX9-~pagY{5e7_laFXa4$O~J11(dQ$$7sa` zKpw{-x9TeP;K6)GTC6SW(CQq#mE3&XK^(xUiIHKH{|FI$RaZf4vVOdz_sI{`|4^2K zhezGk*0y>`7o>-dC0SeX@bL|iIP68lE(Qh$TBd5;f{1S}@YYx;+t}p01GYYisoid2 z)+wV0aKE6is7P=lBeJGFPItp z;AeObSAm~8^-v$tJSH4@Bk(82p+Y!S*?2tRx5X3WO((&eSwA*u`t#YqVCTOlP z=Jh?-JrjMY%%&!ZjI1mU?g+2FUdbTCq<8P$J+uzXj{L|MR>P+q1pO^)e)ppA;&T9HZK2|Q z9-nifFA*uXg^l4;n+9YYJUnVZGn~453+30_|JjFnJv<8Udqk2ELO)LVP*r5pW4l@S zycd;v0`OWYDJb+n&xZ1Jt>*!i+*DEr;FG@N+PL<18I z^v4Rixm#Vaf&k3(m$v?XJ5&{)eM!-)B`C$Dm%k(jQGaLCWB>Q!YI!=7+bY4+WhEu8 zfOh<$^?VM`l{#Ru=kvVIvW8aykE+4vVK<#U)jo&il-Qk}9qkkSJ=Mv9-!S3NV+Aj! zAr7=hRpO=Nj~^Y1i*!SJIBuVY0?S1PcRmD;=EH3P&w9&zYdC<(tnqS{by3*%Ixq#% z8z*L}`h$4?Qwn#vWk}^$WF8?OUg?9Aqg+9lModUZCB#9UNxKOZXx{chc^1b z??8^D0t$Ijt)r-@`0Vp=yAVuOT3((fv(L>Y3un2!<;Qk!$6+|@xJ&?|k^e?@%T{;vjEOHywyK+e}aOJ;$EA}Ff>&~5qmiE@x z<)Yg8g#{9aD2D^hZz}(}2`~3R<5B(Y69ROuz)QPCagz=aSj>pWAK64f+Jqw`FYmyl zl=q|&gU{K((RmjT?2{Jp@(uMSeEbML)Tv_;POJ5o3c}aP1_m4IVfZN~WBvHmRfd~5 zIFtv|UUkFVfJe3Qeq2n6)?MVfb?q8iD~d$YUy4c7GIw2<%Ic_19XP))qwwi0R*>=rsUzUI zoW5UXG0J}MJ@=$?x~{Zzh%OugSx_803yMwYotR)Us@ZV4^?&TMFW}{C(j$>QehGi8 znLF{3TI@X4`z;D^*6Qg;s;Uui4)5DV^MHkseWy$K;#AJXl{LU}ywrg&PhJ4nW#Ac6 zFskR;LxYJqB=(pB0o8pwn8U2ScmYI!rcMSs9DfkUb31{h#-S|LYx)51o(w{f^fsy z+%)Mb9CUo_O3ZEX@wD0N)Ze^22+R&>FX|Rz1Q+MN78WhGNc<+!hNokZ#l%w!42Q`rm_ulXQ$Xx>ehW4|~%cZ#3 zWX&R@x97_rC4$MAkNtsuo)gm1<-n^mGt5o4+dG9$D@CNUNDR;SIME!DS{I|=L3zBU z>6WFicfPFCI=FNF50QP4S-^^1Wg%jvm6N)MNYq}}LFL_>LPGqvZr)4>J`a96 zm1NbQydX<~gC~zj6LF)Ex9SV3Mn~-D=M#o~EzX*r7p;?1+dr$Y z32t#bsZsqg%#3FBFtS-#9h(u$(kHQ6er zhDn^9$Hv{5yE^|+?3@Amx+LL}iXX<}$3AZ(q3ZL@nc79e+rp2VWJUH?-&Z7f%#d>T{=wH4#+=nG zhK!%Z2R}E2$Oagvt3pVee{=v)D(+bz*Q_ZigtT~hStouK_m@_a$QE#3zZaIv-OkHySh|Qi) zLup!8s_>6A13TnX5BeLh@9T@p{Q2>*LVSG3k)fC0Sl$=Gk2gWPf{}>GGz;~}>?gx* z(7PsqzQ-ZQWW-Fh9_;6GelJk_FTYOYhb#c(wRh1I_TS&b@_yf$} z)}45SKR>>DM?rZLgZfp5Cf;O8^4=UDXm_b?`Ea1sIOvJb zr#f`s__;IdU{%pVHYQiptN&il7$iO$7v`2d_7U&@2oyyRO9L@wy>iJvpE8WIe^mXi+#+4}o8 zH$p8>7(2_F%#Eazx3yF@-0I#{hw-_XjanVq>nAkBrlyuC0_CFU6{iY$f1oSB?EzBq zm0%O(`TSm!OYu6Ei%&@r*Lw2g+w4q*AHaB1MQ-+R+$HGl`miY60zuIoyPH);Amic? z?w-WGxDO%7geIOJFR+;QM(d{AAHV4G_S4+|nxq6>A4Gu$bz{AWeX6L`OTll;kMf`? zWAxUhbnKW-Raf=EY8K`zfg;K$sm3%d6Q-s*?MvbKX7rh3egtUfFIwK*L1L?XMS1ma zpBPcj+nNEOuu(sFq)-n?~-iSLc*gZlS~>ao09$oJR-bMuZ%6*?j5A-i&IoSu8F zdXgu(IB55tvD+yXDmprAeRzBe+xS-W1+bk=@N&%;oh0}etzCJc=nEL(9LBs?Z#Oh_ zRlX;S)YDG9inq|Gy5P~lUg@oqD@`jX^Hu%$xm{?e$H0{N8@wvURL>NX9~ZoIh0Yp*v4_8g;3MviQDCrg=w*`A#Tak!a0E9jfUC!U&BO%e%& z^Z#C)h>yLAi4eH;I0=93vrjDn+f^cur>w9$Hys1Qe?=X}xF$%IsK1q1oGDs6 zqHSTn3JR#I)?zgyb^4@etsP?S_46{$%~_8fOufOta-6(4gB^wGYOxY_k=|8qrhZdf zHYGC`z}$6`*2K?4k*7rJ=T%ap^5wy8+nru;#<%d;|90{zC_vvA(%<3;fX-=6rT!TL z=goEjeWNDM654M)28$9C{^N6?#_ulnGt46k<g$VEPZ+yJl&;4WsnI`;^audx6gwT-wd$3GUO=LT+^(hJlpzpchko9Rsh@6xl? zFu}Xj$TM2-;EU`E+{2o~X+| z{_YB*~b1kRkfR6BQF#%WKDHT|vaP9!0YMXeY96jaH)%; z6aX)}i9z}F_o4jU0KJ>=o`YAu(vg=xSPB9HG-aZA`G0@!(=iw&A>k!u_cOd;V%WME zt-?CYeCO^ncd>{0O5_0=!UOBR*Q#oh_zw}V6~Df#%neAlevzYx!q~l-xwgVmnfQH- zZY2>5{l%Isce-EN~1W6 zpVhwyI|Bs=TYY+?e(o|Bj7KB_fw;*39K#hv7WfXO`1$@kqMj|#8ffBdxAEqGc5D!w zSo+i(oXd@LE(XMY!DKpQf3X){?nW6t=*=q?lWe~9TGGjZIK$>1G5&J^s1yoyV38}s z;X{`@YXe4r6It;X*c1J|tMK3D!MpwN8#}}0GY5aWT{^z|#c)_!vBKI%lr+yqrjq~`M-RghWSPo(xi~}NC*Go$|EnM%QKAbz#DmcGa#>p>2wYdi)_wma--IiSwv@L# zqqZsMZ$th+8x9_A0=B#w`{#cB@uvTLRSyNbTRsuebLU^{^VdI7csIEH`IrCwN*m0~ z@@v0=cKaWW(EsQ)SP05rpZTBPfoK1JypZ}DWF=+gl=AX&IV?pbB}#gFdIvM#wtvK7 z15V6Y(;Pf?DK_BXS!me2&fQIW6JLWdXU%gfCD->-1_j?Qnr>mmhcgD({lh?Vne5iPAxI<8X8b1Fjc zI%_Z#>LGJ?GT>~OU0h5H4tV#@;ADUO`|2tqL;kbWtt}gma?dl@)|Qr#XN`VQkxY4_ zqN2ynVERwtv&L)0eD>+~OFg2C;t~?l;df<|mDA)PJ5VeY4}1;9yp?kXadGk1t=UGy zqaA2iNJzXdDRlM4`~TX?nNeU11l-(R_oAEUyRvH{2wjcVnKj}?Bs4QnEteN^)g5hkl8ZR zOh0~XwiyT})HJ0^mGG905$a!@!_j?;7=EYH3Y}rxl8OVkqykXf!SdblKg+ec3zpk? zEpX%Vh5!Q3g{@KLn3EoN{FuQTOeT69eRr?}9l!pOlvM8#!;C_lR7sg(I|1ls99Z-) z`2lYKu_g6j(5GJc)W;sGUmG3Yg@`4%7xFlY{ab2GU!T(QSV@+wj-}kd-6<(4DQ;Ct zO3FPKkb?D8l@S^=24kNhta491R(HvY|JzSYF#~7p)wa`K!vAG&6=;3Z)9IE6GQwp^ z9VR6oSf)=Vilaw!cjA^Dyp~>GUN%yzsZLEvS#~@8VpanptzfqUCAt{^e( z*PeK{U*|L*dVH`B5`eI==DFtJ)%}kB)shz^zYp`$_}Q2OlguJ0VEfTJhQql)^hc?&A&mV0Fuj26E7rR zM}sMs`h7`~SZ{%K08Je4wDvQ=j4S-MDB^Yqb2!L)O6FFsFu>CuQBP-8EpO)T*S-l1 z{D66zPo-S$+OIvje5N=2GTd6*hA#iK-SzEAr)S+~yItvk|>HULvk+i}#8-Fiyk_J?xV&=Utqpk-z;o&N>$yuBlV&$|`ovvBX1=<*{0Bv=Rxc?<)PwYsw&etb(?8;d8(c0AoiI1m{iGdeTO)vVO zkmUp59Qt<5d4jJqPFOeYJy2b~=>Ot!R}jEVFYj5JtDX8k1>O4q_2I*ZD#!UC#S)=| zj)s=8rzOi0c#Bs_tHg|E+I=_3z{m)0$m~n<^VwuzaME;;=ZC(fjScZUJ6?vSf~l=3 z##+Ue<3mbv%<3@E8YA5gs+}jwUqIY3|G6ZqCF8#jZ&ojkx+wk9j4M8_cnU>K=OB|T zBP!~{q*Fa&)jsWU5EDoys1@sZY^o@Foon^^mse<&YhaA7VMY=pxDD7|0AI_fA`r_U z|N9I9IS?h2@gxh}{B`<0&WH@&3EaD6;9{AS>-fage)j^51B;xP(5{#dlX=)V!=~IF zD+mRt>ks$zn?7p(gBYSZN5P#VQX8_%z#F)iHmTlPEYg-MPy3T0VTF-=j%#!)aLD?X z3c}6{Of;oWQq~kCb#BT+CO29O=0~Q)pYwD zV_I8L7FopizUOI^IqAudrsuXJuv+}|%|APmlk5xlfE!s#B8Y?ro(pRhoajrDfo5jq zhFu)RU2K;d&-wg59&2npEDUR6(^%Z!zH|H#;%l1MVV~Sm+gyddQ}xc~d>wAyuM$l$ zOxYQ%6%TtpU`>WYb6&f6u^glOfp+?~7K^D1J$rhm!ZP+`TASNPLV4r3u(Fj5yu~z6Va+JDyIw>iC@fpcyH$c=$r6d@X03Y#+$LGoz|^A6VJ=~xJ~0pz6Zd7RGNRqM;gG%z=EAjs>HzxD z(b3Ah%x(tg;^L~YLNic~GHs9|UJ3bgI5QH6_!r2l5;196e;wC-<(UXB4w`#sA|+*q z?c)6@>h`+Pw&U_vLk;K=yyffS+{2EsQ!KitJ5gOSUA#}{t~4=FEhQk5GrUF-ZyDJb zUezZjCnp}*2mCZMIJ}S-8t-ETnO=1AEt#M0Jce6EUfcOcIb>GHd&@iD16Z|IET(Ip zqOhtofq~7;M=N?@hGL=FAVUm~Ne{*HR83VUtTGm!3Ipllc~A)x@%{UA!K((~3dZE( zH}1L>#cla1H|zXKIUv{HEBK^|gN=O$luCfXo7yfQS$^9rPWsQ=1<~rAa1}JIqB#Ag zQ7;w|V=)FTonuVzi;2AU_eDh6$l9O-=c#PW{gr>_8>fahiM0&SGW|ZLISHcMlKo&U92PELPpGw(zz) znXTtv-(V-cWP%<{<>Tdk69sutspuHnUt9pypyb5STpJ9s=F1O_jm?b=rSyIl`SvGF z141rCka21=^!I!JQ($xub1Of;g@xT2k_n)DYS)TaqVn$8j|I)=7-uBrv?zt%P4pF_ zKJLc1I+hROZbG4F^mQ6-YECu`{8F_eCsF4GWfkRPD2D=yd%v%}!9(*uZdiG-cTpsV;`BAo^P|O-`1pDp z=XA73sxkrg8xxvfzAW97GONMq4i8W(W8Oz?cr#sXW@}WeGB7SUuK2yllY~=Eed`iZjlKjkzBE~jsg339YjlS?x)Q^ZxCm@VVs z*N+q#2U|>(D-LLFQ6sHT#_!j$8B22Bu(~@$>NuP-`Dp;g0jX3vP(cXe;BDo~ctFgG zr-1PGHoxN%t-2SLprEEO6#|Alxn=AxlwSZ;-TI{k(RE*z40uOhS1J4aR_k2KQZ5T} zaX7i@No&>}^ohEpxCP7>O$h)FlMe91Eixx<8gJ~hPz5gul&D-sz#t`)J7-idVLIB| zUl_#~a1Xpuows~XbU})8ue&;7klZF&GaG;G8-py>v8dX@&JWc z1`8cgTs!GjrlFvs&~&Kdu<3ZT2!xIbN!;}F9*8uCG=R@`&S0vpJtmm3CsPko_20jYyaXz0?{nV=7@K45OX;h^WyofwwrSIK)NXS@;d1N37mvmVfZ~~%fk_K>; zf&@<$XvY0A3Y2Xckqs@WGB+E<4B#jlDS64{ zT*Q7l3OdVt$-?j^Aq-Z;<5*YzYX}lB z=bj=aAS~8R#!jIE&msP;gKo7sp7U5H=wG2?jtnLjw&L9%xVlOa1S@h|+1=6p<)wJj zqJb+vTq4}~GC-}DMZWd4E4h~J03c3~R1KZ44;p-Y5r?8(pP=BHjcF@NCAhoUM9t$b z5|jELgl;gq4HjpzM8-OK`YsI3TAHawewn({lc7wDhKd@Jm`GW0ZZjPbcMh#G?j2E9}A_Kwew zeYB9-RJOz>l~b1TiO?`ndz()m)N6^X%l2levyOsh2#t%gB9^)AIZ!*Lx!*&_#8f=7 z&=N{jXxe|*BbWPPW4f-c(-R*KC%A*F;ka_lDamPb3Q{?ETSGX>Eb>2B3KH9darP4Z z<#Ea3nyhJ}49U1^c=gN|qp%F;JM?_5WQD$au>wUT-*nGY^0|3&^GJ4r2C}*y{cZJ% zU)%kUrFCkeZ@w2km*GeLb_ALGbnDh*nS4BD4~jbqQT6pcR~@cUQBjFuk_ph6srgZ5 zfC2XG04>>u!Ezig0zi#dKxJM{vE#ZHF}uMVXdfu&Hk@w>h3taZtNn$JPAs(iE(*BG zO7KX*wF&)r^|yc{3=@KoWSE@F^)i#--H$9SBa@Py-LZU-v3702_U=lh16xAj&i)P| zs}9p<%|R?E_Zq9xHjE|aghNbl2tX4OFh$do;WA7jm>-w7e(;jz4etf>CNnL!ib>;i zru)$-@v_S@WT!xO{K7Mqt^zq7@S;bU zhI?(C2s2h~@0#(3fL#+z+?qUA0VS=N~`O*q`Z3l zT1rmteFp#>Qe~r!l-)t0JG|oltyx;;6+hV&Gr8|`bIk3Ms>%Zkg<4u>b4_-e>%iaz zT>k`Oh*4srnQzs(Mz#QBSm_6Y(E9cF zhVup-GNNa=BO{PvDLF&h<-(+@r;L`A&n;JCI{2RPTH_3K*k)ty$BgQaUL^V#966cH z9M!*(6_pdvq7V?!M!B8o_K2(T87SPW9NAwV7e8YzmSZr%#>ZD(&%VCO*To0-)g1cQ z$IBuKb=?cTSY{hfMZ`Tzc*((#v8ae(^{2eV+YO{~Z1T1f%P!5|eerrtgur9%u7~UW z&sYSN&Phub`Y5k2zC>q9j|hcX1Suv-3}&*t#)ccB{Z}=H$!)``?d2Xdn-h1xtp}zg zNjTh23;5hA9|=VZFg)MzYOhQZUJ~Gn7PIWLjNzt@(amf-o*FW|F9A$V=MY;sZ2AF5 zH@=S7`H^uujsl1wbJMQ`Ni%4i0sN-zWV4Rd>tuY|KK7F$4yl{aQe<45b%xuZs`}fp zJm0?zj1C;((3umrzJ#=F-gy^+TwMk5ve+MXb}6hzMNXTz?XQiFiF-IZ02Li0((G=b zBR^C??zCQ%c=)j84K|g3FfQ{U4Zb``u%akS$%nuwFx{9zIrZ^9`Iw!| z{dffqy0F6c0iQHq$V>~5bd=J0^%qyGNOkct%LYZ^dlA{>eLOLsPQ4xS+D)jGUWj`C zxnhw(M=~T>=|F+LRO<8I`(<;T@Ay8_$nb*Imi%XpdtR(7*0X!d{fx}x8iWI0-3!zE z?W}bZeK$((9h3~~nDeTm!1065wQzuiOM&5eEW5xf9Qgo6`VErQ3&N4!=KH-emxk*z z!%X%Szm?)6%h46GdhM=xP+^H{#~Tjr`EeCx^5+@ktI0xNmB^Jc_IBD?WvU$4vsuS2 zR-SsAhMt`qw1fND{s`nB)T)+qWE(%1XM1ZI*HxxG7do29O*_zK*0dAb9G|ZeYp1T~ zQBVnKa3v4ixvg;WyxIYV0xhCp=agpUig@yYidjs5{-xTPp?i0>b9XUVCl?~X6<0p1%)%waTwr_2GaUc$(y zj!~Ule+8ZsV!*F<3&gFt)XMq{#4ZfIfz&xOUR)4wNHH5LgxWZlA}W%Mg4O-wUcYIFE1k{1iSC-Fj6cJ-WBY z8ePeEWdhROJiv-pUe6~Wnh{7G876=9m`(8Q)V~aee*)l=*V&w=sQe@RA6)VAyLsP{ z{i)EoZMb{YJ@HD+Pju#`F_5oGi;zsyHz#&jNGr| z$1~}z%PNjva3@G|bFfY5e_o;i`QZ=|QPI#2PwNt}LAq1QXTgrtTYTjpY0I;%L=rmB-rCB?{OxtccR~UhYp-I7skk~hvZ@1V;`8xycE>dh zsYj1ONUh2fQahC~eXil&cV`-O?mnkpExR4orvw{(W0#>{MOR_>UEFrLC)bD|@0WWG z4$C>lJ8nCt*tljR!$l8BRK2JV@5Q;ITHZ9PzoQ4UzatCe%PEtLj5zXWn4@jp{9Z(qex^PiO)B;N{47F)GfU|}i@IL)7pk5$AYYqFqB!*~_RQwbc}ij$2hIQ)eV z^0mw3WqC+QNGcg{4kF_FHu2bbbm7E#9?XoMr{7TTT1QTrU(ht~=Ro=;xk)z{$zg81 z#hRb9r(>zVeWS76eZ`mz+~B@6`8bC0MM}gQ%v+6qNG^vJ$YIWFf!pVk3{oh=Em3p) z)U5pC*QFchn`QlJ)-B$j8i`bchB{9BgK~1j5*!8HcM2CxhmPyd&`hUfJOw{fq4|f2 zpYc=jF(j&4D*lSLZn6Po{5idI5Y@m4+RBmVNkdQT6>*hcD6iOFP9hA+zbvGG`J8>H zPX`B^%tCnxP-}q%@f_(E4GuA})Rjhwx46b=^H9Q8-zKKSj-u8=OPB?HM|-wSR`nW3 zQ+A+lU$v|kZ%i0-U0wN;*X#xq3hD@4C(nBm#lvD^nBl1zOoQ~!`4iZxx+z5?i2CZk z)d^42(PCzYzOqD5PA;!c(0k-igEKPl=}%kq#IP?7|z3`^X}rwoc&S@#x}x)3j5a^!UuLAe}-_-dnbMJtG8O z$~uBQQaqQR9`rsOGq=QUkXt4~F+e08O3{&wNC>|v3YtZXT~>3-lJi4ufP|(FsoYF+ z5L#Gh1S^UYOK4c)skHUy2*-zVw?`?3iJ^mKUQ(#{pUi;%!5x6GNxQpOSA(>4SY)L7 zGP5xEemPx7H=9wThpH(t>|Ac7wC8ZBGOzkPPu2F+z%|9N!dpZi^>n>PRY_Zgj^E4u zNq0Hjw0~b1<&i^wv#Ufe3i^m{Ci&Y^Vs_`4%5wS!XxtheS1!p79BX}g;)zcjp{-RI|rRZ_r za#128A#2TE*tz2iQJ?j)SDk(;Z2BM*wU8l}XC@Uf3@QJxnO3p6^|CMrJRX&eT_c~U?m z9h&;WO;z_&9%F85vdBJ}V9Xj`4@c9#rltsyLFKIWK0djaSe2os<&k%Ezev3ouv9Kf zdwrJ!TEE{-!@3$6>J{Xkujf1AvC9_C{`q&#OBFc2>C*n@z%F@5hC>f~eYa1;xw&b{QQyb>W%g`<3YMlI*SLg}p?(Ssd z6xw6v-oKfC?5hjgXJlx>hIz8m(Ph|6kylx3Wp(TvlvS!EiLJP8{J-|TJ09!rjXP3S z6tamzHihg}ME1;{Ss{CGQYa+J$S&k2p=7VSVcu5AUKLr{dq3x6$M^Tw^ZfI?Uizn- z`*wfMxz2UYwcgkJta0)4m((r^13xF(pz0atXUw~w*9nTcs1mQzv(i>{Bnm2fa)3LW z9sBPr;=s^JjAB``g=RjLiMxK>5RP|1WmCjm=%3i|Z}{<{tnxb8JJ}BH3I?xWhCC%s zw;vBYcIcNSTb6heWVG?eYlt>1ll0!YMV4zL)p*ffGnKa!RD7PC86E|lHU!Az_mb>K z-zty?Tg|^!QCA9ANE0chgUUWo@96A&iyQ(_BG4vyEWUzyKX$;t#*Tpe9o|3#l-Mgx z7D`Y5@~K=Y^Q>HLt(>L4o6>ZZnWjWt6G}aQV7)n<{?r!BM*|a-NWNN<=b~1!H}X@p zYuN?&>WSRBlbAV7p;uh~ytgt)ddvGlskoS>=kpKl8u1+FxEksTvpDy!A>m7_q!moQ=vJT{sr<^AnXjfnSGIb=I0SR5`^&eI&6c;X9qWtV4S~H66=7X!2zLr2M@D@hE z(0T)#rXzkVikgJuE^^mo7Insrv|-*54>&Oa@wNOmtkzk46tn1T|Kv!#9>at zuq0dbsmxM_53K|3TSdi>`<0JnQnun@r)=(Im(LTi)u0)6px-098HimfCh-oNP_ipc zm->quhRm7YchCx+dar7_Z;bd<+VaK)dvR$go95q&`F5uSC%~MdTgwldTj*U*GlrIM zqR$y#rw67e9qU2Ce;Sz+G=5CP5c`;fE0gcX-ttOFpu_9Or)xvowX_CwCQWcf_WGK* zL}PW%Wd$keUY?nI#9nu|BqN1Bq``rqq@JFTE3Zaav2bxlvWC{pC%y3Gy*Y)~l-F__ z_aX`XdkwMbjH;}bwE_-BLV$zBN9privsh_K*i4>V`YZQh?b4Q7ZIIQ*+k`$V6b8>5 zi+I)H1KD&`)jhhmzGzl=4xYv(`K}nv5%|KZantt$N@Jms8v}>*S>#|!kTIeLqqSk+>#H85ykBE)XO!Z?bim*xTt{T3q9uh2NhMRLj=+vHa!xF862g-Iv#N zg>lydzFVAf zjaB3YF4rB|N(qoVZI_bDopgS^yn)6b8d^h zX&=AhrGoLLW<&>dp*erQhSkW-faf#x`Keyn*7N8{P8X+VX1;%Zf>i0IR{sr+!&pm= zcA>9qxJ@eAZCItPbI-B?tQ@W$-W17oh3!5CI3CJdxdawMZTnDaTH1ERZ?*or@_AUAwdr+NKSR1{X>x=GoAI(>i61gR}S7_pjR(dmXO=& z&w(W9io0zSD1U*=k)3*Ln{m!t9Ah2y-F}1+oVB&-k;6&|zck@*QP&OZ-OSrELP02C z7K!V&K2w#Vnx(^L-o~UY$J{+QHN|Q--0(iqlcyO}HN;zCdu_-=XOP`7si}s%&yA4N z*2g>!FR$B8H2{1%BM3Eff4$jmfbz~q?{OV}-~3jFR6<7P{q%^LfM+Zb!MM^SF&zIqyB0%{ryjx9) zcm)Ahp-KjuX*0Ey=ZY`D3vM@w_ZB&XZEmcMBX&`&JoY2cVVmiCVj@?K^*E9_myQ5h zfhtF%T|1q0Rr2L_-rt(hXE@$X7M0bq;OAKhDXB036{#Nh?0cJe&G0JzKmp)MSXcmv z6J<$BNkfoCa3y$%p#r0P)b-a5KrD)C!Lt_%3%|8wY8Tsk0t`i`VVv$=&6SlE*P3)* zE)~RCVDxc=ejUmR?0Dt__CSGTY5$zveg}&_(U=wTL~)6T=ol`1&roL{?aWDq(If%z zv3^VV)>`>i3+erG0A8`3tLH-GS#-~jgO>W&h{yi^8Y>Dm=k0yUgBhgJ%G;by ziQGsx*5|Ol;{CnpSI=IB{s7F94yu_7aTnUR6}v}Lc*5iL;@gql;(QLPzMf_$d~bOv z5%p98W{nY=1mz}!&Gi)!L(@ZeaEDOI5WsTAkYz!L z_VO|c3hIEfkP>3Jalk>?n3|>ysgc7{(v$&$Fv|0Nh;CH~MSFdeMZ0*+r~hE-D0l~e zh)(1@tJ@ct=&1@bpZ<}l%}1`LR_dCYQa7C7#R5SmhqTB`0DkBr04TrWwt2&(nI}Ev zGy_0qPrI_arT<6=K6-@0E>-S0)+$jReG@e%P=z)vEsYJJ${_ZMyO|pzIm|g0Ybn+H zweEwJDuJ@UPC@K)5P;q}9A3KA_b$N+z%yq7m>&U{hv>&TTnQ=wL(&l7^JpWrD+f8* z=3H}Cm%&i+WMHWvnv%fCT2)iP(=$7g6f!2j-s%Fd+CKtej_HyN*WPr+TsIKATLE#l zwe}G*oKo`4dd9$Li?g3}-#_-I<-s~$;?3qK0LF2k9+{yDDo+6f)ej_pU;%5kIr;?_ zql^{S1nOdWl)zbNulE|%Re84ne)U4`%a_rG`VDRJ3q?*-ECAyl21;7D0l3VeQ;M}z zxtvA2NVz;+_m3d%=H_Muzr*=(fKOm{S;SV!)S@@Tv&hkQGparUiH1_ZB@zScv`l^T zt^C{lGv4Bu%d4x<>5zFE+e}3S>`H7F7%>sVa|h~YqegMYAT4g97e!=NNQV!rMj*lh z0?^{f2?=R|ef*I_rR5@HEzkFoRn#1BV0v$p=?{HXF5OLHJ)~VUaVpKnjJC z;T1wD?e_|}xQ&ol$g{+A=%CAe|BM`%07#?hMW<7ZP`jXWwy?0U_b03VJ~sASXE>Fo zZ_zj~gJAhf%R4<^;*x8utINv)(JA_8S?ksTQ@#jA^k-CuH(gvNdKqdTZgE=mWte!* zkGIRAia|C95y{%VQ1^=B@#Dv{hmgRlB;^MhwExNqy3uuF>Qp?%w$;-2DV{8nisrIn z!6abH?)KC0GXua7*DS2N0}xu5)1s>yfFx3Y9gY}!(>kjF@Skihvx69)@rtp+_S-pj zjx)$)Ir{)g8<)?Na{=3XzX3-+hZ*V>5D&SO>*fo{COQX0$oW)&1GS*21R-SO&%D8y z|J$h~xIQfc3Lrr;E{Ccf2csqcqpnYC%-KfuwyNumG`)V~Y4*bJ9PyR0RQIut4@oeJ z{b*y)c7h?mT|n;wuhnOqJs%DqjFx_*2s;#J~a2UI3Z2T5*<+P+a2=mpUzvmaPv|(2ih1(niS3^{Vnku7FX)7+ z`JN=s90{S2 z22iUDlh+I--!#rTru!h0Rw9I)ep;6MI5*T^9uly33#ZV*pIcQ-Ev{40$tz0 zy4WXvZC~mUGKJhY50}ZF!lQS@ZtJzonf2aJ{r0Lc78634**To8&H@1ZBFLvt8v#6X zgj9N5`Q}2_N82Gu2&YPua0th-tCiNQ;H;j!p)B&JMVpw7ORBC-}j0uLn&h^Hb=W}ApZkGa_Q}N zc`xBc33-))j?QXuU{^#3$f&gLy5zAxu;L_k?w^jQvg~xm-%@zonepEr{md-DU z`WNyN^-Tc*0ZkTZb1z?BT)1M~bTgrKCbE+NDTw!$BKZ;H=_3YCvG3KV;S;-+`@25i zN#mK?uA?cO+JAxLRll;(uA6ll7Xqxn)JYgT7CTKq51gjH?zxz!l}`#4oTR0tSER5L z-U)C)&Zunx7Q=q?)Sj~?{2L@a@2_7^+-(LdNcPqskfgC&6g7%dW@l)v>;yM0&4SZ? zT!7hgWr%PEfHGAln&r)=FvCF@%V=KKwqjhqvA%Am9f`5`rF&;3}Q&`6NXF|MD7s_YMD$8Bxb zmu<9r9~84#DC{?P>~Aa*Ie-HD-DzjCqr+MniB|n(MPAU&FHt_IxhsnXAp$C|`=JUs zNNLri-+ebP)^BE9;n1#aLT}RW>CT-y*@J1m0Q>J@d6xVEO9Y=f=nz^T*WG#nda-O( zAIR0`@j8qdy7{mlI=gqyb89Ggw7j8Zzq?=j@S=b#2i#$;vaL*QO;0R}LyCL=(aNDp}1c&A@4 zHe8GJWE+3!6~|`u6e81feUd)gp3zue%BQTmU%faGbs2OfAJoxh@zF3bTi6*OFuU2} zSJ0y{?@1)Ixt!FOSiF7-FTdZj7(~(|g5kP?l4lq|yLp<4Z3zelU0>1LsrW~izHSEK zeGo|*3+TMa9I%F2Pcgk&%%fxF&I~sjy#f%?J*q67SMdq6Lt@Fpy!;1qlc$ zX3e~ppp_Fqn{V6zEnU#9DMtNJUzNfV8st}PHx*X;F?7EcL5)lGObh;c*ZP|@ux1}! z=8Q`@!V6I%T!R0(OKe+fj-GO2ICMhepL<%q6tSBbKkgb>10069Fh(1A?caEW)T$$Tk9tDbac-FMY1ZL z=U_FC0O@bwv4;YyN6*C6n!^IpxrvBApuQ2jW(5Ax=(Zr5P@m=A-w^w*#?nQ-vwm*R zNK1G6N#H3ct^oD_Q1l!x_=TV1fBSZpbim=jLJej)=20E&vQaQ)evd~kf(K7O`l?4Bcy^@NB-;C( zJjaF%ZvhUX^D5e$`~RMJ!D}#aE;5dyf63$yZ#VB$sA4sb^JnGQ6ZR)=EdrfV-1qHw zt~ozqWp;j)gWUX4s=B$uP?Y^SZ!g7wAGFriO(SgoTYm9SM{$dI)bM{qT)P8=V}Xem z{7n3AbW~~wGvL<-@=Fc5*7z^6(mxX?1(Y4u|IZc2+Rr#^t-Ui6- zia(=Bb9V+h&5eW)r(*gDE3EP7bFyZz(wgt8+^5KhrmOa9N?`KQ2Eo3NmaNMXfVu4aaSlu<#sSH{=1M; zJY#Cy>9!VT1_J)?G?_9Gp6pPH&5q=I#KGUKfy=CqCQ9I>pr+#dm2NI*XA8CpgZW`S zr#ntLf^`*8j(mm{?nZ@~5c5KAm4DyS%`#vCWL{$N%|&PD(F|Zw70}Oh9^2wgbl`&| zkKh-S>GSC3&ImXM6C^h%{xotoB?JYLauS?+~Lg)%`P9Z zP!V6nQgaz3N=m1Z*c;;w=tw$-sUN>K_%6HAEq0DfEbccgYt( zi&By&ndx?U;opr5c7WIhcQeNB#)TGt!v8tyQI`Rp1Z{{`>)C5NgW`rxa~nRhqcZmv z-hlS3my*UVx)j=q1w+~2O?TAfV5IyiKwqn{na}T(#(=OuQ(+2d$#e{-+qvKQ9~;9B z9U5VJrn|gLP9W&|X-OsKb#!&6AAqUH3zYGb@66~1fjm;s$B!RLB2y`Mesfr=|74Pn zF3awSq03bLL>?#~%lseuya}WOZ&@sk>A=ApyhVUElHE%>c5ELS4>v^H!|q_ZmuonX z*1;<>Trl$sq~Qm@Ira+v3Op({O{)9QSMO-`f!!K-4phm%1Gbkv`mc{RKzb>y-Sxj+ zl~YLmKrgtziP0Qg-a~`3ehVIDGSksx;id-qbeWUk=&`x~0pKCC16ATyip)E@ zei^Jj_6LQ1)W@Os_Vhj$5Qu(#RrKjUlx$x}*buxwAox%V_A&XKsLqM%98(IQ zt|zMVUsBoq-N~u*e}C$DnQ+SPo$Lc$$Pl*;8NahUh#%$~U$L7Qf_|L{yYQ_p^DL+^ zuf2A2WY-iPS{LV7$QL11ytGq<@QKERfC>{AUX$0H&Eu`03DmKd0xUpCP28a@Y17GrgZl85_Yg zvFqoaMfUXcoc){A*fn7q!)YvPtk? zYa&bqOz?eC_w74+fw5pj>v8@a-26^83quqj5ZfgZ6!DCMIc+!e@qV zCy6i!7Xp`#_>EvJ9kCYosev^KMrpLzu{hTFfNw$f6_4Fp87ELl90Hevg~?o^MdL{J zE-x>Ku5AeKvmJo@Ks@lOu5p-$|wt(8UxOaHSMV5~l~IoF~*6m&m++5_3_ ze6pYn=-h5Ys3qk91rfu_85+wbrJ?|D51-$(Ek-TRL}$)hFup2GS;Pzt1k{8ubs|98 zzdE^StPAq#wQ@1oBjaaq>2vy4#mZLnvo2mF;8F}Z%3LVyfwugTI8Bh`4Hg(UpmtPj z$ua8tg7xvi4_SIT-lfz}w+*AT7S{S~TW$3xLlNCc?Ki5@pCTx?n?OUu_BRs>f)+$tpf zJLpvZvUuD|d?;*V^MpyeRJ_l9*p4Sgn>voKLaKe42;6$v?QGqTjb9tKAF{MU&CN0| z=^*jG#Oo+!mAK?)6KZHecxUz1=@;RS%3f*&#J#t_P#L5+*yF8?v*RVpNaxtz;JFRI zf%5dJtezDR$)SV`B0Yv@gXy#oS8V*EEpY;`N^~gk)*1&w72xV zI!LW*$?A2E^|B533rV_)={zo580`~#+viYdKT4$i6R`OgJQW5A`pWWPp~xiK<`fvE z_*Tr9c2?nNju1QwU7?kYieAGm4^>I|#PWCcuRM2^*gFQQUWWO+i2;R1USzXB70IZ5 zVGw)JWUd_z`$D$Nu*RneMgf)*iC1Yuc|lezoR zzT}3sk^4)^-%+Axrhn1FsWAKVZ}GQ;PSG}Zvf=>v)`ne*`@)25O`}A(!CF~l4n1me z!8P57B2+1luP4#vA+DjHJNLqbqC~?_yQA~As|?o#Zr11FVXR*6&hfDv4~bA6-A&!; z@A=xy^!zm}_tqQjaQpP>$yTry0PgZ{z(?lrdG@0aGs=Obj8HTAXIHkj*A{-%+;_Q; zbCGx-=Th?-QCO8jdoo%oxw_bCDBpyMa$<$YYik(zdrP4|==YG`Tm`@U$zS53Xfi$; z-e}#yj1Lc#jm_?*P^V&By|_XZFw@(m%gFro3<`;q-uGsU%Amk2JooELU@YW)#XZZ{ zn8gX)E!KQQ9Tp0ndFPxVa4(f%?R6R%&a%&bzrG>)6f@|2i{Ldulm<=}F~%@~^7xoE zg)*{XG>!=G=$$6l3u}4q8a7vZy!hT48^c&-E)ra7U?0u6pt!`V+#EIQ&(C+mo66f^QvsmQE=~2X*ca5Z~&{J%+O4iMT#>8T>VDi>1}l z0vZxe<~oVf#0N)aKFtx6T^_iC9OFnt!4}(-T0W$y9oag|XCnLeg+OH)>q@1+2{nq= zZP0wDRB5a5_ziMpI1TBT5n7*pk&!@0JJqdgZa{NW0TsY)5Of( zYT@%MjhZ64{?Ce9&lP^VUK9l}?0dIfhBGULtE8oOd&QZ@Qx(gBFEX_qkiU{A2WDKJV)6p^X zv~sZ&_QJptC|{lDJ`4sCWR| zVS4Z76LW;8#$6Gcy9gf8*zl*e4HY-uh zM$P6KCcIy%OT1d&Ep`8nxBEt?*SE%yAGDD zeZ5s(+8qvLTem1)TZ^N9%2P`=M?J@&$0b2OLiGGIXlJ@wWH@vA{yniEvER7)QP(yC zM<_ObE4_JA69g(=qBiI^(HmsGvSFQje);l+OI2ZZaBs!z_-><`YZ-%#73faj<4bAX?Ys8pQ9a+E5d*G< z{P=}MFDu8nHtn2yI4@cGt!!|ggG-)K&@NC44`8985m}u=q~cNv>!}Z)z? zyWwXgm^AmBqS!Sr;a8{i7HgCo_kCn1&!Nzj5!%cc@?qT@PMe5?#<|9lRSyxDiF6z4LIZ1CtZfmdsw%zUi#a+;!E2&wf+Y`$9Q4f>s7q3-Mr;vcwL^7 zZ0xvIiA98L2WN8E$ihchreO`mDxbF{Co4&~U_X}F_c6Z;qt3WWe@ zQ8eG=#_DE&asTqF!CZ4-zx$K8p~&Da+pgO=6Mq?v5q}ouYAPD1W~VF(k^Nu5yF)bd zx146uE7%$1T?bEPNfmOB4E0x;{9Ub%wVm}_sW`7|P1lQ6bxV&kHv7|ZjMGq$;}Twu z%eYIuLpbwB(tkebqJOUAbuV6^^ccab!VKiP-N*i}jfL40m4e5lbUb-w&`L`XasFcQ1@4PyGB=V)hjY04 zd6qm@rU<6YXXLV60>m@b1WYD3S1Nozr#9qLl-oK^xNoo`El2wb-WhPCwr&>)X_(p= zm6?N!$kpdxGE(C;u3!H~W6~&|$?w!gUi!z)9$}2WEd!sg>cVjD*z)2@kkf`V!y8U$ zRqW-tbbiw_-o>))id>S7nLlJZn9FxAMSsXA{*8m6CAzqRdJl> z&cr*fb{5V=6#t1|yOcnM99s$ zjF~sqk5#buN1Xl`=8FBqD$sX#A=QzPelxGVw;R~m>&1l5n~x*^_<0o=L?ndHG$qNg z_KEBDKj{19=~%u-Znr{XQs4YR++&IBo)6Fil(Hmve56ji(0ZWeA1kXOk1h3a1nc-x zErPY7_6OqpdS;XXp-J{uEvptsWZ6>CRKZV-ol|9dbG`HSwkhy5>193m9ZDY?a)|pv z`EZ0+smWyNR*lQ%V}Z3sEurBc=DDQeJ|1z3+*M{fAu_t%7+y+=`Rp`-4fKimD7kC-t0KH2;K@h%ebYj1Cyd(l_^ z^KZc*NRW_{Y(CxkuWyEi_y`$UEWq^X;o%-0-hC95pvvzUhbD9QUCIj>XhfIa(*Lii zCE{GTMk3Dm&z~F`=gGuRR{S3coT&Pt-EnwJp6v0%(l|IzP7b&KKABHW_5U_WC+6&6 z?;Q3wPVD$$X&fBFCl1ViyPYSV+dqEG{vmwgz#QzIe`$qyNF6)WQ`i}%oeDxDw{T~UO1Suy$%0Ch~iOx= Date: Fri, 5 Nov 2021 13:58:09 -0600 Subject: [PATCH 10/17] update documentation --- doc/source/user_guide/figures/CICE_Cgrid.png | Bin 77699 -> 51536 bytes doc/source/user_guide/ug_implementation.rst | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/user_guide/figures/CICE_Cgrid.png b/doc/source/user_guide/figures/CICE_Cgrid.png index 659babe7ad33d68b6406da72658b36953b0a832c..db665ff7261d24e6992be012254cf19e57a8c605 100644 GIT binary patch literal 51536 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 Date: Fri, 5 Nov 2021 14:03:50 -0600 Subject: [PATCH 11/17] update documentation --- doc/source/user_guide/ug_implementation.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/source/user_guide/ug_implementation.rst b/doc/source/user_guide/ug_implementation.rst index 01daef5d5..ebc218e34 100644 --- a/doc/source/user_guide/ug_implementation.rst +++ b/doc/source/user_guide/ug_implementation.rst @@ -148,23 +148,23 @@ the primary prognostic grid variables name on the different grids. .. table:: Primary CICE Prognostic Grid Variable Names - +================+=======+=======+=======+=======+ + +----------------+-------+-------+-------+-------+ | variable | T | U | N | E | +================+=======+=======+=======+=======+ | longitude | TLON | ULON | NLON | ELON | - +================+=======+=======+=======+=======+ + +----------------+-------+-------+-------+-------+ | latitude | TLAT | ULAT | NLAT | ELAT | - +================+=======+=======+=======+=======+ + +----------------+-------+-------+-------+-------+ | dx | dxt | dxu | dxn | dxe | - +================+=======+=======+=======+=======+ + +----------------+-------+-------+-------+-------+ | dy | dyt | dyu | dyn | dye | - +================+=======+=======+=======+=======+ + +----------------+-------+-------+-------+-------+ | area | tarea | uarea | narea | earea | - +================+=======+=======+=======+=======+ + +----------------+-------+-------+-------+-------+ | mask (logical) | tmask | umask | nmask | emask | - +================+=======+=======+=======+=======+ + +----------------+-------+-------+-------+-------+ | mask (real) | hm | uvm | npm | epm | - +================+=======+=======+=======+=======+ + +----------------+-------+-------+-------+-------+ In CESM, the sea ice model may exchange coupling fluxes using a From dc72321f14d7335a6970a06846b2a4a0cb514ca6 Mon Sep 17 00:00:00 2001 From: apcraig Date: Fri, 5 Nov 2021 14:10:29 -0600 Subject: [PATCH 12/17] update documentation --- doc/source/user_guide/ug_implementation.rst | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/doc/source/user_guide/ug_implementation.rst b/doc/source/user_guide/ug_implementation.rst index ebc218e34..b3da2bd8e 100644 --- a/doc/source/user_guide/ug_implementation.rst +++ b/doc/source/user_guide/ug_implementation.rst @@ -375,15 +375,19 @@ testing. Masks ***** -A land mask hm (:math:`M_h`) is specified in the cell centers, with 0 -representing land and 1 representing ocean cells. A corresponding mask -uvm (:math:`M_u`) for velocity and other corner quantities is given by +A land mask hm (:math:`M_h`) is specified in the cell centers (on the +T-grid), with 0 +representing land and 1 representing ocean cells. Corresponding masks +for the U, N, and E grids are given by .. math:: M_u(i,j)=\min\{M_h(l),\,l=(i,j),\,(i+1,j),\,(i,j+1),\,(i+1,j+1)\}. + M_n(i,j)=\min\{M_h(l),\,l=(i,j),\,(i,j+1)\}. + M_e(i,j)=\min\{M_h(l),\,l=(i,j),\,(i+1,j)\}. -The logical masks ``tmask`` and ``umask`` (which correspond to the real masks -``hm`` and ``uvm``, respectively) are useful in conditional statements. +The logical masks ``tmask``, ``umask``, ``nmask``, and ``emask`` +(which correspond to the real masks ``hm``, ``uvm``, ``npm``, and ``epm`` +respectively) are useful in conditional statements. In addition to the land masks, two other masks are implemented in *dyn\_prep* in order to reduce the dynamics component’s work on a global From ce5461d087b823b245f2e02698c70b523d5b1c9a Mon Sep 17 00:00:00 2001 From: apcraig Date: Fri, 5 Nov 2021 14:12:36 -0600 Subject: [PATCH 13/17] update documentation --- doc/source/user_guide/ug_implementation.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/source/user_guide/ug_implementation.rst b/doc/source/user_guide/ug_implementation.rst index b3da2bd8e..2560fe030 100644 --- a/doc/source/user_guide/ug_implementation.rst +++ b/doc/source/user_guide/ug_implementation.rst @@ -382,7 +382,11 @@ for the U, N, and E grids are given by .. math:: M_u(i,j)=\min\{M_h(l),\,l=(i,j),\,(i+1,j),\,(i,j+1),\,(i+1,j+1)\}. + +.. math:: M_n(i,j)=\min\{M_h(l),\,l=(i,j),\,(i,j+1)\}. + +.. math:: M_e(i,j)=\min\{M_h(l),\,l=(i,j),\,(i+1,j)\}. The logical masks ``tmask``, ``umask``, ``nmask``, and ``emask`` From b58e3856c808b88fcb7efb87e4a3b8438b085859 Mon Sep 17 00:00:00 2001 From: apcraig Date: Fri, 5 Nov 2021 14:21:41 -0600 Subject: [PATCH 14/17] update documentation --- doc/source/user_guide/ug_implementation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/user_guide/ug_implementation.rst b/doc/source/user_guide/ug_implementation.rst index 2560fe030..5bccd33e1 100644 --- a/doc/source/user_guide/ug_implementation.rst +++ b/doc/source/user_guide/ug_implementation.rst @@ -142,7 +142,7 @@ The input grid file for the B-grid and CD-grid is identical. That file contains each cells' HTN, HTE, ULON, ULAT, and kmt value. From those variables, the longitude, latitude, grid lengths (dx and dy), areas, and masks can be derived for all grids. Table :ref:`tab-gridvars` lists -the primary prognostic grid variables name on the different grids. +the primary prognostic grid variable names on the different grids. .. _tab-gridvars: From 4cd4039ab1d7a25b6a5af991edf1b67eb011a5dc Mon Sep 17 00:00:00 2001 From: apcraig Date: Sun, 7 Nov 2021 22:27:18 -0700 Subject: [PATCH 15/17] update pio history_write for new grids shift to only support S and F X2Y transforms for clarity add uveln, vvele if grid_system=CD. proposed placeholder for extra velocity variables (but this could change) extend io to start to support different grids for history variables depending on grid_system --- cicecore/cicedynB/analysis/ice_history.F90 | 50 +++- .../cicedynB/analysis/ice_history_shared.F90 | 3 + cicecore/cicedynB/dynamics/ice_dyn_eap.F90 | 12 +- cicecore/cicedynB/dynamics/ice_dyn_evp.F90 | 12 +- cicecore/cicedynB/dynamics/ice_dyn_shared.F90 | 7 +- cicecore/cicedynB/dynamics/ice_dyn_vp.F90 | 12 +- cicecore/cicedynB/general/ice_forcing.F90 | 10 +- cicecore/cicedynB/general/ice_state.F90 | 4 + cicecore/cicedynB/infrastructure/ice_grid.F90 | 24 +- .../io/io_netcdf/ice_history_write.F90 | 4 +- .../io/io_pio2/ice_history_write.F90 | 277 +++++++++++------- .../drivers/mct/cesm1/ice_import_export.F90 | 8 +- .../drivers/nuopc/cmeps/ice_import_export.F90 | 8 +- cicecore/drivers/nuopc/dmi/cice_cap.info | 8 +- 14 files changed, 274 insertions(+), 165 deletions(-) diff --git a/cicecore/cicedynB/analysis/ice_history.F90 b/cicecore/cicedynB/analysis/ice_history.F90 index cf6b470d1..fea284495 100644 --- a/cicecore/cicedynB/analysis/ice_history.F90 +++ b/cicecore/cicedynB/analysis/ice_history.F90 @@ -94,6 +94,7 @@ subroutine init_hist (dt) integer (kind=int_kind), dimension(max_nstrm) :: & ntmp integer (kind=int_kind) :: nml_error ! namelist i/o error flag + character(len=25) :: l_ustr2d, l_vstr2d, l_ucstr, l_vcstr ! define location of u and v fields character(len=*), parameter :: subname = '(init_hist)' !----------------------------------------------------------------- @@ -107,6 +108,18 @@ subroutine init_hist (dt) nzblyr = nblyr+2 ! bio grid nzalyr = nblyr+4 ! aerosols (2 snow & nblyr+2 bio) + ! B grid default + l_ustr2d = ustr2d + l_vstr2d = ustr2d + l_ucstr = ucstr + l_vcstr = ucstr + if (grid_system == 'C' .or. grid_system == 'CD') then + l_ustr2d = estr2d + l_vstr2d = nstr2d + l_ucstr = ecstr + l_vcstr = ncstr + endif + !----------------------------------------------------------------- ! read namelist !----------------------------------------------------------------- @@ -278,6 +291,11 @@ subroutine init_hist (dt) f_sispeed = f_CMIP endif + if (grid_system == 'CD') then + f_uveln = f_uvel + f_vvele = f_vvel + endif + #ifndef ncdf f_bounds = .false. #endif @@ -328,6 +346,8 @@ subroutine init_hist (dt) call broadcast_scalar (f_aice, master_task) call broadcast_scalar (f_uvel, master_task) call broadcast_scalar (f_vvel, master_task) + call broadcast_scalar (f_uveln, master_task) + call broadcast_scalar (f_vvele, master_task) call broadcast_scalar (f_uatm, master_task) call broadcast_scalar (f_vatm, master_task) call broadcast_scalar (f_atmspd, master_task) @@ -549,29 +569,31 @@ subroutine init_hist (dt) "averaged with Tf if no ice is present", c1, c0, & ns1, f_Tsfc) -! tcraig, just to test capability, tcx -! if (grid_system == 'CD') then -! call define_hist_field(n_aice,"aice","1",nstr2D, ncstr, & -! "ice area (aggregate)", & -! "none", c1, c0, & -! ns1, f_aice) -! else call define_hist_field(n_aice,"aice","1",tstr2D, tcstr, & "ice area (aggregate)", & "none", c1, c0, & ns1, f_aice) -! endif - call define_hist_field(n_uvel,"uvel","m/s",ustr2D, ucstr, & + call define_hist_field(n_uvel,"uvel","m/s",l_ustr2D, l_ucstr, & "ice velocity (x)", & - "positive is x direction on U grid", c1, c0, & + "positive is x direction on u grid", c1, c0, & ns1, f_uvel) - call define_hist_field(n_vvel,"vvel","m/s",ustr2D, ucstr, & + call define_hist_field(n_vvel,"vvel","m/s",l_vstr2D, l_vcstr, & "ice velocity (y)", & - "positive is y direction on U grid", c1, c0, & + "positive is y direction on v grid", c1, c0, & ns1, f_vvel) + call define_hist_field(n_uveln,"uveln","m/s",nstr2D, ncstr, & + "ice velocity (x)", & + "positive is x direction on N grid", c1, c0, & + ns1, f_uveln) + + call define_hist_field(n_vvele,"vvele","m/s",estr2D, ecstr, & + "ice velocity (y)", & + "positive is y direction on E grid", c1, c0, & + ns1, f_vvele) + call define_hist_field(n_uatm,"uatm","m/s",ustr2D, ucstr, & "atm velocity (x)", & "positive is x direction on U grid", c1, c0, & @@ -1945,6 +1967,10 @@ subroutine accum_hist (dt) call accum_hist_field(n_uvel, iblk, uvel(:,:,iblk), a2D) if (f_vvel (1:1) /= 'x') & call accum_hist_field(n_vvel, iblk, vvel(:,:,iblk), a2D) + if (f_uveln (1:1) /= 'x') & + call accum_hist_field(n_uveln, iblk, uveln(:,:,iblk), a2D) + if (f_vvele (1:1) /= 'x') & + call accum_hist_field(n_vvele, iblk, vvele(:,:,iblk), a2D) if (f_uatm (1:1) /= 'x') & call accum_hist_field(n_uatm, iblk, uatm(:,:,iblk), a2D) if (f_vatm (1:1) /= 'x') & diff --git a/cicecore/cicedynB/analysis/ice_history_shared.F90 b/cicecore/cicedynB/analysis/ice_history_shared.F90 index 1c8823b62..fc4b68ae3 100644 --- a/cicecore/cicedynB/analysis/ice_history_shared.F90 +++ b/cicecore/cicedynB/analysis/ice_history_shared.F90 @@ -235,6 +235,7 @@ module ice_history_shared f_snowfrac = 'x', f_snowfracn = 'x', & f_Tsfc = 'm', f_aice = 'm', & f_uvel = 'm', f_vvel = 'm', & + f_uveln = 'x', f_vvele = 'x', & f_uatm = 'm', f_vatm = 'm', & f_atmspd = 'm', f_atmdir = 'm', & f_fswup = 'm', & @@ -384,6 +385,7 @@ module ice_history_shared f_snowfrac, f_snowfracn, & f_Tsfc, f_aice , & f_uvel, f_vvel , & +! f_uveln, f_vvele , & ! for now, have this set from f_uvel, f_vvel f_uatm, f_vatm , & f_atmspd, f_atmdir , & f_fswup, & @@ -557,6 +559,7 @@ module ice_history_shared n_snowfrac , n_snowfracn , & n_Tsfc , n_aice , & n_uvel , n_vvel , & + n_uveln , n_vvele , & n_uatm , n_vatm , & n_atmspd , n_atmdir , & n_sice , & diff --git a/cicecore/cicedynB/dynamics/ice_dyn_eap.F90 b/cicecore/cicedynB/dynamics/ice_dyn_eap.F90 index c550a4b14..cf5a2fd67 100644 --- a/cicecore/cicedynB/dynamics/ice_dyn_eap.F90 +++ b/cicecore/cicedynB/dynamics/ice_dyn_eap.F90 @@ -254,8 +254,8 @@ subroutine eap (dt) ! convert fields from T to U grid !----------------------------------------------------------------- - call grid_average_X2Y('T2U',tmass,umass) - call grid_average_X2Y('T2U',aice_init, aiu) + call grid_average_X2Y('T2UF',tmass,umass) + call grid_average_X2Y('T2UF',aice_init, aiu) !---------------------------------------------------------------- ! Set wind stress to values supplied via NEMO or other forcing @@ -274,8 +274,8 @@ subroutine eap (dt) field_loc_center, field_type_vector) call ice_HaloUpdate (strairy, halo_info, & field_loc_center, field_type_vector) - call grid_average_X2Y('T2U',strairx) - call grid_average_X2Y('T2U',strairy) + call grid_average_X2Y('T2UF',strairx) + call grid_average_X2Y('T2UF',strairy) endif ! tcraig, tcx, turned off this threaded region, in evp, this block and @@ -556,8 +556,8 @@ subroutine eap (dt) field_loc_NEcorner, field_type_vector) call ice_HaloUpdate (strocnyT, halo_info, & field_loc_NEcorner, field_type_vector) - call grid_average_X2Y('U2T',strocnxT) ! shift - call grid_average_X2Y('U2T',strocnyT) + call grid_average_X2Y('U2TF',strocnxT) ! shift + call grid_average_X2Y('U2TF',strocnyT) call ice_timer_stop(timer_dynamics) ! dynamics diff --git a/cicecore/cicedynB/dynamics/ice_dyn_evp.F90 b/cicecore/cicedynB/dynamics/ice_dyn_evp.F90 index cf7048e15..861f8780d 100644 --- a/cicecore/cicedynB/dynamics/ice_dyn_evp.F90 +++ b/cicecore/cicedynB/dynamics/ice_dyn_evp.F90 @@ -219,8 +219,8 @@ subroutine evp (dt) ! convert fields from T to U grid !----------------------------------------------------------------- - call grid_average_X2Y('T2U',tmass,umass) - call grid_average_X2Y('T2U',aice_init, aiu) + call grid_average_X2Y('T2UF',tmass,umass) + call grid_average_X2Y('T2UF',aice_init, aiu) !---------------------------------------------------------------- ! Set wind stress to values supplied via NEMO or other forcing @@ -239,8 +239,8 @@ subroutine evp (dt) field_loc_center, field_type_vector) call ice_HaloUpdate (strairy, halo_info, & field_loc_center, field_type_vector) - call grid_average_X2Y('T2U',strairx) - call grid_average_X2Y('T2U',strairy) + call grid_average_X2Y('T2UF',strairx) + call grid_average_X2Y('T2UF',strairy) endif ! tcraig, tcx, threading here leads to some non-reproducbile results and failures in icepack_ice_strength @@ -565,8 +565,8 @@ subroutine evp (dt) field_loc_NEcorner, field_type_vector) call ice_HaloUpdate (strocnyT, halo_info, & field_loc_NEcorner, field_type_vector) - call grid_average_X2Y('U2T',strocnxT) ! shift - call grid_average_X2Y('U2T',strocnyT) + call grid_average_X2Y('U2TF',strocnxT) ! shift + call grid_average_X2Y('U2TF',strocnyT) call ice_timer_stop(timer_dynamics) ! dynamics diff --git a/cicecore/cicedynB/dynamics/ice_dyn_shared.F90 b/cicecore/cicedynB/dynamics/ice_dyn_shared.F90 index 5e14d9686..0cd7f70a5 100755 --- a/cicecore/cicedynB/dynamics/ice_dyn_shared.F90 +++ b/cicecore/cicedynB/dynamics/ice_dyn_shared.F90 @@ -17,6 +17,7 @@ module ice_dyn_shared use ice_domain_size, only: max_blocks use ice_fileunits, only: nu_diag use ice_exit, only: abort_ice + use ice_grid, only: grid_system use icepack_intfc, only: icepack_warnings_flush, icepack_warnings_aborted use icepack_intfc, only: icepack_query_parameters @@ -130,7 +131,7 @@ subroutine init_dyn (dt) stressp_1, stressp_2, stressp_3, stressp_4, & stressm_1, stressm_2, stressm_3, stressm_4, & stress12_1, stress12_2, stress12_3, stress12_4 - use ice_state, only: uvel, vvel, divu, shear + use ice_state, only: uvel, vvel, uveln, vvele, divu, shear use ice_grid, only: ULAT real (kind=dbl_kind), intent(in) :: & @@ -162,6 +163,10 @@ subroutine init_dyn (dt) ! velocity uvel(i,j,iblk) = c0 ! m/s vvel(i,j,iblk) = c0 ! m/s + if (grid_system == 'CD') then ! extra velocity variables + uveln = c0 + vvele = c0 + endif ! strain rates divu (i,j,iblk) = c0 diff --git a/cicecore/cicedynB/dynamics/ice_dyn_vp.F90 b/cicecore/cicedynB/dynamics/ice_dyn_vp.F90 index a8bf7be89..6a8095c69 100644 --- a/cicecore/cicedynB/dynamics/ice_dyn_vp.F90 +++ b/cicecore/cicedynB/dynamics/ice_dyn_vp.F90 @@ -320,8 +320,8 @@ subroutine implicit_solver (dt) ! convert fields from T to U grid !----------------------------------------------------------------- - call grid_average_X2Y('T2U',tmass,umass) - call grid_average_X2Y('T2U',aice_init, aiu) + call grid_average_X2Y('T2UF',tmass,umass) + call grid_average_X2Y('T2UF',aice_init, aiu) !---------------------------------------------------------------- ! Set wind stress to values supplied via NEMO or other forcing @@ -340,8 +340,8 @@ subroutine implicit_solver (dt) field_loc_center, field_type_vector) call ice_HaloUpdate (strairy, halo_info, & field_loc_center, field_type_vector) - call grid_average_X2Y('T2U',strairx) - call grid_average_X2Y('T2U',strairy) + call grid_average_X2Y('T2UF',strairx) + call grid_average_X2Y('T2UF',strairy) endif ! tcraig, tcx, threading here leads to some non-reproducbile results and failures in icepack_ice_strength @@ -655,8 +655,8 @@ subroutine implicit_solver (dt) field_loc_NEcorner, field_type_vector) call ice_HaloUpdate (strocnyT, halo_info, & field_loc_NEcorner, field_type_vector) - call grid_average_X2Y('U2T',strocnxT) ! shift - call grid_average_X2Y('U2T',strocnyT) + call grid_average_X2Y('U2TF',strocnxT) ! shift + call grid_average_X2Y('U2TF',strocnyT) call ice_timer_stop(timer_dynamics) ! dynamics diff --git a/cicecore/cicedynB/general/ice_forcing.F90 b/cicecore/cicedynB/general/ice_forcing.F90 index a4dd66c67..7b1e2eac7 100755 --- a/cicecore/cicedynB/general/ice_forcing.F90 +++ b/cicecore/cicedynB/general/ice_forcing.F90 @@ -4072,8 +4072,8 @@ subroutine ocn_data_ncar_init_3D work1(:,:,:) = ocn_frc_m(:,:,:,n ,m) work2(:,:,:) = ocn_frc_m(:,:,:,n+1,m) - call grid_average_X2Y('T2U',work1,ocn_frc_m(:,:,:,n ,m)) - call grid_average_X2Y('T2U',work2,ocn_frc_m(:,:,:,n+1,m)) + call grid_average_X2Y('T2UF',work1,ocn_frc_m(:,:,:,n ,m)) + call grid_average_X2Y('T2UF',work2,ocn_frc_m(:,:,:,n+1,m)) enddo ! month loop enddo ! field loop @@ -4474,8 +4474,8 @@ subroutine ocn_data_hadgem(dt) ! Interpolate to U grid !----------------------------------------------------------------- - call grid_average_X2Y('T2U',uocn) - call grid_average_X2Y('T2U',vocn) + call grid_average_X2Y('T2UF',uocn) + call grid_average_X2Y('T2UF',vocn) endif ! ocn_data_type = hadgem_sst_uvocn @@ -5278,7 +5278,7 @@ subroutine box2001_data call icepack_query_parameters(pi_out=pi, pi2_out=pi2, puny_out=puny) call icepack_query_parameters(secday_out=secday) - call grid_average_X2Y('T2U',aice, aiu) + call grid_average_X2Y('T2UF',aice, aiu) period = c4*secday diff --git a/cicecore/cicedynB/general/ice_state.F90 b/cicecore/cicedynB/general/ice_state.F90 index 362fd1413..514d30b9a 100644 --- a/cicecore/cicedynB/general/ice_state.F90 +++ b/cicecore/cicedynB/general/ice_state.F90 @@ -108,7 +108,9 @@ module ice_state real (kind=dbl_kind), dimension(:,:,:), allocatable, & public :: & uvel , & ! x-component of velocity (m/s) + uveln , & ! extra x-component of velocity on CD grid (m/s) vvel , & ! y-component of velocity (m/s) + vvele , & ! extra y-component of velocity on CD grid (m/s) divu , & ! strain rate I component, velocity divergence (1/s) shear , & ! strain rate II component (1/s) strength ! ice strength (N/m) @@ -150,7 +152,9 @@ subroutine alloc_state vsno (nx_block,ny_block,max_blocks) , & ! volume per unit area of snow (m) aice0 (nx_block,ny_block,max_blocks) , & ! concentration of open water uvel (nx_block,ny_block,max_blocks) , & ! x-component of velocity (m/s) + uveln (nx_block,ny_block,max_blocks) , & ! extra x-component of velocity on CD grid (m/s) vvel (nx_block,ny_block,max_blocks) , & ! y-component of velocity (m/s) + vvele (nx_block,ny_block,max_blocks) , & ! extra y-component of velocity on CD grid (m/s) divu (nx_block,ny_block,max_blocks) , & ! strain rate I component, velocity divergence (1/s) shear (nx_block,ny_block,max_blocks) , & ! strain rate II component (1/s) strength (nx_block,ny_block,max_blocks) , & ! ice strength (N/m) diff --git a/cicecore/cicedynB/infrastructure/ice_grid.F90 b/cicecore/cicedynB/infrastructure/ice_grid.F90 index 8f8c85904..f6322606a 100644 --- a/cicecore/cicedynB/infrastructure/ice_grid.F90 +++ b/cicecore/cicedynB/infrastructure/ice_grid.F90 @@ -2164,29 +2164,29 @@ subroutine grid_average_X2Y(X2Y,work1,work2) select case (trim(X2Y)) ! flux unmasked - case('T2UF','T2U') + case('T2UF') call grid_average_X2YF('NE',work1,tarea,work2tmp,uarea) - case('T2EF','T2E') + case('T2EF') call grid_average_X2YF('E' ,work1,tarea,work2tmp,earea) - case('T2NF','T2N') + case('T2NF') call grid_average_X2YF('N' ,work1,tarea,work2tmp,narea) - case('U2TF','U2T') + case('U2TF') call grid_average_X2YF('SW',work1,uarea,work2tmp,tarea) - case('U2EF','U2E') + case('U2EF') call grid_average_X2YF('S' ,work1,uarea,work2tmp,earea) - case('U2NF','U2N') + case('U2NF') call grid_average_X2YF('W' ,work1,uarea,work2tmp,narea) - case('E2TF','E2T') + case('E2TF') call grid_average_X2YF('W' ,work1,earea,work2tmp,tarea) - case('E2UF','E2U') + case('E2UF') call grid_average_X2YF('N' ,work1,earea,work2tmp,uarea) - case('E2NF','E2N') + case('E2NF') call grid_average_X2YF('NW',work1,earea,work2tmp,narea) - case('N2TF','N2T') + case('N2TF') call grid_average_X2YF('S' ,work1,narea,work2tmp,tarea) - case('N2UF','N2U') + case('N2UF') call grid_average_X2YF('E' ,work1,narea,work2tmp,uarea) - case('N2EF','N2E') + case('N2EF') call grid_average_X2YF('SE',work1,narea,work2tmp,earea) ! state masked diff --git a/cicecore/cicedynB/infrastructure/io/io_netcdf/ice_history_write.F90 b/cicecore/cicedynB/infrastructure/io/io_netcdf/ice_history_write.F90 index f48371f8d..ddfd95297 100644 --- a/cicecore/cicedynB/infrastructure/io/io_netcdf/ice_history_write.F90 +++ b/cicecore/cicedynB/infrastructure/io/io_netcdf/ice_history_write.F90 @@ -96,8 +96,8 @@ subroutine ice_write_hist (ns) ! 8 coordinate variables: TLON, TLAT, ULON, ULAT, NLON, NLAT, ELON, ELAT INTEGER (kind=int_kind), PARAMETER :: ncoord = 8 - ! 8 vertices in each grid cell - INTEGER (kind=int_kind), PARAMETER :: nverts = 8 + ! 4 vertices in each grid cell + INTEGER (kind=int_kind), PARAMETER :: nverts = 4 ! 8 variables describe T, U grid boundaries: ! lont_bounds, latt_bounds, lonu_bounds, latu_bounds diff --git a/cicecore/cicedynB/infrastructure/io/io_pio2/ice_history_write.F90 b/cicecore/cicedynB/infrastructure/io/io_pio2/ice_history_write.F90 index 0e91d42d0..00a121a59 100644 --- a/cicecore/cicedynB/infrastructure/io/io_pio2/ice_history_write.F90 +++ b/cicecore/cicedynB/infrastructure/io/io_pio2/ice_history_write.F90 @@ -49,9 +49,12 @@ subroutine ice_write_hist (ns) use ice_domain, only: distrb_info, nblocks use ice_domain_size, only: nx_global, ny_global, max_blocks, max_nstrm use ice_gather_scatter, only: gather_global - use ice_grid, only: TLON, TLAT, ULON, ULAT, hm, bm, tarea, uarea, & - dxu, dxt, dyu, dyt, HTN, HTE, ANGLE, ANGLET, tmask, & - lont_bounds, latt_bounds, lonu_bounds, latu_bounds + use ice_grid, only: TLON, TLAT, ULON, ULAT, NLON, NLAT, ELON, ELAT, & + hm, bm, uvm, npm, epm, & + dxu, dxt, dyu, dyt, dxn, dyn, dxe, dye, HTN, HTE, ANGLE, ANGLET, & + tarea, uarea, narea, earea, tmask, umask, nmask, emask, & + lont_bounds, latt_bounds, lonu_bounds, latu_bounds, & + lonn_bounds, latn_bounds, lone_bounds, late_bounds use ice_history_shared use ice_arrays_column, only: hin_max, floe_rad_c use ice_restart_shared, only: runid, lcdf64 @@ -89,15 +92,16 @@ subroutine ice_write_hist (ns) iodesc4di, iodesc4ds, iodesc4df type(var_desc_t) :: varid - ! 4 coordinate variables: TLON, TLAT, ULON, ULAT - INTEGER (kind=int_kind), PARAMETER :: ncoord = 4 + ! 8 coordinate variables: TLON, TLAT, ULON, ULAT, NLON, NLAT, ELON, ELAT + INTEGER (kind=int_kind), PARAMETER :: ncoord = 8 ! 4 vertices in each grid cell INTEGER (kind=int_kind), PARAMETER :: nverts = 4 - ! 4 variables describe T, U grid boundaries: + ! 8 variables describe T, U, N, E grid boundaries: ! lont_bounds, latt_bounds, lonu_bounds, latu_bounds - INTEGER (kind=int_kind), PARAMETER :: nvar_verts = 4 + ! lonn_bounds, latn_bounds, lone_bounds, late_bounds + INTEGER (kind=int_kind), PARAMETER :: nvar_verts = 8 TYPE coord_attributes ! netcdf coordinate attributes character (len=11) :: short_name @@ -110,10 +114,10 @@ subroutine ice_write_hist (ns) character (len=20) :: coordinates END TYPE req_attributes - TYPE(req_attributes), dimension(nvar) :: var - TYPE(coord_attributes), dimension(ncoord) :: coord_var + TYPE(req_attributes), dimension(nvar_grd) :: var_grd + TYPE(coord_attributes), dimension(ncoord) :: var_coord TYPE(coord_attributes), dimension(nvar_verts) :: var_nverts - TYPE(coord_attributes), dimension(nvarz) :: var_nz + TYPE(coord_attributes), dimension(nvar_grdz) :: var_grdz CHARACTER (char_len), dimension(ncoord) :: coord_bounds real (kind=dbl_kind) , allocatable :: workd2(:,:,:) @@ -252,74 +256,118 @@ subroutine ice_write_hist (ns) ind = 0 ind = ind + 1 - coord_var(ind) = coord_attributes('TLON', & + var_coord(ind) = coord_attributes('TLON', & 'T grid center longitude', 'degrees_east') coord_bounds(ind) = 'lont_bounds' ind = ind + 1 - coord_var(ind) = coord_attributes('TLAT', & + var_coord(ind) = coord_attributes('TLAT', & 'T grid center latitude', 'degrees_north') coord_bounds(ind) = 'latt_bounds' ind = ind + 1 - coord_var(ind) = coord_attributes('ULON', & + var_coord(ind) = coord_attributes('ULON', & 'U grid center longitude', 'degrees_east') coord_bounds(ind) = 'lonu_bounds' ind = ind + 1 - coord_var(ind) = coord_attributes('ULAT', & + var_coord(ind) = coord_attributes('ULAT', & 'U grid center latitude', 'degrees_north') coord_bounds(ind) = 'latu_bounds' + ind = ind + 1 + var_coord(ind) = coord_attributes('NLON', & + 'N grid center longitude', 'degrees_east') + coord_bounds(ind) = 'lonn_bounds' + ind = ind + 1 + var_coord(ind) = coord_attributes('NLAT', & + 'N grid center latitude', 'degrees_north') + coord_bounds(ind) = 'latn_bounds' + ind = ind + 1 + var_coord(ind) = coord_attributes('ELON', & + 'E grid center longitude', 'degrees_east') + coord_bounds(ind) = 'lone_bounds' + ind = ind + 1 + var_coord(ind) = coord_attributes('ELAT', & + 'E grid center latitude', 'degrees_north') + coord_bounds(ind) = 'late_bounds' - var_nz(1) = coord_attributes('NCAT', 'category maximum thickness', 'm') - var_nz(2) = coord_attributes('VGRDi', 'vertical ice levels', '1') - var_nz(3) = coord_attributes('VGRDs', 'vertical snow levels', '1') - var_nz(4) = coord_attributes('VGRDb', 'vertical ice-bio levels', '1') - var_nz(5) = coord_attributes('VGRDa', 'vertical snow-ice-bio levels', '1') - var_nz(6) = coord_attributes('NFSD', 'category floe size (center)', 'm') + var_grdz(1) = coord_attributes('NCAT', 'category maximum thickness', 'm') + var_grdz(2) = coord_attributes('VGRDi', 'vertical ice levels', '1') + var_grdz(3) = coord_attributes('VGRDs', 'vertical snow levels', '1') + var_grdz(4) = coord_attributes('VGRDb', 'vertical ice-bio levels', '1') + var_grdz(5) = coord_attributes('VGRDa', 'vertical snow-ice-bio levels', '1') + var_grdz(6) = coord_attributes('NFSD', 'category floe size (center)', 'm') !----------------------------------------------------------------- ! define information for optional time-invariant variables !----------------------------------------------------------------- - var(n_tmask)%req = coord_attributes('tmask', & - 'ocean grid mask', ' ') - var(n_tmask)%coordinates = 'TLON TLAT' - - var(n_blkmask)%req = coord_attributes('blkmask', & - 'ice grid block mask', ' ') - var(n_blkmask)%coordinates = 'TLON TLAT' - - var(n_tarea)%req = coord_attributes('tarea', & + var_grd(n_tmask)%req = coord_attributes('tmask', & + 'mask of T grid cells, 0 = land, 1 = ocean', 'unitless') + var_grd(n_tmask)%coordinates = 'TLON TLAT' + var_grd(n_umask)%req = coord_attributes('umask', & + 'mask of U grid cells, 0 = land, 1 = ocean', 'unitless') + var_grd(n_umask)%coordinates = 'ULON ULAT' + var_grd(n_nmask)%req = coord_attributes('nmask', & + 'mask of N grid cells, 0 = land, 1 = ocean', 'unitless') + var_grd(n_nmask)%coordinates = 'NLON NLAT' + var_grd(n_emask)%req = coord_attributes('emask', & + 'mask of E grid cells, 0 = land, 1 = ocean', 'unitless') + var_grd(n_emask)%coordinates = 'ELON ELAT' + + var_grd(n_blkmask)%req = coord_attributes('blkmask', & + 'ice grid block mask, mytask + iblk/100', 'unitless') + var_grd(n_blkmask)%coordinates = 'TLON TLAT' + + var_grd(n_tarea)%req = coord_attributes('tarea', & 'area of T grid cells', 'm^2') - var(n_tarea)%coordinates = 'TLON TLAT' - - var(n_uarea)%req = coord_attributes('uarea', & + var_grd(n_tarea)%coordinates = 'TLON TLAT' + var_grd(n_uarea)%req = coord_attributes('uarea', & 'area of U grid cells', 'm^2') - var(n_uarea)%coordinates = 'ULON ULAT' - var(n_dxt)%req = coord_attributes('dxt', & + var_grd(n_uarea)%coordinates = 'ULON ULAT' + var_grd(n_narea)%req = coord_attributes('narea', & + 'area of N grid cells', 'm^2') + var_grd(n_narea)%coordinates = 'NLON NLAT' + var_grd(n_earea)%req = coord_attributes('earea', & + 'area of E grid cells', 'm^2') + var_grd(n_earea)%coordinates = 'ELON ELAT' + + var_grd(n_dxt)%req = coord_attributes('dxt', & 'T cell width through middle', 'm') - var(n_dxt)%coordinates = 'TLON TLAT' - var(n_dyt)%req = coord_attributes('dyt', & + var_grd(n_dxt)%coordinates = 'TLON TLAT' + var_grd(n_dyt)%req = coord_attributes('dyt', & 'T cell height through middle', 'm') - var(n_dyt)%coordinates = 'TLON TLAT' - var(n_dxu)%req = coord_attributes('dxu', & + var_grd(n_dyt)%coordinates = 'TLON TLAT' + var_grd(n_dxu)%req = coord_attributes('dxu', & 'U cell width through middle', 'm') - var(n_dxu)%coordinates = 'ULON ULAT' - var(n_dyu)%req = coord_attributes('dyu', & + var_grd(n_dxu)%coordinates = 'ULON ULAT' + var_grd(n_dyu)%req = coord_attributes('dyu', & 'U cell height through middle', 'm') - var(n_dyu)%coordinates = 'ULON ULAT' - var(n_HTN)%req = coord_attributes('HTN', & + var_grd(n_dyu)%coordinates = 'ULON ULAT' + var_grd(n_dxn)%req = coord_attributes('dxn', & + 'N cell width through middle', 'm') + var_grd(n_dxn)%coordinates = 'NLON NLAT' + var_grd(n_dyn)%req = coord_attributes('dyn', & + 'N cell height through middle', 'm') + var_grd(n_dyn)%coordinates = 'NLON NLAT' + var_grd(n_dxe)%req = coord_attributes('dxe', & + 'E cell width through middle', 'm') + var_grd(n_dxe)%coordinates = 'ELON ELAT' + var_grd(n_dye)%req = coord_attributes('dye', & + 'E cell height through middle', 'm') + var_grd(n_dye)%coordinates = 'ELON ELAT' + + var_grd(n_HTN)%req = coord_attributes('HTN', & 'T cell width on North side','m') - var(n_HTN)%coordinates = 'TLON TLAT' - var(n_HTE)%req = coord_attributes('HTE', & + var_grd(n_HTN)%coordinates = 'TLON TLAT' + var_grd(n_HTE)%req = coord_attributes('HTE', & 'T cell width on East side', 'm') - var(n_HTE)%coordinates = 'TLON TLAT' - var(n_ANGLE)%req = coord_attributes('ANGLE', & + var_grd(n_HTE)%coordinates = 'TLON TLAT' + var_grd(n_ANGLE)%req = coord_attributes('ANGLE', & 'angle grid makes with latitude line on U grid', & 'radians') - var(n_ANGLE)%coordinates = 'ULON ULAT' - var(n_ANGLET)%req = coord_attributes('ANGLET', & + var_grd(n_ANGLE)%coordinates = 'ULON ULAT' + var_grd(n_ANGLET)%req = coord_attributes('ANGLET', & 'angle grid makes with latitude line on T grid', & 'radians') - var(n_ANGLET)%coordinates = 'TLON TLAT' + var_grd(n_ANGLET)%coordinates = 'TLON TLAT' ! These fields are required for CF compliance ! dimensions (nx,ny,nverts) @@ -331,6 +379,14 @@ subroutine ice_write_hist (ns) 'longitude boundaries of U cells', 'degrees_east') var_nverts(n_latu_bnds) = coord_attributes('latu_bounds', & 'latitude boundaries of U cells', 'degrees_north') + var_nverts(n_lonn_bnds) = coord_attributes('lonn_bounds', & + 'longitude boundaries of N cells', 'degrees_east') + var_nverts(n_latn_bnds) = coord_attributes('latn_bounds', & + 'latitude boundaries of N cells', 'degrees_north') + var_nverts(n_lone_bnds) = coord_attributes('lone_bounds', & + 'longitude boundaries of E cells', 'degrees_east') + var_nverts(n_late_bnds) = coord_attributes('late_bounds', & + 'latitude boundaries of E cells', 'degrees_north') !----------------------------------------------------------------- ! define attributes for time-invariant variables @@ -340,12 +396,12 @@ subroutine ice_write_hist (ns) dimid2(2) = jmtid do i = 1, ncoord - status = pio_def_var(File, trim(coord_var(i)%short_name), lprecision, & + status = pio_def_var(File, trim(var_coord(i)%short_name), lprecision, & dimid2, varid) - status = pio_put_att(File,varid,'long_name',trim(coord_var(i)%long_name)) - status = pio_put_att(File, varid, 'units', trim(coord_var(i)%units)) - call ice_write_hist_fill(File,varid,coord_var(i)%short_name,history_precision) - if (coord_var(i)%short_name == 'ULAT') then + status = pio_put_att(File,varid,'long_name',trim(var_coord(i)%long_name)) + status = pio_put_att(File, varid, 'units', trim(var_coord(i)%units)) + call ice_write_hist_fill(File,varid,var_coord(i)%short_name,history_precision) + if (var_coord(i)%short_name == 'ULAT') then status = pio_put_att(File,varid,'comment', & trim('Latitude of NE corner of T grid cell')) endif @@ -362,39 +418,23 @@ subroutine ice_write_hist (ns) dimidex(5)=kmtida dimidex(6)=fmtid - do i = 1, nvarz + do i = 1, nvar_grdz if (igrdz(i)) then - status = pio_def_var(File, trim(var_nz(i)%short_name), lprecision, & + status = pio_def_var(File, trim(var_grdz(i)%short_name), lprecision, & (/dimidex(i)/), varid) - status = pio_put_att(File, varid, 'long_name', var_nz(i)%long_name) - status = pio_put_att(File, varid, 'units' , var_nz(i)%units) + status = pio_put_att(File, varid, 'long_name', var_grdz(i)%long_name) + status = pio_put_att(File, varid, 'units' , var_grdz(i)%units) endif enddo - ! Attributes for tmask defined separately, since it has no units - if (igrd(n_tmask)) then - status = pio_def_var(File, 'tmask', lprecision, dimid2, varid) - status = pio_put_att(File,varid, 'long_name', 'ocean grid mask') - status = pio_put_att(File, varid, 'coordinates', 'TLON TLAT') - call ice_write_hist_fill(File,varid,'tmask',history_precision) - status = pio_put_att(File,varid,'comment', '0 = land, 1 = ocean') - endif - if (igrd(n_blkmask)) then - status = pio_def_var(File, 'blkmask', lprecision, dimid2, varid) - status = pio_put_att(File,varid, 'long_name', 'ice grid block mask') - status = pio_put_att(File, varid, 'coordinates', 'TLON TLAT') - status = pio_put_att(File,varid,'comment', 'mytask + iblk/100') - call ice_write_hist_fill(File,varid,'blkmask',history_precision) - endif - - do i = 3, nvar ! note: n_tmask=1, n_blkmask=2 + do i = 1, nvar_grd if (igrd(i)) then - status = pio_def_var(File, trim(var(i)%req%short_name), & + status = pio_def_var(File, trim(var_grd(i)%req%short_name), & lprecision, dimid2, varid) - status = pio_put_att(File,varid, 'long_name', trim(var(i)%req%long_name)) - status = pio_put_att(File, varid, 'units', trim(var(i)%req%units)) - status = pio_put_att(File, varid, 'coordinates', trim(var(i)%coordinates)) - call ice_write_hist_fill(File,varid,var(i)%req%short_name,history_precision) + status = pio_put_att(File,varid, 'long_name', trim(var_grd(i)%req%long_name)) + status = pio_put_att(File, varid, 'units', trim(var_grd(i)%req%units)) + status = pio_put_att(File, varid, 'coordinates', trim(var_grd(i)%coordinates)) + call ice_write_hist_fill(File,varid,var_grd(i)%req%short_name,history_precision) endif enddo @@ -853,8 +893,8 @@ subroutine ice_write_hist (ns) allocate(workr2(nx_block,ny_block,nblocks)) do i = 1,ncoord - status = pio_inq_varid(File, coord_var(i)%short_name, varid) - SELECT CASE (coord_var(i)%short_name) + status = pio_inq_varid(File, var_coord(i)%short_name, varid) + SELECT CASE (var_coord(i)%short_name) CASE ('TLON') ! Convert T grid longitude from -180 -> 180 to 0 to 360 workd2(:,:,:) = mod(tlon(:,:,1:nblocks)*rad_to_deg + c360, c360) @@ -864,6 +904,14 @@ subroutine ice_write_hist (ns) workd2(:,:,:) = ulon(:,:,1:nblocks)*rad_to_deg CASE ('ULAT') workd2(:,:,:) = ulat(:,:,1:nblocks)*rad_to_deg + CASE ('NLON') + workd2(:,:,:) = nlon(:,:,1:nblocks)*rad_to_deg + CASE ('NLAT') + workd2(:,:,:) = nlat(:,:,1:nblocks)*rad_to_deg + CASE ('ELON') + workd2(:,:,:) = elon(:,:,1:nblocks)*rad_to_deg + CASE ('ELAT') + workd2(:,:,:) = elat(:,:,1:nblocks)*rad_to_deg END SELECT if (history_precision == 8) then call pio_write_darray(File, varid, iodesc2d, & @@ -877,10 +925,10 @@ subroutine ice_write_hist (ns) ! Extra dimensions (NCAT, NFSD, VGRD*) - do i = 1, nvarz + do i = 1, nvar_grdz if (igrdz(i)) then - status = pio_inq_varid(File, var_nz(i)%short_name, varid) - SELECT CASE (var_nz(i)%short_name) + status = pio_inq_varid(File, var_grdz(i)%short_name, varid) + SELECT CASE (var_grdz(i)%short_name) CASE ('NCAT') status = pio_put_var(File, varid, hin_max(1:ncat_hist)) CASE ('NFSD') @@ -901,36 +949,43 @@ subroutine ice_write_hist (ns) ! write grid masks, area and rotation angle !----------------------------------------------------------------- -! if (igrd(n_tmask)) then -! status = pio_inq_varid(File, 'tmask', varid) -! call pio_write_darray(File, varid, iodesc2d, & -! hm(:,:,1:nblocks), status, fillval=spval_dbl) -! endif -! if (igrd(n_blkmask)) then -! status = pio_inq_varid(File, 'blkmask', varid) -! call pio_write_darray(File, varid, iodesc2d, & -! bm(:,:,1:nblocks), status, fillval=spval_dbl) -! endif - - do i = 1, nvar ! note: n_tmask=1, n_blkmask=2 + do i = 1, nvar_grd if (igrd(i)) then - SELECT CASE (var(i)%req%short_name) + SELECT CASE (var_grd(i)%req%short_name) CASE ('tmask') workd2 = hm(:,:,1:nblocks) + CASE ('umask') + workd2 = uvm(:,:,1:nblocks) + CASE ('nmask') + workd2 = npm(:,:,1:nblocks) + CASE ('emask') + workd2 = epm(:,:,1:nblocks) CASE ('blkmask') workd2 = bm(:,:,1:nblocks) CASE ('tarea') workd2 = tarea(:,:,1:nblocks) CASE ('uarea') workd2 = uarea(:,:,1:nblocks) - CASE ('dxu') - workd2 = dxu(:,:,1:nblocks) - CASE ('dyu') - workd2 = dyu(:,:,1:nblocks) + CASE ('narea') + workd2 = narea(:,:,1:nblocks) + CASE ('earea') + workd2 = earea(:,:,1:nblocks) CASE ('dxt') workd2 = dxt(:,:,1:nblocks) CASE ('dyt') workd2 = dyt(:,:,1:nblocks) + CASE ('dxu') + workd2 = dxu(:,:,1:nblocks) + CASE ('dyu') + workd2 = dyu(:,:,1:nblocks) + CASE ('dxn') + workd2 = dxn(:,:,1:nblocks) + CASE ('dyn') + workd2 = dyn(:,:,1:nblocks) + CASE ('dxe') + workd2 = dxe(:,:,1:nblocks) + CASE ('dye') + workd2 = dye(:,:,1:nblocks) CASE ('HTN') workd2 = HTN(:,:,1:nblocks) CASE ('HTE') @@ -940,7 +995,7 @@ subroutine ice_write_hist (ns) CASE ('ANGLET') workd2 = ANGLET(:,:,1:nblocks) END SELECT - status = pio_inq_varid(File, var(i)%req%short_name, varid) + status = pio_inq_varid(File, var_grd(i)%req%short_name, varid) if (history_precision == 8) then call pio_write_darray(File, varid, iodesc2d, & workd2, status, fillval=spval_dbl) @@ -978,6 +1033,22 @@ subroutine ice_write_hist (ns) do ivertex = 1, nverts workd3v(ivertex,:,:,:) = latu_bounds(ivertex,:,:,1:nblocks) enddo + CASE ('lonn_bounds') + do ivertex = 1, nverts + workd3v(ivertex,:,:,:) = lonn_bounds(ivertex,:,:,1:nblocks) + enddo + CASE ('latn_bounds') + do ivertex = 1, nverts + workd3v(ivertex,:,:,:) = latn_bounds(ivertex,:,:,1:nblocks) + enddo + CASE ('lone_bounds') + do ivertex = 1, nverts + workd3v(ivertex,:,:,:) = lone_bounds(ivertex,:,:,1:nblocks) + enddo + CASE ('late_bounds') + do ivertex = 1, nverts + workd3v(ivertex,:,:,:) = late_bounds(ivertex,:,:,1:nblocks) + enddo END SELECT status = pio_inq_varid(File, var_nverts(i)%short_name, varid) diff --git a/cicecore/drivers/mct/cesm1/ice_import_export.F90 b/cicecore/drivers/mct/cesm1/ice_import_export.F90 index d0eac5a19..7aa60dbdf 100644 --- a/cicecore/drivers/mct/cesm1/ice_import_export.F90 +++ b/cicecore/drivers/mct/cesm1/ice_import_export.F90 @@ -472,10 +472,10 @@ subroutine ice_import( x2i ) call ice_HaloUpdate(vocn, halo_info, field_loc_center, field_type_scalar) call ice_HaloUpdate(ss_tltx, halo_info, field_loc_center, field_type_scalar) call ice_HaloUpdate(ss_tlty, halo_info, field_loc_center, field_type_scalar) - call grid_average_X2Y('T2U',uocn) - call grid_average_X2Y('T2U',vocn) - call grid_average_X2Y('T2U',ss_tltx) - call grid_average_X2Y('T2U',ss_tlty) + call grid_average_X2Y('T2UF',uocn) + call grid_average_X2Y('T2UF',vocn) + call grid_average_X2Y('T2UF',ss_tltx) + call grid_average_X2Y('T2UF',ss_tlty) call t_stopf ('cice_imp_t2u') end if diff --git a/cicecore/drivers/nuopc/cmeps/ice_import_export.F90 b/cicecore/drivers/nuopc/cmeps/ice_import_export.F90 index 50cba8883..10d42137f 100644 --- a/cicecore/drivers/nuopc/cmeps/ice_import_export.F90 +++ b/cicecore/drivers/nuopc/cmeps/ice_import_export.F90 @@ -801,10 +801,10 @@ subroutine ice_import( importState, rc ) call ice_HaloUpdate(vocn, halo_info, field_loc_center, field_type_scalar) call ice_HaloUpdate(ss_tltx, halo_info, field_loc_center, field_type_scalar) call ice_HaloUpdate(ss_tlty, halo_info, field_loc_center, field_type_scalar) - call grid_average_X2Y('T2U',uocn) - call grid_average_X2Y('T2U',vocn) - call grid_average_X2Y('T2U',ss_tltx) - call grid_average_X2Y('T2U',ss_tlty) + call grid_average_X2Y('T2UF',uocn) + call grid_average_X2Y('T2UF',vocn) + call grid_average_X2Y('T2UF',ss_tltx) + call grid_average_X2Y('T2UF',ss_tlty) call t_stopf ('cice_imp_t2u') end if diff --git a/cicecore/drivers/nuopc/dmi/cice_cap.info b/cicecore/drivers/nuopc/dmi/cice_cap.info index d1eee8ae0..4b2d6d65f 100644 --- a/cicecore/drivers/nuopc/dmi/cice_cap.info +++ b/cicecore/drivers/nuopc/dmi/cice_cap.info @@ -940,10 +940,10 @@ module cice_cap ! call ice_HaloUpdate(vocn, halo_info, field_loc_center, field_type_scalar) ! call ice_HaloUpdate(ss_tltx, halo_info, field_loc_center, field_type_scalar) ! call ice_HaloUpdate(ss_tlty, halo_info, field_loc_center, field_type_scalar) - call grid_average_X2Y('T2U',uocn) - call grid_average_X2Y('T2U',vocn) - call grid_average_X2Y('T2U',ss_tltx) - call grid_average_X2Y('T2U',ss_tlty) + call grid_average_X2Y('T2UF',uocn) + call grid_average_X2Y('T2UF',vocn) + call grid_average_X2Y('T2UF',ss_tltx) + call grid_average_X2Y('T2UF',ss_tlty) end subroutine subroutine CICE_Export(st,rc) From 63a1f1f9d04776223f0b44fde1f14357b6989b61 Mon Sep 17 00:00:00 2001 From: apcraig Date: Mon, 8 Nov 2021 21:24:36 -0700 Subject: [PATCH 16/17] update history coords and attributes --- cicecore/cicedynB/analysis/ice_history.F90 | 33 +- .../io/io_netcdf/ice_history_write.F90 | 351 +++++------------- .../io/io_pio2/ice_history_write.F90 | 277 ++++---------- 3 files changed, 194 insertions(+), 467 deletions(-) diff --git a/cicecore/cicedynB/analysis/ice_history.F90 b/cicecore/cicedynB/analysis/ice_history.F90 index fea284495..aa2a05cd8 100644 --- a/cicecore/cicedynB/analysis/ice_history.F90 +++ b/cicecore/cicedynB/analysis/ice_history.F90 @@ -94,7 +94,6 @@ subroutine init_hist (dt) integer (kind=int_kind), dimension(max_nstrm) :: & ntmp integer (kind=int_kind) :: nml_error ! namelist i/o error flag - character(len=25) :: l_ustr2d, l_vstr2d, l_ucstr, l_vcstr ! define location of u and v fields character(len=*), parameter :: subname = '(init_hist)' !----------------------------------------------------------------- @@ -108,18 +107,6 @@ subroutine init_hist (dt) nzblyr = nblyr+2 ! bio grid nzalyr = nblyr+4 ! aerosols (2 snow & nblyr+2 bio) - ! B grid default - l_ustr2d = ustr2d - l_vstr2d = ustr2d - l_ucstr = ucstr - l_vcstr = ucstr - if (grid_system == 'C' .or. grid_system == 'CD') then - l_ustr2d = estr2d - l_vstr2d = nstr2d - l_ucstr = ecstr - l_vcstr = ncstr - endif - !----------------------------------------------------------------- ! read namelist !----------------------------------------------------------------- @@ -573,16 +560,28 @@ subroutine init_hist (dt) "ice area (aggregate)", & "none", c1, c0, & ns1, f_aice) + + if (grid_system == 'CD') then + call define_hist_field(n_uvel,"uvel","m/s",estr2D, ecstr, & + "ice velocity (x)", & + "positive is x direction on E grid", c1, c0, & + ns1, f_uvel) - call define_hist_field(n_uvel,"uvel","m/s",l_ustr2D, l_ucstr, & + call define_hist_field(n_vvel,"vvel","m/s",nstr2D, ncstr, & + "ice velocity (y)", & + "positive is y direction on N grid", c1, c0, & + ns1, f_vvel) + else + call define_hist_field(n_uvel,"uvel","m/s",ustr2D, ucstr, & "ice velocity (x)", & - "positive is x direction on u grid", c1, c0, & + "positive is x direction on U grid", c1, c0, & ns1, f_uvel) - call define_hist_field(n_vvel,"vvel","m/s",l_vstr2D, l_vcstr, & + call define_hist_field(n_vvel,"vvel","m/s",ustr2D, ucstr, & "ice velocity (y)", & - "positive is y direction on v grid", c1, c0, & + "positive is y direction on U grid", c1, c0, & ns1, f_vvel) + endif call define_hist_field(n_uveln,"uveln","m/s",nstr2D, ncstr, & "ice velocity (x)", & diff --git a/cicecore/cicedynB/infrastructure/io/io_netcdf/ice_history_write.F90 b/cicecore/cicedynB/infrastructure/io/io_netcdf/ice_history_write.F90 index ddfd95297..5587f2b6b 100644 --- a/cicecore/cicedynB/infrastructure/io/io_netcdf/ice_history_write.F90 +++ b/cicecore/cicedynB/infrastructure/io/io_netcdf/ice_history_write.F90 @@ -505,51 +505,7 @@ subroutine ice_write_hist (ns) lprecision, dimid, varid) if (status /= nf90_noerr) call abort_ice(subname// & 'ERROR: defining variable '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'units', & - avail_hist_fields(n)%vunit) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining units for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid, 'long_name', & - avail_hist_fields(n)%vdesc) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining long_name for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'coordinates', & - avail_hist_fields(n)%vcoord) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining coordinates for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'cell_measures', & - avail_hist_fields(n)%vcellmeas) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining cell measures for '//avail_hist_fields(n)%vname) - call ice_write_hist_fill(ncid,varid,avail_hist_fields(n)%vname,history_precision) - - !----------------------------------------------------------------- - ! Add cell_methods attribute to variables if averaged - !----------------------------------------------------------------- - if (hist_avg) then - if (TRIM(avail_hist_fields(n)%vname)/='sig1' & - .or.TRIM(avail_hist_fields(n)%vname)/='sig2' & - .or.TRIM(avail_hist_fields(n)%vname)/='sistreave' & - .or.TRIM(avail_hist_fields(n)%vname)/='sistremax' & - .or.TRIM(avail_hist_fields(n)%vname)/='sigP') then - status = nf90_put_att(ncid,varid,'cell_methods','time: mean') - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining cell methods for '//avail_hist_fields(n)%vname) - endif - endif - - if ((histfreq(ns) == '1' .and. histfreq_n(ns) == 1) & - .or..not. hist_avg & - .or. n==n_divu(ns) .or. n==n_shear(ns) & ! snapshots - .or. n==n_sig1(ns) .or. n==n_sig2(ns) & - .or. n==n_sigP(ns) .or. n==n_trsig(ns) & - .or. n==n_sistreave(ns) .or. n==n_sistremax(ns) & - .or. n==n_mlt_onset(ns) .or. n==n_frz_onset(ns) & - .or. n==n_hisnap(ns) .or. n==n_aisnap(ns)) then - status = nf90_put_att(ncid,varid,'time_rep','instantaneous') - else - status = nf90_put_att(ncid,varid,'time_rep','averaged') - endif + call ice_write_hist_attrs(ncid,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_2D @@ -564,39 +520,7 @@ subroutine ice_write_hist (ns) lprecision, dimidz, varid) if (status /= nf90_noerr) call abort_ice(subname// & 'ERROR: defining variable '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'units', & - avail_hist_fields(n)%vunit) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining units for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid, 'long_name', & - avail_hist_fields(n)%vdesc) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining long_name for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'coordinates', & - avail_hist_fields(n)%vcoord) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining coordinates for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'cell_measures', & - avail_hist_fields(n)%vcellmeas) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining cell measures for '//avail_hist_fields(n)%vname) - call ice_write_hist_fill(ncid,varid,avail_hist_fields(n)%vname,history_precision) - - !----------------------------------------------------------------- - ! Add cell_methods attribute to variables if averaged - !----------------------------------------------------------------- - if (hist_avg) then - status = nf90_put_att(ncid,varid,'cell_methods','time: mean') - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining cell methods for '//avail_hist_fields(n)%vname) - endif - - if ((histfreq(ns) == '1' .and. histfreq_n(ns) == 1) & - .or..not. hist_avg) then - status = nf90_put_att(ncid,varid,'time_rep','instantaneous') - else - status = nf90_put_att(ncid,varid,'time_rep','averaged') - endif + call ice_write_hist_attrs(ncid,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_3Dc @@ -611,24 +535,7 @@ subroutine ice_write_hist (ns) lprecision, dimidz, varid) if (status /= nf90_noerr) call abort_ice(subname// & 'ERROR: defining variable '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'units', & - avail_hist_fields(n)%vunit) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining units for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid, 'long_name', & - avail_hist_fields(n)%vdesc) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining long_name for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'coordinates', & - avail_hist_fields(n)%vcoord) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining coordinates for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'cell_measures', & - avail_hist_fields(n)%vcellmeas) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining cell measures for '//avail_hist_fields(n)%vname) - call ice_write_hist_fill(ncid,varid,avail_hist_fields(n)%vname,history_precision) - + call ice_write_hist_attrs(ncid,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_3Dz @@ -643,24 +550,7 @@ subroutine ice_write_hist (ns) lprecision, dimidz, varid) if (status /= nf90_noerr) call abort_ice(subname// & 'ERROR: defining variable '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'units', & - avail_hist_fields(n)%vunit) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining units for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid, 'long_name', & - avail_hist_fields(n)%vdesc) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining long_name for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'coordinates', & - avail_hist_fields(n)%vcoord) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining coordinates for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'cell_measures', & - avail_hist_fields(n)%vcellmeas) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining cell measures for '//avail_hist_fields(n)%vname) - call ice_write_hist_fill(ncid,varid,avail_hist_fields(n)%vname,history_precision) - + call ice_write_hist_attrs(ncid,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_3Db @@ -675,24 +565,7 @@ subroutine ice_write_hist (ns) lprecision, dimidz, varid) if (status /= nf90_noerr) call abort_ice(subname// & 'ERROR: defining variable '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'units', & - avail_hist_fields(n)%vunit) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining units for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid, 'long_name', & - avail_hist_fields(n)%vdesc) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining long_name for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'coordinates', & - avail_hist_fields(n)%vcoord) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining coordinates for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'cell_measures', & - avail_hist_fields(n)%vcellmeas) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining cell measures for '//avail_hist_fields(n)%vname) - call ice_write_hist_fill(ncid,varid,avail_hist_fields(n)%vname,history_precision) - + call ice_write_hist_attrs(ncid,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_3Da @@ -707,24 +580,7 @@ subroutine ice_write_hist (ns) lprecision, dimidz, varid) if (status /= nf90_noerr) call abort_ice(subname// & 'ERROR: defining variable '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'units', & - avail_hist_fields(n)%vunit) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining units for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid, 'long_name', & - avail_hist_fields(n)%vdesc) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining long_name for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'coordinates', & - avail_hist_fields(n)%vcoord) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining coordinates for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'cell_measures', & - avail_hist_fields(n)%vcellmeas) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining cell measures for '//avail_hist_fields(n)%vname) - call ice_write_hist_fill(ncid,varid,avail_hist_fields(n)%vname,history_precision) - + call ice_write_hist_attrs(ncid,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_3Df @@ -741,39 +597,7 @@ subroutine ice_write_hist (ns) lprecision, dimidcz(1:4), varid) ! ferret if (status /= nf90_noerr) call abort_ice(subname// & 'ERROR: defining variable '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'units', & - avail_hist_fields(n)%vunit) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining units for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid, 'long_name', & - avail_hist_fields(n)%vdesc) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining long_name for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'coordinates', & - avail_hist_fields(n)%vcoord) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining coordinates for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'cell_measures', & - avail_hist_fields(n)%vcellmeas) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining cell measures for '//avail_hist_fields(n)%vname) - call ice_write_hist_fill(ncid,varid,avail_hist_fields(n)%vname,history_precision) - - !----------------------------------------------------------------- - ! Add cell_methods attribute to variables if averaged - !----------------------------------------------------------------- - if (hist_avg) then - status = nf90_put_att(ncid,varid,'cell_methods','time: mean') - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining cell methods for '//avail_hist_fields(n)%vname) - endif - - if ((histfreq(ns) == '1' .and. histfreq_n(ns) == 1) & - .or..not. hist_avg) then - status = nf90_put_att(ncid,varid,'time_rep','instantaneous') - else - status = nf90_put_att(ncid,varid,'time_rep','averaged') - endif + call ice_write_hist_attrs(ncid,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_4Di @@ -790,39 +614,7 @@ subroutine ice_write_hist (ns) lprecision, dimidcz(1:4), varid) ! ferret if (status /= nf90_noerr) call abort_ice(subname// & 'ERROR: defining variable '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'units', & - avail_hist_fields(n)%vunit) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining units for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid, 'long_name', & - avail_hist_fields(n)%vdesc) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining long_name for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'coordinates', & - avail_hist_fields(n)%vcoord) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining coordinates for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'cell_measures', & - avail_hist_fields(n)%vcellmeas) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining cell measures for '//avail_hist_fields(n)%vname) - call ice_write_hist_fill(ncid,varid,avail_hist_fields(n)%vname,history_precision) - - !----------------------------------------------------------------- - ! Add cell_methods attribute to variables if averaged - !----------------------------------------------------------------- - if (hist_avg) then - status = nf90_put_att(ncid,varid,'cell_methods','time: mean') - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining cell methods for '//avail_hist_fields(n)%vname) - endif - - if ((histfreq(ns) == '1' .and. histfreq_n(ns) == 1) & - .or..not. hist_avg) then - status = nf90_put_att(ncid,varid,'time_rep','instantaneous') - else - status = nf90_put_att(ncid,varid,'time_rep','averaged') - endif + call ice_write_hist_attrs(ncid,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_4Ds @@ -839,39 +631,7 @@ subroutine ice_write_hist (ns) lprecision, dimidcz(1:4), varid) ! ferret if (status /= nf90_noerr) call abort_ice(subname// & 'ERROR: defining variable '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'units', & - avail_hist_fields(n)%vunit) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining units for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid, 'long_name', & - avail_hist_fields(n)%vdesc) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining long_name for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'coordinates', & - avail_hist_fields(n)%vcoord) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining coordinates for '//avail_hist_fields(n)%vname) - status = nf90_put_att(ncid,varid,'cell_measures', & - avail_hist_fields(n)%vcellmeas) - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining cell measures for '//avail_hist_fields(n)%vname) - call ice_write_hist_fill(ncid,varid,avail_hist_fields(n)%vname,history_precision) - - !----------------------------------------------------------------- - ! Add cell_methods attribute to variables if averaged - !----------------------------------------------------------------- - if (hist_avg) then - status = nf90_put_att(ncid,varid,'cell_methods','time: mean') - if (status /= nf90_noerr) call abort_ice(subname// & - 'ERROR: defining cell methods for '//avail_hist_fields(n)%vname) - endif - - if ((histfreq(ns) == '1' .and. histfreq_n(ns) == 1) & - .or..not. hist_avg) then - status = nf90_put_att(ncid,varid,'time_rep','instantaneous') - else - status = nf90_put_att(ncid,varid,'time_rep','averaged') - endif + call ice_write_hist_attrs(ncid,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_4Df @@ -1448,6 +1208,94 @@ subroutine ice_write_hist (ns) end subroutine ice_write_hist +!======================================================================= + + subroutine ice_write_hist_attrs(ncid, varid, hfield, ns) + + use ice_kinds_mod + use ice_calendar, only: histfreq, histfreq_n + use ice_history_shared, only: ice_hist_field, history_precision, & + hist_avg +#ifdef USE_NETCDF + use netcdf +#endif + + integer (kind=int_kind), intent(in) :: ncid ! netcdf file id + integer (kind=int_kind), intent(in) :: varid ! netcdf variable id + type (ice_hist_field) , intent(in) :: hfield ! history file info + integer (kind=int_kind), intent(in) :: ns ! history stream + + ! local variables + + integer (kind=int_kind) :: status + character(len=*), parameter :: subname = '(ice_write_hist_attrs)' + +#ifdef USE_NETCDF + status = nf90_put_att(ncid,varid,'units', hfield%vunit) + if (status /= nf90_noerr) call abort_ice(subname// & + 'ERROR: defining units for '//hfield%vname) + + status = nf90_put_att(ncid,varid, 'long_name', hfield%vdesc) + if (status /= nf90_noerr) call abort_ice(subname// & + 'ERROR: defining long_name for '//hfield%vname) + + status = nf90_put_att(ncid,varid,'coordinates', hfield%vcoord) + if (status /= nf90_noerr) call abort_ice(subname// & + 'ERROR: defining coordinates for '//hfield%vname) + + status = nf90_put_att(ncid,varid,'cell_measures', hfield%vcellmeas) + if (status /= nf90_noerr) call abort_ice(subname// & + 'ERROR: defining cell measures for '//hfield%vname) + + if (hfield%vcomment /= "none") then + status = nf90_put_att(ncid,varid,'comment', hfield%vcomment) + if (status /= nf90_noerr) call abort_ice(subname// & + 'ERROR: defining comment for '//hfield%vname) + endif + + call ice_write_hist_fill(ncid,varid,hfield%vname,history_precision) + + ! Add cell_methods attribute to variables if averaged + if (hist_avg) then + if (TRIM(hfield%vname(1:4))/='sig1' & + .and.TRIM(hfield%vname(1:4))/='sig2' & + .and.TRIM(hfield%vname(1:9))/='sistreave' & + .and.TRIM(hfield%vname(1:9))/='sistremax' & + .and.TRIM(hfield%vname(1:4))/='sigP') then + status = nf90_put_att(ncid,varid,'cell_methods','time: mean') + if (status /= nf90_noerr) call abort_ice(subname// & + 'ERROR: defining cell methods for '//hfield%vname) + endif + endif + + if ((histfreq(ns) == '1' .and. histfreq_n(ns) == 1) & + .or..not. hist_avg & + .or.TRIM(hfield%vname(1:4))=='divu' & + .or.TRIM(hfield%vname(1:5))=='shear' & + .or.TRIM(hfield%vname(1:4))=='sig1' & + .or.TRIM(hfield%vname(1:4))=='sig2' & + .or.TRIM(hfield%vname(1:4))=='sigP' & + .or.TRIM(hfield%vname(1:5))=='trsig' & + .or.TRIM(hfield%vname(1:9))=='sistreave' & + .or.TRIM(hfield%vname(1:9))=='sistremax' & + .or.TRIM(hfield%vname(1:9))=='mlt_onset' & + .or.TRIM(hfield%vname(1:9))=='frz_onset' & + .or.TRIM(hfield%vname(1:6))=='hisnap' & + .or.TRIM(hfield%vname(1:6))=='aisnap') then + status = nf90_put_att(ncid,varid,'time_rep','instantaneous') + else + status = nf90_put_att(ncid,varid,'time_rep','averaged') + endif + if (status /= nf90_noerr) call abort_ice(subname// & + 'ERROR: defining time rep for '//hfield%vname) + +#else + call abort_ice(subname//'ERROR: USE_NETCDF cpp not defined', & + file=__FILE__, line=__LINE__) +#endif + + end subroutine ice_write_hist_attrs + !======================================================================= subroutine ice_write_hist_fill(ncid,varid,vname,precision) @@ -1467,6 +1315,7 @@ subroutine ice_write_hist_fill(ncid,varid,vname,precision) integer (kind=int_kind) :: status character(len=*), parameter :: subname = '(ice_write_hist_fill)' +#ifdef USE_NETCDF if (precision == 8) then status = nf90_put_att(ncid,varid,'missing_value',spval_dbl) else @@ -1482,6 +1331,10 @@ subroutine ice_write_hist_fill(ncid,varid,vname,precision) endif if (status /= nf90_noerr) call abort_ice(subname// & 'ERROR: defining _FillValue for '//trim(vname)) +#else + call abort_ice(subname//'ERROR: USE_NETCDF cpp not defined', & + file=__FILE__, line=__LINE__) +#endif end subroutine ice_write_hist_fill diff --git a/cicecore/cicedynB/infrastructure/io/io_pio2/ice_history_write.F90 b/cicecore/cicedynB/infrastructure/io/io_pio2/ice_history_write.F90 index 00a121a59..a6660544e 100644 --- a/cicecore/cicedynB/infrastructure/io/io_pio2/ice_history_write.F90 +++ b/cicecore/cicedynB/infrastructure/io/io_pio2/ice_history_write.F90 @@ -470,39 +470,7 @@ subroutine ice_write_hist (ns) if (avail_hist_fields(n)%vhistfreq == histfreq(ns) .or. write_ic) then status = pio_def_var(File, trim(avail_hist_fields(n)%vname), & lprecision, dimid3, varid) - status = pio_put_att(File,varid,'units', & - trim(avail_hist_fields(n)%vunit)) - status = pio_put_att(File,varid, 'long_name', & - trim(avail_hist_fields(n)%vdesc)) - status = pio_put_att(File,varid,'coordinates', & - trim(avail_hist_fields(n)%vcoord)) - status = pio_put_att(File,varid,'cell_measures', & - trim(avail_hist_fields(n)%vcellmeas)) - call ice_write_hist_fill(File,varid,avail_hist_fields(n)%vname,history_precision) - - ! Add cell_methods attribute to variables if averaged - if (hist_avg) then - if (TRIM(avail_hist_fields(n)%vname)/='sig1' & - .or.TRIM(avail_hist_fields(n)%vname)/='sig2' & - .or.TRIM(avail_hist_fields(n)%vname)/='sistreave' & - .or.TRIM(avail_hist_fields(n)%vname)/='sistremax' & - .or.TRIM(avail_hist_fields(n)%vname)/='sigP') then - status = pio_put_att(File,varid,'cell_methods','time: mean') - endif - endif - - if ((histfreq(ns) == '1' .and. histfreq_n(ns) == 1) & - .or..not. hist_avg & - .or. n==n_divu(ns) .or. n==n_shear(ns) & ! snapshots - .or. n==n_sig1(ns) .or. n==n_sig2(ns) & - .or. n==n_sigP(ns) .or. n==n_trsig(ns) & - .or. n==n_sistreave(ns) .or. n==n_sistremax(ns) & - .or. n==n_mlt_onset(ns) .or. n==n_frz_onset(ns) & - .or. n==n_hisnap(ns) .or. n==n_aisnap(ns)) then - status = pio_put_att(File,varid,'time_rep','instantaneous') - else - status = pio_put_att(File,varid,'time_rep','averaged') - endif + call ice_write_hist_attrs(File,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_2D @@ -519,27 +487,7 @@ subroutine ice_write_hist (ns) if (avail_hist_fields(n)%vhistfreq == histfreq(ns) .or. write_ic) then status = pio_def_var(File, trim(avail_hist_fields(n)%vname), & lprecision, dimidz, varid) - status = pio_put_att(File,varid,'units', & - trim(avail_hist_fields(n)%vunit)) - status = pio_put_att(File,varid, 'long_name', & - trim(avail_hist_fields(n)%vdesc)) - status = pio_put_att(File,varid,'coordinates', & - trim(avail_hist_fields(n)%vcoord)) - status = pio_put_att(File,varid,'cell_measures', & - trim(avail_hist_fields(n)%vcellmeas)) - call ice_write_hist_fill(File,varid,avail_hist_fields(n)%vname,history_precision) - - ! Add cell_methods attribute to variables if averaged - if (hist_avg) then - status = pio_put_att(File,varid,'cell_methods','time: mean') - endif - - if ((histfreq(ns) == '1' .and. histfreq_n(ns) == 1) & - .or..not. hist_avg) then - status = pio_put_att(File,varid,'time_rep','instantaneous') - else - status = pio_put_att(File,varid,'time_rep','averaged') - endif + call ice_write_hist_attrs(File,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_3Dc @@ -556,27 +504,7 @@ subroutine ice_write_hist (ns) if (avail_hist_fields(n)%vhistfreq == histfreq(ns) .or. write_ic) then status = pio_def_var(File, trim(avail_hist_fields(n)%vname), & lprecision, dimidz, varid) - status = pio_put_att(File,varid,'units', & - trim(avail_hist_fields(n)%vunit)) - status = pio_put_att(File,varid, 'long_name', & - trim(avail_hist_fields(n)%vdesc)) - status = pio_put_att(File,varid,'coordinates', & - trim(avail_hist_fields(n)%vcoord)) - status = pio_put_att(File,varid,'cell_measures', & - trim(avail_hist_fields(n)%vcellmeas)) - call ice_write_hist_fill(File,varid,avail_hist_fields(n)%vname,history_precision) - - ! Add cell_methods attribute to variables if averaged - if (hist_avg) then - status = pio_put_att(File,varid,'cell_methods','time: mean') - endif - - if ((histfreq(ns) == '1' .and. histfreq_n(ns) == 1) & - .or..not. hist_avg) then - status = pio_put_att(File,varid,'time_rep','instantaneous') - else - status = pio_put_att(File,varid,'time_rep','averaged') - endif + call ice_write_hist_attrs(File,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_3Dz @@ -593,27 +521,7 @@ subroutine ice_write_hist (ns) if (avail_hist_fields(n)%vhistfreq == histfreq(ns) .or. write_ic) then status = pio_def_var(File, trim(avail_hist_fields(n)%vname), & lprecision, dimidz, varid) - status = pio_put_att(File,varid,'units', & - trim(avail_hist_fields(n)%vunit)) - status = pio_put_att(File,varid, 'long_name', & - trim(avail_hist_fields(n)%vdesc)) - status = pio_put_att(File,varid,'coordinates', & - trim(avail_hist_fields(n)%vcoord)) - status = pio_put_att(File,varid,'cell_measures', & - trim(avail_hist_fields(n)%vcellmeas)) - call ice_write_hist_fill(File,varid,avail_hist_fields(n)%vname,history_precision) - - ! Add cell_methods attribute to variables if averaged - if (hist_avg) then - status = pio_put_att(File,varid,'cell_methods','time: mean') - endif - - if ((histfreq(ns) == '1' .and. histfreq_n(ns) == 1) & - .or..not. hist_avg) then - status = pio_put_att(File,varid,'time_rep','instantaneous') - else - status = pio_put_att(File,varid,'time_rep','averaged') - endif + call ice_write_hist_attrs(File,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_3Db @@ -630,27 +538,7 @@ subroutine ice_write_hist (ns) if (avail_hist_fields(n)%vhistfreq == histfreq(ns) .or. write_ic) then status = pio_def_var(File, trim(avail_hist_fields(n)%vname), & lprecision, dimidz, varid) - status = pio_put_att(File,varid,'units', & - trim(avail_hist_fields(n)%vunit)) - status = pio_put_att(File,varid, 'long_name', & - trim(avail_hist_fields(n)%vdesc)) - status = pio_put_att(File,varid,'coordinates', & - trim(avail_hist_fields(n)%vcoord)) - status = pio_put_att(File,varid,'cell_measures', & - trim(avail_hist_fields(n)%vcellmeas)) - call ice_write_hist_fill(File,varid,avail_hist_fields(n)%vname,history_precision) - - ! Add cell_methods attribute to variables if averaged - if (hist_avg) then - status = pio_put_att(File,varid,'cell_methods','time: mean') - endif - - if ((histfreq(ns) == '1' .and. histfreq_n(ns) == 1) & - .or..not. hist_avg) then - status = pio_put_att(File,varid,'time_rep','instantaneous') - else - status = pio_put_att(File,varid,'time_rep','averaged') - endif + call ice_write_hist_attrs(File,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_3Da @@ -667,27 +555,7 @@ subroutine ice_write_hist (ns) if (avail_hist_fields(n)%vhistfreq == histfreq(ns) .or. write_ic) then status = pio_def_var(File, trim(avail_hist_fields(n)%vname), & lprecision, dimidz, varid) - status = pio_put_att(File,varid,'units', & - trim(avail_hist_fields(n)%vunit)) - status = pio_put_att(File,varid, 'long_name', & - trim(avail_hist_fields(n)%vdesc)) - status = pio_put_att(File,varid,'coordinates', & - trim(avail_hist_fields(n)%vcoord)) - status = pio_put_att(File,varid,'cell_measures', & - trim(avail_hist_fields(n)%vcellmeas)) - call ice_write_hist_fill(File,varid,avail_hist_fields(n)%vname,history_precision) - - ! Add cell_methods attribute to variables if averaged - if (hist_avg) then - status = pio_put_att(File,varid,'cell_methods','time: mean') - endif - - if ((histfreq(ns) == '1' .and. histfreq_n(ns) == 1) & - .or..not. hist_avg) then - status = pio_put_att(File,varid,'time_rep','instantaneous') - else - status = pio_put_att(File,varid,'time_rep','averaged') - endif + call ice_write_hist_attrs(File,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_3Df @@ -710,27 +578,7 @@ subroutine ice_write_hist (ns) if (avail_hist_fields(n)%vhistfreq == histfreq(ns) .or. write_ic) then status = pio_def_var(File, trim(avail_hist_fields(n)%vname), & lprecision, dimidcz, varid) - status = pio_put_att(File,varid,'units', & - trim(avail_hist_fields(n)%vunit)) - status = pio_put_att(File,varid, 'long_name', & - trim(avail_hist_fields(n)%vdesc)) - status = pio_put_att(File,varid,'coordinates', & - trim(avail_hist_fields(n)%vcoord)) - status = pio_put_att(File,varid,'cell_measures', & - trim(avail_hist_fields(n)%vcellmeas)) - call ice_write_hist_fill(File,varid,avail_hist_fields(n)%vname,history_precision) - - ! Add cell_methods attribute to variables if averaged - if (hist_avg) then - status = pio_put_att(File,varid,'cell_methods','time: mean') - endif - - if ((histfreq(ns) == '1' .and. histfreq_n(ns) == 1) & - .or..not. hist_avg) then - status = pio_put_att(File,varid,'time_rep','instantaneous') - else - status = pio_put_att(File,varid,'time_rep','averaged') - endif + call ice_write_hist_attrs(File,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_4Di @@ -748,27 +596,7 @@ subroutine ice_write_hist (ns) if (avail_hist_fields(n)%vhistfreq == histfreq(ns) .or. write_ic) then status = pio_def_var(File, trim(avail_hist_fields(n)%vname), & lprecision, dimidcz, varid) - status = pio_put_att(File,varid,'units', & - trim(avail_hist_fields(n)%vunit)) - status = pio_put_att(File,varid, 'long_name', & - trim(avail_hist_fields(n)%vdesc)) - status = pio_put_att(File,varid,'coordinates', & - trim(avail_hist_fields(n)%vcoord)) - status = pio_put_att(File,varid,'cell_measures', & - trim(avail_hist_fields(n)%vcellmeas)) - call ice_write_hist_fill(File,varid,avail_hist_fields(n)%vname,history_precision) - - ! Add cell_methods attribute to variables if averaged - if (hist_avg) then - status = pio_put_att(File,varid,'cell_methods','time: mean') - endif - - if ((histfreq(ns) == '1' .and. histfreq_n(ns) == 1) & - .or..not. hist_avg) then - status = pio_put_att(File,varid,'time_rep','instantaneous') - else - status = pio_put_att(File,varid,'time_rep','averaged') - endif + call ice_write_hist_attrs(File,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_4Ds @@ -787,27 +615,7 @@ subroutine ice_write_hist (ns) if (avail_hist_fields(n)%vhistfreq == histfreq(ns) .or. write_ic) then status = pio_def_var(File, trim(avail_hist_fields(n)%vname), & lprecision, dimidcz, varid) - status = pio_put_att(File,varid,'units', & - trim(avail_hist_fields(n)%vunit)) - status = pio_put_att(File,varid, 'long_name', & - trim(avail_hist_fields(n)%vdesc)) - status = pio_put_att(File,varid,'coordinates', & - trim(avail_hist_fields(n)%vcoord)) - status = pio_put_att(File,varid,'cell_measures', & - trim(avail_hist_fields(n)%vcellmeas)) - call ice_write_hist_fill(File,varid,avail_hist_fields(n)%vname,history_precision) - - ! Add cell_methods attribute to variables if averaged - if (hist_avg) then - status = pio_put_att(File,varid,'cell_methods','time: mean') - endif - - if ((histfreq(ns) == '1' .and. histfreq_n(ns) == 1) & - .or..not. hist_avg) then - status = pio_put_att(File,varid,'time_rep','instantaneous') - else - status = pio_put_att(File,varid,'time_rep','averaged') - endif + call ice_write_hist_attrs(File,varid,avail_hist_fields(n),ns) endif enddo ! num_avail_hist_fields_4Df @@ -1388,6 +1196,73 @@ subroutine ice_write_hist (ns) end subroutine ice_write_hist +!======================================================================= + + subroutine ice_write_hist_attrs(File, varid, hfield, ns) + + use ice_kinds_mod + use ice_calendar, only: histfreq, histfreq_n + use ice_history_shared, only: ice_hist_field, history_precision, & + hist_avg + use ice_pio + use pio + + type(file_desc_t) :: File ! file id + type(var_desc_t) :: varid ! variable id + type (ice_hist_field), intent(in) :: hfield ! history file info + integer (kind=int_kind), intent(in) :: ns + + ! local variables + + integer (kind=int_kind) :: status + character(len=*), parameter :: subname = '(ice_write_hist_attrs)' + + status = pio_put_att(File,varid,'units', trim(hfield%vunit)) + + status = pio_put_att(File,varid, 'long_name', trim(hfield%vdesc)) + + status = pio_put_att(File,varid,'coordinates', trim(hfield%vcoord)) + + status = pio_put_att(File,varid,'cell_measures', trim(hfield%vcellmeas)) + + if (hfield%vcomment /= "none") then + status = pio_put_att(File,varid,'comment', trim(hfield%vcomment)) + endif + + call ice_write_hist_fill(File,varid,hfield%vname,history_precision) + + ! Add cell_methods attribute to variables if averaged + if (hist_avg) then + if (TRIM(hfield%vname(1:4))/='sig1' & + .and.TRIM(hfield%vname(1:4))/='sig2' & + .and.TRIM(hfield%vname(1:9))/='sistreave' & + .and.TRIM(hfield%vname(1:9))/='sistremax' & + .and.TRIM(hfield%vname(1:4))/='sigP') then + status = pio_put_att(File,varid,'cell_methods','time: mean') + endif + endif + + if ((histfreq(ns) == '1' .and. histfreq_n(ns) == 1) & + .or..not. hist_avg & + .or.TRIM(hfield%vname(1:4))=='divu' & + .or.TRIM(hfield%vname(1:5))=='shear' & + .or.TRIM(hfield%vname(1:4))=='sig1' & + .or.TRIM(hfield%vname(1:4))=='sig2' & + .or.TRIM(hfield%vname(1:4))=='sigP' & + .or.TRIM(hfield%vname(1:5))=='trsig' & + .or.TRIM(hfield%vname(1:9))=='sistreave' & + .or.TRIM(hfield%vname(1:9))=='sistremax' & + .or.TRIM(hfield%vname(1:9))=='mlt_onset' & + .or.TRIM(hfield%vname(1:9))=='frz_onset' & + .or.TRIM(hfield%vname(1:6))=='hisnap' & + .or.TRIM(hfield%vname(1:6))=='aisnap') then + status = pio_put_att(File,varid,'time_rep','instantaneous') + else + status = pio_put_att(File,varid,'time_rep','averaged') + endif + + end subroutine ice_write_hist_attrs + !======================================================================= subroutine ice_write_hist_fill(File,varid,vname,precision) From e0914ccdd08675b635222b5de5a2ca39e5f8764c Mon Sep 17 00:00:00 2001 From: apcraig Date: Wed, 10 Nov 2021 17:04:55 -0700 Subject: [PATCH 17/17] switch to six velocity variables (uvel, vvel, uvele, vvele, uveln, vveln) --- cicecore/cicedynB/analysis/ice_history.F90 | 30 +++++++++---------- .../cicedynB/analysis/ice_history_shared.F90 | 9 ++++-- cicecore/cicedynB/dynamics/ice_dyn_shared.F90 | 6 ++-- cicecore/cicedynB/general/ice_state.F90 | 20 ++++++++----- 4 files changed, 37 insertions(+), 28 deletions(-) diff --git a/cicecore/cicedynB/analysis/ice_history.F90 b/cicecore/cicedynB/analysis/ice_history.F90 index aa2a05cd8..ef7d96e6a 100644 --- a/cicecore/cicedynB/analysis/ice_history.F90 +++ b/cicecore/cicedynB/analysis/ice_history.F90 @@ -279,8 +279,10 @@ subroutine init_hist (dt) endif if (grid_system == 'CD') then - f_uveln = f_uvel + f_uvele = f_uvel f_vvele = f_vvel + f_uveln = f_uvel + f_vveln = f_vvel endif #ifndef ncdf @@ -333,8 +335,10 @@ subroutine init_hist (dt) call broadcast_scalar (f_aice, master_task) call broadcast_scalar (f_uvel, master_task) call broadcast_scalar (f_vvel, master_task) + call broadcast_scalar (f_uvele, master_task) call broadcast_scalar (f_uveln, master_task) call broadcast_scalar (f_vvele, master_task) + call broadcast_scalar (f_vveln, master_task) call broadcast_scalar (f_uatm, master_task) call broadcast_scalar (f_vatm, master_task) call broadcast_scalar (f_atmspd, master_task) @@ -562,12 +566,19 @@ subroutine init_hist (dt) ns1, f_aice) if (grid_system == 'CD') then - call define_hist_field(n_uvel,"uvel","m/s",estr2D, ecstr, & + call define_hist_field(n_uvele,"uvele","m/s",estr2D, ecstr, & "ice velocity (x)", & "positive is x direction on E grid", c1, c0, & ns1, f_uvel) - - call define_hist_field(n_vvel,"vvel","m/s",nstr2D, ncstr, & + call define_hist_field(n_vvele,"vvele","m/s",estr2D, ecstr, & + "ice velocity (y)", & + "positive is y direction on E grid", c1, c0, & + ns1, f_uvel) + call define_hist_field(n_uveln,"uveln","m/s",nstr2D, ncstr, & + "ice velocity (x)", & + "positive is x direction on N grid", c1, c0, & + ns1, f_vvel) + call define_hist_field(n_vveln,"vveln","m/s",nstr2D, ncstr, & "ice velocity (y)", & "positive is y direction on N grid", c1, c0, & ns1, f_vvel) @@ -576,23 +587,12 @@ subroutine init_hist (dt) "ice velocity (x)", & "positive is x direction on U grid", c1, c0, & ns1, f_uvel) - call define_hist_field(n_vvel,"vvel","m/s",ustr2D, ucstr, & "ice velocity (y)", & "positive is y direction on U grid", c1, c0, & ns1, f_vvel) endif - call define_hist_field(n_uveln,"uveln","m/s",nstr2D, ncstr, & - "ice velocity (x)", & - "positive is x direction on N grid", c1, c0, & - ns1, f_uveln) - - call define_hist_field(n_vvele,"vvele","m/s",estr2D, ecstr, & - "ice velocity (y)", & - "positive is y direction on E grid", c1, c0, & - ns1, f_vvele) - call define_hist_field(n_uatm,"uatm","m/s",ustr2D, ucstr, & "atm velocity (x)", & "positive is x direction on U grid", c1, c0, & diff --git a/cicecore/cicedynB/analysis/ice_history_shared.F90 b/cicecore/cicedynB/analysis/ice_history_shared.F90 index fc4b68ae3..74e97d489 100644 --- a/cicecore/cicedynB/analysis/ice_history_shared.F90 +++ b/cicecore/cicedynB/analysis/ice_history_shared.F90 @@ -235,7 +235,8 @@ module ice_history_shared f_snowfrac = 'x', f_snowfracn = 'x', & f_Tsfc = 'm', f_aice = 'm', & f_uvel = 'm', f_vvel = 'm', & - f_uveln = 'x', f_vvele = 'x', & + f_uvele = 'x', f_vvele = 'x', & + f_uveln = 'x', f_vveln = 'x', & f_uatm = 'm', f_vatm = 'm', & f_atmspd = 'm', f_atmdir = 'm', & f_fswup = 'm', & @@ -385,7 +386,8 @@ module ice_history_shared f_snowfrac, f_snowfracn, & f_Tsfc, f_aice , & f_uvel, f_vvel , & -! f_uveln, f_vvele , & ! for now, have this set from f_uvel, f_vvel +! f_uvele, f_vvele , & ! for now, have this set from f_uvel, f_vvel +! f_uveln, f_vveln , & ! for now, have this set from f_uvel, f_vvel f_uatm, f_vatm , & f_atmspd, f_atmdir , & f_fswup, & @@ -559,7 +561,8 @@ module ice_history_shared n_snowfrac , n_snowfracn , & n_Tsfc , n_aice , & n_uvel , n_vvel , & - n_uveln , n_vvele , & + n_uvele , n_vvele , & + n_uveln , n_vveln , & n_uatm , n_vatm , & n_atmspd , n_atmdir , & n_sice , & diff --git a/cicecore/cicedynB/dynamics/ice_dyn_shared.F90 b/cicecore/cicedynB/dynamics/ice_dyn_shared.F90 index 0cd7f70a5..a5ac8a4d9 100755 --- a/cicecore/cicedynB/dynamics/ice_dyn_shared.F90 +++ b/cicecore/cicedynB/dynamics/ice_dyn_shared.F90 @@ -131,7 +131,7 @@ subroutine init_dyn (dt) stressp_1, stressp_2, stressp_3, stressp_4, & stressm_1, stressm_2, stressm_3, stressm_4, & stress12_1, stress12_2, stress12_3, stress12_4 - use ice_state, only: uvel, vvel, uveln, vvele, divu, shear + use ice_state, only: uvel, vvel, uvele, vvele, uveln, vveln, divu, shear use ice_grid, only: ULAT real (kind=dbl_kind), intent(in) :: & @@ -164,8 +164,10 @@ subroutine init_dyn (dt) uvel(i,j,iblk) = c0 ! m/s vvel(i,j,iblk) = c0 ! m/s if (grid_system == 'CD') then ! extra velocity variables - uveln = c0 + uvele = c0 vvele = c0 + uveln = c0 + vveln = c0 endif ! strain rates diff --git a/cicecore/cicedynB/general/ice_state.F90 b/cicecore/cicedynB/general/ice_state.F90 index 514d30b9a..7f93f0392 100644 --- a/cicecore/cicedynB/general/ice_state.F90 +++ b/cicecore/cicedynB/general/ice_state.F90 @@ -107,10 +107,12 @@ module ice_state real (kind=dbl_kind), dimension(:,:,:), allocatable, & public :: & - uvel , & ! x-component of velocity (m/s) - uveln , & ! extra x-component of velocity on CD grid (m/s) - vvel , & ! y-component of velocity (m/s) - vvele , & ! extra y-component of velocity on CD grid (m/s) + uvel , & ! x-component of velocity on U grid (m/s) + vvel , & ! y-component of velocity on U grid (m/s) + uvele , & ! x-component of velocity on E grid (m/s) + vvele , & ! y-component of velocity on E grid (m/s) + uveln , & ! x-component of velocity on N grid (m/s) + vveln , & ! y-component of velocity on N grid (m/s) divu , & ! strain rate I component, velocity divergence (1/s) shear , & ! strain rate II component (1/s) strength ! ice strength (N/m) @@ -151,10 +153,12 @@ subroutine alloc_state vice (nx_block,ny_block,max_blocks) , & ! volume per unit area of ice (m) vsno (nx_block,ny_block,max_blocks) , & ! volume per unit area of snow (m) aice0 (nx_block,ny_block,max_blocks) , & ! concentration of open water - uvel (nx_block,ny_block,max_blocks) , & ! x-component of velocity (m/s) - uveln (nx_block,ny_block,max_blocks) , & ! extra x-component of velocity on CD grid (m/s) - vvel (nx_block,ny_block,max_blocks) , & ! y-component of velocity (m/s) - vvele (nx_block,ny_block,max_blocks) , & ! extra y-component of velocity on CD grid (m/s) + uvel (nx_block,ny_block,max_blocks) , & ! x-component of velocity on U grid (m/s) + vvel (nx_block,ny_block,max_blocks) , & ! y-component of velocity on U grid (m/s) + uvele (nx_block,ny_block,max_blocks) , & ! x-component of velocity on E grid (m/s) + vvele (nx_block,ny_block,max_blocks) , & ! y-component of velocity on E grid (m/s) + uveln (nx_block,ny_block,max_blocks) , & ! x-component of velocity on N grid (m/s) + vveln (nx_block,ny_block,max_blocks) , & ! y-component of velocity on N grid (m/s) divu (nx_block,ny_block,max_blocks) , & ! strain rate I component, velocity divergence (1/s) shear (nx_block,ny_block,max_blocks) , & ! strain rate II component (1/s) strength (nx_block,ny_block,max_blocks) , & ! ice strength (N/m)