Example #1
0
def _core_val_ryd_list(mol):
    from pyscf.gto.ecp import core_configuration
    count = numpy.zeros((mol.natm, 9), dtype=int)
    core_lst = []
    val_lst = []
    rydbg_lst = []
    k = 0
    for ib in range(mol.nbas):
        ia = mol.bas_atom(ib)
# Avoid calling mol.atom_charge because we should include ECP core electrons here
        nuc = mole._charge(mol.atom_symbol(ia))
        l = mol.bas_angular(ib)
        nc = mol.bas_nctr(ib)
        symb = mol.atom_symbol(ia)
        nelec_ecp = mol.atom_nelec_core(ia)
        ecpcore = core_configuration(nelec_ecp)
        coreshell = [int(x) for x in AOSHELL[nuc][0][::2]]
        cvshell = [int(x) for x in AOSHELL[nuc][1][::2]]
        for n in range(nc):
            if l > 3:
                rydbg_lst.extend(range(k, k+(2*l+1)))
            elif ecpcore[l]+count[ia,l]+n < coreshell[l]:
                core_lst.extend(range(k, k+(2*l+1)))
            elif ecpcore[l]+count[ia,l]+n < cvshell[l]:
                val_lst.extend(range(k, k+(2*l+1)))
            else:
                rydbg_lst.extend(range(k, k+(2*l+1)))
            k = k + 2*l+1
        count[ia,l] += nc
    return core_lst, val_lst, rydbg_lst
Example #2
0
    def __init__(self, atoms, basis=None):
        self.atomtypes = mole.atom_types(atoms, basis)
        # fake systems, which treates the atoms of different basis as different atoms.
        # the fake systems do not have the same symmetry as the potential
        # it's only used to determine the main (Z-)axis
        chg1 = numpy.pi - 2
        coords = []
        fake_chgs = []
        idx = []
        for k, lst in self.atomtypes.items():
            idx.append(lst)
            coords.append([atoms[i][1] for i in lst])
            ksymb = mole._rm_digit(k)
            if ksymb != k or ksymb == 'GHOST':
                fake_chgs.append([chg1] * len(lst))
                chg1 *= numpy.pi-2
            else:
                fake_chgs.append([mole._charge(ksymb)] * len(lst))
        coords = numpy.array(numpy.vstack(coords), dtype=float)
        fake_chgs = numpy.hstack(fake_chgs)
        self.charge_center = numpy.einsum('i,ij->j', fake_chgs, coords)/fake_chgs.sum()
        coords = coords - self.charge_center
        self.im = numpy.einsum('i,ij,ik->jk', fake_chgs, coords, coords)/fake_chgs.sum()

        idx = numpy.argsort(numpy.hstack(idx))
        self.atoms = numpy.hstack((fake_chgs.reshape(-1,1), coords))[idx]
Example #3
0
def para(mol, mo1, mo_coeff, mo_occ, hfc_nuc=None):
    if hfc_nuc is None:
        hfc_nuc = range(mol.natm)

    effspin = mol.spin * .5
    mu_B = 1  # lib.param.BOHR_MAGNETON
    mu_N = lib.param.PROTON_MASS * mu_B
    fac = lib.param.ALPHA / 2 / effspin
    fac *= lib.param.G_ELECTRON * mu_B * mu_N

    occidxa = mo_occ[0] > 0
    occidxb = mo_occ[1] > 0
    orboa = mo_coeff[0][:, occidxa]
    orbob = mo_coeff[1][:, occidxb]
    nao = mo_coeff[0].shape[0]
    dm10 = numpy.empty((3, nao, nao))
    for i in range(3):
        dm10[i] = reduce(numpy.dot, (mo_coeff[0], mo1[0][i], orboa.conj().T))
        dm10[i] += reduce(numpy.dot, (mo_coeff[1], mo1[1][i], orbob.conj().T))
    para = numpy.empty((len(hfc_nuc), 3, 3))
    for n, atm_id in enumerate(hfc_nuc):
        Z = mole._charge(mol.atom_symbol(atm_id))
        nuc_spin, g_nuc = parameters.ISOTOPE[Z][1:3]
        gyromag = 1e-6 / (
            2 * numpy.pi) * parameters.g_factor_to_gyromagnetic_ratio(g_nuc)

        mol.set_rinv_origin(mol.atom_coord(atm_id))
        h01 = mol.intor_asymmetric('int1e_prinvxp', 3)
        para[n] = numpy.einsum('xji,yij->yx', dm10, h01) * 2
        para[n] *= fac * gyromag
    return para
