Compare commits

..
319 changed files with 8815 additions and 16756 deletions

View file

@ -14,25 +14,12 @@ jobs:
- uses: actions/setup-python@v5 - uses: actions/setup-python@v5
with: with:
python-version: "3.11" python-version: "3.11"
# Pinned to the pre-commit revisions so CI and local hooks agree. - run: pip install ruff mypy
- run: pip install ruff==0.4.4
- run: ruff check src tests - run: ruff check src tests
- run: ruff format --check src tests - run: ruff format --check src tests
type: test:
runs-on: ubuntu-latest needs: lint
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
# Pinned to the pre-commit revision (see .pre-commit-config.yaml).
- run: pip install mypy==1.10.0 pydantic numpy
- run: pip install -e .
- run: mypy src/otko/core src/otko/services
test-headless:
needs: [lint, type]
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -44,38 +31,18 @@ jobs:
- uses: actions/setup-python@v5 - uses: actions/setup-python@v5
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- run: pip install -e ".[dev]"
- run: pytest tests/unit tests/services -m "not slow"
test-gui:
needs: [lint, type]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install Linux Qt deps - name: Install Linux Qt deps
if: runner.os == 'Linux'
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install -y libegl1 libxkbcommon-x11-0 libxcb-icccm4 \ sudo apt-get install -y libegl1 libxkbcommon-x11-0 libxcb-icccm4 \
libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 \ libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 \
libxcb-shape0 libxcb-sync1 libxcb-xfixes0 libxcb-xinerama0 \ libxcb-shape0 libxcb-sync1 libxcb-xfixes0 libxcb-xinerama0 \
libxcb-cursor0 libdbus-1-3 libgl1 libxkbcommon0 xvfb libxcb-cursor0 libdbus-1-3 libgl1 libxkbcommon0 xvfb
- run: pip install -e ".[gui,dev]"
- run: xvfb-run -a pytest tests/gui -m "not slow"
test-integration:
needs: [lint, type]
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: pip install -e ".[dev]" - run: pip install -e ".[dev]"
- run: pytest tests/integration -m "not slow" - name: Run tests (Linux, headless)
if: runner.os == 'Linux'
run: xvfb-run -a pytest --cov --cov-report=xml -m "not slow"
- name: Run tests (Win/Mac)
if: runner.os != 'Linux'
run: pytest --cov --cov-report=xml -m "not slow"

4
.gitignore vendored
View file

@ -61,7 +61,3 @@ examples/ozan*.osmodel
examples/ozan_results/ examples/ozan_results/
/Ex*.csv /Ex*.csv
/Ex*.png /Ex*.png
# BEGIN oh-my-opencode-slim clonedeps
.slim/clonedeps/repos/
# END oh-my-opencode-slim clonedeps

View file

