REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_DateClock.H File Reference
#include <algorithm>
#include <cmath>
#include <type_traits>
#include <AMReX_REAL.H>
#include <AMReX_Extension.H>
#include <AMReX_GpuQualifiers.H>
Include dependency graph for REMORA_DateClock.H:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int remora_yearday (int year, int month, int day) noexcept
 Day of the year for a calendar date. ROMS yearday.
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real remora_datenum (amrex::Real time_ref, int year, int month, int day, int hour=0, int minutes=0, amrex::Real seconds=amrex::Real(0.0)) noexcept
 Fractional day number for a calendar date. ROMS datenum.
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real remora_ref_datenum (amrex::Real time_ref) noexcept
 Day number of the reference date implied by time_ref.
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void remora_datevec (amrex::Real time_ref, amrex::Real date_number, bool is_day_units, int &year, int &month, int &day) noexcept
 Calendar date for a day (or second) number. ROMS datevec.
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void remora_caldate (amrex::Real time_ref, amrex::Real current_time_days, int &year, int &month, int &day, amrex::Real &yday) noexcept
 Model time in days to calendar date. ROMS caldate.
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void remora_caldate (amrex::Real time_ref, amrex::Real current_time_days, int &year, amrex::Real &yday) noexcept
 remora_caldate for callers that only want the year and day of year.
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool remora_time_ref_is_valid (amrex::Real time_ref) noexcept
 Whether time_ref names a calendar this header implements.
 
AMREX_FORCE_INLINE bool remora_time_ref_is_representable (amrex::Real time_ref) noexcept
 Whether time_ref survives a round trip through amrex::Real.
 

Variables

static constexpr int remora_gregorian_daynum = 2299161
 

Detailed Description

Model time to calendar date, ported from ROMS dateclock.F.

The model clock is elapsed time since a reference date, and remora.time_ref both sets that date and picks the calendar, exactly as ROMS TIME_REF does:

time_ref calendar epoch year length
yyyymmdd.dd proleptic Gregorian the date given 365.2425 d
0 proleptic Gregorian 0001-01-01 00:00:00 365.2425 d
-1 360_day 0000-12-30 00:00:00 360 d
-2 Gregorian, truncated 1968-05-23 00:00:00 365.25 d

Julian day (NASA)

time_ref is passed in rather than read from a global, so these stay pure functions; ROMS keeps the equivalent in Rclock in mod_scalars. The reference date number is recomputed per call, which is a handful of integer operations, rather than cached.

The arithmetic is deliberately a transcription rather than a tidier equivalent. Fortran INT and AINT truncate toward zero, as do a C++ cast to int and std::trunc, and C++ integer division truncates toward zero too, so each expression carries over term for term. Where ROMS uses FLOOR – and in the time_ref = -2 conversion it does, which rounds differently from INT on the negative side of the epoch – std::floor is used here.

Hours, minutes and seconds are not returned. ROMS derives them from the day fraction through the tolerant rounding helper in round_mod, and half-porting that would be worse than leaving it out; the day fraction is available from remora_caldate's yday for a caller that needs it.

Two quirks of the time_ref = -2 calendar carry over, both ROMS's and both confirmed against the Fortran rather than inferred:

  • datenum splits the year as y01 = MyYear/100, which truncates toward zero, so it disagrees with the true Julian day number for years before 0. dateclock.F documents datenum(-4713,11,24) = 0; its own code returns 1, and so does this. From year 1 on it agrees with the standard Fliegel-Van Flandern day number exactly.
  • datevec treats any day number below the 15 October 1582 changeover as a truncated one and adds the reference offset back, so it does not invert datenum before that date. That is the heuristic ROMS uses to accept both full and truncated Julian days in the same argument.

Neither affects a model run in modern times, which is what this calendar is for, but both would bite anyone reaching further back with it.

Definition in file REMORA_DateClock.H.

Function Documentation

◆ remora_caldate() [1/2]

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void remora_caldate ( amrex::Real  time_ref,
amrex::Real  current_time_days,
int &  year,
amrex::Real &  yday 
)
noexcept

remora_caldate for callers that only want the year and day of year.

Definition at line 333 of file REMORA_DateClock.H.

Here is the call graph for this function:

◆ remora_caldate() [2/2]

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void remora_caldate ( amrex::Real  time_ref,
amrex::Real  current_time_days,
int &  year,
int &  month,
int &  day,
amrex::Real &  yday 
)
noexcept

