# Energy band plotting [duplicate]

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?

My function for the energy $$E$$ is:

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


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

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


How do I stitch these together?

• Please add some functions you have defined and code you have tried. Commented Sep 27, 2018 at 16:23
• 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. Commented Sep 27, 2018 at 16:42
• 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? Commented Sep 27, 2018 at 16:44
• Give me an hour or two, I have existing code for this, but it needs a little polishing to post. Commented Sep 27, 2018 at 17:03

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:

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


• Thank you very much! This is really useful. Commented Sep 27, 2018 at 17:15
• 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)? 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[
ArcLength[Line[#]]&,
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}
]


• The code doesn't seem to work on Mathematica 12, would you consider updating it? Commented Jul 21, 2021 at 2:16
• @Dwagg interesting. The original code relied on ArcLength[Line[{{Pi, 0}}]] returning 0. Now it just returns unevaluated. Fixed. 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],
0}};
xList = Range[0, 4, 1];

mapXToK[x_] :=
Piecewise@
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]


Taking the arc-length length comment into account:

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