From 6bb6800e89d1dfd50c8d03253504915270ae5606 Mon Sep 17 00:00:00 2001 From: jswhit2 Date: Thu, 17 Oct 2019 16:23:09 +0000 Subject: [PATCH 1/3] fix for time units attribute when IAU used with netcdf format --- io/module_write_netcdf.F90 | 73 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/io/module_write_netcdf.F90 b/io/module_write_netcdf.F90 index 1fce3d8b9..c1e46f174 100644 --- a/io/module_write_netcdf.F90 +++ b/io/module_write_netcdf.F90 @@ -12,7 +12,7 @@ module module_write_netcdf use esmf use netcdf - use module_fv3_io_def,only : ideflate, nbits, & + use module_fv3_io_def,only : ideflate, nbits, iau_offset, & output_grid,dx,dy,lon1,lat1,lon2,lat2 implicit none @@ -60,8 +60,6 @@ subroutine write_netcdf(fieldbundle, wrtfb, filename, mpi_comm, mype, im, jm, rc real(8) :: varr8val character(len=ESMF_MAXSTR) :: varcval - character(128) :: time_units - integer :: ncerr integer :: ncid integer :: oldMode @@ -520,6 +518,10 @@ subroutine add_dim(ncid, dim_name, dimid, grid, rc) real(ESMF_KIND_R4), allocatable :: valueListR4(:) real(ESMF_KIND_R8), allocatable :: valueListR8(:) character(len=ESMF_MAXSTR), allocatable :: valueListC(:) + character(nf90_max_name) :: time_units + integer idate(6) + real(8) rinc(5) + integer idat(8),jdat(8) ! call ESMF_AttributeGet(grid, convention="NetCDF", purpose="FV3", & attnestflag=ESMF_ATTNEST_OFF, name=dim_name, & @@ -555,8 +557,73 @@ subroutine add_dim(ncid, dim_name, dimid, grid, rc) end if call get_grid_attr(grid, dim_name, ncid, dim_varid, rc) + + ! if iau_offset set, update time units attribute. + if ( trim(dim_name) == "time" .and. iau_offset > 0) then +! get time units just written to file + ncerr = nf90_get_att(ncid, dim_varid, 'units', time_units); NC_ERR_STOP(ncerr) +! idate: year,month,day,hour,minute,second + idate = get_idate_from_time_units(time_units) +! idat: year,month,day,time zone,hour,minute,second,millsecond + idat = 0 + idat(1:3) = idate(1:3) + idat(5:7) = idate(4:6) +! rinc: days,hours,minutes,seconds,milliseconds + rinc = 0; rinc(2) = iau_offset + call w3movdat(rinc,idat,jdat) +! update idate using iau_offset + idate(1:3)=jdat(1:3) + idate(4:6)=jdat(5:7) + time_units = get_time_units_from_idate(idate) +! rewrite time units attribute. + ncerr = nf90_put_att(ncid, dim_varid, 'units', trim(time_units)); NC_ERR_STOP(ncerr) + endif end subroutine add_dim + + function get_idate_from_time_units(time_units) result(idate) + ! return integer array with year,month,day,hour,minute,second + ! parsed from time units attribute. + integer idate(6) + character(len=nf90_max_name), intent(in) :: time_units + integer ipos1,ipos2 + ipos1 = scan(time_units,"since",back=.true.)+1 + ipos2 = scan(time_units,"-",back=.false.)-1 + read(time_units(ipos1:ipos2),*) idate(1) + ipos1 = ipos2+2; ipos2=ipos1+1 + read(time_units(ipos1:ipos2),*) idate(2) + ipos1 = ipos2+2; ipos2=ipos1+1 + read(time_units(ipos1:ipos2),*) idate(3) + ipos1 = scan(time_units,":")-2 + ipos2 = ipos1+1 + read(time_units(ipos1:ipos2),*) idate(4) + ipos1 = ipos2+2 + ipos2 = ipos1+1 + read(time_units(ipos1:ipos2),*) idate(5) + ipos1 = ipos2+2 + ipos2 = ipos1+1 + read(time_units(ipos1:ipos2),*) idate(6) + end function get_idate_from_time_units + + function get_time_units_from_idate(idate, time_measure) result(time_units) + ! create time units attribute of form 'hours since YYYY-MM-DD HH:MM:SS' + ! from integer array with year,month,day,hour,minute,second + ! optional argument 'time_measure' can be used to change 'hours' to + ! 'days', 'minutes', 'seconds' etc. + character(len=*), intent(in), optional :: time_measure + integer, intent(in) :: idate(6) + character(len=12) :: timechar + character(len=nf90_max_name) :: time_units + if (present(time_measure)) then + timechar = trim(time_measure) + else + timechar = 'hours' + endif + write(time_units,101) idate +101 format(' since ',i4.4,'-',i2.2,'-',i2.2,' ',& + i2.2,':',i2.2,':',i2.2) + time_units = trim(adjustl(timechar))//time_units + end function get_time_units_from_idate ! !---------------------------------------------------------------------------------------- subroutine nccheck(status) From b05be211f592c042df06ca92c89e7445e1c699ce Mon Sep 17 00:00:00 2001 From: jswhit2 Date: Fri, 1 Nov 2019 19:22:44 +0000 Subject: [PATCH 2/3] modify time units in module_fcst_grid_comp instead of module_write_netcdf --- io/module_write_netcdf.F90 | 66 +------------------------------------- module_fcst_grid_comp.F90 | 36 +++++++++++++++------ 2 files changed, 28 insertions(+), 74 deletions(-) diff --git a/io/module_write_netcdf.F90 b/io/module_write_netcdf.F90 index c1e46f174..38966d31d 100644 --- a/io/module_write_netcdf.F90 +++ b/io/module_write_netcdf.F90 @@ -12,7 +12,7 @@ module module_write_netcdf use esmf use netcdf - use module_fv3_io_def,only : ideflate, nbits, iau_offset, & + use module_fv3_io_def,only : ideflate, nbits, & output_grid,dx,dy,lon1,lat1,lon2,lat2 implicit none @@ -558,72 +558,8 @@ subroutine add_dim(ncid, dim_name, dimid, grid, rc) call get_grid_attr(grid, dim_name, ncid, dim_varid, rc) - ! if iau_offset set, update time units attribute. - if ( trim(dim_name) == "time" .and. iau_offset > 0) then -! get time units just written to file - ncerr = nf90_get_att(ncid, dim_varid, 'units', time_units); NC_ERR_STOP(ncerr) -! idate: year,month,day,hour,minute,second - idate = get_idate_from_time_units(time_units) -! idat: year,month,day,time zone,hour,minute,second,millsecond - idat = 0 - idat(1:3) = idate(1:3) - idat(5:7) = idate(4:6) -! rinc: days,hours,minutes,seconds,milliseconds - rinc = 0; rinc(2) = iau_offset - call w3movdat(rinc,idat,jdat) -! update idate using iau_offset - idate(1:3)=jdat(1:3) - idate(4:6)=jdat(5:7) - time_units = get_time_units_from_idate(idate) -! rewrite time units attribute. - ncerr = nf90_put_att(ncid, dim_varid, 'units', trim(time_units)); NC_ERR_STOP(ncerr) - endif - end subroutine add_dim - function get_idate_from_time_units(time_units) result(idate) - ! return integer array with year,month,day,hour,minute,second - ! parsed from time units attribute. - integer idate(6) - character(len=nf90_max_name), intent(in) :: time_units - integer ipos1,ipos2 - ipos1 = scan(time_units,"since",back=.true.)+1 - ipos2 = scan(time_units,"-",back=.false.)-1 - read(time_units(ipos1:ipos2),*) idate(1) - ipos1 = ipos2+2; ipos2=ipos1+1 - read(time_units(ipos1:ipos2),*) idate(2) - ipos1 = ipos2+2; ipos2=ipos1+1 - read(time_units(ipos1:ipos2),*) idate(3) - ipos1 = scan(time_units,":")-2 - ipos2 = ipos1+1 - read(time_units(ipos1:ipos2),*) idate(4) - ipos1 = ipos2+2 - ipos2 = ipos1+1 - read(time_units(ipos1:ipos2),*) idate(5) - ipos1 = ipos2+2 - ipos2 = ipos1+1 - read(time_units(ipos1:ipos2),*) idate(6) - end function get_idate_from_time_units - - function get_time_units_from_idate(idate, time_measure) result(time_units) - ! create time units attribute of form 'hours since YYYY-MM-DD HH:MM:SS' - ! from integer array with year,month,day,hour,minute,second - ! optional argument 'time_measure' can be used to change 'hours' to - ! 'days', 'minutes', 'seconds' etc. - character(len=*), intent(in), optional :: time_measure - integer, intent(in) :: idate(6) - character(len=12) :: timechar - character(len=nf90_max_name) :: time_units - if (present(time_measure)) then - timechar = trim(time_measure) - else - timechar = 'hours' - endif - write(time_units,101) idate -101 format(' since ',i4.4,'-',i2.2,'-',i2.2,' ',& - i2.2,':',i2.2,':',i2.2) - time_units = trim(adjustl(timechar))//time_units - end function get_time_units_from_idate ! !---------------------------------------------------------------------------------------- subroutine nccheck(status) diff --git a/module_fcst_grid_comp.F90 b/module_fcst_grid_comp.F90 index 6ff1f39c7..2d767ca01 100644 --- a/module_fcst_grid_comp.F90 +++ b/module_fcst_grid_comp.F90 @@ -103,7 +103,7 @@ module module_fcst_grid_comp !----- coupled model data ----- - integer :: date_init(6) + integer :: date_init(6), date_init2(6) integer :: numLevels = 0 integer :: numSoilLayers = 0 integer :: numTracers = 0 @@ -210,6 +210,8 @@ subroutine fcst_initialize(fcst_comp, importState, exportState, clock, rc) integer :: globalTileLayout(2) integer :: nestRootPet, peListSize(1) integer, allocatable :: petMap(:) + real(8) rinc(5) + integer idat(8),jdat(8) ! !----------------------------------------------------------------------- !*********************************************************************** @@ -536,20 +538,36 @@ subroutine fcst_initialize(fcst_comp, importState, exportState, clock, rc) name="time", value=real(0,ESMF_KIND_R8), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - write(dateSY,'(I4.4)')date_init(1) - write(dateSM,'(I2.2)')date_init(2) - write(dateSD,'(I2.2)')date_init(3) - write(dateSH,'(I2.2)')date_init(4) - write(dateSN,'(I2.2)')date_init(5) - write(dateSS,'(I2.2)')date_init(6) +! update date_init with iau_offset + date_init2 = date_init + if (atm_int_state%Atm%iau_offset > 0) then +! date_init: year,month,day,hour,minute,second +! idat: year,month,day,time zone,hour,minute,second,millsecond + idat = 0 + idat(1:3) = date_init2(1:3) + idat(5:7) = date_init2(4:6) +! rinc: days,hours,minutes,seconds,milliseconds + rinc = 0; rinc(2) = iau_offset + call w3movdat(rinc,idat,jdat) +! update date_init using iau_offset + date_init2(1:3)=jdat(1:3) + date_init2(4:6)=jdat(5:7) + endif + +! time:units attribute uses date_init modified by iau_offset + write(dateSY,'(I4.4)')date_init2(1) + write(dateSM,'(I2.2)')date_init2(2) + write(dateSD,'(I2.2)')date_init2(3) + write(dateSH,'(I2.2)')date_init2(4) + write(dateSN,'(I2.2)')date_init2(5) + write(dateSS,'(I2.2)')date_init2(6) dateS="hours since "//dateSY//'-'//dateSM//'-'//dateSD//' '//dateSH//':'// & dateSN//":"//dateSS - if (mype == 0) write(0,*)'dateS=',trim(dateS),'date_init=',date_init + if (mype == 0) write(0,*)'dateS=',trim(dateS),'date_init=',date_init2 call ESMF_AttributeSet(exportState, convention="NetCDF", purpose="FV3", & name="time:units", value=trim(dateS), rc=rc) -! name="time:units", value="hours since 2016-10-03 00:00:00", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call ESMF_AttributeSet(exportState, convention="NetCDF", purpose="FV3", & From 623dc0cb71fb6f503d460a1358daf3e729c9e00e Mon Sep 17 00:00:00 2001 From: jswhit2 Date: Fri, 1 Nov 2019 19:25:32 +0000 Subject: [PATCH 3/3] remove unused vars --- io/module_write_netcdf.F90 | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/io/module_write_netcdf.F90 b/io/module_write_netcdf.F90 index 38966d31d..1fc3744a2 100644 --- a/io/module_write_netcdf.F90 +++ b/io/module_write_netcdf.F90 @@ -518,10 +518,6 @@ subroutine add_dim(ncid, dim_name, dimid, grid, rc) real(ESMF_KIND_R4), allocatable :: valueListR4(:) real(ESMF_KIND_R8), allocatable :: valueListR8(:) character(len=ESMF_MAXSTR), allocatable :: valueListC(:) - character(nf90_max_name) :: time_units - integer idate(6) - real(8) rinc(5) - integer idat(8),jdat(8) ! call ESMF_AttributeGet(grid, convention="NetCDF", purpose="FV3", & attnestflag=ESMF_ATTNEST_OFF, name=dim_name, & @@ -557,9 +553,8 @@ subroutine add_dim(ncid, dim_name, dimid, grid, rc) end if call get_grid_attr(grid, dim_name, ncid, dim_varid, rc) - - end subroutine add_dim + end subroutine add_dim ! !---------------------------------------------------------------------------------------- subroutine nccheck(status)