2
$\begingroup$

Consider the following toy example:

sol = NDSolve[{ x'[t] == {-1, -2} x[t], x[0] == {2, 2} }, x, {t, 0, 4} ]; Plot[x[t] /. sol, {t, 0, 4}, PlotRange -> All] 

enter image description here

As seen above, both plots are drawn in the same colour.

The usual trick of adding Evaluate does not work here, I guess because x[t] /. sol evaluates to a list with a single element:

enter image description here

and it's the InterpolatingFunction that later evaluates to a list.

Manually specifying the PlotStyle also doesn't seem to work.

How can I ensure that the different plots are assigned different colours/styles?

$\endgroup$

4 Answers 4

2
$\begingroup$

I would use Indexed:

sol = NDSolveValue[ {x'[t] == {-1, -2} x[t], x[0] == {2, 2}}, x, {t, 0, 4} ]; Plot[Evaluate @ Table[Indexed[sol[t], i], {i,2}], {t, 0, 4}] 

enter image description here

$\endgroup$
3
$\begingroup$

I just found that this is covered in this answer, which I previously missed.

The trick is to use ListLinePlot, which seems handle InterpolatingFunctions better:

sol = NDSolve[{ x'[t] == {-1, -2} x[t], x[0] == {2, 2} }, x, {t, 0, 4} ]; ListLinePlot[x /. First@sol // Flatten] 

gives

enter image description here

$\endgroup$
3
$\begingroup$

If Plot is necessary, the only solution in my mind is rebuilding the InterpolatingFunction. I've modified the definition of ODE a bit because x'[t] == {-1, -2} x[t] is not valid in v9.0.1.

Clear@times; times[a_, b_?VectorQ] := a b (* Alternatively: *) (* times = Compile[{{a, _Real, 1}, {b, _Real, 1}}, a b, RuntimeOptions -> EvaluateSymbolically -> False] *) sol = NDSolveValue[{x'[t] == {-1, -2}~times~x[t], x[0] == {2, 2}}, x, {t, 0, 4}] sollst = ListInterpolation[#, sol[Coordinates][[1]]] & /@ Transpose@sol[ValuesOnGrid] Plot[sollst[t] // Through // Evaluate, {t, 0, 4}, PlotRange -> All] 

Mathematica graphics


OK, I happened to recall another solution. We can modify the Graphics instead:

i = 1; Plot[sol[t], {t, 0, 4}, PlotRange -> All] /. Line[a_] :> Sequence[ColorData[1][i++], Line@a] 

But this solution is somewhat hard to control if you need deeper customization for the style.

$\endgroup$
3
$\begingroup$
Clear[sol] sol[t_] = x[t] /. NDSolve[{x'[t] == {-1, -2} x[t], x[0] == {2, 2}}, x, {t, 0, 4}][[1]]; Plot[{sol[t][[1]], sol[t][[2]]}, {t, 0, 4}, PlotRange -> All, PlotLegends -> Placed[Automatic, {0.5, 0.5}]] 

enter image description here

$\endgroup$
3
  • $\begingroup$ What if the number of elements of the solution array is not known a priori? Replacing the first argument of plot with something like sol[t][[#]]&/@Range@10 does not work, while Evaluate[sol[t][[#]]&/@Range@10] throws an error because tmp[t] is not a list when t is unevaluated $\endgroup$ Commented Jul 30, 2018 at 17:30
  • $\begingroup$ ok I think I found the solution to that, leveraging the fact that Plot can handle held arguments: something like Evaluate[Hold[tmp[t][[#]]] & /@ Range@10] works $\endgroup$ Commented Jul 30, 2018 at 17:36
  • 1
    $\begingroup$ @glS - If the number of elements is not unknown a priori then you would need to calculate the Range argument on the fly, i.e., Evaluate[Hold[sol[t][[#]]] & /@ Range@Length@sol[1]] $\endgroup$ Commented Jul 30, 2018 at 17:43

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.