Compare commits

..
317 changed files with 8921 additions and 16888 deletions

View file

@ -14,25 +14,12 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: "3.11"
# Pinned to the pre-commit revisions so CI and local hooks agree.
- run: pip install ruff==0.4.4
- run: pip install ruff mypy
- run: ruff check src tests
- run: ruff format --check src tests
type:
runs-on: ubuntu-latest
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]
test:
needs: lint
strategy:
fail-fast: false
matrix:
@ -44,38 +31,18 @@ jobs:
- uses: actions/setup-python@v5
with:
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
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y libegl1 libxkbcommon-x11-0 libxcb-icccm4 \
libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 \
libxcb-shape0 libxcb-sync1 libxcb-xfixes0 libxcb-xinerama0 \
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: 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/
/Ex*.csv
/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
```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)
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.**
- `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/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.
- 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).
- 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.
## 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
Thanks for helping with OTKO — a SAP2000-style desktop GUI for
OpenSeesPy. Early-stage project: the bar is architecture cleanliness, not
feature count. If your change breaks a layering rule below, it won't
merge — no matter how useful the feature.
Early-stage project. The bar is architecture cleanliness, not feature
count. If your change breaks a layering rule below, it won't merge —
no matter how useful the feature.
## Dev setup
```bash
python -m venv .venv
source .venv/bin/activate # Linux / macOS
# .venv\Scripts\activate # Windows
pip install -e ".[gui,dev]"
source .venv/bin/activate
pip install -e ".[dev]"
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
Run the verify commands in this order and make sure they are all clean:
```bash
ruff check src tests
ruff format src tests # line-length 100, E501 ignored
ruff format src tests
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)
OTKO uses a strict one-way **MVVM + service** architecture. Dependencies
flow outward-in only:
```
views → viewmodels → services → core
```
`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.
1. `core/` may not import Qt or `openseespy`. Period.
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.
5. New domain entities go through Pydantic validation.
6. Long-running operations (>50 ms) run off the GUI thread.
## Commit style
Conventional Commits — `feat:`, `fix:`, `refactor:`, `docs:`, `test:`,
`chore:`, `ci:`. Keep each commit focused; a `feat:` commit should add a
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.
`chore:`, `ci:`.

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.

222
README.md
View file

@ -1,11 +1,13 @@
<p align="center">
<img src="docs/logo.svg" alt="OTKO" width="640">
<img src="docs/logo.svg" alt="OTKO" width="600">
</p>
<h3 align="center">Draw the model. Click run. Read the diagrams.</h3>
<p align="center">
A SAP2000-style desktop GUI for
<a href="https://openseespydoc.readthedocs.io/">OpenSeesPy</a>.
Draw the model, click run, look at the diagrams.
<a href="LICENSE"><img alt="License: AGPL-3.0" src="https://img.shields.io/badge/license-AGPL--3.0-blue"></a>
<img alt="Python 3.10+" src="https://img.shields.io/badge/python-3.10%2B-blue">
<img alt="Status: pre-alpha" src="https://img.shields.io/badge/status-pre--alpha-orange">
</p>
<p align="center">
@ -14,84 +16,47 @@
---
![OTKO main window](docs/screenshots/main_window.png)
<table align="center">
<tr>
<td><img src="docs/screenshots/menu.png" alt="SAP2000-style cascading menus"></td>
<td><img src="docs/screenshots/toolbar.png" alt="Compact dark toolbar"></td>
<td><img src="docs/screenshots/grid.png" alt="Parametric grid generation"></td>
</tr>
<tr>
<td align="center"><sub>SAP2000-style menus</sub></td>
<td align="center"><sub>Compact dark toolbar</sub></td>
<td align="center"><sub>Parametric grid wizard</sub></td>
</tr>
</table>
## Why
## What is OTKO?
OpenSees does nonlinear FEM well. Its user interface is a script.
OTKO puts a visual front-end on it:
- Draw nodes, frames, supports, and loads on a snapped grid.
- Assign materials, sections, and load patterns through dialogs.
- Run static, modal, pushover, and time-history analyses with progress
and cancel.
- Look at the results — deformed shape, mode shapes, force
diagrams, pushover curves, time-history plots, hysteresis loops.
- Save the model as one `.osmodel` JSON file. Diffs cleanly in Git,
builds cleanly from Python.
OTKO puts a visual front-end on top of it: draw nodes, frames,
supports, and loads on a snapped grid; assign materials, sections,
and load patterns through dialogs; run the analysis with progress
and cancel; then read the results — deformed shapes, mode shapes,
force diagrams, pushover curves, hysteresis loops.
Underneath, the `core` Pydantic model works fine from a script or
notebook. The GUI is a front-end, not the whole product.
notebook without any GUI. The GUI is a front-end, not the whole
product.
## What works today
## Highlights
- **Modeling** — grids, nodes, frames (elastic + force-based), trusses,
quads, zero-length sections, restraints, equalDOF constraints,
distributed loads, ground motions (`PathTimeSeries` /
`UniformExcitation`).
- **Materials and sections** — `Steel01`, `Steel02`, `Concrete01`,
`Concrete02`, `ElasticPP`, `Hysteretic`, fiber sections (rectangular /
circular patches + rebar layers), `SectionAggregator`,
`BeamWithHinges`.
- **Analyses** — static (load- or displacement-controlled), modal,
displacement-controlled pushover, transient time-history with
mode-1 Rayleigh damping. Chained workflows: gravity preload →
`loadConst -time 0.0` → pushover or transient.
- **Post-processing** — deformed shape (with scale slider), animated
mode shapes, axial / shear / moment diagrams, pushover curves
(in display units), time-history plots, hysteresis loops,
response-spectrum SRSS / CQC, snapshot + video export.
- **Persistence** — one JSON `.osmodel` per project, Pydantic-validated,
round-trips clean.
- **Examples** — 20+ verified examples, including OpenSees
Wiki Examples 1–4 and a fiber-section RC frame pushover.
See [`examples/README.md`](examples/README.md).
| Area | What you get |
| ---- | ------------ |
| **Modeling** | Grid wizards, nodes, frames (elastic + force-based), trusses, quads, zero-length sections, restraints, equalDOF constraints, distributed loads, ground motions (`PathTimeSeries` / `UniformExcitation`). |
| **Materials &amp; sections** | `Steel01`, `Steel02`, `Concrete01`, `Concrete02`, `ElasticPP`, `Hysteretic`, fiber sections (rectangular / circular patches + rebar), `SectionAggregator`, `BeamWithHinges`. |
| **Analysis** | Static (load- or displacement-controlled), modal, pushover, transient time-history with mode-1 Rayleigh damping. Chained workflows: gravity preload → `loadConst -time 0.0` → pushover or transient. |
| **Post-processing** | Deformed shape with scale slider, animated mode shapes, axial / shear / moment diagrams, pushover curves, time-history plots, hysteresis loops, response-spectrum SRSS / CQC, snapshot + video export. |
| **Persistence** | One Pydantic-validated `.osmodel` JSON per project — diffs cleanly in Git, builds cleanly from Python. Analysis output in HDF5 (`*.osresults.h5`). |
## Tech stack
20+ verified examples ship with the repo, including OpenSees Wiki
Examples 1–4 and a fiber-section RC frame pushover. See
[`examples/README.md`](examples/README.md).
| Layer | Library |
| ------------ | ------------------------------------ |
| GUI | PySide6 (Qt 6) |
| 3D viewport | PyVista + pyvistaqt (VTK) |
| 2D plots | pyqtgraph |
| Solver | OpenSeesPy 3.8.0.0 |
| Numerics | NumPy |
| Storage | Pydantic v2 (model), h5py (results) |
| Tests | pytest, pytest-qt |
| Lint / type | ruff, mypy |
## Architecture
Strict MVVM + service layer. `core` is pure Python — no Qt,
no OpenSeesPy imports — and unit-tests in isolation.
```
views (Qt) → viewmodels → services (OpenSeesRunner, Persistence) → core (model)
```
Long version in [`docs/architecture.md`](docs/architecture.md),
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)
**Desktop GUI** (Qt, PyVista, pyqtgraph, imageio):
## Quick start
```bash
git clone ssh://git@smill-home.ddns.net/smill/otko.git
@ -101,26 +66,9 @@ python -m venv .venv
.venv\Scripts\activate # Windows
source .venv/bin/activate # Linux / macOS
pip install -e ".[gui,dev]"
```
pip install -e ".[gui,dev]" # desktop: Qt + PyVista + dev tools
# pip install -e . # headless: core + services only
**Headless** (core + services only, no Qt):
```bash
pip install -e .
```
That pulls pydantic, numpy, h5py, openseespy and nothing else.
Use it for scripts, notebooks, and web backends that reuse
`otko.core` or `otko.services` without the GUI.
Python 3.10+. On Windows use **3.12+** — `openseespywin==3.8.0.0`
has no 3.11 wheel (`Requires-Python >=3.12`). Both pins already
live in `pyproject.toml`.
## Quick start
```bash
python -m otko
```
@ -128,15 +76,58 @@ Then:
1. **File → Open** → `examples/cantilever.osmodel`.
2. **Analyze → Cases** → run `Tip-Load`.
3. **Display → Show Force Diagram** → **M3**: linear moment,
50 kN·m at the fixed end. **V2**: constant -10 kN.
4. **Display → Show Deformed Shape** → cantilever curve, as advertised.
3. **Display → Show Force Diagram** → **M3**: 50 kN·m at the fixed end.
**V2**: constant −10 kN.
4. **Display → Show Deformed Shape** → the cantilever curve.
Nonlinear version: open `examples/portal_pushover.osmodel`,
run `Push-X`, **Display → Show Pushover Curve**. Elastic ramp,
then a yield plateau as the base hinges form.
Nonlinear version: open `examples/portal_pushover.osmodel`, run
`Push-X`, **Display → Show Pushover Curve** — elastic ramp, then a
yield plateau as the base hinges form.
## Run the test suite
Python 3.10+. On Windows use **3.12+** — `openseespywin==3.8.0.0`
has no 3.11 wheel (`Requires-Python >=3.12`). Both pins already
live in `pyproject.toml`.
## Architecture
Strict MVVM + service layer, one direction only:
```
views (Qt) → viewmodels → services (OpenSeesRunner, Persistence) → core (model)
```
`core` is pure Python — no Qt, no OpenSeesPy imports — and unit-tests
in isolation. PySide6 + PyVista on the view, pyqtgraph for 2D plots,
Pydantic v2 for the model, h5py for results. Long version, including
the OpenSeesPy command order the runner emits, in
[`docs/architecture.md`](docs/architecture.md).
## Roadmap
[`docs/roadmap.md`](docs/roadmap.md) has the phase-by-phase plan.
Phases 0–7 (modeling, analysis, post-processing) are mostly done.
Phase 8 — isolators, ground-motion library, IDA, fiber-section
editor polish — is where the open work is.
## Contributing
Collaborators welcome — most useful to people who already work with
OpenSees and want a shorter path from idea to model:
- **Structural / earthquake engineers** who can tell us when a feature
is almost right but not quite.
- **Researchers** running pushover, IDA, or response-spectrum studies
against hand-built scripts.
- **Python / Qt developers** into scientific desktop apps, VTK
rendering, or Pydantic schema design.
- **Students** learning FEM and GUI architecture — the examples and
tests are meant to read as documentation.
- **UX / icon designers** willing to argue about dialogs and toolbars.
Bug reports and reproducible test cases count as contributions. Setup
and the rules enforced in review: [`CONTRIBUTING.md`](CONTRIBUTING.md).
Test suite:
```bash
pytest tests/unit # pure logic, milliseconds
@ -147,39 +138,10 @@ pytest tests/integration # real OpenSeesPy runs on bundled examples
CI runs lint + the non-`slow` subset on Linux / macOS / Windows
× Python 3.10 / 3.11 / 3.12.
## Roadmap
[`docs/roadmap.md`](docs/roadmap.md) has the phase-by-phase plan.
Phases 0–7 (modeling, analysis, post-processing) are mostly done.
Phase 8 (isolators, ground-motion library, IDA, fiber-section
editor polish) is where the open work is.
## Collaborators wanted
Most useful to people who already work with OpenSees and want a
shorter path from idea to model — and would rather build it together
than alone. Open an issue or say hi if you are:
- A **structural / earthquake engineer** who knows OpenSees Tcl
or OpenSeesPy and can tell us when a feature is almost right
but not quite.
- A **researcher** running pushover, IDA, or response-spectrum studies
who can check the GUI against hand-built scripts.
- A **Python / Qt developer** into scientific desktop apps,
VTK rendering, or Pydantic schema design.
- A **student** learning FEM and GUI architecture at the same time —
the examples and tests are meant to read as documentation.
- A **UX / icon designer** willing to argue about dialogs, toolbar
icons, and visual language.
Bug reports and reproducible test cases count as contributions.
See [`CONTRIBUTING.md`](CONTRIBUTING.md) for setup and the rules
enforced in review.
## License
OTKO is **GNU Affero General Public License v3.0**
([`LICENSE`](LICENSE)). Read the license itself, not just this:
([`LICENSE`](LICENSE)). In short:
- Research, education, personal projects: fine, keep the copyright
notice.
@ -190,6 +152,6 @@ OTKO is **GNU Affero General Public License v3.0**
modifications under AGPL-3.0.
Commercial forks stay open. If you need a different arrangement
(e.g. closed-source commercial license), open an issue.
(e.g. a closed-source commercial license), open an issue.
Copyright © 2026 Ozan and contributors.

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

