5
$\begingroup$

I am using Mathematica to simulate a simple pendulum. I used the Animate command to create an animation of the pendulum, which runs smootly. But when i run any other Manipulate, Animate or ListAnimate command simultaneously to the first one, both of them become very laggy. My intention was to create a plot that traced the angular displacement of the pendulum at each moment. What i noticed is that this happens also if I run a very simple Manipulate command, even only a slider. What I also noticed is that if I run the two animations on separate Notebooks, they run perfectly, which shows that the problem is not my hardware. Does anyone know why this happens? Thanks in advance.

This is the pendulum animation, which runs smoothly.

Animate[
 Graphics[{},
  (*Epilog*)
  Epilog -> {
    Thickness[0.025], RGBColor[0.38, 0.38, 0.38], 
    Line[{{0, 0}, {l*Sin[sol1[a]], -l*Cos[sol1[a]]}}],
    RGBColor[0., 0.29, 0.22], EdgeForm[{Thickness[Medium], Black}], 
    Disk[{l*Sin[sol1[a]], -l*Cos[sol1[a]]}, 0.07 l],
    White, EdgeForm[{Thin, Black}], Disk[{0, 0}, 0.017 l]
    },
  (*Graphics options*)
  PlotRange -> {{-l - 0.405 l, l + 0.405 l}, {-l - 0.35 l, 
     Which[absmax1 < \[Pi]/2, 0.3 l, \[Pi]/2 < absmax1 < \[Pi], 
      l Sin[absmax1 - \[Pi]/2] + 0.1 l, absmax1 > \[Pi], l + 0.2 l]}},
  Axes -> True,
  AxesStyle -> Arrowheads[Automatic],
  LabelStyle -> {15, Black, FontFamily -> "Kalam Light", Bold},
  AxesOrigin -> {0, 0},
  ImageSize -> 600,
  Frame -> False
  ],
 (*Animate options*)
 {a, 0, 60, Appearance -> "Labeled"},
 RefreshRate -> 144,
 DefaultDuration -> 60,
 AnimationRunning -> False
 ]

This is the second one, which I noticed lags even on its own, I was trying to figure out a way to make it run smoothly, maybe using Dynamics or other methods. ListAnimate works but it takes way too much to execute. I just started using Mathemathica so I am not familiar with it.

Animate[
 Plot[{sol1[t]}, {t, 10^-10, a},
  (*Plot options*)
  ImageSize -> 1000,
  PlotRange -> {{0, 60}, {min1, max1}},
  Axes -> True,
  AxesStyle -> Arrowheads[0.02, 0.02],
  AxesLabel -> {"t", "\[Theta](t)"},
  AxesOrigin -> {0, 0},
  LabelStyle -> {18, Black, FontFamily -> "Kalam Light", Bold},
  Ticks ->  {Automatic, 
    Which[absmax1 >= 11 \[Pi], Range[-60 \[Pi], 60 \[Pi], 2 \[Pi]], 
     15.6 <= absmax1 < 11 \[Pi], Range[-60 \[Pi], 60 \[Pi], \[Pi]], 
     8.3 <= absmax1 < 15.6, Range[-60 \[Pi], 60 \[Pi], \[Pi]/2], 
     2 <= absmax1 < 8.3, Range[-60 \[Pi], 60 \[Pi], \[Pi]/4], 
     absmax1 < 2, Range[-20 \[Pi], 20 \[Pi], \[Pi]/8]]},
  TicksStyle -> 
   Directive[Black, FontFamily -> "Kalam Light", 14, Bold],
  GridLines -> {Automatic, 
    Which[absmax1 > 11 \[Pi], Range[-60 \[Pi], 60 \[Pi], 2 \[Pi]], 
     15.6 < absmax1 < 11 \[Pi], Range[-60 \[Pi], 60 \[Pi], \[Pi]], 
     8.3 < absmax1 < 15.6, Range[-60 \[Pi], 60 \[Pi], \[Pi]/2], 
     2 < absmax1 < 8.3, Range[-60 \[Pi], 60 \[Pi], \[Pi]/4], 
     absmax1 < 2, Range[-20 \[Pi], 20 \[Pi], \[Pi]/8]]},
  GridLinesStyle -> Directive[Dashed, LightGray],
  PlotLabel -> 
   Style[Framed["Angular displacement"], FontFamily -> "Kalam Light", 
    15]
  ],
 (*Animate options*)
 {a, 0, 60},
 Paneled -> False,
 AnimationRunning -> False
 ]

This is the setup code I used.

(*Initial conditions*)
mu := 0.1
cd1 := y[0] == 1
cd2 := y'[0] == 1
l := 8
g := 9.81
(*Differential equation*)
eq = y''[t] == -mu*y'[t] - (g/l)*Sin[y[t]];

sol1 = NDSolveValue[{eq, cd1, cd2}, y, {t, 0, 200}];

max1 = NMaxValue[{sol1[t], 0 < t < 60}, t, Method -> "NelderMead"];
min1 = NMinValue[{sol1[t], 0 < t < 60}, t, Method -> "NelderMead"];
absmax1 = Max[Abs[max1], Abs[min1]];

