Example #1
0
def para(gobj, mo10, mo_coeff, mo_occ, qed_fac=1):
    mol = gobj.mol
    effspin = mol.spin * .5
    muB = .5  # Bohr magneton
    #qed_fac = (nist.G_ELECTRON - 1)

    orboa = mo_coeff[0][:,mo_occ[0]>0]
    orbob = mo_coeff[1][:,mo_occ[1]>0]
    dm0a = numpy.dot(orboa, orboa.T)
    dm0b = numpy.dot(orbob, orbob.T)
    dm10a = [reduce(numpy.dot, (mo_coeff[0], x, orboa.T)) for x in mo10[0]]
    dm10b = [reduce(numpy.dot, (mo_coeff[1], x, orbob.T)) for x in mo10[1]]
    dm10a = numpy.asarray([x-x.T for x in dm10a])
    dm10b = numpy.asarray([x-x.T for x in dm10b])

    hso1e = uhf_g.make_h01_soc1e(gobj, mo_coeff, mo_occ, qed_fac)
    gpara1e =-numpy.einsum('xji,yij->xy', dm10a, hso1e)
    gpara1e+= numpy.einsum('xji,yij->xy', dm10b, hso1e)
    gpara1e *= 1./effspin / muB
    _write(gobj, align(gpara1e)[0], 'SOC(1e)/OZ')

    if gobj.para_soc2e:
        gpara2e = gobj.make_para_soc2e((dm0a,dm0b), (dm10a,dm10b), qed_fac)
        _write(gobj, align(gpara2e)[0], 'SOC(2e)/OZ')
    else:
        gpara2e = 0

    gpara = gpara1e + gpara2e
    return gpara
Example #2
0
def para(gobj, mo10, mo_coeff, mo_occ, qed_fac=1):
    mol = gobj.mol
    effspin = mol.spin * .5
    muB = .5  # Bohr magneton
    #qed_fac = (nist.G_ELECTRON - 1)

    orboa = mo_coeff[0][:,mo_occ[0]>0]
    orbob = mo_coeff[1][:,mo_occ[1]>0]
    dm0a = numpy.dot(orboa, orboa.T)
    dm0b = numpy.dot(orbob, orbob.T)
    dm10a = [reduce(numpy.dot, (mo_coeff[0], x, orboa.T)) for x in mo10[0]]
    dm10b = [reduce(numpy.dot, (mo_coeff[1], x, orbob.T)) for x in mo10[1]]
    dm10a = numpy.asarray([x-x.T for x in dm10a])
    dm10b = numpy.asarray([x-x.T for x in dm10b])

    hso1e = uhf_g.make_h01_soc1e(gobj, mo_coeff, mo_occ, qed_fac)
    gpara1e =-numpy.einsum('xji,yij->xy', dm10a, hso1e)
    gpara1e+= numpy.einsum('xji,yij->xy', dm10b, hso1e)
    gpara1e *= 1./effspin / muB
    _write(gobj, align(gpara1e)[0], 'SOC(1e)/OZ')

    if gobj.para_soc2e:
        gpara2e = gobj.make_para_soc2e((dm0a,dm0b), (dm10a,dm10b), qed_fac)
        _write(gobj, align(gpara2e)[0], 'SOC(2e)/OZ')
    else:
        gpara2e = 0

    gpara = gpara1e + gpara2e
    return gpara
Example #3
0
def make_fcdip(hfcobj, dm0, hfc_nuc=None, verbose=None):
    '''The contribution of Fermi-contact term and dipole-dipole interactions'''
    log = logger.new_logger(hfcobj, verbose)
    mol = hfcobj.mol
    if hfc_nuc is None:
        hfc_nuc = range(mol.natm)
    if isinstance(dm0, numpy.ndarray) and dm0.ndim == 2: # RHF DM
        return numpy.zeros((3,3))

    dma, dmb = dm0
    spindm = dma - dmb
    effspin = mol.spin * .5

    e_gyro = .5 * nist.G_ELECTRON
    nuc_mag = .5 * (nist.E_MASS/nist.PROTON_MASS)  # e*hbar/2m
    au2MHz = nist.HARTREE2J / nist.PLANCK * 1e-6
    fac = nist.ALPHA**2 / 2 / effspin * e_gyro * au2MHz

    hfc = []
    for i, atm_id in enumerate(hfc_nuc):
        nuc_gyro = get_nuc_g_factor(mol.atom_symbol(atm_id)) * nuc_mag
        h1 = _get_integrals_fcdip(mol, atm_id)
        fcsd = numpy.einsum('xyij,ji->xy', h1, spindm)

        h1fc = _get_integrals_fc(mol, atm_id)
        fc = numpy.einsum('ij,ji', h1fc, spindm)

        sd = fcsd + numpy.eye(3) * fc

        log.info('FC of atom %d  %s (in MHz)', atm_id, fac * nuc_gyro * fc)
        if hfcobj.verbose >= logger.INFO:
            _write(hfcobj, align(fac*nuc_gyro*sd)[0], 'SD of atom %d (in MHz)' % atm_id)
        hfc.append(fac * nuc_gyro * fcsd)
    return numpy.asarray(hfc)
