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,131 @@
|
|
|
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
|
+
class TrackBall( object ):
|
|
21
|
+
"""
|
|
22
|
+
Class used for controlling the rotation of the scene via mouse or joystick, by generating the virtual trackball effect
|
|
23
|
+
|
|
24
|
+
Constructor
|
|
25
|
+
|
|
26
|
+
========== =========================
|
|
27
|
+
Arguments
|
|
28
|
+
========== =========================
|
|
29
|
+
w_size size of the window
|
|
30
|
+
========== =========================
|
|
31
|
+
|
|
32
|
+
Example:
|
|
33
|
+
Event On click: ::
|
|
34
|
+
|
|
35
|
+
( x , y ) = get_click_coords_on_window()
|
|
36
|
+
trk.track_ball_mapping( [ x , y ] )
|
|
37
|
+
|
|
38
|
+
Event On Move: ::
|
|
39
|
+
|
|
40
|
+
( x , y ) = get_current_coords_on_window()
|
|
41
|
+
( rot_axis , rot_angle ) = trk.on_move( [ x , y ] )
|
|
42
|
+
glRotatef( rot_angle , rot_axis[0] , rot_axis[1] , rot_axis[2] )
|
|
43
|
+
"""
|
|
44
|
+
def __init__( self , w_size ):
|
|
45
|
+
|
|
46
|
+
self.__v = np.array( [ 0.0 , 0.0 , 0.0 ] )
|
|
47
|
+
self.__v_old = np.array( [ 0.0 , 0.0 , 0.0 ] )
|
|
48
|
+
|
|
49
|
+
self.__win_size = ( 800 , 600 )
|
|
50
|
+
|
|
51
|
+
self.__win_width = 800
|
|
52
|
+
self.__win_height = 600
|
|
53
|
+
|
|
54
|
+
self.win_size = w_size
|
|
55
|
+
|
|
56
|
+
def get_V( self ):
|
|
57
|
+
return self.__v
|
|
58
|
+
|
|
59
|
+
def set_V( self , v ):
|
|
60
|
+
self.__v = v
|
|
61
|
+
|
|
62
|
+
V = property( get_V , set_V )
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def get_win_size( self ):
|
|
66
|
+
return ( self.__win_width , self.__win_height )
|
|
67
|
+
|
|
68
|
+
def set_win_size( self , w_size ):
|
|
69
|
+
self.__win_width = w_size[0]
|
|
70
|
+
self.__win_height = w_size[1]
|
|
71
|
+
|
|
72
|
+
win_size = property( get_win_size , set_win_size )
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def track_ball_mapping( self , point ):
|
|
76
|
+
"""
|
|
77
|
+
Function to be called after a click on the mouse or at beginnig of the rotation, it takes the current coordinates of the pointer.
|
|
78
|
+
"""
|
|
79
|
+
self.__v_old[:] = self.__v[:]
|
|
80
|
+
|
|
81
|
+
self.__v[0] = ( 2.0 * point[0] - self.win_size[0] ) / self.win_size[0]
|
|
82
|
+
self.__v[1] = ( self.win_size[1] - 2.0 * point[1] ) / self.win_size[1]
|
|
83
|
+
|
|
84
|
+
self.__v[2] = 0.0
|
|
85
|
+
|
|
86
|
+
d = np.linalg.norm( self.__v )
|
|
87
|
+
|
|
88
|
+
if d > 1.0 :
|
|
89
|
+
self.__v[:] = self.__v[:] / d
|
|
90
|
+
|
|
91
|
+
tb_radius = 4.0
|
|
92
|
+
|
|
93
|
+
self.__v[:] = self.__v[:] * tb_radius * 0.999
|
|
94
|
+
|
|
95
|
+
self.__v[2] = np.sqrt( tb_radius**2 - self.__v[0]**2 - self.__v[1]**2 )
|
|
96
|
+
|
|
97
|
+
self.__v[:] = self.__v / np.linalg.norm( self.__v )
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def on_move( self , point ):
|
|
101
|
+
"""
|
|
102
|
+
function to be called when the mouse is moved. argument requires the coordinates of the mouse pointer and it returns the axis of rotation and angle.
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
self.track_ball_mapping( point )
|
|
106
|
+
|
|
107
|
+
direction = self.__v - self.__v_old
|
|
108
|
+
|
|
109
|
+
velocity = np.linalg.norm( direction )
|
|
110
|
+
|
|
111
|
+
rot_axis = np.cross( self.__v_old , self.__v )
|
|
112
|
+
rot_angle = velocity * 400.0
|
|
113
|
+
|
|
114
|
+
rot_axis = rot_axis / np.linalg.norm( rot_axis )
|
|
115
|
+
|
|
116
|
+
return ( rot_axis , rot_angle )
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def on_joystick( self , jaxes ):
|
|
120
|
+
"""
|
|
121
|
+
Given the axes ( x and y ) of the joystick; it returns the axis and the angle of rotation.
|
|
122
|
+
Example: ::
|
|
123
|
+
|
|
124
|
+
( rot_axis , rot_angle ) = trk.on_joystick( [ x , y ] )
|
|
125
|
+
"""
|
|
126
|
+
ws = self.win_size
|
|
127
|
+
|
|
128
|
+
jd = 400
|
|
129
|
+
|
|
130
|
+
self.track_ball_mapping( ( ws[0]/2 , ws[1]/2 ) )
|
|
131
|
+
return self.on_move( ( ws[0]/2 + jaxes[0]/jd , ws[1]/2 + jaxes[1]/jd ) )
|
|
@@ -0,0 +1,87 @@
|
|
|
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
|
+
class TranslateScene(object):
|
|
21
|
+
def __init__( self , w_size ):
|
|
22
|
+
|
|
23
|
+
self.__v = np.array( [ 0.0 , 0.0 , 0.0 ] )
|
|
24
|
+
self.__v_old = np.array( [ 0.0 , 0.0 , 0.0 ] )
|
|
25
|
+
|
|
26
|
+
self.__win_size = ( 800 , 600 )
|
|
27
|
+
|
|
28
|
+
self.__win_width = 800
|
|
29
|
+
self.__win_height = 600
|
|
30
|
+
|
|
31
|
+
self.win_size = w_size
|
|
32
|
+
|
|
33
|
+
self.factor = 100
|
|
34
|
+
self.__fovy = 2.0
|
|
35
|
+
|
|
36
|
+
def get_V( self ):
|
|
37
|
+
return self.__v
|
|
38
|
+
|
|
39
|
+
def set_V( self , v ):
|
|
40
|
+
self.__v = v
|
|
41
|
+
|
|
42
|
+
V = property( get_V , set_V )
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def get_fovy( self ):
|
|
46
|
+
return self.__fovy
|
|
47
|
+
|
|
48
|
+
def set_fovy( self , fv ):
|
|
49
|
+
if fv > 2.0 :
|
|
50
|
+
fv = 2.0
|
|
51
|
+
self.__fovy = fv
|
|
52
|
+
|
|
53
|
+
fovy = property( get_fovy , set_fovy )
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def get_win_size( self ):
|
|
57
|
+
return ( self.__win_width , self.__win_height )
|
|
58
|
+
|
|
59
|
+
def set_win_size( self , w_size ):
|
|
60
|
+
self.__win_width = w_size[0]
|
|
61
|
+
self.__win_height = w_size[1]
|
|
62
|
+
|
|
63
|
+
win_size = property( get_win_size , set_win_size )
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def translate_mapping( self , point ):
|
|
67
|
+
self.__v_old[:] = self.__v[:]
|
|
68
|
+
|
|
69
|
+
self.__v[0] = ( 2.0 * point[0] - self.win_size[0] ) / self.win_size[0]
|
|
70
|
+
self.__v[1] = ( self.win_size[1] - 2.0 * point[1] ) / self.win_size[1]
|
|
71
|
+
self.__v[2] = 1.0
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def on_move( self , point ):
|
|
75
|
+
self.translate_mapping( point )
|
|
76
|
+
|
|
77
|
+
direction = self.__v - self.__v_old
|
|
78
|
+
|
|
79
|
+
velocity = np.linalg.norm( direction )
|
|
80
|
+
|
|
81
|
+
delta = direction * velocity * self.factor * self.fovy
|
|
82
|
+
|
|
83
|
+
return ( delta[0] , delta[1] )
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
@@ -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,69 @@
|
|
|
1
|
+
# PyParticles : Particles simulation in python
|
|
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 numpy as np
|
|
19
|
+
import sys
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Boundary(object):
|
|
23
|
+
def __init__(self):
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
def set_boundary( self , bound=(-1,1) , dim=3 ):
|
|
27
|
+
if len(bound) not in ( 2 , 4 , 6 ):
|
|
28
|
+
raise ValueError
|
|
29
|
+
|
|
30
|
+
self.__dim = dim
|
|
31
|
+
self.__bound = np.zeros((dim,2))
|
|
32
|
+
|
|
33
|
+
if len(bound) >= 2 :
|
|
34
|
+
self.__bound[0,0] = bound[0]
|
|
35
|
+
self.__bound[0,1] = bound[1]
|
|
36
|
+
|
|
37
|
+
if dim >= 2 :
|
|
38
|
+
self.__bound[1,0] = bound[0]
|
|
39
|
+
self.__bound[1,1] = bound[1]
|
|
40
|
+
|
|
41
|
+
if dim == 3 :
|
|
42
|
+
self.__bound[2,0] = bound[0]
|
|
43
|
+
self.__bound[2,1] = bound[1]
|
|
44
|
+
|
|
45
|
+
if len(bound) == 6:
|
|
46
|
+
self.__bound[1,0] = bound[2]
|
|
47
|
+
self.__bound[1,1] = bound[3]
|
|
48
|
+
|
|
49
|
+
self.__bound[2,0] = bound[4]
|
|
50
|
+
self.__bound[2,1] = bound[5]
|
|
51
|
+
|
|
52
|
+
if len(bound) == 4:
|
|
53
|
+
self.__bound[1,0] = bound[2]
|
|
54
|
+
self.__bound[1,1] = bound[3]
|
|
55
|
+
|
|
56
|
+
def get_dim(self):
|
|
57
|
+
return self.__dim
|
|
58
|
+
|
|
59
|
+
dim = property( get_dim )
|
|
60
|
+
|
|
61
|
+
def get_bound(self):
|
|
62
|
+
return self.__bound
|
|
63
|
+
|
|
64
|
+
bound = property( get_bound )
|
|
65
|
+
|
|
66
|
+
def boundary( self , p_set ):
|
|
67
|
+
NotImplementedError(" %s : is virtual and must be overridden." % sys._getframe().f_code.co_name )
|
|
68
|
+
|
|
69
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
class Cluster(object):
|
|
20
|
+
def __init__(self):
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
def insert3( self , X , M=None ,V=None ):
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
def write_out( self , X , M=None ,V=None ):
|
|
27
|
+
pass
|
|
28
|
+
|
|
@@ -0,0 +1,63 @@
|
|
|
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
|
+
from scipy.sparse import dok_matrix
|
|
19
|
+
|
|
20
|
+
import pyparticles.pset.constraint as ct
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ConstrainedForceInteractions(ct.Constraint):
|
|
24
|
+
def __init__(self, pset=None):
|
|
25
|
+
self.__S = dok_matrix((1, 1), dtype=np.byte)
|
|
26
|
+
super(ConstrainedForceInteractions, self).__init__(pset=None)
|
|
27
|
+
if pset is not None:
|
|
28
|
+
self.pset = pset
|
|
29
|
+
|
|
30
|
+
def get_pset(self):
|
|
31
|
+
return super(ConstrainedForceInteractions, self).get_pset()
|
|
32
|
+
|
|
33
|
+
def set_pset(self, pset):
|
|
34
|
+
self.__S.resize((pset.size, pset.size))
|
|
35
|
+
super(ConstrainedForceInteractions, self).set_pset(pset)
|
|
36
|
+
|
|
37
|
+
pset = property(get_pset, set_pset)
|
|
38
|
+
|
|
39
|
+
def add_connections(self, fc):
|
|
40
|
+
for c in fc:
|
|
41
|
+
i, j = int(c[0]), int(c[1])
|
|
42
|
+
self.__S[i, j] = True
|
|
43
|
+
|
|
44
|
+
def remove_connections(self, fc):
|
|
45
|
+
for c in fc:
|
|
46
|
+
i, j = int(c[0]), int(c[1])
|
|
47
|
+
if (i, j) in self.__S:
|
|
48
|
+
del self.__S[i, j]
|
|
49
|
+
|
|
50
|
+
def get_dense(self):
|
|
51
|
+
return np.asarray(self.__S.todense(), dtype=np.bool_)
|
|
52
|
+
|
|
53
|
+
dense = property(get_dense)
|
|
54
|
+
|
|
55
|
+
def get_sparse(self):
|
|
56
|
+
return self.__S
|
|
57
|
+
|
|
58
|
+
sparse = property(get_sparse)
|
|
59
|
+
|
|
60
|
+
def get_items(self):
|
|
61
|
+
return self.__S.items()
|
|
62
|
+
|
|
63
|
+
items = property(get_items)
|
|
@@ -0,0 +1,158 @@
|
|
|
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.constraint as ct
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ConstrainedX(ct.Constraint):
|
|
23
|
+
def __init__(self, pset=None):
|
|
24
|
+
self.__X_cr = None
|
|
25
|
+
self.__X_cr_i = None
|
|
26
|
+
self.__X_free = None
|
|
27
|
+
|
|
28
|
+
self.__use_slice_const = False
|
|
29
|
+
self.__use_slice_free = False
|
|
30
|
+
|
|
31
|
+
super(ConstrainedX, self).__init__(pset=pset)
|
|
32
|
+
|
|
33
|
+
def add_x_constraint(self, indx, constr):
|
|
34
|
+
"""Add positional constraints and update the referenced particle set."""
|
|
35
|
+
if isinstance(indx, slice):
|
|
36
|
+
self.__X_cr = np.array(constr)
|
|
37
|
+
self.__X_cr_i = indx
|
|
38
|
+
self.__use_slice_const = True
|
|
39
|
+
self.pset.X[indx, :] = constr
|
|
40
|
+
self._optimize()
|
|
41
|
+
return
|
|
42
|
+
|
|
43
|
+
indx = np.asarray(indx, dtype=np.int64)
|
|
44
|
+
constr = np.asarray(constr)
|
|
45
|
+
|
|
46
|
+
if self.__X_cr is None:
|
|
47
|
+
self.__X_cr = constr.copy()
|
|
48
|
+
self.__X_cr_i = indx.copy()
|
|
49
|
+
else:
|
|
50
|
+
self.__X_cr_i = np.concatenate((self.__X_cr_i, indx))
|
|
51
|
+
self.__X_cr = np.concatenate((self.__X_cr, constr))
|
|
52
|
+
|
|
53
|
+
self._optimize()
|
|
54
|
+
self.pset.X[indx, :] = constr
|
|
55
|
+
|
|
56
|
+
def _optimize(self):
|
|
57
|
+
"""Use a slice for free indices when they form one contiguous range."""
|
|
58
|
+
free = list(range(self.pset.size))
|
|
59
|
+
|
|
60
|
+
if self.__X_cr_i is None:
|
|
61
|
+
constrained = []
|
|
62
|
+
elif isinstance(self.__X_cr_i, slice):
|
|
63
|
+
constrained = range(*self.__X_cr_i.indices(self.pset.size))
|
|
64
|
+
else:
|
|
65
|
+
constrained = self.__X_cr_i
|
|
66
|
+
|
|
67
|
+
for i in constrained:
|
|
68
|
+
i = int(i)
|
|
69
|
+
if i in free:
|
|
70
|
+
free.remove(i)
|
|
71
|
+
|
|
72
|
+
if not free:
|
|
73
|
+
self.__X_free = np.array([], dtype=np.int64)
|
|
74
|
+
self.__use_slice_free = False
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
sequential = all((free[i + 1] - free[i]) == 1 for i in range(len(free) - 1))
|
|
78
|
+
if sequential:
|
|
79
|
+
self.__X_free = slice(free[0], free[-1] + 1)
|
|
80
|
+
self.__use_slice_free = True
|
|
81
|
+
else:
|
|
82
|
+
self.__X_free = np.asarray(free, dtype=np.int64)
|
|
83
|
+
self.__use_slice_free = False
|
|
84
|
+
|
|
85
|
+
def get_pset(self):
|
|
86
|
+
return super(ConstrainedX, self).get_pset()
|
|
87
|
+
|
|
88
|
+
def set_pset(self, pset):
|
|
89
|
+
super(ConstrainedX, self).set_pset(pset)
|
|
90
|
+
if self.__X_cr_i is not None and self.__X_cr is not None:
|
|
91
|
+
pset.X[self.__X_cr_i, :] = self.__X_cr
|
|
92
|
+
self._optimize()
|
|
93
|
+
|
|
94
|
+
pset = property(get_pset, set_pset, doc="get and set the particles set (pset)")
|
|
95
|
+
|
|
96
|
+
def remove_x_constraint(self, indxs):
|
|
97
|
+
"""Remove constraints whose particle indices are listed in *indxs*."""
|
|
98
|
+
if self.__use_slice_const or self.__X_cr_i is None:
|
|
99
|
+
return
|
|
100
|
+
|
|
101
|
+
remove_positions = []
|
|
102
|
+
for i in indxs:
|
|
103
|
+
matches = np.flatnonzero(self.__X_cr_i == i)
|
|
104
|
+
remove_positions.extend(matches.tolist())
|
|
105
|
+
|
|
106
|
+
if not remove_positions:
|
|
107
|
+
return
|
|
108
|
+
|
|
109
|
+
remove_positions = np.asarray(sorted(set(remove_positions)), dtype=np.int64)
|
|
110
|
+
self.__X_cr = np.delete(self.__X_cr, remove_positions, axis=0)
|
|
111
|
+
self.__X_cr_i = np.delete(self.__X_cr_i, remove_positions, axis=0)
|
|
112
|
+
|
|
113
|
+
if self.__X_cr_i.size == 0:
|
|
114
|
+
self.__X_cr = None
|
|
115
|
+
self.__X_cr_i = None
|
|
116
|
+
|
|
117
|
+
self._optimize()
|
|
118
|
+
|
|
119
|
+
def get_cx_indicies(self):
|
|
120
|
+
"""Return a copy of the constrained indices (legacy spelling kept)."""
|
|
121
|
+
if isinstance(self.__X_cr_i, slice):
|
|
122
|
+
return self.__X_cr_i
|
|
123
|
+
if self.__X_cr_i is None:
|
|
124
|
+
return None
|
|
125
|
+
return np.copy(self.__X_cr_i)
|
|
126
|
+
|
|
127
|
+
def set_free_indicies(self, indx):
|
|
128
|
+
if isinstance(indx, slice):
|
|
129
|
+
self.__X_free = indx
|
|
130
|
+
self.__use_slice_free = True
|
|
131
|
+
return
|
|
132
|
+
|
|
133
|
+
indx = np.asarray(indx, dtype=np.int64)
|
|
134
|
+
if self.__X_free is None:
|
|
135
|
+
self.__X_free = indx
|
|
136
|
+
elif isinstance(self.__X_free, slice):
|
|
137
|
+
current = np.arange(self.pset.size, dtype=np.int64)[self.__X_free]
|
|
138
|
+
self.__X_free = np.concatenate((current, indx))
|
|
139
|
+
else:
|
|
140
|
+
self.__X_free = np.concatenate((self.__X_free, indx))
|
|
141
|
+
self.__use_slice_free = False
|
|
142
|
+
|
|
143
|
+
def get_cx_free_indicies(self):
|
|
144
|
+
return self.__X_free
|
|
145
|
+
|
|
146
|
+
def clear_all_x_constraint(self):
|
|
147
|
+
self.__X_cr = None
|
|
148
|
+
self.__X_cr_i = None
|
|
149
|
+
self.__X_free = slice(0, self.pset.size) if self.pset is not None else None
|
|
150
|
+
self.__use_slice_const = False
|
|
151
|
+
self.__use_slice_free = self.pset is not None
|
|
152
|
+
|
|
153
|
+
def get_cX(self):
|
|
154
|
+
if self.__X_cr_i is None:
|
|
155
|
+
return None
|
|
156
|
+
return self.pset.X[self.__X_cr_i, :]
|
|
157
|
+
|
|
158
|
+
cX = property(get_cX, doc="return the constrained X elements")
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
from collections import deque
|
|
20
|
+
|
|
21
|
+
import pyparticles.pset.particles_set as ps
|
|
22
|
+
|
|
23
|
+
class Constraint( object ):
|
|
24
|
+
def __init__( self , pset=None ):
|
|
25
|
+
self.__pset = pset
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_pset(self):
|
|
29
|
+
return self.__pset
|
|
30
|
+
|
|
31
|
+
def set_pset( self , pset ):
|
|
32
|
+
self.__pset = pset
|
|
33
|
+
|
|
34
|
+
pset = property( get_pset , set_pset )
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
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
|
+
import pyparticles.pset.boundary as bd
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class DefaultBoundary(bd.Boundary):
|
|
14
|
+
r"""Move particles outside the domain through a user callback."""
|
|
15
|
+
|
|
16
|
+
def __init__(self, bound=(-1, 1), dim=3, defualt_pos=None):
|
|
17
|
+
self.set_boundary(bound, dim)
|
|
18
|
+
self.__defualt_pos = defualt_pos
|
|
19
|
+
|
|
20
|
+
def needs_update(self, p_set):
|
|
21
|
+
"""Return True when at least one position lies outside the domain."""
|
|
22
|
+
for i in range(self.dim):
|
|
23
|
+
if np.any(p_set.X[:, i] < self.bound[i, 0]):
|
|
24
|
+
return True
|
|
25
|
+
if np.any(p_set.X[:, i] > self.bound[i, 1]):
|
|
26
|
+
return True
|
|
27
|
+
return False
|
|
28
|
+
|
|
29
|
+
def boundary(self, p_set):
|
|
30
|
+
changed = False
|
|
31
|
+
for i in range(self.dim):
|
|
32
|
+
b_mi, = np.where(p_set.X[:, i] < self.bound[i, 0])
|
|
33
|
+
b_mx, = np.where(p_set.X[:, i] > self.bound[i, 1])
|
|
34
|
+
|
|
35
|
+
if len(b_mi) > 0:
|
|
36
|
+
self.__defualt_pos(p_set, b_mi)
|
|
37
|
+
changed = True
|
|
38
|
+
|
|
39
|
+
if len(b_mx) > 0:
|
|
40
|
+
self.__defualt_pos(p_set, b_mx)
|
|
41
|
+
changed = True
|
|
42
|
+
|
|
43
|
+
return changed
|