Merge remote-tracking branches 'origin/sub_laptop_4' and 'origin/sub_laptop_8' into main_laptop_1
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
| 전도 측방 한계 (°) | 절리가 사면 반대로 기운 방향 차이가 이 각 안이면 전도 후보 | 5 ~ 45 | 20 |
|
||||
| 암 단위중량 (kN/m³ · 비우면 E02) | 덩이 무게 계산 값 · 비우면 지반 조건(E02)의 그 측점 암 물성 γt · 그것도 없으면 25 | 15 ~ 35 | 빈 칸 |
|
||||
| 우기 수위 비 (0~1) | 우기 조건 물 차는 정도 · 0 = 마름 · 1 = 가득 참 | 0 ~ 1 | 0.5 |
|
||||
| 최소 블록 크기 (m³) | 이보다 작은 블록은 판정(N.G · O.K)과 최소 Fs 에서 빼고 「소규모 · 낙석 관리」로 표시 · 평면은 폭 1 m 당 부피 · 0 = 거르지 않음 · [기본값] 으로 되돌림 | 0 ~ 1,000 | 0.1 |
|
||||
| 인장균열 | 사면 윗면에서 아래로 갈라진 틈을 볼지 · 없음 · 임계(최소 안전율 자리) · 깊이 지정 | - | 없음 |
|
||||
| 균열 깊이 (m) | 「깊이 지정」 때만 보임 · 윗면에서 잰 균열 깊이 | 0.1 ~ 100 | 1 |
|
||||
| 볼트 힘 (평면 kN/m · 쐐기 kN) | 록볼트 · 앵커가 잡아 주는 힘 · 평면은 폭 1 m 당 · 쐐기는 덩이 하나당 | 0 ~ 5,000 | 0 |
|
||||
@@ -35,6 +36,7 @@
|
||||
|
||||
- 측방 한계 기본 20° = 상용 Dips 기본 · 지식DB 03 은 전도에 30° 를 씀 — 화면에서 바꿀 수 있음.
|
||||
- 우기 수위 비 기본 0.5 = 비탈 높이 ½ 수위(KDS 11 70 05 암반).
|
||||
- 최소 블록 크기 기본 0.1 m³ = 상용 쐐기 해석(SWedge)의 최소 쐐기 크기 옵션과 같은 뜻(사용자 확정 전). 아주 얇은 쐐기가 들림으로 N.G 를 내는 것을 막음. 거른 블록 수는 비탈 상세와 보고서 요약에 나옴.
|
||||
- 인장균열 「임계」 = 균열 자리를 마루 뒤로 옮겨 가며 안전율이 가장 낮은 자리를 찾음. 균열 없는 쪽이 더 낮으면 균열 없음으로 셈. 평면 무너짐에만 씀.
|
||||
- 볼트 = 수동 지지력(덩이가 움직이면 버팀). 0 이면 보강 없음.
|
||||
|
||||
|
||||
@@ -497,3 +497,135 @@ def test_e05_rock_sheet(monkeypatch):
|
||||
rock.fill_rock(sheet, old, {})
|
||||
assert sheet["칸"]["A13"]["값"] == doc["sets"][0]["name"]
|
||||
assert sheet["칸"]["G13"]["값"] == "-" # 구간 모름
|
||||
|
||||
|
||||
# ---- 최소 블록 크기 (요구 351 · 536-1 덧) --------------------------------------------
|
||||
def _cases_with_volume(monkeypatch, volume: float, min_block: float):
|
||||
"""엔진을 가짜 부피로 바꿔 경계(< 최소 블록)만 본다 — 평면(W = γ·면적) · 쐐기 둘."""
|
||||
gamma = 25.0
|
||||
monkeypatch.setattr(
|
||||
model.engine,
|
||||
"plane_fs",
|
||||
lambda **_k: {"F": 0.5, "W": volume * gamma, "A": 5.0, "z": 0.0},
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
model.engine,
|
||||
"wedge_fs",
|
||||
lambda **_k: {"F": 0.0, "volume": volume, "line_length": 2.0, "mode": "lift", "W": 1.0},
|
||||
)
|
||||
joints = [
|
||||
{"id": "J1", "dip_direction": 90, "dip": 40, "phi": 30, "c": 0},
|
||||
{"id": "J2", "dip_direction": 200, "dip": 50, "phi": 30, "c": 0},
|
||||
]
|
||||
slope = {"dip_direction": 90, "dip": 68, "upper_dip": 0, "height_m": 5}
|
||||
kin = {"planar": ["J1"], "wedge": [{"ids": ["J1", "J2"]}], "toppling": []}
|
||||
settings = dict(model.DEFAULT_SETTINGS, min_block_m3=min_block)
|
||||
return model._cases_for(slope, joints, kin, settings, gamma, [("dry", 0.0, 0.0)])
|
||||
|
||||
|
||||
def test_min_block_default():
|
||||
assert model.DEFAULT_SETTINGS["min_block_m3"] == 0.1
|
||||
assert model.upgrade({"sets": [], "settings": {}})["settings"]["min_block_m3"] == 0.1
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"volume,small", [(0.0999, True), (0.1, False), (0.3, False), (0.0003, True)]
|
||||
)
|
||||
def test_min_block_boundary(monkeypatch, volume, small):
|
||||
"""최소 블록 0.1 m³ — 미만만 소규모(경계 = 거르지 않음) · 평면 · 쐐기 같은 규칙."""
|
||||
cases = _cases_with_volume(monkeypatch, volume, 0.1)
|
||||
assert [c["small"] for c in cases] == [small, small]
|
||||
|
||||
|
||||
def test_min_block_zero_keeps_all(monkeypatch):
|
||||
cases = _cases_with_volume(monkeypatch, 0.0003, 0.0)
|
||||
assert not any(c["small"] for c in cases)
|
||||
|
||||
|
||||
def test_min_block_verdict_and_counts(monkeypatch):
|
||||
"""얇은 쐐기(들림 Fs 0)가 N.G 를 내던 자리 — 거르면 판정 · 최소 Fs 에서 빠지고 거른 블록 수가 남음."""
|
||||
kin = {"planar": ["J1"], "wedge": [{"ids": ["J1", "J2"]}], "toppling": []}
|
||||
for min_block, verdict, n_small in ((0.0, "NG", 0), (0.1, "none", 2)):
|
||||
cases = _cases_with_volume(monkeypatch, 0.0003, min_block)
|
||||
for c in cases:
|
||||
c["required"] = 1.2
|
||||
c["ok"] = None if c["small"] else c["F"] >= 1.2
|
||||
out = model._verdict(kin, cases)
|
||||
assert (out["verdict"], out["small_blocks"]) == (verdict, n_small)
|
||||
assert out["min_F"] == (0.0 if not n_small else None)
|
||||
# 큰 블록 + 작은 블록 섞임 — 작은 것만 빠지고 큰 것으로 판정
|
||||
big = dict(_cases_with_volume(monkeypatch, 0.5, 0.1)[0], required=1.2, ok=False)
|
||||
tiny = dict(_cases_with_volume(monkeypatch, 0.0003, 0.1)[1], required=1.2, ok=None)
|
||||
tiny["F"] = 0.0
|
||||
out = model._verdict(kin, [big, tiny])
|
||||
assert (out["verdict"], out["min_F"], out["small_blocks"]) == ("NG", 0.5, 1)
|
||||
|
||||
|
||||
def test_min_block_check_range():
|
||||
doc = _doc()
|
||||
doc["settings"]["min_block_m3"] = -1
|
||||
assert {"path": "settings.min_block_m3", "code": "range"} in model.check_joints(doc)
|
||||
doc["settings"]["min_block_m3"] = 2.5
|
||||
assert model.check_joints(doc) == []
|
||||
assert model.clean(doc)["settings"]["min_block_m3"] == 2.5
|
||||
|
||||
|
||||
def test_analyze_min_block_filter(monkeypatch):
|
||||
"""측점 해석 전체 길 — 최소 블록을 크게 주면 모든 경우 소규모 · ok 없음 · 판정 none."""
|
||||
cross, design = _cross("left")
|
||||
monkeypatch.setattr(
|
||||
model,
|
||||
"rock_stations",
|
||||
lambda _s: [{"chainage_m": 20.0, "label": "STA", "ground_type": "ripping_rock"}],
|
||||
)
|
||||
monkeypatch.setattr(model.src, "cross_section", lambda _s, _c: {**cross, "design": design})
|
||||
ground = {
|
||||
"materials": [],
|
||||
"stations": [],
|
||||
"safety_factors": {"dry": {"cut": 1.5}, "wet": {"cut": 1.2}},
|
||||
"seismic": {"enabled": False},
|
||||
}
|
||||
base = model.analyze(None, _doc(), ground)[0]
|
||||
assert not any(c["small"] for c in base["cases"]) and base["small_blocks"] == 0
|
||||
doc = _doc()
|
||||
doc["settings"]["min_block_m3"] = 1000.0
|
||||
e = model.analyze(None, doc, ground)[0]
|
||||
assert all(c["small"] and c["ok"] is None for c in e["cases"])
|
||||
assert (e["verdict"], e["min_F"], e["small_blocks"]) == ("none", None, 1)
|
||||
|
||||
|
||||
def test_e05_rock_sheet_small(monkeypatch):
|
||||
"""E05 s11 — 최소 블록 글 · 소규모 요약 · 줄 비고."""
|
||||
from E05_StabReport import E05_StabReport_Build as build
|
||||
from E05_StabReport import E05_StabReport_Rock as rock
|
||||
from E06_StabRock import E06_StabRock_Router as router
|
||||
|
||||
cross, design = _cross("left")
|
||||
monkeypatch.setattr(
|
||||
model,
|
||||
"rock_stations",
|
||||
lambda _s: [{"chainage_m": 20.0, "label": "STA", "ground_type": "ripping_rock"}],
|
||||
)
|
||||
monkeypatch.setattr(model.src, "cross_section", lambda _s, _c: {**cross, "design": design})
|
||||
ground = {
|
||||
"materials": [],
|
||||
"stations": [],
|
||||
"safety_factors": {"dry": {"cut": 1.5}, "wet": {"cut": 1.2}},
|
||||
"seismic": {"enabled": False},
|
||||
}
|
||||
doc = _doc()
|
||||
doc["settings"]["min_block_m3"] = 1000.0
|
||||
stations = model.analyze(None, doc, ground)
|
||||
value = {
|
||||
"settings": doc["settings"],
|
||||
"sets": doc["sets"],
|
||||
"summary": router._summary(stations),
|
||||
"stations": stations,
|
||||
"stale": False,
|
||||
}
|
||||
sheet = next(s for s in build.form()["시트"] if s["id"] == "s11")
|
||||
rock.fill_rock(sheet, value, {})
|
||||
cells = sheet["칸"]
|
||||
assert "최소 블록 1000 m³" in cells["B8"]["값"] and "사용자 입력" in cells["B8"]["값"]
|
||||
assert "소규모 블록 1" in cells["B9"]["값"]
|
||||
assert any("소규모 · 낙석 관리" in str(c.get("값")) for c in cells.values())
|
||||
|
||||
Reference in New Issue
Block a user