Example #4
0
def get_inertia_momentum(atoms, basis):
    charge = numpy.array([mole._charge(a[0]) for a in atoms])
    coords = numpy.array([a[1] for a in atoms], dtype=float)
    rbar = numpy.einsum('i,ij->j', charge, coords)/charge.sum()
    coords = coords - rbar
    im = numpy.einsum('i,ij,ik->jk', charge, coords, coords)/charge.sum()
    return im
Example #5
0
def _core_val_ryd_list(mol):
    from pyscf.gto.ecp import core_configuration

    count = numpy.zeros((mol.natm, 9), dtype=int)
    core_lst = []
    val_lst = []
    rydbg_lst = []
    k = 0
    for ib in range(mol.nbas):
        ia = mol.bas_atom(ib)
        # Avoid calling mol.atom_charge because we should include ECP core electrons here
        nuc = mole._charge(mol.atom_symbol(ia))
        l = mol.bas_angular(ib)
        nc = mol.bas_nctr(ib)
        symb = mol.atom_symbol(ia)
        nelec_ecp = mol.atom_nelec_core(ia)
        ecpcore = core_configuration(nelec_ecp)
        coreshell = [int(x) for x in AOSHELL[nuc][0][::2]]
        cvshell = [int(x) for x in AOSHELL[nuc][1][::2]]
        for n in range(nc):
            if l > 3:
                rydbg_lst.extend(range(k, k + (2 * l + 1)))
            elif ecpcore[l] + count[ia, l] + n < coreshell[l]:
                core_lst.extend(range(k, k + (2 * l + 1)))
            elif ecpcore[l] + count[ia, l] + n < cvshell[l]:
                val_lst.extend(range(k, k + (2 * l + 1)))
            else:
                rydbg_lst.extend(range(k, k + (2 * l + 1)))
            k = k + 2 * l + 1
        count[ia, l] += nc
    return core_lst, val_lst, rydbg_lst
Example #6
0
File: geom.py Project: pengdl/pyscf
    def __init__(self, atoms, basis=None):
        self.atomtypes = mole.atom_types(atoms, basis)
        # fake systems, which treates the atoms of different basis as different atoms.
        # the fake systems do not have the same symmetry as the potential
        # it's only used to determine the main (Z-)axis
        chg1 = numpy.pi - 2
        coords = []
        fake_chgs = []
        idx = []
        for k, lst in self.atomtypes.items():
            idx.append(lst)
            coords.append([atoms[i][1] for i in lst])
            ksymb = mole._rm_digit(k)
            if ksymb != k or ksymb == 'GHOST':
                # Put random charges on the decorated atoms
                fake_chgs.append([chg1] * len(lst))
                chg1 *= numpy.pi-2
            else:
                fake_chgs.append([mole._charge(ksymb)] * len(lst))
        coords = numpy.array(numpy.vstack(coords), dtype=float)
        fake_chgs = numpy.hstack(fake_chgs)
        self.charge_center = numpy.einsum('i,ij->j', fake_chgs, coords)/fake_chgs.sum()
        coords = coords - self.charge_center
        self.im = numpy.einsum('i,ij,ik->jk', fake_chgs, coords, coords)/fake_chgs.sum()

        idx = numpy.argsort(numpy.hstack(idx))
        self.atoms = numpy.hstack((fake_chgs.reshape(-1,1), coords))[idx]
Example #7
0
    def __init__(self, atoms, basis=None):
        self.atomtypes = mole.atom_types(atoms, basis)
        # fake systems, which treates the atoms of different basis as different atoms.
        # the fake systems do not have the same symmetry as the potential
        # it's only used to determine the main (Z-)axis
        chg1 = numpy.pi - 2
        coords = []
        fake_chgs = []
        idx = []
        for k, lst in self.atomtypes.items():
            idx.append(lst)
            coords.append([atoms[i][1] for i in lst])
            ksymb = mole._rm_digit(k)
            if ksymb != k:
                # Put random charges on the decorated atoms
                fake_chgs.append([chg1] * len(lst))
                chg1 *= numpy.pi - 2
            elif 'GHOST' in ksymb:
                ksymb = mole._remove_prefix_ghost(ksymb)
                fake_chgs.append([mole._charge(ksymb) + .3] * len(lst))
            else:
                fake_chgs.append([mole._charge(ksymb)] * len(lst))
        coords = numpy.array(numpy.vstack(coords), dtype=float)
        fake_chgs = numpy.hstack(fake_chgs)
        self.charge_center = numpy.einsum('i,ij->j', fake_chgs,
                                          coords) / fake_chgs.sum()
        coords = coords - self.charge_center

        idx = numpy.argsort(numpy.hstack(idx))
        self.atoms = numpy.hstack((fake_chgs.reshape(-1, 1), coords))[idx]

        self.group_atoms_by_distance = []
        decimals = int(-numpy.log10(TOLERANCE)) - 1
        for index in self.atomtypes.values():
            index = numpy.asarray(index)
            c = self.atoms[index, 1:]
            dists = numpy.around(norm(c, axis=1), decimals)
            u, idx = numpy.unique(dists, return_inverse=True)
            for i, s in enumerate(u):
                self.group_atoms_by_distance.append(index[idx == i])
