Skip to content

Exploring Materials Synthesis with MP Data and Reaction Networks

Author: Matthew McDermott
Last updated: 08/05/21

Goal

Learn how to build & interpret phase diagrams using MP data and apply these to predict reaction pathways in inorganic materials synthesis.

Outline

  1. Identifying a target system
  2. Building phase diagrams
  3. Predicting interface reactions between solids
  4. Enumerating all possible reactions to a specific target phase
  5. Constructing a reaction network from enumerated reactions
  6. Finding and balancing reaction pathways

1. Identifying a target system

Scenario:

While researching ferroelectric materials, you stumble upon a compound that has shown much promise as a multiferroic material: yttrium manganese oxide, YMnO\(_3\). When you consult the literature, it looks like there are many different approaches for making this material: solid-state synthesis, chimie douce methods, microwave-assisted synthesis, pulsed laser deposition, hydrothermal synthesis, etc.

In almost all of the papers you find, however, the authors describe significant difficulty in synthesizing phase-pure YMnO\(_3\). For example: - "... observation that crystallization at low temperature or high oxygen partial pressures gives a mixture of Y2Mn2O7 together with YMnO3" Brinks et al., Journal of Solid State Chemistry 129, 334-340 (1997). - "The solid state synthesis of YMnO3 requires very long procedure with repeated heating and grinding" Z. Brankovic et al. Ceramics International 41 (2015) - "There are still challenges to be addressed with respect to hydrothermal synthesis of h-YMnO3, most notably the difficulty in synthesising phase pure h-YMnO3. This is a result of the complexity of the system, with a total of eight crystalline phases having been detected throughout the course of the reaction." Marshall et al., Chem Eur. J 2020, 26, 9330-9337 (2020).

Being familiar with the Materials Project database and pymatgen, you decide to check the database to see if it can help answer the question: why is phase-pure YMnO\(_3\) so difficult to synthesize?

We previously learned how to use the MPRester to access computed data on the Materials Project. Let's start by importing MPRester:

from mp_api.matproj import MPRester

1.1 EXERCISE: Acquiring entries from MP

Using the MPRester, acquire all entries from the Materials Project with the composition YMnO\(_3\) in the cell below:

with MPRester() as mpr:
    entries = mpr.get_entries(chemsys_formula="YMnO3")
/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/maggma/api/utils.py:104: RuntimeWarning: fields may not start with an underscore, ignoring "_framework_formula"
  for model in get_flat_models_from_model(pydantic_model)
/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/maggma/api/utils.py:104: RuntimeWarning: fields may not start with an underscore, ignoring "_stable_entries"
  for model in get_flat_models_from_model(pydantic_model)
/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/maggma/api/utils.py:104: RuntimeWarning: fields may not start with an underscore, ignoring "_unstable_entries"
  for model in get_flat_models_from_model(pydantic_model)

1.2 Exploring downloaded entries

Now let's take a look at one of the downloaded entry objects.

In the ComputedStructureEntry printout, we can see the uncorrected energy, correction, final energy, and the various parameters/data associated with the calculation.

Since this is hard to interpret, it will be easier for us to reformat the entries into a pandas DataFrame with the relevant information. First we import pandas:

import pandas

And then we create a function to help us wrangle the entries into the DataFrame format:

def get_df_from_entries(entries):
    formulas = [e.composition.reduced_formula for e in entries]
    energies = [e.energy_per_atom for e in entries]
    spacegroups = [e.structure.get_space_group_info()[0] for e in entries]
    structures = [e.structure for e in entries]

    data = {"formula": formulas, "energy": energies, "spacegroup": spacegroups, "entry":entries}

    df = pandas.DataFrame(data).sort_values("energy")

    return df

The dataframe can now be easily created by calling this function:

df = get_df_from_entries(entries)
df
formula energy spacegroup entry
4 YMnO3 -9.130481 P6_3cm mp-19385 ComputedStructureEntry - Y6 Mn6 O18 ...
0 YMnO3 -9.109891 P6_3/mmc mp-19227 ComputedStructureEntry - Y2 Mn2 O6 ...
3 YMnO3 -9.107394 Pnma mp-20699 ComputedStructureEntry - Y4 Mn4 O12 ...
1 YMnO3 -8.805429 Pm-3m mp-1434307 ComputedStructureEntry - Y1 Mn1 O3 ...
2 YMnO3 -8.731478 Pnma mp-20699 ComputedStructureEntry - Y4 Mn4 O12 ...

