Exemplo n.º 1
0
def matrix_exponential(G_nn, dlt):
    """Computes the matrix exponential of an antihermitian operator

       U = exp(i*dlt*G)
        
    G_nn: ndarray
        anti-hermitian (skew-symmetric) matrix.
            
    dlt: float
        scaling factor for G_nn.
    """

    ndim = G_nn.shape[1]
    w_n = np.zeros((ndim), dtype=float)

    V_nn = np.zeros((ndim, ndim), dtype=complex)
    O_nn = np.zeros((ndim, ndim), dtype=complex)
    if G_nn.dtype == complex:
        V_nn = 1j * G_nn.real - G_nn.imag
    else:
        V_nn = 1j * G_nn.real

    diagonalize(V_nn, w_n)
    #
    O_nn = np.diag(np.exp(1j * dlt * w_n))
    #
    if G_nn.dtype == complex:
        U_nn = np.dot(V_nn.T.conj(), np.dot(O_nn, V_nn)).copy()
    else:
        U_nn = np.dot(V_nn.T.conj(), np.dot(O_nn, V_nn)).real.copy()
    #
    return U_nn
Exemplo n.º 2
0
    def diagonalize(self, istart=None, jend=None, energy_range=None):
        """Evaluate Eigenvectors and Eigenvalues:"""

        map, kss = self.get_map(istart, jend, energy_range)
        nij = len(kss)
        if map is None:
            ApB = self.ApB.copy()
            AmB = self.AmB.copy()
            nij = len(kss)
        else:
            ApB = np.empty((nij, nij))
            AmB = np.empty((nij, nij))
            for ij in range(nij):
                for kq in range(nij):
                    ApB[ij,kq] = self.ApB[map[ij],map[kq]]
                    AmB[ij,kq] = self.AmB[map[ij],map[kq]]

        # the occupation matrix
        C = np.empty((nij,))
        for ij in range(nij):
            C[ij] = 1. / kss[ij].fij

        S = C * inv(AmB) * C
        S = sqrt_matrix(inv(S).copy())

        # get Omega matrix
        M = np.zeros(ApB.shape)
        gemm(1.0, ApB, S, 0.0, M)
        self.eigenvectors = np.zeros(ApB.shape)
        gemm(1.0, S, M, 0.0, self.eigenvectors)
        
        self.eigenvalues = np.zeros((len(kss)))
        self.kss = kss
        diagonalize(self.eigenvectors, self.eigenvalues)
Exemplo n.º 3
0
def matrix_exponential(G_nn, dlt):

    """Computes the matrix exponential of an antihermitian operator

       U = exp(i*dlt*G)
        
    G_nn: ndarray
        anti-hermitian (skew-symmetric) matrix.
            
    dlt: float
        scaling factor for G_nn.
    """
    
    ndim = G_nn.shape[1]
    w_n = np.zeros((ndim), dtype=float)

    V_nn = np.zeros((ndim, ndim), dtype=complex)
    O_nn = np.zeros((ndim, ndim), dtype=complex)
    if G_nn.dtype==complex:
        V_nn = 1j*G_nn.real - G_nn.imag
    else:
        V_nn = 1j*G_nn.real

    diagonalize(V_nn, w_n)
    #
    O_nn  = np.diag(np.exp(1j*dlt*w_n))
    #
    if G_nn.dtype==complex:
        U_nn = np.dot(V_nn.T.conj(),np.dot(O_nn, V_nn)).copy()
    else:
        U_nn = np.dot(V_nn.T.conj(),np.dot(O_nn, V_nn)).real.copy()
    #        
    return U_nn
Exemplo n.º 4
0
    def diagonalize(self, H_sS):
        if self.coupling: # Non-Hermitian matrix can only use linalg.eig
            self.printtxt('Use numpy.linalg.eig')
            H_SS = np.zeros((self.nS, self.nS), dtype=complex)
            if self.nS % world.size == 0:
                world.all_gather(H_sS, H_SS)
            else:
                H_SS = gatherv(H_sS)

            self.w_S, self.v_SS = np.linalg.eig(H_SS)
            self.par_save('v_SS', 'v_SS', self.v_SS[self.nS_start:self.nS_end, :].copy())
        else:
            if world.size == 1:
                self.printtxt('Use lapack.')
                from gpaw.utilities.lapack import diagonalize
                self.w_S = np.zeros(self.nS)
                H_SS = H_sS
                diagonalize(H_SS, self.w_S)
                self.v_SS = H_SS.conj() # eigenvectors in the rows, transposed later
            else:
                self.printtxt('Use scalapack')
                self.w_S, self.v_sS = self.scalapack_diagonalize(H_sS)
                self.v_SS = self.v_sS # just use the same name
            self.par_save('v_SS', 'v_SS', self.v_SS)
        
        return 
Exemplo n.º 5
0
def ortho(W_nn, maxerr=1E-10):
    """ Orthogonalizes the column vectors of a matrix by Symmetric
        Loewdin orthogonalization

    W_nn: ndarray
        unorthonormal matrix.

    maxerr: float
        maximum error for using explicit diagonalization.

    """

    ndim = np.shape(W_nn)[1]

    # overlap matrix
    O_nn = np.dot(W_nn, W_nn.T.conj())

    # check error in orthonormality
    err = np.sum(np.abs(O_nn - np.eye(ndim)))
    if (err < maxerr):
        # perturbative Symmetric-Loewdin
        X_nn = 1.5 * np.eye(ndim) - 0.5 * O_nn
    else:
        # diagonalization
        n_n = np.zeros(ndim, dtype=float)
        diagonalize(O_nn, n_n)
        U_nn = O_nn.T.conj().copy()
        nsqrt_n = np.diag(1.0 / np.sqrt(n_n))
        X_nn = np.dot(np.dot(U_nn, nsqrt_n), U_nn.T.conj())

    # apply orthonormalizing transformation
    O_nn = np.dot(X_nn, W_nn)

    return O_nn
