FCS Analysis & Design Check Pipeline
Extracted from the
fcs-HBC-2-tacrproduction codebase (AnalysisSocket/StructureCheck.fcs, FemAnalysis.fcs).
1. Architecture Overview
The full pipeline follows this flow:
LoadGroups ─┐
LoadCases ─┤
Combinations ─┤──► AnalysisCase ──► FEM Solver ──► BeamsFemResults ──► StructureCheck
Model ─┘ │
├──► Internal Forces (extremes)
├──► Displacements (extremes)
├──► Reactions (resultants)
├──► Eigenvalues (stability)
└──► Design Checks ──► Report
2. AnalysisCase — Central Orchestrator
AnalysisCase = res.comp.analysisCase{
AnalysisClass = ModelClass, # the model with geometry & loads
MeshConnect = res.comp.analysisCase.MeshConnect{
ConnectRules = Fcs.Mesh.ConnectRules{
Rules = [Fcs.Mesh.ConnectRules.ConnectClub{ Entities = Fcs.Assembly.All }]
},
AutoConnect = True,
OneMeshElementPerBeam = False, # False = refined mesh
WeldNodes = True,
ElementSize = 0.4, # target element size [m]
DefaultElementType2D = Fcs.Mesh.Element.Quadrilateral,
},
ResultCase = Fcs.Analysis.ResultCase(Fcs.Action.ResultClass{ Name = "All ULS-Fundamental" }),
ResultCaseULS = ResultCase,
ResultCaseSLS = Fcs.Analysis.ResultCase(Fcs.Action.ResultClass{ Name = "All SLS characteristic" }),
LoadCases = ModelClass.loadCases, # list of FitLoadCase objects
LoadGroups = combinations.loadGroups.All, # top-level FitLoadGroup tree
LoadCombinations = combinations.allEnvelopes, # list of FitLoadEnvelope objects
ResultClasses = combinations.resultClasses.All, # list of FitResultClass objects
globalStabilityLinCombination = [],
globalStabilityLoadCaseName = [],
}
Key Properties
| Property | Type | Purpose |
|---|---|---|
AnalysisClass |
gclass | Model containing geometry, beams, loads |
MeshConnect |
object | Mesh generation settings |
ResultCase |
ResultCase | Which combo set to use for extremes |
LoadCases |
list | All FitLoadCase objects |
LoadGroups |
list | Top-level FitLoadGroup hierarchy |
LoadCombinations |
list | Generated envelopes / combos |
ResultClasses |
list | Named groups of combos |
3. MeshConnect — Mesh Settings
MeshConnect = res.comp.analysisCase.MeshConnect{
ConnectRules = Fcs.Mesh.ConnectRules{
Rules = [
Fcs.Mesh.ConnectRules.ConnectClub{ Entities = Fcs.Assembly.All }
]
},
AutoConnect = True, # auto-connect overlapping nodes
OneMeshElementPerBeam = False, # True = 1 element/beam (coarse), False = refined
WeldNodes = True, # merge coincident nodes
ElementSize = 0.4, # target element size [m]
DefaultElementType2D = Fcs.Mesh.Element.Quadrilateral,
}
ConnectRules options:
Fcs.Assembly.All— connect everything to everythingFcs.Assembly.BeamByPath(path)— select specific beams by path
4. ResultCase — Extracting Results for Specific Combo Sets
# For ULS results (named group must match one of the ResultClasses):
ResultCaseULS = Fcs.Analysis.ResultCase(Fcs.Action.ResultClass{ Name = "All ULS-Fundamental" })
# For SLS results:
ResultCaseSLS = Fcs.Analysis.ResultCase(Fcs.Action.ResultClass{ Name = "All SLS characteristic" })
The Name string must match one of the names in ResultClasses, which are auto-generated
by the combination engine. The ResultCase tells the solver which envelope to evaluate
when extracting min/max extremes.
5. BeamsFemResults — Per-Beam Result Extraction
NumberOfBeams = BeamParts.Count
BeamsFemResults = res.f.EnumerableRange(NumberOfBeams).Select(beamId =>
res.comp.SimpleBeamAnalysisResults{
AnalysisCase,
units,
SingleBeam = BeamParts[beamId],
BeamsCount = RepetitiveBeamsCount, # for repetitive member counts
BeamPathFn = beamPathFn(beamId),
IgnoredLayers = [],
SupportVertexes = ModelClass.supportVertex,
beamId,
}
)
Results Available on Each Beam
| Property | Content |
|---|---|
beam.ExtOnBeam.dx.Max/Min |
Displacement extremes |
beam.ExtremeForcesOnResultParts |
Internal force extremes |
beam.ExtremeDisplacementsOnResultParts |
Displacement extremes per part |
beam.ExtremeResultants |
Support reactions |
beam.lambdaEigenModesLoadCase |
Stability eigenvalues per load case |
beam.lambdaEigenModesLinCombination |
Stability eigenvalues for combinations |
beam.SingleBeam |
Beam geometry / section info |
6. StructureCheck — Design Check Pipeline
Setup
analysisSocketReportSetup = Fcs.Reporting.Setup{
LatexSyntax = True,
Units = Fcs.Units.Setup(Fcs.Units.DefaultSteel, ...),
Collapsible = True,
Numbered = True,
}
Check Class Creation
SimpleBeamCheckByCodeClass := res.en.steel.EnSimpleBeamCheck
AllBeamsCheckClasses = res.f.EnumerableRange(NumberOfBeams).Select(beam =>
SimpleBeamCheckByCodeClass{
AnalysisCase = Analysis.AnalysisCase,
SingleBeam = Analysis.BeamParts[beam],
BeamsCount = Analysis.RepetitiveBeamsCount,
BeamPathFn = Analysis.beamPathFn(beam),
IgnoredLayers = Analysis.IgnoredLayers,
AllBeamsSelector = Fcs.Assembly.BeamByPath(memberPathStringFn(beam)),
GlobalDisplacementLengths,
GlobalDisplacementConditions,
units,
}
)
Available Check Flags
| Flag | Check Type |
|---|---|
isAxialMomentCheckOn |
beam.AllAxialMomentChecks |
isAxialForceCheckOn |
beam.AllAxialForceChecks |
isBendingMomentAndShearCheckOn |
beam.AllBendingMomentChecks |
isShearCheckOn |
beam.AllShearForceChecks |
isBucklingYyCheckOn |
beam.AllBucklingYyChecks |
isBucklingZzCheckOn |
beam.AllBucklingZzChecks |
isAxialAndBendingBucklingCheckOn |
beam.AllAxialAndBendingBucklingChecks |
isAxialAndBendingBucklingYyCheckOn |
beam.AllAxialAndBendingBucklingYyChecks |
isAxialAndBendingBucklingZzCheckOn |
beam.AllAxialAndBendingBucklingZzChecks |
isDisplacementCheckOn |
beam.AllDisplacementChecks |
isAnyGlobalDisplacementCheckOn |
beam.AllGlobalDisplacementChecks |
Check Result Structure
Each check returns a collection of singleCheck objects:
singleCheck.AllCheckBones— individual check pointscheckBone.UnityCheck— utilization ratio (0.0–1.0; >1.0 = fail)
Aggregate Results
# Max utilization across all beams
maxCheckByBones = AllBeamsCheckBones.Select(beam =>
beam.Select(checks =>
checks.Select(singleCheck =>
(singleCheck.Count > 0) ? (singleCheck.Max()) : (0)
)
)
)
# Pass/fail per beam
AreChecksOk = res.f.EnumerableRange(NumberOfBeams).Select(beam =>
AllBeamsCheckClasses[beam].partCheckBoolFn(ChecksOnAllBeams[beam], True).All(ch => ch == True)
)
7. Singularity Detection
isModelSingularCalc = (
AllBeamsFemResults.Select(b => [
Abs([b.ExtOnBeam.dx.Max.Value, b.ExtOnBeam.dy.Max.Value, b.ExtOnBeam.dz.Max.Value].Max()),
Abs([b.ExtOnBeam.dx.Min.Value, b.ExtOnBeam.dy.Min.Value, b.ExtOnBeam.dz.Min.Value].Min()),
].Max()).Max() >= 10 * Unit.m
)
If any displacement exceeds 10 metres the model is considered singular (unstable).
8. Geometry Table for Report
geometryHeaderRow = [
Fcs.Reporting.Text("Id"),
Fcs.Reporting.Text("Name"),
Fcs.Reporting.Text("Layer"),
Fcs.Reporting.Text("Length"),
Fcs.Reporting.Text("Section"),
Fcs.Reporting.Text("Start coordinates"),
Fcs.Reporting.Text("End coordinates"),
]
# Per-beam row with LCS origin/end extraction:
lcsToOriginCoorsFn = fnLcs => ("(" +
fnLcs.Origin.X.ToString("0.000") + ", " +
fnLcs.Origin.Y.ToString("0.000") + ", " +
fnLcs.Origin.Z.ToString("0.000") + ")")
9. Quick Reference
# 1. Wrap model + combos in an AnalysisCase
ac = res.comp.analysisCase{
AnalysisClass = MyModel,
MeshConnect = ...,
LoadCases = MyModel.loadCases,
LoadGroups = combos.loadGroups.All,
LoadCombinations = combos.allEnvelopes,
ResultClasses = combos.resultClasses.All,
ResultCase = Fcs.Analysis.ResultCase(Fcs.Action.ResultClass{ Name = "All ULS-Fundamental" }),
}
# 2. Extract per-beam results
beamResults = res.f.EnumerableRange(nBeams).Select(id =>
res.comp.SimpleBeamAnalysisResults{ AnalysisCase = ac, SingleBeam = beams[id], beamId = id })
# 3. Run design checks
checks = res.f.EnumerableRange(nBeams).Select(id =>
res.en.steel.EnSimpleBeamCheck{ AnalysisCase = ac, SingleBeam = beams[id] })
# 4. Check if model is singular
isSingular = beamResults.Select(b => b.ExtOnBeam.dx.Max.Value).Max() >= 10