使用sympy展开索引表示法

时间:2016-06-05 22:23:09

标签: python sympy

下面我有一个使用索引表示法编写的等式。该等式可以用图中的六个等式表示。

Equation using index notation

使用索引表示法(爱因斯坦符号:https://en.wikipedia.org/wiki/Einstein_notation)扩展第一个等式。 在U_k中,k逗号是导数的约定。由于我们有重复索引(k,k),我们应用求和约定并得到(du_1 / dx_1 + du_2 / dx_2 + du_3 / dx_3)。在图中,术语u_1,u_2和u_3被写为u,v和w,它们由x_1,x_2和x_3(x,y和z)区分。

我是python和Sympy的新手,我看到有一个张量模块,但我看不出Sympy中是否已经实现了可以编写第一个等式(带索引)的内容,并从中获得了其他六个关系。

3 个答案:

答案 0 :(得分:5)

目前,没有直接的方式来做你要求的事情。

我将通过使用 IndexedBase (即其他符号索引的符号)建议一个应该有效的技巧,然后替换。

声明你的符号:

U = IndexedBase("U")
l = symbols("lambda")
var("mu u v w x y z i j k")

声明你的表达式(没有爱因斯坦求和,所以明确地放一个 Sum ):

sij = l*Sum(U[k, k], (k, 0, 2)) * KroneckerDelta(i, j) + mu*(U[i, j] + U[j, i])

定义替换函数:将 U [0,0] Derivative(u,x)匹配,依此类推:

def replace_U(uij):
    i1, i2 = uij.indices
    return Derivative([u, v, w][i1], [x, y, z][i2])

现在,首先使用整数值替换所有 i j 索引替换 U [i,j] ,然后替换< em> U [0,0] ,...

for ii in range(3):
    for ji in range(3):
        if ii < ji:
            continue
        pprint(sij.doit().xreplace({i: ii, j: ji}).replace(lambda v: v.base == U, replace_U))

记住: Sum.doit()扩展总和。条件 ii&gt; = ji 用于避免两次打印相同的表达式(您的等式在 i,j 中是对称的。)

请注意,上面代码中的 U [i,j] 只是一个符号, i j 除了as之外没有特殊含义 U 的索引。替换函数为它们分配衍生物。

我得到的输出是:

  ⎛d       d       d    ⎞       d    
λ⋅⎜──(u) + ──(v) + ──(w)⎟ + 2⋅μ⋅──(u)
  ⎝dx      dy      dz   ⎠       dx   
  ⎛d       d    ⎞
μ⋅⎜──(u) + ──(v)⎟
  ⎝dy      dx   ⎠
  ⎛d       d       d    ⎞       d    
λ⋅⎜──(u) + ──(v) + ──(w)⎟ + 2⋅μ⋅──(v)
  ⎝dx      dy      dz   ⎠       dy   
  ⎛d       d    ⎞
μ⋅⎜──(u) + ──(w)⎟
  ⎝dz      dx   ⎠
  ⎛d       d    ⎞
μ⋅⎜──(v) + ──(w)⎟
  ⎝dz      dy   ⎠
  ⎛d       d       d    ⎞       d    
λ⋅⎜──(u) + ──(v) + ──(w)⎟ + 2⋅μ⋅──(w)
  ⎝dx      dy      dz   ⎠       dz   
  

我是python和Sympy的新手,我看到有一个张量模块   但我无法看到Sympy中是否已经实现了某些功能   在那里我可以写出第一个方程(带索引)并从中获得   其他六个关系。

sympy.tensor.tensor ,它支持抽象索引表示法(一种受限制的爱因斯坦求和)。不幸的是,它不支持衍生品。

如果您想处理组件,最近又添加了sympy.tensor.array。它提供多维数组,张量积和收缩,以及数组导数。

答案 1 :(得分:1)

Francesco Bonazzi所述,还有另一种使用sympy.tensor.array来实现方程式的方法。该方法具有易于实现派生的优点。

示例代码如下:

from sympy import *
lam, mu, x, y, z = symbols("lambda mu x y z")
u, v, w = symbols("u v w", cls=Function)
du = derive_by_array([u(x, y, z), v(x, y, z), w(x, y, z)], [x, y, z])
sig = lam * tensorcontraction(du, (0, 1)) * eye(3) + mu * (du + transpose(du))
for i in range(3):
    for j in range(i, 3):
        Eq(Symbol("sigma_{}{}".format(i+1, j+1)), sig[i, j])

输出:

        ⎛∂                ∂                ∂             ⎞       ∂            
σ₁₁ = λ⋅⎜──(u(x, y, z)) + ──(v(x, y, z)) + ──(w(x, y, z))⎟ + 2⋅μ⋅──(u(x, y, z))
        ⎝∂x               ∂y               ∂z            ⎠       ∂x           
        ⎛∂                ∂             ⎞
σ₁₂ = μ⋅⎜──(u(x, y, z)) + ──(v(x, y, z))⎟
        ⎝∂y               ∂x            ⎠
        ⎛∂                ∂             ⎞
σ₁₃ = μ⋅⎜──(u(x, y, z)) + ──(w(x, y, z))⎟
        ⎝∂z               ∂x            ⎠
        ⎛∂                ∂                ∂             ⎞       ∂            
σ₂₂ = λ⋅⎜──(u(x, y, z)) + ──(v(x, y, z)) + ──(w(x, y, z))⎟ + 2⋅μ⋅──(v(x, y, z))
        ⎝∂x               ∂y               ∂z            ⎠       ∂y           
        ⎛∂                ∂             ⎞
σ₂₃ = μ⋅⎜──(v(x, y, z)) + ──(w(x, y, z))⎟
        ⎝∂z               ∂y            ⎠
        ⎛∂                ∂                ∂             ⎞       ∂            
σ₃₃ = λ⋅⎜──(u(x, y, z)) + ──(v(x, y, z)) + ──(w(x, y, z))⎟ + 2⋅μ⋅──(w(x, y, z))
        ⎝∂x               ∂y               ∂z            ⎠       ∂z           

答案 2 :(得分:0)

这是我对这个问题的回答。代码显示/打印结果,并且不会因为按索引符号计算而给出错误。

欢迎评论进一步 (i) 适用于科学出版物的优化和打印结果。目前看起来很尴尬。

from sympy import Symbol, Derivative
from sympy import * 
lam, mu, x, y, z = symbols("lambda mu x y z")
u, v, w = symbols("u v w", cls=Function)
du = derive_by_array([u(x, y, z), v(x, y, z), w(x, y, z)], [x, y, z])
sig = lam * tensorcontraction(du, (0, 1))*Array(eye(3))  + mu * (du + transpose(du))
alist = []
for i in range(3):
    for j in range(i, 3):
        alist.append(Eq(Symbol("sigma_{}{}".format(i+1, j+1)), sig[i, j]))
        init_printing()

enter image description here