Exemplo n.º 6
0
    def diagonalize(self, H_sS):
        if self.coupling:  # Non-Hermitian matrix can only use linalg.eig
            self.printtxt('Use numpy.linalg.eig')
            H_SS = np.zeros((self.nS, self.nS), dtype=complex)
            if self.nS % world.size == 0:
                world.all_gather(H_sS, H_SS)
            else:
                H_SS = gatherv(H_sS)

            self.w_S, self.v_SS = np.linalg.eig(H_SS)
            self.par_save('v_SS', 'v_SS',
                          self.v_SS[self.nS_start:self.nS_end, :].copy())
        else:
            if world.size == 1:
                self.printtxt('Use lapack.')
                from gpaw.utilities.lapack import diagonalize
                self.w_S = np.zeros(self.nS)
                H_SS = H_sS
                diagonalize(H_SS, self.w_S)
                self.v_SS = H_SS.conj(
                )  # eigenvectors in the rows, transposed later
            else:
                self.printtxt('Use scalapack')
                self.w_S, self.v_sS = self.scalapack_diagonalize(H_sS)
                self.v_SS = self.v_sS  # just use the same name
            self.par_save('v_SS', 'v_SS', self.v_SS)

        return
Exemplo n.º 7
0
    def diagonalize(self,
                    istart=None,
                    jend=None,
                    energy_range=None,
                    TDA=False):
        """Evaluate Eigenvectors and Eigenvalues"""

        ApB, AmB = self.map(istart, jend, energy_range)
        nij = len(self.kss)

        if TDA:
            # Tamm-Dancoff approximation (B=0)
            self.eigenvectors = 0.5 * (ApB + AmB)
            eigenvalues = np.zeros((nij))
            diagonalize(self.eigenvectors, eigenvalues)
            self.eigenvalues = eigenvalues**2
        else:
            # the occupation matrix
            C = np.empty((nij, ))
            for ij in range(nij):
                C[ij] = 1. / self.kss[ij].fij

            S = C * inv(AmB) * C
            S = sqrt_matrix(inv(S).copy())

            # get Omega matrix
            M = np.zeros(ApB.shape)
            gemm(1.0, ApB, S, 0.0, M)
            self.eigenvectors = np.zeros(ApB.shape)
            gemm(1.0, S, M, 0.0, self.eigenvectors)

            self.eigenvalues = np.zeros((nij))
            diagonalize(self.eigenvectors, self.eigenvalues)
Exemplo n.º 8
0
    def diagonalize(self, istart=None, jend=None, energy_range=None, TDA=False):
        """Evaluate Eigenvectors and Eigenvalues"""

        ApB, AmB = self.map(istart, jend, energy_range)
        nij = len(self.kss)

        if TDA:
            # Tamm-Dancoff approximation (B=0)
            self.eigenvectors = 0.5 * (ApB + AmB)
            eigenvalues = np.zeros((nij))
            diagonalize(self.eigenvectors, eigenvalues)
            self.eigenvalues = eigenvalues ** 2
        else:
            # the occupation matrix
            C = np.empty((nij,))
            for ij in range(nij):
                C[ij] = 1.0 / self.kss[ij].fij

            S = C * inv(AmB) * C
            S = sqrt_matrix(inv(S).copy())

            # get Omega matrix
            M = np.zeros(ApB.shape)
            gemm(1.0, ApB, S, 0.0, M)
            self.eigenvectors = np.zeros(ApB.shape)
            gemm(1.0, S, M, 0.0, self.eigenvectors)

            self.eigenvalues = np.zeros((nij))
            diagonalize(self.eigenvectors, self.eigenvalues)
