コード例 #1
0
def test_utilities():
    eps = 1e-5

    atoms = Icosahedron('Cu', 3)
    atoms.numbers[[0, 13, 15, 16, 18, 19, 21, 22, 24, 25, 27, 28, 30]] = 79
    atoms.center(vacuum=0.0)
    atoms.calc = EMT()
    with FIRE(atoms, logfile=None) as opt:
        opt.run(fmax=0.05)

    rmax = 8.
    nbins = 5
    rdf, dists = get_rdf(atoms, rmax, nbins)
    calc_dists = np.arange(rmax / (2 * nbins), rmax, rmax / nbins)
    assert all(abs(dists - calc_dists) < eps)
    calc_rdf = [0., 0.84408157, 0.398689, 0.23748934, 0.15398546]
    assert all(abs(rdf - calc_rdf) < eps)

    dm = atoms.get_all_distances()
    s = np.zeros(5)
    for c in [(29, 29), (29, 79), (79, 29), (79, 79)]:
        inv_norm = len(np.where(atoms.numbers == c[0])[0]) / len(atoms)
        s += get_rdf(atoms, rmax, nbins, elements=c,
                     distance_matrix=dm, no_dists=True) * inv_norm
    assert all(abs(s - calc_rdf) < eps)

    AuAu = get_rdf(atoms, rmax, nbins, elements=(79, 79),
                   distance_matrix=dm, no_dists=True)
    assert all(abs(AuAu[-2:] - [0.12126445, 0.]) < eps)

    bulk = L1_2(['Au', 'Cu'], size=(3, 3, 3), latticeconstant=2 * np.sqrt(2))
    rdf = get_rdf(bulk, 4.2, 5)[0]
    calc_rdf = [0., 0., 1.43905094, 0.36948605, 1.34468694]
    assert all(abs(rdf - calc_rdf) < eps)
コード例 #2
0
    def bond_count_vec(self, data):
        """Bond counting with a distribution measure for coordination.

        Parameters
        ----------
        data : object
            Data object with atomic distances.

        Returns
        -------
        track_nnmat : list
            List with summed number of atoms with given coordination numbers.
        """
        elements = sorted(set(self.get_atomic_numbers(data)))

        # Get coordination number counting.
        dm = self.get_all_distances(data)
        rdf, dists = get_rdf(data, 10., 200, dm)
        nndist = dists[np.argmax(rdf)] + 0.2
        track_nnmat = np.zeros((self.max_bonds, len(elements), len(elements)))
        for j in range(len(data)):
            row = elements.index(data[j].number)
            neighbors = [
                k for k in range(len(dm[j])) if 0.1 < dm[j][k] < nndist
            ]
            ln = len(neighbors)
            if ln > 12:
                continue
            for l in neighbors:
                column = elements.index(data[l].number)
                track_nnmat[ln][row][column] += 1

        return track_nnmat.ravel()
コード例 #3
0
from ase.optimize.fire import FIRE
from ase.lattice.compounds import L1_2

from ase.ga.utilities import get_rdf

eps = 1e-5

atoms = Icosahedron('Cu', 3)
atoms.numbers[[0, 13, 15, 16, 18, 19, 21, 22, 24, 25, 27, 28, 30]] = 79
atoms.set_calculator(EMT())
opt = FIRE(atoms, logfile=None)
opt.run(fmax=0.05)

rmax = 8.
nbins = 5
rdf, dists = get_rdf(atoms, rmax, nbins)
calc_dists = np.arange(rmax / (2 * nbins), rmax, rmax / nbins)
assert all(abs(dists - calc_dists) < eps)
calc_rdf = [0., 0.84408157, 0.398689, 0.23748934, 0.15398546]
assert all(abs(rdf - calc_rdf) < eps)

dm = atoms.get_all_distances()
s = np.zeros(5)
for c in [(29, 29), (29, 79), (79, 29), (79, 79)]:
    inv_norm = len(np.where(atoms.numbers == c[0])[0]) / len(atoms)
    s += get_rdf(
        atoms, rmax, nbins, elements=c, distance_matrix=dm,
        no_dists=True) * inv_norm
assert all(abs(s - calc_rdf) < eps)

