From 0044189b1caabfae726551ab70254bff4a91d884 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 1 Feb 2022 13:59:55 -0700 Subject: [PATCH] Add get_average_days_per_year function For now, use hard-coded parameters (see https://github.com/ESCOMP/CTSM/issues/1624). --- src/utils/clm_time_manager.F90 | 61 ++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/utils/clm_time_manager.F90 b/src/utils/clm_time_manager.F90 index 78c49a75eb..f598dd65d3 100644 --- a/src/utils/clm_time_manager.F90 +++ b/src/utils/clm_time_manager.F90 @@ -37,6 +37,7 @@ module clm_time_manager get_curr_calday, &! return calendar day at end of current timestep get_calday, &! return calendar day from input date get_calendar, &! return calendar + get_average_days_per_year,&! return the average number of days per year for the given calendar get_curr_days_per_year, &! return the days per year for year as of the end of the current time step get_prev_days_per_year, &! return the days per year for year as of the beginning of the current time step get_curr_yearfrac, &! return the fractional position in the current year, as of the end of the current timestep @@ -122,6 +123,9 @@ module clm_time_manager private :: TimeGetymd private :: check_timemgr_initialized + character(len=*), parameter, private :: sourcefile = & + __FILE__ + !========================================================================================= contains !========================================================================================= @@ -1229,6 +1233,63 @@ end function get_calendar !========================================================================================= + real(r8) function get_average_days_per_year() + + !--------------------------------------------------------------------------------- + ! Get the average number of days per year for the given calendar. + ! + ! This should be used, for example, when converting a parameter from units of + ! per-year to units of per-second (so that the parameter will have a fixed, constant + ! value rather than a slightly different value on leap years vs. non-leap years). + + real(r8) :: avg_days_per_year + real(r8) :: curr_days_per_year + + real(r8), parameter :: days_per_year_noleap = 365._r8 + + ! From the definition of ESMF_CALKIND_GREGORIAN in + ! https://earthsystemmodeling.org/docs/release/latest/ESMF_refdoc/node6.html: "In the + ! Gregorian calendar every fourth year is a leap year in which February has 29 and not + ! 28 days; however, years divisible by 100 are not leap years unless they are also + ! divisible by 400." This results in an average number of days per year of 365.2425. + real(r8), parameter :: days_per_year_gregorian = 365.2425_r8 + + character(len=*), parameter :: subname = 'get_average_days_per_year' + !--------------------------------------------------------------------------------- + + ! BUG(wjs, 2022-02-01, ESCOMP/CTSM#1624) Ideally we would use ESMF_CalendarGet here, + ! but that currently isn't possible (see notes in issue 1624 for details) + if (to_upper(calendar) == NO_LEAP_C) then + avg_days_per_year = days_per_year_noleap + else if (to_upper(calendar) == GREGORIAN_C) then + avg_days_per_year = days_per_year_gregorian + else + call shr_sys_abort(subname//' ERROR: unrecognized calendar specified= '//trim(calendar)) + end if + + ! Paranoia: Since we're using a hard-coded value, let's make sure that the user hasn't + ! done some customizations to the calendar that change the days per year from what we + ! expect: Compare the hard-coded value with the number of days per year in the + ! current year, which comes from the actual ESMF calendar; the two should be close. + ! (This check can be removed once we address issue 1624, making the results of this + ! function depend on the actual ESMF calendar instead of a hard-coded value.) + curr_days_per_year = get_curr_days_per_year() + if (abs(avg_days_per_year - curr_days_per_year) > 1._r8) then + write(iulog,*) 'ERROR: hard-coded average days per year differs by more than expected' + write(iulog,*) 'from current days per year. Are you using a non-standard calendar?' + write(iulog,*) 'avg_days_per_year (hard-coded) = ', avg_days_per_year + write(iulog,*) 'curr_days_per_year (from ESMF calendar) = ', curr_days_per_year + write(iulog,*) 'You can fix this by changing the hard-coded parameters in '//subname + write(iulog,*) 'in file: '//sourcefile + call shr_sys_abort(subname//' ERROR: hard-coded average days per year differs by more than expected') + end if + + get_average_days_per_year = avg_days_per_year + + end function get_average_days_per_year + + !========================================================================================= + integer function get_curr_days_per_year( offset ) !---------------------------------------------------------------------------------