FCS Worked Examples
This document provides annotated complete examples of FCS scripts.
Example 1: Cooling Tower Shell (temelin3.fcs)
A complete shell structure model demonstrating geometry, meshing, materials, members, supports, and loads.
######################################
## Automatic FemCAD script file ##
######################################
#=============================================================================
# GEOMETRY PARAMETERS
#=============================================================================
# Tower dimensions
topH = 150 # Height at top
topR = 80/2 # Top radius (diameter/2)
midH = 120 # Height at middle section
midR = 70/2 # Middle radius
botH = 0 # Height at bottom (ground level)
botR = 130/2 # Bottom radius
# Helper constants
s2 = 0.7071 # sqrt(2)/2 for 45° positions
meshH = 5 # Mesh element size
#=============================================================================
# VERTEX DEFINITIONS
# Define key points on the shell surface
#=============================================================================
# Cardinal points (0°, 90°, 180°, 270°) at each level
vertex {Vb1} xyz botR 0 botH # Bottom, +X direction
vertex {Vm1} xyz midR 0 midH # Middle, +X direction
vertex {Vt1} xyz topR 0 topH # Top, +X direction
vertex {Vb2} xyz 0 botR botH # Bottom, +Y direction
vertex {Vm2} xyz 0 midR midH # Middle, +Y direction
vertex {Vt2} xyz 0 topR topH # Top, +Y direction
vertex {Vb3} xyz -botR 0 botH # Bottom, -X direction
vertex {Vm3} xyz -midR 0 midH # Middle, -X direction
vertex {Vt3} xyz -topR 0 topH # Top, -X direction
vertex {Vb4} xyz 0 -botR botH # Bottom, -Y direction
vertex {Vm4} xyz 0 -midR midH # Middle, -Y direction
vertex {Vt4} xyz 0 -topR topH # Top, -Y direction
# Intermediate points (45°, 135°, 225°, 315°) for arc control
vertex {Vb12} xyz +s2*botR +s2*botR botH # 45° at bottom
vertex {Vb23} xyz -s2*botR +s2*botR botH # 135° at bottom
vertex {Vb34} xyz -s2*botR -s2*botR botH # 225° at bottom
vertex {Vb41} xyz +s2*botR -s2*botR botH # 315° at bottom
vertex {Vt12} xyz +s2*topR +s2*topR topH # 45° at top
vertex {Vt23} xyz -s2*topR +s2*topR topH # 135° at top
vertex {Vt34} xyz -s2*topR -s2*topR topH # 225° at top
vertex {Vt41} xyz +s2*topR -s2*topR topH # 315° at top
#=============================================================================
# CURVE DEFINITIONS
# Create arcs connecting the vertices
#=============================================================================
# Vertical generator curves (arc through bottom-middle-top at each position)
curve {Cv1} arc vertex {Vb1} {Vm1} {Vt1}
curve {Cv2} arc vertex {Vb2} {Vm2} {Vt2}
curve {Cv3} arc vertex {Vb3} {Vm3} {Vt3}
curve {Cv4} arc vertex {Vb4} {Vm4} {Vt4}
# Horizontal arcs at bottom (quarter circles)
curve {Cb12} arc vertex {Vb1} {Vb12} {Vb2} # Quadrant 1
curve {Cb23} arc vertex {Vb2} {Vb23} {Vb3} # Quadrant 2
curve {Cb34} arc vertex {Vb3} {Vb34} {Vb4} # Quadrant 3
curve {Cb41} arc vertex {Vb4} {Vb41} {Vb1} # Quadrant 4
# Horizontal arcs at top (quarter circles)
curve {Ct12} arc vertex {Vt1} {Vt12} {Vt2}
curve {Ct23} arc vertex {Vt2} {Vt23} {Vt3}
curve {Ct34} arc vertex {Vt3} {Vt34} {Vt4}
curve {Ct41} arc vertex {Vt4} {Vt41} {Vt1}
#=============================================================================
# SURFACE PATCHES
# Define four quadrant areas bounded by curves
#=============================================================================
area 1 boundary curve {Cv1} {Ct12} {Cv2} {Cb12}
area 2 boundary curve {Cv2} {Ct23} {Cv3} {Cb23}
area 3 boundary curve {Cv3} {Ct34} {Cv4} {Cb34}
area 4 boundary curve {Cv4} {Ct41} {Cv1} {Cb41}
#=============================================================================
# ANALYSIS MODEL SETUP
#=============================================================================
# Declare this is a 3D shell model
model_shell3d
# Generate triangular mesh on each surface patch
mesharea 1 mesh_type MappedTrias h meshH
mesharea 2 mesh_type MappedTrias h meshH
mesharea 3 mesh_type MappedTrias h meshH
mesharea 4 mesh_type MappedTrias h meshH
#=============================================================================
# MATERIAL & THICKNESS
#=============================================================================
# Concrete material properties
# rho=density, alpha=temp factor, lambda=conductivity, c=heat capacity
# E=Young's modulus (MPa), ni=Poisson's ratio
material {concrete} rho 2500 alpha 40 lambda 1.2E-05 c 440 linear E 35000 ni 0.2
# Shell thickness (1 meter) using concrete
thickness 1 material {concrete} t 1
#=============================================================================
# STRUCTURAL MEMBERS
# Assign thickness to areas (plane stress shell elements)
#=============================================================================
planestress 1 area 1 section 1
planestress 2 area 2 section 1
planestress 3 area 3 section 1
planestress 4 area 4 section 1
#=============================================================================
# BOUNDARY CONDITIONS
# Fixed supports at the base (all DOFs constrained)
#=============================================================================
support 1 curve {Cb12} fixed "uxuyuzrxryrz"
support 2 curve {Cb23} fixed "uxuyuzrxryrz"
support 3 curve {Cb34} fixed "uxuyuzrxryrz"
support 4 curve {Cb41} constant 0 0 0 0 0 0 fixed "uxuyuzrxryrz"
#=============================================================================
# LOADS
# Distributed load on one edge of the top rim
#=============================================================================
# Load case 1: vertical distributed load on curve Ct23
# Constant intensity: fx=0, fy=0, fz=-0.1, mx=0, my=0, mz=0
load 1 case 1 curve {Ct23} constant 0 0 -0.1 0 0 0
Key Learnings:
- Variables are defined with
name = valueorname := value - Vertices use
xyzfor 3D coordinates - Curves can be
arc(through 3 points) or straight - Areas use
boundary curveto list bounding curves - Model type must be declared before mesh/members
- Material, thickness, and section work together
- Supports use DOF strings like "uxuyuzrxryrz"
Example 2: Steel Frame with Beams (Cage.fcs)
Demonstrates beam elements, cross-section classes, and distributions.
############################
## FemCAD script file ##
############################
#=============================================================================
# DESIGN PARAMETERS
#=============================================================================
D := 0.05 # Tube diameter [m]
a := 0.4 # Inner ladder width (clear)
b := 0.3 # Rung spacing
hC := 2 # Cage height
aC := 0.7 # Cage width
bC := 0.75 # Cage depth
rC := 0.35 # Cage corner radius
tH := 0.005 # Hoop strip thickness
aH := 0.02 # Hoop strip width
s := 0.5 # Distance between hoops
nHoops := Ceiling(hC/s) # Calculate number of hoops
dC := 0.010 # Vertical bar diameter
overlap := 0.3 # Bar overlap length
#=============================================================================
# HORIZONTAL HOOPS (using GClass/GBlock)
#=============================================================================
# Define hoop geometry class from external file
gclass 1 filename ("Hoop.fcs") parameters {D = D, aC = aC, bC = bC, rC = rC}
# Instantiate top and bottom hoops
gblock {hoopBottom} gclass 1 lcs GCS
gblock {hoopTop} gclass 1 lcs (GCS.Tz(hC-aH))
# Distribute hoops vertically
distribution 1 geometries {hoopTop} {hoopBottom} repetitions count nHoops
#=============================================================================
# VERTICAL BARS
#=============================================================================
# Cross-section geometry class for circular section
gclass 2 filename ("Circle.fcs") parameters {D = dC}
# Offset from centerline (half thickness + half diameter)
odOsy := tH/2 + dC/2
# Define vertical bar endpoints
vertex 1 xyz 0 (-bC+odOsy) -overlap
vertex 2 xyz 0 (-bC+odOsy) hC+overlap
vertex 3 xyz ((-aC)/2+odOsy) ((-bC)+rC) -overlap
vertex 4 xyz ((-aC)/2+odOsy) ((-bC)+rC) hC+overlap
vertex 5 xyz ((aC)/2-odOsy) ((-bC)+rC) -overlap
vertex 6 xyz ((aC)/2-odOsy) ((-bC)+rC) hC+overlap
vertex {v10} xyz (-a/2+odOsy) (-D/2) -overlap
vertex {v11} xyz (a/2-odOsy) (-D/2) -overlap
# Vertical bar curves
curve 1 vertex 1 2
curve 2 vertex 3 4
curve 3 vertex 5 6
#=============================================================================
# ANALYSIS MODEL
#=============================================================================
material 1 # Use default material (material ID 1)
cross_section 1 geometry_class 2 # Reference circular cross-section
model_shell3d # 3D shell/frame model
OneMeshElementPerBeam = True # Single element per beam (frame analysis)
#=============================================================================
# BEAM MEMBERS
#=============================================================================
beam 1 type Frame curve 1 xsection 1
beam {b2} type Frame curve 2 xsection 1
beam {b3} type Frame curve 3 xsection 1
# Distribute beams across width
distribution 5 geometries {b2} {v10} repetitions count 4
distribution 6 geometries {b3} {v11} repetitions count 4
Key Learnings:
- Use
:=for mutable variables Ceiling()is a built-in math functiongclassloads parametric components from external filesgblockinstantiates with specific LCS and parametersGCS.Tz(height)translates in Z directiondistributioncreates repeated copiesbeam type Framefor 3D frame elementscross_section geometry_classlinks section to geometry
Example 3: Variable I-Beam Frame (prFrameMid2.fcs)
Demonstrates variable cross-sections using traction.
#=============================================================================
# FRAME PARAMETERS
#=============================================================================
L := 8 # Total span
LL := L/2 # Left half span
LR := L/2 # Right half span
hL := 4 # Left column height
hP := 5 # Peak height
hR := 6 # Right column height (asymmetric)
# Calculate roof angles
alfaL := Atan((hP-hL)/LL) # Left rafter angle
alfaR := Atan((hP-hR)/LR) # Right rafter angle
OneMeshElementPerBeam = True
#=============================================================================
# VISUALIZATION
#=============================================================================
layer {Primary} color Orange
#=============================================================================
# FRAME GEOMETRY
#=============================================================================
# Corner vertices
vertex 1 xyz 0 0 0 # Left base
vertex 2 xyz 0 0 hL # Left eave
vertex 3 xyz LL 0 hP # Ridge
vertex 4 xyz L 0 hR # Right eave
vertex 5 xyz L 0 0 # Right base
# Frame member curves
curve 1 vertex 1 2 # Left column
curve 2 vertex 2 3 # Left rafter
curve 3 vertex 3 4 # Right rafter
curve 4 vertex 4 5 # Right column
#=============================================================================
# PARAMETRIC CROSS-SECTION
#=============================================================================
# Load I-profile class (height h is parameter)
gclass {gCss} filename "css\I_profile_rotated.fcs"
# Cross-sections at key locations with varying heights
# Note: gbCss1.h references the block's own 'h' property for self-positioning
gblock {gbCss1} gclass {gCss} lcs {Origin={gbCss1.h/2,0,0}, Axes={GCS.Axes}} parameters {h:=0.3}
gblock {gbCss2} gclass {gCss} lcs {
Origin = {gbCss2.h/2*Cos((-alfaL+PI/2)/2), 0, hL-gbCss2.h/2*Sin((-alfaL+PI/2)/2)},
Axes = {GCS.Axes.Ry((-alfaL+PI/2)/2)}
} parameters {h:=0.8}
gblock {gbCss3} gclass {gCss} lcs {
Origin = {LL, 0, hP-gbCss3.h/2},
Axes = {GCS.Axes.Ry(PI/2)}
} parameters {h:=0.3}
gblock {gbCss4} gclass {gCss} lcs {
Origin = {LL+LR+gbCss4.h/2*Cos(PI/2+(alfaR+PI/2)/2), 0, hR-gbCss4.h/2*Sin(PI/2+(alfaR+PI/2)/2)},
Axes = {GCS.Axes.Ry(PI/2+(alfaR+PI/2)/2)}
} parameters {h:=0.8}
gblock {gbCss5} gclass {gCss} lcs {
Origin = {LL+LR-gbCss5.h/2, 0, 0},
Axes = {GCS.Axes.Ry(PI)}
} parameters {h:=0.3}
#=============================================================================
# VARIABLE SECTIONS (TRACTIONS)
# Loft between cross-sections for variable-depth beams
#=============================================================================
traction {tBeam1} sections {gbCss1, gbCss2} layer {Primary} # Column base to haunch
traction {tBeam2} sections {gbCss2, gbCss3} layer {Primary} # Left rafter
traction {tBeam3} sections {gbCss3, gbCss4} layer {Primary} # Right rafter
traction {tBeam4} sections {gbCss4, gbCss5} layer {Primary} # Column to base
Key Learnings:
Atan()calculates arctangent for angles- Cross-sections can have variable heights via parameters
GCS.Axes.Ry(angle)rotates about Y axis- Self-referencing (e.g.,
gbCss1.h) enables dynamic positioning tractioncreates variable-section beams between cross-sections- Complex transforms combine
OriginandAxes
Example 4: Array-Based Distribution (BeamPartDistribution.fcs)
Demonstrates iteration with ith for array-driven geometry.
#=============================================================================
# SEGMENT PARAMETERS (Arrays)
#=============================================================================
BeamLength := [2.25, 2, 2, 2] # Length of each segment
BeamCssHeights := [0.54, 0.28, 0.24, 0.28, 0.36] # Height at each end (n+1 values)
BeamCssAngle := [-PI/2, -PI/2, -PI/2, -PI/3, -PI/2.5] # Angle at each end
HeadCut := 0.5 # Cut at first segment
#=============================================================================
# BEAM SEGMENT CLASS
#=============================================================================
gclass {gBeam} filename "BeamPart.fcs"
#=============================================================================
# DISTRIBUTION WITH ITERATION
#=============================================================================
distribution {dBeam} gclass {gBeam}
lcs {Origin={0,0,0}, Axes=GCS.Axes}
transformation translation direction {1,0,0} # Translate along X
repetitions count (BeamLength.Count) # Number = array length
spacings BeamLength # Use array as spacings
specialization ithparameters {
# ith.i = current index (0-based)
# Access array elements using [ith.i]
Length := BeamLength[ith.i],
HeadCut := ((ith.i==0) ? (HeadCut) : 0), # Only first segment has cut
Headh := BeamCssHeights[ith.i], # Height at start of segment
Endh := BeamCssHeights[ith.i+1], # Height at end of segment
HeadAngleY := BeamCssAngle[ith.i],
EndAngleY := BeamCssAngle[ith.i+1]
}
Key Learnings:
- Arrays defined with
[value1, value2, ...] .Countproperty gets array lengthithparametersprovides iteration contextith.iis the current iteration index (0-based)- Array indexing:
array[index] - Ternary operator:
condition ? trueValue : falseValue spacingscan be an array for variable spacing
Example 5: Loads with Object Syntax (FitLoadVertex.fcs)
Demonstrates modern object-based load definition.
model_shell3d
OneMeshElementPerBeam = True
fitId := "FitLoadVertex"
#=============================================================================
# LOAD PARAMETERS
#=============================================================================
Name := ""
Description := ""
isOn := True
# Load case definition (object with properties)
LoadCase := {
Name := "selfWeight",
ActionType := "Variable", # "Variable" or "Permanent"
Specification := "",
LoadType := "Static"
}
# Transform for load position
Lcs := GCS
# Load components (forces and moments)
Fx := 0
Fy := 0
Fz := 0
Mx := 0
My := 0
Mz := 0
#=============================================================================
# GEOMETRY
#=============================================================================
v1Coords := Lcs.Origin.Point # Extract point from LCS origin
vertex {v1} xyz (v1Coords.X) (v1Coords.Y) (v1Coords.Z)
#=============================================================================
# VERTEX LOAD (Object Syntax)
#=============================================================================
vl1 = VertexLoad{
Vertex := v1,
Intensity := { Fx, Fy, Fz, Mx, My, Mz }, # 6-DOF intensity
LoadCase := LoadCase
}
#=============================================================================
# VISUALIZATION
#=============================================================================
maxFM := [Fx,Fy,Fz,Mx,My,Mz].Select(it => Abs(it)).Max()
isDrawingOn := False
layer {lLoadLayer} color Lime
Length := 1
# Label formatting function (lambda)
strForceFn := val => (val/1000).ToString("# ##0.00 kN")
LabelForceString := strForceFn(Fx) + ", " + strForceFn(Fy) + ", " + strForceFn(Fz)
# Conditional arrow visualization
gclass {ArrowForce} filename "../FcsComponent/ArrowSimpleClass.fcs" parameters {
Layer := lLoadLayer,
isDown := True,
ArrowType := 1
}
gblock {gbArrowForceX} gclass {ArrowForce} lcs (Lcs.Ry(-PI/2)) if (isDrawingOn and Fx!=0) parameters { Length := Fx/maxFM*Length }
gblock {gbArrowForceY} gclass {ArrowForce} lcs (Lcs.Rx(-PI/2)) if (isDrawingOn and Fy!=0) parameters { Length := Fy/maxFM*Length }
gblock {gbArrowForceZ} gclass {ArrowForce} lcs (Lcs.Ry(PI)) if (isDrawingOn and Fz!=0) parameters { Length := Fz/maxFM*Length }
Key Learnings:
- Object literals:
{ Property1 := value1, Property2 := value2 } VertexLoad{}creates typed structural objects- Lambda functions:
name := param => expression .Select()and.Max()for LINQ-style operationsAbs()for absolute value.ToString("format")for number formattingif (condition)for conditional geometry- String concatenation with
+
Common Patterns Summary
Pattern 1: Parametric Input
# Define parameters at top
span := 10
height := 5
load := 25
# Use in expressions
vertex {top} xyz span/2 0 height
Pattern 2: Component Hierarchy
# Load base class
gclass {component} filename "Component.fcs" parameters {param1 := value1}
# Instantiate multiple copies
gblock {inst1} gclass {component} lcs GCS
gblock {inst2} gclass {component} lcs (GCS.Tx(spacing))
Pattern 3: Array-Driven Geometry
heights := [1, 2, 3, 2, 1]
for i in Range(0, heights.Count) {
vertex {v[i]} xyz i*spacing 0 heights[i]
}
Pattern 4: Conditional Features
hasOpening := True
gblock {opening} gclass {openingClass} lcs (Lcs) if (hasOpening)
Pattern 5: Typed Structural Objects
myLoad = VertexLoad{ Vertex := v1, Intensity := {Fz := -1000}, LoadCase := lc1 }
mySupport = VertexSupport{ Vertex := v2, Conditions := {ux := 0, uy := 0, uz := 0} }
Example 3: Parametric Portal-Frame Building (LabComponents/PortalFrame.fcc/)
A multi-file, fully-updater-driven example in LabComponents/PortalFrame.fcc/ that demonstrates the complete HiStruct
building-model pattern at production complexity. Run with:
fli.exe LabComponents/PortalFrame.fcc/Main.fcs L "{B=24, He=6, Hr=8.5, Lb=6, N=5}"
Files
| File | Role |
|---|---|
Main.fcs |
Top-level assembly — parameters B, He, Hr, Lb, N; frame distribution; siding placement |
Frame.fcs |
Single portal frame (columns + rafters as FEM beams, local XZ plane) |
Siding.fcs |
Building envelope — all wall and roof faces spanning total length L, placed once |
Inputs.fcs |
Fcs.Parameter input page definitions for the HiStruct UI |
css/SolidRect.fcs |
Parametric solid rectangle cross-section |
Key patterns demonstrated
1. Updater-driven parameters (Main.fcs)
B := 20 # building span (m)
He := 5 # eaves height (m)
Hr := 7 # ridge height (m)
Lb := 5 # bay spacing (m)
N := 4 # number of bays
L := N * Lb
2. Multi-file component hierarchy with parameter passing
gclass {gcFrame} filename "Frame.fcs" parameters {B=B, He=He, Hr=Hr}
gclass {gcSiding} filename "Siding.fcs" parameters {B=B, He=He, Hr=Hr, L=L}
3. Distribution for repeated portal frames
gblock {frame0} gclass {gcFrame} lcs {lcsF0}
gblock {frameN} gclass {gcFrame} lcs {lcsFN}
distribution 1 geometries {frame0} {frameN} repetitions count (N+1)
4. Fcs.Parameter input page (Inputs.fcs)
SpanDef := Fcs.Parameter.ItemDouble{
HumanName := "Building span",
Identifier := NameSpace+"B",
DefaultUnit := "m",
Min := 6.0, Max := 60.0, Step := 1.0
}
DimensionsPage := Fcs.Parameter.ItemClass{
HumanName := "Portal Frame Building — Dimensions",
Items := [ SpanDef, EavesDef, RidgeDef, BaySpacingDef, BayCountDef, ... ]
}