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

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

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

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

# Imports from units library
from ....utils.units import kN, 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."""
TAU_C = 0.40 * MPa
"""Allowable shear stress carried by the concrete or
the design shear strength of concrete.
Specified in the Article 23 of RBA (1935)."""
TAU_MAX = 1.40 * MPa
"""Allowable shear stress carried by the beam section.
Specified in the Article 23 of RBA (1935)."""
MODULAR_RATIO = 15
"""Assumed steel to concrete elastic modular ratio for reinforcement
computation."""


[docs] class Beam(BeamBase): """Beam implementation for design class ``eu_cdn``. This class extends ``BeamBase`` by narrowing the attribute types and overriding design methods per RBA (1935). Attributes ---------- steel : ~simdesign.rcmrf.bdim.eu_cdn.materials.Steel Steel material assigned to the beam. concrete : ~simdesign.rcmrf.bdim.eu_cdn.materials.Concrete Concrete material assigned to the beam. See Also -------- :class:`~bdim.baselib.beam.BeamBase` Base class defining the core behaviour and configuration. References ---------- RBA (1935) Regulamento do Betão Armado. Decreto N.° 25:948, Lisbon, Portugal. """ steel: Steel concrete: Concrete
[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: - Uses a single expression for computing the height to control emergent beam deformations under gravity loads, assuming ``d' = 0.1h`` for the cover depth. """ # Bending moment used for preliminary design of section dimensions Md = self.pre_Md * kN * m # 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 def_h = self.L / (0.9 * 18) # Get the maximum slab computed from all self.h = max(self.min_h, slab_h, 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 def_h = self.L / (0.9 * 18) # Get the maximum slab computed from all self.h = max(self.min_h, slab_h, 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. Notes ----- Based on Article 23 of RBA (1935). """ # Distance from extreme compression fiber to centroid of longitudinal # tension reinforcement. d = 0.9 * self.h # Lever arm, i.e., distance between comp. and tens. forces z = 0.9 * d # Verify the adequacy of the section dimensions shear = max(self.envelope_forces.V1, self.envelope_forces.V5, self.envelope_forces.V9) tau = shear / (self.b * z) if tau < TAU_MAX: self.ok = True # Ok else: self.ok = False # Not ok
[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. - For doubly reinforced beams, the balanced moment capacity is used to split the moment into a singly reinforced contribution and an excess moment resisted by the compression reinforcement. - Required reinforcement is computed at three different sections: start, middle, end. References ---------- https://mathalino.com/reviewer/reinforced-concrete-design/design-steel-reinforcement-concrete-beams-wsd-method """ # Distance from extreme compression fiber to centroid of longitudinal # tension reinforcement. d = 0.9 * self.h d_prime = 0.1 * self.h # Alternatively, this can be directly computed. n = MODULAR_RATIO # Modular ratio # 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) # No need for the sign # Balanced moment capacity x_bal = (self.fcd * d) / (self.fcd + self.fsyd / n) C_bal = 0.50 * self.fcd * self.b * x_bal M_bal = C_bal * (d - x_bal / 3) # Initialize long. steel area at start, mid and end sections Asl_top = np.zeros(3) # Required steel area at top Asl_bot = np.zeros(3) # Required steel area at bottom # 1) Calculate longitudinal steel area for negative moment envelope (-) mask1 = moment_neg <= M_bal # Identify singly reinforced beams # Excessive moment (doubly reinforced beam case) Mexcess = moment_neg[~mask1] - M_bal # Tension reinforcement (singly reinforced beam) Asl_top[mask1] = moment_neg[mask1] / ( self.fsyd * (d - x_bal / 3)) # As1 (Doubly reinforced beam) Asl1 = moment_neg[~mask1] / (self.fsyd * (d - x_bal / 3)) # As2 (doubly reinforced beam) --> Corrected Asl2 = Mexcess / (self.fsyd * (d - d_prime)) # Total tension reinforcement reinforcement (doubly reinforced beam) Asl_top[~mask1] = Asl1 + Asl2 # Maximum stress of the compression reinforcement (doubly reinforced) fsyd_prime = min( self.fsyd, (2 * self.fsyd * (x_bal - d_prime)) / (d - x_bal) ) # Compression reinforcement (doubly reinforced beam) Asl_bot[~mask1] = (2 * n * Mexcess) / ( fsyd_prime * (2 * n - 1) * (d - d_prime) ) # 2) Calculate longitudinal steel area for positive moment envelope (+) mask2 = moment_pos <= M_bal # Identify singly reinforced beams # Excessive moment (doubly reinforced beam case) Mexcess = moment_pos[~mask2] - M_bal # Tension reinforcement (singly reinforced beam) Asl_bot[mask2] = np.maximum( Asl_bot[mask2], moment_pos[mask2] / (self.fsyd * (d - x_bal / 3)) ) # As1 (doubly reinforced beam) Asl1 = moment_pos[~mask2] / (self.fsyd * (d - x_bal / 3)) # As2 (doubly reinforced beam) --> Corrected Asl2 = Mexcess / (self.fsyd * (d - d_prime)) # Total tension reinforcement reinforcement (doubly reinforced beam) Asl_bot[~mask2] = np.maximum(Asl1 + Asl2, Asl_bot[~mask2]) # Maximum stress of the compression reinforcement (doubly reinforced) fsyd_prime = min( self.fsyd, (2 * self.fsyd * (x_bal - d_prime)) / (d - x_bal) ) # Compression reinforcement (doubly reinforced beam) Asl_top[~mask2] = np.maximum( (2 * n * Mexcess) / (fsyd_prime * (2 * n - 1) * (d - d_prime)), Asl_top[~mask2], ) # Save the required longitudinal reinforcement area 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. - The shear threshold ``Vrd = TAU_C * b * d`` is derived from Article 23 of RBA (1935), which defines ``TAU_C`` as the stress level above which transverse reinforcement becomes mandatory. """ # Distance from extreme compression fiber to centroid of longitudinal # tension reinforcement. d = 0.9 * self.h # Design forces shear = np.array([self.envelope_forces.V1, self.envelope_forces.V5, self.envelope_forces.V9]) # Calculate the required transverse reinforcement area to the spacing sbh = 0.5 # stirrup spacing dbh = 0.006 # stirrup diameter nlegs = 2 # number of legs Ash_sbh_min = nlegs * (np.pi * 0.25 * dbh**2) / sbh Vrd = TAU_C * self.b * d mask = shear > Vrd Ash_sbh = np.ones_like(shear) * Ash_sbh_min Ash_sbh[mask] = np.maximum((shear[mask] - Vrd) / (self.fsyd * d), Ash_sbh[mask]) self.Ash_sbh_req = Ash_sbh # Save