我想计算一下两个二阶张量在Python(NumPy)中的次对称和大对称交叉并矢积.
C[i,j,k,l] = (
A[i, k] * B[j, l] + A[i, l] * B[k, j] + B[i, k] * A[j, l] + B[i, l] * A[k, j]
) / 4
我有两个形状(3, 3, n)
的二阶张量,其中最后一个尾轴表示批次维度.我已经在我最近发布的Python包hyperelastic中实现了该函数,希望得到您对我的代码效率的反馈.我想避免任何像Numba这样的JIT东西.
给定两个对称的二阶张量作为缩减向量存储中的NumPy数组,
import numpy as np
# any random 3x3 tensor
F = np.eye(3).reshape(3, 3, 1) + np.random.rand(3, 3, 100000) / 10
# a symmetric 3x3 tensor
C = F.T @ F
# Voigt-notation vector storage
# (upper triangle items but sorted on the diagonals; starting from the main diag.)
i = [0, 1, 2, 0, 1, 0]
j = [0, 1, 2, 1, 2, 2]
A = C[i, j]
我当前的实现如下所示:
import numpy as np
def cdya(A, B):
i, j = [a.ravel() for a in np.indices((6, 6))]
a = np.array([(0, 0), (1, 1), (2, 2), (0, 1), (1, 2), (0, 2)])
b = np.array([0, 3, 5, 3, 1, 4, 5, 4, 2]).reshape(3, 3)
i, j, k, l = np.hstack([a[i], a[j]]).T
ik = b[i, k].reshape(6, 6)
jl = b[j, l].reshape(6, 6)
il = b[i, l].reshape(6, 6)
kj = b[k, j].reshape(6, 6)
C = (A[ik] * B[jl] + A[il] * B[kj]) / 2
if A is not B:
C += (B[ik] * A[jl] + B[il] * A[kj]) / 2
C /= 2
return C
A = np.random.rand(6, 100000)
B = np.random.rand(6, 100000)
C = cdya(A, B)
在我的机器上,这个函数大约需要花费几分钟.np.einsum
ms.在全张量存储中使用np.einsum
个相同的实现大约需要花费.160毫秒.
A = np.random.rand(3, 3, 100000)
B = np.random.rand(3, 3, 100000)
C = (
np.einsum("ij...,kl...->ikjl...", A, B) + np.einsum("ij...,kl...->ilkj...", A, B) +
np.einsum("ij...,kl...->ikjl...", B, A) + np.einsum("ij...,kl...->ilkj...", B, A)
) / 4
你认为还有改进的余地吗?还是我已经找到了一个很好的解决方案?
首先要感谢大家!