Reputation: 51
I am new to Python and appreciate any constructive feedback. My task is to solve a PDE using ODEINT where my spatial grid is defined as follows:
L = [8.0, 4.0, 8.0] # Lenght of spatial zones
dN = 1.0e2 # Number of grid points
N = [int(l*dN) for l in L] # Gives number of grid points over each spatial zone
By using the ODEINT function believe I must define an array of zeros for my solution, and an array of time points. I am struggling to find out how I write the correct size for the array's. I have tried:
dydt = np.zeros(shape=N) # For solution
t = np.linspace(0, 2, 2000) # for time
IndexError Traceback (most recent call last) in () 70 t = np.linspace(0, 2, lN) 71 ---> 72 U = odeint(numeric, y0, t, args=(h, D1, D2, N)) 73 74 Fexit = U/Np
/Users/severinlangeberg/anaconda/lib/python3.5/site-packages/scipy/integrate/odepack.py in odeint(func, y0, t, args, Dfun, col_deriv, full_output, ml, mu, rtol, atol, tcrit, h0, hmax, hmin, ixpr, mxstep, mxhnil, mxordn, mxords, printmessg) 213 output = _odepack.odeint(func, y0, t, args, Dfun, col_deriv, ml, mu, 214 full_output, rtol, atol, tcrit, h0, hmax, hmin, --> 215 ixpr, mxstep, mxhnil, mxordn, mxords) 216 if output[-1] < 0: 217 warning_msg = _msgs[output[-1]] + " Run with full_output = 1 to get quantitative information."
in numeric(y, t, h, D1, D2, N) 39 40 for i in [N[0] + 1]: # 800 = special 2, must be from begining of N[1] ---> 41 dydt[i] = D2 * (-3*y[i] + 4*y[i + 1] - y[i + 2] / h**2) # pluss 42 43 for i in range (N[0] + 2, N[0] + N[1] - 2): # from 801 to 1197, or 2 to 397
IndexError: index 801 is out of bounds for axis 0 with size 800
Which seems to come from my loops:
# ODE setup
def numeric(y, t, h, D1, D2, N):
dydt = np.zeros((N))
# End grid points
dydt[0] = 0
dydt[-1] = 0
# Inner grid points
for i in range (1, N[0] - 2): # 1 to 797
dydt[i] = D1 * (y[i - 1] - 2*y[i]+ y[i + 1]) / h**2 # range i = j - 1
for i in [N[0] - 2]: # 798 = special 1
dydt[i] = D1 * (-3*y[i] - 4*y[i - 1] + y[i - 2]) / h**2 # minus
for i in [N[0] - 1]: # 799 = unknown, and last index in N[0]
dydt[i] = ((D1*(-3*y[i] + 4*y[i + 1] - y[i + 2])) - (D2*(-3*y[i] - 4*y[i - 1] + y[i - 2])))
for i in [N[0] + 1]: # 800 = special 2, must be from begining of N[1]
dydt[i] = D2 * (-3*y[i] + 4*y[i + 1] - y[i + 2] / h**2) # pluss
for i in range (N[0] + 2, N[0] + N[1] - 2): # from 801 to 1197, or 2 to 397
dydt[i] = D2 * (y[i - 1] - 2*y[i] + y[i + 1]) / h**2 # range
for i in [N[0] + N[1] - 1]: # at 1198, or 398 = special 3
dydt[i] = D2 * (-3*y[i] - 4*y[i - 1] + y[i - 2]) / h**2 # range
for i in [N[0] + N[1]]: # 1199, or 399 = unknown
dydt[i] = ((D1*(-3*y[i] + 4*y[i + 1] - y[i + 2])) - (D2*(-3*y[i] - 4*y[i - 1] + y[i - 2])))
for i in [N[0] + N[1] + 1]: # at 1200, or 1 = special 4
dydt[i] = D1 * (-3*y[i + 1] + 4*y[i + 2] - y[i + 3] / h**2) # pluss
for i in range (N[0] + N[1] + 2, N[0] + N[1] + N[2] - 1): # 1202 to 1999
dydt[i] = D1 * (y[i - 1] - 2*y[i]+ y[i + 1]) / h**2 # range
return dydt
Upvotes: 1
Views: 38790
Reputation: 1441
L = [8.0, 4.0, 8.0]
dN = 1.0e2
N = [int(l*dN) for l in L] # create array [800, 400, 800]
dydt = np.zeros(shape=N) # create 3 dimensional matrix
# 1d has size 800 (from 0 to 799 including)
# 2d has size 400 (from 0 to 399 including)
# 3d same as 1st
In this code:
for i in[N[0]]:
dydt[i] = 0 # Unknown point
I is always 800 so it actually same as dydt[ 800 ] = 0
. which is bigger then 799.
It's looks like that you use numpy arrays in wrong way.
Yes in low level they represents as contiguous array of ints or floats of whatever. But on python level np.array represents as array of arrays. (ie first element as 3d matrix mtx = np.zeros(shape=[800,400,800]
in python will be mtx[0][0][0]
)).
So all code after for i in[N[0]]:
will not work. It tries to access subarray that out of matrix bounds.
UPDATE:
for example you have 3d matrix (3x3x3)
mtx=np.zero(shape=[3,3,3])
print(mtx)
#[ [ [ 0. 0. 0.]
# [ 0. 0. 0.]
# [ 0. 0. 0.] ]
# [ [ 0. 0. 0.]
# [ 0. 0. 0.]
# [ 0. 0. 0.] ]
# [ [ 0. 0. 0.]
# [ 0. 0. 0.]
# [ 0. 0. 0.] ] ]
mtx[0] = 1
print( mtx )
#[ [ [ 1. 1. 1.]
# [ 1. 1. 1.]
# [ 1. 1. 1.] ]
# [ [ 0. 0. 0.]
# [ 0. 0. 0.]
# [ 0. 0. 0.] ]
# [ [ 0. 0. 0.]
# [ 0. 0. 0.]
# [ 0. 0. 0.] ] ]
mtx[0][1] = 2
#[ [ [ 1. 1. 1.]
# [ 2. 2. 2.]
# [ 1. 1. 1.] ]
# others are zeros
mtx[0][1][2] = 3
#[ [ [ 1. 1. 1.]
# [ 2. 2. 3.]
# [ 1. 1. 1.] ]
# others are zeros
Upvotes: 0
Reputation: 20563
From a quick look, it seems the problem is the for loop, instead of using for i in [N[0]]
, are you sure it's not for i in range(N[0])
?
for i in [N[0]]
is rather redundant because the list only contains one element, ie. N[0]
, so the list of size 800 becomes out of index when you try to seek dydt[800]
<-- as the max index is 799
.
Like so:
In [9]: N
Out[9]: [800, 400, 800]
In [10]: for i in [N[0]]: # ie. i == N[0] == 800
....: dydt[i] = 0
....:
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-10-04daa45ec403> in <module>()
1 for i in [N[0]]: # ie. i == N[0] == 800
----> 2 dydt[i] = 0
3
IndexError: index 800 is out of bounds for axis 0 with size 800
In [11]: for i in range(N[0]):
....: dydt[i] = 0
....:
Upvotes: 1