Пример #1
0
    def __init__(self, coordinates, numbers, pseudo_numbers, density, grid, scheme="h", **kwargs):

        wpart = wpart_schemes[scheme]
        # make proatom database
        if scheme.lower() not in ["mbis", "b"]:
            if "proatomdb" not in kwargs.keys():
                proatomdb = ProAtomDB.from_refatoms(numbers)
            kwargs["proatomdb"] = proatomdb
        # partition
        self.part = wpart(coordinates, numbers, pseudo_numbers, grid, density, **kwargs)
        self.part.do_all()

        self.grid = grid
        self.density = density
        self.coordines = coordinates
        self.numbers = numbers
        self.pseudo_numbers = pseudo_numbers
        self.charges = self.part['charges']
Пример #2
0
    def __init__(self,
                 coordinates,
                 numbers,
                 pseudo_numbers,
                 density,
                 grid,
                 scheme="h",
                 **kwargs):
        """Initialize class.

        Parameters
        ----------
        coordinates : np.ndarray, shape=(M, 3)
            Cartesian coordinates of `M` atoms in the molecule.
        numbers : np.ndarray, shape=(M,)
            Atomic number of `M` atoms in the molecule.
        pseudo_numbers : np.ndarray, shape=(M,)
            Pseudo-number of `M` atoms in the molecule.
        density : np.ndarray, shape=(N,)
            Total density to be partitioned.
        grid : BeckeMolGrid
            Instance of BeckeMolGrid numerical integration grid.
        scheme : str
            Type of atoms-in-molecule partitioning scheme.

        """
        wpart = wpart_schemes[scheme]
        # make proatom database
        if scheme.lower() not in ["mbis", "b"]:
            if "proatomdb" not in kwargs.keys():
                proatomdb = ProAtomDB.from_refatoms(numbers)
                kwargs["proatomdb"] = proatomdb
            kwargs["local"] = False
        # partition
        self.part = wpart(coordinates, numbers, pseudo_numbers, grid, density,
                          **kwargs)
        self.part.do_charges()

        self.grid = grid
        self.density = density
        self.coordines = coordinates
        self.numbers = numbers
        self.pseudo_numbers = pseudo_numbers
        self.charges = self.part['charges']
Пример #3
0
def get_dict_population(molecule, approach, scheme, **kwargs):
    r"""Return dictionary of number of electrons and corresponding atomic charges values.

    Parameters
    ----------
    molecule : Molecule or Sequence of Molecule
        Instance of Molecule class, or sequence of Molecule class instances.
    approach : str, optional
        Choose between "FMR" (fragment of molecular response) or "RMF"
        (response of molecular fragment).
    scheme : str
        Partitioning scheme.
    kwargs : optional
    """
    # check approach
    if approach.lower() not in ["rmf", "fmr"]:
        raise ValueError("Argument approach={0} is not valid.".format(approach))

    # case of populations available in molecule
    if scheme.lower() not in wpart_schemes:
        # check approach & molecule instances
        if approach.lower() != "rmf":
            raise ValueError("Condensing with scheme={0} is only possible in combination with "
                             "approach='RMF'! Given approach={1}".format(scheme, approach))
        if (not hasattr(type(molecule), "__iter__") or len(molecule) != 3 or not
                np.all([isinstance(mol, Molecule) for mol in molecule])):
            raise ValueError("Condensing with scheme={0} needs 3 molecules!".format(scheme))
        # get populations
        pops = [getattr(mol, scheme + "_charges") for mol in molecule]
        if np.any([isinstance(pop, type(None)) for pop in pops]):
            raise ValueError("Condensing scheme={0} is not possible, because attribute {1}_charges "
                             "of molecule instances is 'None'.".format(scheme, scheme.lower()))
        # make dictionary of populations
        dict_pops = dict([(sum(m.mo.nelectrons), m.numbers - pop) for m, pop in zip(molecule, pops)])
        return dict_pops

    # case of condensing the density using denspart
    try:
        # check whether molecules have the same coordinates
        get_matching_attr(molecule, "coordinates", 1.e-4)
        same_coordinates = True
    except ValueError:
        if approach.lower() == "fmr":
            raise ValueError("When geometries of molecules are different, only approach='RMF' "
                             "is possible! Given approach={0}".format(approach.upper()))
        same_coordinates = False

    # find reference molecule
    if isinstance(molecule, Molecule):
        mol0 = molecule
    elif np.all([isinstance(mol, Molecule) for mol in molecule]):
        if len(molecule) != 3:
            raise ValueError("Condensing within FD approach, currently works for "
                             "only 3 molecules! Given {0} molecules.".format(len(molecule)))
        # reference molecule is the middle molecule (for 3 molecules)
        dict_mols = {sum(mol.mo.nelectrons): mol for mol in molecule}
        mol0 = dict_mols.pop(sorted(dict_mols.keys())[1])
    else:
        raise ValueError("Argument molecule not recognized!")

    # check and generate partitioning class & proatomdb
    wpart = wpart_schemes[scheme]
    # make proatom database
    if scheme.lower() not in ["mbis", "b"]:
        if "proatomdb" not in list(kwargs.keys()) or kwargs["proatomdb"] is None:
            proatomdb = ProAtomDB.from_refatoms(mol0.numbers)
            kwargs["proatomdb"] = proatomdb

    # check or generate molecular grid
    grid = get_molecular_grid(molecule, kwargs.pop("grid", None))
    # compute dictionary of number of electron and density
    dict_dens = get_dict_density(molecule, grid.points)

    # compute population of reference molecule
    part0 = wpart(mol0.coordinates, mol0.numbers, mol0.pseudo_numbers, grid,
                  dict_dens[sum(mol0.mo.nelectrons)], **kwargs)
    part0.do_all()
    # record population of reference system
    dict_pops = dict([(sum(mol0.mo.nelectrons), part0["populations"])])
    del dict_dens[sum(mol0.mo.nelectrons)]

    # compute and record populations given grid in a dictionary
    for nelec, dens in dict_dens.items():

        if approach.lower() == "fmr":
            # fragment of molecular response
            pops = condense_to_atoms(dens, part0)
        elif approach.lower() == "rmf":
            # response of molecular fragment
            if not same_coordinates:
                mol = dict_mols[nelec]
                grid = get_molecular_grid(molecule, None)
                dens = molecule.compute_density(grid.points, "ab", None)
            else:
                mol = mol0
            parts = wpart(mol.coordinates, mol.numbers, mol.pseudo_numbers,
                          grid, dens, **kwargs)

            parts.do_all()
            pops = parts["populations"]
        else:
            raise ValueError("Condensing approach {0} is not recognized!".format(approach))
        # Store number of electron and populations in a dictionary
        dict_pops[nelec] = pops
    return dict_pops