Message Boards Message Boards

0
|
4031 Views
|
2 Replies
|
2 Total Likes
View groups...
Share
Share this post:

Avoid issue while using Mod[] in NDSolve[]?

Posted 5 years ago

Let us assume a simple rotation motion, when angular acceleration az somewhat depends on angle Phi[t] and set as linear interpolation function in range of 0..360 degrees. To not come out from interpolation range let angle Phi to be truncated to proper range by Mod[Phi][t], 360]:

az = Interpolation[{{0., 1.}, {90., 4}, {180., 7.}, {270., 4.}, {360.,
      1.}}, InterpolationOrder -> 1];

{\[Omega]s, \[CurlyPhi]s} = NDSolveValue[{

   \!\(
\*SubscriptBox[\(\[PartialD]\), \(t\)]\ \(\[Omega][
      t]\)\) == (az[Mod[\[CurlyPhi][t], 360]] + 10000),
   \!\(
\*SubscriptBox[\(\[PartialD]\), \(t\)]\ \(\[CurlyPhi][
      t]\)\) == \[Omega][t],

   \[CurlyPhi][0] == 359, \[Omega][0] == 
    390 }, {\[Omega], \[CurlyPhi]}, {t, 0, 0.0029}]

Let run it, and we get

InterpolatingFunction::dmval: Input value {360.052} lies outside the range of data in the interpolating function. Extrapolation will be used.

This is quite weird result - we have truncate phi by 360 and got 360.0520876770316`

Adding

EvaluationMonitor :> 
 Print[t, "  ", \[CurlyPhi][t], "  ", Mod[\[CurlyPhi][t], 360]]

Gives list like

...
0.00203059  359.813  359.813
0.00232059  359.932  359.932
InterpolatingFunction::dmval: Input value {360.052} lies outside the range of data in the interpolating function. Extrapolation will be used.
0.0026103  360.052  0.0520877
0.00248493  360.  360.
0.00248493  360.  0.
0.00248493  360.  0.
0.00248493  360.  2.19102*10^-6

Mod[] works fine in the EvaluationMonitor, but fails in main NDSolve loop.

Can anyone tell the reason of such behavior and how to fix it?

POSTED BY: Maksym Snegirev
2 Replies

I still wonder why Mod[] gives wrong result.

POSTED BY: Maksym Snegirev
Posted 5 years ago

Likely, this is just a toy problem you have given, and your actual problem is more complicated. But for this simple case, you could have just built a periodic interpolant at the outset, so you wouldn't need Mod[]:

az = Interpolation[{{0., 1.}, {90., 4}, {180., 7.}, {270., 4.}, {360., 1.}},
                   InterpolationOrder -> 1, PeriodicInterpolation -> True];

From here, we can easily simplify your NDSolve[] call:

?s = NDSolveValue[{?''[t] == az[?[t]] + 10000, ?[0] == 359, ?'[0] == 390},
                  ?, {t, 0, 0.0029}];

Note that you don't need to convert to a system of first order equations; NDSolve[] is perfectly capable of handling high-order derivatives directly. From there, you can just evaluate ?s = ?s' if you still need the derivative as a separate function.

POSTED BY: J. M.
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract