如何计算梯度,散度或旋度

本教程将介绍SageMath在三维欧几里得空间中的一些向量演算功能。相应的工具已经通过 SageManifolds 项目。

The tutorial is also available as a Jupyter notebook, either passive (nbviewer) or interactive (binder).

第一阶段:介绍欧几里德3-空间

在计算一些向量场算子之前,需要定义向量场所在的领域,即 3-dimensional Euclidean space mathbb{{E}}^3 . 在SageMath中,我们声明它,以及标准 笛卡尔坐标 (x,y,z) 通过 EuclideanSpace ::

sage: E.<x,y,z> = EuclideanSpace()
sage: E
Euclidean space E^3

多亏了注释 <x,y,z> 在上述声明中,坐标 (x,y,z) 立即可用作三个符号变量 xyz (无需通过 var() ,即键入 x, y, z = var('x y z') ):

sage: x is E.cartesian_coordinates()[1]
True
sage: y is E.cartesian_coordinates()[2]
True
sage: z is E.cartesian_coordinates()[3]
True
sage: type(z)
<type 'sage.symbolic.expression.Expression'>

此外, mathbb{{E}}^3 被赋予 正交向量架 (e_x, e_y, e_z) 与笛卡尔坐标相关:

sage: E.frames()
[Coordinate frame (E^3, (e_x,e_y,e_z))]

在这个舞台上 违约 矢量帧打开 mathbb{{E}}^3 (是迄今为止唯一引入的矢量帧):

sage: E.default_frame()
Coordinate frame (E^3, (e_x,e_y,e_z))

定义向量场

我们定义一个向量场 mathbb{{E}}^3 从它在向量框中的分量 (e_x,e_y,e_z) ::

sage: v = E.vector_field(-y, x, sin(x*y*z), name='v')
sage: v.display()
v = -y e_x + x e_y + sin(x*y*z) e_z

我们可以访问 v 通过方括号运算符:

sage: v[1]
-y
sage: v[:]
[-y, x, sin(x*y*z)]

向量场可以在 mathbb{{E}}^3 ::

sage: p = E((3,-2,1), name='p')
sage: p
Point p on the Euclidean space E^3
sage: p.coordinates()
(3, -2, 1)
sage: vp = v.at(p)
sage: vp
Vector v at Point p on the Euclidean space E^3
sage: vp.display()
v = 2 e_x + 3 e_y - sin(6) e_z

可绘制矢量场:

sage: v.plot(max_range=1.5, scale=0.5)
Graphics3d Object

有关自定义打印的信息,请参见的文档中的选项列表 plot() . 例如,要获得 v 在飞机上 y=1 DO::

sage: v.plot(fixed_coords={y: 1}, ambient_coords=(x,z), max_range=1.5,
....:        scale=0.25)
Graphics object consisting of 81 graphics primitives

我们可以定义一个向量场 u 具有通用组件 (u_x, u_y, y_z) ::

sage: u = E.vector_field(function('u_x')(x,y,z),
....:                    function('u_y')(x,y,z),
....:                    function('u_z')(x,y,z),
....:                    name='u')
sage: u.display()
u = u_x(x, y, z) e_x + u_y(x, y, z) e_y + u_z(x, y, z) e_z
sage: u[:]
[u_x(x, y, z), u_y(x, y, z), u_z(x, y, z)]

它在这一点上的价值 p 然后是:

sage: up = u.at(p)
sage: up.display()
u = u_x(3, -2, 1) e_x + u_y(3, -2, 1) e_y + u_z(3, -2, 1) e_z

如何计算各种向量积

DOT产品

点(或标量)积 ucdot v 向量场的 uv 通过该方法得到 dot_product() ,承认 dot() 作为快捷方式别名:

sage: u.dot(v) == u[1]*v[1] + u[2]*v[2] + u[3]*v[3]
True

s= ucdot v 是一个 标量场 ,即地图 mathbb{{E}}^3 to mathbb{{R}} ::

