Esempio n. 1
0
def _atom_gyro_list(mol):
    gyro = []
    for ia in range(mol.natm):
        symb = mol.atom_symbol(ia)
        if symb in mol.nucprop:
            prop = mol.nucprop[symb]
            mass = prop.get('mass', None)
            gyro.append(get_nuc_g_factor(symb, mass))
        else:
            # Get default isotope
            gyro.append(get_nuc_g_factor(symb))
    return numpy.array(gyro)
Esempio n. 2
0
def _atom_gyro_list(mol):
    gyro = []
    for ia in range(mol.natm):
        symb = mol.atom_symbol(ia)
        if symb in mol.nucprop:
            prop = mol.nucprop[symb]
            mass = prop.get('mass', None)
            gyro.append(get_nuc_g_factor(symb, mass))
        else:
            # Get default isotope
            gyro.append(get_nuc_g_factor(symb))
    return numpy.array(gyro)
Esempio n. 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)
Esempio n. 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)
Esempio n. 5
0
    def kernel(self, mo1=None):
        if len(self.nuc_pair) == 0:
            return

        cput0 = (time.clock(), time.time())
        self.check_sanity()
        self.dump_flags()
        mol = self.mol

        dm0 = self._scf.make_rdm1()
        mo_coeff = self._scf.mo_coeff
        mo_occ = self._scf.mo_occ

        ssc_dia = self.make_dso(mol, dm0)

        if mo1 is None:
            mo1 = self.mo10 = self.solve_mo1()[0]
        ssc_pso = self.make_pso(mol, mo1, mo_coeff, mo_occ)
        e11 = ssc_dia + ssc_pso
        if self.with_fcsd:
            ssc_fcsd = self.make_fcsd(self.nuc_pair)
            e11 += ssc_fcsd
        elif self.with_fc:
            ssc_fc = self.make_fc(self.nuc_pair)
            e11 += ssc_fc
        logger.timer(self, 'spin-spin coupling', *cput0)

        if self.verbose > logger.QUIET:
            nuc_mag = .5 * (nist.E_MASS / nist.PROTON_MASS)  # e*hbar/2m
            au2Hz = nist.HARTREE2J / nist.PLANCK
            #logger.debug('Unit AU -> Hz %s', au2Hz*nuc_mag**2)
            iso_ssc = au2Hz * nuc_mag**2 * numpy.einsum('kii->k', e11) / 3
            natm = mol.natm
            ktensor = numpy.zeros((natm, natm))
            for k, (i, j) in enumerate(self.nuc_pair):
                ktensor[i, j] = ktensor[j, i] = iso_ssc[k]
                if self.verbose >= logger.DEBUG:
                    _write(self.stdout, ssc_dia[k]+ssc_para[k],
                           '\nSSC E11 between %d %s and %d %s' \
                           % (i, self.mol.atom_symbol(i),
                              j, self.mol.atom_symbol(j)))


#                    _write(self.stdout, ssc_dia [k], 'dia-magnetism')
#                    _write(self.stdout, ssc_para[k], 'para-magnetism')

            gyro = [
                get_nuc_g_factor(mol.atom_symbol(ia)) for ia in range(natm)
            ]
            jtensor = numpy.einsum('ij,i,j->ij', ktensor, gyro, gyro)
            label = [
                '%2d %-2s' % (ia, mol.atom_symbol(ia)) for ia in range(natm)
            ]
            logger.note(self, 'Reduced spin-spin coupling constant K (Hz)')
            tools.dump_mat.dump_tri(self.stdout, ktensor, label)
            logger.info(self, '\nNuclear g factor %s', gyro)
            logger.note(self, 'Spin-spin coupling constant J (Hz)')
            tools.dump_mat.dump_tri(self.stdout, jtensor, label)
        return e11