Model time in days to calendar date. ROMS caldate.

Parameters
[in]time_refremora.time_ref; see the table at the top
[in]current_time_daysmodel time in days, as ROMS tdays
[out]yearyear including century
[out]monthmonth of the year, 1 = January
[out]dayday of the month
[out]ydayday of the year, including the day fraction, so 00:00 on the first day of the year is exactly 1.0

Definition at line 303 of file REMORA_DateClock.H.

Referenced by remora_caldate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ remora_datenum()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real remora_datenum ( amrex::Real  time_ref,
int  year,
int  month,
int  day,
int  hour = 0,
int  minutes = 0,
amrex::Real  seconds = amrex::Real(0.0) 
)
noexcept

Fractional day number for a calendar date. ROMS datenum.

Reference values, per calendar:

  • proleptic Gregorian: datenum(0000,01,01) = 1, datenum(0001,01,01) = 367. The origin is Matlab's datenum(0000,00,00) = 0, hence the 61-day offset.
  • 360_day: datenum(0000,01,01) = 0, datenum(0001,01,01) = 360.
  • truncated Julian: datenum(-4713,11,24) = 0, datenum(1968,05,23) = 2440000.

Definition at line 84 of file REMORA_DateClock.H.

Referenced by remora_ref_datenum().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ remora_datevec()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void remora_datevec ( amrex::Real  time_ref,
amrex::Real  date_number,
bool  is_day_units,
int &  year,
int &  month,
int &  day 
)
noexcept

Calendar date for a day (or second) number. ROMS datevec.

is_day_units selects fractional days over fractional seconds, as ROMS's IsDayUnits does.

ROMS's time_ref = -2 branch can also run a proleptic Julian conversion, but its ProlepticJulian switch is a local hardcoded to .FALSE., so that path is unreachable as shipped and is not ported.

Definition at line 192 of file REMORA_DateClock.H.

Referenced by remora_caldate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ remora_ref_datenum()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real remora_ref_datenum ( amrex::Real  time_ref)
noexcept

Day number of the reference date implied by time_ref.

ROMS ref_clock, reduced to the one field the rest of this header needs: RclockDateNumber(1). The two negative calendars carry hardcoded values in ROMS – 359 for 360_day, whose epoch is shifted to 0000-12-30 to undo a historical one-day offset, and 2440000 for the truncated Julian day.

Definition at line 151 of file REMORA_DateClock.H.

Referenced by remora_caldate(), and remora_datevec().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ remora_time_ref_is_representable()

AMREX_FORCE_INLINE bool remora_time_ref_is_representable ( amrex::Real  time_ref)
noexcept

Whether time_ref survives a round trip through amrex::Real.

A yyyymmdd.dd date carries eight significant integer digits, and remora_ref_datenum pulls the year, month, and day back out of them arithmetically. That needs those digits to be exact. A single-precision Real has a 24-bit mantissa, so integers above 2^24 (16777216) are not representable and every date from year 1678 on rounds to a neighbouring value – which then decodes to a different calendar date with nothing to flag it. The three sentinel calendars (0, -1, -2) are small integers and are always fine.

Definition at line 365 of file REMORA_DateClock.H.

Referenced by SolverChoice::init_params().

Here is the caller graph for this function:

◆ remora_time_ref_is_valid()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool remora_time_ref_is_valid ( amrex::Real  time_ref)
noexcept

Whether time_ref names a calendar this header implements.

ROMS's CALENDAR if-chain has no final ELSE, so a value below -2 leaves the date undefined rather than failing. Callers should reject it up front.

Definition at line 348 of file REMORA_DateClock.H.

Referenced by SolverChoice::init_params().

Here is the caller graph for this function:

◆ remora_yearday()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int remora_yearday ( int  year,
int  month,
int  day 
)
noexcept

Day of the year for a calendar date. ROMS yearday.

Definition at line 67 of file REMORA_DateClock.H.

Referenced by remora_caldate().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ remora_gregorian_daynum

constexpr int remora_gregorian_daynum = 2299161
staticconstexpr

Reference day number of the 15 October 1582 Gregorian changeover, as ROMS spells it in datevec.

Definition at line 63 of file REMORA_DateClock.H.

Referenced by remora_datevec().