Электри c вычисление поля с python: постоянно получаю ошибку индекса (Python) - PullRequest
0 голосов
/ 25 марта 2020

Я работаю над проблемой вычислительной физики, используя python. Ожидаемым выходным сигналом должен быть график с маленькими стрелками (с использованием колчана), показывающий направление поля электричества c в каждой точке внутри призмы из полого металла 1010 * с внутренним проводником solid metalli c. На внутреннем проводнике, напряжение = 1, и на границах полой призмы, напряжение = 0. Это (довольно длинный) код, который у меня есть:

import matplotlib #plotting libraries
import numpy as np #numerical routines
import matplotlib.mlab as mlab #bridge from python to matlab that lets matlab look like a normal python library
import matplotlib.pyplot as plt #plotting libraries
from mpl_toolkits.mplot3d import Axes3D #3D axes 
from copy import deepcopy #deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original
from pylab import * #plotting and numerical routines 

v = [] #creates list for values of v(i,j)
dx = 0.01
dy = 0.01

#initializing boundary conditions:
for i in range(101): 
    row_i = [] #list to store initial values of i and j in
    for j in range(101):
        #i in [35,65] b/c my range is 0-100 for a graph from (-1,1). Thus, each step (in 0-100) has a value of 0.02 (in(-1,1))
        #so since in the graph, the inner conductor is from -0.3,0.3, in time step numbers that is 35 to 65
        if 35<=i<=65 and 35<=j<=65: #boundary for inner conductor
            volt = 1

        #inside (65,99] is all of the space between conductor and prism 
        elif 65<i<=99 or 65<j<=99: #outside of conductor inside prism
            volt = 0
        elif i==0 or i==100 or j==0 or j==100: #metallic prism boundary
            volt = 0
        else:
            volt = 0
        row_i.append(volt) #stores initial values of v in row_i list
    v.append(row_i) #stores the initial values of v in 2d array like list

def update_V(v): #uses initialized values to compute improved estimate for v(i,j)
    dv = 0
    #looping through all points (i,j) except for the boundary
    for i in range(101):
        for j in range(101):
            #pass at boundary:
            if i==0 or i==100 or j==0 or j==100: 
                pass
            #pass at boundary:
            elif 35<=i<=65 and 35<=j<=65:
                pass
            else:
                v_new = (v[i+1][j]+v[i-1][j]+v[i][j+1]+v[i][j-1])/4
                v_old = v[i][j] #assigns value of v(i,j) from previous step as v-old
                dv += abs(v_old - v_new)
                v[i][j] = v_new #after loop goes through calculation for v-new, stores it as the current value for v(i,j)
                #v[i][j] is the value stored in v at the index i and j
    return v, dv

#calls update-v and tests for convergence of dv
def laplace_calculate(v):
    #10^-5 times N for checking 10^-5 at each site
    epsilon = 10**(-5)*100**2

    #initializing dv and N
    dv = 0
    N = 0

    while dv >= epsilon or N <= 10:
        v1, dv = update_V(v) #calling update-v so v creates improved guess of v1
        v2, dv = update_V(v1) #calling update-v again so v1 creates further improved guess of v2
        v = v2
        N += 1

    return v2

Z = laplace_calculate(v)
Ex = deepcopy(Z) #copies the function laplace-calculate
Ey = deepcopy(Z)
Ez = deepcopy(Z)
E = deepcopy(Z)

#electric field values calculation
for i in range(101):
    for j in range(101):
        if i==0 or j==0: #prism boundary on left
            #one sided difference equation for Ex and Ey
            Ex_value = -(v[i+1][j])/dx
            Ey_value = -(v[i][j+1])/dy
            Ex[i][j] = Ex_value #updates Ex-value to Ex list 
            Ey[i][j] = Ey_value #updates Ey-value to Ey list
        elif i==100 or j==100:
            #one sided difference equation for Ex and Ey
            Ex_value = -(v[i-1][j])/dx
            Ey_value = -(v[i][j-1])/dy
            Ex[i][j] = Ex_value
            Ey[i][j] = Ey_value
        elif 35<=i<=65 and 35<=j<=65:
            Ex_value = 0
            Ey_value = 0
            Ex[i][j] = Ex_value
            Ey[i][j] = Ey_value
        else:
            Ex_value = -(v[i+1][j] - v[i-1][j])/(2*dx) 
            Ey_value = -(v[i][j+1] - v[i][j-1])/(2*dy)
            Ex[i][j] = Ex_value
            Ey[i][j] = Ey_value

for i in range(101):
    for j in range(101):
        #just calculates the actual electric field value taken from the x and y values above 
        E_value = np.sqrt(Ex[i][j]**2 + Ey[i][j]**2)
        E[i][j] = E_value

x = np.linspace(-1,1,100)
y = np.linspace(-1,1,100)
X, Y = np.meshgrid(x,y)

fig, ax = plt.subplots()
ax.quiver(X, Y, Ey, Ex)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('Electric Field')
plt.xticks([-1.5,-1,-0.5,0,0.5,1,1.5],['','-1','','0','','1',''])
plt.yticks([-1.5,-1,-0.5,0,0.5,1,1.5],['','-1','','0','','1',''])
plt.show()

Однако он продолжает выдавать ошибку при строка 80:

IndexError                                Traceback (most recent call last)
<ipython-input-8-f2be5562450c> in <module>
     78             #one sided difference equation for Ex and Ey
     79             Ex_value = -(v[i+1][j])/dx
---> 80             Ey_value = -(v[i][j+1])/dy
     81             Ex[i][j] = Ex_value #updates Ex-value to Ex list
     82             Ey[i][j] = Ey_value #updates Ey-value to Ey list

IndexError: list index out of range

Я понимаю, что такое ошибка индекса, но здесь я не вижу, как мой индекс выходит за пределы диапазона моего списка. Что мне не хватает? Все остальные циклы if / elif находятся в диапазоне, например, когда я закомментирую уравнения для первого, если l oop внутри моих вычислений в поле electri c, и вместо этого приравниваю их к нулю, я получаю вывод. Я все еще очень плохо знаком с python и пытаюсь получить лучший результат asp. Любая помощь в этом вопросе очень ценится.

1 Ответ

0 голосов
/ 25 марта 2020

Ваши циклы i и j превышают range(101), поэтому наименьшее значение равно 0, а наибольшее 100.

В рассматриваемой строке

Ey_value = -(v[i][j+1])/dy

j+1 может получить до 101.

Если v[i] - это список с len 100, то этот индекс, 100 или 101, слишком велик. Допустимое индексирование для списка такого размера: от 0 до 99 (диапазон (99)). То же самое для массива numpy с формой (100,100) (но это приведет к другому сообщению об ошибке).

...