用雅可比模式求解微分方程

计算科学 matlab 数值建模 微分方程 雅可比
2021-12-16 22:25:57

我正在尝试比较在 MATLAB 中使用 ode15s 为玩具模型求解具有和不具有雅可比模式的微分方程组的仿真时间。

global mat1 mat2
mat1=[ 
       1    -2     1     0     0     0     0     0     0     0;
       0     1    -2     1     0     0     0     0     0     0;
       0     0     1    -2     1     0     0     0     0     0;
       0     0     0     1    -2     1     0     0     0     0;
       0     0     0     0     1    -2     1     0     0     0;
       0     0     0     0     0     1    -2     1     0     0;
       0     0     0     0     0     0     1    -2     1     0;
       0     0     0     0     0     0     0     1    -2     1;
       ];

mat2 = [
        1    -1     0     0     0     0     0     0     0     0;
        0     1    -1     0     0     0     0     0     0     0;
        0     0     1    -1     0     0     0     0     0     0;
        0     0     0     1    -1     0     0     0     0     0;
        0     0     0     0     1    -1     0     0     0     0;
        0     0     0     0     0     1    -1     0     0     0;
        0     0     0     0     0     0     1    -1     0     0;
        0     0     0     0     0     0     0     1    -1     0;
        ];



x0 = [1 0 0 0 0 0 0 0 0 0]';
tspan = 0:0.01:5;

y = sym('y', [10 1]);
s = mat1*y + mat2*y;
J = jacobian(s, y);
[jr, jc] = size(J);
jpattern = sparse(jr, jc);
jpattern(find(J~=0)) = 1;
jac = sparse(10,10);
jac(2:9, :) = jpattern;
jac(10,:) = [0 0 0 0 0 0 0 0 1 1];

options = odeset('Stats', 'on', 'JPattern', jac);

ttic = tic();
[t, sol]  =  ode15s(@(t,x) fun(t,x), tspan , x0, options);
ttoc = toc(ttic)
fprintf('runtime %f seconds ...\n', ttoc)
plot(t, sol)

function f = fun(t,x)
global mat1 mat2
f(1,1) = 0;     
f(2:9,1) = mat1*x + mat2*x;
f(10,1) = 2*(x(end-1) - x(end));
end

我预计当指定雅可比模式时模拟时间会减少 [t, sol] = ode15s(@(t,x) fun(t,x), tspan , x0, options)但是,我发现jpattern指定时模拟需要更长的时间。

解释为什么在给出 jpattern 时模拟时间会增加将是有帮助的。

1个回答

这个问题太小,实际上是稀疏的。稀疏处理有很大的开销,因为索引不是“直接的”,即如果没有分支检查,您不一定知道下一个值在哪里。因此,您需要它“足够稀疏”,以使 O(n^3) 密集 LU 分解成本缩减到纯非零项克服了使用稀疏数组的非常大的恒定成本。这可以通过在 Julia 或 Haskell 等基于类型的语言中使用结构化数组来克服,但如果你想坚持使用 MATLAB,那么只需确保对非常大的问题保持稀疏操作。一个好的经验法则是 <0.01% 非零(这可能有点保守,但这取决于操作)。