def is_solid_phase(mat1, mat2, mat1_co=0.5): """Returns TRUE is there exists a all solid phase in the binary Pourbaix Diagram this means that the phase doesn't have any aqueous species. """ mat2_co = 1 - mat1_co pd_b = pd_entries(mat1, mat2) pd = PourbaixDiagram(pd_b, {mat1: mat1_co, mat2: mat2_co}) pl = PourbaixPlotter(pd) ppd = pl.pourbaix_plot_data([[-2, 16], [-3, 3]]) pd_lst = [] cnt = 0 for stable_entry in ppd[0]: pd_lst.append([]) pd_lst[cnt].append(ppd[0][stable_entry]) pd_lst[cnt].append(stable_entry.entrylist) cnt = cnt + 1 solidphase = False for i in pd_lst: if len(i[1]) == 1: if i[1][0].phase_type == 'Solid': solidphase = True if len(i[1]) == 2: if i[1][0].phase_type and i[1][1].phase_type == 'Solid': solidphase = True return solidphase
def phase_coord(entries, atom_comp, prim_elem=False): """ Produces a list of line segments corresponding to each phase area in a PD along with the PD entries corresponding to each area. The produced list is of the following form: list = [[[coordinate data], [pourbaix entry]], [], [] .... ] Args: entries: List of entries in a PD atom_comp: Composition of atom if system is binary, given as a fraction between 0 and 1. Corresponds to the element with lowest atomic number if prim_elem is left to its default prim_elem: Primary element to which the atom_comp is assigned """ # | - - phase_coord from pymatgen.analysis.pourbaix.maker import PourbaixDiagram from pymatgen.analysis.pourbaix.plotter import PourbaixPlotter from entry_methods import base_atom base_atoms = base_atom(entries) mat0 = base_atoms[0] if len(base_atoms) == 2: mat1 = base_atoms[1] else: mat1 = mat0 # If the primary element is declared then set the given composition to it if not prim_elem == False: for atom in base_atoms: if atom == prim_elem: mat0 = atom else: mat1 = atom pd = PourbaixDiagram(entries, {mat0: atom_comp, mat1: 1 - atom_comp}) pl = PourbaixPlotter(pd) ppd = pl.pourbaix_plot_data([[-2, 16], [-3, 3]]) #ppd == Pourbaix_Plot Data pd_lst = [] cnt = 0 for stable_entry in ppd[0]: pd_lst.append([]) pd_lst[cnt].append(ppd[0][stable_entry]) pd_lst[cnt].append(stable_entry.entrylist) cnt = cnt + 1 return pd_lst
def phase_coord(entries, atom_comp, prim_elem=None): """Produces a list of line segments corresponding to each phase area in a PD along with the PD entries corresponding to each area. The produced list is of the following form: list = [[[coordinate data], [pourbaix entry]], [], [] .... ] Parameters: ----------- entries: list entries in a PD atom_comp: float Composition of atom if system is binary, given as a fraction between 0 and 1. Corresponds to the element with lowest atomic number if prim_elem is left to its default prim_elem: str Primary element to which the atom_comp is assigned """ base_atoms = base_atom(entries) mat0 = base_atoms[0] if len(base_atoms) == 2: mat1 = base_atoms[1] else: mat1 = mat0 if prim_elem: for atom in base_atoms: if atom == prim_elem: mat0 = atom else: mat1 = atom pd = PourbaixDiagram(entries, {mat0: atom_comp, mat1: 1 - atom_comp}) pl = PourbaixPlotter(pd) ppd = pl.pourbaix_plot_data([[-2, 16], [-3, 3]]) pd_lst = [] for i, stable_entry in enumerate(ppd[0]): pd_lst += [[]] pd_lst[i] += [ppd[0][stable_entry]] if isinstance(stable_entry, PourbaixEntry): pd_lst[i] += [stable_entry] else: pd_lst[i] += [stable_entry.entrylist] return pd_lst
def is_solid_phase(mat1, mat2, mat1_co=0.5): """ Returns TRUE is there exists a all solid phase in the binary Pourbaix Diagram This means that the phase doesn't have any aqueous species Args: mat1: mat2: mat1_co: """ # | - - is_solid_phase from pourdiag import pourdiag # Returns Pourbaix entries for binary system from pymatgen.analysis.pourbaix.maker import PourbaixDiagram from pymatgen.analysis.pourbaix.plotter import PourbaixPlotter mat2_co = 1 - mat1_co pd_b = pourdiag(mat1, mat2) return pd_b pd = PourbaixDiagram(pd_b, {mat1: mat1_co, mat2: mat2_co}) pl = PourbaixPlotter(pd) ppd = pl.pourbaix_plot_data([[-2, 16], [-3, 3]]) #ppd == Pourbaix_Plot Data pd_lst = [] cnt = 0 for stable_entry in ppd[0]: pd_lst.append([]) pd_lst[cnt].append(ppd[0][stable_entry]) pd_lst[cnt].append(stable_entry.entrylist) cnt = cnt + 1 solidphase = False for i in pd_lst: if len(i[1]) == 1: if i[1][0].phase_type == 'Solid': solidphase = True if len(i[1]) == 2: if i[1][0].phase_type and i[1][1].phase_type == 'Solid': solidphase = True return solidphase
def find_closest_point_pd(pourbaix_diagram_object): """ """ lw = 1 limits = [[-2, 16], [-3, 3]] plotter = PourbaixPlotter(pourbaix_diagram_object) (stable, unstable) = plotter.pourbaix_plot_data(limits) # Returns the Desirable Regions of PD in "vertices" vertices = [] for entry, lines in list(stable.items()): print(entry.name) is_desired = screening_check_desirable(entry, criteria='only-solid') if is_desired: desired_entry = entry for line in lines: (x, y) = line plt.plot(x, y, "k-", linewidth=lw) point1 = [x[0], y[0]] point2 = [x[1], y[1]] if point1 not in vertices and is_desired: vertices.append(point1) if point2 not in vertices and is_desired: vertices.append(point2) # Placing the desired phase's name in the diagram center_x = 0 center_y = 0 count = 0 for point in vertices: x, y = point count = count + 1 center_x = center_x + x center_y = center_y + y plt.plot(x, y, 'ro') center_x = center_x / count center_y = center_y / count plt.annotate(str(desired_entry.name), xy=(center_x, center_y)) # Plotting Water and Hydrogen Equilibrium Lines. Get water line h_line, o_line = get_water_stability_lines(limits) plt.plot(h_line[0], h_line[1], "r--", linewidth=lw) plt.plot(o_line[0], o_line[1], "r--", linewidth=lw) # Getting distances print("Getting distances of vertices") reference_line = o_line p1 = np.array([reference_line[0][0], reference_line[1][0]]) p2 = np.array([reference_line[0][1], reference_line[1][1]]) min_d = 1000.0 d_and_vert_lst = [] for p3 in vertices: np.array(p3) d = np.linalg.norm(np.cross(p2 - p1, p1 - p3)) / \ np.linalg.norm(p2 - p1) d_and_vert = [d, p3] d_and_vert_lst.append(d_and_vert) # https://stackoverflow.com/questions/39840030/distance-between-point-and-a-line-from-two-points # http://www.fundza.com/vectors/point2line/index.html print("Vertex: ", p3, "Distance: ", d) if d <= min_d: min_d = d fin_lst = [] for i in d_and_vert_lst: if round(i[0], 4) == round(min_d, 4): fin_lst.append(i) # Plotting the star on highest stability vertices for i in fin_lst: plt.plot(i[1][0], i[1][1], '*b', ms=16) ########################################### V_RHE = 1.23 - min_d pH_0 = fin_lst[0][1][0] V_SHE = V_RHE - PREFAC * pH_0 ########################################### # plt.annotate('d = '+ str(round(min_d,2)),xy=(center_x, center_y-0.3)) plt.annotate('V_crit = ' + str(round(V_RHE, 2)) + ' VvsRHE', xy=(center_x, center_y - 0.3)) plt.annotate('V_crit = ' + str(round(V_SHE, 2)) + ' VvsSHE', xy=(center_x, center_y - 0.6)) plt.xlabel("pH") plt.ylabel("E (V)") plt.show()
def plot_pourbaix_diagram(metastability=0.0, ion_concentration=1e-6, fmt='pdf'): """ Creates a Pourbaix diagram for the material in the cwd. Args: metastability (float): desired metastable tolerance energy (meV/atom). <~50 is generally a sensible range to use. ion_concentration (float): in mol/kg. Sensible values are generally between 1e-8 and 1. fmt (str): matplotlib format style. Check the matplotlib docs for options. """ # Create a ComputedEntry object for the 2D material. composition = Structure.from_file('POSCAR').composition energy = Vasprun('vasprun.xml').final_energy cmpd = ComputedEntry(composition, energy) # Define the chemsys that describes the 2D compound. chemsys = ['O', 'H'] + [ elt.symbol for elt in composition.elements if elt.symbol not in ['O', 'H'] ] # Pick out the ions pertaining to the 2D compound. ion_dict = dict() for elt in chemsys: if elt not in ['O', 'H'] and ION_FORMATION_ENERGIES[elt]: ion_dict.update(ION_FORMATION_ENERGIES[elt]) elements = [Element(elt) for elt in chemsys if elt not in ['O', 'H']] # Add "correction" for metastability cmpd.correction -= float(cmpd.composition.num_atoms)\ * float(metastability) / 1000.0 # Calculate formation energy of the compound from its end # members form_energy = cmpd.energy for elt in composition.as_dict(): form_energy -= CHEMICAL_POTENTIALS[elt] * cmpd.composition[elt] # Convert the compound entry to a pourbaix entry. # Default concentration for solid entries = 1 pbx_cmpd = PourbaixEntry(cmpd) pbx_cmpd.g0_replace(form_energy) pbx_cmpd.reduced_entry() # Add corrected ionic entries to the pourbaix diagram # dft corrections for experimental ionic energies: # Persson et.al PHYSICAL REVIEW B 85, 235438 (2012) pbx_ion_entries = list() # Get PourbaixEntry corresponding to each ion. # Default concentration for ionic entries = 1e-6 # ion_energy = ion_exp_energy + ion_correction * factor # where factor = fraction of element el in the ionic entry # compared to the reference entry for elt in elements: for key in ion_dict: comp = Ion.from_formula(key) if comp.composition[elt] != 0: factor = comp.composition[elt] energy = ion_dict[key] pbx_entry_ion = PourbaixEntry(IonEntry(comp, energy)) pbx_entry_ion.correction = (ION_CORRECTIONS[elt.symbol] * factor) pbx_entry_ion.conc = ion_concentration pbx_entry_ion.name = key pbx_ion_entries.append(pbx_entry_ion) # 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_cmpd] + pbx_ion_entries pourbaix = PourbaixDiagram(all_entries) # Analysis features # panalyzer = PourbaixAnalyzer(pourbaix) # instability = panalyzer.get_e_above_hull(pbx_cmpd) plotter = PourbaixPlotter(pourbaix) plot = plotter.get_pourbaix_plot(limits=[[0, 14], [-2, 2]], label_domains=True) fig = plot.gcf() ax1 = fig.gca() # Add coloring to highlight the stability region for the 2D # material, if one exists. stable_entries = plotter.pourbaix_plot_data(limits=[[0, 14], [-2, 2]])[0] for entry in stable_entries: if entry == pbx_cmpd: col = plt.cm.Blues(0) else: col = plt.cm.rainbow( float(ION_COLORS[entry.composition.reduced_formula])) vertices = plotter.domain_vertices(entry) patch = Polygon(vertices, closed=True, fill=True, color=col) ax1.add_patch(patch) fig.set_size_inches((11.5, 9)) plot.tight_layout(pad=1.09) # Save plot if metastability: plot.suptitle('Metastable Tolerance =' ' {} meV/atom'.format(metastability), fontsize=20) plot.savefig('{}_{}.{}'.format(composition.reduced_formula, ion_concentration, fmt), transparent=True) else: plot.savefig('{}_{}.{}'.format(composition.reduced_formula, ion_concentration, fmt), transparent=True) plot.close()
def find_closest_point_pd(pourbaix_diagram_object): from pymatgen.analysis.pourbaix.plotter import PourbaixPlotter import matplotlib.pyplot as plt import numpy as np from pymatgen.util.coord_utils import in_coord_list from pymatgen.analysis.pourbaix.maker import PREFAC lw = 1 limits = [[-2, 16], [-3, 3]] fig1 = plt.figure() ax = fig1.gca() plotter = PourbaixPlotter(pourbaix_diagram_object) (stable, unstable) = plotter.pourbaix_plot_data(limits) #| - - Ambar's Region Filter Check Function def screening_check_desirable(entry, criteria='only-solid'): is_desired = False if criteria not in ['only-solid']: print "Not implemented" sys.exit() if criteria == 'only-solid': if entry.nH2O == 0.0 and entry.npH == 0.0 and entry.nPhi == 0.0: is_desired = True print "Desired entry", entry.name if not criteria: print "Not desired entry", entry.name return is_desired #__| #| - - Ambar's Function for Water and Hydrogen Lines def get_water_stability_lines(limits): from pymatgen.analysis.pourbaix.maker import PREFAC xlim = limits[0] ylim = limits[1] h_line = np.transpose([[xlim[0], -xlim[0] * PREFAC], [xlim[1], -xlim[1] * PREFAC]]) o_line = np.transpose([[xlim[0], -xlim[0] * PREFAC + 1.23], [xlim[1], -xlim[1] * PREFAC + 1.23]]) return (h_line, o_line) #__| #| - - Returns the Desirable Regions of PD in "vertices" vertices = [] import time for entry, lines in stable.items(): print entry.name is_desired = screening_check_desirable(entry, criteria='only-solid') if is_desired: desired_entry = entry for line in lines: (x, y) = line #print "points", x, y plt.plot(x, y, "k-", linewidth=lw) point1 = [x[0], y[0]] point2 = [x[1], y[1]] if point1 not in vertices and is_desired: vertices.append(point1) if point2 not in vertices and is_desired: vertices.append(point2) #__| #| - - Placing the desired phase's name in the diagram center_x = 0 center_y = 0 count = 0 for point in vertices: x, y = point count = count + 1 center_x = center_x + x center_y = center_y + y plt.plot(x, y, 'ro') center_x = center_x / count center_y = center_y / count plt.annotate(str(desired_entry.name), xy=(center_x, center_y)) #__| #| - - Plotting Water and Hydrogen Equilibrium Lines # Get water line h_line, o_line = get_water_stability_lines(limits) plt.plot(h_line[0], h_line[1], "r--", linewidth=lw) plt.plot(o_line[0], o_line[1], "r--", linewidth=lw) #__| # Getting distances print "Getting distances of vertices" reference_line = o_line p1 = np.array([reference_line[0][0], reference_line[1][0]]) p2 = np.array([reference_line[0][1], reference_line[1][1]]) min_d = 1000.0 min_vertex = [] d_and_vert_lst = [] for p3 in vertices: np.array(p3) d = np.linalg.norm(np.cross(p2 - p1, p1 - p3)) / np.linalg.norm(p2 - p1) d_and_vert = [d, p3] d_and_vert_lst.append(d_and_vert) #https://stackoverflow.com/questions/39840030/distance-between-point-and-a-line-from-two-points #http://www.fundza.com/vectors/point2line/index.html print "Vertex: ", p3, "Distance: ", d if d <= min_d: min_d = d min_vertex = p3 fin_lst = [] for i in d_and_vert_lst: if round(i[0], 4) == round(min_d, 4): fin_lst.append(i) # Plotting the star on highest stability vertices for i in fin_lst: plt.plot(i[1][0], i[1][1], '*b', ms=16) ########################################### V_RHE = 1.23 - min_d pH_0 = fin_lst[0][1][0] V_SHE = V_RHE - PREFAC * pH_0 ########################################### # plt.annotate('d = '+ str(round(min_d,2)),xy=(center_x, center_y-0.3)) plt.annotate('V_crit = ' + str(round(V_RHE, 2)) + ' VvsRHE', xy=(center_x, center_y - 0.3)) plt.annotate('V_crit = ' + str(round(V_SHE, 2)) + ' VvsSHE', xy=(center_x, center_y - 0.6)) plt.xlabel("pH") plt.ylabel("E (V)") plt.show()
def plot_pourbaix_diagram(metastability=0.0, ion_concentration=1e-6, fmt='pdf'): """ Creates a Pourbaix diagram for the material in the cwd. Args: metastability (float): desired metastable tolerance energy (meV/atom). <~50 is generally a sensible range to use. ion_concentration (float): in mol/kg. Sensible values are generally between 1e-8 and 1. fmt (str): matplotlib format style. Check the matplotlib docs for options. """ # Create a ComputedEntry object for the 2D material. composition = Structure.from_file('POSCAR').composition energy = Vasprun('vasprun.xml').final_energy cmpd = ComputedEntry(composition, energy) # Define the chemsys that describes the 2D compound. chemsys = ['O', 'H'] + [elt.symbol for elt in composition.elements if elt.symbol not in ['O', 'H']] # Pick out the ions pertaining to the 2D compound. ion_dict = dict() for elt in chemsys: if elt not in ['O', 'H'] and ION_FORMATION_ENERGIES[elt]: ion_dict.update(ION_FORMATION_ENERGIES[elt]) elements = [Element(elt) for elt in chemsys if elt not in ['O', 'H']] # Add "correction" for metastability cmpd.correction -= float(cmpd.composition.num_atoms)\ * float(metastability) / 1000.0 # Calculate formation energy of the compound from its end # members form_energy = cmpd.energy for elt in composition.as_dict(): form_energy -= CHEMICAL_POTENTIALS[elt] * cmpd.composition[elt] # Convert the compound entry to a pourbaix entry. # Default concentration for solid entries = 1 pbx_cmpd = PourbaixEntry(cmpd) pbx_cmpd.g0_replace(form_energy) pbx_cmpd.reduced_entry() # Add corrected ionic entries to the pourbaix diagram # dft corrections for experimental ionic energies: # Persson et.al PHYSICAL REVIEW B 85, 235438 (2012) pbx_ion_entries = list() # Get PourbaixEntry corresponding to each ion. # Default concentration for ionic entries = 1e-6 # ion_energy = ion_exp_energy + ion_correction * factor # where factor = fraction of element el in the ionic entry # compared to the reference entry for elt in elements: for key in ion_dict: comp = Ion.from_formula(key) if comp.composition[elt] != 0: factor = comp.composition[elt] energy = ion_dict[key] pbx_entry_ion = PourbaixEntry(IonEntry(comp, energy)) pbx_entry_ion.correction = ( ION_CORRECTIONS[elt.symbol] * factor ) pbx_entry_ion.conc = ion_concentration pbx_entry_ion.name = key pbx_ion_entries.append(pbx_entry_ion) # 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_cmpd] + pbx_ion_entries total = sum([composition[el] for el in elements]) comp_dict = {el.symbol: composition[el]/total for el in elements} pourbaix_diagram = PourbaixDiagram(all_entries, comp_dict=comp_dict) plotter = PourbaixPlotter(pourbaix_diagram) # Plotting details... font = "serif" fig = plt.figure(figsize=(14, 9)) ax1 = fig.gca() ax1.set_xlim([0, 14]) ax1.set_xticklabels([int(t) for t in ax1.get_xticks()], fontname=font, fontsize=18) ax1.set_ylim(-2, 2) ax1.set_yticklabels(ax1.get_yticks(), fontname=font, fontsize=18) ax1.set_xlabel("pH", fontname=font, fontsize=18) ax1.set_ylabel("Potential vs. SHE (V)", fontname=font, fontsize=18) # Outline water's stability range. ax1.plot([0, 14], [0, -0.829], color="gray", linestyle="--", alpha=0.7, linewidth=2) ax1.plot([0, 14], [1.229, 0.401], color="gray", linestyle="--", alpha=0.7, linewidth=2) stable_entries = plotter.pourbaix_plot_data( limits=[[0, 14], [-2, 2]])[0] # Add coloring. colors = sb.color_palette("Set2", len(stable_entries)) i = 0 for entry in stable_entries: col = colors[i] i += 1 vertices = plotter.domain_vertices(entry) center_x = sum([v[0] for v in vertices])/len(vertices) center_y = sum([v[1] for v in vertices])/len(vertices) patch = Polygon(vertices, closed=True, fill=True, facecolor=col, linewidth=2, edgecolor="w") ax1.text(center_x, center_y, plotter.print_name(entry), verticalalignment="center", horizontalalignment="center", fontname=font, fontsize=18) ax1.add_patch(patch) plt.savefig("pourbaix.{}".format(fmt)) plt.close()
def plot_pourbaix_diagram(metastability=0.0, ion_concentration=1e-6, fmt='pdf'): """ Creates a Pourbaix diagram for the material in the cwd. Args: metastability (float): desired metastable tolerance energy (meV/atom). <~50 is generally a sensible range to use. ion_concentration (float): in mol/kg. Sensible values are generally between 1e-8 and 1. fmt (str): matplotlib format style. Check the matplotlib docs for options. """ # Create a ComputedEntry object for the 2D material. composition = Structure.from_file('POSCAR').composition energy = Vasprun('vasprun.xml').final_energy cmpd = ComputedEntry(composition, energy) # Define the chemsys that describes the 2D compound. chemsys = ['O', 'H'] + [elt.symbol for elt in composition.elements if elt.symbol not in ['O', 'H']] # Experimental ionic energies # See ions.yaml for ion formation energies and references. exp_dict = ION_DATA['ExpFormEnergy'] ion_correction = ION_DATA['IonCorrection'] # Pick out the ions pertaining to the 2D compound. ion_dict = dict() for elt in chemsys: if elt not in ['O', 'H'] and exp_dict[elt]: ion_dict.update(exp_dict[elt]) elements = [Element(elt) for elt in chemsys if elt not in ['O', 'H']] # Add "correction" for metastability cmpd.correction -= float(cmpd.composition.num_atoms)\ * float(metastability) / 1000.0 # Calculate formation energy of the compound from its end # members form_energy = cmpd.energy for elt in composition.as_dict(): form_energy -= END_MEMBERS[elt] * cmpd.composition[elt] # Convert the compound entry to a pourbaix entry. # Default concentration for solid entries = 1 pbx_cmpd = PourbaixEntry(cmpd) pbx_cmpd.g0_replace(form_energy) pbx_cmpd.reduced_entry() # Add corrected ionic entries to the pourbaix diagram # dft corrections for experimental ionic energies: # Persson et.al PHYSICAL REVIEW B 85, 235438 (2012) pbx_ion_entries = list() # Get PourbaixEntry corresponding to each ion. # Default concentration for ionic entries = 1e-6 # ion_energy = ion_exp_energy + ion_correction * factor # where factor = fraction of element el in the ionic entry # compared to the reference entry for elt in elements: for key in ion_dict: comp = Ion.from_formula(key) if comp.composition[elt] != 0: factor = comp.composition[elt] energy = ion_dict[key] pbx_entry_ion = PourbaixEntry(IonEntry(comp, energy)) pbx_entry_ion.correction = ion_correction[elt.symbol]\ * factor pbx_entry_ion.conc = ion_concentration pbx_entry_ion.name = key pbx_ion_entries.append(pbx_entry_ion) # 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_cmpd] + pbx_ion_entries pourbaix = PourbaixDiagram(all_entries) # Analysis features panalyzer = PourbaixAnalyzer(pourbaix) # instability = panalyzer.get_e_above_hull(pbx_cmpd) plotter = PourbaixPlotter(pourbaix) plot = plotter.get_pourbaix_plot(limits=[[0, 14], [-2, 2]], label_domains=True) fig = plot.gcf() ax1 = fig.gca() # Add coloring to highlight the stability region for the 2D # material, if one exists. stable_entries = plotter.pourbaix_plot_data( limits=[[0, 14], [-2, 2]])[0] for entry in stable_entries: if entry == pbx_cmpd: col = plt.cm.Blues(0) else: col = plt.cm.rainbow(float( ION_COLORS[entry.composition.reduced_formula])) vertices = plotter.domain_vertices(entry) patch = Polygon(vertices, closed=True, fill=True, color=col) ax1.add_patch(patch) fig.set_size_inches((11.5, 9)) plot.tight_layout(pad=1.09) # Save plot if metastability: plot.suptitle('Metastable Tolerance =' ' {} meV/atom'.format(metastability), fontsize=20) plot.savefig('{}_{}.{}'.format( composition.reduced_formula, ion_concentration, fmt), transparent=True) else: plot.savefig('{}_{}.{}'.format(composition.reduced_formula, ion_concentration, fmt), transparent=True) plot.close()