Source code for pyscf.ita.promolecule
import numpy as np
from pyscf import scf, dft
from pyscf.scf import atom_hf, atom_ks
from pyscf.dft.rks import KohnShamDFT
from pyscf.scf.hf import SCF
from pyscf.data.elements import NRSRHF_CONFIGURATION
__all__ = ["ProMolecule"]
MULTIPLICITIES = {
"H": 2, "He":1,
"Li":2, "Be":1, "B": 2, "C": 3, "N": 4, "O": 3, "F": 2, "Ne":1,
"Na":2, "Mg":1, "Al":2, "Si":3, "P": 4, "S": 3, "Cl":2, "Ar":1,
"K": 2, "Ca":1, "Sc":2, "Ti":3, "V": 4, "Cr":7, "Mn":6, "Fe":5,
"Co":4, "Ni":3, "Cu":2, "Zn":1, "Ga":2, "Ge":3, "As":4, "Se":3,
"Br":2, "Kr":1, "Rb":2, "Sr":1, "Y": 2, "Zr":3, "Nb":6, "Mo":7,
"Tc":6, "Ru":5, "Rh":4, "Pd":1, "Ag":2, "Cd":1, "In":2, "Sn":3,
"Sb":4, "Te":3, "I" :2, "Xe":1, "Cs":2, "Ba":1, "La":2, "Ce":1,
"Pr":4, "Nd":5, "Pm":6, "Sm":7, "Eu":8, "Gd":9, "Tb":6, "Dy":5,
"Ho":4, "Er":3, "Tm":2, "Yb":1, "Lu":2, "Hf":3, "Ta":4, "W" :5,
"Re":6, "Os":5, "Ir":4, "Pt":3, "Au":2, "Hg":1, "Tl":2, "Pb":3,
"Bi":4, "Po":3, "At":2, "Rn":1, "Fr":2, "Ra":1, "Ac":2, "Th":3,
"Pa":4, "U" :5, "Np":6, "Pu":7, "Am":8, "Cm":9, "Bk":6, "Cf":5,
"Es":4, "Fm":3
}
r"""Dictionary of the multiplicities for each isoelectronic series (up to 100 electrons).
"""
[docs]
class ProMolecule:
r""" Promolecule class.
A promolecule is an approximation of a molecule constructed from a linear combination of atomic
and/or ionic species. Properties of this promolecule can be computed from those of the atomic
and/or ionic species, depending on whether the property is an extensive one or an intensive one.
Examples:
>>> mol = gto.M(atom='H 0 0 0; H 0 0 1.1')
>>> mf = scf.HF(mol)
>>> mf.kernel()
>>> pro_charge, pro_multiplicity = {'H':0, 'O':0}, {'H':2, 'O':3}
>>> promol = ProMolecule.build(mf, pro_charge, pro_multiplicity)
"""
def __init__(
self,
method,
element_methods=None,
pro_charge=None,
pro_multiplicity=None
):
r""" Initialize a instance.
Parameters
----------
method : PyscfMethod
Pyscf method.
element_methods : Dict{element:PyscfMethod}, optional
Dictionary of PyscfMethod for each element, by default None.
pro_charge : Dict{str:int}, optional
Dictionary of charge for each element, by default None.
pro_multiplicity : Dict{str:int}, optional
Dictionary of multiplicity for each element, by default None.
"""
self.method = method
self.element_methods = element_methods
self.pro_charge = pro_charge
self.pro_multiplicity = pro_multiplicity
[docs]
def build(
self,
method=None,
pro_charge=None,
pro_multiplicity=None
):
r""" Initialize a instance.
Parameters
----------
method : PyscfMethod
Pyscf method.
pro_charge : Dict{str:int}, optional
Dictionary of charge for each element, by default None.
pro_multiplicity : Dict{str:int}, optional
Dictionary of multiplicity for each element, by default None.
Returns
-------
ProMolecule
Instance of ProMolecule class.
"""
if method is None:
method = self.method
if pro_charge is None:
pro_charge = self.pro_charge
if pro_multiplicity is None:
pro_multiplicity = self.pro_multiplicity
# By default use neutral atoms.
if (pro_charge is None) and (pro_multiplicity is None):
pro_charge, pro_multiplicity = {}, {}
for element in set(method.mol.elements):
pro_charge[element] = 0
pro_multiplicity[element] = MULTIPLICITIES[element]
# Parse the method
atom_method = self.identical_method(method)
# Build atom in promolecule
mol = method.mol
element_methods = {}
for element in set(mol.elements):
atom = mol.__class__()
atom.atom = [[element, 0.0, 0.0, 0.0]]
atom.basis = mol.basis
atom.charge = pro_charge[element]
atom.multiplicity = pro_multiplicity[element]
atom.unit = mol.unit
atom.cart = mol.cart
atom.verbose = 0
atom.build()
if isinstance(method, SCF):
element_method = atom_method(atom)
element_method.kernel()
else:
element_mf = scf.HF(atom)
element_mf.kernel()
element_method = atom_method(element_mf)
element_method.kernel()
element_methods[element] = element_method
self.method = method
self.element_methods = element_methods
self.pro_charge = pro_charge
self.pro_multiplicity = pro_multiplicity
return self
[docs]
def identical_method(self, method):
"""_summary_
Parameters
----------
method : PyscfMethod
Pyscf scf method or post-scf method instance.
Returns
-------
_type_
_description_
"""
# If Mean field method
if isinstance(method, SCF):
if isinstance(method, KohnShamDFT):
method_func = dft.KS
method_func.xc = method.xc
else:
method_func = scf.HF
# If post-scf method
else:
if 'MP'.lower() in method.__class__.__name__.lower():
from pyscf import mp
method_func = getattr(mp, method.__class__.__name__)
elif 'CC'.lower() in method.__class__.__name__.lower():
from pyscf import cc
method_func = getattr(cc, method.__class__.__name__)
elif 'CI'.lower() in method.__class__.__name__.lower():
from pyscf import ci
method_func = getattr(ci, method.__class__.__name__)
else:
raise TypeError("Method type not supported.")
return method_func
[docs]
def spheric_average_method(self, method):
"""_summary_
Parameters
----------
method : PyscfMethod
Pyscf scf method or post-scf method instance.
Returns
-------
_type_
_description_
"""
# If Mean field method
if isinstance(method, SCF):
if isinstance(method, KohnShamDFT):
method_func = atom_ks.AtomSphAverageRKS
method_func.xc = method.xc
else:
if method.mol.nelectron == 1:
method_func = atom_hf.AtomHF1e
else:
method_func = atom_hf.AtomSphAverageRHF
method_func.atomic_configuration = NRSRHF_CONFIGURATION
# If post-scf method
else:
if 'MP'.lower() in method.__class__.__name__.lower():
from pyscf import mp
method_func = getattr(mp, method.__class__.__name__)
elif 'CC'.lower() in method.__class__.__name__.lower():
from pyscf import cc
method_func = getattr(cc, method.__class__.__name__)
elif 'CI'.lower() in method.__class__.__name__.lower():
from pyscf import ci
method_func = getattr(ci, method.__class__.__name__)
else:
raise TypeError("Method type not supported.")
return method_func
[docs]
def electron_density(
self,
grids_coords,
spin='ab',
deriv=2
):
""" Compute the electron density of the promolecule at the desired points.
Parameters
----------
grid_coords: np.ndarray((N, 3), dtype=float)
Points at which to compute the density.
spin: ('ab' | 'a' | 'b' | 'm')
Type of density to compute; either total, alpha-spin, beta-spin, or magnetization density,
by default 'ab'.
deriv : int
List of molecule and promolecule derivative+1 level, by default 2.
Returns
-------
PartitionDensity
Instance of PartitionDensity class.
"""
from pyscf.ita.dens import ElectronDensity, PartitionDensity
element_methods = self.element_methods
proatom_dens_list = []
for atom_geom in self.method.mol._atom:
symbol = atom_geom[0]
element_methods[symbol].mol.set_geom_([atom_geom],unit='B')
free_atom_dens = ElectronDensity.build(element_methods[symbol], grids_coords=grids_coords, spin=spin, deriv=deriv)
proatom_dens_list.append(free_atom_dens)
promoldens = PartitionDensity(proatom_dens_list)
return promoldens
[docs]
def get_method(self, element):
"""Get the Pyscf method for given element.
Parameters
----------
element : str
Symbol of element.
Returns
-------
PyscfMethod
Pyscf method.
"""
return self.element_methods[element]
[docs]
def get_atom(self, element):
"""Get the Pyscf Mole object for given element.
Parameters
----------
element : str
Symbol of element.
Returns
-------
Mole
Pyscf Mole object for free atom.
"""
return self.element_methods[element].mol
[docs]
def get_xc(self, element):
"""Get the exchange correlation functional for given element.
Parameters
----------
element : str
Symbol of element.
Returns
-------
str
Name of exchange correlation functional.
"""
return self.element_methods[element].xc
[docs]
def get_scf(self, element):
"""Get the mean field Pyscf method for given element.
Parameters
----------
element : str
Symbol of element.
Returns
-------
PyscfMethod
Mean field pyscf method.
"""
return self.element_methods[element]._scf