sage: s = u.dot(v)
sage: s
Scalar field u.v on the Euclidean space E^3
sage: s.display()
u.v: E^3 --> R
   (x, y, z) |--> -y*u_x(x, y, z) + x*u_y(x, y, z) + sin(x*y*z)*u_z(x, y, z)

它映射了 mathbb{{E}}^3 实数:

sage: s(p)
-sin(6)*u_z(3, -2, 1) + 2*u_x(3, -2, 1) + 3*u_y(3, -2, 1)

其坐标表达式为:

sage: s.expr()
-y*u_x(x, y, z) + x*u_y(x, y, z) + sin(x*y*z)*u_z(x, y, z)

标准

规范 |u| 向量场的 u 是根据点积定义的 |u| = sqrt{{ucdot u}} ::

sage: norm(u) == sqrt(u.dot(u))
True

它是上的标量场 mathbb{{E}}^3 ::

sage: s = norm(u)
sage: s
Scalar field |u| on the Euclidean space E^3
sage: s.display()
|u|: E^3 --> R
   (x, y, z) |--> sqrt(u_x(x, y, z)^2 + u_y(x, y, z)^2 + u_z(x, y, z)^2)
sage: s.expr()
sqrt(u_x(x, y, z)^2 + u_y(x, y, z)^2 + u_z(x, y, z)^2)

为了 v ,我们有:

sage: norm(v).expr()
sqrt(x^2 + y^2 + sin(x*y*z)^2)

交叉积

交叉积 utimes v 通过该方法得到 cross_product() ,承认 cross() 作为快捷方式别名:

sage: s = u.cross(v)
sage: s
Vector field u x v on the Euclidean space E^3
sage: s.display()
u x v = (sin(x*y*z)*u_y(x, y, z) - x*u_z(x, y, z)) e_x
 + (-sin(x*y*z)*u_x(x, y, z) - y*u_z(x, y, z)) e_y
 + (x*u_x(x, y, z) + y*u_y(x, y, z)) e_z

我们可以检查用分量表示叉积的标准公式:

sage: all([s[1] == u[2]*v[3] - u[3]*v[2],
....:      s[2] == u[3]*v[1] - u[1]*v[3],
....:      s[3] == u[1]*v[2] - u[2]*v[1]])
True

标量三积

我们引入第三个向量场, w 说吧。例如,我们不将组件作为 vector_field() ,就像我们做的那样 uv ;相反,我们通过方括号运算符将它们设置在第二阶段,任何未设置的组件都假定为零:

sage: w = E.vector_field(name='w')
sage: w[1] = x*z
sage: w[2] = y*z
sage: w.display()
w = x*z e_x + y*z e_y

向量场的标量三积 uvw 得到如下结果:

sage: triple_product = E.scalar_triple_product()
sage: s = triple_product(u, v, w)
sage: s
Scalar field epsilon(u,v,w) on the Euclidean space E^3
sage: s.expr()
-(y*u_x(x, y, z) - x*u_y(x, y, z))*z*sin(x*y*z) - (x^2*u_z(x, y, z)
 + y^2*u_z(x, y, z))*z

让我们检查一下 uvwucdot(vtimes w) ::

sage: s == u.dot(v.cross(w))
True

如何评价标准微分算子

标准操作员 mathrm{{grad}}mathrm{{div}}mathrm{{curl}} 向量演算中涉及到的方法可以作为标量场和向量场上的方法(例如。 v.div() ). 但是,考虑到标准的数学符号(例如。 div(v) ),让我们导入函数 grad()div()curl()laplacian() ::

sage: from sage.manifolds.operators import *

梯度

我们首先引入标量场,通过它在笛卡尔坐标下的表达式;在这个例子中,我们考虑 (x,y,z) ::

sage: F = E.scalar_field(function('f')(x,y,z), name='F')
sage: F.display()
F: E^3 --> R
   (x, y, z) |--> f(x, y, z)

价值 F 在某一点上:

sage: F(p)
f(3, -2, 1)

坡度 F ::

