From f341e0465f5f7235555099af71028152c19df2a6 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Mon, 26 Oct 2026 03:26:18 +0900 Subject: [PATCH] =?UTF-8?q?feat(E03):=20=EB=B0=94=EB=8B=A5=EC=9D=B4=20?= =?UTF-8?q?=EB=B2=BD(=EC=98=B9=EB=B2=BD=20=C2=B7=20=EC=84=9D=EC=B6=95)=20?= =?UTF-8?q?=EC=95=88=EC=9D=84=20=EC=A7=80=EB=82=98=EB=8A=94=20=ED=9B=84?= =?UTF-8?q?=EB=B3=B4=20=ED=99=9C=EB=8F=99=EB=A9=B4=20=EB=B2=84=EB=A6=BC=20?= =?UTF-8?q?(532-2=202=EC=B0=A8=20=E2=91=A4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LEM 절편: 바닥 물성 = 벽 인 절편이 하나라도 있으면 그 면 무효 · 벽 밑으로 도는 면만 후보 - 시험: 벽 한가운데 지나는 꺾은선 = 값 없음 · 벽 바닥 아래 꺾은선 = 값 있음 Co-Authored-By: Claude Opus 5.5 --- E03_StabSection/E03_StabSection_Engine_LEM.py | 4 ++++ resources/tester/test_532_4_stab_walls_water.py | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/E03_StabSection/E03_StabSection_Engine_LEM.py b/E03_StabSection/E03_StabSection_Engine_LEM.py index 79e755295..b3b05c057 100644 --- a/E03_StabSection/E03_StabSection_Engine_LEM.py +++ b/E03_StabSection/E03_StabSection_Engine_LEM.py @@ -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, diff --git a/resources/tester/test_532_4_stab_walls_water.py b/resources/tester/test_532_4_stab_walls_water.py index 86bb68eb5..c15bd00f6 100644 --- a/resources/tester/test_532_4_stab_walls_water.py +++ b/resources/tester/test_532_4_stab_walls_water.py @@ -30,7 +30,7 @@ from E02_StabGround import E02_StabGround_Model as ground_model # noqa: E402 from E02_StabGround import E02_StabGround_Router as router # noqa: E402 from E03_StabSection import E03_StabSection_Types as types # noqa: E402 from E03_StabSection.E03_StabSection_Engine_Model import section_model_from_b06 # noqa: E402 -from E03_StabSection.E03_StabSection_Engine_Search import analyze # noqa: E402 +from E03_StabSection.E03_StabSection_Engine_Search import analyze, evaluate_specified # noqa: E402 from E03_StabSection.E03_StabSection_Engine_Station import analyze_station # noqa: E402 from E03_StabSection.E03_StabSection_Walls import ( # noqa: E402 design_with_walls, @@ -122,6 +122,19 @@ def test_임계면이_벽을_안_지남(found): assert a["min_F"]["bishop"] != pytest.approx(b["min_F"]["bishop"], abs=1e-3) +def test_벽을_지나는_면은_버림(found): + entry = found["100.00"] + model = section_model_from_b06(CROSS, design_with_walls(DESIGN, entry), walls=walls_of(entry)) + side = next(s for s in model["sides"] if s["role"] == "fill") + through = [[-0.5, 10.0], [2.0, 8.5], [6.0, 6.4]] # 벽(x 1.4~3.2 · z 7~10) 한가운데 + under = [[-0.5, 10.0], [2.0, 6.0], [8.0, 5.2]] # 벽 바닥 아래 + for line, ok in ((through, False), (under, True)): + got = evaluate_specified( + model, polyline=line, direction=side["direction"], methods=("janbu", "spencer") + ) + assert all((got[m]["F"] is not None) == ok for m in got) + + def test_벽_없는_측점_모형_그대로(): assert design_with_walls(DESIGN, None) is DESIGN and walls_of(None) is None a = section_model_from_b06(CROSS, DESIGN)