6

我在尝试在两个单独的绘图命令中使用NDSolve的答案时遇到了问题。为了说明这个问题,我将使用一个简单的微分方程和一个绘图命令。如果我写这样的东西:

{Plot[x[t], {t, 0, 10}], x[4]} 
/. NDSolve[{x'[s] == - x[s], x[0] == 1}, x, {s, 0, 10}]

它求解方程并计算 x[4] 没有问题,但情节变空,我不知道为什么。

在我的实际问题中,我的方程是一个包含多个函数的相当复杂的系统,而不是x[4],我绘制了已求解函数的参数图。我最终打算将所有这些都包含在Manipulate语句中,因此我不希望NDSolve语句出现多次(花费太长时间)并且我不能只提前计算它(因为它有很多参数)。


编辑:我想澄清和扩展我的问题:我真正想做的是通过以下方式将我的绘图语句包含在Manipulate语句中:

Manipulate[{Plot[x[t], {t, 0, 10}], x[4]} 
/. NDSolve[{x'[s] == - a*x[s], x[0] == 1}, x, {s, 0, 10}]
,{{a,1},0,5}]

因为只有Manipulate语句给参数a赋值,所以我不能事先计算NDSolve的答案。另外,由于我的实际方程系统非常复杂且非线性,我不能使用符号函数DSolve

抱歉,如果之前不清楚。

4

2 回答 2

9

您的问题是 Plot[] 做了一些有趣的事情以使绘图更方便,而它所做的其中一件事就是不绘制无法以数字方式评估的事物。所以在你发布的表情中,

Plot[x[t], {t, 0, 10}]

在使用 NDSolve 的解进行规则替换之前继续进行评估,生成一个空图的图形对象。该图形对象不包含对 x 的引用,因此没有什么可以替代的。

您要确保在绘图之前完成替换。如果您还想确保可以在多个位置进行替换,则需要将解决方案存储到变量中。

sol = NDSolve[{x'[s] == - x[s], x[0] == 1}, x, {s, 0, 10}];
{Plot[Evaluate[x[t] /. sol], {t, 0, 10}], x[4] /. sol} 

Plot 中的 Evaluate[] 确保 Mathematica 只进行一次替换,而不是对每个绘图点进行一次替换。像这样的简单规则替换并不重要,但如果你想绘制更复杂的东西,使用它是一个好习惯。


为了在 Manipulate 中完成这项工作,简单的方法是使用 With[],这是 Mathematica 的作用域构造之一;它是用于您只想替换某些东西而不将其用作可以变异的变量的地方。

例如,

Manipulate[
  With[{sol = NDSolve[{x'[s] == - x[s], x[0] == 1}, x, {s, 0, 10}]},
    {Plot[x[t] /. sol // Evaluate, {t, 0, 10}, PlotRange -> {0, 1}], 
     x[4] /. sol}],
  {{a, 1}, {0, 5}}]

使用 PlotRange 选项保持 y 轴固定;否则,随着 a 值的变化,事情会以一种丑陋的方式跳跃。当您使用 Manipulate 执行更复杂的事情时,有许多选项可用于控制更新速度,如果您的 ODE 足够复杂以至于需要一段时间才能解决,这可能很重要。

于 2009-08-25T12:44:26.563 回答
2

与此同时,我找到了另一种方法来做到这一点。它不那么优雅,但它只使用了一个替换,所以我想我也会在这里发布它。

这个想法是在Plot上使用Hold ,这样它就不会被评估,做规则替换,然后ReleaseHold,就在Manipulate之前。

Manipulate[ReleaseHold[
  Hold[ {Plot[x[t], {t, 0, 10}, PlotRange -> {0, 1}], x[4]} ]
 /.NDSolve[{x'[s] == -a x[s], x[0] == 1}, x, {s, 0, 10}]
], {{a, 1}, 0, 5}]
于 2009-08-26T09:23:24.603 回答