Exemplo n.º 9
0
    def diagonalize(self):

        print('Diagonalizing Hamiltonian', file=self.fd)
        """The t and T represent local and global
           eigenstates indices respectively
        """

        # Non-Hermitian matrix can only use linalg.eig
        if not self.td:
            print('  Using numpy.linalg.eig...', file=self.fd)
            print('  Eliminated %s pair orbitals' % len(self.excludef_S),
                  file=self.fd)

            self.H_SS = self.collect_A_SS(self.H_sS)
            self.w_T = np.zeros(self.nS - len(self.excludef_S), complex)
            if world.rank == 0:
                self.H_SS = np.delete(self.H_SS, self.excludef_S, axis=0)
                self.H_SS = np.delete(self.H_SS, self.excludef_S, axis=1)
                self.w_T, self.v_ST = np.linalg.eig(self.H_SS)
            world.broadcast(self.w_T, 0)
            self.df_S = np.delete(self.df_S, self.excludef_S)
            self.rhoG0_S = np.delete(self.rhoG0_S, self.excludef_S)
        # Here the eigenvectors are returned as complex conjugated rows
        else:
            if world.size == 1:
                print('  Using lapack...', file=self.fd)
                from gpaw.utilities.lapack import diagonalize
                self.w_T = np.zeros(self.nS)
                diagonalize(self.H_sS, self.w_T)
                self.v_St = self.H_sS.conj().T
            else:
                print('  Using scalapack...', file=self.fd)
                nS = self.nS
                ns = -(-self.kd.nbzkpts // world.size) * (self.nv * self.nc *
                                                          self.spins *
                                                          (self.spinors + 1)**2)
                grid = BlacsGrid(world, world.size, 1)
                desc = grid.new_descriptor(nS, nS, ns, nS)

                desc2 = grid.new_descriptor(nS, nS, 2, 2)
                H_tmp = desc2.zeros(dtype=complex)
                r = Redistributor(world, desc, desc2)
                r.redistribute(self.H_sS, H_tmp)

                self.w_T = np.empty(nS)
                v_tmp = desc2.empty(dtype=complex)
                desc2.diagonalize_dc(H_tmp, v_tmp, self.w_T)

                r = Redistributor(grid.comm, desc2, desc)
                self.v_St = desc.zeros(dtype=complex)
                r.redistribute(v_tmp, self.v_St)
                self.v_St = self.v_St.conj().T

        if self.write_v and self.td:
            # Cannot use par_save without td
            self.par_save('v_TS.ulm', 'v_TS', self.v_St.T)

        return
Exemplo n.º 10
0
def main(nbands=1000, mprocs=2, mb=64):
    # Set-up BlacsGrud
    grid = BlacsGrid(world, mprocs, mprocs)

    # Create descriptor
    nndesc = grid.new_descriptor(nbands, nbands, mb, mb)
    H_nn = nndesc.empty(
        dtype=float)  # outside the BlacsGrid these are size zero
    C_nn = nndesc.empty(
        dtype=float)  # outside the BlacsGrid these are size zero
    eps_N = np.empty((nbands),
                     dtype=float)  # replicated array on all MPI tasks
    # Fill ScaLAPACK array
    alpha = 0.1  # off-diagonal
    beta = 75.0  # diagonal
    uplo = 'L'  # lower-triangular
    scalapack_set(nndesc, H_nn, alpha, beta, uplo)
    scalapack_zero(nndesc, H_nn, switch_uplo[uplo])

    t1 = time()
    # either interface will work, we recommend use the latter interface
    # scalapack_diagonalize_dc(nndesc, H_nn.copy(), C_nn, eps_N, 'L')
    nndesc.diagonalize_dc(H_nn.copy(), C_nn, eps_N)
    t2 = time()
    world.broadcast(eps_N, 0)  # all MPI tasks now have eps_N
    world.barrier()  # wait for everyone to finish

    if rank == 0:
        print('ScaLAPACK diagonalize_dc', t2 - t1)

    # Create replicated NumPy array
    diagonal = np.eye(nbands, dtype=float)
    offdiagonal = np.tril(np.ones((nbands, nbands)), -1)
    H0 = beta * diagonal + alpha * offdiagonal
    E0 = np.empty((nbands), dtype=float)

    t1 = time()
    diagonalize(H0, E0)
    t2 = time()

    if rank == 0:
        print('LAPACK diagonalize', t2 - t1)

    delta = abs(E0 - eps_N).max()
    if rank == 0:
        print(delta)
        assert delta < tol
Exemplo n.º 11
0
    def diagonalize(self, istart=None, jend=None, energy_range=None):
        """Evaluate Eigenvectors and Eigenvalues:"""

        map, kss = self.get_map(istart, jend, energy_range)
        nij = len(kss)
        if map is None:
            evec = self.full.copy()
        else:
            evec = np.zeros((nij,nij))
            for ij in range(nij):
                for kq in range(nij):
                    evec[ij,kq] = self.full[map[ij],map[kq]]

        self.eigenvectors = evec        
        self.eigenvalues = np.zeros((len(kss)))
        self.kss = kss
        diagonalize(self.eigenvectors, self.eigenvalues)
Exemplo n.º 12
0
    def diagonalize(self, istart=None, jend=None, energy_range=None):
        """Evaluate Eigenvectors and Eigenvalues:"""

        map, kss = self.get_map(istart, jend, energy_range)
        nij = len(kss)
        if map is None:
            evec = self.full.copy()
        else:
            evec = np.zeros((nij, nij))
            for ij in range(nij):
                for kq in range(nij):
                    evec[ij, kq] = self.full[map[ij], map[kq]]

        self.eigenvectors = evec
        self.eigenvalues = np.zeros((len(kss)))
        self.kss = kss
        diagonalize(self.eigenvectors, self.eigenvalues)
