我认为您可以通过在计算的不同阶段切换到数值计算来避免羔羊化时间。
也就是说,您的计算似乎是对角的,因为k1
and k2
都是以下形式k = g^T X g
其中 X 是某个 5x5 矩阵(内部有差分运算,但这并不重要),并且g
是 5xM,其中 M 大。所以k[i,j] = g.T[i,:] * X * g[:,j]
.
所以你可以直接替换
for j in xrange(1,n+1):
for i in xrange(1,m+1):
g1 += [uu(i,j,x,t), 0, 0, 0, 0]
g2 += [ 0,vv(i,j,x,t), 0, 0, 0]
g3 += [ 0, 0,ww(i,j,x,t), 0, 0]
g4 += [ 0, 0, 0,bx(i,j,x,t), 0]
g5 += [ 0, 0, 0, 0,bt(i,j,x,t)]
g = Matrix( [g1, g2, g3, g4, g5] )
with
i1 = Symbol('i1')
j1 = Symbol('j1')
g1 = [uu(i1,j1,x,t), 0, 0, 0, 0]
g2 = [ 0,vv(i1,j1,x,t), 0, 0, 0]
g3 = [ 0, 0,ww(i1,j1,x,t), 0, 0]
g4 = [ 0, 0, 0,bx(i1,j1,x,t), 0]
g5 = [ 0, 0, 0, 0,bt(i1,j1,x,t)]
g_right = Matrix( [g1, g2, g3, g4, g5] )
i2 = Symbol('i2')
j2 = Symbol('j2')
g1 = [uu(i2,j2,x,t), 0, 0, 0, 0]
g2 = [ 0,vv(i2,j2,x,t), 0, 0, 0]
g3 = [ 0, 0,ww(i2,j2,x,t), 0, 0]
g4 = [ 0, 0, 0,bx(i2,j2,x,t), 0]
g5 = [ 0, 0, 0, 0,bt(i2,j2,x,t)]
g_left = Matrix( [g1, g2, g3, g4, g5] )
and
tmp = evaluateExpr( B*g )
k1 = r*tmp.transpose() * F * tmp
k2 = r*g.transpose()*evaluateExpr(Bc*g)
k2 = evaluateExpr( k2 )
by
tmp_right = evaluateExpr( B*g_right )
tmp_left = evaluateExpr( B*g_left )
k1 = r*tmp_left.transpose() * F * tmp_right
k2 = r*g_left.transpose()*evaluateExpr(Bc*g_right)
k2 = evaluateExpr( k2 )
没有测试(上午过去),但你明白了。
现在,不再有一个巨大的符号矩阵,这会让一切变慢,而是有两个用于试验函数索引的矩阵索引和自由参数i1,j1
and i2,j2
它们发挥了作用,最后您应该将整数替换为它们。
由于要进行羔羊化的矩阵只有 5x5,并且只需要在所有循环之外进行一次羔羊化,因此羔羊化和简化的开销就消失了。此外,即使对于较大的 m、n,该问题也很容易装入内存。
集成并没有更快,但由于表达式非常小,您可以轻松地例如将它们转储到 Fortran 中或者做一些其他聪明的事情。