示例#1
0
def H(W):
    '''
    H dot W where H is Harmiton operator
    @input:
        W: Expansion coefficients for Ns unconstrained wave functions, stored as 
            an (S0 * S1 * S2, Ns) matrix
    @global variables
        Vdual: Dual potential coefficients stored as a (S0 * S1 * S2, 1) column vector.
    @return:
        matrix of shape (S0 * S1 * S2, Ns)
    '''
    f = 2
    U = np.dot(W.conj().T, op.O(W))
    U_inv = np.linalg.inv(U)
    # each col of W_real represents W's value in sampled real space
    W_real = op.cI(W)
    n = f * op.diagouter(np.dot(W_real, U_inv), W_real)
    exc = excVWN(n)
    exc_prime = excpVWN(n)
    # electrostatic potential (phi) in freqency space
    phi = op.poisson(n, real_phi=False)
    Veff = gb_Vdual \
        + op.cJdag(op.O(phi)) \
        + op.cJdag(op.O(op.cJ(exc))) \
        + op.diagprod(exc_prime, op.cJdag(op.O(op.cJ(n))))
    HW_potential = op.cIdag(op.diagprod(Veff, op.cI(W)))
    HW_kinetic = -0.5 * op.L(W)
    HW = HW_kinetic + HW_potential
    return HW
示例#2
0
def getE(W):
    '''
    get the energy from expansion coefficients for Ns unconstrained wave function
    @input:
        W: Expansion coefficients for Ns unconstrained wave functions, stored as 
            an (S0 * S1 * S2, Ns) matrix
    @global variables
        Vdual: Dual potential coefficients stored as a (S0 * S1 * S2, 1) column vector.
    @return:
        E: Energies summed over Ns states
    '''
    f = 2
    U = np.dot(W.conj().T, op.O(W))
    U_inv = np.linalg.inv(U)
    # each col of W_real represents W's value in sampled real space
    W_real = op.cI(W)
    n = f * op.diagouter(np.dot(W_real, U_inv), W_real)
    E_potential = np.dot(gb_Vdual.T, n)
    E_kinetic = -0.5 * np.trace(np.dot(W.conj().T, op.L(np.dot(W, U_inv)))) * f
    # electrostatic potential (phi) in freqency space
    phi = op.poisson(n, real_phi=False)
    # E_hartree = 0.5 * np.dot(n.conj().T, op.cJdag(op.O(phi)))
    E_hartree = 0.5 * np.dot(op.cJ(n).conj().T, op.O(phi))
    exc = excVWN(n)
    # the Exc is negative here, which seems problematic.
    Exc = np.dot(op.cJ(n).conj().T, op.O(op.cJ(exc)))
    E = (E_potential + E_kinetic + E_hartree + Exc)[0, 0]
    E = E.real
    return E
示例#3
0
def H(W):
    '''
    H dot W where H is Harmiton operator
    @input:
        W: Expansion coefficients for Ns unconstrained wave functions, stored as 
            an (S0 * S1 * S2, Ns) matrix
    @global variables
        Vdual: Dual potential coefficients stored as a (S0 * S1 * S2, 1) column vector.
    @return:
        matrix of shape (S0 * S1 * S2, Ns)
    '''
    HW_kinetic = -0.5 * op.L(W)
    HW_potential = op.cIdag(op.diagprod(gb_Vdual, op.cI(W)))
    HW = HW_kinetic + HW_potential
    return HW
示例#4
0
def test_all():
    ns = 4
    W = np.random.rand(np.prod(global_vars.S),
                       ns) + 1j * np.random.rand(np.prod(global_vars.S), ns)
    W = orthonormalizeW(W)
    sd(W, 500)
    epsilon, Psi = getPsi(W)
    # in harmonic potential with w = 2, the energy level should be 3, 5, 5, 5
    print('energy levels: {:.3f}, {:.3f}, {:.3f}, {:.3f}'.format(
        epsilon[0], epsilon[1], epsilon[2], epsilon[3]))
    W_real = op.cI(W)
    electron_density = W_real.conj() * W_real
    vis_cell_3slice(electron_density[:, 0])  # s orbital
    vis_cell_3slice(electron_density[:, 1])  # p orbital
    vis_cell_3slice(electron_density[:, 2])  # p orbital
    return
