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,50 @@
|
|
|
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 numpy as np
|
|
19
|
+
import pyparticles.ode.ode_solver as os
|
|
20
|
+
import pyparticles.pset.particles_set as ps
|
|
21
|
+
|
|
22
|
+
class StormerVerletSolver( os.OdeSolver ) :
|
|
23
|
+
def __init__( self , force , p_set , dt ):
|
|
24
|
+
super(StormerVerletSolver,self).__init__( force , p_set , dt )
|
|
25
|
+
self.__pset_m1 = ps.ParticlesSet( p_set.size , p_set.dim , mass=False , velocity=False )
|
|
26
|
+
self.__pset_tmp = ps.ParticlesSet( p_set.size , p_set.dim , mass=False , velocity=False )
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def __step__( self , dt ):
|
|
30
|
+
|
|
31
|
+
self.force.update_force( self.pset )
|
|
32
|
+
|
|
33
|
+
if self.steps_cnt == 1 :
|
|
34
|
+
|
|
35
|
+
# for the firse step we use the Euler method
|
|
36
|
+
self.__pset_m1.X[:] = self.pset.X[:]
|
|
37
|
+
self.pset.V[:] = self.pset.V + self.force.A * dt
|
|
38
|
+
self.pset.X[:] = self.pset.X + self.pset.V * dt
|
|
39
|
+
|
|
40
|
+
else :
|
|
41
|
+
|
|
42
|
+
self.__pset_tmp.X[:] = self.pset.X
|
|
43
|
+
|
|
44
|
+
self.pset.X[:] = 2.0*self.pset.X[:] - self.__pset_m1.X[:] + self.force.A[:] * dt**2.0
|
|
45
|
+
self.pset.V[:] = ( self.__pset_tmp.X[:] - self.__pset_m1.X[:] ) / dt
|
|
46
|
+
|
|
47
|
+
self.__pset_m1.X[:] = self.__pset_tmp.X[:]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
self.pset.update_boundary()
|
|
@@ -0,0 +1,73 @@
|
|
|
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 numpy as np
|
|
19
|
+
import pyparticles.ode.ode_solver_constrained as osc
|
|
20
|
+
import pyparticles.pset.particles_set as ps
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class StormerVerletSolverConstrained( osc.OdeSolverConstrained ) :
|
|
24
|
+
def __init__( self , force , p_set , dt , x_constraint=None , v_constraint=None ):
|
|
25
|
+
super(StormerVerletSolverConstrained,self).__init__( force , p_set , dt , x_constraint=None , v_constraint=None )
|
|
26
|
+
|
|
27
|
+
self.__pset_m1 = ps.ParticlesSet( p_set.size , p_set.dim , mass=False , velocity=False )
|
|
28
|
+
self.__pset_tmp = ps.ParticlesSet( p_set.size , p_set.dim , mass=False , velocity=False )
|
|
29
|
+
|
|
30
|
+
if x_constraint != None :
|
|
31
|
+
self.x_constraint = x_constraint
|
|
32
|
+
|
|
33
|
+
def get_x_constraint(self):
|
|
34
|
+
return super(StormerVerletSolverConstrained,self).get_x_constraint()
|
|
35
|
+
|
|
36
|
+
def set_x_constraint(self , xc ):
|
|
37
|
+
super(StormerVerletSolverConstrained,self).set_x_constraint( xc )
|
|
38
|
+
|
|
39
|
+
self.__free_inx = self.x_constraint.get_cx_free_indicies()
|
|
40
|
+
self.__csrt_inx = self.x_constraint.get_cx_indicies()
|
|
41
|
+
|
|
42
|
+
x_constraint = property( get_x_constraint , set_x_constraint , doc="get and set the current positionals constraints" )
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def __step__( self , dt ):
|
|
46
|
+
|
|
47
|
+
self.force.update_force( self.pset )
|
|
48
|
+
|
|
49
|
+
if self.steps_cnt == 1 :
|
|
50
|
+
|
|
51
|
+
# for the firse step we use the Euler method
|
|
52
|
+
self.__pset_m1.X[:] = self.pset.X[:]
|
|
53
|
+
|
|
54
|
+
self.pset.V[self.__free_inx,:] = self.pset.V[self.__free_inx,:] + self.force.A[self.__free_inx,:] * dt
|
|
55
|
+
self.pset.X[self.__free_inx,:] = self.pset.X[self.__free_inx,:] + self.pset.V[self.__free_inx,:] * dt
|
|
56
|
+
|
|
57
|
+
self.pset.V[self.__csrt_inx,:] = 0.0
|
|
58
|
+
|
|
59
|
+
else :
|
|
60
|
+
|
|
61
|
+
self.__pset_tmp.X[:] = self.pset.X[:]
|
|
62
|
+
|
|
63
|
+
self.pset.X[self.__free_inx,:] = 2.0*self.pset.X[self.__free_inx,:] - self.__pset_m1.X[self.__free_inx,:] + self.force.A[self.__free_inx,:] * dt**2.0
|
|
64
|
+
self.pset.V[self.__free_inx,:] = ( self.__pset_tmp.X[self.__free_inx,:] - self.__pset_m1.X[self.__free_inx,:] ) / dt
|
|
65
|
+
|
|
66
|
+
self.__pset_m1.X[:] = self.__pset_tmp.X[:]
|
|
67
|
+
|
|
68
|
+
self.pset.V[self.__csrt_inx,:] = 0.0
|
|
69
|
+
|
|
70
|
+
self.pset.update_boundary()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
@@ -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,210 @@
|
|
|
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 numpy as np
|
|
19
|
+
|
|
20
|
+
import pyparticles.geometry.transformations as tr
|
|
21
|
+
|
|
22
|
+
from OpenGL.GL import *
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class AxisOgl(object):
|
|
26
|
+
def __init__(self):
|
|
27
|
+
self.__arrow_len = 5.0
|
|
28
|
+
self.__dl_axis = None
|
|
29
|
+
|
|
30
|
+
def __del__(self):
|
|
31
|
+
if self.__dl_axis != None :
|
|
32
|
+
glDeleteLists( self.__dl_axis , 1 )
|
|
33
|
+
|
|
34
|
+
def ogl_init( self ):
|
|
35
|
+
|
|
36
|
+
self.__dl_axis = glGenLists(1)
|
|
37
|
+
|
|
38
|
+
glNewList( self.__dl_axis , GL_COMPILE );
|
|
39
|
+
self.draw_axis_procedure()
|
|
40
|
+
glEndList()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def get_axis_len(self):
|
|
44
|
+
return self.__arrow_len
|
|
45
|
+
|
|
46
|
+
def set_axis_len( self , leng ):
|
|
47
|
+
self.__arrow_len = leng
|
|
48
|
+
|
|
49
|
+
axis_len = property( get_axis_len , set_axis_len )
|
|
50
|
+
|
|
51
|
+
def draw_axis( self ):
|
|
52
|
+
glCallList( self.__dl_axis )
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def draw_axis_procedure(self):
|
|
56
|
+
self.draw_arrow( ( 1.0 , 0.0 , 0.0 ) , "x" )
|
|
57
|
+
self.draw_arrow( ( 0.0 , 1.0 , 0.0 ) , "y" )
|
|
58
|
+
self.draw_arrow( ( 0.0 , 0.0 , 1.0 ) , "z" )
|
|
59
|
+
|
|
60
|
+
self.draw_arrow( ( 1.0 , 0.0 , 0.0 ) , "-x" )
|
|
61
|
+
self.draw_arrow( ( 0.0 , 1.0 , 0.0 ) , "-y" )
|
|
62
|
+
self.draw_arrow( ( 0.0 , 0.0 , 1.0 ) , "-z" )
|
|
63
|
+
|
|
64
|
+
for pl in self.axis_planes_codes():
|
|
65
|
+
self.draw_plane( pl )
|
|
66
|
+
|
|
67
|
+
def axis_planes_codes(self):
|
|
68
|
+
return [ "xy" , "x-y" , "-xy" , "-x-y" , "xz" , "x-z" , "-xz" , "-x-z" , "yz" , "y-z" , "-yz" , "-y-z" ]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def draw_plane( self , plane="xy", color=( 0.7 , 0.7 , 0.7 , 0.3 ) , leng=None ):
|
|
72
|
+
|
|
73
|
+
if leng == None :
|
|
74
|
+
leng = self.axis_len
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
t = tr.Transformations()
|
|
78
|
+
t.set_points_tuple_size(2)
|
|
79
|
+
|
|
80
|
+
if plane == "xy" :
|
|
81
|
+
t.rotX( np.radians(0) )
|
|
82
|
+
elif plane == "yz" :
|
|
83
|
+
t.rotY( np.radians(90) )
|
|
84
|
+
elif plane == "xz" :
|
|
85
|
+
t.rotX( np.radians(90) )
|
|
86
|
+
elif plane == "-yz" :
|
|
87
|
+
t.rotX( np.radians(180) )
|
|
88
|
+
t.rotY( np.radians(90) )
|
|
89
|
+
elif plane == "-y-z" :
|
|
90
|
+
t.rotX( np.radians(180) )
|
|
91
|
+
t.rotY( np.radians(-90) )
|
|
92
|
+
elif plane == "y-z" :
|
|
93
|
+
t.rotY( np.radians(-90) )
|
|
94
|
+
elif plane == "x-y" :
|
|
95
|
+
t.rotX( np.radians(180) )
|
|
96
|
+
elif plane == "-x-y" :
|
|
97
|
+
t.rotX( np.radians(180) )
|
|
98
|
+
t.rotY( np.radians(180) )
|
|
99
|
+
elif plane == "x-z" :
|
|
100
|
+
t.rotX( np.radians(-90) )
|
|
101
|
+
elif plane == "-x-z" :
|
|
102
|
+
t.rotX( np.radians(-90) )
|
|
103
|
+
t.rotZ( np.radians(180) )
|
|
104
|
+
elif plane == "-xz" :
|
|
105
|
+
t.rotX( np.radians(90) )
|
|
106
|
+
t.rotZ( np.radians(180) )
|
|
107
|
+
elif plane == "-x-z" :
|
|
108
|
+
t.rotX( np.radians(-90) )
|
|
109
|
+
t.rotZ( np.radians(180) )
|
|
110
|
+
elif plane == "-xy" :
|
|
111
|
+
t.rotY( np.radians(180) )
|
|
112
|
+
|
|
113
|
+
for i in range( 1 , int(leng) ):
|
|
114
|
+
t.append_point( [ float(i) , 0.0 , 0.0 ] )
|
|
115
|
+
t.append_point( [ float(i) , leng , 0.0 ] )
|
|
116
|
+
|
|
117
|
+
t.append_point( [ 0.0 , float(i) , 0.0 ] )
|
|
118
|
+
t.append_point( [ leng , float(i) , 0.0 ] )
|
|
119
|
+
|
|
120
|
+
glColor4f( color[0] , color[1] , color[2] , color[3] )
|
|
121
|
+
|
|
122
|
+
glBegin(GL_LINES)
|
|
123
|
+
|
|
124
|
+
for pts in t :
|
|
125
|
+
glVertex3fv( pts[0] )
|
|
126
|
+
glVertex3fv( pts[1] )
|
|
127
|
+
|
|
128
|
+
glEnd()
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
#t.set_points_tuple_size(4)
|
|
132
|
+
#
|
|
133
|
+
#t.append_point( [ 0.0 , 0.0 , 1.0 ] )
|
|
134
|
+
#t.append_point( [ 0.0 , 0.0 , 0.0 ] )
|
|
135
|
+
#t.append_point( [ leng , 0.0 , 0.0 ] )
|
|
136
|
+
#t.append_point( [ leng , leng , 0.0 ] )
|
|
137
|
+
#
|
|
138
|
+
#t.append_point( [ 0.0 , 0.0 , 1.0 ] )
|
|
139
|
+
#t.append_point( [ 0.0 , 0.0 , 0.0 ] )
|
|
140
|
+
#t.append_point( [ leng , leng , 0.0 ] )
|
|
141
|
+
#t.append_point( [ 0.0 , leng , 0.0 ] )
|
|
142
|
+
#
|
|
143
|
+
#glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
|
|
144
|
+
#
|
|
145
|
+
#glColor4f( color[0] , color[1] , color[2] , 1.0 )
|
|
146
|
+
#
|
|
147
|
+
#glBegin( GL_TRIANGLES )
|
|
148
|
+
#for pts in t :
|
|
149
|
+
# glNormal3fv( pts[0] )
|
|
150
|
+
# glVertex3fv( pts[1] )
|
|
151
|
+
# glVertex3fv( pts[2] )
|
|
152
|
+
# glVertex3fv( pts[3] )
|
|
153
|
+
#glEnd()
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def draw_arrow( self , color , axis , leng=None ):
|
|
159
|
+
|
|
160
|
+
if leng == None :
|
|
161
|
+
leng = self.axis_len
|
|
162
|
+
|
|
163
|
+
arrh = leng * 0.1
|
|
164
|
+
arrp = leng - arrh
|
|
165
|
+
|
|
166
|
+
dash = leng * 0.03
|
|
167
|
+
|
|
168
|
+
t = tr.Transformations()
|
|
169
|
+
t.set_points_tuple_size(2)
|
|
170
|
+
|
|
171
|
+
if axis == "x" :
|
|
172
|
+
t.rotX( np.radians(0) )
|
|
173
|
+
elif axis == "y" :
|
|
174
|
+
t.rotZ( np.radians(90) )
|
|
175
|
+
elif axis == "z" :
|
|
176
|
+
t.rotY( np.radians(-90) )
|
|
177
|
+
if axis == "-x" :
|
|
178
|
+
t.rotZ( np.radians(180) )
|
|
179
|
+
elif axis == "-y" :
|
|
180
|
+
t.rotZ( np.radians(-90) )
|
|
181
|
+
elif axis == "-z" :
|
|
182
|
+
t.rotY( np.radians(90) )
|
|
183
|
+
|
|
184
|
+
t.append_point( np.array( [ 0.0 , 0.0 , 0.0 ] ) )
|
|
185
|
+
t.append_point( np.array( [ leng , 0.0 , 0.0 ] ) )
|
|
186
|
+
|
|
187
|
+
t.append_point( np.array( [ leng , 0.0 , 0.0 ] ) )
|
|
188
|
+
t.append_point( np.array( [ arrp , -arrh , 0.0 ] ) )
|
|
189
|
+
|
|
190
|
+
t.append_point( np.array( [ leng , 0.0 , 0.0 ] ) )
|
|
191
|
+
t.append_point( np.array( [ arrp , arrh , 0.0 ] ) )
|
|
192
|
+
|
|
193
|
+
for i in range( 1 , int(leng) ):
|
|
194
|
+
t.append_point( [ float(i) , dash , 0.0 ] )
|
|
195
|
+
t.append_point( [ float(i) , -dash , 0.0 ] )
|
|
196
|
+
|
|
197
|
+
glColor3f( color[0] , color[1] , color[2] )
|
|
198
|
+
|
|
199
|
+
glBegin(GL_LINES)
|
|
200
|
+
|
|
201
|
+
for pts in t :
|
|
202
|
+
glVertex3fv( pts[0] )
|
|
203
|
+
glVertex3fv( pts[1] )
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
glEnd()
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
|
|
2
|
+
# PyParticles : Particles simulation in python
|
|
3
|
+
# Copyright (C) 2012 Simone Riva
|
|
4
|
+
#
|
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
import pyparticles.pset.particles_set as ps
|
|
19
|
+
|
|
20
|
+
import numpy as np
|
|
21
|
+
|
|
22
|
+
from OpenGL.GL import *
|
|
23
|
+
from OpenGL.GLUT import *
|
|
24
|
+
from OpenGL.GLU import *
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def charged_particles_color( pset , i ):
|
|
28
|
+
a = 0.4
|
|
29
|
+
|
|
30
|
+
if pset.Q[i] > 0.0 :
|
|
31
|
+
return ( 1.0 , a , a , 1.0 )
|
|
32
|
+
elif pset.Q[i] < 0.0 :
|
|
33
|
+
return ( a , a , 1.0 , 1.0 )
|
|
34
|
+
else :
|
|
35
|
+
return ( a , a , a , 1.0 )
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def rand_vect_colors( RGBA , pset ):
|
|
39
|
+
RGBA[:] = np.random.rand( pset.size , 4 )
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def charged_particles_vect_color( RGBA , pset ):
|
|
43
|
+
a = 0.4
|
|
44
|
+
|
|
45
|
+
i, foo = np.where( pset.Q > 0.0 )
|
|
46
|
+
RGBA[ i , : ] = np.array( [ 1.0 , a , a , 1.0 ] )
|
|
47
|
+
|
|
48
|
+
i, foo = np.where( pset.Q < 0.0 )
|
|
49
|
+
RGBA[ i , : ] = np.array( [ a , a , 1.0 , 1.0 ] )
|
|
50
|
+
|
|
51
|
+
i, foo = np.where( pset.Q == 0.0 )
|
|
52
|
+
RGBA[ i , : ] = np.array( [ a , a , a , 1.0 ] )
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class DrawParticlesGL(object):
|
|
56
|
+
|
|
57
|
+
DRAW_MODEL_LOOP = 0
|
|
58
|
+
DRAW_MODEL_VECTOR = 1
|
|
59
|
+
|
|
60
|
+
PARTICLE_MODEL_POINT = "point"
|
|
61
|
+
PARTICLE_MODEL_SPHERE = "sphere"
|
|
62
|
+
PARTICLE_MODEL_TEAPOT = "teapot"
|
|
63
|
+
|
|
64
|
+
def __init__( self , pset=None ):
|
|
65
|
+
self.pset = pset
|
|
66
|
+
self.__trajectory = False
|
|
67
|
+
self.__trajectory_step = 1
|
|
68
|
+
|
|
69
|
+
self.__color_fun = lambda pset , i : ( 1.0 , 1.0 , 1.0 , 1.0 )
|
|
70
|
+
|
|
71
|
+
self.__vect_color_fun = None
|
|
72
|
+
self.__vect_color_fun_fl = False
|
|
73
|
+
|
|
74
|
+
self.__draw_particle = self.draw_particle
|
|
75
|
+
|
|
76
|
+
self.__sph_dl = None
|
|
77
|
+
self.__tea_dl = None
|
|
78
|
+
self.__pt_dl = None
|
|
79
|
+
|
|
80
|
+
self.__draw_model = self.DRAW_MODEL_LOOP
|
|
81
|
+
|
|
82
|
+
self.__init_vect_fl = False
|
|
83
|
+
|
|
84
|
+
self.__log_indices = None
|
|
85
|
+
self.__log_array = None
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def __del__(self):
|
|
89
|
+
if self.__sph_dl != None :
|
|
90
|
+
glDeleteLists( self.__sph_dl , 1 )
|
|
91
|
+
|
|
92
|
+
if self.__tea_dl != None :
|
|
93
|
+
glDeleteLists( self.__tea_dl , 1 )
|
|
94
|
+
|
|
95
|
+
if self.__pt_dl != None :
|
|
96
|
+
glDeleteLists( self.__pt_dl , 1 )
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def ogl_init(self):
|
|
100
|
+
"""
|
|
101
|
+
Initialize opengl display lists (must be called after glutInit!)
|
|
102
|
+
"""
|
|
103
|
+
self.init_sphere_dl()
|
|
104
|
+
self.init_teapot_dl()
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
#######################
|
|
108
|
+
def get_pset(self):
|
|
109
|
+
return self.__pset
|
|
110
|
+
|
|
111
|
+
def set_pset(self , pset):
|
|
112
|
+
self.__pset = pset
|
|
113
|
+
|
|
114
|
+
pset = property( get_pset , set_pset )
|
|
115
|
+
|
|
116
|
+
########################
|
|
117
|
+
def set_color_fun( self , fun ):
|
|
118
|
+
self.__color_fun = fun
|
|
119
|
+
|
|
120
|
+
def get_color_fun( self , fun ):
|
|
121
|
+
return self.__color_fun
|
|
122
|
+
|
|
123
|
+
color_fun = property( get_color_fun , set_color_fun , doc="Set and get the function for calculating the particle color:\n"
|
|
124
|
+
" definition of the function color,"
|
|
125
|
+
" it take as args a particle_set obj. and the particle index "
|
|
126
|
+
" \n (R,G,B,A) = cfun( pset , index ) " )
|
|
127
|
+
|
|
128
|
+
def set_vect_color_fun( self , fun ):
|
|
129
|
+
self.__vect_color_fun = fun
|
|
130
|
+
|
|
131
|
+
def get_vect_color_fun( self , fun ):
|
|
132
|
+
return self.__vect_color_fun
|
|
133
|
+
|
|
134
|
+
vect_color_fun = property( get_vect_color_fun , set_vect_color_fun , doc="get and set the vector color function")
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def get_trajectory( self ) :
|
|
138
|
+
return self.__trajectory
|
|
139
|
+
|
|
140
|
+
def set_trajectory( self , tr ):
|
|
141
|
+
self.__trajectory = tr
|
|
142
|
+
|
|
143
|
+
trajectory = property( get_trajectory , set_trajectory , doc="enable or disable the trajectory" )
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def get_trajectory_step( self ) :
|
|
147
|
+
return self.__trajectory_step
|
|
148
|
+
|
|
149
|
+
def set_trajectory_step( self , trs ):
|
|
150
|
+
self.__trajectory_step = trs
|
|
151
|
+
|
|
152
|
+
trajectory_step = property( get_trajectory_step , set_trajectory_step , doc="set or get the step for drawing the trajectory" )
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def init_sphere_dl(self):
|
|
156
|
+
self.__sph_dl = glGenLists(1)
|
|
157
|
+
glNewList( self.__sph_dl , GL_COMPILE );
|
|
158
|
+
glutSolidSphere( 1.0 , 10 , 10 )
|
|
159
|
+
glEndList()
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def init_teapot_dl(self):
|
|
163
|
+
self.__tea_dl = glGenLists(1)
|
|
164
|
+
glNewList( self.__tea_dl , GL_COMPILE );
|
|
165
|
+
glutSolidTeapot( 1.0 )
|
|
166
|
+
glEndList()
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def set_particle_model( self , model="" , user_fun=None ):
|
|
171
|
+
|
|
172
|
+
if model == "point" :
|
|
173
|
+
self.__draw_particle = self.draw_particle
|
|
174
|
+
elif model == "sphere" :
|
|
175
|
+
self.__draw_particle = self.draw_particle_sphere
|
|
176
|
+
elif model == "teapot" :
|
|
177
|
+
self.__draw_particle = self.draw_particle_teapot
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def set_draw_model( self , model ):
|
|
181
|
+
self.__draw_model = model
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def draw_trajectory(self):
|
|
185
|
+
|
|
186
|
+
if self.pset.log_size < self.trajectory_step + 1 :
|
|
187
|
+
return
|
|
188
|
+
|
|
189
|
+
if self.__log_indices == None :
|
|
190
|
+
self.__log_indices = self.pset.get_log_indices_segments( True )
|
|
191
|
+
self.__log_array = np.zeros( ( self.pset.log_max_size , self.pset.dim ) )
|
|
192
|
+
|
|
193
|
+
unit = self.pset.unit
|
|
194
|
+
glLineWidth( 1.0 )
|
|
195
|
+
|
|
196
|
+
for i in range( self.pset.size ):
|
|
197
|
+
glColor4f( *self.__color_fun( self.pset , i ) )
|
|
198
|
+
|
|
199
|
+
glEnableClientState(GL_VERTEX_ARRAY)
|
|
200
|
+
|
|
201
|
+
( b , e ) = self.pset.read_log_array( i , ( self.__log_array, ) )
|
|
202
|
+
|
|
203
|
+
glVertexPointer( 3 , GL_FLOAT , 0 , self.__log_array / unit )
|
|
204
|
+
|
|
205
|
+
glDrawElements( GL_LINES , e , GL_UNSIGNED_INT , self.__log_indices )
|
|
206
|
+
|
|
207
|
+
glDisableClientState(GL_VERTEX_ARRAY)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def get_pcolor(self):
|
|
211
|
+
return
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def draw_particle( self , pset , i ):
|
|
215
|
+
glPointSize( 0.01 + self.pset.M[i] / self.pset.mass_unit )
|
|
216
|
+
glColor4f( *self.__color_fun( pset , i ) )
|
|
217
|
+
|
|
218
|
+
glBegin(GL_POINTS)
|
|
219
|
+
|
|
220
|
+
glVertex3f( self.pset.X[i,0] / self.pset.unit ,
|
|
221
|
+
self.pset.X[i,1] / self.pset.unit ,
|
|
222
|
+
self.pset.X[i,2] / self.pset.unit )
|
|
223
|
+
|
|
224
|
+
glEnd()
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def draw_particle_sphere( self , pset , i ):
|
|
228
|
+
|
|
229
|
+
radius = 0.5 * ( 0.05 + 0.1 / ( 1.0 + np.exp( -self.pset.M[i] / self.pset.mass_unit ) ) )
|
|
230
|
+
|
|
231
|
+
glColor4f( *self.__color_fun( pset , i ) )
|
|
232
|
+
glPushMatrix()
|
|
233
|
+
glTranslatef( self.pset.X[i,0] / self.pset.unit ,
|
|
234
|
+
self.pset.X[i,1] / self.pset.unit ,
|
|
235
|
+
self.pset.X[i,2] / self.pset.unit )
|
|
236
|
+
|
|
237
|
+
glScalef( radius , radius , radius )
|
|
238
|
+
glCallList( self.__sph_dl )
|
|
239
|
+
|
|
240
|
+
glPopMatrix()
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def draw_particle_teapot( self , pset , i ):
|
|
244
|
+
|
|
245
|
+
radius = 0.5 * ( 0.05 + 0.1 / ( 1.0 + np.exp( -self.pset.M[i] / self.pset.mass_unit ) ) )
|
|
246
|
+
|
|
247
|
+
glColor4f( *self.__color_fun( pset , i ) )
|
|
248
|
+
glPushMatrix()
|
|
249
|
+
glTranslatef( self.pset.X[i,0] / self.pset.unit ,
|
|
250
|
+
self.pset.X[i,1] / self.pset.unit ,
|
|
251
|
+
self.pset.X[i,2] / self.pset.unit )
|
|
252
|
+
|
|
253
|
+
glScalef( radius , radius , radius )
|
|
254
|
+
glCallList( self.__tea_dl )
|
|
255
|
+
|
|
256
|
+
glPopMatrix()
|
|
257
|
+
|
|
258
|
+
def _draw_vectorized(self):
|
|
259
|
+
|
|
260
|
+
if not self.__init_vect_fl :
|
|
261
|
+
self.__indices = np.arange( self.pset.size * 3 , dtype=np.uint )
|
|
262
|
+
self.__init_vect_fl = True
|
|
263
|
+
|
|
264
|
+
if not self.__vect_color_fun_fl and self.__vect_color_fun != None :
|
|
265
|
+
self.__color_vect = np.zeros(( self.pset.size , 4 ))
|
|
266
|
+
self.__vect_color_fun( self.__color_vect , self.pset )
|
|
267
|
+
self.__vect_color_fun_fl = True
|
|
268
|
+
|
|
269
|
+
#glColor4f( *self.__color_fun( self.pset , 1 ) )
|
|
270
|
+
|
|
271
|
+
if self.__vect_color_fun_fl :
|
|
272
|
+
glEnableClientState(GL_COLOR_ARRAY)
|
|
273
|
+
|
|
274
|
+
glEnableClientState(GL_VERTEX_ARRAY)
|
|
275
|
+
|
|
276
|
+
if self.__vect_color_fun_fl :
|
|
277
|
+
glColorPointer( 4 , GL_FLOAT , 0 , self.__color_vect )
|
|
278
|
+
|
|
279
|
+
glVertexPointer( 3 , GL_FLOAT , 0 , self.pset.X / self.pset.unit )
|
|
280
|
+
glDrawElements( GL_POINTS , self.pset.size , GL_UNSIGNED_INT , self.__indices )
|
|
281
|
+
|
|
282
|
+
glDisableClientState(GL_VERTEX_ARRAY)
|
|
283
|
+
|
|
284
|
+
if self.__vect_color_fun_fl :
|
|
285
|
+
glDisableClientState(GL_COLOR_ARRAY)
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def draw(self):
|
|
289
|
+
|
|
290
|
+
if self.__draw_model == self.DRAW_MODEL_LOOP :
|
|
291
|
+
glPointParameterf( GL_POINT_SIZE_MAX , 10.0 )
|
|
292
|
+
glPointParameterf( GL_POINT_SIZE_MIN , 4.0 )
|
|
293
|
+
|
|
294
|
+
glEnable(GL_POINT_SMOOTH)
|
|
295
|
+
|
|
296
|
+
for i in range( self.pset.size ):
|
|
297
|
+
self.__draw_particle( self.pset , i )
|
|
298
|
+
|
|
299
|
+
if self.pset.log_X_enabled and self.trajectory :
|
|
300
|
+
self.draw_trajectory()
|
|
301
|
+
|
|
302
|
+
elif self.__draw_model == self.DRAW_MODEL_VECTOR :
|
|
303
|
+
self._draw_vectorized()
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
|