Legend
Legend

Reputation: 116780

Simulating a simple physics related scenario

I am a total beginner in both simulations so this question might be silly. If so, please feel free to edit it. I am trying to simulate the following scenario in Python. I randomly place a few small particles in a 2D field with fixed dimentions. Each particle has a radius of effect r. If the first particle has the second one within its radius of effect, then a force has to be applied on both the particles (the effect that the first one has on the second and vice versa) and my force function is defined as:

f(i,j)_n = (r - |pi_n - pj_n|)((pj_n - pi_n)/|pi_n - pj_n|)

where n is the time step currently, pi_n represents the position of i at time step n and || represents magnitude calculation and (pj_n - pi_n) represents vector subtraction.

I was wondering if there are any libraries that simplify this stuff for me. All I need is basically the following:

time-step particle position(x,y)

Does anyone have some suggestions for me please?

Upvotes: 0

Views: 405

Answers (2)

Constantinius
Constantinius

Reputation: 35039

I really like the pymunk physics library, a wrapper for the chipmunk physics library.

First of all, the library needs to be initialized:

import pymunk
pymunk.init_pymunk()
space = pymunk.Space()
space.gravity = (0.0, -100.0)

To achieve something the likes you have requested you have to create a Body and a Circle shape for each particle you wish to create.

mass = 1
radius = 14
inertia = pymunk.moment_for_circle(mass, 0, radius, (0,0))
body = pymunk.Body(mass, inertia)
x, y = random.randint(0, 200), random.randint(0, 200)
body.position = x, 550
shape = pymunk.Circle(body, radius, (0,0))
shape.sensor = True
space.add(body, shape)

The particles will not collide with each other, beacause the sensor flag is set to True. The radius is now somewhat of an area of influence.

Now, we create a callback function for particles which have an overlapping area of influence:

def near_callback(space, arbiter, *args, **kwargs):
    body_i = arbiter.shapes[0].body
    body_j = arbiter.shapes[1].body

    # calculate the forces force_i and force_j with your formula
    ...

    body_i.apply_force(force_i)
    body_j.apply_force(force_j)

The callback is set in the space:

space.set_default_collision_handler(near_callback, near_callback, None, None, None)

Of course, the space has to be "stepped" for each time-frame:

space.step(dt)

I hope this was somewhat understandable and helpful.

Upvotes: 1

ninjagecko
ninjagecko

Reputation: 91094

Googling for python library vector 2d returned http://www.supereffective.org/pages/Vector-2d-Vector-Library as the top hit, which seems like a competent library (containing projection-and-perpendicularization, normalization, rotation, scaling, etc.)

As long as the number of particles isn't too large, this should work just fine in combination with an integration scheme. e.g. you keep track of each particle's (pos, vel) and perhaps also accel vectors, and use:

F = m a

-> F = m dv/dt

-> dv/dt = F/m

and thus

dv ~= dt*F/m

-> v' - v ~= dt*F/m

-> ball.vel += timeStep*sum(ball.force(n) for n in ball.neighbors())/ball.mass

This is Euler integration which has pretty bad properties, but is okay for a game.

Upvotes: 2

Related Questions