Skip to content

Commit 490529f

Browse files
authored
Add the high-throughput screening module
1 parent ee88294 commit 490529f

File tree

1 file changed

+155
-0
lines changed

1 file changed

+155
-0
lines changed

garnets_oqmd_htscreen.py

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
2+
# The code below can be used to generate OQMD derived thermodynamic quantities
3+
# for the Li3-garnets predicted by Aykol, Kim, Hegde and Wolverton (2018).
4+
# Please note that this code requires the qmpy library, which can be
5+
# accessed at https://github.com/wolverton-research-group/qmpy and also the OQMD
6+
# installed locally, per the instructions provided therein. Present authors used the
7+
# version 1.1 of the database as available for download at oqmd.org/download.
8+
9+
10+
import matplotlib.pyplot as plt
11+
import numpy as np
12+
from qmpy import *
13+
14+
garnets = Formation.objects.filter(entry__path__contains='garnet')
15+
16+
print 'Garnet, formation_energy stability band_gap V_max V_min stable_phases'
17+
18+
for garnet in garnets:
19+
20+
# Calculating stability with respect to other materials in OQMD within the
21+
# garnet's chemical space
22+
space = PhaseSpace('-'.join(garnet.entry.space))
23+
phase_O = Phase(composition='O',energy=0)
24+
phase_O.energy = -0.31695794 #298 K -TS of oxygen gas at 1 atm
25+
space.phase_dict['O'] = phase_O
26+
energy, phases = space.gclp(garnet.entry.name)
27+
energy = energy/20.0
28+
space.clear_all()
29+
stability = garnet.delta_e-energy
30+
if stability > 0.05:
31+
continue
32+
33+
# COMPUTATION OF BULK VOLTAGE PROFILES
34+
# Taking a slice of the convex hull from the garnet towards Li.
35+
36+
base_comp = str(garnet.entry.name[3:])
37+
slice_comp = base_comp + "-Li15"+base_comp
38+
ps = PhaseSpace(slice_comp)
39+
phase_O = Phase(composition='O',energy=0)
40+
phase_O.energy = -0.31695794
41+
ps.phase_dict['O'] = phase_O
42+
ps.get_hull()
43+
44+
# List of phases on the convex hull slice
45+
eq_list = list(ps.hull)
46+
47+
# Voltages
48+
V_list = []
49+
50+
51+
# We keep track of oxygen evolution as well.
52+
O_x, O_y = [], []
53+
54+
# Scanning the sets of equilibrium phases through the slice
55+
for eq in eq_list:
56+
energy1 = eq.phases[0].energy/eq.phases[0].unit_comp['O']*12.0
57+
energy2 = eq.phases[1].energy/eq.phases[1].unit_comp['O']*12.0
58+
if 'Li' in eq.phases[0].unit_comp:
59+
x_Li1 = eq.phases[0].unit_comp['Li']/eq.phases[0].unit_comp['O']*12.0
60+
else:
61+
x_Li1 = 0
62+
if 'Li' in eq.phases[1].unit_comp:
63+
x_Li2 = eq.phases[1].unit_comp['Li']/eq.phases[1].unit_comp['O']*12.0
64+
else:
65+
x_Li2 = 0
66+
V = -(energy2-energy1)/(x_Li2-x_Li1)
67+
V_list.append([x_Li1,V])
68+
V_list.append([x_Li2,V])
69+
70+
# Check if oxygen is one of the phases (to record evolution).
71+
for phase in eq.phases[0].phase_dict:
72+
if phase.name == 'O':
73+
O_x.append(x_Li1)
74+
O_y.append(V)
75+
for phase in eq.phases[1].phase_dict:
76+
if phase.name == 'O':
77+
O_x.append(x_Li2)
78+
O_y.append(V)
79+
80+
V_list.sort(key=lambda e: e[1], reverse=True)
81+
V_list.sort(key=lambda e: e[0])
82+
83+
window_V = []
84+
85+
# For stable materials, get the voltage window
86+
# For metastable materials, get the average voltage at x=3.0
87+
if np.allclose(stability, 0.0, atol=0.0001):
88+
for i in range(len(V_list)):
89+
if np.allclose(V_list[i][0], 3.0, atol=0.0001):
90+
window_V.append(V_list[i][1])
91+
else:
92+
for i in range(len(V_list)):
93+
if np.allclose(V_list[i][0], 3.0, atol=0.0001):
94+
window_V.append((V_list[i][1]+V_list[i+1][1])/2.0)
95+
break
96+
elif V_list[i][0]>3.0:
97+
window_V.append(V_list[i][1])
98+
break
99+
100+
101+
x_data, y_data = [], []
102+
103+
arrow_y = 3.0
104+
for i in xrange(len(V_list)):
105+
x_data.append(V_list[i][0])
106+
y_data.append(V_list[i][1])
107+
if V_list[i][0]==3.0:
108+
arrow_y=V_list[i][1]
109+
110+
# Plotting the voltage profile
111+
plt.plot(x_data,y_data, linewidth=2.0, color='red')
112+
plt.xlabel(r'x in Li$\mathsf{_x}$'+base_comp,fontsize=14)
113+
plt.ylabel(r'Voltage vs Li/Li+ (V)',fontsize=14)
114+
plt.title('Lix'+base_comp,fontsize=14,fontweight='bold')
115+
plt.axis([0,16,0,5.5])
116+
117+
# Annotating the garnet composition on the plot
118+
string = ' '.join([garnet.entry.latex,
119+
r'$E_g =$ ', str(garnet.calculation.band_gap),
120+
r' eV'])
121+
plt.annotate(string, xy=(3.25, arrow_y+0.1), xytext=(3.6,arrow_y+0.6), fontsize=14,
122+
arrowprops=dict(arrowstyle="-|>", relpos=(0.1, 0.), fc='b') )
123+
124+
# Find the lowest ooxygen release potential
125+
O_volts = 1000.0
126+
i_volts = -1
127+
for i in xrange(len(O_y)):
128+
if O_y[i] < O_volts:
129+
i_volts = i
130+
O_volts = O_y[i]
131+
132+
# Annotate where O is released.
133+
if i_volts != -1:
134+
plt.annotate(r'$\mathrm{O_2-released}$', xy=(O_x[i_volts]+0.25, =O_y[i_volts]+0.1), fontsize=14,
135+
xytext=(O_x[i_volts]+0.6,O_y[i_volts]+0.6),
136+
arrowprops=dict(arrowstyle='-|>',fc='b'))
137+
138+
plt.tight_layout()
139+
plt.savefig('Li3'+base_comp+'.png')
140+
plt.close()
141+
142+
print garnet.entry.name + " {0:.4g}".format(garnet.delta_e) \
143+
+ " {0:.4g}".format(stability) + " " + str(garnet.calculation.band_gap) + " " + \
144+
" {0:.4g}".format(max(window_V)), " {0:.4g}".format(min(window_V)), str(phases)
145+
146+
147+
ps.clear_all()
148+
149+
# It is possible to access the structure (POSCAR) or
150+
# other input files (except POTCARs) as demonstrated below:
151+
152+
for i in garnets:
153+
if i.entry.name=='Li3Nd3Te2O12':
154+
print i.calculation.POSCAR
155+
print i.calculation.INCAR

0 commit comments

Comments
 (0)