Skip to content

Commit

Permalink
Merge pull request ESCOMP#191 from jedwards4b/leap_year_corrections
Browse files Browse the repository at this point in the history
correct mismatch of leap year
### Description of changes
Handle a number of special cases in matching inputdata dates to model dates.
These cases are:

-   Model is no_leap, data is Gregorian and leapyear date 2/29 is encountered in data - skip date
-   Model is Gregorian, data is no_leap and leapyear date 2/29 is encountered in model - repeat 2/28 data
-   Model is Gregorian, data is gregorian but leapyears do not align.
-       if in model leap year repeat data from 2/28 
-       if in data leap year skip date 2/29


### Specific notes

Contributors other than yourself, if any:  @mvertens 

CDEPS Issues Fixed (include github issue #): ESCOMP#190 

Are there dependencies on other component PRs (if so list): ESCOMP/CESM_share#35

Are changes expected to change answers (bfb, different to roundoff, more substantial): bfb

Any User Interface Changes (namelist or namelist defaults changes):

Testing performed (e.g. aux_cdeps, CESM prealpha, etc):  Neon spinup of over 100 years

Hashes used for testing:

sM  ./ccs_config
        modified sandbox, ccs_config_cesm0.0.44 (branch main) --> ccs_config_cesm0.0.38
    ./cime
        clean sandbox, on cime6.0.45
s   ./components/cdeps
        clean sandbox, 0f3f707 (branch leap_year_corrections) --> cdeps0.12.63
    ./components/cdeps/fox
        clean sandbox, on 4.1.2.1
    ./components/cdeps/share/genf90
        clean sandbox, on genf90_200608
    ./components/cism
        clean sandbox, on cismwrap_2_1_95
    ./components/cism/source_cism
        clean sandbox, on cism_main_2.01.011
 M  ./components/cmeps
        modified sandbox, on cmeps0.13.71
    ./components/cpl7
        clean sandbox, on cpl7.0.14
    ./components/mizuRoute
        clean sandbox, on 34723c2e4df7caa16812770f8d53ebc83fa22360
    ./components/mosart
        clean sandbox, on mosart1_0_45
    ./components/rtm
        clean sandbox, on rtm1_0_78
e-o ./doc/doc-builder
        -, not checked out --> v1.0.8
    ./libraries/mct
        clean sandbox, on MCT_2.11.0
    ./libraries/parallelio
        clean sandbox, on pio2_5_7
s   ./share
        clean sandbox, bfa2b5d0a9de06153f2ac94a95818568a1f5cf11 (branch shr_cal_leapyear) --> share1.0.12
    ./src/fates
        clean sandbox, on sci.1.58.1_api.24.1.0
  • Loading branch information
jedwards4b authored Sep 29, 2022
2 parents ed418ee + 4f30632 commit 4d81662
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 6 deletions.
17 changes: 17 additions & 0 deletions share/shr_cal_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ module shr_cal_mod
public :: shr_cal_ymdtod2string ! translate ymdtod to string for filenames
public :: shr_cal_datetod2string ! translate date to string for filenames
public :: shr_cal_ymds2rday_offset ! translate yr,month,day,sec offset to a fractional day offset
public :: shr_cal_leapyear ! logical function: is this a leap year?

! !PUBLIC DATA MEMBERS:

Expand Down Expand Up @@ -1410,5 +1411,21 @@ subroutine shr_cal_ymds2rday_offset(etime, rdays_offset, &
if(rc /= ESMF_SUCCESS) call ESMF_Finalize(rc=rc, endflag=ESMF_END_ABORT)
end subroutine shr_cal_ymds2rday_offset

!===============================================================================
logical function shr_cal_leapyear(yr)
integer, intent(in) :: yr
shr_cal_leapyear = .false.
if (modulo(yr, 4) == 0) then
if (modulo(yr, 100) == 0) then
if(modulo(yr, 400) == 0) then
shr_cal_leapyear = .true.
endif
else
shr_cal_leapyear = .true.
endif
endif

end function shr_cal_leapyear

!===============================================================================
end module shr_cal_mod
49 changes: 43 additions & 6 deletions streams/dshr_strdata_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ module dshr_strdata_mod
use ESMF , only : ESMF_FieldReGridStore, ESMF_FieldRedistStore, ESMF_UNMAPPEDACTION_IGNORE
use ESMF , only : ESMF_TERMORDER_SRCSEQ, ESMF_FieldRegrid, ESMF_FieldFill, ESMF_FieldIsCreated
use ESMF , only : ESMF_REGION_TOTAL, ESMF_FieldGet, ESMF_TraceRegionExit, ESMF_TraceRegionEnter
use ESMF , only : ESMF_LOGMSG_INFO, ESMF_LogWrite, ESMF_RC_ARG_VALUE
use ESMF , only : ESMF_LOGMSG_INFO, ESMF_LogWrite
use shr_kind_mod , only : r8=>shr_kind_r8, r4=>shr_kind_r4, i2=>shr_kind_I2
use shr_kind_mod , only : cs=>shr_kind_cs, cl=>shr_kind_cl, cxx=>shr_kind_cxx
use shr_sys_mod , only : shr_sys_abort
use shr_const_mod , only : shr_const_pi, shr_const_cDay, shr_const_spval
use shr_cal_mod , only : shr_cal_calendarname, shr_cal_timeSet
use shr_cal_mod , only : shr_cal_noleap, shr_cal_gregorian
use shr_cal_mod , only : shr_cal_date2ymd, shr_cal_ymd2date
use shr_cal_mod , only : shr_cal_date2ymd, shr_cal_ymd2date, shr_cal_leapyear
use shr_orb_mod , only : shr_orb_decl, shr_orb_cosz, shr_orb_undef_real
#ifdef CESMCOUPLED
use shr_pio_mod , only : shr_pio_getiosys, shr_pio_getiotype, shr_pio_getioformat
Expand Down Expand Up @@ -786,7 +786,14 @@ subroutine shr_strdata_advance(sdat, ymd, tod, logunit, istr, timers, rc)
! on the time series input data.
!
! (0) The stream calendar and model calendar are identical:
! Proceed in the standard way.
! In this case it is still possible to have a mismatch if both are gregorian.
! These cases are:
! - Model is no_leap, data is Gregorian and leapyear date 2/29 is encountered in data - skip date
! - Model is Gregorian, data is no_leap and leapyear date 2/29 is encountered in model - repeat 2/28 data
! - Model is Gregorian, data is gregorian but leapyears do not align.
! - if in model leap year repeat data from 2/28
! - if in data leap year skip date 2/29
!
!
! (1) The stream is a no leap calendar and the model is gregorian:
! Time interpolate on the noleap calendar. If the model date is Feb 29,
Expand Down Expand Up @@ -846,9 +853,11 @@ subroutine shr_strdata_advance(sdat, ymd, tod, logunit, istr, timers, rc)
real(r8), pointer :: data_v_dst(:) ! pointer into field bundle
type(ESMF_Time) :: timeLB, timeUB ! lb and ub times
type(ESMF_TimeInterval) :: timeint ! delta time
character(CL) :: calendar
integer :: dday ! delta days
real(r8) :: dtime ! delta time
integer :: year,month,day ! date year month day
integer :: datayear,datamonth,dataday ! data date year month day
integer :: nstreams
integer :: stream_index
integer :: lsize
Expand Down Expand Up @@ -899,6 +908,7 @@ subroutine shr_strdata_advance(sdat, ymd, tod, logunit, istr, timers, rc)
! case(0)
ymdmod(ns) = ymd
todmod = tod
calendar = trim(sdat%stream(ns)%calendar)
if (trim(sdat%model_calendar) /= trim(sdat%stream(ns)%calendar)) then
if (( trim(sdat%model_calendar) == trim(shr_cal_gregorian)) .and. &
(trim(sdat%stream(ns)%calendar) == trim(shr_cal_noleap))) then
Expand All @@ -907,6 +917,7 @@ subroutine shr_strdata_advance(sdat, ymd, tod, logunit, istr, timers, rc)
if (month == 2 .and. day == 29) then
call shr_cal_ymd2date(year,2,28,ymdmod(ns))
endif
calendar = shr_cal_noleap
else if ((trim(sdat%model_calendar) == trim(shr_cal_noleap)) .and. &
(trim(sdat%stream(ns)%calendar) == trim(shr_cal_gregorian))) then
! case (2), feb 29 input data will be skipped automatically
Expand All @@ -916,6 +927,31 @@ subroutine shr_strdata_advance(sdat, ymd, tod, logunit, istr, timers, rc)
trim(sdat%model_calendar),':',trim(sdat%stream(ns)%calendar)
call shr_sys_abort(trim(subname)//' ERROR: mismatch calendar ')
endif
else ! calendars are the same
if(trim(sdat%model_calendar) == trim(shr_cal_gregorian)) then
! Both are in gregorian - but it's possible that there is a mismatch
! such that the model is in leapyear but the data is not
call shr_cal_date2ymd (ymd,year,month,day)
call shr_cal_date2ymd(sdat%pstrm(ns)%ymdUB, datayear, datamonth, dataday)

if(month == 2 .and. day==29) then
if(.not. shr_cal_leapyear(datayear)) then
! model is in leap year but data is not
calendar = shr_cal_noleap
endif
else if(datamonth == 2) then
if(.not. shr_cal_leapyear(year)) then
if(debug>0 .and. sdat%mainproc) then
write(logunit, *) subname,' dataday = ', dataday
endif
calendar = shr_cal_noleap
endif
else
calendar = sdat%model_calendar
endif
else
calendar = sdat%model_calendar
endif
endif

! ---------------------------------------------------------
Expand Down Expand Up @@ -948,11 +984,11 @@ subroutine shr_strdata_advance(sdat, ymd, tod, logunit, istr, timers, rc)

if (newData(ns)) then
! Reset time bounds if newdata read in
call shr_cal_date2ymd(sdat%pstrm(ns)%ymdLB,year,month,day)
call shr_cal_timeSet(timeLB,sdat%pstrm(ns)%ymdLB,0,sdat%stream(ns)%calendar,rc=rc)
call shr_cal_timeSet(timeLB,sdat%pstrm(ns)%ymdLB,0,calendar,rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
call shr_cal_timeSet(timeUB,sdat%pstrm(ns)%ymdUB,0,sdat%stream(ns)%calendar,rc=rc)
call shr_cal_timeSet(timeUB,sdat%pstrm(ns)%ymdUB,0,calendar,rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

timeint = timeUB-timeLB
call ESMF_TimeIntervalGet(timeint, StartTimeIn=timeLB, d=dday)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
Expand All @@ -964,6 +1000,7 @@ subroutine shr_strdata_advance(sdat, ymd, tod, logunit, istr, timers, rc)
if ((sdat%pstrm(ns)%dtmax/sdat%pstrm(ns)%dtmin) > sdat%stream(ns)%dtlimit) then
if (sdat%mainproc) then
write(sdat%stream(1)%logunit,*) trim(subname),' ERROR: for stream ',ns
write(sdat%stream(1)%logunit,*) trim(subname),' ERROR: dday = ',dday
write(sdat%stream(1)%logunit,*) trim(subName),' ERROR: dtime, dtmax, dtmin, dtlimit = ',&
dtime, sdat%pstrm(ns)%dtmax, sdat%pstrm(ns)%dtmin, sdat%stream(ns)%dtlimit
write(sdat%stream(1)%logunit,*) trim(subName),' ERROR: ymdLB, todLB, ymdUB, todUB = ', &
Expand Down
9 changes: 9 additions & 0 deletions streams/dshr_stream_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ module dshr_stream_mod
use shr_cal_mod , only : shr_cal_calendarName
use shr_cal_mod , only : shr_cal_advDate
use shr_cal_mod , only : shr_cal_advdateint
use shr_cal_mod , only : shr_cal_leapyear
use dshr_methods_mod , only : chkerr
use pio , only : pio_noerr, pio_seterrorhandling, pio_inq_att, pio_openfile, pio_closefile
use pio , only : file_desc_t, pio_inq_varid, iosystem_desc_t, pio_file_is_open
Expand Down Expand Up @@ -818,6 +819,9 @@ subroutine shr_stream_findBounds(strm, mDateIn, secIn, isroot_task, &

if (cycle) then
dYear = yrFirst + modulo(mYear-yrAlign+(2*nYears),nYears) ! current data year
if(debug>0 .and. isroot_task) then
write(strm%logunit, *) trim(subname), ' dyear, yrfirst, myear, yralign, nyears =', dyear, yrfirst, myear, yralign, nyears
endif
else
dYear = yrFirst + mYear - yrAlign
endif
Expand Down Expand Up @@ -1159,6 +1163,11 @@ subroutine shr_stream_findBounds(strm, mDateIn, secIn, isroot_task, &
dDateUB = strm%file(k_ub)%date(n_ub)
call shr_cal_date2ymd(dDateUB,yy,mm,dd)
yy = yy + (mYear-dYear)
if(mm == 2 .and. dd==29 .and. .not. shr_cal_leapyear(yy)) then
if(isroot_task) write(strm%logunit, *) 'Found leapyear mismatch', myear, dyear, yy
mm = 3
dd = 1
endif
call shr_cal_ymd2date(yy,mm,dd,mDateUB)
secUB = strm%file(k_ub)%secs(n_ub)
fileUB = strm%file(k_ub)%name
Expand Down

0 comments on commit 4d81662

Please sign in to comment.