Example #4
0
def make_fcdip(hfcobj, dm0, hfc_nuc=None, verbose=None):
    '''The contribution of Fermi-contact term and dipole-dipole interactions'''
    log = logger.new_logger(hfcobj, verbose)
    mol = hfcobj.mol
    if hfc_nuc is None:
        hfc_nuc = range(mol.natm)
    if isinstance(dm0, numpy.ndarray) and dm0.ndim == 2: # RHF DM
        return numpy.zeros((3,3))

    dma, dmb = dm0
    spindm = dma - dmb
    effspin = mol.spin * .5

    e_gyro = .5 * nist.G_ELECTRON
    nuc_mag = .5 * (nist.E_MASS/nist.PROTON_MASS)  # e*hbar/2m
    au2MHz = nist.HARTREE2J / nist.PLANCK * 1e-6
    fac = nist.ALPHA**2 / 2 / effspin * e_gyro * au2MHz

    hfc = []
    for i, atm_id in enumerate(hfc_nuc):
        nuc_gyro = get_nuc_g_factor(mol.atom_symbol(atm_id)) * nuc_mag
        h1 = _get_integrals_fcdip(mol, atm_id)
        fcsd = numpy.einsum('xyij,ji->xy', h1, spindm)

        h1fc = _get_integrals_fc(mol, atm_id)
        fc = numpy.einsum('ij,ji', h1fc, spindm)

        sd = fcsd + numpy.eye(3) * fc

        log.info('FC of atom %d  %s (in MHz)', atm_id, fac * nuc_gyro * fc)
        if hfcobj.verbose >= logger.INFO:
            _write(hfcobj, align(fac*nuc_gyro*sd)[0], 'SD of atom %d (in MHz)' % atm_id)
        hfc.append(fac * nuc_gyro * fcsd)
    return numpy.asarray(hfc)
Example #5
0
    def kernel(self, mo1=None):
        cput0 = (time.clock(), time.time())
        self.check_sanity()
        self.dump_flags()
        mol = self.mol

        dm0 = self._scf.make_rdm1()
        hfc_tensor = self.make_fcsd(dm0, self.hfc_nuc)
        hfc_tensor += self.make_pso_soc(self.hfc_nuc)

        logger.timer(self, 'HFC tensor', *cput0)
        if self.verbose > logger.QUIET:
            for i, atm_id in enumerate(self.hfc_nuc):
                _write(self, align(hfc_tensor[i])[0],
                       '\nHyperfine coupling tensor of atom %d %s (in MHz)'
                       % (atm_id, mol.atom_symbol(atm_id)))
        return hfc_tensor
Example #6
0
    def kernel(self, mo1=None):
        cput0 = (time.clock(), time.time())
        self.check_sanity()
        self.dump_flags()
        mol = self.mol

        dm0 = self._scf.make_rdm1()
        hfc_tensor = self.make_fcdip(dm0, self.hfc_nuc)
        hfc_tensor += self.make_pso_soc(self.hfc_nuc)

        logger.timer(self, 'HFC tensor', *cput0)
        if self.verbose > logger.QUIET:
            for i, atm_id in enumerate(self.hfc_nuc):
                _write(self, align(hfc_tensor[i])[0],
                       '\nHyperfine coupling tensor of atom %d %s (in MHz)'
                       % (atm_id, mol.atom_symbol(atm_id)))
        return hfc_tensor
