1

I currently have a list of velocities in an n-body system at 10,000 points in time. It is a three-dimensional array concerning n particles at t points in time in three spatial dimensions. For example, with three particles at two points in time, it is set up as

[[[vx1][vy1][vz1]
  [vx2][vy2][vz2]
  [vx3][vy3][vz3]]
 [[vx1][vy1][vz1]
  [vx2][vy2][vz2]
  [vx3][vy3][vz3]]]

My end goal is to have an array like this:

[[[speed1]
  [speed2]
  [speed3]]
 [[speed1]
  [speed2]
  [speed3]]]

But I can't get the velocity components to add quadratically while the number of particles is free to vary. I could do it with two particles like this:

# Takes all velocities and converts them to speeds
all_speeds=[]
for i in range(len(all_velocities)):
    all_speeds.append([math.sqrt(all_velocities[i][0][0]**2\
        +all_velocities[i][0][1]**2+all_velocities[i][0][2]**2)],\
            [math.sqrt(all_velocities[i][1][0]**2+all_velocities[i][1][1]**2\
                +all_velocities[i][1][2]**2)])

But I am unsure of how to extend it to n particles. My very end goal is to square the velocity array and then multiply it by the array of masses that I have to calculate the system's kinetic energy but I can't extend it to work for any input. Thanks.

Peter Ohaver
  • 87
  • 1
  • 10
  • Are you familiar with the [`map`](https://docs.python.org/2/library/functions.html#map) built-in function? – cod3monk3y Dec 07 '14 at 05:58
  • Also, I'm a bit confused about the input and output data. Could you supply actual samples of data for the inputs and the outputs you're looking for? – cod3monk3y Dec 07 '14 at 06:03
  • It is a `numpy.ndarray` with a shape of (n, 3, t)? – wwii Dec 07 '14 at 06:04

5 Answers5

3
import numpy as np
v1 = [[[1,1,1],
       [2,2,2],
       [3,3,3],
       [4,4,4]],
      [[1,1,1],
       [2,2,2],
       [3,3,3],
       [4,4,4]]]

a = np.array(v1)

a.shape is (t, n, d). You want the square root of the sum of the squares of the three dimensional velocities:

>>> a
array([[[1, 1, 1],
        [2, 2, 2],
        [3, 3, 3],
        [4, 4, 4]],

       [[1, 1, 1],
        [2, 2, 2],
        [3, 3, 3],
        [4, 4, 4]]])
>>> #square each velocity
>>> b = np.square(a)
>>> b
array([[[ 1,  1,  1],
        [ 4,  4,  4],
        [ 9,  9,  9],
        [16, 16, 16]],

       [[ 1,  1,  1],
        [ 4,  4,  4],
        [ 9,  9,  9],
        [16, 16, 16]]])
>>> #sum along the dimensions
>>> b = b.sum(axis = 2)
>>> b
array([[ 3, 12, 27, 48],
       [ 3, 12, 27, 48]])
>>> # root of each sum
>>> b = np.sqrt(b)
>>> b
array([[ 1.73205081,  3.46410162,  5.19615242,  6.92820323],
       [ 1.73205081,  3.46410162,  5.19615242,  6.92820323]])
>>>

b.shape is (t,n). Looks like none of the particles are accelerating in my dataset.

Or simply:

>>> np.linalg.norm(a, axis = 2)
array([[ 1.73205081,  3.46410162,  5.19615242,  6.92820323],
       [ 1.73205081,  3.46410162,  5.19615242,  6.92820323]])
>>> 
wwii
  • 23,232
  • 7
  • 37
  • 77
  • Similar SO question: [How can the euclidean distance be calculated with numpy?](http://stackoverflow.com/q/1401712/2823755). [How do you get the magnitude of a vector in Numpy?](http://stackoverflow.com/q/9171158/2823755) – wwii Dec 07 '14 at 07:31
  • [```numpy.linalg.norm```](http://docs.scipy.org/doc/numpy/reference/generated/numpy.linalg.norm.html#numpy-linalg-norm) – wwii Dec 07 '14 at 07:34
  • Using the norm is the best solution here. All other answers only hide the real mathematical problem. – sebix Dec 07 '14 at 08:34
1

Add one more loop

# Takes all velocities and converts them to speeds
all_speeds=[]
# Looping over time
for i in range(len(all_velocities)):
    #adding and empty list to collect all the speeds
    all_speeds.append([])
    #looping over number of particles
    for j in range(len(all_velocities[i])):
        all_speeds[-1].append([math.sqrt(all_velocities[i][j][0]**2\
                                         +all_velocities[i][j][1]**2\
                                         +all_velocities[i][j][2]**2)])

Hope this helps.

1

You just need an additional loop over the number of particles within the main loop.

To make it easier to read I have also created a function to do the speed calculation in the following code snippet:

import math

all_velocities = [[[1,2,3], [2,3,4]], [[3,4,5], [4,5,6], [7,8,9]]]
all_speeds = []

def calculate_speed(v):
    return math.sqrt(v[0]**2 + v[1]**2 + v[2]**2)

for i in range(len(all_velocities)):
    all_speeds.append([])
    for j in range(len(all_velocities[i])):
        velocity = all_velocities[i][j]
        all_speeds[i].append(calculate_speed(velocity))

print all_speeds
Sonic
  • 186
  • 6
1

It's not very clear to me what your array is. I'm assuming that it looks like this:

system_time_vectors = [
    [
        [x, y, z], # velocity vector for particle 1 at t0 
        [x, y, z], # ... for p2 at t0
        [x, y, z]  # ... for p3 at t0
    ],
    [
        [x, y, z], # for p1 at t1
        [x, y, z], # for p2 at t1
        [x, y, z]  # for p3 at t1
    ]
]

If this is the case, then the following should do the trick. I'm defining a function to calculate the speed given a vector.

The function to_scalar is applied to each [x, y, z] vector array for each time using nested list comprehension.

import math
def to_scalar(*vector_comps):
    return math.sqrt(sum(v*v for v in vector_comps))

speeds = [[to_scalar(*el) for el in moment for moment] in system_time_vectors]
Haleemur Ali
  • 26,718
  • 5
  • 61
  • 85
0
[[math.sqrt(sum(map(lambda x: x**2, body))) for body in frame] for frame in series]

Where series has the following form:

[[[1, 1, 1], [2, 1, 1], [3, 1, 1]], [[2, 2, 2], [4, 2, 2], [6, 2, 2]]]
dta
  • 654
  • 4
  • 19