staad-supports — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited staad-supports (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Fixed — restrains all 6 DOF:
fix_id = sup.CreateSupportFixed()Pinned — translations restrained, rotations free:
pin_id = sup.CreateSupportPinned()Fixed-But — selective releases or springs:
# releaseSpec: [FX,FY,FZ,MX,MY,MZ] → 0=fixed, 1=released, -1=spring
# springSpec: [KFX,KFY,KFZ,KMX,KMY,KMZ] → spring stiffness
sup_id = sup.CreateSupportFixedBut(
ReleaseSpec=[0, -1, 0, 0, 0, 1], # FY=spring, MZ=released
SpringSpec=[0, 100.0, 0, 0, 0, 0] # KFY=100
)sup_id = sup.CreateInclinedSupport(
inclinedType=2, # 1=Pinned, 2=Fixed, 3=FixedBut
refType=2, # 0=distances, 1=coordinates, 2=node reference
refNode=1,
coord=[0, 0, 0],
releaseSpec=[0,0,0,0,0,0],
springSpec=[0,0,0,0,0,0]
)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.
# Typical case: springs in Y direction (STAAD adds X/Z fixity for stability)
mat_id = sup.CreateElasticMat(
direction=1, # 1=Y Direction (use for most foundations)
subgrade=20.0, # CURRENT SetInputUnits, e.g. kN/m^3 if input=Meter/kN — converted to base internally, NOT the model's base unit
printFlag=0,
springType=0 # 0=Normal (bi-directional); 1=Compression only
)
sup.AssignSupportToEntityList(mat_id, [41, 42, 43])
# GetElasticMatDetail(mat_id) returns subgrade in FIXED base units afterward
# (live-verified: unaffected by later SetInputUnits calls) — see staad-core
# Units & Axis for the verification pattern if the value looks off.
# 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.# subgrades: CURRENT SetInputUnits (same convention as CreateElasticMat above)
# GetPlateMatDetail(pm_id) returns a FIXED base-unit value afterward
pm_id = sup.CreatePlateMat(direction, subgrades, printFlag, springType)foot_id = sup.CreateElasticFooting(length, width, direction, subgrade)Marks an existing support spring at a node as tension-only or compression-only — per STAAD.Pro's SPRING TENSION/COMPRESSION command (TR.27.5), this only marks a spring that's already there, it does not create one. The node must already have a real spring in that DOF first (via CreateSupportFixedBut with ReleaseSpec=-1 and a real SpringSpec value).
Use `SetSupportSpringBehavior`, NOT `CreateTensionOnlySpring`/`CreateCompressionOnlySpring` (see Gotchas — the latter are broken and must not be used):
fb_id = sup.CreateSupportFixedBut(ReleaseSpec=[0, -1, 0, 0, 0, 0], SpringSpec=[0, 1000.0, 0, 0, 0, 0])
sup.AssignSupportToEntityList(fb_id, [9]) # real spring in FY at node 9, established first
sup.SetSupportSpringBehavior(1, [9], [0, 1, 0]) # 0=compression-only, 1=tension-only; springFlags=[FX,FY,FZ] enablecompressionOrTensionFlag: 0 = compression-only, 1 = tension-only (per the openstaadpy source docstring — note this is the OPPOSITE of what might seem intuitive; verified against source, not just live behavior, since GetSupportInformationEx does not expose which of the two was actually set). springFlags is a 3-element [FX,FY,FZ] enable array, matching the directions that already have a real spring. Raises [-7504] Spring not defined at node. only if the node has no spring in ANY direction — this check is NOT per-direction: if the node has a real spring in FY but you pass springFlags=[1,0,0] (FX, which has no spring), the call succeeds silently and creates the same broken, unanalyzable state as CreateTensionOnlySpring (confirmed live). Always verify each flagged direction individually against GetSupportInformationEx(nodeNo)'s springs array before calling — do not rely on the function to catch a direction-specific mismatch. When the flagged direction does have a real spring, it modifies the existing support in place (same support ID, stiffness preserved) — confirmed live: GetSupportInformationEx(nodeNo) afterward is unchanged from before the call, and analysis succeeds.
sup.AssignSupportToNode(nodeID, supportID) — assigns to a SINGLE nodefor loop to assign to multiple nodesGetSupportInformationEx(nodeNo) to see what support (if any) isalready on the node (see Gotchas for the exception it raises on an unsupported node). Assigning always replaces the support with no error or warning. Report what was there before and what it becomes after — do not skip this step, and do not block the assignment just because a prior support exists. See assign-fixed-supports.py for a working example of this guarded check.
execute_code to call staad.Geometry.GetNodeCount() and confirm the model has nodesSaveModel(True) before assigning supports (see staad-core for SaveModel vs UpdateStructure)| Function | Returns |
|---|---|
GetSupportCount() | count of supported nodes, equal to len(GetSupportNodes()); one definition on N nodes counts N |
GetSupportNodes() | list of supported node IDs |
GetSupportType(nodeNo) | support type code (see SUPPORT_CODES.md) |
GetSupportInformation(nodeNo) | (type, releases, springs) |
GetSupportInformationEx(nodeNo) | (supportNo, type, releases, springs) — type includes 14=CompressionOnlySpring, 15=TensionOnlySpring (see SUPPORT_CODES.md) |
GetSupportName(nodeNo) | name of the support sitting on that node; "No support" when the node is free |
GetCountOfElasticMat() | elastic mat count |
GetElasticMatDetail(matId) | (direction, subgrade, print, spring, nodeCount) |
GetElasticMatAssignmentList(matId) | assigned node IDs |
GetCountOfPlateMat() | plate mat count |
GetPlateMatSupportId(index) | support ID at index (0-based) |
GetPlateMatDetail(matId) | (direction, subgrade1-3, print, spring, plateCount) |
GetPlateMatAssignmentList(matId) | assigned plate IDs |
GetCountOfElasticFooting() | elastic footing count |
GetElasticFootingDetail(footId) | (length, width, direction, subgrade, nodeCount) |
GetElasticFootingAssignmentList(footId) | assigned node IDs |
GetSupportUniqueID(supportNo) | GUID string |
sup.SetSupportUniqueID(supportNo, guid)sup.RemoveSupportFromNode([1, 2, 3]) # remove from nodes
sup.DeleteSupport(supportNo) # delete definition
sup.RemoveElasticMatFromNode(nodeNo) # remove elastic mat from node
sup.RemoveElasticMat(matId) # delete elastic mat definition
sup.RemovePlateMatFromPlate(plateNo) # remove plate mat from plate
sup.RemovePlateMat(matId) # delete plate mat definition
sup.RemoveElasticFootingFromNode(nodeNo) # remove elastic footing from node
sup.RemoveElasticFooting(footId) # delete elastic footing definitionSee assign-fixed-supports.py for a complete working example. See check-tension-compression-spring.py for verifying a Tension/Compression-Only spring assignment actually produced a usable spring before running analysis.
AssignSupportToNode takes a SINGLE node ID — it does NOT accept a list; iterate with a loopCreateSupportFixed, CreateSupportPinned, CreateSupportFixedBut, AssignSupportToNode, GetSupportNodes, GetSupportType, GetSupportInformation, DeleteSupport) raise on failure instead of returning a negative code — call them directly; execute_code reports any uncaught errornodeNo in sup.GetSupportNodes() first, or wrap the call in try/except, before querying a node that might be unsupported (see assign-fixed-supports.py for the guarded pattern).SaveModel(True) before assigning supports — do NOT use UpdateStructure() (it discards unsaved geometry)CreateSupportFixedBut: use -1 for spring DOFs (not 1); 1 = released, 0 = fixed, -1 = springspringType=1 and to SetSupportSpringBehavior-marked springs alike.Create... call) to an unrelated node with NO prior support at all (nothing to destroy) reproduces the identical zero-stiffness result — ruling out "it works but assignment destroys a real spring that was already there." It also always creates a new support definition and assigns it via AssignSupportToEntityList, which replaces whatever was on the target node — it does not modify an existing spring in place, unlike the real STAAD.Pro SPRING TENSION/COMPRESSION command it's meant to represent. Any model built with these two functions will fail analysis with ERROR: SPRING TENSION/COMPRESSION SPECIFIED AT A JOINT DIRECTION THAT DOES [NOT HAVE A SPRING] (status 4).StaadWriter.cs), which calls only this function, never CreateTensionOnlySpring/CreateCompressionOnlySpring:compressionOrTensionFlag: 0 = compression-only, 1 = tension-only — per the openstaadpy source docstring. This is easy to get backwards; GetSupportInformationEx does not expose which of the two was actually applied, so double-check against the source rather than assuming.[-7504] Spring not defined at node. only if the node has NO spring in any direction. If the node has a real spring in FY but you flag FX (which has none), it succeeds silently and creates the same broken, unanalyzable state as the two functions above — confirmed live. Always check each flagged direction individually against GetSupportInformationEx(nodeNo) before calling.GetSupportInformationEx(nodeNo) is unchanged (same support ID, same stiffness) before and after the call, and the resulting model analyzes successfully. Every other getter reports the underlying spring too, so type codes 14/15 show up only for a node whose own support is a spring entry from the two functions above. Confirm a marking took effect through the analysis reactions.CreateSupportFixedBut (ReleaseSpec=-1, real SpringSpec value), assign it, THEN call SetSupportSpringBehavior — see check-tension-compression-spring.py.RemoveSupportFromNode on it, analysis fails on the entire model with the same "...DOES [NOT HAVE A SPRING]" error, even though GetSupportNodes() shows the node as unsupported. There is no known function in this API to clear that list once a node has been added to it. If you need to "undo" a tension/compression-only marking, leave a real spring on the node (do not fully remove its support) — removing it entirely leaves the model permanently broken for analysis.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.