Increasing Plot3D speed when plotted function is Eigenvalue

This is probably a really simple fix, but I'm fairly new to Mathematica and am not sure how to do this properly. I know that trying to plot eigenvalues directly can be computationally expensive, so I'm trying to create a variable that makes a thread which allows me to plot things more quickly. I've been successful in doing so for a single variable in the following way

data[W_, q_, {xmin_, xmax_, dx_}] := Thread[Table[
({x, #} &)  /@ Sort[ Eigenvalues[Energies[x, q, W]] ],
{x, xmin, xmax, dx}]];


but am not sure how I'd do it when I want to plot over an x and y component so that it is 3 dimensional. What sort of syntax would one use for this? Thank you very much!

• Do you mean ListPlot3D? It seems like you are making a table of the eigenvalues rather than plotting continuous functions. – march Jul 3 '15 at 2:37

Update

It might be worthwhile just specifying PlotPoints. For instance, if we use

Energies[_, _, x_, y_] := SparseArray[
{Band[{1, 2}] -> Cos[x] Sin[y], Band[{2, 1}] -> Cos[x] Sin[y]}
, {3, 3}]


as our set of test-matrices, then

Plot3D[Evaluate @ Sort @ Eigenvalues @ Energies[W, q, x, y]
, {x, 0, 1}, {y, 0, 1}
, PlotPoints -> 10]


yields (much faster than generating the set of points, I might add):

Original post

data[W_, q_, {xmin_, xmax_, dx_}, {ymin_, ymax_, dy_}] := Transpose[
Flatten[
Table[
{x, y, #} & /@ Sort[Eigenvalues[Energies[W, q, x, y]]]
, {x, xmin, xmax, dx}
, {y, ymin, ymax, dy}]
, {1, 2}]
, {2, 1}]


The Flatten is necessary in order to change the 2D list of one "sheet" of eigenvalues into a 1D list over all choices of x and y, and the Transpose is necessary in order to make the output a list of the different "sheets" of eigenvalues. (By the way, if I've interpreted things correctly, you could have replaced Thread with Transpose in your code, although there doesn't seem to be any speed gain.)

To test this, we define 3 by 3 test matrices:

Energies[_, _, x_, y_] := RandomReal[{-x, y}, {3, 3}]


and call the function as

data1[W, q, {0, 1, 0.05}, {-3, 3, 0.1}]


This is the proper format for ListPlot3D, so if we call

ListPlot3D[ data1[W, q, {0, 1, 0.05}, {-3, 3, 0.1}] ]


we get, for example, the following figure:

• Thanks, that's very helpful! One followup question though. If my eigenvalues are actually continuous functions in x and y, is there a way to make this work with Plot3D? To get the plots looking like they did with Plot3D, I need to make dx and dy in the order of .005 and this sacrifices a lot of the speed gain. – Chris Thomas Jul 3 '15 at 20:46
• @ChrisThomas. You could start perhaps by specifying PlotPoints. My examples evaluate pretty fast. What is the size of your matrices and how complicated are the entries? The speed-up might happen there instead. (Also, see the updated answer.) – march Jul 3 '15 at 22:06
• The matrices are 4x4 block-diagonal but the entries are somewhat complicated since they are complex exponential tight-binding parameters. The reason I needed a bit of a speedup is the fact that in order to see the points where the two sheets meet you need quite a large number of plot points (or else it looks like it's got a fairly sizable gap.) I will try the updated answer and see if it works better! – Chris Thomas Jul 3 '15 at 22:17
• @ChrisThomas. If you need more resolution near certain points (or curves), [mathematica.stackexchange.com/questions/10414/… question and answer) and [mathematica.stackexchange.com/questions/56236/… question and answer) might be helpful. Alternatively, you can use ListPlot3D and increase the resolution only near the special points. – march Jul 3 '15 at 22:24