Skip to content

Commit

Permalink
Add 'valid time' variable using ISO string format (#492)
Browse files Browse the repository at this point in the history
Add 'valid time' variable using ISO string format to netcdf history files.
Use double precision variable to set value of 'time' attribute in wrt comp import state
Update ccpp/physics (setting surface-related interstitial variables for SCM prescribed-surface-flux mode)
Update inline_post_stub.F90 subroutine interfaces to match inline_post.F90

Co-authored-by: Ted Mansell <ted.mansell@noaa.gov>
Co-authored-by: Grant Firl <grant.firl@noaa.gov>
  • Loading branch information
3 people authored Mar 17, 2022
1 parent b2272de commit 8c582f7
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 73 deletions.
2 changes: 1 addition & 1 deletion ccpp/physics
6 changes: 4 additions & 2 deletions io/inline_post_stub.F90
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module inline_post

contains

subroutine inline_post_run(wrt_int_state,mypei,mpicomp,lead_write, &
subroutine inline_post_run(wrt_int_state,grid_id,mypei,mpicomp,lead_write, &
mynfhr,mynfmin,mynfsec)
!
! revision history:
Expand All @@ -28,6 +28,7 @@ subroutine inline_post_run(wrt_int_state,mypei,mpicomp,lead_write, &
!
type(wrt_internal_state),intent(in) :: wrt_int_state
integer,intent(in) :: mypei
integer,intent(in) :: grid_id
integer,intent(in) :: mpicomp
integer,intent(in) :: lead_write
integer,intent(in) :: mynfhr
Expand All @@ -40,11 +41,12 @@ end subroutine inline_post_run
!
!-----------------------------------------------------------------------
!
subroutine inline_post_getattr(wrt_int_state)
subroutine inline_post_getattr(wrt_int_state,grid_id)
!
implicit none
!
type(wrt_internal_state),intent(inout) :: wrt_int_state
integer,intent(in) :: grid_id
!
!
print *,'in stub inline_post_getattr - not supported on this machine, return'
Expand Down
3 changes: 0 additions & 3 deletions io/module_write_internal_state.F90
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ module write_internal_state
!-------------------------------------
!
type(ESMF_Time) :: io_basetime
type(ESMF_TimeInterval) :: io_currtimediff
real :: nfhour
integer :: idate(7)
integer :: fdate(7)
!
Expand All @@ -89,7 +87,6 @@ module write_internal_state
!-----------------------------------------
!
logical :: output_history
logical :: write_netcdfflag
!
!-----------------------------------------
!*** POST flags and required variables
Expand Down
19 changes: 16 additions & 3 deletions io/module_write_netcdf.F90
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ subroutine write_netcdf(wrtfb, filename, &
integer :: ncerr,ierr
integer :: ncid
integer :: oldMode
integer :: im_dimid, jm_dimid, tile_dimid, pfull_dimid, phalf_dimid, time_dimid
integer :: im_varid, jm_varid, tile_varid, lon_varid, lat_varid
integer :: im_dimid, jm_dimid, tile_dimid, pfull_dimid, phalf_dimid, time_dimid, ch_dimid
integer :: im_varid, jm_varid, tile_varid, lon_varid, lat_varid, timeiso_varid
integer, dimension(:), allocatable :: dimids_2d, dimids_3d
integer, dimension(:), allocatable :: varids
logical shuffle
Expand Down Expand Up @@ -213,6 +213,7 @@ subroutine write_netcdf(wrtfb, filename, &
! define dimensions [grid_xt, grid_yta ,(pfull/phalf), (tile), time]
ncerr = nf90_def_dim(ncid, "grid_xt", im, im_dimid); NC_ERR_STOP(ncerr)
ncerr = nf90_def_dim(ncid, "grid_yt", jm, jm_dimid); NC_ERR_STOP(ncerr)
ncerr = nf90_def_dim(ncid, "nchars", 20, ch_dimid); NC_ERR_STOP(ncerr)
if (lm > 1) then
call add_dim(ncid, "pfull", pfull_dimid, wrtgrid, rc)
call add_dim(ncid, "phalf", phalf_dimid, wrtgrid, rc)
Expand All @@ -229,9 +230,13 @@ subroutine write_netcdf(wrtfb, filename, &
ncerr = nf90_put_att(ncid, jm_varid, "cartesian_axis", "Y"); NC_ERR_STOP(ncerr)
if (is_cubed_sphere) then
ncerr = nf90_def_var(ncid, "tile", NF90_INT, tile_dimid, tile_varid); NC_ERR_STOP(ncerr)
ncerr = nf90_put_att(ncid, tile_varid, "long_name", "cubed-spehere face"); NC_ERR_STOP(ncerr)
ncerr = nf90_put_att(ncid, tile_varid, "long_name", "cubed-sphere face"); NC_ERR_STOP(ncerr)
end if

ncerr = nf90_def_var(ncid, "time_iso", NF90_CHAR, [ch_dimid,time_dimid], timeiso_varid); NC_ERR_STOP(ncerr)
ncerr = nf90_put_att(ncid, timeiso_varid, "long_name", "valid time"); NC_ERR_STOP(ncerr)
ncerr = nf90_put_att(ncid, timeiso_varid, "description", "ISO 8601 datetime string"); NC_ERR_STOP(ncerr)

! coordinate variable attributes based on output_grid type
if (trim(output_grid(grid_id)) == 'gaussian_grid' .or. &
trim(output_grid(grid_id)) == 'global_latlon' .or. &
Expand Down Expand Up @@ -275,6 +280,7 @@ subroutine write_netcdf(wrtfb, filename, &
ncerr = nf90_var_par_access(ncid, lon_varid, NF90_INDEPENDENT); NC_ERR_STOP(ncerr)
ncerr = nf90_var_par_access(ncid, jm_varid, NF90_INDEPENDENT); NC_ERR_STOP(ncerr)
ncerr = nf90_var_par_access(ncid, lat_varid, NF90_INDEPENDENT); NC_ERR_STOP(ncerr)
ncerr = nf90_var_par_access(ncid, timeiso_varid, NF90_INDEPENDENT); NC_ERR_STOP(ncerr)
if (is_cubed_sphere) then
ncerr = nf90_var_par_access(ncid, tile_varid, NF90_INDEPENDENT); NC_ERR_STOP(ncerr)
end if
Expand Down Expand Up @@ -560,6 +566,13 @@ subroutine write_netcdf(wrtfb, filename, &
ncerr = nf90_put_var(ncid, tile_varid, values=[1,2,3,4,5,6]); NC_ERR_STOP(ncerr)
end if

! write time_iso (timeiso_varid)
if (do_io) then
call ESMF_AttributeGet(wrtgrid, convention="NetCDF", purpose="FV3", &
name="time_iso", value=varcval, rc=rc); ESMF_ERR_RETURN(rc)
ncerr = nf90_put_var(ncid, timeiso_varid, values=[trim(varcval)]); NC_ERR_STOP(ncerr)
end if

! write variables (fields)
do i=1, fieldCount

Expand Down
76 changes: 24 additions & 52 deletions io/module_wrt_grid_comp.F90
Original file line number Diff line number Diff line change
Expand Up @@ -1368,12 +1368,6 @@ subroutine wrt_initialize(wrt_comp, imp_state_write, exp_state_write, clock, rc)
deallocate(attNameList, attNameList2, typekindList)
!
!-----------------------------------------------------------------------
!*** SET THE FIRST HISTORY FILE'S TIME INDEX.
!-----------------------------------------------------------------------
!
wrt_int_state%NFHOUR = 0
!
!-----------------------------------------------------------------------
!*** Initialize for POST
!-----------------------------------------------------------------------
!
Expand Down Expand Up @@ -1410,6 +1404,7 @@ subroutine wrt_run(wrt_comp, imp_state_write, exp_state_write,clock,rc)
TYPE(ESMF_VM) :: VM
type(ESMF_FieldBundle) :: file_bundle
type(ESMF_Time) :: currtime
type(ESMF_TimeInterval) :: io_currtimediff
type(ESMF_Grid) :: fbgrid, wrtGrid
type(ESMF_State),save :: stateGridFB
type(optimizeT), save :: optimize(4)
Expand All @@ -1420,8 +1415,8 @@ subroutine wrt_run(wrt_comp, imp_state_write, exp_state_write,clock,rc)
!
integer :: i,j,n,mype,nolog, grid_id
!
integer :: nf_hours,nf_seconds, nf_minutes, &
nseconds,nseconds_num,nseconds_den
integer :: nf_hours,nf_seconds,nf_minutes
real(ESMF_KIND_R8) :: nfhour
!
integer :: nbdl, date(6), ndig, nnnn
integer :: step=1
Expand All @@ -1431,7 +1426,7 @@ subroutine wrt_run(wrt_comp, imp_state_write, exp_state_write,clock,rc)
!
character(esmf_maxstr) :: filename,compname
character(40) :: cfhour, cform
real(ESMF_KIND_R8) :: time
character(20) :: time_iso
!
real(kind=8) :: MPI_Wtime
real(kind=8) :: tbeg
Expand Down Expand Up @@ -1475,67 +1470,39 @@ subroutine wrt_run(wrt_comp, imp_state_write, exp_state_write,clock,rc)
!*** get current time and elapsed forecast time

call ESMF_ClockGet(clock=CLOCK, currTime=CURRTIME, rc=rc)

if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return

call ESMF_TimeGet(time=currTime,yy=date(1),mm=date(2),dd=date(3),h=date(4), &
m=date(5),s=date(6),rc=rc)
if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return

wrt_int_state%fdate(7) = 1
wrt_int_state%fdate(1:6) = date(1:6)
write(time_iso,'(I4,"-",I2.2,"-",I2.2,"T",I2.2,":",I2.2,":",I2.2,"Z")') date(1:6)

if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return
! if(mype == lead_write_task) print *,'in wrt run, curr time=',date
!
call ESMF_TimeGet(time=wrt_int_state%IO_BASETIME,yy=date(1),mm=date(2),dd=date(3),h=date(4), &
m=date(5),s=date(6),rc=rc)
if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return

io_currtimediff = currtime - wrt_int_state%IO_BASETIME

call ESMF_TimeIntervalGet(timeinterval=io_currtimediff &
,h_r8=nfhour,h=nf_hours,m=nf_minutes,s=nf_seconds,rc=rc)
if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return

if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return
! print *,'in wrt run, io_baseline time=',date
!
wrt_int_state%IO_CURRTIMEDIFF = CURRTIME-wrt_int_state%IO_BASETIME
!
call ESMF_TimeIntervalGet(timeinterval=wrt_int_state%IO_CURRTIMEDIFF &
,h =nf_hours & !<-- Hours of elapsed time
,m =nf_minutes & !<-- Minutes of elapsed time
,s =nseconds & !<-- Seconds of elapsed time
,sN =nseconds_num & !<-- Numerator of fractional elapsed seconds
,sD =nseconds_den & !<-- denominator of fractional elapsed seconds
,rc =RC)
if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return
! if (lprnt) print *,'in wrt run, nf_hours=',nf_hours,nf_minutes,nseconds, &
! 'nseconds_num=',nseconds_num,nseconds_den,'mype=',mype
!
nf_seconds = nf_hours*3600+nf_minuteS*60+nseconds+real(nseconds_num)/real(nseconds_den)
wrt_int_state%nfhour = nf_seconds/3600.
nf_hours = int(nf_seconds/3600.)
if(lprnt) print *,'in write grid comp, nf_hours=',nf_hours
! if iau_offset > nf_hours, don't write out anything
if (nf_hours < 0) return

nf_minutes = int((nf_seconds-nf_hours*3600.)/60.)
nseconds = int(nf_seconds-nf_hours*3600.-nf_minutes*60.)
if (nsout > 0 .or. lflname_fulltime) then
ndig = max(log10(nf_hours+0.5)+1., 3.)
write(cform, '("(I",I1,".",I1,",A1,I2.2,A1,I2.2)")') ndig, ndig
write(cfhour, cform) nf_hours,'-',nf_minutes,'-',nseconds
write(cfhour, cform) nf_hours,'-',nf_minutes,'-',nf_seconds
else
ndig = max(log10(nf_hours+0.5)+1., 3.)
write(cform, '("(I",I1,".",I1,")")') ndig, ndig
write(cfhour, cform) nf_hours
endif
!
if(lprnt) print *,'in wrt run, nf_hours=',nf_hours,nf_minutes,nseconds, &
'nseconds_num=',nseconds_num,nseconds_den,' FBCount=',FBCount,' cfhour=',trim(cfhour)

! if(lprnt) print *,'in wrt run, cfhour=',cfhour, &
! print *,'in wrt run, cfhour=',cfhour, &
! ' nf_seconds=',nf_seconds,wrt_int_state%nfhour

! access the time Attribute which is updated by the driver each time
call ESMF_AttributeGet(imp_state_write, convention="NetCDF", purpose="FV3", &
name="time", value=time, rc=rc)
if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return

if(lprnt) print *,'in wrt run, nfhour=',nfhour,' cfhour=',trim(cfhour)
!
!-----------------------------------------------------------------------
!*** loop on the files that need to write out
Expand Down Expand Up @@ -1570,7 +1537,7 @@ subroutine wrt_run(wrt_comp, imp_state_write, exp_state_write,clock,rc)
endif

call inline_post_run(wrt_int_state, 1, mype, wrt_mpi_comm, lead_write_task, &
nf_hours, nf_minutes,nseconds)
nf_hours, nf_minutes, nf_seconds)
wend = MPI_Wtime()
if (lprnt) then
write(*,'(A,F10.5,A,I4.2,A,I2.2)')' actual inline post Time is ',wend-wbeg &
Expand Down Expand Up @@ -1649,7 +1616,12 @@ subroutine wrt_run(wrt_comp, imp_state_write, exp_state_write,clock,rc)
if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return

call ESMF_AttributeSet(fbgrid, convention="NetCDF", purpose="FV3", &
name="time", value=real(wrt_int_state%nfhour,ESMF_KIND_R8), rc=rc)
name="time", value=nfhour, rc=rc)

if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return

call ESMF_AttributeSet(fbgrid, convention="NetCDF", purpose="FV3", &
name="time_iso", value=trim(time_iso), rc=rc)

if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return

Expand Down Expand Up @@ -1765,7 +1737,7 @@ subroutine wrt_run(wrt_comp, imp_state_write, exp_state_write,clock,rc)
enddo
!
open(nolog,file='logf'//trim(cfhour),form='FORMATTED')
write(nolog,100)wrt_int_state%nfhour,idate(1:6)
write(nolog,100)nfhour,idate(1:6)
100 format(' completed fv3gfs fhour=',f10.3,2x,6(i4,2x))
close(nolog)
endif
Expand Down
32 changes: 20 additions & 12 deletions module_fcst_grid_comp.F90
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,6 @@ subroutine fcst_initialize(fcst_comp, importState, exportState, clock, rc)

integer,dimension(6) :: date, date_end
!
character(len=9) :: month
integer :: initClock, unit, total_inttime
integer :: mype
character(4) dateSY
Expand Down Expand Up @@ -590,17 +589,7 @@ subroutine fcst_initialize(fcst_comp, importState, exportState, clock, rc)
! if there is restart writing during integration
intrm_rst = 0
if (frestart(1)>0) intrm_rst = 1
!
!----- write time stamps (for start time and end time) ------

call mpp_open( unit, 'time_stamp.out', nohdrs=.TRUE. )
month = month_name(date(2))
if ( mpp_pe() == mpp_root_pe() ) write (unit,20) date, month(1:3)
month = month_name(date_end(2))
if ( mpp_pe() == mpp_root_pe() ) write (unit,20) date_end, month(1:3)
call mpp_close (unit)
20 format (6i4,2x,a3)
!
!------ initialize component models ------

call atmos_model_init (Atmos, Time_init, Time, Time_step)
Expand Down Expand Up @@ -829,7 +818,26 @@ subroutine fcst_initialize(fcst_comp, importState, exportState, clock, rc)
call ESMF_AttributeSet(exportState, convention="NetCDF", purpose="FV3", &
name="time:calendar", value=uppercase(trim(calendar)), rc=rc)
if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return
!

! Add time_iso Attribute to the exportState
call ESMF_AttributeAdd(exportState, convention="NetCDF", purpose="FV3", &
attrList=(/ "time_iso ", &
"time_iso:long_name ", &
"time_iso:description " /), rc=rc)
if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return

call ESMF_AttributeSet(exportState, convention="NetCDF", purpose="FV3", &
name="time_iso", value="yyyy-mm-ddThh:mm:ssZ", rc=rc)
if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return

call ESMF_AttributeSet(exportState, convention="NetCDF", purpose="FV3", &
name="time_iso:description", value="ISO 8601 Date String", rc=rc)
if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return

call ESMF_AttributeSet(exportState, convention="NetCDF", purpose="FV3", &
name="time_iso:long_name", value="valid time", rc=rc)
if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return

! Create FieldBundle for Fields that need to be regridded bilinear
if( quilting ) then

Expand Down

0 comments on commit 8c582f7

Please sign in to comment.