diff --git a/src/openstaad_mcp/staad_skills/staad-analysis/SKILL.md b/src/openstaad_mcp/staad_skills/staad-analysis/SKILL.md index 083ffe0..17c0d85 100644 --- a/src/openstaad_mcp/staad_skills/staad-analysis/SKILL.md +++ b/src/openstaad_mcp/staad_skills/staad-analysis/SKILL.md @@ -129,3 +129,4 @@ See [run-analysis.py](./scripts/run-analysis.py) for a complete working example. - Wrap `AnalyzeModel`/`AnalyzeEx` in `SetSilentMode(True/False)` to prevent blocking dialogs - For design workflows always use `AnalyzeEx(1, 0, 1)` — never `AnalyzeModel` - `AnalyzeEx` runs both analysis AND design; `AnalyzeModel` runs analysis only +- **Compression-only springs/supports (elastic mat, plate mat with `springType=1`) are incompatible with P-Delta, Nonlinear, Buckling, and Cable analysis** — the engine uses member/spring deactivation iterations that cannot coexist with geometric nonlinearity or those other solver loops. The engine will throw an error. Use plain `PerformAnalysis` + `AnalyzeEx` for models with compression-only supports. diff --git a/src/openstaad_mcp/staad_skills/staad-geometry/SKILL.md b/src/openstaad_mcp/staad_skills/staad-geometry/SKILL.md index 391596a..e51dfc5 100644 --- a/src/openstaad_mcp/staad_skills/staad-geometry/SKILL.md +++ b/src/openstaad_mcp/staad_skills/staad-geometry/SKILL.md @@ -13,17 +13,20 @@ description: 'Use when creating, querying, modifying, or selecting structure geo - `geo.AddNode(x, y, z)` → node ID (coordinates in base unit) - `geo.AddBeam(startNode, endNode)` → beam ID - `geo.AddPlate(n1, n2, n3, n4)` → plate ID — pass **4 separate int args**, NOT a list + - **Triangle:** the API always takes 4 args; pass `0` as a sentinel for the missing 4th node → `geo.AddPlate(n1, n2, n3, 0)` - `geo.AddSolid(n1, n2, n3, n4, n5, n6, n7, n8)` → solid ID ### Bulk Creation (more efficient than loops) - `geo.AddMultipleNodes([[x,y,z], ...])` → list of node IDs - `geo.AddMultipleBeams([[start,end], ...])` → list of beam IDs - `geo.AddMultiplePlates([[n1,n2,n3,n4], ...])` → list of plate IDs + - **Triangle rows:** each row must have exactly 4 ints; use `0` as the sentinel 4th element → `[n1, n2, n3, 0]` ### Explicit ID Creation - `geo.CreateNode(nodeNo, x, y, z)` — creates node with a specific ID - `geo.CreateBeam(beamNo, startNode, endNode)` — beam with specific ID -- `geo.CreatePlate(plateNo, nA, nB, nC, nD)` — plate with specific ID (nD=0 for triangle) +- `geo.CreatePlate(plateNo, nA, nB, nC, nD)` — plate with specific ID + - **Triangle:** pass `0` for `nD` (the sentinel for a missing 4th node) → `geo.CreatePlate(id, nA, nB, nC, 0)` - `geo.CreateSolid(solidNo, nA, nB, nC, nD, nE, nF, nG, nH)` — solid with specific ID ### Shared Element ID Sequence @@ -128,9 +131,11 @@ pm_count = geo.GetPhysicalMemberCount() ## Examples - [portal-frame.py](./scripts/portal-frame.py) — create a simple portal frame with supports - [add-beam.py](./scripts/add-beam.py) — add a single beam between two new nodes +- [add-plate.py](./scripts/add-plate.py) — create quad and triangular plates (shows the `0` triangle convention) - [select-members.py](./scripts/select-members.py) — select single and multiple beams ## Gotchas +- **Triangle plates use `0` as a sentinel:** all plate functions always take exactly 4 node arguments; `0` tells STAAD the slot is empty (i.e., this is a 3-node element). See [add-plate.py](./scripts/add-plate.py) for a full example. - `AddPlate` takes 4 separate int arguments, NOT a list — `geo.AddPlate(n1, n2, n3, n4)` not `geo.AddPlate([n1,n2,n3,n4])` - After adding geometry in the same script, call `staad.SetSilentMode(True)` → `staad.SaveModel(True)` → `staad.SetSilentMode(False)` before assigning properties, supports, or loads — do NOT use `UpdateStructure()` (it discards unsaved in-memory geometry) - Always use `geo` (OSGeometry) for selections — do NOT use `OSView.SelectByItemList` diff --git a/src/openstaad_mcp/staad_skills/staad-geometry/scripts/add-plate.py b/src/openstaad_mcp/staad_skills/staad-geometry/scripts/add-plate.py new file mode 100644 index 0000000..aabaf0a --- /dev/null +++ b/src/openstaad_mcp/staad_skills/staad-geometry/scripts/add-plate.py @@ -0,0 +1,42 @@ +# add-plate.py +# Demonstrates creating quad plates and triangular plates. +# +# TRIANGLE SENTINEL: all plate functions take exactly 4 node args. +# Pass 0 as the 4th arg to signal a 3-node (triangular) plate. +# geo.AddPlate(n1, n2, n3, 0) <- triangle +# geo.AddMultiplePlates([[n1,n2,n3,0]]) <- triangle row +# geo.CreatePlate(id, nA, nB, nC, 0) <- explicit-ID triangle + +geo = staad.Geometry + +# ── Quad plate (4 corners in a 1×1 square) ────────────────────────────────── +n1 = geo.AddNode(0, 0, 0) +n2 = geo.AddNode(1, 0, 0) +n3 = geo.AddNode(1, 1, 0) +n4 = geo.AddNode(0, 1, 0) + +quad_id = geo.AddPlate(n1, n2, n3, n4) +print(f'Quad plate {quad_id}: nodes {n1},{n2},{n3},{n4}') + +# ── Triangular plate (apex above the midpoint) ─────────────────────────────── +n5 = geo.AddNode(0.5, 0, 1) # apex node + +# 0 is the sentinel for the missing 4th node +tri_id = geo.AddPlate(n1, n2, n5, 0) +print(f'Triangle plate {tri_id}: nodes {n1},{n2},{n5} (4th arg = 0 sentinel)') + +# ── Bulk creation mixing quads and triangles ───────────────────────────────── +# Each row has exactly 4 ints; 0 is the sentinel for triangle (no 4th node) +plate_data = [ + [n1, n2, n3, n4], # quad + [n1, n2, n5, 0], # triangle (0 = sentinel, no 4th node) + [n2, n3, n5, 0], # triangle (0 = sentinel, no 4th node) +] +plate_ids = geo.AddMultiplePlates(plate_data) +print(f'Bulk plates: {plate_ids}') + +# ── Explicit-ID creation (triangle) ────────────────────────────────────────── +# geo.CreatePlate(plateNo, nA, nB, nC, nD) — nD=0 is the sentinel for triangle +next_id = max(geo.GetPlateList()) + 1 +geo.CreatePlate(next_id, n1, n3, n5, 0) # nD=0 → triangle sentinel +print(f'Explicit-ID triangle plate {next_id}') diff --git a/src/openstaad_mcp/staad_skills/staad-supports/SKILL.md b/src/openstaad_mcp/staad_skills/staad-supports/SKILL.md index 684913f..4160e1a 100644 --- a/src/openstaad_mcp/staad_skills/staad-supports/SKILL.md +++ b/src/openstaad_mcp/staad_skills/staad-supports/SKILL.md @@ -51,13 +51,18 @@ Spring support distributed over tributary area. See **[SUPPORT_CODES.md — Direction Codes](./assets/SUPPORT_CODES.md)** for `direction` values and **[SUPPORT_CODES.md — Spring Types](./assets/SUPPORT_CODES.md)** for `springType`. ```python +# Typical case: springs in Y direction (STAAD adds X/Z fixity for stability) mat_id = sup.CreateElasticMat( - direction=5, # Y Only — compression only in Y + direction=1, # 1=Y Direction (use for most foundations) subgrade=20.0, # kN/m^3 or equivalent printFlag=0, - springType=1 # 1=Compression only + springType=0 # 0=Normal (bi-directional); 1=Compression only ) sup.AssignSupportToEntityList(mat_id, [41, 42, 43]) + +# Y Only (direction=4): springs act ONLY in Y — use only when the model already +# has other supports (e.g. pinned/fixed nodes) providing X and Z restraint. +# Without those, the structure will be unstable in X/Z. ``` ### Plate Mat Support @@ -89,7 +94,7 @@ foot_id = sup.CreateElasticFooting(length, width, direction, subgrade) | --------------------------------- | ------------------------------------------------- | | `GetSupportCount()` | total supports | | `GetSupportNodes()` | list of supported node IDs | -| `GetSupportType(nodeNo)` | support type code | +| `GetSupportType(nodeNo)` | support type code (see SUPPORT_CODES.md) | | `GetSupportInformation(nodeNo)` | `(type, releases, springs)` | | `GetSupportInformationEx(nodeNo)` | `(supportNo, type, releases, springs)` | | `GetSupportName(supportNo)` | support name | @@ -114,3 +119,4 @@ See [assign-fixed-supports.py](./scripts/assign-fixed-supports.py) for a complet - `AssignSupportToNode` takes a SINGLE node ID — it does NOT accept a list; iterate with a loop - When nodes were added in-memory in the same script, call `SaveModel(True)` before assigning supports — do NOT use `UpdateStructure()` (it discards unsaved geometry) - For `CreateSupportFixedBut`: use `-1` for spring DOFs (not `1`); `1` = released, `0` = fixed, `-1` = spring +- **Compression-only supports (`springType=1`) are only compatible with plain linear static analysis** — using them with P-Delta, Nonlinear, Buckling, or Cable analysis causes an engine error. The engine uses spring deactivation iterations that cannot coexist with those solver modes. diff --git a/src/openstaad_mcp/staad_skills/staad-supports/assets/SUPPORT_CODES.md b/src/openstaad_mcp/staad_skills/staad-supports/assets/SUPPORT_CODES.md index 78f8b8e..81391f9 100644 --- a/src/openstaad_mcp/staad_skills/staad-supports/assets/SUPPORT_CODES.md +++ b/src/openstaad_mcp/staad_skills/staad-supports/assets/SUPPORT_CODES.md @@ -22,15 +22,37 @@ Used in `CreateElasticMat()`, `CreatePlateMat()`, `GetElasticMatDetail()`. -| Value | Direction | -| ----- | ---------------------------------------- | -| 0 | X Direction | -| 1 | Y Direction | -| 2 | Z Direction | -| 3 | X Only Direction (compression only in X) | -| 4 | Y Only Direction (compression only in Y) | -| 5 | Z Only Direction (compression only in Z) | -| 6 | All Directions (plate mat only) | +| Value | Direction | +| ----- | -------------------------------------------------------------------------------------- | +| 0 | X Direction | +| 1 | Y Direction *(typical for soil springs — use for most foundations)* | +| 2 | Z Direction | +| 3 | X Only — springs act in X only; model needs other supports for Y/Z stability | +| 4 | Y Only — springs act in Y only; model needs other supports for X/Z stability | +| 5 | Z Only — springs act in Z only; model needs other supports for X/Y stability | +| 6 | All Directions (plate mat only) | + +## GetSupportType Return Codes + +Returned by `GetSupportType(nodeNo)` and embedded in `GetSupportInformation` / `GetSupportInformationEx`. + +| Value | Type | +| ----- | --------------------------------- | +| 0 | No support | +| 1 | Pinned | +| 2 | Fixed | +| 3 | Fixed with releases (FixedBut) | +| 4 | Enforced displacement | +| 5 | Enforced with releases | +| 6 | Inclined support | +| 7 | Elastic footing | +| 8 | Elastic mat | +| 9 | Plate mat | +| 10 | Multi-linear spring | +| 11 | Generated pinned | +| 12 | Generated fixed | +| 13 | Generated fixed with releases | +| -1 | Error | ## Spring Types