예제 #1
0
def test_recursive_single_commutator_1():
    h = hamiltonian_operator(2)
    t2e = cluster_operator(2)

    a = recursive_single_commutator([h, t2e], 3, (0, 6), n_process=4)
    b = single_commutator(h, t2e, for_commutator=True)
    assert a[1] == b
예제 #2
0
def test_single_commutator():
    h = hamiltonian_operator(2)
    t2e = cluster_operator(2)

    a = single_commutator(h, t2e, for_commutator=True)
    b = single_commutator(h, t2e, for_commutator=False, n_process=4)
    assert a == b
예제 #3
0
def test_contract_terms_1():
    h = hamiltonian_operator(2)
    t2e = cluster_operator(2, hole_label='c', particle_label='v')
    t2ee = cluster_operator(2, start=4, hole_label='c', particle_label='v')

    a = contract_terms([h, t2e, t2ee], max_cu=1, scale_factor=0.5, for_commutator=True, n_process=2)

    ref = {Term([make_tensor('H', 'c2,c3', 'v2,v3'),
                 make_tensor('t', 'c0,c1', 'v0,v2'), make_tensor('t', 'c2,c3', 'v1,v3')],
                make_sq('v0,v1', 'c0,c1'), -0.25),
           Term([make_tensor('H', 'c2,c3', 'v2,v3'),
                 make_tensor('t', 'c0,c1', 'v2,v3'), make_tensor('t', 'c2,c3', 'v0,v1')],
                make_sq('v0,v1', 'c0,c1'), 1.0/16.0),
           Term([make_tensor('H', 'c2,c3', 'v2,v3'),
                 make_tensor('t', 'c0,c2', 'v0,v1'), make_tensor('t', 'c1,c3', 'v2,v3')],
                make_sq('v0,v1', 'c0,c1'), -0.25),
           Term([make_tensor('H', 'c2,c3', 'v2,v3'),
                 make_tensor('t', 'c0,c2', 'v0,v2'), make_tensor('t', 'c1,c3', 'v1,v3')],
                make_sq('v0,v1', 'c0,c1'), 0.5),
           Term([make_tensor('H', 'v2,v3', 'g0,c3'),
                 make_tensor('t', 'c0,c1', 'v0,v2'), make_tensor('t', 'c2,c3', 'v1,v3')],
                make_sq('g0,v0,v1', 'c0,c1,c2'), -0.5),
           Term([make_tensor('H', 'v2,v3', 'g0,c3'),
                 make_tensor('t', 'c0,c3', 'v0,v1'), make_tensor('t', 'c1,c2', 'v2,v3')],
                make_sq('g0,v0,v1', 'c0,c1,c2'), 0.125),
           Term([make_tensor('H', 'c2,c3', 'g0,v3'),
                 make_tensor('t', 'c0,c1', 'v2,v3'), make_tensor('t', 'c2,c3', 'v0,v1')],
                make_sq('v0,v1,v2', 'g0,c0,c1'), -0.125),
           Term([make_tensor('H', 'c2,c3', 'g0,v3'),
                 make_tensor('t', 'c0,c2', 'v0,v1'), make_tensor('t', 'c1,c3', 'v2,v3')],
                make_sq('v0,v1,v2', 'g0,c0,c1'), 0.5)
           }

    for i in a:
        assert i in ref
예제 #4
0
def test_recursive_single_commutator_2():
    # Jacobi identity [[X, Y], Z] = [X, [Y, Z]] + [Y, [Z, X]] = [[X, Z], Y] + [[Z, Y], X]
    h = hamiltonian_operator(2)

    t1e = cluster_operator(1, start=4, hole_label='c', particle_label='v')
    t2e = cluster_operator(2, start=0, hole_label='c', particle_label='v')
    a = recursive_single_commutator([h, t2e, t1e], 1, (0, 6), n_process=4)

    t1e = cluster_operator(1, start=0, hole_label='c', particle_label='v')
    t2e = cluster_operator(2, start=4, hole_label='c', particle_label='v')
    b = recursive_single_commutator([h, t1e, t2e], 1, (0, 6), n_process=4)

    assert a[2] == b[2]  # note [t2e, t1e] = 0 for single reference
