我有一个我的程序解决的微分方程:
p := dsolve({ic, sys}, numeric, method = rosenbrock);
解决后我们有以下内容:
print(p(10));
[t = 10., alpha(t) = HFloat(0.031724302221312055), beta(t) = HFloat(0.00223975915581258)]
我需要使用这个alpha(t)和beta(t)如下:
a := t->exp( int(alpha(t)),x=0..t) );
b := t->exp( int(beta(t)),x=0..t) )
绘制情节:
odeplot(p, [[t, a(t)], [t, b(t)]], 0 .. 20, thickness = 2, numpoints = 500, color = [red, blue])
这样做的第一件事是:
p := dsolve({sys, ic}, numeric, method=rosenbrock);
alpha := t->rhs(p(t)[2] );
beta := t->rhs(p(t)[3;
a := t->exp( int(alphat)),x=0..t) );
b := t->exp( int(betat)),x=0..t) );
odeplot(p, [[t, a(t)], [t, b(t)]], 0 .. 20, thickness = 2, numpoints = 500, color = [red, blue])
但是代码不起作用,显然,是的,应采取不同的行动。
答案 0 :(得分:1)
首先,让我们尝试让您的方法工作,并进行一些语法和用法更改。
您没有提供示例的详细信息,因此我构建了微分方程sys
和初始条件ic
的系统,以便可以执行计算命令。
restart:
sys := diff(alpha(t),t) = -1/200*beta(t),
diff(beta(t),t) = -1/200*alpha(t) - 1/Pi^2:
ic := alpha(0)=0, beta(0)=-1:
p := dsolve({ic, sys}, numeric, method = rosenbrock, output=listprocedure):
alphat := eval(alpha(t),p):
betat := eval(beta(t),p):
a := unapply( exp( Int(alphat , 0..t) ), t, numeric):
b := unapply( exp( Int(betat , 0..t) ), t, numeric):
evalf(a(20.0)), evalf(b(20.0));
-18
5.347592595, 3.102016550 10
st := time():
P := plots:-odeplot(p, [[t, a(t)], [t, b(t)]], 0 .. 20,
thickness = 2, numpoints = 50, color = [red, blue]):
( time() - st )*`seconds`;
16.770 seconds
P;
我使用了output=listprocedure
,因此我可以将正确的过程从解决方案p
分配到alphat
和betat
。那些调用次数更有效,而不是原始版本为每个数字t
值形成一系列值,然后必须选择某个操作数。它也更稳健,因为它对位置不敏感(如果你改变了变量的名称,可能会因为新的词典排序而改变)。
以上在Intel i7上花了大约16秒。那不是很快。一个原因是数值积分的计算精度高于绘图所需的精度。因此,让我们重新启动(以确保公平的时间安排)并重新计算a
和b
的数字集成的宽松容差。
restart:
sys := diff(alpha(t),t) = -1/200*beta(t),
diff(beta(t),t) = -1/200*alpha(t) - 1/Pi^2:
ic := alpha(0)=0, beta(0)=-1:
p := dsolve({ic, sys}, numeric, method = rosenbrock, output=listprocedure):
alphat := eval(alpha(t),p):
betat := eval(beta(t),p):
a := unapply( exp( Int(alphat , 0..t, epsilon=1e-5) ), t, numeric):
b := unapply( exp( Int(betat , 0..t, epsilon=1e-5) ), t, numeric):
evalf(a(20.0)), evalf(b(20.0));
-18
5.347592681, 3.102018090 10
st := time():
P := plots:-odeplot(p, [[t, a(t)], [t, b(t)]], 0 .. 20,
thickness = 2, numpoints = 50, color = [red, blue]):
( time() - st )*`seconds`;
0.921 seconds
您可以检查这是否显示相同的情节。
现在让我们对示例进行扩充,以便数字积分由dsolve,numeric
本身计算。我们可以通过使用微积分来做到这一点。通过这种方式,我们将它留给数字ode求解器进行自己的误差估计,步长控制,刚度或奇点检测等。
请注意,积分alphat
和betat
不是我们具有显式函数的函数 - 它们的准确性与数字ode求解紧密相关。这与使用数字ode例程简单地用函数替换数字正交例程来解决问题并不完全相同,我们希望直接计算得到任何所需的精度(包括在任何奇点的任一侧)。
restart:
sys := diff(alpha(t),t) = -1/200*beta(t),
diff(beta(t),t) = -1/200*alpha(t) - 1/Pi^2,
diff(g(t),t) = alpha(t), diff(h(t),t) = beta(t):
ic := alpha(0)=0, beta(0)=-1,
g(0)=0, h(0)=0:
p := dsolve({ic, sys}, numeric, method = rosenbrock, output=listprocedure):
alphat := eval(alpha(t),p):
betat := eval(beta(t),p):
gt := eval(g(t),p):
ht := eval(h(t),p):
exp(gt(20.0)), exp(ht(20.0));
-18
5.34759070530497, 3.10201330730572 10
st := time():
P := plots:-odeplot(p, [[t, exp(g(t))], [t, exp(h(t))]], 0 .. 20,
thickness = 2, numpoints = 50, color = [red, blue]):
( time() - st )*`seconds`;
0.031 seconds
P;