fix(simulation): use hydraulic timestep
This commit is contained in:
@@ -29,6 +29,7 @@ import pytz
|
||||
import requests
|
||||
import time
|
||||
import app.services.project_info as project_info
|
||||
from app.services.time_api import parse_clock_duration_seconds
|
||||
|
||||
url_path = 'http://10.101.15.16:9000/loong' # 内网
|
||||
# url_path = 'http://183.64.62.100:9057/loong' # 外网
|
||||
@@ -551,21 +552,11 @@ def from_clock_to_seconds (clock: str)->int:
|
||||
return hr*3600+mnt*60+seconds
|
||||
|
||||
def from_clock_to_seconds_2 (clock: str)->int:
|
||||
str_format="%H:%M:%S"
|
||||
dt=datetime.strptime(clock,str_format)
|
||||
hr=dt.hour
|
||||
mnt=dt.minute
|
||||
seconds=dt.second
|
||||
return hr*3600+mnt*60+seconds
|
||||
return parse_clock_duration_seconds(clock)
|
||||
|
||||
|
||||
def from_clock_to_seconds_3 (clock: str)->int:
|
||||
str_format = "%H:%M" # 更新时间格式以适应 "小时:分钟" 格式
|
||||
dt = datetime.strptime(clock,str_format)
|
||||
hr = dt.hour
|
||||
mnt = dt.minute
|
||||
seconds = dt.second
|
||||
return hr * 3600 + mnt * 60
|
||||
return parse_clock_duration_seconds(clock)
|
||||
|
||||
|
||||
###convert datetimestring
|
||||
|
||||
@@ -35,7 +35,11 @@ from app.services.simulation_ops import (
|
||||
daily_scheduling_simulation,
|
||||
)
|
||||
from app.services.valve_isolation import analyze_valve_isolation
|
||||
from app.services.time_api import parse_aware_time, parse_utc_time
|
||||
from app.services.time_api import (
|
||||
parse_aware_time,
|
||||
parse_clock_duration_seconds,
|
||||
parse_utc_time,
|
||||
)
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
|
||||
router = APIRouter()
|
||||
@@ -118,6 +122,14 @@ def run_simulation_manually_by_date(
|
||||
network_name: str, start_time: datetime, duration: int
|
||||
) -> None:
|
||||
end_datetime = start_time + timedelta(minutes=duration)
|
||||
time_properties = simulation.get_time(network_name)
|
||||
hydraulic_step_seconds = parse_clock_duration_seconds(
|
||||
time_properties["HYDRAULIC TIMESTEP"],
|
||||
field_name="HYDRAULIC TIMESTEP",
|
||||
)
|
||||
if hydraulic_step_seconds <= 0:
|
||||
raise ValueError("HYDRAULIC TIMESTEP must be greater than 0.")
|
||||
hydraulic_step = timedelta(seconds=hydraulic_step_seconds)
|
||||
current_time = start_time
|
||||
while current_time < end_datetime:
|
||||
simulation.run_simulation(
|
||||
@@ -125,7 +137,7 @@ def run_simulation_manually_by_date(
|
||||
simulation_type="realtime",
|
||||
modify_pattern_start_time=current_time.isoformat(timespec="seconds"),
|
||||
)
|
||||
current_time += timedelta(minutes=15)
|
||||
current_time += hydraulic_step
|
||||
|
||||
|
||||
# 必须用这个PlainTextResponse,不然每个key都有引号
|
||||
|
||||
@@ -28,12 +28,13 @@ import pytz
|
||||
import requests
|
||||
import time
|
||||
from typing import Optional, Tuple
|
||||
import app.infra.db.influxdb.api as influxdb_api
|
||||
import typing
|
||||
import psycopg
|
||||
import logging
|
||||
import app.services.globals as globals
|
||||
import app.services.project_info as project_info
|
||||
from app.services.time_api import parse_beijing_time
|
||||
from app.services.time_api import parse_beijing_time, parse_clock_duration_seconds
|
||||
from app.core.config import get_pgconn_string
|
||||
from app.infra.db.timescaledb.internal_queries import (
|
||||
InternalQueries as TimescaleInternalQueries,
|
||||
@@ -756,11 +757,13 @@ def run_simulation(
|
||||
|
||||
# 获取水力模拟步长,如’0:15:00‘
|
||||
globals.hydraulic_timestep = dic_time["HYDRAULIC TIMESTEP"]
|
||||
# 将时间字符串转换为 timedelta 对象
|
||||
time_obj = datetime.strptime(globals.hydraulic_timestep, "%H:%M:%S")
|
||||
# 转换为分钟浮点数
|
||||
globals.PATTERN_TIME_STEP = float(
|
||||
time_obj.hour * 60 + time_obj.minute + time_obj.second / 60
|
||||
# 转换为分钟浮点数,兼容 EPANET 的 H:MM 和 H:MM:SS 写法
|
||||
globals.PATTERN_TIME_STEP = (
|
||||
parse_clock_duration_seconds(
|
||||
globals.hydraulic_timestep,
|
||||
field_name="HYDRAULIC TIMESTEP",
|
||||
)
|
||||
/ 60
|
||||
)
|
||||
# 对输入的时间参数进行处理
|
||||
pattern_start_time = convert_time_format(modify_pattern_start_time)
|
||||
|
||||
@@ -89,6 +89,41 @@ def to_time_range(dt: datetime, delta: float) -> tuple[datetime, datetime]:
|
||||
|
||||
return (start_time, end_time)
|
||||
|
||||
|
||||
def parse_clock_duration_seconds(clock: str, field_name: str = "duration") -> int:
|
||||
"""
|
||||
Parse EPANET-style clock durations into seconds.
|
||||
|
||||
Accepted formats include H:MM, HH:MM, H:MM:SS, and HH:MM:SS.
|
||||
"""
|
||||
if not isinstance(clock, str):
|
||||
raise ValueError(f"{field_name} must be a string clock duration.")
|
||||
|
||||
parts = clock.strip().split(":")
|
||||
if len(parts) not in (2, 3):
|
||||
raise ValueError(
|
||||
f"{field_name} must use H:MM or H:MM:SS format, got {clock!r}."
|
||||
)
|
||||
|
||||
try:
|
||||
values = [int(part) for part in parts]
|
||||
except ValueError as exc:
|
||||
raise ValueError(
|
||||
f"{field_name} must contain numeric clock parts, got {clock!r}."
|
||||
) from exc
|
||||
|
||||
if any(value < 0 for value in values):
|
||||
raise ValueError(f"{field_name} must not contain negative values.")
|
||||
|
||||
hours, minutes = values[0], values[1]
|
||||
seconds = values[2] if len(values) == 3 else 0
|
||||
if minutes >= 60 or seconds >= 60:
|
||||
raise ValueError(
|
||||
f"{field_name} minutes and seconds must be less than 60, got {clock!r}."
|
||||
)
|
||||
|
||||
return hours * 3600 + minutes * 60 + seconds
|
||||
|
||||
def parse_beijing_date_range(query_date: str) -> tuple[datetime, datetime]:
|
||||
'''
|
||||
将一个日期字符串,转换成 start/end 时间段,传进来的日期被认为是北京时间
|
||||
|
||||
Reference in New Issue
Block a user