예제 #5
0
def test_recursive_single_commutator_3():
    # Jacobi identity [[X, Y], Z] = [X, [Y, Z]] + [Y, [Z, X]] = [[X, Z], Y] + [[Z, Y], X]
    h = hamiltonian_operator(2)

    t1e = cluster_operator(1, start=4)
    t2e = cluster_operator(2, start=0)
    a = recursive_single_commutator([h, t2e, t1e], 3, (0, 6), n_process=4)

    t1e = cluster_operator(1, start=0)
    t2e = cluster_operator(2, start=4)
    b = recursive_single_commutator([h, t1e, t2e], [2, 3], [(0, 4), (0, 6)], n_process=4)

    c = recursive_single_commutator([t1e, t2e, h], [2, 3], (0, 6), n_process=4)

    assert a[2] == combine_terms(b[2] + c[2])
예제 #6
0
def nested_commutator_cc(nested_level,
                         cluster_levels,
                         max_cu=3,
                         max_n_open=6,
                         min_n_open=0,
                         for_commutator=True,
                         expand_hole=True,
                         single_reference=False,
                         unitary=False,
                         n_process=1,
                         hermitian_tensor=True):
    """
    Compute the BCH nested commutator in coupled cluster theory.
    :param nested_level: the level of nested commutator
    :param cluster_levels: a list of integers for cluster operator, e.g., [1,2,3] for T1 + T2 + T3
    :param max_cu: max value of cumulant allowed for contraction
    :param max_n_open: the max number of open indices for contractions kept for return
    :param min_n_open: the min number of open indices for contractions kept for return
    :param for_commutator: compute only non-zero terms for commutators if True
    :param expand_hole: expand HoleDensity to Kronecker minus Cumulant if True
    :param single_reference: use single-reference amplitudes if True
    :param unitary: use unitary formalism if True
    :param n_process: number of processes launched for tensor canonicalization
    :param hermitian_tensor: assume tensors being Hermitian if True
    :return: a list of contracted canonicalized Term objects
    """
    if not isinstance(nested_level, int):
        raise ValueError("Invalid nested_level (must be an integer)")
    if not isinstance(cluster_levels, Iterable):
        raise ValueError("Invalid type for cluster_operator")
    if not all(isinstance(t, int) for t in cluster_levels):
        raise ValueError(
            "Invalid content in cluster_operator (must be all integers)")

    scale_factor = 1.0 / factorial(nested_level)
    out = []

    hole_label = 'c' if single_reference else 'h'
    particle_label = 'v' if single_reference else 'p'

    # symbolic evaluate nested commutator
    t = sum(Operator(f'T{i}') for i in cluster_levels)
    h = HermitianOperator('H1') + HermitianOperator('H2')
    a = t - Dagger(t) if unitary else t

    for term in sympy_nested_commutator_recursive(nested_level, h,
                                                  a).doit().expand().args:
        coeff, tensors = term.as_coeff_mul()
        factor = scale_factor * int(coeff)

        tensor_names = []
        for tensor in tensors:
            if isinstance(tensor, Pow):
                if isinstance(tensor.base, Dagger):
                    tensor_names += ['X' + str(tensor.base.args[0])[1:]] * int(
                        tensor.exp)
                else:
                    tensor_names += [str(tensor.base)] * int(tensor.exp)
            else:
                if isinstance(tensor, Dagger):
                    tensor_names.append('X' + str(tensor.args[0])[1:])
                else:
                    tensor_names.append(str(tensor))

        list_of_terms = []
        start = 0
        for name in tensor_names:
            real_name, n_body = name[0], int(name[1:])
            if real_name == 'T' or real_name == 'X':
                list_of_terms.append(
                    cluster_operator(n_body,
                                     start=start,
                                     excitation=(real_name == 'T'),
                                     hole_label=hole_label,
                                     particle_label=particle_label))
                start += n_body
            else:
                list_of_terms.append(hamiltonian_operator(n_body))

        out += contract_terms(list_of_terms, max_cu, max_n_open, min_n_open,
                              factor, for_commutator, expand_hole, n_process,
                              hermitian_tensor)

    return combine_terms(out)
