Spaces:
Runtime error
Runtime error
Create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,432 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import numpy as np
|
| 4 |
+
import matplotlib.pyplot as plt
|
| 5 |
+
import plotly.graph_objects as go
|
| 6 |
+
import plotly.express as px
|
| 7 |
+
from sklearn.ensemble import RandomForestRegressor
|
| 8 |
+
from sklearn.preprocessing import StandardScaler
|
| 9 |
+
import warnings
|
| 10 |
+
warnings.filterwarnings('ignore')
|
| 11 |
+
|
| 12 |
+
# Materials database
|
| 13 |
+
def load_materials_database():
|
| 14 |
+
return pd.DataFrame({
|
| 15 |
+
'Material': ['Steel 1045', 'Steel 4140', 'Aluminum 6061-T6', 'Aluminum 7075-T6',
|
| 16 |
+
'Stainless 304', 'Titanium Ti-6Al-4V', 'Cast Iron GG20', 'Brass C360'],
|
| 17 |
+
'Density (kg/mΒ³)': [7850, 7850, 2700, 2810, 8000, 4430, 7200, 8500],
|
| 18 |
+
'Yield Strength (MPa)': [310, 415, 276, 503, 205, 880, 250, 125],
|
| 19 |
+
'Ultimate Strength (MPa)': [565, 655, 310, 572, 515, 950, 350, 315],
|
| 20 |
+
'Elastic Modulus (GPa)': [200, 205, 69, 72, 200, 114, 100, 100],
|
| 21 |
+
'Cost ($/kg)': [0.80, 1.20, 1.90, 2.50, 3.50, 35.00, 0.60, 6.50],
|
| 22 |
+
'Temperature Limit (Β°C)': [400, 500, 200, 180, 800, 600, 350, 250]
|
| 23 |
+
})
|
| 24 |
+
|
| 25 |
+
materials_db = load_materials_database()
|
| 26 |
+
|
| 27 |
+
# AI Knowledge Base
|
| 28 |
+
def get_ai_response(query):
|
| 29 |
+
responses = {
|
| 30 |
+
"material": "For material selection, consider strength requirements, environmental conditions, cost, and manufacturability. Steel offers good strength at low cost, aluminum provides excellent strength-to-weight ratio, and stainless steel offers superior corrosion resistance.",
|
| 31 |
+
"design": "Design optimization involves balancing performance, cost, and manufacturability. Apply DFMA principles, minimize stress concentrations, and use appropriate safety factors. Consider topology optimization for weight reduction.",
|
| 32 |
+
"stress": "Stress analysis requires proper load identification, material properties, and boundary conditions. Use von Mises criterion for ductile materials and maximum principal stress for brittle materials. Include safety factors based on application criticality.",
|
| 33 |
+
"failure": "Failure prediction involves monitoring key parameters and applying appropriate failure theories. Consider fatigue, wear, corrosion, and overload failure modes. Implement condition-based monitoring for early detection.",
|
| 34 |
+
"gear": "Gear design requires consideration of power transmission, speed ratio, center distance, and material selection. Use Lewis equation for bending stress and Hertz equation for contact stress.",
|
| 35 |
+
"beam": "Beam analysis involves calculating bending moments, shear forces, and deflections. For simply supported beams: Ο_max = Mc/I, Ξ΄_max = 5wLβ΄/384EI (uniform load)."
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
query_lower = query.lower()
|
| 39 |
+
for key, response in responses.items():
|
| 40 |
+
if key in query_lower:
|
| 41 |
+
return response
|
| 42 |
+
return "I can help with material selection, design optimization, stress analysis, failure prediction, gear design, and beam analysis. Please specify your engineering question."
|
| 43 |
+
|
| 44 |
+
# 3D Model Generation
|
| 45 |
+
def generate_3d_model(component, teeth=20, module=2, length=100, diameter=20):
|
| 46 |
+
if component == "Gear":
|
| 47 |
+
# Generate gear profile
|
| 48 |
+
angles = np.linspace(0, 2*np.pi, teeth*4)
|
| 49 |
+
radius = teeth * module / 2
|
| 50 |
+
r_vals = []
|
| 51 |
+
for i, angle in enumerate(angles):
|
| 52 |
+
if i % 4 < 2: # Tooth
|
| 53 |
+
r_vals.append(radius + module)
|
| 54 |
+
else: # Root
|
| 55 |
+
r_vals.append(radius - module)
|
| 56 |
+
|
| 57 |
+
x = np.array(r_vals) * np.cos(angles)
|
| 58 |
+
y = np.array(r_vals) * np.sin(angles)
|
| 59 |
+
|
| 60 |
+
fig = go.Figure()
|
| 61 |
+
fig.add_trace(go.Scatter(x=x, y=y, mode='lines', name='Gear Profile', line=dict(width=3)))
|
| 62 |
+
fig.update_layout(
|
| 63 |
+
title=f"Gear Profile (Teeth: {teeth}, Module: {module})",
|
| 64 |
+
xaxis_title="X (mm)",
|
| 65 |
+
yaxis_title="Y (mm)",
|
| 66 |
+
showlegend=False,
|
| 67 |
+
width=600,
|
| 68 |
+
height=600
|
| 69 |
+
)
|
| 70 |
+
fig.update_xaxis(scaleanchor="y", scaleratio=1)
|
| 71 |
+
|
| 72 |
+
specs = f"""
|
| 73 |
+
**Gear Specifications:**
|
| 74 |
+
- Number of Teeth: {teeth}
|
| 75 |
+
- Module: {module}
|
| 76 |
+
- Pitch Diameter: {teeth * module:.2f} mm
|
| 77 |
+
- Addendum: {module:.2f} mm
|
| 78 |
+
- Dedendum: {1.25 * module:.2f} mm
|
| 79 |
+
"""
|
| 80 |
+
|
| 81 |
+
return fig, specs
|
| 82 |
+
|
| 83 |
+
elif component == "Shaft":
|
| 84 |
+
# Generate shaft 3D visualization
|
| 85 |
+
theta = np.linspace(0, 2*np.pi, 20)
|
| 86 |
+
z_vals = np.linspace(0, length, 10)
|
| 87 |
+
|
| 88 |
+
# Create surface plot
|
| 89 |
+
Z, T = np.meshgrid(z_vals, theta)
|
| 90 |
+
X = (diameter/2) * np.cos(T)
|
| 91 |
+
Y = (diameter/2) * np.sin(T)
|
| 92 |
+
|
| 93 |
+
fig = go.Figure(data=[go.Surface(x=X, y=Y, z=Z, colorscale='Blues')])
|
| 94 |
+
fig.update_layout(
|
| 95 |
+
title=f"Shaft 3D Model (Length: {length}mm, Diameter: {diameter}mm)",
|
| 96 |
+
scene=dict(
|
| 97 |
+
xaxis_title="X (mm)",
|
| 98 |
+
yaxis_title="Y (mm)",
|
| 99 |
+
zaxis_title="Z (mm)"
|
| 100 |
+
),
|
| 101 |
+
width=600,
|
| 102 |
+
height=500
|
| 103 |
+
)
|
| 104 |
+
|
| 105 |
+
specs = f"""
|
| 106 |
+
**Shaft Specifications:**
|
| 107 |
+
- Length: {length} mm
|
| 108 |
+
- Diameter: {diameter} mm
|
| 109 |
+
- Cross-sectional Area: {np.pi * (diameter/2)**2:.2f} mmΒ²
|
| 110 |
+
- Moment of Inertia: {np.pi * diameter**4 / 64:.2f} mmβ΄
|
| 111 |
+
"""
|
| 112 |
+
|
| 113 |
+
return fig, specs
|
| 114 |
+
|
| 115 |
+
return go.Figure(), "Select a component type"
|
| 116 |
+
|
| 117 |
+
# FEA Analysis
|
| 118 |
+
def perform_fea_analysis(material, force, area, length=1000):
|
| 119 |
+
# Get material properties
|
| 120 |
+
mat_data = materials_db[materials_db['Material'] == material].iloc[0]
|
| 121 |
+
|
| 122 |
+
E = mat_data['Elastic Modulus (GPa)'] * 1e9 # Pa
|
| 123 |
+
yield_strength = mat_data['Yield Strength (MPa)'] * 1e6 # Pa
|
| 124 |
+
|
| 125 |
+
# Calculate stress and displacement
|
| 126 |
+
stress = force / (area / 1e6) # Convert area from mmΒ² to mΒ²
|
| 127 |
+
displacement = stress / E * length # mm
|
| 128 |
+
safety_factor = yield_strength / stress if stress > 0 else 10
|
| 129 |
+
|
| 130 |
+
# Generate stress distribution
|
| 131 |
+
n_points = 50
|
| 132 |
+
x_pos = np.linspace(0, length, n_points)
|
| 133 |
+
stress_dist = stress * (1 + 0.3 * np.sin(2 * np.pi * x_pos / length)) / 1e6 # MPa
|
| 134 |
+
|
| 135 |
+
# Create plot
|
| 136 |
+
fig = go.Figure()
|
| 137 |
+
fig.add_trace(go.Scatter(
|
| 138 |
+
x=x_pos,
|
| 139 |
+
y=stress_dist,
|
| 140 |
+
mode='lines+markers',
|
| 141 |
+
name='Stress Distribution',
|
| 142 |
+
line=dict(width=3, color='red')
|
| 143 |
+
))
|
| 144 |
+
fig.update_layout(
|
| 145 |
+
title="Stress Distribution Along Component",
|
| 146 |
+
xaxis_title="Position (mm)",
|
| 147 |
+
yaxis_title="Stress (MPa)",
|
| 148 |
+
width=600,
|
| 149 |
+
height=400
|
| 150 |
+
)
|
| 151 |
+
|
| 152 |
+
# Add safety limit line
|
| 153 |
+
fig.add_hline(y=mat_data['Yield Strength (MPa)'],
|
| 154 |
+
line_dash="dash", line_color="orange",
|
| 155 |
+
annotation_text="Yield Strength Limit")
|
| 156 |
+
|
| 157 |
+
# Results summary
|
| 158 |
+
results = f"""
|
| 159 |
+
**FEA Analysis Results:**
|
| 160 |
+
- Material: {material}
|
| 161 |
+
- Max Stress: {stress/1e6:.2f} MPa
|
| 162 |
+
- Max Displacement: {displacement:.4f} mm
|
| 163 |
+
- Safety Factor: {safety_factor:.2f}
|
| 164 |
+
- Status: {'β
SAFE' if safety_factor > 2 else 'β οΈ CHECK DESIGN'}
|
| 165 |
+
|
| 166 |
+
**Material Properties:**
|
| 167 |
+
- Yield Strength: {mat_data['Yield Strength (MPa)']} MPa
|
| 168 |
+
- Elastic Modulus: {mat_data['Elastic Modulus (GPa)']} GPa
|
| 169 |
+
- Density: {mat_data['Density (kg/mΒ³)']} kg/mΒ³
|
| 170 |
+
"""
|
| 171 |
+
|
| 172 |
+
return fig, results
|
| 173 |
+
|
| 174 |
+
# Material Selection
|
| 175 |
+
def material_selector(min_strength, max_cost, min_temp):
|
| 176 |
+
# Filter materials based on criteria
|
| 177 |
+
filtered = materials_db[
|
| 178 |
+
(materials_db['Yield Strength (MPa)'] >= min_strength) &
|
| 179 |
+
(materials_db['Cost ($/kg)'] <= max_cost) &
|
| 180 |
+
(materials_db['Temperature Limit (Β°C)'] >= min_temp)
|
| 181 |
+
]
|
| 182 |
+
|
| 183 |
+
if filtered.empty:
|
| 184 |
+
return "No materials match your criteria. Please adjust requirements.", go.Figure()
|
| 185 |
+
|
| 186 |
+
# Create comparison chart
|
| 187 |
+
fig = px.scatter(filtered,
|
| 188 |
+
x='Yield Strength (MPa)',
|
| 189 |
+
y='Cost ($/kg)',
|
| 190 |
+
size='Density (kg/mΒ³)',
|
| 191 |
+
color='Material',
|
| 192 |
+
hover_data=['Temperature Limit (Β°C)'],
|
| 193 |
+
title='Recommended Materials')
|
| 194 |
+
fig.update_layout(width=600, height=400)
|
| 195 |
+
|
| 196 |
+
# Format results table
|
| 197 |
+
result_table = filtered[['Material', 'Yield Strength (MPa)', 'Cost ($/kg)', 'Temperature Limit (Β°C)']].to_string(index=False)
|
| 198 |
+
|
| 199 |
+
return f"**Recommended Materials:**\n```\n{result_table}\n```", fig
|
| 200 |
+
|
| 201 |
+
# Gear Calculator
|
| 202 |
+
def gear_calculator(teeth, module, power, speed):
|
| 203 |
+
# Basic calculations
|
| 204 |
+
pitch_diameter = teeth * module
|
| 205 |
+
torque = (power * 1000 * 60) / (2 * np.pi * speed) # Nβ
mm
|
| 206 |
+
pitch_line_velocity = (np.pi * pitch_diameter * speed) / (60 * 1000) # m/s
|
| 207 |
+
|
| 208 |
+
# Lewis equation for bending stress (simplified)
|
| 209 |
+
lewis_factor = 0.154 - 0.912/teeth # Approximation
|
| 210 |
+
face_width = 10 * module # Typical assumption
|
| 211 |
+
tangential_force = 2 * torque / pitch_diameter
|
| 212 |
+
bending_stress = tangential_force / (face_width * module * lewis_factor)
|
| 213 |
+
|
| 214 |
+
# Material recommendation
|
| 215 |
+
required_strength = bending_stress * 3 # Safety factor of 3
|
| 216 |
+
suitable_materials = materials_db[materials_db['Yield Strength (MPa)'] >= required_strength/1e6]
|
| 217 |
+
|
| 218 |
+
if not suitable_materials.empty:
|
| 219 |
+
recommended = suitable_materials.iloc[0]['Material']
|
| 220 |
+
else:
|
| 221 |
+
recommended = "High-strength steel required"
|
| 222 |
+
|
| 223 |
+
results = f"""
|
| 224 |
+
**Gear Design Results:**
|
| 225 |
+
- Pitch Diameter: {pitch_diameter:.2f} mm
|
| 226 |
+
- Torque: {torque:.2f} Nβ
mm
|
| 227 |
+
- Pitch Line Velocity: {pitch_line_velocity:.2f} m/s
|
| 228 |
+
- Estimated Face Width: {face_width:.2f} mm
|
| 229 |
+
- Bending Stress: {bending_stress/1e6:.2f} MPa
|
| 230 |
+
- Recommended Material: {recommended}
|
| 231 |
+
|
| 232 |
+
**Design Notes:**
|
| 233 |
+
- Use appropriate lubrication for velocities > 5 m/s
|
| 234 |
+
- Consider heat treatment for high-stress applications
|
| 235 |
+
- Verify contact stress separately
|
| 236 |
+
"""
|
| 237 |
+
|
| 238 |
+
return results
|
| 239 |
+
|
| 240 |
+
# Create Gradio Interface
|
| 241 |
+
def create_interface():
|
| 242 |
+
with gr.Blocks(title="MechMind - AI Mechanical Engineering Assistant", theme=gr.themes.Soft()) as app:
|
| 243 |
+
|
| 244 |
+
gr.Markdown("""
|
| 245 |
+
# π§ MechMind - AI Mechanical Engineering Assistant
|
| 246 |
+
### AI-powered platform for mechanical design, analysis, and optimization
|
| 247 |
+
**Features:** 3D Model Generation | Advanced FEA | Smart Material Selection | AI Engineering Assistant
|
| 248 |
+
""")
|
| 249 |
+
|
| 250 |
+
with gr.Tabs():
|
| 251 |
+
# Dashboard Tab
|
| 252 |
+
with gr.TabItem("π Dashboard"):
|
| 253 |
+
gr.Markdown("## Engineering Dashboard")
|
| 254 |
+
|
| 255 |
+
with gr.Row():
|
| 256 |
+
gr.Markdown(f"**Materials Database:** {len(materials_db)} materials")
|
| 257 |
+
gr.Markdown("**AI Models Active:** 5")
|
| 258 |
+
gr.Markdown("**Success Rate:** 96.8%")
|
| 259 |
+
|
| 260 |
+
gr.Markdown("### π Materials Overview")
|
| 261 |
+
materials_plot = px.scatter(materials_db,
|
| 262 |
+
x='Yield Strength (MPa)',
|
| 263 |
+
y='Cost ($/kg)',
|
| 264 |
+
size='Density (kg/mΒ³)',
|
| 265 |
+
color='Material',
|
| 266 |
+
title='Material Properties Comparison')
|
| 267 |
+
gr.Plot(materials_plot)
|
| 268 |
+
|
| 269 |
+
# 3D Design Generator Tab
|
| 270 |
+
with gr.TabItem("π§ 3D Design Generator"):
|
| 271 |
+
gr.Markdown("## AI-Powered 3D Model Generator")
|
| 272 |
+
|
| 273 |
+
with gr.Row():
|
| 274 |
+
with gr.Column():
|
| 275 |
+
component_type = gr.Dropdown(["Gear", "Shaft"], label="Component Type", value="Gear")
|
| 276 |
+
|
| 277 |
+
# Gear parameters
|
| 278 |
+
teeth_input = gr.Slider(8, 100, value=20, step=1, label="Number of Teeth")
|
| 279 |
+
module_input = gr.Slider(0.5, 10, value=2, step=0.5, label="Module")
|
| 280 |
+
|
| 281 |
+
# Shaft parameters
|
| 282 |
+
length_input = gr.Slider(50, 500, value=100, step=10, label="Length (mm)")
|
| 283 |
+
diameter_input = gr.Slider(10, 100, value=20, step=5, label="Diameter (mm)")
|
| 284 |
+
|
| 285 |
+
generate_btn = gr.Button("Generate 3D Model", variant="primary")
|
| 286 |
+
|
| 287 |
+
with gr.Column():
|
| 288 |
+
model_plot = gr.Plot(label="3D Model")
|
| 289 |
+
model_specs = gr.Markdown(label="Specifications")
|
| 290 |
+
|
| 291 |
+
generate_btn.click(
|
| 292 |
+
generate_3d_model,
|
| 293 |
+
inputs=[component_type, teeth_input, module_input, length_input, diameter_input],
|
| 294 |
+
outputs=[model_plot, model_specs]
|
| 295 |
+
)
|
| 296 |
+
|
| 297 |
+
# Material Selector Tab
|
| 298 |
+
with gr.TabItem("π Material Selector"):
|
| 299 |
+
gr.Markdown("## Smart Material Selection")
|
| 300 |
+
|
| 301 |
+
with gr.Row():
|
| 302 |
+
with gr.Column():
|
| 303 |
+
min_strength = gr.Slider(0, 1000, value=200, label="Min Yield Strength (MPa)")
|
| 304 |
+
max_cost = gr.Slider(0, 50, value=10, label="Max Cost ($/kg)")
|
| 305 |
+
min_temp = gr.Slider(0, 1000, value=200, label="Min Temperature Limit (Β°C)")
|
| 306 |
+
|
| 307 |
+
select_btn = gr.Button("Find Materials", variant="primary")
|
| 308 |
+
|
| 309 |
+
with gr.Column():
|
| 310 |
+
selection_results = gr.Markdown(label="Recommended Materials")
|
| 311 |
+
selection_plot = gr.Plot(label="Material Comparison")
|
| 312 |
+
|
| 313 |
+
select_btn.click(
|
| 314 |
+
material_selector,
|
| 315 |
+
inputs=[min_strength, max_cost, min_temp],
|
| 316 |
+
outputs=[selection_results, selection_plot]
|
| 317 |
+
)
|
| 318 |
+
|
| 319 |
+
# FEA Analyzer Tab
|
| 320 |
+
with gr.TabItem("π FEA Analyzer"):
|
| 321 |
+
gr.Markdown("## Finite Element Analysis")
|
| 322 |
+
|
| 323 |
+
with gr.Row():
|
| 324 |
+
with gr.Column():
|
| 325 |
+
fea_material = gr.Dropdown(materials_db['Material'].tolist(),
|
| 326 |
+
label="Material", value="Steel 1045")
|
| 327 |
+
fea_force = gr.Number(value=1000, label="Applied Force (N)")
|
| 328 |
+
fea_area = gr.Number(value=100, label="Cross-sectional Area (mmΒ²)")
|
| 329 |
+
fea_length = gr.Number(value=1000, label="Component Length (mm)")
|
| 330 |
+
|
| 331 |
+
fea_btn = gr.Button("Run FEA Analysis", variant="primary")
|
| 332 |
+
|
| 333 |
+
with gr.Column():
|
| 334 |
+
fea_plot = gr.Plot(label="Stress Distribution")
|
| 335 |
+
fea_results = gr.Markdown(label="Analysis Results")
|
| 336 |
+
|
| 337 |
+
fea_btn.click(
|
| 338 |
+
perform_fea_analysis,
|
| 339 |
+
inputs=[fea_material, fea_force, fea_area, fea_length],
|
| 340 |
+
outputs=[fea_plot, fea_results]
|
| 341 |
+
)
|
| 342 |
+
|
| 343 |
+
# Gear Calculator Tab
|
| 344 |
+
with gr.TabItem("βοΈ Gear Calculator"):
|
| 345 |
+
gr.Markdown("## Gear Design Calculator")
|
| 346 |
+
|
| 347 |
+
with gr.Row():
|
| 348 |
+
with gr.Column():
|
| 349 |
+
gear_teeth = gr.Number(value=20, label="Number of Teeth")
|
| 350 |
+
gear_module = gr.Number(value=2, label="Module")
|
| 351 |
+
gear_power = gr.Number(value=10, label="Power (kW)")
|
| 352 |
+
gear_speed = gr.Number(value=1000, label="Speed (rpm)")
|
| 353 |
+
|
| 354 |
+
calc_btn = gr.Button("Calculate Gear Parameters", variant="primary")
|
| 355 |
+
|
| 356 |
+
with gr.Column():
|
| 357 |
+
gear_results = gr.Markdown(label="Gear Design Results")
|
| 358 |
+
|
| 359 |
+
calc_btn.click(
|
| 360 |
+
gear_calculator,
|
| 361 |
+
inputs=[gear_teeth, gear_module, gear_power, gear_speed],
|
| 362 |
+
outputs=[gear_results]
|
| 363 |
+
)
|
| 364 |
+
|
| 365 |
+
# AI Assistant Tab
|
| 366 |
+
with gr.TabItem("π¬ AI Assistant"):
|
| 367 |
+
gr.Markdown("## RAG AI Engineering Assistant")
|
| 368 |
+
|
| 369 |
+
with gr.Row():
|
| 370 |
+
with gr.Column():
|
| 371 |
+
user_query = gr.Textbox(label="Ask your engineering question:",
|
| 372 |
+
placeholder="e.g., How do I select materials for high-temperature applications?")
|
| 373 |
+
ask_btn = gr.Button("Ask AI", variant="primary")
|
| 374 |
+
|
| 375 |
+
gr.Markdown("### Quick Questions:")
|
| 376 |
+
with gr.Row():
|
| 377 |
+
material_btn = gr.Button("Material Selection")
|
| 378 |
+
design_btn = gr.Button("Design Tips")
|
| 379 |
+
stress_btn = gr.Button("Stress Analysis")
|
| 380 |
+
|
| 381 |
+
with gr.Column():
|
| 382 |
+
ai_response = gr.Markdown(label="AI Response")
|
| 383 |
+
|
| 384 |
+
ask_btn.click(get_ai_response, inputs=[user_query], outputs=[ai_response])
|
| 385 |
+
material_btn.click(lambda: get_ai_response("material selection"), outputs=[ai_response])
|
| 386 |
+
design_btn.click(lambda: get_ai_response("design optimization"), outputs=[ai_response])
|
| 387 |
+
stress_btn.click(lambda: get_ai_response("stress analysis"), outputs=[ai_response])
|
| 388 |
+
|
| 389 |
+
gr.Markdown("""
|
| 390 |
+
---
|
| 391 |
+
### π§ MechMind AI Assistant - Empowering Mechanical Engineers with AI
|
| 392 |
+
**Built with Gradio | Ready for Kaggle Deployment**
|
| 393 |
+
""")
|
| 394 |
+
|
| 395 |
+
return app
|
| 396 |
+
|
| 397 |
+
# Launch the application
|
| 398 |
+
if __name__ == "__main__":
|
| 399 |
+
app = create_interface()
|
| 400 |
+
|
| 401 |
+
# Kaggle-specific launch configuration
|
| 402 |
+
import os
|
| 403 |
+
|
| 404 |
+
# Check if running in Kaggle environment
|
| 405 |
+
if 'KAGGLE_KERNEL_RUN_TYPE' in os.environ:
|
| 406 |
+
print("π§ Detected Kaggle environment - launching locally")
|
| 407 |
+
print("π Access the app at: http://localhost:7860")
|
| 408 |
+
print("π‘ If running in Kaggle, the app will be available in the output cell")
|
| 409 |
+
app.launch(
|
| 410 |
+
share=False, # Disable share link in Kaggle
|
| 411 |
+
debug=False, # Disable debug mode
|
| 412 |
+
server_name="0.0.0.0", # Allow external access
|
| 413 |
+
server_port=7860, # Standard port
|
| 414 |
+
inbrowser=False, # Don't try to open browser
|
| 415 |
+
show_error=True, # Show errors in interface
|
| 416 |
+
quiet=False # Show startup messages
|
| 417 |
+
)
|
| 418 |
+
else:
|
| 419 |
+
# Try to launch with share for local development
|
| 420 |
+
try:
|
| 421 |
+
print("π Launching MechMind with public share link...")
|
| 422 |
+
app.launch(share=True, debug=False, server_name="0.0.0.0", server_port=7860)
|
| 423 |
+
except Exception as e:
|
| 424 |
+
print(f"β Share link creation failed: {e}")
|
| 425 |
+
print("π§ Launching locally instead...")
|
| 426 |
+
app.launch(
|
| 427 |
+
share=False,
|
| 428 |
+
debug=False,
|
| 429 |
+
server_name="0.0.0.0",
|
| 430 |
+
server_port=7860,
|
| 431 |
+
inbrowser=True
|
| 432 |
+
)
|