Physics::Particles - Simulate particle dynamics


Current version is 1.00. Version 1.00 and later are incompatible to versions below 1.00.


  use Physics::Particles;
  my $sim = Physics::Particles->new();
     sub {
        my $particle = shift;
        my $excerter = shift;
        my $params = shift;
        my $time_diff = $params->[0];
        # ...
        return($force_x, $force_y, $force_z);
     1   # 1 => symmetric force, 0 => asymmetric force
    x  => -0.001541580, y  => -0.005157481, z  => -0.002146907,
    vx => 0.000008555,  vy => 0.000000341,  vz => -0.000000084,
    m  => 333054.25,    n  => 'sun',
    x  => 0.352233521,  y  => -0.117718043, z  => -0.098961836,
    vx => 0.004046276,  vy => 0.024697922,  vz => 0.0127737,
    m  => 0.05525787,   n  => 'mercury',
  # [...]
  my $iterations = 1000;
  foreach (1..$iterations) {
  my $state = $sim->dump_state();
  # Now do something with it. You could, for example,
  # use GNUPlot or the Math::Project3D module to create
  # 3D graphs of the data.


Physics::Particles is a facility to simulate movements of a small number of particles under a small number of forces that every particle excerts on the others. Complexity increases with particles X particles X forces, so that is why the number of particles should be low.

In the context of this module, a particle is no more or less than a set of attributes like position, velocity, mass, and charge. The example code and test cases that come with the distribution simulate the inner solar system showing that when your scale is large enough, planets and stars may well be approximated as particles. (As a matter of fact, in the case of gravity, if the planet's shape was a sphere, the force of gravity outside the planet would always be its mass times the mass of the body it excerts the force on times the gravitational constant divided by the distance squared.)

Simulation of microscopic particles is a bit more difficult due to floating point arithmetics on extremely small values. You will need to choose your constant factors wisely.


As you might have gleamed from the synopsis, you will have to write subroutines that represent forces which the particles of the simulation excert on one another. You may specify (theoretically) any number of forces.

The force subroutines are passed three parameters. First is the particle that should be modified according to the effect of the force. Second is the particle that excerts the force, and the third argument will be an array reference of parameters passed to the iterate_step method at run time. The first element of this array should be the time slice for which you are to calculate the force vector.

As of version 1.00, forces may no longer modify the particles themselves. Instead, they are to return three values indication x,y,z components of the force vector. Furthermore, the acceleration is calculated from the force according to special relativity.

Physics::Particles can only simulate forces between any two particles. A particle cannot excert a force on itself. (The force subroutine isn't even called if the excerter particle and the particle-to-be-moved are identical.)

To alleviate this shortcoming, there are the Physics::Springs and Physics::Springs::Friction modules which subclass Physics::Particles to extend it towards forces between two specific particles (Physics::Springs) and force fields (Physics::Springs::Friction).



new() is the constructor for a fresh simulation. It does not require any arguments. All arguments directly modify the object as key/value pairs. Returns newly created simulator object.


This method takes key/value pairs of particle attributes. Attributes default to whatever has been set using set_particle_default. A new particle represented by the attributes is then created in the simulation and its particle number is returned. Attributes starting with an underscore are reserved to internal attributes (so don't use any of them).


This method removes a specific particle from the simulation. It takes the particle number as argument and returns 1 on success, 0 otherwise.


This method removes all particles from the simulation.


Takes a hash reference as argument which is then used for particle default attributes such as position, velocity, mass, unique ID, or whatever properties you fancy.

You should not change the defaults after adding particles. You knew that doesn't make sense, did you?


This method adds a new force to the simulation. It takes a subroutine reference (the force) as argument, appends it to the list of forces and returns the force it just appended. Second argument to add_force() is optional and defaults to false. It is a boolean indicating whether or not the force is symmetric. Symmetric means that the force particle1 excerts on particle2 is exactly zero minus the force particle2 excerts on particle1.


This method applies all forces (excerted by every particle) to all particles. That means this is of complexity no_particles * (no_particles-1) * forces. ( O(n**2 * m) or O(n**3) ) iterate_step() takes a list of additional parameters as argument that will be passed to every force subroutine. (The first argument should be the duration of the iteration so the forces know how to calculate the effects on the particles.


This method returns a Data::Dumper dump of the state of all particles.


Steffen Mueller, mail at steffen-mueller dot net


Copyright (c) 2002-2005 Steffen Mueller. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.


You may find the newest version of this module on CPAN or

For more elaborate simulations: Physics::Springs, Physics::Springs::Friction

For a reasonably convenient way of visualizing the produced data: Math::Project3D, Math::Project3D::Plot