从我的SymPy输出中,我有如下所示的矩阵,我必须在2D中集成。目前我正在以元素方式进行,如下所示。对于我的实际案例(其中sympy.mpmath.quad
及其函数更大(参见下面的编辑)),此方法有效,但对于scipy.integrate.dblquad
和A
来说都太慢了:
from sympy import Matrix, sin, cos
import sympy
import scipy
sympy.var( 'x, t' )
A = Matrix([[(sin(2-0.1*x)*sin(t)*x+cos(2-0.1*x)*cos(t)*x)*cos(3-0.1*x)*cos(t)],
[(cos(2-0.1*x)*sin(t)*x+sin(2-0.1*x)*cos(t)*x)*sin(3-0.1*x)*cos(t)],
[(cos(2-0.1*x)*sin(t)*x+cos(2-0.1*x)*sin(t)*x)*sin(3-0.1*x)*sin(t)]])
# integration intervals
x1,x2,t1,t2 = (30, 75, 0, 2*scipy.pi)
# element-wise integration
from sympy.utilities import lambdify
from sympy.mpmath import quad
from scipy.integrate import dblquad
A_int1 = scipy.zeros( A.shape, dtype=float )
A_int2 = scipy.zeros( A.shape, dtype=float )
for (i,j), expr in scipy.ndenumerate(A):
tmp = lambdify( (x,t), expr, 'math' )
A_int1[i,j] = quad( tmp, (x1, x2), (t1, t2) )
# or (in scipy)
A_int2[i,j] = dblquad( tmp, t1, t2, lambda x:x1, lambda x:x2 )[0]
我一直在考虑像这样做,但我不确定这是否可行:
A_eval = lambdify( (x,t), A, 'math' )
A_int1 = sympy.quad( A_eval, (x1, x2), (t1, t2)
# or (in scipy)
A_int2 = scipy.integrate.dblquad( A_eval, t1, t2, lambda x: x1, lambda x: x2 )[0]
编辑:
真实案例已在this link中提供。只需解压缩并运行shadmehri_2012.py
(这个例子的作者来自:Shadmehri et al. 2012)。
我已经为能够做到以下事情的人开始了50美元的赏金:
m=15
和n=15
也设法运行而不会出现内存错误,我在32-中设置了m=7
和n=7
位当前时间可以总结如下(用m = 3和n = 3测量)。从那里可以看出,数值积分是瓶颈。
构建试验函数= 0%
评估微分方程= 2%
lambdifying k1 = 22%
积分k1 = 74%
lambdifying和积分k2 = 2%
提取特征值= 0%
相关问题:about lambdify
答案 0 :(得分:5)
我认为你可以通过在计算的不同阶段切换到数值评估来避免lambdification时间。
即,您的计算似乎是对角线,因为k1
和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] )
与
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] )
和
tmp = evaluateExpr( B*g ) k1 = r*tmp.transpose() * F * tmp k2 = r*g.transpose()*evaluateExpr(Bc*g) k2 = evaluateExpr( k2 )
通过
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
和i2,j2
扮演他们的角色,你应该替换它们最后将它们整合在一起。
由于lambdify的矩阵只有5x5,并且只需要在所有循环之外进行一次lambdified,因此lambdification和简化开销就消失了。而且,即使对于大的m,n,问题也很容易适应记忆。
集成速度不是更快,但由于表达式非常小,因此您可以轻松地进行集成。 dump them in Fortran或做其他聪明的事。
答案 1 :(得分:1)
quadpy(我的一个项目)进行矢量化数值积分。此
from numpy import sin, cos, pi
import quadpy
def f(X):
x, t = X
return [
[(sin(2-0.1*x)*sin(t)*x+cos(2-0.1*x)*cos(t)*x)*cos(3-0.1*x)*cos(t)],
[(cos(2-0.1*x)*sin(t)*x+sin(2-0.1*x)*cos(t)*x)*sin(3-0.1*x)*cos(t)],
[(cos(2-0.1*x)*sin(t)*x+cos(2-0.1*x)*sin(t)*x)*sin(3-0.1*x)*sin(t)]
]
x1 = 30
x2 = 75
t1 = 0
t2 = 2*pi
sol = quadpy.quadrilateral.integrate(
f,
[[x1, t1], [x2, t1], [x2, t2], [x1, t2]],
quadpy.quadrilateral.Product(quadpy.line_segment.GaussLegendre(5))
)
print(sol)
给出
[[ 1456.3701526 ]
[ 2620.60490653]
[ 5034.5831071 ]]
时序:
%timeit quadpy.quadrilateral.integrate(f, [[x1, t1], [x2, t1], [x2, t2], [x1, t2]], q)
1000 loops, best of 3: 219 µs per loop
这会在您的可下载示例中带来显着的加速:
import numpy
array2mat = [{'ImmutableMatrix': numpy.array}, 'numpy']
k1_lambda = lambdify( (x,t), k1, modules=array2mat)
print 'Finished lambdifying k1:', time.clock()
import quadpy
sol = quadpy.quadrilateral.integrate(
lambda X: k1_lambda(X[0], X[1]),
[[x1, t1], [x2, t1], [x2, t2], [x1, t2]],
quadpy.quadrilateral.Product(quadpy.line_segment.GaussLegendre(5))
)
输出:
Start: 0.040001
Finished trial functions: 0.379929
Finished evaluating differential equations: 2.669536
Finished lambdifying k1: 29.961808
Finished integrating k1: 30.106988
Finished lambdifying and integrating k2: 34.229007
Finished calculating eigenvalues and eigenvectors: 34.229924
请注意, quadpy 不进行自适应正交,因此请明智地选择您的方案。