Composite Analysis#

This example highlights how material properties allow composite analysis in sectionproperties.

Geometric vs. Composite#

The default analysis type in sectionproperties is purely geometric, i.e. cross-section properties are reported based on the geometry only. In this analysis, all geometries are assigned the default material:

[1]:
from sectionproperties.analysis import Section
from sectionproperties.pre.library import rectangular_section


rect_geom = rectangular_section(d=100, b=50)
rect_geom.material
[1]:
Material(name='default', elastic_modulus=1, poissons_ratio=0, yield_strength=1, density=1, color='w')

The default material has a unit elastic modulus, yield strength and density, and a Poisson’s ratio of zero.

Geometric-only analysis allows geometric properties to be obtained:

[2]:
rect_geom.create_mesh(mesh_sizes=10)  # create mesh
rect_sec = Section(geometry=rect_geom)
rect_sec.calculate_geometric_properties()
ixx, iyy, ixy = rect_sec.get_ic()  # get second moments of area
print(f"Ixx = {ixx:.5e} mm4")
Ixx = 4.16667e+06 mm4

When a material property gets added to a geometry, the analysis becomes composite.

[3]:
from sectionproperties.pre import Material


# assign steel to the geometry
steel = Material(
    name="Steel",
    elastic_modulus=200e3,
    poissons_ratio=0.3,
    density=7.85e-6,
    yield_strength=500,
    color="grey",
)
rect_geom.material = steel

# recreate mesh and section
rect_geom.create_mesh(mesh_sizes=10)
rect_sec = Section(geometry=rect_geom)
rect_sec.calculate_geometric_properties()

Cross-section properties are now modulus weighted as the assumption is that there are multiple regions with multiple different material properties. We can no longer obtain geometric-only properties:

[4]:
ixx, iyy, ixy = rect_sec.get_ic()  # get second moments of area
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Cell In[4], line 1
----> 1 ixx, iyy, ixy = rect_sec.get_ic()  # get second moments of area

File ~/checkouts/readthedocs.org/user_builds/sectionproperties/envs/latest/lib/python3.10/site-packages/sectionproperties/analysis/section.py:2081, in Section.get_ic(self)
   2079     msg = "Attempting to get a geometric only property for a composite analysis"
   2080     msg += " (material properties have been applied). Consider using get_eic()."
-> 2081     raise RuntimeError(msg)
   2083 try:
   2084     assert self.section_props.ixx_c is not None

RuntimeError: Attempting to get a geometric only property for a composite analysis (material properties have been applied). Consider using get_eic().

In this case, we need to get the modulus weighted second moments of area. Note we can still extract geometric properties by using a reference elastic modulus.

[5]:
# get modulus weighted second moments of area
eixx, eiyy, eixy = rect_sec.get_eic()
print(f"E.Ixx = {eixx:.5e} N.mm2")

# use reference elastic modulus to get transformed properties
ixx, iyy, ixy = rect_sec.get_eic(e_ref=steel)
print(f"Ixx = {ixx:.5e} mm4")
E.Ixx = 8.33333e+11 N.mm2
Ixx = 4.16667e+06 mm4

Steel-Timber Composite Section#

The following section models a composite timber floor and steel beam section. A universal steel beam (310UB40.4) is modelled with a 100D x 600W timber panel placed on its top flange.

Create the Materials#

[6]:
# create the steel material
steel = Material(
    name="Steel",
    elastic_modulus=200e3,
    poissons_ratio=0.3,
    density=7.85e-6,
    yield_strength=500,
    color="grey",
)

# create the timber material
timber = Material(
    name="Timber",
    elastic_modulus=8e3,
    poissons_ratio=0.35,
    yield_strength=20,
    density=0.78e-6,
    color="burlywood",
)

Create the Geometry#

[7]:
from sectionproperties.pre.library import i_section


# universal steel beam
ub = i_section(d=304, b=165, t_f=10.2, t_w=6.1, r=11.4, n_r=8, material=steel)

# timber floor panel
panel = rectangular_section(d=100, b=600, material=timber)
panel = panel.align_center(align_to=ub).align_to(other=ub, on="top")

# combine geometry
geom = ub + panel

Create Mesh and Section Object#

[8]:
# 10 mm2 mesh for UB, 500 mm2 mesh for timber
geom.create_mesh(mesh_sizes=[10, 500])
sec = Section(geometry=geom)
sec.plot_mesh()
../../_images/examples_materials_composite_analysis_19_0.svg
[8]:
<Axes: title={'center': 'Finite Element Mesh'}>

Perform Analysis#

[9]:
sec.calculate_geometric_properties()
sec.calculate_warping_properties()
sec.calculate_plastic_properties()

Display Analysis Results#

We can plot the various centroids found by the analyses.

