Multiscale Beam: Micro Homogenization to Macro Assembly#
Problem Description#
A slender composite blade is analysed at two scales:
Micro scale — a 2D beam cross-section (a Structure Gene) is homogenized by VABS into an effective 1D beam constitutive model (axial
EA, bendingEI22/EI33, torsionGJ).Macro scale — a 1D beam finite-element model uses that effective section along the blade span, together with its boundary conditions and tip load.
The task is to carry the micro-scale effective section into a macro beam model as data, using the generic finite-element entry points, and without invoking any external solver.
Solution#
The script wires four steps:
Read the micro homogenization output with
sgio.read_output_model(). Pointed at a VABS.sg.Kresult it returns anEulerBernoulliBeamModelcarrying the effective section stiffness.Read the macro beam mesh with
sgio.read_fe_model(), the explicit generic-FE entry point. The Abaqus.inp(B31 beam elements) maps to a backend-neutralsgio.FEModel. Itsextrascarry the structural blocks the SG reader does not model —*Boundary,*Cload,*Step— captured as a non-lossy fallback.Wrap and assemble the
FEModelinto asgio.StructuralModelviaStructuralModel.from_fe(...), then inject the homogenized section as the macro beam’s section material (materialsplus a referencingsgio.Section).Inspect the captured boundary/load/step payload from
fe.extras, showing how a caller retrieves the structural data for downstream assembly.
"""Multiscale beam example.
Demonstrates the Phase 10 generic-FE workflow end to end, without running any
external solver:
1. Micro -- read a VABS beam-section *homogenization output* into an effective
Euler-Bernoulli beam model (``read_output_model``).
2. Macro -- read a cantilever B31 beam mesh as a generic ``FEModel``
(``read_fe_model``) and wrap it as a ``StructuralModel``.
3. Assemble -- inject the homogenized effective section as the macro beam's
section material.
4. Inspect -- show the structural blocks (boundary/load/step) that the Abaqus
reader captured into ``FEModel.extras`` as a fallback.
Run:
python examples/multiscale_beam/run.py
"""
from __future__ import annotations
from pathlib import Path
import sgio
from sgio import Section
HERE = Path(__file__).parent
MICRO_OUTPUT = HERE / "micro_section.sg.K" # VABS homogenization result
MACRO_MESH = HERE / "cantilever_macro.inp" # Abaqus B31 beam mesh
def main() -> None:
# --- 1. Micro: effective beam section from VABS homogenization output ----
effective = sgio.read_output_model(str(MICRO_OUTPUT), "vabs", model_type="BM1")
print("[micro] effective Euler-Bernoulli beam section")
print(f" EA = {effective.ea:.6g}")
print(f" EI22 = {effective.ei22:.6g}")
print(f" EI33 = {effective.ei33:.6g}")
print(f" GJ = {effective.gj:.6g}")
# --- 2. Macro: read beam mesh as a generic FEModel, wrap as structural ---
fe = sgio.read_fe_model(str(MACRO_MESH), "abaqus", model_type="BM1", sgdim=3)
sm = sgio.StructuralModel.from_fe(fe)
n_elems = sum(len(cb.data) for cb in sm.mesh.cells)
print(f"\n[macro] beam mesh: {len(sm.mesh.points)} nodes, {n_elems} beam elements")
# --- 3. Assemble: use the homogenized section as the macro beam material --
sm.materials["blade_section"] = effective
sm.sections["beam"] = Section(
name="beam", material="blade_section", property_id=1
)
print("[macro] injected homogenized section as material 'blade_section'")
print(f" materials = {list(sm.materials)}")
print(f" sections = {list(sm.sections)}")
# --- 4. Inspect: structural payload captured by the Abaqus reader ---------
print("\n[macro] structural blocks captured into fe.extras (fallback):")
for key in ("abaqus_boundary", "abaqus_loads", "abaqus_steps"):
blocks = sm.fe.extras.get(key, [])
for block in blocks:
print(f" {key}: *{block['keyword']} {block['parameters']} "
f"data={block['data']}")
print("\nMultiscale handoff complete: micro effective section -> macro beam model.")
if __name__ == "__main__":
main()
The micro→macro handoff is pure data flow: the effective section object becomes a material of the macro model. Model assembly and any solver export remain explicit caller steps — sgio provides the IR and the entry points, not an automated end-to-end pipeline.
Result#
Running the example prints the effective section, the macro mesh summary, the injected section, and the captured structural blocks:
[micro] effective Euler-Bernoulli beam section
EA = 3.07204e+08
EI22 = 2.08882e+08
EI33 = 3.65306e+09
GJ = 1.94298e+08
[macro] beam mesh: 5 nodes, 4 beam elements
[macro] injected homogenized section as material 'blade_section'
materials = ['blade_section']
sections = ['beam']
[macro] structural blocks captured into fe.extras (fallback):
abaqus_boundary: *Boundary {} data=[['ROOT', 'ENCASTRE']]
abaqus_loads: *Cload {} data=[['TIP', 2, '-1000.0']]
abaqus_steps: *Step {'name': 'TipLoad', 'nlgeom': 'NO'} data=[]
Multiscale handoff complete: micro effective section -> macro beam model.
python examples/multiscale_beam/run.py
File List#
run.py: The end-to-end script
micro_section.sg.K: VABS beam-section homogenization output (the micro effective properties)
cantilever_macro.inp: Abaqus B31 cantilever beam mesh with root encastre and a tip load (the macro model)