We see that there are several polymorphs of similar energy. The lowest energy polymorph is the hexagonal YMnO\(_3\) phase which is well known as the thermodynamically stable phase in the literature:

structure = df.iloc[0]["entry"].structure
print(structure)
Full Formula (Y6 Mn6 O18)
Reduced Formula: YMnO3
abc   :   6.233022   6.233022  11.589090
angles:  90.000000  90.000000 119.999996
Sites (30)
  #  SP           a         b         c    magmom
---  ----  --------  --------  --------  --------
  0  Y     0.666667  0.333333  0.233045     0.019
  1  Y     0.333333  0.666667  0.733045     0.019
  2  Y     0.666667  0.333333  0.733045     0.019
  3  Y     0.333333  0.666667  0.233045     0.019
  4  Y     0         0         0.775978     0.016
  5  Y     0         0         0.275978     0.016
  6  Mn    0.666399  0         0.501375     3.939
  7  Mn    0.666399  0.666399  0.001375     3.931
  8  Mn    0         0.333601  0.001375     3.931
  9  Mn    0         0.666399  0.501375     3.939
 10  Mn    0.333601  0.333601  0.501375     3.939
 11  Mn    0.333601  0         0.001375     3.931
 12  O     0.666667  0.333333  0.021222    -0.035
 13  O     0.333333  0.666667  0.521222    -0.026
 14  O     0.666667  0.333333  0.521222    -0.026
 15  O     0.333333  0.666667  0.021222    -0.035
 16  O     0         0         0.97754     -0.03
 17  O     0         0         0.47754     -0.022
 18  O     0.358595  0         0.837277    -0.026
 19  O     0.358595  0.358595  0.337277    -0.026
 20  O     0         0.641405  0.337277    -0.026
 21  O     0         0.358595  0.837277    -0.026
 22  O     0.641405  0.641405  0.837277    -0.026
 23  O     0.641405  0         0.337277    -0.026
 24  O     0.307715  0         0.165664    -0.03
 25  O     0.307715  0.307715  0.665664    -0.03
 26  O     0         0.692285  0.665664    -0.03
 27  O     0         0.307715  0.165664    -0.03
 28  O     0.692285  0.692285  0.165664    -0.03
 29  O     0.692285  0         0.665664    -0.03

If we want to interactively view this structure in JupyterLab, we can also import crystal_toolkit to view it:

import crystal_toolkit
structure
If you see this text, the Crystal Toolkit Jupyter Lab 

extension is not installed. You can install it by running 

"pip install crystaltoolkit-extension" 

from the same environment you run "jupyter lab". 

This only works in Jupyter Lab 3.x or above.


Structure Summary
Lattice
    abc : 6.2330216584852325 6.2330216584852325 11.58909
 angles : 90.0 90.0 119.99999637504301
 volume : 389.9215651386502
      A : 3.116511 -5.397955 0.0
      B : 3.116511 5.397955 0.0
      C : 0.0 0.0 11.58909
