Source code for edrixs.fock_basis

#!/usr/bin/env python

__all__ = ['combination', 'fock_bin', 'get_fock_bin_by_N', 'get_fock_half_N',
           'get_fock_full_N', 'get_fock_basis_by_NLz', 'get_fock_basis_by_NSz',
           'get_fock_basis_by_NJz', 'get_fock_basis_by_N_abelian',
           'get_fock_basis_by_N_LzSz', 'write_fock_dec_by_N']

import numpy as np
import itertools


[docs]def combination(n, m): """ Calculate the combination :math:`C_{n}^{m}`, .. math:: C_{n}^{m} = \\frac{n!}{m!(n-m)!}. Parameters ---------- n: int Number n. m: int Number m. Returns ------- res: int The calculated result. Examples -------- >>> import edrixs >>> edrixs.combination(6, 2) 15 """ if m > n or n < 0 or m < 0: print("wrong number in combination") return if m == 0 or n == m: return 1 largest = max(m, n - m) smallest = min(m, n - m) numer = 1.0 for i in range(largest + 1, n + 1): numer *= i denom = 1.0 for i in range(1, smallest + 1): denom *= i res = int(numer / denom) return res
[docs]def fock_bin(n, k): """ Return all the possible :math:`n`-length binary where :math:`k` of :math:`n` digitals are set to 1. Parameters ---------- n: int Binary length :math:`n`. k: int How many digitals are set to be 1. Returns ------- res: list of int-lists A list of list containing the binary digitals. Examples -------- >>> import edrixs >>> edrixs.fock_bin(4, 2) [[1, 1, 0, 0], [1, 0, 1, 0], [1, 0, 0, 1], [0, 1, 1, 0], [0, 1, 0, 1], [0, 0, 1, 1]] """ if n == 0: return [[0]] res = [] for bits in itertools.combinations(list(range(n)), k): s = [0] * n for bit in bits: s[bit] = 1 res.append(s) return res
[docs]def get_fock_bin_by_N(*args): """ Get binary form to represent a Fock state. Parameters ---------- args: ints args[0]: number of orbitals for 1st-shell, args[1]: number of occupancy for 1st-shell, args[2]: number of orbitals for 2nd-shell, args[3]: number of occupancy for 2nd-shell, ... args[ :math:`2N-2`]: number of orbitals for :math:`N` th-shell, args[ :math:`2N-1`]: number of occupancy for :math:`N` th-shell. Returns ------- result: list of int list The binary form of Fock states. Examples -------- >>> import edrixs >>> edrixs.get_fock_bin_by_N(4, 2) [[1, 1, 0, 0], [1, 0, 1, 0], [1, 0, 0, 1], [0, 1, 1, 0], [0, 1, 0, 1], [0, 0, 1, 1]] >>> edrixs.get_fock_bin_by_N(4, 2, 2, 1) [[1, 1, 0, 0, 1, 0], [1, 0, 1, 0, 1, 0], [1, 0, 0, 1, 1, 0], [0, 1, 1, 0, 1, 0], [0, 1, 0, 1, 1, 0], [0, 0, 1, 1, 1, 0], [1, 1, 0, 0, 0, 1], [1, 0, 1, 0, 0, 1], [1, 0, 0, 1, 0, 1], [0, 1, 1, 0, 0, 1], [0, 1, 0, 1, 0, 1], [0, 0, 1, 1, 0, 1]] """ n = len(args) if n % 2 != 0: print("Error: number of arguments is not even") return if n == 2: return fock_bin(args[0], args[1]) else: result = [] res1 = fock_bin(args[0], args[1]) res2 = get_fock_bin_by_N(*args[2:]) for ifock in res2: for jfock in res1: result.append(jfock + ifock) return result
def get_fock_half_N(N): res = [[] for i in range(N + 1)] for i in range(2**N): occu = bin(i).count('1') res[occu].append(i) return res
[docs]def get_fock_full_N(norb, N): """ Get the decimal digitals to represent Fock states. Parameters ---------- norb: int Number of orbitals. N: int Number of occupancy. Returns ------- res: list of int The decimal digitals to represent Fock states. Examples -------- >>> import edrixs >>> edrixs.fock_bin(4,2) [[1, 1, 0, 0], [1, 0, 1, 0], [0, 1, 1, 0], [1, 0, 0, 1], [0, 1, 0, 1], [0, 0, 1, 1]] >>> import edrixs >>> edrixs.get_fock_full_N(4,2) [3, 5, 6, 9, 10, 12] """ res = [] half_N = get_fock_half_N(norb // 2) for m in range(norb // 2 + 1): n = N - m if n >= 0 and n <= norb // 2: res.extend([i * 2**(norb // 2) + j for i in half_N[m] for j in half_N[n]]) return res
[docs]def get_fock_basis_by_NLz(norb, N, lz_list): """ Get decimal digitals to represent Fock states, use good quantum number: - orbital angular momentum :math:`L_{z}` Parameters ---------- norb: int Number of orbitals. N: int Number of total occupancy. lz_list: list of int Quantum number :math:`l_{z}` for each orbital. Returns ------- res: dict A dictionary containing the decimal digitals, the key is good quantum numbers :math:`L_{z}`, the value is a list of int. Examples -------- >>> import edrixs >>> edrixs.get_fock_basis_by_NLz(6, 2, [-1, -1, 0, 0, 1, 1]) { -2: [3], -1: [5, 6, 9, 10], 0: [12, 17, 18, 33, 34], 1: [20, 36, 24, 40], 2: [48] } """ res = get_fock_basis_by_N_abelian(norb, N, lz_list) return res
[docs]def get_fock_basis_by_NSz(norb, N, sz_list): """ Get decimal digitals to represent Fock states, use good quantum number: - spin angular momentum :math:`S_{z}` Parameters ---------- norb: int Number of orbitals. N: int Number of total occupancy. sz_list: list of int Quantum number :math:`s_{z}` for each orbital. Returns ------- res: dict A dictionary containing the decimal digitals, the key is good quantum numbers :math:`S_{z}`, the value is a list of int. Examples -------- >>> import edrixs >>> edrixs.get_fock_basis_by_NSz(6, 2, [1, -1, 1, -1, 1, -1]) { -2: [10, 34, 40], -1: [], 0: [3, 6, 9, 12, 18, 33, 36, 24, 48], 1: [], 2: [5, 17, 20] } """ res = get_fock_basis_by_N_abelian(norb, N, sz_list) return res
[docs]def get_fock_basis_by_NJz(norb, N, jz_list): """ Get decimal digitals to represent Fock states, use good quantum number: - total angular momentum :math:`J_{z}` Parameters ---------- norb: int Number of orbitals. N: int Number of total occupancy. jz_list: list of int Quantum number :math:`j_{z}` for each orbital. Returns ------- res: dict A dictionary containing the decimal digitals, the key is good quantum numbers :math:`j_{z}`, the value is a list of int. Examples -------- >>> import edrixs >>> edrixs.get_fock_basis_by_NJz(6, 2, [-1, 1, -3, -1, 1, 3]) { -6: [], -5: [], -4: [5, 12], -3: [], -2: [6, 9, 20], -1: [], 0: [3, 10, 17, 36, 24], 1: [], 2: [18, 33, 40], 3: [], 4: [34, 48], 5: [], 6: [] } """ res = get_fock_basis_by_N_abelian(norb, N, jz_list) return res
[docs]def get_fock_basis_by_N_abelian(norb, N, a_list): """ Get decimal digitals to represent Fock states, use some Abelian good quantum number. Parameters ---------- norb: int Number of orbitals. N: int Number of total occupancy. a_list: list of int Quantum number of the Abelian symmetry for each orbital. Returns ------- basis: dict A dictionary containing the decimal digitals, the key is good quantum numbers, the value is a list of int. """ result = get_fock_full_N(norb, N) min_a, max_a = min(a_list) * N, max(a_list) * N basis = {} for i in range(min_a, max_a + 1): basis[i] = [] for n in result: a = sum([a_list[i] for i in range(0, n.bit_length()) if (n >> i & 1)]) basis[a].append(n) return basis
[docs]def get_fock_basis_by_N_LzSz(norb, N, lz_list, sz_list): """ Get decimal digitals to represent Fock states, use good quantum number: - orbital angular momentum :math:`L_{z}` - spin angular momentum :math:`S_{z}` Parameters ---------- norb: int Number of orbitals. N: int Number of total occupancy. lz_list: list of int Quantum number :math:`l_{z}` for each orbital. sz_list: list of int Quantum number :math:`s_{z}` for each orbital. Returns ------- basis: dict A dictionary containing the decimal digitals, the key is a tuple containing good quantum numbers ( :math:`l_{z}`, :math:`s_{z}`), the value is a list of int. Examples -------- >>> import edrixs >>> edrixs.get_fock_basis_by_N_LzSz(6, 2, [-1, -1, 0, 0, 1, 1], [1, -1, 1, -1, 1, -1]) { (-2, -2): [], (-2, -1): [], (-2, 0): [3], (-2, 1): [], (-2, 2): [], (-1, -2): [10], (-1, -1): [], (-1, 0): [6, 9], (-1, 1): [], (-1, 2): [5], (0, -2): [34], (0, -1): [], (0, 0): [12, 18, 33], (0, 1): [], (0, 2): [17], (1, -2): [40], (1, -1): [], (1, 0): [36, 24], (1, 1): [], (1, 2): [20], (2, -2): [], (2, -1): [], (2, 0): [48], (2, 1): [], (2, 2): [] } """ result = get_fock_full_N(norb, N) min_Lz, max_Lz = min(lz_list) * N, max(lz_list) * N min_Sz, max_Sz = min(sz_list) * N, max(sz_list) * N basis = {} for i in range(min_Lz, max_Lz + 1): for j in range(min_Sz, max_Sz + 1): basis[(i, j)] = [] for n in result: Lz, Sz = np.sum([[lz_list[i], sz_list[i]] for i in range(0, n.bit_length()) if (n >> i & 1)], axis=0) basis[(Lz, Sz)].append(n) return basis
[docs]def write_fock_dec_by_N(N, r, fname='fock_i.in'): """ Get decimal digitals to represent Fock states, sort them by ascending order and then write them to file. Parameters ---------- N: int Number of orbitals. r: int Number of occuancy. fname: string File name. Returns ------- ndim: int The dimension of the Hilbert space Examples -------- >>> import edrixs >>> edrixs.write_fock_dec_by_N(4, 2, 'fock_i.in') file fock_i.in looks like 15 3 5 6 9 10 12 17 18 20 24 33 34 36 40 48 where, the first line is the total numer of Fock states, and the following lines are the Fock states in decimal form. """ res = get_fock_full_N(N, r) res.sort() ndim = len(res) f = open(fname, 'w') print(ndim, file=f) for item in res: print(item, file=f) f.close() return ndim