Example #7
0
def make_pso_soc(hfcobj, hfc_nuc=None):
    '''Spin-orbit coupling correction'''
    mol = hfcobj.mol
    if hfc_nuc is None:
        hfc_nuc = range(mol.natm)

    mf = hfcobj._scf
    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    effspin = mol.spin * .5
    e_gyro = .5 * lib.param.G_ELECTRON
    nuc_mag = .5 * (lib.param.E_MASS/lib.param.PROTON_MASS)  # e*hbar/2m
    au2MHz = lib.param.HARTREE2J / lib.param.PLANCK * 1e-6
    fac = lib.param.ALPHA**4 / 4 / effspin * e_gyro * au2MHz

    occidxa = mo_occ[0] > 0
    occidxb = mo_occ[1] > 0
    orboa = mo_coeff[0][:, occidxa]
    orbva = mo_coeff[0][:,~occidxa]
    orbob = mo_coeff[1][:, occidxb]
    orbvb = mo_coeff[1][:,~occidxb]
    # Note sigma_z is considered in h1_soc integral.
    # mo1b has the associated sign (-)
    mo1a, mo1b = hfcobj.solve_mo1()[0]
    dm1a = _dm1_mo2ao(mo1a, orbva, orboa)
    dm1b = _dm1_mo2ao(mo1b, orbvb, orbob)
    dm1 = dm1a + dm1b
    dm1 = dm1 - dm1.transpose(0,2,1)

    para = []
    for n, atm_id in enumerate(hfc_nuc):
        nuc_gyro = get_nuc_g_factor(mol.atom_symbol(atm_id)) * nuc_mag
        # Imaginary part of H01 operator
        # Im[A01 dot p] = Im[vec{r}/r^3 x vec{p}] = Im[-i p (1/r) x p] = -p (1/r) x p
        mol.set_rinv_origin(mol.atom_coord(atm_id))
        h1ao = -mol.intor_asymmetric('int1e_prinvxp', 3)
        de = numpy.einsum('xij,yij->xy', h1ao, dm1)
        de *= fac * nuc_gyro
        if hfcobj.verbose >= logger.INFO:
            _write(hfcobj, align(de)[0], 'PSO of atom %d (in MHz)' % atm_id)
        para.append(de)
    return numpy.asarray(para)
Example #8
0
def make_pso_soc(hfcobj, hfc_nuc=None):
    '''Spin-orbit coupling correction'''
    mol = hfcobj.mol
    if hfc_nuc is None:
        hfc_nuc = range(mol.natm)

    mf = hfcobj._scf
    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    effspin = mol.spin * .5
    e_gyro = .5 * nist.G_ELECTRON
    nuc_mag = .5 * (nist.E_MASS/nist.PROTON_MASS)  # e*hbar/2m
    au2MHz = nist.HARTREE2J / nist.PLANCK * 1e-6
    fac = nist.ALPHA**4 / 4 / effspin * e_gyro * au2MHz

    occidxa = mo_occ[0] > 0
    occidxb = mo_occ[1] > 0
    orboa = mo_coeff[0][:, occidxa]
    orbva = mo_coeff[0][:,~occidxa]
    orbob = mo_coeff[1][:, occidxb]
    orbvb = mo_coeff[1][:,~occidxb]
    # Note sigma_z is considered in h1_soc integral.
    # mo1b has the associated sign (-)
    mo1a, mo1b = hfcobj.solve_mo1()[0]
    dm1a = _dm1_mo2ao(mo1a, orbva, orboa)
    dm1b = _dm1_mo2ao(mo1b, orbvb, orbob)
    dm1 = dm1a + dm1b
    dm1 = dm1 - dm1.transpose(0,2,1)

    para = []
    for n, atm_id in enumerate(hfc_nuc):
        nuc_gyro = get_nuc_g_factor(mol.atom_symbol(atm_id)) * nuc_mag
        # Imaginary part of H01 operator
        # Im[A01 dot p] = Im[vec{r}/r^3 x vec{p}] = Im[-i p (1/r) x p] = -p (1/r) x p
        mol.set_rinv_origin(mol.atom_coord(atm_id))
        h1ao = -mol.intor_asymmetric('int1e_prinvxp', 3)
        de = numpy.einsum('xij,yij->xy', h1ao, dm1)
        de *= fac * nuc_gyro
        if hfcobj.verbose >= logger.INFO:
            _write(hfcobj, align(de)[0], 'PSO of atom %d (in MHz)' % atm_id)
        para.append(de)
    return numpy.asarray(para)
Example #9
0
def make_fcsd(hfcobj, dm0, hfc_nuc=None, verbose=None):
    log = logger.new_logger(hfcobj, verbose)
    mol = hfcobj.mol
    if hfc_nuc is None:
        hfc_nuc = range(mol.natm)
    if isinstance(dm0, numpy.ndarray) and dm0.ndim == 2: # RHF DM
        return numpy.zeros((3,3))

    dma, dmb = dm0
    spindm = dma - dmb
    effspin = mol.spin * .5

    e_gyro = .5 * lib.param.G_ELECTRON
    nuc_mag = .5 * (lib.param.E_MASS/lib.param.PROTON_MASS)  # e*hbar/2m
    au2MHz = lib.param.HARTREE2J / lib.param.PLANCK * 1e-6
    fac = lib.param.ALPHA**2 / 2 / effspin * e_gyro * au2MHz

    coords = mol.atom_coords()
    ao = numint.eval_ao(mol, coords)

    nao = dma.shape[0]
    hfc = []
    for i, atm_id in enumerate(hfc_nuc):
        nuc_gyro = get_nuc_g_factor(mol.atom_symbol(atm_id)) * nuc_mag
        mol.set_rinv_origin(mol.atom_coord(atm_id))
