In [1]:
"""
This is slightly modified version of the notebook in the pymatgen/examples folder
"""
import numpy as np
from pymatgen.matproj.rest import MPRester
from pymatgen.core.ion import Ion
from pymatgen import Element
from pymatgen.phasediagram.pdmaker import PhaseDiagram
from pymatgen.analysis.pourbaix.entry import PourbaixEntry, IonEntry
from pymatgen.analysis.pourbaix.maker import PourbaixDiagram
from pymatgen.analysis.pourbaix.plotter import PourbaixPlotter
from pymatgen.entries.compatibility import MaterialsProjectCompatibility, AqueousCorrection
%matplotlib inline
useful function for filtering duplicate entries.
In [2]:
def contains_entry(entry_list, entry):
for e in entry_list:
if e.entry_id == entry.entry_id or \
(abs(entry.energy_per_atom
- e.energy_per_atom) < 1e-6 and
entry.composition.reduced_formula ==
e.composition.reduced_formula):
return True
In [3]:
#This initializes the REST adaptor. Put your own API key in.
a = MPRester("dwvz2XCFUEI9fJiR")
In [4]:
#Entries are the basic unit for thermodynamic and other analyses in pymatgen.
#This gets all entries belonging to the Fe-O-H system.
entries = a.get_entries_in_chemsys(['Fe', 'O', 'H'])
In [5]:
#exp_entries = a.get_exp_entry("SnO")
#print exp_entries
In [6]:
#Dictionary of ion:energy, where the energy is the formation energy of ions from
#the NBS tables. (Source: NBS Thermochemical Tables; FeO4[2-]: Misawa T., Corr. Sci., 13(9), 659-676 (1973))
ion_dict = {"Fe[2+]":-0.817471, "Fe[3+]":-0.0478, "FeO2[2-]":-3.06055, "FeOH[+]":-2.8738,
"FeOH[2+]":-2.37954, "HFeO2[-]":-3.91578, "Fe(OH)2[+]":-4.54022, "Fe2(OH)2[4+]":-4.84285,
"FeO2[-]":-3.81653, "FeO4[2-]":-3.33946, "Fe(OH)3(aq)":-6.83418, "Fe(OH)2[+]":-4.54022}
In [7]:
elements = set()
data = []
for entry in entries:
elements.update(entry.composition.elements)
#print elements
for entry in entries:
comp = entry.composition
#print comp
row = [comp.get_atomic_fraction(el) for el in elements]
row.append(entry.energy_per_atom)
data.append(row)
data = np.array(data)
#print data
#print data[:, 1:]
Solvent corrections
In [8]:
# Run aqueouscorrection on the entries
aqcompat = AqueousCorrection("/home/matk/Software/pymatgen/pymatgen/entries/MPCompatibility.yaml")
entries_aqcorr = list()
for entry in entries:
aq_corrected_entry = aqcompat.correct_entry(entry)
if not contains_entry(entries_aqcorr, aq_corrected_entry):
entries_aqcorr.append(aq_corrected_entry)
# Generate a phase diagram to consider only solid entries stable in water.
#for e in entries_aqcorr:
# print e.name
pd = PhaseDiagram(entries_aqcorr)
#for e in pd.qhull_entries:
# print e.name
#for el in pd.el_refs:
# print el.name
#print pd.facets
#print pd.qhull_data
Solid state pourbaix entries
In [9]:
stable_solids = pd.stable_entries
for ss in stable_solids:
print ss.name
print ss.composition.get_reduced_composition_and_factor()#[1]
stable_solids_minus_h2o = [entry for entry in stable_solids if
entry.composition.reduced_formula not in ["H2", "O2", "H2O", "H2O2"]]
pbx_solid_entries = []
for entry in stable_solids_minus_h2o:
pbx_entry = PourbaixEntry(entry)
pbx_entry.g0_replace(pd.get_form_energy(entry))
pbx_entry.reduced_entry()
pbx_solid_entries.append(pbx_entry)
Ion pourbaix entries
In [10]:
#Dictionary of reference state:experimental formation energy (from O. Kubaschewski) for reference state.
ref_state = "Fe2O3"
ref_dict = {"Fe2O3": -7.685050670886141}
# Calculate DFT reference energy for ions (See Persson et al, PRB (2012))
ref_entry = [entry for entry in stable_solids_minus_h2o if entry.composition.reduced_formula == ref_state][0]
ion_correction = pd.get_form_energy(ref_entry)/ref_entry.composition.get_reduced_composition_and_factor()[1] - ref_dict[ref_state]
el = Element("Fe")
pbx_ion_entries = []
# Get PourbaixEntry corresponding to each ion
for key in ion_dict:
comp = Ion.from_formula(key)
factor = comp.composition[el] / (ref_entry.composition[el] / ref_entry.composition.get_reduced_composition_and_factor()[1])
#experimental energy + correction
energy = ion_dict[key] + ion_correction * factor
pbx_entry_ion = PourbaixEntry(IonEntry(comp, energy))
pbx_entry_ion.name = key
pbx_ion_entries.append(pbx_entry_ion)
In [11]:
# Generate and plot Pourbaix diagram
#Each bulk solid/ion has a free energy g of the form:
#g = g0_ref + 0.0591 * log10(conc) - nO * mu_H2O + (nH - 2nO) * pH + phi * (-nH + 2nO + q)
all_entries = pbx_solid_entries + pbx_ion_entries
pourbaix = PourbaixDiagram(all_entries)
print pourbaix._qhull_data
plotter = PourbaixPlotter(pourbaix)
plotter.plot_pourbaix(limits=[[-2, 16],[-3, 3]])
In [11]: