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/checkouts/stable/src/sectionproperties/analysis/section.py:2203, in Section.get_ic(self)
   2201     msg = "Attempting to get a geometric only property for a composite analysis"
   2202     msg += " (material properties have been applied). Consider using get_eic()."
-> 2203     raise RuntimeError(msg)
   2205 if (
   2206     self.section_props.ixx_c is None
   2207     or self.section_props.ixy_c is None
   2208     or self.section_props.iyy_c is None
   2209 ):
   2210     msg = "Conduct a geometric analysis."

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 │
│ my_xx       3.605474e+08 │
│ my_yy       1.327437e+08 │
│ 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 │
│ my_11       3.605474e+08 │
│ my_22       1.327437e+08 │
│ 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.500453e+08 │
│ mp_yy       2.510673e+08 │
│ mp_11       4.500453e+08 │
│ mp_22       2.510673e+08 │
│ sf_xx+      1.248228e+00 │
│ sf_xx-      1.248228e+00 │
│ sf_yy+      1.891369e+00 │
│ sf_yy-      1.891369e+00 │
│ sf_11+      1.248228e+00 │
│ sf_11-      1.248228e+00 │
│ sf_22+      1.891369e+00 │
│ sf_22-      1.891369e+00 │
└───────────┴───────────────┘

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

Further, we can display the transformed results with respect to an elastic modulus by calling the display_transformed_results() method. Here we print the transformed section properties with respect to the timber.

[13]:
sec.display_transformed_results(e_ref=timber)
     Transformed Section     
         Properties          
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Property           Value ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ geom area   6.521094e+04 │
│ perimeter   2.306078e+03 │
│ mass        8.770585e-02 │
│ e_ref       8.000000e+03 │
│ a           1.902734e+05 │
│ qx          4.104156e+07 │
│ qy          1.569756e+07 │
│ ixx_g       1.274104e+10 │
│ iyy_g       3.286203e+09 │
│ ixy_g       3.385929e+09 │
│ cx          8.250000e+01 │
│ cy          2.156978e+02 │
│ ixx_c       3.888464e+09 │
│ iyy_c       1.991155e+09 │
│ ixy_c      -1.171875e-05 │
│ zxx+        2.065013e+07 │
│ zxx-        1.802737e+07 │
│ zyy+        6.637183e+06 │
│ zyy-        6.637183e+06 │
│ my_xx       3.605474e+08 │
│ my_yy       1.327437e+08 │
│ rx          1.429552e+02 │
│ ry          1.022971e+02 │
│ i11_c       3.888464e+09 │
│ i22_c       1.991155e+09 │
│ phi         0.000000e+00 │
│ z11+        2.065013e+07 │
│ z11-        1.802737e+07 │
│ z22+        6.637183e+06 │
│ z22-        6.637183e+06 │
│ my_11       3.605474e+08 │
│ my_22       1.327437e+08 │
│ r11         1.429552e+02 │
│ r22         1.022971e+02 │
│ e_eff       2.334252e+04 │
│ g_eff       8.873037e+03 │
│ nu_eff      3.153622e-01 │
│ j           2.711441e+08 │
│ 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 │
│ gamma       1.076684e+13 │
│ a_sx        7.506415e+04 │
│ a_sy        5.315702e+04 │
│ a_s11       7.506415e+04 │
│ a_s22       5.315702e+04 │
│ 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.500453e+08 │
│ mp_yy       2.510673e+08 │
│ mp_11       4.500453e+08 │
│ mp_22       2.510673e+08 │
│ sf_xx+      1.248228e+00 │
│ sf_xx-      1.248228e+00 │
│ sf_yy+      1.891369e+00 │
│ sf_yy-      1.891369e+00 │
│ sf_11+      1.248228e+00 │
│ sf_11-      1.248228e+00 │
│ sf_22+      1.891369e+00 │
│ sf_22-      1.891369e+00 │
└───────────┴───────────────┘

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.

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

Stress Analysis

[15]:
stress = sec.calculate_stress(n=-100e3, mxx=-120e6, vy=-75e3)
[16]:
stress.plot_stress(stress="m_zz")
../../_images/examples_materials_composite_analysis_35_0.svg
[16]:
<Axes: title={'center': 'Stress Contour Plot - $\\sigma_{zz,\\Sigma M}$'}>
[17]:
stress.plot_stress(stress="vm")
../../_images/examples_materials_composite_analysis_36_0.svg
[17]:
<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].

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