Pythonを用いた2次元・3次元空間のベクトル場の図示

# はじめに
n次元空間を表現するためには、一般的に軸の数がn個必要になる。ゆえに、ベクトルの成分数はn個となり複雑になる。しかし、電位などのスカラーは、例えn次元空間でもパラメータは1つである。また、一般的に、電気工学や電磁気の世界では空間は2次元もしくは3次元空間といった”実用的”な空間に限定されることが多い。そこで、今回は、2次元空間における電場もしくは磁場の図示を行うことを目的とする。具体的には、電場の場合は、点電荷から初めて、最終的にはコンデンサに働く電場を図示する。一方で磁場の場合は、一本の無限長の導線に働く磁場を求めた後に有限長のソレノイドコイルに働く磁場を図示する。また、今回用い図示用のライブラリとしては、Matplotlibであり、関数としてはstreamplot(X,Y,U,V)を用いるものとする。

# 電場について
## 導入
電場は、電位の微分をマイナスしたものとして定義することができる。

$\textbf{E(r)}=-\frac{dV(r)}{dr}$

今回は二次元空間なので、

$E_x=-\frac{dV(x,y)}{dx},E_y=-\frac{dV(x,y)}{dy}$

と示すことができる。

また、点$(x_0,y_0)$に存在する電荷Qの点電荷により生じる電位は、

$V(x,y)=k\frac{Q}{\sqrt{(x-x_0)^2+(y-y_0)^2}}$

と表すことができる。ただし、kはクーロン定数とする。

## 点電荷による電場の図示
それでは、2点間に働く電場についてPythonを用いて図示してみよう。
``` python 2point_E.py
import numpy as np
import matplotlib.pyplot as plt
coords,ds = np.linspace(-0.6,0.6,100,retstep=True)

(xq1,yq1) = (0.1,0)#q1

(xq2,yq2)=(-0.1,0)#q2



X,Y = np.meshgrid(coords,coords)
k = 9.0*10**9
q1=1
q2=-1

Z=k*q1/((X-xq1)**2+(Y-yq1)**2)+k*q2/((X-xq2)**2+(Y-yq2)**2)


#電位のグラフ
plt.contour(X,Y,Z)


#勾配の配列は行方向、列方向の順で返されるので注意
#勾配つまり傾きを求める
dY,dX=np.gradient(Z,ds)

Ex=-dX
Ey=-dY

#電場のグラフ
plt.streamplot(X,Y,Ex,Ey)

# ax.quiver(X,Y,dX,dY)

plt.savefig("2点間の電場と電位.png")
plt.show()
```
このプログラムによって以下のような画像が出力される。
![2点間の電場と電位.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/e667bebc-c08b-f49f-aa75-5c8a48c91c25.png)

このように、電場の図示の場合、まずは、電位の足し合わせを考えることが大切である。

## コンデンサにより生じる電場
次に、有限長のコンデンサによって生じる電場について考察してみる。2枚の電極は、それぞれ正負の点電荷が線上に集まったものであると考えることができる。従って数直線上に点を並べる関数であるnumpy.linspace()を用いることとする。このことに留意して以下のようなプログラムを作成した。
``` python con_E.py
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

coords,ds = np.linspace(-0.6,0.6,100,retstep=True)


#XY領域の作成
X,Y = np.meshgrid(coords,coords)

k = 9.0*10**9
#微小区間の電荷の大きさ
q1=1

d=0.1
n=10000
#電極の範囲（長さ0.4の電極平板の作成）
x=np.linspace(-0.2,+0.2,n)
Z=0

for i in range(n):
  #電極の図示
  plt.plot(x[i],-d,'o',color='blue')
  plt.plot(x[i],d,'o',color='red')
  #電位の計算
  Z=Z-  k*q1/((X-x[i])**2+(Y+d)**2)**0.5+k*q1/((X-x[i])**2+(Y-d)**2)**0.5



n=100
#電位のグラフ 等高線n本
plt.contour(X,Y,Z,n)
plt.colorbar()


#勾配の配列は行方向、列方向の順で返されるので注意
#勾配つまり傾きを求める
dY,dX=np.gradient(Z,ds)
#電場
Ex=-dX
Ey=-dY

#電場のグラフ
plt.streamplot(X,Y,Ex,Ey)

# ax.quiver(X,Y,dX,dY)

plt.savefig("異符号の電場と電位_コンデンサ.png")

plt.show()
```

これを実行すると以下のようなグラフが作成される。

![コンデンサ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/701ee130-2e70-50f3-e5e6-8c3c164a49d2.png)

このように、対象となる物体を点電荷の集合体として考察することで電位を求めることができるということが分かる。




# 磁場について
## 導入
次に、無限長の導線に電流を流したときに発生する磁場について考察してみる。

ここで、(x,y)座標に複素数を導入することを考える。

地点$(x_0,y_0)$に対して紙面垂直、ネジを押し込む方向に電流が流れていると仮定する。
その時に、働く磁場ベクトルの方向と大きさは以下のように定義される。
大きさ
$H=\frac{I}{2\pi \sqrt{(x-x_0)^2+(y-y_0)^2}}$

