Skip to content
This repository has been archived by the owner on Oct 23, 2020. It is now read-only.

Commit

Permalink
Merge branch 'framework/linear_interval_division' into release-v3.0
Browse files Browse the repository at this point in the history
This merge causes the linear interval division algorithm to be used
when either of the time intervals involved includes a year or month.

Also, improve the performance of linear interval division when used for
large time intervals.
  • Loading branch information
mgduda committed Nov 18, 2014
2 parents 5b92c01 + 1775c20 commit 6fb3dae
Showing 1 changed file with 40 additions and 10 deletions.
50 changes: 40 additions & 10 deletions src/framework/mpas_timekeeping.F
Original file line number Diff line number Diff line change
Expand Up @@ -1511,13 +1511,11 @@ subroutine mpas_interval_division(ref_time, num, den, n, rem)
integer :: days, secondsNum, secondsDen
integer (kind=I8KIND) :: seconds

call mpas_get_timeInterval(num, startTimeIn=ref_time, DD=days, S_i8=seconds, S_n=secondsNum, S_d=secondsDen)
call mpas_set_timeInterval(newNum, DD=days, S_i8=seconds, S_n=secondsNum, S_d=secondsDen)

call mpas_get_timeInterval(den, startTimeIn=ref_time, DD=days, S_i8=seconds, S_n=secondsNum, S_d=secondsDen)
call mpas_set_timeInterval(newDen, DD=days, S_i8=seconds, S_n=secondsNum, S_d=secondsDen)

call mpas_interval_division_log(newNum, newDen, n, rem)
if ( num % ti % YR == 0 .and. num % ti % MM == 0 .and. den % ti % YR == 0 .and. den % ti % MM == 0 ) then
call mpas_interval_division_log(num, den, n, rem)
else
call mpas_interval_division_linear(ref_time, num, den, n, rem)
end if

end subroutine mpas_interval_division

Expand Down Expand Up @@ -1624,10 +1622,12 @@ subroutine mpas_interval_division_linear(ref_time, num, den, n, rem)
integer, intent(out) :: n
type (MPAS_TimeInterval_type), intent(out) :: rem
integer :: m
type (MPAS_Time_type) :: target_time
type (MPAS_Time_type) :: updated_time
type (MPAS_Time_type) :: updated_time, mid_time
type (MPAS_TimeInterval_type) :: temp
type (MPAS_TimeInterval_type) :: temp, mid_int
type (MPAS_TimeInterval_type) :: zero
target_time = ref_time + num
Expand All @@ -1645,10 +1645,40 @@ subroutine mpas_interval_division_linear(ref_time, num, den, n, rem)
! One interval of den already fits into num
n = n + 1
temp = den
! Search forward, doubling the interval each time.
do while (target_time > updated_time)
n = n * 2
temp = den * n
updated_time = ref_time + temp
end do
! Setup midpoint of search
! The last value of n puts updated_time after target_time, need to back off and find the final time.
n = n / 2
m = n
mid_int = den * n
temp = mid_int
updated_time = ref_time + mid_int + temp
! Seach backward, halving the interval each time.
do while (target_time < updated_time)
m = m / 2
temp = den * m
updated_time = ref_time + mid_int + temp
end do
! Final number of interavls is n + m
n = n + m
! Do a final linear search, just to ensure we aren't missing any divisions.
temp = den * n
updated_time = ref_time + temp

do while (target_time > updated_time)
updated_time = updated_time + den
n = n + 1
updated_time = updated_time + den
end do

! Here, if updated_time is larger than target time. Need to subtract den once, and compute remainder
Expand Down

0 comments on commit 6fb3dae

Please sign in to comment.