harishaseebat92 commited on
Commit
6a43f79
·
verified ·
1 Parent(s): cb7bd1e

uploaded gradio_app.py

Browse files
Files changed (1) hide show
  1. gradio_app.py +155 -0
gradio_app.py ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+ from matplotlib.animation import FuncAnimation
4
+ import tempfile
5
+ import gradio as gr
6
+
7
+ def solve_and_animate_2d(Lx: float,
8
+ Ly: float,
9
+ t_max: float,
10
+ Gamma: float = 0.1,
11
+ Nx: int = 50,
12
+ Ny: int = 50,
13
+ initial: str = "gaussian",
14
+ bc: str = "dirichlet",
15
+ frame_skip: int = 1):
16
+ """
17
+ Solve the 2D heat equation u_t = Gamma*(u_xx + u_yy) and return a GIF animation.
18
+ Initial conditions: {"gaussian", "random", "sinusoidal", "step"}
19
+ Boundary conditions: {"dirichlet", "neumann", "periodic"}
20
+ """
21
+ # Spatial grid
22
+ x = np.linspace(0, Lx, Nx)
23
+ y = np.linspace(0, Ly, Ny)
24
+ dx, dy = x[1] - x[0], y[1] - y[0]
25
+ if dx == 0 or dy == 0:
26
+ raise ValueError("Nx and Ny must be > 1.")
27
+
28
+ # Time stepping for stability
29
+ dt = 1.0 / (2 * Gamma * (1/dx**2 + 1/dy**2))
30
+ Nt = int(np.ceil(t_max / dt)) + 1
31
+ rx, ry = Gamma * dt / dx**2, Gamma * dt / dy**2
32
+
33
+ # Initial condition
34
+ X, Y = np.meshgrid(x, y, indexing='ij')
35
+ if initial == "gaussian":
36
+ u = np.exp(-(((X - Lx/2)**2 + (Y - Ly/2)**2) / (2*(Lx/10)**2)))
37
+ elif initial == "random":
38
+ u = np.random.rand(Nx, Ny)
39
+ elif initial == "sinusoidal":
40
+ kx, ky = 2 * np.pi / Lx, 2 * np.pi / Ly
41
+ u = np.sin(kx * X) * np.sin(ky * Y)
42
+ elif initial == "step":
43
+ u = np.where((X < Lx/2) & (Y < Ly/2), 1.0, 0.0)
44
+ else:
45
+ raise ValueError(f"Unknown initial condition: {initial}")
46
+
47
+ # Storage for solution
48
+ U = np.zeros((Nt, Nx, Ny))
49
+ U[0] = u.copy()
50
+
51
+ # Time-stepping loop
52
+ for n in range(1, Nt):
53
+ un = u.copy()
54
+ # Interior update
55
+ u[1:-1, 1:-1] = (
56
+ un[1:-1, 1:-1]
57
+ + rx * (un[2:, 1:-1] - 2 * un[1:-1, 1:-1] + un[:-2, 1:-1])
58
+ + ry * (un[1:-1, 2:] - 2 * un[1:-1, 1:-1] + un[1:-1, :-2])
59
+ )
60
+ # Boundary conditions
61
+ if bc == "dirichlet":
62
+ u[0, :] = u[-1, :] = u[:, 0] = u[:, -1] = 0.0
63
+ elif bc == "neumann":
64
+ u[0, :] = u[1, :]
65
+ u[-1, :] = u[-2, :]
66
+ u[:, 0] = u[:, 1]
67
+ u[:, -1] = u[:, -2]
68
+ elif bc == "periodic":
69
+ u[0, :] = un[-2, :]
70
+ u[-1, :] = un[1, :]
71
+ u[:, 0] = un[:, -2]
72
+ u[:, -1] = un[:, 1]
73
+ else:
74
+ raise ValueError(f"Unknown bc: {bc}")
75
+ U[n] = u.copy()
76
+
77
+ # Create animation with Matplotlib
78
+ fig, ax = plt.subplots()
79
+ im = ax.imshow(U[0].T, cmap='viridis', origin='lower', extent=[0, Lx, 0, Ly], vmin=U.min(), vmax=U.max())
80
+ ax.set_title(f"2D Heat Eq — init={initial}, bc={bc}, Gamma={Gamma:.2f}")
81
+ ax.set_xlabel("x")
82
+ ax.set_ylabel("y")
83
+ plt.colorbar(im, ax=ax, label="u")
84
+
85
+ # Animation update function
86
+ def update(frame):
87
+ im.set_data(U[frame].T)
88
+ return [im]
89
+
90
+ # Subsample frames
91
+ idx = list(range(0, Nt, frame_skip))
92
+ if idx[-1] != Nt - 1:
93
+ idx.append(Nt - 1)
94
+
95
+ # Generate animation
96
+ ani = FuncAnimation(fig, update, frames=idx, blit=True)
97
+
98
+ # Save as GIF
99
+ with tempfile.NamedTemporaryFile(suffix='.gif', delete=False) as tmpfile:
100
+ ani.save(tmpfile.name, writer='pillow', fps=30)
101
+ gif_path = tmpfile.name
102
+
103
+ plt.close(fig)
104
+ return gif_path
105
+
106
+ def gradio_interface(lx, ly, t_max, gamma, nx, ny, initial, bc, frame_skip):
107
+ nx, ny, frame_skip = int(nx), int(ny), int(frame_skip)
108
+ return solve_and_animate_2d(
109
+ Lx=lx, Ly=ly, t_max=t_max, Gamma=gamma, Nx=nx, Ny=ny,
110
+ initial=initial, bc=bc, frame_skip=frame_skip
111
+ )
112
+
113
+ with gr.Blocks(theme=gr.themes.Soft(), title="2D Heat Simulator") as demo:
114
+ gr.Markdown("# ♨️ 2D Heat Equation Simulator\nAdjust parameters and run the simulation.")
115
+ with gr.Row():
116
+ with gr.Column(scale=1):
117
+ gr.Markdown("## Domain & Grid")
118
+ lx_slider = gr.Slider(0.1, 5.0, 1.0, 0.1, label="Lx")
119
+ ly_slider = gr.Slider(0.1, 5.0, 1.0, 0.1, label="Ly")
120
+ nx_slider = gr.Slider(3, 200, 50, 1, label="Nx")
121
+ ny_slider = gr.Slider(3, 200, 50, 1, label="Ny")
122
+
123
+ gr.Markdown("## Simulation")
124
+ t_slider = gr.Slider(0.01, 5.0, 0.5, 0.01, label="t_max")
125
+ gamma_slider = gr.Slider(0.001, 1.0, 0.1, 0.001, label="Gamma")
126
+
127
+ gr.Markdown("## Conditions")
128
+ initial_dropdown = gr.Dropdown(
129
+ ["gaussian", "random", "sinusoidal", "step"], "gaussian", label="Initial"
130
+ )
131
+ bc_dropdown = gr.Dropdown(
132
+ ["dirichlet", "neumann", "periodic"], "dirichlet", label="Boundary"
133
+ )
134
+
135
+ gr.Markdown("## Animation")
136
+ frame_skip_slider = gr.Slider(1, 50, 5, 1, label="Frame Skip")
137
+ run_btn = gr.Button("Run Simulation", variant="primary")
138
+ with gr.Column(scale=3):
139
+ plot_output = gr.Image(label="Heatmap Animation")
140
+ inputs_list = [lx_slider, ly_slider, t_slider, gamma_slider,
141
+ nx_slider, ny_slider, initial_dropdown, bc_dropdown, frame_skip_slider]
142
+ run_btn.click(fn=gradio_interface, inputs=inputs_list, outputs=plot_output)
143
+ gr.Examples(
144
+ examples=[
145
+ [1.0, 1.0, 0.5, 0.1, 50, 50, "gaussian", "dirichlet", 5],
146
+ [2.0, 1.0, 1.0, 0.05, 60, 30, "sinusoidal", "periodic", 10],
147
+ [1.0, 1.0, 0.2, 0.2, 80, 80, "step", "neumann", 2],
148
+ ],
149
+ inputs=inputs_list,
150
+ outputs=[plot_output],
151
+ fn=gradio_interface
152
+ )
153
+
154
+ if __name__ == "__main__":
155
+ demo.launch()