# a01p[mu,sigma] the imaginary part of integral <vec{r}/r^3 cross p>
        a01p = mol.intor('int1e_sa01sp', 12).reshape(3,4,nao,nao)
        h1 = -(a01p[:,:3] + a01p[:,:3].transpose(0,1,3,2))
        fcsd = numpy.einsum('xyij,ji->xy', h1, spindm)
        fc = 8*numpy.pi/3 * numpy.einsum('i,j,ji', ao[atm_id], ao[atm_id], spindm)
        sd = fcsd - numpy.eye(3) * fc

        log.info('FC of atom %d  %s (in MHz)', atm_id, fac * nuc_gyro * fc)
        if hfcobj.verbose >= logger.INFO:
            _write(hfcobj, align(fac*nuc_gyro*sd)[0], 'SD of atom %d (in MHz)' % atm_id)
        hfc.append(fac * nuc_gyro * fcsd)
    return numpy.asarray(hfc)
Example #10
0
def make_para_soc2e(gobj, dm0, dm10, sso_qed_fac=1):
    if isinstance(gobj.para_soc2e, str):
        with_sso = 'SSO' in gobj.para_soc2e.upper()
        with_soo = 'SOO' in gobj.para_soc2e.upper()
        with_somf = 'SOMF' in gobj.para_soc2e.upper()
        with_amfi = 'AMFI' in gobj.para_soc2e.upper()
        assert(not (with_somf and (with_sso or with_soo)))
    elif gobj.para_soc2e:
        with_sso = with_soo = True
        with_somf = with_amfi = False
    else:
        with_sso = with_soo = with_somf = False
        with_amfi = True

    mol = gobj.mol
    alpha2 = nist.ALPHA ** 2
    effspin = mol.spin * .5
    muB = .5  # Bohr magneton
    #sso_qed_fac = (nist.G_ELECTRON - 1)

    mf = gobj._scf
    ni = mf._numint
    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, spin=mol.spin)
    if abs(omega) > 1e-10:
        raise NotImplementedError
    mem_now = lib.current_memory()[0]
    max_memory = max(2000, mf.max_memory*.9-mem_now)
    v1 = get_vxc_soc(ni, mol, mf.grids, mf.xc, dm0,
                     max_memory=max_memory, verbose=gobj.verbose)
    dm10a, dm10b = dm10
    if with_somf:
        ej = numpy.einsum('yil,xli->xy', v1[0]+v1[1], dm10a-dm10b)
    else:
        ej  = numpy.einsum('yil,xli->xy', v1[0], dm10a)
        ej -= numpy.einsum('yil,xli->xy', v1[1], dm10b)
    #ej *= -2  #Veff(-2X) approximation of JCP 122 034107

    gpara2e = 0
    if abs(hyb) > 1e-10:
        if with_amfi:
            vj, vk = uhf_g.get_jk_amfi(mol, dm0)
        else:
            vj, vk = uhf_g.get_jk(mol, dm0)
        if with_sso or with_soo:
            ek  = numpy.einsum('yil,xli->xy', vk[0], dm10a)
            ek -= numpy.einsum('yil,xli->xy', vk[1], dm10b)
            if with_sso:
                ej += numpy.einsum('yij,xji->xy', vj[0]+vj[1], dm10a-dm10b)
                gpara2e -= sso_qed_fac * (ej - hyb * ek)
            if with_soo:
                ej += numpy.einsum('yij,xji->xy', vj[0]-vj[1], dm10a+dm10b)
                gpara2e -= 2 * (ej - hyb * ek)
        else:  # SOMF, see JCP 122, 034107 Eq (19)
            ej += numpy.einsum('yij,xji->xy', vj[0]+vj[1], dm10a-dm10b)
            ek  = numpy.einsum('yil,xli->xy', vk[0]+vk[1], dm10a-dm10b)
            gpara2e -= ej - 1.5 * hyb * ek
    else:
        if with_amfi:
            vj = uhf_g.get_j_amfi(mol, dm0)
        else:
            vj = uhf_g.get_j(mol, dm0)
        if with_sso or with_soo:
            if with_sso:
                ej += numpy.einsum('yij,xji->xy', vj[0]+vj[1], dm10a-dm10b)
                gpara2e -= sso_qed_fac * ej
            if with_soo:
                ej += numpy.einsum('yij,xji->xy', vj[0]-vj[1], dm10a+dm10b)
                gpara2e -= 2 * ej
        else:  # SOMF, see JCP 122, 034107 Eq (19)
            ej += numpy.einsum('yij,xji->xy', vj[0]+vj[1], dm10a-dm10b)
            gpara2e -= ej

    gpara2e *= (alpha2/4) / effspin / muB
    if gobj.verbose >= logger.INFO:
        _write(gobj, align(gpara2e)[0], 'SOC(2e)/OZ')
    return gpara2e
