Use NSolve
and make the vars argument z
instead of 10
and you'll notice a big improvement in performance, especially when roots
is large.
Manipulate[
ListPlot[{Re@z, Im@z} /. NSolve[BernoulliB[roots, z] == 0, z],
PlotRange -> {{-10, 10}, {-10, 10}}],
{roots, 1, 100, 1}]
I got rid of the global variable sol
because there are issues with having global variables in a Manipulate
. Those issues can be managed, but when possible, localize variables. If you need sol
to use in multiple places, then With
or Module
is an appropriate way to localize a temporary variable. With
may be replaced by Module
if sol
needs to change its value several times during a single update.
Manipulate[
With[{sol = NSolve[BernoulliB[roots, z] == 0, z]},
ListPlot[{Re@z, Im@z} /. sol, PlotRange -> {{-10, 10}, {-10, 10}}]
],
{roots, 1, 100, 1}]
In some cases, it is better to localize a variable in the DynamicModule
constructed by Manipulate
. This can be done by specifying the control type None
(see this answer for some discussion):
Manipulate[
sol = NSolve[BernoulliB[roots, z] == 0, z];
ListPlot[{Re@z, Im@z} /. sol, PlotRange -> {{-10, 10}, {-10, 10}}],
{roots, 1, 100, 1}, {sol, None},
TrackedSymbols :> {roots}]
We have to use TrackedSymbols
or Manipulate
will update twice for each change in roots
: once when roots
changes value and another time when sol
changes value. When With
above is not appropriate, this tends to be my favorite way, although in this particular example, using Module
instead of With
is just as good.