Esempio n. 6
0
def kernel(hfcobj, with_gaunt=False, verbose=None):
    log = lib.logger.new_logger(hfcobj, verbose)
    mf = hfcobj._scf
    mol = mf.mol
    # Add finite field to remove degeneracy
    nuc_spin = numpy.ones(3) * 1e-6
    sc = numpy.dot(mf.get_ovlp(), mf.mo_coeff)
    h0 = reduce(numpy.dot, (sc * mf.mo_energy, sc.conj().T))
    c = lib.param.LIGHT_SPEED
    n4c = h0.shape[0]
    n2c = n4c // 2
    Sigma = numpy.zeros((3, n4c, n4c), dtype=h0.dtype)
    Sigma[:, :n2c, :n2c] = mol.intor('int1e_sigma_spinor', comp=3)
    Sigma[:, n2c:,
          n2c:] = .25 / c**2 * mol.intor('int1e_spsigmasp_spinor', comp=3)

    hfc = []
    for atm_id in range(mol.natm):
        symb = mol.atom_symbol(atm_id)
        nuc_mag = .5 * (nist.E_MASS / nist.PROTON_MASS)  # e*hbar/2m
        nuc_gyro = get_nuc_g_factor(symb) * nuc_mag
        e_gyro = .5 * nist.G_ELECTRON
        au2MHz = nist.HARTREE2J / nist.PLANCK * 1e-6
        fac = nist.ALPHA**2 * nuc_gyro * e_gyro * au2MHz
        #logger.debug('factor (MHz) %s', fac)

        h01 = make_h01(mol, 0)
        mo_occ = mf.mo_occ
        mo_coeff = mf.mo_coeff
        if 0:
            h01b = h0 + numpy.einsum('xij,x->ij', h01, nuc_spin)
            h01b = reduce(numpy.dot, (mf.mo_coeff.conj().T, h01b, mf.mo_coeff))
            mo_energy, v = numpy.linalg.eigh(h01b)
            mo_coeff = numpy.dot(mf.mo_coeff, v)
            mo_occ = mf.get_occ(mo_energy, mo_coeff)

        occidx = mo_occ > 0
        orbo = mo_coeff[:, occidx]
        dm0 = numpy.dot(orbo, orbo.T.conj())
        e01 = numpy.einsum('xij,ji->x', h01, dm0) * fac

        effspin = numpy.einsum('xij,ji->x', Sigma, dm0) * .5
        log.debug('atom %d Eff-spin %s', atm_id, effspin.real)

        e01 = (e01 / effspin).real
        hfc.append(e01)
    return numpy.asarray(hfc)
Esempio n. 7
0
def kernel(hfcobj, with_gaunt=False, verbose=None):
    log = lib.logger.new_logger(hfcobj, verbose)
    mf = hfcobj._scf
    mol = mf.mol