Example #11
0
def make_para_soc2e(gobj, dm0, dm10, sso_qed_fac=1):
    if isinstance(gobj.para_soc2e, str):
        with_sso = 'SSO' in gobj.para_soc2e.upper()
        with_soo = 'SOO' in gobj.para_soc2e.upper()
        with_somf = 'SOMF' in gobj.para_soc2e.upper()
        with_amfi = 'AMFI' in gobj.para_soc2e.upper()
        assert(not (with_somf and (with_sso or with_soo)))
    elif gobj.para_soc2e:
        with_sso = with_soo = True
        with_somf = with_amfi = False
    else:
        with_sso = with_soo = with_somf = False
        with_amfi = True

    mol = gobj.mol
    alpha2 = nist.ALPHA ** 2
    effspin = mol.spin * .5
    muB = .5  # Bohr magneton
    #sso_qed_fac = (nist.G_ELECTRON - 1)

    mf = gobj._scf
    ni = mf._numint
    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, spin=mol.spin)
    if abs(omega) > 1e-10:
        raise NotImplementedError
    mem_now = lib.current_memory()[0]
    max_memory = max(2000, mf.max_memory*.9-mem_now)
    v1 = get_vxc_soc(ni, mol, mf.grids, mf.xc, dm0,
                     max_memory=max_memory, verbose=gobj.verbose)
    dm10a, dm10b = dm10
    if with_somf:
        ej = numpy.einsum('yil,xli->xy', v1[0]+v1[1], dm10a-dm10b)
    else:
        ej  = numpy.einsum('yil,xli->xy', v1[0], dm10a)
        ej -= numpy.einsum('yil,xli->xy', v1[1], dm10b)
    #ej *= -2  #Veff(-2X) approximation of JCP 122 034107

    gpara2e = 0
    if abs(hyb) > 1e-10:
        if with_amfi:
            vj, vk = uhf_g.get_jk_amfi(mol, dm0)
        else:
            vj, vk = uhf_g.get_jk(mol, dm0)
        if with_sso or with_soo:
            ek  = numpy.einsum('yil,xli->xy', vk[0], dm10a)
            ek -= numpy.einsum('yil,xli->xy', vk[1], dm10b)
            if with_sso:
                ej += numpy.einsum('yij,xji->xy', vj[0]+vj[1], dm10a-dm10b)
                gpara2e -= sso_qed_fac * (ej - hyb * ek)
            if with_soo:
                ej += numpy.einsum('yij,xji->xy', vj[0]-vj[1], dm10a+dm10b)
                gpara2e -= 2 * (ej - hyb * ek)
        else:  # SOMF, see JCP 122, 034107 Eq (19)
            ej += numpy.einsum('yij,xji->xy', vj[0]+vj[1], dm10a-dm10b)
            ek  = numpy.einsum('yil,xli->xy', vk[0]+vk[1], dm10a-dm10b)
            gpara2e -= ej - 1.5 * hyb * ek
    else:
        if with_amfi:
            vj = uhf_g.get_j_amfi(mol, dm0)
        else:
            vj = uhf_g.get_j(mol, dm0)
        if with_sso or with_soo:
            if with_sso:
                ej += numpy.einsum('yij,xji->xy', vj[0]+vj[1], dm10a-dm10b)
                gpara2e -= sso_qed_fac * ej
            if with_soo:
                ej += numpy.einsum('yij,xji->xy', vj[0]-vj[1], dm10a+dm10b)
                gpara2e -= 2 * ej
        else:  # SOMF, see JCP 122, 034107 Eq (19)
            ej += numpy.einsum('yij,xji->xy', vj[0]+vj[1], dm10a-dm10b)
            gpara2e -= ej

    gpara2e *= (alpha2/4) / effspin / muB
    if gobj.verbose >= logger.INFO:
        _write(gobj, align(gpara2e)[0], 'SOC(2e)/OZ')
    return gpara2e