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!

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


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):

enter image description here

Original post

Here's one way to go about this that directly generalizes your code.

data[W_, q_, {xmin_, xmax_, dx_}, {ymin_, ymax_, dy_}] := Transpose[
    {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:

enter image description here

  • $\begingroup$ 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. $\endgroup$ Jul 3 '15 at 20:46
  • $\begingroup$ @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.) $\endgroup$
    – march
    Jul 3 '15 at 22:06
  • $\begingroup$ 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! $\endgroup$ Jul 3 '15 at 22:17
  • $\begingroup$ @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. $\endgroup$
    – march
    Jul 3 '15 at 22:24

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.