Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix BandsData issue related to the k-points labels #2492

Merged
merged 3 commits into from
Feb 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions aiida/orm/data/array/bands.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,12 @@ def _get_bandplot_data(self, cartesian, prettify_format=None, join_symbol=None,
plot_info['paths'] = []

if len(labels) > 1:
# I add an empty label that points to the first band if the first label does not do it
if labels[0][0] != 0:
labels.insert(0, (0, ''))
# I add an empty label that points to the last band if the last label does not do it
if labels[-1][0] != len(bands)-1 :
labels.append((len(bands)-1, ''))
for (position_from, label_from), (position_to, label_to) in zip(labels[:-1], labels[1:]):
if position_to - position_from > 1:
# Create a new path line only if there are at least two points,
Expand Down Expand Up @@ -801,10 +807,13 @@ def _matplotlib_get_dict(self, main_file_name="", comments=True, title="", legen

bands = plot_info['y']
x = plot_info['x']
the_bands = numpy.transpose(bands)
labels = plot_info['labels']
# prepare xticks labels
tick_pos, tick_labels = zip(*labels)
if labels:
tick_pos, tick_labels = zip(*labels)
else:
tick_pos = []
tick_labels = []

#all_data['bands'] = the_bands.tolist()
all_data['paths'] = plot_info['paths']
Expand Down
Binary file added docs/source/datatypes/bands.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
116 changes: 116 additions & 0 deletions docs/source/datatypes/bands.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
.. _bands:

BandsData
=========

``BandsData`` object is dedicated to store bands object of different types
(electronic bands, phonons). In this section we describe the usage of the
``BandsData`` to store the (part of) electronic band structure of silicon
and some logic behind its methods.

To start working with ``BandsData`` we should import it using the
``DataFactory`` and create an object of type ``BandsData``::

from aiida.orm import DataFactory
BandsData = DataFactory('array.bands')
bs = BandsData()

To import the bands we need to make sure to have two arrays: one
containing kpoints and another containing bands. The shape of the kpoints object
should be ``nkpoints * 3``, while the shape of the bands should be
``nkpoints * nstates``. Let's assume the number of kpoints is 12, and the number
of states is 5. So the kpoints and the bands array will look as follows::

import numpy as np
kpoints = np.array([[0. , 0. , 0. ], # array shape is 12 * 3
[0.1 , 0. , 0.1 ],
[0.2 , 0. , 0.2 ],
[0.3 , 0. , 0.3 ],
[0.4 , 0. , 0.4 ],
[0.5 , 0. , 0.5 ],
[0.5 , 0. , 0.5 ],
[0.525 , 0.05 , 0.525 ],
[0.55 , 0.1 , 0.55 ],
[0.575 , 0.15 , 0.575 ],
[0.6 , 0.2 , 0.6 ],
[0.625 , 0.25 , 0.625 ]])

bands = np.array([[-5.64024889, 6.66929678, 6.66929678, 6.66929678, 8.91047649], # array shape is 12 * 5, where 12 is the size of the kpoints mesh
[-5.46976726, 5.76113772, 5.97844699, 5.97844699, 8.48186734], # and 5 is the numbe of states
[-4.93870761, 4.06179965, 4.97235487, 4.97235488, 7.68276008],
[-4.05318686, 2.21579935, 4.18048674, 4.18048675, 7.04145185],
[-2.83974972, 0.37738276, 3.69024464, 3.69024465, 6.75053465],
[-1.34041116, -1.34041115, 3.52500177, 3.52500178, 6.92381041],
[-1.34041116, -1.34041115, 3.52500177, 3.52500178, 6.92381041],
[-1.34599146, -1.31663872, 3.34867603, 3.54390139, 6.93928289],
[-1.36769345, -1.24523403, 2.94149041, 3.6004033 , 6.98809593],
[-1.42050683, -1.12604118, 2.48497007, 3.69389815, 7.07537154],
[-1.52788845, -0.95900776, 2.09104321, 3.82330632, 7.20537566],
[-1.71354964, -0.74425095, 1.82242466, 3.98697455, 7.37979746]])

To insert kpoints and bands in the ``bs`` object we should employ
``set_kpoints()`` and ``set_bands()`` methods::

bs.set_kpoints(kpoints)
bs.set_bands(bands, units='eV')

bs.show_mpl() # to visualize the bands

From now the band structure can be visualized. Last thing that we may want to
add is the array of kpoint labels::

labels = [(0, u'GAMMA'),
(5, u'X'),
(6, u'X'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Just a question, is this meant to be X or should it be Y?

(11, u'U')]

bs.labels = labels
bs.show_mpl() # to visualize the bands

The resulting band structure will look as follows

.. figure:: bands.png

.. warning:: Once the ``bs`` object is stored (``bs.store()``) -- it won't
accept any modifications.


Plotting the band structure
++++++++++++++++++++++++++++

You may notice that depending on how you assign the kpoints labels the output
of the ``show_mpl()`` method looks different. Please compare::

bs.labels = [(0, u'GAMMA'),
(5, u'X'),
(6, u'Y'),
(11, u'U')]
bs.show_mpl()

bs.labels = [(0, u'GAMMA'),
(5, u'X'),
(7, u'Y'),
(11, u'U')]
bs.show_mpl()

In the first case two neighboring kpoints with ``X`` and ``Y`` labels will look like
``X|Y``, while in the second case they will be separated by a certain distance.
The logic behind such a difference is the following. In the first case the
plotting method discovers the two neighboring kpoints and assumes them to be a
discontinuity point in the band structure (e.g. Gamma-X|Y-U). In the second case the
kpoints labelled ``X`` and ``Y`` are not neighbors anymore, so they are
plotted with a certain distance between them. The intervals between the kpoints on the X axis are
proportional to the cartesian distance between them.

Dealing with spins
++++++++++++++++++

The ``BandsData`` object can also deal with the results of spin-polarized calculations. Two
provide different bands for two different spins you should just merge them in
one array and import them again using the ``set_bands()`` method::

bands_spins = [bands, bands-0.3] # to distinguish the bands of different spins we substitite 0.3 from the second band structure
bs.set_bands(bands_spins, units='eV')
bs.show_mpl()

Now the shape of the bands array becomes ``nspins * nkpoints * nstates``
1 change: 1 addition & 0 deletions docs/source/working_with_aiida/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ Data types

../datatypes/index
../datatypes/kpoints
../datatypes/bands
../datatypes/functionality

==========
Expand Down