我已经建立了一个微分方程系统,在离散化 pde 后获得,方法如下
dY(1) = terms_starty;
dY(end) = terms_endy;
dY(2:end-1) = (1./Vector1).*(Matrix1*Y+Matrix2*Y);
dZ(1) = terms_startz;
dZ(end) = terms_endz;
dZ(2:end-1) = (1./Vector1).*(Matrix1*Z+Matrix2*Z);
dYZ = [dY dZ];
我正在使用 ode15s 在 MATLAB 中解决上述系统。
odeset('abstol', 1e-10, 'reltol', 1e-9)
[t, s] = ode15s(@(t,s) factory(t,s), tspan , s0, options);
向量 Y,Z 的大小约为 1200,微分方程的数量约为 2400
总仿真时间约为 570 秒,当
odeset('abstol', 1e-10, 'reltol', 1e-9)
用于错误设置,使用默认错误设置时减少 5 倍。我尝试使用分析器,而 ode 求解器大约需要 508 秒。
我想知道是否有方法可以加快 ode 求解器的计算时间。另外,如果 ode 求解器为矩阵运算调用 BLAS 函数,有人可以澄清一下吗?我正在使用 MATLAB 2019b 版。
编辑:我试图通过jpattern
下面的简单示例了解如何生成矩阵
syms x y z;
F = [x*y, cos(x*z), log(3*x*z*y)]
v = [x y z]
J = jacobian(F,v)
给,
J =
[ y, x, 0]
[ -z*sin(x*z), 0, -x*sin(x*z)]
[ 1/x, 1/y, 1/z]
从 J 我想生成jpattern
以下形式的矩阵,
jpattern =
[ 1, 1, 0]
[ 1, 0, 1]
[ 1, 1, 1]
但是我找不到合适的命令来转换J
为jpattern
. 基本上,我试图找到一种方法来分配 1 代替J
. 关于如何做到这一点的建议将非常有帮助。
EDIT2:我尝试在下面的玩具模型中设置稀疏模式,
x0 = [1 0 0 0 0 0 0 0 0 0]';
tspan = 0:0.01:5;
f0 = fun(0, x0);
J = odenumjac(fun,{0 x0}, f0);
sparsity_pattern = sparse(J~=0.);
options = odeset('Stats', 'on', 'JPattern', sparsity_pattern);
[t, sol] = ode15s(@(t,x) fun(t,x), tspan , x0);
plot(t, sol)
function f = fun(t,x)
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;
];
f(1,1) = 0;
f(2:9,1) = mat1*x + mat2*x;
f(10,1) = 2*(x(end-1) - x(end));
end
不幸的是,我不知道如何修复错误
Not enough input arguments.
Error in Untitled>fun (line 36)
f(2:9,1) = mat1*x + mat2*x;
Error in Untitled (line 5)
J = odenumjac(fun,{0 x0}, f0);
有关如何修复此错误的建议将很有帮助。
我不确定矢量化是否正确。所以我也尝试了以下
function df = fun(t,x)
global mat1 mat2
f(1,:) = 0;
f(2:9,:) = mat1*x + mat2*x;
f(10,:) = 2*(x(end-1) - x(end));
df = [f(1, :); f(2:9, :); f(10, :)];
end
这对我也没有帮助。