@ -5,41 +5,40 @@
<defs>
<linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#1F2A3D"/>
<stop offset="100%" stop-color="#0F1620"/>
<stop offset="0%" stop-color="#1B2434"/>
<stop offset="100%" stop-color="#0C1119"/>
</linearGradient>
<linearGradient id="frameStroke" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#9DC8FF"/>
<stop offset="0%" stop-color="#A5D1FF"/>
<stop offset="100%" stop-color="#4F92E8"/>
</linearGradient>
<linearGradient id="deformed" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#4F92E8" stop-opacity="0.0"/>
<stop offset="50%" stop-color="#4F92E8" stop-opacity="0.6"/>
<stop offset="100%" stop-color="#4F92E8" stop-opacity="0.0"/>
</linearGradient>
</defs>
<!-- Background panel — keeps contrast consistent on light and dark GitHub themes -->
<rect x="0" y="0" width="720" height="180" rx="14" fill="url(#bg)"/>
<!-- Background panel — consistent contrast on light and dark themes -->
<rect x="0" y="0" width="720" height="180" rx="16" fill="url(#bg)"/>
<!-- Mark: portal frame with a deformed-shape ghost -->
<g transform="translate(40, 36)" stroke-linecap="round" stroke-linejoin="round" fill="none">
<path d="M 6 100 C 22 100, 22 12, 60 12 L 60 12 C 98 12, 98 100, 114 100"
stroke="url(#deformed)" stroke-width="5" stroke-dasharray="3 5"/>
<path d="M 6 100 L 6 8 L 114 8 L 114 100"
stroke="url(#frameStroke)" stroke-width="7"/>
<rect x="-3" y="100" width="18" height="10" fill="#F2A93B" rx="1"/>
<rect x="105" y="100" width="18" height="10" fill="#F2A93B" rx="1"/>
<circle cx="6" cy="8" r="5" fill="#E8EDF5"/>
<circle cx="114" cy="8" r="5" fill="#E8EDF5"/>
<!-- Mark: portal frame under lateral (pushover) load -->
<g transform="translate(44, 30)" stroke-linecap="round" stroke-linejoin="round" fill="none">
<!-- Deformed-shape ghost — pushover sway to the right -->
<path d="M 8 96 L 24 16 L 124 16 L 108 96"
stroke="#4F92E8" stroke-width="5" stroke-dasharray="2 6" opacity="0.5"/>
<!-- Push arrow -->
<path d="M -30 16 L -12 16" stroke="#F2A93B" stroke-width="6"/>
<polygon points="-6,16 -18,8 -18,24" fill="#F2A93B"/>
<!-- Frame -->
<path d="M 8 96 L 8 16 L 108 16 L 108 96"
stroke="url(#frameStroke)" stroke-width="8"/>
<!-- Fixed supports -->
<polygon points="8,96 -2,108 18,108" fill="#F2A93B"/>
<polygon points="108,96 98,108 118,108" fill="#F2A93B"/>
</g>
<!-- Wordmark -->
<g font-family="Segoe UI, Inter, Helvetica, Arial, sans-serif">
<text x="200" y="92" font-size="56" font-weight="700" letter-spacing="-1">
<text x="200" y="105" font-size="62" font-weight="700" letter-spacing="-1">
<tspan fill="#E8EDF5">OTKO</tspan>
</text>
<text x="202" y="124" font-size="16" font-weight="500" letter-spacing="3" fill="#8FA2BF">
<text x="202" y="133" font-size="15" font-weight="500" letter-spacing="3" fill="#8FA2BF">
A SAP2000-STYLE GUI FOR OPENSEESPY
</text>
</g>

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 306 KiB

After

Width:  |  Height:  |  Size: 306 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 151 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 210 KiB

After

Width:  |  Height:  |  Size: 210 KiB

Before After
Before After

View file

@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "otko"
dynamic = ["version"]
version = "0.1.0"
description = "OTKO — a modern, SAP2000-style desktop GUI for OpenSeesPy."
readme = "README.md"
requires-python = ">=3.10"
@ -42,7 +42,10 @@ gui = [
"vtk>=9.3",
"pyqtgraph>=0.13",
"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 = [
"pytest>=7.4",
@ -52,7 +55,6 @@ dev = [
"mypy>=1.8",
"pre-commit>=3.6",
"hatch>=1.9",
"tomli>=2.0; python_version < '3.11'",
]
docs = [
"sphinx>=7.2",
@ -70,9 +72,6 @@ Issues = "https://github.com/ogunc/otko/issues"
[tool.hatch.build.targets.wheel]
packages = ["src/otko"]
[tool.hatch.version]
path = "src/otko/_const.py"
# ─────────── Ruff ───────────
[tool.ruff]
line-length = 100
@ -90,25 +89,7 @@ select = [
"SIM", # simplify
"RUF", # ruff-specific
]
ignore = [
"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"]
ignore = ["E501"] # line length handled by formatter
[tool.ruff.format]
quote-style = "double"
@ -116,12 +97,11 @@ quote-style = "double"
# ─────────── Mypy ───────────
[tool.mypy]
python_version = "3.10"
warn_unused_configs = true
plugins = []
[[tool.mypy.overrides]]
module = ["otko.core.*", "otko.services.*", "otko.viewmodels.*"]
strict = true
warn_unused_ignores = true
warn_return_any = true
disallow_untyped_defs = true
plugins = []
[[tool.mypy.overrides]]
module = ["openseespy.*", "pyvista.*", "pyvistaqt.*", "vtk.*", "pyqtgraph.*"]
@ -141,8 +121,3 @@ markers = [
branch = true
source = ["src/otko"]
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."""
from otko._const import __version__
__all__ = ["__version__"]
__version__ = "0.1.0"

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

View file

@ -13,7 +13,8 @@ if TYPE_CHECKING:
class AddAnalysisCasesCommand(ProjectCommand):
"""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)")
self._cases = list(cases)
@ -34,16 +35,19 @@ class AddAnalysisCasesCommand(ProjectCommand):
class DeleteAnalysisCasesCommand(ProjectCommand):
"""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)")
self._case_ids = set(case_ids)
self._removed: list[tuple[int, Any]] = []
def redo(self) -> None:
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()
def undo(self) -> None:
@ -56,7 +60,7 @@ class DeleteAnalysisCasesCommand(ProjectCommand):
class UpdateAnalysisCaseCommand(ProjectCommand):
"""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}")
self._new = new_case
self._old: Any | None = None

View file

@ -27,18 +27,20 @@ class ProjectCommand(QUndoCommand):
: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)
self._vm = vm
@property
def vm(self) -> ProjectViewModel:
def vm(self) -> "ProjectViewModel":
return self._vm
@property
def project(self) -> Project:
def project(self) -> "Project":
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
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):
"""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__(
vm,
f"Add equalDOF {constraint.retained_node}->{constraint.constrained_node}",
@ -34,7 +34,8 @@ class AddEqualDOFConstraintCommand(ProjectCommand):
def undo(self) -> None:
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()
@ -48,7 +49,7 @@ class UpdateEqualDOFConstraintCommand(ProjectCommand):
"""
def __init__(
self, vm: ProjectViewModel, index: int, new_constraint: EqualDOFConstraint
self, vm: "ProjectViewModel", index: int, new_constraint: EqualDOFConstraint
) -> None:
super().__init__(vm, f"Edit equalDOF row {index + 1}")
self._index = index
@ -71,7 +72,7 @@ class UpdateEqualDOFConstraintCommand(ProjectCommand):
class DeleteEqualDOFConstraintCommand(ProjectCommand):
"""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)")
self._indices = set(indices)
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."""
def __init__(
self, vm: ProjectViewModel, elements: list[Any], *, text: str | None = None
self, vm: "ProjectViewModel", elements: list[Any], *, text: str | None = None
) -> None:
super().__init__(vm, text or f"Add {len(elements)} element(s)")
self._elements = list(elements)
@ -40,7 +40,7 @@ class AddElementsCommand(ProjectCommand):
class DeleteElementsCommand(ProjectCommand):
"""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)")
self._element_ids = set(element_ids)
self._removed: list[tuple[int, Any]] = []
@ -68,7 +68,7 @@ class AssignSectionCommand(ProjectCommand):
(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)")
self._element_ids = set(element_ids)
self._section_id = section_id
@ -106,7 +106,7 @@ class ConvertElementTypeCommand(ProjectCommand):
def __init__(
self,
vm: ProjectViewModel,
vm: "ProjectViewModel",
element_ids: set[int],
target_type: str,
defaults: dict[str, Any] | None = None,
@ -185,7 +185,7 @@ class ReplaceElementsCommand(ProjectCommand):
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)")
self._replacements = {el.id: el for el in replacements}
self._previous: dict[int, Any] = {}
@ -217,7 +217,7 @@ class UpdateElementFieldsCommand(ProjectCommand):
def __init__(
self,
vm: ProjectViewModel,
vm: "ProjectViewModel",
element_id: int,
fields: dict[str, Any],
) -> None:
@ -254,7 +254,7 @@ class UpdateElementFieldsCommand(ProjectCommand):
class AssignMaterialCommand(ProjectCommand):
"""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)")
self._element_ids = set(element_ids)
self._material_id = material_id

View file

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

View file

@ -35,7 +35,7 @@ class AddNodalLoadsCommand(ProjectCommand):
def __init__(
self,
vm: ProjectViewModel,
vm: "ProjectViewModel",
node_ids: set[int],
forces: tuple[float, float, float, float, float, float],
pattern_id: int | None = None,
@ -47,7 +47,7 @@ class AddNodalLoadsCommand(ProjectCommand):
self._forces = forces
self._pattern_id = pattern_id
self._new_pattern_name = new_pattern_name
self._new_ts_type = new_ts_type # "Linear" or "Constant"
self._new_ts_type = new_ts_type # "Linear" or "Constant"
self._created_ts: TimeSeries | None = None
self._created_pattern: PlainLoadPattern | None = None
self._added_loads: list[tuple[int, NodalLoad]] = [] # (pattern_id, load)
@ -101,10 +101,7 @@ class AddNodalLoadsCommand(ProjectCommand):
break
self._added_loads.clear()
# Roll back any infrastructure we created.
if (
self._created_pattern is not None
and self._created_pattern in self.project.load_patterns
):
if self._created_pattern is not None and self._created_pattern in self.project.load_patterns:
self.project.load_patterns.remove(self._created_pattern)
self._created_pattern = None
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__(
self,
vm: ProjectViewModel,
vm: "ProjectViewModel",
element_ids: set[int],
wy: float = 0.0,
wz: float = 0.0,
@ -160,10 +157,7 @@ class AddElementLoadsCommand(ProjectCommand):
pattern = self._resolve_pattern()
for eid in self._element_ids:
load = UniformElementLoad(
element_id=eid,
wy=self._wy,
wz=self._wz,
wx=self._wx,
element_id=eid, wy=self._wy, wz=self._wz, wx=self._wx,
)
pattern.element_loads.append(load)
self._added_loads.append((pattern.id, load))
@ -177,10 +171,7 @@ class AddElementLoadsCommand(ProjectCommand):
pat.element_loads.remove(load)
break
self._added_loads.clear()
if (
self._created_pattern is not None
and self._created_pattern in self.project.load_patterns
):
if self._created_pattern is not None and self._created_pattern in self.project.load_patterns:
self.project.load_patterns.remove(self._created_pattern)
self._created_pattern = None
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):
"""Add one or more materials in a single undoable step."""
def __init__(
self, vm: ProjectViewModel, materials: list[Any], *, text: str | None = None
) -> None:
def __init__(self, vm: "ProjectViewModel", materials: list[Any], *, text: str | None = None) -> None:
super().__init__(vm, text or f"Add {len(materials)} material(s)")
self._materials = list(materials)
@ -36,14 +34,15 @@ class AddMaterialsCommand(ProjectCommand):
class DeleteMaterialsCommand(ProjectCommand):
"""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)")
self._material_ids = set(material_ids)
self._removed: list[tuple[int, Any]] = []
def redo(self) -> None:
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[:] = [
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.
"""
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}")
self._new = new_material
self._old: Any | None = None

View file