def main(nbands=1000, mprocs=2, mb=64):
    # Set-up BlacsGrud
    grid = BlacsGrid(world, mprocs, mprocs)

    # Create descriptor
    nndesc = grid.new_descriptor(nbands, nbands, mb, mb)
    H_nn = nndesc.empty(dtype=float) # outside the BlacsGrid these are size zero
    C_nn = nndesc.empty(dtype=float) # outside the BlacsGrid these are size zero
    eps_N  = np.empty((nbands), dtype=float) # replicated array on all MPI tasks 
    # Fill ScaLAPACK array
    alpha = 0.1 # off-diagonal
    beta = 75.0 # diagonal
    uplo = 'L' # lower-triangular
    scalapack_set(nndesc, H_nn, alpha, beta, uplo)
    scalapack_zero(nndesc, H_nn, switch_uplo[uplo])

    t1 = time()
    # either interface will work, we recommend use the latter interface
    # scalapack_diagonalize_dc(nndesc, H_nn.copy(), C_nn, eps_N, 'L')
    nndesc.diagonalize_dc(H_nn.copy(), C_nn, eps_N) 
    t2 = time()
    world.broadcast(eps_N, 0) # all MPI tasks now have eps_N
    world.barrier() # wait for everyone to finish

    if rank == 0:
        print('ScaLAPACK diagonalize_dc', t2-t1)

    # Create replicated NumPy array    
    diagonal = np.eye(nbands,dtype=float)
    offdiagonal = np.tril(np.ones((nbands,nbands)), -1)
    H0 = beta*diagonal + alpha*offdiagonal
    E0 = np.empty((nbands), dtype=float)

    t1 = time()
    diagonalize(H0,E0)
    t2 = time()

    if rank == 0:
        print('LAPACK diagonalize', t2-t1)

    delta = abs(E0-eps_N).max()
    if rank == 0:
        print(delta)
        assert delta < tol
Exemplo n.º 14
0
    def diagonalize(self, istart=None, jend=None, energy_range=None,
                    TDA=False):
        """Evaluate Eigenvectors and Eigenvalues:"""

        if TDA:
            raise NotImplementedError

        map, kss = self.get_map(istart, jend, energy_range)
        nij = len(kss)
        if map is None:
            evec = self.full.copy()
        else:
            evec = np.zeros((nij,nij))
            for ij in range(nij):
                for kq in range(nij):
                    evec[ij,kq] = self.full[map[ij],map[kq]]
        assert(len(evec) > 0)

        self.eigenvectors = evec        
        self.eigenvalues = np.zeros((len(kss)))
        self.kss = kss
        diagonalize(self.eigenvectors, self.eigenvalues)
Exemplo n.º 15
0
def main(i,seed=42,dtype=float):
    if (dtype==complex):
        epsilon = 0.1j
    else:
        epsilon = 0.1
    x = i + 1
    N = x*100
    print "N =",N
    H0 = np.zeros((N,N),dtype=dtype) + gen.rand(*(N,N))
    H1 = H0 + epsilon*np.tri(N,N, k=-1)
    W0 = np.zeros((N))
    Z0 = np.zeros_like(H0)
    t0 = time()
    diagonalize(H1, W0)
    t1 = time() - t0
    print "diagonalize", t1
    t2 = time() 
    diagonalize_mr3(H1, W0, Z0)
    t3 = time() - t2
    print "diagonalize_mr3",t3
    # diagonalize_mr3 must be faster than diagonalize 
    assert(t3 < t1)
Exemplo n.º 16
0
def main(i, seed=42, dtype=float):
    if (dtype == complex):
        epsilon = 0.1j
    else:
        epsilon = 0.1
    x = i + 1
    N = x * 100
    print "N =", N
    H0 = np.zeros((N, N), dtype=dtype) + gen.rand(*(N, N))
    H1 = H0 + epsilon * np.tri(N, N, k=-1)
    W0 = np.zeros((N))
    Z0 = np.zeros_like(H0)
    t0 = time()
    diagonalize(H1, W0)
    t1 = time() - t0
    print "diagonalize", t1
    t2 = time()
    diagonalize_mr3(H1, W0, Z0)
    t3 = time() - t2
    print "diagonalize_mr3", t3
    # diagonalize_mr3 must be faster than diagonalize
    assert (t3 < t1)
Exemplo n.º 17
0
    def diagonalize(self, istart=None, jend=None, energy_range=None,
                    TDA=False):
        """Evaluate Eigenvectors and Eigenvalues:"""

        if TDA:
            raise NotImplementedError

        map, kss = self.get_map(istart, jend, energy_range)
        nij = len(kss)
        if map is None:
            evec = self.full.copy()
        else:
            evec = np.zeros((nij, nij))
            for ij in range(nij):
                for kq in range(nij):
                    evec[ij, kq] = self.full[map[ij], map[kq]]
        assert(len(evec) > 0)

        self.eigenvectors = evec
        self.eigenvalues = np.zeros((len(kss)))
        self.kss = kss
        diagonalize(self.eigenvectors, self.eigenvalues)
Exemplo n.º 18
0
def ortho(W_nn, maxerr=1E-10):

    """ Orthogonalizes the column vectors of a matrix by Symmetric
        Loewdin orthogonalization

    W_nn: ndarray
        unorthonormal matrix.
            
    maxerr: float
        maximum error for using explicit diagonalization.

    """

    ndim = np.shape(W_nn)[1]
    #
    # overlap matrix
    O_nn = np.dot(W_nn, W_nn.T.conj())
    #
    # check error in orthonormality
    err = np.sum(np.abs(O_nn - np.eye(ndim)))
    if (err < maxerr):
        #
        # perturbative Symmetric-Loewdin
        X_nn= 1.5*np.eye(ndim) - 0.5*O_nn    
    else:
        #
        # diagonalization
        n_n = np.zeros(ndim, dtype=float)
        diagonalize(O_nn, n_n)
        U_nn = O_nn.T.conj().copy()
        nsqrt_n = np.diag(1.0/np.sqrt(n_n))
        X_nn = np.dot(np.dot(U_nn, nsqrt_n), U_nn.T.conj())
    #
    # apply orthonormalizing transformation
    O_nn = np.dot(X_nn, W_nn)
    
    return O_nn
