import gradio as gr import subprocess import numpy as np import pyvista as pv import matplotlib.pyplot as plt from ansys.mapdl.core import launch_mapdl from pycalculix import * # Simulation Workflow def simulation_workflow( use_case, simulator, thickness, length, width, hole_diameter, force, load ): print(f"Running simulation for use_case={use_case}, simulator={simulator}") # Generate APDL script based on user inputs if use_case == "plate": print("Generating APDL script for plate simulation...") apdl_script = f""" /PREP7 MP,EX,1,2E11 ! Elastic modulus MP,PRXY,1,0.3 ! Poisson's ratio BLOCK,0,{length},0,{width},0,{thickness} ! Main block geometry CYLIND,0,{hole_diameter / 2},0,0,{thickness} ! Circular hole geometry VSUB,ALL ! Subtract the hole from the block ET,1,SOLID185 ! Define element type as SOLID185 ESIZE,5 ! Mesh element size VMESH,ALL ! Mesh the entire volume NSEL,S,LOC,Z,0 ! Select bottom face nodes D,ALL,ALL ! Apply constraints on selected nodes NSEL,S,LOC,Z,{thickness} ! Select top face nodes F,ALL,FY,-{force} ! Apply vertical force /SOLU ANTYPE,STATIC ! Static structural analysis SOLVE /POST1 PRNSOL,S,EQV ! Print equivalent stress results PRNSOL,U,SUM ! Print total deformation results /EXIT """ elif use_case == "beam": print("Generating APDL script for beam simulation...") apdl_script = f""" /PREP7 MP,EX,1,2E11 ! Elastic modulus MP,PRXY,1,0.3 ! Poisson's ratio BLOCK,0,{length},0,{width},0,{thickness} ! Beam geometry ET,1,SOLID185 ! Define element type as SOLID185 ESIZE,5 ! Mesh element size VMESH,ALL ! Mesh the entire volume NSEL,S,LOC,X,0 ! Select nodes at one end of the beam D,ALL,ALL ! Apply fixed constraints on one end NSEL,S,LOC,X,{length} ! Select nodes at the other end F,ALL,FY,-{load} ! Apply uniform load /SOLU ANTYPE,STATIC ! Static structural analysis SOLVE /POST1 PRNSOL,S,EQV ! Print equivalent stress results PRNSOL,U,SUM ! Print total deformation results /EXIT """ else: print("Invalid use case selected.") return "Invalid use case selected.", None, None # Save APDL script with open("simulation_input.inp", "w") as file: file.write(apdl_script) print(f"APDL script saved at: simulation_input.inp") # Run the selected simulator if simulator == "PyCalculix": print("Running PyCalculix simulation...") model = Model("pycalculix_simulation") model.set_units("mm") part = Part("block", model) part.make_box(0, length, 0, width, 0, thickness) if use_case == "plate": part.cut_cylinder(0, hole_diameter / 2, 0, hole_diameter / 2, thickness) model.make_step_static(force if force else load) model.run() stress = model.results().max_stress() deformation = model.results().max_displacement() elif simulator == "ANSYS": print("Running ANSYS simulation...") mapdl = launch_mapdl() mapdl.input("simulation_input.inp") max_stress = mapdl.get_value("NODE", 0, "S", "EQV") deformation = mapdl.get_value("NODE", 0, "U", "SUM") mapdl.exit() stress, deformation = max_stress, deformation else: print("Invalid simulator selected.") return "Invalid simulator selected.", None, None print(f"Simulation results - Stress: {stress}, Deformation: {deformation}") # Visualize results (both 2D and 3D) print("Visualizing results...") fig, ax = plt.subplots() ax.bar(["Stress", "Deformation"], [stress, deformation], color=["red", "blue"]) ax.set_title(f"Results ({simulator})") plt.savefig("results_2d.png") plt.close(fig) # 3D Visualization mesh = pv.Box(bounds=(0, length, 0, width, 0, thickness)) plotter = pv.Plotter(off_screen=True) plotter.add_mesh(mesh, color="white", show_edges=True) plotter.screenshot("results_3d.png") return f"Stress: {stress:.2f} MPa, Deformation: {deformation:.2f} mm", "results_2d.png", "results_3d.png" # Visualize results (both 2D and 3D) print("Visualizing results...") fig, ax = plt.subplots() ax.bar(["Stress", "Deformation"], [stress, deformation], color=["red", "blue"]) ax.set_title(f"Results ({simulator})") plt.savefig("results_2d.png") plt.close(fig) # 3D Visualization mesh = pv.Box(bounds=(0, kwargs["length"], 0, kwargs["width"], 0, kwargs["thickness"])) plotter = pv.Plotter(off_screen=True) plotter.add_mesh(mesh, color="white", show_edges=True) plotter.screenshot("results_3d.png") return f"Stress: {stress:.2f} MPa, Deformation: {deformation:.2f} mm", "results_2d.png", "results_3d.png" # Define Gradio interface with Submit button with gr.Blocks() as demo: # Input components use_case = gr.Radio(["plate", "beam"], label="Select Use Case") simulator = gr.Dropdown(["PyCalculix", "ANSYS"], label="Select Simulator") thickness = gr.Slider(10, 50, step=1, label="Thickness (mm)") length = gr.Slider(100, 500, step=10, label="Length (mm)") width = gr.Slider(50, 200, step=10, label="Width (mm)") hole_diameter = gr.Slider(5, 25, step=1, label="Hole Diameter (mm)", value=5) force = gr.Slider(1000, 10000, step=500, label="Force (N)", value=5000) load = gr.Slider(1000, 20000, step=1000, label="Load (N)", value=5000) # Output components results_text = gr.Textbox(label="Simulation Results") results_2d = gr.Image(label="2D Results Visualization") results_3d = gr.Image(label="3D Results Visualization") # Submit button submit_button = gr.Button("Submit") # Link function to inputs and outputs submit_button.click( simulation_workflow, inputs=[use_case, simulator, thickness, length, width, hole_diameter, force, load], outputs=[results_text, results_2d, results_3d] ) # Define Gradio interface gr.Interface( fn=simulation_workflow, inputs=[ gr.Radio(["plate", "beam"], label="Select Use Case"), gr.Dropdown(["PyCalculix", "ANSYS"], label="Select Simulator"), gr.Slider(10, 50, step=1, label="Thickness (mm)"), gr.Slider(100, 500, step=10, label="Length (mm)"), gr.Slider(50, 200, step=10, label="Width (mm)"), gr.Slider(5, 25, step=1, label="Hole Diameter (mm)", value=5), # Default for Plate gr.Slider(1000, 10000, step=500, label="Force (N)", value=5000), # Default for Plate gr.Slider(1000, 20000, step=1000, label="Load (N)", value=5000) # Default for Beam ], outputs=[ gr.Textbox(label="Simulation Results"), gr.Image(label="2D Results Visualization"), gr.Image(label="3D Results Visualization") ], title="Unified Simulation Tool (PyCalculix and ANSYS)", live=True ).launch()