예제 #7
0
def bch_cc_rsc(nested_level,
               cluster_levels,
               max_cu_levels,
               n_opens,
               for_commutator=True,
               expand_hole=True,
               single_reference=False,
               unitary=False,
               n_process=1,
               hermitian_tensor=True):
    """
    Compute the BCH nested commutator in coupled cluster theory using recursive commutator formalism.
    :param nested_level: the level of nested commutator
    :param cluster_levels: a list of integers for cluster operator, e.g., [1,2,3] for T1 + T2 + T3
    :param max_cu_levels: a list of integers for max cumulant level of each level of commutator
    :param n_opens: a list of tuple [(min, max)] for numbers of open indices of each level of commutator
    :param for_commutator: compute only non-zero terms for commutators if True
    :param expand_hole: expand HoleDensity to Kronecker minus Cumulant if True
    :param single_reference: use single-reference amplitudes if True
    :param unitary: use unitary formalism if True
    :param n_process: number of processes launched for tensor canonicalization
    :param hermitian_tensor: assume tensors being Hermitian if True
    :return: a map of nested level to a list of contracted canonicalized Term objects
    """
    if not isinstance(nested_level, int):
        raise ValueError("Invalid nested_level (must be an integer)")

    if not all(isinstance(t, int) for t in cluster_levels):
        raise ValueError(
            "Invalid content in cluster_operator (must be all integers)")

    if isinstance(max_cu_levels, int):
        max_cu_levels = [max_cu_levels] * nested_level
    if len(max_cu_levels) != nested_level:
        raise ValueError(
            f"Inconsistent size of max_cu_levels ({max_cu_levels}), required {nested_level}"
        )
    if any(not isinstance(i, int) for i in max_cu_levels):
        raise ValueError(
            f"Invalid max_cu_levels ({max_cu_levels}): not all integers")

    if isinstance(n_opens, tuple):
        n_opens = [n_opens] * nested_level
    if len(n_opens) != nested_level:
        raise ValueError(
            f"Inconsistent size of n_opens ({n_opens}), required {nested_level}"
        )
    for n in n_opens:
        if len(n) != 2:
            raise ValueError(
                f"Invalid element in n_opens: {n} cannot be used for min/max numbers of open indices."
            )
        if not (isinstance(n[0], int) and isinstance(n[1], int)):
            raise ValueError(
                f"Invalid element in n_opens: {n} contains non-integer elements"
            )

    max_amp = max(cluster_levels) * 2
    amps = [
        cluster_operators(cluster_levels,
                          start=(i * max_amp) + 4,
                          unitary=unitary,
                          single_reference=single_reference)
        for i in range(nested_level)
    ]

    out = defaultdict(list)
    out[0] = combine_terms([x for x in hamiltonian_operator(1).expand_composite_indices(True)]) + \
             combine_terms([x for x in hamiltonian_operator(2).expand_composite_indices(True)])

    left_pool = combine_terms([x for x in hamiltonian_operator(1).expand_composite_indices(True)]) + \
                combine_terms([x for x in hamiltonian_operator(2).expand_composite_indices(True)])

    for i in range(1, nested_level + 1):
        factor = 1.0 / i

        max_cu = max_cu_levels[i - 1]
        min_n_open, max_n_open = n_opens[i - 1]

        for left in left_pool:
            for right in amps[i - 1]:
                out[i] += single_commutator(left, right, max_cu, max_n_open,
                                            min_n_open, factor, for_commutator,
                                            expand_hole, n_process,
                                            hermitian_tensor)

        out[i] = combine_terms([Term.from_term(term) for term in out[i]])
        left_pool = [Term.from_term(term) for term in out[i]]

    return out