sage: grad(F)
Vector field grad(F) on the Euclidean space E^3
sage: grad(F).display()
grad(F) = d(f)/dx e_x + d(f)/dy e_y + d(f)/dz e_z
sage: norm(grad(F)).display()
|grad(F)|: E^3 --> R
   (x, y, z) |--> sqrt((d(f)/dx)^2 + (d(f)/dy)^2 + (d(f)/dz)^2)

发散

向量场的散度 u ::

sage: s = div(u)
sage: s.display()
div(u): E^3 --> R
   (x, y, z) |--> d(u_x)/dx + d(u_y)/dy + d(u_z)/dz

为了 vw ,我们有:

sage: div(v).expr()
x*y*cos(x*y*z)
sage: div(w).expr()
2*z

对任何标量字段有效的标识 F 以及任何向量场 u ::

sage: div(F*u) == F*div(u) + u.dot(grad(F))
True

卷曲

向量场的旋度 u ::

sage: s = curl(u)
sage: s
Vector field curl(u) on the Euclidean space E^3
sage: s.display()
curl(u) = (-d(u_y)/dz + d(u_z)/dy) e_x + (d(u_x)/dz - d(u_z)/dx) e_y
 + (-d(u_x)/dy + d(u_y)/dx) e_z

使用符号 rot 而不是 curl ,只需:

sage: rot = curl

另一种选择是:

sage: from sage.manifolds.operators import curl as rot

我们有:

sage: rot(u).display()
curl(u) = (-d(u_y)/dz + d(u_z)/dy) e_x + (d(u_x)/dz - d(u_z)/dx) e_y
 + (-d(u_x)/dy + d(u_y)/dx) e_z
sage: rot(u) == curl(u)
True

为了 vw ,我们有:

sage: curl(v).display()
curl(v) = x*z*cos(x*y*z) e_x - y*z*cos(x*y*z) e_y + 2 e_z
sage: curl(w).display()
curl(w) = -y e_x + x e_y

梯度的旋度总是为零:

sage: curl(grad(F)).display()
curl(grad(F)) = 0

旋度的散度总是零:

sage: div(curl(u)).display()
div(curl(u)): E^3 --> R
   (x, y, z) |--> 0

对任何标量字段有效的标识 F 以及任何向量场 u

\[mathrm{curl}(Fu)=mathrm{grad},F乘以u+F,mathrm{curl},u,\]

我们可以查到:

sage: curl(F*u) == grad(F).cross(u) + F*curl(u)
True

拉普拉斯

拉普拉斯人 Delta F 标量场的 F 是另一个标量字段:

sage: s = laplacian(F)
sage: s.display()
Delta(F): E^3 --> R
   (x, y, z) |--> d^2(f)/dx^2 + d^2(f)/dy^2 + d^2(f)/dz^2

以下标识为:

\[Delta F=mathrm{div}左(mathrm{grad},F右),\]

我们可以查到:

sage: laplacian(F) == div(grad(F))
True

拉普拉斯人 Delta u 向量场的 u 是另一个向量场:

sage: Du = laplacian(u)
sage: Du
Vector field Delta(u) on the Euclidean space E^3

其组成部分是:

sage: Du.display()
Delta(u) = (d^2(u_x)/dx^2 + d^2(u_x)/dy^2 + d^2(u_x)/dz^2) e_x
 + (d^2(u_y)/dx^2 + d^2(u_y)/dy^2 + d^2(u_y)/dz^2) e_y
 + (d^2(u_z)/dx^2 + d^2(u_z)/dy^2 + d^2(u_z)/dz^2) e_z

在笛卡尔坐标系中 Delta u 只不过是 u ,我们可以查看:

sage: e = E.cartesian_frame()
sage: Du == sum(laplacian(u[[i]])*e[i] for i in E.irange())
True

在上述公式中, u[[i]] 返回 i -第三部分 u 作为标量场,而 u[i] 会返回这个标量字段的坐标表达式;此外, e 是笛卡尔坐标系:

sage: e[:]
(Vector field e_x on the Euclidean space E^3,
 Vector field e_y on the Euclidean space E^3,
 Vector field e_z on the Euclidean space E^3)

对于向量场 vw ,我们有:

