def calculate_pairing_matrix(u, v, norm): assert is_square_matrix(u) assert is_square_matrix(v) assert u.shape[0] == v.shape[0] # Warn if u is singular, but don't abort cuz sometimes this is OK.. (signdet, logdet) = numpy.linalg.slogdet(u) logger.info('|det(u)| = %g', numpy.abs(numpy.exp(logdet))) # actually, just log it for now.. phiMat = numpy.dot( numpy.linalg.inv(u.conjugate().transpose()), v.conjugate().transpose() ) # logger.debug('Pairing matrix = ...') # logger.debug(phiMat) # logger.debug("Pairing matrix's main diagonal = ...") # logger.debug(phiMat.diagonal()) # Check that phiMat is symmetric: if numpy.max(numpy.abs(phiMat - phiMat.transpose())) > 1e-8: raise RuntimeError('"Symmetricness" of pairing matrix = %.9g', numpy.max(numpy.abs(phiMat - phiMat.transpose()))) # Check against TI code (must first run *_Fourier.py with same parameters): # phiMat_TI = numpy.loadtxt('phiMat_TI.dat').view(complex) # logger.debug('max|phiMat - phiMat_TI| = %.9g ', numpy.max(numpy.abs(phiMat - phiMat_TI))) phiNorm = norm_of_pairing_matrix(phiMat) logger.info('Norm of pairing matrix before normalization = %f', phiNorm) if norm is not None: phiMat = norm * (phiMat / phiNorm) phiNorm = norm_of_pairing_matrix(phiMat) logger.info('Norm of pairing matrix after normalization = %f', phiNorm) return phiMat
def calculate_free_fermion_pairing_matrix(evecs, evals, Nparticles, norm): assert is_square_matrix(evecs) Nsites = evecs.shape[0] assert Nsites == len(evals) M = Nparticles/2 # ( = N_up = N_down ) assert M <= Nsites phiMat = numpy.zeros((Nsites, Nsites), dtype=complex) for ind_r in range(0, Nsites): for ind_rp in range(0, Nsites): phiMat[ind_r, ind_rp] = numpy.dot( evecs[ind_r, 0:M], evecs[ind_rp, 0:M] ) # logger.debug('Pairing matrix = ...') # logger.debug(phiMat) # logger.debug("Pairing matrix's main diagonal = ...") # logger.debug(phiMat.diagonal()) # Check that phiMat is symmetric: if numpy.max(numpy.abs(phiMat - phiMat.transpose())) > 1e-8: raise RuntimeError('"Symmetricness" of pairing matrix = %.9g', numpy.max(numpy.abs(phiMat - phiMat.transpose()))) phiNorm = norm_of_pairing_matrix(phiMat) logger.info('Norm of pairing matrix before normalization = %f', phiNorm) if norm is not None: phiMat = norm * (phiMat / phiNorm) phiNorm = norm_of_pairing_matrix(phiMat) logger.info('Norm of pairing matrix after normalization = %f', phiNorm) return phiMat
def add_noise_to_matrix_diagonal(mat, noiselevel=.001): # only adds noise to the diagonal assert 0 <= noiselevel < 1 assert is_square_matrix(mat) assert numpy.max(numpy.abs(mat - mat.transpose())) < 1e-12 mat = mat.copy() if noiselevel == 0: return mat for i in six.moves.xrange(mat.shape[0]): mat[i, i] *= 1 + random.uniform(-noiselevel, noiselevel) return mat
def add_noise_to_symmetric_matrix(mat, noiselevel=.01): # currently does not add noise to the diagonal assert 0 < noiselevel < 1 assert is_square_matrix(mat) assert numpy.max(numpy.abs(mat - mat.transpose())) < 1e-12 mat = mat.copy() for i in six.moves.xrange(mat.shape[0]): for j in six.moves.xrange(i + 1, mat.shape[1]): z = random.uniform(1 - noiselevel, 1 + noiselevel) mat[(i, j)] *= z mat[(j, i)] *= z return mat
def bcs_stats(u, v): assert is_square_matrix(u) assert is_square_matrix(v) assert u.shape[0] == v.shape[0] Nsites = u.shape[0] fdagf = numpy.zeros((Nsites), dtype=float) fdownfup = numpy.zeros((Nsites), dtype=complex) Tvec = numpy.zeros((Nsites, 3), dtype=float) Ttot = numpy.zeros((Nsites), dtype=float) for ind_r in range(0, Nsites): fdagf[ind_r] = 2.0 * numpy.dot( v[ind_r, :], v[ind_r, :].conjugate() ).real fdownfup[ind_r] = -numpy.dot( u[ind_r, :], v[ind_r, :].conjugate() ) for ind_r in range(0, Nsites): Tvec[ind_r, 0] = fdownfup[ind_r].real Tvec[ind_r, 1] = -fdownfup[ind_r].imag Tvec[ind_r, 2] = 0.5 * (fdagf[ind_r] - 1.0) Tvec[ind_r, :] = 2.0 * Tvec[ind_r, :] # 2.0 to be consistent with Lesik. Ttot[ind_r] = numpy.sqrt( numpy.dot( Tvec[ind_r, :], Tvec[ind_r, :].conjugate() ) ).real return {'fdagf':fdagf, 'fdownfup':fdownfup, 'Tvec':Tvec, 'Ttot':Ttot}
def add_onsite_terms(offsite, onsite): assert is_square_matrix(offsite) check_offsite_for_onsite(offsite) # since we're singling out the on-site terms with this function Nsites = offsite.shape[0] # total_{ij} = offsite_{ij} + onsite_i * krondelta_{ij} if isinstance(onsite, numpy.ndarray): assert onsite.ndim == 1 assert onsite.shape[0] == 1 or onsite.shape[0] == Nsites if onsite.shape[0] == 1: total = offsite + onsite * numpy.identity(Nsites) elif onsite.shape[0] == Nsites: total = offsite + numpy.diag(onsite) else: total = offsite + onsite * numpy.identity(Nsites) return total
def free_fermion_soln(t): assert is_square_matrix(t) Nsites = t.shape[0] # t_{ij} = ttilde_{ij} = t_{ij} + mu_i * krondelta_{ij} from notes (FIXME: take t and mu as separate parameters?) H = -t assert numpy.max(numpy.abs(H - H.conjugate().transpose())) < 1e-12 eigsys = numpy.linalg.eigh(H) idx = eigsys[0].argsort() evals = eigsys[0][idx] evecs = eigsys[1][:,idx] logger.debug('Eigenvalues = ...') logger.debug(evals) return {'evecs':evecs, 'evals':evals}
def plot_pairing_matrix(phiMat, callshow=True): assert is_square_matrix(phiMat) from mpl_toolkits.mplot3d import Axes3D from matplotlib import cm from matplotlib.ticker import LinearLocator, FormatStrFormatter fig = plt.figure() ax = fig.gca(projection='3d') X = numpy.arange(0, phiMat.shape[0], 1) Y = numpy.arange(0, phiMat.shape[0], 1) X, Y = numpy.meshgrid(X, Y) surf = ax.plot_surface(X, Y, numpy.abs(phiMat), rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0, antialiased=False) #ax.zaxis.set_major_locator(LinearLocator(10)) ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f')) fig.colorbar(surf, shrink=0.5, aspect=5) if callshow: plt.show()
def bcs_soln(t, delta): # both t and delta should include on-site terms, e.g., t_{ij} = ttilde_{ij} = t_{ij} + mu_i * krondelta_{ij} from notes assert is_square_matrix(t) assert is_square_matrix(delta) assert t.shape[0] == delta.shape[0] Nsites = t.shape[0] H = numpy.zeros((Nsites, Nsites, 2, 2), dtype=complex) for ind_r in range(0, Nsites): for ind_rp in range(0, Nsites): H[ind_r, ind_rp] = -numpy.array([[t[ind_r, ind_rp], delta[ind_r, ind_rp]], [delta[ind_r, ind_rp].conjugate(), -t[ind_r, ind_rp].conjugate()]]) Hflat = numpy.zeros((2*Nsites, 2*Nsites), dtype=complex) for i in range(0, 2*Nsites): for j in range(0, 2*Nsites): Hflat[i,j] = H[i//2, j//2, numpy.mod(i,2), numpy.mod(j,2)] assert numpy.max(numpy.abs(Hflat - Hflat.conjugate().transpose())) < 1e-12 eigsys = numpy.linalg.eigh(Hflat) idx = eigsys[0].argsort() evals = eigsys[0][idx] evecs = eigsys[1][:,idx] # Check that eigenvectors are orthonormal: Icheck = numpy.dot( evecs.conjugate().transpose(), evecs ) assert numpy.max(numpy.abs(Icheck - numpy.identity(Icheck.shape[0], dtype=complex))) < 1e-12 evalsNeg = evals[0:Nsites] evecsNeg = evecs[:, 0:Nsites] evalsPos = evals[Nsites:2*Nsites] evecsPos = evecs[:, Nsites:2*Nsites] logger.debug('Positive eigenvalues = ...') logger.debug(evalsPos) # logger.debug('Negative eigenvalues = ...') # logger.debug(evalsNeg[::-1]) # Check that positive eigenvalues are positive and that eigenvalues have come in plus-minus pairs: # FIXME: probably shouldn't be so strict, since this gets called when trying to tune the ansatz, # and we could potentially run into degenerate mean field solutions (i.e., those with zero modes) in that process; # if we don't assert evalsPos > 0, then we treat zero modes as positive and don't populate them in the the BCS solution, # which I think is OK; for now, we'll just warn instead of assert # assert numpy.min(evalsPos) > 1e-12 if not numpy.min(evalsPos) > 1e-12: logger.warning('Some of evalsPos are not greater than 1e-12') assert numpy.max(numpy.abs(evalsNeg[::-1] + evalsPos)) < 1e-12 u = evecsPos[0:evecsPos.shape[0]:2, :] v = evecsPos[1:evecsPos.shape[0]:2, :] # Check that (v, -u)^* from evecsPos are indeed negative eigenvectors: errr = [] for n in range(0, Nsites): evecTest = numpy.zeros(2*Nsites, dtype=complex) for i in range(0, Nsites): evecTest[2*i] = v[i,n].conjugate() evecTest[2*i+1] = -u[i,n].conjugate() errr.append(numpy.max(numpy.abs( numpy.dot( Hflat, evecTest ) - (-evalsPos[n] * evecTest )))) assert numpy.max(errr) < 1e-12 return {'u':u, 'v':v, 'evalsPos':evalsPos}