198 lines
11 KiB
Markdown
198 lines
11 KiB
Markdown
|
|
# Roadmap
|
|||
|
|
|
|||
|
|
OTKO is built in eight phases. Phases 0–7 ship the core GUI
|
|||
|
|
plus all the post-processing tooling we need for verification work.
|
|||
|
|
Phase 8 layers in the earthquake-engineering primitives that turn the
|
|||
|
|
GUI from "OpenSees frontend" into a usable research tool.
|
|||
|
|
|
|||
|
|
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 otko` opens a `MainWindow` with 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`, plus `GridSystem` / `CoordinateSystem`
|
|||
|
|
- ✅ `core.materials`: `ElasticIsotropic`, `ElasticUniaxial`, `ElasticPP`,
|
|||
|
|
`Steel01`, `Steel02`, `Concrete01`, `Concrete02`, `HystereticMaterial`
|
|||
|
|
- ✅ `core.sections`: `ElasticSection`, `FiberSection` with 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
|
|||
|
|
via `preload_case_ids` and pattern removal for free-vibration runs
|
|||
|
|
- ✅ `core.constraints`: `EqualDOFConstraint` (multi-point constraints)
|
|||
|
|
- ✅ `core.project.Project` aggregator 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.OpenSeesRunner` emits commands in the
|
|||
|
|
canonical order documented in [`architecture.md`](architecture.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 a `QThread` with
|
|||
|
|
`progress(int)` / `log(str)` / `finished(ResultsHandle)` signals
|
|||
|
|
|
|||
|
|
## Phase 3 — 3D Viewport ✅
|
|||
|
|
- ✅ `views.canvas3d.ModelCanvas` (subclass of `QtInteractor` from 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` / `elementPicked` signals; 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 `QUndoStack` for 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. `FiberSection` rows 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
|
|||
|
|
- ✅ `ZeroLengthSectionElement` for 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):
|
|||
|
|
|
|||
|
|
1. ⬜ Toolbar button icons — `resources/icons/` exists; wire `QIcon`s
|
|||
|
|
in `menu_builder.py` toolbar builders (`@designer` lane: layout,
|
|||
|
|
hierarchy, affordances). Include OS icon (`.ico`/`.icns`, Phase 0 🟡).
|
|||
|
|
2. ⬜ Shell objects — analysis first: `QuadElement` today is continuum
|
|||
|
|
(plane stress/strain). Scope OpenSees `ShellMITC4`/`ShellDKGQ` +
|
|||
|
|
shell sections/materials, then core element + `_emit` + renderer
|
|||
|
|
quad→shell + section dialog. Keep solver-source untouched
|
|||
|
|
(emit `-factor`-style floats only). (`@oracle` for the scope call.)
|
|||
|
|
3. ⬜ Input-dialog layout/usability pass — continue the Lane C pattern:
|
|||
|
|
`QFormLayout` consistency, prefill from selection (done for assign
|
|||
|
|
dialogs), inline validation messages instead of silent reverts,
|
|||
|
|
units-aware labels. (`@designer` for layout, orchestrator for copy.)
|
|||
|
|
4. ⬜ 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).
|
|||
|
|
5. ⬜ 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):
|
|||
|
|
|
|||
|
|
6. ⬜ Named load combinations (deferred phase 3) — `pattern_factors`
|
|||
|
|
covers per-case factoring; add a reusable named-combo entity only
|
|||
|
|
if one combo must be shared across many cases.
|
|||
|
|
7. ⬜ 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.
|
|||
|
|
8. ⬜ Case-manager edit preservation — `modelMutated` while the manager
|
|||
|
|
is open rebuilds the form and discards in-progress edits (audit C2).
|
|||
|
|
9. ⬜ Table dock phase-4 polish — CSV copy/paste, column visibility
|
|||
|
|
(deferred from the Table plan).
|
|||
|
|
10. ⬜ Display-settings persistence — extruded-sections / local-axes /
|
|||
|
|
parallel-projection toggles reset per project; persist viewport
|
|||
|
|
prefs in `QSettings` (no `DisplaySettings` module exists yet).
|
|||
|
|
11. ⬜ 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.
|
|||
|
|
12. ⬜ Pin ruff version — local ruff (0.15.x) flags pre-existing drift
|
|||
|
|
(UP037/RUF001/RUF003/E702) that repo CI doesn't; pin in
|
|||
|
|
`pyproject.toml` or baseline-allowlist so `ruff check` is green.
|
|||
|
|
13. ⬜ Exported-Tcl round trip — `.py` export is solver-verified;
|
|||
|
|
add an equivalent exec-and-compare test for the `.tcl` renderer.
|