Skip to content

Commit

Permalink
Merge pull request #9 from geoschem/feature/timestampStart_and_monthl…
Browse files Browse the repository at this point in the history
…yDiagFix

Atanas Trayanov (GMAO) History updates: monthly diag fix, timestampStart
  • Loading branch information
lizziel committed Apr 20, 2021
2 parents b9db348 + 276e77b commit a464a1b
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 42 deletions.
42 changes: 32 additions & 10 deletions base/MAPL_TimeMethods.F90
Expand Up @@ -26,26 +26,32 @@ module MAPL_TimeDataMod
procedure :: compute_time_vector
procedure :: get_start_time
procedure :: get
procedure :: setFrequency
end type timeData

interface timeData
module procedure new_time_data
end interface timeData
contains

function new_time_data(clock,ntime,frequency,offset,rc) result(tData)
function new_time_data(clock,ntime,frequency,offset,funits,rc) result(tData)
type(timeData) :: tData
type(ESMF_Clock),intent(inout) :: clock
integer, intent(in) :: ntime
integer, intent(in) :: frequency
type(ESMF_TimeInterval) :: offset
character(len=*), optional, intent(in) :: funits
integer, optional, intent(Out) :: rc

tdata%clock=clock
tdata%ntime=ntime
tdata%frequency=frequency
tdata%offset=offset
tdata%funits="minutes"
if(present(funits)) then
tdata%funits=funits
else
tdata%funits="minutes"
end if

_RETURN(ESMF_SUCCESS)

Expand All @@ -61,6 +67,15 @@ subroutine get(this,clock,rc)
_RETURN(_SUCCESS)
end subroutine get

subroutine setFrequency(this,frequency,rc)
class(TimeData) :: this
integer, intent(in) :: frequency
integer, optional, intent(out) :: rc

this%frequency = frequency

_RETURN(_SUCCESS)
end subroutine setFrequency

function define_time_variable(this,rc) result(v)
class(TimeData), intent(inout) :: this
Expand Down Expand Up @@ -98,14 +113,21 @@ function define_time_variable(this,rc) result(v)
i123=10000*i1+100*i2+i3
call v%add_attribute('begin_time',i123)

isc=mod(this%frequency,60)
i2=this%frequency-isc
i2=i2/60
imn=mod(i2,60)
i2=i2-imn
ihr=i2/60
ifreq=10000*ihr+100*imn+isc
call v%add_attribute('time_increment',ifreq)
select case(trim(this%funits))
case('minutes')
isc=mod(this%frequency,60)
i2=this%frequency-isc
i2=i2/60
imn=mod(i2,60)
i2=i2-imn
ihr=i2/60
ifreq=10000*ihr+100*imn+isc
case('days')
ifreq = this%frequency/86400
case default
_ASSERT(.false., 'Not supported yet')
end select
call v%add_attribute('time_increment',ifreq)

call this%tvec%clear()
this%tcount=0
Expand Down
16 changes: 16 additions & 0 deletions base/MAPL_newCFIO.F90
Expand Up @@ -54,6 +54,7 @@ module MAPL_newCFIOMod
procedure :: CreateFileMetaData
procedure :: CreateVariable
procedure :: modifyTime
procedure :: modifyTimeIncrement
procedure :: bundlePost
procedure :: stageData
procedure :: stage2DLatLon
Expand Down Expand Up @@ -328,6 +329,21 @@ subroutine modifyTime(this, oClients, rc)

end subroutine modifyTime

subroutine modifyTimeIncrement(this, frequency, rc)
class(MAPL_newCFIO), intent(inout) :: this
integer, intent(in) :: frequency
integer, optional, intent(out) :: rc

integer :: status

call this%timeInfo%setFrequency(frequency, rc=status)
_VERIFY(status)

_RETURN(ESMF_SUCCESS)

end subroutine modifyTimeIncrement


subroutine bundlepost(this,filename,oClients,rc)
class (MAPL_newCFIO), intent(inout) :: this
character(len=*), intent(in) :: filename
Expand Down
1 change: 1 addition & 0 deletions gridcomps/History/MAPL_HistoryCollection.F90
Expand Up @@ -66,6 +66,7 @@ module MAPL_HistoryCollectionMod
integer :: Psize
integer :: tm
logical :: ForceOffsetZero
logical :: timestampStart
logical :: monthly
logical :: partial = .false.
! Adding Arithemtic Field Rewrite
Expand Down
104 changes: 72 additions & 32 deletions gridcomps/History/MAPL_HistoryGridComp.F90
Expand Up @@ -278,6 +278,9 @@ subroutine Initialize ( gc, import, dumexport, clock, rc )
type(ESMF_Time) :: CurrTime
type(ESMF_Time) :: RingTime
type(ESMF_Time) :: RefTime
type(ESMF_Time) :: StartOfThisMonth
type(ESMF_Time) :: nextMonth
type(ESMF_TimeInterval) :: oneMonth, dur
type(ESMF_TimeInterval) :: Frequency
type(ESMF_Array) :: array
type(ESMF_Field) :: field
Expand Down Expand Up @@ -483,6 +486,12 @@ subroutine Initialize ( gc, import, dumexport, clock, rc )
nymdc = year*10000 + month*100 + day
nhmsc = hour*10000 + minute*100 + second

