movici_drinking_water_model

attributes

Attribute specifications for drinking water network simulation using WNTR

Attribute naming follows the documentation specification: - drinking_water.* : Drinking water specific attributes - shape.* : Physical shape attributes (diameter, length, curves) - geometry.z : Elevation (from PointEntity) - operational.* : Operational status - topology.* : Network topology (from LinkEntity) - type : Entity type enum (string values)

dataset

Entity definitions for drinking water network simulation

Entity groups follow the documentation specification with:

  • drinking_water.* attributes for water-specific properties

  • shape.* attributes for physical dimensions

  • geometry.z for elevation (redeclared as INIT where required)

  • operational.status for link status

  • type attribute for pump/valve type enums

class DrinkingWaterNetwork(junctions: movici_drinking_water_model.dataset.WaterJunctionEntity, tanks: movici_drinking_water_model.dataset.WaterTankEntity, reservoirs: movici_drinking_water_model.dataset.WaterReservoirEntity, pipes: movici_drinking_water_model.dataset.WaterPipeEntity, pumps: movici_drinking_water_model.dataset.WaterPumpEntity, valves: movici_drinking_water_model.dataset.WaterValveEntity)

Bases: object

junctions: WaterJunctionEntity
pipes: WaterPipeEntity
pumps: WaterPumpEntity
reservoirs: WaterReservoirEntity
tanks: WaterTankEntity
valves: WaterValveEntity
class WaterJunctionEntity(name: str | None = None, optional: bool | None = None, exclude: Iterable[str] | None = None, override_exclude: Iterable[str] | None = None)

Bases: WaterNodeEntity

Water network junctions (demand nodes).

Junctions are nodes in the drinking water network. They connect pipes and can be used as demand nodes.

base_demand
demand_factor
elevation
minimum_pressure
pressure_exponent
required_pressure
class WaterLinkEntity(name: str | None = None, optional: bool | None = None, exclude: Iterable[str] | None = None, override_exclude: Iterable[str] | None = None)

Bases: LinkEntity

Base class for water network link entities with common output attributes.

flow
flow_rate_magnitude
is_ready()
class WaterNodeEntity(name: str | None = None, optional: bool | None = None, exclude: Iterable[str] | None = None, override_exclude: Iterable[str] | None = None)

Bases: PointEntity

Base class for water network node entities with common output attributes.

demand
head
is_ready()
pressure
class WaterPipeEntity(name: str | None = None, optional: bool | None = None, exclude: Iterable[str] | None = None, override_exclude: Iterable[str] | None = None)

Bases: WaterLinkEntity

Water pipes.

Pipes transport water from one node at high head to another at lower head, experiencing pressure drop (head loss) in the process.

check_valve
diameter
length
minor_loss
roughness
status
velocity
class WaterPumpEntity(name: str | None = None, optional: bool | None = None, exclude: Iterable[str] | None = None, override_exclude: Iterable[str] | None = None)

Bases: WaterLinkEntity

Water pumps.

Pumps increase the head from one node to another. Two types:

  • Power pump: Fixed power

  • Head pump: Uses head curve

head_curve
power
pump_type
status
class WaterReservoirEntity(name: str | None = None, optional: bool | None = None, exclude: Iterable[str] | None = None, override_exclude: Iterable[str] | None = None)

Bases: WaterNodeEntity

Water reservoirs (infinite head sources).

A reservoir is a tank that never empties. It has a fixed head which can be scaled by a multiplier. Reservoirs can act as water sources or drains depending on the head relative to connected nodes.

Note

Reservoirs don’t use elevation - head is specified directly.

base_head
flow
flow_rate_magnitude
head_factor
class WaterTankEntity(name: str | None = None, optional: bool | None = None, exclude: Iterable[str] | None = None, override_exclude: Iterable[str] | None = None)

Bases: WaterNodeEntity

Water storage tanks.

Tanks are buffers for drinking water. They are transient elements - as simulation progresses, tanks may fill up or empty over time.

