CoordSys3Dを使う方法とReferenceFrameを使う方法があるらしいです。
前者はsympy 1.1.1とnablaで検索して出てきたdocumentを実行してみました。
from sympy import init_printing
init_printing()
from sympy.vector import CoordSys3D
R=CoordSys3D('R')
v=3*R.i+4*R.j+5*R.k
v
i,j,kでなく、x,y,zでもいいみたいですが、a,b,cはダメでした。
w=3*R.x+4*R.y+5*R.z
w
electric_potential=2*R.x**2*R.y
electric_potential
from sympy import diff
diff(electric_potential,R.x)
v=R.x**2*R.i+2*R.x*R.z*R.k
v
$\nabla{}$ nabla記号をDel()で代用できます。doit()で実行します。
from sympy.vector import CoordSys3D, Del
C=CoordSys3D('C')
delop=Del()
gradient_field=delop(C.x*C.y*C.z)
gradient_field
gradient_field.doit()
$\mathbf{F}=\left(F_x,F_y,F_z\right)$として
$\nabla{}\times{}\mathbf{F}=
\left(\frac{\partial{}F_z}{\partial{}y}-\frac{\partial{}F_z}{\partial{}y}\right)\hat{\mathbf{i}}+
\left(\frac{\partial{}F_x}{\partial{}z}-\frac{\partial{}F_z}{\partial{}x}\right)\hat{\mathbf{j}}+
\left(\frac{\partial{}F_y}{\partial{}x}-\frac{\partial{}F_x}{\partial{}y}\right)\hat{\mathbf{k}}
$
from sympy.vector import CoordSys3D,Del
C=CoordSys3D('C')
delop=Del()
delopを$\times{}$ベクトル外積で計算する方法
delopを^排他的論理和XORで計算する方法
delopをcurlで計算する方法
の3つがあります。
$\nabla{}\times{}(xyz,0,0)$の計算をしてみます
delop.cross(C.x*C.y*C.z*C.i)
delop.cross(C.x*C.y*C.z*C.i).doit()
delop^C.x*C.y*C.z*C.i
(delop^C.x*C.y*C.z*C.i).doit()
from sympy.vector import curl
curl(C.x*C.y*C.z*C.i)
$\mathbf{F}=\left(U,V,W\right)$として
$\nabla{}\dot{}\mathbf{F}=
\frac{\partial{}U}{\partial{}x}+\frac{\partial{}V}{\partial{}y}+\frac{\partial{}W}{\partial{}z}
$
from sympy.vector import CoordSys3D,Del
C=CoordSys3D('C')
delop=Del()
$\mathbf{F}=\left(xyz,xyz,xyz\right)$として
$\nabla{}\dot{}\mathbf{F}=\nabla{}\dot{}\left(xyz,xyz,xyz\right)$の計算をしてみます
delopをベクトルの内積で計算する方法
delopを理論積&で計算する方法
delopをdivergenceで計算する方法
の3つの方法があります。
delop.dot(C.x*C.y*C.z*(C.i+C.j+C.k))
delop.dot(C.x*C.y*C.z*(C.i+C.j+C.k)).doit()
(delop & C.x*C.y*C.z*(C.i+C.j+C.k))
(delop & C.x*C.y*C.z*(C.i+C.j+C.k)).doit()
from sympy.vector import divergence
divergence(C.x*C.y*C.z*(C.i+C.j+C.k))
$F=f\left(x,y,z\right)$として
$\nabla{}f=\frac{\partial{}f}{\partial{}x}\mathbf{\hat{i}}+
\frac{\partial{}f}{\partial{}y}\mathbf{\hat{j}}+
\frac{\partial{}f}{\partial{}z}\mathbf{\hat{k}}
$
from sympy.vector import CoordSys3D,Del
C=CoordSys3D('C')
delop=Del()
計算方法は3つあります。
$f=xyz$で計算してみます。
delop.gradient(C.x*C.y*C.z)
delop.gradient(C.x*C.y*C.z).doit()
delop(C.x*C.y*C.z)
delop(C.x*C.y*C.z).doit()
from sympy.vector import gradient
gradient(C.x*C.y*C.z)
$\left(\vec{\upsilon}\dot{}\nabla{}\right)\mathbf{F}\left(x\right)$
from sympy.vector import CoordSys3D,Del
C=CoordSys3D('C')
delop=Del()
vel=C.i+C.j+C.k
scalar_field=C.x*C.y*C.z
vector_field=C.x*C.y*C.z*C.i
(vel.dot(delop))(scalar_field)
(vel & delop)(vector_field)
from sympy.vector import directional_derivative
directional_derivative(C.x*C.y*C.z,3*C.i+4*C.j+C.k)
$\mathbf{F}=\left(yz,xz,xy\right)$でいろいろ計算してみます。
from sympy.vector import CoordSys3D, is_conservative
R=CoordSys3D('R')
field=R.y*R.z*R.i+R.x*R.z*R.j+R.x*R.y*R.k
field
is_conservative(field)
from sympy.vector import curl
curl(field)
from sympy.vector import CoordSys3D, is_solenoidal
R=CoordSys3D('R')
field=R.y*R.z*R.i+R.x*R.z*R.j+R.x*R.y*R.k
field
is_solenoidal(field)
from sympy.vector import divergence
divergence(field)
from sympy.vector import CoordSys3D, Point
from sympy.vector import scalar_potential_difference
R=CoordSys3D('R')
P=R.origin.locate_new('P',1*R.i+2*R.j+3*R.k)
P
vectorfield=4*R.x*R.y*R.i+2*R.x**2*R.j
vectorfield
scalar_potential_difference(vectorfield,R,R.origin, P)
基本的にCoordSys3Dと同じですので、章立てせず、ササっと流していきます。
CoordSys3DだとR.x、R.y、R.zですが、ReferenceFrameだとR[0]、R[1]、R[2]となるようです。
from sympy import init_printing
init_printing()
from sympy.physics.vector import ReferenceFrame
R=ReferenceFrame('R')
electric_potential=2*R[0]**2*R[1]
electric_potential
$F=x^2y$のとき
$\frac{\partial{}F}{\partial{}x}=4xy$
を解きます。
from sympy import diff
diff(electric_potential,R[0])
from sympy.physics.vector import dynamicsymbols,express
q=dynamicsymbols('q')
q
たぶんz軸方向に$q(t)$回転させた空間を設計し、electric_potentialを表現
R1=R.orientnew('R1',rot_type='Axis',amounts=[q,R.z])
express(electric_potential,R1,variables=True)
$R_x$が$R_{1x}\sin{}(q(t))+R_{1y}\cos{}(q(t))$に
$R_y$が$R_{1x}\cos{}(q(t))-R_{1y}\sin{}(q(t))$になり
$R_z$は$R_{1z}$のままとなっています。
from sympy.physics.vector import time_derivative
time_derivative(electric_potential,R)
time_derivative(electric_potential,R1).simplify()
CoordSys3Dのcurl、divergence、gradientと同じですが、 ReferenceFrameのRをつける必要があります。
from sympy.physics.vector import ReferenceFrame
R=ReferenceFrame('R')
from sympy.physics.vector import curl
$\mathbf{F}=\left(xyz,0,0\right)$として
$\nabla{}\times{}\mathbf{F}=
\left(0,xy,-xz\right)$
field=R[0]*R[1]*R[2]*R.x
field
curl(field,R) # Rをつけないといけない
$\mathbf{F}=\left(xyz,xyz,xyz\right)$として
$\nabla{}\dot{}\mathbf{F}=xy+yz+zx$
from sympy.physics.vector import divergence
field=R[0]*R[1]*R[2]*(R.x+R.y+R.z)
field
divergence(field,R)
$F=xyz$として
$\nabla{}F=\left(yz,zx,xz\right)$
from sympy.physics.vector import gradient
scalar_field=R[0]*R[1]*R[2]
scalar_field
gradient(scalar_field,R)
from sympy.physics.vector import ReferenceFrame,is_conservative
R=ReferenceFrame('R')
field=R[1]*R[2]*R.x+R[0]*R[2]*R.y+R[0]*R[1]*R.z
field
is_conservative(field)
curl(field,R)
from sympy.physics.vector import is_solenoidal
is_solenoidal(field)
divergence(field,R)
from sympy.physics.vector import scalar_potential
conservative_field=4*R[0]*R[1]*R[2]*R.x+2*R[0]**2*R[2]*R.y+2*R[0]**2*R[1]*R.z
conservative_field
scalar_potential(conservative_field,R)
from sympy.physics.vector import Point,scalar_potential_difference
O=Point('O')
P=O.locatenew('P',1*R.x+2*R.y+3*R.z)
vector_field=4*R[0]*R[1]*R.x+2*R[0]**2*R.y
vector_field
scalar_potential_difference(vector_field,R,O,P,O)