6

Why do I get a smooth curve (that is obviously wrong) when I run this?

Plot[
 Evaluate[
  NDSolveValue[{x'[t] == -x[t], x[0] == 1}, {x[t]}, {t, 0, 1}, 
   StartingStepSize -> 1, Method -> {"FixedStep", Method -> "ExplicitEuler"}]],
 {t, 0, 1},
 PlotRange -> All]

Shouldn't I just get back a straight line connecting (0, 1) to (1, 0)?!

How do I make Mathematica just do a plain classic Forward Euler?! I don't want fancy smoothing...

Michael E2
  • 235,386
  • 17
  • 334
  • 747
user541686
  • 1,317
  • 7
  • 18

3 Answers3

7

You have to set MaxStepFraction, too, say, to 1.

Plot[
 Evaluate[
  NDSolveValue[{x'[t] == -x[t], x[0] == 1}, {x[t]}, {t, 0, 1}, 
   StartingStepSize -> 1, Method -> {"FixedStep", Method -> "ExplicitEuler"},
   MaxStepFraction -> 1]],
 {t, 0, 1},
 PlotRange -> All]

Mathematica graphics

It's not a straight line because the value of the derivatives are stored & used in the InterpolatingFunction solution. However, we can see there are only two points.

sol /. t -> "Grid"
(*  {{{0.}, {1.}}}  *)
Michael E2
  • 235,386
  • 17
  • 334
  • 747
  • +1 Ahhh! Is there any way to make it draw without smoothing then? It's so misleading the way it draws it... – user541686 Feb 15 '16 at 02:41
  • @Mehrdad Oops, made a mistake editing the comment. Try sol1 = Interpolation[Table[{t, sol}, {t, Flatten[sol /. t -> "Grid"]}], InterpolationOrder -> 1]. – Michael E2 Feb 15 '16 at 02:57
  • Awesome, got it! It ended up being sol = Evaluate[ NDSolveValue[{x'[t] == -x[t], x[0] == 1}, x[t], {t, 0, 1}, StartingStepSize -> 1, MaxStepFraction -> 1, Method -> {"FixedStep", Method -> "ExplicitEuler"}]]; sol = Interpolation[Table[{t, sol}, {t, Flatten[sol /. t -> "Grid"]}], InterpolationOrder -> 1][t]; Plot[sol, {t, 0, 1}, PlotRange -> All]. – user541686 Feb 15 '16 at 03:03
  • PS, this might be more painful but for future reference it might be nice to add how to do it if we're solving for multiple values (e.g. {x[t], x'[t]}). – user541686 Feb 15 '16 at 03:06
  • @Mehrdad I'm not sure what you mean, actually. But, one can plot a linear interpolation with ListLinePlot[sol = NDSolveValue[{x'[t] == -x[t], x[0] == 1}, x, {t, 0, 1}, StartingStepSize -> 1, Method -> {"FixedStep", Method -> "ExplicitEuler"}, MaxStepFraction -> 1]], even though sol is still order 3. ListPlot and ListLinePlot show only the steps, or interpolated points, in an InterpolatingFunction. – Michael E2 Feb 15 '16 at 03:30
  • Oh, I meant what if I want to plot something like NDSolveValue[{x'[t] == -x[t], x[0] == 1}, {x[t], x'[t]}, {t, 0, 1}]? Then Flatten will do the wrong thing. – user541686 Feb 15 '16 at 03:54
  • @MichaelE2 The simplest way to go about this would be to set the InterpolationOrder -> 1 option in NDSolve. Apparetnly this is ignored and InterpolatingFunction is of order 3... – mmal Feb 15 '16 at 14:05
  • 1
    @mmal Yes, I tried that. InterpolationOrder -> 0 generates an error; everything else seems ignored. InterpolationOrder -> All is the only setting shown in the docs, and it seems to do something rather interesting (too long for a comment). – Michael E2 Feb 15 '16 at 21:21
2

I would suggest (as an alternative) the following

pointsAndValues[x_InterpolatingFunction] :=
  Transpose[{First[x["Coordinates"]], x["ValuesOnGrid"]}];

ListPlot[
  pointsAndValues@
    First@NDSolveValue[{x'[t] == -x[t], x[0] == 1}, {x}, {t, 0, 3}, 
      StartingStepSize -> 1, 
      Method -> {"FixedStep", Method -> "ExplicitEuler"}, 
      MaxStepFraction -> 1], Joined -> True, PlotMarkers -> Automatic]

And to check the convergence use e.g.

ListPlot[pointsAndValues@
  First@NDSolveValue[{x'[t] == -x[t], x[0] == 1}, {x}, {t, 0, 2}, 
    StartingStepSize -> 1/#, 
    Method -> {"FixedStep", Method -> "ExplicitEuler"}, 
    MaxStepFraction -> 1] & /@ {1, 2, 4, 16}, Joined -> True, 
 PlotMarkers -> Automatic]
mmal
  • 3,508
  • 2
  • 18
  • 38
0

Here's a more polished version of the currently accepted answer:

Reinterpolate[interpolation_, args___] := 
  Interpolation[
   Transpose[
    Append[Transpose[interpolation["Grid"]], 
     interpolation["ValuesOnGrid"]]], args];
ReinterpolateAll[expr_, args___] := 
  expr /. {InterpolatingFunction[params___] :> 
     Reinterpolate[InterpolatingFunction[params], args]};
sol = NDSolveValue[{x'[t] == -x[t], x[0] == 10}, x[t], {t, 0, 1}, 
   StartingStepSize -> 1/3, MaxStepFraction -> 1, 
   Method -> {"FixedStep", Method -> "ExplicitEuler"}];
Plot[Evaluate[ReinterpolateAll[sol, InterpolationOrder -> 1]], {t, 0, 1}, PlotRange -> All]
user541686
  • 1,317
  • 7
  • 18