sol2 = NDSolveValue[{eq, cd1, cd2}, y', {t, 0, 200}];

$\endgroup$
  • $\begingroup$ Could you share the code that generates these animations? $\endgroup$ – MarcoB Jan 14 at 23:10
  • 1
    $\begingroup$ Yes, I've addded the code to my original question. $\endgroup$ – Lorenzo Gentile Jan 14 at 23:44
  • 1
    $\begingroup$ What version/OS are you using? $\endgroup$ – N.J.Evans Jan 15 at 14:04
  • $\begingroup$ I'm running Mathematica 12.0 on windows 10. My CPU is an Intel i5 7600K and my GPU is a GTX1070. $\endgroup$ – Lorenzo Gentile Jan 15 at 14:16
2
$\begingroup$

You should try to use local variables by wrapping all your code for each animation into a DynamicModule. This evoid multiple asigments to variables you are using. For example,

DynamicModule[{here your local variables}
.
.
.
asigments
.
.
.
Animate[
.
.
.]
]

Well, in fact this approach works enough fine

DynamicModule[{mu, cd1, cd2, l, g, eq, sol1, max1, min1, absmax1, 
  sol2},
 (*Initial conditions*)
 mu := 0.1;
 cd1 := y[0] == 1;
 cd2 := y'[0] == 1;
 l := 8;
 g := 9.81;
 (*Differential equation*)
 eq = y''[t] == -mu*y'[t] - (g/l)*Sin[y[t]];

 sol1 = NDSolveValue[{eq, cd1, cd2}, y, {t, 0, 200}];

 max1 = NMaxValue[{sol1[t], 0 < t < 60}, t, Method -> "NelderMead"];
 min1 = NMinValue[{sol1[t], 0 < t < 60}, t, Method -> "NelderMead"];
 absmax1 = Max[Abs[max1], Abs[min1]];

 sol2 = NDSolveValue[{eq, cd1, cd2}, y', {t, 0, 200}];
 Animate[Graphics[{},(*Epilog*)
   Epilog -> {Thickness[0.025], RGBColor[0.38, 0.38, 0.38], 
     Line[{{0, 0}, {l*Sin[sol1[a]], -l*Cos[sol1[a]]}}], 
     RGBColor[0., 0.29, 0.22], EdgeForm[{Thickness[Medium], Black}], 
     Disk[{l*Sin[sol1[a]], -l*Cos[sol1[a]]}, 0.07 l], White, 
     EdgeForm[{Thin, Black}], 
     Disk[{0, 0}, 0.017 l]},(*Graphics options*)
   PlotRange -> {{-l - 0.405 l, l + 0.405 l}, {-l - 0.35 l, 
      Which[absmax1 < \[Pi]/2, 0.3 l, \[Pi]/2 < absmax1 < \[Pi], 
       l Sin[absmax1 - \[Pi]/2] + 0.1 l, absmax1 > \[Pi], 
       l + 0.2 l]}}, Axes -> True, AxesStyle -> Arrowheads[Automatic],
    LabelStyle -> {15, Black, FontFamily -> "Kalam Light", Bold}, 
   AxesOrigin -> {0, 0}, ImageSize -> 600, 
   Frame -> False],(*Animate options*){a, 0, 60, 
   Appearance -> "Labeled"}, RefreshRate -> 144, 
  DefaultDuration -> 60, AnimationRunning -> False]
 ]

DynamicModule[{mu, cd1, cd2, l, g, eq, sol1, max1, min1, absmax1, 
  sol2},
 (*Initial conditions*)mu := 0.1;
 cd1 := y[0] == 1;
 cd2 := y'[0] == 1;
 l := 8;
 g := 9.81;
 (*Differential equation*)
 eq = y''[t] == -mu*y'[t] - (g/l)*Sin[y[t]];

 sol1 = NDSolveValue[{eq, cd1, cd2}, y, {t, 0, 200}];

 max1 = NMaxValue[{sol1[t], 0 < t < 60}, t, Method -> "NelderMead"];
 min1 = NMinValue[{sol1[t], 0 < t < 60}, t, Method -> "NelderMead"];
 absmax1 = Max[Abs[max1], Abs[min1]];
 sol2 = NDSolveValue[{eq, cd1, cd2}, y', {t, 0, 200}];
 Animate[Plot[{sol1[t]}, {t, 10^-10, a},(*Plot options*)
   ImageSize -> 1000, PlotRange -> {{0, 60}, {min1, max1}}, 
   Axes -> True, AxesStyle -> Arrowheads[0.02, 0.02], 
   AxesLabel -> {"t", "\[Theta](t)"}, AxesOrigin -> {0, 0}, 
   LabelStyle -> {18, Black, FontFamily -> "Kalam Light", Bold}, 
   Ticks -> {Automatic, 
     Which[absmax1 >= 11 \[Pi], Range[-60 \[Pi], 60 \[Pi], 2 \[Pi]], 
      15.6 <= absmax1 < 11 \[Pi], Range[-60 \[Pi], 60 \[Pi], \[Pi]], 
      8.3 <= absmax1 < 15.6, Range[-60 \[Pi], 60 \[Pi], \[Pi]/2], 
      2 <= absmax1 < 8.3, Range[-60 \[Pi], 60 \[Pi], \[Pi]/4], 
      absmax1 < 2, Range[-20 \[Pi], 20 \[Pi], \[Pi]/8]]}, 
   TicksStyle -> 
    Directive[Black, FontFamily -> "Kalam Light", 14, Bold], 
   GridLines -> {Automatic, 
     Which[absmax1 > 11 \[Pi], Range[-60 \[Pi], 60 \[Pi], 2 \[Pi]], 
      15.6 < absmax1 < 11 \[Pi], Range[-60 \[Pi], 60 \[Pi], \[Pi]], 
      8.3 < absmax1 < 15.6, Range[-60 \[Pi], 60 \[Pi], \[Pi]/2], 
      2 < absmax1 < 8.3, Range[-60 \[Pi], 60 \[Pi], \[Pi]/4], 
      absmax1 < 2, Range[-20 \[Pi], 20 \[Pi], \[Pi]/8]]}, 
   GridLinesStyle -> Directive[Dashed, LightGray], 
   PlotLabel -> 
    Style[Framed["Angular displacement"], FontFamily -> "Kalam Light",
      15]],(*Animate options*){a, 0, 60}, Paneled -> False, 
  AnimationRunning -> False]
 ]
```
| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ Hi Diego, thank you for the response, but the method you pointed out doesn't seem to make any difference for me. The animations, when run simultaneously, are still very slow and laggy, and also make the whole notebook almost stuck. $\endgroup$ – Lorenzo Gentile Jan 15 at 13:50
  • $\begingroup$ Oh sorry, but that is not so for me. Modularity avoids conflicts on the notebooks. I run the code with DynamicModule and runs in a good way simultaneously. The notebook works very good. $\endgroup$ – DIEGO R. Jan 15 at 14:26
1
$\begingroup$

First of all, your first animation runs fine with or without the second one; however, the second animation is slow even on its own. So this is not a problem of interactions between the two.

Something is making the second animation very very slow. I noticed that, if I remove all the formatting options, your animations run just fine. It is my opinion that your calculations are not the problem, but your formatting might be. You might want to remove all, then add each option back one at a time and see which one is the culprit.


Some things don't make a lot of sense in your code, which I guess may be leftovers from re-purposing this code from another source. For instance:

  • The definitions of the initial conditions do not need to be delayed (:=); a simple Set (=) can be used here.
  • In the first animation, Graphics[{}, Epilog -> ...] does not make much sense. Much more straightforward to use `Graphics[{...}].
  • In the first animation, the Which statement that determines the plot range always resolves to $2.4$, so you might as well simply use that number instead.
  • RefreshRate -> 144 seems excessive; do you really have an output device that supports that refresh rate? Otherwise you might be wasting processing power there.
  • Similarly in the second animation, the Which statements always resolve to a unique value in your conditions; might as well substitute them with their value. For instance you can check that, using your definitions:

    Block[
     {Range = Inactive[Range]},
      Which[
        absmax1 >= 11 π, Range[-60 π, 60 π, 2 π],
        15.6 <= absmax1 < 11 π, Range[-60 π, 60 π, π],
        8.3 <= absmax1 < 15.6, Range[-60 π, 60 π, π/2],
        2 <= absmax1 < 8.3, Range[-60 π, 60 π, π/4],
        absmax1 < 2, Range[-20 π, 20 π, π/8]
     ]
    ]
    
    (* Out: Inactive[Range][-20 π, 20 π, π/8] *)
    

Alternatively, you can use e.g. Table to pre-calculate the plots and ListAnimate to generate the animation from a static list:

first = Table[(*your original code inside the first Animate*), {a, 0, 60}];
second = Table[(*your original code inside the second Animate *), {a, 0, 60}];

Here is for instance the second, very laggy animation:

ListAnimate[second]

animation running

| improve this answer | |
$\endgroup$
  • $\begingroup$ Thanks for the answer Marco. The option that made the second animation slow was the Ticks option. I noticed that if I set the Ticks using a Range command, it always lags, so I set it to Automatic, which doesn't render Pi units on the y-axis, but that's not a problem. The Which command is used to adapt the PlotRange to different starting conditions, in order to simulate different situations. I manually edit the initial values each time. Finally the Epilog is the only way I found to make the pendulum render on top of the axis and ticks. $\endgroup$ – Lorenzo Gentile Jan 15 at 22:01
  • $\begingroup$ However the simultaneity issue is still there. The first animation runs smoothly on its own, but not simultaneously with other animations, even simple ones. I noticed that If I run the two animations (or any number of animation really) on the same notebook, the CPU usage seems locked at 30%, while if I run them in two separate notebooks, they run perfectly and the CPU usage is at 70%. Does this have anything to do with the issue in your opinion? $\endgroup$ – Lorenzo Gentile Jan 15 at 22:09

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.