API Reference¶
Note
The API reference is incomplete as I am beginning to learn how to do this correctly. Any suggestionss or help are greatly appreciated.
Materials¶
Concrete¶
Concrete
dataclass
¶
Concrete
Returns¶
Concrete Concrete object
Source code in src/rcdesign/is456/concrete.py
@dataclass
class Concrete:
"""Concrete
Returns
-------
Concrete
Concrete object
"""
label: str
fck: float
gamma_m: float = 1.5
density: float = 25.0
def __repr__(self) -> str:
s = f"fck = {self.fck:.2f} N/mm^2, fd = {self.fd:.2f} N/mm^2"
return s
@property
def Ec(self) -> float:
return 5000 * sqrt(self.fck)
@property
def fd(self) -> float:
return 0.67 * self.fck / self.gamma_m
def tauc(self, pt: float) -> float:
if pt < 0.15:
pt = 0.15
if pt > 3:
pt = 3.0
beta = max(1.0, (0.8 * self.fck) / (6.89 * pt))
num = 0.85 * sqrt(0.8 * self.fck) * (sqrt(1 + 5 * beta) - 1)
den = 6 * beta
return num / den
def tauc_max(self):
tauc = np.array([[15, 20, 25, 30, 35, 40], [2.5, 2.8, 3.1, 3.5, 3.7, 4.0]])
if self.fck < 15:
return 0.0
elif self.fck >= tauc[0, -1]:
return tauc[1, -1]
else:
for i in range(1, tauc.shape[1]):
if self.fck <= tauc[0, i]:
if self.fck == tauc[0, i]:
return tauc[1, i]
else:
x1 = tauc[0, i - 1]
y1 = tauc[1, i - 1]
x2 = tauc[0, i]
y2 = tauc[1, i]
print(x1, x2, y1, y2)
return y1 + (y2 - y1) / (x2 - x1) * (self.fck - x1)
Rebar¶
Classes to represent reinforcement bars, layers of reinforcement bars and groups of reinforcement layers
Rebar
dataclass
¶
Bases: ABC
Rebar object represents a reinforcment bar.
Parameters¶
ABC : type description
Returns¶
Rebar description
Source code in src/rcdesign/is456/rebar.py
@dataclass
class Rebar(ABC): # pragma: no cover
"""Rebar object represents a reinforcment bar.
Parameters
----------
ABC : _type_
_description_
Returns
-------
Rebar
_description_
"""
label: str
fy: float
gamma_m: float = 1.15
density: float = 78.5
Es: float = 2e5
rebar_type: RebarType = RebarType.REBAR_HYSD
@property
def fd(self) -> float:
return self.fy / self.gamma_m
def es_min(self) -> float:
return self.fd / self.Es + 0.002
@abstractmethod
def fs(self, es: float) -> float:
pass
Section¶
Class to represent reinforced concrete cross sections
DesignForceType
¶
Bases: Enum
DesignForceType object is an enumeration
Source code in src/rcdesign/is456/section.py
class DesignForceType(Enum):
"""DesignForceType object is an enumeration"""
BEAM = 1
COLUMN = 2
SLAB = 3
SHEARWALL = 4
RectBeamSection
dataclass
¶
RectBeamSection object represnts a rectangular beam section subjected to bending and shear.
Returns¶
RectBeamSection description
Source code in src/rcdesign/is456/section.py
@dataclass
class RectBeamSection:
"""RectBeamSection object represnts a rectangular beam section subjected to bending and shear.
Returns
-------
RectBeamSection
_description_
"""
b: float
D: float
csb: LSMStressBlock
conc: Concrete
long_steel: RebarGroup
shear_steel: ShearRebarGroup
clear_cover: float
def __post_init__(self):
self.design_force_type = DesignForceType.BEAM
self.calc_xc()
def calc_xc(self) -> None:
self.long_steel.calc_xc(self.D)
return None
def get_stress_type(self, xu: float) -> None:
self.calc_xc()
self.long_steel.get_stress_type(xu)
def C(self, xu: float, ecmax: float = ecu) -> Tuple[float, float]:
Fc, Mc, _, _ = self.F_M(xu, ecmax)
return Fc, Mc
def T(self, xu: float, ecmax: float) -> Tuple[float, float]:
_, _, Ft, Mt = self.F_M(xu, ecmax)
return Ft, Mt
def C_T(self, xu: float, ecmax: float = ecu) -> float:
self.get_stress_type(xu)
C, _, T, _ = self.F_M(xu, ecmax)
return C - T
def F_M(self, xu: float, ecmax: float = ecu) -> Tuple[float, float, float, float]:
# sb = LSMStressBlock("LSM Flexure")
self.get_stress_type(xu)
Fc = Mc = Ft = Mt = 0.0
# Compression force - concrete
k = xu / self.D
Fcc = self.csb.C(0, k, k, ecmax) * self.conc.fd * self.b * self.D
Mcc = self.csb.M(0, k, k, ecmax) * self.conc.fd * self.b * self.D**2
# Compression force - compression steel
Fsc, Msc, Fst, Mst = self.long_steel.force_moment(xu, self.csb, self.conc, ecmax)
# Tension force in tension steel
Ft, Mt = self.long_steel.force_tension(xu, ecmax)
Fc = Fcc + Fsc
Mc = Mcc + Msc
return Fc, Mc, Ft, Mt
def xu(self, ecmax: float = ecu) -> Union[float, Any]:
dc_max = 10
x1, x2 = rootsearch(self.C_T, dc_max, self.D, 10, ecmax)
x = brent(self.C_T, x1, x2, ecmax)
# x = brentq(self.C_T, x1, x2, args=(ecmax,))
return x
def Mu(self, xu: float, ecmax: float = ecu) -> float:
# Assuming area of tension steel to be such as to produce a tension force equal to C
_, Mc = self.C(xu, ecmax)
_, Mt = self.T(xu, ecmax)
M = Mc + Mt
return M
def tauc(self, xu: float) -> float:
return self.conc.tauc(self.pt(xu))
def __repr__(self) -> str:
ecmax = self.csb.ecu
xu = self.xu(ecmax)
return self.report(xu, ecmax)
def has_compr_steel(self, xu: float) -> bool:
for L in self.long_steel.layers:
if L._xc < xu:
return True
return False
def report(self, xu: float, ecmax: float = ecu) -> str: # pragma: no cover
self.calc_xc()
self.get_stress_type(xu)
k = xu / self.D
ecy = self.csb.ecy
hdr0 = f"RECTANGULAR BEAM SECTION: {self.b} x {self.D}"
s = f"{header(hdr0, '~')}\n"
s += f"{header('FLEXURE', '=')}\nEquilibrium NA = {xu:.2f} (k = {k:.2f}) (ec_max = {ecmax:.6f})\n\n"
fcc = self.csb._fc_(ecmax) * self.conc.fd
Fc = self.b * self.csb.C(0, k, k, ecmax) * self.conc.fd * self.D
Mc = self.csb.M(0, k, k) * self.conc.fd * self.b * self.D**2
hdr1 = f"{'fck':>6} {' ':>8} {' ':>12} {'ec_max':>12} {'Type':>4} "
hdr1 += f"{' ':>8} {'f_c':>6} {'F (kN)':>8} {'M (kNm)':>8}"
s += hdr1 + "\n" + underline(hdr1) + "\n"
s += f"{self.conc.fck:6.2f} {' ':>8} {' ':>12} {ecmax:12.8f} {'C':>4} {' ':>8} {fcc:6.2f} "
s += f"{Fc / 1e3:8.2f} {Mc / 1e6:8.2f}\n{underline(hdr1)}\n\n"
Ft = 0.0
Mt = 0.0
hdr2 = f"{'fy':>6} {'Bars':>12} {'xc':>8} {'Strain':>12} {'Type':>4} {'f_s':>8} {'f_c':>6}"
hdr2 += f" {'F (kN)':>8} {'M (kNm)':>8}"
s += f"{hdr2}\n{underline(hdr2)}\n"
for L in sorted(self.long_steel.layers):
z = k - (L._xc / self.D)
esc = self.csb.ec(z, k) * ecy
stress_type = L.stress_type(xu)
fsc = L.rebar.fs(esc)
s += f"{L.rebar.fy:6.0f} {L.bar_list():>12} {L._xc:8.2f} {esc:12.8f} "
s += f"{StressLabel[stress_type][0]:>4} {fsc:8.2f} "
if stress_type == StressType.STRESS_COMPRESSION:
fcc = self.csb.fc(z, k, ecmax) * self.conc.fd
c = L.area * (fsc - fcc)
s += f"{fcc:6.2f} "
elif L._stress_type == StressType.STRESS_TENSION:
c = L.area * fsc
s += f"{' ':>6} "
else:
c = 0.0
m = c * (k * self.D - L._xc)
s += f"{c / 1e3:8.2f} {m / 1e6:8.2f}\n"
Ft += c
Mt += m
s += f"{underline(hdr2)}\n"
if len(self.long_steel.layers) > 1:
C_M = f"{Ft / 1e3:8.2f} {Mt / 1e6:8.2f}"
s += f"{' ' * 62} {C_M}\n{' ' * 62} {underline(C_M, '=')}\n"
F = 0.0 if isclose(Fc + Ft, 0, abs_tol=1e-10) else Fc + Ft
C_M = f"{F / 1e3:8.2f} {(Mc + Mt) / 1e6:8.2f}"
s += f"{' ':>62} {C_M}\n"
s += f"{header('SHEAR', '=')}\n"
tauc = self.conc.tauc(self.pt(xu))
area = self.b * self.eff_d(xu)
vuc = area * tauc
hdr3 = f"{'Type':>14} {' ':>14} {'tau_c':>6} {'Area (mm^2)':>16} {' ':>8} {' ':>8} {'V_uc (kN)':>8}"
s += f"{header(hdr3)}\n"
s += f"{'Concrete':>14} {' ':>14} {tauc:6.2f} {area:16.2f} {' ':>8} {' ':>8} {vuc / 1e3:8.2f}\n"
s += f"{underline(hdr3)}\n"
hdr4 = f"{'Type':>14} {'Variant':>14} {'f_y':>6} {'Bars':>16} {'s_v':>8} {'A_sv':>8} {'V_us (kN)':>8}"
s += f"{header(hdr4)}\n"
vus = 0.0
for sh_rein in self.shear_steel.shear_reinforcement:
data = sh_rein.report(self.eff_d(xu))
s += f"{data['label']:>14} {data['type']:>14} {data['fy']:6} "
if data["sh_type"] in [
ShearRebarType.SHEAR_REBAR_VERTICAL_STIRRUP,
ShearRebarType.SHEAR_REBAR_INCLINED_STIRRUP,
]:
bar_info = f"{data['legs']}-{data['bar_dia']}#"
else:
bar_info = f"{data['bars']}"
s += f"{bar_info:>16} {data['sv']:8.1f} {data['Asv']:8.2f} {data['Vus'] / 1e3:8.2f}\n"
vus += data["Vus"]
vu = f"{(vuc + vus) / 1e3:8.2f}"
s += f"{' ':>71} {underline(vu, '=')}\n{' ':>71} {vu}\n"
s += f"{header('CAPACITY', '=')}\n{'Mu = ':>5}{self.Mu(xu, ecmax) / 1e6:.2f} kNm\n"
Vuc, Vus = self.Vu(xu)
Vu = Vuc + sum(Vus)
s += f"{'Vu = ':>5}{Vu / 1e3:.2f} kN\n"
return s
def eff_d(self, xu: float) -> float:
_, ct = self.long_steel.centroid(xu)
return ct
def pt(self, xu: float) -> float:
ast = 0.0
for L in sorted(self.long_steel.layers):
if L._xc > xu:
ast += L.area
d = self.eff_d(xu)
pt = ast / (self.b * d) * 100
return pt
def Vu(self, xu: float) -> Tuple[float, List[float]]:
# print("\nstart::RectBeamSection.Vu(xu)", xu)
pt = self.pt(xu)
# print("stop::RectBeamSection.Vu(xu)\n")
tauc = self.conc.tauc(pt)
d = self.eff_d(xu)
vuc = tauc * self.b * d
vus = self.shear_steel.Vus(d)
return vuc, vus
def analyse(self, ecmax: float = ecu) -> Tuple[float, float]:
xu = self.xu(ecmax)
Mu = self.Mu(xu, ecmax)
return xu, Mu
def design_singly(self, bar_dia: float, Mu: float) -> Tuple[float, float]:
beam = LSMBeam()
fck = self.conc.fck
bottom_layer = self.long_steel.layers[-1]
fy = bottom_layer.rebar.fy
fd = bottom_layer.rebar.fd
d = self.D - self.clear_cover - bar_dia / 2
dc = self.clear_cover + bar_dia / 2
Mulim = beam.Mulim_const(fy) * fck * self.b * d**2
if Mu < Mulim:
ast = beam.reqd_Ast(fck, fy, self.b, d, Mu)
asc = 0.0
else:
ast1 = beam.reqd_Ast(fck, fy, self.b, d, Mulim)
Mu2 = Mu - Mulim
ast2 = Mu2 / (fd * (d - dc))
ast = ast1 + ast2
xu = beam.xumax_d(fy) * d
esc = self.csb.ecu / xu * (xu - dc)
fsc = bottom_layer.rebar.fs(esc)
fcc = self.csb._fc_(esc) * self.conc.fd
asc = ast2 * fd / (fsc - fcc)
print("---", xu, d, esc, fsc, fcc, ast1, ast2, ast, asc)
return ast, asc