'Python: appending numpy.array to list python overwrites the previous elements
I'm trying to plot a stellar orbit in a given potential. First, I initialize the position and velocity, and derive the acceleration from the position according to the given potential.
I then advance the time with a defined timestep and calculate the orbit. The problem arises when I try to store the calculated positions in an empty list. Here is my code:
## Initial position, velocity, and acceleration
r = np.array([20., 20., 0.])
v = np.array([0., 1., 0.])
g = acc(*r) #calculates acceleration from a function
## empty list to store position data
posdata = []
## Orbit integration
dt = 0.1
for t in np.arange(0, 1000, dt):
v += 0.5 * g * dt
r += v * dt
if t%100 == 0:
print(r) #check if r actually changes
g = acc(*r)
v += 0.5 * g * dt
posdata.append(r)
This is what I'm expecting to get:
posdata
>>> [array([19.999875, 20.099875, 0.]), array([19.99950125, 20.19950001, 0.]), array([19.99887999, 20.29887502, 0.]), ...]
But I actually get this:
>>> [array([-17.57080611, -34.03696644, 0.]), array([-17.57080611, -34.03696644, 0.]), array([-17.57080611, -34.03696644, 0.])]
All the elements are identical to the last element calculated. As you can see, I checked if r
actually changes, and it does. I think it has to do with the fact that r
is an array, but I don't know how to correct this.
Solution 1:[1]
You are appending the same object each time you are creating a list of many references to the same object.
[r, r, r, r, r, r, r]
Since the object is mutable, when you update the object the change affects your entire list of references.
You need to create a copy of the object when you append it to your list.
Try this instead
posdata.append(r.copy())
Now you will have a different object in each list location.
[r1, r2, r3, r4, r5, r6, r7]
Solution 2:[2]
When you append array r to the list, only the reference of the array object is appended. And since numpy.array objects are mutable so all the references get updated in-place. For this, you can either
- append the array as list to posdata as list
posdata.append(r.tolist())
Or
append the array as a new numpy.array object to posdata
posdata.append(np.array(r))
Solution 3:[3]
I encountered the same problem. My solution is to change the +=
in the equation r += v * dt
to r = r + v * dt
, and then append it to the list.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | windstorm |
Solution 3 | Michelle Liew |