Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

time manager mixed precision #1091

Closed
wants to merge 10 commits into from

Conversation

rem1776
Copy link
Contributor

@rem1776 rem1776 commented Dec 14, 2022

Description
adds mixed precision real support to time manager.

From testing it looks like most of the assignment and operator overloads can't be overridden since there's no way to make distinct interfaces. This means time type to real conversions and divisions will be r8 and will need to be casted.

I changed the double precision types to real(r8_kind) since its more portable for any routines that use casted integers.

Fixes # (issue)

How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Please also note
any relevant details for your test configuration (e.g. compiler, OS). Include
enough information so someone can reproduce your tests.

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • Any dependent changes have been merged and published in downstream modules
  • New check tests, if applicable, are included
  • make distcheck passes

module procedure get_cal_time_r8
end interface

public :: get_cal_time
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why make this public underneath interface?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think i moved that on purpose, but the order doesn't matter for public statements.

@@ -150,28 +109,28 @@ contains
!!
!! @note This option was originally coded to allow noleap calendar as input when
!! the julian calendar was in effect by the time_manager.
function get_cal_time(time_increment, units, calendar, permit_calendar_conversion)
real, intent(in) :: time_increment
function GET_CAL_TIME(time_increment, units, calendar, permit_calendar_conversion) result(cal_time)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GET_CAL_TIME_

function get_cal_time(time_increment, units, calendar, permit_calendar_conversion)
real, intent(in) :: time_increment
function GET_CAL_TIME(time_increment, units, calendar, permit_calendar_conversion) result(cal_time)
real(FMS_TM_KIND), intent(in) :: time_increment
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FMS_TM_KIND_ for all the FMS_TM_KIND here

character(len=*), intent(in) :: units
character(len=*), intent(in) :: calendar
logical, intent(in), optional :: permit_calendar_conversion
type(time_type) :: get_cal_time
type(time_type) :: cal_time
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GET_CAL_TIME_?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the result to cal_time so it wouldn't have to be replaced by the macro each time it's used.

@@ -313,50 +272,33 @@ else if(lowercase(units(1:12)) == 'months since') then
increment_days = floor(dt/86400)
increment_seconds = int(dt - increment_days*86400)
else
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

between lines 244-273, there are several integers that need to be real(#,FMS_TM_KIND_) IT SEEMS

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah i skipped these cause I don't think the precision makes a difference here, especially for the floor ones. I'll add those in to be consistent though, might as well be explicit with it.

@@ -313,50 +272,33 @@ else if(lowercase(units(1:12)) == 'months since') then
increment_days = floor(dt/86400)
increment_seconds = int(dt - increment_days*86400)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

real(increment_days,FMS_TM_KIND_)

ticks_new = modulo(ticks,ticks_per_second)
days_new = days + floor(seconds_new/real(seconds_per_day))
days_new = days + floor(seconds_new/real(seconds_per_day, r8_kind))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

real(seconds_new,r8_kind)

@@ -456,7 +488,7 @@ function get_tick_from_string(string, err_msg, allow_rounding, tick)
magnitude = 10**nspf
tpsfrac = ticks_per_second*fraction
if(allow_rounding) then
tick = nint((real(tpsfrac)/magnitude))
tick = nint((real(tpsfrac, r8_kind)/magnitude))
else
if(modulo(tpsfrac,magnitude) == 0) then
tick = tpsfrac/magnitude
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int(tpsfrac/magnitude)

@@ -456,7 +488,7 @@ function get_tick_from_string(string, err_msg, allow_rounding, tick)
magnitude = 10**nspf
tpsfrac = ticks_per_second*fraction
if(allow_rounding) then
tick = nint((real(tpsfrac)/magnitude))
tick = nint((real(tpsfrac, r8_kind)/magnitude))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

real(magnitude, r8_kind)

type(time_type) :: time_scalar_mult
type(time_type), intent(in) :: time
integer, intent(in) :: n
integer :: days, seconds, ticks, num_sec
double precision :: sec_prod, tick_prod
real(r8_kind) :: sec_prod, tick_prod

if(.not.module_is_initialized) call time_manager_init

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember you bringing up the double issue. Since the precision should be the same/consistent between Intel and GCC compiled code, maybe should go with real() instead? Not sure.

write(outunit,'(a)') 'test successful: '//trim(err_msg)
endif
!! check equality between r4 and r8 returned types
if ( real_to_time_type(real(86401.1, r4_kind)) .ne. real_to_time_type(real(86401.1, r8_kind))) then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you think it would make a difference if using 86401.1_r4_kind and 86401.1_r8_kind?

@rem1776
Copy link
Contributor Author

rem1776 commented Apr 19, 2023

opening new pr

@rem1776 rem1776 closed this Apr 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants