mirror of
https://github.com/triqs/dft_tools
synced 2024-12-22 04:13:47 +01:00
Fixed 'plotools.py' and restructured 'proj_group.py'
Added missing import of ProjectorGroup and ProjectorShell to 'plotools.py'. Moved separate routines 'orthogonalize_projector_matrix()' and 'select_bands()' into class ProjectorGroup because these routines are anyway not used elsewhere outside this class.
This commit is contained in:
parent
61395b12fa
commit
401d416d4d
1
c/vasp/.gitignore
vendored
Normal file
1
c/vasp/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*.pyc
|
@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
import itertools as it
|
import itertools as it
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
from proj_group import ProjectorGroup
|
||||||
|
from proj_shell import ProjectorShell
|
||||||
|
|
||||||
np.set_printoptions(suppress=True)
|
np.set_printoptions(suppress=True)
|
||||||
|
|
||||||
@ -18,37 +20,6 @@ def issue_warning(message):
|
|||||||
print " !!! WARNING !!!: " + message
|
print " !!! WARNING !!!: " + message
|
||||||
print
|
print
|
||||||
|
|
||||||
class Projector:
|
|
||||||
"""
|
|
||||||
Class describing a local-orbital projector.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, matrix, ib1=1, ib2=None, nion=1):
|
|
||||||
self.p_matrix = matrix.astype(np.complex128)
|
|
||||||
self.norb, self.nb = matrix.shape
|
|
||||||
self.nion = nion
|
|
||||||
self.ib1 = ib1 - 1
|
|
||||||
if not ib2 is None:
|
|
||||||
self.ib2 = ib2 - 1
|
|
||||||
else:
|
|
||||||
self.ib2 = self.nb - 1
|
|
||||||
|
|
||||||
def project_up(self, mat):
|
|
||||||
return np.dot(self.p_matrix.conj().T, np.dot(mat, self.p_matrix))
|
|
||||||
|
|
||||||
def project_down(self, mat):
|
|
||||||
assert mat.shape == (self.nb, self.nb), " Matrix must match projector in size"
|
|
||||||
return np.dot(self.p_matrix, np.dot(mat, self.p_matrix.conj().T))
|
|
||||||
|
|
||||||
def orthogonalize(self):
|
|
||||||
"""
|
|
||||||
Orthogonalizes a projector.
|
|
||||||
Returns an overlap matrix and its eigenvalues for initial projectors.
|
|
||||||
"""
|
|
||||||
self.p_matrix, overlap, over_eig = orthogonalize_projector(self.p_matrix)
|
|
||||||
|
|
||||||
return (overlap, over_eig)
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# check_data_consistency()
|
# check_data_consistency()
|
||||||
################################################################################
|
################################################################################
|
||||||
|
@ -3,95 +3,6 @@ import numpy as np
|
|||||||
|
|
||||||
np.set_printoptions(suppress=True)
|
np.set_printoptions(suppress=True)
|
||||||
|
|
||||||
################################################################################
|
|
||||||
#
|
|
||||||
# orthogonalize_projector_matrix()
|
|
||||||
#
|
|
||||||
################################################################################
|
|
||||||
def orthogonalize_projector_matrix(p_matrix):
|
|
||||||
"""
|
|
||||||
Orthogonalizes a projector defined by a rectangular matrix `p_matrix`.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
|
|
||||||
p_matrix (numpy.array[complex]) : matrix `Nm x Nb`, where `Nm` is
|
|
||||||
the number of orbitals, `Nb` number of bands
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
|
|
||||||
Orthogonalized projector matrix, initial overlap matrix and its eigenvalues.
|
|
||||||
"""
|
|
||||||
# Overlap matrix O_{m m'} = \sum_{v} P_{m v} P^{*}_{v m'}
|
|
||||||
overlap = np.dot(p_matrix, p_matrix.conj().T)
|
|
||||||
# Calculate [O^{-1/2}]_{m m'}
|
|
||||||
eig, eigv = np.linalg.eigh(overlap)
|
|
||||||
assert np.all(eig > 0.0), ("Negative eigenvalues of the overlap matrix:"
|
|
||||||
"projectors are ill-defined")
|
|
||||||
sqrt_eig = np.diag(1.0 / np.sqrt(eig))
|
|
||||||
shalf = np.dot(eigv, np.dot(sqrt_eig, eigv.conj().T))
|
|
||||||
# Apply \tilde{P}_{m v} = \sum_{m'} [O^{-1/2}]_{m m'} P_{m' v}
|
|
||||||
p_ortho = np.dot(shalf, p_matrix)
|
|
||||||
|
|
||||||
return (p_ortho, overlap, eig)
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
#
|
|
||||||
# select_bands()
|
|
||||||
#
|
|
||||||
################################################################################
|
|
||||||
def select_bands(eigvals, emin, emax):
|
|
||||||
"""
|
|
||||||
Select a subset of bands lying within a given energy window.
|
|
||||||
The band energies are assumed to be sorted in an ascending order.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
|
|
||||||
eigvals (numpy.array) : all eigenvalues
|
|
||||||
emin, emax (float) : energy window
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
|
|
||||||
ib_win, nb_min, nb_max :
|
|
||||||
"""
|
|
||||||
# Sanity check
|
|
||||||
if emin > eigvals.max() or emax < eigvals.min():
|
|
||||||
raise Exception("Energy window does not overlap with the band structure")
|
|
||||||
|
|
||||||
nk, nband, ns_band = eigvals.shape
|
|
||||||
ib_win = np.zeros((nk, ns_band, 2), dtype=np.int32)
|
|
||||||
|
|
||||||
ib_min = 10000000
|
|
||||||
ib_max = 0
|
|
||||||
for isp in xrange(ns_band):
|
|
||||||
for ik in xrange(nk):
|
|
||||||
for ib in xrange(nband):
|
|
||||||
en = eigvals[ik, ib, isp]
|
|
||||||
if en >= emin:
|
|
||||||
break
|
|
||||||
ib1 = ib
|
|
||||||
for ib in xrange(ib1, nband):
|
|
||||||
en = eigvals[ik, ib, isp]
|
|
||||||
if en > emax:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
# If we reached the last band add 1 to get the correct bound
|
|
||||||
ib += 1
|
|
||||||
ib2 = ib - 1
|
|
||||||
|
|
||||||
assert ib1 <= ib2, "No bands inside the window for ik = %s"%(ik)
|
|
||||||
|
|
||||||
ib_win[ik, isp, 0] = ib1
|
|
||||||
ib_win[ik, isp, 1] = ib2
|
|
||||||
|
|
||||||
ib_min = min(ib_min, ib1)
|
|
||||||
ib_max = max(ib_max, ib2)
|
|
||||||
|
|
||||||
return ib_win, ib_min, ib_max
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
@ -125,7 +36,7 @@ class ProjectorGroup:
|
|||||||
self.shells = shells
|
self.shells = shells
|
||||||
|
|
||||||
# Determine the minimum and maximum band numbers
|
# Determine the minimum and maximum band numbers
|
||||||
ib_win, ib_min, ib_max = select_bands(eigvals, self.emin, self.emax)
|
ib_win, ib_min, ib_max = self.select_bands(eigvals)
|
||||||
self.ib_win = ib_win
|
self.ib_win = ib_win
|
||||||
self.ib_min = ib_min
|
self.ib_min = ib_min
|
||||||
self.ib_max = ib_max
|
self.ib_max = ib_max
|
||||||
@ -254,7 +165,7 @@ class ProjectorGroup:
|
|||||||
i1, i2 = blocks[ion]
|
i1, i2 = blocks[ion]
|
||||||
p_mat[i1:i2, :nb] = shell.proj_win[ion, isp, ik, :nlm, :nb]
|
p_mat[i1:i2, :nb] = shell.proj_win[ion, isp, ik, :nlm, :nb]
|
||||||
# Now orthogonalize the obtained block projector
|
# Now orthogonalize the obtained block projector
|
||||||
p_orth, overl, eig = orthogonalize_projector_matrix(p_mat)
|
p_orth, overl, eig = self.orthogonalize_projector_matrix(p_mat)
|
||||||
# print "ik = ", ik
|
# print "ik = ", ik
|
||||||
# print overl.real
|
# print overl.real
|
||||||
# Distribute back projectors in the same order
|
# Distribute back projectors in the same order
|
||||||
@ -265,5 +176,93 @@ class ProjectorGroup:
|
|||||||
i1, i2 = blocks[ion]
|
i1, i2 = blocks[ion]
|
||||||
shell.proj_win[ion, isp, ik, :nlm, :nb] = p_orth[i1:i2, :nb]
|
shell.proj_win[ion, isp, ik, :nlm, :nb] = p_orth[i1:i2, :nb]
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# orthogonalize_projector_matrix()
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
def orthogonalize_projector_matrix(self, p_matrix):
|
||||||
|
"""
|
||||||
|
Orthogonalizes a projector defined by a rectangular matrix `p_matrix`.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
p_matrix (numpy.array[complex]) : matrix `Nm x Nb`, where `Nm` is
|
||||||
|
the number of orbitals, `Nb` number of bands
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
|
||||||
|
Orthogonalized projector matrix, initial overlap matrix and its eigenvalues.
|
||||||
|
"""
|
||||||
|
# Overlap matrix O_{m m'} = \sum_{v} P_{m v} P^{*}_{v m'}
|
||||||
|
overlap = np.dot(p_matrix, p_matrix.conj().T)
|
||||||
|
# Calculate [O^{-1/2}]_{m m'}
|
||||||
|
eig, eigv = np.linalg.eigh(overlap)
|
||||||
|
assert np.all(eig > 0.0), ("Negative eigenvalues of the overlap matrix:"
|
||||||
|
"projectors are ill-defined")
|
||||||
|
sqrt_eig = np.diag(1.0 / np.sqrt(eig))
|
||||||
|
shalf = np.dot(eigv, np.dot(sqrt_eig, eigv.conj().T))
|
||||||
|
# Apply \tilde{P}_{m v} = \sum_{m'} [O^{-1/2}]_{m m'} P_{m' v}
|
||||||
|
p_ortho = np.dot(shalf, p_matrix)
|
||||||
|
|
||||||
|
return (p_ortho, overlap, eig)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# select_bands()
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
def select_bands(self, eigvals):
|
||||||
|
"""
|
||||||
|
Select a subset of bands lying within a given energy window.
|
||||||
|
The band energies are assumed to be sorted in an ascending order.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
eigvals (numpy.array) : all eigenvalues
|
||||||
|
emin, emax (float) : energy window
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
|
||||||
|
ib_win, nb_min, nb_max :
|
||||||
|
"""
|
||||||
|
# Sanity check
|
||||||
|
if self.emin > eigvals.max() or self.emax < eigvals.min():
|
||||||
|
raise Exception("Energy window does not overlap with the band structure")
|
||||||
|
|
||||||
|
nk, nband, ns_band = eigvals.shape
|
||||||
|
ib_win = np.zeros((nk, ns_band, 2), dtype=np.int32)
|
||||||
|
|
||||||
|
ib_min = 10000000
|
||||||
|
ib_max = 0
|
||||||
|
for isp in xrange(ns_band):
|
||||||
|
for ik in xrange(nk):
|
||||||
|
for ib in xrange(nband):
|
||||||
|
en = eigvals[ik, ib, isp]
|
||||||
|
if en >= self.emin:
|
||||||
|
break
|
||||||
|
ib1 = ib
|
||||||
|
for ib in xrange(ib1, nband):
|
||||||
|
en = eigvals[ik, ib, isp]
|
||||||
|
if en > self.emax:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# If we reached the last band add 1 to get the correct bound
|
||||||
|
ib += 1
|
||||||
|
ib2 = ib - 1
|
||||||
|
|
||||||
|
assert ib1 <= ib2, "No bands inside the window for ik = %s"%(ik)
|
||||||
|
|
||||||
|
ib_win[ik, isp, 0] = ib1
|
||||||
|
ib_win[ik, isp, 1] = ib2
|
||||||
|
|
||||||
|
ib_min = min(ib_min, ib1)
|
||||||
|
ib_max = max(ib_max, ib2)
|
||||||
|
|
||||||
|
return ib_win, ib_min, ib_max
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user