Data Structure Reference#

This page provides detailed information about the data structures used in StructureGene.

StructureGene Configuration#

from sgio import StructureGene

sg = StructureGene(
    name='my_structure',    # Name of the structure
    sgdim=3,                 # Dimension: 1=beam, 2=plate/shell, 3=solid
    smdim=3,                 # Structural model dimension (usually same as sgdim)
    spdim=3                  # Space dimension (defaults to sgdim if not specified)
)

Parameters#

  • name (str, optional): Name of your structure. Used for file naming. Default: ''

  • sgdim (int, optional): Dimension of the structure gene

    • 1: 1D beam analysis

    • 2: 2D plate/shell analysis

    • 3: 3D solid analysis

  • smdim (int, optional): Dimension of the structural model. Usually matches sgdim.

  • spdim (int, optional): Dimension of the space containing the structure. Defaults to sgdim if not specified. For example, a curved beam in 3D space would have sgdim=1 and spdim=3.

Mesh Structure#

The mesh uses the meshio format:

import numpy as np
from meshio import Mesh, CellBlock

mesh = Mesh(
    points=np.array([[x1, y1, z1], [x2, y2, z2], ...]),
    cells=[...],
    cell_data={...},
    point_data={...}  # Optional
)

sg.mesh = mesh

Points (Nodes)#

points is a NumPy array of shape (n_nodes, 3) containing node coordinates:

points = np.array([
    [0.0, 0.0, 0.0],  # Node 0
    [1.0, 0.0, 0.0],  # Node 1
    [1.0, 1.0, 0.0],  # Node 2
])

Important

Always use 3 columns even for 2D or 1D problems. Set unused dimensions to 0.

Cells (Elements)#

cells is a list of CellBlock objects. Each block contains elements of the same type:

cells = [
    CellBlock(
        type='triangle',
        data=np.array([
            [0, 1, 2],
            [1, 3, 2],
        ])
    ),
    CellBlock(
        type='quad',
        data=np.array([
            [4, 5, 6, 7],
        ])
    )
]

Supported Element Types#

  • 1D elements: 'line' (2 nodes), 'line3' (3 nodes)

  • 2D elements: 'triangle' (3), 'triangle6' (6), 'quad' (4), 'quad8' (8), 'quad9' (9)

  • 3D elements: 'tetra' (4), 'tetra10' (10), 'hexahedron' (8), 'hexahedron20' (20), 'hexahedron27' (27), 'wedge' (6), 'pyramid' (5)

Connectivity: Critical Note#

The connectivity array must use 0-based indices referencing the points array, not original node IDs!

# ✓ CORRECT: Use 0-based array indices
points = np.array([
    [0, 0, 0],  # Index 0 (original ID might be 100)
    [1, 0, 0],  # Index 1 (original ID might be 200)
    [0, 1, 0],  # Index 2 (original ID might be 300)
])
cells = [CellBlock(type='triangle', data=np.array([[0, 1, 2]]))]

# ✗ WRONG: Don't use original IDs in connectivity!
# cells = [CellBlock(type='triangle', data=np.array([[100, 200, 300]]))]

Cell Data (Per-Element Data)#

cell_data is a dictionary with one entry per cell block:

cell_data = {
    'property_id': [
        np.array([1, 1]),     # Property IDs for first cell block
        np.array([2]),        # Property IDs for second cell block
    ],
    'element_id': [          # Optional: original element IDs
        np.array([1000, 1001]),
        np.array([2000]),
    ]
}
Required:
  • 'property_id': List of arrays assigning property IDs to elements

Optional:
  • 'element_id': Original element IDs from your format

  • 'property_ref_csys': Element local coordinate systems

Point Data (Per-Node Data)#

point_data is optional and stores per-node information:

point_data = {
    'node_id': [100, 200, 300, 400],  # Original node IDs
}

Materials#

Materials are stored in a dictionary indexed by name:

from sgio.model import CauchyContinuumModel

# Create material
steel = CauchyContinuumModel(
    name='Steel',
    isotropy=2,    # 0=orthotropic, 1=transverse, 2=isotropic
    e=200e9,
    nu=0.3,
    density=7850
)

# Add to StructureGene
sg.materials['Steel'] = steel

Isotropy Types#

The isotropy parameter determines material symmetry:

Isotropic (isotropy=2)

mat = CauchyContinuumModel(
    name='Aluminum',
    isotropy=2,
    e=70e9,           # Single Young's modulus
    nu=0.33,          # Single Poisson's ratio
    density=2700
)

Transversely Isotropic (isotropy=1)

mat = CauchyContinuumModel(
    name='Fiber',
    isotropy=1,
    e=[135e9, 10e9],      # [E_axial, E_transverse]
    g=[5e9, 5e9],         # [G_axial, G_transverse]
    nu=[0.3, 0.45],       # [nu_axial, nu_transverse]
    density=1600
)

