physics-simulation / pages /electic-field.py
shikharyashmaurya's picture
Added new folder
dfc428f
import streamlit as st
import numpy as np
import matplotlib.pyplot as plt
# Title of the Streamlit app
st.title("Electric Field Visualization")
st.write("Add charges to see how the electric field changes! Positive charges are red, negative charges are blue.")
# Initialize session state to store charges
if 'charges' not in st.session_state:
st.session_state.charges = []
# Function to calculate the electric field on a grid
def calculate_electric_field(charges, X, Y, k=1, epsilon=1e-6):
"""
Calculate the electric field components (E_x, E_y) at each point on the grid.
Parameters:
- charges: List of dictionaries with 'x', 'y', and 'q' for each charge
- X, Y: 2D arrays from np.meshgrid representing grid coordinates
- k: Coulomb's constant (set to 1 for simplicity)
- epsilon: Small value to avoid division by zero at charge locations
Returns:
- E_x, E_y: Electric field components as 2D arrays
"""
E_x_total = np.zeros_like(X)
E_y_total = np.zeros_like(Y)
for charge in charges:
dx = X - charge['x']
dy = Y - charge['y']
r = np.sqrt(dx**2 + dy**2 + epsilon) # Distance with epsilon to avoid singularity
# E = k * q * r̂ / r^2, where r̂ is the unit vector (dx/r, dy/r)
# So, E_x = k * q * dx / r^3, E_y = k * q * dy / r^3
E_x_charge = k * charge['q'] * dx / r**3
E_y_charge = k * charge['q'] * dy / r**3
E_x_total += E_x_charge
E_y_total += E_y_charge
return E_x_total, E_y_total
# UI to add a charge
st.subheader("Add a Charge")
x = st.slider("X position", -5.0, 5.0, 0.0, key="x_add")
y = st.slider("Y position", -5.0, 5.0, 0.0, key="y_add")
q = st.selectbox("Charge", [1, -1], format_func=lambda val: "+1" if val > 0 else "-1", key="q_add")
if st.button("Add Charge", key="add_charge"):
st.session_state.charges.append({'x': x, 'y': y, 'q': q})
st.success(f"Added charge q={q} at ({x}, {y})")
# UI to display and remove charges
st.subheader("Current Charges")
if st.session_state.charges:
for i, charge in enumerate(st.session_state.charges):
st.write(f"Charge {i}: x={charge['x']}, y={charge['y']}, q={'+' if charge['q'] > 0 else '-'}1")
# Select and remove a charge
charge_to_remove = st.selectbox(
"Select charge to remove",
options=range(len(st.session_state.charges)),
format_func=lambda i: f"Charge {i}: x={st.session_state.charges[i]['x']}, y={st.session_state.charges[i]['y']}, q={'+' if st.session_state.charges[i]['q'] > 0 else '-'}1",
key="charge_to_remove"
)
if st.button("Remove Selected Charge", key="remove_charge"):
del st.session_state.charges[charge_to_remove]
st.success("Charge removed!")
else:
st.write("No charges added yet. Add some to see the electric field.")
# Create the plot if there are charges
if st.session_state.charges:
# Define the grid for calculation
x_grid = np.linspace(-5, 5, 20)
y_grid = np.linspace(-5, 5, 20)
X, Y = np.meshgrid(x_grid, y_grid)
# Calculate the electric field
E_x, E_y = calculate_electric_field(st.session_state.charges, X, Y)
# Create the plot
fig, ax = plt.subplots(figsize=(8, 8))
ax.streamplot(X, Y, E_x, E_y, color='black', linewidth=1, density=1.5)
# Plot each charge
for charge in st.session_state.charges:
color = 'red' if charge['q'] > 0 else 'blue'
ax.plot(charge['x'], charge['y'], 'o', color=color, markersize=10, label=f"q={charge['q']}")
# Set plot limits and labels
ax.set_xlim(-5, 5)
ax.set_ylim(-5, 5)
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_title("Electric Field Lines")
ax.grid(True)
# Display the plot in Streamlit
st.pyplot(fig)
else:
st.info("Add some charges above to visualize the electric field!")
# Footer
st.write("Note: The field lines point away from positive charges and toward negative charges, following the direction a positive test charge would move.")