| import streamlit as st |
| import numpy as np |
| import matplotlib.pyplot as plt |
|
|
| |
| st.markdown(""" |
| # Electric Field Visualization |
| |
| This app helps you visualize the electric field created by point charges in a 2D space. |
| |
| ### How to Use |
| - In the sidebar, enter the charges in the format `x,y,Q` (one per line), where: |
| - `x` and `y` are the coordinates of the charge. |
| - `Q` is the charge value (positive or negative). |
| - Example: `0,0,1` places a positive charge of 1 at the origin, and `3,0,-1` places a negative charge at (3,0). |
| - Select the visualization type: |
| - **Quiver Plot**: Shows arrows representing the direction and strength of the electric field. |
| - **Field Lines**: Displays lines that follow the electric field's direction. |
| |
| Try starting with `0,0,1` and `3,0,-1` to see a dipole field! |
| """) |
|
|
| |
| charges_input = st.sidebar.text_area( |
| "Enter charges (x,y,Q) one per line", |
| "0,0,1\n3,0,-1" |
| ) |
| vis_type = st.sidebar.radio("Visualization Type", ["Quiver Plot", "Field Lines"]) |
|
|
| |
| charges = [] |
| for line in charges_input.split('\n'): |
| if line.strip(): |
| try: |
| x, y, Q = map(float, line.split(',')) |
| charges.append((x, y, Q)) |
| except ValueError: |
| st.sidebar.error(f"Invalid input: {line}. Use format x,y,Q.") |
| st.stop() |
|
|
| |
| if not charges: |
| st.warning("No charges entered. Please add charges in the sidebar.") |
| st.stop() |
|
|
| |
| def electric_field(x, y, charges): |
| Ex, Ey = 0, 0 |
| for cx, cy, Q in charges: |
| dx = x - cx |
| dy = y - cy |
| r2 = dx**2 + dy**2 |
| |
| if r2 < 1e-10: |
| continue |
| r3 = r2**1.5 |
| Ex += Q * dx / r3 |
| Ey += Q * dy / r3 |
| return Ex, Ey |
|
|
| |
| fig, ax = plt.subplots(figsize=(8, 8)) |
|
|
| |
| x = np.arange(-10, 11, 1) |
| y = np.arange(-10, 11, 1) |
| X, Y = np.meshgrid(x, y) |
|
|
| if vis_type == "Quiver Plot": |
| |
| Ex = np.zeros_like(X, dtype=float) |
| Ey = np.zeros_like(Y, dtype=float) |
| for i in range(X.shape[0]): |
| for j in range(X.shape[1]): |
| Ex[i, j], Ey[i, j] = electric_field(X[i, j], Y[i, j], charges) |
| |
| |
| M = np.sqrt(Ex**2 + Ey**2) |
| |
| |
| quiv = ax.quiver(X, Y, Ex, Ey, M, cmap='viridis', scale=50) |
| fig.colorbar(quiv, ax=ax, label='Field Magnitude') |
|
|
| else: |
| |
| starting_points = [] |
| for cx, cy, Q in charges: |
| |
| for angle in np.linspace(0, 2*np.pi, 8, endpoint=False): |
| x0 = cx + 0.1 * np.cos(angle) |
| y0 = cy + 0.1 * np.sin(angle) |
| starting_points.append((x0, y0)) |
| |
| |
| for x0, y0 in starting_points: |
| path = [(x0, y0)] |
| for _ in range(100): |
| Ex, Ey = electric_field(x0, y0, charges) |
| mag = np.sqrt(Ex**2 + Ey**2) |
| if mag < 1e-5: |
| break |
| |
| step_x = 0.1 * Ex / mag |
| step_y = 0.1 * Ey / mag |
| x0 += step_x |
| y0 += step_y |
| |
| if x0 < -10 or x0 > 10 or y0 < -10 or y0 > 10: |
| break |
| path.append((x0, y0)) |
| |
| |
| px, py = zip(*path) |
| ax.plot(px, py, 'k-', linewidth=1) |
|
|
| |
| for cx, cy, Q in charges: |
| color = 'red' if Q > 0 else 'blue' |
| ax.plot(cx, cy, 'o', color=color, markersize=10, label=f'Q={Q}') |
|
|
| |
| ax.set_xlim(-10, 10) |
| ax.set_ylim(-10, 10) |
| ax.set_aspect('equal') |
| ax.set_xlabel('x') |
| ax.set_ylabel('y') |
| ax.set_title(f'Electric Field - {vis_type}') |
| ax.grid(True) |
|
|
| |
| st.pyplot(fig) |