harishaseebat92 commited on
Commit
f7421d8
·
verified ·
1 Parent(s): 3184505

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -63
app.py CHANGED
@@ -6,69 +6,71 @@ import gradio as gr
6
  import plotly.graph_objects as go
7
 
8
  # --- Simulation Core ---
9
- def solve_2d_heat_equation(Lx: float,
10
- Ly: float,
11
- t_max: float,
12
- Gamma: float = 0.1,
13
- Nx: int = 50,
14
- Ny: int = 50,
15
- initial: str = "gaussian",
16
- bc: str = "dirichlet"):
17
  """
18
- Solve the 2D heat equation u_t = Gamma*(u_xx + u_yy) and return the solution array U and time step dt.
19
  """
20
  # Spatial grid
21
  x = np.linspace(0, Lx, Nx)
22
  y = np.linspace(0, Ly, Ny)
23
- dx, dy = x[1] - x[0], y[1] - y[0]
24
- if dx == 0 or dy == 0:
25
- raise ValueError("Nx and Ny must be > 1.")
 
26
 
27
  # Time stepping for stability
28
- dt = 1.0 / (2 * Gamma * (1/dx**2 + 1/dy**2))
29
  Nt = int(np.ceil(t_max / dt)) + 1
30
- rx, ry = Gamma * dt / dx**2, Gamma * dt / dy**2
31
 
32
  # Initial condition
33
- X, Y = np.meshgrid(x, y, indexing='ij')
34
  if initial == "gaussian":
35
- u = np.exp(-(((X - Lx/2)**2 + (Y - Ly/2)**2) / (2*(Lx/10)**2)))
36
  elif initial == "random":
37
- u = np.random.rand(Nx, Ny)
38
  elif initial == "sinusoidal":
39
- kx, ky = 2 * np.pi / Lx, 2 * np.pi / Ly
40
- u = np.sin(kx * X) * np.sin(ky * Y)
41
  elif initial == "step":
42
- u = np.where((X < Lx/2) & (Y < Ly/2), 1.0, 0.0)
43
  else:
44
  raise ValueError(f"Unknown initial condition: {initial}")
45
 
46
  # Storage for solution
47
- U = np.zeros((Nt, Nx, Ny))
48
  U[0] = u.copy()
49
 
50
  # Time-stepping loop
51
  for n in range(1, Nt):
52
  un = u.copy()
53
  # Interior update
54
- u[1:-1, 1:-1] = (
55
- un[1:-1, 1:-1]
56
- + rx * (un[2:, 1:-1] - 2 * un[1:-1, 1:-1] + un[:-2, 1:-1])
57
- + ry * (un[1:-1, 2:] - 2 * un[1:-1, 1:-1] + un[1:-1, :-2])
 
58
  )
59
  # Boundary conditions
60
  if bc == "dirichlet":
61
- u[0, :] = u[-1, :] = u[:, 0] = u[:, -1] = 0.0
62
  elif bc == "neumann":
63
- u[0, :] = u[1, :]
64
- u[-1, :] = u[-2, :]
65
- u[:, 0] = u[:, 1]
66
- u[:, -1] = u[:, -2]
 
 
67
  elif bc == "periodic":
68
- u[0, :] = un[-2, :]
69
- u[-1, :] = un[1, :]
70
- u[:, 0] = un[:, -2]
71
- u[:, -1] = un[:, 1]
 
 
72
  else:
73
  raise ValueError(f"Unknown bc: {bc}")
74
  U[n] = u.copy()
