Brillouin zone classes¶
The Brillouin zone objects are all special classes enabling easy manipulation of an underlying physical quantity.
Quite often a physical quantity will be required to be averaged, or calculated individually over a number of k-points. In this regard can the Brillouin zone objects help.
A basic principle of the BrillouinZone objects is that any method called on a BrillouinZone object will defer to the attached parent to the class. Lets take an example.
>>> H = Hamiltonian(...)
>>> bz = BrillouinZone(H)
>>> bz.eigh()
This will actually calculate the eigenvalues for all k-points associated with the BrillouinZone. This may be extremely convenient when calculating band-structures:
>>> H = Hamiltonian(...)
>>> bs = BandStructure(H, [[0, 0, 0], [0.5, 0, 0]], 100)
>>> bs_eig = bs.eigh().T
and then you have all eigenvalues for all the k-points.
Sometimes one may want to post-process the data for each k-point. As an example lets post-process the DOS on a per k-point basis.
>>> H = Hamiltonian(...)
>>> mp = MonkhorstPack(H, [10, 10, 10])
>>> E = np.linspace(-2, 2, 100)
>>> def wrap_DOS(eigenstate):
... # Calculate the DOS for the eigenstates
... DOS = eigenstate.DOS(E)
... # Calculate the velocity for the eigenstates
... v = eigenstate.velocity()
... V = (v ** 2).sum(1)
... return DOS.reshape(-1, 1) * v ** 2 / V.reshape(-1, 1)
>>> DOS = mp.asaverage().eigenstate(wrap=wrap_DOS, eta=True)
This will, calculate the Monkhorst pack k-averaged DOS split into 3 Cartesian
directions based on the eigenstates velocity direction. This method of manipulating
the result can be extremely powerful to calculate many quantities while running an
efficient BrillouinZone average. The eta flag will print, to stdout, a progress-bar.
The usage of the wrap
method are also passed optional arguments, parent
which is
H
in the above example. k
and weight
are the current k-point and weight of the
corresponding k-point. An example could be to manipulate the DOS depending on the k-point and
weight:
>>> H = Hamiltonian(...)
>>> mp = MonkhorstPack(H, [10, 10, 10])
>>> E = np.linspace(-2, 2, 100)
>>> def wrap_DOS(eigenstate, k, weight):
... # Calculate the DOS for the eigenstates and weight by k_x and weight
... return eigenstate.DOS(E) * k[0] * weight
>>> DOS = mp.assum().eigenstate(wrap=wrap_DOS, eta=True)
When using wrap to calculate more than one quantity per eigenstate it may be advantageous
to use oplist
to handle cases of BrillouinZone.asaverage
and BrillouinZone.assum
.
>>> H = Hamiltonian(...)
>>> mp = MonkhorstPack(H, [10, 10, 10])
>>> E = np.linspace(-2, 2, 100)
>>> def wrap_multiple(eigenstate):
... # Calculate DOS/PDOS for eigenstates
... DOS = eigenstate.DOS(E)
... PDOS = eigenstate.PDOS(E)
... # Calculate velocity for the eigenstates
... v = eigenstate.velocity()
... return oplist([DOS, PDOS, v])
>>> DOS, PDOS, v = mp.asaverage().eigenstate(wrap=wrap_multiple, eta=True)
Which does mathematical operations (averaging/summing) using oplist
.
|
A class to construct Brillouin zone related quantities |
|
Create a Monkhorst-Pack grid for the Brillouin zone |
|
Create a path in the Brillouin zone for plotting band-structures etc. |