Exemplo n.º 19
0
        return eps, B
    elif nodes == 'all':
        if rank != 0:
            B = np.zeros((N, N))
        world.broadcast(B, 0)
        return eps, B


# generate a matrix
N = 512
A = np.arange(N**2, dtype=float).reshape(N, N)
for i in range(N):
    for j in range(i, N):
        A[i, j] = A[j, i]

# diagonalize
eps, B = scal_diagonalize(A)

check = 1
if check and rank == 0:
    # check whether it gives the same result with lapack
    eps1 = np.zeros(N)
    diagonalize(A, eps1)
    assert np.abs(eps - eps1).sum() < 1e-6

    for i in range(N // size):
        # the eigenvectors are row of the matrix, it can be differ by a minus sign.
        if np.abs(A[i, :] - B[i, :]).sum() > 1e-6:
            if np.abs(A[i, :] + B[i, :]).sum() > 1e-6:
                raise ValueError('Check !')
Exemplo n.º 20
0
def main(N=72, seed=42, mprocs=2, nprocs=2, dtype=float):
    gen = np.random.RandomState(seed)
    grid = BlacsGrid(world, mprocs, nprocs)

    if (dtype == complex):
        epsilon = 1.0j
    else:
        epsilon = 0.0

    # Create descriptors for matrices on master:
    glob = grid.new_descriptor(N, N, N, N)

    # print globA.asarray()
    # Populate matrices local to master:
    H0 = glob.zeros(dtype=dtype) + gen.rand(*glob.shape)
    S0 = glob.zeros(dtype=dtype) + gen.rand(*glob.shape)
    C0 = glob.empty(dtype=dtype)
    if rank == 0:
        # Complex case must have real numbers on the diagonal.
        # We make a simple complex Hermitian matrix below.
        H0 = H0 + epsilon * (0.1 * np.tri(N, N, k=-N // nprocs) +
                             0.3 * np.tri(N, N, k=-1))
        S0 = S0 + epsilon * (0.2 * np.tri(N, N, k=-N // nprocs) +
                             0.4 * np.tri(N, N, k=-1))
        # Make matrices symmetric
        rk(1.0, H0.copy(), 0.0, H0)
        rk(1.0, S0.copy(), 0.0, S0)
        # Overlap matrix must be semi-positive definite
        S0 = S0 + 50.0 * np.eye(N, N, 0)
        # Hamiltonian is usually diagonally dominant
        H0 = H0 + 75.0 * np.eye(N, N, 0)
        C0 = S0.copy()
        S0_inv = S0.copy()

    # Local result matrices
    W0 = np.empty((N), dtype=float)
    W0_g = np.empty((N), dtype=float)

    # Calculate eigenvalues / other serial results
    if rank == 0:
        diagonalize(H0.copy(), W0)
        general_diagonalize(H0.copy(), W0_g, S0.copy())
        inverse_cholesky(C0)  # result returned in lower triangle
        tri2full(S0_inv, 'L')
        S0_inv = inv(S0_inv)
        # tri2full(C0) # symmetrize

    assert glob.check(H0) and glob.check(S0) and glob.check(C0)

    # Create distributed destriptors with various block sizes:
    dist = grid.new_descriptor(N, N, 8, 8)

    # Distributed matrices:
    # We can use empty here, but end up with garbage on
    # on the other half of the triangle when we redistribute.
    # This is fine because ScaLAPACK does not care.

    H = dist.empty(dtype=dtype)
    S = dist.empty(dtype=dtype)
    Sinv = dist.empty(dtype=dtype)
    Z = dist.empty(dtype=dtype)
    C = dist.empty(dtype=dtype)
    Sinv = dist.empty(dtype=dtype)

    # Eigenvalues are non-BLACS matrices
    W = np.empty((N), dtype=float)
    W_dc = np.empty((N), dtype=float)
    W_mr3 = np.empty((N), dtype=float)
    W_g = np.empty((N), dtype=float)
    W_g_dc = np.empty((N), dtype=float)
    W_g_mr3 = np.empty((N), dtype=float)

    Glob2dist = Redistributor(world, glob, dist)
    Glob2dist.redistribute(H0, H, uplo='L')
    Glob2dist.redistribute(S0, S, uplo='L')
    Glob2dist.redistribute(S0, C, uplo='L')  # C0 was previously overwritten
    Glob2dist.redistribute(S0, Sinv, uplo='L')

    # we don't test the expert drivers anymore since there
    # might be a buffer overflow error
    ## scalapack_diagonalize_ex(dist, H.copy(), Z, W, 'L')
    scalapack_diagonalize_dc(dist, H.copy(), Z, W_dc, 'L')
    ## scalapack_diagonalize_mr3(dist, H.copy(), Z, W_mr3, 'L')
    ## scalapack_general_diagonalize_ex(dist, H.copy(), S.copy(), Z, W_g, 'L')
    scalapack_general_diagonalize_dc(dist, H.copy(), S.copy(), Z, W_g_dc, 'L')
    ## scalapack_general_diagonalize_mr3(dist, H.copy(), S.copy(), Z, W_g_mr3, 'L')

    scalapack_inverse_cholesky(dist, C, 'L')

    if dtype == complex:  # Only supported for complex for now
        scalapack_inverse(dist, Sinv, 'L')
    # Undo redistribute
    C_test = glob.empty(dtype=dtype)
    Sinv_test = glob.empty(dtype=dtype)
    Dist2glob = Redistributor(world, dist, glob)
    Dist2glob.redistribute(C, C_test)
    Dist2glob.redistribute(Sinv, Sinv_test)

    if rank == 0:
        ## diag_ex_err = abs(W - W0).max()
        diag_dc_err = abs(W_dc - W0).max()
        ## diag_mr3_err = abs(W_mr3 - W0).max()
        ## general_diag_ex_err = abs(W_g - W0_g).max()
        general_diag_dc_err = abs(W_g_dc - W0_g).max()
        ## general_diag_mr3_err = abs(W_g_mr3 - W0_g).max()
        inverse_chol_err = abs(C_test - C0).max()

        tri2full(Sinv_test, 'L')
        inverse_err = abs(Sinv_test - S0_inv).max()
        ## print 'diagonalize ex err', diag_ex_err
        print('diagonalize dc err', diag_dc_err)
        ## print 'diagonalize mr3 err', diag_mr3_err
        ## print 'general diagonalize ex err', general_diag_ex_err
        print('general diagonalize dc err', general_diag_dc_err)
        ## print 'general diagonalize mr3 err', general_diag_mr3_err
        print('inverse chol err', inverse_chol_err)
        if dtype == complex:
            print('inverse err', inverse_err)
    else:
        ## diag_ex_err = 0.0
        diag_dc_err = 0.0
        ## diag_mr3_err = 0.0
        ## general_diag_ex_err = 0.0
        general_diag_dc_err = 0.0
        ## general_diag_mr3_err = 0.0
        inverse_chol_err = 0.0
        inverse_err = 0.0

    # We don't like exceptions on only one cpu
    ## diag_ex_err = world.sum(diag_ex_err)
    diag_dc_err = world.sum(diag_dc_err)
    ## diag_mr3_err = world.sum(diag_mr3_err)
    ## general_diag_ex_err = world.sum(general_diag_ex_err)
    general_diag_dc_err = world.sum(general_diag_dc_err)
    ## general_diag_mr3_err = world.sum(general_diag_mr3_err)
    inverse_chol_err = world.sum(inverse_chol_err)
    inverse_err = world.sum(inverse_err)
    ## assert diag_ex_err < tol
    assert diag_dc_err < tol
    ## assert diag_mr3_err < tol
    ## assert general_diag_ex_err < tol
    assert general_diag_dc_err < tol
    ## assert general_diag_mr3_err < tol
    assert inverse_chol_err < tol
    if dtype == complex:
        assert inverse_err < tol
Exemplo n.º 21
0
 def _diagonalize(self, H_NN, eps_N):
     """Serial diagonalize via LAPACK."""
     # This is replicated computation but ultimately avoids
     # additional communication.
     diagonalize(H_NN, eps_N)
Exemplo n.º 22
0
def main(N=73, seed=42, mprocs=2, nprocs=2, dtype=float):
    gen = np.random.RandomState(seed)
    grid = BlacsGrid(world, mprocs, nprocs)
    
    if (dtype==complex):
        epsilon = 1.0j
    else:
        epsilon = 0.0

    # Create descriptors for matrices on master:
    glob = grid.new_descriptor(N, N, N, N)

    # print globA.asarray()
    # Populate matrices local to master:
    H0 = glob.zeros(dtype=dtype) + gen.rand(*glob.shape)
    S0 = glob.zeros(dtype=dtype) + gen.rand(*glob.shape)
    C0 = glob.empty(dtype=dtype)
    if rank == 0:
        # Complex case must have real numbers on the diagonal.
        # We make a simple complex Hermitian matrix below.
        H0 = H0 + epsilon * (0.1*np.tri(N, N, k= -N // nprocs) + 0.3*np.tri(N, N, k=-1))
        S0 = S0 + epsilon * (0.2*np.tri(N, N, k= -N // nprocs) + 0.4*np.tri(N, N, k=-1))
        # Make matrices symmetric
        rk(1.0, H0.copy(), 0.0, H0)
        rk(1.0, S0.copy(), 0.0, S0)
        # Overlap matrix must be semi-positive definite
        S0 = S0 + 50.0*np.eye(N, N, 0)
        # Hamiltonian is usually diagonally dominant
        H0 = H0 + 75.0*np.eye(N, N, 0)
        C0 = S0.copy()

    # Local result matrices
    W0 = np.empty((N),dtype=float)
    W0_g = np.empty((N),dtype=float)

    # Calculate eigenvalues
    if rank == 0:
        diagonalize(H0.copy(), W0)
        general_diagonalize(H0.copy(), W0_g, S0.copy())
        inverse_cholesky(C0) # result returned in lower triangle
        # tri2full(C0) # symmetrize
        
    assert glob.check(H0) and glob.check(S0) and glob.check(C0)

    # Create distributed destriptors with various block sizes:
    dist = grid.new_descriptor(N, N, 8, 8)

    # Distributed matrices:
    # We can use empty here, but end up with garbage on
    # on the other half of the triangle when we redistribute.
    # This is fine because ScaLAPACK does not care.

    H = dist.empty(dtype=dtype)
    S = dist.empty(dtype=dtype)
    Z = dist.empty(dtype=dtype)
    C = dist.empty(dtype=dtype)

    # Eigenvalues are non-BLACS matrices
    W = np.empty((N), dtype=float)
    W_dc = np.empty((N), dtype=float)
    W_mr3 = np.empty((N), dtype=float)
    W_g = np.empty((N), dtype=float)
    W_g_dc = np.empty((N), dtype=float)
    W_g_mr3 = np.empty((N), dtype=float)

    Glob2dist = Redistributor(world, glob, dist)
    Glob2dist.redistribute(H0, H, uplo='L')
    Glob2dist.redistribute(S0, S, uplo='L')
    Glob2dist.redistribute(S0, C, uplo='L') # C0 was previously overwritten

    # we don't test the expert drivers anymore since there
    # might be a buffer overflow error
    ## scalapack_diagonalize_ex(dist, H.copy(), Z, W, 'L')
    scalapack_diagonalize_dc(dist, H.copy(), Z, W_dc, 'L')
    ## scalapack_diagonalize_mr3(dist, H.copy(), Z, W_mr3, 'L')
    ## scalapack_general_diagonalize_ex(dist, H.copy(), S.copy(), Z, W_g, 'L')
    scalapack_general_diagonalize_dc(dist, H.copy(), S.copy(), Z, W_g_dc, 'L')
    ## scalapack_general_diagonalize_mr3(dist, H.copy(), S.copy(), Z, W_g_mr3, 'L')
    scalapack_inverse_cholesky(dist, C, 'L')

    # Undo redistribute
    C_test = glob.empty(dtype=dtype)
    Dist2glob = Redistributor(world, dist, glob)
    Dist2glob.redistribute(C, C_test)

    if rank == 0:
        ## diag_ex_err = abs(W - W0).max()
        diag_dc_err = abs(W_dc - W0).max()
        ## diag_mr3_err = abs(W_mr3 - W0).max()
        ## general_diag_ex_err = abs(W_g - W0_g).max()
        general_diag_dc_err = abs(W_g_dc - W0_g).max()
        ## general_diag_mr3_err = abs(W_g_mr3 - W0_g).max()
        inverse_chol_err = abs(C_test-C0).max()
        ## print 'diagonalize ex err', diag_ex_err
        print 'diagonalize dc err', diag_dc_err
        ## print 'diagonalize mr3 err', diag_mr3_err
        ## print 'general diagonalize ex err', general_diag_ex_err
        print 'general diagonalize dc err', general_diag_dc_err
        ## print 'general diagonalize mr3 err', general_diag_mr3_err
        print 'inverse chol err', inverse_chol_err 
    else:
        ## diag_ex_err = 0.0
        diag_dc_err = 0.0
        ## diag_mr3_err = 0.0
        ## general_diag_ex_err = 0.0
        general_diag_dc_err = 0.0
        ## general_diag_mr3_err = 0.0
        inverse_chol_err = 0.0

    # We don't like exceptions on only one cpu
    ## diag_ex_err = world.sum(diag_ex_err)
    diag_dc_err = world.sum(diag_dc_err)
    ## diag_mr3_err = world.sum(diag_mr3_err)
    ## general_diag_ex_err = world.sum(general_diag_ex_err)
    general_diag_dc_err = world.sum(general_diag_dc_err)
    ## general_diag_mr3_err = world.sum(general_diag_mr3_err) 
    inverse_chol_err = world.sum(inverse_chol_err)
    ## assert diag_ex_err < tol
    assert diag_dc_err < tol
    ## assert diag_mr3_err < tol
    ## assert general_diag_ex_err < tol
    assert general_diag_dc_err < tol
    ## assert general_diag_mr3_err < tol
    assert inverse_chol_err < tol
Exemplo n.º 23
0
from __future__ import print_function
import numpy as np
tol = 1e-8
a = np.eye(3, dtype=complex)
a[1:, 0] = 0.01j
w0 = [0.98585786, 1.0, 1.01414214]
# NumPy's Diagonalize
from numpy.linalg import eigh
w = eigh(a)[0]
print(w)
assert abs(w - w0).max() < tol
# LAPACK's QR Diagonalize
from gpaw.utilities.lapack import diagonalize
diagonalize(a.copy(), w)
print(w)
assert abs(w - w0).max() < tol
# LAPACK's MR3 Diagonalize
# Requires Netlib LAPACK 3.2.1 or later
# from gpaw.utilities.lapack import diagonalize_mr3
# z = np.zeros_like(a)
# diagonalize_mr3(a, w, z)
# print w
# assert abs(w - w0).max() < tol

Exemplo n.º 24
0
        if rank != 0:
            B = np.zeros((N, N))
        world.broadcast(B, 0)
        return eps, B
    

# generate a matrix
N = 512
A = np.arange(N**2,dtype=float).reshape(N,N)
for i in range(N):
    for j in range(i,N):
        A[i,j] = A[j,i]

# diagonalize
eps, B = scal_diagonalize(A)


check = 1
if check and rank == 0:
# check whether it gives the same result with lapack
    eps1 = np.zeros(N)
    diagonalize(A, eps1)
    assert np.abs(eps-eps1).sum() < 1e-6
    
    for i in range(N//size):
        # the eigenvectors are row of the matrix, it can be differ by a minus sign.
        if np.abs(A[i,:] - B[i,:]).sum() > 1e-6:
            if np.abs(A[i,:] + B[i,:]).sum() > 1e-6:
                raise ValueError('Check !')

Exemplo n.º 25
0
    def orthonormalize(self, wfs, kpt, psit_nG=None):
        """Orthonormalizes the vectors a_nG with respect to the overlap.

        First, a Cholesky factorization C is done for the overlap
        matrix S_nn = <a_nG | S | a_nG> = C*_nn C_nn Cholesky matrix C
        is inverted and orthonormal vectors a_nG' are obtained as::

          psit_nG' = inv(C_nn) psit_nG
                    __
           ~   _   \    -1   ~   _
          psi (r) = )  C    psi (r)
             n     /__  nm     m
                    m

        Parameters
        ----------

        psit_nG: ndarray, input/output
            On input the set of vectors to orthonormalize,
            on output the overlap-orthonormalized vectors.
        kpt: KPoint object:
            k-point object from kpoint.py.
        work_nG: ndarray
            Optional work array for overlap matrix times psit_nG.
        work_nn: ndarray
            Optional work array for overlap matrix.

        """
        self.timer.start('Orthonormalize')
        if psit_nG is None:
            psit_nG = kpt.psit_nG
        P_ani = kpt.P_ani
        self.timer.start('projections')
        wfs.pt.integrate(psit_nG, P_ani, kpt.q)
        self.timer.stop('projections')

        # Construct the overlap matrix:
        operator = wfs.matrixoperator

        def S(psit_G):
            return psit_G
        
        def dS(a, P_ni):
            return np.dot(P_ni, wfs.setups[a].dO_ii)

        self.timer.start('calc_s_matrix')
        S_nn = operator.calculate_matrix_elements(psit_nG, P_ani, S, dS)
        self.timer.stop('calc_s_matrix')

        orthonormalization_string = repr(self.ksl)
        self.timer.start(orthonormalization_string)
        #
        if extra_parameters.get('sic', False):
            #
            # symmetric Loewdin Orthonormalization
            tri2full(S_nn, UL='L', map=np.conj)
            nrm_n = np.empty(S_nn.shape[0])
            diagonalize(S_nn, nrm_n)
            nrm_nn = np.diag(1.0/np.sqrt(nrm_n))
            S_nn = np.dot(np.dot(S_nn.T.conj(), nrm_nn), S_nn)
        else:
            #
            self.ksl.inverse_cholesky(S_nn)
        # S_nn now contains the inverse of the Cholesky factorization.
        # Let's call it something different:
        C_nn = S_nn
        del S_nn
        self.timer.stop(orthonormalization_string)

        self.timer.start('rotate_psi')
        operator.matrix_multiply(C_nn, psit_nG, P_ani, out_nG=kpt.psit_nG)
        self.timer.stop('rotate_psi')
        self.timer.stop('Orthonormalize')
Exemplo n.º 26
0
    def orthonormalize(self, wfs, kpt, psit_nG=None):
        """Orthonormalizes the vectors a_nG with respect to the overlap.

        First, a Cholesky factorization C is done for the overlap
        matrix S_nn = <a_nG | S | a_nG> = C*_nn C_nn Cholesky matrix C
        is inverted and orthonormal vectors a_nG' are obtained as::

          psit_nG' = inv(C_nn) psit_nG
                    __
           ~   _   \    -1   ~   _
          psi (r) = )  C    psi (r)
             n     /__  nm     m
                    m

        Parameters
        ----------

        psit_nG: ndarray, input/output
            On input the set of vectors to orthonormalize,
            on output the overlap-orthonormalized vectors.
        kpt: KPoint object:
            k-point object from kpoint.py.
        work_nG: ndarray
            Optional work array for overlap matrix times psit_nG.
        work_nn: ndarray
            Optional work array for overlap matrix.

        """
        self.timer.start('Orthonormalize')
        if psit_nG is None:
            psit_nG = kpt.psit_nG
        P_ani = kpt.P_ani
        self.timer.start('projections')
        wfs.pt.integrate(psit_nG, P_ani, kpt.q)
        self.timer.stop('projections')

        # Construct the overlap matrix:
        operator = wfs.matrixoperator

        def S(psit_G):
            return psit_G
        
        def dS(a, P_ni):
            return np.dot(P_ni, wfs.setups[a].dO_ii)

        self.timer.start('calc_s_matrix')
        S_nn = operator.calculate_matrix_elements(psit_nG, P_ani, S, dS)
        self.timer.stop('calc_s_matrix')

        orthonormalization_string = repr(self.ksl)
        self.timer.start(orthonormalization_string)
        #
        if extra_parameters.get('sic', False):
            #
            # symmetric Loewdin Orthonormalization
            tri2full(S_nn, UL='L', map=np.conj)
            nrm_n = np.empty(S_nn.shape[0])
            diagonalize(S_nn, nrm_n)
            nrm_nn = np.diag(1.0/np.sqrt(nrm_n))
            S_nn = np.dot(np.dot(S_nn.T.conj(), nrm_nn), S_nn)
        else:
            #
            self.ksl.inverse_cholesky(S_nn)
        # S_nn now contains the inverse of the Cholesky factorization.
        # Let's call it something different:
        C_nn = S_nn
        del S_nn
        self.timer.stop(orthonormalization_string)

        self.timer.start('rotate_psi')
        operator.matrix_multiply(C_nn, psit_nG, P_ani, out_nG=kpt.psit_nG)
        self.timer.stop('rotate_psi')
        self.timer.stop('Orthonormalize')