harishaseebat92 commited on
Commit
6c6dc22
·
verified ·
1 Parent(s): 3d367f2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +63 -145
app.py CHANGED
@@ -1,26 +1,26 @@
 
1
  import numpy as np
2
  import gradio as gr
3
- import plotly.graph_objects as go
4
 
5
- # --- 1. Simulation Core ---
6
- def solve_2d_heat_equation(Lx: float,
7
- Ly: float,
8
- t_max: float,
9
- Gamma: float = 0.1,
10
- Nx: int = 50,
11
- Ny: int = 50,
12
- initial: str = "gaussian",
13
- bc: str = "dirichlet"):
14
- # [Unchanged code from original]
15
  x = np.linspace(0, Lx, Nx)
16
  y = np.linspace(0, Ly, Ny)
17
  dx, dy = x[1] - x[0], y[1] - y[0]
18
- if dx == 0 or dy == 0:
19
- raise ValueError("Nx and Ny must be > 1.")
20
  dt = 0.9 / (2 * Gamma * (1/dx**2 + 1/dy**2))
21
  Nt = int(np.ceil(t_max / dt)) + 1
22
  rx, ry = Gamma * dt / dx**2, Gamma * dt / dy**2
 
 
23
  X, Y = np.meshgrid(x, y, indexing='ij')
 
24
  if initial == "gaussian":
25
  u = np.exp(-(((X - Lx/2)**2 + (Y - Ly/2)**2) / (2*(Lx/10)**2)))
26
  elif initial == "random":
