"""Subside a `SequenceModelGrid`."""
from __future__ import annotations
import os
from collections.abc import Callable
import numpy as np
from landlab import Component
from numpy.typing import NDArray
from scipy import interpolate
from sequence.grid import SequenceModelGrid
[docs]
class SubsidenceTimeSeries(Component):
"""A *Landlab* component that subsides a grid."""
_name = "Subsider"
_time_units = "y"
_info = {
"bedrock_surface__increment_of_elevation": {
"dtype": "float",
"intent": "inout",
"optional": False,
"units": "m",
"mapping": "node",
"doc": "Change in elevation due to subsidence",
}
}
[docs]
def __init__(
self, grid: SequenceModelGrid, filepath: os.PathLike, kind: str = "linear"
):
"""Create a grid subsider from a time-series file.
Parameters
----------
grid: SequenceModelGrid
A landlab grid.
filepath: os.PathLike
Name of csv-formatted subsidence file.
kind: str, optional
Kind of interpolation as a string (one of 'linear',
'nearest', 'zero', 'slinear', 'quadratic', 'cubic').
Default is 'linear'.
"""
if "bedrock_surface__increment_of_elevation" not in grid.at_node:
grid.add_zeros("bedrock_surface__increment_of_elevation", at="node")
super().__init__(grid)
self._filepath = filepath
self._kind = kind
data = np.loadtxt(filepath, delimiter=",", comments="#")
self._subsidence = SubsidenceTimeSeries._subsidence_interpolator(
data, kind=self._kind
)
self._dz_dt = self._calc_subsidence_rate()
self._time = 0.0
@property
def subsidence_rate(self) -> NDArray:
"""Return the current subsidence rate."""
return self._dz_dt
@staticmethod
def _subsidence_interpolator(
data: NDArray, kind: str = "linear"
) -> Callable[[float | NDArray], NDArray]:
return interpolate.interp1d(
data[:, 0],
data[:, 1],
kind=kind,
copy=True,
assume_sorted=True,
bounds_error=True,
)
def _calc_subsidence_rate(self) -> NDArray:
return self._subsidence(self.grid.x_of_node[self.grid.nodes_at_bottom_edge])
@property
def time(self) -> float:
"""Return the current component time."""
return self._time
@property
def filepath(self) -> str:
"""Return the path to the current subsidence file."""
return str(self._filepath)
@filepath.setter
def filepath(self, new_path: os.PathLike) -> None:
self._filepath = new_path
self._subsidence = SubsidenceTimeSeries._subsidence_interpolator(
np.loadtxt(self._filepath, delimiter=",", comments="#"), kind=self._kind
)
self._dz_dt = self._calc_subsidence_rate()
[docs]
def run_one_step(self, dt: float) -> None:
"""Update the component by a time step.
Parameters
----------
dt : float
The time step to update the component by.
"""
self.grid.get_profile("bedrock_surface__increment_of_elevation")[:] += (
self.subsidence_rate * dt
)
self._time += dt