Использование решения дифференциального уравнения в двух отдельных командах построения в Mathematica - PullRequest
6 голосов
/ 25 августа 2009

Я столкнулся с проблемой при попытке использовать ответ из 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[{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 .

Извините, если раньше не было ясно.

Ответы [ 2 ]

8 голосов
/ 25 августа 2009

Ваша проблема в том, что 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 выполняет замену только один раз, а не один раз для каждой точки графика. Для такой простой замены правил это не важно, но это хорошая привычка использовать ее на тот случай, если вы захотите построить что-то более сложное.


Для того, чтобы сделать эту работу в Манипуляции, простой способ состоит в использовании 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; в противном случае вещи будут безобразно прыгать по мере изменения стоимости. Когда вы делаете более сложные вещи с помощью Manipulate, есть ряд опций для контроля скорости обновлений, которые могут быть важны, если ваш ODE достаточно сложен, и его решение занимает некоторое время.

2 голосов
/ 26 августа 2009

Тем временем я нашел другой способ сделать это. Это менее элегантно, но в нем используется только одна замена, поэтому я решил опубликовать ее здесь.

Идея состоит в том, чтобы использовать Удерживать на графике , чтобы он не оценивался, выполнить подстановку правил и затем 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}]
...