- 엑셀 모양(흰 종이 · 노랑 칸 · 쪽 표시) 대신 공용 카드 · 입력 · 드롭다운 · 테마 토큰 색 - 테두리는 입력 · 선택 칸만 · 굵게 + 붉은 계열은 Qd · 유출량 · 판정 · 유출율만 · 관 단면 그림 테마 색 - 지역 = 전처리 행정구역(노선 대표점) > 시군구 하나 > 프로젝트 등록 지역 · R24 = 전처리 강우량표의 재현기간별 24시간 값(없으면 입력 칸) - 계산 때 R24 는 서버가 공사지 표로 정함 · 빈칸에 기대는 계산 칸은 「—」 - 처음 값 = 표준 값만(할증 2.0 · 관 종류 · 단면 가정 · 유출계수 0.8 · 재현기간 100년) · 측점 고유 값 빈칸 - [저장] = PUT …/quantity/hydro → B08_Quantity/quantities/hydro_inputs.json 만 · 성공 뒤 캐시 비움 · 캐시 판 올림(v2) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W4uKaV4ZBhsJN4GHG7yRj4
91 lines
3.9 KiB
Python
91 lines
3.9 KiB
Python
"""B08 4탭 홍수량 계산서 엔진 — 순수 식 (PLAN 62-2 · 계산 자리 ③ 서버 단독).
|
||
|
||
배수유역 계산 코드(`common_util_drainage_detail` 등)를 부르지 않음 — 화면 입력만으로 계산.
|
||
|
||
1-1 합리식 Q = (1/3.6)·f·rt·A[㎢] · Qd = Q × 할증
|
||
1-2 도달시간 Kirpich T = 0.0663·L[㎞]^0.77·s^-0.385 [hr] · s = H/L · 최소 도달시간 적용
|
||
1-3 강우강도 rt = (R24/24)·(24/T)^0.557 (Mononobe형)
|
||
2 단면검토 V = (1/n)·R^(2/3)·S^(1/2) · Q = A·V · 판정 Q ≥ Qd · 유출율 = Q/Qd
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import math
|
||
from typing import Any
|
||
|
||
from B08_Quantity.B08_Quantity_Hydro_Defaults import PIPE_KINDS
|
||
|
||
MONONOBE_EXPONENT = 0.557
|
||
EFFECTIVE_RATIO = 0.7
|
||
|
||
|
||
def section_props(section: str, diameter_m: float) -> dict[str, float]:
|
||
"""단면 가정별 단면적 A · 윤변 P · 경심 R."""
|
||
d = diameter_m
|
||
full_area = math.pi * d * d / 4.0
|
||
if section == "arc240":
|
||
# 240° 부채꼴 + 현 아래 삼각형(반지름 둘 · 끼인각 120°) — 수심 0.75D
|
||
area = full_area * 240.0 / 360.0 + (d / 2.0) ** 2 * math.sin(math.radians(60)) * math.cos(
|
||
math.radians(60)
|
||
)
|
||
perimeter = math.pi * d * 240.0 / 360.0
|
||
return {"area": area, "perimeter": perimeter, "radius": area / perimeter}
|
||
if section == "eff70":
|
||
# 배관 제안 방식 — 유속은 만관 경심(D/4) · 통수단면은 70 %
|
||
return {"area": EFFECTIVE_RATIO * full_area, "perimeter": math.pi * d, "radius": d / 4.0}
|
||
return {"area": full_area, "perimeter": math.pi * d, "radius": d / 4.0}
|
||
|
||
|
||
def _num(inputs: dict[str, Any], key: str) -> float | None:
|
||
value = inputs.get(key)
|
||
return None if value is None or value == "" else float(value)
|
||
|
||
|
||
def compute(inputs: dict[str, Any]) -> dict[str, Any]:
|
||
"""입력 → 계산서 값 전부(반올림 없음 · 화면이 자릿수를 정함).
|
||
|
||
빈칸(None)이 있으면 그 값에 기대는 칸만 None — 화면은 「—」 (69-6).
|
||
"""
|
||
length_m, height_m = _num(inputs, "length_m"), _num(inputs, "height_m")
|
||
r24, area_km2 = _num(inputs, "r24_mm"), _num(inputs, "area_km2")
|
||
slope_ground = tc_raw_hr = tc_hr = intensity = flow = design_flow = None
|
||
if length_m and height_m:
|
||
slope_ground = height_m / length_m
|
||
tc_raw_hr = 0.0663 * (length_m / 1000.0) ** 0.77 * slope_ground**-0.385
|
||
tc_hr = max(tc_raw_hr, float(inputs["tc_min_minutes"]) / 60.0)
|
||
if tc_hr and r24:
|
||
intensity = (r24 / 24.0) * (24.0 / tc_hr) ** MONONOBE_EXPONENT
|
||
if intensity is not None and area_km2:
|
||
flow = float(inputs["runoff"]) * intensity * area_km2 / 3.6
|
||
design_flow = flow * float(inputs["factor"])
|
||
|
||
n = _num(inputs, "n") or PIPE_KINDS[inputs["pipe_kind"]]
|
||
diameter_mm, slope_den = _num(inputs, "diameter_mm"), _num(inputs, "slope_denominator")
|
||
props = section_props(inputs["section"], diameter_mm / 1000.0) if diameter_mm else {}
|
||
slope_bed = 1.0 / slope_den if slope_den else None
|
||
velocity = capacity = None
|
||
if props and slope_bed:
|
||
velocity = (1.0 / n) * props["radius"] ** (2.0 / 3.0) * math.sqrt(slope_bed)
|
||
capacity = props["area"] * velocity
|
||
judged = capacity is not None and design_flow is not None
|
||
return {
|
||
"area_ha": area_km2 * 100.0 if area_km2 else None,
|
||
"r24_mm": r24,
|
||
"slope_ground": slope_ground,
|
||
"tc_raw_hr": tc_raw_hr,
|
||
"tc_hr": tc_hr,
|
||
"tc_floored": tc_hr is not None and tc_hr > tc_raw_hr,
|
||
"intensity": intensity,
|
||
"flow": flow,
|
||
"design_flow": design_flow,
|
||
"n": n,
|
||
"section_area": props.get("area"),
|
||
"perimeter": props.get("perimeter"),
|
||
"radius": props.get("radius"),
|
||
"slope_bed": slope_bed,
|
||
"velocity": velocity,
|
||
"capacity": capacity,
|
||
"ok": capacity >= design_flow if judged else None,
|
||
"ratio_pct": capacity / design_flow * 100.0 if judged and design_flow > 0 else None,
|
||
}
|