Tank volume can be defined either by:

  • Constant diameter (cylindrical tank): use diameter, min_level, max_level

  • Volume curve (non-cylindrical): use volume_curve, min_level, max_level

diameter
elevation
level
max_level
min_level
volume_curve
class WaterValveEntity(name: str | None = None, optional: bool | None = None, exclude: Iterable[str] | None = None, override_exclude: Iterable[str] | None = None)

Bases: WaterLinkEntity

Water valves.

Valves reduce flow in a controlled manner. Types:

  • PRV (Pressure Reducing): Limits downstream pressure

  • PSV (Pressure Sustaining): Maintains upstream pressure

  • FCV (Flow Control): Limits maximum flow

  • TCV (Throttle Control): Uses loss coefficient

Note

GPV and PBV valves are not supported by the WNTRSimulator.

diameter
minor_loss
status
valve_flow
valve_loss_coefficient
valve_pressure
valve_type

epanet_source

EPANET INP file DataSource for the dataset creator, backed by WNTR.

class EPANETSource(file: Path | str)

Bases: MultipleEntityTypeSource

Multi-entity source for reading EPANET INP files via WNTR.

Registered as the "epanet" source type for the dataset creator. Contains entity types: junctions, tanks, reservoirs, pipes, pumps, valves. Use bracket notation to access individual entity types as DataSources:

source = EPANETSource("network.inp")
junctions = source["junctions"]
len(junctions)
junctions.get_attribute("elevation")

The WNTR model is loaded lazily on first entity-type access and shared across sub-sources of the same EPANETSource instance.

Parameters:

file – Path to the INP file

ENTITY_TYPES = frozenset({'junctions', 'pipes', 'pumps', 'reservoirs', 'tanks', 'valves'})
classmethod from_source_info(source_info)

Create from a source info dictionary.

If entity_type is present in the source info, returns a single-entity DataSource for that type; otherwise returns the full multi-entity source.

get_bounding_box()
keys() Iterable[str]

model

Water network simulation model using WNTR.

This model simulates drinking water distribution networks using the WNTR (Water Network Tool for Resilience) library. It supports hydraulic simulation including pressure, flow, and velocity calculations.

Note

Controls (time-based or conditional) are NOT handled internally by this model. Use the Movici Rules Model to implement control logic externally.

class Model(model_config: dict)

Bases: TrackedModel

Water network simulation model using WNTRSimulator.

This model simulates water distribution networks including:

  • Hydraulic simulation (pressure, flow, velocity)

  • Support for pipes, pumps, valves, tanks, and reservoirs

  • CSR curve data for pump head curves and tank volume curves

Note

Controls are handled by the Movici Rules Model, not internally.

auto_reset = 8
classmethod get_schema_attributes()

Return all AttributeSpecs used by this model.

Returns:

Sequence of AttributeSpec objects

initialize(state: TrackedState)

Initialize model: validate network and configure WNTR.

Parameters:

state – Tracked state

setup(state: TrackedState, logger: Logger, **kwargs)

Setup the model and initialize network.

Parameters:
  • state – Tracked state for entity registration

  • schema – Attribute schema

shutdown(state: TrackedState)

Clean up resources.

Parameters:

state – Tracked state

update(state: TrackedState, moment: Moment) Moment | None

Update simulation at each timestep.

Parameters:
  • state – Tracked state

  • moment – Current simulation moment

Returns:

Next update time or None

network_wrapper

Main wrapper for WNTR WaterNetworkModel with Movici integration.

This module provides a clean interface between Movici’s entity-based data model and WNTR’s water network simulation engine.

class IdMapper

Bases: object

Maps between Movici integer IDs and WNTR string names.

Each processor registers its entities with a type-specific prefix (e.g. "J" for junctions, "P" for pipes), producing WNTR names like "J5" or "P101".

get_wntr_name(entity_id: int) str

Get WNTR name for a Movici ID.

Parameters:

movici_id – Movici entity ID

Returns:

WNTR name string

