def test_solve1(): np.random.seed(1285947159) a = np.random.rand(10, 10) b = np.random.rand(10, 10) xs = sl.solve(a, b) x = solve(a, b) assert np.allclose(xs, x)
def _calc_green(k, no, tile, idx0): Gf, A2 = SE(E, k, dtype=dtype, bulk=True) # A1 == Gf, because of memory usage tY = M1Sk(k, dtype=dtype, format='array') # S tX = M1Pk(k, dtype=dtype, format='array') # H B = tY * E - tX # C = _conj(tY.T) * E - _conj(tX.T) tY = solve(Gf, conjugate(tY.T) * E - conjugate(tX.T), True, True) Gf = inv(A2 - dot(B, tY), True) tX = solve(A2, B, True, True) G = empty([tile, no, tile, no], dtype=dtype) G[idx0, :, idx0, :] = Gf.reshape(1, no, no) for i in range(1, tile): G[idx0[i:], :, idx0[:-i], :] = - dot(tX, G[i-1, :, 0, :]).reshape(1, no, no) G[idx0[:-i], :, idx0[i:], :] = - dot(tY, G[0, :, i-1, :]).reshape(1, no, no) return G.reshape(tile * no, -1)
def _calc_green(k, no, tile, idx0): # Calculate left/right self-energies Gf, A2 = SE(E, k, dtype=dtype, bulk=True) # A1 == Gf, because of memory usage B = - M1Pk(k, dtype=dtype, format='array') # C = conjugate(B.T) tY = solve(Gf, conjugate(B.T), True, True) Gf = inv(A2 - dot(B, tY), True) tX = solve(A2, B, True, True) # Since this is the pristine case, we know that # G11 and G22 are the same: # G = [A1 - C.tX]^-1 == [A2 - B.tY]^-1 G = empty([tile, no, tile, no], dtype=dtype) G[idx0, :, idx0, :] = Gf.reshape(1, no, no) for i in range(1, tile): G[idx0[i:], :, idx0[:-i], :] = - dot(tX, G[i-1, :, 0, :]).reshape(1, no, no) G[idx0[:-i], :, idx0[i:], :] = - dot(tY, G[0, :, i-1, :]).reshape(1, no, no) return G.reshape(tile * no, -1)
def test_solve2(): a = np.random.rand(10, 10) ac = a.copy() b = np.random.rand(10) bc = b.copy() xs = sl.solve(a, b) x = solve(a, b) assert np.allclose(xs, x) assert x.shape == (10, ) assert np.allclose(a, ac) assert np.allclose(b, bc)
def solve_lagrange(self): r""" Calculate the coefficients according to Pulay's method, return everything + Lagrange multiplier """ hist = self.history n_h = len(hist) metric = self._metric if n_h == 0: # Externally the coefficients should reflect the weight per previous iteration. # The mixing weight is an additional parameter return _a.arrayd([1.]), 100. elif n_h == 1: return _a.arrayd([1.]), metric(hist[0][-1], hist[0][-1]) # Initialize the matrix to be solved against B = _a.emptyd([n_h + 1, n_h + 1]) # Fill matrix B for i in range(n_h): ei = hist[i][-1] B[i, i] = metric(ei, ei) for j in range(i + 1, n_h): ej = hist[j][-1] B[i, j] = metric(ei, ej) B[j, i] = B[i, j] B[:, n_h] = 1. B[n_h, :] = 1. B[n_h, n_h] = 0. # Although B contains 1 and a number on the order of # number of elements (self._hist.size), it seems very # numerically stable. # Create RHS RHS = _a.zerosd(n_h + 1) RHS[-1] = 1 try: # Apparently we cannot use assume_a='sym' # Is this because sym also implies positive definitiness? # However, these are matrices of order ~30, so we don't care c = solve(B, RHS) return c[:-1], -c[-1] except np.linalg.LinAlgError as e: # We have a LinalgError return _a.arrayd([1.]), metric(hist[-1][-1], hist[-1][-1])
def self_energy_lr(self, E, k=None, dtype=None, eps=1e-14, bulk=False): r""" Return two dense matrices with the left/right self-energy at energy `E` and k-point `k` (default Gamma). Note calculating the LR self-energies simultaneously requires that their chemical potentials are the same. I.e. only when the reference energy is equivalent in the left/right schemes does this make sense. Parameters ---------- E : float/complex energy at which the calculation will take place, if complex, the hosting ``eta`` won't be used. k : array_like, optional k-point at which the self-energy should be evaluated. the k-point should be in units of the reciprocal lattice vectors, and the semi-infinite component will be automatically set to zero. dtype : numpy.dtype, optional the resulting data type, default to ``np.complex128`` eps : float, optional convergence criteria for the recursion bulk : bool, optional if true, :math:`E\cdot \mathbf S - \mathbf H -\boldsymbol\Sigma` is returned, else :math:`\boldsymbol\Sigma` is returned (default). Returns ------- left : the left self-energy right : the right self-energy """ if E.imag == 0.: E = E.real + 1j * self.eta # Get k-point k = self._correct_k(k) if dtype is None: dtype = complex128 sp0 = self.spgeom0 sp1 = self.spgeom1 # As the SparseGeometry inherently works for # orthogonal and non-orthogonal basis, there is no # need to have two algorithms. SmH0 = sp0.Sk(k, dtype=dtype, format='array') * E - sp0.Pk(k, dtype=dtype, format='array') GB = SmH0.copy() n = GB.shape[0] ab = empty([n, 2, n], dtype=dtype) shape = ab.shape # Get direct arrays alpha = ab[:, 0, :].view() beta = ab[:, 1, :].view() # Get solve step arary ab2 = ab.view() ab2.shape = (n, 2 * n) if sp1.orthogonal: alpha[:, :] = sp1.Pk(k, dtype=dtype, format='array') beta[:, :] = conjugate(alpha.T) else: P = sp1.Pk(k, dtype=dtype, format='array') S = sp1.Sk(k, dtype=dtype, format='array') alpha[:, :] = P - S * E beta[:, :] = conjugate(P.T) - conjugate(S.T) * E del P, S # Surface Green function (self-energy) if bulk: GS = GB.copy() else: GS = zeros_like(GB) # Specifying dot with 'out' argument should be faster tmp = empty_like(GS) while True: tab = solve(GB, ab2).reshape(shape) dot(alpha, tab[:, 1, :], tmp) # Update bulk Green function subtract(GB, tmp, out=GB) subtract(GB, dot(beta, tab[:, 0, :]), out=GB) # Update surface self-energy GS -= tmp # Update forward/backward alpha[:, :] = dot(alpha, tab[:, 0, :]) beta[:, :] = dot(beta, tab[:, 1, :]) # Convergence criteria, it could be stricter if _abs(alpha).max() < eps: # Return the pristine Green function del ab, alpha, beta, ab2, tab if self.semi_inf_dir == 1: # GS is the "right" self-energy if bulk: return GB - GS + SmH0, GS return GS - GB + SmH0, - GS # GS is the "left" self-energy if bulk: return GS, GB - GS + SmH0 return - GS, GS - GB + SmH0 raise ValueError(self.__class__.__name__+': could not converge self-energy (LR) calculation')
def test_solve1(): a = np.random.rand(10, 10) b = np.random.rand(10, 10) xs = sl.solve(a, b) x = solve(a, b) assert np.allclose(xs, x)
def test_solve3(): a = np.random.rand(10, 2) b = np.random.rand(10) with pytest.raises(ValueError): solve(a, b)
def test_solve3(): a = np.random.rand(10, 2) b = np.random.rand(10) solve(a, b)
def test_solve3(): np.random.seed(1285947159) a = np.random.rand(10, 2) b = np.random.rand(10) with pytest.raises(ValueError): solve(a, b)