Source code for sectionproperties.pre.library.concrete_sections

"""Concrete sections library."""

from __future__ import annotations

import numpy as np

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


[docs] def concrete_rectangular_section( d: float, b: float, dia_top: float, area_top: float, n_top: int, c_top: float, dia_bot: float, area_bot: float, n_bot: int, c_bot: float, dia_side: float | None = None, area_side: float | None = None, n_side: int = 0, c_side: float = 0.0, n_circle: int = 4, conc_mat: pre.Material = pre.DEFAULT_MATERIAL, steel_mat: pre.Material = pre.DEFAULT_MATERIAL, ) -> geometry.CompoundGeometry: """Constructs a reinforced concrete rectangular section. Constructs a reinforced concrete rectangular section of depth ``d`` and width ``b``. .. note:: As the reinforcing bars are described by discretised circles, the area of each bar is required to ensure that the correct reinforcing area is provided. Args: d: Concrete section depth b: Concrete section width dia_top: Diameter of the top reinforcing bars, used for calculating bar placement area_top: Area of the top reinforcing bars n_top: Number of top, equally spaced reinforcing bars c_top: Clear cover to the top reinforcing bars dia_bot: Diameter of the bottom reinforcing bars, used for calculating bar placement area_bot: Area of the bottom reinforcing bars n_bot: Number of bottom, equally spaced reinforcing bars c_bot: Clear cover to the bottom reinforcing bars dia_side: Diameter of the side reinforcing bars, used for calculating bar placement area_side: Area of the side reinforcing bars n_side: Number of side, equally spaced reinforcing bars c_side: Clear cover to the side reinforcing bars n_circle: Number of points used to discretise the circular reinforcing bars conc_mat: Material object to assign to the concrete area steel_mat: Material object to assign to the steel area Raises: ValueError: Geometry generation failed Returns: Reinforced concrete rectangular section geometry Example: The following example creates a 600 mm deep x 300 mm wide concrete beam. The beam is reinforced with 3 x 16 mm top bars (20 mm cover), 3 x 20 mm bottom bars (30 mm cover), and 2 x 12 mm side bars (30 mm cover). A coarse finite element mesh is generated to show the different material regions: .. plot:: :include-source: True :caption: Reinforced concrete rectangular section geometry from sectionproperties.pre import Material from sectionproperties.pre.library import concrete_rectangular_section from sectionproperties.analysis import Section concrete = Material( name="Concrete", elastic_modulus=30.1e3, poissons_ratio=0.2, yield_strength=32, density=2.4e-6, color="lightgrey", ) steel = Material( name="Steel", elastic_modulus=200e3, poissons_ratio=0.3, yield_strength=500, density=7.85e-6, color="grey", ) geom = concrete_rectangular_section( d=600, b=300, dia_top=16, area_top=200, n_top=3, c_top=20, dia_bot=20, area_bot=310, n_bot=3, c_bot=30, dia_side=12, area_side=110, n_side=2, c_side=30, n_circle=16, conc_mat=concrete, steel_mat=steel, ) geom.create_mesh(mesh_sizes=[0]) # a size of zero creates a coarse mesh Section(geometry=geom).plot_mesh() """ # create rectangular concrete geometry geom = primitive_sections.rectangular_section(b=b, d=d, material=conc_mat) # calculate reinforcing bar dimensions for top and bottom layers if n_top == 1: x_i_top = b / 2 spacing_top = 0.0 else: if c_side: x_i_top = c_side + dia_top / 2 spacing_top = (b - 2 * c_side - dia_top) / (n_top - 1) else: x_i_top = c_top + dia_top / 2 spacing_top = (b - 2 * c_top - dia_top) / (n_top - 1) if n_bot == 1: x_i_bot = b / 2 spacing_bot = 0.0 else: if c_side: x_i_bot = c_side + dia_bot / 2 spacing_bot = (b - 2 * c_side - dia_bot) / (n_bot - 1) else: x_i_bot = c_bot + dia_bot / 2 spacing_bot = (b - 2 * c_bot - dia_bot) / (n_bot - 1) # calculate reinforcing bar dimensions for side layers if specified if dia_side and n_side != 0: x_i_side_left = c_side + dia_side / 2 x_i_side_right = b - x_i_side_left spacing_side = (d - c_top - c_bot - dia_top / 2 - dia_bot / 2) / (n_side + 1) else: x_i_side_left = 0.0 x_i_side_right = 0.0 spacing_side = 0.0 # add top bars for idx in range(n_top): bar = primitive_sections.circular_section_by_area( area=area_top, n=n_circle, material=steel_mat, ).shift_section( x_offset=x_i_top + spacing_top * idx, y_offset=d - c_top - dia_top / 2, ) geom = (geom - bar) + bar # add bot bars for i in range(n_bot): bar = primitive_sections.circular_section_by_area( area=area_bot, n=n_circle, material=steel_mat, ).shift_section( x_offset=x_i_bot + spacing_bot * i, y_offset=c_bot + dia_bot / 2, ) geom = (geom - bar) + bar # add side bars if area_side: for i in range(n_side): bar_left = primitive_sections.circular_section_by_area( area=area_side, n=n_circle, material=steel_mat, ).shift_section( x_offset=x_i_side_left, y_offset=c_bot + dia_bot / 2 + spacing_side * (i + 1), ) bar_right = bar_left.shift_section(x_offset=x_i_side_right - x_i_side_left) geom = (geom - bar_left - bar_right) + bar_left + bar_right if isinstance(geom, geometry.CompoundGeometry): return geom else: raise ValueError("Concrete section generation failed.")
[docs] def concrete_column_section( d: float, b: float, dia_bar: float, area_bar: float, n_x: int, n_y: int, cover: float, n_circle: int = 4, filled: bool = False, conc_mat: pre.Material = pre.DEFAULT_MATERIAL, steel_mat: pre.Material = pre.DEFAULT_MATERIAL, ) -> geometry.CompoundGeometry: """Constructs a reinforced concrete column section. Constructs a reinforced concrete column section of depth ``d`` and width ``b``. .. note:: As the reinforcing bars are described by discretised circles, the area of each bar is required to ensure that the correct reinforcing area is provided. Args: d: Concrete section depth, parallel to the y-axis b: Concrete section width, parallel to the x-axis dia_bar: Diameter of the reinforcing bars, used for calculating bar placement area_bar: Area of the reinforcing bars n_x: Number of bars placed across the width of the section, minimum 2 n_y: Number of bars placed across the depth of the section, minimum 2 cover: Clear cover to the reinforcing bars n_circle: Number of points used to discretise the circular reinforcing bars filled: When True, will populate the concrete section with an equally spaced 2D array of reinforcing bars numbering 'n_x' by 'n_y'. When False, only the bars around the perimeter of the array will be present. conc_mat: Material object to assign to the concrete area steel_mat: Material object to assign to the steel area Returns: Reinforced concrete column section geometry Raises: ValueError: If the number of bars in either 'n_x' or 'n_y' is not greater than or equal to 2 Example: The following example creates a 600 mm deep x 300 mm wide concrete column. The beam is reinforced with 25 mm diameter reinforcing bars with 35 mm cover. There are 3 bars in the x-direction and 6 bars in the y-direction. A coarse finite element mesh is generated to show the different material regions: .. plot:: :include-source: True :caption: Reinforced concrete column section geometry from sectionproperties.pre import Material from sectionproperties.pre.library import concrete_column_section from sectionproperties.analysis import Section concrete = Material( name="Concrete", elastic_modulus=30.1e3, poissons_ratio=0.2, yield_strength=32, density=2.4e-6, color="lightgrey", ) steel = Material( name="Steel", elastic_modulus=200e3, poissons_ratio=0.3, yield_strength=500, density=7.85e-6, color="grey", ) geom = concrete_column_section( d=600, b=300, dia_bar=25, area_bar=500, n_x=3, n_y=6, cover=35, n_circle=4, filled=False, conc_mat=concrete, steel_mat=steel, ) geom.create_mesh(mesh_sizes=[0]) # a size of zero creates a coarse mesh Section(geometry=geom).plot_mesh() """ concrete_geometry = primitive_sections.rectangular_section( d=d, b=b, material=conc_mat ) bar_extents = concrete_geometry.offset_perimeter( -cover - dia_bar / 2 ).calculate_extents() bar_x_min, bar_x_max, bar_y_min, bar_y_max = bar_extents b_edge_bars_x: list[float] = np.linspace(bar_x_min, bar_x_max, n_x).tolist() d_edge_bars_y: list[float] = np.linspace(bar_y_min, bar_y_max, n_y).tolist() if not filled: b_edge_bars_y1 = [bar_y_min] * n_x b_edge_bars_y2 = [bar_y_max] * n_x d_edge_bars_x1 = [bar_x_min] * n_y d_edge_bars_x2 = [bar_x_max] * n_y b_edge_bars_top = list(zip(b_edge_bars_x, b_edge_bars_y2)) b_edge_bars_bottom = list(zip(b_edge_bars_x, b_edge_bars_y1)) d_edge_bars_right = list(zip(d_edge_bars_x2, d_edge_bars_y)) d_edge_bars_left = list(zip(d_edge_bars_x1, d_edge_bars_y)) all_bar_coords = list( set( b_edge_bars_top + b_edge_bars_bottom + d_edge_bars_right + d_edge_bars_left ) ) else: xy = np.meshgrid(b_edge_bars_x, d_edge_bars_y) all_bar_coords = np.append(xy[0].reshape(-1, 1), xy[1].reshape(-1, 1), axis=1) # type: ignore for bar_coord in all_bar_coords: concrete_geometry = add_bar( geometry=concrete_geometry, area=area_bar, material=steel_mat, x=bar_coord[0], y=bar_coord[1], n=n_circle, ) if isinstance(concrete_geometry, geometry.CompoundGeometry): return concrete_geometry else: raise ValueError("Concrete section generation failed.")
[docs] def concrete_tee_section( d: float, b: float, d_f: float, b_f: float, dia_top: float, area_top: float, n_top: int, c_top: float, dia_bot: float, area_bot: float, n_bot: int, c_bot: float, dia_side: float | None = None, area_side: float | None = None, n_side: int = 0, c_side: float = 0.0, n_circle: int = 4, conc_mat: pre.Material = pre.DEFAULT_MATERIAL, steel_mat: pre.Material = pre.DEFAULT_MATERIAL, ) -> geometry.CompoundGeometry: """Constructs a reinforced concrete tee section. Constructs a concrete tee section of depth ``d``, width ``b``, flange depth ``d_f`` and flange width ``b_f``. Args: d: Concrete section depth b: Concrete section width d_f: Concrete section flange depth b_f: Concrete section flange width dia_top: Diameter of the top reinforcing bars, used for calculating bar placement area_top: Area of the top reinforcing bars n_top: Number of top, equally spaced reinforcing bars c_top: Clear cover to the top reinforcing bars dia_bot: Diameter of the bottom reinforcing bars, used for calculating bar placement area_bot: Area of the bottom reinforcing bars n_bot: Number of bottom, equally spaced reinforcing bars c_bot: Clear cover to the bottom reinforcing bars dia_side: Diameter of the side reinforcing bars, used for calculating bar placement area_side: Area of the side reinforcing bars n_side: Number of side, equally spaced reinforcing bars c_side: Clear cover to the side reinforcing bars n_circle: Number of points used to discretise the circular reinforcing bars conc_mat: Material object to assign to the concrete area steel_mat: Material object to assign to the steel area Raises: ValueError: Geometry generation failed Returns: Reinforced concrete tee section geometry Example: The following example creates a 900 mm deep x 450 mm wide concrete tee beam with a 150 mm deep x 1800 mm wide flange. The tee beam is reinforced with 12 x 24 mm top bars, 5 x 28 mm bottom bars and 4 x 16 mm side bars, with 42 mm cover all around (30 mm cover + 12 mm tie). A coarse finite element mesh is generated to show the different material regions: .. plot:: :include-source: True :caption: Reinforced concrete tee section geometry from sectionproperties.pre import Material from sectionproperties.pre.library import concrete_tee_section from sectionproperties.analysis import Section concrete = Material( name="Concrete", elastic_modulus=30.1e3, poissons_ratio=0.2, yield_strength=32, density=2.4e-6, color="lightgrey", ) steel = Material( name="Steel", elastic_modulus=200e3, poissons_ratio=0.3, yield_strength=500, density=7.85e-6, color="grey", ) geom = concrete_tee_section( d=900, b=450, d_f=150, b_f=1800, dia_top=24, area_top=450, n_top=12, c_top=42, dia_bot=28, area_bot=620, n_bot=5, c_bot=42, dia_side=16, area_side=200, n_side=4, c_side=42, n_circle=16, conc_mat=concrete, steel_mat=steel, ) geom.create_mesh(mesh_sizes=[0]) # a size of zero creates a coarse mesh Section(geometry=geom).plot_mesh() """ # generate concrete geometry beam = primitive_sections.rectangular_section(b=b, d=d - d_f, material=conc_mat) flange = primitive_sections.rectangular_section(b=b_f, d=d_f, material=conc_mat) geom = beam + flange.align_to(other=beam, on="top").shift_section( x_offset=-(b_f / 2 - b / 2) ) geom = geom.shift_section(x_offset=-b / 2) # calculate reinforcing bar dimensions for top and bottom layers if n_top == 1: x_i_top = 0.0 spacing_top = 0.0 else: if c_side: x_i_top = -b_f / 2 + c_side + dia_top / 2 spacing_top = (b_f - 2 * c_side - dia_top) / (n_top - 1) else: x_i_top = -b_f / 2 + c_top + dia_top / 2 spacing_top = (b_f - 2 * c_top - dia_top) / (n_top - 1) if n_bot == 1: x_i_bot = 0.0 spacing_bot = 0.0 else: if c_side: x_i_bot = -b / 2 + c_side + dia_bot / 2 spacing_bot = (b - 2 * c_side - dia_bot) / (n_bot - 1) else: x_i_bot = -b / 2 + c_bot + dia_bot / 2 spacing_bot = (b - 2 * c_bot - dia_bot) / (n_bot - 1) # calculate reinforcing bar dimensions for side layers if specified if dia_side and n_side != 0: x_i_side_left = -b / 2 + c_side + dia_side / 2 x_i_side_right = -x_i_side_left spacing_side = (d - c_top - c_bot - dia_top / 2 - dia_bot / 2) / (n_side + 1) else: x_i_side_left = 0.0 x_i_side_right = 0.0 spacing_side = 0.0 # add top bars for idx in range(n_top): bar = primitive_sections.circular_section_by_area( area=area_top, n=n_circle, material=steel_mat, ).shift_section( x_offset=x_i_top + spacing_top * idx, y_offset=d - c_top - dia_top / 2, ) geom = (geom - bar) + bar # add bot bars for i in range(n_bot): bar = primitive_sections.circular_section_by_area( area=area_bot, n=n_circle, material=steel_mat, ).shift_section( x_offset=x_i_bot + spacing_bot * i, y_offset=c_bot + dia_bot / 2, ) geom = (geom - bar) + bar # add side bars if area_side: for i in range(n_side): bar_left = primitive_sections.circular_section_by_area( area=area_side, n=n_circle, material=steel_mat, ).shift_section( x_offset=x_i_side_left, y_offset=c_bot + dia_bot / 2 + spacing_side * (i + 1), ) bar_right = bar_left.shift_section(x_offset=x_i_side_right - x_i_side_left) geom = (geom - bar_left - bar_right) + bar_left + bar_right if isinstance(geom, geometry.CompoundGeometry): return geom else: raise ValueError("Concrete section generation failed.")
[docs] def concrete_circular_section( d: float, area_conc: float, n_conc: int, dia_bar: float, area_bar: float, n_bar: int, cover: float, n_circle: int = 4, conc_mat: pre.Material = pre.DEFAULT_MATERIAL, steel_mat: pre.Material = pre.DEFAULT_MATERIAL, ) -> geometry.CompoundGeometry: """Constructs a reinforced concrete circular section. Constructs a reinforced concrete circular section of diameter ``d``. .. note:: As the concrete area and reinforcing bars are described by discretised circles, the area of the circle and each bar is required to ensure that the correct concrete and reinforcing area is provided. Args: d: Concrete diameter area_conc: Area of the circular concrete section n_conc: Number of points discretising the circular concrete section dia_bar: Diameter of the steel reinforcing bars area_bar: Area of the reinforcing bars n_bar: Number of steel reinforcing bars cover: Clear cover to the reinforcing bars n_circle: Number of points discretising the steel reinforcing bars conc_mat: Material object to assign to the concrete area steel_mat: Material object to assign to the steel area Returns: Reinforced concrete circular section geometry Raises: ValueError: If the number of bars is not greater than or equal to 2 Example: The following example creates a 450 mm diameter concrete column with 6 x 20 mm steel reinforcing bars with 45 mm cover. A coarse finite element mesh is generated to show the different material regions: .. plot:: :include-source: True :caption: Reinforced concrete circular section geometry import numpy as np from sectionproperties.pre import Material from sectionproperties.pre.library import concrete_circular_section from sectionproperties.analysis import Section concrete = Material( name="Concrete", elastic_modulus=30.1e3, poissons_ratio=0.2, yield_strength=32, density=2.4e-6, color="lightgrey", ) steel = Material( name="Steel", elastic_modulus=200e3, poissons_ratio=0.3, yield_strength=500, density=7.85e-6, color="grey", ) geom = concrete_circular_section( d=450, area_conc=np.pi * 450 * 450 / 4, n_conc=64, dia_bar=20, area_bar=310, n_bar=6, cover=45, n_circle=24, conc_mat=concrete, steel_mat=steel, ) geom.create_mesh(mesh_sizes=[0]) # a size of zero creates a coarse mesh Section(geometry=geom).plot_mesh() """ if n_bar < 2: raise ValueError("Please provide 2 or more steel reinforcing bars.") # create circular geometry geom = primitive_sections.circular_section_by_area( area=area_conc, n=n_conc, material=conc_mat ) # calculate bar geometry r = d / 2 - cover - dia_bar / 2 d_theta = 2 * np.pi / n_bar for i in range(n_bar): bar = primitive_sections.circular_section_by_area( area=area_bar, n=n_circle, material=steel_mat, ).shift_section( x_offset=r * np.cos(i * d_theta), y_offset=r * np.sin(i * d_theta), ) geom = (geom - bar) + bar if isinstance(geom, geometry.CompoundGeometry): return geom else: raise ValueError("Concrete section generation failed.")
[docs] def add_bar( geometry: geometry.Geometry | geometry.CompoundGeometry, area: float, material: pre.Material, x: float, y: float, n: int, ) -> geometry.CompoundGeometry: """Adds a reinforcing bar to a ``sectionproperties`` geometry. First removes the geometry through a subtraction operation, then adds the geometry on top of the newly created hole. This method avoids the doubling up of geometry. Args: geometry: Reinforced concrete geometry to which the new bar will be added area: Bar cross-sectional area material: Material object for the bar x: x-position of the bar y: y-position of the bar n: Number of points to discretise the bar circle Returns: Geometry object with added bar """ bar = primitive_sections.circular_section_by_area( area=area, n=n, material=material, ).shift_section(x_offset=x, y_offset=y) return (geometry - bar) + bar