Mathematica Stack Exchange is a question and answer site for users of Mathematica. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I first do a 3D Plot of four surfaces (eigenvalues of a $4\times4$ matrix) over $kx,kz$ (setting $ky=0$ all along). And then I try to give a 2D plot along three connected particular lines in $kx,kz$-plane, which is simply a tiny part of the 3D one. However, the 2D one turns out to be far slower than the 3D one. Also I use Evaluate in both cases, otherwise a weird mess (Why?). What's wrong with my code? And I'm wondering what the faster code ought to be.

zero2 = DiagonalMatrix[{0, 0}];
I2 = IdentityMatrix[2];
I4 = IdentityMatrix[4];
t = 1/2;
λ = 1;
Subscript[λ, z] = 1;
ϵ = 6 t;
b = {0, 0, 0, 1};

H[kx_, ky_, kz_] := 2 λ KroneckerProduct[PauliMatrix[3], PauliMatrix[1] Sin[ky] - PauliMatrix[2] Sin[kx]] + 2 Subscript[λ, z]   KroneckerProduct[PauliMatrix[2], I2] Sin[kz] + KroneckerProduct[PauliMatrix[1], I2] (ϵ - 2 t (Cos[kx] + Cos[ky] + Cos[kz]));
Subscript[H, 1][kx_, ky_, kz_] := b.{KroneckerProduct[PauliMatrix[2], PauliMatrix[3]], -KroneckerProduct[PauliMatrix[1], PauliMatrix[1]], KroneckerProduct[PauliMatrix[1], PauliMatrix[2]], KroneckerProduct[I2, PauliMatrix[3]]};
Eval[kx_, ky_, kz_] := FullSimplify[Eigenvalues[H[kx, ky, kz] + Subscript[H, 1][kx, ky, kz]]];

Plot3D[Evaluate[Eval[kx, 0, kz]],
  {kx, -π, π}, {kz, -π, π},
  AxesLabel -> Automatic, PlotLegends -> "Placeholder"

a0 = 1;
b1 = 2 π/a0; 
b2 = 2 π/a0; 
b3 = 2 π/a0; 
BZKx = b1/2; 
BZKz = b3/2;
Plot[Evaluate@Eval[If[k <= 0, k/Sqrt[2], If[k <= BZKx, 0, BZKx]], 0, If[k <= 0, k/Sqrt[2], If[k <= BZKx, k, k - BZKx]]],
  {k, -Sqrt[2] BZKx, 2 BZKx},
  ImageMargins -> 0, PlotStyle -> Thickness[.01]

The 3D oneThe 2D one

share|improve this question
just out of curiosity: is this a band structure of some topological insulator? – hat Feb 11 at 9:33
@hat That's right! – huotuichang Feb 11 at 9:53
up vote 18 down vote accepted

You seem to be re-evaluating the eigenvalues at every point. Just use this definition:

Clear[Eval,kx, ky, kz];
Eval[kx_, ky_, kz_] = 
   Eigenvalues[H[kx, ky, kz] + Subscript[H, 1][kx, ky, kz]]];

Then the plots will be faster. This will symbolically evaluate the eigenvalues once, and the variables kx, ky, kz get substituted into the symbolic result when needed.

Regarding the need for Evaluate mentioned in the question, it's needed because Plot has attribute HoldAll as explained here.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.