feat(E03): 바닥이 벽(옹벽 · 석축) 안을 지나는 후보 활동면 버림 (532-2 2차 ⑤)

- LEM 절편: 바닥 물성 = 벽 인 절편이 하나라도 있으면 그 면 무효 · 벽 밑으로 도는 면만 후보
- 시험: 벽 한가운데 지나는 꺾은선 = 값 없음 · 벽 바닥 아래 꺾은선 = 값 있음

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-26 03:26:18 +09:00
co-authored by Claude Opus 5.5
parent b33e0cd9ed
commit f341e0465f
2 changed files with 18 additions and 1 deletions
@@ -28,6 +28,7 @@ TOL = 1e-6
#: Janbu 보정 f0 식의 d/L 상한(지식DB 02 §2.3)
JANBU_DL_MAX = 0.35
MAX_ITER = 100
WALL_ID = "wall" # Engine_Model.WALL_MATERIAL id
class Prepared:
@@ -44,6 +45,8 @@ class Prepared:
self.gamma_sat = np.array([m["gamma_sat"] for m in mats] + [0.0])
self.c = np.array([m["c"] for m in mats] + [np.nan])
self.tanphi = np.array([np.tan(np.radians(m["phi"])) for m in mats] + [np.nan])
# 벽(옹벽 · 석축) — 바닥이 벽 안을 지나는 활동면은 버림(벽 밑 · 뒤로 돌아가는 면만 후보)
self.blocked = np.array([m["id"] == WALL_ID for m in mats] + [False])
polys = []
for region in model["regions"]:
rings = [region["polygon"], *region.get("holes", [])]
@@ -209,6 +212,7 @@ def slices(prep: Prepared, xe: np.ndarray, ze: np.ndarray) -> dict:
xw = np.where(W > 0, (Ws * xm + Mq) / np.maximum(W, _TINY), xm)
valid = np.all(found & (zb >= prep.bottom_z - 1e-6) & np.isfinite(zt), axis=1)
valid &= np.all(b > 0, axis=1)
valid &= ~np.any(prep.blocked[base_mat] & found, axis=1)
return {
"xe": xe,
"ze": ze,