Python: рассчитать магнитное поле провода, используя закон Био-Саварта - PullRequest
2 голосов
/ 11 февраля 2011

Я хочу рассчитать магнитное поле провода, используя закон Био-Саварта.Некоторые люди рекомендуют использовать массивы NumPy.Сначала я сделал это с vpython, и это сработало.Но знаете, я хочу использовать Matplotlib для визуализации.Поэтому мне нужны массивы правильно?Но я застрял сейчас.

Я также отправил этот вопрос в codereview, но они отправили меня в stackoverflow.

Проблема в этой строке -> bfield2 = konstante * I * cross (dl, (rx, ry, rz)) / r ** 3

import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
from visual import *

I = 1
mu0 = 1e-7
konstante = mu0/(4*np.pi)

# wire elements; always lenght one
coord = [(0,0), (1,0), (2,0), (3,0), (4,0), (5,0), (6,0), (7,0), (8,0), (9,0), (9,1),
         (9,2), (9,3), (9,4), (9,5), (9,6), (9,7), (9,8)]
# draw the wires
#for i in range(len(coord)-1):
#    wire = curve(pos=(coord[i],coord[i+1]), radius=0.2)

# calculate the b-field
def bfield(x,y,z):
    bfield3 = 0
    # number of wire elements
    for i in range(len(coord)-1):
        # center of the wire element
        wiremiddlex = coord[i][0]+(coord[i+1][0]-coord[i][0])/2.0
        wiremiddley = coord[i][1]+(coord[i+1][1]-coord[i][1])/2.0
        wiremiddlez = 0
        rx = x-wiremiddlex
        ry = y-wiremiddley
        rz = 0
        r = (rx**2+ry**2+rz**2)**0.5
        dl = ((coord[i+1][0]-coord[i][0]), (coord[i+1][1]-coord[i][1]), 0)
        bfield2 = konstante*I*cross(dl, (rx,ry,rz))/r**3 # i have to use numpy arrays
        bfield3 += (bfield2[0]**2 + bfield2[1]**2 + bfield2[2]**2)**0.5
    return bfield3

# visualize
xwidth=10
ywidth=10
delta = 1
x = np.arange(0, xwidth, delta)
y = np.arange(0, ywidth, delta)
X, Y = np.meshgrid(x, y)
slicee = 3
Z = bfield(X,Y,slicee)

plt.figure()
CS = plt.contour(X, Y, Z)
plt.clabel(CS, inline=1, fontsize=10)
plt.title('Simplest default with labels')
plt.show()

РЕДАКТИРОВАТЬ № 7: Я удаляю другие правки.Я не хочу путать.Вывод не правильный.Пожалуйста, смотрите следующее Правление.

# Calculation of a magnetic field of a wire
# later I want to to it three dimensional

import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
from pylab import *

I = 10000000000
mu0 = 1e-7
constant = mu0/(4*np.pi)

# wire elements; always lenght one
coord = [(0,0), (1,0), (2,0), (3,0), (4,0), (5,0), (6,0), (7,0), (8,0),
         (9,0), (9,1), (9,2), (9,3), (9,4), (9,5), (9,6), (9,7), (9,8),
         (8,8), (7,8), (6,8), (5,8)]

# calculate the b-field
def bfield(x,y,z):
    b2 = np.zeros((xwidth,ywidth))
    for x in range(xwidth):
        for y in range(ywidth):
            # number of wire elements
            for i in range(21):
                rx = (coord[i][0]+coord[i+1][0])/2. - x
                ry = (coord[i][1]+coord[i+1][1])/2. - y
                rz = z * 1.0 # = z-0
                r = (rx**2+ry**2+rz**2)**0.5 # distance r between field and middle of the wire
                dl = np.array([(coord[i+1][0]-coord[i][0]), (coord[i+1][1]-coord[i][1]), 0])
                b = np.cross(dl, np.array([rx,ry,rz]))
                e = constant*I*b/r**3
                b2[y][x] += e[2] # why not x y?
    return b2

xwidth = 15 
ywidth = 15
delay = 1
x = np.arange(0, xwidth, delay)
y = np.arange(0, ywidth, delay)
X, Y = np.meshgrid(x, y)
slicee = 0.1
Z = bfield(X,Y,slicee)

# visualize
plt.figure()
CS = plt.contour(X, Y, Z)
plt.clabel(CS, inline=1, fontsize=10)
x1 = array([0,1,2,3,4,5,6,7,8,9,9,9,9,9,9,9,9,9,8,7,6,5])
y1 = array([0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,8,8,8,8])
plot(x1,y1)
plt.title('magnetic field')
plt.show()

Последнее редактирование: Наконец-то я сделал это без numpy.Следующая версия работает.

# Calculation of a magnetic field of a wire
# later I want to to it three dimensional

