Geometric Analysis#

This example demonstrates how to perform a geometric analysis in sectionproperties.

Steel I-Beam#

In this example, the geometric cross-section properties of a 200UB25.4 are obtained.

First we create the cross-section geometry.

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


geom = i_section(d=203, b=133, t_f=7.8, t_w=5.8, r=8.9, n_r=8)

Next we must create a finite element mesh and a Section() object.

[2]:
from sectionproperties.analysis import Section


geom.create_mesh(mesh_sizes=5)
sec = Section(geometry=geom)

We can check the mesh quality by calling the display_mesh_info() method, or by generating a plot of the mesh by using plot_mesh().

[3]:
sec.display_mesh_info()
Mesh Statistics:
- 2304 nodes
- 991 elements
- 1 region
[4]:
sec.plot_mesh(materials=False)
../../_images/examples_analysis_geometric_analysis_9_0.svg
[4]:
<Axes: title={'center': 'Finite Element Mesh'}>

Note that in sectionproperties, the geometric properties are mesh independent. As a result, we can create a mesh with no area constraints by setting mesh_sizes=0.

[5]:
geom.create_mesh(mesh_sizes=0)
sec = Section(geometry=geom)
sec.display_mesh_info()
sec.plot_mesh(materials=False)
Mesh Statistics:
- 622 nodes
- 235 elements
- 1 region
../../_images/examples_analysis_geometric_analysis_11_5.svg
[5]:
<Axes: title={'center': 'Finite Element Mesh'}>

We can now perform the geometric analysis by calling calculate_geometric_properties().

[6]:
sec.calculate_geometric_properties()

One easy way to view all the results that have been calculated to date, is to print them to the terminal by using display_results().

[7]:
sec.display_results(fmt=".0f")
   Section Properties   
┏━━━━━━━━━━━┳━━━━━━━━━━┓
┃ Property      Value ┃
┡━━━━━━━━━━━╇━━━━━━━━━━┩
│ area           3232 │
│ perimeter       911 │
│ qx           328027 │
│ qy           214915 │
│ ixx_g      56839451 │
│ iyy_g      17355200 │
│ ixy_g      21813826 │
│ cx               66 │
│ cy              102 │
│ ixx_c      23544664 │
│ iyy_c       3063383 │
│ ixy_c            -0 │
│ zxx+         231967 │
│ zxx-         231967 │
│ zyy+          46066 │
│ zyy-          46066 │
│ rx               85 │
│ ry               31 │
│ i11_c      23544664 │
│ i22_c       3063383 │
│ phi               0 │
│ z11+         231967 │
│ z11-         231967 │
│ z22+          46066 │
│ z22-          46066 │
│ r11              85 │
│ r22              31 │
└───────────┴──────────┘

Unconnected Sections#

sectionproperties can compute the geometric properties of unconnected sections. Note that a warping analysis cannot be undertaken on unconnected sections. This example analyses two 150PFC sections separated by 1 metre forming the flanges of a truss.

[8]:
from sectionproperties.pre.library import channel_section


# create 150 pfc geometry
pfc = channel_section(d=150, b=75, t_f=9.5, t_w=6, r=10, n_r=8)
pfc.plot_geometry(legend=False)
../../_images/examples_analysis_geometric_analysis_17_0.svg
[8]:
<Axes: title={'center': 'Cross-Section Geometry'}>

We can analyse the section properties of a single PFC first, then compare the results to the combined section.

[9]:
pfc.create_mesh(mesh_sizes=0)
sec_pfc = Section(geometry=pfc)
sec_pfc.calculate_geometric_properties()

Now we create the truss geometry by mirroring one PFC and offsetting the other.

[10]:
# create compound geometry
geom = pfc.mirror_section(axis="y", mirror_point=(0, 0)) + pfc.shift_section(
    x_offset=1000
)
geom.create_mesh(mesh_sizes=0)
sec_truss = Section(geometry=geom)
sec_truss.plot_mesh(materials=False)
sec_truss.calculate_geometric_properties()
../../_images/examples_analysis_geometric_analysis_21_0.svg

Let’s compare some of the calculated section properties:

[11]:
area_ratio = sec_truss.get_area() / sec_pfc.get_area()
ixx_ratio = sec_truss.get_ic()[0] / sec_pfc.get_ic()[0]
iyy_ratio = sec_truss.get_ic()[1] / sec_pfc.get_ic()[1]
zyy_ratio = sec_truss.get_z()[2] / sec_pfc.get_z()[2]
ry_ratio = sec_truss.get_rc()[1] / sec_pfc.get_rc()[1]

We can format the results in a tabulated way by using the rich library.

[12]:
from rich.console import Console
from rich.table import Table


# setup table
table = Table(title="Section Properties Comparison")
table.add_column("Property", justify="left", style="cyan", no_wrap=True)
table.add_column("PFC", justify="right", style="green")
table.add_column("Truss", justify="right", style="green")
table.add_column("Ratio", justify="right", style="green")

# add data to the table
table.add_row(
    "area",
    f"{sec_pfc.get_area():.0f}",
    f"{sec_truss.get_area():.0f}",
    f"{area_ratio:.2f}",
)
table.add_row(
    "ixx",
    f"{sec_pfc.get_ic()[0]:.3e}",
    f"{sec_truss.get_ic()[0]:.3e}",
    f"{ixx_ratio:.2f}",
)
table.add_row(
    "iyy",
    f"{sec_pfc.get_ic()[1]:.3e}",
    f"{sec_truss.get_ic()[1]:.3e}",
    f"{iyy_ratio:.2f}",
)
table.add_row(
    "zyy",
    f"{sec_pfc.get_z()[2]:.3e}",
    f"{sec_truss.get_z()[2]:.3e}",
    f"{zyy_ratio:.2f}",
)
table.add_row(
    "ry",
    f"{sec_pfc.get_rc()[1]:.0f}",
    f"{sec_truss.get_rc()[1]:.0f}",
    f"{ry_ratio:.2f}",
)

# print table
console = Console()
console.print(table)
        Section Properties Comparison        
┏━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━┓
┃ Property        PFC      Truss   Ratio ┃
┡━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━┩
│ area           2255       4510    2.00 │
│ ixx       8.344e+06  1.669e+07    2.00 │
│ iyy       1.286e+06  1.245e+09  968.42 │
│ zyy       2.567e+04  2.166e+06   84.37 │
│ ry               24        525   22.00 │
└──────────┴───────────┴───────────┴────────┘