Source code for simdesign.rcmrf.bdim.tr_0018_dch.beam

"""This module provides the beam class implementation for the ``tr_0018_dch``
design class in the BDIM layer.
"""
# Imports from installed packages
from math import ceil
import numpy as np
from typing import Tuple, Optional

# Imports from the design class (tr_0018_dch) library
from .materials import Steel, Concrete

# Imports from bdim base library
from ..baselib.beam import BeamBase, Array3

# Imports from units library
from ....utils.units import MPa, m

# Constants
ECONOMIC_MU_EB: float = 0.25
"""Maximum mu value considered for the economic emergent beam design."""
ECONOMIC_MU_WB: float = 0.25
"""Maximum mu value considered for the economic wide beam design."""


[docs] class Beam(BeamBase): """Beam implementation for design class ``tr_0018_dch``. This class extends ``BeamBase`` by narrowing the attribute types and overriding design methods per TBEC-2007 and TS500-2000. Attributes ---------- steel : ~simdesign.rcmrf.bdim.tr_0018_dch.materials.Steel Steel material assigned to the beam. concrete : ~simdesign.rcmrf.bdim.tr_0018_dch.materials.Concrete Concrete material assigned to the beam. MIN_B_EB: float The default minimum breadth (width) of emergent beams. MIN_H_EB: float The default minimum height (depth) of emergent beams. Ve1 : float | None Beam capacity design shear force at 1st gaussian point Ve9 : float | None Beam capacity design shear force at 9st gaussian point See Also -------- :class:`~bdim.baselib.beam.BeamBase` Base class defining the core behaviour and configuration. References ---------- TBEC (1998). *Afet Bölgelerinde Yapılacak Yapılar Hakkında Yönetmelik*. Resmi Gazete, Ankara, Türkiye. TBEC (2007). *Deprem Bölgelerinde Yapılacak Binalar Hakkında Esaslar*. Resmi Gazete, Ankara, Türkiye. TS500 (2000). *Requirements for Design and Construction of Reinforced Concrete Structures*. Turkish Standards Institution (TSE), Ankara, Türkiye. """ steel: Steel concrete: Concrete MIN_B_EB: float = 0.25 * m # from TBEC-1998 MIN_H_EB: float = 0.30 * m # from TBEC-1998 Ve1: Optional[float] = None Ve9: Optional[float] = None @property def max_b(self) -> float: """ Returns ------- float Computed maximum allowed section breadth (width). Notes ----- Based on: Section 7.4.1 in TBEC-1998, Section 3.4.1 in TBEC-2007. """ if self.direction == "x": # Beam is along x bc = max(col.by for col in self.columns if col) elif self.direction == "y": # Beam is along y bc = max(col.bx for col in self.columns if col) b_max_code = bc + self.h # Masks for finding emergent beams bool1 = self.typology == 2 bool2 = self.exterior bool3 = self.stairs_wg != 0.0 if bool1 or bool2 or bool3: return min(b_max_code, self.MAX_B_EB) else: return min(b_max_code, self.MAX_B_WB) @property def max_h(self) -> float: """ Returns ------- float Computed maximum allowed section height (depth). Notes ----- Based on: Section 7.4.1 in TBEC-1998, Section 3.4.1 in TBEC-2007. """ # Masks for finding emergent beams bool1 = self.typology == 2 # Emergent by default bool2 = self.exterior # Forces exterior beams to emergent bool3 = self.stairs_wg != 0.0 # Forces stairs beams to be emergent if bool3: return self.MAX_H_EB else: if self.direction == 'x': # Beam is along x bxmax = max(col.bx for col in self.columns if col) bxmin = min(col.bx for col in self.columns if col) clear_length = self.L - (bxmax + bxmin) / 2 elif self.direction == 'y': # Beam is along y bymax = max(col.by for col in self.columns if col) bymin = min(col.by for col in self.columns if col) clear_length = self.L - (bymax + bymin) / 2 h_max_code = max(3.5 * self.b, clear_length / 4) if bool1 or bool2: return min(self.MAX_H_EB, h_max_code) else: return min(self.MAX_H_WB, h_max_code) @property def fctk(self) -> float: """ Returns ------- float Characteristic tensional strength of concrete (in base units). Notes ----- Based on Equation 3.1 in T5500-2000. """ return (0.35 * (self.concrete.fck) ** (1 / 2)) * MPa @property def fctd(self) -> float: """ Returns ------- float Design value for characteristic tensional strength of concrete (in base units). """ return self.fctk / self.concrete.PARTIAL_FACTOR @property def rhol_min_tens(self) -> float: """ Returns ------- float Minimum longitudinal reinforcement ratio in tension zone. Notes ----- Based on Equation 3.8 in TBEC-2007. """ return 0.8 * (self.fctd / self.fsyd) @property def rhol_max_tens(self) -> float: """ Returns ------- float Maximum longitudinal reinforcement ratio in tens. and comp. zones. Notes ----- Based on Equation 7.5 in T5500-2000. """ return 0.02 @property def rhoh_min(self) -> float: """ Returns ------- float Minimum transverse reinforcement ratio. Notes ----- Based on Equation 8.6 in T5500-2000. """ return 0.3 * (self.fctd) / (self.fsyd)
[docs] def predesign_section_dimensions(self, slab_h: float) -> None: """Make an initial guess for beam section dimensions. Parameters ---------- slab_h : float Slab thickness. Notes ----- This method overrides ``BeamBase.predesign_section_dimensions`` with the following changes: - It uses additional constraint on beam height based on Section 7.4.1 in TBEC-1998. """ # Unit conversions Md = self.pre_Md # Emergent beam cases bool1 = self.typology == 2 bool2 = self.exterior bool3 = self.stairs_wg != 0.0 if bool1 or bool2 or bool3: # Set section breadth to minimum self.b = self.min_b # Compute height for economic section, assuming d = 0.1h mu_h = ((Md / (ECONOMIC_MU_EB * self.fcd * self.b)) ** 0.5) / 0.9 # Compute height to control deformations if self.stairs_wg != 0.0 or sum(self.slab_wg) != 0.0: # The beam carries a slab (stairs or floor slab) def_h = self.L / 12 else: # The beam is secondary gravity beam def_h = self.L / (0.9 * 18) # Compute height to provide support condition for slabs bh_s = 3 * slab_h # Section 7.4.1 in TBEC-1998 # Get the maximum slab computed from all self.h = max(self.min_h, bh_s, mu_h, def_h) # Iterate for aspect ratio consideration while self.h / self.b > self.MAX_ASPECT_RATIO_EB: # Increase breadth self.b += self.B_INCR_EB # Compute height for economic section, assuming d = 0.1h mu_h = ((Md / (ECONOMIC_MU_EB * self.fcd * self.b)) ** 0.5) / 0.9 # Compute height to control deformations if self.stairs_wg != 0.0 or sum(self.slab_wg) != 0.0: # The beam carries a slab (stairs or floor slab) def_h = self.L / 12 else: # The beam is secondary gravity beam def_h = self.L / (0.9 * 18) # Get the maximum slab computed from all self.h = max(self.min_h, bh_s, mu_h, def_h) # Wide beam cases else: # Set section height (slab thickness or minimum) self.h = max(slab_h, self.min_h) # Section widths if sum(self.slab_wg) == 0.0: # Secondary gravity beams self.b = self.min_b # Use minimum dimension else: # Primary gravity beams # Set width based on economic mu value and minimum allowed self.b = max( self.min_b, (Md / (ECONOMIC_MU_WB * self.fcd * (0.9 * self.h) ** 2)), ) while ( self.b > self.max_b or self.b / self.h > self.MAX_ASPECT_RATIO_WB ): self.h += self.H_INCR_WB self.b = Md / ( ECONOMIC_MU_WB * self.fcd * (0.9 * self.h) ** 2 ) # Round self.h = ceil(20 * self.h) / 20 self.b = ceil(20 * self.b) / 20
[docs] def verify_section_adequacy(self) -> None: """Verify the beam section dimensions for design forces.""" # mu values (dimensionless) for economic section (eng. practice) if self.typology == 1: mu_economic = ECONOMIC_MU_WB elif self.typology == 2: mu_economic = ECONOMIC_MU_EB # Distance from extreme compression fiber to centroid of longitudinal # tension reinforcement. d = 0.90 * self.h # Maximum of envelope forces if self.Ve1 is not None and self.Ve9 is not None: Vmax = max(self.Ve1, self.Ve9) else: Vmax = max( self.envelope_forces.V1, self.envelope_forces.V5, self.envelope_forces.V9, ) Mmax = max( self.envelope_forces.M1_pos, self.envelope_forces.M5_pos, self.envelope_forces.M9_pos, abs(self.envelope_forces.M1_neg), abs(self.envelope_forces.M5_neg), abs(self.envelope_forces.M9_neg), ) # Verify the adequacy of the section dimensions mu = Mmax / (self.fcd * self.b * d**2) Vrd_max = 0.22 * self.b * d * self.fcd # Equation 8.7 in TS500-2000 if mu < mu_economic and Vmax < Vrd_max: self.ok = True # Ok else: self.ok = False # Not ok
def _get_long_area(self, Md: Array3 ) -> Tuple[Array3[np.float64], Array3[np.float64]]: """Get longitudinal reinforcement area given bending moment. Parameters ---------- Md : np.ndarray Moment value to be used for beam design. Returns ------- As_required : np.ndarray Required tension steel area. Asprime_required : np.ndarray Required compression steel area. """ # Initial material and geometrical definitions fcd = self.fcd fyd = self.fsyd Es = self.Es bw = self.b dprime = 0.1 * self.h d = self.h - dprime # Definition of k1 and k3 k1 = min(1 - 0.006 * self.fck / MPa, 0.85) k3 = 0.85 # Bending moment calculation for the choice between single # and double reinforcement. Mr1 = 0.235 * fcd * bw * (d**2) * (1 - 0.1175 / k3) As_required = np.zeros(len(Md)) Asprime_required = np.zeros(len(Md)) mask = Md < Mr1 if np.any(mask): # Single reinforcement K = Md[mask] / (bw * d**2) rho = k3 * (fcd / fyd) * (1 - (1 - (2 * K) / (k3 * fcd)) ** 0.5) As_required[mask] = rho * bw * d Asprime_required[mask] = 0 else: # Double reinforcement As1 = 0.235 * (fcd / fyd) * bw * d Mr2 = Md[~mask] - Mr1 As2 = Mr2 / (fyd * (d - dprime)) epss_prime = 0.003 * (1 - (k1 * k3 / 0.235) * (dprime / d)) sigmas_prime = epss_prime * Es if sigmas_prime >= fyd: sigmas_prime = fyd else: sigmas_prime = sigmas_prime As_required[~mask] = As1 + As2 Asprime_required[~mask] = As2 * fyd / sigmas_prime return As_required, Asprime_required
[docs] def compute_required_longitudinal_reinforcement(self) -> None: """Compute the required longitudinal reinforcement for design forces. Notes ----- - Top reinforcement is calculated as the maximum of required reinforcement in tension for maximum of negative bending moments and required reinforcement in compression for maximum of positive bending moments. - Bottom reinforcement is calculated as the maximum of required reinforcement in compression for maximum of negative bending moments and required reinforcement in tension for maximum of positive bending moments. - Required reinforcement is computed at three different sections: start, middle, end. """ # Design forces moment_pos = np.array( [ self.envelope_forces.M1_pos, self.envelope_forces.M5_pos, self.envelope_forces.M9_pos, ] ) moment_neg = np.array( [ self.envelope_forces.M1_neg, self.envelope_forces.M5_neg, self.envelope_forces.M9_neg, ] ) moment_neg = np.abs(moment_neg) # Required area for positive moment envelope (+) Asl_pos_bot, Asl_pos_top = self._get_long_area(moment_pos) # Required area for negative moment envelope (-) Asl_neg_top, Asl_neg_bot = self._get_long_area(moment_neg) # Determine required reinforcement at top and bottom Asl_bot = np.maximum(Asl_pos_bot, Asl_neg_bot) Asl_top = np.maximum(Asl_neg_top, Asl_pos_top) # Check against minimum longitudinal reinforcement area Asl_min_tens = self.rhol_min_tens * self.b * (0.9 * self.h) Asl_top = np.maximum(Asl_top, Asl_min_tens) Asl_bot = np.maximum(Asl_bot, Asl_min_tens) # Compression to tension reinf. ratio must be greater than 0.5 # for 1st and 2nd seismic zones mask = Asl_top / Asl_bot < 0.5 if any(mask): Asl_top[mask] = 0.5 * Asl_bot[mask] mask = Asl_bot / Asl_top < 0.5 if any(mask): Asl_bot[mask] = 0.5 * Asl_top[mask] # Save required longitudinal steel area at top and bottom self.Asl_top_req = Asl_top self.Asl_bot_req = Asl_bot
[docs] def compute_required_transverse_reinforcement(self) -> None: """Compute the required transverse reinforcement for design forces. Notes ----- Reinforcement is computed at three sections: start, mid, and end. """ # Shear forces due to gravity and earthquake loads Vd = np.array( [self.envelope_forces.V1, self.envelope_forces.V5, self.envelope_forces.V9] ) # Design shear force (Ve1 and Ve9 are calculated in building.py) Ve = np.array([self.Ve1, self.envelope_forces.V5, self.Ve9]) # Shear force due to gravity loads grav_forces = self.forces["G/seismic"] + self.forces["Q/seismic"] Vd_gravity = np.array([abs(grav_forces.V1), abs(grav_forces.V5), abs(grav_forces.V9)]) # Shear force resisted by concrete, Eq.8.1 in TS500-2000 Vcr = 0.65 * self.fctd * self.b * (0.9 * self.h) Vc = 0.8 * Vcr # Transverse reinforcement computation, # Section 7.4.5 in TBEC-1998 and Section 3.4.5 in TBEC-2007 Ash_sbh = np.zeros(len(Ve)) # Ve <= Vcr case mask = Ve <= Vcr Ash_sbh[mask] = self.rhoh_min * self.b # Ve > Vcr case shear_force_for_reinforcement = np.where((Vd - Vd_gravity) >= 0.5 * Vd, Ve, Ve - Vc) Ash_sbh[~mask] = shear_force_for_reinforcement[~mask] / \ (self.fsyd * (0.9 * self.h)) # Save required transverse reinforcement area to spacing ratio Ash_sbh_min = self.rhoh_min * self.b # Min. transverse reinforcement self.Ash_sbh_req = np.maximum(Ash_sbh, Ash_sbh_min)