0

I have a function:

def euler(a, b, R, r, time, h):        # Euler Method
    a0 = a
    b0 = b
    R0 = R
    r0 = r
    for i in range(3):
        a[0][i] = a[0][i] + h * fai_1(a0, b0, R0, r0, i)
        a[1][i] = a[1][i] + h * fai_2(a0, b0, R0, r0, i)
        a[2][i] = a[2][i] + h * fai_3(a0, b0, R0, r0, i)
        b[0][i] = b[0][i] + h * fbi_1(a0, b0, R0, r0, i)
        b[1][i] = b[1][i] + h * fbi_2(a0, b0, R0, r0, i)
        b[2][i] = b[2][i] + h * fbi_3(a0, b0, R0, r0, i)
        r[i] = r[i] + h * fr(a0, b0, R0, r0, i)
    for i in range(3):
        R[0][i] = R[0][i] + h * fR(a0, b0, R0, r0)[0][i]
        R[1][i] = R[1][i] + h * fR(a0, b0, R0, r0)[1][i]
        R[2][i] = R[2][i] + h * fR(a0, b0, R0, r0)[2][i]
    time = time + h
    return [a, b, R, r, time]

where the h is a constant prescribed value, a, b, r, and R are 3x3 matrices (2D arrays), and the functions fai_1, fai_2,... also prescribed.

I would like to run the above function for 100 steps, where the elements are appended to an empty array at each step. The trouble I am having is that this function updates the values at each step and overwrite the elements in my array so I end with 100 identical elements.

For example, I am starting with

a = [[0.0, 0.0, 0.0], [1.0, -1.0, 0.0], [-0.5, 1.0, 1.0]]  
b = [[0.0, 0.0, 0.0], [1.0, 1.0, 0.5], [-1.0, 0.5, 1.0]]
R = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]   
r = [-1.0, 1.0, 0.0]        
time = 0.0

and tried executing (to extract the first array in b)

barr = []
for i in range(3):
    u = euler(a, b, R, r, time, h)
    barr.append( u[1][0] )

print( barr )

This prints:

[0.27195, 0.3172665, 0.175097505], [0.27195, 0.3172665, 0.175097505],
[0.27195, 0.3172665, 0.175097505]

And I would like to get:

[0.1, 0.1, 0.05], [0.19, 0.205, 0.11], [0.27195, 0.3172665, 0.175097505]

I believe I know what is happening here. The function is updating the value u[1][0] each time it is called, which in turn rewrites the value in barr. However, I have no idea how to fix this issue. I have tried many different way to write this, but it always ends in the same issue.

What's most frustrating to me, is that I have written code extremely similar to this before:

def euler(theta, x, y, h):
    theta0 = theta
    x0 = x
    y0 = y
    for i in range(5):
        theta[i] = theta[i] + h * ftheta[i](theta0,x0,y0)
        x[i] = x[i] + h * fx[i](theta0,x0,y0)
        y[i] = y[i] + h * fy[i](theta0,x0,y0)
    return [theta, x, y]

with

x = [-1.39, 6.05, 1.0 , 0, 0]                        
y = [-3.33, -1.82, -2.0, 2.0, 0]
theta = [-3.98, 0.0, 1.0, np.pi / 4, 0]

Then, executing

xarr = [] 

for i in range(p):            
    u1 = euler(theta, x, y, h)
    xarr.append( u1[1][3] )
    yarr1.append( u1[2][3] )
    thetaarr1.append( u1[0][3] )

print(xarr)

This works as I would like it to, and doesn't update all of the values in xarr at each iteration. The only difference I can see here is the introduction of 2D arrays, as opposed to 1D.

Can anyone help me see what's happening here?

Unfortunately, the code I am working on is too long to include in its entirety, but if anyone would like me to add a part that may be relevant, please let me know.

infinitylord
  • 175
  • 7
  • The reason is that you don't make copies of your list - remember `theta0 = theta` doesn't make a copy and passing a list to a function also doesn't make a copy!. You always change the list in-place. – MSeifert Aug 29 '17 at 08:52
  • @MSeifert: That does not explain why the second example works but the first does not, however – infinitylord Aug 29 '17 at 09:33
  • You're right - but that's because you don't append a "shared list" (`u[1][0]` is a list in the first example) in the second case but append "immutable numbers" (`u1[1][3]` is a number in that case). – MSeifert Aug 29 '17 at 09:40
  • Please let me know if you want that I reopen the question. I still think it's basically the problem mentioned in the duplicate but if you need a more detailed explanation for your cases I'll reopen the question. – MSeifert Aug 29 '17 at 09:49
  • @MSeifert: No, I believe I understand now, thank you! Though I am still admittedly boggled by the reason Python does this, the question should remain closed. – infinitylord Aug 29 '17 at 10:12

0 Answers0