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
10 KiB
10 KiB
Roadmap
Eight phases. 0–7 are the core GUI plus post-processing. Phase 8 is the earthquake-engineering primitives — the part that makes it a research tool instead of a model viewer.
Status legend: ✅ done · 🟡 partial · ⬜ planned · ✂️ deferred / out-of-scope.
Phase 0 — Scaffolding ✅
- ✅ Repo,
.gitignore,pyproject.toml - ✅ Pre-commit + ruff + mypy
- ✅ GitHub Actions CI (Linux/Mac/Win × Py 3.10–3.12)
- ✅
python -m otkoopens aMainWindowwith PyVista 3D viewport, model-tree dock, property dock, console dock, working-plane toolbar, and a full menu bar (File / Edit / Define / Assign / Analyze / Display / View / Options / Help) - 🟡 Application icon and About dialog — wordmark logo done; native
OS icon (
.ico/.icns) still pending
Phase 1 — Core Data Model ✅
- ✅
core.geometry:Node,Element,TrussElement,CorotTrussElement,ElasticBeamColumn,ForceBeamColumn,DispBeamColumn,ZeroLengthElement,ZeroLengthSectionElement,BeamWithHingesElement,QuadElement, plusGridSystem/CoordinateSystem - ✅
core.materials:ElasticIsotropic,ElasticUniaxial,ElasticPP,Steel01,Steel02,Concrete01,Concrete02,HystereticMaterial - ✅
core.sections:ElasticSection,FiberSectionwith rectangular / circular patches and straight rebar layers,SectionAggregator - ✅
core.loads:NodalLoad,UniformElementLoad,LinearTimeSeries,ConstantTimeSeries,PathTimeSeries,PlainLoadPattern,UniformExcitationPattern,ResponseSpectrum - ✅
core.analysis:StaticCase,ModalCase,TransientCase,PushoverCase,ResponseSpectrumCase— including chained preload viapreload_case_idsand pattern removal for free-vibration runs - ✅
core.constraints:EqualDOFConstraint(multi-point constraints) - ✅
core.project.Projectaggregator with id allocation, validation,validate_references() - ✅
services.persistence:.osmodel(Pydantic JSON) load/save with round-trip-clean assertion in every example script
Phase 2 — OpenSees Service ✅
- ✅
services.opensees_runner.OpenSeesRunneremits commands in the canonical order documented inarchitecture.md - ✅ Verified examples (matched analytically or against the OpenSees Wiki Tcl reference): cantilever (point + UDL), portal frame, basic truss, SDOF pushover, RC frame gravity / pushover / earthquake, Examples 1–4 family, two-storey shear / one-bay frames, simply supported beam with quad elements
- ✅
AnalysisWorker(QObject)runnable inside aQThreadwithprogress(int)/log(str)/finished(ResultsHandle)signals
Phase 3 — 3D Viewport ✅
- ✅
views.canvas3d.ModelCanvas(subclass ofQtInteractorfrom pyvistaqt) - ✅ Grid plane, world axes triad, view-cube-style preset buttons (Isometric / Top XY / Front XZ / Right YZ), parallel projection toggle
- ✅ Node rendering as glyphs; element rendering as tubes (frames / trusses) and shells (quads); supports rendered as gizmos
- ✅ Mouse picking →
nodePicked/elementPickedsignals; pixel-space grid snap (rejects clicks more than 15 px from an intersection) - ✅ Selection highlighting with in-place colour updates
Phase 4 — Modeling Tools ✅
- ✅ Grid system dialog (X / Y / Z spacing, generates nodes); SAP2000-style table editor; off-grid clicks rejected
- ✅ Working-plane filter — grid + snap restricted to the active level
- ✅ Draw Node / Draw Frame / Draw Truss tools with hover snap highlight
- ✅ Inline element editing from the Properties dock (truss area, any scalar field)
- ✅ Assign Support tool (Free / Pin / Roller / Fix + custom 6-DOF dialog)
- ✅ Assign Load: nodal loads, distributed beam loads, ground motions
- ✅ Assign EqualDOF (multi-point constraints) from the UI
- ✅ Show Extruded Sections toolbar shortcut
- ✅ Undo / Redo via
QUndoStackfor every model mutation - 🟡 Replicate / Mirror / Move / Extrude — basic copy works; story-extrude and mirror still pending
Phase 5 — Properties ✅
- ✅ Material library dialog (CRUD)
- ✅ Section library dialog (incl.
FiberSectionrows that previously crashed are now handled) - ✅ Property editor dock — context-aware, multi-selection assignment, inline mass editor
- 🟡 Fiber-section visual editor — exists; some UI polish still needed
Phase 6 — Analysis Pipeline ✅
- ✅ Analysis case manager dialog with case-type factories
- ✅ Run dialog with progress + log + cancel
- ✅ Per-run Rayleigh damping override (no project mutation)
- ✅ Results stored to
<project>.osresults.h5 - 🟡 Convergence diagnostics view (residuals per step) — partial info in run log; dedicated diagnostics dock pending
Phase 7 — Post-processing ✅
- ✅ Deformed shape with scale-factor slider
- ✅ Mode-shape animator (1-indexed; play / scrub / scale)
- ✅ Element force diagrams (axial, shear, moment) with auto-pick of the largest-magnitude component on dock open, numerical labels at global min/max ends
- ✅ Time-history plotter (pyqtgraph) with displacement / velocity / acceleration switching
- ✅ Hysteresis plotter — node DOF orbits and element local-force loops
- ✅ Pushover curve view in display units
- ✅ Response-spectrum view (Sa-T curve with modal-period markers and a mass-participation table)
- ✅ Snapshot / video export (mode shapes + time histories) via
imageio[ffmpeg] - ⬜ Render performance pass — collapse per-entity actors into glyphed PolyData (single draw call), in-place colour updates for selection, AA, lower-tessellation spheres. Target: 10k nodes / 20k frames @ 30 fps
Phase 8 — Earthquake Engineering 🟡
- ✅
HystereticMaterial,BeamWithHinges,FiberSection→ all flowing into the runner, end-to-end pushover example - ✅ Response spectrum generator + SRSS / CQC modal combination
- ✅ Ground-motion import via
PathTimeSeries+UniformExcitationPattern, with an example wired up against the OpenSees A10000 record - ✅
ZeroLengthSectionElementfor moment-curvature workflows; closed-form verification example shipped - ✅
Concrete04(Popovics) end-to-end: model → runner → UI form → tests → fiber-section cantilever example - ✅ Material Tester service (
services/material_tester.py) — headless, Qt-free; runs any uniaxial material through a monotonic or cyclic strain protocol in an isolated single-element model and returns the full stress–strain history. Verified: Elastic linearity, ElasticPP plateau, Steel01 hysteresis energy (EPP formula, <1%), Concrete04 Popovics C1 continuity; state-cleanup and interleave proofs. - ⬜ Material Tester dialog — Qt front-end for the service above; live stress–strain plot with strain-amplitude and step controls
- ⬜ Seismic isolators:
elastomericBearing*,frictionPendulumBearing,singleFPBearing,TripleFrictionPendulum - ⬜ Ground-motion library (PEER-style record set + scaling tools)
- ⬜ IDA (Incremental Dynamic Analysis) batch runner
- 🟡 Fiber-section editor — exists for rectangular / circular sections; confined / unconfined visual presets pending
Out-of-scope (for now)
- ✂️ Code-checking (TBDY-2018, ASCE 41, Eurocode 8)
- ✂️ Soil-structure interaction GUI
- ✂️ Cloud / collaborative editing
- ✂️ Native shell-element rendering / pre-processing (quads exist as a primitive, but a proper shell workflow is its own phase)
Next sessions — backlog (Sept 2026 cooldown session)
Session handoff first: ~60 files of uncommitted work in the tree
(Table dock, extrusion shapes, exporter, pattern_factors, all audit
fixes). Commit per Conventional Commits on develop before new work
(feat:/fix: split per lane), then ruff check src tests && ruff format src tests, mypy, pytest -m "not slow".
Requested (user-ordered):
- ⬜ Toolbar button icons —
resources/icons/exists; wireQIcons inmenu_builder.pytoolbar builders (@designerlane: layout, hierarchy, affordances). Include OS icon (.ico/.icns, Phase 0 🟡). - ⬜ Shell objects — analysis first:
QuadElementtoday is continuum (plane stress/strain). Scope OpenSeesShellMITC4/ShellDKGQ+ shell sections/materials, then core element +_emit+ renderer quad→shell + section dialog. Keep solver-source untouched (emit-factor-style floats only). (@oraclefor the scope call.) - ⬜ Input-dialog layout/usability pass — continue the Lane C pattern:
QFormLayoutconsistency, prefill from selection (done for assign dialogs), inline validation messages instead of silent reverts, units-aware labels. (@designerfor layout, orchestrator for copy.) - ⬜ Hover tooltips — two halves: (a) canvas entity hover (node/element id + key values via existing picking signals); (b) widget tooltip audit (every toolbar button/dialog field documents itself).
- ⬜ Load visibility filter — show only loads of the selected pattern / case; hide the rest. Renderer load-overlay filter + selector combo (builds on the Table Loads tabs' pattern filter). Natural home: View toolbar next to Show Local Axes.
Identified this session (audit + build leftovers):
- ⬜ Named load combinations (deferred phase 3) —
pattern_factorscovers per-case factoring; add a reusable named-combo entity only if one combo must be shared across many cases. - ⬜ Per-row Run + status in Table Analyses tab — run control lives only in the Run dialog today; add per-case Run button + last-run status (converged/failed/when). No overlap: the tab lists cases, this operates them.
- ⬜ Case-manager edit preservation —
modelMutatedwhile the manager is open rebuilds the form and discards in-progress edits (audit C2). - ⬜ Table dock phase-4 polish — CSV copy/paste, column visibility (deferred from the Table plan).
- ⬜ Display-settings persistence — extruded-sections / local-axes /
parallel-projection toggles reset per project; persist viewport
prefs in
QSettings(noDisplaySettingsmodule exists yet). - ⬜ GUI test coverage under xvfb —
views/*omitted from coverage; lanes verified via offscreen smoke only. Add pytest-qt tests for: dock toggles, Level refresh, post-state teardown, Table edits, factor spins, local-axes overlay. - ⬜ Pin ruff version — local ruff (0.15.x) flags pre-existing drift
(UP037/RUF001/RUF003/E702) that repo CI doesn't; pin in
pyproject.tomlor baseline-allowlist soruff checkis green. - ⬜ Exported-Tcl round trip —
.pyexport is solver-verified; add an equivalent exec-and-compare test for the.tclrenderer.