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']
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']
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