-
Notifications
You must be signed in to change notification settings - Fork 0
/
particle_shapes.py
102 lines (84 loc) · 4.34 KB
/
particle_shapes.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import numpy as np
class ParticleShape:
def __init__(self, cell_size, object_id):
self.cell_size = cell_size
self.particles_per_cell = 4 # 4 particles per cell in 2D
self.object_id = object_id
def generate_particles(self):
raise NotImplementedError("Subclasses must implement generate_particles method")
def _generate_grid_particles(self, x_range, y_range):
particles = []
for i in range(x_range[0], x_range[1]):
for j in range(y_range[0], y_range[1]):
for px in range(2):
for py in range(2):
# Place particles at the center of each quadrant (1/4 and 3/4 of the cell)
x = (i + (px + 0.5) / 2) * self.cell_size
y = (j + (py + 0.5) / 2) * self.cell_size
if self._is_inside(x, y):
particle = {
'position': np.array([x, y]),
'velocity': np.zeros(2),
'mass': self.density * self.cell_size**2 / self.particles_per_cell,
'volume': self.cell_size**2 / self.particles_per_cell,
'stress': np.zeros((2, 2)),
'strain': np.zeros((2, 2)),
'object_id': self.object_id, # Add object_id to the particle
}
particles.append(particle)
return particles
def _is_inside(self, x, y):
raise NotImplementedError("Subclasses must implement _is_inside method")
class Block(ParticleShape):
def __init__(self, cell_size, width, height, position, object_id):
super().__init__(cell_size, object_id)
self.width = width
self.height = height
self.position = np.array(position)
def generate_particles(self):
num_cells_x = int(self.width / self.cell_size)
num_cells_y = int(self.height / self.cell_size)
x_range = (0, num_cells_x)
y_range = (0, num_cells_y)
return self._generate_grid_particles(x_range, y_range)
def _is_inside(self, x, y):
return (0 <= x < self.width) and (0 <= y < self.height)
class Disk(ParticleShape):
def __init__(self, cell_size, radius, center, object_id, material_density):
super().__init__(cell_size, object_id)
self.radius = radius
self.center = np.array(center)
self.material_density = material_density # Added material density
print(f"Disk created with radius={radius}, center={center}")
def generate_particles(self):
particles = []
x_min, x_max = self.center[0] - self.radius, self.center[0] + self.radius
y_min, y_max = self.center[1] - self.radius, self.center[1] + self.radius
# Determine the area per particle
area_per_particle = (self.cell_size ** 2) / self.particles_per_cell
mass_per_particle = self.material_density * area_per_particle
for i in range(int(x_min / self.cell_size), int(x_max / self.cell_size) + 1):
for j in range(int(y_min / self.cell_size), int(y_max / self.cell_size) + 1):
for px in range(2):
for py in range(2):
x = (i + (px + 0.5) / 2) * self.cell_size
y = (j + (py + 0.5) / 2) * self.cell_size
if self._is_inside(x, y):
particle = {
'position': np.array([x, y]),
'velocity': np.zeros(2),
'mass': mass_per_particle,
'volume': area_per_particle,
'stress': np.zeros((2, 2)),
'strain': np.zeros((2, 2)),
'object_id': max(0, self.object_id),
}
particles.append(particle)
print(f"Disk generated {len(particles)} particles")
if len(particles) == 0:
print(f"Warning: No particles generated. Check disk parameters.")
return particles
def _is_inside(self, x, y):
dx = x - self.center[0]
dy = y - self.center[1]
return dx**2 + dy**2 <= self.radius**2