Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 220 additions & 3 deletions docs/examples/geometry/section_library.ipynb

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions src/sectionproperties/pre/library/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,6 @@
tee_section,
zed_section,
)
from sectionproperties.pre.library.timber_sections import (
clt_rectangular_section
)
66 changes: 66 additions & 0 deletions src/sectionproperties/pre/library/timber_sections.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""Timber sections library."""

from __future__ import annotations

import sectionproperties.pre.geometry as geometry
import sectionproperties.pre.library.primitive_sections as primitive_sections
import sectionproperties.pre.pre as pre


def clt_rectangular_section(
d: list[float],
lay_orient: list[int],
b: float,
timb_mat0: pre.Material = pre.DEFAULT_MATERIAL,
timb_mat90: pre.Material = pre.DEFAULT_MATERIAL,
) -> geometry.CompoundGeometry:
"""Constructs a timber rectangular section.

Constructs a timber rectangular section of depth ``d`` and width ``b``.

.. note::

Args:
d: Timber layer section thickness
lay_orient: List of layer orientation
b: Timber section width
timb_mat0: Material object to assign to the timber area
parallel-to-grain
timb_mat90: Material object to assign to the timber area,
perpendicular-to-grain

Raises:
ValueError: Geometry generation failed

Returns:
Timber rectangular section geometry

Example:
The following example creates a 120mm CLT cross-section.
"""

layer_geom = list()
for idx in range(len(d)):
di = float(d[idx])
layer = lay_orient[idx]

if layer is int(0):
timb_mat = timb_mat0
else:
timb_mat = timb_mat90

# create rectangular timber geometry
layer = primitive_sections.rectangular_section(d=di, b=b,
material=timb_mat)
offset = -d[idx] * (idx + 1)
layer = layer.shift_section(y_offset=offset)

layer_geom.append(layer)

# create compound geometry
geom = geometry.CompoundGeometry(geoms=layer_geom)

if isinstance(geom, geometry.CompoundGeometry):
return geom
else:
raise ValueError("Timber section generation failed.")
74 changes: 74 additions & 0 deletions tests/section_library/test_timber_sections.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""Tests for the timber sections library."""

from __future__ import annotations

import numpy as np
import pytest
import pytest_check as check

import sectionproperties.pre.library.timber_sections as ts
import sectionproperties.pre.library.primitive_sections as ps
import sectionproperties.pre.pre as pre


r_tol = 1e-6


# material setup
@pytest.fixture
def get_materials() -> tuple[pre.Material, pre.Material]:
"""Creates a timber material parallel and perpendicular-to-grain.

Returns:
Material objects
"""

timb_mat0 = pre.Material(
name="Timber E0",
elastic_modulus=9.5e3,
poissons_ratio=0.35,
density=4.4e-7,
yield_strength=5.5,
color="burlywood",
)

timb_mat90 = pre.Material(
name="Timber90",
elastic_modulus=317,
poissons_ratio=0.35,
density=4.4e-7,
yield_strength=5.5,
color="orange",
)

return timb_mat0, timb_mat90


def test_timber_clt_rectangular_section(get_materials):
"""Tests the timber clt_rectangular_section() method."""
timber0, timber90 = get_materials

rect = ts.clt_rectangular_section(
d=[40, 40, 40],
lay_orient=[0, 90, 0],
b=1000,
timb_mat0=timber0,
timb_mat90=timber90
)

# check geometry is created correctly
timb0_area = 0
timb90_area = 0

for geom in rect.geoms:
if geom.material == timber0:
timb0_area += geom.calculate_area()
elif geom.material == timber90:
timb90_area += geom.calculate_area()

actual_timb0_area = 2 * 40 * 1000
actual_timb90_area = 40 * 1000

# check areas
check.almost_equal(timb0_area, actual_timb0_area)
check.almost_equal(timb90_area, actual_timb90_area)
Loading