PyParticles3 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyparticles/__init__.py +26 -0
- pyparticles/__main__.py +7 -0
- pyparticles/animation/__init__.py +21 -0
- pyparticles/animation/animated_cli.py +53 -0
- pyparticles/animation/animated_ogl.py +691 -0
- pyparticles/animation/animated_ogl_compat.py +243 -0
- pyparticles/animation/animated_scatter.py +94 -0
- pyparticles/animation/animation.py +251 -0
- pyparticles/animation/test_animation.py +310 -0
- pyparticles/demo/__init__.py +33 -0
- pyparticles/demo/bubble.py +106 -0
- pyparticles/demo/electromagnetic_demo.py +128 -0
- pyparticles/demo/electrostatic_demo.py +126 -0
- pyparticles/demo/fountain.py +478 -0
- pyparticles/demo/gas_lennard_jones.py +87 -0
- pyparticles/demo/gravity_clusters.py +73 -0
- pyparticles/demo/solar_system.py +222 -0
- pyparticles/demo/springs.py +141 -0
- pyparticles/demo/springs_constr.py +135 -0
- pyparticles/demo/test.py +34 -0
- pyparticles/forces/__init__.py +21 -0
- pyparticles/forces/const_force.py +140 -0
- pyparticles/forces/damping.py +174 -0
- pyparticles/forces/drag.py +167 -0
- pyparticles/forces/electromagnetic.py +105 -0
- pyparticles/forces/electromagnetic_field.py +95 -0
- pyparticles/forces/electrostatic.py +72 -0
- pyparticles/forces/force.py +75 -0
- pyparticles/forces/force_constrained.py +32 -0
- pyparticles/forces/fused_const_drag.py +445 -0
- pyparticles/forces/gravity.py +345 -0
- pyparticles/forces/lennard_jones.py +74 -0
- pyparticles/forces/linear_spring.py +86 -0
- pyparticles/forces/linear_spring_constrained.py +72 -0
- pyparticles/forces/multiple_force.py +134 -0
- pyparticles/forces/pseudo_bubble.py +226 -0
- pyparticles/forces/van_der_waals_force.py +60 -0
- pyparticles/forces/vector_field_force.py +52 -0
- pyparticles/geometry/__init__.py +21 -0
- pyparticles/geometry/dist.py +24 -0
- pyparticles/geometry/intersection.py +62 -0
- pyparticles/geometry/transformations.py +387 -0
- pyparticles/main/__init__.py +21 -0
- pyparticles/main/main.py +466 -0
- pyparticles/measures/__init__.py +21 -0
- pyparticles/measures/elastic_potential_energy.py +67 -0
- pyparticles/measures/gravitational_potential_energy.py +69 -0
- pyparticles/measures/kinetic_energy.py +68 -0
- pyparticles/measures/mass.py +59 -0
- pyparticles/measures/measure.py +156 -0
- pyparticles/measures/momentum.py +144 -0
- pyparticles/measures/total_energy.py +68 -0
- pyparticles/ode/__init__.py +21 -0
- pyparticles/ode/euler_solver.py +214 -0
- pyparticles/ode/euler_solver_constrained.py +49 -0
- pyparticles/ode/leapfrog_solver.py +37 -0
- pyparticles/ode/leapfrog_solver_constrained.py +53 -0
- pyparticles/ode/midpoint_solver.py +43 -0
- pyparticles/ode/midpoint_solver_constrained.py +60 -0
- pyparticles/ode/ode_solver.py +134 -0
- pyparticles/ode/ode_solver_constrained.py +43 -0
- pyparticles/ode/runge_kutta_solver.py +79 -0
- pyparticles/ode/runge_kutta_solver_constrained.py +98 -0
- pyparticles/ode/sim_time.py +56 -0
- pyparticles/ode/stormer_verlet_solver.py +50 -0
- pyparticles/ode/stormer_verlet_solver_constrained.py +73 -0
- pyparticles/ogl/__init__.py +21 -0
- pyparticles/ogl/axis_ogl.py +210 -0
- pyparticles/ogl/draw_particles_ogl.py +313 -0
- pyparticles/ogl/draw_particles_ogl_compat.py +509 -0
- pyparticles/ogl/draw_vector_field.py +221 -0
- pyparticles/ogl/opencl_gl_vbo.py +485 -0
- pyparticles/ogl/trackball.py +131 -0
- pyparticles/ogl/translate_scene.py +87 -0
- pyparticles/pset/__init__.py +21 -0
- pyparticles/pset/boundary.py +69 -0
- pyparticles/pset/cluster.py +28 -0
- pyparticles/pset/constrained_force_interactions.py +63 -0
- pyparticles/pset/constrained_x.py +158 -0
- pyparticles/pset/constraint.py +42 -0
- pyparticles/pset/default_boundary.py +43 -0
- pyparticles/pset/file_cluster.py +131 -0
- pyparticles/pset/logger.py +152 -0
- pyparticles/pset/octree.py +451 -0
- pyparticles/pset/opencl_context.py +374 -0
- pyparticles/pset/particles_set.py +499 -0
- pyparticles/pset/periodic_boundary.py +36 -0
- pyparticles/pset/rand_cluster.py +188 -0
- pyparticles/pset/rebound_boundary.py +68 -0
- pyparticles/utils/__init__.py +21 -0
- pyparticles/utils/parse_args.py +72 -0
- pyparticles/utils/problem_config.py +608 -0
- pyparticles/utils/pypart_global.py +122 -0
- pyparticles/utils/time_formatter.py +50 -0
- pyparticles3-0.4.0.dist-info/METADATA +395 -0
- pyparticles3-0.4.0.dist-info/RECORD +100 -0
- pyparticles3-0.4.0.dist-info/WHEEL +5 -0
- pyparticles3-0.4.0.dist-info/entry_points.txt +3 -0
- pyparticles3-0.4.0.dist-info/licenses/LICENSE-gpl-3.0.txt +674 -0
- pyparticles3-0.4.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
# PyParticles : Particles simulation in python
|
|
2
|
+
# Copyright (C) 2012 Simone Riva
|
|
3
|
+
#
|
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
|
|
17
|
+
import pyparticles.pset.particles_set as ps
|
|
18
|
+
|
|
19
|
+
import pyparticles.animation.animation as pan
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
import pyparticles.forces.gravity as gr
|
|
23
|
+
import pyparticles.ode.euler_solver as els
|
|
24
|
+
import pyparticles.ode.leapfrog_solver as lps
|
|
25
|
+
import pyparticles.ode.runge_kutta_solver as rks
|
|
26
|
+
import pyparticles.ode.midpoint_solver as mps
|
|
27
|
+
import pyparticles.ode.stormer_verlet_solver as svs
|
|
28
|
+
|
|
29
|
+
import pyparticles.ode.euler_solver_constrained as asc
|
|
30
|
+
import pyparticles.ode.leapfrog_solver_constrained as lpc
|
|
31
|
+
import pyparticles.ode.stormer_verlet_solver_constrained as svc
|
|
32
|
+
import pyparticles.ode.runge_kutta_solver_constrained as rkc
|
|
33
|
+
import pyparticles.ode.midpoint_solver_constrained as mdc
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
import matplotlib.pyplot as plt
|
|
37
|
+
import numpy as np
|
|
38
|
+
|
|
39
|
+
import pyparticles.forces.const_force as cf
|
|
40
|
+
import pyparticles.forces.drag as dr
|
|
41
|
+
import pyparticles.forces.multiple_force as mf
|
|
42
|
+
import pyparticles.forces.linear_spring as ls
|
|
43
|
+
import pyparticles.forces.damping as da
|
|
44
|
+
|
|
45
|
+
import pyparticles.pset.constrained_x as csx
|
|
46
|
+
import pyparticles.pset.constrained_force_interactions as cfi
|
|
47
|
+
|
|
48
|
+
from matplotlib.ticker import FuncFormatter
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def free_fall( t , m=1. , g=10. , k=1. ):
|
|
53
|
+
z = (np.sqrt(2.*g*k)*t*m**2.-2.*m**(5./2.)*np.log((1./2.)*np.exp(np.sqrt(2.)*np.sqrt(g*k)*t/np.sqrt(m))+1./2.))/(m**(3./2.)*k)
|
|
54
|
+
return np.array( [ 0.0 , 0.0 , z ] )
|
|
55
|
+
|
|
56
|
+
def harmonic( t ):
|
|
57
|
+
a = np.cos( t ) / np.sqrt(3.0)
|
|
58
|
+
return np.array( [ a , a , a ] )
|
|
59
|
+
|
|
60
|
+
def damp_harmonic( t ):
|
|
61
|
+
a = (1./15.)*np.sqrt(15.)*np.exp(-(1./4.)*t)*np.sin((1./4.)*np.sqrt(15.)*t)+np.exp(-(1./4.)*t)*np.cos((1./4.)*np.sqrt(15.)*t)
|
|
62
|
+
a = a / np.sqrt(3.0)
|
|
63
|
+
|
|
64
|
+
return np.array( [ a , a , a ] )
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class TestAnimation( pan.Animation ):
|
|
68
|
+
"""
|
|
69
|
+
Test the free fall with the fluid drag
|
|
70
|
+
"""
|
|
71
|
+
def __init__(self):
|
|
72
|
+
super( TestAnimation , self ).__init__()
|
|
73
|
+
|
|
74
|
+
self.__analytical_sol = free_fall
|
|
75
|
+
|
|
76
|
+
def set_analytical_sol( self , f ):
|
|
77
|
+
self.__analytical_sol = f
|
|
78
|
+
|
|
79
|
+
def get_analytical_sol( self ):
|
|
80
|
+
return self.__analytical_sol
|
|
81
|
+
|
|
82
|
+
analytical_sol = property( get_analytical_sol , set_analytical_sol )
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def set_ip( self , i ):
|
|
87
|
+
self.__ip = i
|
|
88
|
+
|
|
89
|
+
def get_ip( self ):
|
|
90
|
+
return self.__ip
|
|
91
|
+
|
|
92
|
+
ip = property( get_ip , set_ip )
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def init_pset(self):
|
|
96
|
+
self.pset.M[:] = 1.0
|
|
97
|
+
self.pset.V[:] = 0.0
|
|
98
|
+
self.pset.X[:] = 0.0
|
|
99
|
+
|
|
100
|
+
def build_animation(self):
|
|
101
|
+
|
|
102
|
+
self.steps = 3000
|
|
103
|
+
|
|
104
|
+
self.pset = ps.ParticlesSet( 1 , 3 )
|
|
105
|
+
|
|
106
|
+
self.ip = 0
|
|
107
|
+
|
|
108
|
+
self.pset.M[:] = 1.0
|
|
109
|
+
self.pset.V[:] = 0.0
|
|
110
|
+
|
|
111
|
+
self.t = np.zeros(( self.steps ))
|
|
112
|
+
self.x = np.zeros(( self.steps , self.pset.dim ))
|
|
113
|
+
|
|
114
|
+
self.xn = np.zeros(( self.steps , self.pset.dim ))
|
|
115
|
+
|
|
116
|
+
constf = cf.ConstForce( self.pset.size , u_force=[ 0 , 0 , -10.0 ] , dim=self.pset.dim )
|
|
117
|
+
drag = dr.Drag( self.pset.size , Consts=1.0 )
|
|
118
|
+
|
|
119
|
+
multi = mf.MultipleForce( self.pset.size )
|
|
120
|
+
|
|
121
|
+
multi.append_force( constf )
|
|
122
|
+
multi.append_force( drag )
|
|
123
|
+
|
|
124
|
+
multi.set_masses( self.pset.M )
|
|
125
|
+
|
|
126
|
+
dt = 0.001
|
|
127
|
+
|
|
128
|
+
self.odes = dict()
|
|
129
|
+
|
|
130
|
+
self.odes["Euler "] = els.EulerSolver( multi , self.pset , dt )
|
|
131
|
+
self.odes["Runge Kutta"] = rks.RungeKuttaSolver( multi , self.pset , dt )
|
|
132
|
+
self.odes["Leap Frog "] = lps.LeapfrogSolver( multi , self.pset , dt )
|
|
133
|
+
self.odes["MidPoint "] = mps.MidpointSolver( multi , self.pset , dt )
|
|
134
|
+
self.odes["Verlet "] = svs.StormerVerletSolver( multi , self.pset , dt )
|
|
135
|
+
|
|
136
|
+
def data_stream( self ):
|
|
137
|
+
|
|
138
|
+
for i in range( self.steps ) :
|
|
139
|
+
|
|
140
|
+
self.t[i] = self.ode_solver.time
|
|
141
|
+
|
|
142
|
+
#print( self.t[i] )
|
|
143
|
+
|
|
144
|
+
self.x[i,:] = self.analytical_sol( self.t[i] )
|
|
145
|
+
|
|
146
|
+
self.xn[i,:] = self.pset.X[self.ip,:]
|
|
147
|
+
|
|
148
|
+
#print( " t: %f , x: %s , xn: %s " % ( self.t[i] , self.x[i,:] , self.xn[i,:] ) )
|
|
149
|
+
self.ode_solver.step()
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def start(self):
|
|
154
|
+
|
|
155
|
+
print( "Start testing:" )
|
|
156
|
+
|
|
157
|
+
j = 0
|
|
158
|
+
|
|
159
|
+
print("")
|
|
160
|
+
print("Errors:")
|
|
161
|
+
|
|
162
|
+
#plt.ion()
|
|
163
|
+
|
|
164
|
+
for ky in self.odes.keys():
|
|
165
|
+
|
|
166
|
+
self.init_pset()
|
|
167
|
+
|
|
168
|
+
self.ode_solver = self.odes[ky]
|
|
169
|
+
self.data_stream()
|
|
170
|
+
|
|
171
|
+
err = np.sqrt( np.sum( (self.x-self.xn)**2 , 1 ) )
|
|
172
|
+
|
|
173
|
+
merr = np.mean( err )
|
|
174
|
+
|
|
175
|
+
mt = np.array( [ self.t[0] , self.t[self.steps-1] ] )
|
|
176
|
+
me = np.array( [ merr , merr ] )
|
|
177
|
+
|
|
178
|
+
print( " %s - mean err: %f " % ( ky , merr ) )
|
|
179
|
+
|
|
180
|
+
ax = plt.subplot( 230+j+1 )
|
|
181
|
+
|
|
182
|
+
ax.yaxis.set_major_formatter(FuncFormatter(lambda x, pos: ('%.1f')%(x*1e3)))
|
|
183
|
+
|
|
184
|
+
p1, = plt.plot( self.t[:] , err , linewidth=2 )
|
|
185
|
+
p2, = plt.plot( mt , me , linewidth=1 , color="g" )
|
|
186
|
+
|
|
187
|
+
plt.title( "Absolute error: %s " % ky )
|
|
188
|
+
plt.xlabel( "Time" )
|
|
189
|
+
plt.ylabel( "Abs error [1e-3]" )
|
|
190
|
+
|
|
191
|
+
plt.legend([p1, p2], ["Abs Error", "Mean"] , loc=4 )
|
|
192
|
+
|
|
193
|
+
plt.grid(1)
|
|
194
|
+
|
|
195
|
+
plt.draw()
|
|
196
|
+
|
|
197
|
+
j += 1
|
|
198
|
+
|
|
199
|
+
plt.show()
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
class TestAnimationHarmonic( TestAnimation ):
|
|
204
|
+
"""
|
|
205
|
+
Test the harmonic motion with two particles.
|
|
206
|
+
"""
|
|
207
|
+
|
|
208
|
+
def __init__(self):
|
|
209
|
+
self.analytical_sol = harmonic
|
|
210
|
+
|
|
211
|
+
def init_pset(self):
|
|
212
|
+
self.pset.X[0,:] = 0.0
|
|
213
|
+
self.pset.X[1,:] = 1.0 / np.sqrt(3)
|
|
214
|
+
self.pset.M[:] = 1.0
|
|
215
|
+
self.pset.V[:] = 0.0
|
|
216
|
+
|
|
217
|
+
def build_animation(self):
|
|
218
|
+
|
|
219
|
+
self.steps = 6000
|
|
220
|
+
dt = 0.004
|
|
221
|
+
|
|
222
|
+
self.ip = 1
|
|
223
|
+
|
|
224
|
+
self.pset = ps.ParticlesSet( 2 , 3 )
|
|
225
|
+
self.pset.M[:] = 1.0
|
|
226
|
+
self.pset.V[:] = 0.0
|
|
227
|
+
|
|
228
|
+
self.pset.X[0,:] = 0.0
|
|
229
|
+
self.pset.X[1,:] = 1.0 / np.sqrt(3)
|
|
230
|
+
|
|
231
|
+
ci = np.array( [ 0 ] )
|
|
232
|
+
cx = np.array( [ 0.0 , 0.0 , 0.0 ] )
|
|
233
|
+
|
|
234
|
+
costrs = csx.ConstrainedX( self.pset )
|
|
235
|
+
costrs.add_x_constraint( ci , cx )
|
|
236
|
+
|
|
237
|
+
self.t = np.zeros(( self.steps ))
|
|
238
|
+
self.x = np.zeros(( self.steps , self.pset.dim ))
|
|
239
|
+
|
|
240
|
+
self.xn = np.zeros(( self.steps , self.pset.dim ))
|
|
241
|
+
|
|
242
|
+
spring = ls.LinearSpring( self.pset.size , self.pset.dim , Consts=1.0 )
|
|
243
|
+
|
|
244
|
+
spring.set_masses( self.pset.M )
|
|
245
|
+
|
|
246
|
+
self.odes = dict()
|
|
247
|
+
|
|
248
|
+
self.odes["Euler "] = asc.EulerSolverConstrained( spring , self.pset , dt , costrs )
|
|
249
|
+
self.odes["Runge Kutta"] = rkc.RungeKuttaSolverConstrained( spring , self.pset , dt , costrs )
|
|
250
|
+
self.odes["Leap Frog "] = lpc.LeapfrogSolverConstrained( spring , self.pset , dt , costrs )
|
|
251
|
+
self.odes["MidPoint "] = mdc.MidpointSolverConstrained( spring , self.pset , dt , costrs )
|
|
252
|
+
self.odes["Verlet "] = svc.StormerVerletSolverConstrained( spring , self.pset , dt , costrs )
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class TestAnimationDampedHarmonic( TestAnimation ):
|
|
256
|
+
"""
|
|
257
|
+
Test the damped harmonic motion with two particles.
|
|
258
|
+
"""
|
|
259
|
+
|
|
260
|
+
def __init__(self):
|
|
261
|
+
self.analytical_sol = damp_harmonic
|
|
262
|
+
|
|
263
|
+
def init_pset(self):
|
|
264
|
+
self.pset.X[0,:] = 0.0
|
|
265
|
+
self.pset.X[1,:] = 1.0 / np.sqrt(3)
|
|
266
|
+
self.pset.M[:] = 1.0
|
|
267
|
+
self.pset.V[:] = 0.0
|
|
268
|
+
|
|
269
|
+
def build_animation(self):
|
|
270
|
+
|
|
271
|
+
self.steps = 6000
|
|
272
|
+
dt = 0.004
|
|
273
|
+
|
|
274
|
+
self.ip = 1
|
|
275
|
+
|
|
276
|
+
self.pset = ps.ParticlesSet( 2 , 3 )
|
|
277
|
+
self.pset.M[:] = 1.0
|
|
278
|
+
self.pset.V[:] = 0.0
|
|
279
|
+
|
|
280
|
+
self.pset.X[0,:] = 0.0
|
|
281
|
+
self.pset.X[1,:] = 1.0 / np.sqrt(3)
|
|
282
|
+
|
|
283
|
+
ci = np.array( [ 0 ] )
|
|
284
|
+
cx = np.array( [ 0.0 , 0.0 , 0.0 ] )
|
|
285
|
+
|
|
286
|
+
costrs = csx.ConstrainedX( self.pset )
|
|
287
|
+
costrs.add_x_constraint( ci , cx )
|
|
288
|
+
|
|
289
|
+
self.t = np.zeros(( self.steps ))
|
|
290
|
+
self.x = np.zeros(( self.steps , self.pset.dim ))
|
|
291
|
+
|
|
292
|
+
self.xn = np.zeros(( self.steps , self.pset.dim ))
|
|
293
|
+
|
|
294
|
+
spring = ls.LinearSpring( self.pset.size , self.pset.dim , Consts=1.0 )
|
|
295
|
+
damp = da.Damping( self.pset.size , self.pset.dim , Consts=0.5 )
|
|
296
|
+
|
|
297
|
+
multi = mf.MultipleForce( self.pset.size )
|
|
298
|
+
|
|
299
|
+
multi.append_force( spring )
|
|
300
|
+
multi.append_force( damp )
|
|
301
|
+
|
|
302
|
+
multi.set_masses( self.pset.M )
|
|
303
|
+
|
|
304
|
+
self.odes = dict()
|
|
305
|
+
|
|
306
|
+
self.odes["Euler "] = asc.EulerSolverConstrained( multi , self.pset , dt , costrs )
|
|
307
|
+
self.odes["Runge Kutta"] = rkc.RungeKuttaSolverConstrained( multi , self.pset , dt , costrs )
|
|
308
|
+
self.odes["Leap Frog "] = lpc.LeapfrogSolverConstrained( multi , self.pset , dt , costrs )
|
|
309
|
+
self.odes["MidPoint "] = mdc.MidpointSolverConstrained( multi , self.pset , dt , costrs )
|
|
310
|
+
self.odes["Verlet "] = svc.StormerVerletSolverConstrained( multi , self.pset , dt , costrs )
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# PyParticles : Particles simulation in python
|
|
2
|
+
#Copyright (C) 2012 Simone Riva
|
|
3
|
+
#
|
|
4
|
+
#This program is free software: you can redistribute it and/or modify
|
|
5
|
+
#it under the terms of the GNU General Public License as published by
|
|
6
|
+
#the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
#(at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
#This program is distributed in the hope that it will be useful,
|
|
10
|
+
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
#GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
#You should have received a copy of the GNU General Public License
|
|
15
|
+
#along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
import glob
|
|
19
|
+
import os
|
|
20
|
+
import sys
|
|
21
|
+
|
|
22
|
+
import pyparticles.animation as _animation
|
|
23
|
+
from pyparticles.animation import animated_ogl_compat as _animated_ogl_compat
|
|
24
|
+
|
|
25
|
+
# All official demos were written against the legacy animated_ogl module.
|
|
26
|
+
# Route both the module cache and package attribute to the modern FreeGLUT
|
|
27
|
+
# compatibility layer. animated_ogl_compat itself keeps a private reference
|
|
28
|
+
# to the original renderer.
|
|
29
|
+
_animation.animated_ogl = _animated_ogl_compat
|
|
30
|
+
sys.modules["pyparticles.animation.animated_ogl"] = _animated_ogl_compat
|
|
31
|
+
|
|
32
|
+
__all__ = [ os.path.splitext( os.path.basename(f) )[0] for f in glob.glob(os.path.dirname(os.path.abspath(__file__))+"/*.py")]
|
|
33
|
+
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# PyParticles : Particles simulation in python
|
|
2
|
+
# Copyright (C) 2012 Simone Riva
|
|
3
|
+
#
|
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
|
|
17
|
+
import numpy as np
|
|
18
|
+
|
|
19
|
+
import pyparticles.pset.particles_set as ps
|
|
20
|
+
import pyparticles.pset.opencl_context as occ
|
|
21
|
+
import pyparticles.pset.rand_cluster as rc
|
|
22
|
+
import pyparticles.pset.rebound_boundary as rb
|
|
23
|
+
|
|
24
|
+
import pyparticles.forces.pseudo_bubble as pb
|
|
25
|
+
import pyparticles.forces.const_force as cf
|
|
26
|
+
import pyparticles.forces.drag as dr
|
|
27
|
+
import pyparticles.forces.multiple_force as mf
|
|
28
|
+
|
|
29
|
+
import pyparticles.ode.stormer_verlet_solver as svs
|
|
30
|
+
|
|
31
|
+
import pyparticles.animation.animated_ogl as aogl
|
|
32
|
+
|
|
33
|
+
from pyparticles.utils.pypart_global import test_pyopencl
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def bubble():
|
|
37
|
+
"""Pseudo bubble simulation."""
|
|
38
|
+
ocl_ok = test_pyopencl()
|
|
39
|
+
|
|
40
|
+
if ocl_ok:
|
|
41
|
+
pcnt = 9000
|
|
42
|
+
r_min = 0.5
|
|
43
|
+
else:
|
|
44
|
+
pcnt = 700
|
|
45
|
+
r_min = 1.5
|
|
46
|
+
|
|
47
|
+
steps = 1000000
|
|
48
|
+
dt = 0.01
|
|
49
|
+
|
|
50
|
+
pset = ps.ParticlesSet(pcnt, dtype=np.float32)
|
|
51
|
+
rand_c = rc.RandCluster()
|
|
52
|
+
rand_c.insert3(
|
|
53
|
+
X=pset.X,
|
|
54
|
+
M=pset.M,
|
|
55
|
+
start_indx=0,
|
|
56
|
+
n=pset.size,
|
|
57
|
+
radius=3.0,
|
|
58
|
+
mass_rng=(0.5, 0.8),
|
|
59
|
+
r_min=0.0,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
if ocl_ok:
|
|
63
|
+
occx = occ.OpenCLcontext(
|
|
64
|
+
pset.size,
|
|
65
|
+
pset.dim,
|
|
66
|
+
occ.OCLC_X | occ.OCLC_V | occ.OCLC_A | occ.OCLC_M,
|
|
67
|
+
)
|
|
68
|
+
bubble_force = pb.PseudoBubbleOCL(
|
|
69
|
+
pset.size,
|
|
70
|
+
pset.dim,
|
|
71
|
+
Consts=(r_min, 10),
|
|
72
|
+
ocl_context=occx,
|
|
73
|
+
)
|
|
74
|
+
drag = dr.DragOCL(
|
|
75
|
+
pset.size,
|
|
76
|
+
pset.dim,
|
|
77
|
+
Consts=0.01,
|
|
78
|
+
ocl_context=occx,
|
|
79
|
+
)
|
|
80
|
+
else:
|
|
81
|
+
bubble_force = pb.PseudoBubble(pset.size, pset.dim, Consts=(r_min, 10))
|
|
82
|
+
drag = dr.Drag(pset.size, pset.dim, Consts=0.01)
|
|
83
|
+
|
|
84
|
+
constf = cf.ConstForce(pset.size, dim=pset.dim, u_force=[0, 0, -10.0])
|
|
85
|
+
|
|
86
|
+
multif = mf.MultipleForce(pset.size, pset.dim)
|
|
87
|
+
multif.append_force(bubble_force)
|
|
88
|
+
multif.append_force(constf)
|
|
89
|
+
multif.append_force(drag)
|
|
90
|
+
multif.set_masses(pset.M)
|
|
91
|
+
|
|
92
|
+
solver = svs.StormerVerletSolver(multif, pset, dt)
|
|
93
|
+
|
|
94
|
+
pset.set_boundary(rb.ReboundBoundary(bound=(-5.0, 5.0)))
|
|
95
|
+
|
|
96
|
+
a = aogl.AnimatedGl()
|
|
97
|
+
a.ode_solver = solver
|
|
98
|
+
a.pset = pset
|
|
99
|
+
a.steps = steps
|
|
100
|
+
|
|
101
|
+
if ocl_ok:
|
|
102
|
+
a.draw_particles.set_draw_model(a.draw_particles.DRAW_MODEL_VECTOR)
|
|
103
|
+
|
|
104
|
+
a.init_rotation(-80, [0.7, 0.05, 0])
|
|
105
|
+
a.build_animation()
|
|
106
|
+
a.start()
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# PyParticles : Particles simulation in python
|
|
2
|
+
# Copyright (C) 2012 Simone Riva mail: simone.rva {at} gmail {dot} com
|
|
3
|
+
#
|
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
import numpy as np
|
|
19
|
+
|
|
20
|
+
import pyparticles.pset.particles_set as ps
|
|
21
|
+
import pyparticles.pset.default_boundary as db
|
|
22
|
+
|
|
23
|
+
import pyparticles.forces.electromagnetic_field as elmf
|
|
24
|
+
|
|
25
|
+
import pyparticles.ode.euler_solver as els
|
|
26
|
+
import pyparticles.ode.leapfrog_solver as lps
|
|
27
|
+
import pyparticles.ode.runge_kutta_solver as rks
|
|
28
|
+
import pyparticles.ode.stormer_verlet_solver as svs
|
|
29
|
+
import pyparticles.ode.midpoint_solver as mds
|
|
30
|
+
|
|
31
|
+
import pyparticles.animation.animated_ogl as aogl
|
|
32
|
+
import pyparticles.ogl.draw_particles_ogl as drp
|
|
33
|
+
|
|
34
|
+
def electric_field( E , X ):
|
|
35
|
+
E[:] = np.array( [ 10 , 10 , 10 ] )
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def magnetic_field( B , X ):
|
|
39
|
+
#B[:] = 1000.0 * np.sin( 500.0 * X )
|
|
40
|
+
B[:] = np.array( [ 0 , 0 , 1000 ] )
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def magf_color( RGBA , X ):
|
|
44
|
+
RGBA[:] = np.array([ 0.4 , 0.4 , 1.0 , 0.6 ])
|
|
45
|
+
|
|
46
|
+
def elf_color( RGBA , X ):
|
|
47
|
+
RGBA[:] = np.array([ 0.4 , 1.0 , 0.4 , 0.6 ])
|
|
48
|
+
|
|
49
|
+
def default_pos( pset , indx ):
|
|
50
|
+
pset.X[indx,:] = 0.0
|
|
51
|
+
pset.V[indx,:] = ( ( np.random.rand( len(indx) , 3 ) - 0.5 ) / 3.0 )
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def electromag_field():
|
|
55
|
+
"""
|
|
56
|
+
Electrimagnetic field demo
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
steps = 1000000
|
|
60
|
+
size = 25000
|
|
61
|
+
dt = 1e-4
|
|
62
|
+
|
|
63
|
+
qe = 1.60217646e-19
|
|
64
|
+
|
|
65
|
+
me = 9.10938188e-31
|
|
66
|
+
mp = 1.67262158e-18
|
|
67
|
+
|
|
68
|
+
pset = ps.ParticlesSet( size , charge=True )
|
|
69
|
+
|
|
70
|
+
pset.X[:] = 10.0e-3 * ( ( 2.0*np.random.rand( size , 3 ) - 1.0 ) )
|
|
71
|
+
|
|
72
|
+
pset.Q[:] = qe * np.sign( np.random.rand( size , 1 ) - 0.5 )
|
|
73
|
+
|
|
74
|
+
pset.V[:] = 0.5 * ( ( np.random.rand( size , 3 ) - 0.5 ) / 2.0 )
|
|
75
|
+
|
|
76
|
+
pset.M[:] = mp
|
|
77
|
+
|
|
78
|
+
elmag = elmf.ElectromagneticField( pset.size , dim=pset.dim , m=pset.M , q=pset.Q )
|
|
79
|
+
|
|
80
|
+
elmag.append_electric_field( electric_field )
|
|
81
|
+
elmag.append_magnetic_field( magnetic_field )
|
|
82
|
+
|
|
83
|
+
#solver = els.EulerSolver( elmag , pset , dt )
|
|
84
|
+
#solver = lps.LeapfrogSolver( elmag , pset , dt )
|
|
85
|
+
#solver = svs.StormerVerletSolver( elmag , pset , dt )
|
|
86
|
+
#solver = rks.RungeKuttaSolver( elmag , pset , dt )
|
|
87
|
+
solver = mds.MidpointSolver( elmag , pset , dt )
|
|
88
|
+
|
|
89
|
+
pset.unit = 2e-3
|
|
90
|
+
pset.mass_unit = 1e-3
|
|
91
|
+
|
|
92
|
+
bound = db.DefaultBoundary( ( -pset.unit*5.0 , pset.unit*5.0 ) , dim=3 , defualt_pos=default_pos )
|
|
93
|
+
pset.set_boundary(bound)
|
|
94
|
+
|
|
95
|
+
pset.enable_log( True , log_max_size=200 )
|
|
96
|
+
|
|
97
|
+
solver.update_force()
|
|
98
|
+
|
|
99
|
+
a = aogl.AnimatedGl()
|
|
100
|
+
|
|
101
|
+
a.ode_solver = solver
|
|
102
|
+
|
|
103
|
+
a.trajectory = False
|
|
104
|
+
|
|
105
|
+
a.xlim = ( -pset.unit*5.0 , pset.unit*5.0 )
|
|
106
|
+
a.ylim = ( -pset.unit*5.0 , pset.unit*5.0 )
|
|
107
|
+
a.zlim = ( -pset.unit*5.0 , pset.unit*5.0 )
|
|
108
|
+
|
|
109
|
+
a.add_vector_field_fun( magnetic_field , 2000.0 , pset.unit , color_fun=magf_color )
|
|
110
|
+
a.add_vector_field_fun( electric_field , 50.0 , pset.unit , color_fun=elf_color )
|
|
111
|
+
|
|
112
|
+
a.draw_vector_field = False
|
|
113
|
+
|
|
114
|
+
a.pset = pset
|
|
115
|
+
a.steps = steps
|
|
116
|
+
|
|
117
|
+
a.draw_particles.color_fun = drp.charged_particles_color
|
|
118
|
+
|
|
119
|
+
a.draw_particles.vect_color_fun = drp.charged_particles_vect_color
|
|
120
|
+
|
|
121
|
+
a.draw_particles.set_draw_model( a.draw_particles.DRAW_MODEL_VECTOR )
|
|
122
|
+
|
|
123
|
+
a.build_animation()
|
|
124
|
+
|
|
125
|
+
a.start()
|
|
126
|
+
|
|
127
|
+
return
|
|
128
|
+
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# PyParticles : Particles simulation in python
|
|
2
|
+
# Copyright (C) 2012 Simone Riva
|
|
3
|
+
#
|
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
|
|
17
|
+
import numpy as np
|
|
18
|
+
|
|
19
|
+
import pyparticles.pset.particles_set as ps
|
|
20
|
+
|
|
21
|
+
import pyparticles.forces.electrostatic as esf
|
|
22
|
+
|
|
23
|
+
import pyparticles.ode.euler_solver as els
|
|
24
|
+
import pyparticles.ode.leapfrog_solver as lps
|
|
25
|
+
import pyparticles.ode.runge_kutta_solver as rks
|
|
26
|
+
import pyparticles.ode.stormer_verlet_solver as svs
|
|
27
|
+
import pyparticles.ode.midpoint_solver as mds
|
|
28
|
+
|
|
29
|
+
import pyparticles.measures.kinetic_energy as ke
|
|
30
|
+
import pyparticles.measures.total_energy as te
|
|
31
|
+
|
|
32
|
+
import pyparticles.pset.rand_cluster as rc
|
|
33
|
+
import pyparticles.pset.rebound_boundary as rb
|
|
34
|
+
|
|
35
|
+
import pyparticles.animation.animated_ogl as aogl
|
|
36
|
+
import pyparticles.ogl.draw_particles_ogl as drp
|
|
37
|
+
|
|
38
|
+
import sys
|
|
39
|
+
|
|
40
|
+
def electro():
|
|
41
|
+
"""
|
|
42
|
+
Electrostatic demo
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
steps = 1000000
|
|
46
|
+
dt = 0.01
|
|
47
|
+
|
|
48
|
+
r_min=1.5
|
|
49
|
+
|
|
50
|
+
Ke = 8.9875517873681764e9
|
|
51
|
+
qe = 1.60217646e-19 * 1.0e8
|
|
52
|
+
|
|
53
|
+
me = 9.10938188e-31
|
|
54
|
+
mp = 1.67262158e-18
|
|
55
|
+
|
|
56
|
+
rand_c = rc.RandCluster()
|
|
57
|
+
|
|
58
|
+
pset = ps.ParticlesSet( 10 , charge=True )
|
|
59
|
+
|
|
60
|
+
pset.Q[:5] = qe
|
|
61
|
+
pset.Q[5:10] = -qe
|
|
62
|
+
|
|
63
|
+
pset.M[:] = 1e-3
|
|
64
|
+
|
|
65
|
+
pset.V[:] = 0.0
|
|
66
|
+
|
|
67
|
+
pset.X[:] = 1.0e-3 * np.array( [
|
|
68
|
+
[ 0.0 , 0.0 , 0.0 ] ,
|
|
69
|
+
[ 0.0 , 0.0 , 1.0 ] ,
|
|
70
|
+
[ 0.0 , 0.0 , -1.0 ] ,
|
|
71
|
+
[ 0.0 , 1.0 , 1.0 ] ,
|
|
72
|
+
[ -1.0 , -1.0 , -1.0 ] ,
|
|
73
|
+
[ 2.0 , -2.0 , 4.0 ] ,
|
|
74
|
+
[ 4.0 , 7.0 , 2.0 ] ,
|
|
75
|
+
[ -3.0 , -5.0 , 1.0 ] ,
|
|
76
|
+
[ 4.0 , 4.0 , -7.0 ] ,
|
|
77
|
+
[ 2.0 , 8.0 , -6.0 ]
|
|
78
|
+
]
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
#rand_c.insert3( X=pset.X ,
|
|
82
|
+
# M=pset.M ,
|
|
83
|
+
# start_indx=0 ,
|
|
84
|
+
# n=pset.size ,
|
|
85
|
+
# radius=5.0 ,
|
|
86
|
+
# mass_rng=(0.5,0.8) ,
|
|
87
|
+
# r_min=0.0 )
|
|
88
|
+
|
|
89
|
+
elecs = esf.Electrostatic( pset.size , dim=3 , Consts=Ke )
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
elecs.set_masses( pset.M )
|
|
93
|
+
elecs.set_charges( pset.Q )
|
|
94
|
+
|
|
95
|
+
#solver = els.EulerSolver( multif , pset , dt )
|
|
96
|
+
#solver = lps.LeapfrogSolver( lennard_jones , pset , dt )
|
|
97
|
+
#solver = svs.StormerVerletSolver( multif , pset , dt )
|
|
98
|
+
solver = rks.RungeKuttaSolver( elecs , pset , dt )
|
|
99
|
+
#solver = mds.MidpointSolver( lennard_jones , pset , dt )
|
|
100
|
+
|
|
101
|
+
bound = rb.ReboundBoundary( bound=( -10.0e-3 , 10.0e-3 ) )
|
|
102
|
+
pset.set_boundary( bound )
|
|
103
|
+
|
|
104
|
+
pset.unit = 2e-3
|
|
105
|
+
pset.mass_unit = 1e-3
|
|
106
|
+
|
|
107
|
+
pset.enable_log( True , log_max_size=1000 )
|
|
108
|
+
|
|
109
|
+
solver.update_force()
|
|
110
|
+
|
|
111
|
+
a = aogl.AnimatedGl()
|
|
112
|
+
|
|
113
|
+
a.ode_solver = solver
|
|
114
|
+
|
|
115
|
+
a.trajectory = True
|
|
116
|
+
|
|
117
|
+
a.pset = pset
|
|
118
|
+
a.steps = steps
|
|
119
|
+
|
|
120
|
+
a.draw_particles.color_fun = drp.charged_particles_color
|
|
121
|
+
|
|
122
|
+
a.build_animation()
|
|
123
|
+
|
|
124
|
+
a.start()
|
|
125
|
+
|
|
126
|
+
return
|