PeriodicSite: Y (3.1165, -1.7993, 2.7008) [0.6667, 0.3333, 0.2330]
PeriodicSite: Y (3.1165, 1.7993, 8.4953) [0.3333, 0.6667, 0.7330]
PeriodicSite: Y (3.1165, -1.7993, 8.4953) [0.6667, 0.3333, 0.7330]
PeriodicSite: Y (3.1165, 1.7993, 2.7008) [0.3333, 0.6667, 0.2330]
PeriodicSite: Y (0.0000, 0.0000, 8.9929) [0.0000, 0.0000, 0.7760]
PeriodicSite: Y (0.0000, 0.0000, 3.1983) [0.0000, 0.0000, 0.2760]
PeriodicSite: Mn (2.0768, -3.5972, 5.8105) [0.6664, 0.0000, 0.5014]
PeriodicSite: Mn (4.1537, 0.0000, 0.0159) [0.6664, 0.6664, 0.0014]
PeriodicSite: Mn (1.0397, 1.8008, 0.0159) [0.0000, 0.3336, 0.0014]
PeriodicSite: Mn (2.0768, 3.5972, 5.8105) [0.0000, 0.6664, 0.5014]
PeriodicSite: Mn (2.0793, 0.0000, 5.8105) [0.3336, 0.3336, 0.5014]
PeriodicSite: Mn (1.0397, -1.8008, 0.0159) [0.3336, 0.0000, 0.0014]
PeriodicSite: O (3.1165, -1.7993, 0.2459) [0.6667, 0.3333, 0.0212]
PeriodicSite: O (3.1165, 1.7993, 6.0405) [0.3333, 0.6667, 0.5212]
PeriodicSite: O (3.1165, -1.7993, 6.0405) [0.6667, 0.3333, 0.5212]
PeriodicSite: O (3.1165, 1.7993, 0.2459) [0.3333, 0.6667, 0.0212]
PeriodicSite: O (0.0000, 0.0000, 11.3288) [0.0000, 0.0000, 0.9775]
PeriodicSite: O (0.0000, 0.0000, 5.5343) [0.0000, 0.0000, 0.4775]
PeriodicSite: O (1.1176, -1.9357, 9.7033) [0.3586, 0.0000, 0.8373]
PeriodicSite: O (2.2351, -0.0000, 3.9087) [0.3586, 0.3586, 0.3373]
PeriodicSite: O (1.9989, 3.4623, 3.9087) [0.0000, 0.6414, 0.3373]
PeriodicSite: O (1.1176, 1.9357, 9.7033) [0.0000, 0.3586, 0.8373]
PeriodicSite: O (3.9979, -0.0000, 9.7033) [0.6414, 0.6414, 0.8373]
PeriodicSite: O (1.9989, -3.4623, 3.9087) [0.6414, 0.0000, 0.3373]
PeriodicSite: O (0.9590, -1.6610, 1.9199) [0.3077, 0.0000, 0.1657]
PeriodicSite: O (1.9180, -0.0000, 7.7144) [0.3077, 0.3077, 0.6657]
PeriodicSite: O (2.1575, 3.7369, 7.7144) [0.0000, 0.6923, 0.6657]
PeriodicSite: O (0.9590, 1.6610, 1.9199) [0.0000, 0.3077, 0.1657]
PeriodicSite: O (4.3150, 0.0000, 1.9199) [0.6923, 0.6923, 0.1657]
PeriodicSite: O (2.1575, -3.7369, 7.7144) [0.6923, 0.0000, 0.6657]

2. Building phase diagrams

Now that we've confirmed the existence of the target phase within the MP database, we'd like to better understand phase competition within the Y-Mn-O system. This means answering questions suchs as:

  1. Just how stable is YMnO\(_3\)?
  2. How much energy is released upon formation of YMnO\(_3\) from the corresponding binary oxides?
  3. What other phases might compete against the formation of YMnO\(_3\)?
  4. What kinds of oxygen chemical potentials stabilize YMnO\(_3\)?

These are all questions that can be answered by constructing phase diagrams within pymatgen.

2.1 EXERCISE: Acquiring all entries within the chemical system

Let's start by downloading entries for the full Y-Mn-O system using MPRester. How many entries exist within the full Y-Mn-O system?

with MPRester() as mpr:
    entries = mpr.get_entries_in_chemsys("Y-Mn-O")
print(len(entries))
160

2.2 Compositional phase diagrams

Now that we have all the entries within the Y-Mn-O system, we can create a ternary compositional phase diagram by simply passing the list of entries to create a PhaseDiagram object. Let's first import this class from the phase_diagram module:

from pymatgen.analysis.phase_diagram import PhaseDiagram

And we can create the phase diagram:

pd = PhaseDiagram(entries)

To plot the phase diagram, we can either: 1. Create a PDPlotter object and call get_plot() with custom arguments 2. Create a PDPlotter object and call show() 3. In JupyterLab, just type the name of the phase diagram object in a cell and click "enter"!

Let's do option 1 so that we can see the possible arguments of the plotting function. First we import PDPlotter:

from pymatgen.analysis.phase_diagram import PDPlotter

And then we create the plotting object and call the get_plot() function:

plotter = PDPlotter(pd)
plotter.get_plot()