Skip to content
Snippets Groups Projects
Commit 8c18865f authored by Kostas Vilkelis's avatar Kostas Vilkelis :flamingo:
Browse files

fix bug in exchange calculation

parent 4ac2691a
No related branches found
No related tags found
1 merge request!4Interface refactoring
This commit is part of merge request !4. Comments created here will be created in the context of that merge request.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
import numpy as np import numpy as np
from scipy.integrate import quad, quad_vec from scipy.integrate import quad, quad_vec
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def tb2kfunc(tb_model): def tb2kfunc(tb_model):
""" """
Fourier transforms a real-space tight-binding model to a k-space function. Fourier transforms a real-space tight-binding model to a k-space function.
Parameters Parameters
---------- ----------
tb_model : dict tb_model : dict
A dictionary with real-space vectors as keys and complex np.arrays as values. A dictionary with real-space vectors as keys and complex np.arrays as values.
Returns Returns
------- -------
function function
A function that takes a k-space vector and returns a complex np.array. A function that takes a k-space vector and returns a complex np.array.
""" """
def bloch_ham(k): def bloch_ham(k):
ham = 0 ham = 0
for vector in tb_model.keys(): for vector in tb_model.keys():
ham += tb_model[vector] * np.exp( ham += tb_model[vector] * np.exp(
-1j * np.dot(k, np.array(vector, dtype=float)) -1j * np.dot(k, np.array(vector, dtype=float))
) )
return ham return ham
return bloch_ham return bloch_ham
def kfunc2tbfunc(kfunc): def kfunc2tbfunc(kfunc):
""" """
Inverse Fourier transforms a k-space function to a real-space function. Inverse Fourier transforms a k-space function to a real-space function.
Parameters Parameters
---------- ----------
kfunc : function kfunc : function
A function that takes a k-space vector and returns a np.array. A function that takes a k-space vector and returns a np.array.
Returns Returns
------- -------
function function
A function that takes a real-space integer vector and returns a np.array. A function that takes a real-space integer vector and returns a np.array.
""" """
def tbfunc(vector): def tbfunc(vector):
def integrand(k): def integrand(k):
return kfunc(k) * np.exp(1j * np.dot(k, np.array(vector, dtype=float))) return kfunc(k) * np.exp(1j * np.dot(k, np.array(vector, dtype=float)))
return quad_vec(integrand, -np.pi, np.pi)[0] return quad_vec(integrand, -np.pi, np.pi)[0]
return tbfunc return tbfunc
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def addTb(tb1, tb2): def addTb(tb1, tb2):
""" """
Add up two tight-binding models together. Add up two tight-binding models together.
Parameters: Parameters:
----------- -----------
tb1 : dict tb1 : dict
Tight-binding model. Tight-binding model.
tb2 : dict tb2 : dict
Tight-binding model. Tight-binding model.
Returns: Returns:
-------- --------
dict dict
Sum of the two tight-binding models. Sum of the two tight-binding models.
""" """
return {k: tb1.get(k, 0) + tb2.get(k, 0) for k in frozenset(tb1) | frozenset(tb2)} return {k: tb1.get(k, 0) + tb2.get(k, 0) for k in frozenset(tb1) | frozenset(tb2)}
def generateRho(hkfunc, E_F): def generateRho(hkfunc, E_F):
""" """
Generate a function that returns the density matrix at a given k-point. Generate a function that returns the density matrix at a given k-point.
Parameters Parameters
---------- ----------
hkfunc : function hkfunc : function
Function that return Hamiltonian at a given k-point. Function that return Hamiltonian at a given k-point.
E_F : float E_F : float
Fermi level Fermi level
Returns Returns
------- -------
rho : function rho : function
Density matrix at the same k-point as hk Density matrix at the same k-point as hk
""" """
def rhofunc(k): def rhofunc(k):
hk = hkfunc(k) hk = hkfunc(k)
vals, vecs = np.linalg.eigh(hk) vals, vecs = np.linalg.eigh(hk)
unocc_vals = vals > E_F unocc_vals = vals > E_F
occ_vecs = vecs occ_vecs = vecs
occ_vecs[:, unocc_vals] = 0 occ_vecs[:, unocc_vals] = 0
# Outter products between eigenvectors # Outter products between eigenvectors
return occ_vecs @ occ_vecs.T.conj() return occ_vecs @ occ_vecs.T.conj()
return rhofunc return rhofunc
def fermiOnGrid(hkfunc, filling, Nk=100): def fermiOnGrid(hkfunc, filling, Nk=100):
""" """
Compute the Fermi energy on a grid of k-points. Compute the Fermi energy on a grid of k-points.
Parameters Parameters
---------- ----------
hkfunc : function hkfunc : function
Function that returns the Hamiltonian at a given k-point. Function that returns the Hamiltonian at a given k-point.
Nk : int Nk : int
Number of k-points in the grid. Number of k-points in the grid.
Returns Returns
------- -------
E_F : float E_F : float
Fermi energy Fermi energy
""" """
ks = np.linspace(-np.pi, np.pi, Nk, endpoint=False) ks = np.linspace(-np.pi, np.pi, Nk, endpoint=False)
hkarray = np.array([hkfunc(k) for k in ks]) hkarray = np.array([hkfunc(k) for k in ks])
vals = np.linalg.eigvalsh(hkarray) vals = np.linalg.eigvalsh(hkarray)
norbs = vals.shape[-1] norbs = vals.shape[-1]
vals_flat = np.sort(vals.flatten()) vals_flat = np.sort(vals.flatten())
ne = len(vals_flat) ne = len(vals_flat)
ifermi = int(round(ne * filling / norbs)) ifermi = int(round(ne * filling / norbs))
if ifermi >= ne: if ifermi >= ne:
return vals_flat[-1] return vals_flat[-1]
elif ifermi == 0: elif ifermi == 0:
return vals_flat[0] return vals_flat[0]
else: else:
fermi = (vals_flat[ifermi - 1] + vals_flat[ifermi]) / 2 fermi = (vals_flat[ifermi - 1] + vals_flat[ifermi]) / 2
return fermi return fermi
def totalEnergy(rho, hk): def totalEnergy(rho, hk):
def integrand(k): def integrand(k):
return np.real(np.trace(rho(k) @ hk(k))) return np.real(np.trace(rho(k) @ hk(k)))
return quad(integrand, -np.pi, np.pi)[0] return quad(integrand, -np.pi, np.pi)[0]
def meanField(rhoTbfunc, int_model): def meanField(rhoTbfunc, int_model):
""" """
Compute the mean-field in real space. Compute the mean-field in real space.
Parameters Parameters
---------- ----------
rhoTbfunc : function rhoTbfunc : function
Function that returns the density matrix at a given real-space vector. Function that returns the density matrix at a given real-space vector.
int_model : dict int_model : dict
Interaction tb model. Interaction tb model.
Returns Returns
------- -------
dict dict
Mean-field tb model. Mean-field tb model.
""" """
exchange = {vec: -1*(int_model.get(vec, 0) + rhoTbfunc(vec)) for vec in frozenset(int_model)} exchange = {vec: -1*(int_model.get(vec, 0)*rhoTbfunc(vec)) for vec in frozenset(int_model)}
# direct interaction is missing # direct interaction is missing
return exchange return exchange
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
U0 = 1 U0 = 1
nk = 100 nk = 100
filling = 2 filling = 2
hopp = np.kron(np.array([[0, 1], [0, 0]]), np.eye(2)) hopp = np.kron(np.array([[0, 1], [0, 0]]), np.eye(2))
tb_model = {(0,): hopp + hopp.T.conj(), (1,): hopp, (-1,): hopp.T.conj()} tb_model = {(0,): hopp + hopp.T.conj(), (1,): hopp, (-1,): hopp.T.conj()}
mf_model = {} # placeholder for guess mf_model = {} # placeholder for guess
int_model = { int_model = {
(0,): U0 * np.kron(np.eye(2), np.ones((2, 2))), (0,): U0 * np.kron(np.eye(2), np.ones((2, 2))),
} }
# attempting to do a single iteration of mean-field # attempting to do a single iteration of mean-field
hkfunc = tb2kfunc(addTb(tb_model, mf_model)) hkfunc = tb2kfunc(addTb(tb_model, mf_model))
EF = fermiOnGrid(hkfunc, filling, nk) EF = fermiOnGrid(hkfunc, filling, nk)
rhofunc = generateRho(hkfunc, EF) rhofunc = generateRho(hkfunc, EF)
rhoTbfunc = kfunc2tbfunc(rhofunc) rhoTbfunc = kfunc2tbfunc(rhofunc)
mf_model = meanField(rhoTbfunc, int_model) mf_model = meanField(rhoTbfunc, int_model)
``` ```
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment