Example #1
0
def analyze_operator_blockbreaking(the_operator,
                                   the_blocks,
                                   block_labels=None):
    if block_labels is None:
        block_labels = np.arange(len(the_blocks), dtype=int)
    if isinstance(the_blocks[0], np.ndarray):
        c2s = np.concatenate(the_blocks, axis=1)
        assert (is_basis_orthonormal_and_complete(c2s)
                ), "Symmetry block problem? Not a complete, orthonormal basis."
        blocked_operator = represent_operator_in_basis(the_operator, c2s)
        blocked_idx = np.concatenate([[
            idx,
        ] * blk.shape[1] for idx, blk in enumerate(the_blocks)])
        c2l, op_svals, c2r = analyze_operator_blockbreaking(
            blocked_operator, blocked_idx, block_labels=block_labels)
        c2l = [c2s @ s2l for s2l in c2l]
        c2r = [c2s @ s2r for s2r in c2r]
        return c2l, op_svals, c2r
    elif np.asarray(the_blocks).dtype == np.asarray(block_labels).dtype:
        the_indices = np.empty(len(the_blocks), dtype=int)
        for idx, lbl in enumerate(block_labels):
            idx_indices = (the_blocks == lbl)
            the_indices[idx_indices] = idx
        the_blocks = the_indices
    c2l = []
    c2r = []
    op_svals = []
    norbs = the_operator.shape[0]
    my_range = [
        idx for idx, bl in enumerate(block_labels) if idx in the_blocks
    ]
    for idx1, idx2 in combinations(my_range, 2):
        blk1 = block_labels[idx1]
        blk2 = block_labels[idx2]
        idx12 = np.ix_(the_blocks == idx1, the_blocks == idx2)
        lvecs = np.eye(norbs, dtype=the_operator.dtype)[:, the_blocks == idx1]
        rvecs = np.eye(norbs, dtype=the_operator.dtype)[:, the_blocks == idx2]
        mat12 = the_operator[idx12]
        if is_matrix_zero(mat12):
            c2l.append(np.zeros((norbs, 0), dtype=the_operator.dtype))
            c2r.append(np.zeros((norbs, 0), dtype=the_operator.dtype))
            op_svals.append(np.zeros((0), dtype=the_operator.dtype))
            continue
        try:
            vecs1, svals, vecs2 = matrix_svd_control_options(
                mat12, sort_vecs=-1, only_nonzero_vals=False)
            lvecs = lvecs @ vecs1
            rvecs = rvecs @ vecs2
        except ValueError as e:
            if the_operator[idx12].size > 0: raise (e)
            c2l.append(np.zeros((norbs, 0), dtype=the_operator.dtype))
            c2r.append(np.zeros((norbs, 0), dtype=the_operator.dtype))
            op_svals.append(np.zeros((0), dtype=the_operator.dtype))
            continue
        #print ("Coupling between {} and {}: {} svals, norm = {}".format (idx1, idx2, len (svals), linalg.norm (svals)))
        c2l.append(lvecs)
        c2r.append(rvecs)
        op_svals.append(svals)
    return c2l, op_svals, c2r
Example #2
0
def are_bases_orthogonal(bra_basis,
                         ket_basis,
                         ovlp=1,
                         rtol=params.num_zero_rtol,
                         atol=params.num_zero_atol):
    test_matrix = basis_olap(bra_basis, ket_basis, ovlp)
    rtol *= sqrt(bra_basis.shape[1] * ket_basis.shape[1])
    atol *= sqrt(bra_basis.shape[1] * ket_basis.shape[1])
    return is_matrix_zero(test_matrix, rtol=rtol, atol=atol), test_matrix
Example #3
0
def count_linind_states (the_states, ovlp=1, num_zero_atol=params.num_zero_atol):
    c2b = np.asarray (the_states)
    b2c = c2b.conjugate ().T
    cOc = np.asarray (ovlp)
    nbas = c2b.shape[0]
    nstates = c2b.shape[1]
    bOb = b2c @ cOc @ c2b if cOc.shape == ((nbas, nbas)) else b2c @ c2b
    if is_matrix_zero (bOb) or np.abs (np.trace (bOb)) <= num_zero_atol: return 0
    evals = matrix_eigen_control_options (bOb, only_nonzero_vals=True)[0]
    return len (evals)