! set up few variables to deal with monthly
startOfThisMonth = currTime
call ESMF_TimeSet(startOfThisMonth,dd=1,h=0,m=0,s=0,__RC__)
call ESMF_TimeIntervalSet( oneMonth, MM=1, __RC__)


! Read User-Supplied History Lists from Config File
! -------------------------------------------------
call ESMF_GridCompGet( gc, config=config, rc=STATUS ) ; _VERIFY(STATUS)
Expand Down Expand Up @@ -731,12 +740,6 @@ subroutine Initialize ( gc, import, dumexport, clock, rc )
! Initialize History Lists
! ------------------------

allocate(INTSTATE%AVERAGE (nlist), stat=status)
_VERIFY(STATUS)
allocate(INTSTATE%STAMPOFFSET(nlist), stat=status)
_VERIFY(STATUS)

IntState%average = .false.
LISTLOOP: do n=1,nlist

list(n)%unit = 0
Expand Down Expand Up @@ -1113,6 +1116,10 @@ subroutine Initialize ( gc, import, dumexport, clock, rc )
call ESMF_ConfigGetAttribute(cfg, list(n)%ForceOffsetZero, default=.false., &
label=trim(string)//'timestampEnd:', rc=status)
_VERIFY(status)
! Force history so that time averaged collections are timestamped at the begining of the accumulation interval
call ESMF_ConfigGetAttribute(cfg, list(n)%timeStampStart, default=.false., &
label=trim(string)//'timestampStart:', rc=status)
_VERIFY(status)

! Get an optional chunk size
! --------------------------
Expand Down Expand Up @@ -1164,15 +1171,6 @@ subroutine Initialize ( gc, import, dumexport, clock, rc )

if (list(n)%disabled) cycle

if(list(n)%mode == "instantaneous" .or. list(n)%ForceOffsetZero) then
sec = 0
else
IntState%average(n) = .true.
sec = MAPL_nsecf(list(n)%acc_interval) / 2
endif
call ESMF_TimeIntervalSet( INTSTATE%STAMPOFFSET(n), S=sec, rc=status )
_VERIFY(STATUS)

! His and Seg Alarms based on Reference Date and Time
! ---------------------------------------------------
REF_TIME(1) = list(n)%ref_date/10000
Expand All @@ -1182,8 +1180,13 @@ subroutine Initialize ( gc, import, dumexport, clock, rc )
REF_TIME(5) = mod(list(n)%ref_time,10000)/100
REF_TIME(6) = mod(list(n)%ref_time,100)

!ALT if monthly, modify ref_time(4:6)=0
if (list(n)%monthly) REF_TIME(4:6) = 0
!ALT if monthly, modify ref_time to midnight first of the month
if (list(n)%monthly) then
REF_TIME(3) = 1
REF_TIME(4:6) = 0
list(n)%ref_time = 0
list(n)%ref_date = 10000*REF_TIME(1) + 100*REF_TIME(2) + REF_TIME(3)
end if

call ESMF_TimeSet( RefTime, YY = REF_TIME(1), &
MM = REF_TIME(2), &
Expand All @@ -1194,9 +1197,17 @@ subroutine Initialize ( gc, import, dumexport, clock, rc )

! ALT if monthly, set interval "Frequncy" to 1 month
! also in this case sec should be set to non-zero
sec = MAPL_nsecf( list(n)%frequency )
call ESMF_TimeIntervalSet( Frequency, S=sec, calendar=cal, rc=status ) ; _VERIFY(STATUS)
RingTime = RefTime
!ALT if monthly overwrite duration and frequency
if (list(n)%monthly) then
list(n)%duration = 1 !ALT simply non-zero
sec = 1 !ALT simply non-zero
Frequency = oneMonth
RingTime = startOfThisMonth
else
sec = MAPL_nsecf( list(n)%frequency )
call ESMF_TimeIntervalSet( Frequency, S=sec, calendar=cal, rc=status ) ; _VERIFY(STATUS)
RingTime = RefTime
end if

! Added Logic to eliminate BEG_DATE = cap_restart date problem
! ------------------------------------------------------------
Expand All @@ -1214,21 +1225,17 @@ subroutine Initialize ( gc, import, dumexport, clock, rc )
endif
_VERIFY(STATUS)

!ALT if monthly overwrite duration and frequency
if (list(n)%monthly) then
list(n)%duration = 1 !ALT simply non-zero
end if
if( list(n)%duration.ne.0 ) then
if (.not.list(n)%monthly) then
sec = MAPL_nsecf( list(n)%duration )
call ESMF_TimeIntervalSet( Frequency, S=sec, calendar=cal, rc=status ) ; _VERIFY(STATUS)
RingTime = RefTime
else
call ESMF_TimeIntervalSet( Frequency, MM=1, calendar=cal, rc=status ) ; _VERIFY(STATUS)
Frequency = oneMonth
!ALT keep the values from above
! and for debugging print
call WRITE_PARALLEL("DEBUG: monthly averaging is active for collection "//trim(list(n)%collection))
end if
RingTime = RefTime
if (RingTime < currTime) then
RingTime = RingTime + (INT((currTime - RingTime)/frequency)+1)*frequency
endif
Expand Down Expand Up @@ -1621,12 +1628,13 @@ subroutine Initialize ( gc, import, dumexport, clock, rc )
IntState%average = .false.
do n=1, nlist
if (list(n)%disabled) cycle
if(list(n)%monthly) cycle
if(list(n)%mode == "instantaneous" .or. list(n)%ForceOffsetZero) then
sec = 0
else if (list(n)%timeStampStart) then
sec = MAPL_nsecf(list(n)%acc_interval)
else
IntState%average(n) = .true.
sec = MAPL_nsecf(list(n)%acc_interval) / 2
if(list(n)%monthly) cycle
endif
call ESMF_TimeIntervalSet( INTSTATE%STAMPOFFSET(n), S=sec, rc=status )
_VERIFY(STATUS)
Expand Down Expand Up @@ -2415,7 +2423,14 @@ subroutine Initialize ( gc, import, dumexport, clock, rc )
_VERIFY(status)
call list(n)%mNewCFIO%set_param(itemOrder=intState%fileOrderAlphabetical,rc=status)
_VERIFY(status)
list(n)%timeInfo = TimeData(clock,tm,MAPL_nsecf(list(n)%frequency),IntState%stampoffset(n))
if (list(n)%monthly) then
nextMonth = currTime - oneMonth
dur = nextMonth - currTime
call ESMF_TimeIntervalGet(dur, s=sec, __RC__)
list(n)%timeInfo = TimeData(clock,tm,sec,IntState%stampoffset(n),'days')
else
list(n)%timeInfo = TimeData(clock,tm,MAPL_nsecf(list(n)%frequency),IntState%stampoffset(n))
end if
if (list(n)%timeseries_output) then
list(n)%trajectory = HistoryTrajectory(trim(list(n)%trackfile),rc=status)
_VERIFY(status)
Expand Down Expand Up @@ -2458,12 +2473,20 @@ subroutine Initialize ( gc, import, dumexport, clock, rc )
print *, ' Nbits: ', list(n)%nbits
print *, ' Slices: ', list(n)%Slices
print *, ' Deflate: ', list(n)%deflate
print *, ' Frequency: ', list(n)%frequency
if(IntState%average(n) ) &
if (list(n)%monthly) then
print *, ' Frequency: ', 'monthly'
else
print *, ' Frequency: ', list(n)%frequency
end if
if(IntState%average(n) .and. .not. list(n)%monthly) &
print *, 'Acc_Interval: ', list(n)%acc_interval
print *, ' Ref_Date: ', list(n)%ref_date
print *, ' Ref_Time: ', list(n)%ref_time
print *, ' Duration: ', list(n)%duration
if (list(n)%monthly) then
print *, ' Duration: ', 'one month'
else
print *, ' Duration: ', list(n)%duration
end if
if( list(n)%end_date.ne.-999 ) then
print *, ' End_Date: ', list(n)%end_date
print *, ' End_Time: ', list(n)%end_time
Expand Down Expand Up @@ -3217,6 +3240,9 @@ subroutine Run ( gc, import, export, clock, rc )
character(len=ESMF_MAXSTR) :: DateStamp
integer :: CollBlock
type(ESMF_Time) :: current_time
type(ESMF_Time) :: lastMonth
type(ESMF_TimeInterval) :: dur, oneMonth
integer :: sec

! variables for "backwards" mode
logical :: fwd
Expand Down Expand Up @@ -3438,6 +3464,20 @@ subroutine Run ( gc, import, export, clock, rc )

if( NewSeg) then
list(n)%partial = .false.
if (list(n)%monthly) then
! get the number of seconds in this month
! it's tempting to use the variable "oneMonth" but it does not work
! instead we compute the differece between
! thisMonth and lastMonth and as a new timeInterval

call ESMF_ClockGet(clock,currTime=current_time,rc=status)
_VERIFY(status)
call ESMF_TimeIntervalSet( oneMonth, MM=1, __RC__)
lastMonth = current_time - oneMonth
dur = current_time - lastMonth
call ESMF_TimeIntervalGet(dur, s=sec, __RC__)
call list(n)%mNewCFIO%modifyTimeIncrement(sec, __RC__)
end if
endif

if (list(n)%timeseries_output) then
Expand Down

0 comments on commit a464a1b

Please sign in to comment.