"""E03 측점 하나 해석 — 좌 · 우 비탈 × 조건(건기 · 우기 · 지진) × 방법. 조건 = KDS 11 70 05 표 4.3-3: 건기 u = 0 · 우기 지하수위 = 지표 · 지진 = 건기 수위 + kh. 판정(기준안전율 대조)은 화면 · 보고서 몫 — 여기는 값만 냄. """ import time from E03_StabSection.E03_StabSection_Engine_Model import section_model_from_b06 from E03_StabSection.E03_StabSection_Engine_Search import METHODS, analyze #: 활동면 최소 깊이(m) — 지표를 얇게 긁는 면(표토 박리)은 사면 붕괴로 보지 않음. MIN_DEPTH_M = 0.3 def analyze_station( cross: dict, design: dict, *, materials=None, layers=None, ground=None, conditions=("dry", "wet"), seismic_kh: float = 0.0, methods=METHODS, noncircular: bool = True, min_depth: float = MIN_DEPTH_M, **model_kw, ) -> dict: t0 = time.perf_counter() out = {"chainage_m": cross.get("chainage_m"), "label": cross.get("label"), "cases": []} for cond in conditions: model = section_model_from_b06( cross, design, materials=materials, layers=layers, ground=ground, wet=cond == "wet", seismic_kh=seismic_kh if cond == "seismic" else 0.0, **model_kw, ) out.setdefault("areas", model["areas"]) for side in model["sides"]: res = analyze( model, direction=side["direction"], limits=side["limits"], methods=methods, noncircular=noncircular, min_depth=min_depth, ) mins = {m: (res["methods"][m]["min"] or {}).get("F") for m in methods} out["cases"].append({"condition": cond, **side, "min_F": mins, "result": res}) out["elapsed_s"] = round(time.perf_counter() - t0, 3) return out def analyze_stations(items: list[dict], workers: int | None = None, **kw) -> list[dict]: """전 측점 — 측점마다 따로 도니 프로세스로 나눠 돎. items = [{"cross", "design", "ground"?}, …] · 순서 그대로.""" import os from concurrent.futures import ProcessPoolExecutor workers = workers or max(1, (os.cpu_count() or 2) - 2) if workers == 1 or len(items) < 2: return [ analyze_station(it["cross"], it["design"], ground=it.get("ground"), **kw) for it in items ] with ProcessPoolExecutor(max_workers=workers) as pool: futures = [ pool.submit(analyze_station, it["cross"], it["design"], ground=it.get("ground"), **kw) for it in items ] return [f.result() for f in futures]