Skip to content

Commit 4dfe4e2

Browse files
bfocassioNils Wittemeiergreschd
authored
hm System with non-orthogonal basis (#94)
hm System with non-orthogonal basis Implemented handling of non-orthonal basis by z2pack.hm.System. Added _hamilton_orthogonal property (bool) which is True is the Hamiltonian is orthogonal and False ortherwise Added basis_overlaps to store the function to call for the overlap matrix at each k The orthogonalization of the Hamiltonian is performed by a Lowdin transformation at each k. Co-authored-by: Nils Wittemeier <[email protected]> Co-authored-by: Dominik Gresch <[email protected]>
1 parent 8d75e26 commit 4dfe4e2

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

z2pack/hm.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ class System(EigenstateSystem):
3535
:param hermitian_tol: Maximum absolute value in the difference between the Hamiltonian and its hermitian conjugate. Use ``hermitian_tol=None`` to deactivate the test entirely.
3636
:type hermitian_tol: float
3737
38+
:param basis_overlap: A function taking the wavevector ``k`` (``list`` of length 3) as an input and returning the overlap matrix between the basis vectors w.r.t which the Hamiltonian is defined. If no value is given, the basis is assumed to be orthonormal.
39+
:type basis_overlap: collections.abc.Callable
40+
3841
:param convention: The convention used for the Hamiltonian, following the `pythtb formalism <http://www.physics.rutgers.edu/pythtb/_downloads/pythtb-formalism.pdf>`_. Convention 1 means that the eigenvalues of :math:`\mathcal{H}(\mathbf{k})` are wave vectors :math:`\left|\psi_{n\mathbf{k}}\right>`. With convention 2, they are the cell-periodic Bloch functions :math:`\left|u_{n\mathbf{k}}\right>`.
3942
:type convention: int
4043
@@ -49,17 +52,20 @@ def __init__(
4952
pos=None,
5053
bands=None,
5154
hermitian_tol=1e-6,
55+
basis_overlap=None,
5256
convention=2,
5357
check_periodic=False
5458
):
5559
self._hamilton = hamilton
5660
self._hermitian_tol = hermitian_tol
61+
self._basis_overlap = basis_overlap
5762
self._convention = int(convention)
5863
if self._convention not in {1, 2}:
5964
raise ValueError(
6065
"Invalid value '{}' for 'convention', must be either 1 or 2.".
6166
format(self._convention)
6267
)
68+
self._hamilton_orthogonal = basis_overlap is None
6369

6470
if check_periodic:
6571
k_values = itertools.product([0, 1], repeat=dim)
@@ -73,6 +79,14 @@ def __init__(
7379
)
7480

7581
size = len(self._hamilton([0] * dim)) # assuming to be square...
82+
if not self._hamilton_orthogonal:
83+
size_S = len(self._basis_overlap([0] * dim)) # assuming to be square...
84+
if size_S != size:
85+
raise ValueError(
86+
'The dimensions of overlap matrix ({0}) and Hamilontonian ({1}) do not match.'.
87+
format(size_S, size)
88+
)
89+
7690
# add one atom for each orbital in the hamiltonian
7791
if pos is None:
7892
self._pos = [np.zeros(dim) for _ in range(size)]
@@ -106,6 +120,19 @@ def get_eig(self, kpt):
106120
'The Hamiltonian you used is not hermitian, with the maximum difference between the Hamiltonian and its adjoint being {0}. Use the ``hamilton_tol`` input parameter (in the ``tb.Hamilton`` constructor; currently {1}) to set the sensitivity of this test or turn it off completely (``hamilton_tol=None``).'
107121
.format(diff, self._hermitian_tol)
108122
)
123+
if not self._hamilton_orthogonal:
124+
ovl = self._basis_overlap(k)
125+
if self._hermitian_tol is not None:
126+
diff = la.norm(ovl - ovl.conjugate().transpose(), ord=np.inf)
127+
if diff > self._hermitian_tol:
128+
raise ValueError(
129+
'The overlap you used is not hermitian, with the maximum difference between the overlap matrix and its adjoint being {0}. Use the ``hermitian_tol`` input parameter (currently {1}) to set the sensitivity of this test or turn it off completely (``hermitian_tol=None``).'.
130+
format(diff, self._hermitian_tol)
131+
)
132+
ovl2 = la.inv(la.sqrtm(ovl))
133+
ortho_ham = np.dot(ovl2,ham.dot(ovl2))
134+
ham = ortho_ham
135+
109136
eigval, eigvec = la.eigh(ham)
110137
eigval = np.real(eigval)
111138
idx = eigval.argsort()

0 commit comments

Comments
 (0)