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

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

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

第一阶段:介绍欧几里得三维空间

在评估某些向量场运算符之前,需要定义向量场所在的领域,即 3-dimensional Euclidean space mathbb{E}^3 。在SageMath中,我们将其与标准 Cartesian coordinates (x,y,z) 、VIA 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)
<class 'sage.symbolic.expression.Expression'>

再说了, mathbb{E}^3 被赋予了 orthonormal vector frame (e_x, e_y, e_z) 与笛卡尔坐标关联:

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

在这个阶段,这是 default 启用向量帧 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

如何计算各种向量积

点积

点(或标量)积 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 is a scalar field, i.e. a map 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 → ℝ
   (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)

常模

The norm |u| of the vector field u is defined in terms of the dot product by |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 → ℝ
   (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 → ℝ
   (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 → ℝ
   (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 → ℝ
   (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 → ℝ
   (x, y, z) ↦ 0

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

\[\mathrm{curl}(Fu) = \mathrm{grad}\, F\times 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 → ℝ
   (x, y, z) ↦ d^2(f)/dx^2 + d^2(f)/dy^2 + d^2(f)/dz^2

以下身份成立:

\[\Delta F = \mathrm{div}\left(\mathrm{grad}\, F\right),\]

正如我们可以查看的:

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 -第7个组件 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}\, u\right) = \mathrm{grad}\left(\mathrm{div}\, u\right) - \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