3
$\begingroup$

Again I have question I hope someone can answer. I made a very simple example illustrating my more difficult problem.

I want to solve a differential equation numerically with a conditional in the equation depending on a dataset. Mathematica does not give an error but never evaluates my conditional to true. When I try the same thing with a function in the conditional instead of an InterpolatingFunction it does work. What am I doing wrong?

datafunc = Interpolation[{{0, 0}, {5, 0}, {6, 2}, {10, 0}, {15, 1}, {21, 1}}, InterpolationOrder -> 0];
Plot[datafunc[t], {t, 0, 21}]

enter image description here

solvefunc = NDSolve[{D[f[t], t] == Piecewise[{{7, datafunc[t] > 0.}}, -5], f[0] == 0}, f[t], {t, 0, 20}];
output[t_] := Evaluate[f[t] /. solvefunc];

Plot[output[t], {t, 0, 20}]

enter image description here

As you see the result only takes evaluates the -5 part.

However when I take a function instead of the Interpolating function, it does seem to work.

testfunc[t_] := Sin[t]
solvetest = NDSolve[{D[f[t], t] == Piecewise[{{7, testfunc[t] > 0.}}, -5], f[0] == 0}, f[t], {t, 0, 20}];
outputtest[t_] := Evaluate[f[t] /. solvetest];
Plot[outputtest[t], {t, 0, 20}]

enter image description here

Can someone explain me the difference between the two. And why the first example does not work?

Edit: I noticed now that when I start the interpolating function with a number >0. It does work for the first switch. But then when it changes back to 0 again it does not.

datafunc1 = Interpolation[{{0, 1}, {5, 1}, {6, 2}, {10, 0}, {15, 0}, {21, 1}}, InterpolationOrder -> 0]; 
solvefunc1 = NDSolve[{D[f[t], t] == Piecewise[{{7, datafunc1[t] > 0.}}, -5], f[0] == 0}, f[t], {t, 0, 20}] 
output1[t_] := Evaluate[f[t] /. solvefunc1]; 
Plot[output1[t], {t, 0, 20}]

enter image description here

$\endgroup$
2
  • $\begingroup$ Very odd, considering that directly plugging in the equivalent Piecewise[{{2, 5 < x <= 6}, {1, 10 < x <= 21}}] works. But here is something interesting: if you do datafunc[x_?NumericQ] := Piecewise[{{2, 5 < x <= 6}, {1, 10 < x <= 21}}], then you get the same result as using Interpolation[]. I guess you might need to reformulate this in terms of WhenEvent[]. $\endgroup$ Mar 17, 2016 at 9:46
  • $\begingroup$ Thanks for your idea. The problem is that for my "real" problem, the interpolating function is a list of daily data over a year. That's why I change it into an interpolating function instead of plugging in piecewise directly. Do you have an idea how to work around that? $\endgroup$
    – Wiebe
    Mar 17, 2016 at 10:26

1 Answer 1

4
$\begingroup$

Encapsulating the right-hand side in a NumericQ-protected function and setting the MaxStepSize to 1 seems to work for me:

df[t_?NumericQ] := Piecewise[{{7, datafunc[t] > 0.}, {-5, datafunc[t] <= 0.}}];
solvefunc = NDSolve[{D[f[t], t] == df[t], f[0] == 0}, f[t], {t, 0, 20}, MaxStepSize -> 1];
output[t_] := Evaluate[f[t] /. solvefunc];
$\endgroup$
2
  • $\begingroup$ This seems to work, indeed. Still do not get why my code did not work. But I am happy with this solution! Thanks $\endgroup$
    – Wiebe
    Mar 17, 2016 at 16:32
  • $\begingroup$ Glad it helps. We'll need a real M guru to weigh in on the why & why not question! $\endgroup$
    – Chris K
    Mar 17, 2016 at 17:18

Your Answer

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

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