otko/tests/integration/test_moment_curvature_example.py
smillmorel 61b850bf46
Some checks failed
CI / lint (pull_request) Has been cancelled
CI / type (pull_request) Has been cancelled
CI / test-headless (macos-latest, 3.10) (pull_request) Has been cancelled
CI / test-headless (macos-latest, 3.11) (pull_request) Has been cancelled
CI / test-headless (macos-latest, 3.12) (pull_request) Has been cancelled
CI / test-headless (ubuntu-latest, 3.10) (pull_request) Has been cancelled
CI / test-headless (ubuntu-latest, 3.11) (pull_request) Has been cancelled
CI / test-headless (ubuntu-latest, 3.12) (pull_request) Has been cancelled
CI / test-headless (windows-latest, 3.10) (pull_request) Has been cancelled
CI / test-headless (windows-latest, 3.11) (pull_request) Has been cancelled
CI / test-headless (windows-latest, 3.12) (pull_request) Has been cancelled
CI / test-gui (pull_request) Has been cancelled
CI / test-integration (macos-latest) (pull_request) Has been cancelled
CI / test-integration (ubuntu-latest) (pull_request) Has been cancelled
CI / test-integration (windows-latest) (pull_request) Has been cancelled
style: resolve the remaining ruff findings
Auto-fixes (UP037, UP038, F401, I001, SIM105, RUF100) plus hand-fixes:
drop the now-unused `Union` imports, annotate mutable class attributes
with ClassVar, raise ValidationError instead of blind Exception in the
zero-length test, delete two dead locals, and bind the per-iteration
grid-builder closures to their loop variables (B023).
2026-09-16 13:20:36 -04:00

56 lines
1.8 KiB
Python

"""Round-trip + physics check on the shipped moment-curvature example."""
from __future__ import annotations
import pytest
pytest.importorskip("openseespy")
from otko.services import load_project
from otko.services.opensees_runner import OpenSeesRunner
pytestmark = pytest.mark.slow
def test_moment_curvature_example_round_trips_and_converges(tmp_path) -> None: # type: ignore[no-untyped-def]
"""build_moment_curvature() → save → load → run → expected shape."""
from examples.moment_curvature import (
COL_DEPTH,
COVER,
E_STEEL,
FY,
MU,
NUM_INCR,
build_moment_curvature,
)
proj = build_moment_curvature()
proj.validate_references()
# Save + reload — catches schema drift.
from otko.services import save_project
path = tmp_path / "mk.osmodel"
save_project(proj, path)
reloaded = load_project(path)
reloaded.validate_references()
assert reloaded.meta.units.value.startswith("US (in,")
result = OpenSeesRunner(reloaded).run(reloaded.analyses[0])
# Yield curvature estimate.
d = COL_DEPTH - COVER
ky = (FY / E_STEEL) / (0.7 * d)
# At least half of the NUM_INCR pushover steps converged.
assert (
len(result.control_disp) > NUM_INCR * 0.5
), "Pushover bailed out prematurely — check Concrete01 softening"
# Reached the mu * Ky target.
assert result.control_disp[-1] == pytest.approx(MU * ky, rel=1e-2)
# Moment at yield curvature is plausible: > 3 kip·in and < 10 kip·in per rebar
# → for 8 bars total, the section moment capacity is roughly O(3000-6000) kip·in.
peak_moment = max(abs(m) for m in result.base_shear)
assert 2000 < peak_moment < 10000, (
f"Peak moment {peak_moment:.1f} kip·in is outside the " "expected RC section range"
)