AuAu = get_rdf(atoms,
コード例 #4
0
    def nearestneighbour_vec(self, data):
        """Nearest neighbour average, Topics in Catalysis, 2014, 57, 33.

        This is a slightly modified version of the code found in the `ase.ga`
        module.

        Parameters
        ----------
        data : object
            Data object with atomic numbers available.

        Returns
        -------
        nnlist : list
            Feature vector that will be n**2 where n is the number of atomic
            species passed to the class.
        """
        # Return feature names in no atomic data is passed.
        if data is None:
            msg = 'Class must have atom_types set to return feature names.'
            assert hasattr(self, 'atom_types') and self.atom_types is not \
                None, msg
            names = []
            for i in self.atom_types:
                names += [
                    '{0}_{1}_nnmat'.format(i, j) for j in self.atom_types
                ]
            return names

        # WARNING: Will be set permanently whichever atom is first passed.
        if self.atom_types is None:
            msg = 'atom_types variable will be set permanently to whichever '
            msg += 'atom object is first passed'
            warnings.warn(msg)
            self.atom_types = sorted(frozenset(self.get_atomic_numbers(data)))

        # Calculate the distance parameters.
        dm = self.get_all_distances(data)
        rdf, dists = get_rdf(data, 10., 200, dm)
        nndist = dists[np.argmax(rdf)] + 0.2

        # initialize correct shape feature martix.
        nnmat = np.zeros((len(self.atom_types), len(self.atom_types)))

        # Calculate the neighbor properties.
        for i, d in enumerate(data):
            row = [
                j for j in range(len(self.atom_types))
                if d.number == self.atom_types[j]
            ][0]
            neighbors = [j for j in range(len(dm[i])) if dm[i][j] < nndist]
            for n in neighbors:
                column = [
                    j for j in range(len(self.atom_types))
                    if data[n].number == self.atom_types[j]
                ][0]
                nnmat[row][column] += 1

        # Normalize the features.
        for i, el in enumerate(self.atom_types):
            nnmat[i] /= len(
                [j for j in range(len(data)) if data[int(j)].number == el])

        # convert matrix to vector and replace np.nan values.
        nnlist = np.nan_to_num(nnmat.flatten())

        return nnlist
コード例 #5
0
    def get_rdf(self,
                rmax,
                nbins,
                imageIdx=None,
                elements=None,
                return_dists=False):
        """Get RDF.

        Wrapper for :meth:`ase.ga.utilities.get_rdf` with more selection possibilities.

        Parameters:

        rmax: float
            Maximum distance of RDF.
        nbins: int
            Number of bins to divide RDF.
        imageIdx: int/slice/None
            Images to analyze, see :func:`_get_slice` for details.
        elements: str/int/list/tuple
            Make partial RDFs.

        If elements is *None*, a full RDF is calculated. If elements is an *integer* or a *list/tuple
        of integers*, only those atoms will contribute to the RDF (like a mask). If elements
        is a *string* or a *list/tuple of strings*, only Atoms of those elements will contribute.

        Returns:

        return: list of lists / list of tuples of lists
            If return_dists is True, the returned tuples contain (rdf, distances). Otherwise
            only rdfs for each image are returned.
        """

        sl = self._get_slice(imageIdx)

        r = []
        el = None

        for image in self.images[sl]:
            if elements is None:
                tmpImage = image
            #integers
            elif isinstance(elements, int):
                tmpImage = Atoms(cell=image.get_cell(), pbc=image.get_pbc())
                tmpImage.append(image[elements])
            #strings
            elif isinstance(elements, str):
                tmpImage = Atoms(cell=image.get_cell(), pbc=image.get_pbc())
                for idx in self._get_symbol_idxs(image, elements):
                    tmpImage.append(image[idx])
            #lists
            elif isinstance(elements, list) or isinstance(elements, tuple):
                #list of ints
                if all(isinstance(x, int) for x in elements):
                    if len(elements) == 2:
                        #use builtin get_rdf mask
                        el = elements
                        tmpImage = image
                    else:
                        #create dummy image
                        tmpImage = Atoms(cell=image.get_cell(),
                                         pbc=image.get_pbc())
                        for idx in elements:
                            tmpImage.append(image[idx])
                #list of strings
                elif all(isinstance(x, str) for x in elements):
                    tmpImage = Atoms(cell=image.get_cell(),
                                     pbc=image.get_pbc())
                    for element in elements:
                        for idx in self._get_symbol_idxs(image, element):
                            tmpImage.append(image[idx])
                else:
                    raise ValueError(
                        "Unsupported type of elements given in ase.geometry.analysis.Analysis.get_rdf!"
                    )
            else:
                raise ValueError(
                    "Unsupported type of elements given in ase.geometry.analysis.Analysis.get_rdf!"
                )

            r.append(
                get_rdf(tmpImage,
                        rmax,
                        nbins,
                        elements=el,
                        no_dists=(not return_dists)))
        return r
コード例 #6
0
print atoms
up = Atoms()
up.set_cell(atoms.get_cell())
up_target = 'X'
dn = Atoms()
dn.set_cell(atoms.get_cell())
dn_target = 'He'
nuclei = Atoms()
nuclei.set_cell(atoms.get_cell())

for a in range(len(atoms)):
    if atoms[a].symbol == up_target:
        up.append(atoms[a])
    if atoms[a].symbol == dn_target:
        dn.append(atoms[a])
    if atoms[a].symbol != up_target and atoms[a].symbol != dn_target:
        nuclei.append(atoms[a])

data_up = get_rdf(up, l, nmax)
data_dn = get_rdf(dn, l, nmax)
data_nuclei = get_rdf(nuclei, l, nmax)
data_all = get_rdf(atoms, l, nmax)
# data_up[0]/max(data_up[0])*len(up)
# data_dn[0]/max(data_dn[0])*len(dn)
bar(data_up[1], data_up[0], label='up', width=0.02)
bar(data_dn[1], data_dn[0], label='dn', width=0.01)
bar(data_nuclei[1], data_nuclei[0], label='nuclei', width=0.02)
#bar(data_all[1],data_all[0],label='all',width=0.05)
legend()
show()
コード例 #7
0
def estimate_rcut(dbfiles, element1, element2):
    ''' Returns an estimated, optimal cutoff radius for the
    repulsive interaction between the given elements.
    It is estimated as the radius for the first minimum
    after the first maximum of the radial distribution
    function (RDF), as employed in e.g.
    http://dx.doi.org/10.1021/acs.jctc.5b00742

    dbfiles: list of database filenames which contain the
             structures for calculating the RDF
    element1: the symbol of the first element
    element2: the symbol of the second element
    '''
    num1 = atomic_numbers[element1]
    num2 = atomic_numbers[element2]
    cr1 = covalent_radii[num1]
    cr2 = covalent_radii[num2]
    rlim = 2 * (cr1 + cr2)
    d = 0.1
    nbins = int(rlim / d)
    rdf_tot = np.zeros(nbins)
    dist = None

    for dbfile in dbfiles:
        db = connect(dbfile)
        for row in db.select(relaxed=1):
            atoms = row.toatoms()
            sym = atoms.get_chemical_symbols()
            if element1 not in sym or element2 not in sym:
                continue
            cell = atoms.get_cell()
            vol = atoms.get_volume()
            rep = [1, 1, 1]
            for i in range(3):
                if atoms.pbc[i]:
                    axb = np.cross(cell[(i + 1) % 3, :], cell[(i + 2) % 3, :])
                    h = vol / np.linalg.norm(axb)
                    rep[i] = int(np.ceil((2.001 * rlim) / h))
            a = atoms.repeat(rep)
            rdf, dist = get_rdf(a, rlim, nbins, elements=(num1, num2))
            rdf_tot += rdf

    if dist is None:
        print('Warning: no %s-%s nearest neighbours in data sets' % \
              (element1, element2))
        return 0.

    rdf_smooth = gaussian_filter1d(rdf_tot, sigma=1, mode='reflect')

    imax = len(dist) - 1
    for imax in find_peaks(rdf_smooth)[0]:
        if rdf_smooth[imax] > 0.5 * np.max(rdf_smooth):
            break

    imin = min(imax + 1, len(dist) - 1)
    for imin in find_peaks(-rdf_smooth)[0]:
        if imin > imax:
            break

    rmin = dist[imin]
    rmax = dist[imax]
    rcut = rmin if imin > imax else rlim
    print('%s-%s RDF: 1st maximum = %.3f' % (element1, element2, rmax))
    print('%s-%s RDF: subsequent minimum = %.3f' % (element1, element2, rmin))
    print('%s-%s RDF: suggested rcut = %.3f' % (element1, element2, rcut))

    try:
        plt.plot(dist, rdf_tot, '--', label='as-is')
        plt.plot(dist, rdf_smooth, '-', label='smoothened')
        plt.plot([rmax, rmax], [0, max(rdf_tot)], label='first maximum')
        plt.plot([rcut, rcut], [0, max(rdf_tot)], label='suggested rcut')
        plt.xlabel('%s-%s distance [Angstrom]' % (element1, element2))
        plt.ylabel('RDF [-]')
        plt.legend(loc='upper left')
        plt.savefig('%s-%s_rdf.pdf' % (element1, element2))
        plt.clf()
    except Exception as err:
        print(err.message)

    return rcut
コード例 #8
0
ファイル: utilities.py プロジェクト: rchiechi/QuantumParse
from ase.optimize.fire import FIRE
from ase.lattice.compounds import L1_2

from ase.ga.utilities import get_rdf

eps = 1e-5

atoms = Icosahedron('Cu', 3)
atoms.numbers[[0, 13, 15, 16, 18, 19, 21, 22, 24, 25, 27, 28, 30]] = 79
atoms.set_calculator(EMT())
opt = FIRE(atoms, logfile=None)
opt.run(fmax=0.05)

rmax = 8.
nbins = 5
rdf, dists = get_rdf(atoms, rmax, nbins)
calc_dists = np.arange(rmax / (2 * nbins), rmax, rmax / nbins)
assert all(abs(dists - calc_dists) < eps)
calc_rdf = [0., 0.84408157, 0.398689, 0.23748934, 0.15398546]
assert all(abs(rdf - calc_rdf) < eps)

dm = atoms.get_all_distances()
s = np.zeros(5)
for c in [(29, 29), (29, 79), (79, 29), (79, 79)]:
    inv_norm = len(np.where(atoms.numbers == c[0])[0]) / len(atoms)
    s += get_rdf(atoms, rmax, nbins, elements=c,
                 distance_matrix=dm, no_dists=True) * inv_norm
assert all(abs(s - calc_rdf) < eps)

AuAu = get_rdf(atoms, rmax, nbins, elements=(79, 79),
               distance_matrix=dm, no_dists=True)