@@ -30,10 +30,12 @@ def solve_2d_heat_equation(Lx: float,
30
  u = np.sin(kx * X) * np.sin(ky * Y)
31
  elif initial == "step":
32
  u = np.where((X < Lx/2) & (Y < Ly/2), 1.0, 0.0)
33
- else:
34
- raise ValueError(f"Unknown initial condition: {initial}")
35
  U = np.zeros((Nt, Nx, Ny))
36
  U[0] = u.copy()
 
 
37
  for n in range(1, Nt):
38
  un = u.copy()
39
  u[1:-1, 1:-1] = (
@@ -41,6 +43,7 @@ def solve_2d_heat_equation(Lx: float,
41
  + rx * (un[2:, 1:-1] - 2 * un[1:-1, 1:-1] + un[:-2, 1:-1])
42
  + ry * (un[1:-1, 2:] - 2 * un[1:-1, 1:-1] + un[1:-1, :-2])
43
  )
 
44
  if bc == "dirichlet":
45
  u[0, :] = u[-1, :] = u[:, 0] = u[:, -1] = 0.0
46
  elif bc == "neumann":
@@ -48,142 +51,57 @@ def solve_2d_heat_equation(Lx: float,
48
  u[-1, :] = u[-2, :]
49
  u[:, 0] = u[:, 1]
50
  u[:, -1] = u[:, -2]
51
- elif bc == "periodic":
52
- u[0, :] = un[-2, :]
53
- u[-1, :] = un[1, :]
54
- u[:, 0] = un[:, -2]
55
- u[:, -1] = un[:, 1]
56
- else:
57
- raise ValueError(f"Unknown bc: {bc}")
58
  U[n] = u.copy()
59
- return U, dt
 
 
60
 
61
- # --- 2. Plotly Animation Generator ---
62
- def create_plotly_animation(U, Lx, Ly, initial, bc, Gamma, frame_skip, dt):
63
- # [Unchanged code from original]
64
- Nt, Nx, Ny = U.shape
65
- vmin, vmax = U.min(), U.max()
66
- idx = list(range(0, Nt, frame_skip))
67
- if not idx or idx[-1] != Nt - 1:
68
- idx.append(Nt - 1)
69
- frames_to_animate_data = U[idx]
70
- fig = go.Figure(
71
- frames=[go.Frame(data=go.Heatmap(z=frame_data.T, zmin=vmin, zmax=vmax), name=str(i))
72
- for i, frame_data in enumerate(frames_to_animate_data)]
73
- )
74
- fig.add_trace(go.Heatmap(
75
- z=frames_to_animate_data[0].T,
76
- colorscale='viridis',
77
- zmin=vmin,
78
- zmax=vmax,
79
- colorbar=dict(title="u")
80
- ))
81
- fig.update_layout(
82
- updatemenus=[dict(
83
- type="buttons",
84
- direction="left",
85
- x=0.1,
86
- xanchor="left",
87
- y=1.15,
88
- yanchor="top",
89
- buttons=[dict(label="Play",
90
- method="animate",
91
- args=[None, {"frame": {"duration": 50, "redraw": True},
92
- "fromcurrent": True, "transition": {"duration": 0}}]),
93
- dict(label="Pause",
94
- method="animate",
95
- args=[[None], {"frame": {"duration": 0, "redraw": False},
96
- "mode": "immediate", "transition": {"duration": 0}}])]
97
- )]
98
  )
99
- sliders = [dict(
100
- active=0,
101
- yanchor="top",
102
- xanchor="left",
103
- currentvalue=dict(
104
- font=dict(size=16),
105
- prefix="Time: ",
106
- visible=True,
107
- xanchor="right"
108
- ),
109
- pad=dict(b=10, t=50),
110
- len=0.9,
111
- x=0.1,
112
- y=0,
113
- steps=[dict(
114
- args=[[f.name], {"frame": {"duration": 0, "redraw": True},
115
- "mode": "immediate",
116
- "transition": {"duration": 0}}],
117
- label=f"{idx[i]*dt:.2f}s",
118
- method="animate")
119
- for i, f in enumerate(fig.frames)]
120
- )]
121
- fig.update_layout(
122
- title=f"2D Heat Eq — init={initial}, bc={bc}, Gamma={Gamma:.2f}",
123
- xaxis_title="x",
124
- yaxis_title="y",
125
- sliders=sliders,
126
- yaxis=dict(scaleanchor="x", scaleratio=Ly/Lx if Lx > 0 else 1)
127
- )
128
- return fig
129
-
130
- # --- 3. Gradio Interface Logic ---
131
- def gradio_interface(lx, ly, t_max, gamma, nx, ny, initial, bc, frame_skip):
132
- """Main function for the Gradio interface."""
133
- nx, ny, frame_skip = int(nx), int(ny), int(frame_skip)
134
- try:
135
- U, dt = solve_2d_heat_equation(
136
- Lx=lx, Ly=ly, t_max=t_max, Gamma=gamma, Nx=nx, Ny=ny,
137
- initial=initial, bc=bc
138
- )
139
- fig = create_plotly_animation(
140
- U=U, Lx=lx, Ly=ly, initial=initial, bc=bc, Gamma=gamma,
141
- frame_skip=frame_skip, dt=dt
142
- )
143
- return fig
144
- except Exception as e:
145
- print(f"Error in simulation: {e}")
146
- return None
147
 
148
- # --- 4. Gradio UI Layout ---
149
- with gr.Blocks(theme=gr.themes.Soft(), title="2D Heat Simulator") as demo:
150
- gr.Markdown("# ♨️ Interactive 2D Heat Equation Simulator\nAdjust parameters and run the simulation.")
151
- with gr.Row():
152
- with gr.Column(scale=1):
153
- gr.Markdown("## Domain & Grid")
154
- lx_slider = gr.Slider(0.1, 5.0, 1.0, 0.1, label="Lx")
155
- ly_slider = gr.Slider(0.1, 5.0, 1.0, 0.1, label="Ly")
156
- nx_slider = gr.Slider(3, 200, 50, 1, label="Nx")
157
- ny_slider = gr.Slider(3, 200, 50, 1, label="Ny")
158
- gr.Markdown("## Simulation")
159
- t_slider = gr.Slider(0.01, 5.0, 0.5, 0.01, label="t_max")
160
- gamma_slider = gr.Slider(0.001, 1.0, 0.1, 0.001, label="Gamma")
161
- gr.Markdown("## Conditions")
162
- initial_dropdown = gr.Dropdown(
163
- ["gaussian", "random", "sinusoidal", "step"], "gaussian", label="Initial"
164
- )
165
- bc_dropdown = gr.Dropdown(
166
- ["dirichlet", "neumann", "periodic"], "dirichlet", label="Boundary"
167
- )
168
- gr.Markdown("## Animation")
169
- frame_skip_slider = gr.Slider(1, 50, 5, 1, label="Frame Skip")
170
- run_btn = gr.Button("Run Simulation", variant="primary")
171
- with gr.Column(scale=3):
172
- gr.Markdown("### Interactive Heatmap Animation\nUse the play/pause buttons, drag the slider, or use your mouse/trackpad to zoom and pan the plot.")
173
- plot_output = gr.Plot(label="Interactive Heatmap")
174
- inputs_list = [lx_slider, ly_slider, t_slider, gamma_slider,
175
- nx_slider, ny_slider, initial_dropdown, bc_dropdown, frame_skip_slider]
176
- run_btn.click(fn=gradio_interface, inputs=inputs_list, outputs=plot_output)
177
- gr.Examples(
178
- examples=[
179
- [1.0, 1.0, 0.5, 0.1, 50, 50, "gaussian", "dirichlet", 5],
180
- [2.0, 1.0, 1.0, 0.05, 60, 30, "sinusoidal", "periodic", 10],
181
- [1.0, 1.0, 0.2, 0.2, 80, 80, "step", "neumann", 2],
182
  ],
183
- inputs=inputs_list,
184
- outputs=[plot_output],
185
- fn=gradio_interface
186
  )
187
 
188
  if __name__ == "__main__":
 
189
  demo.launch()
 
1
+ # app.py
2
  import numpy as np
3
  import gradio as gr
 
4
 
5
+ # --- Simulation Core (No changes needed here) ---
6
+ def solve_2d_heat_equation(Lx, Ly, t_max, Gamma, Nx, Ny, initial, bc):
7
+ """
8
+ Solves the 2D heat equation and returns the data and time step.
9
+ (This function is the same as in your original code)
10
+ """
11
+ # Spatial grid
 
 
 
12
  x = np.linspace(0, Lx, Nx)
13
  y = np.linspace(0, Ly, Ny)
14
  dx, dy = x[1] - x[0], y[1] - y[0]
15
+
16
+ # Time stepping for stability
17
  dt = 0.9 / (2 * Gamma * (1/dx**2 + 1/dy**2))
18
  Nt = int(np.ceil(t_max / dt)) + 1
19
  rx, ry = Gamma * dt / dx**2, Gamma * dt / dy**2
20
+
21
+ # Initial condition
22
  X, Y = np.meshgrid(x, y, indexing='ij')
23
+ u = np.zeros((Nx, Ny))
24
  if initial == "gaussian":
25
  u = np.exp(-(((X - Lx/2)**2 + (Y - Ly/2)**2) / (2*(Lx/10)**2)))
26
  elif initial == "random":
 
30
  u = np.sin(kx * X) * np.sin(ky * Y)
31
  elif initial == "step":
32
  u = np.where((X < Lx/2) & (Y < Ly/2), 1.0, 0.0)
33
+
34
+ # Storage for solution
35
  U = np.zeros((Nt, Nx, Ny))
36
  U[0] = u.copy()
37
+
38
+ # Time-stepping loop
39
  for n in range(1, Nt):
40
  un = u.copy()
41
  u[1:-1, 1:-1] = (
 
43
  + rx * (un[2:, 1:-1] - 2 * un[1:-1, 1:-1] + un[:-2, 1:-1])
44
  + ry * (un[1:-1, 2:] - 2 * un[1:-1, 1:-1] + un[1:-1, :-2])
45
  )
46
+ # Boundary conditions (simplified for brevity)
47
  if bc == "dirichlet":
48
  u[0, :] = u[-1, :] = u[:, 0] = u[:, -1] = 0.0
49
  elif bc == "neumann":
 
51
  u[-1, :] = u[-2, :]
52
  u[:, 0] = u[:, 1]
53
  u[:, -1] = u[:, -2]
 
 
 
 
 
 
 
54
  U[n] = u.copy()
55
+
56
+ # Return raw data - convert numpy arrays to lists for JSON compatibility
57
+ return U.tolist(), dt
58
 
59
+ # --- Gradio API Function ---
60
+ def run_simulation_api(lx, ly, t_max, gamma, nx, ny, initial, bc):
61
+ """
62
+ API function that runs the simulation and returns data as a dictionary.
63
+ """
64
+ U, dt = solve_2d_heat_equation(
65
+ Lx=lx, Ly=ly, t_max=t_max, Gamma=gamma, Nx=int(nx), Ny=int(ny),
66
+ initial=initial, bc=bc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  )
68
+
69
+ # Return data in a format that's easy to use in JavaScript
70
+ return {
71
+ "simulation_data": U,
72
+ "time_step": dt,
73
+ "domain": {"Lx": lx, "Ly": ly},
74
+ "params": {"initial": initial, "bc": bc, "gamma": gamma}
75
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
+ # --- Gradio Interface (API only) ---
78
+ with gr.Blocks(title="2D Heat Simulator API") as demo:
79
+ # We define the inputs for the API
80
+ lx_slider = gr.Slider(0.1, 5.0, 1.0, label="Lx")
81
+ ly_slider = gr.Slider(0.1, 5.0, 1.0, label="Ly")
82
+ nx_slider = gr.Slider(3, 200, 50, label="Nx")
83
+ ny_slider = gr.Slider(3, 200, 50, label="Ny")
84
+ t_slider = gr.Slider(0.01, 5.0, 0.5, label="t_max")
85
+ gamma_slider = gr.Slider(0.001, 1.0, 0.1, label="Gamma")
86
+ initial_dropdown = gr.Dropdown(["gaussian", "random", "sinusoidal", "step"], value="gaussian", label="Initial")
87
+ bc_dropdown = gr.Dropdown(["dirichlet", "neumann"], value="dirichlet", label="Boundary")
88
+
89
+ # We only need a JSON output component for the API
90
+ output_json = gr.JSON(label="Simulation Output")
91
+
92
+ # This is the crucial part: we create a hidden button to host our API endpoint
93
+ api_btn = gr.Button("Run Simulation")
94
+
95
+ api_btn.click(
96
+ fn=run_simulation_api,
97
+ inputs=[
98
+ lx_slider, ly_slider, t_slider, gamma_slider,
99
+ nx_slider, ny_slider, initial_dropdown, bc_dropdown
 
 
 
 
 
 
 
 
 
 
 
100
  ],
101
+ outputs=output_json,
102
+ api_name="run_simulation" # This makes it available at /run/run_simulation
 
103
  )
104
 
105
  if __name__ == "__main__":
106
+ # Launch the Gradio app
107
  demo.launch()