Orthotropic (isotropy=0)

mat = CauchyContinuumModel(
    name='CarbonFiber',
    isotropy=0,
    e=[135e9, 10e9, 10e9],    # [E1, E2, E3]
    g=[5e9, 5e9, 5e9],        # [G12, G13, G23]
    nu=[0.3, 0.3, 0.45],      # [nu12, nu13, nu23]
    density=1600
)

For more material types, see Material and Structural Models.

Material-Orientation Combinations (mocombos)#

The mocombos dictionary maps property IDs to (material_name, angle) pairs:

sg.mocombos = {
    1: ('Steel', 0.0),           # Property 1: Steel at 0°
    2: ('CarbonFiber', 45.0),    # Property 2: Carbon at 45°
    3: ('CarbonFiber', -45.0),   # Property 3: Carbon at -45°
}

Why separate from materials?

This separation allows you to reuse the same material at different orientations without creating duplicate material definitions.

Relationship Chain#

Element → property_id → mocombo → (material_name, angle) → Material object

Example:
Element 5 → property_id=2 → mocombo[2]=('CarbonFiber', 45.0) → sg.materials['CarbonFiber']

Complete Example: Composite Laminate#

import numpy as np
from meshio import Mesh, CellBlock
from sgio import StructureGene
from sgio.model import CauchyContinuumModel
import sgio

# Create StructureGene
sg = StructureGene(name='laminate', sgdim=2, smdim=2)

# Define one material
carbon = CauchyContinuumModel(
    name='CarbonFiber',
    isotropy=0,
    e=[135e9, 10e9, 10e9],
    g=[5e9, 5e9, 5e9],
    nu=[0.3, 0.3, 0.45],
    density=1600
)
sg.materials['CarbonFiber'] = carbon

# Create [0/45/-45/90] layup using mocombos
sg.mocombos = {
    1: ('CarbonFiber', 0.0),
    2: ('CarbonFiber', 45.0),
    3: ('CarbonFiber', -45.0),
    4: ('CarbonFiber', 90.0),
}

# Create 2x2 mesh (4 quad elements)
points = np.array([
    [0.0, 0.0, 0.0], [0.5, 0.0, 0.0], [1.0, 0.0, 0.0],
    [0.0, 0.5, 0.0], [0.5, 0.5, 0.0], [1.0, 0.5, 0.0],
    [0.0, 1.0, 0.0], [0.5, 1.0, 0.0], [1.0, 1.0, 0.0],
])

cells = [
    CellBlock(type='quad', data=np.array([
        [0, 1, 4, 3],  # Element 0
        [1, 2, 5, 4],  # Element 1
        [3, 4, 7, 6],  # Element 2
        [4, 5, 8, 7],  # Element 3
    ]))
]

# Assign different orientations to different elements
cell_data = {
    'property_id': [np.array([1, 2, 3, 4])]
}

sg.mesh = Mesh(points=points, cells=cells, cell_data=cell_data)

# Write to file
sgio.write(sg=sg, fn='laminate.sc', file_format='swiftcomp',
           format_version='2.1', model_type='PL1')

Material Name-ID Mapping#

VABS/SwiftComp use numeric material IDs. Sgio handles this automatically, but you can control it explicitly:

# Automatic (recommended)
sg.add_material(steel)      # Gets ID 1
sg.add_material(aluminum)   # Gets ID 2

# Manual control
sg.material_name_id_pairs = [
    ['Steel', 1],
    ['Aluminum', 2],
    ['CarbonFiber', 3]
]

Model Type Selection#

When writing to VABS/SwiftComp, specify the analysis model:

1D Beam (sgdim=1)
  • 'BM1': Classical (Euler-Bernoulli)

  • 'BM2': Refined (Timoshenko)

  • 'BM3': Vlasov

  • 'BM4': Trapeze effect

2D Plate/Shell (sgdim=2)
  • 'PL1': Classical (Kirchhoff-Love)

  • 'PL2': Refined (Reissner-Mindlin)

3D Solid (sgdim=3)
  • 'SD1': Classical continuum

  • 'SD2': Refined continuum

See Material and Structural Models for details on each model.

Summary Checklist#

Before writing your StructureGene to file, verify:

# ✓ StructureGene configured
assert sg.sgdim in [1, 2, 3]
assert sg.name != ''

# ✓ Mesh created
assert sg.mesh is not None
assert sg.nnodes > 0
assert sg.nelems > 0

# ✓ Materials defined
assert len(sg.materials) > 0

# ✓ Mocombos created
assert len(sg.mocombos) > 0

# ✓ All property IDs reference valid mocombos
for prop_array in sg.mesh.cell_data['property_id']:
    for prop_id in prop_array:
        assert prop_id in sg.mocombos

# ✓ All mocombos reference valid materials
for prop_id, (mat_name, angle) in sg.mocombos.items():
    assert mat_name in sg.materials

Next Steps#