0

Something of a follow-up question to my last one about writing efficient python programs. I have been playing with writing my own physics simulations, and want to get away from using a billion classes and methods.

So I want to be able to perform calculations on sets of data. This is my latest attempt:

particles = np.array([ #position, last position, velocity, mass, size
                 [[200,0],[200,200],[5,5],10,15], \
                 [[210,210],[210,210],[8,2],20,25],\
                 [[215,215],[195,195],[5,3],5,15], \
                 [[192,186],[160,160],[10,-4],30,30]])

def moveParticles(part, dt):
    part[0] = part[1]
    part[1] += np.multiply(part[2],dt)

I am trying to store each of the properties of each particle in an array, and then update them in-place. Here I am trying to multiply the velocity vector by the time step, and then add that to the position vector. This seems like a natural way to express this to me, but it gives me the error:

TypeError: can't multiply sequence by non-int of type 'float'

Can I write data back into the same array, and how would I go about doing so?

I have been reading around, and looked at things like numpy's vectorize function, itertools, map(), etc... but how would I go about placing the results back into the original array?

Or is using an intermediate array to store the results before overwriting the original the only way to go?

Community
  • 1
  • 1
mooglinux
  • 815
  • 1
  • 11
  • 27
  • 1
    how is moveParticles being called? – Sinkingpoint Mar 18 '13 at 07:51
  • Please provide requested output. – root Mar 18 '13 at 07:52
  • 1
    Because you have lists of varying length in your data, what `np.array` returns is of dtype `object`, and `particles[:, 0]`, `particles[:, 1]` and `particles[:, 2]` are Python lists, not arrays. Hence the error, when you try to multiply the velocity list with the `dt` float. You should try too store homogeneous data in arrays. I like Balint's sanswer below! – Jaime Mar 18 '13 at 14:06

1 Answers1

2

I think, you just invoke your routine the wrong way (probably passing it the entire particle array instead of the array for only one particle.

Anyway, on other possible solution would be to split your array in individual arrays:

import numpy as np
pos = np.array([[200,0], [210,210], [215,215], [192,186]], dtype=float)
lastpos = np.array([[200,2000], [ 210,210], [195, 195], [160,160]], dtype=float)
velocity = np.array([[ 5,5], [8,2], [5,3], [10,-4]], dtype=float)
mass = np.array([ 10, 20, 5, 30 ], dtype=float)
size = np.array([ 15, 25, 15, 30 ], dtype=float)

def moveParticles(pos, lastpos, velocity, dt):
    lastpos[:] = pos[:]
    pos[:] += velocity * dt

This would make in-place replacement for pos and lastpos. In order to move your particles, you would have to invoke the function as:

moveParticles(pos, lastpos, velocity, 1)

where I set dt = 1. I also assumed, that you want to have floating point coordinates, if not, you should generate integer arrays instead.

Bálint Aradi
  • 3,754
  • 16
  • 22
  • That does look like a very good solution. It just means I will have to remove the same element from multiple arrays if I destroy a particle, rather than just removing a single element. Thanks! – mooglinux Mar 18 '13 at 14:56