@ -1,9 +0,0 @@
# BEGIN oh-my-opencode-slim clonedeps
!.slim/
!.slim/clonedeps.json
!.slim/clonedeps/
!.slim/clonedeps/repos/
!.slim/clonedeps/repos/**
.slim/clonedeps/repos/**/.git/
.slim/clonedeps/repos/**/.git/**
# END oh-my-opencode-slim clonedeps

View file

@ -1,15 +0,0 @@
{
"version": "1.0.0",
"updatedAt": "2026-09-16T17:30:00.000Z",
"dependencies": [
{
"name": "opstool",
"resolvedVersion": "1.0.26",
"repoUrl": "https://github.com/yexiang92/opstool.git",
"ref": "v1.0.26",
"path": ".slim/clonedeps/repos/yexiang92__opstool",
"packagePath": "opstool/vis",
"reason": "Read-only source for evaluating whether to port opstool's PyVista/Plotly visualization settings into otko's canvas backends, or to depend on opstool.vis directly (GPL-3.0, compatible with otko's AGPL-3.0 via GPLv3 section 13)."
}
]
}

View file

@ -5,7 +5,7 @@ Pre-alpha SAP2000-style desktop GUI for OpenSeesPy. Python 3.10+; **Windows requ
## Install ## Install
```bash ```bash
pip install -e ".[gui,dev]" # desktop: Qt + PyVista + plotly.js backend + dev tools pip install -e ".[gui,dev]" # desktop: Qt + PyVista + dev tools
pip install -e . # headless: core + services only, no Qt (scripts, notebooks, web backends) pip install -e . # headless: core + services only, no Qt (scripts, notebooks, web backends)
python -m otko # launch GUI (src/otko/app.py:run) python -m otko # launch GUI (src/otko/app.py:run)
``` ```
@ -19,8 +19,6 @@ Strict one-way MVVM + services: `views → viewmodels → services → core`.
- `core/` (entities: `project.py`, `geometry/`, `materials/`, `sections/`, `loads/`, `analysis/`, `catalog/`): stdlib + numpy + pydantic only. **No Qt, no openseespy. Period.** - `core/` (entities: `project.py`, `geometry/`, `materials/`, `sections/`, `loads/`, `analysis/`, `catalog/`): stdlib + numpy + pydantic only. **No Qt, no openseespy. Period.**
- `services/` (`opensees_runner.py`, `persistence.py`, `results.py`, ...): may use core + h5py + openseespy. **No Qt.** - `services/` (`opensees_runner.py`, `persistence.py`, `results.py`, ...): may use core + h5py + openseespy. **No Qt.**
- `views/`: PySide6/pyvistaqt only. **No direct `import openseespy`** — go through a service. - `views/`: PySide6/pyvistaqt only. **No direct `import openseespy`** — go through a service.
- `views/canvas3d/` (**PyVista/VTK**, default) and `views/canvas_plotly/` (plotly.js in a `QWebEngineView`) are two backends for the same central 3D view. Both satisfy the `CanvasBackend` protocol in `views/canvas_base.py`, share one `SelectionState` owned by `MainWindow`, and are swapped live via **Options → Canvas Backend** (persisted in `QSettings` under `canvas/backend`). `MainWindow._activate_canvas` keeps both widgets in a `QStackedWidget` — never destroy a canvas mid-session (VTK leaves dangling make-current callbacks). Backend-specific gaps are declared by `CanvasCapabilities` (e.g. Plotly has no force-diagram overlay or video export yet); gate UI on `canvas.capabilities`, never on the backend name. `canvas_plotly/trace_builder.py` is pure (no Qt, no pyvista) and unit-tested headless. `PlotlyCanvas` pushes with `Plotly.react`, which resets scene attributes the layout omits: data-only pushes pass `preserveView` so `html.py` carries the live camera and padded axis ranges forward, and the hover/snap marker is restyled only when its visible state changes (a restyle per hover event redraws per mouse move until the stack blows). Regression tests: `tests/gui/test_plotly_view_preservation.py`, `tests/gui/test_plotly_hover.py`.
- `views/canvas3d/style.py` (`RenderStyle`) is the single source of truth for colours/sizes on **both** backends; renderers must read it rather than hard-coding a colour. The `STYLE_FIELDS` subset is user-editable via **Options → Plot Properties…** (`views/dialogs/plot_properties.py`), previews live through `MainWindow.set_plot_style(..., persist=False)`, and persists as JSON in `QSettings` under `plot/props`.
- `viewmodels/` bridges core↔Qt (signals, `QUndoStack`); `commands/` holds `QUndoCommand` subclasses. - `viewmodels/` bridges core↔Qt (signals, `QUndoStack`); `commands/` holds `QUndoCommand` subclasses.
- Rules: public functions need type hints + docstring; new domain entities go through Pydantic validation; ops >50 ms run off the GUI thread (`AnalysisWorker` in QThread, cancel via `isInterruptionRequested()`, results cross threads as lightweight `ResultsHandle` to HDF5). - Rules: public functions need type hints + docstring; new domain entities go through Pydantic validation; ops >50 ms run off the GUI thread (`AnalysisWorker` in QThread, cancel via `isInterruptionRequested()`, results cross threads as lightweight `ResultsHandle` to HDF5).
@ -58,17 +56,3 @@ git remote add origin ssh://git@smill-home.ddns.net/smill/otko.git
- `examples/*.py` are source of truth; `examples/*.osmodel` are generated artifacts (checked in). Never hand-edit `.osmodel` — change the script and regen: `python examples/cantilever.py` (each script saves, reloads, asserts clean round-trip). - `examples/*.py` are source of truth; `examples/*.osmodel` are generated artifacts (checked in). Never hand-edit `.osmodel` — change the script and regen: `python examples/cantilever.py` (each script saves, reloads, asserts clean round-trip).
- Projects persist as single Pydantic-validated JSON `.osmodel` (diffable); analysis output goes to `*.osresults.h5` (HDF5, one group per case). - Projects persist as single Pydantic-validated JSON `.osmodel` (diffable); analysis output goes to `*.osresults.h5` (HDF5, one group per case).
- Quick smoke: open `examples/cantilever.osmodel` → run `Tip-Load` → M3 peaks 50 kN·m at fixed end. - Quick smoke: open `examples/cantilever.osmodel` → run `Tip-Load` → M3 peaks 50 kN·m at fixed end.
## Cloned Dependency Source
Read-only dependency source repositories are available under
`.slim/clonedeps/repos/` for inspection. Do not edit these clones. The
structured manifest is `.slim/clonedeps.json`.
- `.slim/clonedeps/repos/yexiang92__opstool/` — `yexiang92/opstool` at `v1.0.26`; the OpenSeesPy
pre/post-processor whose PyVista and Plotly visualization settings
(`opstool/vis/{pyvista,plotly}/plot_utils.py`, `plot_resp_base.py`, `vis_model.py`) are the
reference for otko's canvas look-and-feel. GPL-3.0, and GPLv3 §13 explicitly permits combining
it with otko's AGPL-3.0. Any code actually ported from it must keep the opstool copyright notice
and record that it was modified (GPLv3 §5a/b) — add that entry to `NOTICE` when the port lands.

View file

@ -1,97 +1,37 @@
# Contributing # Contributing
Thanks for helping with OTKO — a SAP2000-style desktop GUI for Early-stage project. The bar is architecture cleanliness, not feature
OpenSeesPy. Early-stage project: the bar is architecture cleanliness, not count. If your change breaks a layering rule below, it won't merge —
feature count. If your change breaks a layering rule below, it won't no matter how useful the feature.
merge — no matter how useful the feature.
## Dev setup ## Dev setup
```bash ```bash
python -m venv .venv python -m venv .venv
source .venv/bin/activate # Linux / macOS source .venv/bin/activate
# .venv\Scripts\activate # Windows pip install -e ".[dev]"
pip install -e ".[gui,dev]"
pre-commit install pre-commit install
``` ```
`pip install -e ".[gui,dev]"` pulls the Qt/PyVista desktop stack plus the
dev tools. For a headless checkout (core + services only, no Qt) use
`pip install -e .` instead. Python 3.10+; on Windows use 3.12+.
Launch the GUI with:
```bash
python -m otko
```
`pre-commit install` wires ruff + mypy into your local git hooks so
obvious issues are caught before a commit. Run it once per clone.
## Before opening a PR ## Before opening a PR
Run the verify commands in this order and make sure they are all clean:
```bash ```bash
ruff check src tests ruff check src tests
ruff format src tests # line-length 100, E501 ignored ruff format src tests
mypy src/otko/core src/otko/services mypy src/otko/core src/otko/services
pytest -m "not slow" # CI gate: lint → this, on 3.10/3.11/3.12 × ubuntu/windows/macos pytest -m "not slow"
``` ```
Focused runs are faster while iterating: `pytest tests/unit` (pure logic,
milliseconds), `pytest tests/gui -k <name>` (pytest-qt, needs a display;
Linux GUI tests want `xvfb-run -a pytest ...`), and
`pytest tests/integration -k <name>` (real OpenSeesPy runs). Single test:
`pytest tests/unit/test_project.py::test_name -q`. Markers: `gui`, `slow`.
## Architectural rules (enforced in review) ## Architectural rules (enforced in review)
OTKO uses a strict one-way **MVVM + service** architecture. Dependencies 1. `core/` may not import Qt or `openseespy`. Period.
flow outward-in only: 2. `services/` may not import Qt.
3. `views/` may not import `openseespy` directly — go through a service.
``` 4. Public functions and methods need type hints and a docstring.
views → viewmodels → services → core 5. New domain entities go through Pydantic validation.
``` 6. Long-running operations (>50 ms) run off the GUI thread.
`commands` sits alongside the bridge and owns every model mutation.
1. `core/` is pure Python — stdlib + numpy + pydantic. It may **not**
import Qt or `openseespy`. Period.
2. `services/` may use `core` + `h5py` + `openseespy`, but may **not**
import Qt.
3. `views/` (PySide6/pyvistaqt) may **not** import `openseespy` directly —
go through a service. No business logic in `views`.
4. `viewmodels/` bridges `core` ↔ Qt (signals, `QUndoStack`).
5. `commands/` holds the `QUndoCommand` subclasses; all model mutations
go through `commands`, not ad-hoc edits in `views`.
6. Public functions and methods need type hints and a docstring.
7. New domain entities go through Pydantic validation.
8. Long-running operations (>50 ms) run off the GUI thread (`AnalysisWorker`
in a `QThread`, cancelled via `isInterruptionRequested()`; results cross
threads as a lightweight `ResultsHandle` written to HDF5).
The full package map and the fixed OpenSeesPy command order the runner
emits live in [`docs/architecture.md`](docs/architecture.md). Never
reorder the runner's commands.
## Branch model
`main` is the default and integration branch. Work on short-lived topic
branches cut from `main` — `feat/<topic>`, `fix/<topic>`, or
`docs/<topic>` — and open a pull request against `main`. Do not commit
directly to `main` from an agent session. There is no `develop` branch.
## Commit style ## Commit style
Conventional Commits — `feat:`, `fix:`, `refactor:`, `docs:`, `test:`, Conventional Commits — `feat:`, `fix:`, `refactor:`, `docs:`, `test:`,
`chore:`, `ci:`. Keep each commit focused; a `feat:` commit should add a `chore:`, `ci:`.
feature, not mix one in with unrelated refactors.
## Documentation
If your change is user-visible, update
[`docs/QUICK_GUIDE.md`](docs/QUICK_GUIDE.md) and the relevant roadmap or
ADR entry. Project model files are `.osmodel` (Pydantic-validated JSON);
regenerate the checked-in `examples/*.osmodel` from their scripts with
`python examples/<name>.py` rather than hand-editing them.

85
NOTICE
View file

@ -1,85 +0,0 @@
# NOTICE
OTKO
Copyright © 2026 Ozan and contributors.
## OTKO license
OTKO's own source code is licensed under the **GNU Affero General Public
License v3.0** (AGPL-3.0). The full text is in [`LICENSE`](LICENSE). This
`NOTICE` file does not replace or modify that license; where the two
disagree, `LICENSE` governs.
OTKO is **not** an MIT-licensed project. Portions of the codebase were
ported or adapted from an earlier, MIT-licensed prototype called
`otko-development`, so the original MIT notice is reproduced below as
required by that license.
## Ported / adapted code: `otko-development`
Portions of OTKO were ported or adapted from the `otko-development`
project, which is distributed under the MIT License. The MIT
copyright and permission notice is reproduced verbatim below:
```
MIT License
Copyright (c) 2026 OTKO contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
## Ported / adapted code: `opstool`
The canvas element colour palette in `src/otko/views/canvas3d/style.py`
(per-family element colours and the diverging response colour scale) and the
resulting diagram colouring in `views/canvas3d/diagram_renderer.py` were
adapted from the `opstool` project, which is distributed under the **GNU
General Public License v3.0**. opstool is Copyright © Yexiang Yan and
contributors.
In accordance with GPLv3 §5(a)/(b) this notice records that the material was
modified and adapted for OTKO. Combining the GPLv3-covered material with
OTKO's AGPL-3.0 code is permitted by GPLv3 §13; the combined work is
conveyed under AGPL-3.0, and the GPLv3 terms continue to apply to the
opstool-derived portions.
## Runtime dependencies
OTKO depends on third-party software that is not covered by OTKO's
AGPL-3.0 license. Each component remains under its own license, and its
license text ships with the corresponding package. The notes below are a
summary for attribution, not a substitute for those license texts.
- **OpenSees / OpenSeesPy** — the finite-element solver invoked by
`otko.services.opensees_runner`. OpenSees is copyright The Regents of
the University of California and is distributed under a BSD-style
license; the notice is shipped inside the `openseespy` package.
- **PySide6** — the Qt 6 bindings used by the desktop GUI. PySide6 is
available under the GNU Lesser General Public License v3 (LGPLv3) or a
commercial license. OTKO links against it dynamically, which keeps the
LGPL relinking obligation satisfiable for redistributors.
- **numpy**, **pydantic**, **h5py**, **pyvista**, **VTK**,
**pyqtgraph**, and **imageio** — each is distributed under its own
license (for example BSD-3-Clause, MIT, and similar permissive terms).
See the license file bundled with each installed package for the exact
terms.
When redistributing OTKO, keep `LICENSE`, this `NOTICE`, and the license
notices of the dependencies above.

View file

@ -82,13 +82,6 @@ views (Qt) → viewmodels → services (OpenSeesRunner, Persistence) → c
Long version in [`docs/architecture.md`](docs/architecture.md), Long version in [`docs/architecture.md`](docs/architecture.md),
including the OpenSeesPy command order the runner emits. including the OpenSeesPy command order the runner emits.
## Documentation
Practical, task-first walkthroughs live in
[`docs/QUICK_GUIDE.md`](docs/QUICK_GUIDE.md) — a cantilever build,
modal analysis, report/script export, display units, and undo/redo.
The full index is [`docs/README.md`](docs/README.md).
## Install (development) ## Install (development)
**Desktop GUI** (Qt, PyVista, pyqtgraph, imageio): **Desktop GUI** (Qt, PyVista, pyqtgraph, imageio):

View file

@ -1,132 +0,0 @@
# OTKO Quick Guide
A practical, task-first guide to the OTKO desktop GUI. It assumes you
have already installed the desktop extras and can launch the app:
```bash
pip install -e ".[gui,dev]"
python -m otko
```
Project files use the `.osmodel` extension — a single, Pydantic-validated
JSON document that diffs cleanly in Git. Analysis output is written
separately to `*.osresults.h5`.
For the layer map and the OpenSeesPy command order, see
[`architecture.md`](architecture.md). For the feature-by-feature plan, see
[`roadmap.md`](roadmap.md).
## 1. A cantilever walkthrough
This follows the bundled `examples/cantilever.osmodel` model: a 5 m
horizontal beam, fixed at the left end, with a tip load. If you would
rather build it by hand, the steps are below.
1. **Start a project.** **File → New (3D Frame)**. Pick display units in
the bottom-right **Units** combo before typing any values.
2. **Lay out a grid.** **Define → Coordinate System/Grids…** (Ctrl+G).
Define X lines at 0…5 m (say, every 1 m), Y = 0, Z = 0, and set the
grid as the active coordinate system. The 3D canvas will draw it as
reference geometry.
3. **Add nodes.** **Define → Add Node…** (Ctrl+N), or use the **Draw
Node** tool and click on grid intersections at (0,0,0) … (5,0,0).
4. **Define material and section.** **Define → Material Library…**
(Ctrl+Shift+M) then **Define → Section Library…** (Ctrl+Shift+S). The
example uses a steel `ElasticSection` named `W12x40`.
5. **Draw the element.** **Assign/Define → Draw Frame** (F2), then click
from the first node to the last. Assign the section with
**Assign → Frame → Section…**.
6. **Add the support.** Select the node at x = 0 and use
**Assign → Joint → Restraints…** (Ctrl+R); restrain all six DOF. The
support icon confirms the fixed end.
7. **Add the load.** Select the tip node and use **Assign → Joint →
Point Loads…** (Ctrl+L). The example applies -10 kN in Y. Alternatively
build the distributed case with **Assign → Frame → Distributed
Load…**.
8. **Set up and run the case.** **Analyze → Cases…** (Ctrl+Shift+A) to
create or review a Static case, then **Analyze → Run…** (F5). The
bundled file already contains `Tip-Load`, `Uniform-Load`, and a modal
`Modal-3` case.
### Smoke check
Open `examples/cantilever.osmodel`, run the `Tip-Load` static case, then
**Display → Show Force Diagram… → M3**. The moment diagram is linear and
peaks at **50 kN·m at the fixed end**. V2 is a constant -10 kN along the
span. If you see that, the model, runner, and post-processor are wired up
correctly.
## 2. Running a modal analysis
1. Open a model that has mass assigned (the bundled cantilever lumps mass
at every free node so modal works out of the box).
2. **Analyze → Cases…**, add or select a **Modal** case, and set the
number of modes `n_modes` (the example uses 3).
3. **Analyze → Run…** (F5). Results appear in the results/report panel:
periods, frequencies, and participation factors per mode.
4. **Display → Animate Mode Shape** to view each mode. Use the mode
selector and the animation controls, and **Export…** if you want a
video of the mode shape.
5. Modal results also feed the response-spectrum case: define a response
spectrum, then run the SRSS or CQC combination and open
**Display → Show Response Spectrum**.
## 3. Reviewing results and exporting a report or script
After a run, the results/report panel shows a summary for the active case
(static reactions and forces, modal periods, and so on). Use the display
actions to inspect the model visually:
- **Display → Show Deformed Shape** — with a scale slider.
- **Display → Show Force Diagram…** — axial (P), shear (V2/V3), moment
(M2/M3) diagrams.
- **Display → Show Pushover Curve**, **Show Time-History**, **Show
Hysteresis** as applicable.
To hand the analysis to someone else, or to archive exactly what was run,
export a script:
- **File → Export OpenSeesPy (.py)…** — writes the full model, and
optionally a selected analysis case, as a runnable Python script.
- **File → Export Tcl (.tcl)…** — the same model as classic OpenSees Tcl.
The export dialog lets you choose "Model only (no analysis case)" or one
of the configured cases. The generated script follows the runner's fixed
command order (`wipe → model → node → fix → … → analyze`), so it
reproduces the analysis outside the GUI.
## 4. Changing display units
Use either control, they are the same setting:
- The **Units** combo in the bottom-right of the status bar, or
- **Options → Set Display Units…**
Changing units updates how lengths, forces, and moments are formatted in
the UI and plots. It does **not** rescale the underlying model numbers —
pick the right unit system before you type values, and convert
deliberately if you switch later. A set of unit labels is available in the
unit-label tests under `tests/unit/test_unit_labels.py`.
## 5. Undo and redo
Every model mutation goes through the undo stack, so most edits are
reversible:
- **Edit → Undo** (Ctrl+Z)
- **Edit → Redo** (Ctrl+Y / Ctrl+Shift+Z)
Menu text is dynamic — it names the operation, for example "Undo Add 4
Nodes". Compound operations such as drawing a frame (node + element) are
wrapped in a single macro, so one undo removes the whole step. File
loads, analysis runs, and display-only changes are not model mutations and
are not undoable.
## Where to go next
- [`architecture.md`](architecture.md) — MVVM layering and command order.
- [`roadmap.md`](roadmap.md) — what is done and what is planned.
- `examples/` — 20+ verified models, each generated from a checked-in
Python script.
- [`../CONTRIBUTING.md`](../CONTRIBUTING.md) — setup, rules, and verify
commands.

View file

@ -1,26 +0,0 @@
# OTKO Documentation
Index of the project documentation. Start with the quick guide if you
just want to build and run a model; read the architecture page if you are
changing code.
| Document | What it covers |
| --- | --- |
| [QUICK_GUIDE.md](QUICK_GUIDE.md) | Task-first walkthrough: cantilever model, modal analysis, report and script export, display units, undo/redo. |
| [architecture.md](architecture.md) | MVVM layering, package responsibilities, threading, persistence, and the fixed OpenSeesPy command order. |
| [roadmap.md](roadmap.md) | Phase-by-phase feature status, from scaffolding through the earthquake-engineering primitives. |
| [adr/](adr/) | Architecture Decision Records — the "why" behind individual design choices. |
| [screenshots/](screenshots/) | Screenshots referenced by the docs and README. |
## Architecture Decision Records
- [ADR-0001 — GiD/OpenSees schema import](adr/ADR-0001-gidopensees-schema-import.md)
- [ADR-0002 — Headless / GUI dependency split](adr/ADR-0002-headless-gui-dep-split.md)
## Related documentation
- [`../README.md`](../README.md) — project overview, install, and quick start.
- [`../CONTRIBUTING.md`](../CONTRIBUTING.md) — dev setup, layering rules, commit style, and verify commands.
- [`../AGENTS.md`](../AGENTS.md) — condensed context for automated agents.
- [`gap-analysis-gidopensees.md`](gap-analysis-gidopensees.md) — gap analysis against the GiD/OpenSees reference.
- [`../examples/README.md`](../examples/README.md) — the bundled example models.

View file

@ -222,7 +222,6 @@ def main() -> None:
project = build_ex1a_canti2d() project = build_ex1a_canti2d()
project.validate_references() project.validate_references()
gm = next(ts for ts in project.time_series if ts.id == 3) gm = next(ts for ts in project.time_series if ts.id == 3)
assert isinstance(gm, PathTimeSeries)
print(f"Built '{project.meta.name}'") print(f"Built '{project.meta.name}'")
print(f" Gravity + pushover + earthquake cases: {len(project.analyses)}") print(f" Gravity + pushover + earthquake cases: {len(project.analyses)}")
print(f" Ground motion file: {GROUND_MOTION_FILE.name}") print(f" Ground motion file: {GROUND_MOTION_FILE.name}")

View file

@ -190,7 +190,6 @@ def main() -> None:
project = build_ex1a_canti2d_eq() project = build_ex1a_canti2d_eq()
project.validate_references() project.validate_references()
gm = next(ts for ts in project.time_series if ts.id == 2) gm = next(ts for ts in project.time_series if ts.id == 2)
assert isinstance(gm, PathTimeSeries)
print(f"Built '{project.meta.name}'") print(f"Built '{project.meta.name}'")
print(f" Ground motion file: {GROUND_MOTION_FILE.name}") print(f" Ground motion file: {GROUND_MOTION_FILE.name}")
print(f" Reference Tcl: {REFERENCE_TCL.name}") print(f" Reference Tcl: {REFERENCE_TCL.name}")

View file

@ -209,7 +209,6 @@ def main() -> None:
project = build_ex1b_portal2d() project = build_ex1b_portal2d()
project.validate_references() project.validate_references()
gm = next(ts for ts in project.time_series if ts.id == 3) gm = next(ts for ts in project.time_series if ts.id == 3)
assert isinstance(gm, PathTimeSeries)
print(f"Built '{project.meta.name}'") print(f"Built '{project.meta.name}'")
print(f" Gravity + pushover + earthquake cases: {len(project.analyses)}") print(f" Gravity + pushover + earthquake cases: {len(project.analyses)}")
print(f" Ground motion file: {GROUND_MOTION_FILE.name}") print(f" Ground motion file: {GROUND_MOTION_FILE.name}")

View file

@ -231,7 +231,6 @@ def main() -> None:
project = build_ex2a_canti2d_elastic_element() project = build_ex2a_canti2d_elastic_element()
project.validate_references() project.validate_references()
gm = next(ts for ts in project.time_series if ts.id == 3) gm = next(ts for ts in project.time_series if ts.id == 3)
assert isinstance(gm, PathTimeSeries)
print(f"Built '{project.meta.name}'") print(f"Built '{project.meta.name}'")
print(f" LCol={L_COL}, Weight={WEIGHT}, ACol={A_COL:.1f}, Ec={E_C:.3f}") print(f" LCol={L_COL}, Weight={WEIGHT}, ACol={A_COL:.1f}, Ec={E_C:.3f}")
print(f" Gravity + pushover + earthquake cases: {len(project.analyses)}") print(f" Gravity + pushover + earthquake cases: {len(project.analyses)}")

View file

@ -253,7 +253,6 @@ def main() -> None:
project = build_ex2b_canti2d_inelastic_section() project = build_ex2b_canti2d_inelastic_section()
project.validate_references() project.validate_references()
gm = next(ts for ts in project.time_series if ts.id == 400) gm = next(ts for ts in project.time_series if ts.id == 400)
assert isinstance(gm, PathTimeSeries)
print(f"Built '{project.meta.name}'") print(f"Built '{project.meta.name}'")
print( print(
f" LCol={L_COL}, EA={EA_COL:.1f}, My={MY_COL:.1f}, " f" LCol={L_COL}, EA={EA_COL:.1f}, My={MY_COL:.1f}, "

View file

@ -301,7 +301,6 @@ def main() -> None:
project = build_ex2c_canti2d_inelastic_fiber_section() project = build_ex2c_canti2d_inelastic_fiber_section()
project.validate_references() project.validate_references()
gm = next(ts for ts in project.time_series if ts.id == 400) gm = next(ts for ts in project.time_series if ts.id == 400)
assert isinstance(gm, PathTimeSeries)
print(f"Built '{project.meta.name}'") print(f"Built '{project.meta.name}'")
print( print(
f" LCol={L_COL}, ACol={A_COL:.1f}, Iz={IZ_COL:.1f}, " f" LCol={L_COL}, ACol={A_COL:.1f}, Iz={IZ_COL:.1f}, "

View file

@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project] [project]
name = "otko" name = "otko"
dynamic = ["version"] version = "0.1.0"
description = "OTKO — a modern, SAP2000-style desktop GUI for OpenSeesPy." description = "OTKO — a modern, SAP2000-style desktop GUI for OpenSeesPy."
readme = "README.md" readme = "README.md"
requires-python = ">=3.10" requires-python = ">=3.10"
@ -42,7 +42,10 @@ gui = [
"vtk>=9.3", "vtk>=9.3",
"pyqtgraph>=0.13", "pyqtgraph>=0.13",
"imageio[ffmpeg]>=2.34", "imageio[ffmpeg]>=2.34",
"plotly>=5.18", # scipy and pandas are listed for forward-compatibility; they are not
# currently imported by any module in this repo (phantom deps as of 2026-06-15).
"scipy>=1.11",
"pandas>=2.1",
] ]
dev = [ dev = [
"pytest>=7.4", "pytest>=7.4",
@ -52,7 +55,6 @@ dev = [
"mypy>=1.8", "mypy>=1.8",
"pre-commit>=3.6", "pre-commit>=3.6",
"hatch>=1.9", "hatch>=1.9",
"tomli>=2.0; python_version < '3.11'",
] ]
docs = [ docs = [
"sphinx>=7.2", "sphinx>=7.2",
@ -70,9 +72,6 @@ Issues = "https://github.com/ogunc/otko/issues"
[tool.hatch.build.targets.wheel] [tool.hatch.build.targets.wheel]
packages = ["src/otko"] packages = ["src/otko"]
[tool.hatch.version]
path = "src/otko/_const.py"
# ─────────── Ruff ─────────── # ─────────── Ruff ───────────
[tool.ruff] [tool.ruff]
line-length = 100 line-length = 100
@ -90,25 +89,7 @@ select = [
"SIM", # simplify "SIM", # simplify
"RUF", # ruff-specific "RUF", # ruff-specific
] ]
ignore = [ ignore = ["E501"] # line length handled by formatter
"E501", # line-length handled by the formatter
"RUF001", # ambiguous unicode: engineering notation (×, ≈, ²) is deliberate
"RUF002",
"RUF003",
]
[tool.ruff.lint.per-file-ignores]
# Engineering symbols (A, I, L, E, P) and `importorskip`-then-import blocks
# are normal in tests.
"tests/**" = ["E402", "E741", "N802", "N806", "N815"]
# Qt requires camelCase signal names and PascalCase event overrides.
"src/otko/views/**" = ["N802", "N815"]
"src/otko/viewmodels/**" = ["N815"]
# Material fields mirror the OpenSees parameter names verbatim (cR1, epsU, ...).
"src/otko/core/materials/__init__.py" = ["N815"]
# Engineering symbols in numeric code: L (length), Iz/Iy (second moments).
"src/otko/services/section_properties.py" = ["N806"]
"src/otko/views/canvas3d/model_renderer.py" = ["N802", "N806", "N815"]
[tool.ruff.format] [tool.ruff.format]
quote-style = "double" quote-style = "double"
@ -116,12 +97,11 @@ quote-style = "double"
# ─────────── Mypy ─────────── # ─────────── Mypy ───────────
[tool.mypy] [tool.mypy]
python_version = "3.10" python_version = "3.10"
warn_unused_configs = true
plugins = []
[[tool.mypy.overrides]]
module = ["otko.core.*", "otko.services.*", "otko.viewmodels.*"]
strict = true strict = true
warn_unused_ignores = true
warn_return_any = true
disallow_untyped_defs = true
plugins = []
[[tool.mypy.overrides]] [[tool.mypy.overrides]]
module = ["openseespy.*", "pyvista.*", "pyvistaqt.*", "vtk.*", "pyqtgraph.*"] module = ["openseespy.*", "pyvista.*", "pyvistaqt.*", "vtk.*", "pyqtgraph.*"]
@ -141,8 +121,3 @@ markers = [
branch = true branch = true
source = ["src/otko"] source = ["src/otko"]
omit = ["src/otko/views/*"] # GUI excluded from coverage targets omit = ["src/otko/views/*"] # GUI excluded from coverage targets
[tool.coverage.report]
exclude_lines = ["if TYPE_CHECKING:", "raise NotImplementedError"]
# Conservative floor for the headless suite; raise deliberately with evidence.
fail_under = 50

View file

@ -1,383 +0,0 @@
# 15 — Rebuild Adoption Plan
> **Status:** proposed. **Source of truth for intent:** the greenfield
> rebuild specs at `~/Sync/otko-development/specifications` (`00`–`14`).
> This document plans how to bring that rebuild's good ideas into **this**
> repo without breaking the working app.
>
> Requirement IDs are shown without brackets for brevity (e.g. `PKG-032` =
> `[PKG-032]` in the rebuild set) so they stay grep-able.
---
## 1. Context
| | This repo (`~/Sync/otko`) | Rebuild (`~/Sync/otko-development`) |
|---|---|---|
| Role | **Working app** — the primary deliverable | Greenfield spec-conformant attempt |
| VCS | Not a git repo in this checkout | `rebuild` branch, commit `725040e` |
| License | AGPL-3.0 | MIT (+ `NOTICE`) |
| Python | 3.10–3.12 | 3.12 only |
| Project file | `.osmodel` | `.otko` |
| Scope | Superset: static, modal, **transient, pushover, response-spectrum**, quad/shell-adjacent elements, HDF5 | Narrow v1: static + modal; reports, combinations, self-weight, units display |
| src LOC | ~37k | ~25k |
| Gate | deps not installed here; **57 collection errors** locally | `ruff` passes; `mypy`/`pytest` deps missing locally |
The rebuild is *ahead* on: **reporting/Typst, load combinations, self-weight,
display-unit conversion, closed-form diagrams, modal mass participation,
progress/cancel, local-axis editing, viewmodel separation, and quality
gates**. It is *behind* on everything this repo already ships. Therefore the
plan is a **selective harvest**, not a merge.
## 2. Goal and non-goals
**Goal.** Adopt the rebuild's good capabilities into this repo, incrementally,
each phase independently shippable, with the existing app and tests staying
green.
**Non-goals.**
- Do **not** rewrite this repo to the rebuild's architecture (`ProjectStore`,
frozen `Project`, `CommandFactory`, `services/scene.py`,
`services/diagram_data.py` substrates).
- Do **not** replace the runner/export/results surface — this repo's is a
strict superset.
- Do **not** change `.osmodel`, the AGPL license, or the Python 3.10–3.12
support range as part of this plan.
## 3. Principles
1. **Additive, adapt, don't copy.** Port algorithms/patterns; re-type to this
repo's APIs (`StaticResults`/`ModalResults`, mutable `Project`,
4-value `UnitSystem`, `element_forces.DiagramData`).
2. **Protect the working app.** Every phase keeps `pytest -m "not slow"` and
the GUI smoke tests green. New optional deps stay **lazy** so headless
installs are unaffected.
3. **One phase = one branch = one shippable PR**, with tests and a gate.
4. **Trace every item to a rebuild spec ID** so "is it done?" stays mechanical.
5. **License hygiene.** MIT→AGPL-3.0 is one-way compatible: preserve the MIT
copyright/permission notice for ported files (`NOTICE` + per-file header).
Never copy this repo's AGPL code back into the MIT rebuild.
6. **Establish version control first.** This checkout has **no `.git`**. Before
any work, create a repo/branch per `AGENTS.md` (`origin` is the self-hosted
Forgejo; work on `feat/<topic>`, PR against `main`).
## 4. Adoption matrix
Verdicts: **PORT** (near-verbatim), **ADAPT** (re-type/re-wire), **REIMPL**
(reimplement against this repo's APIs), **SKIP** (intentional divergence).
Size: **S** ≈ hours · **M** ≈ a few days · **L** ≈ 1–2+ weeks.
### 4.1 Quality / foundations
| # | Capability | Rebuild source | Verdict | Phase | Size | Spec IDs |
|---|---|---|---|---|---|---|
| Q1 | Single-source version + solver pin via `_const.py` | `src/otko/_const.py`, `pyproject.toml` `[tool.hatch.version]` | ADAPT | 0 | S | PKG-032/033, RUN-085 |
| Q2 | Layering/import-discipline AST tests | `tests/unit/test_architecture.py` (246) | ADAPT (paths) | 0 | M | ARC-001..003/006/011/060..064 |
| Q3 | CI split into 5 jobs incl. missing **`type` (mypy)** job; mark integration `slow` | `.github/workflows/ci.yml`, `tests/unit/test_ci_config.py`, `test_meta_gates.py` | ADAPT | 0 | M | TST-004/031/040/041 |
| Q4 | conftest hardening (offscreen default; `ops.wipe()` in teardown) | `tests/conftest.py` | ADAPT | 0 | S | TST §7 |
| Q5 | `tests/services/` split from `tests/unit/` | tests layout | ADAPT | 0 | M | TST-002 |
| Q6 | Standalone docs + docs test | `docs/QUICK_GUIDE.md`, `docs/README.md`, `tests/unit/test_docs.py` | ADAPT | 0 | M | — |
| Q7 | `NOTICE` + attribution for ported MIT code | `NOTICE` | REIMPL (AGPL wording) | 0 | S | PKG-042 |
| Q8 | Drop phantom `scipy`/`pandas` from `[gui]` | `pyproject.toml`, `tests/unit/test_packaging.py` | ADAPT | 0 | S | PKG-011 |
| Q9 | Scoped mypy overrides + coverage `fail_under` | `pyproject.toml` | ADAPT | 0 | S | TST-031/032 |
| Q10 | Packaging config tests subset (entrypoint, line length, single-source) | `tests/unit/test_packaging.py` (117) | ADAPT | 0 | S | PKG-030..033 |
| Q11 | Spec-ID traceability harness | `tests/unit/test_spec_traceability.py` (343) | REIMPL | 8 | L | TST-013/024/025 |
| Q12 | Performance probes | `tests/performance/*` | ADAPT | 8 | L | OVR-010..014 |
### 4.2 Services / engine
| # | Capability | Rebuild source | Verdict | Phase | Size | Spec IDs |
|---|---|---|---|---|---|---|
| S1 | `SolverSession` Protocol + `Real`/`Recording` sessions | `services/solver_session.py` (154) | PORT | 1 | S | RUN-003/010/011/012 |
| S2 | Persistence refuses to save an invalid model + resolved path | `services/persistence.py` (63) | ADAPT | 1 | S | PER-021/022 |
| S3 | Result fields: `StaticResults.time`, modal `ModeParticipation` record | `services/results.py` (138) | ADAPT | 1 | S | RES-001/003/005, ANL-012 |
| S4 | Component-less element forces = absent, not zeros | `runner/run.py` | ADAPT | 1 | S | RUN-053 |
| S5 | `progress(int)` + `cancelled` + `isInterruptionRequested()` + `cancel()`; real Cancel UX | `services/qt_workers.py`, `viewmodels/analysis_vm.py`, `views/dialogs/run.py` | ADAPT | 2 | M | ANL-031..036, ARC-032/033, UX-081 |
| S6 | Modal mass participation unified with response-spectrum path | `runner/modal.py` (466), `services/results.py` | ADAPT | 2 | M | RUN-062/070..072, ANL-013 |
| S7 | Display-unit layer + `GRAVITY` + `ProjectMeta.display` (adapter over 4-system enum) | `core/units.py` (298) | ADAPT | 3 | M | UNT-003/004/010/020..024/030..032 |
| S8 | Closed-form diagram math (`N/V/M/T` shapes + extrema) | `core/diagrams.py` (436) | PORT | 4 | S | RES-010/011/012 |
| S9 | Backend-neutral `diagram_data` service + `render_matplotlib` | `services/diagram_data.py` (400) | REIMPL | 4 | M | RES-020..024/030..032, CAN-084 |
| S10 | **Report pipeline** CSV / PNG(≥300 dpi) / SVG / Typst (+optional PDF) + case-report action | `services/report/*` (1141) | PORT + ADAPT deps | 5 | M | RES-040..047/050/051/061 |
| S11 | Local axis: `LocalAxis`, element field, geomTransf dedup by `(type,vecxz,roll)`, editor + triad | `core/geometry/local_axis.py`, `runner/emit.py` | ADAPT | 6 | M | GEO-060..064, DOM-040 |
| S12 | Load combinations entity + commands + runner materialisation | `core/combinations.py` (44), `commands/combinations.py` (146) | PORT + ADAPT | 7 | M | LOD-050..058, ANL-001, RUN-050 |
| S13 | Self-weight service + regenerate command | `services/self_weight.py` (364) | REIMPL | 7 | M | UNT-040..045, LOD-011/040..043 |
| S14 | Material `rho` coverage for self-weight | `core/materials` | ADAPT | 7 | S | UNT-041 |
### 4.3 UI / UX
| # | Capability | Rebuild source | Verdict | Phase | Size | Spec IDs |
|---|---|---|---|---|---|---|
| U1 | Pure formatting helpers (`DOF/MASS/RESTRAINT_LABELS`, number/float parse) | `views/formatting.py` (84) | PORT | 0 | S | UX-033/062 |
| U2 | Timestamped, severity-tagged console | `views/docks/console.py` (103) | PORT | 0 | S | UX-042 |
| U3 | `ValidatedDialog` base (help line, inline errors, OK-gating, unit suffix) | `views/dialogs/base.py` (191) | PORT + staged | 8 | M | UX-060..064 |
| U4 | `ResultsVM` per-case handle cache; `CanvasVM` selection ownership | `viewmodels/results_vm.py`, `canvas_vm.py` | REIMPL | 8 | M | RES-005, CAN-042/041 |
| U5 | Overlay helpers: ghost undeformed, unit-labelled diagram extremes, zero hint, pattern-filtered loads | `views/canvas/overlays.py` (684) | REIMPL | 8 | M | CAN-052/062/082/083, LOD-063 |
| U6 | `QSettings` layout persistence + `closeEvent` save prompt | `views/main_window.py` | PORT | 0 | S | UX-013, PER-032/033, ARC-050 |
| U7 | `ThemeManager` + dark icon set | `views/resources/theme.py`, `icons.py` | ADAPT (verify icon provenance) | 8 | S | UX-070/071/072 |
| U8 | Thicken `ProjectViewModel` (move `action_handlers` logic into VM methods) | `viewmodels/project_vm.py` (713) | REIMPL | 8 | L | UX-001/002/005, ARC-005/020..022 |
| U9 | Analysis VM status + Simple/Advanced control fields | `viewmodels/analysis_vm.py` | ADAPT | 8 | M | ANL-021/050..054, UX-037 |
### 4.4 Explicitly deferred / skipped
| Item | Verdict | Why |
|---|---|---|
| Polygon-first sections + `services/sections_mesh.py` (opstool GPLv3) | DEFER (Phase 9, conditional) | Schema-breaking redesign; adds GPLv3/runtime deps; not report-critical |
| Frozen `Project`/entities + `ProjectStore`/`CommandFactory` rewrite | DEFER (not recommended now) | Large coordinated rewrite of 43 commands + all call sites; low user-visible value vs risk |
| Canvas backend Protocol + `plotly_backend.py` + `services/scene.py` | DEFER (Phase 9) | Requires core + views surgery; plotly pulls QtWebEngine (known teardown SIGSEGV) |
| `.otko` file suffix / greenfield `Project` schema (PER-001/006) | SKIP | Breaks `.osmodel` corpus and compatibility; do only as an explicit user-approved migration |
| Rebuild `runner/export.py` | SKIP | This repo's `export.py` is a superset (5 case types, `.py`+`.tcl`) |
| Rebuild static/modal HDF5 | SKIP | Rebuild has none; this repo's transient HDF5 is already better |
| Rebuild slim `materials`/`analysis`/`loads` unions | SKIP | Dropping `HystereticSM`, Transient/Pushover/ResponseSpectrum, Path/Imposed patterns would regress shipped features |
| MIT license / py3.12-only / single-OS CI assertions | SKIP | Intentional differences (AGPL, 3.10–3.12, 3-OS matrix) |
## 5. Phases
### Phase 0 — Foundations, safety net, quick wins
**Why first:** makes later phases verifiable and cheap; all items are
additive and low risk. Also unblocks the mpy gate that currently does nothing.
- **Prep:** initialise git and a `feat/rebuild-adoption` branch (§3.6).
- **Q1** Create `src/otko/_const.py` (`__version__`, `OPENSEESPY_VERSION`),
switch `pyproject.toml` to `dynamic = ["version"]` + `[tool.hatch.version]`,
and import the pin in `services/export.py` (currently duplicated at
`export.py:52`). Spec: PKG-032/033, RUN-085.
- **Q2** Port `tests/unit/test_architecture.py`; adapt `CANVAS = views/canvas3d`
path and `services/{_emit,_run}.py` paths. Expect it to flag three existing
offenders — decide per item: `OSS_PICK_DEBUG` env var in
`views/canvas3d/model_canvas.py:29` (ARC-052), `QUndoStack` outside VMs, and
the canvas path. Either fix or add a documented, narrow allowlist.
- **Q3** Split CI: `lint` (+`ruff format --check`), **`type` (mypy scopes)**,
`test-headless` (`pytest tests/unit tests/services -m "not slow"`),
`test-gui` (`xvfb-run pytest tests/gui`), `test-integration`
(`pytest tests/integration -m slow`). Add `pytestmark = pytest.mark.slow` to
integration modules. Keep the existing 3-OS × 3.10–3.12 matrix and the long
Linux Qt apt list.
- **Q4** `tests/conftest.py`: `QT_QPA_PLATFORM=offscreen` default; move
`ops.wipe()` to teardown (this repo currently wipes before each test).
- **Q5** Move service-level tests (`runner_translation`, `persistence`,
`results`, `export`, …) into `tests/services/`; update CI and `AGENTS.md`.
- **Q6** Add `docs/QUICK_GUIDE.md` + `docs/README.md` (rewrite `.otko` →
`.osmodel`, rebuild-only APIs → this repo's), update `CONTRIBUTING.md` with
the 5-layer table + install/run/test commands; port `test_docs.py`.
- **Q7** Add `NOTICE` crediting MIT `otko-development` for ported files;
add a per-file header to ported files (`# Ported from otko-development
(MIT), (c) 2026 OTKO contributors`).
- **Q8/Q9/Q10** `pyproject.toml`: drop `scipy`/`pandas` from `[gui]`; convert
mypy to scoped `strict` overrides (core/services/viewmodels); add
`[tool.coverage.run] fail_under`; port the `test_packaging.py` subset that
applies (entrypoint, version single-source, line length).
- **U1/U2/U6** Port `views/formatting.py`; timestamp the console
(`views/docks/console.py` into the existing dock); add `save_layout`/
`restore_layout` (`QSettings`) and a `closeEvent` unsaved-changes prompt.
**Gate:** `ruff check src tests`, `ruff format --check src tests`,
`mypy src/otko/core src/otko/services src/otko/viewmodels`,
`pytest -m "not slow"`, arch test, and the new packaging/docs tests pass.
### Phase 1 — Cheap, safe services wins
- **S1** Port `services/solver_session.py` (`SolverSession`, `RealSolverSession`,
`RecordingSolverSession`). Inject into `OpenSeesRunner` while keeping the
existing `ops_module=` shim; consolidate the two wipe paths
(`_emit.py:105` → `session.reset()`). Tests:
`tests/services/test_solver_session.py`.
- **S2** In `services/persistence.py::save_project`, call
`validate_references()` first and refuse to write an invalid model,
reporting the problem list (PER-022); return the resolved path (PER-021).
- **S3** Extend `StaticResults` with `time` and add a `ModeParticipation`
record to `ModalResults` (keep the existing dataclass names — consumers in
`views/docks/results_panel.py` dispatch on them).
- **S4** `RUN-053`: return an absent (not zero-filled) force entry when a
component is missing; guard the static `eleForce` fallback.
**Gate:** new service tests + existing runner/persistence tests green; runner
integration suite unchanged.
### Phase 2 — Progress & cancellation
- **S5** Add to `services/qt_workers.py`: `progress(int)`, `cancelled`,
an `_interruption_requested()` check between steps, and a bounded teardown
wait. Add `AnalysisRunner.cancel()` (calls `QThread.requestInterruption()`).
Wire progress callbacks through static (`RUN-054`) and modal (`RUN-063`)
runs. Replace the indeterminate bar in `views/dialogs/run_analysis.py` with
a real progress bar + working Cancel (UX-081). Add per-case status to the
case manager (ANL-050).
- **S6** Unify modal mass participation: put the rebuild's participation
math into one service and have **both** modal results and the existing
response-spectrum path (`services/spectrum.py`) consume it. Add the ANL-013
no-mass warning.
**Gate:** cancel leaves no partial handle; progress reaches 100; participation
sums to 1.0 against a hand-checked example.
### Phase 3 — Units display layer + GRAVITY
- **S7** Port the display machinery from `core/units.py` **as an adapter**:
keep this repo's 4-value `UnitSystem` and map families
(`SI_M_N|SI_MM_N → METRIC`, `US_FT_KIP|US_IN_KIP → IMPERIAL`); add
`GRAVITY`, `display(value, system, quantity, pref)`, `DisplayPrefs`; add
`ProjectMeta.display` (persisted). Retarget the status-bar/menu unit picker
so it writes **display prefs**, not the stored `meta.units` (fixes UNT-031).
- Watch-outs: rebuild uses `StrEnum` (3.11+) — do **not** adopt it (this repo
targets 3.10). `export.py` currently embeds `meta.units.value`; keep that
but source labels via the new API.
**Gate:** switching display units changes every label and leaves
`project.model_dump()` byte-identical; old 4-system `.osmodel` files still load.
### Phase 4 — Closed-form diagrams
- **S8** Port `core/diagrams.py` near-verbatim (pure numpy, self-contained).
- **S9** Build a new `services/diagram_data.py` (REIMPL) on top of this repo's
`StaticResults` + load patterns, reusing `core/diagrams` for interior
shapes/extrema. Run it **alongside** `services/element_forces.py`, migrate
`views/canvas3d/diagram_renderer.py` and `views/dock_manager.py` behind a
flag, then retire the old extractor once the on-screen output matches.
**Gate:** port `test_diagram_data.py` (end-values, Vz/My plane, axial,
all-six components, shared data, auto-scale); on-screen diagrams unchanged.
### Phase 5 — Reporting pipeline ★ (the headline v1 capability)
- **S10** Port `services/report/{__init__,csv,figures,typst,pdf}.py`. Add a
`[reports]` extra (`matplotlib`, `imageio-ffmpeg`; Typst CLI optional, probed
via `shutil.which`, graceful degradation per RES-046). Expose a "case report"
action that produces the full set: CSV tables, PNG (≥300 dpi), SVG, a Typst
document (PDF optional), conditional static/modal sections.
- Dependencies: **Phase 3** (units) and **Phase 4** (diagrams) must land first;
reuse **Phase 1** result fields.
**Gate:** the reference test — cantilever moment **50 kN·m at the fixed end**
(RES-061) — plus report generation off the GUI thread and preservation of the
original model file. Port `test_report_{csv,figures,typst,modal}.py` and the
`test_full_report.py` / `test_report_reference.py` integration tests.
### Phase 6 — Local axis (user-editable)
- **S11** Port `core/geometry/local_axis.py`; add
`local_axis: LocalAxis` to the frame elements (`ElasticBeamColumn`,
`ForceBeamColumn`, `DispBeamColumn`, `BeamWithHinges`). Change
`services/_emit.py` geomTransf to read the explicit axis and dedup by
`(type, vecxz, roll_deg)` instead of auto-deriving. Update the renderer
triad (its current `getattr(el, "vecxz")` at `model_renderer.py:727` is dead
code) and add an editor (property dock / dialog).
- **Critical migration risk:** a blind default `vecxz=(0,0,1)` is parallel to
a vertical member's axis and would break existing vertical models. Use a
**safe default rule** (e.g. derive the default from geometry exactly as the
runner does today, then only override when the user sets it) so existing
`.osmodel` files keep loading and producing identical results.
**Gate:** existing frame/eigen integration tests unchanged; new
`test_local_axis_parallel_rejected` + `test_geom_transf_dedup_by_combination`.
### Phase 7 — Load combinations + self-weight
- **S12** Port `core/combinations.py` and `commands/combinations.py`; add
`Project.combinations`; extend `validate_references`; add
`StaticCase.combination_id` with the XOR invariant (combination **or**
patterns+factors, ANL-001); materialise scaled loads in the runner
(LOD-054) without regressing the existing per-pattern factor path.
- **S13** Reimplement `services/self_weight.py` against this repo's types:
`w = ρ·A·g` distributed local for frames, equivalent nodal loads for trusses
(UNT-042/043), a `ConstantTimeSeries` + `PlainLoadPattern`, regeneration that
replaces the prior pattern (LOD-041), no-density/unresolved reporting
(LOD-042), and the gravity constant recorded in the description (UNT-045).
Add a `RegenerateSelfWeightCommand` (undoable).
- **S14** `ElasticIsotropic` currently is the only material with `rho`
(`materials/__init__.py:28`); add `rho` to the other self-weight-capable
materials, or report them as missing density.
- Depends on **Phase 3** (`GRAVITY`) and **Phase 6** (correct local projection).
**Gate:** port `test_loads_combinations.py` and `test_self_weight.py` (minus
the combination assertion until S12 lands); verify superposition matches a
hand calculation.
### Phase 8 — UI/UX adoption (larger, optional but valuable)
- **U3** `ValidatedDialog` base + migrate dialogs incrementally (unit suffix
via the Phase 3 API).
- **U4** Extract `ResultsVM` (per-case handle cache) and `CanvasVM` (selection
ownership) as supersets of the current state holders so existing call sites
keep working.
- **U5** Reimplement overlay **pure helpers** against this repo's
`deformation`/`element_forces`: ghost undeformed (CAN-062), unit-labelled
diagram extremes (CAN-082), zero-component hint (CAN-083), and
pattern-filtered load display (CAN-052/LOD-063). Unit-test them display-free.
- **U7** Adopt `ThemeManager` + a dark icon set — **verify SVG provenance and
license first** before copying any icon assets.
- **U8/U9** Thicken `ProjectViewModel` (move `action_handlers.py` logic into VM
methods, one command family at a time) and add analysis-case status /
Simple-vs-Advanced controls.
- **Q11/Q12** Spec-ID traceability harness and performance probes (only if the
team commits to the `[AREA-NNN]` convention and a perf budget).
**Gate:** GUI tests under `xvfb-run`; VM logic unit-tested without a display.
### Phase 9 — Deferred, only on explicit decision
- Polygon-first sections + `sections_mesh` (opstool **GPLv3**, lazy import,
optional `[sections]` extra; ensure AGPL compatibility and attribution).
- Frozen `Project`/`ProjectStore`/`CommandFactory` migration.
- Canvas backend Protocol + plotly backend + `services/scene.py`.
Revisit only after Phases 0–8 are stable and if the value justifies the blast
radius documented in the dossiers.
## 6. Dependency graph
```
Phase 0 (foundations)
│
├─► Phase 1 (sessions, persistence, result fields)
│ │
│ ├─► Phase 2 (progress/cancel, mass participation)
│ │
│ └─► Phase 3 (units display + GRAVITY) ──┐
│ │
│ Phase 4 (diagrams) ────────────────┤
│ ▼
│ Phase 5 (REPORTING) ★
│
├─► Phase 6 (local axis) ──┐
│ ▼
└─► Phase 7 (combinations + self-weight)
│
▼
Phase 8 (UI/UX) ──► Phase 9 (deferred)
```
**Critical path to the v1 promise (a printable case report):**
`Phase 3 → Phase 4 → Phase 5`, with `Phase 1` as a cheap prerequisite and
`Phase 2` interleavable.
## 7. Licensing & attribution
- This repo is **AGPL-3.0**; the rebuild is **MIT**. MIT code may be
incorporated into an AGPL work — **one-way**. Preserve the MIT notice:
add a `NOTICE` (Phase 0) and a short provenance header to each ported file.
- **Never** copy this repo's AGPL code back into the MIT rebuild.
- `opstool` is **GPLv3** (only relevant to deferred `sections_mesh`); GPLv3 ↔
AGPLv3 are compatible. Keep it lazy/optional and do not vendor its source.
- Verify the provenance/license of any copied **icon/SVG assets** before
adopting the dark icon set (U7).
## 8. Risks and mitigations
| Risk | Mitigation |
|---|---|
| Big-bang port destabilises the working app | Strict additive phases; feature flags for diagram/report migration; keep old paths until parity is proven |
| Freezing/command rewrite stalls progress | Explicitly deferred (Phase 9); combinations/self-weight do **not** require it |
| Units enum change corrupts stored models | Keep 4-value enum; add a family mapping + `DisplayPrefs`; byte-identical dump test |
| Local-axis default breaks vertical members | Derive default per-element as today; override only on explicit user set; regression tests on vertical frames |
| opstool private-API coupling / GPL | Deferred; pin version + thin adapter; lazy import; attribution |
| Report pipeline pulls GUI deps into headless | Keep `matplotlib`/Typst optional and imported lazily; headless CI must pass without `[reports]` |
| `StrEnum` / 3.11-only syntax | Target py3.10: avoid `StrEnum`, `zip(strict=)`, etc. |
| No VCS in this checkout | Initialise git + branch before any code changes |
| Tests can't run locally (deps missing) | Phase 0 fixes env expectations; run gates in CI |
## 9. Tracking
Adopt the rebuild's `.otko-build/tasks.json` **pattern** (schema, gates,
`{id, phase, layer, specs, title, tests, status, deps}`), seeded from this
plan. Each task names the phase, the spec IDs it implements, and its tests
(the rebuild's `tasks.json` is a working reference). Keep build state out of
versioned source (`.gitignore` it) or commit it deliberately — team choice.
## 10. Recommended first step
Execute **Phase 0** in one branch. It is almost entirely additive, it turns
the currently-inert mypy/CI gate into a real one, and it establishes the
attribution and docs baseline the later ports depend on. Then proceed
`1 → 2 → 3 → 4 → 5`, pulling Phase 6/7 forward only if self-weight is needed
before reporting.

View file

@ -1,37 +0,0 @@
# OTKO — specifications (this repo)
This folder holds **OTKO's own planning documents**. It is deliberately
separate from the greenfield rebuild spec set at
`~/Sync/otko-development/specifications` (docs `00`–`14`), which stays the
reference for *what a conformant rebuild looks like*. Requirement IDs of
the form `[AREA-NNN]` cited in this folder refer to that rebuild set.
## Why this folder exists
`~/Sync/otko` (this repo) is the **working, feature-rich app** and is the
primary deliverable. `~/Sync/otko-development` is a **greenfield rebuild**
that conforms closely to the rebuild specs but is less capable in several
areas (transient/pushover/response-spectrum, richer element/material
coverage, `.osmodel` corpus, HDF5). The goal of the plan below is to
**harvest the rebuild's good, spec-conformant capabilities into this app
without breaking what already works** — not to rewrite this app to the
rebuild's architecture.
## Documents
| # | Document | Purpose |
|---|---|---|
| 15 | [15-rebuild-adoption-plan.md](15-rebuild-adoption-plan.md) | Dependency-ordered plan for porting rebuild capabilities into this repo, with adoption matrix, phases, gates, risks and explicit skips. |
## Ground rules (summary — see doc 15 §3)
- **Additive, never replacement.** This repo is a superset of the rebuild
in the solver/runner/export surface; protect that.
- **Keep the working app working:** `.osmodel` format, AGPL-3.0 license,
Python 3.10–3.12 support, existing tests green.
- **Adapt, don't copy:** re-type ported code to this repo's APIs
(`StaticResults`/`ModalResults`, mutable `Project`, 4-value `UnitSystem`).
- **One phase = one branch = independently shippable**, each with its own
tests and gate.
- **License hygiene:** the rebuild is MIT, this repo is AGPL-3.0; MIT→AGPL
is compatible, but ported files need attribution (see doc 15 §7).

View file

@ -1,5 +1,3 @@
"""OTKO — a desktop GUI for OpenSeesPy.""" """OTKO — a desktop GUI for OpenSeesPy."""
from otko._const import __version__ __version__ = "0.1.0"
__all__ = ["__version__"]

View file

@ -1,13 +0,0 @@
# Ported from otko-development (MIT), (c) 2026 OTKO contributors
"""Single source of truth for OTKO's version and the pinned solver version.
Defines the package version and the pinned OpenseesPy version exactly once
so neither is duplicated as a literal anywhere else in the source.
"""
from __future__ import annotations
__version__ = "0.1.0"
#: Pinned OpenseesPy version the application targets.
OPENSEESPY_VERSION = "3.8.0.0"

View file

@ -6,11 +6,6 @@ from otko.commands.analysis import (
UpdateAnalysisCaseCommand, UpdateAnalysisCaseCommand,
) )
from otko.commands.base import ProjectCommand from otko.commands.base import ProjectCommand
from otko.commands.combinations import (
AddCombinationsCommand,
DeleteCombinationsCommand,
UpdateCombinationCommand,
)
from otko.commands.constraints import ( from otko.commands.constraints import (
AddEqualDOFConstraintCommand, AddEqualDOFConstraintCommand,
DeleteEqualDOFConstraintCommand, DeleteEqualDOFConstraintCommand,
@ -29,6 +24,14 @@ from otko.commands.grid import (
SetCoordSystemsCommand, SetCoordSystemsCommand,
SetGridSystemCommand, SetGridSystemCommand,
) )
from otko.commands.series_and_patterns import (
AddLoadPatternCommand,
AddTimeSeriesCommand,
DeleteLoadPatternCommand,
DeleteTimeSeriesCommand,
UpdateLoadPatternCommand,
UpdateTimeSeriesCommand,
)
from otko.commands.loads import ( from otko.commands.loads import (
AddElementLoadsCommand, AddElementLoadsCommand,
AddNodalLoadsCommand, AddNodalLoadsCommand,
@ -55,14 +58,6 @@ from otko.commands.sections import (
DeleteSectionsCommand, DeleteSectionsCommand,
UpdateSectionCommand, UpdateSectionCommand,
) )
from otko.commands.series_and_patterns import (
AddLoadPatternCommand,
AddTimeSeriesCommand,
DeleteLoadPatternCommand,
DeleteTimeSeriesCommand,
UpdateLoadPatternCommand,
UpdateTimeSeriesCommand,
)
from otko.commands.transforms import ( from otko.commands.transforms import (
MirrorCommand, MirrorCommand,
MoveNodesCommand, MoveNodesCommand,
@ -72,50 +67,25 @@ from otko.commands.transforms import (
__all__ = [ __all__ = [
"ProjectCommand", "ProjectCommand",
"AddNodesCommand", "AddNodesCommand", "DeleteNodesCommand", "SetRestraintCommand", "SetMassCommand",
"DeleteNodesCommand",
"SetRestraintCommand",
"SetMassCommand",
"UpdateNodeFieldsCommand", "UpdateNodeFieldsCommand",
"AddElementsCommand", "AddElementsCommand", "DeleteElementsCommand",
"DeleteElementsCommand", "AssignSectionCommand", "AssignMaterialCommand",
"AssignSectionCommand", "ReplaceElementsCommand", "ConvertElementTypeCommand",
"AssignMaterialCommand",
"ReplaceElementsCommand",
"ConvertElementTypeCommand",
"UpdateElementFieldsCommand", "UpdateElementFieldsCommand",
"AddMaterialsCommand", "AddMaterialsCommand", "DeleteMaterialsCommand", "UpdateMaterialCommand",
"DeleteMaterialsCommand", "AddSectionsCommand", "DeleteSectionsCommand", "UpdateSectionCommand",
"UpdateMaterialCommand", "AddNodalLoadsCommand", "AddElementLoadsCommand",
"AddSectionsCommand", "UpdateNodalLoadCommand", "DeleteNodalLoadsCommand",
"DeleteSectionsCommand", "UpdateElementLoadCommand", "DeleteElementLoadsCommand",
"UpdateSectionCommand", "MoveNodesCommand", "ReplicateCommand", "MirrorCommand", "Plane",
"AddNodalLoadsCommand", "AddAnalysisCasesCommand", "DeleteAnalysisCasesCommand", "UpdateAnalysisCaseCommand",
"AddElementLoadsCommand",
"UpdateNodalLoadCommand",
"DeleteNodalLoadsCommand",
"UpdateElementLoadCommand",
"DeleteElementLoadsCommand",
"MoveNodesCommand",
"ReplicateCommand",
"MirrorCommand",
"Plane",
"AddAnalysisCasesCommand",
"DeleteAnalysisCasesCommand",
"UpdateAnalysisCaseCommand",
"AddCombinationsCommand",
"DeleteCombinationsCommand",
"UpdateCombinationCommand",
"SetGridSystemCommand", "SetGridSystemCommand",
"SetCoordSystemsCommand", "SetCoordSystemsCommand",
"AddTimeSeriesCommand", "AddTimeSeriesCommand", "AddLoadPatternCommand",
"AddLoadPatternCommand", "UpdateTimeSeriesCommand", "DeleteTimeSeriesCommand",
"UpdateTimeSeriesCommand", "UpdateLoadPatternCommand", "DeleteLoadPatternCommand",
"DeleteTimeSeriesCommand",
"UpdateLoadPatternCommand",
"DeleteLoadPatternCommand",
"AddEqualDOFConstraintCommand", "AddEqualDOFConstraintCommand",
"UpdateEqualDOFConstraintCommand", "UpdateEqualDOFConstraintCommand", "DeleteEqualDOFConstraintCommand",
"DeleteEqualDOFConstraintCommand",
"SetUnitsCommand", "SetUnitsCommand",
] ]

View file

@ -13,7 +13,8 @@ if TYPE_CHECKING:
class AddAnalysisCasesCommand(ProjectCommand): class AddAnalysisCasesCommand(ProjectCommand):
"""Add one or more analysis cases.""" """Add one or more analysis cases."""
def __init__(self, vm: ProjectViewModel, cases: list[Any], *, text: str | None = None) -> None: def __init__(self, vm: "ProjectViewModel", cases: list[Any], *,
text: str | None = None) -> None:
super().__init__(vm, text or f"Add {len(cases)} analysis case(s)") super().__init__(vm, text or f"Add {len(cases)} analysis case(s)")
self._cases = list(cases) self._cases = list(cases)
@ -34,16 +35,19 @@ class AddAnalysisCasesCommand(ProjectCommand):
class DeleteAnalysisCasesCommand(ProjectCommand): class DeleteAnalysisCasesCommand(ProjectCommand):
"""Remove a set of analysis cases.""" """Remove a set of analysis cases."""
def __init__(self, vm: ProjectViewModel, case_ids: set[int]) -> None: def __init__(self, vm: "ProjectViewModel", case_ids: set[int]) -> None:
super().__init__(vm, f"Delete {len(case_ids)} analysis case(s)") super().__init__(vm, f"Delete {len(case_ids)} analysis case(s)")
self._case_ids = set(case_ids) self._case_ids = set(case_ids)
self._removed: list[tuple[int, Any]] = [] self._removed: list[tuple[int, Any]] = []
def redo(self) -> None: def redo(self) -> None:
self._removed = [ self._removed = [
(i, c) for i, c in enumerate(self.project.analyses) if c.id in self._case_ids (i, c) for i, c in enumerate(self.project.analyses)
if c.id in self._case_ids
]
self.project.analyses[:] = [
c for c in self.project.analyses if c.id not in self._case_ids
] ]
self.project.analyses[:] = [c for c in self.project.analyses if c.id not in self._case_ids]
self._notify() self._notify()
def undo(self) -> None: def undo(self) -> None:
@ -56,7 +60,7 @@ class DeleteAnalysisCasesCommand(ProjectCommand):
class UpdateAnalysisCaseCommand(ProjectCommand): class UpdateAnalysisCaseCommand(ProjectCommand):
"""Replace an analysis case at a given id.""" """Replace an analysis case at a given id."""
def __init__(self, vm: ProjectViewModel, new_case: Any) -> None: def __init__(self, vm: "ProjectViewModel", new_case: Any) -> None:
super().__init__(vm, f"Edit analysis case {new_case.id}") super().__init__(vm, f"Edit analysis case {new_case.id}")
self._new = new_case self._new = new_case
self._old: Any | None = None self._old: Any | None = None

View file

@ -27,18 +27,20 @@ class ProjectCommand(QUndoCommand):
:meth:`_notify` exactly once at the end of each. :meth:`_notify` exactly once at the end of each.
""" """
def __init__(self, vm: ProjectViewModel, text: str) -> None: def __init__(self, vm: "ProjectViewModel", text: str) -> None:
super().__init__(text) super().__init__(text)
self._vm = vm self._vm = vm
@property @property
def vm(self) -> ProjectViewModel: def vm(self) -> "ProjectViewModel":
return self._vm return self._vm
@property @property
def project(self) -> Project: def project(self) -> "Project":
if self._vm.project is None: if self._vm.project is None:
raise RuntimeError(f"Cannot apply '{self.text()}': no active project.") raise RuntimeError(
f"Cannot apply '{self.text()}': no active project."
)
return self._vm.project return self._vm.project
def _notify(self) -> None: def _notify(self) -> None:

View file

@ -1,80 +0,0 @@
"""Commands for load-combination management."""
from __future__ import annotations
from typing import TYPE_CHECKING, Any
from otko.commands.base import ProjectCommand
if TYPE_CHECKING:
from otko.viewmodels import ProjectViewModel
class AddCombinationsCommand(ProjectCommand):
"""Add one or more load combinations."""
def __init__(self, vm: ProjectViewModel, combos: list[Any], *, text: str | None = None) -> None:
super().__init__(vm, text or f"Add {len(combos)} load combination(s)")
self._combos = list(combos)
def redo(self) -> None:
existing = {c.id for c in self.project.combinations}
for combo in self._combos:
if combo.id in existing:
raise ValueError(f"Load combination id {combo.id} already exists.")
self.project.combinations.extend(self._combos)
self._notify()
def undo(self) -> None:
ids = {c.id for c in self._combos}
self.project.combinations[:] = [c for c in self.project.combinations if c.id not in ids]
self._notify()
class DeleteCombinationsCommand(ProjectCommand):
"""Remove a set of load combinations."""
def __init__(self, vm: ProjectViewModel, combo_ids: set[int]) -> None:
super().__init__(vm, f"Delete {len(combo_ids)} load combination(s)")
self._combo_ids = set(combo_ids)
self._removed: list[tuple[int, Any]] = []
def redo(self) -> None:
self._removed = [
(i, c) for i, c in enumerate(self.project.combinations) if c.id in self._combo_ids
]
self.project.combinations[:] = [
c for c in self.project.combinations if c.id not in self._combo_ids
]
self._notify()
def undo(self) -> None:
for i, c in self._removed:
self.project.combinations.insert(min(i, len(self.project.combinations)), c)
self._removed.clear()
self._notify()
class UpdateCombinationCommand(ProjectCommand):
"""Replace a load combination at a given id."""
def __init__(self, vm: ProjectViewModel, new_combo: Any) -> None:
super().__init__(vm, f"Edit load combination {new_combo.id}")
self._new = new_combo
self._old: Any | None = None
self._index: int | None = None
def redo(self) -> None:
for i, c in enumerate(self.project.combinations):
if c.id == self._new.id:
self._old = c
self._index = i
self.project.combinations[i] = self._new
self._notify()
return
raise KeyError(f"Load combination with id={self._new.id} not found.")
def undo(self) -> None:
if self._old is not None and self._index is not None:
self.project.combinations[self._index] = self._old
self._notify()

View file

@ -14,7 +14,7 @@ if TYPE_CHECKING:
class AddEqualDOFConstraintCommand(ProjectCommand): class AddEqualDOFConstraintCommand(ProjectCommand):
"""Append an ``equalDOF`` constraint to the project (undoable).""" """Append an ``equalDOF`` constraint to the project (undoable)."""
def __init__(self, vm: ProjectViewModel, constraint: EqualDOFConstraint) -> None: def __init__(self, vm: "ProjectViewModel", constraint: EqualDOFConstraint) -> None:
super().__init__( super().__init__(
vm, vm,
f"Add equalDOF {constraint.retained_node}->{constraint.constrained_node}", f"Add equalDOF {constraint.retained_node}->{constraint.constrained_node}",
@ -34,7 +34,8 @@ class AddEqualDOFConstraintCommand(ProjectCommand):
def undo(self) -> None: def undo(self) -> None:
self.project.mp_constraints[:] = [ self.project.mp_constraints[:] = [
mp for mp in self.project.mp_constraints if mp != self._constraint mp for mp in self.project.mp_constraints
if mp != self._constraint
] ]
self._notify() self._notify()
@ -48,7 +49,7 @@ class UpdateEqualDOFConstraintCommand(ProjectCommand):
""" """
def __init__( def __init__(
self, vm: ProjectViewModel, index: int, new_constraint: EqualDOFConstraint self, vm: "ProjectViewModel", index: int, new_constraint: EqualDOFConstraint
) -> None: ) -> None:
super().__init__(vm, f"Edit equalDOF row {index + 1}") super().__init__(vm, f"Edit equalDOF row {index + 1}")
self._index = index self._index = index
@ -71,7 +72,7 @@ class UpdateEqualDOFConstraintCommand(ProjectCommand):
class DeleteEqualDOFConstraintCommand(ProjectCommand): class DeleteEqualDOFConstraintCommand(ProjectCommand):
"""Remove ``equalDOF`` constraints by table-row index (no cascade).""" """Remove ``equalDOF`` constraints by table-row index (no cascade)."""
def __init__(self, vm: ProjectViewModel, indices: set[int]) -> None: def __init__(self, vm: "ProjectViewModel", indices: set[int]) -> None:
super().__init__(vm, f"Delete {len(indices)} constraint(s)") super().__init__(vm, f"Delete {len(indices)} constraint(s)")
self._indices = set(indices) self._indices = set(indices)
self._removed: list[tuple[int, EqualDOFConstraint]] = [] self._removed: list[tuple[int, EqualDOFConstraint]] = []

View file

@ -14,7 +14,7 @@ class AddElementsCommand(ProjectCommand):
"""Add one or more elements in a single undoable step.""" """Add one or more elements in a single undoable step."""
def __init__( def __init__(
self, vm: ProjectViewModel, elements: list[Any], *, text: str | None = None self, vm: "ProjectViewModel", elements: list[Any], *, text: str | None = None
) -> None: ) -> None:
super().__init__(vm, text or f"Add {len(elements)} element(s)") super().__init__(vm, text or f"Add {len(elements)} element(s)")
self._elements = list(elements) self._elements = list(elements)
@ -40,7 +40,7 @@ class AddElementsCommand(ProjectCommand):
class DeleteElementsCommand(ProjectCommand): class DeleteElementsCommand(ProjectCommand):
"""Remove a set of elements (no cascade — nodes are not affected).""" """Remove a set of elements (no cascade — nodes are not affected)."""
def __init__(self, vm: ProjectViewModel, element_ids: set[int]) -> None: def __init__(self, vm: "ProjectViewModel", element_ids: set[int]) -> None:
super().__init__(vm, f"Delete {len(element_ids)} element(s)") super().__init__(vm, f"Delete {len(element_ids)} element(s)")
self._element_ids = set(element_ids) self._element_ids = set(element_ids)
self._removed: list[tuple[int, Any]] = [] self._removed: list[tuple[int, Any]] = []
@ -68,7 +68,7 @@ class AssignSectionCommand(ProjectCommand):
(e.g. trusses, zero-length elements). (e.g. trusses, zero-length elements).
""" """
def __init__(self, vm: ProjectViewModel, element_ids: set[int], section_id: int) -> None: def __init__(self, vm: "ProjectViewModel", element_ids: set[int], section_id: int) -> None:
super().__init__(vm, f"Assign section {section_id} to {len(element_ids)} element(s)") super().__init__(vm, f"Assign section {section_id} to {len(element_ids)} element(s)")
self._element_ids = set(element_ids) self._element_ids = set(element_ids)
self._section_id = section_id self._section_id = section_id
@ -106,7 +106,7 @@ class ConvertElementTypeCommand(ProjectCommand):
def __init__( def __init__(
self, self,
vm: ProjectViewModel, vm: "ProjectViewModel",
element_ids: set[int], element_ids: set[int],
target_type: str, target_type: str,
defaults: dict[str, Any] | None = None, defaults: dict[str, Any] | None = None,
@ -185,7 +185,7 @@ class ReplaceElementsCommand(ProjectCommand):
for another while preserving the id and node connectivity. for another while preserving the id and node connectivity.
""" """
def __init__(self, vm: ProjectViewModel, replacements: list[Any]) -> None: def __init__(self, vm: "ProjectViewModel", replacements: list[Any]) -> None:
super().__init__(vm, f"Replace {len(replacements)} element(s)") super().__init__(vm, f"Replace {len(replacements)} element(s)")
self._replacements = {el.id: el for el in replacements} self._replacements = {el.id: el for el in replacements}
self._previous: dict[int, Any] = {} self._previous: dict[int, Any] = {}
@ -217,7 +217,7 @@ class UpdateElementFieldsCommand(ProjectCommand):
def __init__( def __init__(
self, self,
vm: ProjectViewModel, vm: "ProjectViewModel",
element_id: int, element_id: int,
fields: dict[str, Any], fields: dict[str, Any],
) -> None: ) -> None:
@ -254,7 +254,7 @@ class UpdateElementFieldsCommand(ProjectCommand):
class AssignMaterialCommand(ProjectCommand): class AssignMaterialCommand(ProjectCommand):
"""Set ``material_id`` on a set of elements (truss-style).""" """Set ``material_id`` on a set of elements (truss-style)."""
def __init__(self, vm: ProjectViewModel, element_ids: set[int], material_id: int) -> None: def __init__(self, vm: "ProjectViewModel", element_ids: set[int], material_id: int) -> None:
super().__init__(vm, f"Assign material {material_id} to {len(element_ids)} element(s)") super().__init__(vm, f"Assign material {material_id} to {len(element_ids)} element(s)")
self._element_ids = set(element_ids) self._element_ids = set(element_ids)
self._material_id = material_id self._material_id = material_id

View file

@ -20,7 +20,7 @@ class SetCoordSystemsCommand(ProjectCommand):
def __init__( def __init__(
self, self,
vm: ProjectViewModel, vm: "ProjectViewModel",
new_systems: list[CoordinateGridSystem], new_systems: list[CoordinateGridSystem],
) -> None: ) -> None:
super().__init__(vm, "Update coordinate/grid systems") super().__init__(vm, "Update coordinate/grid systems")
@ -46,7 +46,7 @@ class SetGridSystemCommand(ProjectCommand):
systems at once. systems at once.
""" """
def __init__(self, vm: ProjectViewModel, new_grid: GridSystem) -> None: def __init__(self, vm: "ProjectViewModel", new_grid: GridSystem) -> None:
super().__init__(vm, "Update grid system") super().__init__(vm, "Update grid system")
self._new_grid = new_grid self._new_grid = new_grid
self._previous: GridSystem | None = None self._previous: GridSystem | None = None

View file

@ -35,7 +35,7 @@ class AddNodalLoadsCommand(ProjectCommand):
def __init__( def __init__(
self, self,
vm: ProjectViewModel, vm: "ProjectViewModel",
node_ids: set[int], node_ids: set[int],
forces: tuple[float, float, float, float, float, float], forces: tuple[float, float, float, float, float, float],
pattern_id: int | None = None, pattern_id: int | None = None,
@ -101,10 +101,7 @@ class AddNodalLoadsCommand(ProjectCommand):
break break
self._added_loads.clear() self._added_loads.clear()
# Roll back any infrastructure we created. # Roll back any infrastructure we created.
if ( if self._created_pattern is not None and self._created_pattern in self.project.load_patterns:
self._created_pattern is not None
and self._created_pattern in self.project.load_patterns
):
self.project.load_patterns.remove(self._created_pattern) self.project.load_patterns.remove(self._created_pattern)
self._created_pattern = None self._created_pattern = None
if self._created_ts is not None and self._created_ts in self.project.time_series: if self._created_ts is not None and self._created_ts in self.project.time_series:
@ -122,7 +119,7 @@ class AddElementLoadsCommand(ProjectCommand):
def __init__( def __init__(
self, self,
vm: ProjectViewModel, vm: "ProjectViewModel",
element_ids: set[int], element_ids: set[int],
wy: float = 0.0, wy: float = 0.0,
wz: float = 0.0, wz: float = 0.0,
@ -160,10 +157,7 @@ class AddElementLoadsCommand(ProjectCommand):
pattern = self._resolve_pattern() pattern = self._resolve_pattern()
for eid in self._element_ids: for eid in self._element_ids:
load = UniformElementLoad( load = UniformElementLoad(
element_id=eid, element_id=eid, wy=self._wy, wz=self._wz, wx=self._wx,
wy=self._wy,
wz=self._wz,
wx=self._wx,
) )
pattern.element_loads.append(load) pattern.element_loads.append(load)
self._added_loads.append((pattern.id, load)) self._added_loads.append((pattern.id, load))
@ -177,10 +171,7 @@ class AddElementLoadsCommand(ProjectCommand):
pat.element_loads.remove(load) pat.element_loads.remove(load)
break break
self._added_loads.clear() self._added_loads.clear()
if ( if self._created_pattern is not None and self._created_pattern in self.project.load_patterns:
self._created_pattern is not None
and self._created_pattern in self.project.load_patterns
):
self.project.load_patterns.remove(self._created_pattern) self.project.load_patterns.remove(self._created_pattern)
self._created_pattern = None self._created_pattern = None
if self._created_ts is not None and self._created_ts in self.project.time_series: if self._created_ts is not None and self._created_ts in self.project.time_series:

View file

@ -13,9 +13,7 @@ if TYPE_CHECKING:
class AddMaterialsCommand(ProjectCommand): class AddMaterialsCommand(ProjectCommand):
"""Add one or more materials in a single undoable step.""" """Add one or more materials in a single undoable step."""
def __init__( def __init__(self, vm: "ProjectViewModel", materials: list[Any], *, text: str | None = None) -> None:
self, vm: ProjectViewModel, materials: list[Any], *, text: str | None = None
) -> None:
super().__init__(vm, text or f"Add {len(materials)} material(s)") super().__init__(vm, text or f"Add {len(materials)} material(s)")
self._materials = list(materials) self._materials = list(materials)
@ -36,14 +34,15 @@ class AddMaterialsCommand(ProjectCommand):
class DeleteMaterialsCommand(ProjectCommand): class DeleteMaterialsCommand(ProjectCommand):
"""Remove materials (no cascade).""" """Remove materials (no cascade)."""
def __init__(self, vm: ProjectViewModel, material_ids: set[int]) -> None: def __init__(self, vm: "ProjectViewModel", material_ids: set[int]) -> None:
super().__init__(vm, f"Delete {len(material_ids)} material(s)") super().__init__(vm, f"Delete {len(material_ids)} material(s)")
self._material_ids = set(material_ids) self._material_ids = set(material_ids)
self._removed: list[tuple[int, Any]] = [] self._removed: list[tuple[int, Any]] = []
def redo(self) -> None: def redo(self) -> None:
self._removed = [ self._removed = [
(i, m) for i, m in enumerate(self.project.materials) if m.id in self._material_ids (i, m) for i, m in enumerate(self.project.materials)
if m.id in self._material_ids
] ]
self.project.materials[:] = [ self.project.materials[:] = [
m for m in self.project.materials if m.id not in self._material_ids m for m in self.project.materials if m.id not in self._material_ids
@ -64,7 +63,7 @@ class UpdateMaterialCommand(ProjectCommand):
otherwise this is an Add+Delete, not an update. otherwise this is an Add+Delete, not an update.
""" """
def __init__(self, vm: ProjectViewModel, new_material: Any) -> None: def __init__(self, vm: "ProjectViewModel", new_material: Any) -> None:
super().__init__(vm, f"Edit material {new_material.id}") super().__init__(vm, f"Edit material {new_material.id}")
self._new = new_material self._new = new_material
self._old: Any | None = None self._old: Any | None = None

View file

@ -14,7 +14,7 @@ if TYPE_CHECKING:
class AddNodesCommand(ProjectCommand): class AddNodesCommand(ProjectCommand):
"""Add one or more nodes in a single undoable step.""" """Add one or more nodes in a single undoable step."""
def __init__(self, vm: ProjectViewModel, nodes: list[Node], *, text: str | None = None) -> None: def __init__(self, vm: "ProjectViewModel", nodes: list[Node], *, text: str | None = None) -> None:
super().__init__(vm, text or f"Add {len(nodes)} node(s)") super().__init__(vm, text or f"Add {len(nodes)} node(s)")
self._nodes = list(nodes) self._nodes = list(nodes)
@ -39,7 +39,7 @@ class DeleteNodesCommand(ProjectCommand):
them in their original positions. them in their original positions.
""" """
def __init__(self, vm: ProjectViewModel, node_ids: set[int]) -> None: def __init__(self, vm: "ProjectViewModel", node_ids: set[int]) -> None:
super().__init__(vm, f"Delete {len(node_ids)} node(s)") super().__init__(vm, f"Delete {len(node_ids)} node(s)")
self._node_ids = set(node_ids) self._node_ids = set(node_ids)
self._removed_nodes: list[tuple[int, Node]] = [] # (index, node) self._removed_nodes: list[tuple[int, Node]] = [] # (index, node)
@ -49,8 +49,7 @@ class DeleteNodesCommand(ProjectCommand):
def redo(self) -> None: def redo(self) -> None:
# Cascade: snapshot every element that references a doomed node. # Cascade: snapshot every element that references a doomed node.
self._removed_elements = [ self._removed_elements = [
(i, el) (i, el) for i, el in enumerate(self.project.elements)
for i, el in enumerate(self.project.elements)
if any(nid in self._node_ids for nid in el.nodes) if any(nid in self._node_ids for nid in el.nodes)
] ]
doomed_elem_ids = {el.id for _, el in self._removed_elements} doomed_elem_ids = {el.id for _, el in self._removed_elements}
@ -59,8 +58,7 @@ class DeleteNodesCommand(ProjectCommand):
] ]
self._removed_mp_constraints = [ self._removed_mp_constraints = [
(i, mp) (i, mp) for i, mp in enumerate(self.project.mp_constraints)
for i, mp in enumerate(self.project.mp_constraints)
if mp.retained_node in self._node_ids or mp.constrained_node in self._node_ids if mp.retained_node in self._node_ids or mp.constrained_node in self._node_ids
] ]
doomed_mp = {id(mp) for _, mp in self._removed_mp_constraints} doomed_mp = {id(mp) for _, mp in self._removed_mp_constraints}
@ -71,7 +69,9 @@ class DeleteNodesCommand(ProjectCommand):
self._removed_nodes = [ self._removed_nodes = [
(i, n) for i, n in enumerate(self.project.nodes) if n.id in self._node_ids (i, n) for i, n in enumerate(self.project.nodes) if n.id in self._node_ids
] ]
self.project.nodes[:] = [n for n in self.project.nodes if n.id not in self._node_ids] self.project.nodes[:] = [
n for n in self.project.nodes if n.id not in self._node_ids
]
self._notify() self._notify()
def undo(self) -> None: def undo(self) -> None:
@ -93,7 +93,7 @@ class SetRestraintCommand(ProjectCommand):
def __init__( def __init__(
self, self,
vm: ProjectViewModel, vm: "ProjectViewModel",
node_ids: set[int], node_ids: set[int],
restraint: tuple[bool, bool, bool, bool, bool, bool], restraint: tuple[bool, bool, bool, bool, bool, bool],
) -> None: ) -> None:
@ -128,7 +128,7 @@ class UpdateNodeFieldsCommand(ProjectCommand):
def __init__( def __init__(
self, self,
vm: ProjectViewModel, vm: "ProjectViewModel",
node_id: int, node_id: int,
fields: dict[str, Any], fields: dict[str, Any],
) -> None: ) -> None:
@ -166,7 +166,7 @@ class SetMassCommand(ProjectCommand):
def __init__( def __init__(
self, self,
vm: ProjectViewModel, vm: "ProjectViewModel",
node_ids: set[int], node_ids: set[int],
mass: tuple[float, float, float, float, float, float], mass: tuple[float, float, float, float, float, float],
) -> None: ) -> None:

View file

@ -19,7 +19,7 @@ class SetUnitsCommand(ProjectCommand):
so both redo and undo notify (dirty + modelMutated) to refresh. so both redo and undo notify (dirty + modelMutated) to refresh.
""" """
def __init__(self, vm: ProjectViewModel, units: UnitSystem) -> None: def __init__(self, vm: "ProjectViewModel", units: UnitSystem) -> None:
super().__init__(vm, f"Set display units to {units.value}") super().__init__(vm, f"Set display units to {units.value}")
self._units = units self._units = units
self._previous: UnitSystem | None = None self._previous: UnitSystem | None = None

View file

@ -13,9 +13,7 @@ if TYPE_CHECKING:
class AddSectionsCommand(ProjectCommand): class AddSectionsCommand(ProjectCommand):
"""Add one or more sections in a single undoable step.""" """Add one or more sections in a single undoable step."""
def __init__( def __init__(self, vm: "ProjectViewModel", sections: list[Any], *, text: str | None = None) -> None:
self, vm: ProjectViewModel, sections: list[Any], *, text: str | None = None
) -> None:
super().__init__(vm, text or f"Add {len(sections)} section(s)") super().__init__(vm, text or f"Add {len(sections)} section(s)")
self._sections = list(sections) self._sections = list(sections)
@ -36,14 +34,15 @@ class AddSectionsCommand(ProjectCommand):
class DeleteSectionsCommand(ProjectCommand): class DeleteSectionsCommand(ProjectCommand):
"""Remove sections (no cascade — elements referencing them must be cleaned separately).""" """Remove sections (no cascade — elements referencing them must be cleaned separately)."""
def __init__(self, vm: ProjectViewModel, section_ids: set[int]) -> None: def __init__(self, vm: "ProjectViewModel", section_ids: set[int]) -> None:
super().__init__(vm, f"Delete {len(section_ids)} section(s)") super().__init__(vm, f"Delete {len(section_ids)} section(s)")
self._section_ids = set(section_ids) self._section_ids = set(section_ids)
self._removed: list[tuple[int, Any]] = [] self._removed: list[tuple[int, Any]] = []
def redo(self) -> None: def redo(self) -> None:
self._removed = [ self._removed = [
(i, s) for i, s in enumerate(self.project.sections) if s.id in self._section_ids (i, s) for i, s in enumerate(self.project.sections)
if s.id in self._section_ids
] ]
self.project.sections[:] = [ self.project.sections[:] = [
s for s in self.project.sections if s.id not in self._section_ids s for s in self.project.sections if s.id not in self._section_ids
@ -60,7 +59,7 @@ class DeleteSectionsCommand(ProjectCommand):
class UpdateSectionCommand(ProjectCommand): class UpdateSectionCommand(ProjectCommand):
"""Replace a section's parameters at a given id.""" """Replace a section's parameters at a given id."""
def __init__(self, vm: ProjectViewModel, new_section: Any) -> None: def __init__(self, vm: "ProjectViewModel", new_section: Any) -> None:
super().__init__(vm, f"Edit section {new_section.id}") super().__init__(vm, f"Edit section {new_section.id}")
self._new = new_section self._new = new_section
self._old: Any | None = None self._old: Any | None = None

View file

@ -19,7 +19,7 @@ if TYPE_CHECKING:
class AddTimeSeriesCommand(ProjectCommand): class AddTimeSeriesCommand(ProjectCommand):
"""Append a :class:`TimeSeries` to the project (undoable).""" """Append a :class:`TimeSeries` to the project (undoable)."""
def __init__(self, vm: ProjectViewModel, ts: TimeSeries) -> None: def __init__(self, vm: "ProjectViewModel", ts: "TimeSeries") -> None:
super().__init__(vm, f"Add time series '{ts.name or ts.id}'") super().__init__(vm, f"Add time series '{ts.name or ts.id}'")
self._ts = ts self._ts = ts
@ -31,7 +31,9 @@ class AddTimeSeriesCommand(ProjectCommand):
self._notify() self._notify()
def undo(self) -> None: def undo(self) -> None:
self.project.time_series[:] = [t for t in self.project.time_series if t.id != self._ts.id] self.project.time_series[:] = [
t for t in self.project.time_series if t.id != self._ts.id
]
self._notify() self._notify()
@ -41,7 +43,7 @@ class UpdateTimeSeriesCommand(ProjectCommand):
The new series must carry the same id as the one being replaced. The new series must carry the same id as the one being replaced.
""" """
def __init__(self, vm: ProjectViewModel, new_ts: Any) -> None: def __init__(self, vm: "ProjectViewModel", new_ts: Any) -> None:
super().__init__(vm, f"Edit time series {new_ts.id}") super().__init__(vm, f"Edit time series {new_ts.id}")
self._new = new_ts self._new = new_ts
self._old: Any | None = None self._old: Any | None = None
@ -67,7 +69,7 @@ class DeleteTimeSeriesCommand(ProjectCommand):
"""Remove time series (no cascade — patterns referencing them must be """Remove time series (no cascade — patterns referencing them must be
cleaned separately; ``validate_references`` catches strays before save).""" cleaned separately; ``validate_references`` catches strays before save)."""
def __init__(self, vm: ProjectViewModel, ts_ids: set[int]) -> None: def __init__(self, vm: "ProjectViewModel", ts_ids: set[int]) -> None:
super().__init__(vm, f"Delete {len(ts_ids)} time serie(s)") super().__init__(vm, f"Delete {len(ts_ids)} time serie(s)")
self._ts_ids = set(ts_ids) self._ts_ids = set(ts_ids)
self._removed: list[tuple[int, Any]] = [] self._removed: list[tuple[int, Any]] = []
@ -91,7 +93,7 @@ class DeleteTimeSeriesCommand(ProjectCommand):
class AddLoadPatternCommand(ProjectCommand): class AddLoadPatternCommand(ProjectCommand):
"""Append a :class:`LoadPattern` to the project (undoable).""" """Append a :class:`LoadPattern` to the project (undoable)."""
def __init__(self, vm: ProjectViewModel, pattern: LoadPattern) -> None: def __init__(self, vm: "ProjectViewModel", pattern: "LoadPattern") -> None:
super().__init__(vm, f"Add pattern '{pattern.name or pattern.id}'") super().__init__(vm, f"Add pattern '{pattern.name or pattern.id}'")
self._pattern = pattern self._pattern = pattern
@ -117,7 +119,7 @@ class UpdateLoadPatternCommand(ProjectCommand):
drops the pattern's stored loads. drops the pattern's stored loads.
""" """
def __init__(self, vm: ProjectViewModel, new_pattern: Any) -> None: def __init__(self, vm: "ProjectViewModel", new_pattern: Any) -> None:
super().__init__(vm, f"Edit pattern {new_pattern.id}") super().__init__(vm, f"Edit pattern {new_pattern.id}")
self._new = new_pattern self._new = new_pattern
self._old: Any | None = None self._old: Any | None = None
@ -142,7 +144,7 @@ class UpdateLoadPatternCommand(ProjectCommand):
class DeleteLoadPatternCommand(ProjectCommand): class DeleteLoadPatternCommand(ProjectCommand):
"""Remove load patterns (their child nodal/element loads go with them).""" """Remove load patterns (their child nodal/element loads go with them)."""
def __init__(self, vm: ProjectViewModel, pattern_ids: set[int]) -> None: def __init__(self, vm: "ProjectViewModel", pattern_ids: set[int]) -> None:
super().__init__(vm, f"Delete {len(pattern_ids)} pattern(s)") super().__init__(vm, f"Delete {len(pattern_ids)} pattern(s)")
self._pattern_ids = set(pattern_ids) self._pattern_ids = set(pattern_ids)
self._removed: list[tuple[int, Any]] = [] self._removed: list[tuple[int, Any]] = []

View file

@ -15,9 +15,10 @@ All copies inherit the source node's restraint, mass, and name.
from __future__ import annotations from __future__ import annotations
from typing import TYPE_CHECKING, Literal from typing import TYPE_CHECKING, Any, Literal
from otko.commands.base import ProjectCommand from otko.commands.base import ProjectCommand
from otko.core import Node
if TYPE_CHECKING: if TYPE_CHECKING:
from otko.viewmodels import ProjectViewModel from otko.viewmodels import ProjectViewModel
@ -29,7 +30,7 @@ class MoveNodesCommand(ProjectCommand):
def __init__( def __init__(
self, self,
vm: ProjectViewModel, vm: "ProjectViewModel",
node_ids: set[int], node_ids: set[int],
offset: tuple[float, float, float], offset: tuple[float, float, float],
) -> None: ) -> None:
@ -44,9 +45,9 @@ class MoveNodesCommand(ProjectCommand):
for i, n in enumerate(self.project.nodes): for i, n in enumerate(self.project.nodes):
if n.id in self._node_ids: if n.id in self._node_ids:
self._previous[n.id] = n.coords self._previous[n.id] = n.coords
self.project.nodes[i] = n.model_copy( self.project.nodes[i] = n.model_copy(update={
update={"coords": (n.coords[0] + dx, n.coords[1] + dy, n.coords[2] + dz)} "coords": (n.coords[0] + dx, n.coords[1] + dy, n.coords[2] + dz)
) })
self._notify() self._notify()
def undo(self) -> None: def undo(self) -> None:
@ -62,7 +63,7 @@ class ReplicateCommand(ProjectCommand):
def __init__( def __init__(
self, self,
vm: ProjectViewModel, vm: "ProjectViewModel",
node_ids: set[int], node_ids: set[int],
element_ids: set[int], element_ids: set[int],
offset: tuple[float, float, float], offset: tuple[float, float, float],
@ -83,8 +84,7 @@ class ReplicateCommand(ProjectCommand):
# Snapshot the source nodes/elements once (won't change during redo). # Snapshot the source nodes/elements once (won't change during redo).
src_nodes = [n for n in self.project.nodes if n.id in self._node_ids] src_nodes = [n for n in self.project.nodes if n.id in self._node_ids]
src_elements = [ src_elements = [
e e for e in self.project.elements
for e in self.project.elements
if e.id in self._element_ids and all(nid in self._node_ids for nid in e.nodes) if e.id in self._element_ids and all(nid in self._node_ids for nid in e.nodes)
] ]
next_node_id = self.project.next_node_id() next_node_id = self.project.next_node_id()
@ -95,34 +95,30 @@ class ReplicateCommand(ProjectCommand):
for k in range(1, self._n_copies + 1): for k in range(1, self._n_copies + 1):
mapping: dict[int, int] = {} mapping: dict[int, int] = {}
for orig in src_nodes: for orig in src_nodes:
new_node = orig.model_copy( new_node = orig.model_copy(update={
update={
"id": next_node_id, "id": next_node_id,
"coords": ( "coords": (orig.coords[0] + k * dx,
orig.coords[0] + k * dx,
orig.coords[1] + k * dy, orig.coords[1] + k * dy,
orig.coords[2] + k * dz, orig.coords[2] + k * dz),
), })
}
)
self.project.nodes.append(new_node) self.project.nodes.append(new_node)
self._added_node_ids.add(next_node_id) self._added_node_ids.add(next_node_id)
mapping[orig.id] = next_node_id mapping[orig.id] = next_node_id
next_node_id += 1 next_node_id += 1
for orig in src_elements: for orig in src_elements:
new_elem = orig.model_copy( new_elem = orig.model_copy(update={
update={
"id": next_elem_id, "id": next_elem_id,
"nodes": tuple(mapping[nid] for nid in orig.nodes), "nodes": tuple(mapping[nid] for nid in orig.nodes),
} })
)
self.project.elements.append(new_elem) self.project.elements.append(new_elem)
self._added_element_ids.add(next_elem_id) self._added_element_ids.add(next_elem_id)
next_elem_id += 1 next_elem_id += 1
self._notify() self._notify()
def undo(self) -> None: def undo(self) -> None:
self.project.nodes[:] = [n for n in self.project.nodes if n.id not in self._added_node_ids] self.project.nodes[:] = [
n for n in self.project.nodes if n.id not in self._added_node_ids
]
self.project.elements[:] = [ self.project.elements[:] = [
e for e in self.project.elements if e.id not in self._added_element_ids e for e in self.project.elements if e.id not in self._added_element_ids
] ]
@ -146,7 +142,7 @@ class MirrorCommand(ProjectCommand):
def __init__( def __init__(
self, self,
vm: ProjectViewModel, vm: "ProjectViewModel",
node_ids: set[int], node_ids: set[int],
element_ids: set[int], element_ids: set[int],
plane: Plane, plane: Plane,
@ -170,8 +166,7 @@ class MirrorCommand(ProjectCommand):
def redo(self) -> None: def redo(self) -> None:
src_nodes = [n for n in self.project.nodes if n.id in self._node_ids] src_nodes = [n for n in self.project.nodes if n.id in self._node_ids]
src_elements = [ src_elements = [
e e for e in self.project.elements
for e in self.project.elements
if e.id in self._element_ids and all(nid in self._node_ids for nid in e.nodes) if e.id in self._element_ids and all(nid in self._node_ids for nid in e.nodes)
] ]
next_node_id = self.project.next_node_id() next_node_id = self.project.next_node_id()
@ -181,30 +176,28 @@ class MirrorCommand(ProjectCommand):
mapping: dict[int, int] = {} mapping: dict[int, int] = {}
for orig in src_nodes: for orig in src_nodes:
new_node = orig.model_copy( new_node = orig.model_copy(update={
update={
"id": next_node_id, "id": next_node_id,
"coords": self._reflect(orig.coords, self._plane), "coords": self._reflect(orig.coords, self._plane),
} })
)
self.project.nodes.append(new_node) self.project.nodes.append(new_node)
self._added_node_ids.add(next_node_id) self._added_node_ids.add(next_node_id)
mapping[orig.id] = next_node_id mapping[orig.id] = next_node_id
next_node_id += 1 next_node_id += 1
for orig in src_elements: for orig in src_elements:
new_elem = orig.model_copy( new_elem = orig.model_copy(update={
update={
"id": next_elem_id, "id": next_elem_id,
"nodes": tuple(mapping[nid] for nid in orig.nodes), "nodes": tuple(mapping[nid] for nid in orig.nodes),
} })
)
self.project.elements.append(new_elem) self.project.elements.append(new_elem)
self._added_element_ids.add(next_elem_id) self._added_element_ids.add(next_elem_id)
next_elem_id += 1 next_elem_id += 1
self._notify() self._notify()
def undo(self) -> None: def undo(self) -> None:
self.project.nodes[:] = [n for n in self.project.nodes if n.id not in self._added_node_ids] self.project.nodes[:] = [
n for n in self.project.nodes if n.id not in self._added_node_ids
]
self.project.elements[:] = [ self.project.elements[:] = [
e for e in self.project.elements if e.id not in self._added_element_ids e for e in self.project.elements if e.id not in self._added_element_ids
] ]

View file

@ -50,8 +50,6 @@ from otko.core.loads import (
ConstantTimeSeries, ConstantTimeSeries,
ImposedSupportMotionPattern, ImposedSupportMotionPattern,
LinearTimeSeries, LinearTimeSeries,
LoadCombination,
LoadCombinationItem,
LoadPattern, LoadPattern,
NodalLoad, NodalLoad,
PathTimeSeries, PathTimeSeries,
@ -167,8 +165,6 @@ __all__ = [
"PlainLoadPattern", "PlainLoadPattern",
"UniformExcitationPattern", "UniformExcitationPattern",
"ImposedSupportMotionPattern", "ImposedSupportMotionPattern",
"LoadCombination",
"LoadCombinationItem",
"NodalLoad", "NodalLoad",
"UniformElementLoad", "UniformElementLoad",
"ResponseSpectrum", "ResponseSpectrum",

View file

@ -22,7 +22,5 @@ class Entity(BaseModel):
populate_by_name=True, populate_by_name=True,
) )
id: PositiveInt = Field( id: PositiveInt = Field(..., description="Unique tag within its kind. Used as the OpenSees tag.")
..., description="Unique tag within its kind. Used as the OpenSees tag."
)
name: str = Field(default="", description="Optional human-readable label.") name: str = Field(default="", description="Optional human-readable label.")

View file

@ -9,7 +9,7 @@ in Phase 6/8.
from __future__ import annotations from __future__ import annotations
from typing import Annotated, Literal from typing import Annotated, Literal, Union
from pydantic import Field, PositiveFloat, PositiveInt, model_validator from pydantic import Field, PositiveFloat, PositiveInt, model_validator
@ -83,8 +83,7 @@ class TransientCase(Entity):
constraints: str = "Plain" constraints: str = "Plain"
integrator: str = "Newmark" integrator: str = "Newmark"
integrator_params: tuple[float, float] = Field( integrator_params: tuple[float, float] = Field(
default=(0.5, 0.25), default=(0.5, 0.25), description="Newmark gamma, beta (default = average acceleration).",
description="Newmark gamma, beta (default = average acceleration).",
) )
algorithm: str = "Newton" algorithm: str = "Newton"
test: str = "NormDispIncr" test: str = "NormDispIncr"
@ -115,11 +114,11 @@ class TransientCase(Entity):
) )
rayleigh_beta_k_comm: float = Field( rayleigh_beta_k_comm: float = Field(
default=0.0, default=0.0,
description="Stiffness-proportional βK on COMMITTED stiffness — " "``rayleigh`` slot 4.", description="Stiffness-proportional βK on COMMITTED stiffness — "
"``rayleigh`` slot 4.",
) )
rayleigh_mode1_damping: float | None = Field( rayleigh_mode1_damping: float | None = Field(
default=None, default=None, ge=0.0,
ge=0.0,
description=( description=(
"If set, βK is computed as 2·ζ/√λ₁ (first-mode eigenvalue) and " "If set, βK is computed as 2·ζ/√λ₁ (first-mode eigenvalue) and "
"overrides ``rayleigh_beta_k``. ``rayleigh_alpha_m`` still applies." "overrides ``rayleigh_beta_k``. ``rayleigh_alpha_m`` still applies."
@ -245,30 +244,23 @@ class ResponseSpectrumCase(Entity):
type: Literal["ResponseSpectrum"] = "ResponseSpectrum" type: Literal["ResponseSpectrum"] = "ResponseSpectrum"
modal_case_id: PositiveInt = Field( modal_case_id: PositiveInt = Field(
..., ..., description="ID of the ModalCase whose mode shapes drive this analysis.",
description="ID of the ModalCase whose mode shapes drive this analysis.",
) )
spectrum_id: PositiveInt = Field( spectrum_id: PositiveInt = Field(
..., ..., description="ID of the ResponseSpectrum to apply.",
description="ID of the ResponseSpectrum to apply.",
) )
direction: int = Field( direction: int = Field(
..., ..., ge=1, le=6, description="DOF direction (1..6) for the seismic excitation.",
ge=1,
le=6,
description="DOF direction (1..6) for the seismic excitation.",
) )
combination: Literal["SRSS", "CQC"] = "SRSS" combination: Literal["SRSS", "CQC"] = "SRSS"
damping_ratio: float | None = Field( damping_ratio: float | None = Field(
default=None, default=None, ge=0.0, le=1.0,
ge=0.0,
le=1.0,
description="Override the spectrum's damping for CQC correlation. " description="Override the spectrum's damping for CQC correlation. "
"Defaults to the spectrum's damping_ratio.", "Defaults to the spectrum's damping_ratio.",
) )
AnalysisCase = Annotated[ AnalysisCase = Annotated[
StaticCase | ModalCase | TransientCase | PushoverCase | ResponseSpectrumCase, Union[StaticCase, ModalCase, TransientCase, PushoverCase, ResponseSpectrumCase],
Field(discriminator="type"), Field(discriminator="type"),
] ]

View file

@ -8,9 +8,7 @@ from pydantic import BaseModel
from otko.core.catalog.generated.elastic import ElasticSpec from otko.core.catalog.generated.elastic import ElasticSpec
from otko.core.catalog.generated.elastic_perfectly_plastic import ElasticPerfectlyPlasticSpec from otko.core.catalog.generated.elastic_perfectly_plastic import ElasticPerfectlyPlasticSpec
from otko.core.catalog.generated.elastic_perfectly_plastic_with_gap import ( from otko.core.catalog.generated.elastic_perfectly_plastic_with_gap import ElasticPerfectlyPlasticWithGapSpec
ElasticPerfectlyPlasticWithGapSpec,
)
from otko.core.catalog.generated.viscous import ViscousSpec from otko.core.catalog.generated.viscous import ViscousSpec
from otko.core.catalog.generated.viscous_damper import ViscousDamperSpec from otko.core.catalog.generated.viscous_damper import ViscousDamperSpec
from otko.core.catalog.generated.hyperbolic_gap import HyperbolicGapSpec from otko.core.catalog.generated.hyperbolic_gap import HyperbolicGapSpec
@ -23,12 +21,8 @@ from otko.core.catalog.generated.steel02 import Steel02Spec
from otko.core.catalog.generated.reinforcing_steel import ReinforcingSteelSpec from otko.core.catalog.generated.reinforcing_steel import ReinforcingSteelSpec
from otko.core.catalog.generated.hysteretic import HystereticSpec from otko.core.catalog.generated.hysteretic import HystereticSpec
from otko.core.catalog.generated.ramberg_osgood_steel import RambergOsgoodSteelSpec from otko.core.catalog.generated.ramberg_osgood_steel import RambergOsgoodSteelSpec
from otko.core.catalog.generated.concrete01_zero_tensile_strength import ( from otko.core.catalog.generated.concrete01_zero_tensile_strength import Concrete01ZeroTensileStrengthSpec
Concrete01ZeroTensileStrengthSpec, from otko.core.catalog.generated.concrete02_linear_tension_softening import Concrete02LinearTensionSofteningSpec
)
from otko.core.catalog.generated.concrete02_linear_tension_softening import (
Concrete02LinearTensionSofteningSpec,
)
from otko.core.catalog.generated.concrete04_popovics_concrete import Concrete04PopovicsConcreteSpec from otko.core.catalog.generated.concrete04_popovics_concrete import Concrete04PopovicsConcreteSpec
from otko.core.catalog.generated.concrete06 import Concrete06Spec from otko.core.catalog.generated.concrete06 import Concrete06Spec
from otko.core.catalog.generated.concretecm import ConcretecmSpec from otko.core.catalog.generated.concretecm import ConcretecmSpec
@ -56,16 +50,10 @@ from otko.core.catalog.generated.elastic_membrane_plate import ElasticMembranePl
from otko.core.catalog.generated.layeredshell import LayeredshellSpec from otko.core.catalog.generated.layeredshell import LayeredshellSpec
from otko.core.catalog.generated.ground_motion_record import GroundMotionRecordSpec from otko.core.catalog.generated.ground_motion_record import GroundMotionRecordSpec
from otko.core.catalog.generated.elastic_beam_column import ElasticBeamColumnSpec from otko.core.catalog.generated.elastic_beam_column import ElasticBeamColumnSpec
from otko.core.catalog.generated.elastic_timoshenko_beam_column import ( from otko.core.catalog.generated.elastic_timoshenko_beam_column import ElasticTimoshenkoBeamColumnSpec
ElasticTimoshenkoBeamColumnSpec,
)
from otko.core.catalog.generated.force_based_beam_column import ForceBasedBeamColumnSpec from otko.core.catalog.generated.force_based_beam_column import ForceBasedBeamColumnSpec
from otko.core.catalog.generated.displacement_based_beam_column import ( from otko.core.catalog.generated.displacement_based_beam_column import DisplacementBasedBeamColumnSpec
DisplacementBasedBeamColumnSpec, from otko.core.catalog.generated.flexure_shear_interaction_displacement_based_beam_column import FlexureShearInteractionDisplacementBasedBeamColumnSpec
)
from otko.core.catalog.generated.flexure_shear_interaction_displacement_based_beam_column import (
FlexureShearInteractionDisplacementBasedBeamColumnSpec,
)
from otko.core.catalog.generated.truss import TrussSpec from otko.core.catalog.generated.truss import TrussSpec
from otko.core.catalog.generated.corotational_truss import CorotationalTrussSpec from otko.core.catalog.generated.corotational_truss import CorotationalTrussSpec
from otko.core.catalog.generated.quad import QuadSpec from otko.core.catalog.generated.quad import QuadSpec
@ -79,124 +67,64 @@ from otko.core.catalog.generated.auto_equal_constraint import AutoEqualConstrain
CATALOG: dict[str, type[BaseModel]] = { CATALOG: dict[str, type[BaseModel]] = {
"Elastic": ElasticSpec, 'Elastic': ElasticSpec,
"Elastic_Perfectly_Plastic": ElasticPerfectlyPlasticSpec, 'Elastic_Perfectly_Plastic': ElasticPerfectlyPlasticSpec,
"Elastic_Perfectly_Plastic_with_Gap": ElasticPerfectlyPlasticWithGapSpec, 'Elastic_Perfectly_Plastic_with_Gap': ElasticPerfectlyPlasticWithGapSpec,
"Viscous": ViscousSpec, 'Viscous': ViscousSpec,
"Viscous_Damper": ViscousDamperSpec, 'Viscous_Damper': ViscousDamperSpec,
"Hyperbolic_Gap": HyperbolicGapSpec, 'Hyperbolic_Gap': HyperbolicGapSpec,
"PySimple1": Pysimple1Spec, 'PySimple1': Pysimple1Spec,
"TzSimple1": Tzsimple1Spec, 'TzSimple1': Tzsimple1Spec,
"QzSimple1": Qzsimple1Spec, 'QzSimple1': Qzsimple1Spec,
"BondSP01": Bondsp01Spec, 'BondSP01': Bondsp01Spec,
"Steel01": Steel01Spec, 'Steel01': Steel01Spec,
"Steel02": Steel02Spec, 'Steel02': Steel02Spec,
"Reinforcing_steel": ReinforcingSteelSpec, 'Reinforcing_steel': ReinforcingSteelSpec,
"Hysteretic": HystereticSpec, 'Hysteretic': HystereticSpec,
"Ramberg-Osgood steel": RambergOsgoodSteelSpec, 'Ramberg-Osgood steel': RambergOsgoodSteelSpec,
"Concrete01_(Zero_tensile_strength)": Concrete01ZeroTensileStrengthSpec, 'Concrete01_(Zero_tensile_strength)': Concrete01ZeroTensileStrengthSpec,
"Concrete02_(Linear_tension_softening)": Concrete02LinearTensionSofteningSpec, 'Concrete02_(Linear_tension_softening)': Concrete02LinearTensionSofteningSpec,
"Concrete04_(Popovics_concrete)": Concrete04PopovicsConcreteSpec, 'Concrete04_(Popovics_concrete)': Concrete04PopovicsConcreteSpec,
"Concrete06": Concrete06Spec, 'Concrete06': Concrete06Spec,
"ConcreteCM": ConcretecmSpec, 'ConcreteCM': ConcretecmSpec,
"Series": SeriesSpec, 'Series': SeriesSpec,
"Parallel": ParallelSpec, 'Parallel': ParallelSpec,
"Section_Aggregator": SectionAggregatorSpec, 'Section_Aggregator': SectionAggregatorSpec,
"Initial_Strain": InitialStrainSpec, 'Initial_Strain': InitialStrainSpec,
"Initial_Stress": InitialStressSpec, 'Initial_Stress': InitialStressSpec,
"MinMax": MinmaxSpec, 'MinMax': MinmaxSpec,
"User_Material": UserMaterialSpec, 'User_Material': UserMaterialSpec,
"Elastic_Isotropic": ElasticIsotropicSpec, 'Elastic_Isotropic': ElasticIsotropicSpec,
"Elastic_Orthotropic": ElasticOrthotropicSpec, 'Elastic_Orthotropic': ElasticOrthotropicSpec,
"J2Plasticity": J2plasticitySpec, 'J2Plasticity': J2plasticitySpec,
"Damage2p": Damage2pSpec, 'Damage2p': Damage2pSpec,
"PressureIndependMultiYield": PressureindependmultiyieldSpec, 'PressureIndependMultiYield': PressureindependmultiyieldSpec,
"PressureDependMultiYield": PressuredependmultiyieldSpec, 'PressureDependMultiYield': PressuredependmultiyieldSpec,
"PressureDependMultiYield02": Pressuredependmultiyield02Spec, 'PressureDependMultiYield02': Pressuredependmultiyield02Spec,
"Contact": ContactSpec, 'Contact': ContactSpec,
"Elastic_Section": ElasticSectionSpec, 'Elastic_Section': ElasticSectionSpec,
"Fiber": FiberSpec, 'Fiber': FiberSpec,
"Fiber_Custom": FiberCustomSpec, 'Fiber_Custom': FiberCustomSpec,
"FiberInt": FiberintSpec, 'FiberInt': FiberintSpec,
"Plate_Fiber": PlateFiberSpec, 'Plate_Fiber': PlateFiberSpec,
"Elastic_Membrane_Plate": ElasticMembranePlateSpec, 'Elastic_Membrane_Plate': ElasticMembranePlateSpec,
"LayeredShell": LayeredshellSpec, 'LayeredShell': LayeredshellSpec,
"Ground_Motion_Record": GroundMotionRecordSpec, 'Ground_Motion_Record': GroundMotionRecordSpec,
"Elastic_Beam-Column": ElasticBeamColumnSpec, 'Elastic_Beam-Column': ElasticBeamColumnSpec,
"Elastic_Timoshenko_Beam-Column": ElasticTimoshenkoBeamColumnSpec, 'Elastic_Timoshenko_Beam-Column': ElasticTimoshenkoBeamColumnSpec,
"Force-Based_Beam-Column": ForceBasedBeamColumnSpec, 'Force-Based_Beam-Column': ForceBasedBeamColumnSpec,
"Displacement-Based_Beam-Column": DisplacementBasedBeamColumnSpec, 'Displacement-Based_Beam-Column': DisplacementBasedBeamColumnSpec,
"Flexure-Shear_Interaction_Displacement-Based_Beam-Column": FlexureShearInteractionDisplacementBasedBeamColumnSpec, 'Flexure-Shear_Interaction_Displacement-Based_Beam-Column': FlexureShearInteractionDisplacementBasedBeamColumnSpec,
"Truss": TrussSpec, 'Truss': TrussSpec,
"Corotational_Truss": CorotationalTrussSpec, 'Corotational_Truss': CorotationalTrussSpec,
"Quad": QuadSpec, 'Quad': QuadSpec,
"Shell": ShellSpec, 'Shell': ShellSpec,
"ShellDKGQ": ShelldkgqSpec, 'ShellDKGQ': ShelldkgqSpec,
"Tri31": Tri31Spec, 'Tri31': Tri31Spec,
"QuadUP": QuadupSpec, 'QuadUP': QuadupSpec,
"Standard_Brick_Element": StandardBrickElementSpec, 'Standard_Brick_Element': StandardBrickElementSpec,
"Auto_Zero_Length": AutoZeroLengthSpec, 'Auto_Zero_Length': AutoZeroLengthSpec,
"Auto_equal_constraint": AutoEqualConstraintSpec, 'Auto_equal_constraint': AutoEqualConstraintSpec,
} }
__all__ = [ __all__ = ["CATALOG", 'ElasticSpec', 'ElasticPerfectlyPlasticSpec', 'ElasticPerfectlyPlasticWithGapSpec', 'ViscousSpec', 'ViscousDamperSpec', 'HyperbolicGapSpec', 'Pysimple1Spec', 'Tzsimple1Spec', 'Qzsimple1Spec', 'Bondsp01Spec', 'Steel01Spec', 'Steel02Spec', 'ReinforcingSteelSpec', 'HystereticSpec', 'RambergOsgoodSteelSpec', 'Concrete01ZeroTensileStrengthSpec', 'Concrete02LinearTensionSofteningSpec', 'Concrete04PopovicsConcreteSpec', 'Concrete06Spec', 'ConcretecmSpec', 'SeriesSpec', 'ParallelSpec', 'SectionAggregatorSpec', 'InitialStrainSpec', 'InitialStressSpec', 'MinmaxSpec', 'UserMaterialSpec', 'ElasticIsotropicSpec', 'ElasticOrthotropicSpec', 'J2plasticitySpec', 'Damage2pSpec', 'PressureindependmultiyieldSpec', 'PressuredependmultiyieldSpec', 'Pressuredependmultiyield02Spec', 'ContactSpec', 'ElasticSectionSpec', 'FiberSpec', 'FiberCustomSpec', 'FiberintSpec', 'PlateFiberSpec', 'ElasticMembranePlateSpec', 'LayeredshellSpec', 'GroundMotionRecordSpec', 'ElasticBeamColumnSpec', 'ElasticTimoshenkoBeamColumnSpec', 'ForceBasedBeamColumnSpec', 'DisplacementBasedBeamColumnSpec', 'FlexureShearInteractionDisplacementBasedBeamColumnSpec', 'TrussSpec', 'CorotationalTrussSpec', 'QuadSpec', 'ShellSpec', 'ShelldkgqSpec', 'Tri31Spec', 'QuadupSpec', 'StandardBrickElementSpec', 'AutoZeroLengthSpec', 'AutoEqualConstraintSpec']
"CATALOG",
"ElasticSpec",
"ElasticPerfectlyPlasticSpec",
"ElasticPerfectlyPlasticWithGapSpec",
"ViscousSpec",
"ViscousDamperSpec",
"HyperbolicGapSpec",
"Pysimple1Spec",
"Tzsimple1Spec",
"Qzsimple1Spec",
"Bondsp01Spec",
"Steel01Spec",
"Steel02Spec",
"ReinforcingSteelSpec",
"HystereticSpec",
"RambergOsgoodSteelSpec",
"Concrete01ZeroTensileStrengthSpec",
"Concrete02LinearTensionSofteningSpec",
"Concrete04PopovicsConcreteSpec",
"Concrete06Spec",
"ConcretecmSpec",
"SeriesSpec",
"ParallelSpec",
"SectionAggregatorSpec",
"InitialStrainSpec",
"InitialStressSpec",
"MinmaxSpec",
"UserMaterialSpec",
"ElasticIsotropicSpec",
"ElasticOrthotropicSpec",
"J2plasticitySpec",
"Damage2pSpec",
"PressureindependmultiyieldSpec",
"PressuredependmultiyieldSpec",
"Pressuredependmultiyield02Spec",
"ContactSpec",
"ElasticSectionSpec",
"FiberSpec",
"FiberCustomSpec",
"FiberintSpec",
"PlateFiberSpec",
"ElasticMembranePlateSpec",
"LayeredshellSpec",
"GroundMotionRecordSpec",
"ElasticBeamColumnSpec",
"ElasticTimoshenkoBeamColumnSpec",
"ForceBasedBeamColumnSpec",
"DisplacementBasedBeamColumnSpec",
"FlexureShearInteractionDisplacementBasedBeamColumnSpec",
"TrussSpec",
"CorotationalTrussSpec",
"QuadSpec",
"ShellSpec",
"ShelldkgqSpec",
"Tri31Spec",
"QuadupSpec",
"StandardBrickElementSpec",
"AutoZeroLengthSpec",
"AutoEqualConstraintSpec",
]

View file

@ -7,9 +7,7 @@ from typing import Union
from otko.core.catalog.generated.elastic import ElasticSpec from otko.core.catalog.generated.elastic import ElasticSpec
from otko.core.catalog.generated.elastic_perfectly_plastic import ElasticPerfectlyPlasticSpec from otko.core.catalog.generated.elastic_perfectly_plastic import ElasticPerfectlyPlasticSpec
from otko.core.catalog.generated.elastic_perfectly_plastic_with_gap import ( from otko.core.catalog.generated.elastic_perfectly_plastic_with_gap import ElasticPerfectlyPlasticWithGapSpec
ElasticPerfectlyPlasticWithGapSpec,
)
from otko.core.catalog.generated.viscous import ViscousSpec from otko.core.catalog.generated.viscous import ViscousSpec
from otko.core.catalog.generated.viscous_damper import ViscousDamperSpec from otko.core.catalog.generated.viscous_damper import ViscousDamperSpec
from otko.core.catalog.generated.hyperbolic_gap import HyperbolicGapSpec from otko.core.catalog.generated.hyperbolic_gap import HyperbolicGapSpec
@ -22,12 +20,8 @@ from otko.core.catalog.generated.steel02 import Steel02Spec
from otko.core.catalog.generated.reinforcing_steel import ReinforcingSteelSpec from otko.core.catalog.generated.reinforcing_steel import ReinforcingSteelSpec
from otko.core.catalog.generated.hysteretic import HystereticSpec from otko.core.catalog.generated.hysteretic import HystereticSpec
from otko.core.catalog.generated.ramberg_osgood_steel import RambergOsgoodSteelSpec from otko.core.catalog.generated.ramberg_osgood_steel import RambergOsgoodSteelSpec
from otko.core.catalog.generated.concrete01_zero_tensile_strength import ( from otko.core.catalog.generated.concrete01_zero_tensile_strength import Concrete01ZeroTensileStrengthSpec
Concrete01ZeroTensileStrengthSpec, from otko.core.catalog.generated.concrete02_linear_tension_softening import Concrete02LinearTensionSofteningSpec
)
from otko.core.catalog.generated.concrete02_linear_tension_softening import (
Concrete02LinearTensionSofteningSpec,
)
from otko.core.catalog.generated.concrete04_popovics_concrete import Concrete04PopovicsConcreteSpec from otko.core.catalog.generated.concrete04_popovics_concrete import Concrete04PopovicsConcreteSpec
from otko.core.catalog.generated.concrete06 import Concrete06Spec from otko.core.catalog.generated.concrete06 import Concrete06Spec
from otko.core.catalog.generated.concretecm import ConcretecmSpec from otko.core.catalog.generated.concretecm import ConcretecmSpec
@ -55,16 +49,10 @@ from otko.core.catalog.generated.elastic_membrane_plate import ElasticMembranePl
from otko.core.catalog.generated.layeredshell import LayeredshellSpec from otko.core.catalog.generated.layeredshell import LayeredshellSpec
from otko.core.catalog.generated.ground_motion_record import GroundMotionRecordSpec from otko.core.catalog.generated.ground_motion_record import GroundMotionRecordSpec
from otko.core.catalog.generated.elastic_beam_column import ElasticBeamColumnSpec from otko.core.catalog.generated.elastic_beam_column import ElasticBeamColumnSpec
from otko.core.catalog.generated.elastic_timoshenko_beam_column import ( from otko.core.catalog.generated.elastic_timoshenko_beam_column import ElasticTimoshenkoBeamColumnSpec
ElasticTimoshenkoBeamColumnSpec,
)
from otko.core.catalog.generated.force_based_beam_column import ForceBasedBeamColumnSpec from otko.core.catalog.generated.force_based_beam_column import ForceBasedBeamColumnSpec
from otko.core.catalog.generated.displacement_based_beam_column import ( from otko.core.catalog.generated.displacement_based_beam_column import DisplacementBasedBeamColumnSpec
DisplacementBasedBeamColumnSpec, from otko.core.catalog.generated.flexure_shear_interaction_displacement_based_beam_column import FlexureShearInteractionDisplacementBasedBeamColumnSpec
)
from otko.core.catalog.generated.flexure_shear_interaction_displacement_based_beam_column import (
FlexureShearInteractionDisplacementBasedBeamColumnSpec,
)
from otko.core.catalog.generated.truss import TrussSpec from otko.core.catalog.generated.truss import TrussSpec
from otko.core.catalog.generated.corotational_truss import CorotationalTrussSpec from otko.core.catalog.generated.corotational_truss import CorotationalTrussSpec
from otko.core.catalog.generated.quad import QuadSpec from otko.core.catalog.generated.quad import QuadSpec
@ -77,141 +65,19 @@ from otko.core.catalog.generated.auto_zero_length import AutoZeroLengthSpec
from otko.core.catalog.generated.auto_equal_constraint import AutoEqualConstraintSpec from otko.core.catalog.generated.auto_equal_constraint import AutoEqualConstraintSpec
StandardUniaxialMaterials = Union[ StandardUniaxialMaterials = Union[ElasticSpec, ElasticPerfectlyPlasticSpec, ElasticPerfectlyPlasticWithGapSpec, ViscousSpec, ViscousDamperSpec, HyperbolicGapSpec, Pysimple1Spec, Tzsimple1Spec, Qzsimple1Spec, Bondsp01Spec]
ElasticSpec, UniaxialSteelMaterials = Union[Steel01Spec, Steel02Spec, ReinforcingSteelSpec, HystereticSpec, RambergOsgoodSteelSpec]
ElasticPerfectlyPlasticSpec, UniaxialConcreteMaterials = Union[Concrete01ZeroTensileStrengthSpec, Concrete02LinearTensionSofteningSpec, Concrete04PopovicsConcreteSpec, Concrete06Spec, ConcretecmSpec]
ElasticPerfectlyPlasticWithGapSpec, CombinedMaterials = Union[SeriesSpec, ParallelSpec, SectionAggregatorSpec, InitialStrainSpec, InitialStressSpec, MinmaxSpec]
ViscousSpec,
ViscousDamperSpec,
HyperbolicGapSpec,
Pysimple1Spec,
Tzsimple1Spec,
Qzsimple1Spec,
Bondsp01Spec,
]
UniaxialSteelMaterials = Union[
Steel01Spec, Steel02Spec, ReinforcingSteelSpec, HystereticSpec, RambergOsgoodSteelSpec
]
UniaxialConcreteMaterials = Union[
Concrete01ZeroTensileStrengthSpec,
Concrete02LinearTensionSofteningSpec,
Concrete04PopovicsConcreteSpec,
Concrete06Spec,
ConcretecmSpec,
]
CombinedMaterials = Union[
SeriesSpec,
ParallelSpec,
SectionAggregatorSpec,
InitialStrainSpec,
InitialStressSpec,
MinmaxSpec,
]
UserMaterials = UserMaterialSpec UserMaterials = UserMaterialSpec
MultidimensionalNdMaterials = Union[ MultidimensionalNdMaterials = Union[ElasticIsotropicSpec, ElasticOrthotropicSpec, J2plasticitySpec, Damage2pSpec, PressureindependmultiyieldSpec, PressuredependmultiyieldSpec, Pressuredependmultiyield02Spec, ContactSpec]
ElasticIsotropicSpec, SectionForceDeformation = Union[ElasticSectionSpec, FiberSpec, FiberCustomSpec, FiberintSpec, PlateFiberSpec, ElasticMembranePlateSpec, LayeredshellSpec]
ElasticOrthotropicSpec,
J2plasticitySpec,
Damage2pSpec,
PressureindependmultiyieldSpec,
PressuredependmultiyieldSpec,
Pressuredependmultiyield02Spec,
ContactSpec,
]
SectionForceDeformation = Union[
ElasticSectionSpec,
FiberSpec,
FiberCustomSpec,
FiberintSpec,
PlateFiberSpec,
ElasticMembranePlateSpec,
LayeredshellSpec,
]
Records = GroundMotionRecordSpec Records = GroundMotionRecordSpec
BeamColumnElements = Union[ BeamColumnElements = Union[ElasticBeamColumnSpec, ElasticTimoshenkoBeamColumnSpec, ForceBasedBeamColumnSpec, DisplacementBasedBeamColumnSpec, FlexureShearInteractionDisplacementBasedBeamColumnSpec]
ElasticBeamColumnSpec,
ElasticTimoshenkoBeamColumnSpec,
ForceBasedBeamColumnSpec,
DisplacementBasedBeamColumnSpec,
FlexureShearInteractionDisplacementBasedBeamColumnSpec,
]
TrussElements = Union[TrussSpec, CorotationalTrussSpec] TrussElements = Union[TrussSpec, CorotationalTrussSpec]
SurfaceElements = Union[QuadSpec, ShellSpec, ShelldkgqSpec, Tri31Spec, QuadupSpec] SurfaceElements = Union[QuadSpec, ShellSpec, ShelldkgqSpec, Tri31Spec, QuadupSpec]
SolidElements = StandardBrickElementSpec SolidElements = StandardBrickElementSpec
Autozl = AutoZeroLengthSpec Autozl = AutoZeroLengthSpec
Autoedof = AutoEqualConstraintSpec Autoedof = AutoEqualConstraintSpec
__all__ = [ __all__ = ['ElasticSpec', 'ElasticPerfectlyPlasticSpec', 'ElasticPerfectlyPlasticWithGapSpec', 'ViscousSpec', 'ViscousDamperSpec', 'HyperbolicGapSpec', 'Pysimple1Spec', 'Tzsimple1Spec', 'Qzsimple1Spec', 'Bondsp01Spec', 'Steel01Spec', 'Steel02Spec', 'ReinforcingSteelSpec', 'HystereticSpec', 'RambergOsgoodSteelSpec', 'Concrete01ZeroTensileStrengthSpec', 'Concrete02LinearTensionSofteningSpec', 'Concrete04PopovicsConcreteSpec', 'Concrete06Spec', 'ConcretecmSpec', 'SeriesSpec', 'ParallelSpec', 'SectionAggregatorSpec', 'InitialStrainSpec', 'InitialStressSpec', 'MinmaxSpec', 'UserMaterialSpec', 'ElasticIsotropicSpec', 'ElasticOrthotropicSpec', 'J2plasticitySpec', 'Damage2pSpec', 'PressureindependmultiyieldSpec', 'PressuredependmultiyieldSpec', 'Pressuredependmultiyield02Spec', 'ContactSpec', 'ElasticSectionSpec', 'FiberSpec', 'FiberCustomSpec', 'FiberintSpec', 'PlateFiberSpec', 'ElasticMembranePlateSpec', 'LayeredshellSpec', 'GroundMotionRecordSpec', 'ElasticBeamColumnSpec', 'ElasticTimoshenkoBeamColumnSpec', 'ForceBasedBeamColumnSpec', 'DisplacementBasedBeamColumnSpec', 'FlexureShearInteractionDisplacementBasedBeamColumnSpec', 'TrussSpec', 'CorotationalTrussSpec', 'QuadSpec', 'ShellSpec', 'ShelldkgqSpec', 'Tri31Spec', 'QuadupSpec', 'StandardBrickElementSpec', 'AutoZeroLengthSpec', 'AutoEqualConstraintSpec', 'StandardUniaxialMaterials', 'UniaxialSteelMaterials', 'UniaxialConcreteMaterials', 'CombinedMaterials', 'UserMaterials', 'MultidimensionalNdMaterials', 'SectionForceDeformation', 'Records', 'BeamColumnElements', 'TrussElements', 'SurfaceElements', 'SolidElements', 'Autozl', 'Autoedof']
"ElasticSpec",
"ElasticPerfectlyPlasticSpec",
"ElasticPerfectlyPlasticWithGapSpec",
"ViscousSpec",
"ViscousDamperSpec",
"HyperbolicGapSpec",
"Pysimple1Spec",
"Tzsimple1Spec",
"Qzsimple1Spec",
"Bondsp01Spec",
"Steel01Spec",
"Steel02Spec",
"ReinforcingSteelSpec",
"HystereticSpec",
"RambergOsgoodSteelSpec",
"Concrete01ZeroTensileStrengthSpec",
"Concrete02LinearTensionSofteningSpec",
"Concrete04PopovicsConcreteSpec",
"Concrete06Spec",
"ConcretecmSpec",
"SeriesSpec",
"ParallelSpec",
"SectionAggregatorSpec",
"InitialStrainSpec",
"InitialStressSpec",
"MinmaxSpec",
"UserMaterialSpec",
"ElasticIsotropicSpec",
"ElasticOrthotropicSpec",
"J2plasticitySpec",
"Damage2pSpec",
"PressureindependmultiyieldSpec",
"PressuredependmultiyieldSpec",
"Pressuredependmultiyield02Spec",
"ContactSpec",
"ElasticSectionSpec",
"FiberSpec",
"FiberCustomSpec",
"FiberintSpec",
"PlateFiberSpec",
"ElasticMembranePlateSpec",
"LayeredshellSpec",
"GroundMotionRecordSpec",
"ElasticBeamColumnSpec",
"ElasticTimoshenkoBeamColumnSpec",
"ForceBasedBeamColumnSpec",
"DisplacementBasedBeamColumnSpec",
"FlexureShearInteractionDisplacementBasedBeamColumnSpec",
"TrussSpec",
"CorotationalTrussSpec",
"QuadSpec",
"ShellSpec",
"ShelldkgqSpec",
"Tri31Spec",
"QuadupSpec",
"StandardBrickElementSpec",
"AutoZeroLengthSpec",
"AutoEqualConstraintSpec",
"StandardUniaxialMaterials",
"UniaxialSteelMaterials",
"UniaxialConcreteMaterials",
"CombinedMaterials",
"UserMaterials",
"MultidimensionalNdMaterials",
"SectionForceDeformation",
"Records",
"BeamColumnElements",
"TrussElements",
"SurfaceElements",
"SolidElements",
"Autozl",
"Autoedof",
]

View file

@ -17,478 +17,478 @@ from pydantic import BaseModel, ConfigDict, Field
class AutoEqualConstraintSpec(BaseModel): class AutoEqualConstraintSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Auto_equal_constraint", 'x-gid-name': 'Auto_equal_constraint',
"x-book": "AutoEDOF", 'x-book': 'AutoEDOF',
"dependencies": [ 'dependencies': [
{ {
"field": "source", 'field': 'source',
"gid_name": "Source", 'gid_name': 'Source',
"rules": [ 'rules': [
{ {
"trigger": "Layer", 'trigger': 'Layer',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Layer_name", 'field': 'Layer_name',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "All", 'trigger': 'All',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Layer_name", 'field': 'Layer_name',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Visible", 'trigger': 'Visible',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Layer_name", 'field': 'Layer_name',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "x_criteria", 'field': 'x_criteria',
"gid_name": "X-Criteria", 'gid_name': 'X-Criteria',
"rules": [ 'rules': [
{ {
"trigger": "Any", 'trigger': 'Any',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "X-Coordinate", 'field': 'X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_X-Coordinate", 'field': 'Min_X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_X-Coordinate", 'field': 'Max_X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Fixed", 'trigger': 'Fixed',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Coordinate", 'field': 'X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_X-Coordinate", 'field': 'Min_X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_X-Coordinate", 'field': 'Max_X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "GT", 'trigger': 'GT',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Coordinate", 'field': 'X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_X-Coordinate", 'field': 'Min_X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_X-Coordinate", 'field': 'Max_X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "GET", 'trigger': 'GET',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Coordinate", 'field': 'X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_X-Coordinate", 'field': 'Min_X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_X-Coordinate", 'field': 'Max_X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "LT", 'trigger': 'LT',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Coordinate", 'field': 'X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_X-Coordinate", 'field': 'Min_X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_X-Coordinate", 'field': 'Max_X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "LET", 'trigger': 'LET',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Coordinate", 'field': 'X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_X-Coordinate", 'field': 'Min_X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_X-Coordinate", 'field': 'Max_X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Between", 'trigger': 'Between',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "X-Coordinate", 'field': 'X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Min_X-Coordinate", 'field': 'Min_X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Max_X-Coordinate", 'field': 'Max_X-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "y_criteria", 'field': 'y_criteria',
"gid_name": "Y-Criteria", 'gid_name': 'Y-Criteria',
"rules": [ 'rules': [
{ {
"trigger": "Any", 'trigger': 'Any',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Y-Coordinate", 'field': 'Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_Y-Coordinate", 'field': 'Min_Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_Y-Coordinate", 'field': 'Max_Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Fixed", 'trigger': 'Fixed',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Coordinate", 'field': 'Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_Y-Coordinate", 'field': 'Min_Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_Y-Coordinate", 'field': 'Max_Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "GT", 'trigger': 'GT',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Coordinate", 'field': 'Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_Y-Coordinate", 'field': 'Min_Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_Y-Coordinate", 'field': 'Max_Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "GET", 'trigger': 'GET',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Coordinate", 'field': 'Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_Y-Coordinate", 'field': 'Min_Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_Y-Coordinate", 'field': 'Max_Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "LT", 'trigger': 'LT',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Coordinate", 'field': 'Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_Y-Coordinate", 'field': 'Min_Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_Y-Coordinate", 'field': 'Max_Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "LET", 'trigger': 'LET',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Coordinate", 'field': 'Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_Y-Coordinate", 'field': 'Min_Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_Y-Coordinate", 'field': 'Max_Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Between", 'trigger': 'Between',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Y-Coordinate", 'field': 'Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Min_Y-Coordinate", 'field': 'Min_Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Max_Y-Coordinate", 'field': 'Max_Y-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "z_criteria", 'field': 'z_criteria',
"gid_name": "Z-Criteria", 'gid_name': 'Z-Criteria',
"rules": [ 'rules': [
{ {
"trigger": "Any", 'trigger': 'Any',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Z-Coordinate", 'field': 'Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_Z-Coordinate", 'field': 'Min_Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_Z-Coordinate", 'field': 'Max_Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Fixed", 'trigger': 'Fixed',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Coordinate", 'field': 'Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_Z-Coordinate", 'field': 'Min_Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_Z-Coordinate", 'field': 'Max_Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "GT", 'trigger': 'GT',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Coordinate", 'field': 'Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_Z-Coordinate", 'field': 'Min_Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_Z-Coordinate", 'field': 'Max_Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "GET", 'trigger': 'GET',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Coordinate", 'field': 'Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_Z-Coordinate", 'field': 'Min_Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_Z-Coordinate", 'field': 'Max_Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "LT", 'trigger': 'LT',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Coordinate", 'field': 'Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_Z-Coordinate", 'field': 'Min_Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_Z-Coordinate", 'field': 'Max_Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "LET", 'trigger': 'LET',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Coordinate", 'field': 'Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Min_Z-Coordinate", 'field': 'Min_Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Max_Z-Coordinate", 'field': 'Max_Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Between", 'trigger': 'Between',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Z-Coordinate", 'field': 'Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Min_Z-Coordinate", 'field': 'Min_Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Max_Z-Coordinate", 'field': 'Max_Z-Coordinate',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
@ -498,40 +498,29 @@ class AutoEqualConstraintSpec(BaseModel):
} }
) )
determine_master_node: Literal["Existed", "Extra"] = "Existed" determine_master_node: Literal['Existed', 'Extra'] = 'Existed'
source: Literal["Layer", "All", "Visible"] = Field( source: Literal['Layer', 'All', 'Visible'] = Field('Layer', description='Layer: Points or Nodes from specific layer regardless the visibility\\nAll: all points or nodes regardless the visibility\\nVisible: Only visible points or nodes')
"Layer", layer_name: str = Field('Layer0', description='Layer with name "AutoZL" will be ignored.')
description="Layer: Points or Nodes from specific layer regardless the visibility\\nAll: all points or nodes regardless the visibility\\nVisible: Only visible points or nodes", x_criteria: Literal['Any', 'Fixed', 'GT', 'GET', 'LT', 'LET', 'Between'] = Field('Any', description='GT: Greater than\\nGET: Greater/Equal than\\nLT: Less than\\nLET: Less/Equal than\\nBetween: inside (min,max) space including boundaries')
)
layer_name: str = Field("Layer0", description='Layer with name "AutoZL" will be ignored.')
x_criteria: Literal["Any", "Fixed", "GT", "GET", "LT", "LET", "Between"] = Field(
"Any",
description="GT: Greater than\\nGET: Greater/Equal than\\nLT: Less than\\nLET: Less/Equal than\\nBetween: inside (min,max) space including boundaries",
)
x_coordinate: float = 0.0 x_coordinate: float = 0.0
min_x_coordinate: float = 0.0 min_x_coordinate: float = 0.0
max_x_coordinate: float = 0.0 max_x_coordinate: float = 0.0
y_criteria: Literal["Any", "Fixed", "GT", "GET", "LT", "LET", "Between"] = Field( y_criteria: Literal['Any', 'Fixed', 'GT', 'GET', 'LT', 'LET', 'Between'] = Field('Any', description='GT: Greater than\\nGET: Greater/Equal than\\nLT: Less than\\nLET: Less/Equal than\\nBetween: inside (min,max) space including boundaries')
"Any",
description="GT: Greater than\\nGET: Greater/Equal than\\nLT: Less than\\nLET: Less/Equal than\\nBetween: inside (min,max) space including boundaries",
)
y_coordinate: float = 0.0 y_coordinate: float = 0.0
min_y_coordinate: float = 0.0 min_y_coordinate: float = 0.0
max_y_coordinate: float = 0.0 max_y_coordinate: float = 0.0
z_criteria: Literal["Any", "Fixed", "GT", "GET", "LT", "LET", "Between"] = Field( z_criteria: Literal['Any', 'Fixed', 'GT', 'GET', 'LT', 'LET', 'Between'] = Field('Any', description='GT: Greater than\\nGET: Greater/Equal than\\nLT: Less than\\nLET: Less/Equal than\\nBetween: inside (min,max) space including boundaries')
"Any",
description="GT: Greater than\\nGET: Greater/Equal than\\nLT: Less than\\nLET: Less/Equal than\\nBetween: inside (min,max) space including boundaries",
)
z_coordinate: float = 0.0 z_coordinate: float = 0.0
min_z_coordinate: float = 0.0 min_z_coordinate: float = 0.0
max_z_coordinate: float = 0.0 max_z_coordinate: float = 0.0
extra_point_node_offset: Literal["_"] = "_" extra_point_node_offset: Literal['_'] = '_'
x_offset: float = 0.0 x_offset: float = 0.0
y_offset: float = 0.0 y_offset: float = 0.0
z_offset: float = 0.0 z_offset: float = 0.0
x_translation: Literal["1", "0"] = "1" x_translation: Literal['1', '0'] = '1'
y_translation: Literal["1", "0"] = "1" y_translation: Literal['1', '0'] = '1'
z_translation: Literal["1", "0"] = "1" z_translation: Literal['1', '0'] = '1'
x_rotation: Literal["1", "0"] = "1" x_rotation: Literal['1', '0'] = '1'
y_rotation: Literal["1", "0"] = "1" y_rotation: Literal['1', '0'] = '1'
z_rotation: Literal["1", "0"] = "1" z_rotation: Literal['1', '0'] = '1'

File diff suppressed because it is too large Load diff

View file

@ -23,86 +23,86 @@ class CyclicDataRow(BaseModel):
class Bondsp01Spec(BaseModel): class Bondsp01Spec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "BondSP01", 'x-gid-name': 'BondSP01',
"x-book": "Standard_Uniaxial_Materials", 'x-book': 'Standard_Uniaxial_Materials',
"dependencies": [ 'dependencies': [
{ {
"field": "formulation", 'field': 'formulation',
"gid_name": "Formulation", 'gid_name': 'Formulation',
"rules": [ 'rules': [
{ {
"trigger": "Stress-Slip", 'trigger': 'Stress-Slip',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Yield_stress_Fy", 'field': 'Yield_stress_Fy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Ultimate_stress_Fu", 'field': 'Ultimate_stress_Fu',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Yield_force_Fy", 'field': 'Yield_force_Fy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Ultimate_Force_Fu", 'field': 'Ultimate_Force_Fu',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Force-Slip", 'trigger': 'Force-Slip',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Yield_force_Fy", 'field': 'Yield_force_Fy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Ultimate_Force_Fu", 'field': 'Ultimate_Force_Fu',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Yield_stress_Fy", 'field': 'Yield_stress_Fy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Ultimate_stress_Fu", 'field': 'Ultimate_stress_Fu',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "analysis_type", 'field': 'analysis_type',
"gid_name": "Analysis_type", 'gid_name': 'Analysis_type',
"rules": [ 'rules': [
{ {
"trigger": "Monotonic", 'trigger': 'Monotonic',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Cyclic", 'trigger': 'Cyclic',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
@ -112,15 +112,16 @@ class Bondsp01Spec(BaseModel):
} }
) )
material: Literal["_"] = "_" material: Literal['_'] = '_'
formulation: Literal["Stress-Slip", "Force-Slip"] = "Stress-Slip" formulation: Literal['Stress-Slip', 'Force-Slip'] = 'Stress-Slip'
yield_stress_fy: str = "500 MPa" # TODO: unit-aware type yield_stress_fy: str = '500 MPa' # TODO: unit-aware type
yield_force_fy: str = "157 kN" # TODO: unit-aware type yield_force_fy: str = '157 kN' # TODO: unit-aware type
rebar_slip_at_fy: str = "1 mm" # TODO: unit-aware type rebar_slip_at_fy: str = '1 mm' # TODO: unit-aware type
ultimate_stress_fu: str = "675 MPa" # TODO: unit-aware type ultimate_stress_fu: str = '675 MPa' # TODO: unit-aware type
ultimate_force_fu: str = "212 kN" # TODO: unit-aware type ultimate_force_fu: str = '212 kN' # TODO: unit-aware type
rebar_slip_at_the_loaded_end_at_the_bar_fracture_strength: str = "2 mm" # TODO: unit-aware type rebar_slip_at_the_loaded_end_at_the_bar_fracture_strength: str = '2 mm' # TODO: unit-aware type
initial_hardening: float = 0.4 initial_hardening: float = 0.4
pinching_factor_for_the_cyclic_slip_vs_bar_response: float = 0.5 pinching_factor_for_the_cyclic_slip_vs_bar_response: float = 0.5
analysis_type: Literal["Monotonic", "Cyclic"] = "Monotonic" analysis_type: Literal['Monotonic', 'Cyclic'] = 'Monotonic'
cyclic_data: list[CyclicDataRow] = Field(default_factory=list) cyclic_data: list[CyclicDataRow] = Field(default_factory=list)

View file

@ -23,176 +23,176 @@ class CyclicDataRow(BaseModel):
class Concrete01ZeroTensileStrengthSpec(BaseModel): class Concrete01ZeroTensileStrengthSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Concrete01_(Zero_tensile_strength)", 'x-gid-name': 'Concrete01_(Zero_tensile_strength)',
"x-book": "Uniaxial_Concrete_Materials", 'x-book': 'Uniaxial_Concrete_Materials',
"dependencies": [ 'dependencies': [
{ {
"field": "strength_class", 'field': 'strength_class',
"gid_name": "Strength_class", 'gid_name': 'Strength_class',
"rules": [ 'rules': [
{ {
"trigger": "C12/15", 'trigger': 'C12/15',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C16/20", 'trigger': 'C16/20',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C20/25", 'trigger': 'C20/25',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C25/30", 'trigger': 'C25/30',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C30/37", 'trigger': 'C30/37',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C35/45", 'trigger': 'C35/45',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C40/50", 'trigger': 'C40/50',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C45/55", 'trigger': 'C45/55',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C50/60", 'trigger': 'C50/60',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C60/75", 'trigger': 'C60/75',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C70/85", 'trigger': 'C70/85',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C80/95", 'trigger': 'C80/95',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C90/105", 'trigger': 'C90/105',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Custom", 'trigger': 'Custom',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "analysis_type", 'field': 'analysis_type',
"gid_name": "Analysis_type", 'gid_name': 'Analysis_type',
"rules": [ 'rules': [
{ {
"trigger": "Monotonic", 'trigger': 'Monotonic',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Cyclic", 'trigger': 'Cyclic',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
@ -202,36 +202,15 @@ class Concrete01ZeroTensileStrengthSpec(BaseModel):
} }
) )
material: Literal["Concrete01"] = Field( material: Literal['Concrete01'] = Field('Concrete01', description='uniaxial Kent-Scott-Park concrete material object with degraded linear unloading/reloading stiffness according to the work of Karsan-Jirsa and no tensile strength')
"Concrete01", strength_class: Literal['C12/15', 'C16/20', 'C20/25', 'C25/30', 'C30/37', 'C35/45', 'C40/50', 'C45/55', 'C50/60', 'C55/67', 'C60/75', 'C70/85', 'C80/95', 'C90/105', 'Custom'] = Field('Custom', description='Choose concrete strength category, to take some standard values in the following fields.')
description="uniaxial Kent-Scott-Park concrete material object with degraded linear unloading/reloading stiffness according to the work of Karsan-Jirsa and no tensile strength", strength_type: Literal['Mean', 'Characteristic'] = 'Characteristic'
) compressive_strength_fpc: str = '-20 MPa' # TODO: unit-aware type
strength_class: Literal[
"C12/15",
"C16/20",
"C20/25",
"C25/30",
"C30/37",
"C35/45",
"C40/50",
"C45/55",
"C50/60",
"C55/67",
"C60/75",
"C70/85",
"C80/95",
"C90/105",
"Custom",
] = Field(
"Custom",
description="Choose concrete strength category, to take some standard values in the following fields.",
)
strength_type: Literal["Mean", "Characteristic"] = "Characteristic"
compressive_strength_fpc: str = "-20 MPa" # TODO: unit-aware type
strain_at_maximum_strength_epsc0: float = -2.0e-3 strain_at_maximum_strength_epsc0: float = -2.0e-3
crushing_strength_fpcu: str = "-17.0 MPa" # TODO: unit-aware type crushing_strength_fpcu: str = '-17.0 MPa' # TODO: unit-aware type
strain_at_crushing_strength_epscu: float = -3.5e-3 strain_at_crushing_strength_epscu: float = -3.5e-3
analysis_type: Literal["Monotonic", "Cyclic"] = "Monotonic" analysis_type: Literal['Monotonic', 'Cyclic'] = 'Monotonic'
cyclic_data: list[CyclicDataRow] = Field(default_factory=list) cyclic_data: list[CyclicDataRow] = Field(default_factory=list)
field: Literal["_"] = "_" field: Literal['_'] = '_'
set_as_variable: Literal["0", "1"] = "0" set_as_variable: Literal['0', '1'] = '0'

View file

@ -23,176 +23,176 @@ class CyclicDataRow(BaseModel):
class Concrete02LinearTensionSofteningSpec(BaseModel): class Concrete02LinearTensionSofteningSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Concrete02_(Linear_tension_softening)", 'x-gid-name': 'Concrete02_(Linear_tension_softening)',
"x-book": "Uniaxial_Concrete_Materials", 'x-book': 'Uniaxial_Concrete_Materials',
"dependencies": [ 'dependencies': [
{ {
"field": "strength_class", 'field': 'strength_class',
"gid_name": "Strength_class", 'gid_name': 'Strength_class',
"rules": [ 'rules': [
{ {
"trigger": "C12/15", 'trigger': 'C12/15',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C16/20", 'trigger': 'C16/20',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C20/25", 'trigger': 'C20/25',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C25/30", 'trigger': 'C25/30',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C30/37", 'trigger': 'C30/37',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C35/45", 'trigger': 'C35/45',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C40/50", 'trigger': 'C40/50',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C45/55", 'trigger': 'C45/55',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C50/60", 'trigger': 'C50/60',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C60/75", 'trigger': 'C60/75',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C70/85", 'trigger': 'C70/85',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C80/95", 'trigger': 'C80/95',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C90/105", 'trigger': 'C90/105',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Custom", 'trigger': 'Custom',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "analysis_type", 'field': 'analysis_type',
"gid_name": "Analysis_type", 'gid_name': 'Analysis_type',
"rules": [ 'rules': [
{ {
"trigger": "Monotonic", 'trigger': 'Monotonic',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Cyclic", 'trigger': 'Cyclic',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
@ -202,36 +202,18 @@ class Concrete02LinearTensionSofteningSpec(BaseModel):
} }
) )
material: Literal["Concrete02"] = "Concrete02" material: Literal['Concrete02'] = 'Concrete02'
strength_class: Literal[ strength_class: Literal['C12/15', 'C16/20', 'C20/25', 'C25/30', 'C30/37', 'C35/45', 'C40/50', 'C45/55', 'C50/60', 'C55/67', 'C60/75', 'C70/85', 'C80/95', 'C90/105', 'Custom'] = Field('Custom', description='Choose concrete strength category, to generate fast properties in the following fields.')
"C12/15", strength_type: Literal['Mean', 'Characteristic'] = 'Characteristic'
"C16/20", compressive_strength_fpc: str = '-20 MPa' # TODO: unit-aware type
"C20/25",
"C25/30",
"C30/37",
"C35/45",
"C40/50",
"C45/55",
"C50/60",
"C55/67",
"C60/75",
"C70/85",
"C80/95",
"C90/105",
"Custom",
] = Field(
"Custom",
description="Choose concrete strength category, to generate fast properties in the following fields.",
)
strength_type: Literal["Mean", "Characteristic"] = "Characteristic"
compressive_strength_fpc: str = "-20 MPa" # TODO: unit-aware type
strain_at_maximum_strength_epsc0: float = -2.0e-3 strain_at_maximum_strength_epsc0: float = -2.0e-3
crushing_strength_fpcu: str = "-17.0 MPa" # TODO: unit-aware type crushing_strength_fpcu: str = '-17.0 MPa' # TODO: unit-aware type
strain_at_crushing_strength_epscu: float = -3.5e-3 strain_at_crushing_strength_epscu: float = -3.5e-3
ratio_between_unloading_slope_at_epscu_and_initial_slope_lambda: float = 0.5 ratio_between_unloading_slope_at_epscu_and_initial_slope_lambda: float = 0.5
tensile_strength_ft: str = "2.2 MPa" # TODO: unit-aware type tensile_strength_ft: str = '2.2 MPa' # TODO: unit-aware type
tension_softening_stiffness_ets: str = "2 GPa" # TODO: unit-aware type tension_softening_stiffness_ets: str = '2 GPa' # TODO: unit-aware type
analysis_type: Literal["Monotonic", "Cyclic"] = "Monotonic" analysis_type: Literal['Monotonic', 'Cyclic'] = 'Monotonic'
cyclic_data: list[CyclicDataRow] = Field(default_factory=list) cyclic_data: list[CyclicDataRow] = Field(default_factory=list)
field: Literal["_"] = "_" field: Literal['_'] = '_'
set_as_variable: Literal["0", "1"] = "0" set_as_variable: Literal['0', '1'] = '0'

View file

@ -23,176 +23,176 @@ class CyclicDataRow(BaseModel):
class Concrete04PopovicsConcreteSpec(BaseModel): class Concrete04PopovicsConcreteSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Concrete04_(Popovics_concrete)", 'x-gid-name': 'Concrete04_(Popovics_concrete)',
"x-book": "Uniaxial_Concrete_Materials", 'x-book': 'Uniaxial_Concrete_Materials',
"dependencies": [ 'dependencies': [
{ {
"field": "strength_class", 'field': 'strength_class',
"gid_name": "Strength_class", 'gid_name': 'Strength_class',
"rules": [ 'rules': [
{ {
"trigger": "C12/15", 'trigger': 'C12/15',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C16/20", 'trigger': 'C16/20',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C20/25", 'trigger': 'C20/25',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C25/30", 'trigger': 'C25/30',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C30/37", 'trigger': 'C30/37',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C35/45", 'trigger': 'C35/45',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C40/50", 'trigger': 'C40/50',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C45/55", 'trigger': 'C45/55',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C50/60", 'trigger': 'C50/60',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C60/75", 'trigger': 'C60/75',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C70/85", 'trigger': 'C70/85',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C80/95", 'trigger': 'C80/95',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C90/105", 'trigger': 'C90/105',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Custom", 'trigger': 'Custom',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "analysis_type", 'field': 'analysis_type',
"gid_name": "Analysis_type", 'gid_name': 'Analysis_type',
"rules": [ 'rules': [
{ {
"trigger": "Monotonic", 'trigger': 'Monotonic',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Cyclic", 'trigger': 'Cyclic',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
@ -202,35 +202,17 @@ class Concrete04PopovicsConcreteSpec(BaseModel):
} }
) )
material: Literal["Concrete04"] = "Concrete04" material: Literal['Concrete04'] = 'Concrete04'
strength_class: Literal[ strength_class: Literal['C12/15', 'C16/20', 'C20/25', 'C25/30', 'C30/37', 'C35/45', 'C40/50', 'C45/55', 'C50/60', 'C55/67', 'C60/75', 'C70/85', 'C80/95', 'C90/105', 'Custom'] = Field('Custom', description='Choose concrete strength category, to generate fast properties in the following fields.')
"C12/15", strength_type: Literal['Mean', 'Characteristic'] = 'Characteristic'
"C16/20", compressive_strength: str = '-20 MPa' # TODO: unit-aware type
"C20/25",
"C25/30",
"C30/37",
"C35/45",
"C40/50",
"C45/55",
"C50/60",
"C55/67",
"C60/75",
"C70/85",
"C80/95",
"C90/105",
"Custom",
] = Field(
"Custom",
description="Choose concrete strength category, to generate fast properties in the following fields.",
)
strength_type: Literal["Mean", "Characteristic"] = "Characteristic"
compressive_strength: str = "-20 MPa" # TODO: unit-aware type
strain_at_maximum_strength: float = -2.0e-3 strain_at_maximum_strength: float = -2.0e-3
strain_at_crushing_strength: float = -3.5e-3 strain_at_crushing_strength: float = -3.5e-3
initial_stiffness: str = "30 GPa" # TODO: unit-aware type initial_stiffness: str = '30 GPa' # TODO: unit-aware type
maximum_tensile_strength: str = "2.2 MPa" # TODO: unit-aware type maximum_tensile_strength: str = '2.2 MPa' # TODO: unit-aware type
ultimate_tensile_strain: float = 1e-3 ultimate_tensile_strain: float = 1e-3
analysis_type: Literal["Monotonic", "Cyclic"] = "Monotonic" analysis_type: Literal['Monotonic', 'Cyclic'] = 'Monotonic'
cyclic_data: list[CyclicDataRow] = Field(default_factory=list) cyclic_data: list[CyclicDataRow] = Field(default_factory=list)
field: Literal["_"] = "_" field: Literal['_'] = '_'
set_as_variable: Literal["0", "1"] = "0" set_as_variable: Literal['0', '1'] = '0'

View file

@ -23,176 +23,176 @@ class CyclicDataRow(BaseModel):
class Concrete06Spec(BaseModel): class Concrete06Spec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Concrete06", 'x-gid-name': 'Concrete06',
"x-book": "Uniaxial_Concrete_Materials", 'x-book': 'Uniaxial_Concrete_Materials',
"dependencies": [ 'dependencies': [
{ {
"field": "strength_class", 'field': 'strength_class',
"gid_name": "Strength_class", 'gid_name': 'Strength_class',
"rules": [ 'rules': [
{ {
"trigger": "C12/15", 'trigger': 'C12/15',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C16/20", 'trigger': 'C16/20',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C20/25", 'trigger': 'C20/25',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C25/30", 'trigger': 'C25/30',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C30/37", 'trigger': 'C30/37',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C35/45", 'trigger': 'C35/45',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C40/50", 'trigger': 'C40/50',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C45/55", 'trigger': 'C45/55',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C50/60", 'trigger': 'C50/60',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C60/75", 'trigger': 'C60/75',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C70/85", 'trigger': 'C70/85',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C80/95", 'trigger': 'C80/95',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C90/105", 'trigger': 'C90/105',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Custom", 'trigger': 'Custom',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "analysis_type", 'field': 'analysis_type',
"gid_name": "Analysis_type", 'gid_name': 'Analysis_type',
"rules": [ 'rules': [
{ {
"trigger": "Monotonic", 'trigger': 'Monotonic',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Cyclic", 'trigger': 'Cyclic',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
@ -202,38 +202,20 @@ class Concrete06Spec(BaseModel):
} }
) )
material: Literal["Concrete06"] = "Concrete06" material: Literal['Concrete06'] = 'Concrete06'
strength_class: Literal[ strength_class: Literal['C12/15', 'C16/20', 'C20/25', 'C25/30', 'C30/37', 'C35/45', 'C40/50', 'C45/55', 'C50/60', 'C55/67', 'C60/75', 'C70/85', 'C80/95', 'C90/105', 'Custom'] = Field('Custom', description='Choose concrete strength category, to generate fast properties in the following fields.')
"C12/15", strength_type: Literal['Mean', 'Characteristic'] = 'Characteristic'
"C16/20", concrete_compressive_strength_fc: str = '-20 MPa' # TODO: unit-aware type
"C20/25",
"C25/30",
"C30/37",
"C35/45",
"C40/50",
"C45/55",
"C50/60",
"C55/67",
"C60/75",
"C70/85",
"C80/95",
"C90/105",
"Custom",
] = Field(
"Custom",
description="Choose concrete strength category, to generate fast properties in the following fields.",
)
strength_type: Literal["Mean", "Characteristic"] = "Characteristic"
concrete_compressive_strength_fc: str = "-20 MPa" # TODO: unit-aware type
strain_at_compressive_strength_e0: float = -2.0e-3 strain_at_compressive_strength_e0: float = -2.0e-3
compressive_shape_factor_n: int = 1 compressive_shape_factor_n: int = 1
post_peak_compressive_shape_factor_k: int = 1 post_peak_compressive_shape_factor_k: int = 1
parameter_a1_for_compressive_plastic_strain_definition: float = -2.500e-003 parameter_a1_for_compressive_plastic_strain_definition: float = -2.500e-003
tensile_strength_fcr: str = "2.2 MPa" # TODO: unit-aware type tensile_strength_fcr: str = '2.2 MPa' # TODO: unit-aware type
tensile_strain_at_peak_stress_ecr: float = 1.100e-004 tensile_strain_at_peak_stress_ecr: float = 1.100e-004
exponent_of_the_tension_stiffering_curve_b: int = 1 exponent_of_the_tension_stiffering_curve_b: int = 1
parameter_a2_for_tensile_plastic_strain_definition: float = 7.700e-004 parameter_a2_for_tensile_plastic_strain_definition: float = 7.700e-004
analysis_type: Literal["Monotonic", "Cyclic"] = "Monotonic" analysis_type: Literal['Monotonic', 'Cyclic'] = 'Monotonic'
cyclic_data: list[CyclicDataRow] = Field(default_factory=list) cyclic_data: list[CyclicDataRow] = Field(default_factory=list)
field: Literal["_"] = "_" field: Literal['_'] = '_'
set_as_variable: Literal["0", "1"] = "0" set_as_variable: Literal['0', '1'] = '0'

View file

@ -23,202 +23,202 @@ class CyclicDataRow(BaseModel):
class ConcretecmSpec(BaseModel): class ConcretecmSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "ConcreteCM", 'x-gid-name': 'ConcreteCM',
"x-book": "Uniaxial_Concrete_Materials", 'x-book': 'Uniaxial_Concrete_Materials',
"dependencies": [ 'dependencies': [
{ {
"field": "strength_class", 'field': 'strength_class',
"gid_name": "Strength_class", 'gid_name': 'Strength_class',
"rules": [ 'rules': [
{ {
"trigger": "C12/15", 'trigger': 'C12/15',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C16/20", 'trigger': 'C16/20',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C20/25", 'trigger': 'C20/25',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C25/30", 'trigger': 'C25/30',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C30/37", 'trigger': 'C30/37',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C35/45", 'trigger': 'C35/45',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C40/50", 'trigger': 'C40/50',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C45/55", 'trigger': 'C45/55',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C50/60", 'trigger': 'C50/60',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C60/75", 'trigger': 'C60/75',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C70/85", 'trigger': 'C70/85',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C80/95", 'trigger': 'C80/95',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "C90/105", 'trigger': 'C90/105',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Custom", 'trigger': 'Custom',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "consider_gap_closure", 'field': 'consider_gap_closure',
"gid_name": "Consider_gap_closure", 'gid_name': 'Consider_gap_closure',
"rules": [ 'rules': [
{ {
"trigger": "1", 'trigger': '1',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Gap_parameter", 'field': 'Gap_parameter',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "0", 'trigger': '0',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Gap_parameter", 'field': 'Gap_parameter',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "analysis_type", 'field': 'analysis_type',
"gid_name": "Analysis_type", 'gid_name': 'Analysis_type',
"rules": [ 'rules': [
{ {
"trigger": "Monotonic", 'trigger': 'Monotonic',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Cyclic", 'trigger': 'Cyclic',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
@ -228,37 +228,19 @@ class ConcretecmSpec(BaseModel):
} }
) )
material: Literal["ConcreteCM"] = "ConcreteCM" material: Literal['ConcreteCM'] = 'ConcreteCM'
strength_class: Literal[ strength_class: Literal['C12/15', 'C16/20', 'C20/25', 'C25/30', 'C30/37', 'C35/45', 'C40/50', 'C45/55', 'C50/60', 'C55/67', 'C60/75', 'C70/85', 'C80/95', 'C90/105', 'Custom'] = Field('Custom', description='Choose concrete strength category, to generate fast properties in the following fields.')
"C12/15", strength_type: Literal['Mean', 'Characteristic'] = 'Characteristic'
"C16/20", concrete_compressive_strength_fpcc: str = '-20 MPa' # TODO: unit-aware type
"C20/25",
"C25/30",
"C30/37",
"C35/45",
"C40/50",
"C45/55",
"C50/60",
"C55/67",
"C60/75",
"C70/85",
"C80/95",
"C90/105",
"Custom",
] = Field(
"Custom",
description="Choose concrete strength category, to generate fast properties in the following fields.",
)
strength_type: Literal["Mean", "Characteristic"] = "Characteristic"
concrete_compressive_strength_fpcc: str = "-20 MPa" # TODO: unit-aware type
strain_at_compressive_strength_epcc: float = -2.0e-3 strain_at_compressive_strength_epcc: float = -2.0e-3
initial_tangent_modulus_ec: str = "30 GPa" # TODO: unit-aware type initial_tangent_modulus_ec: str = '30 GPa' # TODO: unit-aware type
shape_parameter_rc_in_tsai_s_equation_for_compression: int = 7 shape_parameter_rc_in_tsai_s_equation_for_compression: int = 7
critical_strain_on_compression_envelope: float = 1.035 critical_strain_on_compression_envelope: float = 1.035
tensile_strength_ft: str = "2.2 MPa" # TODO: unit-aware type tensile_strength_ft: str = '2.2 MPa' # TODO: unit-aware type
strain_at_tensile_strength_et: float = 1.100e-004 strain_at_tensile_strength_et: float = 1.100e-004
shape_parameter_rc_in_tsai_s_equation_for_tension: float = 1.2 shape_parameter_rc_in_tsai_s_equation_for_tension: float = 1.2
critical_strain_on_tension_envelope: int = 10000 critical_strain_on_tension_envelope: int = 10000
consider_gap_closure: Literal["1", "0"] = "0" consider_gap_closure: Literal['1', '0'] = '0'
analysis_type: Literal["Monotonic", "Cyclic"] = "Monotonic" analysis_type: Literal['Monotonic', 'Cyclic'] = 'Monotonic'
cyclic_data: list[CyclicDataRow] = Field(default_factory=list) cyclic_data: list[CyclicDataRow] = Field(default_factory=list)

View file

@ -15,173 +15,42 @@ from otko.core.catalog.generated.conditions.line_uniform_forces import LineUnifo
from otko.core.catalog.generated.conditions.point_displacements import PointDisplacementsSpec from otko.core.catalog.generated.conditions.point_displacements import PointDisplacementsSpec
from otko.core.catalog.generated.conditions.line_displacements import LineDisplacementsSpec from otko.core.catalog.generated.conditions.line_displacements import LineDisplacementsSpec
from otko.core.catalog.generated.conditions.surface_displacements import SurfaceDisplacementsSpec from otko.core.catalog.generated.conditions.surface_displacements import SurfaceDisplacementsSpec
from otko.core.catalog.generated.conditions.point_ground_motion_from_record import ( from otko.core.catalog.generated.conditions.point_ground_motion_from_record import PointGroundMotionFromRecordSpec
PointGroundMotionFromRecordSpec, from otko.core.catalog.generated.conditions.point_sine_ground_motion import PointSineGroundMotionSpec
) from otko.core.catalog.generated.conditions.point_equal_constraint_master_node import PointEqualConstraintMasterNodeSpec
from otko.core.catalog.generated.conditions.point_sine_ground_motion import ( from otko.core.catalog.generated.conditions.point_equal_constraint_slave_nodes import PointEqualConstraintSlaveNodesSpec
PointSineGroundMotionSpec, from otko.core.catalog.generated.conditions.line_equal_constraint_slave_nodes import LineEqualConstraintSlaveNodesSpec
) from otko.core.catalog.generated.conditions.point_rigid_link_master_node import PointRigidLinkMasterNodeSpec
from otko.core.catalog.generated.conditions.point_equal_constraint_master_node import ( from otko.core.catalog.generated.conditions.point_rigid_link_slave_nodes import PointRigidLinkSlaveNodesSpec
PointEqualConstraintMasterNodeSpec, from otko.core.catalog.generated.conditions.line_rigid_link_slave_nodes import LineRigidLinkSlaveNodesSpec
) from otko.core.catalog.generated.conditions.point_rigid_diaphragm_master_node import PointRigidDiaphragmMasterNodeSpec
from otko.core.catalog.generated.conditions.point_equal_constraint_slave_nodes import ( from otko.core.catalog.generated.conditions.point_rigid_diaphragm_slave_nodes import PointRigidDiaphragmSlaveNodesSpec
PointEqualConstraintSlaveNodesSpec, from otko.core.catalog.generated.conditions.line_rigid_diaphragm_slave_nodes import LineRigidDiaphragmSlaveNodesSpec
)
from otko.core.catalog.generated.conditions.line_equal_constraint_slave_nodes import (
LineEqualConstraintSlaveNodesSpec,
)
from otko.core.catalog.generated.conditions.point_rigid_link_master_node import (
PointRigidLinkMasterNodeSpec,
)
from otko.core.catalog.generated.conditions.point_rigid_link_slave_nodes import (
PointRigidLinkSlaveNodesSpec,
)
from otko.core.catalog.generated.conditions.line_rigid_link_slave_nodes import (
LineRigidLinkSlaveNodesSpec,
)
from otko.core.catalog.generated.conditions.point_rigid_diaphragm_master_node import (
PointRigidDiaphragmMasterNodeSpec,
)
from otko.core.catalog.generated.conditions.point_rigid_diaphragm_slave_nodes import (
PointRigidDiaphragmSlaveNodesSpec,
)
from otko.core.catalog.generated.conditions.line_rigid_diaphragm_slave_nodes import (
LineRigidDiaphragmSlaveNodesSpec,
)
from otko.core.catalog.generated.conditions.point_mass import PointMassSpec from otko.core.catalog.generated.conditions.point_mass import PointMassSpec
from otko.core.catalog.generated.conditions.line_mass import LineMassSpec from otko.core.catalog.generated.conditions.line_mass import LineMassSpec
from otko.core.catalog.generated.conditions.surface_mass import SurfaceMassSpec from otko.core.catalog.generated.conditions.surface_mass import SurfaceMassSpec
from otko.core.catalog.generated.conditions.volume_mass import VolumeMassSpec from otko.core.catalog.generated.conditions.volume_mass import VolumeMassSpec
from otko.core.catalog.generated.conditions.line_rayleigh_damping_elements import ( from otko.core.catalog.generated.conditions.line_rayleigh_damping_elements import LineRayleighDampingElementsSpec
LineRayleighDampingElementsSpec, from otko.core.catalog.generated.conditions.surface_rayleigh_damping_elements import SurfaceRayleighDampingElementsSpec
) from otko.core.catalog.generated.conditions.volume_rayleigh_damping_elements import VolumeRayleighDampingElementsSpec
from otko.core.catalog.generated.conditions.surface_rayleigh_damping_elements import ( from otko.core.catalog.generated.conditions.point_rayleigh_damping_nodes import PointRayleighDampingNodesSpec
SurfaceRayleighDampingElementsSpec, from otko.core.catalog.generated.conditions.line_rayleigh_damping_nodes import LineRayleighDampingNodesSpec
) from otko.core.catalog.generated.conditions.surface_rayleigh_damping_nodes import SurfaceRayleighDampingNodesSpec
from otko.core.catalog.generated.conditions.volume_rayleigh_damping_elements import ( from otko.core.catalog.generated.conditions.volume_rayleigh_damping_nodes import VolumeRayleighDampingNodesSpec
VolumeRayleighDampingElementsSpec,
)
from otko.core.catalog.generated.conditions.point_rayleigh_damping_nodes import (
PointRayleighDampingNodesSpec,
)
from otko.core.catalog.generated.conditions.line_rayleigh_damping_nodes import (
LineRayleighDampingNodesSpec,
)
from otko.core.catalog.generated.conditions.surface_rayleigh_damping_nodes import (
SurfaceRayleighDampingNodesSpec,
)
from otko.core.catalog.generated.conditions.volume_rayleigh_damping_nodes import (
VolumeRayleighDampingNodesSpec,
)
from otko.core.catalog.generated.conditions.point_zerolength import PointZerolengthSpec from otko.core.catalog.generated.conditions.point_zerolength import PointZerolengthSpec
from otko.core.catalog.generated.conditions.line_beam_contact_master_end_nodes import ( from otko.core.catalog.generated.conditions.line_beam_contact_master_end_nodes import LineBeamContactMasterEndNodesSpec
LineBeamContactMasterEndNodesSpec, from otko.core.catalog.generated.conditions.point_beam_contact_slave_nodes import PointBeamContactSlaveNodesSpec
) from otko.core.catalog.generated.conditions.point_body_constraint_master_node import PointBodyConstraintMasterNodeSpec
from otko.core.catalog.generated.conditions.point_beam_contact_slave_nodes import ( from otko.core.catalog.generated.conditions.point_body_constraint_slave_nodes import PointBodyConstraintSlaveNodesSpec
PointBeamContactSlaveNodesSpec, from otko.core.catalog.generated.conditions.line_body_constraint_slave_nodes import LineBodyConstraintSlaveNodesSpec
)
from otko.core.catalog.generated.conditions.point_body_constraint_master_node import (
PointBodyConstraintMasterNodeSpec,
)
from otko.core.catalog.generated.conditions.point_body_constraint_slave_nodes import (
PointBodyConstraintSlaveNodesSpec,
)
from otko.core.catalog.generated.conditions.line_body_constraint_slave_nodes import (
LineBodyConstraintSlaveNodesSpec,
)
from otko.core.catalog.generated.conditions.zerolength import ZerolengthSpec from otko.core.catalog.generated.conditions.zerolength import ZerolengthSpec
Restraints = Union[PointRestraintsSpec, LineRestraintsSpec, SurfaceRestraintsSpec] Restraints = Union[PointRestraintsSpec, LineRestraintsSpec, SurfaceRestraintsSpec]
Loads = Union[ Loads = Union[PointForcesSpec, LineForcesSpec, SurfaceForcesSpec, LineUniformForcesSpec, PointDisplacementsSpec, LineDisplacementsSpec, SurfaceDisplacementsSpec, PointGroundMotionFromRecordSpec, PointSineGroundMotionSpec]
PointForcesSpec, Constraints = Union[PointEqualConstraintMasterNodeSpec, PointEqualConstraintSlaveNodesSpec, LineEqualConstraintSlaveNodesSpec, PointRigidLinkMasterNodeSpec, PointRigidLinkSlaveNodesSpec, LineRigidLinkSlaveNodesSpec, PointRigidDiaphragmMasterNodeSpec, PointRigidDiaphragmSlaveNodesSpec, LineRigidDiaphragmSlaveNodesSpec]
LineForcesSpec, MassDamping = Union[PointMassSpec, LineMassSpec, SurfaceMassSpec, VolumeMassSpec, LineRayleighDampingElementsSpec, SurfaceRayleighDampingElementsSpec, VolumeRayleighDampingElementsSpec, PointRayleighDampingNodesSpec, LineRayleighDampingNodesSpec, SurfaceRayleighDampingNodesSpec, VolumeRayleighDampingNodesSpec]
SurfaceForcesSpec, ZerolengthElements = Union[PointZerolengthSpec, LineBeamContactMasterEndNodesSpec, PointBeamContactSlaveNodesSpec]
LineUniformForcesSpec, OldConditions = Union[PointBodyConstraintMasterNodeSpec, PointBodyConstraintSlaveNodesSpec, LineBodyConstraintSlaveNodesSpec, ZerolengthSpec]
PointDisplacementsSpec,
LineDisplacementsSpec,
SurfaceDisplacementsSpec,
PointGroundMotionFromRecordSpec,
PointSineGroundMotionSpec,
]
Constraints = Union[
PointEqualConstraintMasterNodeSpec,
PointEqualConstraintSlaveNodesSpec,
LineEqualConstraintSlaveNodesSpec,
PointRigidLinkMasterNodeSpec,
PointRigidLinkSlaveNodesSpec,
LineRigidLinkSlaveNodesSpec,
PointRigidDiaphragmMasterNodeSpec,
PointRigidDiaphragmSlaveNodesSpec,
LineRigidDiaphragmSlaveNodesSpec,
]
MassDamping = Union[
PointMassSpec,
LineMassSpec,
SurfaceMassSpec,
VolumeMassSpec,
LineRayleighDampingElementsSpec,
SurfaceRayleighDampingElementsSpec,
VolumeRayleighDampingElementsSpec,
PointRayleighDampingNodesSpec,
LineRayleighDampingNodesSpec,
SurfaceRayleighDampingNodesSpec,
VolumeRayleighDampingNodesSpec,
]
ZerolengthElements = Union[
PointZerolengthSpec, LineBeamContactMasterEndNodesSpec, PointBeamContactSlaveNodesSpec
]
OldConditions = Union[
PointBodyConstraintMasterNodeSpec,
PointBodyConstraintSlaveNodesSpec,
LineBodyConstraintSlaveNodesSpec,
ZerolengthSpec,
]
__all__ = [ __all__ = ['PointRestraintsSpec', 'LineRestraintsSpec', 'SurfaceRestraintsSpec', 'PointForcesSpec', 'LineForcesSpec', 'SurfaceForcesSpec', 'LineUniformForcesSpec', 'PointDisplacementsSpec', 'LineDisplacementsSpec', 'SurfaceDisplacementsSpec', 'PointGroundMotionFromRecordSpec', 'PointSineGroundMotionSpec', 'PointEqualConstraintMasterNodeSpec', 'PointEqualConstraintSlaveNodesSpec', 'LineEqualConstraintSlaveNodesSpec', 'PointRigidLinkMasterNodeSpec', 'PointRigidLinkSlaveNodesSpec', 'LineRigidLinkSlaveNodesSpec', 'PointRigidDiaphragmMasterNodeSpec', 'PointRigidDiaphragmSlaveNodesSpec', 'LineRigidDiaphragmSlaveNodesSpec', 'PointMassSpec', 'LineMassSpec', 'SurfaceMassSpec', 'VolumeMassSpec', 'LineRayleighDampingElementsSpec', 'SurfaceRayleighDampingElementsSpec', 'VolumeRayleighDampingElementsSpec', 'PointRayleighDampingNodesSpec', 'LineRayleighDampingNodesSpec', 'SurfaceRayleighDampingNodesSpec', 'VolumeRayleighDampingNodesSpec', 'PointZerolengthSpec', 'LineBeamContactMasterEndNodesSpec', 'PointBeamContactSlaveNodesSpec', 'PointBodyConstraintMasterNodeSpec', 'PointBodyConstraintSlaveNodesSpec', 'LineBodyConstraintSlaveNodesSpec', 'ZerolengthSpec', 'Restraints', 'Loads', 'Constraints', 'MassDamping', 'ZerolengthElements', 'OldConditions']
"PointRestraintsSpec",
"LineRestraintsSpec",
"SurfaceRestraintsSpec",
"PointForcesSpec",
"LineForcesSpec",
"SurfaceForcesSpec",
"LineUniformForcesSpec",
"PointDisplacementsSpec",
"LineDisplacementsSpec",
"SurfaceDisplacementsSpec",
"PointGroundMotionFromRecordSpec",
"PointSineGroundMotionSpec",
"PointEqualConstraintMasterNodeSpec",
"PointEqualConstraintSlaveNodesSpec",
"LineEqualConstraintSlaveNodesSpec",
"PointRigidLinkMasterNodeSpec",
"PointRigidLinkSlaveNodesSpec",
"LineRigidLinkSlaveNodesSpec",
"PointRigidDiaphragmMasterNodeSpec",
"PointRigidDiaphragmSlaveNodesSpec",
"LineRigidDiaphragmSlaveNodesSpec",
"PointMassSpec",
"LineMassSpec",
"SurfaceMassSpec",
"VolumeMassSpec",
"LineRayleighDampingElementsSpec",
"SurfaceRayleighDampingElementsSpec",
"VolumeRayleighDampingElementsSpec",
"PointRayleighDampingNodesSpec",
"LineRayleighDampingNodesSpec",
"SurfaceRayleighDampingNodesSpec",
"VolumeRayleighDampingNodesSpec",
"PointZerolengthSpec",
"LineBeamContactMasterEndNodesSpec",
"PointBeamContactSlaveNodesSpec",
"PointBodyConstraintMasterNodeSpec",
"PointBodyConstraintSlaveNodesSpec",
"LineBodyConstraintSlaveNodesSpec",
"ZerolengthSpec",
"Restraints",
"Loads",
"Constraints",
"MassDamping",
"ZerolengthElements",
"OldConditions",
]

View file

@ -15,9 +15,10 @@ from pydantic import BaseModel, ConfigDict, Field
class LineBeamContactMasterEndNodesSpec(BaseModel): class LineBeamContactMasterEndNodesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Line_Beam_contact_master_end_nodes", 'x-gid-name': 'Line_Beam_contact_master_end_nodes',
"x-book": "ZeroLength_Elements", 'x-book': 'ZeroLength_Elements',
} }
) )
beam_contact_id: int = 1 beam_contact_id: int = 1

View file

@ -17,80 +17,80 @@ from pydantic import BaseModel, ConfigDict, Field
class LineBodyConstraintSlaveNodesSpec(BaseModel): class LineBodyConstraintSlaveNodesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Line_Body_constraint_slave_nodes", 'x-gid-name': 'Line_Body_constraint_slave_nodes',
"x-book": "Old_Conditions", 'x-book': 'Old_Conditions',
"dependencies": [ 'dependencies': [
{ {
"field": "fast_constraints", 'field': 'fast_constraints',
"gid_name": "Fast_constraints", 'gid_name': 'Fast_constraints',
"rules": [ 'rules': [
{ {
"trigger": "Pinned_Connection", 'trigger': 'Pinned_Connection',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Fixed_Connection", 'trigger': 'Fixed_Connection',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "1", 'target': '1',
}, },
], ],
}, },
@ -100,13 +100,12 @@ class LineBodyConstraintSlaveNodesSpec(BaseModel):
} }
) )
line_constraint_id_number: int = Field( line_constraint_id_number: int = Field(1, description='Enter a positive integer number for the body constraint.')
1, description="Enter a positive integer number for the body constraint." x_translation: Literal['1', '0'] = '1'
) y_translation: Literal['1', '0'] = '1'
x_translation: Literal["1", "0"] = "1" z_translation: Literal['1', '0'] = '1'
y_translation: Literal["1", "0"] = "1" x_rotation: Literal['1', '0'] = '1'
z_translation: Literal["1", "0"] = "1" y_rotation: Literal['1', '0'] = '1'
x_rotation: Literal["1", "0"] = "1" z_rotation: Literal['1', '0'] = '1'
y_rotation: Literal["1", "0"] = "1" fast_constraints: Literal['Pinned_Connection', 'Fixed_Connection'] = 'Pinned_Connection'
z_rotation: Literal["1", "0"] = "1"
fast_constraints: Literal["Pinned_Connection", "Fixed_Connection"] = "Pinned_Connection"

View file

@ -15,14 +15,15 @@ from pydantic import BaseModel, ConfigDict, Field
class LineDisplacementsSpec(BaseModel): class LineDisplacementsSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Line_Displacements", 'x-gid-name': 'Line_Displacements',
"x-book": "Loads", 'x-book': 'Loads',
} }
) )
x_displacement: str = "0.0m" # TODO: unit-aware type x_displacement: str = '0.0m' # TODO: unit-aware type
y_displacement: str = "0.0m" # TODO: unit-aware type y_displacement: str = '0.0m' # TODO: unit-aware type
z_displacement: str = "0.0m" # TODO: unit-aware type z_displacement: str = '0.0m' # TODO: unit-aware type
x_rotation: str = "0.0 rad" # TODO: unit-aware type x_rotation: str = '0.0 rad' # TODO: unit-aware type
y_rotation: str = "0.0 rad" # TODO: unit-aware type y_rotation: str = '0.0 rad' # TODO: unit-aware type
z_rotation: str = "0.0 rad" # TODO: unit-aware type z_rotation: str = '0.0 rad' # TODO: unit-aware type

View file

@ -17,17 +17,16 @@ from pydantic import BaseModel, ConfigDict, Field
class LineEqualConstraintSlaveNodesSpec(BaseModel): class LineEqualConstraintSlaveNodesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Line_Equal_constraint_slave_nodes", 'x-gid-name': 'Line_Equal_constraint_slave_nodes',
"x-book": "Constraints", 'x-book': 'Constraints',
} }
) )
equal_constraint_id: int = Field( equal_constraint_id: int = Field(1, description='Enter a positive integer number for the equal constraint.')
1, description="Enter a positive integer number for the equal constraint." x_translation: Literal['1', '0'] = '1'
) y_translation: Literal['1', '0'] = '1'
x_translation: Literal["1", "0"] = "1" z_translation: Literal['1', '0'] = '1'
y_translation: Literal["1", "0"] = "1" x_rotation: Literal['1', '0'] = '1'
z_translation: Literal["1", "0"] = "1" y_rotation: Literal['1', '0'] = '1'
x_rotation: Literal["1", "0"] = "1" z_rotation: Literal['1', '0'] = '1'
y_rotation: Literal["1", "0"] = "1"
z_rotation: Literal["1", "0"] = "1"

View file

@ -15,14 +15,15 @@ from pydantic import BaseModel, ConfigDict, Field
class LineForcesSpec(BaseModel): class LineForcesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Line_Forces", 'x-gid-name': 'Line_Forces',
"x-book": "Loads", 'x-book': 'Loads',
} }
) )
x_force: str = "0.0 kN" # TODO: unit-aware type x_force: str = '0.0 kN' # TODO: unit-aware type
y_force: str = "0.0 kN" # TODO: unit-aware type y_force: str = '0.0 kN' # TODO: unit-aware type
z_force: str = "0.0 kN" # TODO: unit-aware type z_force: str = '0.0 kN' # TODO: unit-aware type
x_moment: str = "0.0 kNm" # TODO: unit-aware type x_moment: str = '0.0 kNm' # TODO: unit-aware type
y_moment: str = "0.0 kNm" # TODO: unit-aware type y_moment: str = '0.0 kNm' # TODO: unit-aware type
z_moment: str = "0.0 kNm" # TODO: unit-aware type z_moment: str = '0.0 kNm' # TODO: unit-aware type

View file

@ -17,15 +17,16 @@ from pydantic import BaseModel, ConfigDict, Field
class LineMassSpec(BaseModel): class LineMassSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Line_Mass", 'x-gid-name': 'Line_Mass',
"x-book": "Mass/Damping", 'x-book': 'Mass/Damping',
} }
) )
mass_dof_values: Literal[":"] = ":" mass_dof_values: Literal[':'] = ':'
x_direction: str = "0.0ton" # TODO: unit-aware type x_direction: str = '0.0ton' # TODO: unit-aware type
y_direction: str = "0.0ton" # TODO: unit-aware type y_direction: str = '0.0ton' # TODO: unit-aware type
z_direction: str = "0.0ton" # TODO: unit-aware type z_direction: str = '0.0ton' # TODO: unit-aware type
x_rotation: str = "0.0ton" # TODO: unit-aware type x_rotation: str = '0.0ton' # TODO: unit-aware type
y_rotation: str = "0.0ton" # TODO: unit-aware type y_rotation: str = '0.0ton' # TODO: unit-aware type
z_rotation: str = "0.0ton" # TODO: unit-aware type z_rotation: str = '0.0ton' # TODO: unit-aware type

View file

@ -15,8 +15,8 @@ from pydantic import BaseModel, ConfigDict, Field
class LineRayleighDampingElementsSpec(BaseModel): class LineRayleighDampingElementsSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Line_Rayleigh_Damping-Elements", 'x-gid-name': 'Line_Rayleigh_Damping-Elements',
"x-book": "Mass/Damping", 'x-book': 'Mass/Damping',
} }
) )
@ -25,3 +25,4 @@ class LineRayleighDampingElementsSpec(BaseModel):
betak: float = 0.0 betak: float = 0.0
betakinit: float = 0.0 betakinit: float = 0.0
betakcomm: float = 0.0 betakcomm: float = 0.0

View file

@ -15,8 +15,8 @@ from pydantic import BaseModel, ConfigDict, Field
class LineRayleighDampingNodesSpec(BaseModel): class LineRayleighDampingNodesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Line_Rayleigh_Damping-Nodes", 'x-gid-name': 'Line_Rayleigh_Damping-Nodes',
"x-book": "Mass/Damping", 'x-book': 'Mass/Damping',
} }
) )
@ -25,3 +25,4 @@ class LineRayleighDampingNodesSpec(BaseModel):
betak: float = 0.0 betak: float = 0.0
betakinit: float = 0.0 betakinit: float = 0.0
betakcomm: float = 0.0 betakcomm: float = 0.0

View file

@ -17,290 +17,290 @@ from pydantic import BaseModel, ConfigDict, Field
class LineRestraintsSpec(BaseModel): class LineRestraintsSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Line_Restraints", 'x-gid-name': 'Line_Restraints',
"x-book": "Restraints", 'x-book': 'Restraints',
"dependencies": [ 'dependencies': [
{ {
"field": "fast_restraints", 'field': 'fast_restraints',
"gid_name": "Fast_restraints", 'gid_name': 'Fast_restraints',
"rules": [ 'rules': [
{ {
"trigger": "Fix_XYZ", 'trigger': 'Fix_XYZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "1", 'target': '1',
}, },
], ],
}, },
{ {
"trigger": "Fix_XY", 'trigger': 'Fix_XY',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Fix_XZ", 'trigger': 'Fix_XZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Fix_YZ", 'trigger': 'Fix_YZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Pin_XYZ", 'trigger': 'Pin_XYZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Pin_XY", 'trigger': 'Pin_XY',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Pin_XZ", 'trigger': 'Pin_XZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Pin_YZ", 'trigger': 'Pin_YZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
@ -310,13 +310,12 @@ class LineRestraintsSpec(BaseModel):
} }
) )
x_translation: Literal["1", "0"] = "1" x_translation: Literal['1', '0'] = '1'
y_translation: Literal["1", "0"] = "1" y_translation: Literal['1', '0'] = '1'
z_translation: Literal["1", "0"] = "1" z_translation: Literal['1', '0'] = '1'
x_rotation: Literal["1", "0"] = "1" x_rotation: Literal['1', '0'] = '1'
y_rotation: Literal["1", "0"] = "1" y_rotation: Literal['1', '0'] = '1'
z_rotation: Literal["1", "0"] = "1" z_rotation: Literal['1', '0'] = '1'
fluid_pressure: Literal["1", "0"] = "0" fluid_pressure: Literal['1', '0'] = '0'
fast_restraints: Literal[ fast_restraints: Literal['Fix_XYZ', 'Fix_XY', 'Fix_XZ', 'Fix_YZ', 'Pin_XYZ', 'Pin_XY', 'Pin_XZ', 'Pin_YZ'] = 'Fix_XYZ'
"Fix_XYZ", "Fix_XY", "Fix_XZ", "Fix_YZ", "Pin_XYZ", "Pin_XY", "Pin_XZ", "Pin_YZ"
] = "Fix_XYZ"

View file

@ -17,10 +17,11 @@ from pydantic import BaseModel, ConfigDict, Field
class LineRigidDiaphragmSlaveNodesSpec(BaseModel): class LineRigidDiaphragmSlaveNodesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Line_Rigid_diaphragm_slave_nodes", 'x-gid-name': 'Line_Rigid_diaphragm_slave_nodes',
"x-book": "Constraints", 'x-book': 'Constraints',
} }
) )
rigid_diaphragm_id: int = 1 rigid_diaphragm_id: int = 1
rigid_plane: Literal["XY", "YZ", "ZX"] = "XY" rigid_plane: Literal['XY', 'YZ', 'ZX'] = 'XY'

View file

@ -17,12 +17,11 @@ from pydantic import BaseModel, ConfigDict, Field
class LineRigidLinkSlaveNodesSpec(BaseModel): class LineRigidLinkSlaveNodesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Line_Rigid_link_slave_nodes", 'x-gid-name': 'Line_Rigid_link_slave_nodes',
"x-book": "Constraints", 'x-book': 'Constraints',
} }
) )
rigid_link_id: int = Field( rigid_link_id: int = Field(1, description='Give a positive integer number for body constraint group.')
1, description="Give a positive integer number for body constraint group." rigid_link_type: Literal['Bar', 'Beam'] = 'Beam'
)
rigid_link_type: Literal["Bar", "Beam"] = "Beam"

View file

@ -15,11 +15,12 @@ from pydantic import BaseModel, ConfigDict, Field
class LineUniformForcesSpec(BaseModel): class LineUniformForcesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Line_Uniform_Forces", 'x-gid-name': 'Line_Uniform_Forces',
"x-book": "Loads", 'x-book': 'Loads',
} }
) )
uniform_load_along_line_longitudinal_axis: str = "0.0 kN/m" # TODO: unit-aware type uniform_load_along_line_longitudinal_axis: str = '0.0 kN/m' # TODO: unit-aware type
uniform_load_acting_in_local_y_direction: str = "0.0 kN/m" # TODO: unit-aware type uniform_load_acting_in_local_y_direction: str = '0.0 kN/m' # TODO: unit-aware type
uniform_load_acting_in_local_z_direction: str = "0.0 kN/m" # TODO: unit-aware type uniform_load_acting_in_local_z_direction: str = '0.0 kN/m' # TODO: unit-aware type

View file

@ -17,14 +17,15 @@ from pydantic import BaseModel, ConfigDict, Field
class PointBeamContactSlaveNodesSpec(BaseModel): class PointBeamContactSlaveNodesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Point_Beam_contact_slave_nodes", 'x-gid-name': 'Point_Beam_contact_slave_nodes',
"x-book": "ZeroLength_Elements", 'x-book': 'ZeroLength_Elements',
} }
) )
beam_contact_id: int = 1 beam_contact_id: int = 1
contact_material_mat_multidimensional_nd_materials_user_materials: str = "Contact" contact_material_mat_multidimensional_nd_materials_user_materials: str = 'Contact'
width_radius: str = "0.25m" # TODO: unit-aware type width_radius: str = '0.25m' # TODO: unit-aware type
gap_tolerance: float = 1.0e-10 gap_tolerance: float = 1.0e-10
force_tolerance: float = 1.0e-10 force_tolerance: float = 1.0e-10
initial_assumption: Literal["Contact", "No_Contact"] = "Contact" initial_assumption: Literal['Contact', 'No_Contact'] = 'Contact'

View file

@ -15,11 +15,10 @@ from pydantic import BaseModel, ConfigDict, Field
class PointBodyConstraintMasterNodeSpec(BaseModel): class PointBodyConstraintMasterNodeSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Point_Body_constraint_master_node", 'x-gid-name': 'Point_Body_constraint_master_node',
"x-book": "Old_Conditions", 'x-book': 'Old_Conditions',
} }
) )
body_constraint_id_number: int = Field( body_constraint_id_number: int = Field(1, description='Give a positive integer number for body constraint group.')
1, description="Give a positive integer number for body constraint group."
)

View file

@ -17,80 +17,80 @@ from pydantic import BaseModel, ConfigDict, Field
class PointBodyConstraintSlaveNodesSpec(BaseModel): class PointBodyConstraintSlaveNodesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Point_Body_constraint_slave_nodes", 'x-gid-name': 'Point_Body_constraint_slave_nodes',
"x-book": "Old_Conditions", 'x-book': 'Old_Conditions',
"dependencies": [ 'dependencies': [
{ {
"field": "fast_constraints", 'field': 'fast_constraints',
"gid_name": "Fast_constraints", 'gid_name': 'Fast_constraints',
"rules": [ 'rules': [
{ {
"trigger": "Pinned_Connection", 'trigger': 'Pinned_Connection',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Fixed_Connection", 'trigger': 'Fixed_Connection',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "1", 'target': '1',
}, },
], ],
}, },
@ -100,13 +100,12 @@ class PointBodyConstraintSlaveNodesSpec(BaseModel):
} }
) )
body_constraint_id_number: int = Field( body_constraint_id_number: int = Field(1, description='Give a positive integer number for body constraint group.')
1, description="Give a positive integer number for body constraint group." x_translation: Literal['1', '0'] = '1'
) y_translation: Literal['1', '0'] = '1'
x_translation: Literal["1", "0"] = "1" z_translation: Literal['1', '0'] = '1'
y_translation: Literal["1", "0"] = "1" x_rotation: Literal['1', '0'] = '1'
z_translation: Literal["1", "0"] = "1" y_rotation: Literal['1', '0'] = '1'
x_rotation: Literal["1", "0"] = "1" z_rotation: Literal['1', '0'] = '1'
y_rotation: Literal["1", "0"] = "1" fast_constraints: Literal['Pinned_Connection', 'Fixed_Connection'] = 'Pinned_Connection'
z_rotation: Literal["1", "0"] = "1"
fast_constraints: Literal["Pinned_Connection", "Fixed_Connection"] = "Pinned_Connection"

View file

@ -15,14 +15,15 @@ from pydantic import BaseModel, ConfigDict, Field
class PointDisplacementsSpec(BaseModel): class PointDisplacementsSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Point_Displacements", 'x-gid-name': 'Point_Displacements',
"x-book": "Loads", 'x-book': 'Loads',
} }
) )
x_displacement: str = "0.0m" # TODO: unit-aware type x_displacement: str = '0.0m' # TODO: unit-aware type
y_displacement: str = "0.0m" # TODO: unit-aware type y_displacement: str = '0.0m' # TODO: unit-aware type
z_displacement: str = "0.0m" # TODO: unit-aware type z_displacement: str = '0.0m' # TODO: unit-aware type
x_rotation: str = "0.0 rad" # TODO: unit-aware type x_rotation: str = '0.0 rad' # TODO: unit-aware type
y_rotation: str = "0.0 rad" # TODO: unit-aware type y_rotation: str = '0.0 rad' # TODO: unit-aware type
z_rotation: str = "0.0 rad" # TODO: unit-aware type z_rotation: str = '0.0 rad' # TODO: unit-aware type

View file

@ -15,11 +15,10 @@ from pydantic import BaseModel, ConfigDict, Field
class PointEqualConstraintMasterNodeSpec(BaseModel): class PointEqualConstraintMasterNodeSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Point_Equal_constraint_master_node", 'x-gid-name': 'Point_Equal_constraint_master_node',
"x-book": "Constraints", 'x-book': 'Constraints',
} }
) )
equal_constraint_id: int = Field( equal_constraint_id: int = Field(1, description='Give a positive integer number for body constraint group.')
1, description="Give a positive integer number for body constraint group."
)

View file

@ -17,17 +17,16 @@ from pydantic import BaseModel, ConfigDict, Field
class PointEqualConstraintSlaveNodesSpec(BaseModel): class PointEqualConstraintSlaveNodesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Point_Equal_constraint_slave_nodes", 'x-gid-name': 'Point_Equal_constraint_slave_nodes',
"x-book": "Constraints", 'x-book': 'Constraints',
} }
) )
equal_constraint_id: int = Field( equal_constraint_id: int = Field(1, description='Give a positive integer number for body constraint group.')
1, description="Give a positive integer number for body constraint group." x_translation: Literal['1', '0'] = '1'
) y_translation: Literal['1', '0'] = '1'
x_translation: Literal["1", "0"] = "1" z_translation: Literal['1', '0'] = '1'
y_translation: Literal["1", "0"] = "1" x_rotation: Literal['1', '0'] = '1'
z_translation: Literal["1", "0"] = "1" y_rotation: Literal['1', '0'] = '1'
x_rotation: Literal["1", "0"] = "1" z_rotation: Literal['1', '0'] = '1'
y_rotation: Literal["1", "0"] = "1"
z_rotation: Literal["1", "0"] = "1"

View file

@ -15,14 +15,15 @@ from pydantic import BaseModel, ConfigDict, Field
class PointForcesSpec(BaseModel): class PointForcesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Point_Forces", 'x-gid-name': 'Point_Forces',
"x-book": "Loads", 'x-book': 'Loads',
} }
) )
x_force: str = "0.0 kN" # TODO: unit-aware type x_force: str = '0.0 kN' # TODO: unit-aware type
y_force: str = "0.0 kN" # TODO: unit-aware type y_force: str = '0.0 kN' # TODO: unit-aware type
z_force: str = "0.0 kN" # TODO: unit-aware type z_force: str = '0.0 kN' # TODO: unit-aware type
x_moment: str = "0.0 kNm" # TODO: unit-aware type x_moment: str = '0.0 kNm' # TODO: unit-aware type
y_moment: str = "0.0 kNm" # TODO: unit-aware type y_moment: str = '0.0 kNm' # TODO: unit-aware type
z_moment: str = "0.0 kNm" # TODO: unit-aware type z_moment: str = '0.0 kNm' # TODO: unit-aware type

View file

@ -17,10 +17,11 @@ from pydantic import BaseModel, ConfigDict, Field
class PointGroundMotionFromRecordSpec(BaseModel): class PointGroundMotionFromRecordSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Point_Ground_Motion_from_Record", 'x-gid-name': 'Point_Ground_Motion_from_Record',
"x-book": "Loads", 'x-book': 'Loads',
} }
) )
record_file: str = "Ground_Motion_Record" record_file: str = 'Ground_Motion_Record'
ground_motion_direction: Literal["Ux", "Uy", "Uz", "Rx", "Ry", "Rz"] = "Ux" ground_motion_direction: Literal['Ux', 'Uy', 'Uz', 'Rx', 'Ry', 'Rz'] = 'Ux'

View file

@ -17,15 +17,16 @@ from pydantic import BaseModel, ConfigDict, Field
class PointMassSpec(BaseModel): class PointMassSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Point_Mass", 'x-gid-name': 'Point_Mass',
"x-book": "Mass/Damping", 'x-book': 'Mass/Damping',
} }
) )
mass_dof_values: Literal[":"] = ":" mass_dof_values: Literal[':'] = ':'
x_direction: str = "0.0ton" # TODO: unit-aware type x_direction: str = '0.0ton' # TODO: unit-aware type
y_direction: str = "0.0ton" # TODO: unit-aware type y_direction: str = '0.0ton' # TODO: unit-aware type
z_direction: str = "0.0ton" # TODO: unit-aware type z_direction: str = '0.0ton' # TODO: unit-aware type
x_rotation: str = "0.0ton" # TODO: unit-aware type x_rotation: str = '0.0ton' # TODO: unit-aware type
y_rotation: str = "0.0ton" # TODO: unit-aware type y_rotation: str = '0.0ton' # TODO: unit-aware type
z_rotation: str = "0.0ton" # TODO: unit-aware type z_rotation: str = '0.0ton' # TODO: unit-aware type

View file

@ -15,8 +15,8 @@ from pydantic import BaseModel, ConfigDict, Field
class PointRayleighDampingNodesSpec(BaseModel): class PointRayleighDampingNodesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Point_Rayleigh_Damping-Nodes", 'x-gid-name': 'Point_Rayleigh_Damping-Nodes',
"x-book": "Mass/Damping", 'x-book': 'Mass/Damping',
} }
) )
@ -25,3 +25,4 @@ class PointRayleighDampingNodesSpec(BaseModel):
betak: float = 0.0 betak: float = 0.0
betakinit: float = 0.0 betakinit: float = 0.0
betakcomm: float = 0.0 betakcomm: float = 0.0

View file

@ -17,290 +17,290 @@ from pydantic import BaseModel, ConfigDict, Field
class PointRestraintsSpec(BaseModel): class PointRestraintsSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Point_Restraints", 'x-gid-name': 'Point_Restraints',
"x-book": "Restraints", 'x-book': 'Restraints',
"dependencies": [ 'dependencies': [
{ {
"field": "fast_restraints", 'field': 'fast_restraints',
"gid_name": "Fast_restraints", 'gid_name': 'Fast_restraints',
"rules": [ 'rules': [
{ {
"trigger": "Fix_XYZ", 'trigger': 'Fix_XYZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "1", 'target': '1',
}, },
], ],
}, },
{ {
"trigger": "Fix_XY", 'trigger': 'Fix_XY',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Fix_XZ", 'trigger': 'Fix_XZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Fix_YZ", 'trigger': 'Fix_YZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Pin_XYZ", 'trigger': 'Pin_XYZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Pin_XY", 'trigger': 'Pin_XY',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Pin_XZ", 'trigger': 'Pin_XZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Pin_YZ", 'trigger': 'Pin_YZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
@ -310,13 +310,12 @@ class PointRestraintsSpec(BaseModel):
} }
) )
x_translation: Literal["1", "0"] = "1" x_translation: Literal['1', '0'] = '1'
y_translation: Literal["1", "0"] = "1" y_translation: Literal['1', '0'] = '1'
z_translation: Literal["1", "0"] = "1" z_translation: Literal['1', '0'] = '1'
x_rotation: Literal["1", "0"] = "1" x_rotation: Literal['1', '0'] = '1'
y_rotation: Literal["1", "0"] = "1" y_rotation: Literal['1', '0'] = '1'
z_rotation: Literal["1", "0"] = "1" z_rotation: Literal['1', '0'] = '1'
fluid_pressure: Literal["1", "0"] = "0" fluid_pressure: Literal['1', '0'] = '0'
fast_restraints: Literal[ fast_restraints: Literal['Fix_XYZ', 'Fix_XY', 'Fix_XZ', 'Fix_YZ', 'Pin_XYZ', 'Pin_XY', 'Pin_XZ', 'Pin_YZ'] = 'Fix_XYZ'
"Fix_XYZ", "Fix_XY", "Fix_XZ", "Fix_YZ", "Pin_XYZ", "Pin_XY", "Pin_XZ", "Pin_YZ"
] = "Fix_XYZ"

View file

@ -15,9 +15,10 @@ from pydantic import BaseModel, ConfigDict, Field
class PointRigidDiaphragmMasterNodeSpec(BaseModel): class PointRigidDiaphragmMasterNodeSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Point_Rigid_diaphragm_master_node", 'x-gid-name': 'Point_Rigid_diaphragm_master_node',
"x-book": "Constraints", 'x-book': 'Constraints',
} }
) )
rigid_diaphragm_id: int = 1 rigid_diaphragm_id: int = 1

View file

@ -17,10 +17,11 @@ from pydantic import BaseModel, ConfigDict, Field
class PointRigidDiaphragmSlaveNodesSpec(BaseModel): class PointRigidDiaphragmSlaveNodesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Point_Rigid_diaphragm_slave_nodes", 'x-gid-name': 'Point_Rigid_diaphragm_slave_nodes',
"x-book": "Constraints", 'x-book': 'Constraints',
} }
) )
rigid_diaphragm_id: int = 1 rigid_diaphragm_id: int = 1
rigid_plane: Literal["XY", "YZ", "ZX"] = "XY" rigid_plane: Literal['XY', 'YZ', 'ZX'] = 'XY'

View file

@ -15,9 +15,10 @@ from pydantic import BaseModel, ConfigDict, Field
class PointRigidLinkMasterNodeSpec(BaseModel): class PointRigidLinkMasterNodeSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Point_Rigid_link_master_node", 'x-gid-name': 'Point_Rigid_link_master_node',
"x-book": "Constraints", 'x-book': 'Constraints',
} }
) )
rigid_link_id: int = 1 rigid_link_id: int = 1

View file

@ -17,12 +17,11 @@ from pydantic import BaseModel, ConfigDict, Field
class PointRigidLinkSlaveNodesSpec(BaseModel): class PointRigidLinkSlaveNodesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Point_Rigid_link_slave_nodes", 'x-gid-name': 'Point_Rigid_link_slave_nodes',
"x-book": "Constraints", 'x-book': 'Constraints',
} }
) )
rigid_link_id: int = Field( rigid_link_id: int = Field(1, description='Give a positive integer number for body constraint group.')
1, description="Give a positive integer number for body constraint group." rigid_link_type: Literal['Bar', 'Beam'] = 'Beam'
)
rigid_link_type: Literal["Bar", "Beam"] = "Beam"

View file

@ -17,40 +17,40 @@ from pydantic import BaseModel, ConfigDict, Field
class PointSineGroundMotionSpec(BaseModel): class PointSineGroundMotionSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Point_Sine_Ground_Motion", 'x-gid-name': 'Point_Sine_Ground_Motion',
"x-book": "Loads", 'x-book': 'Loads',
"dependencies": [ 'dependencies': [
{ {
"field": "type", 'field': 'type',
"gid_name": "Type", 'gid_name': 'Type',
"rules": [ 'rules': [
{ {
"trigger": "Acceleration", 'trigger': 'Acceleration',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Acceleration_Amplitude", 'field': 'Acceleration_Amplitude',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Displacement_Amplitude", 'field': 'Displacement_Amplitude',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Displacement", 'trigger': 'Displacement',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Acceleration_Amplitude", 'field': 'Acceleration_Amplitude',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Displacement_Amplitude", 'field': 'Displacement_Amplitude',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
@ -60,10 +60,11 @@ class PointSineGroundMotionSpec(BaseModel):
} }
) )
type: Literal["Acceleration", "Displacement"] = "Displacement" type: Literal['Acceleration', 'Displacement'] = 'Displacement'
ground_motion_direction: Literal["Ux", "Uy", "Uz", "Rx", "Ry", "Rz"] = "Ux" ground_motion_direction: Literal['Ux', 'Uy', 'Uz', 'Rx', 'Ry', 'Rz'] = 'Ux'
acceleration_amplitude: str = "1.0m/s^2" # TODO: unit-aware type acceleration_amplitude: str = '1.0m/s^2' # TODO: unit-aware type
displacement_amplitude: str = "1.0m" # TODO: unit-aware type displacement_amplitude: str = '1.0m' # TODO: unit-aware type
period: str = "0.6sec" # TODO: unit-aware type period: str = '0.6sec' # TODO: unit-aware type
duration: str = "10sec" # TODO: unit-aware type duration: str = '10sec' # TODO: unit-aware type
shift: float = 0.0 shift: float = 0.0

View file

@ -17,160 +17,160 @@ from pydantic import BaseModel, ConfigDict, Field
class PointZerolengthSpec(BaseModel): class PointZerolengthSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Point_ZeroLength", 'x-gid-name': 'Point_ZeroLength',
"x-book": "ZeroLength_Elements", 'x-book': 'ZeroLength_Elements',
"dependencies": [ 'dependencies': [
{ {
"field": "activate_ux", 'field': 'activate_ux',
"gid_name": "Activate_Ux", 'gid_name': 'Activate_Ux',
"rules": [ 'rules': [
{ {
"trigger": "0", 'trigger': '0',
"actions": [ 'actions': [
{ {
"action": "SET", 'action': 'SET',
"field": "Ux_material", 'field': 'Ux_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "1", 'trigger': '1',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Ux_material", 'field': 'Ux_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "activate_uy", 'field': 'activate_uy',
"gid_name": "Activate_Uy", 'gid_name': 'Activate_Uy',
"rules": [ 'rules': [
{ {
"trigger": "0", 'trigger': '0',
"actions": [ 'actions': [
{ {
"action": "SET", 'action': 'SET',
"field": "Uy_material", 'field': 'Uy_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "1", 'trigger': '1',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Uy_material", 'field': 'Uy_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "activate_uz", 'field': 'activate_uz',
"gid_name": "Activate_Uz", 'gid_name': 'Activate_Uz',
"rules": [ 'rules': [
{ {
"trigger": "0", 'trigger': '0',
"actions": [ 'actions': [
{ {
"action": "SET", 'action': 'SET',
"field": "Uz_material", 'field': 'Uz_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "1", 'trigger': '1',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Uz_material", 'field': 'Uz_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "activate_rx", 'field': 'activate_rx',
"gid_name": "Activate_Rx", 'gid_name': 'Activate_Rx',
"rules": [ 'rules': [
{ {
"trigger": "0", 'trigger': '0',
"actions": [ 'actions': [
{ {
"action": "SET", 'action': 'SET',
"field": "Rx_material", 'field': 'Rx_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "1", 'trigger': '1',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Rx_material", 'field': 'Rx_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "activate_ry", 'field': 'activate_ry',
"gid_name": "Activate_Ry", 'gid_name': 'Activate_Ry',
"rules": [ 'rules': [
{ {
"trigger": "0", 'trigger': '0',
"actions": [ 'actions': [
{ {
"action": "SET", 'action': 'SET',
"field": "Ry_material", 'field': 'Ry_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "1", 'trigger': '1',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Ry_material", 'field': 'Ry_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "activate_rz", 'field': 'activate_rz',
"gid_name": "Activate_Rz", 'gid_name': 'Activate_Rz',
"rules": [ 'rules': [
{ {
"trigger": "0", 'trigger': '0',
"actions": [ 'actions': [
{ {
"action": "SET", 'action': 'SET',
"field": "Rz_material", 'field': 'Rz_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "1", 'trigger': '1',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Rz_material", 'field': 'Rz_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
@ -181,15 +181,16 @@ class PointZerolengthSpec(BaseModel):
) )
zerolength_id: int = 1 zerolength_id: int = 1
activate_ux: Literal["0", "1"] = "1" activate_ux: Literal['0', '1'] = '1'
ux_material: str = "Elastic" ux_material: str = 'Elastic'
activate_uy: Literal["0", "1"] = "0" activate_uy: Literal['0', '1'] = '0'
uy_material: str = "Elastic" uy_material: str = 'Elastic'
activate_uz: Literal["0", "1"] = "0" activate_uz: Literal['0', '1'] = '0'
uz_material: str = "Elastic" uz_material: str = 'Elastic'
activate_rx: Literal["0", "1"] = "0" activate_rx: Literal['0', '1'] = '0'
rx_material: str = "Elastic" rx_material: str = 'Elastic'
activate_ry: Literal["0", "1"] = "0" activate_ry: Literal['0', '1'] = '0'
ry_material: str = "Elastic" ry_material: str = 'Elastic'
activate_rz: Literal["0", "1"] = "0" activate_rz: Literal['0', '1'] = '0'
rz_material: str = "Elastic" rz_material: str = 'Elastic'

View file

@ -15,14 +15,15 @@ from pydantic import BaseModel, ConfigDict, Field
class SurfaceDisplacementsSpec(BaseModel): class SurfaceDisplacementsSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Surface_Displacements", 'x-gid-name': 'Surface_Displacements',
"x-book": "Loads", 'x-book': 'Loads',
} }
) )
x_displacement: str = "0.0m" # TODO: unit-aware type x_displacement: str = '0.0m' # TODO: unit-aware type
y_displacement: str = "0.0m" # TODO: unit-aware type y_displacement: str = '0.0m' # TODO: unit-aware type
z_displacement: str = "0.0m" # TODO: unit-aware type z_displacement: str = '0.0m' # TODO: unit-aware type
x_rotation: str = "0.0 rad" # TODO: unit-aware type x_rotation: str = '0.0 rad' # TODO: unit-aware type
y_rotation: str = "0.0 rad" # TODO: unit-aware type y_rotation: str = '0.0 rad' # TODO: unit-aware type
z_rotation: str = "0.0 rad" # TODO: unit-aware type z_rotation: str = '0.0 rad' # TODO: unit-aware type

View file

@ -15,14 +15,15 @@ from pydantic import BaseModel, ConfigDict, Field
class SurfaceForcesSpec(BaseModel): class SurfaceForcesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Surface_Forces", 'x-gid-name': 'Surface_Forces',
"x-book": "Loads", 'x-book': 'Loads',
} }
) )
x_force: str = "0.0 kN" # TODO: unit-aware type x_force: str = '0.0 kN' # TODO: unit-aware type
y_force: str = "0.0 kN" # TODO: unit-aware type y_force: str = '0.0 kN' # TODO: unit-aware type
z_force: str = "0.0 kN" # TODO: unit-aware type z_force: str = '0.0 kN' # TODO: unit-aware type
x_moment: str = "0.0 kNm" # TODO: unit-aware type x_moment: str = '0.0 kNm' # TODO: unit-aware type
y_moment: str = "0.0 kNm" # TODO: unit-aware type y_moment: str = '0.0 kNm' # TODO: unit-aware type
z_moment: str = "0.0 kNm" # TODO: unit-aware type z_moment: str = '0.0 kNm' # TODO: unit-aware type

View file

@ -17,15 +17,16 @@ from pydantic import BaseModel, ConfigDict, Field
class SurfaceMassSpec(BaseModel): class SurfaceMassSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Surface_Mass", 'x-gid-name': 'Surface_Mass',
"x-book": "Mass/Damping", 'x-book': 'Mass/Damping',
} }
) )
mass_dof_values: Literal[":"] = ":" mass_dof_values: Literal[':'] = ':'
x_direction: str = "0.0ton" # TODO: unit-aware type x_direction: str = '0.0ton' # TODO: unit-aware type
y_direction: str = "0.0ton" # TODO: unit-aware type y_direction: str = '0.0ton' # TODO: unit-aware type
z_direction: str = "0.0ton" # TODO: unit-aware type z_direction: str = '0.0ton' # TODO: unit-aware type
x_rotation: str = "0.0ton" # TODO: unit-aware type x_rotation: str = '0.0ton' # TODO: unit-aware type
y_rotation: str = "0.0ton" # TODO: unit-aware type y_rotation: str = '0.0ton' # TODO: unit-aware type
z_rotation: str = "0.0ton" # TODO: unit-aware type z_rotation: str = '0.0ton' # TODO: unit-aware type

View file

@ -15,8 +15,8 @@ from pydantic import BaseModel, ConfigDict, Field
class SurfaceRayleighDampingElementsSpec(BaseModel): class SurfaceRayleighDampingElementsSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Surface_Rayleigh_Damping-Elements", 'x-gid-name': 'Surface_Rayleigh_Damping-Elements',
"x-book": "Mass/Damping", 'x-book': 'Mass/Damping',
} }
) )
@ -25,3 +25,4 @@ class SurfaceRayleighDampingElementsSpec(BaseModel):
betak: float = 0.0 betak: float = 0.0
betakinit: float = 0.0 betakinit: float = 0.0
betakcomm: float = 0.0 betakcomm: float = 0.0

View file

@ -15,8 +15,8 @@ from pydantic import BaseModel, ConfigDict, Field
class SurfaceRayleighDampingNodesSpec(BaseModel): class SurfaceRayleighDampingNodesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Surface_Rayleigh_Damping-Nodes", 'x-gid-name': 'Surface_Rayleigh_Damping-Nodes',
"x-book": "Mass/Damping", 'x-book': 'Mass/Damping',
} }
) )
@ -25,3 +25,4 @@ class SurfaceRayleighDampingNodesSpec(BaseModel):
betak: float = 0.0 betak: float = 0.0
betakinit: float = 0.0 betakinit: float = 0.0
betakcomm: float = 0.0 betakcomm: float = 0.0

View file

@ -17,290 +17,290 @@ from pydantic import BaseModel, ConfigDict, Field
class SurfaceRestraintsSpec(BaseModel): class SurfaceRestraintsSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Surface_Restraints", 'x-gid-name': 'Surface_Restraints',
"x-book": "Restraints", 'x-book': 'Restraints',
"dependencies": [ 'dependencies': [
{ {
"field": "fast_restraints", 'field': 'fast_restraints',
"gid_name": "Fast_restraints", 'gid_name': 'Fast_restraints',
"rules": [ 'rules': [
{ {
"trigger": "Fix_XYZ", 'trigger': 'Fix_XYZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "1", 'target': '1',
}, },
], ],
}, },
{ {
"trigger": "Fix_XY", 'trigger': 'Fix_XY',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Fix_XZ", 'trigger': 'Fix_XZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Fix_YZ", 'trigger': 'Fix_YZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Pin_XYZ", 'trigger': 'Pin_XYZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Pin_XY", 'trigger': 'Pin_XY',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Pin_XZ", 'trigger': 'Pin_XZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
{ {
"trigger": "Pin_YZ", 'trigger': 'Pin_YZ',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Translation", 'field': 'Y-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Translation", 'field': 'Z-Translation',
"target": "1", 'target': '1',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Translation", 'field': 'X-Translation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "X-Rotation", 'field': 'X-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Y-Rotation", 'field': 'Y-Rotation',
"target": "0", 'target': '0',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Z-Rotation", 'field': 'Z-Rotation',
"target": "0", 'target': '0',
}, },
], ],
}, },
@ -310,13 +310,12 @@ class SurfaceRestraintsSpec(BaseModel):
} }
) )
x_translation: Literal["1", "0"] = "1" x_translation: Literal['1', '0'] = '1'
y_translation: Literal["1", "0"] = "1" y_translation: Literal['1', '0'] = '1'
z_translation: Literal["1", "0"] = "1" z_translation: Literal['1', '0'] = '1'
x_rotation: Literal["1", "0"] = "1" x_rotation: Literal['1', '0'] = '1'
y_rotation: Literal["1", "0"] = "1" y_rotation: Literal['1', '0'] = '1'
z_rotation: Literal["1", "0"] = "1" z_rotation: Literal['1', '0'] = '1'
fluid_pressure: Literal["1", "0"] = "0" fluid_pressure: Literal['1', '0'] = '0'
fast_restraints: Literal[ fast_restraints: Literal['Fix_XYZ', 'Fix_XY', 'Fix_XZ', 'Fix_YZ', 'Pin_XYZ', 'Pin_XY', 'Pin_XZ', 'Pin_YZ'] = 'Fix_XYZ'
"Fix_XYZ", "Fix_XY", "Fix_XZ", "Fix_YZ", "Pin_XYZ", "Pin_XY", "Pin_XZ", "Pin_YZ"
] = "Fix_XYZ"

View file

@ -17,15 +17,16 @@ from pydantic import BaseModel, ConfigDict, Field
class VolumeMassSpec(BaseModel): class VolumeMassSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Volume_Mass", 'x-gid-name': 'Volume_Mass',
"x-book": "Mass/Damping", 'x-book': 'Mass/Damping',
} }
) )
mass_dof_values: Literal[":"] = ":" mass_dof_values: Literal[':'] = ':'
x_direction: str = "0.0ton" # TODO: unit-aware type x_direction: str = '0.0ton' # TODO: unit-aware type
y_direction: str = "0.0ton" # TODO: unit-aware type y_direction: str = '0.0ton' # TODO: unit-aware type
z_direction: str = "0.0ton" # TODO: unit-aware type z_direction: str = '0.0ton' # TODO: unit-aware type
x_rotation: str = "0.0ton" # TODO: unit-aware type x_rotation: str = '0.0ton' # TODO: unit-aware type
y_rotation: str = "0.0ton" # TODO: unit-aware type y_rotation: str = '0.0ton' # TODO: unit-aware type
z_rotation: str = "0.0ton" # TODO: unit-aware type z_rotation: str = '0.0ton' # TODO: unit-aware type

View file

@ -15,8 +15,8 @@ from pydantic import BaseModel, ConfigDict, Field
class VolumeRayleighDampingElementsSpec(BaseModel): class VolumeRayleighDampingElementsSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Volume_Rayleigh_Damping-Elements", 'x-gid-name': 'Volume_Rayleigh_Damping-Elements',
"x-book": "Mass/Damping", 'x-book': 'Mass/Damping',
} }
) )
@ -25,3 +25,4 @@ class VolumeRayleighDampingElementsSpec(BaseModel):
betak: float = 0.0 betak: float = 0.0
betakinit: float = 0.0 betakinit: float = 0.0
betakcomm: float = 0.0 betakcomm: float = 0.0

View file

@ -15,8 +15,8 @@ from pydantic import BaseModel, ConfigDict, Field
class VolumeRayleighDampingNodesSpec(BaseModel): class VolumeRayleighDampingNodesSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Volume_Rayleigh_Damping-Nodes", 'x-gid-name': 'Volume_Rayleigh_Damping-Nodes',
"x-book": "Mass/Damping", 'x-book': 'Mass/Damping',
} }
) )
@ -25,3 +25,4 @@ class VolumeRayleighDampingNodesSpec(BaseModel):
betak: float = 0.0 betak: float = 0.0
betakinit: float = 0.0 betakinit: float = 0.0
betakcomm: float = 0.0 betakcomm: float = 0.0

View file

@ -17,160 +17,160 @@ from pydantic import BaseModel, ConfigDict, Field
class ZerolengthSpec(BaseModel): class ZerolengthSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "ZeroLength", 'x-gid-name': 'ZeroLength',
"x-book": "Old_Conditions", 'x-book': 'Old_Conditions',
"dependencies": [ 'dependencies': [
{ {
"field": "activate_ux", 'field': 'activate_ux',
"gid_name": "Activate_Ux", 'gid_name': 'Activate_Ux',
"rules": [ 'rules': [
{ {
"trigger": "0", 'trigger': '0',
"actions": [ 'actions': [
{ {
"action": "SET", 'action': 'SET',
"field": "Ux_material", 'field': 'Ux_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "1", 'trigger': '1',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Ux_material", 'field': 'Ux_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "activate_uy", 'field': 'activate_uy',
"gid_name": "Activate_Uy", 'gid_name': 'Activate_Uy',
"rules": [ 'rules': [
{ {
"trigger": "0", 'trigger': '0',
"actions": [ 'actions': [
{ {
"action": "SET", 'action': 'SET',
"field": "Uy_material", 'field': 'Uy_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "1", 'trigger': '1',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Uy_material", 'field': 'Uy_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "activate_uz", 'field': 'activate_uz',
"gid_name": "Activate_Uz", 'gid_name': 'Activate_Uz',
"rules": [ 'rules': [
{ {
"trigger": "0", 'trigger': '0',
"actions": [ 'actions': [
{ {
"action": "SET", 'action': 'SET',
"field": "Uz_material", 'field': 'Uz_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "1", 'trigger': '1',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Uz_material", 'field': 'Uz_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "activate_rx", 'field': 'activate_rx',
"gid_name": "Activate_Rx", 'gid_name': 'Activate_Rx',
"rules": [ 'rules': [
{ {
"trigger": "0", 'trigger': '0',
"actions": [ 'actions': [
{ {
"action": "SET", 'action': 'SET',
"field": "Rx_material", 'field': 'Rx_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "1", 'trigger': '1',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Rx_material", 'field': 'Rx_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "activate_ry", 'field': 'activate_ry',
"gid_name": "Activate_Ry", 'gid_name': 'Activate_Ry',
"rules": [ 'rules': [
{ {
"trigger": "0", 'trigger': '0',
"actions": [ 'actions': [
{ {
"action": "SET", 'action': 'SET',
"field": "Ry_material", 'field': 'Ry_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "1", 'trigger': '1',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Ry_material", 'field': 'Ry_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "activate_rz", 'field': 'activate_rz',
"gid_name": "Activate_Rz", 'gid_name': 'Activate_Rz',
"rules": [ 'rules': [
{ {
"trigger": "0", 'trigger': '0',
"actions": [ 'actions': [
{ {
"action": "SET", 'action': 'SET',
"field": "Rz_material", 'field': 'Rz_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "1", 'trigger': '1',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Rz_material", 'field': 'Rz_material',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
@ -181,15 +181,16 @@ class ZerolengthSpec(BaseModel):
) )
zerolength_id_number: int = 1 zerolength_id_number: int = 1
activate_ux: Literal["0", "1"] = "1" activate_ux: Literal['0', '1'] = '1'
ux_material: str = "Elastic" ux_material: str = 'Elastic'
activate_uy: Literal["0", "1"] = "0" activate_uy: Literal['0', '1'] = '0'
uy_material: str = "Elastic" uy_material: str = 'Elastic'
activate_uz: Literal["0", "1"] = "0" activate_uz: Literal['0', '1'] = '0'
uz_material: str = "Elastic" uz_material: str = 'Elastic'
activate_rx: Literal["0", "1"] = "0" activate_rx: Literal['0', '1'] = '0'
rx_material: str = "Elastic" rx_material: str = 'Elastic'
activate_ry: Literal["0", "1"] = "0" activate_ry: Literal['0', '1'] = '0'
ry_material: str = "Elastic" ry_material: str = 'Elastic'
activate_rz: Literal["0", "1"] = "0" activate_rz: Literal['0', '1'] = '0'
rz_material: str = "Elastic" rz_material: str = 'Elastic'

View file

@ -17,13 +17,14 @@ from pydantic import BaseModel, ConfigDict, Field
class ContactSpec(BaseModel): class ContactSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Contact", 'x-gid-name': 'Contact',
"x-book": "Multidimensional_(nD)_Materials", 'x-book': 'Multidimensional_(nD)_Materials',
} }
) )
material: Literal["Contact"] = "Contact" material: Literal['Contact'] = 'Contact'
frictional_coefficient: float = 0.1 frictional_coefficient: float = 0.1
stiffness_parameter: str = "1000.0kN/m" # TODO: unit-aware type stiffness_parameter: str = '1000.0kN/m' # TODO: unit-aware type
cohesive_intercept: float = 0.0 cohesive_intercept: float = 0.0
tensile_strength: str = "0.0kN" # TODO: unit-aware type tensile_strength: str = '0.0kN' # TODO: unit-aware type

View file

@ -17,196 +17,196 @@ from pydantic import BaseModel, ConfigDict, Field
class CorotationalTrussSpec(BaseModel): class CorotationalTrussSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Corotational_Truss", 'x-gid-name': 'Corotational_Truss',
"x-book": "Truss_Elements", 'x-book': 'Truss_Elements',
"dependencies": [ 'dependencies': [
{ {
"field": "cross_section", 'field': 'cross_section',
"gid_name": "Cross_section", 'gid_name': 'Cross_section',
"rules": [ 'rules': [
{ {
"trigger": "Rectangular", 'trigger': 'Rectangular',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Height_h", 'field': 'Height_h',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Width_B", 'field': 'Width_B',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Diameter_d", 'field': 'Diameter_d',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Height_hf", 'field': 'Height_hf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_bf", 'field': 'Width_bf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_Bw", 'field': 'Width_Bw',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Area_A", 'field': 'Area_A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Circular", 'trigger': 'Circular',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Height_h", 'field': 'Height_h',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_B", 'field': 'Width_B',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Diameter_d", 'field': 'Diameter_d',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Height_hf", 'field': 'Height_hf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_bf", 'field': 'Width_bf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_Bw", 'field': 'Width_Bw',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Area_A", 'field': 'Area_A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Tee", 'trigger': 'Tee',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Height_h", 'field': 'Height_h',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_B", 'field': 'Width_B',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Diameter_d", 'field': 'Diameter_d',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Height_hf", 'field': 'Height_hf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Width_bf", 'field': 'Width_bf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Width_Bw", 'field': 'Width_Bw',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Area_A", 'field': 'Area_A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "General", 'trigger': 'General',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Height_h", 'field': 'Height_h',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_B", 'field': 'Width_B',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Diameter_d", 'field': 'Diameter_d',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_bf", 'field': 'Width_bf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Height_hf", 'field': 'Height_hf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_Bw", 'field': 'Width_Bw',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Area_A", 'field': 'Area_A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "set_modification_factors", 'field': 'set_modification_factors',
"gid_name": "Set_modification_factors", 'gid_name': 'Set_modification_factors',
"rules": [ 'rules': [
{ {
"trigger": "0", 'trigger': '0',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "mod._A", 'field': 'mod._A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "1", 'trigger': '1',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "mod._A", 'field': 'mod._A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
@ -216,22 +216,21 @@ class CorotationalTrussSpec(BaseModel):
} }
) )
element_type: Literal["CorotationalTruss"] = "CorotationalTruss" element_type: Literal['CorotationalTruss'] = 'CorotationalTruss'
compatible_materials: Literal["_"] = "_" compatible_materials: Literal['_'] = '_'
material: str = Field( material: str = Field('Elastic', description='Choose one existing material to use its parameters.')
"Elastic", description="Choose one existing material to use its parameters." mass_density: str = '0.0ton/m^3' # TODO: unit-aware type
) consider_consistent_mass_matrix: Literal['1', '0'] = '0'
mass_density: str = "0.0ton/m^3" # TODO: unit-aware type include_rayleigh_damping: Literal['1', '0'] = '0'
consider_consistent_mass_matrix: Literal["1", "0"] = "0" weight_density: str = '0.0 kN/m^3' # TODO: unit-aware type
include_rayleigh_damping: Literal["1", "0"] = "0" cross_section: Literal['Rectangular', 'Tee', 'Circular', 'General'] = 'General'
weight_density: str = "0.0 kN/m^3" # TODO: unit-aware type height_h: str = '0.5m' # TODO: unit-aware type
cross_section: Literal["Rectangular", "Tee", "Circular", "General"] = "General" width_b: str = '0.3m' # TODO: unit-aware type
height_h: str = "0.5m" # TODO: unit-aware type diameter_d: str = '0.5m' # TODO: unit-aware type
width_b: str = "0.3m" # TODO: unit-aware type width_bf: str = '0.4m' # TODO: unit-aware type
diameter_d: str = "0.5m" # TODO: unit-aware type height_hf: str = '0.15m' # TODO: unit-aware type
width_bf: str = "0.4m" # TODO: unit-aware type width_bw: str = '0.25m' # TODO: unit-aware type
height_hf: str = "0.15m" # TODO: unit-aware type area_a: str = '1 m^2' # TODO: unit-aware type
width_bw: str = "0.25m" # TODO: unit-aware type set_modification_factors: Literal['0', '1'] = '0'
area_a: str = "1 m^2" # TODO: unit-aware type
set_modification_factors: Literal["0", "1"] = "0"
mod_a: int = 1 mod_a: int = 1

View file

@ -17,22 +17,21 @@ from pydantic import BaseModel, ConfigDict, Field
class Damage2pSpec(BaseModel): class Damage2pSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Damage2p", 'x-gid-name': 'Damage2p',
"x-book": "Multidimensional_(nD)_Materials", 'x-book': 'Multidimensional_(nD)_Materials',
} }
) )
material: Literal["Damage2p"] = "Damage2p" material: Literal['Damage2p'] = 'Damage2p'
concrete_compressive_strength: str = "-20MPa" # TODO: unit-aware type concrete_compressive_strength: str = '-20MPa' # TODO: unit-aware type
calculate_default_values_update_to_apply_cb_1_0: int = 1 calculate_default_values_update_to_apply_cb_1_0: int = 1
young_modulus: str = "21.243GPa" # TODO: unit-aware type young_modulus: str = '21.243GPa' # TODO: unit-aware type
concrete_tensile_strength: str = "2.0MPa" # TODO: unit-aware type concrete_tensile_strength: str = '2.0MPa' # TODO: unit-aware type
poisson_coefficient: float = 0.15 poisson_coefficient: float = 0.15
tension_fracture_energy_density: str = "3.465e-004GPa" # TODO: unit-aware type tension_fracture_energy_density: str = '3.465e-004GPa' # TODO: unit-aware type
comp_fracture_energy_density: str = "1.177e-001GPa" # TODO: unit-aware type comp_fracture_energy_density: str = '1.177e-001GPa' # TODO: unit-aware type
parameter_of_plastic_volume_change: float = 0.20 parameter_of_plastic_volume_change: float = 0.20
linear_hardening_parameter: str = "5.311GPa" # TODO: unit-aware type linear_hardening_parameter: str = '5.311GPa' # TODO: unit-aware type
isotropic_kinematic_hardening_ratio: float = 0.50 isotropic_kinematic_hardening_ratio: float = 0.50
computational_stiffness_matrix: Literal["Computational_tangent", "Damaged_secant_stiffness"] = ( computational_stiffness_matrix: Literal['Computational_tangent', 'Damaged_secant_stiffness'] = 'Computational_tangent'
"Computational_tangent"
)

View file

@ -17,19 +17,18 @@ from pydantic import BaseModel, ConfigDict, Field
class DisplacementBasedBeamColumnSpec(BaseModel): class DisplacementBasedBeamColumnSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Displacement-Based_Beam-Column", 'x-gid-name': 'Displacement-Based_Beam-Column',
"x-book": "Beam-Column_Elements", 'x-book': 'Beam-Column_Elements',
} }
) )
element_type: Literal["dispBeamColumn"] = "dispBeamColumn" element_type: Literal['dispBeamColumn'] = 'dispBeamColumn'
compatible_sections: Literal["_"] = "_" compatible_sections: Literal['_'] = '_'
number_of_integration_points: int = Field( number_of_integration_points: int = Field(3, description='number of integration points along the element')
3, description="number of integration points along the element" the_number_of_integration: Literal['_'] = '_'
) to_increase_analysis_accuracy: Literal['_'] = '_'
the_number_of_integration: Literal["_"] = "_" section: str = 'Fiber'
to_increase_analysis_accuracy: Literal["_"] = "_" geometric_transformation: Literal['Linear', 'P-Delta', 'Corotational'] = 'Linear'
section: str = "Fiber" mass_density: str = '0.0ton/m^3' # TODO: unit-aware type
geometric_transformation: Literal["Linear", "P-Delta", "Corotational"] = "Linear" weight_density: str = '25 kN/m^3' # TODO: unit-aware type
mass_density: str = "0.0ton/m^3" # TODO: unit-aware type
weight_density: str = "25 kN/m^3" # TODO: unit-aware type

View file

@ -23,187 +23,187 @@ class CyclicDataRow(BaseModel):
class ElasticSpec(BaseModel): class ElasticSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Elastic", 'x-gid-name': 'Elastic',
"x-book": "Standard_Uniaxial_Materials", 'x-book': 'Standard_Uniaxial_Materials',
"dependencies": [ 'dependencies': [
{ {
"field": "formulation", 'field': 'formulation',
"gid_name": "Formulation", 'gid_name': 'Formulation',
"rules": [ 'rules': [
{ {
"trigger": "Stress-Strain", 'trigger': 'Stress-Strain',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Material_type", 'field': 'Material_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Stiffness_K", 'field': 'Stiffness_K',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_per_rotation_unit", 'field': 'Moment_per_rotation_unit',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Elastic_modulus_E", 'field': 'Elastic_modulus_E',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_per_rotation_unit", 'field': 'Moment_per_rotation_unit',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Force-Deformation", 'trigger': 'Force-Deformation',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Material_type", 'field': 'Material_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Steel_grade", 'field': 'Steel_grade',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Elastic_modulus_E", 'field': 'Elastic_modulus_E',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Stiffness_K", 'field': 'Stiffness_K',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_per_rotation_unit", 'field': 'Moment_per_rotation_unit',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Moment-Rotation", 'trigger': 'Moment-Rotation',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Material_type", 'field': 'Material_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Steel_grade", 'field': 'Steel_grade',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Elastic_modulus_E", 'field': 'Elastic_modulus_E',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Stiffness_K", 'field': 'Stiffness_K',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Moment_per_rotation_unit", 'field': 'Moment_per_rotation_unit',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "material_type", 'field': 'material_type',
"gid_name": "Material_type", 'gid_name': 'Material_type',
"rules": [ 'rules': [
{ {
"trigger": "Concrete", 'trigger': 'Concrete',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Steel_grade", 'field': 'Steel_grade',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Steel", 'trigger': 'Steel',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Steel_grade", 'field': 'Steel_grade',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Custom", 'trigger': 'Custom',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Steel_grade", 'field': 'Steel_grade',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "analysis_type", 'field': 'analysis_type',
"gid_name": "Analysis_type", 'gid_name': 'Analysis_type',
"rules": [ 'rules': [
{ {
"trigger": "Monotonic", 'trigger': 'Monotonic',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Cyclic", 'trigger': 'Cyclic',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
@ -213,32 +213,16 @@ class ElasticSpec(BaseModel):
} }
) )
material: Literal["Elastic"] = Field("Elastic", description="Elastic uniaxial material object") material: Literal['Elastic'] = Field('Elastic', description='Elastic uniaxial material object')
formulation: Literal["Stress-Strain", "Force-Deformation", "Moment-Rotation"] = "Stress-Strain" formulation: Literal['Stress-Strain', 'Force-Deformation', 'Moment-Rotation'] = 'Stress-Strain'
material_type: Literal["Concrete", "Steel", "Custom"] = "Custom" material_type: Literal['Concrete', 'Steel', 'Custom'] = 'Custom'
concrete_class: Literal[ concrete_class: Literal['C12/15', 'C16/20', 'C20/25', 'C25/30', 'C30/37', 'C35/45', 'C40/50', 'C45/55', 'C50/60', 'C55/67', 'C60/75', 'C70/85', 'C80/95', 'C90/105'] = 'C20/25'
"C12/15", steel_grade: Literal['S235', 'S275', 'S355', 'S450', 'B500'] = 'S235'
"C16/20", elastic_modulus_e: str = Field('30 GPa', description='Young modulus of elasticity E, considering stress-strain diagram') # TODO: unit-aware type
"C20/25", stiffness_k: str = '4000 kN/m' # TODO: unit-aware type
"C25/30", moment_per_rotation_unit: str = '10000 kNm' # TODO: unit-aware type
"C30/37", analysis_type: Literal['Monotonic', 'Cyclic'] = 'Monotonic'
"C35/45",
"C40/50",
"C45/55",
"C50/60",
"C55/67",
"C60/75",
"C70/85",
"C80/95",
"C90/105",
] = "C20/25"
steel_grade: Literal["S235", "S275", "S355", "S450", "B500"] = "S235"
elastic_modulus_e: str = Field(
"30 GPa", description="Young modulus of elasticity E, considering stress-strain diagram"
) # TODO: unit-aware type
stiffness_k: str = "4000 kN/m" # TODO: unit-aware type
moment_per_rotation_unit: str = "10000 kNm" # TODO: unit-aware type
analysis_type: Literal["Monotonic", "Cyclic"] = "Monotonic"
cyclic_data: list[CyclicDataRow] = Field(default_factory=list) cyclic_data: list[CyclicDataRow] = Field(default_factory=list)
field: Literal["_"] = "_" field: Literal['_'] = '_'
set_as_variable: Literal["0", "1"] = "0" set_as_variable: Literal['0', '1'] = '0'

View file

@ -17,286 +17,286 @@ from pydantic import BaseModel, ConfigDict, Field
class ElasticBeamColumnSpec(BaseModel): class ElasticBeamColumnSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Elastic_Beam-Column", 'x-gid-name': 'Elastic_Beam-Column',
"x-book": "Beam-Column_Elements", 'x-book': 'Beam-Column_Elements',
"dependencies": [ 'dependencies': [
{ {
"field": "cross_section", 'field': 'cross_section',
"gid_name": "Cross_section", 'gid_name': 'Cross_section',
"rules": [ 'rules': [
{ {
"trigger": "Rectangular", 'trigger': 'Rectangular',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Height_h", 'field': 'Height_h',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Width_B", 'field': 'Width_B',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Diameter_d", 'field': 'Diameter_d',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Height_hf", 'field': 'Height_hf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_bf", 'field': 'Width_bf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_bw", 'field': 'Width_bw',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Area_A", 'field': 'Area_A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_of_inertia_about_local-y_Iyy", 'field': 'Moment_of_inertia_about_local-y_Iyy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_of_inertia_about_local-z_Izz", 'field': 'Moment_of_inertia_about_local-z_Izz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Torsional_moment_of_inertia_Iyz", 'field': 'Torsional_moment_of_inertia_Iyz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Circular", 'trigger': 'Circular',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Height_h", 'field': 'Height_h',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_B", 'field': 'Width_B',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Diameter_d", 'field': 'Diameter_d',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Height_hf", 'field': 'Height_hf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_bf", 'field': 'Width_bf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_bw", 'field': 'Width_bw',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Area_A", 'field': 'Area_A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_of_inertia_about_local-y_Iyy", 'field': 'Moment_of_inertia_about_local-y_Iyy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_of_inertia_about_local-z_Izz", 'field': 'Moment_of_inertia_about_local-z_Izz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Torsional_moment_of_inertia_Iyz", 'field': 'Torsional_moment_of_inertia_Iyz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Tee", 'trigger': 'Tee',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Height_h", 'field': 'Height_h',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_B", 'field': 'Width_B',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Diameter_d", 'field': 'Diameter_d',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Height_hf", 'field': 'Height_hf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Width_bf", 'field': 'Width_bf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Width_bw", 'field': 'Width_bw',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Area_A", 'field': 'Area_A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_of_inertia_about_local-y_Iyy", 'field': 'Moment_of_inertia_about_local-y_Iyy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_of_inertia_about_local-z_Izz", 'field': 'Moment_of_inertia_about_local-z_Izz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Torsional_moment_of_inertia_Iyz", 'field': 'Torsional_moment_of_inertia_Iyz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "General", 'trigger': 'General',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Height_h", 'field': 'Height_h',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_B", 'field': 'Width_B',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Diameter_d", 'field': 'Diameter_d',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_bf", 'field': 'Width_bf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Height_hf", 'field': 'Height_hf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_bw", 'field': 'Width_bw',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Area_A", 'field': 'Area_A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Moment_of_inertia_about_local-y_Iyy", 'field': 'Moment_of_inertia_about_local-y_Iyy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Moment_of_inertia_about_local-z_Izz", 'field': 'Moment_of_inertia_about_local-z_Izz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Torsional_moment_of_inertia_Iyz", 'field': 'Torsional_moment_of_inertia_Iyz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "set_modification_factors", 'field': 'set_modification_factors',
"gid_name": "Set_modification_factors", 'gid_name': 'Set_modification_factors',
"rules": [ 'rules': [
{ {
"trigger": "1", 'trigger': '1',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "mod._A", 'field': 'mod._A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "mod._Iyy", 'field': 'mod._Iyy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "mod._Izz", 'field': 'mod._Izz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "mod._Iyz", 'field': 'mod._Iyz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "0", 'trigger': '0',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "mod._A", 'field': 'mod._A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "mod._Iyy", 'field': 'mod._Iyy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "mod._Izz", 'field': 'mod._Izz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "mod._Iyz", 'field': 'mod._Iyz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
@ -306,24 +306,25 @@ class ElasticBeamColumnSpec(BaseModel):
} }
) )
element_type: Literal["ElasticBeamColumn"] = "ElasticBeamColumn" element_type: Literal['ElasticBeamColumn'] = 'ElasticBeamColumn'
compatible_materials: Literal["Elastic_Isotropic"] = "Elastic_Isotropic" compatible_materials: Literal['Elastic_Isotropic'] = 'Elastic_Isotropic'
material_mat_multidimensional_nd_materials_user_materials: str = "Elastic_Isotropic" material_mat_multidimensional_nd_materials_user_materials: str = 'Elastic_Isotropic'
cross_section: Literal["Rectangular", "Tee", "Circular", "General"] = "Rectangular" cross_section: Literal['Rectangular', 'Tee', 'Circular', 'General'] = 'Rectangular'
height_h: str = "0.5m" # TODO: unit-aware type height_h: str = '0.5m' # TODO: unit-aware type
width_b: str = "0.3m" # TODO: unit-aware type width_b: str = '0.3m' # TODO: unit-aware type
diameter_d: str = "0.5m" # TODO: unit-aware type diameter_d: str = '0.5m' # TODO: unit-aware type
width_bf: str = "0.4m" # TODO: unit-aware type width_bf: str = '0.4m' # TODO: unit-aware type
height_hf: str = "0.15m" # TODO: unit-aware type height_hf: str = '0.15m' # TODO: unit-aware type
width_bw: str = "0.25m" # TODO: unit-aware type width_bw: str = '0.25m' # TODO: unit-aware type
area_a: str = "1.0 m^2" # TODO: unit-aware type area_a: str = '1.0 m^2' # TODO: unit-aware type
moment_of_inertia_about_local_y_iyy: str = "0.5 m^4" # TODO: unit-aware type moment_of_inertia_about_local_y_iyy: str = '0.5 m^4' # TODO: unit-aware type
moment_of_inertia_about_local_z_izz: str = "0.5 m^4" # TODO: unit-aware type moment_of_inertia_about_local_z_izz: str = '0.5 m^4' # TODO: unit-aware type
torsional_moment_of_inertia_iyz: str = "1.0 m^4" # TODO: unit-aware type torsional_moment_of_inertia_iyz: str = '1.0 m^4' # TODO: unit-aware type
set_modification_factors: Literal["1", "0"] = "0" set_modification_factors: Literal['1', '0'] = '0'
mod_a: int = 1 mod_a: int = 1
mod_iyy: int = 1 mod_iyy: int = 1
mod_izz: int = 1 mod_izz: int = 1
mod_iyz: int = 1 mod_iyz: int = 1
geometric_transformation: Literal["Linear", "P-Delta", "Corotational"] = "Linear" geometric_transformation: Literal['Linear', 'P-Delta', 'Corotational'] = 'Linear'
weight_density: str = "25 kN/m^3" # TODO: unit-aware type weight_density: str = '25 kN/m^3' # TODO: unit-aware type

View file

@ -17,40 +17,40 @@ from pydantic import BaseModel, ConfigDict, Field
class ElasticIsotropicSpec(BaseModel): class ElasticIsotropicSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Elastic_Isotropic", 'x-gid-name': 'Elastic_Isotropic',
"x-book": "Multidimensional_(nD)_Materials", 'x-book': 'Multidimensional_(nD)_Materials',
"dependencies": [ 'dependencies': [
{ {
"field": "material_type", 'field': 'material_type',
"gid_name": "Material_type", 'gid_name': 'Material_type',
"rules": [ 'rules': [
{ {
"trigger": "Concrete", 'trigger': 'Concrete',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Steel", 'trigger': 'Steel',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Custom", 'trigger': 'Custom',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
@ -60,24 +60,10 @@ class ElasticIsotropicSpec(BaseModel):
} }
) )
material: Literal["ElasticIsotropic"] = "ElasticIsotropic" material: Literal['ElasticIsotropic'] = 'ElasticIsotropic'
material_type: Literal["Concrete", "Steel", "Custom"] = "Custom" material_type: Literal['Concrete', 'Steel', 'Custom'] = 'Custom'
concrete_class: Literal[ concrete_class: Literal['C12/15', 'C16/20', 'C20/25', 'C25/30', 'C30/37', 'C35/45', 'C40/50', 'C45/55', 'C50/60', 'C55/67', 'C60/75', 'C70/85', 'C80/95', 'C90/105'] = 'C20/25'
"C12/15", elastic_modulus_e: str = '30GPa' # TODO: unit-aware type
"C16/20",
"C20/25",
"C25/30",
"C30/37",
"C35/45",
"C40/50",
"C45/55",
"C50/60",
"C55/67",
"C60/75",
"C70/85",
"C80/95",
"C90/105",
] = "C20/25"
elastic_modulus_e: str = "30GPa" # TODO: unit-aware type
poisson_s_ratio: float = 0.20 poisson_s_ratio: float = 0.20
mass_density: str = "0.0ton/m^3" # TODO: unit-aware type mass_density: str = '0.0ton/m^3' # TODO: unit-aware type

View file

@ -17,13 +17,14 @@ from pydantic import BaseModel, ConfigDict, Field
class ElasticMembranePlateSpec(BaseModel): class ElasticMembranePlateSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Elastic_Membrane_Plate", 'x-gid-name': 'Elastic_Membrane_Plate',
"x-book": "Section_Force-Deformation", 'x-book': 'Section_Force-Deformation',
} }
) )
section: Literal["ElasticMembranePlate"] = "ElasticMembranePlate" section: Literal['ElasticMembranePlate'] = 'ElasticMembranePlate'
elastic_modulus_e: str = "28GPa" # TODO: unit-aware type elastic_modulus_e: str = '28GPa' # TODO: unit-aware type
poisson_s_ratio: float = 0.2 poisson_s_ratio: float = 0.2
section_depth_h: str = "0.25m" # TODO: unit-aware type section_depth_h: str = '0.25m' # TODO: unit-aware type
mass_density: str = "0.0ton/m^3" # TODO: unit-aware type mass_density: str = '0.0ton/m^3' # TODO: unit-aware type

View file

@ -17,19 +17,20 @@ from pydantic import BaseModel, ConfigDict, Field
class ElasticOrthotropicSpec(BaseModel): class ElasticOrthotropicSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Elastic_Orthotropic", 'x-gid-name': 'Elastic_Orthotropic',
"x-book": "Multidimensional_(nD)_Materials", 'x-book': 'Multidimensional_(nD)_Materials',
} }
) )
material: Literal["ElasticOrthotropic"] = "ElasticOrthotropic" material: Literal['ElasticOrthotropic'] = 'ElasticOrthotropic'
elastic_modulus_ex: str = "30GPa" # TODO: unit-aware type elastic_modulus_ex: str = '30GPa' # TODO: unit-aware type
elastic_modulus_ey: str = "30GPa" # TODO: unit-aware type elastic_modulus_ey: str = '30GPa' # TODO: unit-aware type
elastic_modulus_ez: str = "30GPa" # TODO: unit-aware type elastic_modulus_ez: str = '30GPa' # TODO: unit-aware type
poisson_s_ratio_vxy: float = 0.20 poisson_s_ratio_vxy: float = 0.20
poisson_s_ratio_vyz: float = 0.20 poisson_s_ratio_vyz: float = 0.20
poisson_s_ratio_vzx: float = 0.20 poisson_s_ratio_vzx: float = 0.20
shear_modulus_gxy: str = "11GPa" # TODO: unit-aware type shear_modulus_gxy: str = '11GPa' # TODO: unit-aware type
shear_modulus_gyz: str = "11GPa" # TODO: unit-aware type shear_modulus_gyz: str = '11GPa' # TODO: unit-aware type
shear_modulus_gzx: str = "11GPa" # TODO: unit-aware type shear_modulus_gzx: str = '11GPa' # TODO: unit-aware type
mass_density: str = "0.0ton/m^3" # TODO: unit-aware type mass_density: str = '0.0ton/m^3' # TODO: unit-aware type

View file

@ -23,332 +23,332 @@ class CyclicDataRow(BaseModel):
class ElasticPerfectlyPlasticSpec(BaseModel): class ElasticPerfectlyPlasticSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Elastic_Perfectly_Plastic", 'x-gid-name': 'Elastic_Perfectly_Plastic',
"x-book": "Standard_Uniaxial_Materials", 'x-book': 'Standard_Uniaxial_Materials',
"dependencies": [ 'dependencies': [
{ {
"field": "formulation", 'field': 'formulation',
"gid_name": "Formulation", 'gid_name': 'Formulation',
"rules": [ 'rules': [
{ {
"trigger": "Stress-Strain", 'trigger': 'Stress-Strain',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Material_type", 'field': 'Material_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Stiffness_K", 'field': 'Stiffness_K',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Elastic_modulus_E", 'field': 'Elastic_modulus_E',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Deformation_epsN", 'field': 'Deformation_epsN',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Deformation_epsP", 'field': 'Deformation_epsP',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Initial_strain_eps0", 'field': 'Initial_strain_eps0',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Initial_deformation_eps0", 'field': 'Initial_deformation_eps0',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_per_rotation_unit", 'field': 'Moment_per_rotation_unit',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Rotation_epsP", 'field': 'Rotation_epsP',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Rotation_epsN", 'field': 'Rotation_epsN',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Initial_rotation_eps0", 'field': 'Initial_rotation_eps0',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Force-Deformation", 'trigger': 'Force-Deformation',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Material_type", 'field': 'Material_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Steel_grade", 'field': 'Steel_grade',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Elastic_modulus_E", 'field': 'Elastic_modulus_E',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Stiffness_K", 'field': 'Stiffness_K',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Deformation_epsN", 'field': 'Deformation_epsN',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Deformation_epsP", 'field': 'Deformation_epsP',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strain_epsN", 'field': 'Strain_epsN',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strain_epsP", 'field': 'Strain_epsP',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Initial_strain_eps0", 'field': 'Initial_strain_eps0',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Initial_deformation_eps0", 'field': 'Initial_deformation_eps0',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_per_rotation_unit", 'field': 'Moment_per_rotation_unit',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Rotation_epsP", 'field': 'Rotation_epsP',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Rotation_epsN", 'field': 'Rotation_epsN',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Initial_rotation_eps0", 'field': 'Initial_rotation_eps0',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Moment-Rotation", 'trigger': 'Moment-Rotation',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Material_type", 'field': 'Material_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Steel_grade", 'field': 'Steel_grade',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Elastic_modulus_E", 'field': 'Elastic_modulus_E',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Stiffness_K", 'field': 'Stiffness_K',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Deformation_epsN", 'field': 'Deformation_epsN',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Deformation_epsP", 'field': 'Deformation_epsP',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strain_epsN", 'field': 'Strain_epsN',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strain_epsP", 'field': 'Strain_epsP',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Initial_strain_eps0", 'field': 'Initial_strain_eps0',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Initial_deformation_eps0", 'field': 'Initial_deformation_eps0',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Moment_per_rotation_unit", 'field': 'Moment_per_rotation_unit',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Rotation_epsP", 'field': 'Rotation_epsP',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Rotation_epsN", 'field': 'Rotation_epsN',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Initial_rotation_eps0", 'field': 'Initial_rotation_eps0',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "material_type", 'field': 'material_type',
"gid_name": "Material_type", 'gid_name': 'Material_type',
"rules": [ 'rules': [
{ {
"trigger": "Concrete", 'trigger': 'Concrete',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Steel_grade", 'field': 'Steel_grade',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Steel", 'trigger': 'Steel',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Steel_grade", 'field': 'Steel_grade',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Custom", 'trigger': 'Custom',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Steel_grade", 'field': 'Steel_grade',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "analysis_type", 'field': 'analysis_type',
"gid_name": "Analysis_type", 'gid_name': 'Analysis_type',
"rules": [ 'rules': [
{ {
"trigger": "Monotonic", 'trigger': 'Monotonic',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Cyclic", 'trigger': 'Cyclic',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
@ -358,50 +358,26 @@ class ElasticPerfectlyPlasticSpec(BaseModel):
} }
) )
material: Literal["ElasticPerfectlyPlastic"] = Field( material: Literal['ElasticPerfectlyPlastic'] = Field('ElasticPerfectlyPlastic', description='elastic perfectly-plastic uniaxial material object')
"ElasticPerfectlyPlastic", description="elastic perfectly-plastic uniaxial material object" formulation: Literal['Stress-Strain', 'Force-Deformation', 'Moment-Rotation'] = 'Stress-Strain'
) material_type: Literal['Concrete', 'Steel', 'Custom'] = 'Custom'
formulation: Literal["Stress-Strain", "Force-Deformation", "Moment-Rotation"] = "Stress-Strain" concrete_class: Literal['C12/15', 'C16/20', 'C20/25', 'C25/30', 'C30/37', 'C35/45', 'C40/50', 'C45/55', 'C50/60', 'C55/67', 'C60/75', 'C70/85', 'C80/95', 'C90/105'] = 'C20/25'
material_type: Literal["Concrete", "Steel", "Custom"] = "Custom" strength_type: Literal['Mean', 'Characteristic'] = 'Characteristic'
concrete_class: Literal[ steel_grade: Literal['S235', 'S275', 'S355', 'S450', 'B500'] = 'B500'
"C12/15", elastic_modulus_e: str = Field('20GPa', description='young modulus of elasticity E') # TODO: unit-aware type
"C16/20", stiffness_k: str = '4000 kN/m' # TODO: unit-aware type
"C20/25", moment_per_rotation_unit: str = '10000 kNm' # TODO: unit-aware type
"C25/30", strain_epsp: float = Field(1.10e-004, description='strain or deformation at which material reaches plastic state in tension')
"C30/37", strain_epsn: float = Field(-2.0e-3, description='strain or deformation at which material reaches plastic state in compression')
"C35/45", deformation_epsp: str = '1m' # TODO: unit-aware type
"C40/50", deformation_epsn: str = '-1m' # TODO: unit-aware type
"C45/55", rotation_epsp: str = '0.5 rad' # TODO: unit-aware type
"C50/60", rotation_epsn: str = '-0.5 rad' # TODO: unit-aware type
"C55/67",
"C60/75",
"C70/85",
"C80/95",
"C90/105",
] = "C20/25"
strength_type: Literal["Mean", "Characteristic"] = "Characteristic"
steel_grade: Literal["S235", "S275", "S355", "S450", "B500"] = "B500"
elastic_modulus_e: str = Field(
"20GPa", description="young modulus of elasticity E"
) # TODO: unit-aware type
stiffness_k: str = "4000 kN/m" # TODO: unit-aware type
moment_per_rotation_unit: str = "10000 kNm" # TODO: unit-aware type
strain_epsp: float = Field(
1.10e-004,
description="strain or deformation at which material reaches plastic state in tension",
)
strain_epsn: float = Field(
-2.0e-3,
description="strain or deformation at which material reaches plastic state in compression",
)
deformation_epsp: str = "1m" # TODO: unit-aware type
deformation_epsn: str = "-1m" # TODO: unit-aware type
rotation_epsp: str = "0.5 rad" # TODO: unit-aware type
rotation_epsn: str = "-0.5 rad" # TODO: unit-aware type
initial_strain_eps0: float = 0.0 initial_strain_eps0: float = 0.0
initial_deformation_eps0: str = "0.0m" # TODO: unit-aware type initial_deformation_eps0: str = '0.0m' # TODO: unit-aware type
initial_rotation_eps0: str = "0.0 rad" # TODO: unit-aware type initial_rotation_eps0: str = '0.0 rad' # TODO: unit-aware type
analysis_type: Literal["Monotonic", "Cyclic"] = "Monotonic" analysis_type: Literal['Monotonic', 'Cyclic'] = 'Monotonic'
cyclic_data: list[CyclicDataRow] = Field(default_factory=list) cyclic_data: list[CyclicDataRow] = Field(default_factory=list)
field: Literal["_"] = "_" field: Literal['_'] = '_'
set_as_variable: Literal["0", "1"] = "0" set_as_variable: Literal['0', '1'] = '0'

View file

@ -23,307 +23,307 @@ class CyclicDataRow(BaseModel):
class ElasticPerfectlyPlasticWithGapSpec(BaseModel): class ElasticPerfectlyPlasticWithGapSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Elastic_Perfectly_Plastic_with_Gap", 'x-gid-name': 'Elastic_Perfectly_Plastic_with_Gap',
"x-book": "Standard_Uniaxial_Materials", 'x-book': 'Standard_Uniaxial_Materials',
"dependencies": [ 'dependencies': [
{ {
"field": "formulation", 'field': 'formulation',
"gid_name": "Formulation", 'gid_name': 'Formulation',
"rules": [ 'rules': [
{ {
"trigger": "Stress-Strain", 'trigger': 'Stress-Strain',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Elastic_modulus_E", 'field': 'Elastic_modulus_E',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Yield_Stress_Fy", 'field': 'Yield_Stress_Fy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Material_type", 'field': 'Material_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strain_gap", 'field': 'Strain_gap',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Deformation_gap", 'field': 'Deformation_gap',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Stiffness_K", 'field': 'Stiffness_K',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Force_Fy", 'field': 'Force_Fy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_per_rotation_unit", 'field': 'Moment_per_rotation_unit',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_My", 'field': 'Moment_My',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Rotation_gap", 'field': 'Rotation_gap',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Force-Deformation", 'trigger': 'Force-Deformation',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Elastic_modulus_E", 'field': 'Elastic_modulus_E',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Steel_grade", 'field': 'Steel_grade',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strain_gap", 'field': 'Strain_gap',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Yield_Stress_Fy", 'field': 'Yield_Stress_Fy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Material_type", 'field': 'Material_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Stiffness_K", 'field': 'Stiffness_K',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Force_Fy", 'field': 'Force_Fy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Deformation_gap", 'field': 'Deformation_gap',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_per_rotation_unit", 'field': 'Moment_per_rotation_unit',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_My", 'field': 'Moment_My',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Rotation_gap", 'field': 'Rotation_gap',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Moment-Rotation", 'trigger': 'Moment-Rotation',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Elastic_modulus_E", 'field': 'Elastic_modulus_E',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Steel_grade", 'field': 'Steel_grade',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strain_gap", 'field': 'Strain_gap',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Yield_Stress_Fy", 'field': 'Yield_Stress_Fy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Material_type", 'field': 'Material_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Stiffness_K", 'field': 'Stiffness_K',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Force_Fy", 'field': 'Force_Fy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Deformation_gap", 'field': 'Deformation_gap',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Moment_per_rotation_unit", 'field': 'Moment_per_rotation_unit',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Moment_My", 'field': 'Moment_My',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Rotation_gap", 'field': 'Rotation_gap',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "material_type", 'field': 'material_type',
"gid_name": "Material_type", 'gid_name': 'Material_type',
"rules": [ 'rules': [
{ {
"trigger": "Concrete", 'trigger': 'Concrete',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Steel_grade", 'field': 'Steel_grade',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Steel", 'trigger': 'Steel',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Steel_grade", 'field': 'Steel_grade',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Yield_Stress_Fy", 'field': 'Yield_Stress_Fy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Custom", 'trigger': 'Custom',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Concrete_class", 'field': 'Concrete_class',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Steel_grade", 'field': 'Steel_grade',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Yield_Stress_Fy", 'field': 'Yield_Stress_Fy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Strength_type", 'field': 'Strength_type',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "analysis_type", 'field': 'analysis_type',
"gid_name": "Analysis_type", 'gid_name': 'Analysis_type',
"rules": [ 'rules': [
{ {
"trigger": "Monotonic", 'trigger': 'Monotonic',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Cyclic", 'trigger': 'Cyclic',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Cyclic_data", 'field': 'Cyclic_data',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
@ -333,45 +333,23 @@ class ElasticPerfectlyPlasticWithGapSpec(BaseModel):
} }
) )
material: Literal["ElasticPerfectlyPlasticwithGap"] = Field( material: Literal['ElasticPerfectlyPlasticwithGap'] = Field('ElasticPerfectlyPlasticwithGap', description='elastic perfectly-plastic gap uniaxial material object')
"ElasticPerfectlyPlasticwithGap", formulation: Literal['Stress-Strain', 'Force-Deformation', 'Moment-Rotation'] = 'Stress-Strain'
description="elastic perfectly-plastic gap uniaxial material object", material_type: Literal['Concrete', 'Steel', 'Custom'] = 'Custom'
) concrete_class: Literal['C12/15', 'C16/20', 'C20/25', 'C25/30', 'C30/37', 'C35/45', 'C40/50', 'C45/55', 'C50/60', 'C55/67', 'C60/75', 'C70/85', 'C80/95', 'C90/105'] = 'C20/25'
formulation: Literal["Stress-Strain", "Force-Deformation", "Moment-Rotation"] = "Stress-Strain" strength_type: Literal['Mean', 'Characteristic'] = 'Characteristic'
material_type: Literal["Concrete", "Steel", "Custom"] = "Custom" steel_grade: Literal['S235', 'S275', 'S355', 'S450', 'B500'] = 'B500'
concrete_class: Literal[ elastic_modulus_e: str = Field('20GPa', description='young modulus of elasticity E') # TODO: unit-aware type
"C12/15", stiffness_k: str = '4000 kN/m' # TODO: unit-aware type
"C16/20", moment_per_rotation_unit: str = '10000 kNm' # TODO: unit-aware type
"C20/25", yield_stress_fy: str = '-20MPa' # TODO: unit-aware type
"C25/30", force_fy: str = Field('1000 kN', description='Yield stress at which material reaches the plastic plate. Negative value for compression.') # TODO: unit-aware type
"C30/37", moment_my: str = '150 kNm' # TODO: unit-aware type
"C35/45",
"C40/50",
"C45/55",
"C50/60",
"C55/67",
"C60/75",
"C70/85",
"C80/95",
"C90/105",
] = "C20/25"
strength_type: Literal["Mean", "Characteristic"] = "Characteristic"
steel_grade: Literal["S235", "S275", "S355", "S450", "B500"] = "B500"
elastic_modulus_e: str = Field(
"20GPa", description="young modulus of elasticity E"
) # TODO: unit-aware type
stiffness_k: str = "4000 kN/m" # TODO: unit-aware type
moment_per_rotation_unit: str = "10000 kNm" # TODO: unit-aware type
yield_stress_fy: str = "-20MPa" # TODO: unit-aware type
force_fy: str = Field(
"1000 kN",
description="Yield stress at which material reaches the plastic plate. Negative value for compression.",
) # TODO: unit-aware type
moment_my: str = "150 kNm" # TODO: unit-aware type
strain_gap: float = 0.0 strain_gap: float = 0.0
deformation_gap: str = "0.0m" # TODO: unit-aware type deformation_gap: str = '0.0m' # TODO: unit-aware type
rotation_gap: str = "0.0 rad" # TODO: unit-aware type rotation_gap: str = '0.0 rad' # TODO: unit-aware type
analysis_type: Literal["Monotonic", "Cyclic"] = "Monotonic" analysis_type: Literal['Monotonic', 'Cyclic'] = 'Monotonic'
cyclic_data: list[CyclicDataRow] = Field(default_factory=list) cyclic_data: list[CyclicDataRow] = Field(default_factory=list)
field: Literal["_"] = "_" field: Literal['_'] = '_'
set_as_variable: Literal["0", "1"] = "0" set_as_variable: Literal['0', '1'] = '0'

View file

@ -17,332 +17,332 @@ from pydantic import BaseModel, ConfigDict, Field
class ElasticSectionSpec(BaseModel): class ElasticSectionSpec(BaseModel):
model_config = ConfigDict( model_config = ConfigDict(
json_schema_extra={ json_schema_extra={
"x-gid-name": "Elastic_Section", 'x-gid-name': 'Elastic_Section',
"x-book": "Section_Force-Deformation", 'x-book': 'Section_Force-Deformation',
"dependencies": [ 'dependencies': [
{ {
"field": "calculate_shear_modulus_update_to_apply_cb_0_1", 'field': 'calculate_shear_modulus_update_to_apply_cb_0_1',
"gid_name": "Calculate_Shear_modulus_(update_to_apply)#CB#(0,1)", 'gid_name': 'Calculate_Shear_modulus_(update_to_apply)#CB#(0,1)',
"rules": [ 'rules': [
{ {
"trigger": "0", 'trigger': '0',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Poisson's_ratio", 'field': "Poisson's_ratio",
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "1", 'trigger': '1',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Poisson's_ratio", 'field': "Poisson's_ratio",
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "cross_section", 'field': 'cross_section',
"gid_name": "Cross_section", 'gid_name': 'Cross_section',
"rules": [ 'rules': [
{ {
"trigger": "Rectangular", 'trigger': 'Rectangular',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Height_h", 'field': 'Height_h',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Width_B", 'field': 'Width_B',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Diameter_d", 'field': 'Diameter_d',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Height_hf", 'field': 'Height_hf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_bf", 'field': 'Width_bf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_bw", 'field': 'Width_bw',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Area_A", 'field': 'Area_A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_of_inertia_about_local-y_Iyy", 'field': 'Moment_of_inertia_about_local-y_Iyy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_of_inertia_about_local-z_Izz", 'field': 'Moment_of_inertia_about_local-z_Izz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Torsional_moment_of_inertia_Iyz", 'field': 'Torsional_moment_of_inertia_Iyz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Circular", 'trigger': 'Circular',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Height_h", 'field': 'Height_h',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_B", 'field': 'Width_B',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Diameter_d", 'field': 'Diameter_d',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Height_hf", 'field': 'Height_hf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_bf", 'field': 'Width_bf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_bw", 'field': 'Width_bw',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Area_A", 'field': 'Area_A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_of_inertia_about_local-y_Iyy", 'field': 'Moment_of_inertia_about_local-y_Iyy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_of_inertia_about_local-z_Izz", 'field': 'Moment_of_inertia_about_local-z_Izz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Torsional_moment_of_inertia_Iyz", 'field': 'Torsional_moment_of_inertia_Iyz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "Tee", 'trigger': 'Tee',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Height_h", 'field': 'Height_h',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_B", 'field': 'Width_B',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Diameter_d", 'field': 'Diameter_d',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Height_hf", 'field': 'Height_hf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Width_bf", 'field': 'Width_bf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Width_bw", 'field': 'Width_bw',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Area_A", 'field': 'Area_A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_of_inertia_about_local-y_Iyy", 'field': 'Moment_of_inertia_about_local-y_Iyy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Moment_of_inertia_about_local-z_Izz", 'field': 'Moment_of_inertia_about_local-z_Izz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Torsional_moment_of_inertia_Iyz", 'field': 'Torsional_moment_of_inertia_Iyz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "General", 'trigger': 'General',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Height_h", 'field': 'Height_h',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_B", 'field': 'Width_B',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Diameter_d", 'field': 'Diameter_d',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_bf", 'field': 'Width_bf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Height_hf", 'field': 'Height_hf',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "Width_bw", 'field': 'Width_bw',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Area_A", 'field': 'Area_A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Moment_of_inertia_about_local-y_Iyy", 'field': 'Moment_of_inertia_about_local-y_Iyy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Moment_of_inertia_about_local-z_Izz", 'field': 'Moment_of_inertia_about_local-z_Izz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "Torsional_moment_of_inertia_Iyz", 'field': 'Torsional_moment_of_inertia_Iyz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
], ],
}, },
{ {
"field": "set_modification_factors", 'field': 'set_modification_factors',
"gid_name": "Set_modification_factors", 'gid_name': 'Set_modification_factors',
"rules": [ 'rules': [
{ {
"trigger": "1", 'trigger': '1',
"actions": [ 'actions': [
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "mod._A", 'field': 'mod._A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "mod._Iyy", 'field': 'mod._Iyy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "mod._Izz", 'field': 'mod._Izz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "mod._Iyz", 'field': 'mod._Iyz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "mod._Sy", 'field': 'mod._Sy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "RESTORE", 'action': 'RESTORE',
"field": "mod._Sz", 'field': 'mod._Sz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
{ {
"trigger": "0", 'trigger': '0',
"actions": [ 'actions': [
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "mod._A", 'field': 'mod._A',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "mod._Iyy", 'field': 'mod._Iyy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "mod._Izz", 'field': 'mod._Izz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "mod._Iyz", 'field': 'mod._Iyz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "mod._Sy", 'field': 'mod._Sy',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
{ {
"action": "HIDE", 'action': 'HIDE',
"field": "mod._Sz", 'field': 'mod._Sz',
"target": "#CURRENT#", 'target': '#CURRENT#',
}, },
], ],
}, },
@ -352,25 +352,26 @@ class ElasticSectionSpec(BaseModel):
} }
) )
section: Literal["ElasticSection"] = "ElasticSection" section: Literal['ElasticSection'] = 'ElasticSection'
elastic_modulus_e: str = "28 GPa" # TODO: unit-aware type elastic_modulus_e: str = '28 GPa' # TODO: unit-aware type
calculate_shear_modulus_update_to_apply_cb_0_1: int = 0 calculate_shear_modulus_update_to_apply_cb_0_1: int = 0
shear_modulus_g: str = "11.66666667 GPa" # TODO: unit-aware type shear_modulus_g: str = '11.66666667 GPa' # TODO: unit-aware type
cross_section: Literal["Rectangular", "Tee", "Circular", "General"] = "Rectangular" cross_section: Literal['Rectangular', 'Tee', 'Circular', 'General'] = 'Rectangular'
height_h: str = "0.5m" # TODO: unit-aware type height_h: str = '0.5m' # TODO: unit-aware type
width_b: str = "0.3m" # TODO: unit-aware type width_b: str = '0.3m' # TODO: unit-aware type
diameter_d: str = "0.5m" # TODO: unit-aware type diameter_d: str = '0.5m' # TODO: unit-aware type
width_bf: str = "0.4m" # TODO: unit-aware type width_bf: str = '0.4m' # TODO: unit-aware type
height_hf: str = "0.15m" # TODO: unit-aware type height_hf: str = '0.15m' # TODO: unit-aware type
width_bw: str = "0.25m" # TODO: unit-aware type width_bw: str = '0.25m' # TODO: unit-aware type
area_a: str = "1.0 m^2" # TODO: unit-aware type area_a: str = '1.0 m^2' # TODO: unit-aware type
moment_of_inertia_about_local_y_iyy: str = "0.5 m^4" # TODO: unit-aware type moment_of_inertia_about_local_y_iyy: str = '0.5 m^4' # TODO: unit-aware type
moment_of_inertia_about_local_z_izz: str = "0.5 m^4" # TODO: unit-aware type moment_of_inertia_about_local_z_izz: str = '0.5 m^4' # TODO: unit-aware type
torsional_moment_of_inertia_iyz: str = "1.0 m^4" # TODO: unit-aware type torsional_moment_of_inertia_iyz: str = '1.0 m^4' # TODO: unit-aware type
set_modification_factors: Literal["1", "0"] = "0" set_modification_factors: Literal['1', '0'] = '0'
mod_a: int = 1 mod_a: int = 1
mod_sy: int = 1 mod_sy: int = 1
mod_sz: int = 1 mod_sz: int = 1
mod_iyy: int = 1 mod_iyy: int = 1
mod_izz: int = 1 mod_izz: int = 1
mod_iyz: int = 1 mod_iyz: int = 1

Some files were not shown because too many files have changed in this diff Show more