Skip to content

Commit

Permalink
Python side
Browse files Browse the repository at this point in the history
  • Loading branch information
SouthEndMusic committed Apr 10, 2024
1 parent 35dfc2c commit 4812bca
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 5 deletions.
10 changes: 10 additions & 0 deletions core/src/schema.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# The identifier is parsed as ribasim.nodetype.kind, no capitals or underscores are allowed.
@schema "ribasim.discretecontrol.condition" DiscreteControlCondition
@schema "ribasim.discretecontrol.logic" DiscreteControlLogic
@schema "ribasim.discretecontrol.compoundvariable" DiscreteControlCompoundVariable
@schema "ribasim.basin.static" BasinStatic
@schema "ribasim.basin.time" BasinTime
@schema "ribasim.basin.profile" BasinProfile
Expand Down Expand Up @@ -183,6 +184,15 @@ end
node_id::Int32
end

@version DiscreteControlCompoundVariableV1 begin
node_id::Int32
name::String
listen_node_type::String
listen_node_id::Int
variable::String
weight::Float64
end

@version DiscreteControlConditionV1 begin
node_id::Int32
listen_node_type::String
Expand Down
5 changes: 5 additions & 0 deletions python/ribasim/ribasim/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
BasinStaticSchema,
BasinSubgridSchema,
BasinTimeSchema,
DiscreteControlCompoundVariableSchema,
DiscreteControlConditionSchema,
DiscreteControlLogicSchema,
FlowBoundaryStaticSchema,
Expand Down Expand Up @@ -287,6 +288,10 @@ class ManningResistance(MultiNodeModel):


class DiscreteControl(MultiNodeModel):
compound_variable: TableModel[DiscreteControlCompoundVariableSchema] = Field(
default_factory=TableModel[DiscreteControlCompoundVariableSchema],
json_schema_extra={"sort_keys": ["name"]},
)
condition: TableModel[DiscreteControlConditionSchema] = Field(
default_factory=TableModel[DiscreteControlConditionSchema],
json_schema_extra={
Expand Down
12 changes: 9 additions & 3 deletions python/ribasim/ribasim/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,11 +321,17 @@ def plot_control_listen(self, ax):
df_listen_edge = pd.concat([df_listen_edge, to_add])

# Listen edges from DiscreteControl
condition = self.discrete_control.condition.df
if condition is not None:
to_add = condition[
for table in (
self.discrete_control.condition.df,
self.discrete_control.compound_variable.df,
):
if table is None:
continue

to_add = table[
["node_id", "listen_node_id", "listen_node_type"]
].drop_duplicates()
to_add = to_add[to_add["listen_node_type"] != "compound"]
to_add.columns = ["control_node_id", "listen_node_id", "listen_node_type"]
to_add["control_node_type"] = "DiscreteControl"
df_listen_edge = pd.concat([df_listen_edge, to_add])
Expand Down
13 changes: 11 additions & 2 deletions python/ribasim/ribasim/nodes/discrete_control.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
from pandas import DataFrame

from ribasim.input_base import TableModel
from ribasim.schemas import DiscreteControlConditionSchema, DiscreteControlLogicSchema
from ribasim.schemas import (
DiscreteControlCompoundVariableSchema,
DiscreteControlConditionSchema,
DiscreteControlLogicSchema,
)

__all__ = ["Condition", "Logic"]
__all__ = ["Condition", "Logic", "CompoundVariable"]


class CompoundVariable(TableModel[DiscreteControlCompoundVariableSchema]):
def __init__(self, **kwargs):
super().__init__(df=DataFrame(dict(**kwargs)))

Check warning on line 15 in python/ribasim/ribasim/nodes/discrete_control.py

View check run for this annotation

Codecov / codecov/patch

python/ribasim/ribasim/nodes/discrete_control.py#L15

Added line #L15 was not covered by tests


class Condition(TableModel[DiscreteControlConditionSchema]):
Expand Down
9 changes: 9 additions & 0 deletions python/ribasim/ribasim/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ class BasinTimeSchema(_BaseSchema):
urban_runoff: Series[float] = pa.Field(nullable=True)


class DiscreteControlCompoundVariableSchema(_BaseSchema):
node_id: Series[Int32] = pa.Field(nullable=False, default=0)
name: Series[str] = pa.Field(nullable=False)
listen_node_type: Series[str] = pa.Field(nullable=False)
listen_node_id: Series[Int32] = pa.Field(nullable=False, default=0)
variable: Series[str] = pa.Field(nullable=False)
weight: Series[float] = pa.Field(nullable=False)


class DiscreteControlConditionSchema(_BaseSchema):
node_id: Series[Int32] = pa.Field(nullable=False, default=0)
listen_node_type: Series[str] = pa.Field(nullable=False)
Expand Down
2 changes: 2 additions & 0 deletions python/ribasim_testmodels/ribasim_testmodels/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
)
from ribasim_testmodels.bucket import bucket_model, leaky_bucket_model
from ribasim_testmodels.discrete_control import (
compound_variable_condition_model,
flow_condition_model,
level_boundary_condition_model,
level_setpoint_with_minmax_model,
Expand Down Expand Up @@ -64,6 +65,7 @@
"basic_model",
"basic_transient_model",
"bucket_model",
"compound_variable_condition_model",
"discrete_control_of_pid_control_model",
"dutch_waterways_model",
"flow_boundary_time_model",
Expand Down
60 changes: 60 additions & 0 deletions python/ribasim_testmodels/ribasim_testmodels/discrete_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,3 +390,63 @@ def level_setpoint_with_minmax_model() -> Model:
)

return model


def compound_variable_condition_model() -> Model:
"""
Set up a minimal model containing a condition on a compound variable
for discrete control.
"""

model = Model(
starttime="2020-01-01",
endtime="2021-01-01",
crs="EPSG:28992",
)

model.basin.add(
Node(1, Point(1, 0)),
[
basin.Profile(area=1000.0, level=[0.0, 1.0]),
basin.State(level=[1.0]),
],
)
model.flow_boundary.add(
Node(2, Point(0, 0)), [flow_boundary.Static(flow_rate=[0.0])]
)
model.flow_boundary.add(
Node(3, Point(0, 1)),
[flow_boundary.Time(time=["2020-01-01", "2022-01-01"], flow_rate=[0.0, 2.0])],
)
model.pump.add(
Node(4, Point(2, 0)),
[pump.Static(control_state=["Off", "On"], flow_rate=[0.0, 1.0])],
)
model.terminal.add(Node(5, Point(3, 0)))
model.discrete_control.add(
Node(6, Point(1, 1)),
[
discrete_control.CompoundVariable(
name="flow_mean",
listen_node_type="FlowBoundary",
listen_node_id=[2, 3],
variable="flow",
weight=0.5,
),
discrete_control.Condition(
listen_node_type="compound",
listen_node_id=[0], # Irrelevant
variable="flow_mean",
greater_than=1.0,
),
discrete_control.Logic(truth_state=["T", "F"], control_state=["On", "Off"]),
],
)

model.edge.add(model.flow_boundary[2], model.basin[1])
model.edge.add(model.flow_boundary[3], model.basin[1])
model.edge.add(model.basin[1], model.pump[4])
model.edge.add(model.pump[4], model.terminal[5])
model.edge.add(model.discrete_control[6], model.pump[4])

return model

0 comments on commit 4812bca

Please sign in to comment.