import attrs
import matplotlib.pyplot as plt
import numpy as np
from rscm.core import (
InterpolationStrategy,
ModelBuilder,
PythonComponent,
RequirementDefinition,
RequirementType,
TimeAxis,
Timeseries,
TimeseriesCollection,
)
@attrs.frozen
class ScaleComponent:
scale_factor: float
scale_year: int
def definitions(self) -> list[RequirementDefinition]:
return [
RequirementDefinition("input", "K", RequirementType.Input),
RequirementDefinition("output", "K", RequirementType.Output),
]
def solve(
self, time_current: float, time_next: float, input_state: dict[str, float]
) -> dict[str, float]:
if time_current > self.scale_year:
return {"output": input_state.get("input") * self.scale_factor}
else:
return {"output": input_state.get("input")}
scale_component = ScaleComponent(scale_factor=3, scale_year=2015)
res = scale_component.solve(2000, 1, {"input": 35.0})
assert res["output"] == 35.0
res = scale_component.solve(2050, 1, {"input": 35.0})
assert res["output"] == 35.0 * 3.0
component_in_rust = PythonComponent.build(scale_component)
collection = TimeseriesCollection()
collection.add_timeseries(
"input",
Timeseries(
np.asarray([35.0, 35.0]),
TimeAxis.from_bounds(np.asarray([2000.0, 2001.0, 2002.0])),
"K",
InterpolationStrategy.Previous,
),
)
res = component_in_rust.solve(2000, 2001, collection)
assert res["output"] == 35.0, res["output"]
input_ts = Timeseries(
np.asarray([1.0, 2.0, 3.0]),
TimeAxis.from_values(np.asarray([1850.0, 2000.0, 2100.0])),
"K",
InterpolationStrategy.Previous,
)
time_axis = TimeAxis.from_bounds(np.arange(1750.0, 2100, 10.0))
model = (
ModelBuilder()
.with_py_component(component_in_rust)
.with_time_axis(time_axis)
.with_exogenous_variable("input", input_ts)
).build()
model.run()
result = model.timeseries()
result
plt.plot(time_axis.values(), result.get_timeseries_by_name("input").values())
plt.plot(time_axis.values(), result.get_timeseries_by_name("output").values())
assert result.get_timeseries_by_name("input").at_time(1800.0) == 1.0
assert (
result.get_timeseries_by_name("output").at_time(1800.0) == 2.0
) assert result.get_timeseries_by_name("input").at_time(2050.0) == 2.0
assert result.get_timeseries_by_name("output").at_time(2050.0) == 2.0 * 3.0