portedportable, not yet portedexecuted, not portableexecutable, not hit by this run
| 1 | ! This file is part of MOM6, the Modular Ocean Model version 6. | |
| 2 | ! See the LICENSE file for licensing information. | |
| 3 | ! SPDX-License-Identifier: Apache-2.0 | |
| 4 | ||
| 5 | !> Wraps the FMS time manager functions | |
| 6 | module MOM_time_manager | |
| 7 | ||
| 8 | use time_manager_mod, only : time_type, get_time, set_time | |
| 9 | use time_manager_mod, only : time_type_to_real, real_to_time_type | |
| 10 | use time_manager_mod, only : operator(+), operator(-), operator(*), operator(/) | |
| 11 | use time_manager_mod, only : operator(>), operator(<), operator(>=), operator(<=) | |
| 12 | use time_manager_mod, only : operator(==), operator(/=), operator(//) | |
| 13 | use time_manager_mod, only : set_ticks_per_second , get_ticks_per_second | |
| 14 | use time_manager_mod, only : get_date, set_date, increment_date | |
| 15 | use time_manager_mod, only : days_in_month, month_name | |
| 16 | use time_manager_mod, only : set_calendar_type, get_calendar_type | |
| 17 | use time_manager_mod, only : JULIAN, NOLEAP, THIRTY_DAY_MONTHS, GREGORIAN | |
| 18 | use time_manager_mod, only : NO_CALENDAR | |
| 19 | ||
| 20 | implicit none ; private | |
| 21 | ||
| 22 | ! FMS re-exports | |
| 23 | public :: time_type, get_time, set_time | |
| 24 | public :: time_type_to_real, real_to_time_type | |
| 25 | public :: set_ticks_per_second, get_ticks_per_second | |
| 26 | public :: operator(+), operator(-), operator(*), operator(/) | |
| 27 | public :: operator(>), operator(<), operator(>=), operator(<=) | |
| 28 | public :: operator(==), operator(/=), operator(//) | |
| 29 | public :: get_date, set_date, increment_date, month_name, days_in_month | |
| 30 | public :: JULIAN, NOLEAP, THIRTY_DAY_MONTHS, GREGORIAN, NO_CALENDAR | |
| 31 | public :: set_calendar_type, get_calendar_type | |
| 32 | ! Module functions | |
| 33 | public :: real_to_time, time_minus_signed, time_to_real | |
| 34 | ||
| 35 | contains | |
| 36 | ||
| 37 | !> Returns a time_type version of a real time in seconds, using an alternate implementation to the | |
| 38 | !! FMS function real_to_time_type that is accurate over a larger range of input values. With 32 bit | |
| 39 | !! signed integers, this version should work over the entire valid range (2^31 days or ~5.8835 | |
| 40 | !! million years) of time_types, whereas the standard version in the FMS time_manager stops working | |
| 41 | !! for conversions of times greater than 2^31 seconds, or ~68.1 years. | |
| 42 | 139 | type(time_type) function real_to_time(time_in, err_msg, unscale) |
| 43 | ! type(time_type) :: real_to_time !< The output time as a time_type | |
| 44 | real, intent(in) :: time_in !< The input time in [s] or [T ~> s] | |
| 45 | character(len=*), optional, intent(out) :: err_msg !< An optional returned error message. | |
| 46 | real, optional, intent(in) :: unscale !< A scaling factor that the input time is | |
| 47 | !! multiplied by, often in [s T-1 ~> nondim] | |
| 48 | ||
| 49 | ! Local variables | |
| 50 | real :: x ! The time in real seconds [s] | |
| 51 | real :: real_subsecond_remainder ! The fractional seconds from time_in [s] | |
| 52 | integer :: seconds, days, ticks | |
| 53 | ||
| 54 | 134 | x = time_in ; if (present(unscale)) x = unscale*time_in |
| 55 | ||
| 56 | 139 | days = floor(x/86400.) |
| 57 | 139 | seconds = floor(x - 86400.*days) |
| 58 | 139 | real_subsecond_remainder = x - (days*86400. + seconds) |
| 59 | 139 | ticks = nint(real_subsecond_remainder * get_ticks_per_second()) |
| 60 | ||
| 61 | 139 | real_to_time = set_time(seconds=seconds, days=days, ticks=ticks, err_msg=err_msg) |
| 62 | ||
| 63 | 278 | end function real_to_time |
| 64 | ||
| 65 | !> Returns the real number of seconds encoded in the time type [s] or the rescaled | |
| 66 | !! amount of time in other units, often [T ~> s] | |
| 67 | 25 | real function time_to_real(time, scale) |
| 68 | type(time_type), intent(in) :: time !< The time to be converted. | |
| 69 | real, optional, intent(in) :: scale !< A scaling factor that returned the time is | |
| 70 | !! multiplied by, often in [T s-1 ~> nondim] | |
| 71 | ||
| 72 | 25 | time_to_real = time_type_to_real(time) |
| 73 | 25 | if (present(scale)) time_to_real = scale * time_to_real |
| 74 | ||
| 75 | 25 | end function time_to_real |
| 76 | ||
| 77 | !> Returns a real number representing time_a - time_b in [s] or [T ~> s] if scale is present. | |
| 78 | !! The FMS - operator for time types returns a new time type representing | |
| 79 | !! a difference that is always >= 0. | |
| 80 | !! In contrast, this function returns a negative real number if time_b > time_a, | |
| 81 | !! and a positive real otherwise, as would be expected for subtraction. | |
| 82 | 0 | real function time_minus_signed(time_a, time_b, scale) |
| 83 | type(time_type), intent(in) :: time_a, time_b !< Two times for calculating time_a - time_b | |
| 84 | real, optional, intent(in) :: scale !< A scaling factor that returned the time is | |
| 85 | !! multiplied by, often in [T s-1 ~> nondim] | |
| 86 | ||
| 87 | ! Local variables | |
| 88 | real :: abs_diff ! The absolute value of the difference in times [s] or [T ~> s] | |
| 89 | ||
| 90 | ! Do FMS time subtraction, which will always be >= 0, | |
| 91 | ! and convert to a real number. | |
| 92 | 0 | abs_diff = time_to_real(time_a - time_b, scale) |
| 93 | ||
| 94 | ! Add the sign back by comparing time_a and time_b | |
| 95 | 0 | time_minus_signed = merge(abs_diff, -abs_diff, time_a >= time_b) |
| 96 | ||
| 97 | 0 | end function time_minus_signed |
| 98 | ||
| 99 | end module MOM_time_manager |