Spaces:
Running
Running
File size: 11,402 Bytes
0be7e4d b2c3381 0be7e4d b2c3381 0be7e4d b2c3381 0be7e4d b2c3381 0be7e4d b2c3381 0be7e4d e0ca7be 0be7e4d e0ca7be 0be7e4d e0ca7be 0be7e4d b2c3381 0be7e4d b2c3381 0be7e4d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
import gradio as gr
import pandas as pd
from continuous_beam import ContinuousBeam
import matplotlib.pyplot as plt
import numpy as np
import io
import base64
import gc # Garbage collection for memory management
import warnings
warnings.filterwarnings('ignore') # Suppress warnings for cleaner output
# Configure matplotlib for cloud deployment
plt.style.use('default') # Use simple style
plt.rcParams['figure.max_open_warning'] = 0 # Disable figure warnings
class GradioBeamApp:
def __init__(self):
self.beam = ContinuousBeam()
self.spans_data = []
def parse_point_loads(self, point_loads_text):
"""Parse point loads from text input"""
if not point_loads_text or point_loads_text.strip() == "":
return []
point_loads = []
try:
# Expected format: "position1,load1; position2,load2; ..."
# Example: "2.0,50; 4.0,30"
load_pairs = point_loads_text.split(';')
for pair in load_pairs:
if pair.strip():
pos_str, load_str = pair.split(',')
position = float(pos_str.strip())
load = float(load_str.strip())
point_loads.append((position, load))
except:
raise ValueError("Invalid point load format. Use: position1,load1; position2,load2")
return point_loads
def add_span(self, length, distributed_load, point_loads_text, spans_display):
"""Add a span to the beam"""
try:
length = float(length)
distributed_load = float(distributed_load)
if length <= 0 or distributed_load < 0:
return spans_display, "Error: Please enter valid values (length > 0, distributed_load >= 0)"
# Parse point loads
point_loads = self.parse_point_loads(point_loads_text)
# Validate point load positions
for pos, load in point_loads:
if pos < 0 or pos > length:
return spans_display, f"Error: Point load at {pos}m is outside span length {length}m"
if load < 0:
return spans_display, f"Error: Point load {load}kN must be positive"
self.beam.add_span(length, distributed_load, point_loads)
# Create span description
span_info = f"Span {len(self.beam.spans)}: L={length}m, w={distributed_load}kN/m"
if point_loads:
point_load_str = ", ".join([f"P={load}kN@{pos}m" for pos, load in point_loads])
span_info += f", {point_load_str}"
self.spans_data.append(span_info)
# Update display
updated_display = "\n".join(self.spans_data)
return updated_display, f"Added: {span_info}"
except ValueError as e:
return spans_display, f"Error: {str(e)}"
def clear_spans(self):
"""Clear all spans"""
self.beam = ContinuousBeam()
self.spans_data = []
return "", "All spans cleared"
def design_beam(self, width, depth, fc, fy, cover, spans_display):
"""Design the beam and return results"""
if not self.beam.spans:
return "No spans added. Please add at least one span.", None, None, None, None, None
try:
# Limit spans for cloud deployment
if len(self.beam.spans) > 10:
return "Error: Maximum 10 spans allowed for cloud deployment.", None, None, None, None, "Error: Too many spans"
# Update beam properties
self.beam.beam_width = float(width)
self.beam.beam_depth = float(depth)
self.beam.fc = float(fc)
self.beam.fy = float(fy)
self.beam.cover = float(cover)
self.beam.d = self.beam.beam_depth - self.beam.cover
# Perform design with timeout protection
design_results = self.beam.design_beam()
# Generate report
report = self.beam.generate_report(design_results)
# Create summary table
summary_data = []
for span_data in design_results:
span_num = span_data['span']
for i, (reinf, stirrup) in enumerate(zip(span_data['reinforcement'], span_data['stirrups'])):
if reinf['moment'] != 0 or stirrup['shear'] != 0:
summary_data.append([
span_num if i == 0 else '',
reinf['location'],
f"{reinf['moment']:.2f}" if reinf['moment'] != 0 else '-',
reinf['bars'] if reinf['moment'] != 0 else '-',
f"{stirrup['shear']:.2f}" if stirrup['shear'] != 0 else '-',
stirrup['stirrup_spacing'] if stirrup['shear'] != 0 else '-'
])
# Create DataFrame for table display
df = pd.DataFrame(summary_data, columns=[
'Span', 'Location', 'Moment (kN-m)', 'Reinforcement', 'Shear (kN)', 'Stirrups'
])
# Generate plots with error handling
try:
bmd_sfd_plot = self.beam.plot_bmd_sfd(design_results)
reinforcement_plot = self.beam.plot_reinforcement_layout(design_results)
stirrup_plot = self.beam.plot_stirrup_layout(design_results)
except Exception as plot_error:
print(f"Plotting error: {plot_error}")
# Return simplified results if plotting fails
return report, df, None, None, None, "Design completed (plots unavailable)"
# Force garbage collection to free memory
gc.collect()
return report, df, bmd_sfd_plot, reinforcement_plot, stirrup_plot, "Design completed successfully!"
except Exception as e:
gc.collect() # Clean up memory on error
error_msg = str(e)
if "memory" in error_msg.lower() or "allocation" in error_msg.lower():
return "Error: Insufficient memory. Try reducing the number of spans or load complexity.", None, None, None, None, "Memory Error"
return f"Design calculation failed: {error_msg}", None, None, None, None, f"Error: {error_msg}"
def create_interface():
app = GradioBeamApp()
with gr.Blocks(title="Continuous Beam RC Design - Thai Standards", theme=gr.themes.Default()) as interface:
gr.Markdown("# Continuous Beam RC Design - Thai Standards")
gr.Markdown("*Using Finite Element Analysis with Thai reinforcement standards (DB bars, RB stirrups)*")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("## Beam Properties")
with gr.Row():
width_input = gr.Number(label="Beam Width (mm)", value=300)
depth_input = gr.Number(label="Beam Depth (mm)", value=500)
with gr.Row():
fc_input = gr.Number(label="f'c (ksc)", value=280)
fy_input = gr.Number(label="fy (ksc)", value=4000)
cover_input = gr.Number(label="Cover (mm)", value=40)
gr.Markdown("## Spans Configuration")
with gr.Row():
span_length_input = gr.Number(label="Span Length (m)", value=6.0)
distributed_load_input = gr.Number(label="Distributed Load (kN/m)", value=25.0)
point_loads_input = gr.Textbox(
label="Point Loads (position,load; position,load; ...)",
placeholder="Example: 2.0,50; 4.0,30 (means 50kN at 2m and 30kN at 4m)",
value=""
)
with gr.Row():
add_span_btn = gr.Button("Add Span", variant="primary")
clear_spans_btn = gr.Button("Clear All", variant="secondary")
spans_display = gr.Textbox(
label="Added Spans",
lines=5,
interactive=False,
placeholder="No spans added yet..."
)
design_btn = gr.Button("Design Beam", variant="primary", size="lg")
status_output = gr.Textbox(label="Status", interactive=False)
with gr.Column(scale=2):
gr.Markdown("## Design Results")
with gr.Tabs():
with gr.TabItem("Summary"):
summary_table = gr.Dataframe(
label="Design Summary",
headers=["Span", "Location", "Moment (kN-m)", "Reinforcement", "Shear (kN)", "Stirrups"],
interactive=False
)
with gr.TabItem("BMD & SFD"):
bmd_sfd_plot = gr.Plot(label="Bending Moment and Shear Force Diagrams")
with gr.TabItem("Reinforcement Layout"):
reinforcement_plot = gr.Plot(label="Reinforcement Bar Layout")
with gr.TabItem("Stirrup Layout"):
stirrup_plot = gr.Plot(label="Shear Stirrup Layout")
with gr.TabItem("Detailed Report"):
results_output = gr.Textbox(
label="Detailed Design Report",
lines=20,
interactive=False,
show_copy_button=True
)
# Event handlers
add_span_btn.click(
fn=lambda length, dist_load, point_loads, spans: app.add_span(length, dist_load, point_loads, spans),
inputs=[span_length_input, distributed_load_input, point_loads_input, spans_display],
outputs=[spans_display, status_output]
)
clear_spans_btn.click(
fn=lambda: app.clear_spans(),
outputs=[spans_display, status_output]
)
design_btn.click(
fn=lambda w, d, fc, fy, c, spans: app.design_beam(w, d, fc, fy, c, spans),
inputs=[width_input, depth_input, fc_input, fy_input, cover_input, spans_display],
outputs=[results_output, summary_table, bmd_sfd_plot, reinforcement_plot, stirrup_plot, status_output]
)
return interface
def main():
interface = create_interface()
# Optimized for Hugging Face Spaces
interface.launch(
share=False,
debug=False, # Disable debug for production
show_error=True,
quiet=True, # Reduce console output
ssr_mode=False, # Disable SSR for compatibility
auth=None, # No authentication required
max_threads=10 # Limit concurrent threads
)
if __name__ == "__main__":
main() |