@ -14,7 +14,7 @@ if TYPE_CHECKING:
class AddNodesCommand(ProjectCommand):
"""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)")
self._nodes = list(nodes)
@ -39,18 +39,17 @@ class DeleteNodesCommand(ProjectCommand):
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)")
self._node_ids = set(node_ids)
self._removed_nodes: list[tuple[int, Node]] = [] # (index, node)
self._removed_elements: list[tuple[int, object]] = [] # (index, element)
self._removed_nodes: list[tuple[int, Node]] = [] # (index, node)
self._removed_elements: list[tuple[int, object]] = [] # (index, element)
self._removed_mp_constraints: list[tuple[int, object]] = []
def redo(self) -> None:
# Cascade: snapshot every element that references a doomed node.
self._removed_elements = [
(i, el)
for i, el in enumerate(self.project.elements)
(i, el) for i, el in enumerate(self.project.elements)
if any(nid in self._node_ids for nid in el.nodes)
]
doomed_elem_ids = {el.id for _, el in self._removed_elements}
@ -59,8 +58,7 @@ class DeleteNodesCommand(ProjectCommand):
]
self._removed_mp_constraints = [
(i, mp)
for i, mp in enumerate(self.project.mp_constraints)
(i, mp) 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
]
doomed_mp = {id(mp) for _, mp in self._removed_mp_constraints}
@ -71,7 +69,9 @@ class DeleteNodesCommand(ProjectCommand):
self._removed_nodes = [
(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()
def undo(self) -> None:
@ -93,7 +93,7 @@ class SetRestraintCommand(ProjectCommand):
def __init__(
self,
vm: ProjectViewModel,
vm: "ProjectViewModel",
node_ids: set[int],
restraint: tuple[bool, bool, bool, bool, bool, bool],
) -> None:
@ -128,7 +128,7 @@ class UpdateNodeFieldsCommand(ProjectCommand):
def __init__(
self,
vm: ProjectViewModel,
vm: "ProjectViewModel",
node_id: int,
fields: dict[str, Any],
) -> None:
@ -166,7 +166,7 @@ class SetMassCommand(ProjectCommand):
def __init__(
self,
vm: ProjectViewModel,
vm: "ProjectViewModel",
node_ids: set[int],
mass: tuple[float, float, float, float, float, float],
) -> None:

View file

@ -19,7 +19,7 @@ class SetUnitsCommand(ProjectCommand):
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}")
self._units = units
self._previous: UnitSystem | None = None

View file

@ -13,9 +13,7 @@ if TYPE_CHECKING:
class AddSectionsCommand(ProjectCommand):
"""Add one or more sections in a single undoable step."""
def __init__(
self, vm: ProjectViewModel, sections: list[Any], *, text: str | None = None
) -> None:
def __init__(self, vm: "ProjectViewModel", sections: list[Any], *, text: str | None = None) -> None:
super().__init__(vm, text or f"Add {len(sections)} section(s)")
self._sections = list(sections)
@ -36,14 +34,15 @@ class AddSectionsCommand(ProjectCommand):
class DeleteSectionsCommand(ProjectCommand):
"""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)")
self._section_ids = set(section_ids)
self._removed: list[tuple[int, Any]] = []
def redo(self) -> None:
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[:] = [
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):
"""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}")
self._new = new_section
self._old: Any | None = None

View file

@ -19,7 +19,7 @@ if TYPE_CHECKING:
class AddTimeSeriesCommand(ProjectCommand):
"""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}'")
self._ts = ts
@ -31,7 +31,9 @@ class AddTimeSeriesCommand(ProjectCommand):
self._notify()
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()
@ -41,7 +43,7 @@ class UpdateTimeSeriesCommand(ProjectCommand):
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}")
self._new = new_ts
self._old: Any | None = None
@ -67,7 +69,7 @@ class DeleteTimeSeriesCommand(ProjectCommand):
"""Remove time series (no cascade — patterns referencing them must be
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)")
self._ts_ids = set(ts_ids)
self._removed: list[tuple[int, Any]] = []
@ -91,7 +93,7 @@ class DeleteTimeSeriesCommand(ProjectCommand):
class AddLoadPatternCommand(ProjectCommand):
"""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}'")
self._pattern = pattern
@ -117,7 +119,7 @@ class UpdateLoadPatternCommand(ProjectCommand):
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}")
self._new = new_pattern
self._old: Any | None = None
@ -142,7 +144,7 @@ class UpdateLoadPatternCommand(ProjectCommand):
class DeleteLoadPatternCommand(ProjectCommand):
"""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)")
self._pattern_ids = set(pattern_ids)
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 typing import TYPE_CHECKING, Literal
from typing import TYPE_CHECKING, Any, Literal
from otko.commands.base import ProjectCommand
from otko.core import Node
if TYPE_CHECKING:
from otko.viewmodels import ProjectViewModel
@ -29,7 +30,7 @@ class MoveNodesCommand(ProjectCommand):
def __init__(
self,
vm: ProjectViewModel,
vm: "ProjectViewModel",
node_ids: set[int],
offset: tuple[float, float, float],
) -> None:
@ -44,9 +45,9 @@ class MoveNodesCommand(ProjectCommand):
for i, n in enumerate(self.project.nodes):
if n.id in self._node_ids:
self._previous[n.id] = n.coords
self.project.nodes[i] = n.model_copy(
update={"coords": (n.coords[0] + dx, n.coords[1] + dy, n.coords[2] + dz)}
)
self.project.nodes[i] = n.model_copy(update={
"coords": (n.coords[0] + dx, n.coords[1] + dy, n.coords[2] + dz)
})
self._notify()
def undo(self) -> None:
@ -62,7 +63,7 @@ class ReplicateCommand(ProjectCommand):
def __init__(
self,
vm: ProjectViewModel,
vm: "ProjectViewModel",
node_ids: set[int],
element_ids: set[int],
offset: tuple[float, float, float],
@ -83,8 +84,7 @@ class ReplicateCommand(ProjectCommand):
# 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_elements = [
e
for e in self.project.elements
e 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)
]
next_node_id = self.project.next_node_id()
@ -95,34 +95,30 @@ class ReplicateCommand(ProjectCommand):
for k in range(1, self._n_copies + 1):
mapping: dict[int, int] = {}
for orig in src_nodes:
new_node = orig.model_copy(
update={
"id": next_node_id,
"coords": (
orig.coords[0] + k * dx,
orig.coords[1] + k * dy,
orig.coords[2] + k * dz,
),
}
)
new_node = orig.model_copy(update={
"id": next_node_id,
"coords": (orig.coords[0] + k * dx,
orig.coords[1] + k * dy,
orig.coords[2] + k * dz),
})
self.project.nodes.append(new_node)
self._added_node_ids.add(next_node_id)
mapping[orig.id] = next_node_id
next_node_id += 1
for orig in src_elements:
new_elem = orig.model_copy(
update={
"id": next_elem_id,
"nodes": tuple(mapping[nid] for nid in orig.nodes),
}
)
new_elem = orig.model_copy(update={
"id": next_elem_id,
"nodes": tuple(mapping[nid] for nid in orig.nodes),
})
self.project.elements.append(new_elem)
self._added_element_ids.add(next_elem_id)
next_elem_id += 1
self._notify()
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[:] = [
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__(
self,
vm: ProjectViewModel,
vm: "ProjectViewModel",
node_ids: set[int],
element_ids: set[int],
plane: Plane,
@ -170,8 +166,7 @@ class MirrorCommand(ProjectCommand):
def redo(self) -> None:
src_nodes = [n for n in self.project.nodes if n.id in self._node_ids]
src_elements = [
e
for e in self.project.elements
e 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)
]
next_node_id = self.project.next_node_id()
@ -181,30 +176,28 @@ class MirrorCommand(ProjectCommand):
mapping: dict[int, int] = {}
for orig in src_nodes:
new_node = orig.model_copy(
update={
"id": next_node_id,
"coords": self._reflect(orig.coords, self._plane),
}
)
new_node = orig.model_copy(update={
"id": next_node_id,
"coords": self._reflect(orig.coords, self._plane),
})
self.project.nodes.append(new_node)
self._added_node_ids.add(next_node_id)
mapping[orig.id] = next_node_id
next_node_id += 1
for orig in src_elements:
new_elem = orig.model_copy(
update={
"id": next_elem_id,
"nodes": tuple(mapping[nid] for nid in orig.nodes),
}
)
new_elem = orig.model_copy(update={
"id": next_elem_id,
"nodes": tuple(mapping[nid] for nid in orig.nodes),
})
self.project.elements.append(new_elem)
self._added_element_ids.add(next_elem_id)
next_elem_id += 1
self._notify()
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[:] = [
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,
ImposedSupportMotionPattern,
LinearTimeSeries,
LoadCombination,
LoadCombinationItem,
LoadPattern,
NodalLoad,
PathTimeSeries,
@ -167,8 +165,6 @@ __all__ = [
"PlainLoadPattern",
"UniformExcitationPattern",
"ImposedSupportMotionPattern",
"LoadCombination",
"LoadCombinationItem",
"NodalLoad",
"UniformElementLoad",
"ResponseSpectrum",

View file

@ -16,13 +16,11 @@ class Entity(BaseModel):
"""Base class for every persisted domain object."""
model_config = ConfigDict(
frozen=False, # individual setters allowed; we lock at the Project boundary
extra="forbid", # unknown JSON keys are an error, not a silent ignore
frozen=False, # individual setters allowed; we lock at the Project boundary
extra="forbid", # unknown JSON keys are an error, not a silent ignore
validate_assignment=True,
populate_by_name=True,
)
id: PositiveInt = Field(
..., description="Unique tag within its kind. Used as the OpenSees tag."
)
id: PositiveInt = Field(..., description="Unique tag within its kind. Used as the OpenSees tag.")
name: str = Field(default="", description="Optional human-readable label.")

View file

@ -9,7 +9,7 @@ in Phase 6/8.
from __future__ import annotations
from typing import Annotated, Literal
from typing import Annotated, Literal, Union
from pydantic import Field, PositiveFloat, PositiveInt, model_validator
@ -83,8 +83,7 @@ class TransientCase(Entity):
constraints: str = "Plain"
integrator: str = "Newmark"
integrator_params: tuple[float, float] = Field(
default=(0.5, 0.25),
description="Newmark gamma, beta (default = average acceleration).",
default=(0.5, 0.25), description="Newmark gamma, beta (default = average acceleration).",
)
algorithm: str = "Newton"
test: str = "NormDispIncr"
@ -101,7 +100,7 @@ class TransientCase(Entity):
rayleigh_beta_k: float = Field(
default=0.0,
description="Stiffness-proportional βK on CURRENT/tangent stiffness — "
"``rayleigh`` slot 2 (damps high frequencies).",
"``rayleigh`` slot 2 (damps high frequencies).",
)
rayleigh_beta_k_init: float = Field(
default=0.0,
@ -115,11 +114,11 @@ class TransientCase(Entity):
)
rayleigh_beta_k_comm: float = Field(
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(
default=None,
ge=0.0,
default=None, ge=0.0,
description=(
"If set, βK is computed as 2·ζ/√λ₁ (first-mode eigenvalue) and "
"overrides ``rayleigh_beta_k``. ``rayleigh_alpha_m`` still applies."
@ -196,7 +195,7 @@ class PushoverCase(Entity):
base_nodes: list[PositiveInt] = Field(
default_factory=list,
description="Nodes whose reactions sum into the 'base shear' for the curve. "
"Leave empty to use every restrained node in the project.",
"Leave empty to use every restrained node in the project.",
)
system: str = "BandGeneral"
constraints: str = "Plain"
@ -245,30 +244,23 @@ class ResponseSpectrumCase(Entity):
type: Literal["ResponseSpectrum"] = "ResponseSpectrum"
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(
...,
description="ID of the ResponseSpectrum to apply.",
..., description="ID of the ResponseSpectrum to apply.",
)
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"
damping_ratio: float | None = Field(
default=None,
ge=0.0,
le=1.0,
default=None, ge=0.0, le=1.0,
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[
StaticCase | ModalCase | TransientCase | PushoverCase | ResponseSpectrumCase,
Union[StaticCase, ModalCase, TransientCase, PushoverCase, ResponseSpectrumCase],
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_perfectly_plastic import ElasticPerfectlyPlasticSpec
from otko.core.catalog.generated.elastic_perfectly_plastic_with_gap import (
ElasticPerfectlyPlasticWithGapSpec,
)
from otko.core.catalog.generated.elastic_perfectly_plastic_with_gap import ElasticPerfectlyPlasticWithGapSpec
from otko.core.catalog.generated.viscous import ViscousSpec
from otko.core.catalog.generated.viscous_damper import ViscousDamperSpec
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.hysteretic import HystereticSpec
from otko.core.catalog.generated.ramberg_osgood_steel import RambergOsgoodSteelSpec
from otko.core.catalog.generated.concrete01_zero_tensile_strength import (
Concrete01ZeroTensileStrengthSpec,
)
from otko.core.catalog.generated.concrete02_linear_tension_softening import (
Concrete02LinearTensionSofteningSpec,
)
from otko.core.catalog.generated.concrete01_zero_tensile_strength import Concrete01ZeroTensileStrengthSpec
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.concrete06 import Concrete06Spec
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.ground_motion_record import GroundMotionRecordSpec
from otko.core.catalog.generated.elastic_beam_column import ElasticBeamColumnSpec
from otko.core.catalog.generated.elastic_timoshenko_beam_column import (
ElasticTimoshenkoBeamColumnSpec,
)
from otko.core.catalog.generated.elastic_timoshenko_beam_column import ElasticTimoshenkoBeamColumnSpec
from otko.core.catalog.generated.force_based_beam_column import ForceBasedBeamColumnSpec
from otko.core.catalog.generated.displacement_based_beam_column import (
DisplacementBasedBeamColumnSpec,
)
from otko.core.catalog.generated.flexure_shear_interaction_displacement_based_beam_column import (
FlexureShearInteractionDisplacementBasedBeamColumnSpec,
)
from otko.core.catalog.generated.displacement_based_beam_column import DisplacementBasedBeamColumnSpec
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.corotational_truss import CorotationalTrussSpec
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]] = {
"Elastic": ElasticSpec,
"Elastic_Perfectly_Plastic": ElasticPerfectlyPlasticSpec,
"Elastic_Perfectly_Plastic_with_Gap": ElasticPerfectlyPlasticWithGapSpec,
"Viscous": ViscousSpec,
"Viscous_Damper": ViscousDamperSpec,
"Hyperbolic_Gap": HyperbolicGapSpec,
"PySimple1": Pysimple1Spec,
"TzSimple1": Tzsimple1Spec,
"QzSimple1": Qzsimple1Spec,
"BondSP01": Bondsp01Spec,
"Steel01": Steel01Spec,
"Steel02": Steel02Spec,
"Reinforcing_steel": ReinforcingSteelSpec,
"Hysteretic": HystereticSpec,
"Ramberg-Osgood steel": RambergOsgoodSteelSpec,
"Concrete01_(Zero_tensile_strength)": Concrete01ZeroTensileStrengthSpec,
"Concrete02_(Linear_tension_softening)": Concrete02LinearTensionSofteningSpec,
"Concrete04_(Popovics_concrete)": Concrete04PopovicsConcreteSpec,
"Concrete06": Concrete06Spec,
"ConcreteCM": ConcretecmSpec,
"Series": SeriesSpec,
"Parallel": ParallelSpec,
"Section_Aggregator": SectionAggregatorSpec,
"Initial_Strain": InitialStrainSpec,
"Initial_Stress": InitialStressSpec,
"MinMax": MinmaxSpec,
"User_Material": UserMaterialSpec,
"Elastic_Isotropic": ElasticIsotropicSpec,
"Elastic_Orthotropic": ElasticOrthotropicSpec,
"J2Plasticity": J2plasticitySpec,
"Damage2p": Damage2pSpec,
"PressureIndependMultiYield": PressureindependmultiyieldSpec,
"PressureDependMultiYield": PressuredependmultiyieldSpec,
"PressureDependMultiYield02": Pressuredependmultiyield02Spec,
"Contact": ContactSpec,
"Elastic_Section": ElasticSectionSpec,
"Fiber": FiberSpec,
"Fiber_Custom": FiberCustomSpec,
"FiberInt": FiberintSpec,
"Plate_Fiber": PlateFiberSpec,
"Elastic_Membrane_Plate": ElasticMembranePlateSpec,
"LayeredShell": LayeredshellSpec,
"Ground_Motion_Record": GroundMotionRecordSpec,
"Elastic_Beam-Column": ElasticBeamColumnSpec,
"Elastic_Timoshenko_Beam-Column": ElasticTimoshenkoBeamColumnSpec,
"Force-Based_Beam-Column": ForceBasedBeamColumnSpec,
"Displacement-Based_Beam-Column": DisplacementBasedBeamColumnSpec,
"Flexure-Shear_Interaction_Displacement-Based_Beam-Column": FlexureShearInteractionDisplacementBasedBeamColumnSpec,
"Truss": TrussSpec,
"Corotational_Truss": CorotationalTrussSpec,
"Quad": QuadSpec,
"Shell": ShellSpec,
"ShellDKGQ": ShelldkgqSpec,
"Tri31": Tri31Spec,
"QuadUP": QuadupSpec,
"Standard_Brick_Element": StandardBrickElementSpec,
"Auto_Zero_Length": AutoZeroLengthSpec,
"Auto_equal_constraint": AutoEqualConstraintSpec,
'Elastic': ElasticSpec,
'Elastic_Perfectly_Plastic': ElasticPerfectlyPlasticSpec,
'Elastic_Perfectly_Plastic_with_Gap': ElasticPerfectlyPlasticWithGapSpec,
'Viscous': ViscousSpec,
'Viscous_Damper': ViscousDamperSpec,
'Hyperbolic_Gap': HyperbolicGapSpec,
'PySimple1': Pysimple1Spec,
'TzSimple1': Tzsimple1Spec,
'QzSimple1': Qzsimple1Spec,
'BondSP01': Bondsp01Spec,
'Steel01': Steel01Spec,
'Steel02': Steel02Spec,
'Reinforcing_steel': ReinforcingSteelSpec,
'Hysteretic': HystereticSpec,
'Ramberg-Osgood steel': RambergOsgoodSteelSpec,
'Concrete01_(Zero_tensile_strength)': Concrete01ZeroTensileStrengthSpec,
'Concrete02_(Linear_tension_softening)': Concrete02LinearTensionSofteningSpec,
'Concrete04_(Popovics_concrete)': Concrete04PopovicsConcreteSpec,
'Concrete06': Concrete06Spec,
'ConcreteCM': ConcretecmSpec,
'Series': SeriesSpec,
'Parallel': ParallelSpec,
'Section_Aggregator': SectionAggregatorSpec,
'Initial_Strain': InitialStrainSpec,
'Initial_Stress': InitialStressSpec,
'MinMax': MinmaxSpec,
'User_Material': UserMaterialSpec,
'Elastic_Isotropic': ElasticIsotropicSpec,
'Elastic_Orthotropic': ElasticOrthotropicSpec,
'J2Plasticity': J2plasticitySpec,
'Damage2p': Damage2pSpec,
'PressureIndependMultiYield': PressureindependmultiyieldSpec,
'PressureDependMultiYield': PressuredependmultiyieldSpec,
'PressureDependMultiYield02': Pressuredependmultiyield02Spec,
'Contact': ContactSpec,
'Elastic_Section': ElasticSectionSpec,
'Fiber': FiberSpec,
'Fiber_Custom': FiberCustomSpec,
'FiberInt': FiberintSpec,
'Plate_Fiber': PlateFiberSpec,
'Elastic_Membrane_Plate': ElasticMembranePlateSpec,
'LayeredShell': LayeredshellSpec,
'Ground_Motion_Record': GroundMotionRecordSpec,
'Elastic_Beam-Column': ElasticBeamColumnSpec,
'Elastic_Timoshenko_Beam-Column': ElasticTimoshenkoBeamColumnSpec,
'Force-Based_Beam-Column': ForceBasedBeamColumnSpec,
'Displacement-Based_Beam-Column': DisplacementBasedBeamColumnSpec,
'Flexure-Shear_Interaction_Displacement-Based_Beam-Column': FlexureShearInteractionDisplacementBasedBeamColumnSpec,
'Truss': TrussSpec,
'Corotational_Truss': CorotationalTrussSpec,
'Quad': QuadSpec,
'Shell': ShellSpec,
'ShellDKGQ': ShelldkgqSpec,
'Tri31': Tri31Spec,
'QuadUP': QuadupSpec,
'Standard_Brick_Element': StandardBrickElementSpec,
'Auto_Zero_Length': AutoZeroLengthSpec,
'Auto_equal_constraint': AutoEqualConstraintSpec,
}
__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",
]
__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']

View file

@ -7,9 +7,7 @@ from typing import Union
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_with_gap import (
ElasticPerfectlyPlasticWithGapSpec,
)
from otko.core.catalog.generated.elastic_perfectly_plastic_with_gap import ElasticPerfectlyPlasticWithGapSpec
from otko.core.catalog.generated.viscous import ViscousSpec
from otko.core.catalog.generated.viscous_damper import ViscousDamperSpec
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.hysteretic import HystereticSpec
from otko.core.catalog.generated.ramberg_osgood_steel import RambergOsgoodSteelSpec
from otko.core.catalog.generated.concrete01_zero_tensile_strength import (
Concrete01ZeroTensileStrengthSpec,
)
from otko.core.catalog.generated.concrete02_linear_tension_softening import (
Concrete02LinearTensionSofteningSpec,
)
from otko.core.catalog.generated.concrete01_zero_tensile_strength import Concrete01ZeroTensileStrengthSpec
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.concrete06 import Concrete06Spec
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.ground_motion_record import GroundMotionRecordSpec
from otko.core.catalog.generated.elastic_beam_column import ElasticBeamColumnSpec
from otko.core.catalog.generated.elastic_timoshenko_beam_column import (
ElasticTimoshenkoBeamColumnSpec,
)
from otko.core.catalog.generated.elastic_timoshenko_beam_column import ElasticTimoshenkoBeamColumnSpec
from otko.core.catalog.generated.force_based_beam_column import ForceBasedBeamColumnSpec
from otko.core.catalog.generated.displacement_based_beam_column import (
DisplacementBasedBeamColumnSpec,
)
from otko.core.catalog.generated.flexure_shear_interaction_displacement_based_beam_column import (
FlexureShearInteractionDisplacementBasedBeamColumnSpec,
)
from otko.core.catalog.generated.displacement_based_beam_column import DisplacementBasedBeamColumnSpec
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.corotational_truss import CorotationalTrussSpec
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
StandardUniaxialMaterials = Union[
ElasticSpec,
ElasticPerfectlyPlasticSpec,
ElasticPerfectlyPlasticWithGapSpec,
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,
]
StandardUniaxialMaterials = Union[ElasticSpec, ElasticPerfectlyPlasticSpec, ElasticPerfectlyPlasticWithGapSpec, 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
MultidimensionalNdMaterials = Union[
ElasticIsotropicSpec,
ElasticOrthotropicSpec,
J2plasticitySpec,
Damage2pSpec,
PressureindependmultiyieldSpec,
PressuredependmultiyieldSpec,
Pressuredependmultiyield02Spec,
ContactSpec,
]
SectionForceDeformation = Union[
ElasticSectionSpec,
FiberSpec,
FiberCustomSpec,
FiberintSpec,
PlateFiberSpec,
ElasticMembranePlateSpec,
LayeredshellSpec,
]
MultidimensionalNdMaterials = Union[ElasticIsotropicSpec, ElasticOrthotropicSpec, J2plasticitySpec, Damage2pSpec, PressureindependmultiyieldSpec, PressuredependmultiyieldSpec, Pressuredependmultiyield02Spec, ContactSpec]
SectionForceDeformation = Union[ElasticSectionSpec, FiberSpec, FiberCustomSpec, FiberintSpec, PlateFiberSpec, ElasticMembranePlateSpec, LayeredshellSpec]
Records = GroundMotionRecordSpec
BeamColumnElements = Union[
ElasticBeamColumnSpec,
ElasticTimoshenkoBeamColumnSpec,
ForceBasedBeamColumnSpec,
DisplacementBasedBeamColumnSpec,
FlexureShearInteractionDisplacementBasedBeamColumnSpec,
]
BeamColumnElements = Union[ElasticBeamColumnSpec, ElasticTimoshenkoBeamColumnSpec, ForceBasedBeamColumnSpec, DisplacementBasedBeamColumnSpec, FlexureShearInteractionDisplacementBasedBeamColumnSpec]
TrussElements = Union[TrussSpec, CorotationalTrussSpec]
SurfaceElements = Union[QuadSpec, ShellSpec, ShelldkgqSpec, Tri31Spec, QuadupSpec]
SolidElements = StandardBrickElementSpec
Autozl = AutoZeroLengthSpec
Autoedof = AutoEqualConstraintSpec
__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",
]
__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']

View file

@ -17,478 +17,478 @@ from pydantic import BaseModel, ConfigDict, Field
class AutoEqualConstraintSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Auto_equal_constraint",
"x-book": "AutoEDOF",
"dependencies": [
'x-gid-name': 'Auto_equal_constraint',
'x-book': 'AutoEDOF',
'dependencies': [
{
"field": "source",
"gid_name": "Source",
"rules": [
'field': 'source',
'gid_name': 'Source',
'rules': [
{
"trigger": "Layer",
"actions": [
'trigger': 'Layer',
'actions': [
{
"action": "RESTORE",
"field": "Layer_name",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Layer_name',
'target': '#CURRENT#',
},
],
},
{
"trigger": "All",
"actions": [
'trigger': 'All',
'actions': [
{
"action": "HIDE",
"field": "Layer_name",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Layer_name',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Visible",
"actions": [
'trigger': 'Visible',
'actions': [
{
"action": "HIDE",
"field": "Layer_name",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Layer_name',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "x_criteria",
"gid_name": "X-Criteria",
"rules": [
'field': 'x_criteria',
'gid_name': 'X-Criteria',
'rules': [
{
"trigger": "Any",
"actions": [
'trigger': 'Any',
'actions': [
{
"action": "HIDE",
"field": "X-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'X-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_X-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_X-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_X-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_X-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Fixed",
"actions": [
'trigger': 'Fixed',
'actions': [
{
"action": "RESTORE",
"field": "X-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'X-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_X-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_X-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_X-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_X-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "GT",
"actions": [
'trigger': 'GT',
'actions': [
{
"action": "RESTORE",
"field": "X-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'X-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_X-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_X-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_X-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_X-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "GET",
"actions": [
'trigger': 'GET',
'actions': [
{
"action": "RESTORE",
"field": "X-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'X-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_X-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_X-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_X-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_X-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "LT",
"actions": [
'trigger': 'LT',
'actions': [
{
"action": "RESTORE",
"field": "X-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'X-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_X-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_X-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_X-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_X-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "LET",
"actions": [
'trigger': 'LET',
'actions': [
{
"action": "RESTORE",
"field": "X-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'X-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_X-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_X-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_X-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_X-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Between",
"actions": [
'trigger': 'Between',
'actions': [
{
"action": "HIDE",
"field": "X-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'X-Coordinate',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Min_X-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Min_X-Coordinate',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Max_X-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Max_X-Coordinate',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "y_criteria",
"gid_name": "Y-Criteria",
"rules": [
'field': 'y_criteria',
'gid_name': 'Y-Criteria',
'rules': [
{
"trigger": "Any",
"actions": [
'trigger': 'Any',
'actions': [
{
"action": "HIDE",
"field": "Y-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Y-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_Y-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_Y-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_Y-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_Y-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Fixed",
"actions": [
'trigger': 'Fixed',
'actions': [
{
"action": "RESTORE",
"field": "Y-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Y-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_Y-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_Y-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_Y-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_Y-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "GT",
"actions": [
'trigger': 'GT',
'actions': [
{
"action": "RESTORE",
"field": "Y-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Y-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_Y-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_Y-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_Y-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_Y-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "GET",
"actions": [
'trigger': 'GET',
'actions': [
{
"action": "RESTORE",
"field": "Y-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Y-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_Y-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_Y-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_Y-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_Y-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "LT",
"actions": [
'trigger': 'LT',
'actions': [
{
"action": "RESTORE",
"field": "Y-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Y-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_Y-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_Y-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_Y-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_Y-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "LET",
"actions": [
'trigger': 'LET',
'actions': [
{
"action": "RESTORE",
"field": "Y-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Y-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_Y-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_Y-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_Y-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_Y-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Between",
"actions": [
'trigger': 'Between',
'actions': [
{
"action": "HIDE",
"field": "Y-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Y-Coordinate',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Min_Y-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Min_Y-Coordinate',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Max_Y-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Max_Y-Coordinate',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "z_criteria",
"gid_name": "Z-Criteria",
"rules": [
'field': 'z_criteria',
'gid_name': 'Z-Criteria',
'rules': [
{
"trigger": "Any",
"actions": [
'trigger': 'Any',
'actions': [
{
"action": "HIDE",
"field": "Z-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Z-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_Z-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_Z-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_Z-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_Z-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Fixed",
"actions": [
'trigger': 'Fixed',
'actions': [
{
"action": "RESTORE",
"field": "Z-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Z-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_Z-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_Z-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_Z-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_Z-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "GT",
"actions": [
'trigger': 'GT',
'actions': [
{
"action": "RESTORE",
"field": "Z-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Z-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_Z-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_Z-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_Z-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_Z-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "GET",
"actions": [
'trigger': 'GET',
'actions': [
{
"action": "RESTORE",
"field": "Z-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Z-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_Z-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_Z-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_Z-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_Z-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "LT",
"actions": [
'trigger': 'LT',
'actions': [
{
"action": "RESTORE",
"field": "Z-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Z-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_Z-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_Z-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_Z-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_Z-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "LET",
"actions": [
'trigger': 'LET',
'actions': [
{
"action": "RESTORE",
"field": "Z-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Z-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Min_Z-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Min_Z-Coordinate',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Max_Z-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Max_Z-Coordinate',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Between",
"actions": [
'trigger': 'Between',
'actions': [
{
"action": "HIDE",
"field": "Z-Coordinate",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Z-Coordinate',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Min_Z-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Min_Z-Coordinate',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Max_Z-Coordinate",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Max_Z-Coordinate',
'target': '#CURRENT#',
},
],
},
@ -498,40 +498,29 @@ class AutoEqualConstraintSpec(BaseModel):
}
)
determine_master_node: Literal["Existed", "Extra"] = "Existed"
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_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",
)
determine_master_node: Literal['Existed', 'Extra'] = 'Existed'
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_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
min_x_coordinate: float = 0.0
max_x_coordinate: float = 0.0
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",
)
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')
y_coordinate: float = 0.0
min_y_coordinate: float = 0.0
max_y_coordinate: float = 0.0
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",
)
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')
z_coordinate: float = 0.0
min_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
y_offset: float = 0.0
z_offset: float = 0.0
x_translation: Literal["1", "0"] = "1"
y_translation: Literal["1", "0"] = "1"
z_translation: Literal["1", "0"] = "1"
x_rotation: Literal["1", "0"] = "1"
y_rotation: Literal["1", "0"] = "1"
z_rotation: Literal["1", "0"] = "1"
x_translation: Literal['1', '0'] = '1'
y_translation: Literal['1', '0'] = '1'
z_translation: Literal['1', '0'] = '1'
x_rotation: Literal['1', '0'] = '1'
y_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):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "BondSP01",
"x-book": "Standard_Uniaxial_Materials",
"dependencies": [
'x-gid-name': 'BondSP01',
'x-book': 'Standard_Uniaxial_Materials',
'dependencies': [
{
"field": "formulation",
"gid_name": "Formulation",
"rules": [
'field': 'formulation',
'gid_name': 'Formulation',
'rules': [
{
"trigger": "Stress-Slip",
"actions": [
'trigger': 'Stress-Slip',
'actions': [
{
"action": "RESTORE",
"field": "Yield_stress_Fy",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Yield_stress_Fy',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Ultimate_stress_Fu",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Ultimate_stress_Fu',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Yield_force_Fy",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Yield_force_Fy',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Ultimate_Force_Fu",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Ultimate_Force_Fu',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Force-Slip",
"actions": [
'trigger': 'Force-Slip',
'actions': [
{
"action": "RESTORE",
"field": "Yield_force_Fy",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Yield_force_Fy',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Ultimate_Force_Fu",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Ultimate_Force_Fu',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Yield_stress_Fy",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Yield_stress_Fy',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Ultimate_stress_Fu",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Ultimate_stress_Fu',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "analysis_type",
"gid_name": "Analysis_type",
"rules": [
'field': 'analysis_type',
'gid_name': 'Analysis_type',
'rules': [
{
"trigger": "Monotonic",
"actions": [
'trigger': 'Monotonic',
'actions': [
{
"action": "HIDE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Cyclic",
"actions": [
'trigger': 'Cyclic',
'actions': [
{
"action": "RESTORE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
@ -112,15 +112,16 @@ class Bondsp01Spec(BaseModel):
}
)
material: Literal["_"] = "_"
formulation: Literal["Stress-Slip", "Force-Slip"] = "Stress-Slip"
yield_stress_fy: str = "500 MPa" # 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
ultimate_stress_fu: str = "675 MPa" # 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
material: Literal['_'] = '_'
formulation: Literal['Stress-Slip', 'Force-Slip'] = 'Stress-Slip'
yield_stress_fy: str = '500 MPa' # 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
ultimate_stress_fu: str = '675 MPa' # 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
initial_hardening: float = 0.4
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)

View file

@ -23,176 +23,176 @@ class CyclicDataRow(BaseModel):
class Concrete01ZeroTensileStrengthSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Concrete01_(Zero_tensile_strength)",
"x-book": "Uniaxial_Concrete_Materials",
"dependencies": [
'x-gid-name': 'Concrete01_(Zero_tensile_strength)',
'x-book': 'Uniaxial_Concrete_Materials',
'dependencies': [
{
"field": "strength_class",
"gid_name": "Strength_class",
"rules": [
'field': 'strength_class',
'gid_name': 'Strength_class',
'rules': [
{
"trigger": "C12/15",
"actions": [
'trigger': 'C12/15',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C16/20",
"actions": [
'trigger': 'C16/20',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C20/25",
"actions": [
'trigger': 'C20/25',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C25/30",
"actions": [
'trigger': 'C25/30',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C30/37",
"actions": [
'trigger': 'C30/37',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C35/45",
"actions": [
'trigger': 'C35/45',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C40/50",
"actions": [
'trigger': 'C40/50',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C45/55",
"actions": [
'trigger': 'C45/55',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C50/60",
"actions": [
'trigger': 'C50/60',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C60/75",
"actions": [
'trigger': 'C60/75',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C70/85",
"actions": [
'trigger': 'C70/85',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C80/95",
"actions": [
'trigger': 'C80/95',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C90/105",
"actions": [
'trigger': 'C90/105',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Custom",
"actions": [
'trigger': 'Custom',
'actions': [
{
"action": "HIDE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "analysis_type",
"gid_name": "Analysis_type",
"rules": [
'field': 'analysis_type',
'gid_name': 'Analysis_type',
'rules': [
{
"trigger": "Monotonic",
"actions": [
'trigger': 'Monotonic',
'actions': [
{
"action": "HIDE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Cyclic",
"actions": [
'trigger': 'Cyclic',
'actions': [
{
"action": "RESTORE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
@ -202,36 +202,15 @@ class Concrete01ZeroTensileStrengthSpec(BaseModel):
}
)
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",
)
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
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')
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
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
analysis_type: Literal["Monotonic", "Cyclic"] = "Monotonic"
analysis_type: Literal['Monotonic', 'Cyclic'] = 'Monotonic'
cyclic_data: list[CyclicDataRow] = Field(default_factory=list)
field: Literal["_"] = "_"
set_as_variable: Literal["0", "1"] = "0"
field: Literal['_'] = '_'
set_as_variable: Literal['0', '1'] = '0'

View file

@ -23,176 +23,176 @@ class CyclicDataRow(BaseModel):
class Concrete02LinearTensionSofteningSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Concrete02_(Linear_tension_softening)",
"x-book": "Uniaxial_Concrete_Materials",
"dependencies": [
'x-gid-name': 'Concrete02_(Linear_tension_softening)',
'x-book': 'Uniaxial_Concrete_Materials',
'dependencies': [
{
"field": "strength_class",
"gid_name": "Strength_class",
"rules": [
'field': 'strength_class',
'gid_name': 'Strength_class',
'rules': [
{
"trigger": "C12/15",
"actions": [
'trigger': 'C12/15',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C16/20",
"actions": [
'trigger': 'C16/20',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C20/25",
"actions": [
'trigger': 'C20/25',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C25/30",
"actions": [
'trigger': 'C25/30',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C30/37",
"actions": [
'trigger': 'C30/37',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C35/45",
"actions": [
'trigger': 'C35/45',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C40/50",
"actions": [
'trigger': 'C40/50',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C45/55",
"actions": [
'trigger': 'C45/55',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C50/60",
"actions": [
'trigger': 'C50/60',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C60/75",
"actions": [
'trigger': 'C60/75',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C70/85",
"actions": [
'trigger': 'C70/85',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C80/95",
"actions": [
'trigger': 'C80/95',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C90/105",
"actions": [
'trigger': 'C90/105',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Custom",
"actions": [
'trigger': 'Custom',
'actions': [
{
"action": "HIDE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "analysis_type",
"gid_name": "Analysis_type",
"rules": [
'field': 'analysis_type',
'gid_name': 'Analysis_type',
'rules': [
{
"trigger": "Monotonic",
"actions": [
'trigger': 'Monotonic',
'actions': [
{
"action": "HIDE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Cyclic",
"actions": [
'trigger': 'Cyclic',
'actions': [
{
"action": "RESTORE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
@ -202,36 +202,18 @@ class Concrete02LinearTensionSofteningSpec(BaseModel):
}
)
material: Literal["Concrete02"] = "Concrete02"
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.",
)
strength_type: Literal["Mean", "Characteristic"] = "Characteristic"
compressive_strength_fpc: str = "-20 MPa" # TODO: unit-aware type
material: Literal['Concrete02'] = 'Concrete02'
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.')
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
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
ratio_between_unloading_slope_at_epscu_and_initial_slope_lambda: float = 0.5
tensile_strength_ft: str = "2.2 MPa" # TODO: unit-aware type
tension_softening_stiffness_ets: str = "2 GPa" # TODO: unit-aware type
analysis_type: Literal["Monotonic", "Cyclic"] = "Monotonic"
tensile_strength_ft: str = '2.2 MPa' # TODO: unit-aware type
tension_softening_stiffness_ets: str = '2 GPa' # TODO: unit-aware type
analysis_type: Literal['Monotonic', 'Cyclic'] = 'Monotonic'
cyclic_data: list[CyclicDataRow] = Field(default_factory=list)
field: Literal["_"] = "_"
set_as_variable: Literal["0", "1"] = "0"
field: Literal['_'] = '_'
set_as_variable: Literal['0', '1'] = '0'

View file

@ -23,176 +23,176 @@ class CyclicDataRow(BaseModel):
class Concrete04PopovicsConcreteSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Concrete04_(Popovics_concrete)",
"x-book": "Uniaxial_Concrete_Materials",
"dependencies": [
'x-gid-name': 'Concrete04_(Popovics_concrete)',
'x-book': 'Uniaxial_Concrete_Materials',
'dependencies': [
{
"field": "strength_class",
"gid_name": "Strength_class",
"rules": [
'field': 'strength_class',
'gid_name': 'Strength_class',
'rules': [
{
"trigger": "C12/15",
"actions": [
'trigger': 'C12/15',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C16/20",
"actions": [
'trigger': 'C16/20',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C20/25",
"actions": [
'trigger': 'C20/25',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C25/30",
"actions": [
'trigger': 'C25/30',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C30/37",
"actions": [
'trigger': 'C30/37',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C35/45",
"actions": [
'trigger': 'C35/45',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C40/50",
"actions": [
'trigger': 'C40/50',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C45/55",
"actions": [
'trigger': 'C45/55',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C50/60",
"actions": [
'trigger': 'C50/60',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C60/75",
"actions": [
'trigger': 'C60/75',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C70/85",
"actions": [
'trigger': 'C70/85',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C80/95",
"actions": [
'trigger': 'C80/95',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C90/105",
"actions": [
'trigger': 'C90/105',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Custom",
"actions": [
'trigger': 'Custom',
'actions': [
{
"action": "HIDE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "analysis_type",
"gid_name": "Analysis_type",
"rules": [
'field': 'analysis_type',
'gid_name': 'Analysis_type',
'rules': [
{
"trigger": "Monotonic",
"actions": [
'trigger': 'Monotonic',
'actions': [
{
"action": "HIDE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Cyclic",
"actions": [
'trigger': 'Cyclic',
'actions': [
{
"action": "RESTORE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
@ -202,35 +202,17 @@ class Concrete04PopovicsConcreteSpec(BaseModel):
}
)
material: Literal["Concrete04"] = "Concrete04"
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.",
)
strength_type: Literal["Mean", "Characteristic"] = "Characteristic"
compressive_strength: str = "-20 MPa" # TODO: unit-aware type
material: Literal['Concrete04'] = 'Concrete04'
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.')
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_crushing_strength: float = -3.5e-3
initial_stiffness: str = "30 GPa" # TODO: unit-aware type
maximum_tensile_strength: str = "2.2 MPa" # TODO: unit-aware type
initial_stiffness: str = '30 GPa' # TODO: unit-aware type
maximum_tensile_strength: str = '2.2 MPa' # TODO: unit-aware type
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)
field: Literal["_"] = "_"
set_as_variable: Literal["0", "1"] = "0"
field: Literal['_'] = '_'
set_as_variable: Literal['0', '1'] = '0'

View file

@ -23,176 +23,176 @@ class CyclicDataRow(BaseModel):
class Concrete06Spec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Concrete06",
"x-book": "Uniaxial_Concrete_Materials",
"dependencies": [
'x-gid-name': 'Concrete06',
'x-book': 'Uniaxial_Concrete_Materials',
'dependencies': [
{
"field": "strength_class",
"gid_name": "Strength_class",
"rules": [
'field': 'strength_class',
'gid_name': 'Strength_class',
'rules': [
{
"trigger": "C12/15",
"actions": [
'trigger': 'C12/15',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C16/20",
"actions": [
'trigger': 'C16/20',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C20/25",
"actions": [
'trigger': 'C20/25',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C25/30",
"actions": [
'trigger': 'C25/30',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C30/37",
"actions": [
'trigger': 'C30/37',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C35/45",
"actions": [
'trigger': 'C35/45',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C40/50",
"actions": [
'trigger': 'C40/50',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C45/55",
"actions": [
'trigger': 'C45/55',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C50/60",
"actions": [
'trigger': 'C50/60',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C60/75",
"actions": [
'trigger': 'C60/75',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C70/85",
"actions": [
'trigger': 'C70/85',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C80/95",
"actions": [
'trigger': 'C80/95',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C90/105",
"actions": [
'trigger': 'C90/105',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Custom",
"actions": [
'trigger': 'Custom',
'actions': [
{
"action": "HIDE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "analysis_type",
"gid_name": "Analysis_type",
"rules": [
'field': 'analysis_type',
'gid_name': 'Analysis_type',
'rules': [
{
"trigger": "Monotonic",
"actions": [
'trigger': 'Monotonic',
'actions': [
{
"action": "HIDE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Cyclic",
"actions": [
'trigger': 'Cyclic',
'actions': [
{
"action": "RESTORE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
@ -202,38 +202,20 @@ class Concrete06Spec(BaseModel):
}
)
material: Literal["Concrete06"] = "Concrete06"
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.",
)
strength_type: Literal["Mean", "Characteristic"] = "Characteristic"
concrete_compressive_strength_fc: str = "-20 MPa" # TODO: unit-aware type
material: Literal['Concrete06'] = 'Concrete06'
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.')
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
compressive_shape_factor_n: int = 1
post_peak_compressive_shape_factor_k: int = 1
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
exponent_of_the_tension_stiffering_curve_b: int = 1
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)
field: Literal["_"] = "_"
set_as_variable: Literal["0", "1"] = "0"
field: Literal['_'] = '_'
set_as_variable: Literal['0', '1'] = '0'

View file

@ -23,202 +23,202 @@ class CyclicDataRow(BaseModel):
class ConcretecmSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "ConcreteCM",
"x-book": "Uniaxial_Concrete_Materials",
"dependencies": [
'x-gid-name': 'ConcreteCM',
'x-book': 'Uniaxial_Concrete_Materials',
'dependencies': [
{
"field": "strength_class",
"gid_name": "Strength_class",
"rules": [
'field': 'strength_class',
'gid_name': 'Strength_class',
'rules': [
{
"trigger": "C12/15",
"actions": [
'trigger': 'C12/15',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C16/20",
"actions": [
'trigger': 'C16/20',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C20/25",
"actions": [
'trigger': 'C20/25',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C25/30",
"actions": [
'trigger': 'C25/30',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C30/37",
"actions": [
'trigger': 'C30/37',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C35/45",
"actions": [
'trigger': 'C35/45',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C40/50",
"actions": [
'trigger': 'C40/50',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C45/55",
"actions": [
'trigger': 'C45/55',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C50/60",
"actions": [
'trigger': 'C50/60',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C60/75",
"actions": [
'trigger': 'C60/75',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C70/85",
"actions": [
'trigger': 'C70/85',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C80/95",
"actions": [
'trigger': 'C80/95',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "C90/105",
"actions": [
'trigger': 'C90/105',
'actions': [
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Custom",
"actions": [
'trigger': 'Custom',
'actions': [
{
"action": "HIDE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "consider_gap_closure",
"gid_name": "Consider_gap_closure",
"rules": [
'field': 'consider_gap_closure',
'gid_name': 'Consider_gap_closure',
'rules': [
{
"trigger": "1",
"actions": [
'trigger': '1',
'actions': [
{
"action": "RESTORE",
"field": "Gap_parameter",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Gap_parameter',
'target': '#CURRENT#',
},
],
},
{
"trigger": "0",
"actions": [
'trigger': '0',
'actions': [
{
"action": "HIDE",
"field": "Gap_parameter",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Gap_parameter',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "analysis_type",
"gid_name": "Analysis_type",
"rules": [
'field': 'analysis_type',
'gid_name': 'Analysis_type',
'rules': [
{
"trigger": "Monotonic",
"actions": [
'trigger': 'Monotonic',
'actions': [
{
"action": "HIDE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Cyclic",
"actions": [
'trigger': 'Cyclic',
'actions': [
{
"action": "RESTORE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
@ -228,37 +228,19 @@ class ConcretecmSpec(BaseModel):
}
)
material: Literal["ConcreteCM"] = "ConcreteCM"
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.",
)
strength_type: Literal["Mean", "Characteristic"] = "Characteristic"
concrete_compressive_strength_fpcc: str = "-20 MPa" # TODO: unit-aware type
material: Literal['ConcreteCM'] = 'ConcreteCM'
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.')
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
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
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
shape_parameter_rc_in_tsai_s_equation_for_tension: float = 1.2
critical_strain_on_tension_envelope: int = 10000
consider_gap_closure: Literal["1", "0"] = "0"
analysis_type: Literal["Monotonic", "Cyclic"] = "Monotonic"
consider_gap_closure: Literal['1', '0'] = '0'
analysis_type: Literal['Monotonic', 'Cyclic'] = 'Monotonic'
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.line_displacements import LineDisplacementsSpec
from otko.core.catalog.generated.conditions.surface_displacements import SurfaceDisplacementsSpec
from otko.core.catalog.generated.conditions.point_ground_motion_from_record import (
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_equal_constraint_slave_nodes import (
PointEqualConstraintSlaveNodesSpec,
)
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_ground_motion_from_record import 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_equal_constraint_slave_nodes import PointEqualConstraintSlaveNodesSpec
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.line_mass import LineMassSpec
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.line_rayleigh_damping_elements import (
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.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.line_rayleigh_damping_elements import 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.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.line_beam_contact_master_end_nodes import (
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_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.line_beam_contact_master_end_nodes import 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_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
Restraints = Union[PointRestraintsSpec, LineRestraintsSpec, SurfaceRestraintsSpec]
Loads = Union[
PointForcesSpec,
LineForcesSpec,
SurfaceForcesSpec,
LineUniformForcesSpec,
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,
]
Loads = Union[PointForcesSpec, LineForcesSpec, SurfaceForcesSpec, LineUniformForcesSpec, 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__ = [
"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",
]
__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']

View file

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

View file

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

View file

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

View file

@ -17,15 +17,16 @@ from pydantic import BaseModel, ConfigDict, Field
class LineMassSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Line_Mass",
"x-book": "Mass/Damping",
'x-gid-name': 'Line_Mass',
'x-book': 'Mass/Damping',
}
)
mass_dof_values: Literal[":"] = ":"
x_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
x_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
mass_dof_values: Literal[':'] = ':'
x_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
x_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

View file

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

View file

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

View file

@ -17,290 +17,290 @@ from pydantic import BaseModel, ConfigDict, Field
class LineRestraintsSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Line_Restraints",
"x-book": "Restraints",
"dependencies": [
'x-gid-name': 'Line_Restraints',
'x-book': 'Restraints',
'dependencies': [
{
"field": "fast_restraints",
"gid_name": "Fast_restraints",
"rules": [
'field': 'fast_restraints',
'gid_name': 'Fast_restraints',
'rules': [
{
"trigger": "Fix_XYZ",
"actions": [
'trigger': 'Fix_XYZ',
'actions': [
{
"action": "RESTORE",
"field": "X-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'X-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Y-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'Y-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Z-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'Z-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "X-Rotation",
"target": "1",
'action': 'RESTORE',
'field': 'X-Rotation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Y-Rotation",
"target": "1",
'action': 'RESTORE',
'field': 'Y-Rotation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Z-Rotation",
"target": "1",
'action': 'RESTORE',
'field': 'Z-Rotation',
'target': '1',
},
],
},
{
"trigger": "Fix_XY",
"actions": [
'trigger': 'Fix_XY',
'actions': [
{
"action": "RESTORE",
"field": "X-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'X-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Y-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'Y-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Z-Rotation",
"target": "1",
'action': 'RESTORE',
'field': 'Z-Rotation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Z-Translation",
"target": "0",
'action': 'RESTORE',
'field': 'Z-Translation',
'target': '0',
},
{
"action": "RESTORE",
"field": "X-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'X-Rotation',
'target': '0',
},
{
"action": "RESTORE",
"field": "Y-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'Y-Rotation',
'target': '0',
},
],
},
{
"trigger": "Fix_XZ",
"actions": [
'trigger': 'Fix_XZ',
'actions': [
{
"action": "RESTORE",
"field": "X-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'X-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Z-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'Z-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Y-Rotation",
"target": "1",
'action': 'RESTORE',
'field': 'Y-Rotation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Y-Translation",
"target": "0",
'action': 'RESTORE',
'field': 'Y-Translation',
'target': '0',
},
{
"action": "RESTORE",
"field": "X-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'X-Rotation',
'target': '0',
},
{
"action": "RESTORE",
"field": "Z-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'Z-Rotation',
'target': '0',
},
],
},
{
"trigger": "Fix_YZ",
"actions": [
'trigger': 'Fix_YZ',
'actions': [
{
"action": "RESTORE",
"field": "Y-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'Y-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Z-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'Z-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "X-Rotation",
"target": "1",
'action': 'RESTORE',
'field': 'X-Rotation',
'target': '1',
},
{
"action": "RESTORE",
"field": "X-Translation",
"target": "0",
'action': 'RESTORE',
'field': 'X-Translation',
'target': '0',
},
{
"action": "RESTORE",
"field": "Z-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'Z-Rotation',
'target': '0',
},
{
"action": "RESTORE",
"field": "Y-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'Y-Rotation',
'target': '0',
},
],
},
{
"trigger": "Pin_XYZ",
"actions": [
'trigger': 'Pin_XYZ',
'actions': [
{
"action": "RESTORE",
"field": "X-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'X-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Y-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'Y-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Z-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'Z-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "X-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'X-Rotation',
'target': '0',
},
{
"action": "RESTORE",
"field": "Y-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'Y-Rotation',
'target': '0',
},
{
"action": "RESTORE",
"field": "Z-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'Z-Rotation',
'target': '0',
},
],
},
{
"trigger": "Pin_XY",
"actions": [
'trigger': 'Pin_XY',
'actions': [
{
"action": "RESTORE",
"field": "X-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'X-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Y-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'Y-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Z-Translation",
"target": "0",
'action': 'RESTORE',
'field': 'Z-Translation',
'target': '0',
},
{
"action": "RESTORE",
"field": "X-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'X-Rotation',
'target': '0',
},
{
"action": "RESTORE",
"field": "Y-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'Y-Rotation',
'target': '0',
},
{
"action": "RESTORE",
"field": "Z-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'Z-Rotation',
'target': '0',
},
],
},
{
"trigger": "Pin_XZ",
"actions": [
'trigger': 'Pin_XZ',
'actions': [
{
"action": "RESTORE",
"field": "X-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'X-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Z-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'Z-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Y-Translation",
"target": "0",
'action': 'RESTORE',
'field': 'Y-Translation',
'target': '0',
},
{
"action": "RESTORE",
"field": "X-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'X-Rotation',
'target': '0',
},
{
"action": "RESTORE",
"field": "Y-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'Y-Rotation',
'target': '0',
},
{
"action": "RESTORE",
"field": "Z-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'Z-Rotation',
'target': '0',
},
],
},
{
"trigger": "Pin_YZ",
"actions": [
'trigger': 'Pin_YZ',
'actions': [
{
"action": "RESTORE",
"field": "Y-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'Y-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Z-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'Z-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "X-Translation",
"target": "0",
'action': 'RESTORE',
'field': 'X-Translation',
'target': '0',
},
{
"action": "RESTORE",
"field": "X-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'X-Rotation',
'target': '0',
},
{
"action": "RESTORE",
"field": "Y-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'Y-Rotation',
'target': '0',
},
{
"action": "RESTORE",
"field": "Z-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'Z-Rotation',
'target': '0',
},
],
},
@ -310,13 +310,12 @@ class LineRestraintsSpec(BaseModel):
}
)
x_translation: Literal["1", "0"] = "1"
y_translation: Literal["1", "0"] = "1"
z_translation: Literal["1", "0"] = "1"
x_rotation: Literal["1", "0"] = "1"
y_rotation: Literal["1", "0"] = "1"
z_rotation: Literal["1", "0"] = "1"
fluid_pressure: Literal["1", "0"] = "0"
fast_restraints: Literal[
"Fix_XYZ", "Fix_XY", "Fix_XZ", "Fix_YZ", "Pin_XYZ", "Pin_XY", "Pin_XZ", "Pin_YZ"
] = "Fix_XYZ"
x_translation: Literal['1', '0'] = '1'
y_translation: Literal['1', '0'] = '1'
z_translation: Literal['1', '0'] = '1'
x_rotation: Literal['1', '0'] = '1'
y_rotation: Literal['1', '0'] = '1'
z_rotation: Literal['1', '0'] = '1'
fluid_pressure: Literal['1', '0'] = '0'
fast_restraints: Literal['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):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Line_Rigid_diaphragm_slave_nodes",
"x-book": "Constraints",
'x-gid-name': 'Line_Rigid_diaphragm_slave_nodes',
'x-book': 'Constraints',
}
)
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):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Line_Rigid_link_slave_nodes",
"x-book": "Constraints",
'x-gid-name': 'Line_Rigid_link_slave_nodes',
'x-book': 'Constraints',
}
)
rigid_link_id: int = Field(
1, description="Give a positive integer number for body constraint group."
)
rigid_link_type: Literal["Bar", "Beam"] = "Beam"
rigid_link_id: int = Field(1, description='Give a positive integer number for body constraint group.')
rigid_link_type: Literal['Bar', 'Beam'] = 'Beam'

View file

@ -15,11 +15,12 @@ from pydantic import BaseModel, ConfigDict, Field
class LineUniformForcesSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Line_Uniform_Forces",
"x-book": "Loads",
'x-gid-name': 'Line_Uniform_Forces',
'x-book': 'Loads',
}
)
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_z_direction: 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_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):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Point_Beam_contact_slave_nodes",
"x-book": "ZeroLength_Elements",
'x-gid-name': 'Point_Beam_contact_slave_nodes',
'x-book': 'ZeroLength_Elements',
}
)
beam_contact_id: int = 1
contact_material_mat_multidimensional_nd_materials_user_materials: str = "Contact"
width_radius: str = "0.25m" # TODO: unit-aware type
contact_material_mat_multidimensional_nd_materials_user_materials: str = 'Contact'
width_radius: str = '0.25m' # TODO: unit-aware type
gap_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):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Point_Body_constraint_master_node",
"x-book": "Old_Conditions",
'x-gid-name': 'Point_Body_constraint_master_node',
'x-book': 'Old_Conditions',
}
)
body_constraint_id_number: int = Field(
1, description="Give a positive integer number for body constraint group."
)
body_constraint_id_number: int = Field(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):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Point_Body_constraint_slave_nodes",
"x-book": "Old_Conditions",
"dependencies": [
'x-gid-name': 'Point_Body_constraint_slave_nodes',
'x-book': 'Old_Conditions',
'dependencies': [
{
"field": "fast_constraints",
"gid_name": "Fast_constraints",
"rules": [
'field': 'fast_constraints',
'gid_name': 'Fast_constraints',
'rules': [
{
"trigger": "Pinned_Connection",
"actions": [
'trigger': 'Pinned_Connection',
'actions': [
{
"action": "RESTORE",
"field": "X-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'X-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Y-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'Y-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Z-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'Z-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "X-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'X-Rotation',
'target': '0',
},
{
"action": "RESTORE",
"field": "Y-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'Y-Rotation',
'target': '0',
},
{
"action": "RESTORE",
"field": "Z-Rotation",
"target": "0",
'action': 'RESTORE',
'field': 'Z-Rotation',
'target': '0',
},
],
},
{
"trigger": "Fixed_Connection",
"actions": [
'trigger': 'Fixed_Connection',
'actions': [
{
"action": "RESTORE",
"field": "X-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'X-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Y-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'Y-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Z-Translation",
"target": "1",
'action': 'RESTORE',
'field': 'Z-Translation',
'target': '1',
},
{
"action": "RESTORE",
"field": "X-Rotation",
"target": "1",
'action': 'RESTORE',
'field': 'X-Rotation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Y-Rotation",
"target": "1",
'action': 'RESTORE',
'field': 'Y-Rotation',
'target': '1',
},
{
"action": "RESTORE",
"field": "Z-Rotation",
"target": "1",
'action': 'RESTORE',
'field': 'Z-Rotation',
'target': '1',
},
],
},
@ -100,13 +100,12 @@ class PointBodyConstraintSlaveNodesSpec(BaseModel):
}
)
body_constraint_id_number: int = Field(
1, description="Give a positive integer number for body constraint group."
)
x_translation: Literal["1", "0"] = "1"
y_translation: Literal["1", "0"] = "1"
z_translation: Literal["1", "0"] = "1"
x_rotation: Literal["1", "0"] = "1"
y_rotation: Literal["1", "0"] = "1"
z_rotation: Literal["1", "0"] = "1"
fast_constraints: Literal["Pinned_Connection", "Fixed_Connection"] = "Pinned_Connection"
body_constraint_id_number: int = Field(1, description='Give a positive integer number for body constraint group.')
x_translation: Literal['1', '0'] = '1'
y_translation: Literal['1', '0'] = '1'
z_translation: Literal['1', '0'] = '1'
x_rotation: Literal['1', '0'] = '1'
y_rotation: Literal['1', '0'] = '1'
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):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Point_Displacements",
"x-book": "Loads",
'x-gid-name': 'Point_Displacements',
'x-book': 'Loads',
}
)
x_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
x_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
x_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
x_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

View file

@ -15,11 +15,10 @@ from pydantic import BaseModel, ConfigDict, Field
class PointEqualConstraintMasterNodeSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Point_Equal_constraint_master_node",
"x-book": "Constraints",
'x-gid-name': 'Point_Equal_constraint_master_node',
'x-book': 'Constraints',
}
)
equal_constraint_id: int = Field(
1, description="Give a positive integer number for body constraint group."
)
equal_constraint_id: int = Field(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):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Point_Equal_constraint_slave_nodes",
"x-book": "Constraints",
'x-gid-name': 'Point_Equal_constraint_slave_nodes',
'x-book': 'Constraints',
}
)
equal_constraint_id: int = Field(
1, description="Give a positive integer number for body constraint group."
)
x_translation: Literal["1", "0"] = "1"
y_translation: Literal["1", "0"] = "1"
z_translation: Literal["1", "0"] = "1"
x_rotation: Literal["1", "0"] = "1"
y_rotation: Literal["1", "0"] = "1"
z_rotation: Literal["1", "0"] = "1"
equal_constraint_id: int = Field(1, description='Give a positive integer number for body constraint group.')
x_translation: Literal['1', '0'] = '1'
y_translation: Literal['1', '0'] = '1'
z_translation: Literal['1', '0'] = '1'
x_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):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Point_Forces",
"x-book": "Loads",
'x-gid-name': 'Point_Forces',
'x-book': 'Loads',
}
)
x_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
x_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
x_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
x_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

View file

@ -17,10 +17,11 @@ from pydantic import BaseModel, ConfigDict, Field
class PointGroundMotionFromRecordSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Point_Ground_Motion_from_Record",
"x-book": "Loads",
'x-gid-name': 'Point_Ground_Motion_from_Record',
'x-book': 'Loads',
}
)
record_file: str = "Ground_Motion_Record"
ground_motion_direction: Literal["Ux", "Uy", "Uz", "Rx", "Ry", "Rz"] = "Ux"
record_file: str = 'Ground_Motion_Record'
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):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Point_Mass",
"x-book": "Mass/Damping",
'x-gid-name': 'Point_Mass',
'x-book': 'Mass/Damping',
}
)
mass_dof_values: Literal[":"] = ":"
x_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
x_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
mass_dof_values: Literal[':'] = ':'
x_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
x_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

View file

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

View file

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

View file

@ -17,10 +17,11 @@ from pydantic import BaseModel, ConfigDict, Field
class PointRigidDiaphragmSlaveNodesSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Point_Rigid_diaphragm_slave_nodes",
"x-book": "Constraints",
'x-gid-name': 'Point_Rigid_diaphragm_slave_nodes',
'x-book': 'Constraints',
}
)
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):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Point_Rigid_link_master_node",
"x-book": "Constraints",
'x-gid-name': 'Point_Rigid_link_master_node',
'x-book': 'Constraints',
}
)
rigid_link_id: int = 1

View file

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

View file

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

View file

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

View file

@ -15,14 +15,15 @@ from pydantic import BaseModel, ConfigDict, Field
class SurfaceDisplacementsSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Surface_Displacements",
"x-book": "Loads",
'x-gid-name': 'Surface_Displacements',
'x-book': 'Loads',
}
)
x_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
x_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
x_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
x_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

View file

@ -15,14 +15,15 @@ from pydantic import BaseModel, ConfigDict, Field
class SurfaceForcesSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Surface_Forces",
"x-book": "Loads",
'x-gid-name': 'Surface_Forces',
'x-book': 'Loads',
}
)
x_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
x_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
x_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
x_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

View file

@ -17,15 +17,16 @@ from pydantic import BaseModel, ConfigDict, Field
class SurfaceMassSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Surface_Mass",
"x-book": "Mass/Damping",
'x-gid-name': 'Surface_Mass',
'x-book': 'Mass/Damping',
}
)
mass_dof_values: Literal[":"] = ":"
x_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
x_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
mass_dof_values: Literal[':'] = ':'
x_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
x_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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -17,13 +17,14 @@ from pydantic import BaseModel, ConfigDict, Field
class ContactSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Contact",
"x-book": "Multidimensional_(nD)_Materials",
'x-gid-name': 'Contact',
'x-book': 'Multidimensional_(nD)_Materials',
}
)
material: Literal["Contact"] = "Contact"
material: Literal['Contact'] = 'Contact'
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
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):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Corotational_Truss",
"x-book": "Truss_Elements",
"dependencies": [
'x-gid-name': 'Corotational_Truss',
'x-book': 'Truss_Elements',
'dependencies': [
{
"field": "cross_section",
"gid_name": "Cross_section",
"rules": [
'field': 'cross_section',
'gid_name': 'Cross_section',
'rules': [
{
"trigger": "Rectangular",
"actions": [
'trigger': 'Rectangular',
'actions': [
{
"action": "RESTORE",
"field": "Height_h",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Height_h',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Width_B",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Width_B',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Diameter_d",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Diameter_d',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Height_hf",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Height_hf',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_bf",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_bf',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_Bw",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_Bw',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Area_A",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Area_A',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Circular",
"actions": [
'trigger': 'Circular',
'actions': [
{
"action": "HIDE",
"field": "Height_h",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Height_h',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_B",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_B',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Diameter_d",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Diameter_d',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Height_hf",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Height_hf',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_bf",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_bf',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_Bw",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_Bw',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Area_A",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Area_A',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Tee",
"actions": [
'trigger': 'Tee',
'actions': [
{
"action": "RESTORE",
"field": "Height_h",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Height_h',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_B",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_B',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Diameter_d",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Diameter_d',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Height_hf",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Height_hf',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Width_bf",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Width_bf',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Width_Bw",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Width_Bw',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Area_A",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Area_A',
'target': '#CURRENT#',
},
],
},
{
"trigger": "General",
"actions": [
'trigger': 'General',
'actions': [
{
"action": "HIDE",
"field": "Height_h",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Height_h',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_B",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_B',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Diameter_d",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Diameter_d',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_bf",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_bf',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Height_hf",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Height_hf',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_Bw",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_Bw',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Area_A",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Area_A',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "set_modification_factors",
"gid_name": "Set_modification_factors",
"rules": [
'field': 'set_modification_factors',
'gid_name': 'Set_modification_factors',
'rules': [
{
"trigger": "0",
"actions": [
'trigger': '0',
'actions': [
{
"action": "HIDE",
"field": "mod._A",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'mod._A',
'target': '#CURRENT#',
},
],
},
{
"trigger": "1",
"actions": [
'trigger': '1',
'actions': [
{
"action": "RESTORE",
"field": "mod._A",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'mod._A',
'target': '#CURRENT#',
},
],
},
@ -216,22 +216,21 @@ class CorotationalTrussSpec(BaseModel):
}
)
element_type: Literal["CorotationalTruss"] = "CorotationalTruss"
compatible_materials: Literal["_"] = "_"
material: str = Field(
"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"
include_rayleigh_damping: Literal["1", "0"] = "0"
weight_density: str = "0.0 kN/m^3" # TODO: unit-aware type
cross_section: Literal["Rectangular", "Tee", "Circular", "General"] = "General"
height_h: str = "0.5m" # TODO: unit-aware type
width_b: str = "0.3m" # TODO: unit-aware type
diameter_d: str = "0.5m" # TODO: unit-aware type
width_bf: str = "0.4m" # TODO: unit-aware type
height_hf: str = "0.15m" # TODO: unit-aware type
width_bw: str = "0.25m" # TODO: unit-aware type
area_a: str = "1 m^2" # TODO: unit-aware type
set_modification_factors: Literal["0", "1"] = "0"
element_type: Literal['CorotationalTruss'] = 'CorotationalTruss'
compatible_materials: Literal['_'] = '_'
material: str = Field('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'
include_rayleigh_damping: Literal['1', '0'] = '0'
weight_density: str = '0.0 kN/m^3' # TODO: unit-aware type
cross_section: Literal['Rectangular', 'Tee', 'Circular', 'General'] = 'General'
height_h: str = '0.5m' # TODO: unit-aware type
width_b: str = '0.3m' # TODO: unit-aware type
diameter_d: str = '0.5m' # TODO: unit-aware type
width_bf: str = '0.4m' # TODO: unit-aware type
height_hf: str = '0.15m' # TODO: unit-aware type
width_bw: str = '0.25m' # TODO: unit-aware type
area_a: str = '1 m^2' # TODO: unit-aware type
set_modification_factors: Literal['0', '1'] = '0'
mod_a: int = 1

View file

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

View file

@ -17,19 +17,18 @@ from pydantic import BaseModel, ConfigDict, Field
class DisplacementBasedBeamColumnSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Displacement-Based_Beam-Column",
"x-book": "Beam-Column_Elements",
'x-gid-name': 'Displacement-Based_Beam-Column',
'x-book': 'Beam-Column_Elements',
}
)
element_type: Literal["dispBeamColumn"] = "dispBeamColumn"
compatible_sections: Literal["_"] = "_"
number_of_integration_points: int = Field(
3, description="number of integration points along the element"
)
the_number_of_integration: Literal["_"] = "_"
to_increase_analysis_accuracy: Literal["_"] = "_"
section: str = "Fiber"
geometric_transformation: Literal["Linear", "P-Delta", "Corotational"] = "Linear"
mass_density: str = "0.0ton/m^3" # TODO: unit-aware type
weight_density: str = "25 kN/m^3" # TODO: unit-aware type
element_type: Literal['dispBeamColumn'] = 'dispBeamColumn'
compatible_sections: Literal['_'] = '_'
number_of_integration_points: int = Field(3, description='number of integration points along the element')
the_number_of_integration: Literal['_'] = '_'
to_increase_analysis_accuracy: Literal['_'] = '_'
section: str = 'Fiber'
geometric_transformation: Literal['Linear', 'P-Delta', 'Corotational'] = 'Linear'
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):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Elastic",
"x-book": "Standard_Uniaxial_Materials",
"dependencies": [
'x-gid-name': 'Elastic',
'x-book': 'Standard_Uniaxial_Materials',
'dependencies': [
{
"field": "formulation",
"gid_name": "Formulation",
"rules": [
'field': 'formulation',
'gid_name': 'Formulation',
'rules': [
{
"trigger": "Stress-Strain",
"actions": [
'trigger': 'Stress-Strain',
'actions': [
{
"action": "RESTORE",
"field": "Material_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Material_type',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Stiffness_K",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Stiffness_K',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Moment_per_rotation_unit",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Moment_per_rotation_unit',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Elastic_modulus_E",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Elastic_modulus_E',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Moment_per_rotation_unit",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Moment_per_rotation_unit',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Force-Deformation",
"actions": [
'trigger': 'Force-Deformation',
'actions': [
{
"action": "HIDE",
"field": "Material_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Material_type',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Steel_grade",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Steel_grade',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Elastic_modulus_E",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Elastic_modulus_E',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Stiffness_K",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Stiffness_K',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Moment_per_rotation_unit",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Moment_per_rotation_unit',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Moment-Rotation",
"actions": [
'trigger': 'Moment-Rotation',
'actions': [
{
"action": "HIDE",
"field": "Material_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Material_type',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Steel_grade",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Steel_grade',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Elastic_modulus_E",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Elastic_modulus_E',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Stiffness_K",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Stiffness_K',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Moment_per_rotation_unit",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Moment_per_rotation_unit',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "material_type",
"gid_name": "Material_type",
"rules": [
'field': 'material_type',
'gid_name': 'Material_type',
'rules': [
{
"trigger": "Concrete",
"actions": [
'trigger': 'Concrete',
'actions': [
{
"action": "RESTORE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Steel_grade",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Steel_grade',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Steel",
"actions": [
'trigger': 'Steel',
'actions': [
{
"action": "HIDE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Steel_grade",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Steel_grade',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Custom",
"actions": [
'trigger': 'Custom',
'actions': [
{
"action": "HIDE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Steel_grade",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Steel_grade',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "analysis_type",
"gid_name": "Analysis_type",
"rules": [
'field': 'analysis_type',
'gid_name': 'Analysis_type',
'rules': [
{
"trigger": "Monotonic",
"actions": [
'trigger': 'Monotonic',
'actions': [
{
"action": "HIDE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Cyclic",
"actions": [
'trigger': 'Cyclic',
'actions': [
{
"action": "RESTORE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
@ -213,32 +213,16 @@ class ElasticSpec(BaseModel):
}
)
material: Literal["Elastic"] = Field("Elastic", description="Elastic uniaxial material object")
formulation: Literal["Stress-Strain", "Force-Deformation", "Moment-Rotation"] = "Stress-Strain"
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"
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"
material: Literal['Elastic'] = Field('Elastic', description='Elastic uniaxial material object')
formulation: Literal['Stress-Strain', 'Force-Deformation', 'Moment-Rotation'] = 'Stress-Strain'
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'
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)
field: Literal["_"] = "_"
set_as_variable: Literal["0", "1"] = "0"
field: Literal['_'] = '_'
set_as_variable: Literal['0', '1'] = '0'

View file

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

View file

@ -17,40 +17,40 @@ from pydantic import BaseModel, ConfigDict, Field
class ElasticIsotropicSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Elastic_Isotropic",
"x-book": "Multidimensional_(nD)_Materials",
"dependencies": [
'x-gid-name': 'Elastic_Isotropic',
'x-book': 'Multidimensional_(nD)_Materials',
'dependencies': [
{
"field": "material_type",
"gid_name": "Material_type",
"rules": [
'field': 'material_type',
'gid_name': 'Material_type',
'rules': [
{
"trigger": "Concrete",
"actions": [
'trigger': 'Concrete',
'actions': [
{
"action": "RESTORE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Steel",
"actions": [
'trigger': 'Steel',
'actions': [
{
"action": "HIDE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Custom",
"actions": [
'trigger': 'Custom',
'actions': [
{
"action": "HIDE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
],
},
@ -60,24 +60,10 @@ class ElasticIsotropicSpec(BaseModel):
}
)
material: Literal["ElasticIsotropic"] = "ElasticIsotropic"
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"
elastic_modulus_e: str = "30GPa" # TODO: unit-aware type
material: Literal['ElasticIsotropic'] = 'ElasticIsotropic'
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'
elastic_modulus_e: str = '30GPa' # TODO: unit-aware type
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):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Elastic_Membrane_Plate",
"x-book": "Section_Force-Deformation",
'x-gid-name': 'Elastic_Membrane_Plate',
'x-book': 'Section_Force-Deformation',
}
)
section: Literal["ElasticMembranePlate"] = "ElasticMembranePlate"
elastic_modulus_e: str = "28GPa" # TODO: unit-aware type
section: Literal['ElasticMembranePlate'] = 'ElasticMembranePlate'
elastic_modulus_e: str = '28GPa' # TODO: unit-aware type
poisson_s_ratio: float = 0.2
section_depth_h: str = "0.25m" # TODO: unit-aware type
mass_density: str = "0.0ton/m^3" # 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

View file

@ -17,19 +17,20 @@ from pydantic import BaseModel, ConfigDict, Field
class ElasticOrthotropicSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Elastic_Orthotropic",
"x-book": "Multidimensional_(nD)_Materials",
'x-gid-name': 'Elastic_Orthotropic',
'x-book': 'Multidimensional_(nD)_Materials',
}
)
material: Literal["ElasticOrthotropic"] = "ElasticOrthotropic"
elastic_modulus_ex: str = "30GPa" # TODO: unit-aware type
elastic_modulus_ey: str = "30GPa" # TODO: unit-aware type
elastic_modulus_ez: str = "30GPa" # TODO: unit-aware type
material: Literal['ElasticOrthotropic'] = 'ElasticOrthotropic'
elastic_modulus_ex: str = '30GPa' # TODO: unit-aware type
elastic_modulus_ey: 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_vyz: float = 0.20
poisson_s_ratio_vzx: float = 0.20
shear_modulus_gxy: str = "11GPa" # TODO: unit-aware type
shear_modulus_gyz: 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
shear_modulus_gxy: str = '11GPa' # TODO: unit-aware type
shear_modulus_gyz: 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

View file

@ -23,332 +23,332 @@ class CyclicDataRow(BaseModel):
class ElasticPerfectlyPlasticSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Elastic_Perfectly_Plastic",
"x-book": "Standard_Uniaxial_Materials",
"dependencies": [
'x-gid-name': 'Elastic_Perfectly_Plastic',
'x-book': 'Standard_Uniaxial_Materials',
'dependencies': [
{
"field": "formulation",
"gid_name": "Formulation",
"rules": [
'field': 'formulation',
'gid_name': 'Formulation',
'rules': [
{
"trigger": "Stress-Strain",
"actions": [
'trigger': 'Stress-Strain',
'actions': [
{
"action": "RESTORE",
"field": "Material_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Material_type',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Stiffness_K",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Stiffness_K',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Elastic_modulus_E",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Elastic_modulus_E',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Deformation_epsN",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Deformation_epsN',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Deformation_epsP",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Deformation_epsP',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Initial_strain_eps0",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Initial_strain_eps0',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Initial_deformation_eps0",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Initial_deformation_eps0',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Moment_per_rotation_unit",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Moment_per_rotation_unit',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Rotation_epsP",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Rotation_epsP',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Rotation_epsN",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Rotation_epsN',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Initial_rotation_eps0",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Initial_rotation_eps0',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Force-Deformation",
"actions": [
'trigger': 'Force-Deformation',
'actions': [
{
"action": "HIDE",
"field": "Material_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Material_type',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Steel_grade",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Steel_grade',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Elastic_modulus_E",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Elastic_modulus_E',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Stiffness_K",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Stiffness_K',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Deformation_epsN",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Deformation_epsN',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Deformation_epsP",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Deformation_epsP',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Strain_epsN",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strain_epsN',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Strain_epsP",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strain_epsP',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Initial_strain_eps0",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Initial_strain_eps0',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Initial_deformation_eps0",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Initial_deformation_eps0',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Moment_per_rotation_unit",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Moment_per_rotation_unit',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Rotation_epsP",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Rotation_epsP',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Rotation_epsN",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Rotation_epsN',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Initial_rotation_eps0",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Initial_rotation_eps0',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Moment-Rotation",
"actions": [
'trigger': 'Moment-Rotation',
'actions': [
{
"action": "HIDE",
"field": "Material_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Material_type',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Steel_grade",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Steel_grade',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Elastic_modulus_E",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Elastic_modulus_E',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Stiffness_K",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Stiffness_K',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Deformation_epsN",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Deformation_epsN',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Deformation_epsP",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Deformation_epsP',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Strain_epsN",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strain_epsN',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Strain_epsP",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strain_epsP',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Initial_strain_eps0",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Initial_strain_eps0',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Initial_deformation_eps0",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Initial_deformation_eps0',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Moment_per_rotation_unit",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Moment_per_rotation_unit',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Rotation_epsP",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Rotation_epsP',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Rotation_epsN",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Rotation_epsN',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Initial_rotation_eps0",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Initial_rotation_eps0',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "material_type",
"gid_name": "Material_type",
"rules": [
'field': 'material_type',
'gid_name': 'Material_type',
'rules': [
{
"trigger": "Concrete",
"actions": [
'trigger': 'Concrete',
'actions': [
{
"action": "RESTORE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Steel_grade",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Steel_grade',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Steel",
"actions": [
'trigger': 'Steel',
'actions': [
{
"action": "HIDE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Steel_grade",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Steel_grade',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Custom",
"actions": [
'trigger': 'Custom',
'actions': [
{
"action": "HIDE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Steel_grade",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Steel_grade',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "analysis_type",
"gid_name": "Analysis_type",
"rules": [
'field': 'analysis_type',
'gid_name': 'Analysis_type',
'rules': [
{
"trigger": "Monotonic",
"actions": [
'trigger': 'Monotonic',
'actions': [
{
"action": "HIDE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Cyclic",
"actions": [
'trigger': 'Cyclic',
'actions': [
{
"action": "RESTORE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
@ -358,50 +358,26 @@ class ElasticPerfectlyPlasticSpec(BaseModel):
}
)
material: Literal["ElasticPerfectlyPlastic"] = Field(
"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"
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"
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
material: Literal['ElasticPerfectlyPlastic'] = Field('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'
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'
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_deformation_eps0: str = "0.0m" # TODO: unit-aware type
initial_rotation_eps0: str = "0.0 rad" # TODO: unit-aware type
analysis_type: Literal["Monotonic", "Cyclic"] = "Monotonic"
initial_deformation_eps0: str = '0.0m' # TODO: unit-aware type
initial_rotation_eps0: str = '0.0 rad' # TODO: unit-aware type
analysis_type: Literal['Monotonic', 'Cyclic'] = 'Monotonic'
cyclic_data: list[CyclicDataRow] = Field(default_factory=list)
field: Literal["_"] = "_"
set_as_variable: Literal["0", "1"] = "0"
field: Literal['_'] = '_'
set_as_variable: Literal['0', '1'] = '0'

View file

@ -23,307 +23,307 @@ class CyclicDataRow(BaseModel):
class ElasticPerfectlyPlasticWithGapSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Elastic_Perfectly_Plastic_with_Gap",
"x-book": "Standard_Uniaxial_Materials",
"dependencies": [
'x-gid-name': 'Elastic_Perfectly_Plastic_with_Gap',
'x-book': 'Standard_Uniaxial_Materials',
'dependencies': [
{
"field": "formulation",
"gid_name": "Formulation",
"rules": [
'field': 'formulation',
'gid_name': 'Formulation',
'rules': [
{
"trigger": "Stress-Strain",
"actions": [
'trigger': 'Stress-Strain',
'actions': [
{
"action": "RESTORE",
"field": "Elastic_modulus_E",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Elastic_modulus_E',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Yield_Stress_Fy",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Yield_Stress_Fy',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Material_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Material_type',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Strain_gap",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strain_gap',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Deformation_gap",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Deformation_gap',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Stiffness_K",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Stiffness_K',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Force_Fy",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Force_Fy',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Moment_per_rotation_unit",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Moment_per_rotation_unit',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Moment_My",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Moment_My',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Rotation_gap",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Rotation_gap',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Force-Deformation",
"actions": [
'trigger': 'Force-Deformation',
'actions': [
{
"action": "HIDE",
"field": "Elastic_modulus_E",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Elastic_modulus_E',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Steel_grade",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Steel_grade',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Strain_gap",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strain_gap',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Yield_Stress_Fy",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Yield_Stress_Fy',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Material_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Material_type',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Stiffness_K",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Stiffness_K',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Force_Fy",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Force_Fy',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Deformation_gap",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Deformation_gap',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Moment_per_rotation_unit",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Moment_per_rotation_unit',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Moment_My",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Moment_My',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Rotation_gap",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Rotation_gap',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Moment-Rotation",
"actions": [
'trigger': 'Moment-Rotation',
'actions': [
{
"action": "HIDE",
"field": "Elastic_modulus_E",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Elastic_modulus_E',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Steel_grade",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Steel_grade',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Strain_gap",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strain_gap',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Yield_Stress_Fy",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Yield_Stress_Fy',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Material_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Material_type',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Stiffness_K",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Stiffness_K',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Force_Fy",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Force_Fy',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Deformation_gap",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Deformation_gap',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Moment_per_rotation_unit",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Moment_per_rotation_unit',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Moment_My",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Moment_My',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Rotation_gap",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Rotation_gap',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "material_type",
"gid_name": "Material_type",
"rules": [
'field': 'material_type',
'gid_name': 'Material_type',
'rules': [
{
"trigger": "Concrete",
"actions": [
'trigger': 'Concrete',
'actions': [
{
"action": "RESTORE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Steel_grade",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Steel_grade',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Steel",
"actions": [
'trigger': 'Steel',
'actions': [
{
"action": "HIDE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Steel_grade",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Steel_grade',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Yield_Stress_Fy",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Yield_Stress_Fy',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Custom",
"actions": [
'trigger': 'Custom',
'actions': [
{
"action": "HIDE",
"field": "Concrete_class",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Concrete_class',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Steel_grade",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Steel_grade',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Yield_Stress_Fy",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Yield_Stress_Fy',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Strength_type",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Strength_type',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "analysis_type",
"gid_name": "Analysis_type",
"rules": [
'field': 'analysis_type',
'gid_name': 'Analysis_type',
'rules': [
{
"trigger": "Monotonic",
"actions": [
'trigger': 'Monotonic',
'actions': [
{
"action": "HIDE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Cyclic",
"actions": [
'trigger': 'Cyclic',
'actions': [
{
"action": "RESTORE",
"field": "Cyclic_data",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Cyclic_data',
'target': '#CURRENT#',
},
],
},
@ -333,45 +333,23 @@ class ElasticPerfectlyPlasticWithGapSpec(BaseModel):
}
)
material: Literal["ElasticPerfectlyPlasticwithGap"] = Field(
"ElasticPerfectlyPlasticwithGap",
description="elastic perfectly-plastic gap uniaxial material object",
)
formulation: Literal["Stress-Strain", "Force-Deformation", "Moment-Rotation"] = "Stress-Strain"
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"
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
material: Literal['ElasticPerfectlyPlasticwithGap'] = Field('ElasticPerfectlyPlasticwithGap', description='elastic perfectly-plastic gap uniaxial material object')
formulation: Literal['Stress-Strain', 'Force-Deformation', 'Moment-Rotation'] = 'Stress-Strain'
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'
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
deformation_gap: str = "0.0m" # TODO: unit-aware type
rotation_gap: str = "0.0 rad" # TODO: unit-aware type
analysis_type: Literal["Monotonic", "Cyclic"] = "Monotonic"
deformation_gap: str = '0.0m' # TODO: unit-aware type
rotation_gap: str = '0.0 rad' # TODO: unit-aware type
analysis_type: Literal['Monotonic', 'Cyclic'] = 'Monotonic'
cyclic_data: list[CyclicDataRow] = Field(default_factory=list)
field: Literal["_"] = "_"
set_as_variable: Literal["0", "1"] = "0"
field: Literal['_'] = '_'
set_as_variable: Literal['0', '1'] = '0'

View file

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

View file

@ -17,306 +17,306 @@ from pydantic import BaseModel, ConfigDict, Field
class ElasticTimoshenkoBeamColumnSpec(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"x-gid-name": "Elastic_Timoshenko_Beam-Column",
"x-book": "Beam-Column_Elements",
"dependencies": [
'x-gid-name': 'Elastic_Timoshenko_Beam-Column',
'x-book': 'Beam-Column_Elements',
'dependencies': [
{
"field": "cross_section",
"gid_name": "Cross_section",
"rules": [
'field': 'cross_section',
'gid_name': 'Cross_section',
'rules': [
{
"trigger": "Rectangular",
"actions": [
'trigger': 'Rectangular',
'actions': [
{
"action": "RESTORE",
"field": "Height_h",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Height_h',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Width_B",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Width_B',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Diameter_d",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Diameter_d',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Height_hf",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Height_hf',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_bf",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_bf',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_bw",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_bw',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Area_A",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Area_A',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Moment_of_inertia_about_local-y_Iyy",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Moment_of_inertia_about_local-y_Iyy',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Moment_of_inertia_about_local-z_Izz",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Moment_of_inertia_about_local-z_Izz',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Torsional_moment_of_inertia_Iyz",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Torsional_moment_of_inertia_Iyz',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Circular",
"actions": [
'trigger': 'Circular',
'actions': [
{
"action": "HIDE",
"field": "Height_h",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Height_h',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_B",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_B',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Diameter_d",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Diameter_d',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Height_hf",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Height_hf',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_bf",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_bf',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_bw",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_bw',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Area_A",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Area_A',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Moment_of_inertia_about_local-y_Iyy",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Moment_of_inertia_about_local-y_Iyy',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Moment_of_inertia_about_local-z_Izz",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Moment_of_inertia_about_local-z_Izz',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Torsional_moment_of_inertia_Iyz",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Torsional_moment_of_inertia_Iyz',
'target': '#CURRENT#',
},
],
},
{
"trigger": "Tee",
"actions": [
'trigger': 'Tee',
'actions': [
{
"action": "RESTORE",
"field": "Height_h",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Height_h',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_B",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_B',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Diameter_d",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Diameter_d',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Height_hf",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Height_hf',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Width_bf",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Width_bf',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Width_bw",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Width_bw',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Area_A",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Area_A',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Moment_of_inertia_about_local-y_Iyy",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Moment_of_inertia_about_local-y_Iyy',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Moment_of_inertia_about_local-z_Izz",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Moment_of_inertia_about_local-z_Izz',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Torsional_moment_of_inertia_Iyz",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Torsional_moment_of_inertia_Iyz',
'target': '#CURRENT#',
},
],
},
{
"trigger": "General",
"actions": [
'trigger': 'General',
'actions': [
{
"action": "HIDE",
"field": "Height_h",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Height_h',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_B",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_B',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Diameter_d",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Diameter_d',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_bf",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_bf',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Height_hf",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Height_hf',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "Width_bw",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'Width_bw',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Area_A",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Area_A',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Moment_of_inertia_about_local-y_Iyy",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Moment_of_inertia_about_local-y_Iyy',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Moment_of_inertia_about_local-z_Izz",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Moment_of_inertia_about_local-z_Izz',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "Torsional_moment_of_inertia_Iyz",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'Torsional_moment_of_inertia_Iyz',
'target': '#CURRENT#',
},
],
},
],
},
{
"field": "set_modification_factors",
"gid_name": "Set_modification_factors",
"rules": [
'field': 'set_modification_factors',
'gid_name': 'Set_modification_factors',
'rules': [
{
"trigger": "1",
"actions": [
'trigger': '1',
'actions': [
{
"action": "RESTORE",
"field": "mod._A",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'mod._A',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "mod._Sy",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'mod._Sy',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "mod._Sz",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'mod._Sz',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "mod._Iyy",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'mod._Iyy',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "mod._Izz",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'mod._Izz',
'target': '#CURRENT#',
},
{
"action": "RESTORE",
"field": "mod._Iyz",
"target": "#CURRENT#",
'action': 'RESTORE',
'field': 'mod._Iyz',
'target': '#CURRENT#',
},
],
},
{
"trigger": "0",
"actions": [
'trigger': '0',
'actions': [
{
"action": "HIDE",
"field": "mod._A",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'mod._A',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "mod._Sy",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'mod._Sy',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "mod._Sz",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'mod._Sz',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "mod._Iyy",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'mod._Iyy',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "mod._Izz",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'mod._Izz',
'target': '#CURRENT#',
},
{
"action": "HIDE",
"field": "mod._Iyz",
"target": "#CURRENT#",
'action': 'HIDE',
'field': 'mod._Iyz',
'target': '#CURRENT#',
},
],
},
@ -326,33 +326,27 @@ class ElasticTimoshenkoBeamColumnSpec(BaseModel):
}
)
element_type: Literal["ElasticTimoshenkoBeamColumn"] = Field(
"ElasticTimoshenkoBeamColumn",
description="A Timoshenko beam is a frame member that accounts for shear deformations.",
)
compatible_materials: Literal["Elastic_Isotropic"] = "Elastic_Isotropic"
material_mat_multidimensional_nd_materials_user_materials: str = "Elastic_Isotropic"
cross_section: Literal["Rectangular", "Tee", "Circular", "General"] = "Rectangular"
height_h: str = "0.5m" # TODO: unit-aware type
width_b: str = "0.3m" # TODO: unit-aware type
diameter_d: str = "0.5m" # TODO: unit-aware type
width_bf: str = "0.4m" # TODO: unit-aware type
height_hf: str = "0.15m" # TODO: unit-aware type
width_bw: str = "0.25m" # 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_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
set_modification_factors: Literal["1", "0"] = "0"
element_type: Literal['ElasticTimoshenkoBeamColumn'] = Field('ElasticTimoshenkoBeamColumn', description='A Timoshenko beam is a frame member that accounts for shear deformations.')
compatible_materials: Literal['Elastic_Isotropic'] = 'Elastic_Isotropic'
material_mat_multidimensional_nd_materials_user_materials: str = 'Elastic_Isotropic'
cross_section: Literal['Rectangular', 'Tee', 'Circular', 'General'] = 'Rectangular'
height_h: str = '0.5m' # TODO: unit-aware type
width_b: str = '0.3m' # TODO: unit-aware type
diameter_d: str = '0.5m' # TODO: unit-aware type
width_bf: str = '0.4m' # TODO: unit-aware type
height_hf: str = '0.15m' # TODO: unit-aware type
width_bw: str = '0.25m' # 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_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
set_modification_factors: Literal['1', '0'] = '0'
mod_a: int = 1
mod_sy: int = Field(
1, description="This value will be multiplied by the Area (A) for local-y Shear Area (Sy)"
)
mod_sz: int = Field(
1, description="This value will be multiplied by the Area (A) for local-z Shear Area (Sz)"
)
mod_sy: int = Field(1, description='This value will be multiplied by the Area (A) for local-y Shear Area (Sy)')
mod_sz: int = Field(1, description='This value will be multiplied by the Area (A) for local-z Shear Area (Sz)')
mod_iyy: int = 1
mod_izz: int = 1
mod_iyz: int = 1
geometric_transformation: Literal["Linear", "P-Delta", "Corotational"] = "Linear"
weight_density: str = "25 kN/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

File diff suppressed because it is too large Load diff

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