标量和矢量场功能

在 sympy.vector 中的实现

标量场和矢量场

sympy.vector 中,每个 CoordSys3D 实例都被分配了对应于 \(X\)\(Y\)\(Z\) 轴的基向量。这些可以通过分别命名为 ijk 的属性来访问。因此,要在给定框架 \(\mathbf{R}\) 下定义一个形式为 \(3\mathbf{\hat{i}} + 4\mathbf{\hat{j}} + 5\mathbf{\hat{k}}\) 的向量 \(\mathbf{v}\),你可以这样做

>>> from sympy.vector import CoordSys3D
>>> R = CoordSys3D('R')
>>> v = 3*R.i + 4*R.j + 5*R.k

关于向量的数学和基本微积分运算,在本模块文档的早期部分已经详细阐述。

另一方面,基本标量(或坐标变量)是在一个名为 BaseScalar 的特殊类中实现的,并且分配给每个坐标系,每个轴从 \(X\)\(Y\)\(Z\) 各有一个。这些坐标变量用于形成三维空间中向量或标量场的表达式。对于一个系统 R\(X\)\(Y\)\(Z\)BaseScalars 实例可以通过 R.xR.yR.z 表达式分别访问。

因此,要生成上述电势场 \(2{x}^{2}y\) 的表达式,您必须执行

>>> from sympy.vector import CoordSys3D
>>> R = CoordSys3D('R')
>>> electric_potential = 2*R.x**2*R.y
>>> electric_potential
2*R.x**2*R.y

需要注意的是,BaseScalar 实例可以像其他 SymPy Symbol 一样使用,只不过它们存储了关于它们所对应的坐标系和轴的信息。

标量场可以像任何其他 SymPy 表达式一样处理,用于任何数学/微积分功能。因此,要对上述电势相对于 \(x\) (即 R.x)进行微分,您可以使用 diff 方法。

>>> from sympy.vector import CoordSys3D
>>> R = CoordSys3D('R')
>>> electric_potential = 2*R.x**2*R.y
>>> from sympy import diff
>>> diff(electric_potential, R.x)
4*R.x*R.y

值得注意的是,表达式中包含 BaseScalar 意味着在三维空间中,’场’ 随位置变化。从技术上讲,一个没有 BaseScalar 的简单 Expr 仍然是一个场,尽管是常数。

与标量场类似,随位置变化的向量场也可以使用 BaseScalar 在度量数表达式中构建。

>>> from sympy.vector import CoordSys3D
>>> R = CoordSys3D('R')
>>> v = R.x**2*R.i + 2*R.x*R.z*R.k

Del 运算符

Del 算子,或称为 ‘Nabla’ 算子 - 写作 \(\mathbf{\nabla}\) ,通常被称为向量微分算子。根据其在数学表达式中的使用,它可以表示标量场的梯度、向量场的散度或向量场的旋度。

本质上,\(\mathbf{\nabla}\) 在技术上不是一个’运算符’,而是一种方便的数学符号,用来表示上述任何一种场操作。

sympy.vector 中,\(\mathbf{\nabla}\) 被实现为 Del() 类。该类的实例与坐标系无关。因此,\(\mathbf{\nabla}\) 运算符可以通过 Del() 访问。

下面是一个 Del() 类使用示例。

>>> from sympy.vector import CoordSys3D, Del
>>> C = CoordSys3D('C')
>>> delop = Del()
>>> gradient_field = delop(C.x*C.y*C.z)
>>> gradient_field
(Derivative(C.x*C.y*C.z, C.x))*C.i + (Derivative(C.x*C.y*C.z, C.y))*C.j
+ (Derivative(C.x*C.y*C.z, C.z))*C.k

上述表达式可以使用 SymPy 的 doit() 例程进行求值。

>>> gradient_field.doit()
C.y*C.z*C.i + C.x*C.z*C.j + C.x*C.y*C.k

sympy.vector 模块中使用 \(\mathbf{\nabla}\) 符号的用法已在后续小节中进行了更详细的描述。

正交曲线坐标系中的场算子

vector 包支持在不同类型的正交曲线坐标系中进行计算。为此,使用比例因子(也称为Lame系数)来表示所需坐标系中的 curldivergencegradient

例如,如果我们想在柱坐标系中计算 gradient ,我们只需要创建适当的坐标系

>>> from sympy.vector import CoordSys3D
>>> c = CoordSys3D('c', transformation='cylindrical', variable_names=("r", "theta", "z"))
>>> gradient(c.r*c.theta*c.z)
    c.theta*c.z*c.i + c.z*c.j + c.r*c.theta*c.k

保守场和无散场

在向量微积分中,保守场是一个场的梯度,这个场是某个标量场的梯度。保守场具有这样的性质:它们在任何路径上的线积分仅取决于端点,并且与所经过的路径无关。保守向量场也被称为‘无旋的’,因为保守场的旋度总是零。

在物理学中,保守场表示物理系统中的力,其中能量是守恒的。

要检查一个向量场在 sympy.vector 中是否是保守的,可以使用 is_conservative 函数。

>>> 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
>>> is_conservative(field)
True
>>> curl(field)
0

另一方面,螺线管场是一个矢量场,其在空间中所有点的散度为零。

要在 sympy.vector 中检查一个向量场是否是无散的,可以使用 is_solenoidal 函数。

>>> 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
>>> is_solenoidal(field)
True
>>> divergence(field)
0

标量势函数

我们之前提到过,每个保守场都可以定义为某个标量场的梯度。这个标量场也称为与上述保守场对应的’标量势场’。

sympy.vector 模块中的 scalar_potential 函数计算给定保守向量场在三维空间中对应的标量势场 - 当然,减去了积分常数。

使用示例 -

>>> from sympy.vector import CoordSys3D, scalar_potential
>>> R = CoordSys3D('R')
>>> conservative_field = 4*R.x*R.y*R.z*R.i + 2*R.x**2*R.z*R.j + 2*R.x**2*R.y*R.k
>>> scalar_potential(conservative_field, R)
2*R.x**2*R.y*R.z

将一个非保守向量场作为参数传递给 scalar_potential 会引发 ValueError

标量势差,或简称为’势差’,对应于保守向量场的标量势函数在空间中两点之间的差值可以被定义。这在计算关于保守函数的线积分时非常有用,因为它仅依赖于路径的端点。

此计算在 sympy.vector 中执行如下。

>>> 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)
>>> vectfield = 4*R.x*R.y*R.i + 2*R.x**2*R.j
>>> scalar_potential_difference(vectfield, R, R.origin, P)
4

如果提供的是标量表达式而不是矢量场,scalar_potential_difference 返回的是该标量场在两个给定空间点上的值之差。