├── .gitignore ├── LICENSE-gpl-3.0.txt ├── README.rst ├── __init__.py ├── doc ├── Config File.rst ├── Config File.rst~ ├── Logo │ └── pyparticles_logo.svg ├── Makefile ├── Packages Descriptions.rst ├── Programming Example II.rst ├── Programming Example.rst ├── Testing.rst ├── conf.py ├── img │ ├── dam_an.jpg │ ├── dhar.png │ ├── fall.png │ ├── fall_an.jpg │ ├── har.png │ └── har_an.jpg ├── index.rst ├── intro.rst ├── logo.png ├── logo_pyp.png ├── make.bat ├── modules.rst ├── pyparticles.animation.rst ├── pyparticles.demo.rst ├── pyparticles.forces.rst ├── pyparticles.geometry.rst ├── pyparticles.main.rst ├── pyparticles.measures.rst ├── pyparticles.ode.rst ├── pyparticles.ogl.rst ├── pyparticles.pset.rst ├── pyparticles.rst └── pyparticles.utils.rst ├── example ├── cluster_demo.cfg ├── solar_sys.csv └── solar_system.csv ├── man ├── install.sh └── pyparticles.1 ├── pyparticles ├── __init__.py ├── animation │ ├── __init__.py │ ├── animated_cli.py │ ├── animated_ogl.py │ ├── animated_scatter.py │ ├── animation.py │ └── test_animation.py ├── demo │ ├── __init__.py │ ├── bubble.py │ ├── electromagnetic_demo.py │ ├── electrostatic_demo.py │ ├── fountain.py │ ├── gas_lennard_jones.py │ ├── gravity_clusters.py │ ├── solar_system.py │ ├── springs.py │ ├── springs_constr.py │ └── test.py ├── forces │ ├── __init__.py │ ├── const_force.py │ ├── damping.py │ ├── drag.py │ ├── electromagnetic.py │ ├── electromagnetic_field.py │ ├── electrostatic.py │ ├── force.py │ ├── force_constrained.py │ ├── gravity.py │ ├── lennard_jones.py │ ├── linear_spring.py │ ├── linear_spring_constrained.py │ ├── multiple_force.py │ ├── pseudo_bubble.py │ ├── van_der_waals_force.py │ └── vector_field_force.py ├── geometry │ ├── __init__.py │ ├── dist.py │ ├── intersection.py │ └── transformations.py ├── main │ ├── __init__.py │ └── main.py ├── measures │ ├── __init__.py │ ├── elastic_potential_energy.py │ ├── gravitational_potential_energy.py │ ├── kinetic_energy.py │ ├── mass.py │ ├── measure.py │ ├── momentum.py │ └── total_energy.py ├── ode │ ├── __init__.py │ ├── euler_solver.py │ ├── euler_solver_constrained.py │ ├── leapfrog_solver.py │ ├── leapfrog_solver_constrained.py │ ├── midpoint_solver.py │ ├── midpoint_solver_constrained.py │ ├── ode_solver.py │ ├── ode_solver_constrained.py │ ├── runge_kutta_solver.py │ ├── runge_kutta_solver_constrained.py │ ├── sim_time.py │ ├── stormer_verlet_solver.py │ └── stormer_verlet_solver_constrained.py ├── ogl │ ├── __init__.py │ ├── axis_ogl.py │ ├── draw_particles_ogl.py │ ├── draw_vector_field.py │ ├── trackball.py │ └── translate_scene.py ├── pset │ ├── __init__.py │ ├── boundary.py │ ├── cluster.py │ ├── constrained_force_interactions.py │ ├── constrained_x.py │ ├── constraint.py │ ├── default_boundary.py │ ├── file_cluster.py │ ├── logger.py │ ├── octree.py │ ├── opencl_context.py │ ├── particles_set.py │ ├── periodic_boundary.py │ ├── rand_cluster.py │ └── rebound_boundary.py └── utils │ ├── __init__.py │ ├── parse_args.py │ ├── problem_config.py │ ├── pypart_global.py │ └── time_formatter.py ├── pyparticles_app └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | ## My 2 | _build/ 3 | *~ 4 | .* 5 | *.e4p 6 | 7 | ################# 8 | ## Eclipse 9 | ################# 10 | 11 | *.pydevproject 12 | .project 13 | .metadata 14 | bin/ 15 | tmp/ 16 | *.tmp 17 | *.bak 18 | *.swp 19 | *~.nib 20 | local.properties 21 | .classpath 22 | .settings/ 23 | .loadpath 24 | 25 | # External tool builders 26 | .externalToolBuilders/ 27 | 28 | # Locally stored "Eclipse launch configurations" 29 | *.launch 30 | 31 | # CDT-specific 32 | .cproject 33 | 34 | # PDT-specific 35 | .buildpath 36 | 37 | 38 | ################# 39 | ## Visual Studio 40 | ################# 41 | 42 | ## Ignore Visual Studio temporary files, build results, and 43 | ## files generated by popular Visual Studio add-ons. 44 | 45 | # User-specific files 46 | *.suo 47 | *.user 48 | *.sln.docstates 49 | 50 | # Build results 51 | [Dd]ebug/ 52 | [Rr]elease/ 53 | *_i.c 54 | *_p.c 55 | *.ilk 56 | *.meta 57 | *.obj 58 | *.pch 59 | *.pdb 60 | *.pgc 61 | *.pgd 62 | *.rsp 63 | *.sbr 64 | *.tlb 65 | *.tli 66 | *.tlh 67 | *.tmp 68 | *.vspscc 69 | .builds 70 | *.dotCover 71 | 72 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 73 | #packages/ 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opensdf 80 | *.sdf 81 | 82 | # Visual Studio profiler 83 | *.psess 84 | *.vsp 85 | 86 | # ReSharper is a .NET coding add-in 87 | _ReSharper* 88 | 89 | # Installshield output folder 90 | [Ee]xpress 91 | 92 | # DocProject is a documentation generator add-in 93 | DocProject/buildhelp/ 94 | DocProject/Help/*.HxT 95 | DocProject/Help/*.HxC 96 | DocProject/Help/*.hhc 97 | DocProject/Help/*.hhk 98 | DocProject/Help/*.hhp 99 | DocProject/Help/Html2 100 | DocProject/Help/html 101 | 102 | # Click-Once directory 103 | publish 104 | 105 | # Others 106 | [Bb]in 107 | [Oo]bj 108 | sql 109 | TestResults 110 | *.Cache 111 | ClientBin 112 | stylecop.* 113 | ~$* 114 | *.dbmdl 115 | Generated_Code #added for RIA/Silverlight projects 116 | 117 | # Backup & report files from converting an old project file to a newer 118 | # Visual Studio version. Backup files are not needed, because we have git ;-) 119 | _UpgradeReport_Files/ 120 | Backup*/ 121 | UpgradeLog*.XML 122 | 123 | 124 | 125 | ############ 126 | ## Windows 127 | ############ 128 | 129 | # Windows image file caches 130 | Thumbs.db 131 | 132 | # Folder config file 133 | Desktop.ini 134 | 135 | 136 | ############# 137 | ## Python 138 | ############# 139 | 140 | *.py[co] 141 | 142 | # Packages 143 | *.egg 144 | *.egg-info 145 | dist 146 | build 147 | eggs 148 | parts 149 | bin 150 | var 151 | sdist 152 | develop-eggs 153 | .installed.cfg 154 | 155 | # Installer logs 156 | pip-log.txt 157 | 158 | # Unit test / coverage reports 159 | .coverage 160 | .tox 161 | 162 | #Translations 163 | *.mo 164 | 165 | #Mr Developer 166 | .mr.developer.cfg 167 | 168 | # Mac crap 169 | .DS_Store 170 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | PyParticles 2 | =========== 3 | 4 | PyParticles is a particle simulation toolbox entirely written in python 3. 5 | 6 | The main objective of PyParticles is to provide a system API simple and fast to use. 7 | Furthermore is to provide a basic application for the implementation of simple models. 8 | 9 | | Visit: http://pyparticles.wordpress.com/ 10 | | Docs: http://simon-r.github.com/PyParticles/index.html 11 | 12 | 13 | Download 14 | -------- 15 | 16 | `PyParticles v0.3.5 tgz `_ 17 | 18 | 19 | Features 20 | -------- 21 | 22 | Simulate a particle by particle model with the most popular integrations methods, and it represents the results on a OpenGL or Matplotlib plot. 23 | 24 | **PyParticle includes** the followings integrations methods 25 | 26 | #. Euler method 27 | #. Leap Frog method 28 | #. Rung Kutta method 29 | #. Midpoint 30 | #. Stormer Verlet method 31 | 32 | **As a forces model** it includes: 33 | 34 | #. Gravity 35 | #. Particle by Particle spring 36 | #. Constant 37 | #. User defined field 38 | #. Lennard Jones 39 | #. Drag 40 | #. Damping 41 | #. Electromagnetic fields 42 | 43 | We have also the possibility of modeling the forces with user-defined constraints (See demo *cat_spri*). 44 | 45 | PyParticle offers an easy to use class structure with a fully *interchangeable* integrations method or force model, it also implements the possibility to add some boundary model. 46 | 47 | 48 | Requirements 49 | ------------ 50 | | PyParticles require the following packages: 51 | 52 | | **numpy** : http://scipy.org/Download 53 | | **scipy** : http://scipy.org/Download 54 | | **pyopengl** : http://pyopengl.sourceforge.net/ 55 | | **matplotlib** : http://matplotlib.org/ 56 | | **pyopencl** : http://mathema.tician.de/software/pyopencl (optional) 57 | 58 | For more details about the installation visit the Blog: http://pyparticles.wordpress.com/installation/ 59 | 60 | 61 | 62 | Command line tool usage: 63 | ------------------------ 64 | 65 | 66 | In PyParticles a simulation model is entirely described in a config file that should be edited by the user. 67 | 68 | The following are the main command of the PyParticles application. 69 | 70 | * **Start the demo simulation:** 71 | 72 | :: 73 | 74 | pyparticles_app 75 | 76 | 77 | * **Start a simulation described in a config file** 78 | :: 79 | 80 | pyparticle_app 81 | 82 | 83 | * **Start the specified demo simulation** 84 | 85 | ============= ======================================================== 86 | Demos 87 | ============= ======================================================== 88 | springs 3 body springs 89 | solar_system Simulation of the solar system with realistic magnitudes 90 | bubble Bubbles. With a non realistic force 91 | cat_spri Vibrating string with gravity and air drag 92 | gas_lj Lennard jones gas model (should be improved) 93 | elmag_field Electromagnetic field 94 | fountain 250'000 particles fountain 95 | ============= ======================================================== 96 | :: 97 | 98 | pyparticles_app --demo springs 99 | pyparticles_app --demo solar_system 100 | pyparticles_app --demo bubble 101 | pyparticles_app --demo cat_spri 102 | pyparticles_app --demo gas_lj 103 | pyparticles_app --demo elmag_field 104 | pyparticles_app --demo fountain 105 | 106 | 107 | * **Start a testing procedure** 108 | Execute the specified test: :: 109 | 110 | pyparticles_app --test harmonic 111 | pyparticles_app --test fall 112 | 113 | 114 | 115 | * **Write out a model config file** 116 | :: 117 | 118 | pyparticle_app -m 119 | 120 | 121 | * **Print out the help and version** 122 | :: 123 | 124 | pyparticles_app --help 125 | pyparticles_app --version 126 | 127 | 128 | During the simulation you can toggle the help message by pressing **h** 129 | 130 | 131 | Config file Example: :: 132 | 133 | [pset_origin] 134 | media_origin = from_file 135 | file_name = solar_sys.csv 136 | 137 | [set_config] 138 | len_unit = 149597870700.0 139 | mass_unit = 5.9736e24 140 | boundary = open 141 | 142 | [model] 143 | force = gravity 144 | ode_solver_name = euler 145 | time_step = 3600 146 | steps = 1000000 147 | force_const = 6.67384e-11 148 | force_vector = 0 0 0 149 | 150 | [animation] 151 | animation_type = opengl 152 | xlim = -5.0 5.0 153 | ylim = -5.0 5.0 154 | zlim = -5.0 5.0 155 | 156 | 157 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | __all__ = [ "pyparticles" ] 18 | 19 | -------------------------------------------------------------------------------- /doc/Packages Descriptions.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simon-r/PyParticles/de24a5ad6059501182c75503c4f289fe30f2709e/doc/Packages Descriptions.rst -------------------------------------------------------------------------------- /doc/Programming Example II.rst: -------------------------------------------------------------------------------- 1 | Programming examples II 2 | ======================= 3 | 4 | 250K Particles Fountain 5 | ----------------------- 6 | 7 | Bellow I describe how to build the 250'000 particles fountain demo included as example in the main application. 8 | 9 | The demo can be executed with the command: :: 10 | 11 | pyparticles_app -d fountain 12 | 13 | 14 | First, you must import the libraries: numpy and particles set. :: 15 | 16 | import numpy as np 17 | import pyparticles.pset.particles_set as ps 18 | 19 | For this demo I've chosen the midpoint method as ode numerical integration, but you can try with another one. :: 20 | 21 | import pyparticles.ode.midpoint_solver as mds 22 | 23 | The force is a combination between the constant gravity and the drag of the atmosphere, so I import the 'const_force' and 'drag'; and the multiple force for building the full scenario :: 24 | 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 | The 'animation' that control the simulation and the visualization is animation_ogl. :: 30 | 31 | import pyparticles.animation.animated_ogl as aogl 32 | 33 | 34 | And I use the default_boundary model to control the jet. :: 35 | 36 | import pyparticles.pset.default_boundary as db 37 | 38 | 39 | Let's start 40 | +++++++++++ 41 | 42 | As first I've defined the function for modeling the jet. This function will be used by the boundary controller. 43 | 44 | This is a time-dependent function. And for convenience time is defined as variable internal to the function. As rule, the time must be based on a reference to an object of type **SimTime**. 45 | :: 46 | 47 | def default_pos( pset , indx ): 48 | 49 | t = default_pos.sim_time.time 50 | 51 | pset.X[indx,:] = 0.01 * np.random.rand( len(indx) , pset.dim ) 52 | 53 | fs = 1.0 / ( 1.0 + np.exp( -( t - 2.0 ) ) ) 54 | 55 | alpha = 2.0 * np.pi * np.random.rand( len(indx) ) 56 | 57 | vel_x = 2.0 * fs * np.cos( alpha ) 58 | vel_y = 2.0 * fs * np.sin( alpha ) 59 | 60 | pset.V[indx,0] = vel_x 61 | pset.V[indx,1] = vel_y 62 | pset.V[indx,2] = 10.0 * fs + 1.0 * fs * ( np.random.rand( len(indx)) ) 63 | 64 | the main function 65 | +++++++++++++++++ 66 | 67 | And finally you can start with the main function: 68 | As first I've defined the number of steps the *dt* (step time), the size of the particle set and the **particles set** pset 69 | :: 70 | 71 | def fountain(): 72 | 73 | steps = 10000000 74 | dt = 0.01 75 | 76 | pcnt = 250000 77 | 78 | pset = ps.ParticlesSet( pcnt ) 79 | 80 | Initial position 81 | ++++++++++++++++ 82 | 83 | As a second point define the initial positions of the particles, in order to generate a continuous stream. 84 | :: 85 | 86 | pset.M[:] = 0.1 87 | pset.X[:,2] = 0.7 * np.random.rand( pset.size ) 88 | 89 | Forces model 90 | ++++++++++++ 91 | 92 | The force model is based on a combination between a constant force, for simulating the gravity, and the drag for simulating the friction of the air. 93 | 94 | The two forces must be stored in an object of type MultipleForce. 95 | :: 96 | 97 | grav = cf.ConstForce( pset.size , dim=pset.dim , u_force=( 0.0 , 0.0 , -10.0 ) ) 98 | drag = dr.Drag( pset.size , dim=pset.dim , Consts=0.01 ) 99 | 100 | multi = mf.MultipleForce( pset.size , dim=pset.dim ) 101 | 102 | multi.append_force( grav ) 103 | multi.append_force( drag ) 104 | 105 | multi.set_masses( pset.M ) 106 | 107 | ODE integration 108 | +++++++++++++++ 109 | 110 | As a ODE numerical integration method I've used the mid point algorithm. 111 | :: 112 | 113 | solver = mds.MidpointSolver( multi , pset , dt ) 114 | solver.update_force() 115 | 116 | Simulation time 117 | +++++++++++++++ 118 | 119 | Set up the simulation time in the *default_pos* function, used for modeling the jet. 120 | :: 121 | 122 | default_pos.sim_time = solver.get_sim_time() 123 | 124 | 125 | Build the boundary model 126 | ++++++++++++++++++++++++ 127 | 128 | The tuples bd represents the size of the box closed domain: :math:`( min_x , max_x , min_y , max_y , min_z , max_z )` 129 | 130 | .. note:: 131 | The class DefaultBoundary positions the particles exited from the limits of the domain according to the function defualt_pos 132 | :: 133 | 134 | bd = ( -100.0 , 100.0 , -100.0 , 100.0 , 0.0 , 100.0 ) 135 | bound = db.DefaultBoundary( bd , dim=3 , defualt_pos=default_pos ) 136 | 137 | pset.set_boundary( bound ) 138 | 139 | Build the 'animation' class and start 140 | +++++++++++++++++++++++++++++++++++++ 141 | 142 | .. note:: 143 | a.init_rotation( -80 , [ 0.7 , 0.05 , 0 ] ) 144 | setup an initial rotation where parameters are ( rot angle , axis of rotation ) 145 | 146 | a.draw_particles.set_draw_model( 1 ) 147 | enable the vectorized rendering, that is fundamental for drawing 250'000 particles 148 | :: 149 | 150 | a = aogl.AnimatedGl() 151 | 152 | a.ode_solver = solver 153 | a.pset = pset 154 | a.steps = steps 155 | 156 | a.draw_particles.set_draw_model( 1 ) 157 | 158 | a.init_rotation( -80 , [ 0.7 , 0.05 , 0 ] ) 159 | 160 | a.build_animation() 161 | a.start() 162 | 163 | return 164 | 165 | -------------------------------------------------------------------------------- /doc/img/dam_an.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simon-r/PyParticles/de24a5ad6059501182c75503c4f289fe30f2709e/doc/img/dam_an.jpg -------------------------------------------------------------------------------- /doc/img/dhar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simon-r/PyParticles/de24a5ad6059501182c75503c4f289fe30f2709e/doc/img/dhar.png -------------------------------------------------------------------------------- /doc/img/fall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simon-r/PyParticles/de24a5ad6059501182c75503c4f289fe30f2709e/doc/img/fall.png -------------------------------------------------------------------------------- /doc/img/fall_an.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simon-r/PyParticles/de24a5ad6059501182c75503c4f289fe30f2709e/doc/img/fall_an.jpg -------------------------------------------------------------------------------- /doc/img/har.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simon-r/PyParticles/de24a5ad6059501182c75503c4f289fe30f2709e/doc/img/har.png -------------------------------------------------------------------------------- /doc/img/har_an.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simon-r/PyParticles/de24a5ad6059501182c75503c4f289fe30f2709e/doc/img/har_an.jpg -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | PyParticles 2 | =========== 3 | 4 | PyParticles is a particle simulation toolbox entirely written in python. 5 | 6 | The main objective of PyParticles is to provide a system API simple and fast to use. 7 | Furthermore is to provide a basic application for the implementation of simple models. 8 | 9 | | Blog: http://pyparticles.wordpress.com/ 10 | | GitHub: https://github.com/simon-r/PyParticles 11 | 12 | Index 13 | ----- 14 | 15 | .. toctree:: 16 | :maxdepth: 2 17 | 18 | Programming Example 19 | Programming Example II 20 | Config File 21 | Testing 22 | Packages Descriptions 23 | pyparticles 24 | 25 | 26 | Features 27 | -------- 28 | 29 | Simulate a particle by particle model with the most popular integrations methods, and it represents the results on a OpenGL or Matplotlib plot. 30 | 31 | **PyParticle includes** the followings integrations methods 32 | 33 | #. Euler method 34 | #. Leap Frog method 35 | #. Rung Kutta method 36 | #. Midpoint 37 | #. Stormer Verlet method 38 | 39 | **As a forces model** it includes: 40 | 41 | #. Gravity 42 | #. Particle by Particle spring 43 | #. Constant 44 | #. User defined field 45 | #. Lennard Jones 46 | #. Drag 47 | #. Damping 48 | #. Electromagnetic fields 49 | 50 | We have also the possibility of modeling the forces with user-defined constraints (See demo *cat_spri*). 51 | 52 | PyParticle offers an easy to use class structure with a fully *interchangeable* integrations method or force model, it also implements the possibility to add some boundary model. 53 | 54 | 55 | Requirements 56 | ------------ 57 | | PyParticles require the following packages: 58 | 59 | | **numpy** : http://scipy.org/Download 60 | | **scipy** : http://scipy.org/Download 61 | | **pyopengl** : http://pyopengl.sourceforge.net/ 62 | | **matplotlib** : http://matplotlib.org/ 63 | 64 | For more details about the installation visit the Blog: http://pyparticles.wordpress.com/installation/ 65 | 66 | 67 | Command line tool usage: 68 | ------------------------ 69 | 70 | 71 | In PyParticles a simulation model is entirely described in a config file that should be edited by the user. 72 | 73 | The following are the main command of the PyParticles application. 74 | 75 | **Start the demo simulation:** 76 | 77 | :: 78 | 79 | pyparticles_app 80 | 81 | 82 | **Start a simulation described in a config file** 83 | :: 84 | 85 | pyparticle_app 86 | 87 | 88 | **Start the specified demo simulation** 89 | 90 | ============= ======================================================== 91 | Demos 92 | ============= ======================================================== 93 | springs 3 body springs 94 | solar_system Simulation of the solar system with realistic magnitudes 95 | bubble Bubbles. With a non realistic force 96 | cat_spri Vibrating string with gravity and air drag 97 | gas_lj Lennard jones gas model (should be improved) 98 | elmag_field Electromagnetic field 99 | fountain 250'000 particles fountain 100 | ============= ======================================================== 101 | :: 102 | 103 | pyparticles_app --demo springs 104 | pyparticles_app --demo solar_system 105 | pyparticles_app --demo bubble 106 | pyparticles_app --demo cat_spri 107 | pyparticles_app --demo gas_lj 108 | pyparticles_app --demo elmag_field 109 | pyparticles_app --demo fountain 110 | 111 | **Start a testing procedure** 112 | Execute the specified test: :: 113 | 114 | pyparticles_app --test harmonic 115 | pyparticles_app --test fall 116 | 117 | 118 | 119 | **Write out a model config file** 120 | :: 121 | 122 | pyparticle_app -m 123 | 124 | 125 | **Print out the help and version** 126 | :: 127 | 128 | pyparticles_app --help 129 | pyparticles_app --version 130 | 131 | 132 | During the simulation you can toggle the help message by pressing **h** 133 | 134 | 135 | Config file Example: :: 136 | 137 | [pset_origin] 138 | media_origin = from_file 139 | file_name = solar_sys.csv 140 | 141 | [set_config] 142 | len_unit = 149597870700.0 143 | mass_unit = 5.9736e24 144 | boundary = open 145 | 146 | [model] 147 | force = gravity 148 | ode_solver_name = euler 149 | time_step = 3600 150 | steps = 1000000 151 | force_const = 6.67384e-11 152 | force_vector = 0 0 0 153 | 154 | [animation] 155 | animation_type = opengl 156 | xlim = -5.0 5.0 157 | ylim = -5.0 5.0 158 | zlim = -5.0 5.0 -------------------------------------------------------------------------------- /doc/intro.rst: -------------------------------------------------------------------------------- 1 | un altro to 2 | =========== 3 | 4 | ciao mondo 5 | -------------------------------------------------------------------------------- /doc/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simon-r/PyParticles/de24a5ad6059501182c75503c4f289fe30f2709e/doc/logo.png -------------------------------------------------------------------------------- /doc/logo_pyp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simon-r/PyParticles/de24a5ad6059501182c75503c4f289fe30f2709e/doc/logo_pyp.png -------------------------------------------------------------------------------- /doc/modules.rst: -------------------------------------------------------------------------------- 1 | pyparticles 2 | =========== 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | pyparticles 8 | -------------------------------------------------------------------------------- /doc/pyparticles.animation.rst: -------------------------------------------------------------------------------- 1 | animation Package 2 | ================= 3 | 4 | :mod:`animation` Package 5 | ------------------------ 6 | 7 | .. automodule:: pyparticles.animation 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | :mod:`animation` Module 13 | ----------------------- 14 | 15 | .. automodule:: pyparticles.animation.animation 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | 21 | :mod:`animated_ogl` Module 22 | -------------------------- 23 | 24 | .. automodule:: pyparticles.animation.animated_ogl 25 | :members: 26 | :undoc-members: 27 | :show-inheritance: 28 | 29 | :mod:`animated_scatter` Module 30 | ------------------------------ 31 | 32 | .. automodule:: pyparticles.animation.animated_scatter 33 | :members: 34 | :undoc-members: 35 | :show-inheritance: 36 | 37 | 38 | 39 | :mod:`test_animation` Module 40 | ---------------------------- 41 | 42 | .. automodule:: pyparticles.animation.test_animation 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | -------------------------------------------------------------------------------- /doc/pyparticles.demo.rst: -------------------------------------------------------------------------------- 1 | demo Package 2 | ============ 3 | 4 | :mod:`demo` Package 5 | ------------------- 6 | 7 | .. automodule:: pyparticles.demo 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | :mod:`bubble` Module 13 | -------------------- 14 | 15 | .. automodule:: pyparticles.demo.bubble 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | :mod:`gas_lennard_jones` Module 21 | ------------------------------- 22 | 23 | .. automodule:: pyparticles.demo.gas_lennard_jones 24 | :members: 25 | :undoc-members: 26 | :show-inheritance: 27 | 28 | :mod:`solar_system` Module 29 | -------------------------- 30 | 31 | .. automodule:: pyparticles.demo.solar_system 32 | :members: 33 | :undoc-members: 34 | :show-inheritance: 35 | 36 | :mod:`springs` Module 37 | --------------------- 38 | 39 | .. automodule:: pyparticles.demo.springs 40 | :members: 41 | :undoc-members: 42 | :show-inheritance: 43 | 44 | :mod:`springs_constr` Module 45 | ---------------------------- 46 | 47 | .. automodule:: pyparticles.demo.springs_constr 48 | :members: 49 | :undoc-members: 50 | :show-inheritance: 51 | 52 | :mod:`test` Module 53 | ------------------ 54 | 55 | .. automodule:: pyparticles.demo.test 56 | :members: 57 | :undoc-members: 58 | :show-inheritance: 59 | 60 | -------------------------------------------------------------------------------- /doc/pyparticles.forces.rst: -------------------------------------------------------------------------------- 1 | forces Package 2 | ============== 3 | 4 | :mod:`forces` Package 5 | --------------------- 6 | 7 | .. automodule:: pyparticles.forces 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | :mod:`force` Module 13 | ------------------- 14 | 15 | .. automodule:: pyparticles.forces.force 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | :mod:`force_constrained` Module 21 | ------------------------------- 22 | 23 | .. automodule:: pyparticles.forces.force_constrained 24 | :members: 25 | :undoc-members: 26 | :show-inheritance: 27 | 28 | :mod:`gravity` Module 29 | --------------------- 30 | 31 | .. automodule:: pyparticles.forces.gravity 32 | :members: 33 | :undoc-members: 34 | :show-inheritance: 35 | 36 | :mod:`const_force` Module 37 | ------------------------- 38 | 39 | .. automodule:: pyparticles.forces.const_force 40 | :members: 41 | :undoc-members: 42 | :show-inheritance: 43 | 44 | :mod:`drag` Module 45 | ------------------ 46 | 47 | .. automodule:: pyparticles.forces.drag 48 | :members: 49 | :undoc-members: 50 | :show-inheritance: 51 | 52 | 53 | :mod:`damping` Module 54 | --------------------- 55 | 56 | .. automodule:: pyparticles.forces.damping 57 | :members: 58 | :undoc-members: 59 | :show-inheritance: 60 | 61 | 62 | :mod:`electrostatic` Module 63 | --------------------------- 64 | 65 | .. automodule:: pyparticles.forces.electrostatic 66 | :members: 67 | :undoc-members: 68 | :show-inheritance: 69 | 70 | 71 | :mod:`electromagnetic_field` Module 72 | ----------------------------------- 73 | 74 | .. automodule:: pyparticles.forces.electromagnetic_field 75 | :members: 76 | :undoc-members: 77 | :show-inheritance: 78 | 79 | :mod:`lennard_jones` Module 80 | --------------------------- 81 | 82 | .. automodule:: pyparticles.forces.lennard_jones 83 | :members: 84 | :undoc-members: 85 | :show-inheritance: 86 | 87 | :mod:`linear_spring` Module 88 | --------------------------- 89 | 90 | .. automodule:: pyparticles.forces.linear_spring 91 | :members: 92 | :undoc-members: 93 | :show-inheritance: 94 | 95 | :mod:`linear_spring_constrained` Module 96 | --------------------------------------- 97 | 98 | .. automodule:: pyparticles.forces.linear_spring_constrained 99 | :members: 100 | :undoc-members: 101 | :show-inheritance: 102 | 103 | 104 | :mod:`multiple_force` Module 105 | ---------------------------- 106 | 107 | .. automodule:: pyparticles.forces.multiple_force 108 | :members: 109 | :undoc-members: 110 | :show-inheritance: 111 | 112 | :mod:`pseudo_bubble` Module 113 | --------------------------- 114 | 115 | .. automodule:: pyparticles.forces.pseudo_bubble 116 | :members: 117 | :undoc-members: 118 | :show-inheritance: 119 | 120 | :mod:`van_der_waals_force` Module 121 | --------------------------------- 122 | 123 | .. automodule:: pyparticles.forces.van_der_waals_force 124 | :members: 125 | :undoc-members: 126 | :show-inheritance: 127 | 128 | :mod:`vector_field_force` Module 129 | -------------------------------- 130 | 131 | .. automodule:: pyparticles.forces.vector_field_force 132 | :members: 133 | :undoc-members: 134 | :show-inheritance: 135 | 136 | -------------------------------------------------------------------------------- /doc/pyparticles.geometry.rst: -------------------------------------------------------------------------------- 1 | geometry Package 2 | ================ 3 | 4 | :mod:`geometry` Package 5 | ----------------------- 6 | 7 | .. automodule:: pyparticles.geometry 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | :mod:`dist` Module 13 | ------------------ 14 | 15 | .. automodule:: pyparticles.geometry.dist 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | :mod:`intersection` Module 21 | -------------------------- 22 | 23 | .. automodule:: pyparticles.geometry.intersection 24 | :members: 25 | :undoc-members: 26 | :show-inheritance: 27 | 28 | :mod:`transformations` Module 29 | ----------------------------- 30 | 31 | .. automodule:: pyparticles.geometry.transformations 32 | :members: 33 | :undoc-members: 34 | :show-inheritance: 35 | 36 | -------------------------------------------------------------------------------- /doc/pyparticles.main.rst: -------------------------------------------------------------------------------- 1 | main Package 2 | ============ 3 | 4 | :mod:`main` Package 5 | ------------------- 6 | 7 | .. automodule:: pyparticles.main 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | :mod:`main` Module 13 | ------------------ 14 | 15 | .. automodule:: pyparticles.main.main 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | -------------------------------------------------------------------------------- /doc/pyparticles.measures.rst: -------------------------------------------------------------------------------- 1 | measures Package 2 | ================ 3 | 4 | :mod:`measures` Package 5 | ----------------------- 6 | 7 | .. automodule:: pyparticles.measures 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | :mod:`elastic_potential_energy` Module 13 | -------------------------------------- 14 | 15 | .. automodule:: pyparticles.measures.elastic_potential_energy 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | :mod:`gravitational_potential_energy` Module 21 | -------------------------------------------- 22 | 23 | .. automodule:: pyparticles.measures.gravitational_potential_energy 24 | :members: 25 | :undoc-members: 26 | :show-inheritance: 27 | 28 | :mod:`kinetic_energy` Module 29 | ---------------------------- 30 | 31 | .. automodule:: pyparticles.measures.kinetic_energy 32 | :members: 33 | :undoc-members: 34 | :show-inheritance: 35 | 36 | :mod:`mass` Module 37 | ------------------ 38 | 39 | .. automodule:: pyparticles.measures.mass 40 | :members: 41 | :undoc-members: 42 | :show-inheritance: 43 | 44 | :mod:`measure` Module 45 | --------------------- 46 | 47 | .. automodule:: pyparticles.measures.measure 48 | :members: 49 | :undoc-members: 50 | :show-inheritance: 51 | 52 | :mod:`momentum` Module 53 | ---------------------- 54 | 55 | .. automodule:: pyparticles.measures.momentum 56 | :members: 57 | :undoc-members: 58 | :show-inheritance: 59 | 60 | :mod:`total_energy` Module 61 | -------------------------- 62 | 63 | .. automodule:: pyparticles.measures.total_energy 64 | :members: 65 | :undoc-members: 66 | :show-inheritance: 67 | 68 | -------------------------------------------------------------------------------- /doc/pyparticles.ode.rst: -------------------------------------------------------------------------------- 1 | ode Package 2 | =========== 3 | 4 | :mod:`ode` Package 5 | ------------------ 6 | 7 | .. automodule:: pyparticles.ode 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | 13 | :mod:`ode_solver` Module 14 | ------------------------ 15 | 16 | .. automodule:: pyparticles.ode.ode_solver 17 | :members: 18 | :undoc-members: 19 | :show-inheritance: 20 | 21 | :mod:`ode_solver_constrained` Module 22 | ------------------------------------ 23 | 24 | .. automodule:: pyparticles.ode.ode_solver_constrained 25 | :members: 26 | :undoc-members: 27 | :show-inheritance: 28 | 29 | :mod:`sim_time` Module 30 | ------------------------------------ 31 | 32 | .. automodule:: pyparticles.ode.sim_time 33 | :members: 34 | :undoc-members: 35 | :show-inheritance: 36 | 37 | :mod:`euler_solver` Module 38 | -------------------------- 39 | 40 | .. automodule:: pyparticles.ode.euler_solver 41 | :members: 42 | :undoc-members: 43 | :show-inheritance: 44 | 45 | :mod:`euler_solver_constrained` Module 46 | -------------------------------------- 47 | 48 | .. automodule:: pyparticles.ode.euler_solver_constrained 49 | :members: 50 | :undoc-members: 51 | :show-inheritance: 52 | 53 | :mod:`leapfrog_solver` Module 54 | ----------------------------- 55 | 56 | .. automodule:: pyparticles.ode.leapfrog_solver 57 | :members: 58 | :undoc-members: 59 | :show-inheritance: 60 | 61 | :mod:`leapfrog_solver_constrained` Module 62 | ----------------------------------------- 63 | 64 | .. automodule:: pyparticles.ode.leapfrog_solver_constrained 65 | :members: 66 | :undoc-members: 67 | :show-inheritance: 68 | 69 | :mod:`midpoint_solver` Module 70 | ----------------------------- 71 | 72 | .. automodule:: pyparticles.ode.midpoint_solver 73 | :members: 74 | :undoc-members: 75 | :show-inheritance: 76 | 77 | :mod:`midpoint_solver_constrained` Module 78 | ----------------------------------------- 79 | 80 | .. automodule:: pyparticles.ode.midpoint_solver_constrained 81 | :members: 82 | :undoc-members: 83 | :show-inheritance: 84 | 85 | :mod:`runge_kutta_solver` Module 86 | -------------------------------- 87 | 88 | .. automodule:: pyparticles.ode.runge_kutta_solver 89 | :members: 90 | :undoc-members: 91 | :show-inheritance: 92 | 93 | :mod:`runge_kutta_solver_constrained` Module 94 | -------------------------------------------- 95 | 96 | .. automodule:: pyparticles.ode.runge_kutta_solver_constrained 97 | :members: 98 | :undoc-members: 99 | :show-inheritance: 100 | 101 | :mod:`stormer_verlet_solver` Module 102 | ----------------------------------- 103 | 104 | .. automodule:: pyparticles.ode.stormer_verlet_solver 105 | :members: 106 | :undoc-members: 107 | :show-inheritance: 108 | 109 | :mod:`stormer_verlet_solver_constrained` Module 110 | ----------------------------------------------- 111 | 112 | .. automodule:: pyparticles.ode.stormer_verlet_solver_constrained 113 | :members: 114 | :undoc-members: 115 | :show-inheritance: 116 | 117 | -------------------------------------------------------------------------------- /doc/pyparticles.ogl.rst: -------------------------------------------------------------------------------- 1 | ogl Package 2 | =========== 3 | 4 | :mod:`ogl` Package 5 | ------------------ 6 | 7 | .. automodule:: pyparticles.ogl 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | :mod:`axis_ogl` Module 13 | ---------------------- 14 | 15 | .. automodule:: pyparticles.ogl.axis_ogl 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | :mod:`draw_particles_ogl` Module 21 | -------------------------------- 22 | 23 | .. automodule:: pyparticles.ogl.draw_particles_ogl 24 | :members: 25 | :undoc-members: 26 | :show-inheritance: 27 | 28 | :mod:`draw_vector_field` Module 29 | -------------------------------- 30 | 31 | .. automodule:: pyparticles.ogl.draw_vector_field 32 | :members: 33 | :undoc-members: 34 | :show-inheritance: 35 | 36 | :mod:`trackball` Module 37 | ----------------------- 38 | 39 | .. automodule:: pyparticles.ogl.trackball 40 | :members: 41 | :undoc-members: 42 | :show-inheritance: 43 | 44 | :mod:`translate_scene` Module 45 | ----------------------------- 46 | 47 | .. automodule:: pyparticles.ogl.translate_scene 48 | :members: 49 | :undoc-members: 50 | :show-inheritance: 51 | 52 | -------------------------------------------------------------------------------- /doc/pyparticles.pset.rst: -------------------------------------------------------------------------------- 1 | pset Package 2 | ============ 3 | 4 | :mod:`pset` Package 5 | ------------------- 6 | 7 | .. automodule:: pyparticles.pset 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | :mod:`particles_set` Module 13 | --------------------------- 14 | 15 | .. automodule:: pyparticles.pset.particles_set 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | 21 | :mod:`logger` Module 22 | --------------------------- 23 | 24 | .. automodule:: pyparticles.pset.logger 25 | :members: 26 | :undoc-members: 27 | :show-inheritance: 28 | 29 | 30 | :mod:`boundary` Module 31 | ---------------------- 32 | 33 | .. automodule:: pyparticles.pset.boundary 34 | :members: 35 | :undoc-members: 36 | :show-inheritance: 37 | 38 | :mod:`cluster` Module 39 | --------------------- 40 | 41 | .. automodule:: pyparticles.pset.cluster 42 | :members: 43 | :undoc-members: 44 | :show-inheritance: 45 | 46 | :mod:`constrained_force_interactions` Module 47 | -------------------------------------------- 48 | 49 | .. automodule:: pyparticles.pset.constrained_force_interactions 50 | :members: 51 | :undoc-members: 52 | :show-inheritance: 53 | 54 | :mod:`constrained_x` Module 55 | --------------------------- 56 | 57 | .. automodule:: pyparticles.pset.constrained_x 58 | :members: 59 | :undoc-members: 60 | :show-inheritance: 61 | 62 | :mod:`constraint` Module 63 | ------------------------ 64 | 65 | .. automodule:: pyparticles.pset.constraint 66 | :members: 67 | :undoc-members: 68 | :show-inheritance: 69 | 70 | 71 | :mod:`file_cluster` Module 72 | -------------------------- 73 | 74 | .. automodule:: pyparticles.pset.file_cluster 75 | :members: 76 | :undoc-members: 77 | :show-inheritance: 78 | 79 | :mod:`octree` Module 80 | -------------------- 81 | 82 | .. automodule:: pyparticles.pset.octree 83 | :members: 84 | :undoc-members: 85 | :show-inheritance: 86 | 87 | 88 | :mod:`periodic_boundary` Module 89 | ------------------------------- 90 | 91 | .. automodule:: pyparticles.pset.periodic_boundary 92 | :members: 93 | :undoc-members: 94 | :show-inheritance: 95 | 96 | :mod:`rand_cluster` Module 97 | -------------------------- 98 | 99 | .. automodule:: pyparticles.pset.rand_cluster 100 | :members: 101 | :undoc-members: 102 | :show-inheritance: 103 | 104 | :mod:`rebound_boundary` Module 105 | ------------------------------ 106 | 107 | .. automodule:: pyparticles.pset.rebound_boundary 108 | :members: 109 | :undoc-members: 110 | :show-inheritance: 111 | 112 | -------------------------------------------------------------------------------- /doc/pyparticles.rst: -------------------------------------------------------------------------------- 1 | pyparticles Package 2 | =================== 3 | 4 | :mod:`pyparticles` Package 5 | -------------------------- 6 | 7 | .. automodule:: pyparticles.__init__ 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | Subpackages 13 | ----------- 14 | 15 | .. toctree:: 16 | 17 | pyparticles.animation 18 | pyparticles.demo 19 | pyparticles.forces 20 | pyparticles.geometry 21 | pyparticles.main 22 | pyparticles.measures 23 | pyparticles.ode 24 | pyparticles.ogl 25 | pyparticles.pset 26 | pyparticles.utils 27 | 28 | -------------------------------------------------------------------------------- /doc/pyparticles.utils.rst: -------------------------------------------------------------------------------- 1 | utils Package 2 | ============= 3 | 4 | :mod:`utils` Package 5 | -------------------- 6 | 7 | .. automodule:: pyparticles.utils 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | :mod:`parse_args` Module 13 | ------------------------ 14 | 15 | .. automodule:: pyparticles.utils.parse_args 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | :mod:`problem_config` Module 21 | ---------------------------- 22 | 23 | .. automodule:: pyparticles.utils.problem_config 24 | :members: 25 | :undoc-members: 26 | :show-inheritance: 27 | 28 | :mod:`pypart_global` Module 29 | --------------------------- 30 | 31 | .. automodule:: pyparticles.utils.pypart_global 32 | :members: 33 | :undoc-members: 34 | :show-inheritance: 35 | 36 | :mod:`time_formatter` Module 37 | ---------------------------- 38 | 39 | .. automodule:: pyparticles.utils.time_formatter 40 | :members: 41 | :undoc-members: 42 | :show-inheritance: 43 | 44 | -------------------------------------------------------------------------------- /example/cluster_demo.cfg: -------------------------------------------------------------------------------- 1 | [pset_origin] 2 | media_origin = rand 3 | file_name = solar_sys.csv 4 | 5 | [set_config] 6 | #comment 7 | len_unit = 1 8 | mass_unit = 1 9 | boundary = open 10 | boundary_lim = -7 7 11 | sim_log = 0 12 | sim_log_x = True 13 | sim_log_v = False 14 | rand_part_nr = 350 15 | 16 | [model] 17 | force = gravity 18 | ode_solver_name = runge_kutta 19 | time_step = 0.005 20 | steps = 1000000 21 | force_const = 0.001 22 | force_vector = 0 0 -7 23 | 24 | [animation] 25 | animation_type = opengl 26 | draw_trajectory = False 27 | trajectory_step = 15 28 | xlim = -5.0 5.0 29 | ylim = -5.0 5.0 30 | zlim = -5.0 5.0 31 | 32 | [rand_cluster_bar] 33 | rc_part_nr = 150 34 | rc_centre = 0 0 1 35 | rc_radius = 1.0 36 | rc_mass_rng = 0.5 1.0 37 | rc_vel_rng = 0.1 0.2 38 | rc_vel_mdl = no 39 | rc_vel_dir = 0 1 0 40 | rc_r_min = 0.05 41 | 42 | [rand_cluster_foo] 43 | rc_part_nr = 150 44 | rc_centre = 0 0 -1 45 | rc_radius = 2.0 46 | rc_mass_rng = 0.5 2.0 47 | rc_vel_rng = 0.021 0.2 48 | rc_vel_mdl = const 49 | rc_vel_dir = 1 1 0 50 | 51 | [rand_cluster_foobar] 52 | rc_part_nr = 50 53 | rc_centre = 0 3 -3 54 | rc_radius = 2.0 55 | rc_mass_rng = 0.2 2.0 56 | rc_vel_rng = .1 .2 57 | rc_vel_mdl = bomb 58 | rc_vel_dir = 0 1 0 59 | -------------------------------------------------------------------------------- /example/solar_sys.csv: -------------------------------------------------------------------------------- 1 | 10 3 2 | 149597870701 0 0 0 29800 0 5980000000000000000000000 3 | 778357721262.506 0 0 0 13100 0 1900000000000000000000000000 4 | 227987154951.372 0 0 0 24100 0 642000000000000000000000 5 | 58343169574.56 0 0 0 47900 0 330000000000000000000000 6 | 4496911993392.3 0 0 0 5400 0 102000000000000000000000000 7 | 5913603829008.18 0 0 0 4700 0 12900000000000000000000 8 | 1427014088674.07 0 0 0 9600 0 569000000000000000000000000 9 | 2869287160179.44 0 0 0 6800 0 86800000000000000000000000 10 | 104718509496.3 0 0 0 35000 0 4870000000000000000000000 11 | 0 0 0 0 0 0 1989100000000000000000000000000 12 | -------------------------------------------------------------------------------- /example/solar_system.csv: -------------------------------------------------------------------------------- 1 | 12 3 label 2 | 0.0 0.0 0.0 0.0 0.0 0.0 1.9891e+30 Sun 3 | 146717967565.58728 -29212343301.349762 0.0 5819.119112866405 29226.321231901096 0.0 5.98e+24 Earth 4 | -141737567528.98758 765343846771.6844 0.0 -12877.631497874438 -2384.868150103385 298.34696508375396 1.9e+27 Jupiter 5 | 147878129611.8402 173522913839.92435 0.0 -18333.1490114991 15623.710585085148 778.019842721165 6.42e+23 Mars 6 | 38788072827.04515 43582230843.982796 0.0 -35514.11572656068 31607.471221958658 5841.690432872219 3.3e+23 Mercury 7 | -2997004924094.1416 3352637608027.6304 0.0 -4024.0113211290754 -3597.162340229592 166.60127688286767 1.02e+26 Neptune 8 | -2050284719047.1633 5546804740481.89 0.0 -4212.43534299812 -1557.0571198749124 1385.9875924795103 1.29e+22 Pluto 9 | -572262123494.0645 1307243387848.1055 0.0 -8785.992453275763 -3846.1779535874966 416.2352223429017 5.69e+26 Saturn 10 | 791412235351.533 2757983952142.7163 0.0 -6535.62625871414 1875.418666889865 91.62003212866 8.68e+25 Uranus 11 | 24129594267.002003 101900582960.51572 0.0 -33998.42948988567 8050.673366845134 2072.0643237223385 4.87e+24 Venus 12 | 69062768322.07823 408029097624.9563 0.0 -17331.091779415474 2933.450538938322 3285.4299062801424 9.43e+20 Ceres 13 | 147073557743.0722 -29283143234.797813 0.0 6018.687560294239 30228.646745290458 0.0 7.3477e+22 Moon 14 | -------------------------------------------------------------------------------- /man/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | MAN_PREFIX="${PREFIX}/share/man" 4 | 5 | for i in *.1; do 6 | section=`echo ${i}|sed 's/.*\([0-9]\).*/\1/'` 7 | 8 | #echo ${section} 9 | target="${MAN_PREFIX}/man${section}" 10 | 11 | # check if man directory exists 12 | if ! test -d ${target}; then 13 | mkdir -p ${target} 14 | fi 15 | echo "${i} --> ${target}" 16 | install -m644 ${i} ${target} 17 | gzip ${target}/${i} 18 | done -------------------------------------------------------------------------------- /man/pyparticles.1: -------------------------------------------------------------------------------- 1 | usage: pyparticles_app [-h] [-m] 2 | [-d {springs,solar_system,gas_lj,bubble,cat_spri,el_static,elmag_field,fountain,galaxy}] 3 | [-t {fall,harmonic,dharmonic}] [-v] [-a] 4 | [path_name] 5 | 6 | PyParticles is a particle simulation tool box that support the most diffused 7 | numerical integration and forces models 8 | 9 | positional arguments: 10 | path_name 11 | 12 | optional arguments: 13 | -h, --help show this help message and exit 14 | -m, --config_model Write out the model of a config file and exit 15 | -d {springs,solar_system,gas_lj,bubble,cat_spri,el_static,elmag_field,fountain,galaxy}, --demo {springs,solar_system,gas_lj,bubble,cat_spri,el_static,elmag_field,fountain,galaxy} 16 | Execute the specified buildin demo 17 | -t {fall,harmonic,dharmonic}, --test {fall,harmonic,dharmonic} 18 | Execute the specified buildin test 19 | -v, --version print the current version and exit 20 | -a, --about print the about message and exit 21 | 22 | -------------------------------------------------------------------------------- /pyparticles/__init__.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | 18 | __all__ = [ "pset" , 19 | "ogl" , 20 | "ode" , 21 | "utils" , 22 | "forces" , 23 | "demo" , 24 | "animation" , 25 | "measures" , 26 | "main" ] 27 | -------------------------------------------------------------------------------- /pyparticles/animation/__init__.py: -------------------------------------------------------------------------------- 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 . 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")] -------------------------------------------------------------------------------- /pyparticles/animation/animated_cli.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import pyparticles.animation.animation as pan 18 | import pyparticles.utils.time_formatter as tf 19 | 20 | import numpy as np 21 | import sys 22 | 23 | 24 | class AnimatedCLI( pan.Animation ): 25 | def __init__(self): 26 | super( AnimatedCLI , self ).__init__() 27 | 28 | def build_animation(self): 29 | print( "Build ... " ) 30 | 31 | def data_stream(self): 32 | 33 | self.pset.log() 34 | self.ode_solver.step() 35 | 36 | self.perform_measurement() 37 | 38 | self.update_fps() 39 | 40 | return self.ode_solver.steps_cnt 41 | 42 | def closing_procedure(self): 43 | pass 44 | 45 | def start(self): 46 | tfrmt = tf.MyTimeFormatter() 47 | for i in range( self.steps ): 48 | self.data_stream() 49 | 50 | if np.mod( self.ode_solver.steps_cnt , 100 ): 51 | print( "time: %s " % ( tfrmt.to_str( self.ode_solver.time ) ) ) 52 | 53 | self.closing_procedure() -------------------------------------------------------------------------------- /pyparticles/animation/animated_scatter.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import pyparticles.pset.particles_set as ps 18 | 19 | import pyparticles.animation.animation as pan 20 | 21 | #import pyparticles.rand_cluster as clu 22 | #import pyparticles.euler_solver as els 23 | #import pyparticles.leapfrog_solver as lps 24 | #import pyparticles.runge_kutta_solver as rks 25 | 26 | import matplotlib.animation as animation 27 | 28 | from mpl_toolkits.mplot3d import Axes3D 29 | import matplotlib.pyplot as plt 30 | import numpy as np 31 | #import pyparticles.periodic_boundary as pb 32 | #import pyparticles.rebound_boundary as rb 33 | 34 | 35 | 36 | FLOOR = -10 37 | CEILING = 10 38 | 39 | class AnimatedScatter( pan.Animation ): 40 | 41 | def __init__(self, numpoints=50): 42 | super( AnimatedScatter , self ).__init__() 43 | 44 | 45 | def build_animation(self): 46 | self.fig = plt.figure() 47 | self.ax = self.fig.add_subplot(111, projection='3d') 48 | 49 | self.stream = self.data_stream() 50 | 51 | self.ani = animation.FuncAnimation(self.fig, self.update, interval=5, 52 | init_func=self.setup_plot, blit=True) 53 | 54 | 55 | def setup_plot(self): 56 | 57 | j = next(self.stream) 58 | self.scat = self.ax.scatter( self.pset.X[:,0]/self.pset.unit , 59 | self.pset.X[:,1]/self.pset.unit , 60 | self.pset.X[:,2]/self.pset.unit , 61 | animated=True , marker='o' , alpha=None , s=10) 62 | 63 | self.ax.set_xlim3d( self.xlim ) 64 | self.ax.set_ylim3d( self.ylim ) 65 | self.ax.set_zlim3d( self.zlim ) 66 | 67 | return self.scat, 68 | 69 | 70 | def data_stream(self): 71 | 72 | self.ode_solver.update_force() 73 | 74 | for j in range(self.steps): 75 | self.ode_solver.step() 76 | yield j 77 | 78 | 79 | 80 | def update(self, i): 81 | """Update the scatter plot.""" 82 | j = next(self.stream) 83 | 84 | self.scat._offsets3d = ( np.ma.ravel(self.pset.X[:,0]/self.pset.unit) , 85 | np.ma.ravel(self.pset.X[:,1]/self.pset.unit) , 86 | np.ma.ravel(self.pset.X[:,2]/self.pset.unit) 87 | ) 88 | 89 | plt.draw() 90 | return self.scat, 91 | 92 | def start(self): 93 | plt.show() 94 | 95 | -------------------------------------------------------------------------------- /pyparticles/demo/__init__.py: -------------------------------------------------------------------------------- 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 . 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")] 22 | 23 | -------------------------------------------------------------------------------- /pyparticles/demo/bubble.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import pyparticles.pset.particles_set as ps 18 | 19 | import pyparticles.forces.pseudo_bubble as pb 20 | import pyparticles.forces.const_force as cf 21 | import pyparticles.forces.drag as dr 22 | import pyparticles.forces.multiple_force as mf 23 | 24 | import pyparticles.ode.euler_solver as els 25 | import pyparticles.ode.leapfrog_solver as lps 26 | import pyparticles.ode.runge_kutta_solver as rks 27 | import pyparticles.ode.stormer_verlet_solver as svs 28 | import pyparticles.ode.midpoint_solver as mds 29 | 30 | import pyparticles.pset.rand_cluster as rc 31 | import pyparticles.pset.rebound_boundary as rb 32 | 33 | import pyparticles.animation.animated_ogl as aogl 34 | 35 | import numpy as np 36 | 37 | from pyparticles.utils.pypart_global import test_pyopencl 38 | import pyparticles.pset.opencl_context as occ 39 | 40 | 41 | def bubble(): 42 | """ 43 | Pseudo bubble simulation 44 | """ 45 | 46 | ocl_ok = test_pyopencl() 47 | 48 | if ocl_ok : 49 | pcnt = 9000 50 | r_min=0.5 51 | occx = occ.OpenCLcontext( pcnt , 3 ) 52 | else : 53 | pcnt = 700 54 | r_min = 1.5 55 | 56 | steps = 1000000 57 | dt = 0.01 58 | 59 | 60 | rand_c = rc.RandCluster() 61 | 62 | pset = ps.ParticlesSet( pcnt , dtype=np.float32 ) 63 | 64 | rand_c.insert3( X=pset.X , 65 | M=pset.M , 66 | start_indx=0 , 67 | n=pset.size , 68 | radius=3.0 , 69 | mass_rng=(0.5,0.8) , 70 | r_min=0.0 ) 71 | 72 | if ocl_ok : 73 | bubble = pb.PseudoBubbleOCL( pset.size , pset.dim , Consts=(r_min,10) ) 74 | drag = dr.DragOCL( pset.size , pset.dim , Consts=0.01 ) 75 | else : 76 | bubble = pb.PseudoBubble( pset.size , pset.dim , Consts=(r_min,10) ) 77 | drag = dr.Drag( pset.size , pset.dim , Consts=0.01 ) 78 | 79 | constf = cf.ConstForce( pset.size , dim=pset.dim , u_force=[ 0 , 0 , -10.0 ] ) 80 | 81 | multif = mf.MultipleForce( pset.size , pset.dim ) 82 | multif.append_force( bubble ) 83 | multif.append_force( constf ) 84 | multif.append_force( drag ) 85 | 86 | multif.set_masses( pset.M ) 87 | 88 | #solver = els.EulerSolver( multif , pset , dt ) 89 | #solver = lps.LeapfrogSolver( multif , pset , dt ) 90 | solver = svs.StormerVerletSolver( multif , pset , dt ) 91 | #solver = rks.RungeKuttaSolver( lennard_jones , pset , dt ) 92 | #solver = mds.MidpointSolver( lennard_jones , pset , dt ) 93 | 94 | bound = rb.ReboundBoundary( bound=(-5.0,5.0) ) 95 | 96 | pset.set_boundary( bound ) 97 | 98 | a = aogl.AnimatedGl() 99 | 100 | a.ode_solver = solver 101 | a.pset = pset 102 | a.steps = steps 103 | 104 | if ocl_ok : 105 | a.draw_particles.set_draw_model( a.draw_particles.DRAW_MODEL_VECTOR ) 106 | 107 | a.init_rotation( -80 , [ 0.7 , 0.05 , 0 ] ) 108 | 109 | a.build_animation() 110 | 111 | a.start() 112 | 113 | return 114 | -------------------------------------------------------------------------------- /pyparticles/demo/electromagnetic_demo.py: -------------------------------------------------------------------------------- 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 . 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 | 129 | -------------------------------------------------------------------------------- /pyparticles/demo/electrostatic_demo.py: -------------------------------------------------------------------------------- 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 . 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 -------------------------------------------------------------------------------- /pyparticles/demo/fountain.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | 18 | import numpy as np 19 | 20 | import pyparticles.pset.particles_set as ps 21 | 22 | import pyparticles.pset.opencl_context as occ 23 | 24 | import pyparticles.ode.euler_solver as els 25 | import pyparticles.ode.leapfrog_solver as lps 26 | import pyparticles.ode.runge_kutta_solver as rks 27 | import pyparticles.ode.stormer_verlet_solver as svs 28 | import pyparticles.ode.midpoint_solver as mds 29 | 30 | import pyparticles.forces.const_force as cf 31 | import pyparticles.forces.drag as dr 32 | import pyparticles.forces.multiple_force as mf 33 | 34 | import pyparticles.animation.animated_ogl as aogl 35 | 36 | import pyparticles.pset.default_boundary as db 37 | 38 | from pyparticles.utils.pypart_global import test_pyopencl 39 | 40 | def default_pos( pset , indx ): 41 | 42 | t = default_pos.sim_time.time 43 | 44 | pset.X[indx,:] = 0.01 * np.random.rand( len(indx) , pset.dim ).astype( pset.dtype ) 45 | 46 | fs = 1.0 / ( 1.0 + np.exp( -( t*4.0 - 2.0 ) ) ) 47 | 48 | alpha = 2.0 * np.pi * np.random.rand( len(indx) ).astype( pset.dtype ) 49 | 50 | vel_x = 2.0 * fs * np.cos( alpha ) 51 | vel_y = 2.0 * fs * np.sin( alpha ) 52 | 53 | pset.V[indx,0] = vel_x 54 | pset.V[indx,1] = vel_y 55 | pset.V[indx,2] = 10.0 * fs + 1.0 * fs * ( np.random.rand( len(indx)) ) 56 | 57 | 58 | def fountain(): 59 | """ 60 | Fountain demo 61 | """ 62 | steps = 10000000 63 | dt = 0.005 64 | pcnt = 100000 65 | 66 | fl = True 67 | if test_pyopencl() : 68 | print( "OpenCL is installed and enabled " ) 69 | print( " Try, at least, 200000 particles " ) 70 | 71 | while fl : 72 | try : 73 | print( " " ) 74 | pcnt = int( input('How many particles: ') ) 75 | except : 76 | print( "Please insert a number! " ) 77 | else : 78 | fl = False 79 | 80 | 81 | 82 | pset = ps.ParticlesSet( pcnt , dtype=np.float32 ) 83 | 84 | pset.M[:] = 0.1 85 | pset.X[:,2] = 0.7 * np.random.rand( pset.size ) 86 | 87 | grav = cf.ConstForce( pset.size , dim=pset.dim , u_force=( 0.0 , 0.0 , -10.0 ) ) 88 | 89 | occx = None 90 | if test_pyopencl() : 91 | occx = occ.OpenCLcontext( pset.size , pset.dim , ( occ.OCLC_X | occ.OCLC_V | occ.OCLC_A | occ.OCLC_M ) ) 92 | drag = dr.DragOCL( pset.size , dim=pset.dim , Consts=0.01 , ocl_context=occx ) 93 | else : 94 | drag = dr.Drag( pset.size , dim=pset.dim , Consts=0.01 ) 95 | 96 | 97 | multi = mf.MultipleForce( pset.size , dim=pset.dim ) 98 | 99 | multi.append_force( grav ) 100 | multi.append_force( drag ) 101 | 102 | multi.set_masses( pset.M ) 103 | 104 | #solver = mds.MidpointSolver( multi , pset , dt ) 105 | if test_pyopencl() : 106 | solver = els.EulerSolverOCL( multi , pset , dt , ocl_context=occx ) 107 | else : 108 | solver = els.EulerSolver( multi , pset , dt ) 109 | 110 | 111 | solver.update_force() 112 | 113 | default_pos.sim_time = solver.get_sim_time() 114 | 115 | bd = ( -100.0 , 100.0 , -100.0 , 100.0 , 0.0 , 100.0 ) 116 | bound = db.DefaultBoundary( bd , dim=3 , defualt_pos=default_pos ) 117 | 118 | pset.set_boundary( bound ) 119 | 120 | a = aogl.AnimatedGl() 121 | 122 | a.ode_solver = solver 123 | a.pset = pset 124 | a.steps = steps 125 | 126 | a.draw_particles.set_draw_model( a.draw_particles.DRAW_MODEL_VECTOR ) 127 | 128 | a.init_rotation( -80 , [ 0.7 , 0.05 , 0 ] ) 129 | 130 | a.build_animation() 131 | a.start() 132 | 133 | return 134 | 135 | 136 | -------------------------------------------------------------------------------- /pyparticles/demo/gas_lennard_jones.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | 19 | import pyparticles.pset.particles_set as ps 20 | 21 | import pyparticles.forces.lennard_jones as lj 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.periodic_boundary as pb 34 | 35 | import pyparticles.animation.animated_ogl as aogl 36 | 37 | import sys 38 | 39 | def gas_lj(): 40 | """ 41 | Gas simulation based on the Lennard Jones force 42 | """ 43 | 44 | steps = 1000000 45 | dt = 0.001 46 | 47 | omicron = 0.05 48 | epsilon = 1.0 49 | 50 | rand_c = rc.RandCluster() 51 | 52 | pset = ps.ParticlesSet( 1000 ) 53 | 54 | r_min = 2.0**(1./6.) * omicron 55 | 56 | rand_c.insert3( X=pset.X , 57 | M=pset.M , 58 | start_indx=0 , 59 | n=pset.size , 60 | radius=5.0 , 61 | mass_rng=(0.1,0.3) , 62 | r_min=r_min ) 63 | 64 | lennard_jones = lj.LenardJones( pset.size , pset.dim , pset.M , Consts=( epsilon , omicron ) ) 65 | 66 | solver = els.EulerSolver( lennard_jones , pset , dt ) 67 | #solver = lps.LeapfrogSolver( lennard_jones , pset , dt ) 68 | #solver = svs.StormerVerletSolver( lennard_jones , pset , dt ) 69 | #solver = rks.RungeKuttaSolver( lennard_jones , pset , dt ) 70 | #solver = mds.MidpointSolver( lennard_jones , pset , dt ) 71 | 72 | bound = pb.PeriodicBoundary( bound=(-6.0,6.0) ) 73 | 74 | pset.set_boundary( bound ) 75 | 76 | a = aogl.AnimatedGl() 77 | 78 | a.ode_solver = solver 79 | a.pset = pset 80 | a.steps = steps 81 | 82 | a.build_animation() 83 | 84 | a.start() 85 | 86 | return 87 | -------------------------------------------------------------------------------- /pyparticles/demo/gravity_clusters.py: -------------------------------------------------------------------------------- 1 | # PyParticles : Particles simulation in python 2 | # Copyright (C) 2012 Simone Riva mail: simone {dot} 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 . 16 | 17 | import pyparticles.pset.rand_cluster as clu 18 | import pyparticles.forces.gravity as gr 19 | 20 | import pyparticles.ode.euler_solver as els 21 | 22 | import pyparticles.pset.particles_set as ps 23 | import pyparticles.pset.opencl_context as occ 24 | 25 | import pyparticles.animation.animated_ogl as aogl 26 | 27 | from pyparticles.utils.pypart_global import test_pyopencl 28 | 29 | import numpy as np 30 | 31 | def gravity_cluster(): 32 | 33 | if not test_pyopencl() : 34 | print("") 35 | print("Attention !!! ") 36 | print(" This demo works only with PyOpenCL: \n http://mathema.tician.de/software/pyopencl \n http://www.khronos.org/opencl/ \n ") 37 | print(" Please install the package: python-pyopencl for continuing") 38 | print("") 39 | return 40 | 41 | 42 | G = 0.000001 43 | steps = 100000000 44 | 45 | n = 3000 46 | dt = 0.04 47 | 48 | pset = ps.ParticlesSet( n , dtype=np.float32 ) 49 | 50 | cs = clu.RandGalaxyCluster() 51 | 52 | print("Building initial galaxy .... ") 53 | cs.insert3( pset.X, M=pset.M, V=pset.V , G=G ) 54 | 55 | try : 56 | occx = occ.OpenCLcontext( pset.size , pset.dim , (occ.OCLC_X|occ.OCLC_V|occ.OCLC_A|occ.OCLC_M) ) 57 | except : 58 | print("") 59 | print("ERROR !!! ") 60 | print(" Please verify your opencl installation ") 61 | print(" Probably you must install your GPU OpenCL drivers") 62 | print("") 63 | return 64 | 65 | grav = gr.GravityOCL( pset.size , Consts=G , ocl_context=occx ) 66 | grav.set_masses( pset.M ) 67 | 68 | grav.update_force( pset ) 69 | 70 | solver = els.EulerSolverOCL( grav , pset , dt , ocl_context=occx ) 71 | 72 | a = aogl.AnimatedGl() 73 | 74 | a.draw_particles.set_draw_model( a.draw_particles.DRAW_MODEL_VECTOR ) 75 | 76 | a.ode_solver = solver 77 | a.pset = pset 78 | a.steps = steps 79 | 80 | a.build_animation() 81 | 82 | a.start() 83 | 84 | return 85 | -------------------------------------------------------------------------------- /pyparticles/demo/springs.py: -------------------------------------------------------------------------------- 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 . 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 -------------------------------------------------------------------------------- /pyparticles/demo/springs_constr.py: -------------------------------------------------------------------------------- 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 . 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 as els 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 = 60 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[15:20,1] = 4 80 | #pset.X[10:15,1] = 6 81 | 82 | ci = np.array( [ 0 , len(ar)-1 ] ) 83 | cx = np.array( [ 84 | [ -4.0 , -4.0 , 3.0] , 85 | [ 4.0 , 4.0 , 3.0] 86 | ] ) 87 | 88 | f_conn = list([]) 89 | for i in range( len(ar) - 1 ): 90 | f_conn.append( list( [ i , i+1 ] ) ) 91 | 92 | f_conn = np.array( f_conn , np.float64 ) 93 | 94 | costrs = csx.ConstrainedX( pset ) 95 | costrs.add_x_constraint( ci , cx ) 96 | 97 | fi = cfi.ConstrainedForceInteractions( pset ) 98 | 99 | fi.add_connections( f_conn ) 100 | 101 | spring = lsc.LinearSpringConstrained( pset.size , pset.dim , pset.M , Consts=K , f_inter=fi ) 102 | constf = cf.ConstForce( pset.size , dim=pset.dim , u_force=[ 0 , 0 , -10 ] ) 103 | drag = dr.Drag( pset.size , pset.dim , Consts=0.003 ) 104 | #damp = da.Damping( pset.size , pset.dim , Consts=0.003 ) 105 | 106 | multif = mf.MultipleForce( pset.size , pset.dim ) 107 | multif.append_force( spring ) 108 | multif.append_force( constf ) 109 | multif.append_force( drag ) 110 | 111 | multif.set_masses( pset.M ) 112 | 113 | solver = els.EulerSolverConstrained( multif , pset , dt , costrs ) 114 | #solver = lpc.LeapfrogSolverConstrained( multif , pset , dt , costrs ) 115 | #solver = svc.StormerVerletSolverConstrained( multif , pset , dt , costrs ) 116 | #solver = rkc.RungeKuttaSolverConstrained( multif , pset , dt , costrs ) 117 | #solver = mdc.MidpointSolverConstrained( multif , pset , dt , costrs ) 118 | 119 | a = aogl.AnimatedGl() 120 | 121 | pset.enable_log( True , log_max_size=1000 ) 122 | 123 | a.trajectory = False 124 | a.trajectory_step = 1 125 | 126 | a.ode_solver = solver 127 | a.pset = pset 128 | a.steps = steps 129 | 130 | a.init_rotation( -80 , [ 0.7 , 0.05 , 0 ] ) 131 | 132 | a.build_animation() 133 | 134 | a.start() 135 | 136 | return 137 | -------------------------------------------------------------------------------- /pyparticles/demo/test.py: -------------------------------------------------------------------------------- 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 . 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() -------------------------------------------------------------------------------- /pyparticles/forces/__init__.py: -------------------------------------------------------------------------------- 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 . 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")] 22 | -------------------------------------------------------------------------------- /pyparticles/forces/const_force.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | import pyparticles.forces.force as fr 19 | 20 | class ConstForce( fr.Force ) : 21 | """ 22 | Constant force field. 23 | 24 | Constructor 25 | 26 | :param size: the number of particles in the system 27 | :param dim: the dimension of the system 28 | :param m: a vector containig the masses 29 | :param u_force: The force vector (Force per unit of mass) 30 | """ 31 | 32 | def __init__(self , size , dim=3 , m=None , u_force=[0,0,0] , Consts=1.0 ): 33 | self.__dim = dim 34 | self.__size = size 35 | self.__G = Consts 36 | self.__UF = np.array( u_force ) 37 | self.__A = np.zeros( ( size , dim ) ) 38 | self.__M = np.zeros( ( size , 1 ) ) 39 | if m != None : 40 | self.set_messes( m ) 41 | 42 | self.__A[:] = self.__UF 43 | 44 | 45 | def set_masses( self , m ): 46 | self.__M[:] = m 47 | 48 | def update_force( self , p_set ): 49 | return self.__A 50 | 51 | def getA(self): 52 | return self.__A 53 | 54 | A = property( getA ) 55 | 56 | def getF(self): 57 | return self.__A * self.__M 58 | 59 | F = property( getF ) 60 | 61 | -------------------------------------------------------------------------------- /pyparticles/forces/electromagnetic.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | import scipy.spatial.distance as dist 19 | 20 | import pyparticles.forces.force as fr 21 | 22 | class Electromagnetic( fr.Force ) : 23 | r""" 24 | Compute the electromagnetic force of a self-interacting particles system according to the Lorenz formulation. 25 | 26 | 27 | 28 | Not yet tested. 29 | """ 30 | def __init__( self , size , dim=3 , m=None , Consts=1.0 ): 31 | 32 | self.__dim = dim 33 | self.__size = size 34 | 35 | self.__Ke = Consts[0] 36 | self.__Km = Consts[1] 37 | 38 | self.__Am = np.zeros( ( size , dim ) ) 39 | self.__Ae = np.zeros( ( size , dim ) ) 40 | 41 | self.__Fe = np.zeros( ( size , size ) ) 42 | self.__Fm = np.zeros( ( size , size ) ) 43 | 44 | self.__V = np.zeros( ( size , size ) ) 45 | self.__D = np.zeros( ( size , size ) ) 46 | self.__Q = np.zeros( ( size , size ) ) 47 | self.__M = np.zeros( ( size , 1 ) ) 48 | 49 | self.__r = np.zeros( ( size , dim ) ) 50 | 51 | self.__Cr = np.zeros( ( size , dim ) ) 52 | 53 | if m != None : 54 | self.set_masses( m ) 55 | 56 | def set_masses( self , m ): 57 | self.__M[:] = m 58 | 59 | def set_charges( self , q ): 60 | self.__Q[:,:] = q 61 | self.__Q[:,:] = self.__Q * self.__Q.T 62 | 63 | def update_force( self , p_set ): 64 | self.__D[:] = dist.squareform( dist.pdist( p_set.X , 'euclidean' ) ) 65 | 66 | self.__Fe[:] = self.__Ke * self.__Q[:] / ( ( self.__D[:] ) ** 3.0 ) 67 | self.__Fm[:] = self.__Km * self.__Q[:] / ( ( self.__D[:] ) ** 2.0 ) 68 | 69 | np.fill_diagonal( self.__Fe , 0.0 ) 70 | np.fill_diagonal( self.__Fm , 0.0 ) 71 | 72 | for i in range( self.__dim ): 73 | self.__V[:,:] = p_set.X[:,i] 74 | self.__V[:,:] = ( self.__V[:,:].T - p_set.X[:,i] ).T 75 | 76 | self.__Ae[:,i] = np.sum( self.__Fe * self.__V[:,:] , 0 ) 77 | 78 | r = self.__r 79 | for j in range( self.__size ) : 80 | r[:] = p_set.X[j,:] - p_set.X[:] 81 | 82 | r[:] = (r.T / np.sqrt( np.sum(r**2,1))).T 83 | r[j,:] = 0.0 84 | 85 | r[:] = np.cross( p_set.V[:] , r[:] ) 86 | r[:] = np.cross( p_set.V[j,:] , r[:] ) 87 | 88 | self.__Am[j,:] = np.sum( self.__Fm[:,j].T * r[:] , 0 ).T / self.__M[j] 89 | 90 | 91 | #print( self.__X ) 92 | self.__A[:] = self.__Ae + self.__Am 93 | 94 | return self.__A 95 | 96 | def getA(self): 97 | return self.__A 98 | 99 | A = property( getA ) 100 | 101 | 102 | def getF(self): 103 | return self.__A * self.__M 104 | 105 | F = property( getF ) 106 | -------------------------------------------------------------------------------- /pyparticles/forces/electromagnetic_field.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | import sys 19 | import scipy.spatial.distance as dist 20 | 21 | import pyparticles.forces.force as fr 22 | 23 | import random 24 | 25 | class ElectromagneticField( fr.Force ) : 26 | r""" 27 | Compute the electromagnetic force of a system of charged and non-selfinteracting particles system immersed in an electromagnetic filed according to the Lorenz formulation. 28 | 29 | .. math:: 30 | 31 | \mathbf{F} = q(\mathbf{E} + \mathbf{v} \times \mathbf{B}) 32 | """ 33 | 34 | def __init__( self , size , dim=3 , m=None , q=None , Consts=1.0 ): 35 | 36 | self.__dim = dim 37 | self.__size = size 38 | 39 | #self.__Ke = Consts[0] 40 | #self.__Km = Consts[1] 41 | 42 | self.__A = np.zeros( ( size , dim ) ) 43 | 44 | self.__E = np.zeros( ( size , dim ) ) 45 | self.__B = np.zeros( ( size , dim ) ) 46 | 47 | self.__Fe = np.zeros( ( size , dim ) ) 48 | self.__Fm = np.zeros( ( size , dim ) ) 49 | 50 | self.__M = np.zeros( ( size , 1 ) ) 51 | self.__Q = np.zeros( ( size , 1 ) ) 52 | 53 | self.__Cr = np.zeros( ( size , dim ) ) 54 | 55 | if m is not None: 56 | self.set_masses( m ) 57 | 58 | if q is not None: 59 | self.set_charges( q ) 60 | 61 | self.__el_fields = dict() 62 | self.__ma_fields = dict() 63 | 64 | def set_masses( self , m ): 65 | self.__M[:] = m 66 | 67 | def set_charges( self , q ): 68 | self.__Q[:] = q 69 | 70 | def append_electric_field( self , ef , key=None ): 71 | r""" 72 | Append a vector field funcion to the list of electric field funtions. 73 | 74 | The field function must be in the form 75 | | ef( E , X ) 76 | | 77 | | Where: 78 | | E is a n by 3 numpy array of vectors used for the resulting filed. 79 | | X is a n by 3 numpy array of coordinates 80 | """ 81 | if key == None : 82 | key = str( random.randint( 0 , 2**64 ) ) 83 | 84 | self.__el_fields[key] = ef 85 | 86 | return key 87 | 88 | def append_magnetic_field( self , bf , key=None ): 89 | r""" 90 | Append a vector field funcion to the list of megnetic field funtions. 91 | 92 | It return the key used to identify the funtion, if key == None it uses a random number. 93 | 94 | The filed function must be in the form 95 | | bf( B , X ) 96 | | 97 | | Where: 98 | | B is a n by 3 numpy array of vectors used for the resulting filed. 99 | | X is a n by 3 numpy array of coordinates 100 | """ 101 | if key == None : 102 | key = str( random.randint( 0 , 2**64 ) ) 103 | 104 | self.__ma_fields[key] = bf 105 | 106 | return key 107 | 108 | 109 | def update_force( self , pset ): 110 | 111 | self.__Fe[:] = 0.0 112 | self.__Fm[:] = 0.0 113 | 114 | for key in self.__el_fields.keys() : 115 | self.__el_fields[key]( self.__E , pset.X[:] ) 116 | self.__Fe[:] = self.__Fe[:] + self.__Q[:] * self.__E[:] 117 | 118 | 119 | for key in self.__ma_fields.keys() : 120 | self.__ma_fields[key]( self.__B , pset.X[:] ) 121 | self.__Fm[:] = self.__Fm[:] + self.__Q[:] * np.cross( pset.V[:] , self.__B[:] ) 122 | 123 | self.__Fe[:] += self.__Fm[:] 124 | 125 | self.__A[:] = self.__Fe[:] / self.__M[:] 126 | 127 | return self.__A 128 | 129 | 130 | def getA(self): 131 | return self.__A 132 | 133 | A = property( getA ) 134 | 135 | 136 | def getF(self): 137 | return self.__Fe 138 | 139 | F = property( getF ) 140 | -------------------------------------------------------------------------------- /pyparticles/forces/electrostatic.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | import sys 19 | import scipy.spatial.distance as dist 20 | 21 | import pyparticles.forces.force as fr 22 | 23 | class Electrostatic( fr.Force ) : 24 | r""" 25 | Compute the electrostatic force using the Culomb law. 26 | 27 | ..note:: 28 | 29 | The real forces of an electrodynamic system is given by the **Maxwell equations**! and not from the Culomb law. 30 | 31 | The Culomb law is adapt for computing forces in a static system of particles and not for moving particles. 32 | 33 | But for a very slow movement it should be a good approximation. 34 | 35 | .. math:: 36 | 37 | \vec F = k \, q_1 \, q_2 \, \frac {\vec r_1 - \vec r_2}{\left \| \vec r_1 - \vec r_2 \right \|^3} 38 | """ 39 | def __init__(self , size , dim=3 , m=None , q=None , Consts=1.0 ): 40 | 41 | self.__dim = dim 42 | self.__size = size 43 | self.__K = Consts # Culomb constant! 44 | self.__A = np.zeros( ( size , dim ) ) 45 | self.__Fm = np.zeros( ( size , size ) ) 46 | self.__V = np.zeros( ( size , size ) ) 47 | self.__D = np.zeros( ( size , size ) ) 48 | self.__Q = np.zeros( ( size , size ) ) 49 | self.__M = np.zeros( ( size , 1 ) ) 50 | 51 | if m != None : 52 | self.set_masses( m ) 53 | 54 | if q != None : 55 | self.set_charges( q ) 56 | 57 | 58 | def set_masses( self , m ): 59 | self.__M[:] = m 60 | 61 | def set_charges( self , q ): 62 | self.__Q[:,:] = q 63 | self.__Q[:,:] = self.__Q * self.__Q.T 64 | 65 | def update_force( self , p_set ): 66 | 67 | self.__D[:] = dist.squareform( dist.pdist( p_set.X , 'euclidean' ) ) 68 | 69 | self.__Fm[:] = self.__K * self.__Q[:] / ( ( self.__D[:] ) ** 3.0 ) 70 | 71 | #for j in range( self.__size ) : 72 | # self.__Fm[j,j] = 0.0 73 | 74 | np.fill_diagonal( self.__Fm , 0.0 ) 75 | 76 | for i in range( self.__dim ): 77 | self.__V[:,:] = p_set.X[:,i] 78 | self.__V[:,:] = ( self.__V[:,:].T - p_set.X[:,i] ).T 79 | 80 | self.__A[:,i] = np.sum( self.__Fm * self.__V[:,:] , 0 ) / self.__M.T 81 | 82 | 83 | #print( self.__X ) 84 | 85 | return self.__A 86 | 87 | def getA(self): 88 | return self.__A 89 | 90 | A = property( getA ) 91 | 92 | 93 | def getF(self): 94 | return self.__A * self.__M 95 | 96 | F = property( getF ) 97 | 98 | -------------------------------------------------------------------------------- /pyparticles/forces/force.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import sys 18 | 19 | class Force(object): 20 | """ 21 | The main abstract class used as interface for the forces classes 22 | 23 | Constructor 24 | 25 | :param size: the number of particles in the system 26 | :param dim: the dimension of the system (3D, 2D..) 27 | :param m: a vector containig the masses 28 | :param Const: the force constants (Like G, K ...) 29 | """ 30 | 31 | def __init__(self , size , dim , m=None , Conts=1.0 ): 32 | NotImplementedError(" %s : is virtual and must be overridden." % sys._getframe().f_code.co_name ) 33 | 34 | def set_masses( self , m ): 35 | """ 36 | Set the masses used for computing the forces. 37 | 38 | :param m: An array containig the masses 39 | """ 40 | NotImplementedError(" %s : is virtual and must be overridden." % sys._getframe().f_code.co_name ) 41 | 42 | def update_force( self , p_set ): 43 | """ 44 | Computes the forces of the current status ad return the accelerations of the particles 45 | 46 | :param p_set: Particles set obj. 47 | """ 48 | NotImplementedError(" %s : is virtual and must be overridden." % sys._getframe().f_code.co_name ) 49 | 50 | def getA(self): 51 | """ 52 | return the array of the acclerations 53 | """ 54 | NotImplementedError(" %s : is virtual and must be overridden." % sys._getframe().f_code.co_name ) 55 | 56 | A = property( getA , doc="(property) return the array of the acclerations") 57 | 58 | def getF(self): 59 | """ 60 | returns the array of the forces 61 | """ 62 | NotImplementedError(" %s : is virtual and must be overridden." % sys._getframe().f_code.co_name ) 63 | 64 | F = property( getF , doc="(property) returns the array of the forces" ) 65 | 66 | 67 | def get_const( self ): 68 | """ 69 | returns the force contants 70 | """ 71 | NotImplementedError(" %s : is virtual and must be overridden." % sys._getframe().f_code.co_name ) 72 | 73 | const = property( get_const , doc="(property) returns the force contants") 74 | 75 | 76 | -------------------------------------------------------------------------------- /pyparticles/forces/force_constrained.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | 19 | import pyparticles.forces.force as fr 20 | 21 | class ForceConstrained( fr.Force ) : 22 | def __init__( self , size , dim , m=None , Conts=1.0 , f_inter=None ): 23 | self.__f_inter = f_inter 24 | 25 | 26 | def get_force_interactions( self ): 27 | return self.__f_inter 28 | 29 | def set_force_interactions( self , fi ): 30 | self.__f_inter = fi 31 | 32 | force_interactions = property( get_force_interactions , set_force_interactions ) 33 | -------------------------------------------------------------------------------- /pyparticles/forces/lennard_jones.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | import numpy as np 19 | import scipy.spatial.distance as dist 20 | 21 | import pyparticles.forces.force as fr 22 | 23 | 24 | class LenardJones( fr.Force ) : 25 | r""" 26 | Compute the lenard jones force between the particles 27 | 28 | The L. J. force between two particles is defined as follow: 29 | 30 | .. math:: 31 | 32 | \mathbf{F}(r) = 4 \epsilon \left(12\,{\frac{{\sigma}^{12}}{{r}^{13}}}-6\,{\frac{{\sigma}^{6}}{{r}^{7}}}\right)\hat{\mathbf{r}} 33 | 34 | Constructor: 35 | 36 | :param size: the number of particles in the system 37 | :param dim: the dimension of the system 38 | :param m: a vector containig the masses 39 | :param Const: An indexable object[*] with the two contants 40 | 41 | 42 | [*] Const[0] = :math:`\epsilon` 43 | Const[1] = :math:`\sigma` 44 | 45 | """ 46 | 47 | 48 | import scipy.spatial.distance as dist 49 | 50 | def __init__( self , size , dim=3 , m=None , Consts=( 1.0 , 1.0 ) ): 51 | self.__dim = dim 52 | self.__size = size 53 | self.__E = Consts[0] 54 | self.__O = Consts[1] 55 | 56 | self.__M = np.zeros( ( size , 1 ) ) 57 | 58 | self.__pF = np.zeros(np.int32((size**2-size)/2)) 59 | 60 | self.__V = np.zeros( ( size , size ) ) 61 | 62 | self.__A = np.zeros( ( size , dim ) ) 63 | 64 | if m is not None : 65 | self.set_masses( m ) 66 | 67 | 68 | def set_masses( self , m ): 69 | """ 70 | Set the masses used for computing the forces. 71 | """ 72 | self.__M[:] = m 73 | 74 | 75 | def update_force( self , p_set ): 76 | """ 77 | Compute the force of the current status of the system and return the accelerations of every particle in a *size by dim* array 78 | 79 | :param p_set: Particles set obj. 80 | """ 81 | 82 | r = dist.pdist( p_set.X , 'euclidean' ) 83 | 84 | self.__pF[:] = 4.0 * self.__E * ( 12.0 * self.__O**12.0 / r**13.0 - 6.0 * self.__O**6.0 / r**7.0 ) / ( r ) 85 | 86 | F = dist.squareform( self.__pF[:] ) 87 | 88 | for i in range( p_set.dim ) : 89 | self.__V[:,:] = p_set.X[:,i] 90 | self.__V[:,:] = ( self.__V[:,:].T - p_set.X[:,i] ).T 91 | 92 | self.__A[:,i] = np.sum( F * self.__V[:,:] / self.__M.T , 0 ) 93 | 94 | 95 | return self.__A 96 | 97 | def getA(self): 98 | """ 99 | Return the currents accelerations of the particles 100 | """ 101 | return self.__A 102 | 103 | A = property( getA , doc="Return the currents accelerations of the particles (getter only)") 104 | 105 | 106 | def getF(self): 107 | """ 108 | Return the currents forces on the particles 109 | """ 110 | return self.__A * self.__M[:,0] 111 | 112 | F = property( getF , doc="Return the currents forces on the particles (getter only)") -------------------------------------------------------------------------------- /pyparticles/forces/linear_spring.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | import sys 19 | import scipy.spatial.distance as dist 20 | 21 | import pyparticles.forces.force as fr 22 | 23 | class LinearSpring( fr.Force ) : 24 | r""" 25 | Compute the forces according to the Hooke's law. 26 | 27 | .. math:: 28 | 29 | F_i = -k X 30 | 31 | :param size: size of the particles system 32 | :param dim: dimension of the system 33 | :param m: an array containing the masses 34 | :param const: spring constant ( K ) 35 | """ 36 | def __init__(self , size , dim=3 , m=None , Consts=1.0 ): 37 | 38 | self.__dim = dim 39 | self.__size = size 40 | 41 | self.__K = Consts 42 | 43 | self.__A = np.zeros( ( size , dim ) ) 44 | self.__F = np.zeros( ( size , dim ) ) 45 | self.__Fm = np.zeros( ( size , size ) ) 46 | 47 | self.__M = np.zeros( ( size , 1 ) ) 48 | if m != None : 49 | self.set_masses( m ) 50 | 51 | 52 | def set_masses( self , m ): 53 | """ 54 | set the masses of the particles 55 | """ 56 | self.__M[:] = m 57 | 58 | 59 | def update_force( self , p_set ): 60 | 61 | for i in range( self.__dim ): 62 | self.__Fm[:,:] = p_set.X[:,i] 63 | self.__Fm[:,:] = -self.__K * ( self.__Fm[:,:].T - p_set.X[:,i] ).T 64 | 65 | self.__F[:,i] = np.sum( self.__Fm , 0 ) 66 | 67 | self.__A[:,:] = self.__F[:,:] / self.__M[:] 68 | 69 | return self.__A 70 | 71 | def getA(self): 72 | return self.__A 73 | 74 | A = property( getA ) 75 | 76 | 77 | def getF(self): 78 | return self.__F 79 | 80 | F = property( getF ) 81 | 82 | 83 | def get_const( self ): 84 | return self.__K 85 | 86 | const = property( get_const ) 87 | -------------------------------------------------------------------------------- /pyparticles/forces/linear_spring_constrained.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import pyparticles.forces.force_constrained as fcr 18 | import numpy as np 19 | 20 | import scipy.sparse.dok as dok 21 | import scipy.sparse.csr as csr 22 | 23 | class LinearSpringConstrained ( fcr.ForceConstrained ): 24 | def __init__( self , size , dim , m=np.array([]) , Consts=1.0 , f_inter=None ): 25 | super( LinearSpringConstrained , self ).__init__( size , dim , m , Consts , f_inter=f_inter ) 26 | 27 | self.__dim = dim 28 | self.__size = size 29 | 30 | self.__K = Consts 31 | 32 | self.__A = np.zeros( ( size , dim ) ) 33 | self.__F = np.zeros( ( size , dim ) ) 34 | 35 | self.__Fm = dok.dok_matrix( ( size , size ) ) 36 | self.__Fm2 = csr.csr_matrix( ( size , size ) ) 37 | 38 | self.__M = np.zeros( ( size , 1 ) ) 39 | if len(m) != 0 : 40 | self.set_masses( m ) 41 | 42 | def set_masses( self , m ): 43 | """ 44 | set the masses of the particles 45 | """ 46 | self.__M[:] = m 47 | 48 | 49 | def update_force( self , pset ): 50 | 51 | dk = self.force_interactions.sparse.keys() 52 | 53 | for i in range( self.__dim ): 54 | #self.__Fm = dok.dok_matrix( ( pset.size , pset.size ) ) 55 | 56 | for k in dk : 57 | self.__Fm[k[0],k[1]] = pset.X[k[1],i] 58 | self.__Fm[k[1],k[0]] = pset.X[k[0],i] 59 | 60 | self.__Fm2 = -self.__K * ( self.__Fm.T - self.__Fm ).T 61 | 62 | self.__F[:,i] = self.__Fm2.sum( 0 ) 63 | 64 | self.__A[:,:] = self.__F[:,:] / self.__M[:] 65 | 66 | return self.__A 67 | 68 | 69 | def getA(self): 70 | return self.__A 71 | 72 | A = property( getA ) 73 | 74 | 75 | def getF(self): 76 | return self.__F 77 | 78 | F = property( getF ) 79 | 80 | 81 | def get_const( self ): 82 | return self.__K 83 | 84 | const = property( get_const ) 85 | -------------------------------------------------------------------------------- /pyparticles/forces/multiple_force.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | 18 | import numpy as np 19 | import sys 20 | 21 | class MultipleForce(object): 22 | """ 23 | Combine the effect of some forces, for example constant force and springs. 24 | It behaves like any other force, and can be used with all methods of numerical integration. 25 | """ 26 | def __init__(self , size , dim=3 , m=None , Conts=None ): 27 | 28 | self.__forces = [] 29 | 30 | self.__M = np.zeros(( size , 1 )) 31 | self.__A = np.zeros(( size , dim )) 32 | self.__F = np.zeros(( size , dim )) 33 | 34 | if m != None : 35 | self.set_masses( m ) 36 | 37 | 38 | def append_force( self , force ): 39 | """ 40 | Append a new force to the forces list 41 | """ 42 | self.__forces.append( force ) 43 | 44 | 45 | def set_masses( self , m ): 46 | """ 47 | Set the masses in the forces system 48 | """ 49 | self.__M[:] = m 50 | 51 | for f in self.__forces : 52 | f.set_masses( m ) 53 | 54 | 55 | def update_force( self , p_set ): 56 | self.A[:] = 0.0 57 | for f in self.__forces : 58 | self.A[:] = self.A[:] + f.update_force( p_set ) 59 | 60 | self.__F = self.__A[:] * self.__M[:] 61 | return self.__A 62 | 63 | def getA(self): 64 | return self.__A 65 | 66 | A = property( getA ) 67 | 68 | def getF(self): 69 | return self.__F 70 | 71 | F = property( getF ) 72 | 73 | -------------------------------------------------------------------------------- /pyparticles/forces/van_der_waals_force.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | import sys 19 | import scipy.spatial.distance as dist 20 | 21 | import pyparticles.forces.force as fr 22 | 23 | class VanDerWaals( fr.Force ) : 24 | def __init__(self , size , dim=3 , m=None , Consts=1.0 ): 25 | 26 | self.__dim = dim 27 | self.__size = size 28 | 29 | self.__C = Consts # Hamaker coefficient (A) 30 | 31 | self.__A = np.zeros( ( size , dim ) ) 32 | self.__F = np.zeros( ( size , dim ) ) 33 | self.__Fm = np.zeros( ( size , size ) ) 34 | 35 | self.__R = np.zeros( ( size , 1 ) ) 36 | if m != None : 37 | self.set_messes( m ) 38 | 39 | 40 | def set_masses( self , m ): 41 | self.__R[:] = m 42 | 43 | 44 | def update_force( self , p_set ): 45 | 46 | self.__D[:] = dist.squareform( dist.pdist( p_set.X , 'euclidean' ) ) 47 | 48 | return self.__A 49 | 50 | def getA(self): 51 | return self.__A 52 | 53 | A = property( getA ) 54 | 55 | 56 | def getF(self): 57 | return self.__F 58 | 59 | F = property( getF ) 60 | 61 | -------------------------------------------------------------------------------- /pyparticles/forces/vector_field_force.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | import sys 19 | import scipy.spatial.distance as dist 20 | 21 | import pyparticles.forces.force as fr 22 | 23 | class VectorFieldForce( fr.Force ) : 24 | def __init__(self , size , dim=3 , m=None ): 25 | self.__dim = dim 26 | self.__size = size 27 | self.__A = np.zeros( ( size , dim ) ) 28 | self.__M = np.zeros( ( size , size ) ) 29 | if m != None : 30 | self.set_messes( m ) 31 | 32 | 33 | def set_masses( self , m ): 34 | self.__M[:] = m 35 | 36 | def update_force( self , p_set ): 37 | self.__A[:] = self.vect_fun( p_set.X ) 38 | return self.__A 39 | 40 | def vect_fun( self , X ): 41 | NotImplementedError(" %s : is virtual and must be overridden." % sys._getframe().f_code.co_name ) 42 | 43 | def getA(self): 44 | return self.__A 45 | 46 | A = property( getA ) 47 | 48 | 49 | def getF(self): 50 | return self.__A * self.__M[:] 51 | 52 | F = property( getF ) 53 | -------------------------------------------------------------------------------- /pyparticles/geometry/__init__.py: -------------------------------------------------------------------------------- 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 . 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")] 22 | -------------------------------------------------------------------------------- /pyparticles/geometry/dist.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | 18 | import numpy as np 19 | 20 | def distance( x , y ): 21 | """ 22 | return the euclideian distance between *x* and *y* 23 | """ 24 | return np.sqrt( np.sum( (x-y)**2.0 ) ) 25 | -------------------------------------------------------------------------------- /pyparticles/geometry/intersection.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | from numpy import linalg as LA 19 | 20 | import pyparticles.geometry.dist as dist 21 | 22 | def box_intersects_sphere( b_min , b_max , c , r ): 23 | """ 24 | return True if the box defined by the opposite vertices *n_max*, *b max* intersect the sphere centred in *c* with a radius *r* 25 | """ 26 | 27 | r2 = r**2.0 28 | dmin = 0.0 29 | 30 | if c[0] < b_min[0] : 31 | dmin += ( c[0] - b_min[0] )**2.0 32 | elif c[0] > b_max[0]: 33 | dmin += ( c[0] - b_max[0] )**2.0 34 | 35 | if c[1] < b_min[1] : 36 | dmin += ( c[1] - b_min[1] )**2.0 37 | elif c[1] > b_max[1]: 38 | dmin += ( c[1] - b_max[1] )**2.0 39 | 40 | if c[2] < b_min[2] : 41 | dmin += ( c[2] - b_min[2] )**2.0 42 | elif c[2] > b_max[2]: 43 | dmin += ( c[2] - b_max[2] )**2.0 44 | 45 | return dmin <= r2 46 | 47 | 48 | def sphere_intersect_sphere( c1 , r1 , c2 , r2 ): 49 | """ 50 | returns the average intersection point if the two spheres centred in *c1* and *c2* and radius *r1*, *r2* are intersecting, else it returns *None* 51 | """ 52 | d = dist.distance( c1 , c2 ) 53 | 54 | if r1 + r2 >= d : 55 | 56 | u = ( c2 - c1 ) / LA.norm( c2 - c1 ) 57 | p = ( ( c1 + u*r1 ) + ( c2 - u*r2 ) ) / 2.0 58 | 59 | return p 60 | else : 61 | return None 62 | -------------------------------------------------------------------------------- /pyparticles/main/__init__.py: -------------------------------------------------------------------------------- 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 . 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")] 22 | -------------------------------------------------------------------------------- /pyparticles/measures/__init__.py: -------------------------------------------------------------------------------- 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 . 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")] 22 | -------------------------------------------------------------------------------- /pyparticles/measures/elastic_potential_energy.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | import scipy.spatial.distance as dist 19 | 20 | import pyparticles.measures.measure as me 21 | 22 | class ElasticPotentialEnergy( me.Measure ): 23 | """ 24 | Class derived from Measure usedfor computing the total elastic potential energy of the particle system 25 | """ 26 | def __init__( self , pset=None , force=None ): 27 | 28 | self.__pot = 0.0 29 | 30 | super( ElasticPotentialEnergy , self ).__init__( pset , force ) 31 | 32 | 33 | def value(self): 34 | """ 35 | return the current value of the potential energy 36 | """ 37 | return self.__pot 38 | 39 | 40 | def update_measure( self ): 41 | """ 42 | Compute and return the elestic potential energy on the current state of the pset 43 | """ 44 | 45 | D = dist.pdist( self.pset.X , 'euclidean' ) 46 | self.__pot = np.sum( 1.0/2.0 * D**2.0 * self.force.const ) 47 | 48 | return self.__pot 49 | 50 | 51 | def shape( self ): 52 | """ 53 | return a tuple containing the shape of the measures dataset 54 | """ 55 | return 1, 56 | 57 | def dim( self ): 58 | """ 59 | return the dimension of the measure: 1 for the potential energy 60 | """ 61 | return 1 62 | 63 | def name(self): 64 | """ 65 | Return the string: "potential energy" 66 | """ 67 | return "potential energy" -------------------------------------------------------------------------------- /pyparticles/measures/gravitational_potential_energy.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | import scipy.spatial.distance as dist 19 | 20 | import pyparticles.measures.measure as me 21 | 22 | class GravitationalPotentialEnergy( me.Measure ): 23 | """ 24 | Class derived from Measure usedfor computing the total gravitational potential energy of the particle system 25 | """ 26 | def __init__( self , pset=None , force=None ): 27 | 28 | self.__pot = 0.0 29 | 30 | super( GravitationalPotentialEnergy , self ).__init__( pset , force ) 31 | 32 | 33 | def value(self): 34 | """ 35 | return the current value of the potential energy 36 | """ 37 | return self.__pot 38 | 39 | 40 | def update_measure( self ): 41 | """ 42 | Compute and return the elestic potential energy on the current state of the pset 43 | """ 44 | 45 | D = dist.pdist( self.pset.X , 'euclidean' ) 46 | Mm = dist.pdist( self.pset.M , lambda v , u : v*u ) 47 | 48 | self.__pot = np.sum( - Mm/D * self.force.const ) 49 | 50 | return self.__pot 51 | 52 | 53 | def shape( self ): 54 | """ 55 | return a tuple containing the shape of the measures dataset 56 | """ 57 | return 1, 58 | 59 | def dim( self ): 60 | """ 61 | return the dimension of the measure: 1 for the potential energy 62 | """ 63 | return 1 64 | 65 | def name(self): 66 | """ 67 | Return the string: "potential energy" 68 | """ 69 | return "potential energy" -------------------------------------------------------------------------------- /pyparticles/measures/kinetic_energy.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | import scipy.spatial.distance as dist 19 | 20 | import pyparticles.measures.measure as me 21 | 22 | class KineticEnergy( me.Measure ): 23 | """ 24 | Mesure for computing the total potential energy of the particle system 25 | """ 26 | def __init__( self , pset=None , force=None ): 27 | 28 | self.__ke = 0.0 29 | 30 | super( KineticEnergy , self ).__init__( pset , force ) 31 | 32 | 33 | def value(self): 34 | """ 35 | return the current value of the potential energy 36 | """ 37 | return self.__ke 38 | 39 | 40 | def update_measure( self ): 41 | """ 42 | Compute and return the elestic potential energy on the current state of the pset 43 | """ 44 | 45 | self.__Va = np.sum( self.pset.V**2.0 , 1 ) 46 | 47 | self.__ke = np.sum( 1.0/2.0 * self.__Va * self.pset.M.T ) 48 | 49 | return self.__ke 50 | 51 | 52 | def shape( self ): 53 | """ 54 | return a tuple containing the shape of the measures dataset 55 | """ 56 | return 1, 57 | 58 | def dim( self ): 59 | """ 60 | return the dimension of the measure: 1 for the potential energy 61 | """ 62 | return 1 63 | 64 | def name(self): 65 | """ 66 | Return the string: "potential energy" 67 | """ 68 | return "kinetic energy" -------------------------------------------------------------------------------- /pyparticles/measures/mass.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | 19 | class Mass( object ): 20 | """ 21 | 'Meaure' for computing the total mass of the particle system 22 | """ 23 | def __init__( self , pset=None, force=None ): 24 | super( Mass , self ).__init__( pset=pset , force=force ) 25 | self.__M = 0.0 26 | 27 | 28 | def update_measure( self ): 29 | """ 30 | Compute and return the totale mass of the system 31 | """ 32 | self.__M = np.sum( self.pset.M[:] ) 33 | return self.__M 34 | 35 | 36 | def value(self): 37 | """ 38 | Return the current measured total mass 39 | """ 40 | return self.__M 41 | 42 | 43 | def shape(self ): 44 | """ 45 | return a tuple containing the shape of the measures dataset 46 | """ 47 | return 1, 48 | 49 | def dim( self ): 50 | """ 51 | return the dimension of the measure: 1 for the mass 52 | """ 53 | return 1 54 | 55 | def name(self): 56 | """ 57 | Return the string: "mass" 58 | """ 59 | return "mass" -------------------------------------------------------------------------------- /pyparticles/measures/momentum.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | import scipy.spatial.distance as dist 19 | 20 | import pyparticles.measures.measure as me 21 | 22 | class MomentumSystem( me.Measure ): 23 | """ 24 | 'Measure' for computing the total momentum of the particle system 25 | """ 26 | def __init__( self , pset=None ): 27 | 28 | if pset != None : 29 | self.__P = np.zeros(( pset.dim )) 30 | else : 31 | self.__P = None 32 | 33 | super( MomentumSystem , self ).__init__( pset=pset , force=None ) 34 | 35 | 36 | def value(self): 37 | """ 38 | return the current value of the total momentum 39 | """ 40 | return self.__P 41 | 42 | 43 | def update_measure( self ): 44 | """ 45 | Compute and return the total momentum of the system 46 | """ 47 | 48 | self.__P = np.sum( self.pset.V * self.pset.M , 0 ) 49 | 50 | return self.__P 51 | 52 | 53 | def shape( self ): 54 | """ 55 | return a tuple containing the shape of the measures dataset 56 | """ 57 | return ( self.pset.dim ) 58 | 59 | def dim( self ): 60 | """ 61 | return the dimension of the measure: Dim for the momentum 62 | """ 63 | return self.pset.dim 64 | 65 | def name(self): 66 | """ 67 | Return the string: "momentum" 68 | """ 69 | return "momentum" 70 | 71 | 72 | 73 | class MomentumParticles( me.MeasureParticles ): 74 | """ 75 | 'Measure' for computing the momentum particle by particle or of a subsystem 76 | Example: :: 77 | 78 | P = MomentumParticles( pset , subset=np.array([1,4,5]) , model="part_by_part") 79 | P.update_measure() 80 | print( P.value ) 81 | > [[ 1.1 , 2.3 , 3.2 ], 82 | > [ 1.7 , 5.2 , 6.9 ], 83 | > [ 1.8 , 2.3 , 1.7 ] 84 | > ] 85 | 86 | Constructor: 87 | 88 | :param pset The particles set 89 | :param force The model of the used force 90 | :param subset a numpy 1D array containing the indicies of the measured particles 91 | :param model a strung describing the model for the measure: "part_by_part" or "subsystem" 92 | """ 93 | def __init__( self , pset=None , force=None , subset=None , model="part_by_part" ): 94 | 95 | if pset != None and model == "subsystem" : 96 | self.__P = np.zeros(( pset.dim )) 97 | elif pset != None and model == "part_by_part" and subset != None : 98 | self.__P = np.zeros(( len(subset) , pset.dim )) 99 | else : 100 | self.__P = None 101 | 102 | super( MomentumParticles , self ).__init__( pset , force , subset , model ) 103 | 104 | 105 | def value(self): 106 | """ 107 | return the current value of the momentum 108 | """ 109 | return self.__P 110 | 111 | 112 | def update_measure( self ): 113 | """ 114 | Compute and return the total momentum of the specified particles 115 | """ 116 | 117 | if self.model == "part_by_part" : 118 | self.__P = self.pset.V[self.subset] * self.pset.M[self.subset] 119 | else : 120 | self.__P = np.sum( self.pset.V[self.subset] * self.pset.M[self.subset] , 0 ) 121 | 122 | return self.__P 123 | 124 | 125 | def shape( self ): 126 | """ 127 | return a tuple containing the shape of the measures dataset 128 | """ 129 | if self.model == "part_by_part" : 130 | return ( len( self.subset ) , pset.dim ) 131 | else : 132 | return ( 1 , pset.dim ) 133 | 134 | def dim( self ): 135 | """ 136 | return the dimension of the measure: Dim: (2D or 3D) for the momentum 137 | """ 138 | return self.pset.dim 139 | 140 | def name(self): 141 | """ 142 | Return the string: "momentum" 143 | """ 144 | return "momentum" -------------------------------------------------------------------------------- /pyparticles/measures/total_energy.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | import scipy.spatial.distance as dist 19 | 20 | import pyparticles.measures.measure as me 21 | 22 | class TotalEnergy( me.Measure ): 23 | """ 24 | Class derived from Measure used for computing the total energy of the particle system 25 | given a potential and a kinetic energy it simply sum the two value 26 | """ 27 | def __init__( self , kinetic , potential ): 28 | 29 | self.__kinetic = kinetic 30 | self.__potential = potential 31 | 32 | self.__tot = 0.0 33 | 34 | super( TotalEnergy , self ).__init__( pset=None , force=None ) 35 | 36 | 37 | def value(self): 38 | """ 39 | return the current value of the potential energy 40 | """ 41 | self.__tot = self.__kinetic.value() + self.__potential.value() 42 | return self.__tot 43 | 44 | 45 | def update_measure( self ): 46 | """ 47 | Compute and return the total energy on the current state of pset 48 | """ 49 | return self.__tot 50 | 51 | 52 | def shape( self ): 53 | """ 54 | return a tuple containing the shape of the measures dataset 55 | """ 56 | return 1, 57 | 58 | def dim( self ): 59 | """ 60 | return the dimension of the measure: 1 for the energy 61 | """ 62 | return 1 63 | 64 | def name(self): 65 | """ 66 | Return the string: "total energy" 67 | """ 68 | return "total energy" -------------------------------------------------------------------------------- /pyparticles/ode/__init__.py: -------------------------------------------------------------------------------- 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 . 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")] 22 | -------------------------------------------------------------------------------- /pyparticles/ode/euler_solver.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | 18 | import numpy as np 19 | import pyparticles.ode.ode_solver as os 20 | import pyparticles.pset.opencl_context as occ 21 | 22 | try: 23 | import pyopencl as cl 24 | except: 25 | ___foo = 0 26 | 27 | 28 | class EulerSolver( os.OdeSolver ) : 29 | def __init__( self , force , p_set , dt ): 30 | super(EulerSolver,self).__init__( force , p_set , dt ) 31 | 32 | 33 | def __step__( self , dt ): 34 | 35 | self.force.update_force( self.pset ) 36 | 37 | self.pset.V[:] = self.pset.V + self.force.A * dt 38 | self.pset.X[:] = self.pset.X + self.pset.V * dt 39 | 40 | self.pset.update_boundary() 41 | 42 | 43 | class EulerSolverConstrained( os.OdeSolverConstrained ) : 44 | def __init__( self , force , p_set , dt , x_constraint=None , v_constraint=None ): 45 | super(EulerSolverConstrained,self).__init__( force , p_set , dt , x_constraint=None , v_constraint=None ) 46 | 47 | if x_constraint != None : 48 | self.x_constraint = x_constraint 49 | 50 | 51 | def get_x_constraint(self): 52 | return super(EulerSolverConstrained,self).get_x_constraint() 53 | 54 | def set_x_constraint(self , xc ): 55 | super(EulerSolverConstrained,self).set_x_constraint( xc ) 56 | self.__free_inx = self.x_constraint.get_cx_free_indicies() 57 | self.__csrt_inx = self.x_constraint.get_cx_indicies() 58 | 59 | x_constraint = property( get_x_constraint , set_x_constraint , doc="get and set the current positionals constraints" ) 60 | 61 | 62 | def __step__( self , dt ): 63 | 64 | self.force.update_force( self.pset ) 65 | 66 | self.pset.V[self.__free_inx,:] = self.pset.V[self.__free_inx,:] + self.force.A[self.__free_inx,:] * dt 67 | self.pset.X[self.__free_inx,:] = self.pset.X[self.__free_inx,:] + self.pset.V[self.__free_inx,:] * dt 68 | 69 | self.pset.V[self.__csrt_inx,:] = 0.0 70 | 71 | self.pset.update_boundary() 72 | 73 | 74 | class EulerSolverOCL( os.OdeSolver ) : 75 | def __init__( self , force , p_set , dt , ocl_context=None ): 76 | super(EulerSolverOCL,self).__init__( force , p_set , dt ) 77 | 78 | if ocl_context == None : 79 | self.__occ = occ.OpenCLcontext( self.pset.size , self.pset.dim , ( occ.OCLC_X | occ.OCLC_V | occ.OCLC_A ) ) 80 | else : 81 | self.__occ = ocl_context 82 | 83 | self.__init_prog_cl() 84 | 85 | 86 | def __init_prog_cl(self): 87 | self.__euler_prg = """ 88 | __kernel void euler( __global float *V , 89 | __global const float *A , 90 | __global float *X , 91 | float dt ) 92 | { 93 | int i = get_global_id(0) ; 94 | 95 | V[3*i] = V[3*i] + A[3*i]*dt ; 96 | V[3*i+1] = V[3*i+1] + A[3*i+1]*dt ; 97 | V[3*i+2] = V[3*i+2] + A[3*i+2]*dt ; 98 | 99 | X[3*i] = X[3*i] + V[3*i]*dt ; 100 | X[3*i+1] = X[3*i+1] + V[3*i+1]*dt ; 101 | X[3*i+2] = X[3*i+2] + V[3*i+2]*dt ; 102 | } 103 | """ 104 | 105 | self.__cl_program = cl.Program( self.__occ.CL_context , self.__euler_prg ).build() 106 | 107 | 108 | def __step__( self , dt ): 109 | 110 | self.force.update_force( self.pset ) 111 | 112 | dtype = self.__occ.dtype 113 | 114 | self.__occ.V_cla.set( dtype( self.pset.V ) , queue=self.__occ.CL_queue ) 115 | self.__occ.A_cla.set( dtype( self.force.A ) , queue=self.__occ.CL_queue ) 116 | self.__occ.X_cla.set( dtype( self.pset.X ) , queue=self.__occ.CL_queue ) 117 | 118 | self.__cl_program.euler( self.__occ.CL_queue , ( self.pset.size , ) , None , 119 | self.__occ.V_cla.data , 120 | self.__occ.A_cla.data , 121 | self.__occ.X_cla.data , 122 | np.float32( dt ) ) 123 | 124 | self.__occ.X_cla.get( self.__occ.CL_queue , self.pset.X ) 125 | self.__occ.V_cla.get( self.__occ.CL_queue , self.pset.V ) 126 | 127 | self.pset.update_boundary() 128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /pyparticles/ode/euler_solver_constrained.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | 18 | #import numpy as np 19 | #import pyparticles.ode.ode_solver_constrained as osc 20 | #import pyparticles.ode.ode_solver as ods 21 | 22 | #class EulerSolverConstrained( ods.OdeSolverConstrained ) : 23 | # def __init__( self , force , p_set , dt , x_constraint=None , v_constraint=None ): 24 | # super(EulerSolverConstrained,self).__init__( force , p_set , dt , x_constraint=None , v_constraint=None ) 25 | # 26 | # if x_constraint != None : 27 | # self.x_constraint = x_constraint 28 | # 29 | # 30 | # def get_x_constraint(self): 31 | # return super(EulerSolverConstrained,self).get_x_constraint() 32 | # 33 | # def set_x_constraint(self , xc ): 34 | # super(EulerSolverConstrained,self).set_x_constraint( xc ) 35 | # self.__free_inx = self.x_constraint.get_cx_free_indicies() 36 | # self.__csrt_inx = self.x_constraint.get_cx_indicies() 37 | # 38 | # x_constraint = property( get_x_constraint , set_x_constraint , doc="get and set the current positionals constraints" ) 39 | # 40 | # 41 | # def __step__( self , dt ): 42 | # 43 | # self.force.update_force( self.pset ) 44 | # 45 | # self.pset.V[self.__free_inx,:] = self.pset.V[self.__free_inx,:] + self.force.A[self.__free_inx,:] * dt 46 | # self.pset.X[self.__free_inx,:] = self.pset.X[self.__free_inx,:] + self.pset.V[self.__free_inx,:] * dt 47 | # 48 | # self.pset.V[self.__csrt_inx,:] = 0.0 49 | # 50 | # self.pset.update_boundary() -------------------------------------------------------------------------------- /pyparticles/ode/leapfrog_solver.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | 18 | import numpy as np 19 | import pyparticles.ode.ode_solver as os 20 | 21 | class LeapfrogSolver( os.OdeSolver ) : 22 | def __init__( self , force , p_set , dt ): 23 | super(LeapfrogSolver,self).__init__( force , p_set , dt ) 24 | self.__Ai = np.zeros( self.force.A.shape ) 25 | 26 | def __step__( self , dt ): 27 | 28 | self.pset.X[:] = self.pset.X + self.pset.V * dt + 0.5*self.force.A * dt**2.0 29 | self.__Ai[:] = self.force.A 30 | 31 | self.force.update_force( self.pset ) 32 | 33 | self.pset.V[:] = self.pset.V + 0.5 * ( self.__Ai + self.force.A ) * dt 34 | 35 | 36 | self.pset.update_boundary() 37 | 38 | 39 | class LeapfrogSolverConstrained( os.OdeSolverConstrained ) : 40 | def __init__( self , force , p_set , dt , x_constraint=None , v_constraint=None ): 41 | super(LeapfrogSolverConstrained,self).__init__( force , p_set , dt , x_constraint=None , v_constraint=None ) 42 | self.__Ai = np.zeros( self.force.A.shape ) 43 | 44 | if x_constraint != None : 45 | self.x_constraint = x_constraint 46 | 47 | def get_x_constraint(self): 48 | return super(LeapfrogSolverConstrained,self).get_x_constraint() 49 | 50 | def set_x_constraint(self , xc ): 51 | super(LeapfrogSolverConstrained,self).set_x_constraint( xc ) 52 | self.__free_inx = self.x_constraint.get_cx_free_indicies() 53 | self.__csrt_inx = self.x_constraint.get_cx_indicies() 54 | 55 | x_constraint = property( get_x_constraint , set_x_constraint , doc="get and set the current positionals constraints" ) 56 | 57 | 58 | def __step__( self , dt ): 59 | 60 | self.pset.X[self.__free_inx,:] = self.pset.X[self.__free_inx,:] + self.pset.V[self.__free_inx,:] * dt + 0.5*self.force.A[self.__free_inx,:] * dt**2.0 61 | self.__Ai[self.__free_inx,:] = self.force.A[self.__free_inx,:] 62 | 63 | self.force.update_force( self.pset ) 64 | 65 | self.pset.V[self.__free_inx,:] = self.pset.V[self.__free_inx,:] + 0.5 * ( self.__Ai[self.__free_inx,:] + self.force.A[self.__free_inx,:] ) * dt 66 | 67 | self.pset.V[self.__csrt_inx,:] = 0.0 68 | 69 | #print( self.pset.V ) 70 | 71 | self.pset.update_boundary() 72 | 73 | -------------------------------------------------------------------------------- /pyparticles/ode/leapfrog_solver_constrained.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | 18 | #import numpy as np 19 | ##import pyparticles.ode.ode_solver_constrained as osc 20 | #import pyparticles.ode.ode_solver as ods 21 | 22 | #class LeapfrogSolverConstrained( ods.OdeSolverConstrained ) : 23 | # def __init__( self , force , p_set , dt , x_constraint=None , v_constraint=None ): 24 | # super(LeapfrogSolverConstrained,self).__init__( force , p_set , dt , x_constraint=None , v_constraint=None ) 25 | # self.__Ai = np.zeros( self.force.A.shape ) 26 | # 27 | # if x_constraint != None : 28 | # self.x_constraint = x_constraint 29 | # 30 | # def get_x_constraint(self): 31 | # return super(LeapfrogSolverConstrained,self).get_x_constraint() 32 | # 33 | # def set_x_constraint(self , xc ): 34 | # super(LeapfrogSolverConstrained,self).set_x_constraint( xc ) 35 | # self.__free_inx = self.x_constraint.get_cx_free_indicies() 36 | # self.__csrt_inx = self.x_constraint.get_cx_indicies() 37 | # 38 | # x_constraint = property( get_x_constraint , set_x_constraint , doc="get and set the current positionals constraints" ) 39 | # 40 | # 41 | # def __step__( self , dt ): 42 | # 43 | # self.pset.X[self.__free_inx,:] = self.pset.X[self.__free_inx,:] + self.pset.V[self.__free_inx,:] * dt + 0.5*self.force.A[self.__free_inx,:] * dt**2.0 44 | # self.__Ai[self.__free_inx,:] = self.force.A[self.__free_inx,:] 45 | # 46 | # self.force.update_force( self.pset ) 47 | # 48 | # self.pset.V[self.__free_inx,:] = self.pset.V[self.__free_inx,:] + 0.5 * ( self.__Ai[self.__free_inx,:] + self.force.A[self.__free_inx,:] ) * dt 49 | # 50 | # self.pset.V[self.__csrt_inx,:] = 0.0 51 | # 52 | # #print( self.pset.V ) 53 | # 54 | # self.pset.update_boundary() -------------------------------------------------------------------------------- /pyparticles/ode/midpoint_solver.py: -------------------------------------------------------------------------------- 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 . 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 MidpointSolver( os.OdeSolver ) : 23 | def __init__( self , force , p_set , dt ): 24 | 25 | super(MidpointSolver,self).__init__( force , p_set , dt ) 26 | 27 | self.__mid_pset = ps.ParticlesSet( p_set.size , p_set.dim ) 28 | 29 | 30 | def __step__( self , dt ): 31 | 32 | self.__mid_pset.X[:] = self.pset.X[:] + dt/2.0 * self.pset.V 33 | 34 | self.force.update_force( self.__mid_pset ) 35 | 36 | self.__mid_pset.V[:] = self.pset.V[:] + dt/2.0 * self.force.A 37 | 38 | self.pset.V[:] = self.pset.V[:] + dt * self.force.A 39 | self.pset.X[:] = self.pset.X[:] + dt * self.__mid_pset.V[:] 40 | 41 | self.pset.update_boundary() 42 | self.force.update_force( self.pset ) 43 | 44 | 45 | class MidpointSolverConstrained( os.OdeSolverConstrained ) : 46 | 47 | def __init__( self , force , p_set , dt , x_constraint=None , v_constraint=None ): 48 | super(MidpointSolverConstrained,self).__init__( force , p_set , dt , x_constraint=None , v_constraint=None ) 49 | 50 | self.__mid_pset = ps.ParticlesSet( p_set.size , p_set.dim ) 51 | 52 | if x_constraint != None : 53 | self.x_constraint = x_constraint 54 | 55 | 56 | def get_x_constraint(self): 57 | return super(MidpointSolverConstrained,self).get_x_constraint() 58 | 59 | def set_x_constraint(self , xc ): 60 | super(MidpointSolverConstrained,self).set_x_constraint( xc ) 61 | self.__free_inx = self.x_constraint.get_cx_free_indicies() 62 | self.__csrt_inx = self.x_constraint.get_cx_indicies() 63 | 64 | x_constraint = property( get_x_constraint , set_x_constraint , doc="get and set the current positionals constraints" ) 65 | 66 | 67 | 68 | def __step__( self , dt ): 69 | 70 | 71 | self.__mid_pset.X[self.__free_inx,:] = self.pset.X[self.__free_inx,:] + dt/2.0 * self.pset.V[self.__free_inx,:] 72 | self.__mid_pset.X[self.__csrt_inx,:] = self.pset.X[self.__csrt_inx,:] 73 | 74 | self.force.update_force( self.__mid_pset ) 75 | 76 | self.__mid_pset.V[self.__free_inx,:] = self.pset.V[self.__free_inx,:] + dt/2.0 * self.force.A[self.__free_inx,:] 77 | 78 | self.pset.V[self.__free_inx,:] = self.pset.V[self.__free_inx,:] + dt * self.force.A[self.__free_inx,:] 79 | self.pset.X[self.__free_inx,:] = self.pset.X[self.__free_inx,:] + dt * self.__mid_pset.V[self.__free_inx,:] 80 | 81 | self.pset.update_boundary() 82 | self.force.update_force( self.pset ) 83 | 84 | -------------------------------------------------------------------------------- /pyparticles/ode/midpoint_solver_constrained.py: -------------------------------------------------------------------------------- 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 . 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 | #import pyparticles.ode.ode_solver as ods 23 | # 24 | #class MidpointSolverConstrained( ods.OdeSolverConstrained ) : 25 | # 26 | # def __init__( self , force , p_set , dt , x_constraint=None , v_constraint=None ): 27 | # super(MidpointSolverConstrained,self).__init__( force , p_set , dt , x_constraint=None , v_constraint=None ) 28 | # 29 | # self.__mid_pset = ps.ParticlesSet( p_set.size , p_set.dim ) 30 | # 31 | # if x_constraint != None : 32 | # self.x_constraint = x_constraint 33 | # 34 | # 35 | # def get_x_constraint(self): 36 | # return super(MidpointSolverConstrained,self).get_x_constraint() 37 | # 38 | # def set_x_constraint(self , xc ): 39 | # super(MidpointSolverConstrained,self).set_x_constraint( xc ) 40 | # self.__free_inx = self.x_constraint.get_cx_free_indicies() 41 | # self.__csrt_inx = self.x_constraint.get_cx_indicies() 42 | # 43 | # x_constraint = property( get_x_constraint , set_x_constraint , doc="get and set the current positionals constraints" ) 44 | # 45 | # 46 | # 47 | # def __step__( self , dt ): 48 | # 49 | # 50 | # self.__mid_pset.X[self.__free_inx,:] = self.pset.X[self.__free_inx,:] + dt/2.0 * self.pset.V[self.__free_inx,:] 51 | # self.__mid_pset.X[self.__csrt_inx,:] = self.pset.X[self.__csrt_inx,:] 52 | # 53 | # self.force.update_force( self.__mid_pset ) 54 | # 55 | # self.__mid_pset.V[self.__free_inx,:] = self.pset.V[self.__free_inx,:] + dt/2.0 * self.force.A[self.__free_inx,:] 56 | # 57 | # self.pset.V[self.__free_inx,:] = self.pset.V[self.__free_inx,:] + dt * self.force.A[self.__free_inx,:] 58 | # self.pset.X[self.__free_inx,:] = self.pset.X[self.__free_inx,:] + dt * self.__mid_pset.V[self.__free_inx,:] 59 | # 60 | # self.pset.update_boundary() 61 | # self.force.update_force( self.pset ) 62 | -------------------------------------------------------------------------------- /pyparticles/ode/ode_solver_constrained.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | 18 | #import numpy as np 19 | #import pyparticles.ode.ode_solver 20 | 21 | #class OdeSolverConstrained( os.OdeSolver ) : 22 | # def __init__(self , force , p_set , dt , x_constraint=None , v_constraint=None ): 23 | # 24 | # self.__x_constr = x_constraint 25 | # self.__v_constr = v_constraint 26 | # 27 | # super(OdeSolverConstrained,self).__init__( force , p_set , dt ) 28 | # 29 | # 30 | # def get_x_constraint(self): 31 | # """ 32 | # returns a reference to the current positionals constraints 33 | # """ 34 | # return self.__x_constr 35 | # 36 | # def set_x_constraint(self , xc ): 37 | # """ 38 | # set the new positionals contraints 39 | # """ 40 | # self.__x_constr = xc 41 | # self.__x_constr.pset = self.pset 42 | # 43 | # x_constraint = property( get_x_constraint , set_x_constraint , doc="get and set the current positionals constraints" ) 44 | # 45 | # -------------------------------------------------------------------------------- /pyparticles/ode/runge_kutta_solver_constrained.py: -------------------------------------------------------------------------------- 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 . 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 | #import pyparticles.ode.ode_solver as ods 23 | 24 | #class RungeKuttaSolverConstrained( ods.OdeSolverConstrained ) : 25 | # def __init__( self , force , p_set , dt , x_constraint=None , v_constraint=None ): 26 | # super(RungeKuttaSolverConstrained,self).__init__( force , p_set , dt , x_constraint=None , v_constraint=None ) 27 | # 28 | # if x_constraint != None : 29 | # self.x_constraint = x_constraint 30 | # 31 | # self.__Kv1 = np.zeros( self.force.A.shape ) 32 | # self.__Kv2 = np.zeros( self.force.A.shape ) 33 | # self.__Kv3 = np.zeros( self.force.A.shape ) 34 | # self.__Kv4 = np.zeros( self.force.A.shape ) 35 | # 36 | # self.__Kx1 = np.zeros( self.force.A.shape ) 37 | # self.__Kx2 = np.zeros( self.force.A.shape ) 38 | # self.__Kx3 = np.zeros( self.force.A.shape ) 39 | # self.__Kx4 = np.zeros( self.force.A.shape ) 40 | # 41 | # self.__tmp_pset = ps.ParticlesSet( p_set.size , p_set.dim ) 42 | # 43 | # 44 | # def get_x_constraint(self): 45 | # return super(RungeKuttaSolverConstrained,self).get_x_constraint() 46 | # 47 | # def set_x_constraint(self , xc ): 48 | # super(RungeKuttaSolverConstrained,self).set_x_constraint( xc ) 49 | # self.__fi = self.x_constraint.get_cx_free_indicies() 50 | # self.__ci = self.x_constraint.get_cx_indicies() 51 | # 52 | # x_constraint = property( get_x_constraint , set_x_constraint , doc="get and set the current positionals constraints" ) 53 | # 54 | # 55 | # def __step__( self , dt ): 56 | # 57 | # self.__tmp_pset.V[:] = self.pset.V[:] 58 | # 59 | # # K1 60 | # self.__Kv1[self.__fi,:] = self.force.A[self.__fi,:] 61 | # self.__Kx1[self.__fi,:] = self.pset.V[self.__fi,:] 62 | # 63 | # # K2 64 | # self.__tmp_pset.X[self.__fi,:] = self.pset.X[self.__fi,:] + dt/2.0*self.__Kx1[self.__fi,:] 65 | # self.__tmp_pset.X[self.__ci,:] = self.pset.X[self.__ci,:] 66 | # self.force.update_force( self.__tmp_pset ) 67 | # 68 | # self.__Kv2[self.__fi,:] = self.force.A[self.__fi,:] 69 | # self.__Kx2[self.__fi,:] = self.pset.V[self.__fi,:] + dt/2.0*self.__Kv1[self.__fi,:] 70 | # 71 | # #K3 72 | # self.__tmp_pset.X[self.__fi,:] = self.pset.X[self.__fi,:] + dt/2.0*self.__Kx2[self.__fi,:] 73 | # self.__tmp_pset.X[self.__ci,:] = self.pset.X[self.__ci,:] 74 | # self.force.update_force( self.__tmp_pset ) 75 | # 76 | # self.__Kv3[self.__fi,:] = self.force.A[self.__fi,:] 77 | # self.__Kx3[self.__fi,:] = self.pset.V[self.__fi,:] + dt/2.0*self.__Kv2[self.__fi,:] 78 | # 79 | # #K4 80 | # self.__tmp_pset.X[self.__fi,:] = self.pset.X[self.__fi,:] + dt*self.__Kx3[self.__fi,:] 81 | # self.__tmp_pset.X[self.__ci,:] = self.pset.X[self.__ci,:] 82 | # self.force.update_force( self.__tmp_pset ) 83 | # 84 | # self.__Kv4[self.__fi,:] = self.force.A[self.__fi,:] 85 | # self.__Kx4[self.__fi,:] = self.pset.V[self.__fi,:] + dt*self.__Kv3[self.__fi,:] 86 | # 87 | # 88 | # 89 | # self.pset.V[self.__fi,:] = self.pset.V[self.__fi,:] + dt/6.0 * ( self.__Kv1[self.__fi,:] + 2.0*self.__Kv2[self.__fi,:] + 2.0*self.__Kv3[self.__fi,:] + self.__Kv4[self.__fi,:] ) 90 | # self.pset.X[self.__fi,:] = self.pset.X[self.__fi,:] + dt/6.0 * ( self.__Kx1[self.__fi,:] + 2.0*self.__Kx2[self.__fi,:] + 2.0*self.__Kx3[self.__fi,:] + self.__Kx4[self.__fi,:] ) 91 | # 92 | # self.pset.V[self.__ci,:] = 0.0 93 | # 94 | # self.pset.update_boundary() 95 | # self.force.update_force( self.pset ) 96 | # 97 | 98 | -------------------------------------------------------------------------------- /pyparticles/ode/sim_time.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | 18 | class SimTime( object ): 19 | """ 20 | Class used for storing the current simulation time: 21 | 22 | Constructor 23 | 24 | :param controller: a reference to the object that control the simulation time 25 | 26 | """ 27 | def __init__( self , controller ): 28 | self.__time = 0.0 29 | self.__controller = controller 30 | 31 | def get_time( self ): 32 | """ 33 | get the current time 34 | """ 35 | return self.__time 36 | 37 | def set_time( self , t ): 38 | """ 39 | set the current time 40 | """ 41 | self.__time = t 42 | 43 | time = property( get_time , set_time , doc="get and set the current simulation time" ) 44 | 45 | 46 | def get_controller( self ): 47 | r""" 48 | Get a reference to the simulation time controller, normally an ODE solver 49 | 50 | :returns the reference to the ODE solver object 51 | """ 52 | return self.__controller 53 | 54 | controller = property( get_controller , doc="get the reference to the time controller" ) 55 | 56 | -------------------------------------------------------------------------------- /pyparticles/ode/stormer_verlet_solver.py: -------------------------------------------------------------------------------- 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 . 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() 51 | 52 | 53 | class StormerVerletSolverConstrained( os.OdeSolverConstrained ) : 54 | def __init__( self , force , p_set , dt , x_constraint=None , v_constraint=None ): 55 | super(StormerVerletSolverConstrained,self).__init__( force , p_set , dt , x_constraint=None , v_constraint=None ) 56 | 57 | self.__pset_m1 = ps.ParticlesSet( p_set.size , p_set.dim , mass=False , velocity=False ) 58 | self.__pset_tmp = ps.ParticlesSet( p_set.size , p_set.dim , mass=False , velocity=False ) 59 | 60 | if x_constraint != None : 61 | self.x_constraint = x_constraint 62 | 63 | def get_x_constraint(self): 64 | return super(StormerVerletSolverConstrained,self).get_x_constraint() 65 | 66 | def set_x_constraint(self , xc ): 67 | super(StormerVerletSolverConstrained,self).set_x_constraint( xc ) 68 | 69 | self.__free_inx = self.x_constraint.get_cx_free_indicies() 70 | self.__csrt_inx = self.x_constraint.get_cx_indicies() 71 | 72 | x_constraint = property( get_x_constraint , set_x_constraint , doc="get and set the current positionals constraints" ) 73 | 74 | 75 | def __step__( self , dt ): 76 | 77 | self.force.update_force( self.pset ) 78 | 79 | if self.steps_cnt == 1 : 80 | 81 | # for the firse step we use the Euler method 82 | self.__pset_m1.X[:] = self.pset.X[:] 83 | 84 | self.pset.V[self.__free_inx,:] = self.pset.V[self.__free_inx,:] + self.force.A[self.__free_inx,:] * dt 85 | self.pset.X[self.__free_inx,:] = self.pset.X[self.__free_inx,:] + self.pset.V[self.__free_inx,:] * dt 86 | 87 | self.pset.V[self.__csrt_inx,:] = 0.0 88 | 89 | else : 90 | 91 | self.__pset_tmp.X[:] = self.pset.X[:] 92 | 93 | 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 94 | self.pset.V[self.__free_inx,:] = ( self.__pset_tmp.X[self.__free_inx,:] - self.__pset_m1.X[self.__free_inx,:] ) / dt 95 | 96 | self.__pset_m1.X[:] = self.__pset_tmp.X[:] 97 | 98 | self.pset.V[self.__csrt_inx,:] = 0.0 99 | 100 | self.pset.update_boundary() 101 | -------------------------------------------------------------------------------- /pyparticles/ode/stormer_verlet_solver_constrained.py: -------------------------------------------------------------------------------- 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 . 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 | #import pyparticles.ode.ode_solver as ods 22 | # 23 | # 24 | #class StormerVerletSolverConstrained( ods.OdeSolverConstrained ) : 25 | # def __init__( self , force , p_set , dt , x_constraint=None , v_constraint=None ): 26 | # super(StormerVerletSolverConstrained,self).__init__( force , p_set , dt , x_constraint=None , v_constraint=None ) 27 | # 28 | # self.__pset_m1 = ps.ParticlesSet( p_set.size , p_set.dim , mass=False , velocity=False ) 29 | # self.__pset_tmp = ps.ParticlesSet( p_set.size , p_set.dim , mass=False , velocity=False ) 30 | # 31 | # if x_constraint != None : 32 | # self.x_constraint = x_constraint 33 | # 34 | # def get_x_constraint(self): 35 | # return super(StormerVerletSolverConstrained,self).get_x_constraint() 36 | # 37 | # def set_x_constraint(self , xc ): 38 | # super(StormerVerletSolverConstrained,self).set_x_constraint( xc ) 39 | # 40 | # self.__free_inx = self.x_constraint.get_cx_free_indicies() 41 | # self.__csrt_inx = self.x_constraint.get_cx_indicies() 42 | # 43 | # x_constraint = property( get_x_constraint , set_x_constraint , doc="get and set the current positionals constraints" ) 44 | # 45 | # 46 | # def __step__( self , dt ): 47 | # 48 | # self.force.update_force( self.pset ) 49 | # 50 | # if self.steps_cnt == 1 : 51 | # 52 | # # for the firse step we use the Euler method 53 | # self.__pset_m1.X[:] = self.pset.X[:] 54 | # 55 | # self.pset.V[self.__free_inx,:] = self.pset.V[self.__free_inx,:] + self.force.A[self.__free_inx,:] * dt 56 | # self.pset.X[self.__free_inx,:] = self.pset.X[self.__free_inx,:] + self.pset.V[self.__free_inx,:] * dt 57 | # 58 | # self.pset.V[self.__csrt_inx,:] = 0.0 59 | # 60 | # else : 61 | # 62 | # self.__pset_tmp.X[:] = self.pset.X[:] 63 | # 64 | # 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 65 | # self.pset.V[self.__free_inx,:] = ( self.__pset_tmp.X[self.__free_inx,:] - self.__pset_m1.X[self.__free_inx,:] ) / dt 66 | # 67 | # self.__pset_m1.X[:] = self.__pset_tmp.X[:] 68 | # 69 | # self.pset.V[self.__csrt_inx,:] = 0.0 70 | # 71 | # self.pset.update_boundary() 72 | 73 | 74 | -------------------------------------------------------------------------------- /pyparticles/ogl/__init__.py: -------------------------------------------------------------------------------- 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 . 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")] 22 | -------------------------------------------------------------------------------- /pyparticles/ogl/trackball.py: -------------------------------------------------------------------------------- 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 . 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 ) ) 132 | -------------------------------------------------------------------------------- /pyparticles/ogl/translate_scene.py: -------------------------------------------------------------------------------- 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 . 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 | -------------------------------------------------------------------------------- /pyparticles/pset/__init__.py: -------------------------------------------------------------------------------- 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 . 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")] 22 | -------------------------------------------------------------------------------- /pyparticles/pset/boundary.py: -------------------------------------------------------------------------------- 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 . 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 | 70 | -------------------------------------------------------------------------------- /pyparticles/pset/cluster.py: -------------------------------------------------------------------------------- 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 . 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 | 29 | -------------------------------------------------------------------------------- /pyparticles/pset/constrained_force_interactions.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | 18 | import numpy as np 19 | from collections import deque 20 | 21 | import scipy.sparse.dok as dok 22 | 23 | import pyparticles.pset.particles_set as ps 24 | import pyparticles.pset.constraint as ct 25 | 26 | 27 | 28 | class ConstrainedForceInteractions ( ct.Constraint ): 29 | def __init__ ( self , pset=None ): 30 | 31 | self.__S = dok.dok_matrix( (1,1) , dtype=np.byte ) 32 | 33 | if pset != None : 34 | self.pset = pset 35 | 36 | 37 | 38 | def get_pset(self): 39 | return super(ConstrainedForceInteractions,self).get_pset() 40 | 41 | def set_pset( self , pset ): 42 | self.__S.resize( ( pset.size , pset.size ) ) 43 | super(ConstrainedForceInteractions,self).set_pset( pset ) 44 | 45 | pset = property( get_pset , set_pset ) 46 | 47 | 48 | def add_connections( self , fc ): 49 | """ 50 | Adds the connections listed in *fc* . 51 | fc must be a list of list or a 2d array of pairs 52 | for example:: 53 | 54 | cfi = ConstrainedForceInteractions( pset ) 55 | a = [[1,1],[3,5]] 56 | cfi.add_connections( a ) 57 | """ 58 | for c in fc: 59 | print("c[0] = ", c[0], "c[1] = ", c[1], "self.__S = ", self.__S) 60 | self.__S[ np.int32(c[0]) , np.int32(c[1])] = True 61 | 62 | def remove_connections( self , fc ): 63 | """ 64 | Removes the connections listed in *fc* . 65 | fc must be a list of list or a 2d array of pairs 66 | for example:: 67 | 68 | cfi = ConstrainedForceInteractions( pset ) 69 | a = [[1,1],[3,5]] 70 | cfi.remove_connections( a ) 71 | """ 72 | for c in fc : 73 | self.__S[ c[0] , c[1] ] = False 74 | 75 | 76 | def get_dense(self): 77 | """ 78 | Return the dense reppresentations of the connections matrix. 79 | Don't use this function in a loop, don't use this function in a loop, but execute the conversion to a dense matix before the loop. 80 | """ 81 | return np.bool8( self.__S.todense() ) 82 | 83 | dense = property( get_dense ) 84 | 85 | 86 | def get_sparse(self): 87 | """ 88 | Return the reference to the dok_matrix sparse matrix of the connections. 89 | For the operations with a dense matricies, don't use this function in a loop, but execute the conversion to a dense matix before the loop. 90 | """ 91 | return self.__S 92 | 93 | sparse = property( get_sparse ) 94 | 95 | 96 | def get_items(self): 97 | """ 98 | list of the commection ((i,j), value) pairs, ...) 99 | """ 100 | return self.__S.items() 101 | 102 | items = property( get_items ) 103 | -------------------------------------------------------------------------------- /pyparticles/pset/constraint.py: -------------------------------------------------------------------------------- 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 . 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 | -------------------------------------------------------------------------------- /pyparticles/pset/default_boundary.py: -------------------------------------------------------------------------------- 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 . 17 | 18 | import numpy as np 19 | import pyparticles.pset.boundary as bd 20 | 21 | 22 | class DefaultBoundary( bd.Boundary ): 23 | r""" 24 | If a particle exits form the boundary it's moved to a default position according to the function 'defualt_pos' 25 | 26 | 27 | :param bound: A tuple that describe the boundary - (min , max) or (x_min,x_man,y_min,y_max,z_min,z_max) 28 | :param dim: dimension of the system 29 | :param defualt_pos: default position function 30 | 31 | | Where: 32 | | defualt_pos( pset , indx ) update the X and/or V of the particles set pset 33 | | pset: particles set 34 | | indx: indices of the involved particles 35 | """ 36 | def __init__( self , bound=(-1,1) , dim=3 , defualt_pos=None ): 37 | self.set_boundary( bound , dim ) 38 | self.__defualt_pos = defualt_pos 39 | 40 | 41 | def boundary( self , p_set ): 42 | for i in range( self.dim ) : 43 | 44 | b_mi, = np.where( p_set.X[:,i] < self.bound[i,0] ) 45 | b_mx, = np.where( p_set.X[:,i] > self.bound[i,1] ) 46 | 47 | if len( b_mi ) > 0 : 48 | self.__defualt_pos( p_set , b_mi ) 49 | 50 | if len( b_mx ) > 0 : 51 | self.__defualt_pos( p_set , b_mx ) -------------------------------------------------------------------------------- /pyparticles/pset/file_cluster.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | import numpy as np 18 | import csv 19 | import re 20 | 21 | 22 | class FileCluster(object): 23 | """ 24 | Read the data from a csv formatted file: 25 | 26 | The first row of the csv contains the size and the dim of the particles set. 27 | 28 | The other rows are the data of the perticles in the order: 29 | """ 30 | 31 | def __init__(self): 32 | pass 33 | 34 | def open( self , cfile , mode="r" ): 35 | """ 36 | Open the csv file named cfile. 37 | 38 | :param cfile: The file name 39 | :param mode: file mode (default reading) 40 | """ 41 | 42 | self.__cfile = cfile 43 | 44 | 45 | def close(self): 46 | """ 47 | Close the file 48 | """ 49 | pass 50 | #self.__f.close() 51 | 52 | 53 | def insert3( self , pset ): 54 | """ 55 | Insert the particles described in the file in the ParticlesSet pset 56 | 57 | :param pset: A reference to the particles set 58 | """ 59 | ff = open( self.__cfile , 'rb') 60 | csv_w = csv.reader( ff , delimiter=' ') 61 | 62 | i = -1 63 | 64 | dim = 0 65 | size = 0 66 | print( self.__cfile ) 67 | #print( csv_w ) 68 | 69 | label = False 70 | 71 | for row in csv_w : 72 | #print( row ) 73 | if i == -1 : 74 | size = int(row[0]) 75 | dim = int(row[1]) 76 | try: 77 | il = row.index( "label" ) 78 | label = True 79 | except: 80 | label = False 81 | 82 | pset.realloc( size , dim , label=il) 83 | 84 | else : 85 | for j in range( dim ) : 86 | pset.X[i,j] = float(row[j]) 87 | pset.V[i,j] = float(row[j+dim]) 88 | 89 | pset.M[i] = float( row[dim*2] ) 90 | 91 | if label : 92 | pset.label[i] = row[dim*2+1] 93 | 94 | i+=1 95 | 96 | #print( pset.label ) 97 | ff.close() 98 | #exit() 99 | 100 | 101 | 102 | def write_out( self , pset ): 103 | """ 104 | Write out in the csv file the particles described in pset. 105 | 106 | :param pset: A reference to the particles set 107 | """ 108 | ff = open( self.__cfile , 'wb') 109 | csv_w = csv.writer( ff , delimiter=' ') 110 | 111 | head = [ str(pset.size) , str(pset.dim) ] 112 | 113 | try: 114 | foo = pset.Q 115 | head.append("Charge") 116 | except: 117 | pass 118 | 119 | if pset.label != None : 120 | head.append( "Label" ) 121 | 122 | csv_w.writerow( head ) 123 | 124 | for i in range( pset.size ): 125 | lst = pset.get_list( i , to=float ) 126 | csv_w.writerow( lst ) 127 | 128 | ff.close() 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /pyparticles/pset/periodic_boundary.py: -------------------------------------------------------------------------------- 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 . 17 | 18 | import numpy as np 19 | import pyparticles.pset.boundary as bd 20 | 21 | 22 | class PeriodicBoundary( bd.Boundary ): 23 | 24 | def __init__( self , bound=(-1,1) , dim=3 ): 25 | self.set_boundary( bound , dim ) 26 | 27 | 28 | def boundary( self , p_set ): 29 | for i in range( self.dim ) : 30 | delta = self.bound[i,1] - self.bound[i,0] 31 | 32 | b_mi = p_set.X[:,i] < self.bound[i,0] 33 | b_mx = p_set.X[:,i] > self.bound[i,1] 34 | 35 | p_set.X[b_mi,i] = p_set.X[b_mi,i] + delta 36 | p_set.X[b_mx,i] = p_set.X[b_mx,i] - delta -------------------------------------------------------------------------------- /pyparticles/pset/rebound_boundary.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | 18 | import numpy as np 19 | import pyparticles.pset.boundary as bd 20 | 21 | class ReboundBoundary( bd.Boundary ): 22 | 23 | def __init__( self , bound=(-1,1) , dim=3 ): 24 | self.set_boundary( bound , dim ) 25 | self.set_normals() 26 | 27 | 28 | def set_normals( self ): 29 | self.__N = np.zeros( ( 2*self.dim , self.dim ) ) 30 | 31 | #print( self.__N ) 32 | 33 | if self.dim >= 2 : 34 | self.__N[0,:2] = np.array( [1,0] ) 35 | self.__N[1,:2] = np.array( [-1,0] ) 36 | 37 | self.__N[2,:2] = np.array( [0,1] ) 38 | self.__N[3,:2] = np.array( [0,-1] ) 39 | 40 | if self.dim == 3 : 41 | self.__N[4,:] = np.array( [0,0,1] ) 42 | self.__N[5,:] = np.array( [0,0,-1] ) 43 | 44 | def boundary( self , p_set ): 45 | 46 | v_mi = np.zeros((3)) 47 | v_mx = np.zeros((3)) 48 | 49 | for i in range( self.dim ) : 50 | j = 2*i 51 | 52 | v_mi[:] = 0.0 53 | v_mx[:] = 0.0 54 | 55 | #delta = self.bound[i,1] - self.bound[i,0] 56 | 57 | b_mi = p_set.X[:,i] < self.bound[i,0] 58 | b_mx = p_set.X[:,i] > self.bound[i,1] 59 | 60 | v_mi[i] = self.bound[i,0] 61 | v_mx[i] = self.bound[i,1] 62 | 63 | p_set.X[b_mi,:] = p_set.X[b_mi,:] + 2.0 * self.__N[j,:] * ( v_mi - p_set.X[b_mi,:] ) 64 | p_set.X[b_mx,:] = p_set.X[b_mx,:] + 2.0 * self.__N[j,:] * ( v_mx - p_set.X[b_mx,:] ) 65 | 66 | p_set.V[b_mi,i] = -p_set.V[b_mi,i] 67 | p_set.V[b_mx,i] = -p_set.V[b_mx,i] 68 | 69 | 70 | -------------------------------------------------------------------------------- /pyparticles/utils/__init__.py: -------------------------------------------------------------------------------- 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 . 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")] -------------------------------------------------------------------------------- /pyparticles/utils/parse_args.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | 18 | import argparse 19 | 20 | def parse_args(): 21 | desc = "PyParticles is a particle simulation tool box that support the most diffused numerical integration " 22 | desc = desc + " and forces models " 23 | 24 | parser = argparse.ArgumentParser( description=desc ) 25 | 26 | parser.add_argument("-m", "--config_model", 27 | action="store_true", 28 | dest="config_model", 29 | help="Write out the model of a config file and exit") 30 | 31 | parser.add_argument( "-d" , "--demo", 32 | action="store", 33 | choices=[ "springs" , 34 | "solar_system" , 35 | "gas_lj" , 36 | "bubble" , 37 | "cat_spri" , 38 | "el_static" , 39 | "elmag_field" , 40 | "fountain" , 41 | "galaxy"] , 42 | dest="demo", 43 | default=None , 44 | help="Execute the specified builtin demo" 45 | ) 46 | 47 | parser.add_argument( "-t" , "--test", 48 | action="store", 49 | choices=[ "fall" , "harmonic" , "dharmonic" ] , 50 | dest="test", 51 | default=None , 52 | help="Execute the specified builtin test") 53 | 54 | parser.add_argument( 55 | dest="path_name", 56 | nargs='?', 57 | default=None 58 | ) 59 | 60 | parser.add_argument( "-v" , "--version", 61 | action="store_true", 62 | dest="version", 63 | help="print the current version and exit" 64 | ) 65 | 66 | parser.add_argument( "-a" , "--about", 67 | action="store_true", 68 | dest="about", 69 | help="print the about message and exit" 70 | ) 71 | 72 | return parser.parse_args() 73 | -------------------------------------------------------------------------------- /pyparticles/utils/pypart_global.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | 18 | 19 | import zlib 20 | 21 | ########################### 22 | # Current version 23 | v_major = 0 24 | v_minor = 4 25 | v_revision = 0 26 | ########################### 27 | 28 | def py_particle_version( r='s' ): 29 | global v_major 30 | global v_minor 31 | global v_revision 32 | 33 | if r == 's' : 34 | return "%d.%d.%d" % ( v_major , v_minor , v_revision ) 35 | else : 36 | return ( v_major , v_minor , v_revision ) 37 | 38 | 39 | def test_pyopencl(): 40 | try : 41 | import pyopencl 42 | except : 43 | return False 44 | else : 45 | return True 46 | 47 | def about(): 48 | 49 | mail = zlib.decompress(b'x\x9c+\xce\xcc\xcd\xcfK\xd5+*KtH\xcfM\xcc\xcc\xd1K\xce\xcf\x05\x00R\x9c\x07\xba').decode('utf-8') 50 | 51 | message = """ 52 | 53 | PyParticles is a particle simulation toolbox entirely written in python. 54 | 55 | The main objective of PyParticles is to provide a system API simple and fast to use. 56 | Furthermore is to provide a basic application for the implementation of simple models. 57 | 58 | Visit: http://pyparticles.wordpress.com/ 59 | Docs: http://simon-r.github.com/PyParticles/index.html 60 | 61 | Copyright (C) %s %s email: %s 62 | 63 | -------------------------------------------------------------------- 64 | 65 | This program is free software: you can redistribute it and/or modify 66 | it under the terms of the GNU General Public License as published by 67 | the Free Software Foundation, either version 3 of the License, or 68 | (at your option) any later version. 69 | 70 | This program is distributed in the hope that it will be useful, 71 | but WITHOUT ANY WARRANTY; without even the implied warranty of 72 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 73 | GNU General Public License for more details. 74 | 75 | You should have received a copy of the GNU General Public License 76 | along with this program. If not, see 77 | """ 78 | 79 | message = message % ( '2012' , 'Simone Riva' , mail ) 80 | 81 | print( message ) 82 | 83 | 84 | -------------------------------------------------------------------------------- /pyparticles/utils/time_formatter.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | 18 | import time 19 | 20 | class MyTimeFormatter( object ): 21 | 22 | def __init__(self): 23 | pass 24 | 25 | 26 | def to_str( self , t ): 27 | 28 | tf = [ "%4dy " , "%3dd " , "%02dh " , "%02dm " , "%02ds " , "%07.3fms " ] 29 | 30 | days_y = 365.256363004 31 | sec_y = days_y * 3600 * 24 32 | 33 | years = int( t / sec_y ) 34 | days = int( t / (3600*24) - years*days_y ) 35 | hr = int( t / 3600 - days*24 - days_y*years*24 ) 36 | minu = int( t / 60 - hr*60 - days*(24*60) - days_y*years*24*60 ) 37 | sec = int( t - minu*60 - hr*3600 - days*(24*3600) - days_y*years*24*60*60 ) 38 | msec = float( 1000 * ( t - int( t ) ) ) 39 | 40 | res = "" 41 | 42 | i = 0 43 | f = False 44 | for tt in list( [ years , days , hr , minu , sec , msec ] ): 45 | if tt > 0 or f : 46 | res = res + tf[i] % tt 47 | f = True 48 | i+=1 49 | 50 | return res 51 | -------------------------------------------------------------------------------- /pyparticles_app: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # PyParticles : Particles simulation in python 4 | #Copyright (C) 2012 Simone Riva 5 | # 6 | #This program is free software: you can redistribute it and/or modify 7 | #it under the terms of the GNU General Public License as published by 8 | #the Free Software Foundation, either version 3 of the License, or 9 | #(at your option) any later version. 10 | # 11 | #This program is distributed in the hope that it will be useful, 12 | #but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | #GNU General Public License for more details. 15 | # 16 | #You should have received a copy of the GNU General Public License 17 | #along with this program. If not, see . 18 | 19 | import sys 20 | import pyparticles.main.main as main 21 | 22 | sys.path.append( "pyparticles" ) 23 | 24 | 25 | main.main() 26 | 27 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 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 . 16 | 17 | 18 | 19 | import os 20 | import shutil 21 | import subprocess 22 | import sys 23 | import re 24 | import sys 25 | 26 | is_winows = sys.platform.startswith('linux') 27 | 28 | from distutils.core import setup 29 | from pyparticles.utils.pypart_global import py_particle_version 30 | from distutils.command.install import install 31 | 32 | 33 | class particles_install(install): 34 | user_options = install.user_options 35 | 36 | def run(self): 37 | 38 | install.run(self) 39 | 40 | # man ... Linux only 41 | if sys.platform.startswith('linux'): 42 | 43 | man_dir = os.path.abspath("./man/") 44 | 45 | prefix = re.sub( r'^/' , '' , self.prefix ) 46 | 47 | output = subprocess.Popen([os.path.join(man_dir, "install.sh")], 48 | stdout=subprocess.PIPE, 49 | cwd=man_dir, 50 | env=dict({"PREFIX": os.path.join( self.root , prefix ) }, **dict(os.environ))).communicate()[0] 51 | 52 | print( output ) 53 | 54 | 55 | 56 | 57 | setup(name = "pyparticles", 58 | version = "%s" % py_particle_version() , 59 | description = "Particles simulation toolbox for python, with some force model and integrations methods", 60 | author = "Simone Riva", 61 | author_email = "simone.rva [at] gmail.com", 62 | url = "https://github.com/simon-r/PyParticles", 63 | packages = ['pyparticles' , 64 | 'pyparticles.utils' , 65 | 'pyparticles.ode' , 66 | 'pyparticles.forces' , 67 | 'pyparticles.animation' , 68 | 'pyparticles.demo' , 69 | 'pyparticles.pset' , 70 | 'pyparticles.measures' , 71 | 'pyparticles.main' , 72 | 'pyparticles.geometry' , 73 | 'pyparticles.ogl' ], 74 | scripts = ["pyparticles_app"], 75 | long_description = "Particles simulation toolbox in python, with some force model and integrations methods. Particles includes an OpenGL GUI and an easy to use problem comfiguration" , 76 | classifiers=[ 77 | 'Development Status :: %s Stable' % py_particle_version() , 78 | 'Topic :: Scientific/Engineering :: Physics' , 79 | 'Topic :: Scientific/Engineering :: Mathematics' , 80 | 'Environment :: Console' , 81 | 'Environment :: X11 Applications' , 82 | 'Environment :: Win32 (MS Windows)' , 83 | 'Intended Audience :: Users', 84 | 'License :: OSI Approved :: GPL-3.0+' , 85 | 'Operating System :: Linux' , 86 | 'Programming Language :: Python' ] , 87 | cmdclass={"install": particles_install } 88 | ) 89 | --------------------------------------------------------------------------------