import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
from pylab import *

# constant
I = 10000000000
mu0 = 1e-7
constant = mu0/(4*np.pi)

# wire position
coord = [(10,10), (20,10), (20,20), (10,20), (10,25)]
coord2 = []

# devide path of the wire in parts of length one
parts = 0
for n in range(len(coord)-1):
    lengthx = coord[n+1][0] - coord[n][0]
    lengthy = coord[n+1][1] - coord[n][1]
    length = (lengthx**2 + lengthy**2)**.5
    for m in range(int(length)):
        coord2.append((coord[n][0]+lengthx/length*m, coord[n][1]+lengthy/length*m))
        parts += 1

# calculate the b-field
def bfield(x,y,z):
    b = 0
    for i in range(parts-1):
        dlx = coord2[i+1][0]-coord2[i][0]
        dly = coord2[i+1][1]-coord2[i][1] 
        dlz = 0
        dl = np.array([dlx,dly,dlz])
        rspace_minus_rwire_x = x - (coord2[i][0]+dlx)
        rspace_minus_rwire_y = y - (coord2[i][1]+dly)
        rspace_minus_rwire_z = z - 0
        rspace_minus_rwire = np.array([rspace_minus_rwire_x, rspace_minus_rwire_y, rspace_minus_rwire_z])
        absr = (rspace_minus_rwire_x**2 + rspace_minus_rwire_y**2 + rspace_minus_rwire_z**2)**0.5
        a = constant * I * np.cross(dl, rspace_minus_rwire) / absr**3
        b += (a[0]**2 + a[1]**2 + a[2]**2)**0.5
    return b

xwidth = 26
ywidth = 26
z = 1
bmatrix = np.zeros((xwidth,ywidth))
for x in range(xwidth):
    for y in range(ywidth):
        bmatrix[x][y] = bfield(x,y,z)

# visualize
plt.figure()
x = range(xwidth)
y = range(ywidth)
z = bmatrix[x][y].T
contour(x,y,z,35)
plt.show()

Ответы [ 4 ]

2 голосов
/ 11 февраля 2011

Это не какой-либо ответ на ваш исходный вопрос, а просто подсказка, как работать с numpy массивами:

In []: coord = [(0,0), (1,0), (2,0), (3,0), (4,0), (5,0), (6,0), (7,0), (8,0), (9,0), (9,1), (9,2), (9,3), (9,4), (9,5), (9,6), (9,7), (9,8)]
In []: coord= np.array(coord).T
In []: coord
Out[]:
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8]])
In [170]: wiremiddle= (coord[:, 1:]- coord[:, :-1])/ 2.
In []: wiremiddle
Out[]:
array([[ 0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0. ,  0. , 0. ,  0. ,  0. ,  0. ,  0. , 0. ],
       [ 0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0.5,  0.5, 0.5,  0.5,  0.5,  0.5,  0.5,  0.5]])

Я надеюсь, это поможет переписать ваш код.

2 голосов
/ 11 февраля 2011

Изменение

dl = ((coord[i+1][0]-coord[i][0]), (coord[i+1][1]-coord[i][1]), 0)
bfield2 = konstante*I*cross(dl, (rx,ry,rz))/r**3 # i have to use numpy arrays

Для

dl = np.array([(coord[i+1][0]-coord[i][0]), (coord[i+1][1]-coord[i][1]), 0])
bfield2 = konstante*I*cross(dl, np.array([rx,ry,rz]))/r**3 # i have to use numpy arrays

У меня нет Numpy на этой машине, так что это не проверено. В основном, измените ваши кортежи в массивы с помощью np.array.

Вы также можете оставить dl в покое и изменить bfield2 на np.array(dl) вместо dl.

.
1 голос
/ 11 февраля 2011

Я бы не использовал визуальный модуль, который, по-видимому, вы используете только для вызова 'cross' и использовал вместо него крестик numpy: http://docs.scipy.org/doc/numpy/reference/generated/numpy.cross.html

Вам придется изменитьпара строк для создания dl и второй аргумент массива кроссовок numpy

 dl = np.array([(coord[i+1][0]-coord[i][0]), (coord[i+1][1]-coord[i][1]), 0])

и двойная проверка, чтобы убедиться, что крест numpy делает то же самое, что и визуал.

Если вы настаиваетепри использовании метода визуального кроссирования из ошибки ясно, что у вас конфликт типов, который вам придется устранить

1 голос
/ 11 февраля 2011

вы делаете это:

bfield3 = 0

возможно, вы должны сделать что-то вроде этого:

bfield3 = np.zeros((len(...),len(...)))

Или, возможно, bfield3 уже выделен?а вы просто хотите установить все значения на ноль?Затем сделайте это:

bfield3[:,:] = 0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...