Source code for hydrocouple.temporal
"""
HydroCouple temporal abstract base classes.
Python ABC mirrors of the C++ HydroCouple v2.0.0 interfaces defined in
``hydrocoupletemporal.h``: date/time representation, time spans,
time-marching model components, and time-series component data items.
"""
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING
from hydrocouple.core import (
IComponentDataItem,
IDimension,
IModelComponent,
IPropertyChanged,
)
if TYPE_CHECKING:
import numpy as np
[docs]
class IDateTime(IPropertyChanged):
"""A date/time based on a Julian day.
Mirrors C++ ``Temporal::IDateTime``. The normative convention is the
astronomical Julian day number in the proleptic Gregorian ("standard")
calendar, UTC; persistence layers writing CF metadata should emit
``units = "days since ..."`` with ``calendar = "standard"``.
"""
@property
@abstractmethod
def julian_day(self) -> float:
"""Date and time as a Julian day value."""
raise NotImplementedError
@property
@abstractmethod
def modified_julian_day(self) -> float:
"""Modified Julian day value."""
raise NotImplementedError
@property
@abstractmethod
def serial_date(self) -> float:
"""Serial date number."""
raise NotImplementedError
[docs]
class ITimeSpan(IDateTime):
"""A time duration anchored at a start date/time.
Mirrors C++ ``Temporal::ITimeSpan``.
"""
@property
@abstractmethod
def duration(self) -> float:
"""Duration of the timespan in days."""
raise NotImplementedError
[docs]
class ITimeModelComponent(IModelComponent):
"""A model component that advances through time during simulation.
Mirrors C++ ``Temporal::ITimeModelComponent``.
"""
@property
@abstractmethod
def current_date_time(self) -> IDateTime:
"""Current date and time of the model simulation."""
raise NotImplementedError
@property
@abstractmethod
def simulation_period(self) -> ITimeSpan:
"""The time horizon of the model."""
raise NotImplementedError
[docs]
class ITimeSeriesComponentDataItem(IComponentDataItem):
"""An :class:`~hydrocouple.core.IComponentDataItem` with a temporal
dimension.
Mirrors C++ ``Temporal::ITimeSeriesComponentDataItem``. Canonical
dimension ordering: time is dimension 0 of :attr:`shape`; any
additional dimensions follow. Data access uses the inherited
:meth:`~hydrocouple.core.IComponentDataItem.get_values_into` /
:meth:`~hydrocouple.core.IComponentDataItem.set_values_from` hyperslab
API with the time index as ``start[0]``, so "current time step, all
entities" is a contiguous slab.
"""
[docs]
@abstractmethod
def time(self, time_index: int) -> IDateTime:
"""The :class:`IDateTime` at the given time index (spot queries)."""
raise NotImplementedError
@property
@abstractmethod
def time_count(self) -> int:
"""The number of times."""
raise NotImplementedError
@property
@abstractmethod
def times(self) -> "np.ndarray":
"""Bulk access to all time coordinates as Julian day values.
A float64 array of :attr:`time_count` elements ordered with the
time dimension; the accessor IO writers and interpolating adapters
must use.
"""
raise NotImplementedError
@property
@abstractmethod
def time_span(self) -> ITimeSpan:
"""The time span covered by this data item."""
raise NotImplementedError
@property
@abstractmethod
def time_dimension(self) -> IDimension:
"""The time dimension (dimension 0 of :attr:`shape`)."""
raise NotImplementedError
[docs]
class ITimeIdBasedComponentDataItem(ITimeSeriesComponentDataItem):
"""A time-series data item whose entity dimension is identifier-based.
Mirrors C++ ``Temporal::ITimeIdBasedComponentDataItem``. Canonical
dimension ordering: time is dimension 0, the identifier dimension is
dimension 1 of :attr:`shape`; any additional dimensions follow.
"""
@property
@abstractmethod
def identifiers(self) -> list[str]:
"""The identifiers of the identifier dimension."""
raise NotImplementedError
@property
@abstractmethod
def identifier_dimension(self) -> IDimension:
"""The identifier dimension (dimension 1 of :attr:`shape`)."""
raise NotImplementedError