Example #4
0
def orthonormalize_a_basis (overlapping_basis, ovlp=1, num_zero_atol=params.num_zero_ltol, symmetry=None, enforce_symmetry=False):
    if (is_basis_orthonormal (overlapping_basis)):
        return overlapping_basis
    c2b = np.asarray (overlapping_basis)
    cOc = np.asarray (ovlp)
    if enforce_symmetry:
        c2n = np.zeros ((overlapping_basis.shape[0], 0), dtype=overlapping_basis.dtype)
        for c2s in symmetry:
            s2c = c2s.conjugate ().T
            s2b = s2c @ c2b
            sOs = s2c @ cOc @ c2s if cOc.shape == ((c2b.shape[0], c2b.shape[0])) else (s2c * cOc) @ c2s
            s2n = orthonormalize_a_basis (s2b, ovlp=sOs, num_zero_atol=num_zero_atol, symmetry=None, enforce_symmetry=False)
            c2n = np.append (c2n, c2s @ s2n, axis=1)
        return (c2n)

    b2c = c2b.conjugate ().T
    bOb = b2c @ cOc @ c2b if cOc.shape == ((c2b.shape[0], c2b.shape[0])) else (b2c * cOc) @ c2b
    assert (not is_matrix_zero (bOb)), "overlap matrix is zero! problem with basis?"
    assert (np.allclose (bOb, bOb.conjugate ().T)), "overlap matrix not hermitian! problem with basis?"
    assert (np.abs (np.trace (bOb)) > num_zero_atol), "overlap matrix zero or negative trace! problem with basis?"
     
    evals, evecs = matrix_eigen_control_options (bOb, sort_vecs=-1, only_nonzero_vals=True, num_zero_atol=num_zero_atol)
    if len (evals) == 0:
        return np.zeros ((c2b.shape[0], 0), dtype=c2b.dtype)
    p2x = np.asarray (evecs)
    c2x = c2b @ p2x 
    assert (not np.any (evals < 0)), "overlap matrix has negative eigenvalues! problem with basis?"

    # I want c2n = c2x * x2n
    # x2n defined such that n2c * c2n = I
    # n2x * x2c * c2x * x2n = n2x * evals_xx * x2n = I
    # therefore
    # x2n = evals_xx^{-1/2}
    x2n = np.asarray (np.diag (np.reciprocal (np.sqrt (evals))))
    c2n = c2x @ x2n
    n2c = c2n.conjugate ().T
    nOn = n2c @ cOc @ c2n if cOc.shape == ((c2b.shape[0], c2b.shape[0])) else (n2c * cOc) @ c2n
    if not is_basis_orthonormal (c2n):
        # Assuming numerical problem due to massive degeneracy; remove constant from diagonal to improve solver?
        assert (np.all (np.isclose (np.diag (nOn), 1))), np.diag (nOn) - 1
        nOn[np.diag_indices_from (nOn)] -= 1
        evals, evecs = matrix_eigen_control_options (nOn, sort_vecs=-1, only_nonzero_vals=False)
        n2x = np.asarray (evecs)
        c2x = c2n @ n2x
        x2n = np.asarray (np.diag (np.reciprocal (np.sqrt (evals + 1))))
        c2n = c2x @ x2n
        n2c = c2n.conjugate ().T
        nOn = n2c @ cOc @ c2n if cOc.shape == ((c2b.shape[0], c2b.shape[0])) else (n2c * cOc) @ c2n
        assert (is_basis_orthonormal (c2n)), "failed to orthonormalize basis even after two tries somehow\n" + str (
            prettyprint_ndarray (nOn)) + "\n" + str (np.linalg.norm (nOn - np.eye (c2n.shape[1]))) + "\n" + str (evals)

    return np.asarray (c2n)
Example #5
0
def is_operator_block_adapted (the_operator, the_blocks, tol=params.num_zero_atol):
    tol *= the_operator.shape[0]
    if isinstance (the_blocks[0], np.ndarray):
        umat = np.concatenate (the_blocks, axis=1)
        assert (is_basis_orthonormal_and_complete (umat)), 'Symmetry blocks must be orthonormal and complete, {}'.format (len (the_blocks))
        operator_block = represent_operator_in_basis (the_operator, umat)
        labels = np.concatenate ([[idx,] * blk.shape[1] for idx, blk in enumerate (the_blocks)])
        return is_operator_block_adapted (operator_block, labels)
    iterable = the_blocks if isinstance (the_blocks[0], np.ndarray) else np.unique (the_blocks)
    offblk_operator = the_operator.copy ()
    for blk in np.unique (the_blocks):
        offblk_operator[np.ix_(the_blocks==blk,the_blocks==blk)] = 0
    return is_matrix_zero (offblk_operator, atol=tol)