Is there some way in which I could plot energy bands using Mathematica in a manner that is given in the image below? I have $E$ as a function of $k_x$ and $k_y$. How can the plot given below be made with these specific points on the $(k_x,k_y)$ axis?

enter image description here

My function for the energy $E$ is:


and I can plot parts of the graph with something like:

Plot[energy[kx,0],{kx,Pi,2 Pi}]

How do I stitch these together?

  • 3
    $\begingroup$ Please add some functions you have defined and code you have tried. $\endgroup$
    – Edmund
    Commented Sep 27, 2018 at 16:23
  • 2
    $\begingroup$ Don't forget to take the tour now and learning about asking and what's on-topic. There you will learn why you should edit your question to show due diligence, give brief context that is meaningful for non-physicist, include minimal working example of code and data in formatted form. By doing all this you help us to help you and likely you will inspire great answers. Not doing that risks getting you question closed as off-topic. $\endgroup$
    – rhermans
    Commented Sep 27, 2018 at 16:42
  • $\begingroup$ I have tried setting ky=0, and then Plot[E[kx,0],{kx,0,Pi}], and I get one branch of that whole graph. Is there a way to concatenate all these parts with one plotting? $\endgroup$
    – Theorist
    Commented Sep 27, 2018 at 16:44
  • 1
    $\begingroup$ Please follow the advise in the comments, it's not fair to ask us to guess your functions and write code you already have. Sharing what you have makes it more likely for somebody to decide to commit effort to solve your problem. You should definitely share your code in formatted form so people can Copy&Paste it. Help us to help you. $\endgroup$
    – rhermans
    Commented Sep 27, 2018 at 16:49
  • $\begingroup$ Give me an hour or two, I have existing code for this, but it needs a little polishing to post. $\endgroup$
    – rcollyer
    Commented Sep 27, 2018 at 17:03

3 Answers 3


Construct an Interpolation function that translates from the $x$-value to the $\{k_x,k_y\}$ coordinates:

xkData = {{0,{Pi,0}},{1,{0,0}},{2,{Pi,-Pi}},{3,{Pi,0}},{4,{2Pi,0}}};
if = Interpolation[xkData, InterpolationOrder->1];

Then, use the above interpolating function to construct the plot, and use xkData again to create the ticks:

    energy @@ if[x],
    {x, 0, 4},
    Frame -> True,
        {xkData, None}
    GridLines->{Range[0,4], None}

enter image description here

  • $\begingroup$ Thank you very much! This is really useful. $\endgroup$
    – Theorist
    Commented Sep 27, 2018 at 17:15
  • $\begingroup$ Can I add some points in specific parts of plot after creating this plot, say I want these points represented as black dots, and for example only in interval from (Pi,0) to (0,0)? $\endgroup$
    – Theorist
    Commented Feb 11, 2019 at 17:01

Compared to my old solution, Carl's is much better. But, there is a subtle flaw in it, and in the original image that the OP posted: the distances between the intervals are not identical. The correct parameterization is to use arc-length. Essentially, we need to Accumulate the arc-length between the points in k-space, as follows:

pts = {{π, 0}, {0, 0}, {π, -π}, {π, 0}, {2 π, 0}};
arcs = {0}~Join~Map[
   Rest@FoldList[Join[#1, {#2}] &, {First @ #}, Rest @ #]& @ pts
(* {0, π, π + Sqrt[2] π, 2 π + Sqrt[2] π, 3 π + Sqrt[2] π} *)

Then, with some modifications, we can adapt the answer:

xkData = Transpose[{arcs, pts}];
if = Interpolation[xkData, InterpolationOrder -> 1];
Plot[energy @@ if[x], {x, arcs[[1]], arcs[[-1]]}, 
  Frame -> True, 
  FrameTicks -> {{Automatic, None}, {xkData, None}}, 
  GridLines -> {arcs, None}

enter image description here

  • 1
    $\begingroup$ The code doesn't seem to work on Mathematica 12, would you consider updating it? $\endgroup$
    – Dwagg
    Commented Jul 21, 2021 at 2:16
  • $\begingroup$ @Dwagg interesting. The original code relied on ArcLength[Line[{{Pi, 0}}]] returning 0. Now it just returns unevaluated. Fixed. $\endgroup$
    – rcollyer
    Commented Jul 21, 2021 at 11:47

There have been some great answers, but I decided to add an alternative, which uses Piecewise and Rescale instead.

kList = {{\[Pi], 0}, {0, 0}, {\[Pi], -\[Pi]}, {\[Pi], 0}, {2 \[Pi], 
xList = Range[0, 4, 1];

mapXToK[x_] := 
   MapThread[{Rescale[x, {#1, #2}, {#3, #4}], x < #2} &, {Most[xList],
      Rest[xList], Most[kList], Rest[kList]}];

energy[kx_, ky_] := Sqrt[1 - (Cos[kx/2] Cos[ky/2])^2];

Plot[energy @@ mapXToK[x], {x, 0, 4}, GridLines -> {xList, None}, 
 FrameTicks -> {Automatic, {Transpose[{xList, kList}], None}}, 
 Frame -> True]

enter image description here

Taking the arc-length length comment into account:

xList = Prepend[
    MapThread[ArcLength[Line[{##}]] &, {Most[kList], Rest[kList]}], 
Plot[energy @@ mapXToK[x], {x, 0, Last[xList]}, 
 GridLines -> {xList, None}, 
 FrameTicks -> {Automatic, {Transpose[{xList, kList}], None}}, 
 Frame -> True]

enter image description here


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