# Add finite field to remove degeneracy
    nuc_spin = numpy.ones(3) * 1e-6
    sc = numpy.dot(mf.get_ovlp(), mf.mo_coeff)
    h0 = reduce(numpy.dot, (sc*mf.mo_energy, sc.conj().T))
    c = lib.param.LIGHT_SPEED
    n4c = h0.shape[0]
    n2c = n4c // 2
    Sigma = numpy.zeros((3,n4c,n4c), dtype=h0.dtype)
    Sigma[:,:n2c,:n2c] = mol.intor('int1e_sigma_spinor', comp=3)
    Sigma[:,n2c:,n2c:] = .25/c**2 * mol.intor('int1e_spsigmasp_spinor', comp=3)

    hfc = []
    for atm_id in range(mol.natm):
        symb = mol.atom_symbol(atm_id)
        nuc_mag = .5 * (nist.E_MASS/nist.PROTON_MASS)  # e*hbar/2m
        nuc_gyro = get_nuc_g_factor(symb) * nuc_mag
        e_gyro = .5 * nist.G_ELECTRON
        au2MHz = nist.HARTREE2J / nist.PLANCK * 1e-6
        fac = nist.ALPHA**2 * nuc_gyro * e_gyro * au2MHz
        #logger.debug('factor (MHz) %s', fac)

        h01 = make_h01(mol, 0)
        mo_occ = mf.mo_occ
        mo_coeff = mf.mo_coeff
        if 0:
            h01b = h0 + numpy.einsum('xij,x->ij', h01, nuc_spin)
            h01b = reduce(numpy.dot, (mf.mo_coeff.conj().T, h01b, mf.mo_coeff))
            mo_energy, v = numpy.linalg.eigh(h01b)
            mo_coeff = numpy.dot(mf.mo_coeff, v)
            mo_occ = mf.get_occ(mo_energy, mo_coeff)

        occidx = mo_occ > 0
        orbo = mo_coeff[:,occidx]
        dm0 = numpy.dot(orbo, orbo.T.conj())
        e01 = numpy.einsum('xij,ji->x', h01, dm0) * fac

        effspin = numpy.einsum('xij,ji->x', Sigma, dm0) * .5
        log.debug('atom %d Eff-spin %s', atm_id, effspin.real)

        e01 = (e01 / effspin).real
        hfc.append(e01)
    return numpy.asarray(hfc)
Esempio n. 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)
Esempio n. 9
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)
Esempio n. 10
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]
    nocca = orboa.shape[1]
    nvira = orbva.shape[1]
    noccb = orbob.shape[1]
    nvirb = orbvb.shape[1]
    mo1a, mo1b = solve_mo1_pso(hfcobj, hfc_nuc)
    mo1a = mo1a.reshape(len(hfc_nuc),3,nvira,nocca)
    mo1b = mo1b.reshape(len(hfc_nuc),3,nvirb,noccb)
    dm0 = hfcobj._scf.make_rdm1()
    h1a, h1b = uhf_hfc.make_h1_soc(hfcobj, dm0)
    h1a = numpy.asarray([reduce(numpy.dot, (orbva.T, x, orboa)) for x in h1a])
    h1b = numpy.asarray([reduce(numpy.dot, (orbvb.T, x, orbob)) for x in h1b])
    para = []
    for n, atm_id in enumerate(hfc_nuc):
        nuc_gyro = get_nuc_g_factor(mol.atom_symbol(atm_id)) * nuc_mag
        e = numpy.einsum('xij,yij->xy', mo1a[n], h1a) * 2
        e+= numpy.einsum('xij,yij->xy', mo1b[n], h1b) * 2
        para.append(fac * nuc_gyro * e)
    return numpy.asarray(para)
Esempio n. 11
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]
    nocca = orboa.shape[1]
    nvira = orbva.shape[1]
    noccb = orbob.shape[1]
    nvirb = orbvb.shape[1]
    mo1a, mo1b = solve_mo1_pso(hfcobj, hfc_nuc)
    mo1a = mo1a.reshape(len(hfc_nuc), 3, nvira, nocca)
    mo1b = mo1b.reshape(len(hfc_nuc), 3, nvirb, noccb)
    dm0 = hfcobj._scf.make_rdm1()
    h1a, h1b = uhf_hfc.make_h1_soc(hfcobj, dm0)
    h1a = numpy.asarray([reduce(numpy.dot, (orbva.T, x, orboa)) for x in h1a])
    h1b = numpy.asarray([reduce(numpy.dot, (orbvb.T, x, orbob)) for x in h1b])
    para = []
    for n, atm_id in enumerate(hfc_nuc):
        nuc_gyro = get_nuc_g_factor(mol.atom_symbol(atm_id)) * nuc_mag
        e = numpy.einsum('xij,yij->xy', mo1a[n], h1a) * 2
        e += numpy.einsum('xij,yij->xy', mo1b[n], h1b) * 2
        para.append(fac * nuc_gyro * e)
    return numpy.asarray(para)
Esempio n. 12
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 * 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

    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)