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$
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

| improve this answer | |
$\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

| improve this answer | |
$\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.

| improve this answer | |
$\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

| improve this answer | |
$\endgroup$
  • $\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$ – glS Jul 30 '18 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$ – glS Jul 30 '18 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$ – Bob Hanlon Jul 30 '18 at 17:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.