[10]:
sec.plot_centroids()
../../_images/examples_materials_composite_analysis_24_0.svg
[10]:
<Axes: title={'center': 'Centroids'}>

We can also print all the calculated section properties to the terminal, note that because have conducted a composite analysis, modulus weighted properties are displayed.

[11]:
sec.display_results()
     Section Properties      
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Property           Value ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ area        6.521094e+04 │
│ perimeter   2.306078e+03 │
│ mass        8.770585e-02 │
│ e.a         1.522187e+09 │
│ e.qx        3.283325e+11 │
│ e.qy        1.255805e+11 │
│ e.ixx_g     1.019283e+14 │
│ e.iyy_g     2.628963e+13 │
│ e.ixy_g     2.708743e+13 │
│ cx          8.250000e+01 │
│ cy          2.156978e+02 │
│ e.ixx_c     3.110771e+13 │
│ e.iyy_c     1.592924e+13 │
│ e.ixy_c    -9.375000e-02 │
│ e.zxx+      1.652010e+11 │
│ e.zxx-      1.442190e+11 │
│ e.zyy+      5.309747e+10 │
│ e.zyy-      5.309747e+10 │
│ rx          1.429552e+02 │
│ ry          1.022971e+02 │
│ e.i11_c     3.110771e+13 │
│ e.i22_c     1.592924e+13 │
│ phi         0.000000e+00 │
│ e.z11+      1.652010e+11 │
│ e.z11-      1.442190e+11 │
│ e.z22+      5.309747e+10 │
│ e.z22-      5.309747e+10 │
│ r11         1.429552e+02 │
│ r22         1.022971e+02 │
│ e_eff       2.334252e+04 │
│ g_eff       8.873037e+03 │
│ nu_eff      3.153622e-01 │
│ e.j         2.169153e+12 │
│ x_se        8.255462e+01 │
│ y_se        3.200131e+02 │
│ x1_se       5.461533e-02 │
│ y2_se       1.043152e+02 │
│ x_st        8.255367e+01 │
│ y_st        3.179106e+02 │
│ e.gamma     8.613474e+16 │
│ e.a_sx      6.005132e+08 │
│ e.a_sy      4.252562e+08 │
│ e.a_s11     6.005132e+08 │
│ e.a_s22     4.252562e+08 │
│ beta_x+     2.165060e+02 │
│ beta_x-    -2.165060e+02 │
│ beta_y+     1.092307e-01 │
│ beta_y-    -1.092307e-01 │
│ beta_11+    2.165060e+02 │
│ beta_11-   -2.165060e+02 │
│ beta_22+    1.092307e-01 │
│ beta_22-   -1.092307e-01 │
│ x_pc        8.250000e+01 │
│ y_pc        2.954820e+02 │
│ x11_pc      8.250000e+01 │
│ y22_pc      2.954820e+02 │
│ mp_xx       4.858134e+08 │
│ mp_yy       5.335011e+08 │
│ mp_11       4.858134e+08 │
│ mp_22       5.335011e+08 │
└───────────┴───────────────┘

We can also get transformed properties by specifying a reference material.

[12]:
ixx_timber, _, _ = sec.get_eic(e_ref=timber)
ixx_steel, _, _ = sec.get_eic(e_ref=steel)
print(f"Ixx,t = {ixx_timber:.3e} mm4")
print(f"Ixx,s = {ixx_steel:.3e} mm4")
Ixx,t = 3.888e+09 mm4
Ixx,s = 1.555e+08 mm4

A plastic analysis for composite sections will calculate plastic moments rather than plastic section moduli. The plastic moment assumes all geometry fibres reach the yield strength.

[13]:
mp_xx, _ = sec.get_mp()
print(f"Mp = {mp_xx / 1e6:.1f} kN.m")
Mp = 485.8 kN.m

Stress Analysis#

[14]:
stress = sec.calculate_stress(n=-100e3, mxx=-120e6, vy=-75e3)
[15]:
stress.plot_stress(stress="m_zz")
../../_images/examples_materials_composite_analysis_33_0.svg
[15]:
<Axes: title={'center': 'Stress Contour Plot - $\\sigma_{zz,\\Sigma M}$'}>
[16]:
stress.plot_stress(stress="vm")
../../_images/examples_materials_composite_analysis_34_0.svg
[16]:
<Axes: title={'center': 'Stress Contour Plot - $\\sigma_{vM}$'}>

We can plot only a specific list of materials by including the material_list argument. In the above plot it is difficult to see the stress in the timber so we set material_list=[timber].

[17]:
stress.plot_stress(stress="vm", material_list=[timber])
../../_images/examples_materials_composite_analysis_36_0.svg
[17]:
<Axes: title={'center': 'Stress Contour Plot - $\\sigma_{vM}$'}>