feat(567-2): E04 임계 활동체 기둥 수 · 100 미만 경고 · 기본 설정 Scoops3D 재현 시험 · E07 집수면적 D∞

- E04 best · stats 에 columns · few_columns(< 100 · Scoops3D limcol)
- 시험 533_3: 기본 설정 그대로 · 상자 없이 제방 30° 1.3203 · D&G 1a 1.0385 · 제방 60° 0.7488(±2 %) · 기둥 경고
- E07 집수면적 = D∞(Tarboton 1997 · SINMAP 원본) · 내리막 없는 채운 평지만 D8
- 시험 536_2: D∞ 면 몫(22.5° = 반씩) · 30° 돌린 평면 줄무늬 표준편차 0.05(D8 0.16)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-27 20:25:43 +09:00
co-authored by Claude Opus 5.5
parent a843aa3ad3
commit 9d67c3eba6
4 changed files with 124 additions and 9 deletions
+35
View File
@@ -217,3 +217,38 @@ def test_ground_order_and_label_map(tmp_path):
assert ids == ["fill", "weathered_soil", "weathered_rock", "soft_rock"]
mapped = grid_engine.strata_from_grid(grid, label_map={"soil": "colluvium", "fill": "fill"})
assert [m["id"] for m in mapped.materials][:2] == ["fill", "colluvium"]
def _embankment(run_m, gamma, phi, c, half=20.0):
"""Scoops3D 검증 제방(H 10 m) — 탐색 상자 없이 격자 전체 · y ±20 m."""
x = np.arange(-25, run_m + 35 + 1e-9, 1.0)
y = np.arange(-half, half + 1e-9, 1.0)
xx, _ = np.meshgrid(x, y)
z = np.clip(xx / run_m * 10.0, 0, 10.0)
mat = {"id": "m", "name": "m", "gamma_t": gamma, "gamma_sat": gamma, "c": c, "phi": phi}
return Strata(x, y, z, np.zeros((0,) + z.shape), [mat])
@pytest.mark.parametrize(
("run_m", "gamma", "phi", "c", "expected"),
[
(10 / math.tan(math.radians(30)), 19, 20, 8.64, 1.32), # 표 6.8 제방 30°
(20.0, 20, 19.6, 3.0, 1.04), # Donald & Giam 1a
(10 / math.tan(math.radians(60)), 19, 20, 8.64, 0.75), # 표 6.11 제방 60°
],
)
def test_default_settings_reproduce_scoops3d(run_m, gamma, phi, c, expected):
"""567-2 — 실사용 기본 설정 그대로(노드 2 m · 거친 4 배 · 높이 2~30 m · dr 1 m · 부피 10~10,000 m³ ·
구 + 타원체) · 좁힌 상자 없이 → 문헌값 ±2 %(실측 +0.0 · −0.1 · −0.2 %)."""
best = search(_embankment(run_m, gamma, phi, c), SearchParams(workers=8)).best
assert best["governing"] == pytest.approx(expected, rel=0.02)
assert best["columns"] == len(best["cells"]) >= 100 and best["few_columns"] is False
def test_few_columns_warning():
"""567-2 — 임계 활동체 기둥 < 100(Scoops3D limcol) → few_columns 경고."""
st = _embankment(10 / math.tan(math.radians(60)), 19, 20, 8.64, half=8.0)
p = SearchParams(box=(-9, -3, -1, 1), h_min=4, h_max=10, v_min=10, v_max=60, ratios=(1.0,))
r = search(st, p)
assert r.best["columns"] < 100 and r.best["few_columns"] is True
assert r.stats["columns"] == r.best["columns"] and r.stats["few_columns"] is True