"""NASTRAN sections library."""
from __future__ import annotations
import numpy as np
from shapely import Polygon
import sectionproperties.pre.geometry as geometry
import sectionproperties.pre.library.utils as sp_utils
import sectionproperties.pre.pre as pre
[docs]
def nastran_bar(
dim_1: float,
dim_2: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a BAR section.
Constructs a BAR section with the center at the origin ``(0, 0)``, with two
parameters defining dimensions.
Args:
dim_1: Width (x) of bar
dim_2: Depth (y) of bar
material: Material to associate with this geometry
Returns:
BAR section geometry
Example:
The following example creates a BAR cross-section with a depth of 1.5 and width
of 2.0:
.. plot::
:include-source: True
:caption: Bar section geometry
from sectionproperties.pre.library import nastran_bar
nastran_bar(dim_1=2.0, dim_2=1.5).plot_geometry()
"""
points = [
(-0.5 * dim_1, -0.5 * dim_2),
(0.5 * dim_1, -0.5 * dim_2),
(0.5 * dim_1, 0.5 * dim_2),
(-0.5 * dim_1, 0.5 * dim_2),
]
geom = geometry.Geometry(geom=Polygon(points), material=material)
c = (0.5 * dim_1, 0.5 * dim_2)
d = (0.5 * dim_1, -0.5 * dim_2)
e = (-0.5 * dim_1, -0.5 * dim_2)
f = (-0.5 * dim_1, 0.5 * dim_2)
geom.recovery_points = [c, d, e, f]
return geom
[docs]
def nastran_box(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a BOX section.
Constructs a BOX section with the center at the origin ``(0, 0)``, with four
parameters defining dimensions.
Args:
dim_1: Width (x) of box
dim_2: Depth (y) of box
dim_3: Thickness of box in y direction
dim_4: Thickness of box in x direction
material: Material to associate with this geometry
Returns:
BOX section geometry
Example:
The following example creates a BOX cross-section with a depth of 3.0 and width
of 4.0:
.. plot::
:include-source: True
:caption: BOX section geometry
from sectionproperties.pre.library import nastran_box
nastran_box(dim_1=4.0, dim_2=3.0, dim_3=0.375, dim_4=0.5).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert 2.0 * dim_4 < dim_1, "Invalid geometry specified."
assert 2.0 * dim_3 < dim_2, "Invalid geometry specified."
points_outer = [
(-0.5 * dim_1, -0.5 * dim_2),
(0.5 * dim_1, -0.5 * dim_2),
(0.5 * dim_1, 0.5 * dim_2),
(-0.5 * dim_1, 0.5 * dim_2),
]
points_inner = [
(-0.5 * dim_1 + dim_4, -0.5 * dim_2 + dim_3),
(0.5 * dim_1 - dim_4, -0.5 * dim_2 + dim_3),
(0.5 * dim_1 - dim_4, 0.5 * dim_2 - dim_3),
(-0.5 * dim_1 + dim_4, 0.5 * dim_2 - dim_3),
]
inner_box = Polygon(points_inner)
outer_box = Polygon(points_outer)
c = (0.5 * dim_1, 0.5 * dim_2)
d = (0.5 * dim_1, -0.5 * dim_2)
e = (-0.5 * dim_1, -0.5 * dim_2)
f = (-0.5 * dim_1, 0.5 * dim_2)
geom = geometry.Geometry(geom=outer_box - inner_box, material=material)
geom.recovery_points = [c, d, e, f]
return geom
[docs]
def nastran_box1(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
dim_5: float,
dim_6: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a BOX1 section.
Constructs a BOX1 section with the center at the origin ``(0, 0)``, with six
parameters defining dimensions.
Args:
dim_1: Width (x) of box
dim_2: Depth (y) of box
dim_3: Thickness of top wall
dim_4: Thickness of bottom wall
dim_5: Thickness of left wall
dim_6: Thickness of right wall
material: Material to associate with this geometry
Returns:
BOX1 section geometry
Example:
The following example creates a BOX1 cross-section with a depth of 3.0 and width
of 4.0:
.. plot::
:include-source: True
:caption: BOX1 section geometry
from sectionproperties.pre.library import nastran_box1
nastran_box1(
dim_1=4.0, dim_2=3.0, dim_3=0.375, dim_4=0.5, dim_5=0.25, dim_6=0.75
).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert dim_5 + dim_6 < dim_1, "Invalid geometry specified."
assert dim_3 + dim_4 < dim_2, "Invalid geometry specified."
exterior_points = [
(0.0, 0.0),
(dim_1, 0.0),
(dim_1, dim_2),
(0.0, dim_2),
]
interior_points = [
(dim_6, dim_4),
(dim_1 - dim_5, dim_4),
(dim_1 - dim_5, dim_2 - dim_3),
(dim_6, dim_2 - dim_3),
]
geom = geometry.Geometry(
geom=Polygon(exterior_points) - Polygon(interior_points), material=material
)
c = (0.5 * dim_1, 0.5 * dim_2)
d = (0.5 * dim_1, -0.5 * dim_2)
e = (-0.5 * dim_1, -0.5 * dim_2)
f = (-0.5 * dim_1, 0.5 * dim_2)
geom.recovery_points = [c, d, e, f]
return geom
[docs]
def nastran_chan(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a CHAN section.
Constructs a CHAN (C-Channel) section with the web's middle center at the origin
``(0, 0)``, with four parameters defining dimensions.
Args:
dim_1: Width (x) of the CHAN-section
dim_2: Depth (y) of the CHAN-section
dim_3: Thickness of web (vertical portion)
dim_4: Thickness of flanges (top/bottom portion)
material: Material to associate with this geometry
Returns:
CHAN section geometry
Example:
The following example creates a CHAN cross-section with a depth of 4.0 and width
of 2.0:
.. plot::
:include-source: True
:caption: CHAN section geometry
from sectionproperties.pre.library import nastran_chan
nastran_chan(dim_1=2.0, dim_2=4.0, dim_3=0.25, dim_4=0.5).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert 2.0 * dim_4 < dim_2, "Invalid geometry specified."
assert dim_3 < dim_1, "Invalid geometry specified."
# construct the points
points = [
(0.0, 0.0),
(dim_1, 0.0),
(dim_1, dim_4),
(dim_3, dim_4),
(dim_3, dim_2 - dim_4),
(dim_1, dim_2 - dim_4),
(dim_1, dim_2),
(0.0, dim_2),
]
geom = geometry.Geometry(geom=Polygon(points), material=material)
c = (0.5 * dim_1, 0.5 * dim_2)
d = (0.5 * dim_1, -0.5 * dim_2)
e = (-0.5 * dim_1, -0.5 * dim_2)
f = (-0.5 * dim_1, 0.5 * dim_2)
geom.recovery_points = [c, d, e, f]
return geom
[docs]
def nastran_chan1(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a CHAN1 section.
Constructs a CHAN1 (C-Channel) section with the web's middle center at the origin
``(0, 0)``, with four parameters defining dimensions.
Args:
dim_1: Width (x) of channels
dim_2: Thickness (x) of web
dim_3: Spacing between channels (length of web)
dim_4: Depth (y) of CHAN1-section
material: Material to associate with this geometry
Returns:
CHAN1 section geometry
Example:
The following example creates a CHAN1 cross-section with a depth of 4.0 and
width of 1.75:
.. plot::
:include-source: True
:caption: CHAN1 section geometry
from sectionproperties.pre.library import nastran_chan1
nastran_chan1(dim_1=0.75, dim_2=1.0, dim_3=3.5, dim_4=4.0).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert dim_4 > dim_3, "Invalid geometry specified."
# construct the points and facets
tf = 0.5 * (dim_4 - dim_3)
points = [
(0, 0),
(dim_1 + dim_2, 0),
(dim_1 + dim_2, tf),
(dim_2, tf),
(dim_2, tf + dim_3),
(dim_2 + dim_1, tf + dim_3),
(dim_2 + dim_1, dim_4),
(0, dim_4),
]
geom = geometry.Geometry(geom=Polygon(points), material=material)
c = (0.5 * dim_2 + dim_1, 0.5 * dim_4)
d = (0.5 * dim_2 + dim_1, -0.5 * dim_4)
e = (-0.5 * dim_2, -0.5 * dim_4)
f = (-0.5 * dim_2, 0.5 * dim_4)
geom.recovery_points = [c, d, e, f]
return geom
[docs]
def nastran_chan2(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a CHAN2 section.
Constructs a CHAN2 (C-Channel) section with the bottom web's middle center at the
origin ``(0, 0)``, with four parameters defining dimensions.
Args:
dim_1: Thickness of channels
dim_2: Thickness of web
dim_3: Depth (y) of CHAN2-section
dim_4: Width (x) of CHAN2-section
material: Material to associate with this geometry
Returns:
CHAN2 section geometry
Example:
The following example creates a CHAN2 cross-section with a depth of 2.0 and
width of 4.0:
.. plot::
:include-source: True
:caption: CHAN2 section geometry
from sectionproperties.pre.library import nastran_chan2
nastran_chan2(dim_1=0.375, dim_2=0.5, dim_3=2.0, dim_4=4.0).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert dim_4 > 2.0 * dim_1, "Invalid geometry specified."
assert dim_3 > dim_2, "Invalid geometry specified."
# construct the points and facets
points = [
(0.0, 0.0),
(dim_4, 0.0),
(dim_4, dim_3),
(dim_4 - dim_1, dim_3),
(dim_4 - dim_1, dim_2),
(dim_1, dim_2),
(dim_1, dim_3),
(0.0, dim_3),
]
geom = geometry.Geometry(geom=Polygon(points), material=material)
c = (0.5 * dim_4, dim_3 - 0.5 * dim_2)
d = (0.5 * dim_4, -0.5 * dim_2)
e = (-0.5 * dim_4, -0.5 * dim_2)
f = (-0.5 * dim_4, dim_3 - 0.5 * dim_2)
geom.recovery_points = [c, d, e, f]
return geom
[docs]
def nastran_cross(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs Nastran's cruciform section.
Constructs Nastran's cruciform cross-section with the intersection's middle center
at the origin ``(0, 0)``, with four parameters defining dimensions.
Args:
dim_1: Twice the width of horizontal member protruding from the vertical center
member
dim_2: Thickness of the vertical member
dim_3: Depth (y) of the CROSS-section
dim_4: Thickness of the horizontal members
material: Material to associate with this geometry
Returns:
Cruciform section geometry
Example:
The following example creates a cruciform cross-section with a depth of 3.0:
.. plot::
:include-source: True
:caption: Cruciform section geometry
from sectionproperties.pre.library import nastran_cross
nastran_cross(dim_1=1.5, dim_2=0.375, dim_3=3.0, dim_4=0.25).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert dim_4 < dim_3, "Invalid geometry specified."
# construct the points and facets
d = 0.5 * (dim_3 - dim_4)
points = [
(0.5 * dim_1, 0.0),
(0.5 * dim_1 + dim_2, 0.0),
(0.5 * dim_1 + dim_2, d),
(dim_1 + dim_2, d),
(dim_1 + dim_2, d + dim_4),
(0.5 * dim_1 + dim_2, d + dim_4),
(0.5 * dim_1 + dim_2, dim_3),
(0.5 * dim_1, dim_3),
(0.5 * dim_1, d + dim_4),
(0.0, d + dim_4),
(0.0, d),
(0.5 * dim_1, d),
]
geom = geometry.Geometry(geom=Polygon(points), material=material)
c = (0.0, 0.5 * dim_3)
d_r = (0.5 * (dim_1 + dim_2), 0.0)
e = (0.0, -0.5 * dim_3)
f = (-0.5 * (dim_1 + dim_2), 0.0)
geom.recovery_points = [c, d_r, e, f]
return geom
[docs]
def nastran_fcross(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
dim_5: float,
dim_6: float,
dim_7: float,
dim_8: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a flanged cruciform section.
Constructs a flanged cruciform cross-section with the intersection's middle
center at the origin ``(0, 0)``, with eight parameters defining dimensions
Args:
dim_1: Depth (y) of flanged cruciform
dim_2: Width (x) of flanged cruciform
dim_3: Thickness of vertical web
dim_4: Thickness of horizontal web
dim_5: Length of flange attached to vertical web
dim_6: Thickness of flange attached to vertical web
dim_7: Length of flange attached to horizontal web
dim_8: Thickness of flange attached to horizontal web
material: Material to associate with this geometry
Returns:
Flanged cruciform section geometry
Example:
The following example demonstrates the creation of a flanged cross section:
.. plot::
:include-source: True
:caption: Flanged cruciform section geometry
from sectionproperties.pre.library import nastran_fcross
nastran_fcross(
dim_1=9.0, dim_2=6.0, dim_3=0.75, dim_4=0.625, dim_5=2.1, dim_6=0.375,
dim_7=4.5, dim_8=0.564
).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert dim_5 > dim_3, "Invalid geometry specified."
assert dim_7 > dim_4, "Invalid geometry specified."
assert dim_7 < dim_1, "Invalid geometry specified."
assert dim_5 < dim_2, "Invalid geometry specified."
assert dim_8 < (0.5 * dim_2 - 0.5 * dim_3), "Invalid geometry specified."
assert dim_6 < (0.5 * dim_1 - 0.5 * dim_4), "Invalid geometry specified."
# construct the points and facets
points = [
(0.5 * dim_3, -0.5 * dim_4),
(0.5 * dim_2 - dim_8, -0.5 * dim_4),
(0.5 * dim_2 - dim_8, -0.5 * dim_7),
(0.5 * dim_2, -0.5 * dim_7),
(0.5 * dim_2, 0.5 * dim_7),
(0.5 * dim_2 - dim_8, 0.5 * dim_7),
(0.5 * dim_2 - dim_8, 0.5 * dim_4),
(0.5 * dim_3, 0.5 * dim_4),
(0.5 * dim_3, 0.5 * dim_1 - dim_6),
(0.5 * dim_5, 0.5 * dim_1 - dim_6),
(0.5 * dim_5, 0.5 * dim_1),
(-0.5 * dim_5, 0.5 * dim_1),
(-0.5 * dim_5, 0.5 * dim_1 - dim_6),
(-0.5 * dim_3, 0.5 * dim_1 - dim_6),
(-0.5 * dim_3, 0.5 * dim_4),
(-0.5 * dim_2 + dim_8, 0.5 * dim_4),
(-0.5 * dim_2 + dim_8, 0.5 * dim_7),
(-0.5 * dim_2, 0.5 * dim_7),
(-0.5 * dim_2, -0.5 * dim_7),
(-0.5 * dim_2 + dim_8, -0.5 * dim_7),
(-0.5 * dim_2 + dim_8, -0.5 * dim_4),
(-0.5 * dim_3, -0.5 * dim_4),
(-0.5 * dim_3, -0.5 * dim_1 + dim_6),
(-0.5 * dim_5, -0.5 * dim_1 + dim_6),
(-0.5 * dim_5, -0.5 * dim_1),
(0.5 * dim_5, -0.5 * dim_1),
(0.5 * dim_5, -0.5 * dim_1 + dim_6),
(0.5 * dim_3, -0.5 * dim_1 + dim_6),
]
geom = geometry.Geometry(geom=Polygon(points), material=material)
c = (0.0, 0.5 * dim_1)
d = (0.5 * dim_2, 0.0)
e = (0.0, -0.5 * dim_1)
f = (-0.5 * dim_2, 0.0)
geom.recovery_points = [c, d, e, f]
return geom
[docs]
def nastran_dbox(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
dim_5: float,
dim_6: float,
dim_7: float,
dim_8: float,
dim_9: float,
dim_10: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a DBOX section.
Constructs a DBOX section with the center at the origin ``(0, 0)``, with ten
parameters defining dimensions.
Args:
dim_1: Width (x) of the DBOX-section
dim_2: Depth (y) of the DBOX-section
dim_3: Width (x) of left-side box
dim_4: Thickness of left wall
dim_5: Thickness of center wall
dim_6: Thickness of right wall
dim_7: Thickness of top left wall
dim_8: Thickness of bottom left wall
dim_9: Thickness of top right wall
dim_10: Thickness of bottom right wall
material: Material to associate with this geometry
Returns:
DBOX section geometry
Example:
The following example creates a DBOX cross-section with a depth of 3.0 and width
of 8.0:
.. plot::
:include-source: True
:caption: DBOX section geometry
from sectionproperties.pre.library import nastran_dbox
nastran_dbox(
dim_1=8.0, dim_2=3.0, dim_3=3.0, dim_4=0.5, dim_5=0.625, dim_6=0.75,
dim_7=0.375, dim_8=0.25, dim_9=0.5, dim_10=0.375
).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert (dim_4 + dim_5 + dim_6) < dim_1, "Invalid geometry specified."
assert (dim_4 + 0.5 * dim_5) < dim_3, "Invalid geometry specified."
assert (dim_7 + dim_8) < dim_2, "Invalid geometry specified."
assert (dim_9 + dim_10) < dim_2, "Invalid geometry specified."
# construct the points and facets
exterior_points = [
(0.0, 0.0),
(dim_1, 0.0),
(dim_1, dim_2),
(0.0, dim_2),
]
interior_points_1 = [
(dim_4, dim_8),
(dim_3 - dim_5 / 2.0, dim_8),
(dim_3 - dim_5 / 2.0, dim_2 - dim_7),
(dim_4, dim_2 - dim_7),
]
interior_points_2 = [
(dim_3 + dim_5 / 2.0, dim_10),
(dim_1 - dim_6, dim_10),
(dim_1 - dim_6, dim_2 - dim_9),
(dim_3 + dim_5 / 2.0, dim_2 - dim_9),
]
geom = geometry.Geometry(
geom=Polygon(exterior_points)
- Polygon(interior_points_1)
- Polygon(interior_points_2),
material=material,
)
c = (0.5 * dim_1, 0.5 * dim_2)
d = (0.5 * dim_1, -0.5 * dim_2)
e = (-0.5 * dim_1, -0.5 * dim_2)
f = (-0.5 * dim_1, 0.5 * dim_2)
geom.recovery_points = [c, d, e, f]
return geom
[docs]
def nastran_gbox(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
dim_5: float,
dim_6: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a GBOX section.
Constructs a GBOX section with the center at the origin ``(0, 0)``, with six
parameters defining dimensions.
Args:
dim_1: Width (x) of the GBOX-section
dim_2: Depth (y) of the GBOX-section
dim_3: Thickness of top flange
dim_4: Thickness of bottom flange
dim_5: Thickness of webs
dim_6: Spacing between webs
material: Material to associate with this geometry
Returns:
GBOX section geometry
Example:
The following example creates a GBOX cross-section with a depth of 2.5 and width
of 6.0:
.. plot::
:include-source: True
:caption: GBOX section geometry
from sectionproperties.pre.library import nastran_gbox
nastran_gbox(
dim_1=6.0, dim_2=2.5, dim_3=0.375, dim_4=0.25, dim_5=0.625, dim_6=1.0
).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert (dim_3 + dim_4) < dim_2, "Invalid geometry specified."
assert (2.0 * dim_5 + dim_6) < dim_1, "Invalid geometry specified."
# construct the points and facets
d = 0.5 * (dim_1 - dim_6 - 2.0 * dim_5)
exterior_points = [
(0.0, 0.0),
(dim_1, 0.0),
(dim_1, dim_4),
(d + 2.0 * dim_5 + dim_6, dim_4),
(d + 2.0 * dim_5 + dim_6, dim_2 - dim_3),
(dim_1, dim_2 - dim_3),
(dim_1, dim_2),
(0.0, dim_2),
(0.0, dim_2 - dim_3),
(d, dim_2 - dim_3),
(d, dim_4),
(0.0, dim_4),
]
interior_points = [
(d + dim_5, dim_4),
(d + dim_5 + dim_6, dim_4),
(d + dim_5 + dim_6, dim_2 - dim_3),
(d + dim_5, dim_2 - dim_3),
]
geom = geometry.Geometry(
geom=Polygon(exterior_points) - Polygon(interior_points), material=material
)
c = (0.5 * dim_1, 0.5 * dim_2)
d_r = (0.5 * dim_1, -0.5 * dim_2)
e = (-0.5 * dim_1, -0.5 * dim_2)
f = (-0.5 * dim_1, 0.5 * dim_2)
geom.recovery_points = [c, d_r, e, f]
return geom
[docs]
def nastran_h(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a H section.
Constructs a H section with the middle web's middle center at the origin ``(0, 0)``,
with four parameters defining dimensions.
Args:
dim_1: Spacing between vertical flanges (length of web)
dim_2: Twice the thickness of the vertical flanges
dim_3: Depth (y) of the H-section
dim_4: Thickness of the middle web
material: Material to associate with this geometry
Returns:
H section geometry
Example:
The following example creates a H cross-section with a depth of 3.5 and width of
2.75:
.. plot::
:include-source: True
:caption: H section geometry
from sectionproperties.pre.library import nastran_h
nastran_h(
dim_1=2.0, dim_2=0.75, dim_3=3.5, dim_4=0.2
).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert dim_4 < dim_3, "Invalid geometry specified."
d1 = 0.5 * (dim_3 - dim_4)
d2 = 0.5 * dim_2
# construct the points and facets
points = [
(0, 0),
(d2, 0),
(d2, d1),
(d2 + dim_1, d1),
(d2 + dim_1, 0),
(dim_1 + dim_2, 0),
(dim_1 + dim_2, dim_3),
(dim_1 + dim_2 - d2, dim_3),
(dim_1 + dim_2 - d2, d1 + dim_4),
(d2, d1 + dim_4),
(d2, dim_3),
(0, dim_3),
]
geom = geometry.Geometry(geom=Polygon(points), material=material)
c = (0.5 * (dim_1 + dim_2), 0.5 * dim_3)
d = (0.5 * (dim_1 + dim_2), -0.5 * dim_3)
e = (-0.5 * (dim_1 + dim_2), -0.5 * dim_3)
f = (-0.5 * (dim_1 + dim_2), 0.5 * dim_3)
geom.recovery_points = [c, d, e, f]
return geom
[docs]
def nastran_hat(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a HAT section.
Constructs a HAT section with the top most section's middle center at the origin
``(0, 0)``, with four parameters defining dimensions.
Args:
dim_1: Depth (y) of HAT-section
dim_2: Thickness of HAT-section
dim_3: Width (x) of top most section
dim_4: Width (x) of bottom sections
material: Material to associate with this geometry
Returns:
HAT section geometry
Example:
The following example creates a HAT cross-section with a depth of 1.25 and width
of 2.5:
.. plot::
:include-source: True
:caption: HAT section geometry
from sectionproperties.pre.library import nastran_hat
nastran_hat(dim_1=1.25, dim_2=0.25, dim_3=1.5, dim_4=0.5).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert 2.0 * dim_2 < dim_1, "Invalid geometry specified."
# construct the points and facets
points = [
(0.0, 0.0),
(dim_4 + dim_2, 0.0),
(dim_4 + dim_2, dim_1 - dim_2),
(dim_4 + dim_3 - dim_2, dim_1 - dim_2),
(dim_4 + dim_3 - dim_2, 0.0),
(2 * dim_4 + dim_3, 0.0),
(2.0 * dim_4 + dim_3, dim_2),
(dim_4 + dim_3, dim_2),
(dim_4 + dim_3, dim_1),
(dim_4, dim_1),
(dim_4, dim_2),
(0.0, dim_2),
]
geom = geometry.Geometry(geom=Polygon(points), material=material)
c = (0.5 * dim_3, 0.5 * dim_2)
d = (0.5 * dim_3 + dim_4, -dim_1 + dim_2)
e = (-0.5 * dim_3 - dim_4, -dim_1 + dim_2)
f = (-0.5 * dim_3, 0.5 * dim_2)
geom.recovery_points = [c, d, e, f]
return geom
[docs]
def nastran_hat1(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
dim_5: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a HAT1 section.
Constructs a HAT1 section with the bottom plate's bottom center at the origin
``(0, 0)``, with five parameters defining dimensions.
Args:
dim_1: Width(x) of the HAT1-section
dim_2: Depth (y) of the HAT1-section
dim_3: Width (x) of hat's top flange
dim_4: Thickness of hat stiffener
dim_5: Thicknesss of bottom plate
material: Material to associate with this geometry
Returns:
HAT1 section geometry
Example:
The following example creates a HAT1 cross-section with a depth of 2.0 and width
of 4.0:
.. plot::
:include-source: True
:caption: HAT1 section geometry
from sectionproperties.pre.library import nastran_hat1
nastran_hat1(
dim_1=4.0, dim_2=2.0, dim_3=1.5, dim_4=0.1875, dim_5=0.375
).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert (2.0 * dim_4 + dim_5) < dim_2, "Invalid geometry specified."
assert dim_3 < dim_1, "Invalid geometry specified."
# create bottom rectangular plate
bottom_plate = nastran_bar(
dim_1=dim_1, dim_2=dim_5, material=material
).shift_section(y_offset=dim_5 / 2)
# create the hat stiffener
d1 = dim_2 - dim_5
d2 = dim_4
d3 = dim_3
d4 = 0.5 * (dim_1 - dim_3)
hat = nastran_hat(dim_1=d1, dim_2=d2, dim_3=d3, dim_4=d4, material=material)
# Merge the two sections into one geometry
geom = (
hat.align_center(align_to=bottom_plate).align_to(other=bottom_plate, on="top")
+ bottom_plate
)
c = (-0.5 * dim_1, 0.0)
d = (0.5 * dim_1, 0.0)
e = (-0.5 * dim_3, dim_2)
f = (0.5 * dim_3, dim_2)
geom.recovery_points = [c, d, e, f]
return geom
[docs]
def nastran_hexa(
dim_1: float,
dim_2: float,
dim_3: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a HEXA section.
Constructs a HEXA (hexagon) section with the center at the origin ``(0, 0)``, with
three parameters defining dimensions.
Args:
dim_1: Spacing between bottom right point and right most point
dim_2: Width (x) of hexagon
dim_3: Depth (y) of hexagon
material: Material to associate with this geometry
Returns:
HEXA section geometry
Example:
The following example creates a HEXA cross-section with a depth of 1.5 and width
of 2.0:
.. plot::
:include-source: True
:caption: HEXA section geometry
from sectionproperties.pre.library import nastran_hexa
nastran_hexa(dim_1=0.5, dim_2=2.0, dim_3=1.5).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert dim_2 > dim_1, "Invalid geometry specified."
# construct the points and facets
points = [
(dim_1, 0.0),
(dim_2 - dim_1, 0.0),
(dim_2, 0.5 * dim_3),
(dim_2 - dim_1, dim_3),
(dim_1, dim_3),
(0.0, 0.5 * dim_3),
]
geom = geometry.Geometry(geom=Polygon(points), material=material)
c = 0.0, 0.5 * dim_3
d = 0.0, -0.5 * dim_3
e = 0.5 * dim_2, 0.0
f = -0.5 * dim_2, 0.0
geom.recovery_points = [c, d, e, f]
return geom
[docs]
def nastran_i(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
dim_5: float,
dim_6: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs Nastran's I section.
Constructs Nastran's I section with the bottom flange's middle center at the origin
``(0, 0)``, with six parameters defining dimensions.
Args:
dim_1: Depth(y) of the I Section
dim_2: Width (x) of bottom flange
dim_3: Width (x) of top flange
dim_4: Thickness of web
dim_5: Thickness of bottom web
dim_6: Thickness of top web
material: Material to associate with this geometry
Returns:
I section geometry
Example:
The following example creates an I cross-section with a depth of 5.0:
.. plot::
:include-source: True
:caption: I section geometry
from sectionproperties.pre.library import nastran_i
nastran_i(
dim_1=5.0, dim_2=2.0, dim_3=3.0, dim_4=0.25, dim_5=0.375, dim_6=0.5
).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert (dim_5 + dim_6) < dim_1, "Invalid geometry specified."
assert dim_4 < dim_3, "Invalid geometry specified."
assert dim_4 < dim_2, "Invalid geometry specified."
# construct the points and facets
db = 0.5 * (dim_2 - dim_4)
dt = 0.5 * (dim_3 - dim_4)
points = [
(0.0, 0.0),
(dim_2, 0.0),
(dim_2, dim_5),
(db + dim_4, dim_5),
(db + dim_4, dim_1 - dim_6),
(db + dim_4 + dt, dim_1 - dim_6),
(db + dim_4 + dt, dim_1),
(db - dt, dim_1),
(db - dt, dim_1 - dim_6),
(db, dim_1 - dim_6),
(db, dim_5),
(0, dim_5),
]
geom = geometry.Geometry(geom=Polygon(points), material=material)
c = (0.5 * dim_3, 0.5 * dim_1)
d = (0.5 * dim_3, -0.5 * dim_1)
e = (-0.5 * dim_3, -0.5 * dim_1)
f = (-0.5 * dim_3, 0.5 * dim_1)
geom.recovery_points = [c, d, e, f]
return geom
[docs]
def nastran_i1(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs an I1 section.
Constructs an I1 section with the web's middle center at the origin ``(0, 0)``, with
four parameters defining dimensions.
Args:
dim_1: Twice distance from web end to flange end
dim_2: Thickness of web
dim_3: Length of web (spacing between flanges)
dim_4: Depth (y) of the I1-section
material: Material to associate with this geometry
Returns:
I1 section geometry
Example:
The following example creates an I1 cross-section with a depth of 5.0 and width
of 1.75:
.. plot::
:include-source: True
:caption: I1 section geometry
from sectionproperties.pre.library import nastran_i1
nastran_i1(dim_1=1.0, dim_2=0.75, dim_3=4.0, dim_4=5.0).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert dim_4 > dim_3, "Invalid geometry specified."
# construct the points and facets
t = 0.5 * (dim_4 - dim_3)
points = [
(0.0, 0.0),
(dim_1 + dim_2, 0.0),
(dim_1 + dim_2, t),
(0.5 * dim_1 + dim_2, t),
(0.5 * dim_1 + dim_2, t + dim_3),
(dim_1 + dim_2, t + dim_3),
(dim_1 + dim_2, dim_4),
(0.0, dim_4),
(0.0, t + dim_3),
(0.5 * dim_1, t + dim_3),
(0.5 * dim_1, t),
(0.0, t),
]
geom = geometry.Geometry(geom=Polygon(points), material=material)
c = (0.5 * (dim_1 + dim_2), 0.5 * dim_4)
d = (0.5 * (dim_1 + dim_2), -0.5 * dim_4)
e = (-0.5 * (dim_1 + dim_2), -0.5 * dim_4)
f = (-0.5 * (dim_1 + dim_2), 0.5 * dim_4)
geom.recovery_points = [c, d, e, f]
return geom
[docs]
def nastran_l(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs an L section.
Constructs an L section with the intersection's center at the origin ``(0, 0)``,with
four parameters defining dimensions.
Args:
dim_1: Width (x) of the L-section
dim_2: Depth (y) of the L-section
dim_3: Thickness of flange (horizontal portion)
dim_4: Thickness of web (vertical portion)
material: Material to associate with this geometry
Returns:
L section geometry
Example:
The following example creates an L cross-section with a depth of 6.0 and width
of 3.0:
.. plot::
:include-source: True
:caption: L section geometry
from sectionproperties.pre.library import nastran_l
nastran_l(dim_1=3.0, dim_2=6.0, dim_3=0.375, dim_4=0.625).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert dim_4 < dim_1, "Invalid geometry specified."
assert dim_3 < dim_2, "Invalid geometry specified."
# construct the points and facets
points = [
(0, 0),
(dim_1, 0),
(dim_1, dim_3),
(dim_4, dim_3),
(dim_4, dim_2),
(0, dim_2),
]
geom = geometry.Geometry(geom=Polygon(points), material=material)
c = (0.5 * dim_4, dim_2 - 0.5 * dim_3)
d = (dim_1 - 0.5 * dim_4, -0.5 * dim_3)
e = (-0.5 * dim_4, -0.5 * dim_3)
f = (-0.5 * dim_4, dim_2 - 0.5 * dim_3)
geom.recovery_points = [c, d, e, f]
return geom
[docs]
def nastran_rod(
dim_1: float,
n: int,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a circular rod section.
Constructs a circular rod section with the center at the origin ``(0, 0)``, with one
parameter defining dimension.
Args:
dim_1: Radius of the circular rod section
n: Number of points discretising the circle
material: Material to associate with this geometry
Returns:
Circular rod section geometry
Example:
The following example creates a circular rod with a radius of 3.0 and 50 points
discretising the boundary:
.. plot::
:include-source: True
:caption: Circular rod section geometry
from sectionproperties.pre.library import nastran_rod
nastran_rod(dim_1=3.0, n=50).plot_geometry()
"""
# loop through each point on the circle
d = 2.0 * dim_1
points = []
for i in range(n):
# determine polar angle
theta = i * 2 * np.pi * 1.0 / n
# calculate location of the point
x = 0.5 * d * np.cos(theta)
y = 0.5 * d * np.sin(theta)
# append the current point to the points list
points.append((x, y))
geom = geometry.Geometry(geom=Polygon(points), material=material)
c = (0.0, dim_1)
d_r = (dim_1, 0.0)
e = (0.0, -dim_1)
f = (-dim_1, 0.0)
geom.recovery_points = [c, d_r, e, f]
return geom
[docs]
def nastran_tee(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a T section.
Constructs a T section with the top flange's middle center at the origin ``(0, 0)``,
with four parameters defining dimensions.
Args:
dim_1: Width (x) of top flange
dim_2: Depth (y) of the T-section
dim_3: Thickness of top flange
dim_4: Thickness of web
material: Material to associate with this geometry
Returns:
T section geometry
Example:
The following example creates a T cross-section with a depth of 4.0 and width of
3.0:
.. plot::
:include-source: True
:caption: T section geometry
from sectionproperties.pre.library import nastran_tee
nastran_tee(dim_1=3.0, dim_2=4.0, dim_3=0.375, dim_4=0.25).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert dim_4 < dim_1, "Invalid geometry specified."
assert dim_3 < dim_2, "Invalid geometry specified."
d = dim_2
b = dim_1
t_f = dim_3
t_w = dim_4
r = 0.0
n_r = 1
points: list[tuple[float, float]] = []
# add first two points
points.append((b * 0.5 - t_w * 0.5, 0))
points.append((b * 0.5 + t_w * 0.5, 0))
# construct the top right radius
pt = b * 0.5 + t_w * 0.5 + r, d - t_f - r
points += sp_utils.draw_radius(pt=pt, r=r, theta=np.pi, n=n_r, ccw=False)
# add next four points
points.append((b, d - t_f))
points.append((b, d))
points.append((0, d))
points.append((0, d - t_f))
# construct the top left radius
pt = b * 0.5 - t_w * 0.5 - r, d - t_f - r
points += sp_utils.draw_radius(pt=pt, r=r, theta=0.5 * np.pi, n=n_r, ccw=False)
geom = geometry.Geometry(geom=Polygon(points), material=material)
c = (0.0, 0.5 * dim_3)
d_r = (0.5 * dim_1, 0.5 * dim_3)
e = (0.0, 0.5 * dim_3 - dim_2)
f = (-0.5 * dim_1, 0.5 * dim_3)
geom.recovery_points = [c, d_r, e, f]
return geom
[docs]
def nastran_tee1(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a T1 section.
Constructs a T1 section with the right flange's middle center at the origin
``(0, 0)``, with four parameters defining dimensions.
Args:
dim_1: Depth (y) of T1-section
dim_2: Length (x) of web
dim_3: Thickness of right flange
dim_4: Thickness of web
material: Material to associate with this geometry
Returns:
T1 section geometry
Example:
The following example creates a T1 cross-section with a depth of 3.0 and width
of 3.875:
.. plot::
:include-source: True
:caption: T1 section geometry
from sectionproperties.pre.library import nastran_tee1
nastran_tee1(dim_1=3.0, dim_2=3.5, dim_3=0.375, dim_4=0.25).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert dim_4 < dim_1, "Invalid geometry specified."
# construct the points and facets
d1 = (dim_1 - dim_4) / 2.0
points = [
(0, 0),
(dim_3, 0),
(dim_3, dim_1),
(0, dim_1),
(0, d1 + dim_4),
(-dim_2, d1 + dim_4),
(-dim_2, d1),
(0, d1),
]
geom = geometry.Geometry(geom=Polygon(points), material=material)
c = (0.5 * dim_3, 0)
d = (0.5 * dim_3, -0.5 * dim_1)
e = (-0.5 * dim_3 - dim_2, 0)
f = (0.5 * dim_3, 0.5 * dim_1)
geom.recovery_points = [c, d, e, f]
return geom
[docs]
def nastran_tee2(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a T2 section.
Constructs a T2 section with the bottom flange's middle center at the origin
``(0, 0)``, with four parameters defining dimensions.
Args:
dim_1: Width (x) of T2-section
dim_2: Depth (y) of T2-section
dim_3: Thickness of bottom flange
dim_4: Thickness of web
material: Material to associate with this geometry
Returns:
T2 section geometry
Example:
The following example creates a T2 cross-section with a depth of 4.0 and width
of 3.0:
.. plot::
:include-source: True
:caption: T2 section geometry
from sectionproperties.pre.library import nastran_tee2
nastran_tee2(dim_1=3.0, dim_2=4.0, dim_3=0.375, dim_4=0.5).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert dim_4 < dim_1, "Invalid geometry specified."
assert dim_3 < dim_2, "Invalid geometry specified."
# construct the points and facets
d1 = 0.5 * (dim_1 - dim_4)
points = [
(0.0, 0.0),
(dim_1, 0.0),
(dim_1, dim_3),
(dim_1 - d1, dim_3),
(dim_1 - d1, dim_2),
(d1, dim_2),
(d1, dim_3),
(0, dim_3),
]
geom = geometry.Geometry(geom=Polygon(points), material=material)
c = (0.5 * dim_4, dim_2 - 0.5 * dim_3)
d = (0.5 * dim_1, -0.5 * dim_3)
e = (-0.5 * dim_1, -0.5 * dim_3)
f = (-0.5 * dim_4, dim_2 - 0.5 * dim_3)
geom.recovery_points = [c, d, e, f]
return geom
[docs]
def nastran_tube(
dim_1: float,
dim_2: float,
n: int,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a circular tube section.
Constructs a circular tube section with the center at the origin ``(0, 0)``, with
two parameters defining dimensions.
Args:
dim_1: Outer radius of the circular tube section
dim_2: Inner radius of the circular tube section
n: Number of points discretising the circle
material: Material to associate with this geometry
Returns:
Circular tube section geometry
Example:
The following example creates a circular tube cross-section with an outer radius
of 3.0 and an inner radius of 2.5:
.. plot::
:include-source: True
:caption: Circular tube section geometry
from sectionproperties.pre.library import nastran_tube
nastran_tube(dim_1=3.0, dim_2=2.5, n=37).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert dim_2 < dim_1, "Invalid geometry specified."
d = 2.0 * dim_1
t = dim_1 - dim_2
points_inner = []
points_outer = []
# loop through each point of the CHS
for i in range(n):
# determine polar angle
theta = i * 2 * np.pi * 1.0 / n
# calculate location of outer and inner points
x_outer = 0.5 * d * np.cos(theta)
y_outer = 0.5 * d * np.sin(theta)
x_inner = (0.5 * d - t) * np.cos(theta)
y_inner = (0.5 * d - t) * np.sin(theta)
# append the current points to the points list
points_outer.append((x_outer, y_outer))
points_inner.append((x_inner, y_inner))
exterior = geometry.Geometry(geom=Polygon(points_outer), material=material)
interior = geometry.Geometry(geom=Polygon(points_inner), material=material)
geom = exterior - interior
c = (0.0, dim_1)
d_r = (dim_1, 0.0)
e = (0.0, -dim_1)
f = (-dim_1, 0.0)
geom.recovery_points = [c, d_r, e, f]
return geom
[docs]
def nastran_tube2(
dim_1: float,
dim_2: float,
n: int,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a circular TUBE2 section.
Constructs a circular TUBE2 section with the center at the origin ``(0, 0)``, with
two parameters defining dimensions.
Args:
dim_1: Outer radius of the circular tube section
dim_2: Thickness of wall
n: Number of points discretising the circle
material: Material to associate with this geometry
Returns:
TUBE2 section geometry
Example:
The following example creates a circular TUBE2 cross-section with an outer
radius of 3.0 and a wall thickness of 0.5:
.. plot::
:include-source: True
:caption: TUBE2 section geometry
from sectionproperties.pre.library import nastran_tube2
nastran_tube2(dim_1=3.0, dim_2=0.5, n=37).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert dim_2 < dim_1, "Invalid geometry specified."
d = 2.0 * dim_1
t = dim_2
points_inner = []
points_outer = []
# loop through each point of the section
for i in range(n):
# determine polar angle
theta = i * 2 * np.pi * 1.0 / n
# calculate location of outer and inner points
x_outer = 0.5 * d * np.cos(theta)
y_outer = 0.5 * d * np.sin(theta)
x_inner = (0.5 * d - t) * np.cos(theta)
y_inner = (0.5 * d - t) * np.sin(theta)
# append the current points to the points list
points_outer.append((x_outer, y_outer))
points_inner.append((x_inner, y_inner))
exterior = geometry.Geometry(geom=Polygon(points_outer), material=material)
interior = geometry.Geometry(geom=Polygon(points_inner), material=material)
geom = exterior - interior
c = (0.0, dim_1)
d_r = (dim_1, 0.0)
e = (0.0, -dim_1)
f = (-dim_1, 0.0)
geom.recovery_points = [c, d_r, e, f]
return geom
[docs]
def nastran_zed(
dim_1: float,
dim_2: float,
dim_3: float,
dim_4: float,
material: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.Geometry:
"""Constructs a Z section.
Constructs a Z section with the web's middle center at the origin ``(0, 0)``, with
four parameters defining dimensions.
Args:
dim_1: Width (x) of horizontal members
dim_2: Thickness of web
dim_3: Spacing between horizontal members (length of web)
dim_4: Depth (y) of Z-section
material: Material to associate with this geometry
Returns:
Z section geometry
Example:
The following example creates a Z cross-section with a depth of 4.0 and width of
1.125:
.. plot::
:include-source: True
:caption: Z section geometry
from sectionproperties.pre.library import nastran_zed
nastran_zed(dim_1=1.125, dim_2=0.5, dim_3=3.5, dim_4=4.0).plot_geometry()
"""
# Ensure dimensions are physically relevant
assert dim_4 > dim_3, "Invalid geometry specified."
# construct the points and facets
t = 0.5 * (dim_4 - dim_3)
points = [
(dim_1, 0.0),
(2.0 * dim_1 + dim_2, 0.0),
(2.0 * dim_1 + dim_2, t),
(dim_1 + dim_2, t),
(dim_1 + dim_2, dim_4),
(0.0, dim_4),
(0.0, dim_4 - t),
(dim_1, dim_4 - t),
]
geom = geometry.Geometry(geom=Polygon(points), material=material)
c = (0.5 * dim_2, 0.5 * dim_4)
d = (0.5 * dim_2 + dim_1, -0.5 * dim_4)
e = (-0.5 * dim_2, -0.5 * dim_4)
f = (-0.5 * dim_2 - dim_1, 0.5 * dim_4)
geom.recovery_points = [c, d, e, f]
return geom