6
$\begingroup$

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

$\endgroup$

3 Answers 3

7
$\begingroup$

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.}}}  *)
$\endgroup$
8
  • $\begingroup$ +1 Ahhh! Is there any way to make it draw without smoothing then? It's so misleading the way it draws it... $\endgroup$
    – user541686
    Commented Feb 15, 2016 at 2:41
  • $\begingroup$ @Mehrdad Oops, made a mistake editing the comment. Try sol1 = Interpolation[Table[{t, sol}, {t, Flatten[sol /. t -> "Grid"]}], InterpolationOrder -> 1]. $\endgroup$
    – Michael E2
    Commented Feb 15, 2016 at 2:57
  • $\begingroup$ 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]. $\endgroup$
    – user541686
    Commented Feb 15, 2016 at 3:03
  • $\begingroup$ 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]}). $\endgroup$
    – user541686
    Commented Feb 15, 2016 at 3:06
  • 1
    $\begingroup$ @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). $\endgroup$
    – Michael E2
    Commented Feb 15, 2016 at 21:21
2
$\begingroup$

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]
$\endgroup$
0
$\begingroup$

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]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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