register(entity_id: int, wntr_name: str)
class JunctionProcessor(wrapper: NetworkWrapper, entity_group: T)

Bases: NodeProcessor[WaterJunctionEntity]

PREFIX: str = 'J'
create_elements()
update_elements()
class LinkProcessor(wrapper: NetworkWrapper, entity_group: T)

Bases: WNTRElementProcessor[L]

Base for link processors that write flow, flow_rate_magnitude, link_status.

Subclasses must define PREFIX (e.g. "P" for pipes).

PREFIX: str
write_results(results: SimulationResults, df_offset: int)
class NetworkWrapper(logger: Logger | None = None)

Bases: object

Wraps WNTR WaterNetworkModel with Movici-friendly API.

This class provides a clean interface between Movici’s entity-based data model and WNTR’s water network simulation engine.

add_curve(curve_data: ndarray, curve_type: str) str

Add a curve to the WNTR network.

Parameters:
  • curve_data – Numpy array of shape (N, 2) with x, y points

  • curve_type – Type of curve ("HEAD", "VOLUME", etc.)

Returns:

Name of the created curve

close()

Clean up resources.

configure_options(options: dict)

Configure WNTR options from a dict of section_name -> {key: value} mappings.

Parameters:

options – Dict mapping section names to dicts of option key/value pairs

initialize(dataset: DrinkingWaterNetwork)

Build the WNTR WaterNetworkModel from a DrinkingWaterNetwork.

Parameters:

dataset – A valid DrinkingWaterNetwork whose entity groups have been loaded with init data.

process_changes()

Process any changes to the DrinkingWaterNetwork that may have happened and update the WNTR WaterNetworkModel.

processors: dict[str, WNTRElementProcessor]
run_simulation(new_time: int, hydraulic_timestep: int) SimulationResults

Run WNTR simulation for one step using pause/restart.

The simulator is kept alive across calls so that WNTR’s internal state (tank levels, solver state) carries forward between timesteps. Duration is cumulative: each call advances sim_time by step.

Parameters:
  • new_time – the new simulation time to progress the internal WNTR network to

  • hydraulic_timestep – Hydraulic timestep in seconds

Returns:

WNTR SimulationResults object

write_results(results: SimulationResults)

Write WNTR results back into entity group arrays.

The results dataframe columns are ordered by category then insertion order. Nodes: Junction, Tank, Reservoir. Links: Pipe, Pump, Valve.

When adding new element types, the correct order in the result dataframe must be determined to calculate the right offset for each element’s data.

class NodeProcessor(wrapper: NetworkWrapper, entity_group: T)

Bases: WNTRElementProcessor[N]

Base for node processors that write head & pressure.

Subclasses must define PREFIX (e.g. "J" for junctions).

PREFIX: str
write_results(results: SimulationResults, df_offset: int)
class PipeProcessor(wrapper: NetworkWrapper, entity_group: T)

Bases: LinkProcessor[WaterPipeEntity]

PREFIX: str = 'P'
create_elements()
update_elements()
class PumpProcessor(wrapper: NetworkWrapper, entity_group: T)

Bases: LinkProcessor[WaterPumpEntity]

PREFIX: str = 'PU'
create_elements()
update_elements()
class ReservoirProcessor(wrapper: NetworkWrapper, entity_group: T)

Bases: NodeProcessor[WaterReservoirEntity]

PREFIX: str = 'R'
create_elements()
update_elements()
class TankProcessor(wrapper: NetworkWrapper, entity_group: T)

Bases: NodeProcessor[WaterTankEntity]

PREFIX: str = 'T'
create_elements()
class ValveProcessor(wrapper: NetworkWrapper, entity_group: T)

Bases: LinkProcessor[WaterValveEntity]

PREFIX: str = 'V'
create_elements()
update_elements()
class WNTRElementProcessor(wrapper: NetworkWrapper, entity_group: T)

Bases: Generic[T]

create_elements()
update_elements()
property wn: WaterNetworkModel
write_results(results: SimulationResults, df_offset: int)