Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Matrix 求解大型耦合微分方程组_Matrix_Scipy_Linear Algebra_Sparse Matrix_Numerical Methods - Fatal编程技术网

Matrix 求解大型耦合微分方程组

Matrix 求解大型耦合微分方程组,matrix,scipy,linear-algebra,sparse-matrix,numerical-methods,Matrix,Scipy,Linear Algebra,Sparse Matrix,Numerical Methods,我有一个耦合的常微分方程组 dx/dt=(A+Cúd(t)*B)*x, 其中A和B为常数矩阵,C_d为对角线系数矩阵,根据积分变量的当前值平滑变化 方阵A和B由较小的60*60上三角矩阵或零矩阵组成。整个系统的尺寸约为2500*2500。A和B是稀疏的,约有10%的非零元素。对角线元素为负或零。主要的(物理)约束是x(t)的元素在积分过程中不允许变为负值 目前,我使用了一个“天真”的步骤求解器 x_(i+1)=A*x_i*dt_i+B*(C_d(t_i)*x_i)*dt_i+x_i 或者在CPU

我有一个耦合的常微分方程组
dx/dt=(A+Cúd(t)*B)*x

其中A和B为常数矩阵,C_d为对角线系数矩阵,根据积分变量的当前值平滑变化

方阵A和B由较小的60*60上三角矩阵或零矩阵组成。整个系统的尺寸约为2500*2500。A和B是稀疏的,约有10%的非零元素。对角线元素为负或零。主要的(物理)约束是x(t)的元素在积分过程中不允许变为负值

目前,我使用了一个“天真”的步骤求解器
x_(i+1)=A*x_i*dt_i+B*(C_d(t_i)*x_i)*dt_i+x_i

或者在CPU/GPU版本中

def solve_CPU(nsteps, dt, c_d, x):
    for step in xrange(nsteps): 
        x += (A.dot(x) + B.dot(x * c_d[step])) * dt[step]

def solve_GPU(m, n, nsteps, dt, c_d, cu_curr_x, cu_delta_x, cu_A, cu_B):
    for step in xrange(nsteps): 
        cubl.gemv(trans='T', m=m, n=n, alpha=1.0, A=cu_A,
                  x=cu_curr_x, beta=0.0, y=cu_delta_x)
        cubl.gemv(trans='T', m=m, n=n, alpha=c_d[step], A=cu_B,
                  x=cu_curr_x, beta=1.0, y=cu_delta_x)
        cubl.axpy(alpha=dt[step], x=cu_delta_x, y=cu_curr_x)
并利用一个特性,即步长
dt_i
,这可以通过一种方法计算出来,即在积分过程中x的元素总是>=0。根据近似量和设置,积分步数在25k和10M之间变化

我尝试了几种方法来优化通用硬件的性能:

  • (未知)当使用ODEPACK的VODE解算器时,我不知道如何表达x>=0约束
  • 使用英特尔MKL的(最慢)密集BLAS 2点积
  • 在NVIDIA GPU上使用单精度立方体的(中等)密集BLAS
  • (最快)使用CSR/CSC格式的SCIPY稀疏模块
代码是用Python编写的,可以通过Anaconda、Numba、Accelerate、Numpy等访问上述库。SCIPY的稀疏BLAS例程没有正确链接到Anaconda中的MKL,据我所知,cuSPARSE周围的Python包装器还不可用。我知道如何通过直接与cuSPARSE/C-MKL稀疏点积接口来提高性能,但仅此而已。如果模型发生变化,这个问题需要反复解决几十次,因此性能始终是一个问题。我不是这方面的专家,所以我不太了解预条件、因式分解定理等。是什么让我想到了我的问题:


有没有更优雅或更好的方法来解决这样的线性代数任务?

步长dt_i是否比函数C_d(t_i)的变化率小得多?如果是的话,一个更复杂的集成方案,它包含了约束,并且可以使用更长的时间步长。第二个问题:为什么不在计算后将任何负值剪裁为零?如果由于数值不精确而出现负值,并且您通过事先选择时间步长来解决此问题,结果将不会告诉您解决方案接近零的程度(因为数值不精确更大)。非常感谢向我指出函数C_d(t_i)的性质。我还没有尝试去寻找它的特性。它是日志中的一条线,因此不会缓慢变化。您的第二个问题:我尝试在VODE的解算器函数中对x向量进行封顶。结果是速度变慢了。我猜是因为VODE的错误估计程序被搞糊涂了?或者:如果你的意思是“计算完成后”=“计算完成后”,那么问题是方程是耦合的,本征模是重的,你的方程是线性的,因此,我并没有立即发现一个数学上的原因来解释为什么避免负的
x
值很重要——方程是耦合的,等等,这与解的准确性无关。您可以尝试在完成积分器时对值进行封顶(这样就不会弄乱被积函数的平滑度),然后将精度与其他方法进行比较。另外,如果你对能量守恒或其他物理量感兴趣,研究辛或变分积分器可能会很有用,它们具有精确的守恒性质。我试着忽略负值和解发散。该系统是粒子产生和衰变的级联方程。因此,负值表示负粒子数。因此,如果有更多的粒子衰变,它们就开始创造它们的母亲,这有点奇怪:)我们可以把这个系统看作一个更复杂的捕食者-食饵模型。系统是线性化的,因此选择太大的dt会导致线性化范围失效。解耦系统的自治解将是指数的,它永远不会变为零。我来看看你建议的积分类型。如果你能在问题形成的论文中添加引文,那可能会有所帮助。