方向

$(x-x_0,y-y_0)$ベクトルに対して、時計回りで90度回転させた単位ベクトル

したがって、これを元にしてプログラムを書くと以下のようになる。



``` python lin_h.py
"""
画面垂直方向に伸びる導線の周辺に働く磁場について
"""

import numpy as np
import matplotlib.pyplot as plt
import math
plt.figure()


LX, LY=3,3

gridwidth=0.3 
X, Y= np.meshgrid(np.arange(-LX, LX, gridwidth), np.arange(-LY, LY,gridwidth)) 




#導線の位置
x1,y1=0,0 
z1=x1+1j*y1
I=10  #定常電流の値
R1=np.sqrt((X-x1)**2+(Y-y1)**2)
plt.plot(x1,y1,'o',color='blue')

#ベクトル関数の設定。定常電流が作る静磁場 F(U(x,y), V(x,y))


x=[]
y=[]

U=np.zeros((len(X),len(X)))
V=np.zeros((len(X),len(X)))
z=0

for i in range(len(X)):
    for k in range(len(X)):
        x=X[i][k]
        y=Y[i][k]
        z=x+1j*y
        z_1=z-z1
        H=I/(2*math.pi*abs(z_1))*((-1j)*z_1/abs(z_1))
        U[i][k]=H.real
        V[i][k]=H.imag
        # if abs(z_1)>0.3:
        #     plt.quiver(x,y,u,v,color='red',angles='xy',scale_units='xy', scale=4.5)

plt.streamplot(X,Y,U,V,color="red")
plt.xlim([-LX,LX])
plt.ylim([-LY,LY])

# グラフ描画
plt.grid()
plt.draw()
plt.savefig("線電流により生じる磁場.png")
plt.show()
```

このプログラムを実行すると以下のようになる。

![線電流により生じる磁場.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/d8a6cd33-ea26-cf75-6342-e3c68525fa75.png)
このように、時計回りで磁場の流束が生じていることが分かる。

## 有限長のソレノイドコイルに働く磁場

次に、ソレノイドコイルの断面は、並行に導線が上下に複数並んだものとみなせるため、それらに働く磁場はそれぞれの導線によって働く磁場を合成してあげることによって求めることができる。したがって、今回も等間隔で点の座標をプロットすることができる、numpy.linspaceを用いる。

``` python coil_h.py

"""
ソレノイドコイルに生じる磁場
"""


import numpy as np
import matplotlib.pyplot as plt
import math
plt.figure()


LX, LY=4,4

gridwidth=0.3 
X, Y= np.meshgrid(np.arange(-LX, LX, gridwidth), np.arange(-LY, LY,gridwidth)) 

n=20
x=np.linspace(-2,+2,n)
d=1.5
zp=np.zeros(n)
zp2=np.zeros(n)
for i in range(n):
    zp[i]=x[i]    
    plt.plot(x[i],0,'o',color='blue')

    plt.plot(x[i],d,'o',color='blue')



I=1
print()
x=[]
y=[]
# u=[]
# v=[]

U=np.zeros((len(X),len(X)))
V=np.zeros((len(X),len(X)))

z=0

for i in range(len(X)):
    for k in range(len(X)):
        x=X[i][k]
        y=Y[i][k]
        z=x+1j*y
        
     
        #H=I1/(2*math.pi*abs(z_1))*((-1j)*z_1/abs(z_1)) +I2/(2*math.pi*abs(z_2))*((-1j)*z_2/abs(z_2))
        H=0
        for p in range(len(zp)):
            z_1=z-zp[p]
            z_2=z-(zp[p]+d*1j)
            H=H+I/(2*math.pi*abs(z_1))*((-1j)*z_1/abs(z_1)) -I/(2*math.pi*abs(z_2))*((-1j)*z_2/abs(z_2)) 
        U[i][k]=H.real
        V[i][k]=H.imag
        # u=H.real
        # v=H.imag
        
        # plt.quiver(x,y,u,v,color='red',angles='xy',scale_units='xy', scale=4.5)

plt.streamplot(X,Y,U,V,color="red")

plt.xlim([-LX,LX])
plt.ylim([-LY,LY])

# グラフ描画
plt.grid()
plt.draw()
plt.savefig("solenoid.png")
plt.show()
```
これを実行すると以下のような画像が出力される。

![solenoid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686019/a2560f5b-32e3-0c9f-330b-6bafc3150433.png)

このように、ソレノイドコイル中心付近に強い磁場が生じていて、コイルの端に行くにつれて磁場が乱れてしまうということが分かる。

# まとめ
今回は、2次元空間における電場・磁場ベクトルの描写方法について学んだ。その結果として関数streamplot(X,Y,U,V)を用いれば、きれいに描写することができるということが分かった。具体的にはまず、それぞれの場合で基礎となる点電荷と線電流のときを示し、次にそれらの集合体であるコンデンサ、ソレノイドコイルにおけるベクトル場を描写した。これらのことから、電場・磁場解析は基本となる要素を定義して、それらを組み合わせて合成するという作業を行えうことによって可能になるということを示唆することができた。