1)
import math
import [Link] as plt
# Constants
gamma_m = 1.5 # Partial safety factor for material
d_ratio = 0.1 # Effective depth to span ratio (typical ~1/10th for simply supported)
cover = 25 # mm concrete cover
phi = 16 # mm bar diameter (assumption)
# Design Parameters (User Input)
span_m = float(input("Enter span of the beam in meters: "))
udl_kN_m = float(input("Enter factored UDL in kN/m: "))
fck = float(input("Enter concrete grade (fck) in MPa (e.g., 20 for M20): "))
fy = float(input("Enter steel grade (fy) in MPa, e.g., 500: "))
# Step 1: Effective depth and overall depth estimation
span_mm = span_m * 1000
effective_depth = d_ratio * span_mm
overall_depth = effective_depth + cover + phi/2
print(f"\nEffective depth (d): {effective_depth:.2f} mm")
print(f"Overall depth (D): {overall_depth:.2f} mm")
# Step 2: Bending moment
w = udl_kN_m * 1e3 # convert to N/m
Mu = (w * span_m ** 2) / 8 # in N-m
Mu = Mu * 1e6 # Convert to N-mm
print(f"Ultimate Bending Moment (Mu): {Mu / 1e6:.2f} kN-m")
# Step 3: Required area of steel (Limit State Design)
xu_max_d = 0.48 # For Fe500
Mu_lim = 0.138 * fck * effective_depth ** 2 * 1e3 # Limiting moment
if Mu <= Mu_lim:
# Singly reinforced
Ast = Mu / (0.87 * fy * 0.9 * effective_depth)
print(f"Required Steel Area (Ast): {Ast:.2f} mm²")
else:
print("Section is under-reinforced or needs to be redesigned (doubly reinforced).")
# Step 4: Plot BMD and SFD
x_vals = [i for i in range(0, int(span_m*1000)+1, 100)]
bmd_vals = [w * (x / 1000) * (span_m - (x / 1000)) / 2 for x in x_vals] # in N-m
sfd_vals = [w * (span_m / 2 - x / 1000) for x in x_vals] # in N
# Plot BMD
[Link](figsize=(12, 5))
[Link](1, 2, 1)
[Link](x_vals, bmd_vals, color='blue')
[Link]("Bending Moment Diagram (BMD)")
[Link]("Position along beam (mm)")
[Link]("Bending Moment (Nm)")
[Link](True)
# Plot SFD
[Link](1, 2, 2)
[Link](x_vals, sfd_vals, color='green')
[Link]("Shear Force Diagram (SFD)")
[Link]("Position along beam (mm)")
[Link]("Shear Force (N)")
[Link](True)
plt.tight_layout()
[Link]()
2)
import [Link] as plt
import numpy as np
# === MATERIAL PROPERTIES ===
MATERIALS = {
"concrete": {"fck": None, "fy": None},
"steel": {"fy": None},
"timber": {"f_allow": None}
# === USER INPUTS ===
print("--- Beam Design Tool (CLI Version) ---")
material = input("Enter material (concrete/steel/timber): ").strip().lower()
beam_type = input("Enter beam type (simply_supported/cantilever/fixed/overhanging):
").strip().lower()
load_type = input("Enter load type (point/udl/uvl): ").strip().lower()
L = float(input("Enter span of the beam (in mm): "))
b = float(input("Enter width of the beam (in mm): "))
d = float(input("Enter effective depth of the beam (in mm): "))
cover = float(input("Enter cover (in mm): "))
if material == "concrete":
fck = float(input("Enter concrete grade fck (MPa): "))
fy = float(input("Enter steel grade fy (MPa): "))
MATERIALS["concrete"]["fck"] = fck
MATERIALS["concrete"]["fy"] = fy
elif material == "steel":
fy = float(input("Enter steel yield stress fy (MPa): "))
MATERIALS["steel"]["fy"] = fy
elif material == "timber":
f_allow = float(input("Enter allowable bending stress (MPa): "))
MATERIALS["timber"]["f_allow"] = f_allow
else:
raise ValueError("Unsupported material")
if load_type == "point":
P = float(input("Enter point load value in kN: ")) * 1e3
a=L/2
elif load_type == "udl":
w = float(input("Enter UDL in kN/m: ")) * 1e3
elif load_type == "uvl":
w1 = float(input("Enter UVL start load (kN/m): ")) * 1e3
w2 = float(input("Enter UVL end load (kN/m): ")) * 1e3
else:
raise ValueError("Unsupported load type")
# === ANALYSIS SECTION ===
print("\n--- Analysis ---")
dx = L / 1000
x = [Link](0, L, 1000)
V = np.zeros_like(x)
M = np.zeros_like(x)
if beam_type == "simply_supported":
if load_type == "point":
R=P/2
V = [Link](x < a, R, R - P)
M = [Link](x < a, R * x, R * x - P * (x - a))
elif load_type == "udl":
R=w*L/2
V=R-w*x
M = R * x - (w * x**2) / 2
elif load_type == "uvl":
V = (w1 + (w2 - w1) * x / L / 2) * L - (w1 + (w2 - w1) * x / L) * x / 2
M = (w1 * x**2) / 2 + ((w2 - w1) * x**3) / (6 * L)
elif beam_type == "cantilever":
if load_type == "point":
V = [Link](x <= a, -P, 0)
M = [Link](x <= a, -P * (L - x), 0)
elif load_type == "udl":
V = -w * (L - x)
M = -w * (L - x)**2 / 2
elif load_type == "uvl":
V = -((w1 + (w2 - w1) * (L - x) / L) * (L - x) / 2)
M = -((w1 * (L - x)**2) / 2 + ((w2 - w1) * (L - x)**3) / (6 * L))
elif beam_type == "fixed":
if load_type == "point":
R=P/2
M0 = P * L / 8
V = [Link](x < a, R, R - P)
M = [Link](x < a, R * x - M0, R * x - P * (x - a) - M0)
elif load_type == "udl":
R=w*L/2
M0 = w * L**2 / 12
V=R-w*x
M = R * x - (w * x**2) / 2 - M0
elif load_type == "uvl":
R = (w1 + w2) * L / 2
V = R - ((w1 * x) + ((w2 - w1) * x**2) / (2 * L))
M = R * x - ((w1 * x**2) / 2 + ((w2 - w1) * x**3) / (6 * L))
elif beam_type == "overhanging":
if load_type == "point":
R1 = P * (L - a) / L
R2 = P * a / L
V = [Link](x < a, R1, R1 - P)
M = [Link](x < a, R1 * x, R1 * x - P * (x - a))
elif load_type == "udl":
R1 = w * L / 2
V = R1 - w * x
M = R1 * x - (w * x**2) / 2
elif load_type == "uvl":
V = ((w1 + (w2 - w1) * x / L / 2) * L - (w1 + (w2 - w1) * x / L) * x / 2)
M = (w1 * x**2) / 2 + ((w2 - w1) * x**3) / (6 * L)
else:
raise ValueError("Unsupported beam type")
# === DESIGN SECTION (Concrete Only) ===
if material == "concrete":
Mu = max(abs(M))
fck = MATERIALS["concrete"]["fck"]
fy = MATERIALS["concrete"]["fy"]
b = float(b)
d = float(d)
Mulim = 0.138 * fck * b * d**2
print(f"Ultimate Moment: {Mu/1e6:.2f} kN-m")
print(f"Limiting Moment: {Mulim/1e6:.2f} kN-m")
if Mu <= Mulim:
Ast = Mu / (0.87 * fy * (d - 0.42 * d))
print("Beam is singly reinforced")
print(f"Required Ast: {Ast:.2f} mm²")
else:
Ast1 = Mulim / (0.87 * fy * (d - 0.42 * d))
Mu2 = Mu - Mulim
d_dash = cover
Ast2 = Mu2 / (0.87 * fy * (d - d_dash))
Asc = Ast2
Ast = Ast1 + Ast2
print("Beam is doubly reinforced")
print(f"Ast1 (main): {Ast1:.2f} mm²")
print(f"Ast2 (extra): {Ast2:.2f} mm²")
print(f"Asc (compression): {Asc:.2f} mm²")
# === PLOTTING ===
[Link](figsize=(10, 6))
[Link](2, 1, 1)
[Link](x, V, color='green')
plt.fill_between(x, 0, V, alpha=0.3, color='lightgreen')
[Link]("Shear Force Diagram")
[Link](True)
[Link](2, 1, 2)
[Link](x, M, color='blue')
plt.fill_between(x, 0, M, alpha=0.3, color='skyblue')
[Link]("Bending Moment Diagram")
[Link]("Beam Length (mm)")
[Link](True)
plt.tight_layout()
[Link]()
multiple loads
import numpy as np
import [Link] as plt
# ----------- Helper functions -----------
def validate_positive_float(value, name):
try:
v = float(value)
if v <= 0:
raise ValueError
return v
except:
raise ValueError(f"{name} must be a positive number.")
def validate_choice(value, choices, name):
val = [Link]().lower()
if val not in choices:
raise ValueError(f"Invalid {name}. Choose from {choices}")
return val
def find_points_of_contraflexure(x, M):
sign_changes = [Link]([Link]([Link](M)))[0]
points = []
for idx in sign_changes:
x0, x1 = x[idx], x[idx+1]
M0, M1 = M[idx], M[idx+1]
# Linear interpolation to find zero crossing
zero_cross = x0 - M0*(x1 - x0)/(M1 - M0)
[Link](zero_cross)
return points
def plot_arrow(ax, x, y, direction='up', length=0.1, color='black', linewidth=1.5):
if direction == 'up':
[Link]('', xy=(x, y), xytext=(x, y-length),
arrowprops=dict(facecolor=color, edgecolor=color, lw=linewidth, shrink=0.05))
elif direction == 'down':
[Link]('', xy=(x, y), xytext=(x, y+length),
arrowprops=dict(facecolor=color, edgecolor=color, lw=linewidth, shrink=0.05))
elif direction == 'left':
[Link]('', xy=(x, y), xytext=(x+length, y),
arrowprops=dict(facecolor=color, edgecolor=color, lw=linewidth, shrink=0.05))
elif direction == 'right':
[Link]('', xy=(x, y), xytext=(x-length, y),
arrowprops=dict(facecolor=color, edgecolor=color, lw=linewidth, shrink=0.05))
# ----------- User Inputs -----------
print("=== Enhanced Beam Design Tool ===")
material = validate_choice(input("Material (concrete/steel/timber): "), ["concrete", "steel", "timber"], "material")
beam_type = validate_choice(input("Beam type (simply_supported/cantilever/fixed/overhanging): "),
["simply_supported", "cantilever", "fixed", "overhanging"], "beam type")
# Input beam span (meters) and convert to mm
L = validate_positive_float(input("Beam span (m): "), "Beam span") * 1000
# Cross-section inputs (mm)
b = validate_positive_float(input("Beam width b (mm): "), "Beam width")
d = validate_positive_float(input("Effective depth d (mm): "), "Effective depth")
cover = validate_positive_float(input("Cover (mm): "), "Cover")
# Material properties for concrete design
if material == "concrete":
fck = validate_positive_float(input("Concrete grade fck (MPa): "), "Concrete grade fck")
fy = validate_positive_float(input("Steel yield strength fy (MPa): "), "Steel yield strength fy")
# Collect loads
print("\nEnter loads on the beam. For each load:")
print("Type: 'point', 'udl', or 'uvl'. Type 'done' when finished.")
loads = []
while True:
load_type = input("Load type (point/udl/uvl/done): ").strip().lower()
if load_type == 'done':
if len(loads) == 0:
print("At least one load required.")
continue
break
if load_type not in ['point', 'udl', 'uvl']:
print("Invalid load type. Try again.")
continue
if load_type == 'point':
P = float(input("Point load magnitude (kN, positive downward): "))
a = float(input(f"Distance from left support (0 to {L/1000} m): "))
if a < 0 or a > L:
print("Invalid position.")
continue
[Link]({"type":"point", "P":P*1e3, "a":a*1e3})
elif load_type == 'udl':
w = float(input("UDL intensity (kN/m, positive downward): "))
start = float(input(f"UDL start position (0 to {L/1000} m): "))
end = float(input(f"UDL end position (> start, ≤ {L/1000} m): "))
if start < 0 or end > L/1000 or end <= start:
print("Invalid UDL positions.")
continue
[Link]({"type":"udl", "w":w*1e3, "start":start*1e3, "end":end*1e3})
else: # uvl
w1 = float(input("UVL start intensity (kN/m): "))
w2 = float(input("UVL end intensity (kN/m): "))
start = float(input(f"UVL start position (0 to {L/1000} m): "))
end = float(input(f"UVL end position (> start, ≤ {L/1000} m): "))
if start < 0 or end > L*1e-3 or end <= start:
print("Invalid UVL positions.")
continue
[Link]({"type":"uvl", "w1":w1*1e3, "w2":w2*1e3, "start":start*1e3, "end":end*1e3})
# ----------- Analysis -----------
x = [Link](0, L, 1000)
V = np.zeros_like(x)
M = np.zeros_like(x)
# Support reactions - initialize
R1 = 0
R2 = 0
# For cantilever, only one support reaction (R1 vertical + moment)
# Function to calculate reactions for simply supported beam with multiple loads
def calc_reactions_simply_supported(L, loads):
R1 = 0
R2 = 0
for load in loads:
if load["type"] == "point":
R1 += load["P"] * (L - load["a"]) / L
R2 += load["P"] * load["a"] / L
elif load["type"] == "udl":
w = load["w"]
a = load["start"]
b = load["end"]
length = b - a
total_load = w * length
centroid = (a + b) / 2
R1 += total_load * (L - centroid) / L
R2 += total_load * centroid / L
elif load["type"] == "uvl":
w1 = load["w1"]
w2 = load["w2"]
a = load["start"]
b = load["end"]
length = b - a
total_load = length * (w1 + w2) / 2
# centroid of triangular trapezoid load:
if w1 == w2:
centroid = (a + b) / 2
else:
centroid = a + length * (2 * w1 + w2) / (3 * (w1 + w2))
R1 += total_load * (L - centroid) / L
R2 += total_load * centroid / L
return R1, R2
# Similar helper for cantilever, fixed, overhanging beams would be complex
# Here, for brevity, we implement simply_supported fully; others approximately
# Calculate V, M based on beam type and loads
if beam_type == "simply_supported":
R1, R2 = calc_reactions_simply_supported(L, loads)
for i, xi in enumerate(x):
# Shear force summation at xi:
Vx = R1
for load in loads:
if load["type"] == "point":
if xi >= load["a"]:
Vx -= load["P"]
elif load["type"] == "udl":
a = load["start"]
b = load["end"]
if xi >= a:
length = min(xi, b) - a
if length > 0:
Vx -= load["w"] * length
elif load["type"] == "uvl":
a = load["start"]
b = load["end"]
if xi >= a:
length = min(xi, b) - a
if length > 0:
w1 = load["w1"]
w2 = load["w2"]
# load intensity at xi
w_x = w1 + (w2 - w1) * (length) / (b - a)
# Area of trapezoid from start to xi:
Vx -= (length * (w1 + w_x)) / 2
V[i] = Vx
# Moment by integrating shear or summation of moments about left end
for i, xi in enumerate(x):
Mx = 0
# R1 moment
Mx += R1 * xi
# subtract moments due to loads left of xi
for load in loads:
if load["type"] == "point":
if xi >= load["a"]:
Mx -= load["P"] * (xi - load["a"])
elif load["type"] == "udl":
a = load["start"]
b = load["end"]
if xi >= a:
length = min(xi, b) - a
if length > 0:
w = load["w"]
# Load resultant and centroid from a
W = w * length
centroid = length / 2
Mx -= W * (xi - a - centroid)
elif load["type"] == "uvl":
a = load["start"]
b = load["end"]
if xi >= a:
length = min(xi, b) - a
if length > 0:
w1 = load["w1"]
w2 = load["w2"]
# total load on length
W = length * (w1 + w1 + (w2 - w1) * length / (b - a)) / 2
# centroid calculation for trapezoid (UVL)
centroid = length * (2*w1 + w1 + (w2 - w1)*length/(b - a)) / (3*(w1 + w1 + (w2 - w1)*length/(b - a)))
Mx -= W * (xi - a - centroid)
M[i] = Mx
elif beam_type == "cantilever":
# Support reaction R1 at fixed end
R1 = 0
M1 = 0
# Summation of loads for R1
for load in loads:
if load["type"] == "point":
R1 += load["P"]
M1 += load["P"] * (L - load["a"])
elif load["type"] == "udl":
length = load["end"] - load["start"]
W = load["w"] * length
centroid = (load["start"] + load["end"]) / 2
R1 += W
M1 += W * (L - centroid)
elif load["type"] == "uvl":
length = load["end"] - load["start"]
w1 = load["w1"]
w2 = load["w2"]
W = length * (w1 + w2) / 2
centroid = load["start"] + length * (2*w1 + w2) / (3*(w1 + w2))
R1 += W
M1 += W * (L - centroid)
for i, xi in enumerate(x):
Vx = - sum([
(load["P"] if load["type"] == "point" and xi >= load["a"] else 0) +
(load["w"] * (min(xi, load["end"]) - load["start"]) if load["type"] == "udl" and xi >= load["start"] else 0) +
((load["w1"] + (load["w2"] - load["w1"]) * (min(xi, load["end"]) - load["start"]) / (load["end"] - load["start"])) / 2 *
(min(xi, load["end"]) - load["start"]) if load["type"] == "uvl" and xi >= load["start"] else 0)
for load in loads
])
V[i] = Vx
for i, xi in enumerate(x):
Mx = - sum([
(load["P"] * (xi - load["a"]) if load["type"] == "point" and xi >= load["a"] else 0) +
(load["w"] * (min(xi, load["end"]) - load["start"]) * (xi - (load["start"] + min(xi, load["end"]) - load["start"]) / 2) if
load["type"] == "udl" and xi >= load["start"] else 0) +
(((load["w1"] + (load["w2"] - load["w1"]) * (min(xi, load["end"]) - load["start"]) / (load["end"] - load["start"])) / 2) *
(min(xi, load["end"]) - load["start"]) *
(xi - (load["start"] + (min(xi, load["end"]) - load["start"]) * (2*load["w1"] + load["w2"]) / (3*(load["w1"] +
load["w2"])))) if load["type"] == "uvl" and xi >= load["start"] else 0)
for load in loads
])
M[i] = Mx
else:
print(f"Beam type '{beam_type}' not fully implemented. Defaulting to simply supported calculations.")
R1, R2 = calc_reactions_simply_supported(L, loads)
for i, xi in enumerate(x):
Vx = R1
for load in loads:
if load["type"] == "point":
if xi >= load["a"]:
Vx -= load["P"]
elif load["type"] == "udl":
a = load["start"]
b = load["end"]
if xi >= a:
length = min(xi, b) - a
if length > 0:
Vx -= load["w"] * length
elif load["type"] == "uvl":
a = load["start"]
b = load["end"]
if xi >= a:
length = min(xi, b) - a
if length > 0:
w1 = load["w1"]
w2 = load["w2"]
w_x = w1 + (w2 - w1) * length / (b - a)
Vx -= (length * (w1 + w_x)) / 2
V[i] = Vx
for i, xi in enumerate(x):
Mx = 0
Mx += R1 * xi
for load in loads:
if load["type"] == "point":
if xi >= load["a"]:
Mx -= load["P"] * (xi - load["a"])
elif load["type"] == "udl":
a = load["start"]
b = load["end"]
if xi >= a:
length = min(xi, b) - a
if length > 0:
w = load["w"]
W = w * length
centroid = length / 2
Mx -= W * (xi - a - centroid)
elif load["type"] == "uvl":
a = load["start"]
b = load["end"]
if xi >= a:
length = min(xi, b) - a
if length > 0:
w1 = load["w1"]
w2 = load["w2"]
W = length * (w1 + w2) / 2
centroid = length * (2*w1 + w2) / (3*(w1 + w2))
Mx -= W * (xi - a - centroid)
M[i] = Mx
# ----------- Plotting -----------
fig, axs = [Link](3, 1, figsize=(12, 10), constrained_layout=True)
beam_y = 0
# Plot beam sketch
ax = axs[0]
ax.set_title("Beam Sketch with Supports and Loads")
[Link]([0, L], [beam_y, beam_y], 'k-', lw=6, label="Beam")
# Plot supports
support_size = L * 0.03
if beam_type in ['simply_supported', 'overhanging', 'fixed']:
[Link](0, beam_y, marker='^', markersize=15, color='blue', label='Support (Left)')
plot_arrow(ax, 0, beam_y - 0.05 * L, 'up', length=0.04 * L, color='blue')
if beam_type in ['simply_supported', 'overhanging', 'fixed']:
[Link](L, beam_y, marker='^', markersize=15, color='blue', label='Support (Right)')
plot_arrow(ax, L, beam_y - 0.05 * L, 'up', length=0.04 * L, color='blue')
if beam_type == 'cantilever':
[Link](0, beam_y, marker='s', markersize=15, color='red', label='Fixed Support (Left)')
plot_arrow(ax, 0, beam_y - 0.05 * L, 'up', length=0.04 * L, color='red')
# Plot loads
for load in loads:
if load["type"] == "point":
[Link](load["a"], beam_y + 0.1*L, 'ro', markersize=10)
plot_arrow(ax, load["a"], beam_y + 0.15*L, 'down', length=0.05*L, color='red')
[Link](load["a"], beam_y + 0.18*L, f'{load["P"]/1e3:.1f} kN', color='red', ha='center')
elif load["type"] == "udl":
start, end = load["start"], load["end"]
[Link](beam_y + 0.12*L, start, end, color='green', lw=6)
n_arrows = int((end - start) / (0.1 * L)) + 1
xs = [Link](start, end, n_arrows)
for x_pos in xs:
plot_arrow(ax, x_pos, beam_y + 0.12*L + 0.03*L, 'down', length=0.02*L, color='green')
[Link]((start+end)/2, beam_y + 0.18*L, f'{load["w"]/1e3:.1f} kN/m', color='green', ha='center')
elif load["type"] == "uvl":
# Plot UVL as linearly varying arrows
start, end = load["start"], load["end"]
n_arrows = int((end - start) / (0.1 * L)) + 1
xs = [Link](start, end, n_arrows)
w1, w2 = load["w1"], load["w2"]
for x_pos in xs:
w_at_x = w1 + (w2 - w1) * (x_pos - start) / (end - start)
length = 0.03*L * (w_at_x / max(w1, w2, 1))
plot_arrow(ax, x_pos, beam_y + 0.12*L + length/2, 'down', length=length, color='purple')
[Link]((start+end)/2, beam_y + 0.18*L, f'UVL {w1/1e3:.1f}→{w2/1e3:.1f} kN/m', color='purple', ha='center')
ax.set_ylim(-0.1*L, 0.25*L)
ax.set_xlim(-0.05*L, 1.05*L)
[Link]('off')
[Link]()
# Plot Shear Force Diagram (SFD)
ax = axs[1]
ax.set_title("Shear Force Diagram (N)")
[Link](x, V, 'b-', lw=2, label='Shear Force V(x)')
# Mark shear jumps at point loads with vertical arrows
for load in loads:
if load["type"] == "point":
idx = [Link](x, load["a"])
if idx < len(V)-1:
V_left = V[idx-1] if idx>0 else V[0]
V_right = V[idx]
jump = V_left - V_right
[Link]('', xy=(load["a"], V_right), xytext=(load["a"], V_left),
arrowprops=dict(arrowstyle='<|-|>', color='red', lw=2))
[Link](load["a"], max(V_left, V_right)+0.05*max(abs(V)), f'{jump/1e3:.1f} kN', color='red', ha='center')
# Highlight max/min shear
Vmax = max(V)
Vmin = min(V)
idx_max = [Link](V)
idx_min = [Link](V)
[Link](x[idx_max], Vmax, 'ro')
[Link](x[idx_max], Vmax + 0.05*Vmax, f'Max V = {Vmax/1e3:.2f} kN', color='red')
[Link](x[idx_min], Vmin, 'ro')
[Link](x[idx_min], Vmin - 0.1*abs(Vmin), f'Min V = {Vmin/1e3:.2f} kN', color='red')
[Link](0, color='black', lw=1)
ax.set_xlabel('Length (mm)')
ax.set_ylabel('Shear Force (N)')
[Link](True)
[Link]()
# Plot Bending Moment Diagram (BMD)
ax = axs[2]
ax.set_title("Bending Moment Diagram (N·mm)")
[Link](x, M, 'g-', lw=2, label='Bending Moment M(x)')
# Mark points of contraflexure (moment = 0 crossing)
contraflexures = find_points_of_contraflexure(x, M)
for pt in contraflexures:
idx = [Link](x, pt)
M_pt = 0
[Link](pt, M_pt, 'ko')
[Link](pt, M_pt + 0.05 * max(M), f'Contraflexure\n{pt:.0f} mm', ha='center')
# Highlight max/min moment
Mmax = max(M)
Mmin = min(M)
idx_Mmax = [Link](M)
idx_Mmin = [Link](M)
[Link](x[idx_Mmax], Mmax, 'ro')
[Link](x[idx_Mmax], Mmax + 0.05 * Mmax, f'Max M = {Mmax/1e6:.2f} kN·m', color='red')
[Link](x[idx_Mmin], Mmin, 'ro')
[Link](x[idx_Mmin], Mmin - 0.1 * abs(Mmin), f'Min M = {Mmin/1e6:.2f} kN·m', color='red')
[Link](0, color='black', lw=1)
ax.set_xlabel('Length (mm)')
ax.set_ylabel('Bending Moment (N·mm)')
[Link](True)
[Link]()
[Link]()
5)perfect one
import numpy as np
import [Link] as plt
import pandas as pd
from [Link] import canvas
from [Link] import letter
def get_support_reactions(beam_type, load_type, L, **kwargs):
"""Calculate support reactions based on beam type and load"""
if beam_type == "simply_supported":
if load_type == "point":
P = kwargs['P']
a = kwargs['a']
RA = P * (L - a) / L
RB = P * a / L
return {'RA': RA, 'RB': RB}
elif load_type == "udl":
w = kwargs['w']
RA = w * L / 2
RB = RA
return {'RA': RA, 'RB': RB}
elif load_type == "uvl":
w1 = kwargs['w1']
w2 = kwargs['w2']
total_load = (w1 + w2) * L / 2
RA = total_load / 2 # Approximate, better calc can be done
RB = total_load - RA
return {'RA': RA, 'RB': RB}
elif beam_type == "cantilever":
# Only one reaction at fixed end for cantilever
if load_type == "point":
P = kwargs['P']
a = kwargs['a']
RA = P
return {'RA': RA}
elif load_type == "udl":
w = kwargs['w']
RA = w * L
return {'RA': RA}
elif load_type == "uvl":
w1 = kwargs['w1']
w2 = kwargs['w2']
total_load = (w1 + w2) * L / 2
RA = total_load
return {'RA': RA}
elif beam_type == "fixed":
# Fixed end moments and reactions can be calculated for point load and UDL here
if load_type == "point":
P = kwargs['P']
a = kwargs['a']
RA = P * (L - a) ** 2 * (3 * a + L) / L**3
RB = P * a**2 * (3 * (L - a) + L) / L**3
MA = -P * a * (L - a)**2 / L**2
MB = -P * a**2 * (L - a) / L**2
return {'RA': RA, 'RB': RB, 'MA': MA, 'MB': MB}
elif load_type == "udl":
w = kwargs['w']
RA = w * L / 2
RB = RA
MA = -w * L**2 / 12
MB = MA
return {'RA': RA, 'RB': RB, 'MA': MA, 'MB': MB}
elif load_type == "uvl":
w1 = kwargs['w1']
w2 = kwargs['w2']
# approximate
total_load = (w1 + w2) * L / 2
RA = total_load / 2
RB = total_load / 2
MA = -total_load * L / 12
MB = MA
return {'RA': RA, 'RB': RB, 'MA': MA, 'MB': MB}
elif beam_type == "overhanging":
# Example simple case - support reactions for point load
if load_type == "point":
P = kwargs['P']
a = kwargs['a']
R1 = P * (L - a) / L
R2 = P * a / L
return {'R1': R1, 'R2': R2}
elif load_type == "udl":
w = kwargs['w']
R1 = w * L / 2
R2 = R1
return {'R1': R1, 'R2': R2}
elif load_type == "uvl":
w1 = kwargs['w1']
w2 = kwargs['w2']
total_load = (w1 + w2) * L / 2
R1 = total_load / 2
R2 = total_load / 2
return {'R1': R1, 'R2': R2}
elif beam_type == "continuous":
# Complex, simplified to simply supported for now
print("Continuous beam support reaction calc simplified to simply supported.")
if load_type == "point":
P = kwargs['P']
a = kwargs['a']
RA = P * (L - a) / L
RB = P * a / L
return {'RA': RA, 'RB': RB}
elif load_type == "udl":
w = kwargs['w']
RA = w * L / 2
RB = RA
return {'RA': RA, 'RB': RB}
elif load_type == "uvl":
w1 = kwargs['w1']
w2 = kwargs['w2']
total_load = (w1 + w2) * L / 2
RA = total_load / 2
RB = total_load / 2
return {'RA': RA, 'RB': RB}
else:
raise ValueError("Unsupported beam type")
def shear_moment_diagrams(beam_type, load_type, L, x, **kwargs):
V = np.zeros_like(x)
M = np.zeros_like(x)
if beam_type == "simply_supported":
if load_type == "point":
P = kwargs['P']
a = kwargs['a']
R = P * (L - a) / L
V = [Link](x < a, R, R - P)
M = [Link](x < a, R * x, R * x - P * (x - a))
elif load_type == "udl":
w = kwargs['w']
R=w*L/2
V=R-w*x
M = R * x - (w * x**2) / 2
elif load_type == "uvl":
w1 = kwargs['w1']
w2 = kwargs['w2']
# linear variation load, moment and shear by integration
V = (w1 + (w2 - w1) * x / L / 2) * L - (w1 + (w2 - w1) * x / L) * x / 2
M = (w1 * x**2) / 2 + ((w2 - w1) * x**3) / (6 * L)
elif beam_type == "cantilever":
if load_type == "point":
P = kwargs['P']
a = kwargs['a']
V = [Link](x <= a, -P, 0)
M = [Link](x <= a, -P * (L - x), 0)
elif load_type == "udl":
w = kwargs['w']
V = -w * (L - x)
M = -w * (L - x)**2 / 2
elif load_type == "uvl":
w1 = kwargs['w1']
w2 = kwargs['w2']
V = -((w1 + (w2 - w1) * (L - x) / L) * (L - x) / 2)
M = -((w1 * (L - x)**2) / 2 + ((w2 - w1) * (L - x)**3) / (6 * L))
elif beam_type == "fixed":
if load_type == "point":
P = kwargs['P']
a = kwargs['a']
RA = P * (L - a) ** 2 * (3 * a + L) / L**3
RB = P * a**2 * (3 * (L - a) + L) / L**3
MA = -P * a * (L - a)**2 / L**2
MB = -P * a**2 * (L - a) / L**2
V = [Link](x < a, RA, RA - P)
M = [Link](x < a, RA * x + MA, RB * (L - x) + MB)
elif load_type == "udl":
w = kwargs['w']
RA = w * L / 2
RB = w * L / 2
MA = -w * L**2 / 12
MB = MA
V = RA - w * x
M = RA * x - (w * x**2) / 2 + MA * (1 - x / L)
elif load_type == "uvl":
w1 = kwargs['w1']
w2 = kwargs['w2']
RA = (w1 + w2) * L / 2
RB = RA
MA = -RA * L / 6
MB = MA
# Simplified linear approx for V, M
V = RA - ((w1 * x) + ((w2 - w1) * x**2) / (2 * L))
M = RA * x - ((w1 * x**2) / 2 + ((w2 - w1) * x**3) / (6 * L)) + MA * (1 - x / L)
elif beam_type == "overhanging":
if load_type == "point":
P = kwargs['P']
a = kwargs['a']
R1 = P * (L - a) / L
R2 = P * a / L
V = [Link](x < a, R1, R1 - P)
M = [Link](x < a, R1 * x, R1 * x - P * (x - a))
elif load_type == "udl":
w = kwargs['w']
R1 = w * L / 2
V = R1 - w * x
M = R1 * x - (w * x**2) / 2
elif load_type == "uvl":
w1 = kwargs['w1']
w2 = kwargs['w2']
V = ((w1 + (w2 - w1) * x / L / 2) * L - (w1 + (w2 - w1) * x / L) * x / 2)
M = (w1 * x**2) / 2 + ((w2 - w1) * x**3) / (6 * L)
elif beam_type == "continuous":
print("Continuous beam treated as simply supported for diagram.")
# Treat as simply supported for diagram here:
if load_type == "point":
P = kwargs['P']
a = kwargs['a']
R = P * (L - a) / L
V = [Link](x < a, R, R - P)
M = [Link](x < a, R * x, R * x - P * (x - a))
elif load_type == "udl":
w = kwargs['w']
R=w*L/2
V=R-w*x
M = R * x - (w * x**2) / 2
elif load_type == "uvl":
w1 = kwargs['w1']
w2 = kwargs['w2']
V = (w1 + (w2 - w1) * x / L / 2) * L - (w1 + (w2 - w1) * x / L) * x / 2
M = (w1 * x**2) / 2 + ((w2 - w1) * x**3) / (6 * L)
else:
raise ValueError("Unsupported beam type")
return V, M
def find_points_of_contraflexure(M, x):
"""Find points where bending moment crosses zero (contraflexure points)"""
sign_changes = [Link]([Link]([Link](M)))[0]
points = []
for idx in sign_changes:
# Linear interpolation for zero crossing
x0, x1 = x[idx], x[idx+1]
M0, M1 = M[idx], M[idx+1]
zero_x = x0 - M0 * (x1 - x0) / (M1 - M0)
[Link](zero_x)
return points
def max_values(x, V, M):
"""Find max shear force and moment"""
max_V = [Link]([Link](V))
max_M = [Link]([Link](M))
max_x_V = x[[Link]([Link](V))]
max_x_M = x[[Link]([Link](M))]
return max_V, max_x_V, max_M, max_x_M
def reinforcement_design(Mu, b, d, fck, fy, cover):
Mulim = 0.138 * fck * b * d**2
if Mu <= Mulim:
Ast = Mu / (0.87 * fy * (d - 0.42 * d))
return {
"Type": "Singly Reinforced",
"Ast (mm²)": Ast,
else:
Ast1 = Mulim / (0.87 * fy * (d - 0.42 * d))
Mu2 = Mu - Mulim
d_dash = cover
Ast2 = Mu2 / (0.87 * fy * (d - d_dash))
Asc = Ast2
Ast = Ast1 + Ast2
return {
"Type": "Doubly Reinforced",
"Ast1 (mm²)": Ast1,
"Ast2 (mm²)": Ast2,
"Asc (mm²)": Asc,
"Total Ast (mm²)": Ast,
def shear_design(Vmax, b, d, fck):
tau_v = Vmax / (b * d)
tau_c = 0.36 # conservative for M25
return {
"Vmax (N)": Vmax,
"Nominal Shear Stress (MPa)": tau_v,
"Shear Capacity (MPa)": tau_c,
"Shear Check": "Safe" if tau_v < tau_c else "Not Safe"
def deflection_check(L, d):
limit = L / d
return {
"L/d": limit,
"Deflection Check": "Safe (L/d < 20)" if limit < 20 else "Check Required"
def crack_control():
max_spacing = 300
return {
"Max Bar Spacing (mm)": max_spacing,
"Crack Control": f"Max spacing should be < {max_spacing} mm"
def main():
print("Beam Design Tool - Enter Inputs:")
beam_type = input("Beam type
(simply_supported/cantilever/fixed/overhanging/continuous): ").strip()
load_type = input("Load type (point/udl/uvl): ").strip()
L = float(input("Beam length (mm): "))
b = float(input("Beam width (mm): "))
d = float(input("Effective depth (mm): "))
cover = float(input("Cover (mm): "))
fck = float(input("Concrete compressive strength fck (MPa): "))
fy = float(input("Steel yield strength fy (MPa): "))
kwargs = {}
if load_type == "point":
P = float(input("Point load magnitude P (N): "))
a = float(input("Distance from left support a (mm): "))
[Link]({'P': P, 'a': a})
elif load_type == "udl":
w = float(input("Uniformly distributed load w (N/mm): "))
[Link]({'w': w})
elif load_type == "uvl":
w1 = float(input("Load intensity at left w1 (N/mm): "))
w2 = float(input("Load intensity at right w2 (N/mm): "))
[Link]({'w1': w1, 'w2': w2})
else:
print("Invalid load type")
return
# Calculate support reactions
reactions = get_support_reactions(beam_type, load_type, L, **kwargs)
print("\nSupport Reactions:")
for k, v in [Link]():
print(f" {k} = {v:.2f} N")
# Prepare x axis for diagrams
x = [Link](0, L, 1000)
# Calculate Shear Force and Moment diagrams
V, M = shear_moment_diagrams(beam_type, load_type, L, x, **kwargs)
# Max values
Vmax, xVmax, Mmax, xMmax = max_values(x, V, M)
# Reinforcement design
reinforcement = reinforcement_design(Mmax, b, d, fck, fy, cover)
shear = shear_design(Vmax, b, d, fck)
deflection = deflection_check(L, d)
crack = crack_control()
# Show design summary
print("\nDesign Summary:")
print(f"Beam dimensions: b={b} mm, d={d} mm, L={L} mm")
print(f"Ultimate moment Mu = {Mmax/1e6:.2f} kN-m")
for k,v in [Link]():
print(f"{k}: {v if isinstance(v,float) else v}")
for k,v in [Link]():
print(f"{k}: {v if isinstance(v,float) else v}")
for k,v in [Link]():
print(f"{k}: {v if isinstance(v,float) else v}")
for k,v in [Link]():
print(f"{k}: {v if isinstance(v,float) else v}")
# Save results to Excel
result_data = {
"Parameter": [],
"Value": []
result_data["Parameter"].extend([
"Beam Type", "Load Type", "Beam Length (mm)", "Beam Width (mm)", "Effective Depth
(mm)",
"Cover (mm)", "fck (MPa)", "fy (MPa)", "Ultimate Moment Mu (kN-m)"
])
result_data["Value"].extend([
beam_type, load_type, L, b, d, cover, fck, fy, f"{Mmax/1e6:.2f}"
])
for k,v in [Link]():
result_data["Parameter"].append(k)
result_data["Value"].append(f"{v:.2f}" if isinstance(v,float) else v)
for k,v in [Link]():
result_data["Parameter"].append(k)
result_data["Value"].append(f"{v:.3f}" if isinstance(v,float) else v)
for k,v in [Link]():
result_data["Parameter"].append(k)
result_data["Value"].append(f"{v:.2f}" if isinstance(v,float) else v)
for k,v in [Link]():
result_data["Parameter"].append(k)
result_data["Value"].append(v)
# Include reactions
for k,v in [Link]():
result_data["Parameter"].append(f"Reaction {k} (N)")
result_data["Value"].append(f"{v:.2f}")
df = [Link](result_data)
df.to_excel("beam_design_results.xlsx", index=False)
# Export to PDF
pdf_file = "beam_design_report.pdf"
c = [Link](pdf_file, pagesize=letter)
[Link](50, 750, "Beam Design Report")
y = 730
for k, v in zip(result_data["Parameter"], result_data["Value"]):
[Link](50, y, f"{k}: {v}")
y -= 15
if y < 50:
[Link]()
y = 750
[Link]()
# Plot SFD and BMD
[Link](figsize=(10, 8))
[Link](2, 1, 1)
[Link](x, V / 1000, 'g-', label='Shear Force (kN)')
plt.fill_between(x, 0, V / 1000, color='lightgreen', alpha=0.4)
[Link](True)
[Link]("Shear Force Diagram")
[Link]("Shear Force (kN)")
[Link](0, color='black', linewidth=0.8)
[Link](2, 1, 2)
[Link](x, M / 1e6, 'b-', label='Bending Moment (kN-m)')
plt.fill_between(x, 0, M / 1e6, color='skyblue', alpha=0.4)
[Link](True)
[Link]("Bending Moment Diagram")
[Link]("Beam Length (mm)")
[Link]("Moment (kN-m)")
[Link](0, color='black', linewidth=0.8)
plt.tight_layout()
[Link]("sfd_bmd_plot.png")
[Link]()
print("\nDesign complete. Results saved to Excel, PDF, and plots saved as image.")
if __name__ == "__main__":
main()