Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import datetime | |
| import re | |
| import joblib | |
| # Load the trained pipeline | |
| model = joblib.load("gradient_boosting_model.pkl") | |
| ERROR_LABELS = { | |
| "UnderConstrained": "1) Under-constrained / rigid-body", | |
| "MeshQuality": "2) Bad mesh / distortion", | |
| "ContactFailure": "3) Contact issues", | |
| "MaterialError": "4) Material / units issues", | |
| "other_or_unknown": "Other / unknown" | |
| } | |
| GLOSSARY = { | |
| "rigid body motion": "Movement of an entire structure without deformation, often caused by missing constraints.", | |
| "jacobian": "A matrix used to calculate element distortion during deformation; bad values mean mesh issues.", | |
| "newton-raphson": "A nonlinear solution method sensitive to poor contact setup or load step configuration.", | |
| "initial penetration": "When contact surfaces start interpenetrated, often due to bad geometry or setup.", | |
| "divergence": "The solver cannot find a converging solution, often caused by too-large load steps or unstable models.", | |
| "singular matrix": "Solver can't invert the stiffness matrix, often caused by unconstrained parts.", | |
| "degrees of freedom": "Independent movements allowed for a part (translation/rotation in X, Y, Z directions)." | |
| } | |
| EXPLANATIONS = { | |
| "UnderConstrained": ( | |
| "Your model appears under-constrained. The solver detected rigid-body motion or insufficient constraints.", | |
| "- Check if all bodies have proper supports.\n- Ensure key DOFs are restrained.\n- Avoid soft supports that only partially constrain motion.\n"), | |
| "MeshQuality": ( | |
| "Your mesh likely has poor quality or distortion. This causes inaccurate results or solver failure.", | |
| "- Refine the mesh near stress concentrations.\n- Improve skewed or stretched elements.\n- Use proper element types for geometry.\n"), | |
| "ContactFailure": ( | |
| "Contact elements may be missing or misconfigured. The solver can't resolve interactions between parts.", | |
| "- Check that all contacts are correctly defined.\n- Consider using bonded contact instead of frictionless.\n- Inspect contact surfaces and face orientation.\n"), | |
| "MaterialError": ( | |
| "Material data or units are inconsistent. Properties like Young’s modulus or density may be off by scale.", | |
| "- Verify if Young’s modulus is in MPa or Pa.\n- Check that material density makes sense (e.g. kg/m³).\n- Look at plastic strain curve units if applicable.\n"), | |
| "other_or_unknown": ( | |
| "I couldn't confidently match this log to a known error category.", | |
| "- Try checking boundary conditions, contact, and mesh. Rerun with more detailed solver output enabled.\n") | |
| } | |
| def classify_and_explain(log_text): | |
| if not log_text.strip(): | |
| return ("No log detected", "Paste an ANSYS solver output to analyze.", log_text, "", None) | |
| pred = model.predict([log_text])[0] | |
| label = ERROR_LABELS.get(pred, "Other / unknown") | |
| explanation, troubleshooting = EXPLANATIONS.get(pred, EXPLANATIONS["other_or_unknown"]) | |
| highlighted = re.sub( | |
| r"(?i)\b(" + "|".join(re.escape(k) for k in GLOSSARY) + r")\b", | |
| lambda m: f"**{m.group(1)}** 🛈", | |
| log_text, | |
| ) | |
| found_terms = [term for term in GLOSSARY if term in log_text.lower()] | |
| glossary_text = "\n\n".join(f"**{term.title()}**: {GLOSSARY[term]}" for term in found_terms) | |
| return label, f"### Explanation\n{explanation}\n\n### Troubleshooting\n{troubleshooting}", highlighted, glossary_text, pred | |
| def export_report(log_text, category, explanation): | |
| if not log_text or not category: | |
| return None, "⚠️ Please run analysis before exporting." | |
| timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") | |
| filename = f"/tmp/ansys_debug_report_{timestamp}.txt" | |
| try: | |
| with open(filename, "w", encoding="utf-8") as f: | |
| f.write("ANSYS Solver Debug Report\n") | |
| f.write("=" * 30 + "\n") | |
| f.write(f"Category: {category}\n\n") | |
| f.write("Explanation:\n") | |
| f.write(explanation + "\n\n") | |
| f.write("Original Log:\n") | |
| f.write(log_text + "\n") | |
| return filename, "✅ Report exported successfully." | |
| except Exception as e: | |
| return None, f"❌ Export failed: {str(e)}" | |
| with gr.Blocks(title="ANSYS Structural Solver Debugger — ML Edition") as demo: | |
| gr.Markdown("# 🧠 ANSYS Structural Solver Debugger — ML Edition") | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| log_input = gr.Textbox(label="Paste ANSYS Solver Output", lines=20) | |
| analyze_btn = gr.Button("🔍 Analyze Log") | |
| export_btn = gr.Button("📁 Export Report") | |
| export_status = gr.Textbox(label="Export Status", interactive=False) | |
| report_file = gr.File(label="Download Report") | |
| with gr.Column(scale=3): | |
| category_out = gr.Textbox(label="Detected Error Type", interactive=False) | |
| explanation_out = gr.Markdown() | |
| highlighted_out = gr.Markdown(label="🔍 Highlighted Log") | |
| glossary_box = gr.Markdown(label="📘 Glossary Definitions") | |
| analyze_btn.click(classify_and_explain, inputs=[log_input], outputs=[category_out, explanation_out, highlighted_out, glossary_box]) | |
| export_btn.click(export_report, inputs=[log_input, category_out, explanation_out], outputs=[report_file, export_status]) | |
| demo.launch() | |