sage: laplacian(v).display()
Delta(v) = -(x^2*y^2 + (x^2 + y^2)*z^2)*sin(x*y*z) e_z
sage: laplacian(w).display()
Delta(w) = 0

我们有::

sage: curl(curl(u)).display()
curl(curl(u)) = (-d^2(u_x)/dy^2 - d^2(u_x)/dz^2 + d^2(u_y)/dxdy
 + d^2(u_z)/dxdz) e_x + (d^2(u_x)/dxdy - d^2(u_y)/dx^2 - d^2(u_y)/dz^2
 + d^2(u_z)/dydz) e_y + (d^2(u_x)/dxdz + d^2(u_y)/dydz - d^2(u_z)/dx^2
 - d^2(u_z)/dy^2) e_z
sage: grad(div(u)).display()
grad(div(u)) = (d^2(u_x)/dx^2 + d^2(u_y)/dxdy + d^2(u_z)/dxdz) e_x
 + (d^2(u_x)/dxdy + d^2(u_y)/dy^2 + d^2(u_z)/dydz) e_y
 + (d^2(u_x)/dxdz + d^2(u_y)/dydz + d^2(u_z)/dz^2) e_z

一个著名的身份是

\[mathrm{curl}left(mathrm{curl},uright)=mathrm{grad}left(mathrm{div},uright)-Delta u。\]

让我们检查一下:

sage: curl(curl(u)) == grad(div(u)) - laplacian(u)
True

如何自定义各种符号

自定义正交帧向量的符号

默认情况下,表示与笛卡尔坐标关联的正交坐标系的向量 (e_x,e_y,e_z) ::

sage: frame = E.cartesian_frame()
sage: frame
Coordinate frame (E^3, (e_x,e_y,e_z))

但这是可以改变的,多亏了这种方法 set_name() ::

sage: frame.set_name('a', indices=('x', 'y', 'z'))
sage: frame
Coordinate frame (E^3, (a_x,a_y,a_z))
sage: v.display()
v = -y a_x + x a_y + sin(x*y*z) a_z
sage: frame.set_name(('hx', 'hy', 'hz'),
....:                latex_symbol=(r'\mathbf{\hat{x}}', r'\mathbf{\hat{y}}',
....:                              r'\mathbf{\hat{z}}'))
sage: frame
Coordinate frame (E^3, (hx,hy,hz))
sage: v.display()
v = -y hx + x hy + sin(x*y*z) hz

自定义坐标符号

坐标符号在尖括号内定义 <...> 在欧几里德空间的构造上。上面是:

sage: E.<x,y,z> = EuclideanSpace()

这就产生了坐标符号 (x,y,z) 以及相应的Python变量 xyz (SageMath符号表达式)。使用其他符号,例如 (X,Y,Z) ,它足以创造 E AS::

sage: E.<X,Y,Z> = EuclideanSpace()

我们有:

sage: E.atlas()
[Chart (E^3, (X, Y, Z))]
sage: E.cartesian_frame()
Coordinate frame (E^3, (e_X,e_Y,e_Z))
sage: v = E.vector_field(-Y, X, sin(X*Y*Z), name='v')
sage: v.display()
v = -Y e_X + X e_Y + sin(X*Y*Z) e_Z

默认情况下,坐标的 Latex 符号与尖括号内给出的字母一致。但这可以通过可选参数进行调整 symbols 函数的 EuclideanSpace ,它必须是一个字符串,通常以 r (用于 raw 字符串,以便允许LaTeX表达式的反斜杠字符)。此字符串包含由空格分隔的坐标字段;每个字段都包含坐标的文本符号,也可能包含坐标的 Latex 符号(当后者与文本符号不同时),两个符号用冒号分隔 (: ):

sage: E.<xi,et,ze> = EuclideanSpace(symbols=r"xi:\xi et:\eta ze:\zeta")
sage: E.atlas()
[Chart (E^3, (xi, et, ze))]
sage: v = E.vector_field(-et, xi, sin(xi*et*ze), name='v')
sage: v.display()
v = -et e_xi + xi e_et + sin(et*xi*ze) e_ze