@@ -76,22 +78,22 @@ def solve_2d_heat_equation(Lx: float,
76
  return U, dt
77
 
78
  # --- Animation Generator ---
79
- def create_animation_gif(U, Lx, Ly, initial, bc, Gamma, frame_skip, dt):
80
  """
81
- Create and save a GIF animation from the solution array U.
82
  """
83
- Nt, Nx, Ny = U.shape
84
  fig, ax = plt.subplots()
85
  x = np.linspace(0, Lx, Nx)
86
  y = np.linspace(0, Ly, Ny)
87
- im = ax.imshow(U[0].T, cmap='viridis', origin='lower', extent=[0, Lx, 0, Ly], vmin=U.min(), vmax=U.max())
88
- ax.set_title(f"2D Heat Eq — init={initial}, bc={bc}, Gamma={Gamma:.2f}")
89
  ax.set_xlabel("x")
90
  ax.set_ylabel("y")
91
  plt.colorbar(im, ax=ax, label="u")
92
 
93
  def update(frame):
94
- im.set_data(U[frame].T)
95
  return [im]
96
 
97
  idx = list(range(0, Nt, frame_skip))
@@ -108,33 +110,34 @@ def create_animation_gif(U, Lx, Ly, initial, bc, Gamma, frame_skip, dt):
108
  return gif_path
109
 
110
  # --- Plotly Figure Generator ---
111
- def create_plotly_figure(u, Lx, Ly, time_label):
112
  """
113
- Create an interactive Plotly heatmap for a given time slice u.
114
  """
115
  x = np.linspace(0, Lx, u.shape[0])
116
  y = np.linspace(0, Ly, u.shape[1])
117
  fig = go.Figure(data=go.Heatmap(
118
- z=u.T,
119
  x=x,
120
  y=y,
121
  colorscale='viridis'
122
  ))
123
  fig.update_layout(
124
- title=f"Heat Distribution at t={time_label}",
125
  xaxis_title='x',
126
  yaxis_title='y'
127
  )
128
  return fig
129
 
130
- # --- Gradio Interface Logic ---
131
- def gradio_interface(lx, ly, t_max, gamma, nx, ny, initial, bc, frame_skip):
132
- nx, ny, frame_skip = int(nx), int(ny), int(frame_skip)
133
- U, dt = solve_2d_heat_equation(
134
- Lx=lx, Ly=ly, t_max=t_max, Gamma=gamma, Nx=nx, Ny=ny,
135
  initial=initial, bc=bc
136
  )
137
  Nt = U.shape[0]
 
 
138
  # Compute indices for t=0, t/4, 3t/4, t
139
  idx0 = 0
140
  idx1 = round((Nt - 1) / 4)
@@ -145,25 +148,32 @@ def gradio_interface(lx, ly, t_max, gamma, nx, ny, initial, bc, frame_skip):
145
  u1 = U[idx1]
146
  u2 = U[idx2]
147
  u3 = U[idx3]
148
- # Create Plotly figures
149
- fig0 = create_plotly_figure(u0, lx, ly, "0")
150
- fig1 = create_plotly_figure(u1, lx, ly, f"{idx1*dt:.2f}")
151
- fig2 = create_plotly_figure(u2, lx, ly, f"{idx2*dt:.2f}")
152
- fig3 = create_plotly_figure(u3, lx, ly, f"{idx3*dt:.2f}")
153
- # Create GIF
154
- gif_path = create_animation_gif(U, lx, ly, initial, bc, gamma, frame_skip, dt)
155
  return gif_path, fig0, fig1, fig2, fig3
156
 
 
 
 
 
 
157
  # --- Gradio UI Layout ---
158
- with gr.Blocks(theme=gr.themes.Soft(), title="2D Heat Simulator") as demo:
159
- gr.Markdown("# ♨️ 2D Heat Equation Simulator\nAdjust parameters and run the simulation.")
160
  with gr.Row():
161
  with gr.Column(scale=1):
162
  gr.Markdown("## Domain & Grid")
163
  lx_slider = gr.Slider(0.1, 5.0, 1.0, 0.1, label="Lx")
164
  ly_slider = gr.Slider(0.1, 5.0, 1.0, 0.1, label="Ly")
 
165
  nx_slider = gr.Slider(3, 200, 50, 1, label="Nx")
166
  ny_slider = gr.Slider(3, 200, 50, 1, label="Ny")
 
167
 
168
  gr.Markdown("## Simulation")
169
  t_slider = gr.Slider(0.01, 5.0, 0.5, 0.01, label="t_max")
@@ -179,6 +189,8 @@ with gr.Blocks(theme=gr.themes.Soft(), title="2D Heat Simulator") as demo:
179
 
180
  gr.Markdown("## Animation")
181
  frame_skip_slider = gr.Slider(1, 50, 5, 1, label="Frame Skip")
 
 
182
  run_btn = gr.Button("Run Simulation", variant="primary")
183
  with gr.Column(scale=3):
184
  gif_output = gr.Image(label="Animation")
@@ -188,15 +200,15 @@ with gr.Blocks(theme=gr.themes.Soft(), title="2D Heat Simulator") as demo:
188
  with gr.Row():
189
  plot3 = gr.Plot(label="t=3t/4")
190
  plot4 = gr.Plot(label="t=t")
191
- inputs_list = [lx_slider, ly_slider, t_slider, gamma_slider,
192
- nx_slider, ny_slider, initial_dropdown, bc_dropdown, frame_skip_slider]
193
  outputs_list = [gif_output, plot1, plot2, plot3, plot4]
194
  run_btn.click(fn=gradio_interface, inputs=inputs_list, outputs=outputs_list)
195
  gr.Examples(
196
  examples=[
197
- [1.0, 1.0, 0.5, 0.1, 50, 50, "gaussian", "dirichlet", 5],
198
- [2.0, 1.0, 1.0, 0.05, 60, 30, "sinusoidal", "periodic", 10],
199
- [1.0, 1.0, 0.2, 0.2, 80, 80, "step", "neumann", 2],
200
  ],
201
  inputs=inputs_list,
202
  outputs=outputs_list,
 
6
  import plotly.graph_objects as go
7
 
8
  # --- Simulation Core ---
9
+ def solve_3d_heat_equation(Lx: float, Ly: float, Lz: float,
10
+ t_max: float, Gamma: float = 0.1,
11
+ Nx: int = 50, Ny: int = 50, Nz: int = 50,
12
+ initial: str = "gaussian", bc: str = "dirichlet"):
 
 
 
 
13
  """
14
+ Solve the 3D heat equation u_t = Gamma*(u_xx + u_yy + u_zz) and return the solution array U and time step dt.
15
  """
16
  # Spatial grid
17
  x = np.linspace(0, Lx, Nx)
18
  y = np.linspace(0, Ly, Ny)
19
+ z = np.linspace(0, Lz, Nz)
20
+ dx, dy, dz = x[1] - x[0], y[1] - y[0], z[1] - z[0]
21
+ if dx <= 0 or dy <= 0 or dz <= 0:
22
+ raise ValueError("Nx, Ny, and Nz must be > 1.")
23
 
24
  # Time stepping for stability
25
+ dt = 1.0 / (2 * Gamma * (1/dx**2 + 1/dy**2 + 1/dz**2))
26
  Nt = int(np.ceil(t_max / dt)) + 1
27
+ rx, ry, rz = Gamma * dt / dx**2, Gamma * dt / dy**2, Gamma * dt / dz**2
28
 
29
  # Initial condition
30
+ X, Y, Z = np.meshgrid(x, y, z, indexing='ij')
31
  if initial == "gaussian":
32
+ u = np.exp(-((X - Lx/2)**2 / (2*(Lx/10)**2) + (Y - Ly/2)**2 / (2*(Ly/10)**2) + (Z - Lz/2)**2 / (2*(Lz/10)**2)))
33
  elif initial == "random":
34
+ u = np.random.rand(Nx, Ny, Nz)
35
  elif initial == "sinusoidal":
36
+ kx, ky, kz = 2 * np.pi / Lx, 2 * np.pi / Ly, 2 * np.pi / Lz
37
+ u = np.sin(kx * X) * np.sin(ky * Y) * np.sin(kz * Z)
38
  elif initial == "step":
39
+ u = np.where((X < Lx/2) & (Y < Ly/2) & (Z < Lz/2), 1.0, 0.0)
40
  else:
41
  raise ValueError(f"Unknown initial condition: {initial}")
42
 
43
  # Storage for solution
44
+ U = np.zeros((Nt, Nx, Ny, Nz))
45
  U[0] = u.copy()
46
 
47
  # Time-stepping loop
48
  for n in range(1, Nt):
49
  un = u.copy()
50
  # Interior update
51
+ u[1:-1, 1:-1, 1:-1] = (
52
+ un[1:-1, 1:-1, 1:-1]
53
+ + rx * (un[2:, 1:-1, 1:-1] - 2 * un[1:-1, 1:-1, 1:-1] + un[:-2, 1:-1, 1:-1])
54
+ + ry * (un[1:-1, 2:, 1:-1] - 2 * un[1:-1, 1:-1, 1:-1] + un[1:-1, :-2, 1:-1])
55
+ + rz * (un[1:-1, 1:-1, 2:] - 2 * un[1:-1, 1:-1, 1:-1] + un[1:-1, 1:-1, :-2])
56
  )
57
  # Boundary conditions
58
  if bc == "dirichlet":
59
+ u[0, :, :] = u[-1, :, :] = u[:, 0, :] = u[:, -1, :] = u[:, :, 0] = u[:, :, -1] = 0.0
60
  elif bc == "neumann":
61
+ u[0, :, :] = u[1, :, :]
62
+ u[-1, :, :] = u[-2, :, :]
63
+ u[:, 0, :] = u[:, 1, :]
64
+ u[:, -1, :] = u[:, -2, :]
65
+ u[:, :, 0] = u[:, :, 1]
66
+ u[:, :, -1] = u[:, :, -2]
67
  elif bc == "periodic":
68
+ u[0, :, :] = un[-2, :, :]
69
+ u[-1, :, :] = un[1, :, :]
70
+ u[:, 0, :] = un[:, -2, :]
71
+ u[:, -1, :] = un[:, 1, :]
72
+ u[:, :, 0] = un[:, :, -2]
73
+ u[:, :, -1] = un[:, :, 1]
74
  else:
75
  raise ValueError(f"Unknown bc: {bc}")
76
  U[n] = u.copy()
 
78
  return U, dt
79
 
80
  # --- Animation Generator ---
81
+ def create_animation_gif(U, Lx, Ly, Lz, initial, bc, Gamma, frame_skip, dt, z_slice):
82
  """
83
+ Create and save a GIF animation from the 3D solution array U at a fixed z-slice.
84
  """
85
+ Nt, Nx, Ny, Nz = U.shape
86
  fig, ax = plt.subplots()
87
  x = np.linspace(0, Lx, Nx)
88
  y = np.linspace(0, Ly, Ny)
89
+ im = ax.imshow(U[0, :, :, z_slice].T, cmap='viridis', origin='lower', extent=[0, Lx, 0, Ly], vmin=U.min(), vmax=U.max())
90
+ ax.set_title(f"2D Slice at z={z_slice} — init={initial}, bc={bc}, Gamma={Gamma:.2f}")
91
  ax.set_xlabel("x")
92
  ax.set_ylabel("y")
93
  plt.colorbar(im, ax=ax, label="u")
94
 
95
  def update(frame):
96
+ im.set_data(U[frame, :, :, z_slice].T)
97
  return [im]
98
 
99
  idx = list(range(0, Nt, frame_skip))
 
110
  return gif_path
111
 
112
  # --- Plotly Figure Generator ---
113
+ def create_plotly_figure(u, Lx, Ly, Lz, time_label, z_slice):
114
  """
115
+ Create an interactive Plotly heatmap for a given time slice u at a fixed z-slice.
116
  """
117
  x = np.linspace(0, Lx, u.shape[0])
118
  y = np.linspace(0, Ly, u.shape[1])
119
  fig = go.Figure(data=go.Heatmap(
120
+ z=u[:, :, z_slice].T,
121
  x=x,
122
  y=y,
123
  colorscale='viridis'
124
  ))
125
  fig.update_layout(
126
+ title=f"Heat Distribution at t={time_label}, z={z_slice}",
127
  xaxis_title='x',
128
  yaxis_title='y'
129
  )
130
  return fig
131
 
132
+ # --- Simulation Runner ---
133
+ def run_simulation(lx, ly, lz, t_max, gamma, nx, ny, nz, initial, bc, frame_skip, z_slice_percent):
134
+ U, dt = solve_3d_heat_equation(
135
+ Lx=lx, Ly=ly, Lz=lz, t_max=t_max, Gamma=gamma, Nx=nx, Ny=ny, Nz=nz,
 
136
  initial=initial, bc=bc
137
  )
138
  Nt = U.shape[0]
139
+ # Compute z_slice from percentage
140
+ z_slice = int((z_slice_percent / 100) * (nz - 1))
141
  # Compute indices for t=0, t/4, 3t/4, t
142
  idx0 = 0
143
  idx1 = round((Nt - 1) / 4)
 
148
  u1 = U[idx1]
149
  u2 = U[idx2]
150
  u3 = U[idx3]
151
+ # Create Plotly figures for the z_slice
152
+ fig0 = create_plotly_figure(u0, lx, ly, lz, "0", z_slice)
153
+ fig1 = create_plotly_figure(u1, lx, ly, lz, f"{idx1*dt:.2f}", z_slice)
154
+ fig2 = create_plotly_figure(u2, lx, ly, lz, f"{idx2*dt:.2f}", z_slice)
155
+ fig3 = create_plotly_figure(u3, lx, ly, lz, f"{idx3*dt:.2f}", z_slice)
156
+ # Create GIF for the z_slice
157
+ gif_path = create_animation_gif(U, lx, ly, lz, initial, bc, gamma, frame_skip, dt, z_slice)
158
  return gif_path, fig0, fig1, fig2, fig3
159
 
160
+ # --- Gradio Interface Logic ---
161
+ def gradio_interface(lx, ly, lz, t_max, gamma, nx, ny, nz, initial, bc, frame_skip, z_slice_percent):
162
+ nx, ny, nz, frame_skip = int(nx), int(ny), int(nz), int(frame_skip)
163
+ return run_simulation(lx, ly, lz, t_max, gamma, nx, ny, nz, initial, bc, frame_skip, z_slice_percent)
164
+
165
  # --- Gradio UI Layout ---
166
+ with gr.Blocks(theme=gr.themes.Soft(), title="3D Heat Simulator") as demo:
167
+ gr.Markdown("# ♨️ 3D Heat Equation Simulator\nAdjust parameters and run the simulation.")
168
  with gr.Row():
169
  with gr.Column(scale=1):
170
  gr.Markdown("## Domain & Grid")
171
  lx_slider = gr.Slider(0.1, 5.0, 1.0, 0.1, label="Lx")
172
  ly_slider = gr.Slider(0.1, 5.0, 1.0, 0.1, label="Ly")
173
+ lz_slider = gr.Slider(0.1, 5.0, 1.0, 0.1, label="Lz")
174
  nx_slider = gr.Slider(3, 200, 50, 1, label="Nx")
175
  ny_slider = gr.Slider(3, 200, 50, 1, label="Ny")
176
+ nz_slider = gr.Slider(3, 200, 50, 1, label="Nz")
177
 
178
  gr.Markdown("## Simulation")
179
  t_slider = gr.Slider(0.01, 5.0, 0.5, 0.01, label="t_max")
 
189
 
190
  gr.Markdown("## Animation")
191
  frame_skip_slider = gr.Slider(1, 50, 5, 1, label="Frame Skip")
192
+ z_slice_percent_slider = gr.Slider(0, 100, 50, 1, label="Z-Slice Position (%)")
193
+
194
  run_btn = gr.Button("Run Simulation", variant="primary")
195
  with gr.Column(scale=3):
196
  gif_output = gr.Image(label="Animation")
 
200
  with gr.Row():
201
  plot3 = gr.Plot(label="t=3t/4")
202
  plot4 = gr.Plot(label="t=t")
203
+ inputs_list = [lx_slider, ly_slider, lz_slider, t_slider, gamma_slider,
204
+ nx_slider, ny_slider, nz_slider, initial_dropdown, bc_dropdown, frame_skip_slider, z_slice_percent_slider]
205
  outputs_list = [gif_output, plot1, plot2, plot3, plot4]
206
  run_btn.click(fn=gradio_interface, inputs=inputs_list, outputs=outputs_list)
207
  gr.Examples(
208
  examples=[
209
+ [1.0, 1.0, 1.0, 0.5, 0.1, 50, 50, 50, "gaussian", "dirichlet", 5, 50],
210
+ [2.0, 1.0, 1.5, 1.0, 0.05, 60, 30, 40, "sinusoidal", "periodic", 10, 50],
211
+ [1.0, 1.0, 1.0, 0.2, 0.2, 80, 80, 80, "step", "neumann", 2, 50],
212
  ],
213
  inputs=inputs_list,
214
  outputs=outputs_list,