Example #8
0
def dia(gobj, mol, dm0, hfc_nuc=None, verbose=None):
    log = logger.new_logger(gobj, verbose)
    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

    mu_B = 1  # lib.param.BOHR_MAGNETON
    mu_N = lib.param.PROTON_MASS * mu_B
    fac = lib.param.ALPHA / 2 / effspin
    fac *= lib.param.G_ELECTRON * mu_B * mu_N

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

    nao = dma.shape[0]
    dia = []
    for i, atm_id in enumerate(hfc_nuc):
        Z = mole._charge(mol.atom_symbol(atm_id))
        nuc_spin, g_nuc = parameters.ISOTOPE[Z][1:3]
        # g factor of other isotopes can be found in file nuclear_g_factor.dat
        gyromag = 1e-6 / (
            2 * numpy.pi) * parameters.g_factor_to_gyromagnetic_ratio(g_nuc)
        log.info(
            'Atom %d %s  nuc-spin %g  nuc-g-factor %g  gyromagnetic ratio %g (in MHz)',
            atm_id, mol.atom_symbol(atm_id), nuc_spin, g_nuc, gyromag)
        mol.set_rinv_origin(mol.atom_coord(atm_id))
        # a01p[mu,sigma] the imaginary part of integral <vec{r}/r^3 cross p>
        # mu = gN * I * mu_N
        a01p = mol.intor('int1e_sa01sp', 12).reshape(3, 4, nao, nao)
        h11 = a01p[:, 1:] - a01p[:, 1:].transpose(0, 1, 3, 2)
        e11 = numpy.einsum('xyij,ji->xy', h11, spindm)
        e11 *= fac * gyromag
        # e11 includes fermi-contact and spin-dipolar contriutions and a rank-2 contact
        # term.  We ignore the contribution of rank-2 contact term, view it as part of
        # SD contribution.  See also TCA, 73, 173
        fermi_contact = (
            4 * numpy.pi / 3 * fac * gyromag *
            numpy.einsum('i,j,ji', ao[atm_id], ao[atm_id], spindm))
        dip = e11 - numpy.eye(3) * fermi_contact
        log.info('FC %s', fermi_contact)
        if gobj.verbose >= logger.INFO:
            _write(gobj, dip, 'SD')
        dia.append(e11)
    return numpy.asarray(dia)
Example #9
0
def set_atom_conf(element, description):
    '''Change the default atomic core and valence configuration to the one
    given by "description".
    See lo.nao.AOSHELL for the default configuration.

    Args:
        element : str or int
            Element symbol or nuclear charge
        description : str or a list of str
            | "double p" : double p shell
            | "double d" : double d shell
            | "double f" : double f shell
            | "polarize" : add one polarized shell
            | "1s1d"     : keep core unchanged and set 1 s 1 d shells for valence
            | ("3s2p","1d") : 3 s, 2 p shells for core and 1 d shells for valence
    '''
    charge = mole._charge(element)

    def to_conf(desc):
        desc = desc.replace(' ', '').replace('-', '').replace('_', '').lower()
        if "doublep" in desc:
            desc = '2p'
        elif "doubled" in desc:
            desc = '2d'
        elif "doublef" in desc:
            desc = '2f'
        elif "polarize" in desc:
            loc = AOSHELL[charge][1].find('0')
            desc = '1' + AOSHELL[charge][1][loc + 1]
        return desc

    if isinstance(description, str):
        c_desc, v_desc = AOSHELL[charge][0], to_conf(description)
    else:
        c_desc, v_desc = to_conf(description[0]), to_conf(description[1])

    ncore = [int(x) for x in AOSHELL[charge][0][::2]]
    ncv = [int(x) for x in AOSHELL[charge][1][::2]]
    for i, s in enumerate(('s', 'p', 'd', 'f')):
        if s in c_desc:
            ncore[i] = int(c_desc.split(s)[0][-1])
        if s in v_desc:
            ncv[i] = ncore[i] + int(v_desc.split(s)[0][-1])
    c_conf = '%ds%dp%dd%df' % tuple(ncore)
    cv_conf = '%ds%dp%dd%df' % tuple(ncv)
    AOSHELL[charge] = [c_conf, cv_conf]
    sys.stderr.write('Update %s conf: core %s core+valence %s\n' %
                     (element, c_conf, cv_conf))
