在 Mathematica 中的两个单独的绘图命令中使用微分方程的解

发布于 2024-08-03 01:06:54 字数 859 浏览 5 评论 0原文

我在尝试在两个单独的绘图命令中使用 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

抱歉,如果之前不清楚。

I've encountered a problem while trying to use the answer from a NDSolve in two separate plot commands. To illustrate the problem, I'll use a simple differential equation and only one plot command. If I write something like this:

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

It solves the equation and calculates x[4] with no problem, but the plot turns empty, and I have no idea why.

In my actual problem, my equation is a quite complicated system for several functions, and instead of x[4] I draw a parametric plot of the solved functions. I ultimately intend to include all this in a Manipulate statement so I don't want the NDSolve statement to appear more than once (takes too long) and I can't just calculate it in advance (since it has a lot of parameters).


Edit: I would like to clarify and expand my question: What I actually want to do is to include my plotting statement in a Manipulate statement in the following way:

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}]

Since only the Manipulate statement gives value to the parameter a, I can't calculate the answer to the NDSolve beforehand. Also, since my actual equation system is very complicated and non-linear, I can't use the symbolic function DSolve.

Sorry if it wasn't clear before.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

哎呦我呸! 2024-08-10 01:06:54

你的问题是 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} 

图中的 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 足够复杂以至于需要一段时间才能求解,那么这可能很重要。

Your problem is that Plot[] does some funny things to make plotting more convenient, and one of the things it does is just not plot things it can't evaluate numerically. So in the expression you posted,

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

just goes ahead and evaluates before doing the rule substitution with the solution from NDSolve, producing a graphics object of an empty plot. That graphics object contains no reference to x, so there's nothing to substitute for.

You want to make sure the substitution is done before the plotting. If you also want to make sure the substitution can be done in multiple places, you want to store the solution into a variable.

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

The Evaluate[] in the Plot makes sure that Mathematica only does the substitution once, instead of once for each plot point. It's not important for a simple rule substitution like this, but it's a good habit to use it in case you ever want to plot something more complicated.


In order to make this work in a Manipulate, the simple way is to use With[], which is one of Mathematica's scoping constructs; it's the one to use where you just want to substitute something in without using it as variable you can mutate.

For example,

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}}]

Use the PlotRange option to keep the y-axis fixed; otherwise things will jump around in an ugly way as the value of a changes. When you do more complex things with Manipulate, there are a number of options for controlling the speed of updates, which can be important if your ODE is complicated enough that it takes a while to solve.

空袭的梦i 2024-08-10 01:06:54

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

这个想法是在Plot上使用Hold,这样它就不会被评估,进行规则替换,然后ReleaseHold,就在<强>操纵。

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}]

Meanwhile, I found another way to do this. It's less elegant, but it only uses one substitution so I've thought I'll post it here also.

The idea is to use Hold on the Plot so it wouldn't get evaluated, do the rule substitution and then ReleaseHold, just before the 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}]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文