示例#5
0
def getE(W):
    '''
    get the energy from expansion coefficients for Ns unconstrained wave function
    @input:
        W: Expansion coefficients for Ns unconstrained wave functions, stored as 
            an (S0 * S1 * S2, Ns) matrix
    @global variables
        Vdual: Dual potential coefficients stored as a (S0 * S1 * S2, 1) column vector.
    @return:
        E: Energies summed over Ns states
    '''
    U = np.dot(W.conj().T, op.O(W))
    U_inv = np.linalg.inv(U)
    W_real = op.cI(
        W)  # each col of W_real represents W's value in sampled real space
    n = op.diagouter(np.dot(W_real, U_inv), W_real)
    E_potential = np.dot(gb_Vdual.T, n)
    E_kinetic = -0.5 * np.trace(np.dot(W.conj().T, op.L(np.dot(W, U_inv))))
    E = (E_potential + E_kinetic)[0, 0]
    E = E.real
    return E
示例#6
0
sum_over_cell = lambda x: np.sum(x) * np.linalg.det(global_vars.R) / \
    (global_vars.S[0] * global_vars.S[1] * global_vars.S[2])  # sum(xdv)
sigma1, sigma2 = 0.75, 0.5
g1 = gen_gaussian3(dr, sigma1)
g2 = gen_gaussian3(dr, sigma2)
n = g2 - g1

if global_vars.is_debug:
    print(sum_over_cell(g1))
    print(sum_over_cell(g2))

net_charge = sum_over_cell(n)
print('net charge is {:.4f}'.format(net_charge))
assert net_charge < 1e-3, 'Current charge is not zero'

phi = op.cI(op.Linv(-4 * np.pi * op.O(op.cJ(n))))
# Due to rounding, tiny imaginary parts creep into the solution. Eliminate
# by taking the real part.
phi = np.real(phi)

# Unum = (0.5 * np.real(np.dot(op.cJ(phi).conj().T, op.O(op.cJ(n)))))[0, 0]
Unum = (0.5 * np.dot(phi.T, n)[0]) * (np.linalg.det(global_vars.R) /
                                      np.prod(global_vars.S))
Uanal = ((1 / sigma1 + 1 / sigma2) / 2 -
         np.sqrt(2) / np.sqrt(sigma1**2 + sigma2**2)) / np.sqrt(np.pi)
res_deviation = np.abs(Unum - Uanal)
print('Deviation between numerical and analytical results is {:.4f}'.format(
    res_deviation))
if global_vars.is_debug:
    print(Unum)
    print(Uanal)
示例#7
0
import numpy as np
import global_vars
import op
import vis

lattice_center = np.reshape(np.sum(global_vars.R / 2, axis=1), (1, -1))
dr = np.sqrt(np.sum((global_vars.r - lattice_center)**2, axis=1))
gen_gaussian3 = lambda x, sigma: np.exp(-(x**2) / (2 * sigma**2)) / (
    2 * np.pi * sigma**2)**(3 / 2)
sum_over_cell = lambda x: np.sum(x) * np.linalg.det(global_vars.R) / \
    (global_vars.S[0] * global_vars.S[1] * global_vars.S[2])  # sum(xdv)
sigma = 0.25
g1 = global_vars.Z * gen_gaussian3(dr, sigma)
n = op.cI(op.cJ(g1) * global_vars.Sf)
n = np.real(n)

net_charge = sum_over_cell(n)
print('net charge is {:.4f}'.format(net_charge))

vis.slice(n.reshape(global_vars.S[2], global_vars.S[1], global_vars.S[0]),
          'xy', global_vars.S[2] // 2)

# phi = op.cI(op.Linv(-4 * np.pi * op.O( op.cJ(n) )))
# # Due to rounding, tiny imaginary parts creep into the solution. Eliminate
# # by taking the real part.
# phi = np.real(phi)

# Unum = (0.5 * np.real(np.dot(op.cJ(phi).conj().T, op.O(op.cJ(n)))))[0, 0]
# Uself = global_vars.Z ** 2 / (2 * np.sqrt(np.pi)) * (1 / sigma) * global_vars.X.shape[0]
# res_deviation = np.abs(Unum - Uself)
# print('Deviation between numerical and analytical results is {:.4f}'.format(res_deviation))