# Plot with different colors the results of an NDSolve with vector solution

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]


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:

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?

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


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

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]


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.

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


• 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
– glS
Commented Jul 30, 2018 at 17:30
• 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
– glS
Commented Jul 30, 2018 at 17:36
• @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]] Commented Jul 30, 2018 at 17:43