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()