# Enumerate structures¶

## Predict mixing energies¶

In this step the cluster expansion constructed previously will be employed to predict the mixing energies for a much larger set of structures obtained by enumeration. After loading the CE from file, we loop over all structures with up 8 atoms in the unit cell and compile silver concentrations and predicted mixing energy into a list, which is calculated by calling the ClusterExpansion.predict() method with the ASE Atoms object that represents the present structure as input argument.

ce = ClusterExpansion.read('cluster_expansion.icet')
data = []
structures = []
for atoms in enumerate_structures(ce.cluster_space.primitive_structure,
range(1, 9),
ce.cluster_space.chemical_symbols):
conc = float(atoms.get_chemical_symbols().count('Ag')) / len(atoms)
emix = ce.predict(atoms)
data.append([conc, emix])
structures.append(atoms)
print('Predicted energies for {} structures'.format(len(data)))
data = np.array(data).T



## Extract convex hull¶

Using the complete set of mixing energies we then generate the convex hull using the ConvexHull class.

hull = ConvexHull(data[0], data[1])



## Plot results¶

The predicted energies are then plotted together with the convex hull as a function of the concentration of silver atoms.

fig, ax = plt.subplots(figsize=(4, 3))
ax.set_xlabel(r'Ag concentration')
ax.set_ylabel(r'Mixing energy (meV/atom)')
ax.set_xlim([0, 1])
ax.scatter(data[0], 1e3 * data[1], marker='x')
ax.plot(hull.concentrations, 1e3 * hull.energies, '-o', color='green')
plt.savefig('mixing-energy-predicted.png', bbox_inches='tight')



The figure generated by this diagram is shown below.

## Filter for low energy structures¶

The ConvexHull class also provides some convenience functions including e.g., the possibility to extract structures that are within a certain distance of the convex hull.

tol = 0.0005
low_energy_structures = hull.extract_low_energy_structures(data[0], data[1],
tol, structures)
print('Found {} structures within {} meV/atom of the convex hull'.
format(len(low_energy_structures), 1e3*tol))


These structures can then be calculated for example using the reference method of choice.

## Source code¶

The complete source code is available in tutorial/basic/4_enumerate_structures.py
import matplotlib.pyplot as plt
import numpy as np
from icet import ClusterExpansion
from icet.tools import ConvexHull, enumerate_structures

# step 1: Predict energies for enumerated structures
data = []
structures = []
for atoms in enumerate_structures(ce.cluster_space.primitive_structure,
range(1, 9),
ce.cluster_space.chemical_symbols):
conc = float(atoms.get_chemical_symbols().count('Ag')) / len(atoms)
emix = ce.predict(atoms)
data.append([conc, emix])
structures.append(atoms)
print('Predicted energies for {} structures'.format(len(data)))
data = np.array(data).T

# step 2: Construct convex hull
hull = ConvexHull(data[0], data[1])

# step 3: Plot the results
fig, ax = plt.subplots(figsize=(4, 3))
ax.set_xlabel(r'Ag concentration')
ax.set_ylabel(r'Mixing energy (meV/atom)')
ax.set_xlim([0, 1])
ax.scatter(data[0], 1e3 * data[1], marker='x')
ax.plot(hull.concentrations, 1e3 * hull.energies, '-o', color='green')
plt.savefig('mixing-energy-predicted.png', bbox_inches='tight')

# step 4: Extract candidate ground state structures
tol = 0.0005
low_energy_structures = hull.extract_low_energy_structures(data[0], data[1],
tol, structures)
print('Found {} structures within {} meV/atom of the convex hull'.
format(len(low_energy_structures), 1e3*tol))