otko/examples/ex4_portal2d_inelastic_section.py
smill f361fee969 feat: named case-result load combinations with full GUI support
Snapshots the current development tree, headlined by proper load
combinations (user request): a reusable LoadCombination entity of
weighted completed static-case results (e.g. 1.2xDead + 1.6xLive).

- core: LoadCombination/LoadCombinationItem entities, Project
  integration (lookup, unique ids, reference validation)
- services: combinations.py (linear superposition + envelope),
  exported via services __init__
- commands: undoable Add/Delete/Update for combinations
- GUI: Load Combinations manager dialog, Run-dialog evaluation,
  envelope display in Results panel, Combinations tab in Table dock
- tests: unit coverage (validation, math, error paths) + integration
  superposition check vs a single factored run
2026-09-11 13:19:59 -04:00

56 lines
1.7 KiB
Python

"""OpenSees Example 4. Portal Frame: inelastic uniaxial-section build."""
from __future__ import annotations
from pathlib import Path
import sys
if __package__ is None or __package__ == "":
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
sys.path.insert(0, str(Path(__file__).resolve().parent))
from otko.services import load_project, save_project # noqa: E402
if __package__:
from ._ex4_portal2d_common import ( # noqa: E402
ANALYSIS_DT,
ANALYSIS_STEPS,
INELASTIC_SECTION_VARIANT,
PUSH_STEP,
PUSH_TARGET,
REFERENCE_PUSH_TCL,
REFERENCE_SINE_TCL,
build_ex4_portal2d_inelastic_section,
)
else:
from _ex4_portal2d_common import ( # noqa: E402
ANALYSIS_DT,
ANALYSIS_STEPS,
INELASTIC_SECTION_VARIANT,
PUSH_STEP,
PUSH_TARGET,
REFERENCE_PUSH_TCL,
REFERENCE_SINE_TCL,
build_ex4_portal2d_inelastic_section,
)
def main() -> None:
project = build_ex4_portal2d_inelastic_section()
project.validate_references()
print(f"Built '{project.meta.name}'")
print(f" Build Tcl: {INELASTIC_SECTION_VARIANT.build_tcl_name}")
print(f" Analysis Tcls: {REFERENCE_PUSH_TCL.name}, {REFERENCE_SINE_TCL.name}")
print(f" Pushover target = {PUSH_TARGET}, step = {PUSH_STEP}")
print(f" Sine transient: dt = {ANALYSIS_DT}s, steps = {ANALYSIS_STEPS}")
out_path = Path(__file__).with_suffix(".osmodel")
save_project(project, out_path)
print(f"Saved -> {out_path}")
restored = load_project(out_path)
restored.validate_references()
assert restored.model_dump(by_alias=True) == project.model_dump(by_alias=True)
print("Round-trip OK.")
if __name__ == "__main__":
main()