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,222 @@
|
|
|
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.gravity as gr
|
|
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.animation.animated_ogl as aogl
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def solar_system():
|
|
36
|
+
"""
|
|
37
|
+
Solar system demo
|
|
38
|
+
"""
|
|
39
|
+
dt = 3.0*3600.0
|
|
40
|
+
steps = 1000000
|
|
41
|
+
|
|
42
|
+
G = 6.67384e-11
|
|
43
|
+
|
|
44
|
+
FLOOR = -10
|
|
45
|
+
CEILING = 10
|
|
46
|
+
|
|
47
|
+
pset = ps.ParticlesSet( 12 , 3 , label=True )
|
|
48
|
+
|
|
49
|
+
pset.label[0] = "Sun"
|
|
50
|
+
pset.label[1] = "Earth"
|
|
51
|
+
pset.label[2] = "Jupiter"
|
|
52
|
+
pset.label[3] = "Mars"
|
|
53
|
+
pset.label[4] = "Mercury"
|
|
54
|
+
pset.label[5] = "Neptune"
|
|
55
|
+
pset.label[6] = "Pluto"
|
|
56
|
+
pset.label[7] = "Saturn"
|
|
57
|
+
pset.label[8] = "Uranus"
|
|
58
|
+
pset.label[9] = "Venus"
|
|
59
|
+
pset.label[10] = "Ceres"
|
|
60
|
+
pset.label[11] = "Moon"
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# Coordinates
|
|
64
|
+
pset.X[:] = np.array( [
|
|
65
|
+
[ 0.00000000e+00 , 0.00000000e+00 , 0.00000000e+00], # Sun
|
|
66
|
+
[ 1.49597871e+11 , 0.00000000e+00 , 0.00000000e+00], # Earth
|
|
67
|
+
[ 7.78357721e+11 , 0.00000000e+00 , 0.00000000e+00], # Jupiter
|
|
68
|
+
[ 2.27987155e+11 , 0.00000000e+00 , 0.00000000e+00], # Mars
|
|
69
|
+
[ 5.83431696e+10 , 0.00000000e+00 , 0.00000000e+00], # Mercury
|
|
70
|
+
[ 4.49691199e+12 , 0.00000000e+00 , 0.00000000e+00], # Neptune
|
|
71
|
+
[ 5.91360383e+12 , 0.00000000e+00 , 0.00000000e+00], # Pluto
|
|
72
|
+
[ 1.42701409e+12 , 0.00000000e+00 , 0.00000000e+00], # Saturn
|
|
73
|
+
[ 2.86928716e+12 , 0.00000000e+00 , 0.00000000e+00], # Uranus
|
|
74
|
+
[ 1.04718509e+11 , 0.00000000e+00 , 0.00000000e+00], # Venus
|
|
75
|
+
[ 4.138325875e+11, 0.00000000e+00 , 0.00000000e+00], # Ceres
|
|
76
|
+
[ 1.499604410e+11, 0.00000000e+00 , 0.00000000e+00] # Moon
|
|
77
|
+
])
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# Mass
|
|
81
|
+
pset.M[:] = np.array( [
|
|
82
|
+
[ 1.98910000e+30] ,
|
|
83
|
+
[ 5.98000000e+24] ,
|
|
84
|
+
[ 1.90000000e+27] ,
|
|
85
|
+
[ 6.42000000e+23] ,
|
|
86
|
+
[ 3.30000000e+23] ,
|
|
87
|
+
[ 1.02000000e+26] ,
|
|
88
|
+
[ 1.29000000e+22] ,
|
|
89
|
+
[ 5.69000000e+26] ,
|
|
90
|
+
[ 8.68000000e+25] ,
|
|
91
|
+
[ 4.87000000e+24] ,
|
|
92
|
+
[ 9.43000000e+20] ,
|
|
93
|
+
[ 7.34770000e+22]
|
|
94
|
+
] )
|
|
95
|
+
|
|
96
|
+
# Speed
|
|
97
|
+
pset.V[:] = np.array( [ [ 0. , 0. , 0.] ,
|
|
98
|
+
[ 0. , 29800. , 0.] ,
|
|
99
|
+
[ 0. , 13100. , 0.] ,
|
|
100
|
+
[ 0. , 24100. , 0.] ,
|
|
101
|
+
[ 0. , 47900. , 0.] ,
|
|
102
|
+
[ 0. , 5400. , 0.] ,
|
|
103
|
+
[ 0. , 4700. , 0.] ,
|
|
104
|
+
[ 0. , 9600. , 0.] ,
|
|
105
|
+
[ 0. , 6800. , 0.] ,
|
|
106
|
+
[ 0. , 35000. , 0.] ,
|
|
107
|
+
[ 0 , 17882. , 0.] ,
|
|
108
|
+
[ 0 , 30822. , 0.]
|
|
109
|
+
] )
|
|
110
|
+
|
|
111
|
+
# Inclination
|
|
112
|
+
incl = np.array([ 0.0 ,
|
|
113
|
+
0.0 ,
|
|
114
|
+
1.305 ,
|
|
115
|
+
1.850 ,
|
|
116
|
+
7.005 ,
|
|
117
|
+
1.767975,
|
|
118
|
+
17.151 ,
|
|
119
|
+
2.485 ,
|
|
120
|
+
0.772 ,
|
|
121
|
+
3.394 ,
|
|
122
|
+
10.587 ,
|
|
123
|
+
0.0 ,
|
|
124
|
+
])
|
|
125
|
+
|
|
126
|
+
# Longitude of the ascending node
|
|
127
|
+
lan = np.array([ 0.0 ,
|
|
128
|
+
348.73936 ,
|
|
129
|
+
100.492 ,
|
|
130
|
+
49.562 ,
|
|
131
|
+
48.331 ,
|
|
132
|
+
131.794310 ,
|
|
133
|
+
110.286 ,
|
|
134
|
+
113.642 ,
|
|
135
|
+
73.989 ,
|
|
136
|
+
76.678 ,
|
|
137
|
+
80.3932 ,
|
|
138
|
+
348.73936
|
|
139
|
+
])
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
incl[:] = incl * 2.0*np.pi / 360.0
|
|
144
|
+
|
|
145
|
+
lan[:] = lan * 2.0*np.pi / 360.0
|
|
146
|
+
|
|
147
|
+
pset.V[:,2] = np.sin( incl ) * pset.V[:,1]
|
|
148
|
+
pset.V[:,1] = np.cos( incl ) * pset.V[:,1]
|
|
149
|
+
|
|
150
|
+
for i in range ( pset.V.shape[0] ) :
|
|
151
|
+
x = pset.V[i,0]
|
|
152
|
+
y = pset.V[i,1]
|
|
153
|
+
|
|
154
|
+
pset.V[i,0] = x * np.cos( lan[i] ) - y * np.sin( lan[i] )
|
|
155
|
+
pset.V[i,1] = x * np.sin( lan[i] ) + y * np.cos( lan[i] )
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
for i in range ( pset.X.shape[0] ) :
|
|
159
|
+
x = pset.X[i,0]
|
|
160
|
+
y = pset.X[i,1]
|
|
161
|
+
|
|
162
|
+
pset.X[i,0] = x * np.cos( lan[i] ) - y * np.sin( lan[i] )
|
|
163
|
+
pset.X[i,1] = x * np.sin( lan[i] ) + y * np.cos( lan[i] )
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
#outf = fc.FileCluster()
|
|
167
|
+
#outf.open( "solar_system.csv" , "wb" )
|
|
168
|
+
#outf.write_out( pset )
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
pset.unit = 149597870700.0
|
|
172
|
+
pset.mass_unit = 5.9736e24
|
|
173
|
+
|
|
174
|
+
grav = gr.Gravity( pset.size , Consts=G )
|
|
175
|
+
|
|
176
|
+
grav.set_masses( pset.M )
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
bound = None
|
|
180
|
+
|
|
181
|
+
pset.set_boundary( bound )
|
|
182
|
+
|
|
183
|
+
pset.enable_log( True , log_max_size=1000 )
|
|
184
|
+
|
|
185
|
+
grav.update_force( pset )
|
|
186
|
+
|
|
187
|
+
#solver = els.EulerSolver( grav , pset , dt )
|
|
188
|
+
#solver = lps.LeapfrogSolver( grav , pset , dt )
|
|
189
|
+
#solver = svs.StormerVerletSolver( grav , pset , dt )
|
|
190
|
+
#solver = rks.RungeKuttaSolver( grav , pset , dt )
|
|
191
|
+
solver = mds.MidpointSolver( grav , pset , dt )
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
ken = ke.KineticEnergy( pset , grav )
|
|
195
|
+
ken.set_str_format( "%e" )
|
|
196
|
+
|
|
197
|
+
#
|
|
198
|
+
ken.update_measure()
|
|
199
|
+
|
|
200
|
+
a = aogl.AnimatedGl()
|
|
201
|
+
# a = anim.AnimatedScatter()
|
|
202
|
+
|
|
203
|
+
a.trajectory = True
|
|
204
|
+
a.trajectory_step = 1
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
a.xlim = ( FLOOR , CEILING )
|
|
208
|
+
a.ylim = ( FLOOR , CEILING )
|
|
209
|
+
a.zlim = ( FLOOR , CEILING )
|
|
210
|
+
|
|
211
|
+
a.ode_solver = solver
|
|
212
|
+
a.pset = pset
|
|
213
|
+
a.steps = steps
|
|
214
|
+
|
|
215
|
+
a.add_measure( ken )
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
a.build_animation()
|
|
219
|
+
|
|
220
|
+
a.start()
|
|
221
|
+
|
|
222
|
+
return
|
|
@@ -0,0 +1,141 @@
|
|
|
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.linear_spring as ls
|
|
22
|
+
import pyparticles.forces.const_force as cf
|
|
23
|
+
import pyparticles.forces.multiple_force as mf
|
|
24
|
+
import pyparticles.forces.drag as dr
|
|
25
|
+
|
|
26
|
+
import pyparticles.pset.rebound_boundary as rb
|
|
27
|
+
|
|
28
|
+
import pyparticles.measures.elastic_potential_energy as epe
|
|
29
|
+
import pyparticles.measures.kinetic_energy as ke
|
|
30
|
+
import pyparticles.measures.momentum as mm
|
|
31
|
+
import pyparticles.measures.total_energy as te
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
import pyparticles.ode.euler_solver as els
|
|
36
|
+
import pyparticles.ode.leapfrog_solver as lps
|
|
37
|
+
import pyparticles.ode.runge_kutta_solver as rks
|
|
38
|
+
import pyparticles.ode.stormer_verlet_solver as svs
|
|
39
|
+
import pyparticles.ode.midpoint_solver as mds
|
|
40
|
+
|
|
41
|
+
import sys
|
|
42
|
+
|
|
43
|
+
import pyparticles.animation.animated_ogl as aogl
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def springs() :
|
|
47
|
+
"""
|
|
48
|
+
Springs demo
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
dt = 0.02
|
|
52
|
+
steps = 1000000
|
|
53
|
+
|
|
54
|
+
G = 0.5
|
|
55
|
+
|
|
56
|
+
pset = ps.ParticlesSet( 3 , 3 , label=True )
|
|
57
|
+
|
|
58
|
+
pset.label[0] = "1"
|
|
59
|
+
pset.label[1] = "2"
|
|
60
|
+
pset.label[2] = "3"
|
|
61
|
+
|
|
62
|
+
pset.X[:] = np.array( [
|
|
63
|
+
[ 2.0 , 4.0 , 1.0 ], # 1
|
|
64
|
+
[ -2.0 , -2.0 , 1.0 ], # 2
|
|
65
|
+
[ 3.0 , -3.0 , 2.0 ] # 3
|
|
66
|
+
] )
|
|
67
|
+
|
|
68
|
+
pset.M[:] = np.array( [
|
|
69
|
+
[ 1.0 ] ,
|
|
70
|
+
[ 1.0 ] ,
|
|
71
|
+
[ 1.5 ]
|
|
72
|
+
] )
|
|
73
|
+
|
|
74
|
+
pset.V[:] = np.array( [ [ 0. , 0. , 0.] ,
|
|
75
|
+
[ 0. , 0 , 0.] ,
|
|
76
|
+
[ 0. , 0 , 0.]
|
|
77
|
+
] )
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
springs = ls.LinearSpring( pset.size , Consts=G )
|
|
81
|
+
constf = cf.ConstForce( pset.size , u_force=[ 0,0,-1.5 ] )
|
|
82
|
+
drag = dr.Drag( pset.size , Consts=0.2 )
|
|
83
|
+
|
|
84
|
+
mlf = mf.MultipleForce( pset.size , 3 )
|
|
85
|
+
|
|
86
|
+
mlf.append_force( springs )
|
|
87
|
+
#mlf.append_force( constf )
|
|
88
|
+
#mlf.append_force( drag )
|
|
89
|
+
|
|
90
|
+
pot = epe.ElasticPotentialEnergy( pset , springs )
|
|
91
|
+
ken = ke.KineticEnergy( pset , springs )
|
|
92
|
+
tot = te.TotalEnergy( ken , pot )
|
|
93
|
+
|
|
94
|
+
#
|
|
95
|
+
pot.update_measure()
|
|
96
|
+
ken.update_measure()
|
|
97
|
+
tot.update_measure()
|
|
98
|
+
|
|
99
|
+
#
|
|
100
|
+
#print( "Potential = %f " % pot.value() )
|
|
101
|
+
#print( "Kinetic = %f " % ken.value() )
|
|
102
|
+
|
|
103
|
+
#P = mm.MomentumParticles( pset , subset=np.array([1,2]) , model="part_by_part")
|
|
104
|
+
#
|
|
105
|
+
#P.update_measure()
|
|
106
|
+
#
|
|
107
|
+
#print( P.value() )
|
|
108
|
+
|
|
109
|
+
bound = rb.ReboundBoundary( bound=(-10,10) )
|
|
110
|
+
pset.set_boundary( bound )
|
|
111
|
+
|
|
112
|
+
mlf.set_masses( pset.M )
|
|
113
|
+
springs.set_masses( pset.M )
|
|
114
|
+
|
|
115
|
+
springs.update_force( pset )
|
|
116
|
+
mlf.update_force( pset )
|
|
117
|
+
|
|
118
|
+
#solver = rks.RungeKuttaSolver( springs , pset , dt )
|
|
119
|
+
solver = rks.RungeKuttaSolver( mlf , pset , dt )
|
|
120
|
+
|
|
121
|
+
pset.enable_log( True , log_max_size=1000 )
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
a = aogl.AnimatedGl()
|
|
125
|
+
|
|
126
|
+
a.trajectory = True
|
|
127
|
+
a.trajectory_step = 1
|
|
128
|
+
|
|
129
|
+
a.ode_solver = solver
|
|
130
|
+
a.pset = pset
|
|
131
|
+
a.steps = steps
|
|
132
|
+
|
|
133
|
+
a.add_measure( ken )
|
|
134
|
+
a.add_measure( pot )
|
|
135
|
+
a.add_measure( tot )
|
|
136
|
+
|
|
137
|
+
a.build_animation()
|
|
138
|
+
|
|
139
|
+
a.start()
|
|
140
|
+
|
|
141
|
+
return
|
|
@@ -0,0 +1,135 @@
|
|
|
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
|
+
|
|
19
|
+
import numpy as np
|
|
20
|
+
|
|
21
|
+
import pyparticles.pset.particles_set as ps
|
|
22
|
+
|
|
23
|
+
import pyparticles.forces.linear_spring_constrained as lsc
|
|
24
|
+
|
|
25
|
+
import pyparticles.forces.const_force as cf
|
|
26
|
+
import pyparticles.forces.multiple_force as mf
|
|
27
|
+
import pyparticles.forces.drag as dr
|
|
28
|
+
import pyparticles.forces.damping as da
|
|
29
|
+
|
|
30
|
+
import pyparticles.pset.constrained_x as csx
|
|
31
|
+
import pyparticles.pset.constrained_force_interactions as cfi
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
import pyparticles.measures.elastic_potential_energy as epe
|
|
35
|
+
import pyparticles.measures.kinetic_energy as ke
|
|
36
|
+
import pyparticles.measures.momentum as mm
|
|
37
|
+
import pyparticles.measures.total_energy as te
|
|
38
|
+
|
|
39
|
+
import pyparticles.animation.animated_ogl as aogl
|
|
40
|
+
|
|
41
|
+
import pyparticles.ode.euler_solver_constrained as asc
|
|
42
|
+
import pyparticles.ode.leapfrog_solver_constrained as lpc
|
|
43
|
+
import pyparticles.ode.stormer_verlet_solver_constrained as svc
|
|
44
|
+
import pyparticles.ode.runge_kutta_solver_constrained as rkc
|
|
45
|
+
import pyparticles.ode.midpoint_solver_constrained as mdc
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def spring_constr():
|
|
49
|
+
"""
|
|
50
|
+
Constrained catenary springs demo
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
dt = 0.01
|
|
54
|
+
steps = 1000000
|
|
55
|
+
|
|
56
|
+
K = 30
|
|
57
|
+
|
|
58
|
+
x = list([])
|
|
59
|
+
m = list([])
|
|
60
|
+
#v = list([])
|
|
61
|
+
|
|
62
|
+
d = 0.1
|
|
63
|
+
|
|
64
|
+
ar = np.arange( -4.0 , 4.0+d , d )
|
|
65
|
+
|
|
66
|
+
for i in ar :
|
|
67
|
+
x.append( list( [i,i,3.0] ) )
|
|
68
|
+
m.append( list([ 1.0 / float( len(ar) ) ] ) )
|
|
69
|
+
#v.append( list([0.0]) )
|
|
70
|
+
|
|
71
|
+
pset = ps.ParticlesSet( len(ar) , 3 )
|
|
72
|
+
|
|
73
|
+
pset.X[:] = np.array( x , np.float64 )
|
|
74
|
+
pset.M[:] = np.array( m , np.float64 )
|
|
75
|
+
pset.V[:] = 0.0
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
pset.X[10:12,2] = 4
|
|
79
|
+
#pset.X[10:15,1] = 6
|
|
80
|
+
|
|
81
|
+
ci = np.array( [ 0 , len(ar)-1 ] )
|
|
82
|
+
cx = np.array( [
|
|
83
|
+
[ -4.0 , -4.0 , 3.0] ,
|
|
84
|
+
[ 4.0 , 4.0 , 3.0]
|
|
85
|
+
] )
|
|
86
|
+
|
|
87
|
+
f_conn = list([])
|
|
88
|
+
for i in range( len(ar) - 1 ):
|
|
89
|
+
f_conn.append( list( [ i , i+1 ] ) )
|
|
90
|
+
|
|
91
|
+
f_conn = np.array( f_conn , np.float64 )
|
|
92
|
+
|
|
93
|
+
costrs = csx.ConstrainedX( pset )
|
|
94
|
+
costrs.add_x_constraint( ci , cx )
|
|
95
|
+
|
|
96
|
+
fi = cfi.ConstrainedForceInteractions( pset )
|
|
97
|
+
|
|
98
|
+
fi.add_connections( f_conn )
|
|
99
|
+
|
|
100
|
+
spring = lsc.LinearSpringConstrained( pset.size , pset.dim , pset.M , Consts=K , f_inter=fi )
|
|
101
|
+
constf = cf.ConstForce( pset.size , dim=pset.dim , u_force=[ 0 , 0 , -10 ] )
|
|
102
|
+
drag = dr.Drag( pset.size , pset.dim , Consts=0.003 )
|
|
103
|
+
#damp = da.Damping( pset.size , pset.dim , Consts=0.003 )
|
|
104
|
+
|
|
105
|
+
multif = mf.MultipleForce( pset.size , pset.dim )
|
|
106
|
+
multif.append_force( spring )
|
|
107
|
+
multif.append_force( constf )
|
|
108
|
+
multif.append_force( drag )
|
|
109
|
+
|
|
110
|
+
multif.set_masses( pset.M )
|
|
111
|
+
|
|
112
|
+
#solver = asc.EulerSolverConstrained( multif , pset , dt , costrs )
|
|
113
|
+
#solver = lpc.LeapfrogSolverConstrained( multif , pset , dt , costrs )
|
|
114
|
+
#solver = svc.StormerVerletSolverConstrained( multif , pset , dt , costrs )
|
|
115
|
+
#solver = rkc.RungeKuttaSolverConstrained( multif , pset , dt , costrs )
|
|
116
|
+
solver = mdc.MidpointSolverConstrained( multif , pset , dt , costrs )
|
|
117
|
+
|
|
118
|
+
a = aogl.AnimatedGl()
|
|
119
|
+
|
|
120
|
+
pset.enable_log( True , log_max_size=1000 )
|
|
121
|
+
|
|
122
|
+
a.trajectory = False
|
|
123
|
+
a.trajectory_step = 1
|
|
124
|
+
|
|
125
|
+
a.ode_solver = solver
|
|
126
|
+
a.pset = pset
|
|
127
|
+
a.steps = steps
|
|
128
|
+
|
|
129
|
+
a.init_rotation( -80 , [ 0.7 , 0.05 , 0 ] )
|
|
130
|
+
|
|
131
|
+
a.build_animation()
|
|
132
|
+
|
|
133
|
+
a.start()
|
|
134
|
+
|
|
135
|
+
return
|
pyparticles/demo/test.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
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 pyparticles.animation.test_animation as tt
|
|
19
|
+
|
|
20
|
+
def test( ty ):
|
|
21
|
+
"""
|
|
22
|
+
testing procedures
|
|
23
|
+
|
|
24
|
+
ty: test name
|
|
25
|
+
"""
|
|
26
|
+
if ty == "fall":
|
|
27
|
+
tst = tt.TestAnimation()
|
|
28
|
+
elif ty == "harmonic" :
|
|
29
|
+
tst = tt.TestAnimationHarmonic()
|
|
30
|
+
elif ty == "dharmonic" :
|
|
31
|
+
tst = tt.TestAnimationDampedHarmonic()
|
|
32
|
+
|
|
33
|
+
tst.build_animation()
|
|
34
|
+
tst.start()
|
|
@@ -0,0 +1,21 @@
|
|
|
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 os
|
|
19
|
+
import glob
|
|
20
|
+
|
|
21
|
+
__all__ = [ os.path.splitext( os.path.basename(f) )[0] for f in glob.glob(os.path.dirname(os.path.abspath(__file__))+"/*.py")]
|
|
@@ -0,0 +1,140 @@
|
|
|
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
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
import pyparticles.forces.force as fr
|
|
12
|
+
import pyparticles.pset.opencl_context as occ
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
import pyopencl as cl
|
|
16
|
+
except ImportError:
|
|
17
|
+
cl = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ConstForce(fr.Force):
|
|
21
|
+
"""Constant acceleration field."""
|
|
22
|
+
|
|
23
|
+
def __init__(self, size, dim=3, m=None, u_force=(0, 0, 0), Consts=1.0):
|
|
24
|
+
self.__dim = int(dim)
|
|
25
|
+
self.__size = int(size)
|
|
26
|
+
self.__G = Consts
|
|
27
|
+
self.__UF = np.asarray(u_force, dtype=float)
|
|
28
|
+
self.__A = np.zeros((size, dim))
|
|
29
|
+
self.__M = np.zeros((size, 1))
|
|
30
|
+
self.__A[:] = self.__UF
|
|
31
|
+
|
|
32
|
+
if m is not None:
|
|
33
|
+
self.set_masses(m)
|
|
34
|
+
|
|
35
|
+
def set_masses(self, m):
|
|
36
|
+
self.__M[:] = m
|
|
37
|
+
|
|
38
|
+
def update_force(self, p_set):
|
|
39
|
+
return self.__A
|
|
40
|
+
|
|
41
|
+
def getA(self):
|
|
42
|
+
return self.__A
|
|
43
|
+
|
|
44
|
+
A = property(getA)
|
|
45
|
+
|
|
46
|
+
def getF(self):
|
|
47
|
+
return self.__A * self.__M
|
|
48
|
+
|
|
49
|
+
F = property(getF)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class ConstForceOCL(fr.Force):
|
|
53
|
+
"""Constant acceleration field accumulated directly in an OpenCL A buffer."""
|
|
54
|
+
|
|
55
|
+
def __init__(self, size, dim=3, m=None, u_force=(0, 0, 0), Consts=1.0, ocl_context=None):
|
|
56
|
+
if cl is None:
|
|
57
|
+
raise RuntimeError("PyOpenCL is required for ConstForceOCL")
|
|
58
|
+
if int(dim) != 3:
|
|
59
|
+
raise ValueError("ConstForceOCL currently supports only 3 dimensions")
|
|
60
|
+
|
|
61
|
+
self.__size = int(size)
|
|
62
|
+
self.__dim = int(dim)
|
|
63
|
+
self.__occ = ocl_context or occ.OpenCLcontext(size, dim, occ.OCLC_A | occ.OCLC_M)
|
|
64
|
+
self.__dtype = self.__occ.dtype
|
|
65
|
+
self.__UF = np.asarray(u_force, dtype=self.__dtype).reshape(3)
|
|
66
|
+
self.__A = np.zeros((size, dim), dtype=self.__dtype)
|
|
67
|
+
self.__M = np.zeros((size, 1), dtype=self.__dtype)
|
|
68
|
+
|
|
69
|
+
source = r"""
|
|
70
|
+
__kernel void const_force(
|
|
71
|
+
float ax,
|
|
72
|
+
float ay,
|
|
73
|
+
float az,
|
|
74
|
+
int accumulate,
|
|
75
|
+
__global float *A)
|
|
76
|
+
{
|
|
77
|
+
int i = get_global_id(0);
|
|
78
|
+
int i0 = 3*i;
|
|
79
|
+
int i1 = i0 + 1;
|
|
80
|
+
int i2 = i0 + 2;
|
|
81
|
+
|
|
82
|
+
if (accumulate)
|
|
83
|
+
{
|
|
84
|
+
A[i0] += ax;
|
|
85
|
+
A[i1] += ay;
|
|
86
|
+
A[i2] += az;
|
|
87
|
+
}
|
|
88
|
+
else
|
|
89
|
+
{
|
|
90
|
+
A[i0] = ax;
|
|
91
|
+
A[i1] = ay;
|
|
92
|
+
A[i2] = az;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
"""
|
|
96
|
+
self.__program = cl.Program(self.__occ.CL_context, source).build()
|
|
97
|
+
self.__kernel = cl.Kernel(self.__program, "const_force")
|
|
98
|
+
|
|
99
|
+
if m is not None:
|
|
100
|
+
self.set_masses(m)
|
|
101
|
+
|
|
102
|
+
def set_masses(self, m):
|
|
103
|
+
self.__M[:] = np.asarray(m, dtype=self.__dtype)
|
|
104
|
+
if self.__occ.M_cla is not None:
|
|
105
|
+
self.__occ.set_from_host("M", self.__M)
|
|
106
|
+
|
|
107
|
+
def update_force_device(self, p_set=None, accumulate=False, host_authoritative=False):
|
|
108
|
+
self.__kernel(
|
|
109
|
+
self.__occ.CL_queue,
|
|
110
|
+
(self.__size,),
|
|
111
|
+
None,
|
|
112
|
+
self.__dtype(self.__UF[0]),
|
|
113
|
+
self.__dtype(self.__UF[1]),
|
|
114
|
+
self.__dtype(self.__UF[2]),
|
|
115
|
+
np.int32(bool(accumulate)),
|
|
116
|
+
self.__occ.A_cla.data,
|
|
117
|
+
)
|
|
118
|
+
self.__occ.mark_device_modified("A")
|
|
119
|
+
return self.__occ.A_cla
|
|
120
|
+
|
|
121
|
+
def update_force(self, p_set):
|
|
122
|
+
self.update_force_device(p_set, accumulate=False)
|
|
123
|
+
self.__occ.sync_to_host("A", self.__A)
|
|
124
|
+
return self.__A
|
|
125
|
+
|
|
126
|
+
def getA(self):
|
|
127
|
+
return self.__A
|
|
128
|
+
|
|
129
|
+
A = property(getA)
|
|
130
|
+
|
|
131
|
+
def getF(self):
|
|
132
|
+
self.__occ.sync_to_host("A", self.__A)
|
|
133
|
+
return self.__A * self.__M
|
|
134
|
+
|
|
135
|
+
F = property(getF)
|
|
136
|
+
|
|
137
|
+
def get_ocl_context(self):
|
|
138
|
+
return self.__occ
|
|
139
|
+
|
|
140
|
+
ocl_context = property(get_ocl_context)
|