import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
NUM_PARTICLES = 50
SIM_TIME = 10.0
DT = 0.02
WINDOW_SIZE = 10.0
AIR_VISCOSITY = 1.8e-5
PARTICLE_DENSITY = 1500
AIR_DENSITY = 1.2
class Particle:
def __init__(self):
self.pos = np.random.rand(2) * WINDOW_SIZE
self.vel = np.zeros(2)
self.diameter = np.random.uniform(0.02, 0.05)
self.mass = PARTICLE_DENSITY * np.pi * (self.diameter ** 3) / 6
def apply_force(self, force):
self.vel += force / self.mass * DT
class FlowField:
def __init__(self):
self.wind_speed = 2.0
def get_velocity(self, pos):
x, y = pos
center = WINDOW_SIZE / 2
factor = 1 - abs(x - center) / center
return np.array([self.wind_speed * factor, 0])
def update(frame):
global particles, flow
plt.cla()
for p in particles:
air_vel = flow.get_velocity(p.pos)
rel_vel = air_vel - p.vel
Re = np.linalg.norm(rel_vel) * p.diameter * AIR_DENSITY / AIR_VISCOSITY
Cd = 24 / Re + 6 / (1 + np.sqrt(Re)) + 0.4
drag_force = 0.5 * AIR_DENSITY * np.pi * (p.diameter ** 2) / 4 * Cd * rel_vel
gravity = np.array([0, -9.81 * p.mass])
p.apply_force(drag_force + gravity)
p.pos += p.vel * DT
p.pos = np.clip(p.pos, 0, WINDOW_SIZE)
if p.pos[1] <= 0 or p.pos[1] >= WINDOW_SIZE:
p.vel[1] *= -0.5
plt.scatter([p.pos[0] for p in particles],
[p.pos[1] for p in particles],
s=[p.diameter * 1000 for p in particles],
c='blue', alpha=0.6)
x = np.linspace(0, WINDOW_SIZE, 6)
y = np.linspace(0, WINDOW_SIZE, 6)
X, Y = np.meshgrid(x, y)
U = np.array([flow.get_velocity([xi, yi])[0] for xi, yi in zip(X.flatten(), Y.flatten())])
V = np.array([flow.get_velocity([xi, yi])[1] for xi, yi in zip(X.flatten(), Y.flatten())])
plt.quiver(X, Y, U.reshape(X.shape), V.reshape(Y.shape), color='red')
plt.xlim(0, WINDOW_SIZE)
plt.ylim(0, WINDOW_SIZE)
plt.title(f"Gas-Solid Flow Simulation (t={frame * DT:.2f}s)")
plt.xlabel("X Position")
plt.ylabel("Y Position")
particles = [Particle() for _ in range(NUM_PARTICLES)]
flow = FlowField()
fig = plt.figure(figsize=(8, 6))
ani = FuncAnimation(fig, update, frames=int(SIM_TIME / DT), interval=50)
plt.show()