shikharyashmaurya's picture
Added new folder
dfc428f
import streamlit as st
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import matplotlib.animation as animation
class GravitySimulation:
def __init__(self, num_bodies=3, width=10, height=10):
"""
Initialize the gravity simulation
Parameters:
-----------
num_bodies : int, optional
Number of bodies in the simulation (default is 3)
width : float, optional
Width of the simulation space (default is 10)
height : float, optional
Height of the simulation space (default is 10)
"""
self.num_bodies = num_bodies
self.width = width
self.height = height
# Gravitational constant (scaled for visualization)
self.G = 1.0
# Initialize positions, velocities, and masses
self.positions = np.random.rand(num_bodies, 2) * np.array([width, height])
self.velocities = np.random.randn(num_bodies, 2) * 0.1
self.masses = np.random.uniform(0.5, 2, num_bodies)
def compute_accelerations(self):
"""
Compute gravitational accelerations between bodies
Returns:
--------
numpy.ndarray
Accelerations for each body
"""
accelerations = np.zeros_like(self.positions)
for i in range(self.num_bodies):
for j in range(self.num_bodies):
if i != j:
# Vector from body i to body j
r_vector = self.positions[j] - self.positions[i]
# Distance between bodies
r_magnitude = np.linalg.norm(r_vector)
# Avoid division by zero
if r_magnitude > 0:
# Gravitational acceleration
acceleration_magnitude = self.G * self.masses[j] / (r_magnitude ** 2)
# Direction of acceleration
acceleration = acceleration_magnitude * (r_vector / r_magnitude)
accelerations[i] += acceleration
return accelerations
def update(self, dt=0.01):
"""
Update positions and velocities using Euler integration
Parameters:
-----------
dt : float, optional
Time step for simulation (default is 0.01)
"""
# Compute accelerations
accelerations = self.compute_accelerations()
# Update velocities
self.velocities += accelerations * dt
# Update positions
self.positions += self.velocities * dt
# Simple boundary conditions (bouncing off walls)
for i in range(self.num_bodies):
for dim in range(2):
if (self.positions[i, dim] < 0) or (self.positions[i, dim] > [self.width, self.height][dim]):
self.velocities[i, dim] *= -0.9 # Damped bounce
self.positions[i, dim] = np.clip(self.positions[i, dim], 0, [self.width, self.height][dim])
def main():
st.title("Gravitational N-Body Simulation")
# Sidebar for simulation parameters
st.sidebar.header("Simulation Parameters")
# Number of bodies slider
num_bodies = st.sidebar.slider("Number of Bodies", min_value=2, max_value=10, value=3)
# Simulation space dimensions
width = st.sidebar.number_input("Simulation Width", min_value=5.0, max_value=20.0, value=10.0)
height = st.sidebar.number_input("Simulation Height", min_value=5.0, max_value=20.0, value=10.0)
# Time step slider
dt = st.sidebar.slider("Time Step", min_value=0.001, max_value=0.1, value=0.01, step=0.001)
# Create simulation
sim = GravitySimulation(num_bodies=num_bodies, width=width, height=height)
# Matplotlib figure for animation
fig, ax = plt.subplots(figsize=(8, 6))
ax.set_xlim(0, width)
ax.set_ylim(0, height)
ax.set_title("Gravitational Interaction")
ax.set_xlabel("X Position")
ax.set_ylabel("Y Position")
# Scatter plot for bodies
scatter = ax.scatter(sim.positions[:, 0], sim.positions[:, 1],
c=sim.masses, cmap='viridis',
s=sim.masses*100, alpha=0.7)
# Animation update function
def update_plot(frame):
sim.update(dt)
scatter.set_offsets(sim.positions)
return scatter,
# Create animation
anim = FuncAnimation(fig, update_plot, frames=200, interval=50, blit=True)
# Convert animation to HTML for Streamlit
plt.close(fig)
# Display animation
st.pyplot(fig)
# Optional: Provide download of animation
st.sidebar.header("Animation Options")
if st.sidebar.button("Save Animation"):
# Save animation as gif
anim.save('gravity_simulation.gif', writer='pillow')
with open('gravity_simulation.gif', 'rb') as f:
st.sidebar.download_button(
label="Download Animation",
data=f.read(),
file_name="gravity_simulation.gif",
mime="image/gif"
)
# Information section
st.markdown("## About the Simulation")
st.markdown("""
This simulation demonstrates gravitational interactions between multiple bodies:
- Bodies attract each other based on their masses
- Gravitational force is inversely proportional to the square of the distance
- Bodies bounce off the simulation boundaries
- Larger/darker points represent bodies with more mass
""")
if __name__ == "__main__":
main()