Example #10
0
def set_atom_conf(element, description):
    """Change the default atomic core and valence configuration to the one
    given by "description".
    See lo.nao.AOSHELL for the default configuration.

    Args:
        element : str or int
            Element symbol or nuclear charge
        description : str or a list of str
            | "double p" : double p shell
            | "double d" : double d shell
            | "double f" : double f shell
            | "polarize" : add one polarized shell
            | "1s1d"     : keep core unchanged and set 1 s 1 d shells for valence
            | ("3s2p","1d") : 3 s, 2 p shells for core and 1 d shells for valence
    """
    charge = mole._charge(element)

    def to_conf(desc):
        desc = desc.replace(" ", "").replace("-", "").replace("_", "").lower()
        if "doublep" in desc:
            desc = "2p"
        elif "doubled" in desc:
            desc = "2d"
        elif "doublef" in desc:
            desc = "2f"
        elif "polarize" in desc:
            loc = AOSHELL[charge][1].find("0")
            desc = "1" + AOSHELL[charge][1][loc + 1]
        return desc

    if isinstance(description, str):
        c_desc, v_desc = AOSHELL[charge][0], to_conf(description)
    else:
        c_desc, v_desc = to_conf(description[0]), to_conf(description[1])

    ncore = [int(x) for x in AOSHELL[charge][0][::2]]
    ncv = [int(x) for x in AOSHELL[charge][1][::2]]
    for i, s in enumerate(("s", "p", "d", "f")):
        if s in c_desc:
            ncore[i] = int(c_desc.split(s)[0][-1])
        if s in v_desc:
            ncv[i] = ncore[i] + int(v_desc.split(s)[0][-1])
    c_conf = "%ds%dp%dd%df" % tuple(ncore)
    cv_conf = "%ds%dp%dd%df" % tuple(ncv)
    AOSHELL[charge] = [c_conf, cv_conf]
    sys.stderr.write("Update %s conf: core %s core+valence %s\n" % (element, c_conf, cv_conf))
Example #11
0
    def __init__(self, atoms, basis=None):
        self.atomtypes = mole.atom_types(atoms, basis)
        # fake systems, which treates the atoms of different basis as different atoms.
        # the fake systems do not have the same symmetry as the potential
        # it's only used to determine the main (Z-)axis
        chg1 = numpy.pi - 2
        coords = []
        fake_chgs = []
        idx = []
        for k, lst in self.atomtypes.items():
            idx.append(lst)
            coords.append([atoms[i][1] for i in lst])
            ksymb = mole._rm_digit(k)
            if ksymb != k or ksymb == 'GHOST':
                # Put random charges on the decorated atoms
                fake_chgs.append([chg1] * len(lst))
                chg1 *= numpy.pi-2
            else:
                fake_chgs.append([mole._charge(ksymb)] * len(lst))
        coords = numpy.array(numpy.vstack(coords), dtype=float)
        fake_chgs = numpy.hstack(fake_chgs)
        self.charge_center = numpy.einsum('i,ij->j', fake_chgs, coords)/fake_chgs.sum()
        coords = coords - self.charge_center

        idx = numpy.argsort(numpy.hstack(idx))
        self.atoms = numpy.hstack((fake_chgs.reshape(-1,1), coords))[idx]

        self.group_atoms_by_distance = []
        decimals = int(-numpy.log10(TOLERANCE)) - 1
        for index in self.atomtypes.values():
            index = numpy.asarray(index)
            c = self.atoms[index,1:]
            dists = numpy.around(norm(c, axis=1), decimals)
            u, idx = numpy.unique(dists, return_inverse=True)
            for i, s in enumerate(u):
                self.group_atoms_by_distance.append(index[idx == i])
Example #12
0
def get_mass_center(atoms):
    mass = numpy.array([pyscf.lib.parameters.ELEMENTS[mole._charge(a[0])][1]
                        for a in atoms])
    coords = numpy.array([a[1] for a in atoms], dtype=float)
    rbar = numpy.einsum('i,ij->j', mass, coords)/mass.sum()
    return rbar
Example #13
0
def get_charge_center(atoms):
    charge = numpy.array([mole._charge(a[0]) for a in atoms])
    coords = numpy.array([a[1] for a in atoms], dtype=float)
    rbar = numpy.einsum('i,ij->j', charge, coords)/charge.sum()
    return rbar
Example #14
0
def get_nuc_g_factor(symb, mass=None):
    Z = mole._charge(symb)
# g factor of other isotopes can be found in file nuclear_g_factor.dat
    nuc_spin, g_nuc = ISOTOPE[Z][1:3]
    #gyromag = g_factor_to_gyromagnetic_ratio(g_nuc)
    return g_nuc