105 lines
3.3 KiB
Python
105 lines
3.3 KiB
Python
from app.native.wndb.commands.executor import execute_batch_command
|
|
from app.native.wndb.core.database import ChangeSet
|
|
from app.native.wndb.gis.region_geometry import Topology, get_nodes_in_region
|
|
from app.native.wndb.gis.network_views import (
|
|
get_junction_demands,
|
|
sum_junction_base_demand,
|
|
)
|
|
from app.native.wndb.model.elements import get_nodes
|
|
|
|
|
|
DISTRIBUTION_TYPE_ADD = 'ADD'
|
|
DISTRIBUTION_TYPE_OVERRIDE = 'OVERRIDE'
|
|
|
|
|
|
def calculate_demand_to_nodes(name: str, demand: float, nodes: list[str]) -> dict[str, float]:
|
|
if len(nodes) == 0 or demand == 0.0:
|
|
return {}
|
|
|
|
topology = Topology(name, nodes)
|
|
t_nodes = topology.nodes()
|
|
t_links = topology.links()
|
|
|
|
length_sum = 0.0
|
|
for value in t_links.values():
|
|
length_sum += abs(value['length'])
|
|
|
|
if length_sum <= 0.0:
|
|
return {}
|
|
|
|
demand_per_length = demand / length_sum
|
|
|
|
result: dict[str, float] = {}
|
|
for node, value in t_nodes.items():
|
|
if value["type"] != "junction":
|
|
continue
|
|
demand_per_node = 0.0
|
|
for link in value['links']:
|
|
demand_per_node += abs(t_links[link]['length']) * demand_per_length * 0.5
|
|
result[node] = demand_per_node
|
|
|
|
return result
|
|
|
|
|
|
def calculate_demand_to_region(name: str, demand: float, region: str) -> dict[str, float]:
|
|
nodes = get_nodes_in_region(name, region)
|
|
return calculate_demand_to_nodes(name, demand, nodes)
|
|
|
|
|
|
def calculate_demand_to_network(name: str, demand: float) -> dict[str, float]:
|
|
nodes = get_nodes(name)
|
|
return calculate_demand_to_nodes(name, demand, nodes)
|
|
|
|
|
|
def distribute_demand_to_nodes(name: str, demand: float, nodes: list[str], type: str = DISTRIBUTION_TYPE_ADD) -> ChangeSet:
|
|
if len(nodes) == 0 or demand == 0.0:
|
|
return ChangeSet()
|
|
if type != DISTRIBUTION_TYPE_ADD and type != DISTRIBUTION_TYPE_OVERRIDE:
|
|
return ChangeSet()
|
|
|
|
topology = Topology(name, nodes)
|
|
t_nodes = topology.nodes()
|
|
t_links = topology.links()
|
|
|
|
length_sum = 0.0
|
|
for value in t_links.values():
|
|
length_sum += abs(value['length'])
|
|
|
|
if length_sum <= 0.0:
|
|
return ChangeSet()
|
|
|
|
demand_per_length = demand / length_sum
|
|
|
|
cs = ChangeSet()
|
|
demands_by_junction = get_junction_demands(
|
|
name,
|
|
[node for node, value in t_nodes.items() if value["type"] == "junction"],
|
|
)
|
|
|
|
for node, value in t_nodes.items():
|
|
if value["type"] != "junction":
|
|
continue
|
|
demand_per_node = 0.0
|
|
for link in value['links']:
|
|
demand_per_node += abs(t_links[link]['length']) * demand_per_length * 0.5
|
|
|
|
ds = demands_by_junction.get(node, [])
|
|
if len(ds) == 0:
|
|
ds = [{'demand': demand_per_node, 'pattern': None, 'category': None}]
|
|
elif type == DISTRIBUTION_TYPE_ADD:
|
|
ds[0]['demand'] += demand_per_node
|
|
else:
|
|
ds[0]['demand'] = demand_per_node
|
|
cs.update({'type': 'demand', 'junction': node, 'demands': ds})
|
|
|
|
return execute_batch_command(name, cs)
|
|
|
|
|
|
def distribute_demand_to_region(name: str, demand: float, region: str, type: str = DISTRIBUTION_TYPE_ADD) -> ChangeSet:
|
|
nodes = get_nodes_in_region(name, region)
|
|
return distribute_demand_to_nodes(name, demand, nodes, type)
|
|
|
|
def get_total_base_demand(name: str, region: str) -> float:
|
|
nodes = get_nodes_in_region(name, region)
|
|
return sum_junction_base_demand(name, nodes)
|