Assignment 3 Solution: Introduction to pymatgen

1. Install pymatgen (reccomended: install into a virtual environment. See resources)

If you need help, please send an email to whomever is helping you with this course.

2. Open up an interactive Python interpreter (or Jupyter notebook) and go through the pymatgen quick start examples. Pay particular attention to the instance of the Structure class (rather than Element or Molecule). Since our group deals primarily with infinite crystalline lattices, we use pymatgen structures almost exclusively.


In [2]:
import pymatgen as pmg
si = pmg.Element('Si')
print('Si:')
print(si.atomic_mass)
print(si.common_oxidation_states)
print(si.number)

lattice = pmg.Lattice.cubic(4.2)
cscl = pmg.Structure(lattice, ["Cs", "Cl"], [[0,0,0],[0.5,0.5,0.5]])
print('\nCsCl structure')
print(cscl)
print('\n')
print(cscl.composition)
cscl.to(filename='POSCAR')
# ... 
# The examples are online at http://pymatgen.org/#quick-start


Si:
28.0855 amu
(-4, 4)
14

CsCl structure
Full Formula (Cs1 Cl1)
Reduced Formula: CsCl
abc   :   4.200000   4.200000   4.200000
angles:  90.000000  90.000000  90.000000
Sites (2)
  #  SP      a    b    c
---  ----  ---  ---  ---
  0  Cs    0    0    0
  1  Cl    0.5  0.5  0.5


Cs1 Cl1

3. Create the following Structures from Lattices. Instead of using the convience class methods e.g. Lattice.cubic, create them from basis vectors. Print the volumes and densities of the structures after you create them to check yourself. The API documentation for these classes may be helpful (see resources). Pay attention to the units! You are encourage, but not required to use Structure.to('POSCAR') (or CIF) and then load the file into something like VESTA (free) or CrystalMaker (commercial).

i. Po. Simple cubic with lattice parameter of 335 pm


In [3]:
from pymatgen import Structure, Lattice
# convert 335 pm to A:
a = 335*10**-2 # lattice parameter, a
latt = Lattice([[a, 0, 0], [0, a, 0], [0, 0, a]])
Po = Structure(latt, ['Po'], [(0, 0, 0)])
print(Po)
print(Po.volume)
print(Po.density)


Full Formula (Po1)
Reduced Formula: Po
abc   :   3.350000   3.350000   3.350000
angles:  90.000000  90.000000  90.000000
Sites (1)
  #  SP      a    b    c
---  ----  ---  ---  ---
  0  Po      0    0    0
37.595375
9.27542811849 g

ii. Fe. Body centered cubic with lattice parameter of 2.866 Angstrom


In [4]:
a = 2.866 # lattice parameter, a
latt = Lattice([[a, 0, 0], [0, a, 0], [0, 0, a]])
Fe = Structure(latt, ['Fe', 'Fe'], [(0, 0, 0), (0.5, 0.5, 0.5)])
print(Fe)
print(Fe.volume)
print(Fe.density)


Full Formula (Fe2)
Reduced Formula: Fe
abc   :   2.866000   2.866000   2.866000
angles:  90.000000  90.000000  90.000000
Sites (2)
  #  SP      a    b    c
---  ----  ---  ---  ---
  0  Fe    0    0    0
  1  Fe    0.5  0.5  0.5
23.541197896
7.87834188375 g

iii. Al. Face centered cubic with volume of 65.89 cubic Angstrom


In [5]:
a = 65.89**(1.0/3.0) # lattice parameter, a
latt = Lattice([[a, 0, 0], [0, a, 0], [0, 0, a]])
Al = Structure(latt, ['Al', 'Al', 'Al', 'Al'], [(0.0,0.0,0.0), (0.5,0.5,0.0),
                                                (0.5,0.0,0.5), (0.0,0.5,0.5)])
print(Al)
print(Al.volume)
print(Al.density)


Full Formula (Al4)
Reduced Formula: Al
abc   :   4.038994   4.038994   4.038994
angles:  90.000000  90.000000  90.000000
Sites (4)
  #  SP      a    b    c
---  ----  ---  ---  ---
  0  Al    0    0    0
  1  Al    0.5  0.5  0
  2  Al    0.5  0    0.5
  3  Al    0    0.5  0.5
65.89
2.71992097159 g

iv. NaCl. Rock salt structure. Use the Lattice.cubic staticmethod and a lattice parameter of 5.6402 Angstrom


In [6]:
a = 5.6402 # lattice parameter, a
latt = Lattice.cubic(a)
NaCl = Structure(latt, ['Na', 'Na', 'Na', 'Na', 'Cl', 'Cl', 'Cl', 'Cl'], 
                 [(0.0,0.0,0.0), (0.5,0.5,0.0), (0.5,0.0,0.5), (0.0,0.5,0.5),
                  (0.5,0.0,0.0), (0.0,0.5,0.0), (0.0,0.0,0.5), (0.5,0.5,0.5)])
print(NaCl)
print(NaCl.volume)
print(NaCl.density)
NaCl.to(filename='POSCAR')


Full Formula (Na4 Cl4)
Reduced Formula: NaCl
abc   :   5.640200   5.640200   5.640200
angles:  90.000000  90.000000  90.000000
Sites (8)
  #  SP      a    b    c
---  ----  ---  ---  ---
  0  Na    0    0    0
  1  Na    0.5  0.5  0
  2  Na    0.5  0    0.5
  3  Na    0    0.5  0.5
  4  Cl    0.5  0    0
  5  Cl    0    0.5  0
  6  Cl    0    0    0.5
  7  Cl    0.5  0.5  0.5
179.425230437
2.16349729096 g

v. Ti. Hexagonal. For this, you can use the hexagonal staticmethod. Try to look up the correct lattice parameter by browsing the Materials Project. It's highly suggested to plot this and convince yourself that the answer is correct. For best results, turn on space filling and increase the boundary to see the close packed structure.

An interesting note here: first principles calculations find the most stable Ti phase to be omega-Ti, when we usually find beta-Ti (bcc) in nature. The reason for this is that bcc is dynamically stabilized (with temperature). See Kadkhodaei, Hong, and van de Walle. Phys. Rev. B 95 (2017) 064101.

Any answer for this question is really fine, but the idea was to use the hexagonal constructor and the true hcp structure is mp-46 (the omega phase is mp-72)


In [7]:
# found lattice parameters for P6_3/mmc at https://materialsproject.org/materials/mp-46/
# this i
a = 2.939
c = 4.641
latt = Lattice.hexagonal(a, c)
Ti = Structure(latt, ['Ti', 'Ti'], 
                 [(0.0,0.33333,0.0), (0.33333,0.0, 0.5)])
print(Ti)
print(Ti.volume)
print(Ti.density)
Ti.to(filename='POSCAR')


Full Formula (Ti2)
Reduced Formula: Ti
abc   :   2.939000   2.939000   4.641000
angles:  90.000000  90.000000 120.000000
Sites (2)
  #  SP          a        b    c
---  ----  -------  -------  ---
  0  Ti    0        0.33333  0
  1  Ti    0.33333  0        0.5
34.7169346758
4.57903458183 g

HCP Ti

HCP Ti with space filling

4. Now that you have some appreciation for the tedious creation of structures from lattices, even for pure elements, you might imaging that 'there must be a better way'. You may have noticed on the Materials Project that there are many different spacegroups. Spacegroups define different symmetry elements in infinite 2D or 3D lattices and are useful for both understanding and predicting properties and useful in a practical sense. Make the following structures from spacegroups (note, if not given, you're intended to look them up)

i. NaCl has the spacegroupm F-m3-m, where an Na can be found at (0,0,0) and Cl at (0.5,0.5,0.5). Make a Structure object directly from the spacegroup and atom positions (don't make a Lattice). Look up the API to do this in the pymatgen documentation. Take note that You only have to enter one of each element, unlike in the problem above. Explain why this is.

Note that the Structure.from_spacegroup classmethod can take either the symbol or the number. I've used both here. For NaCl, you should get exactly the same result as above (unless you use a different lattice or site coordinates)


In [8]:
a = 5.6402 # lattice parameter, a
latt = Lattice.cubic(a)
NaCl_spg = Structure.from_spacegroup('Fm-3m', latt, ['Na', 'Cl'], [(0,0,0), (0.5,0.5,0.5)])
print(NaCl_spg)
print(NaCl_spg.volume)
print(NaCl_spg.density)


Full Formula (Na4 Cl4)
Reduced Formula: NaCl
abc   :   5.640200   5.640200   5.640200
angles:  90.000000  90.000000  90.000000
Sites (8)
  #  SP      a    b    c
---  ----  ---  ---  ---
  0  Na    0    0    0
  1  Na    0    0.5  0.5
  2  Na    0.5  0    0.5
  3  Na    0.5  0.5  0
  4  Cl    0.5  0.5  0.5
  5  Cl    0.5  0    0
  6  Cl    0    0.5  0
  7  Cl    0    0    0.5
179.425230437
2.16349729096 g

ii. Pick a relatively complex (3 or more component) metal or oxide structure from the Materials Project and create it from the spacegroup. Optionally, visualize it in VESTA to verify that you constructed it correctly.

For this I chose forsterite. After applying symmetry operations, there are 28 atoms in the cell but we only needed to enter 6 positions. Symmetry is great.


In [9]:
a, b, c = 4.803, 6.048, 10.323 # lattice parameter, a
latt = Lattice.orthorhombic(a, b, c)
forsterite = Structure.from_spacegroup(62, latt, ['Mg', 'Mg', 'Si', 'O', 'O', 'O'],
                                       [(0, 0, 0), 
                                        (0.222736, 0.750000, 0.491625),
                                        (0.093638, 0.250000, 0.425974),
                                        (0.162835, 0.033014, 0.276946),
                                        (0.053218, 0.750000, 0.722149),
                                        (0.091677, 0.250000, 0.765961),])
print(forsterite)
print(forsterite.volume)
print(forsterite.density)
forsterite.to(filename='POSCAR')


Full Formula (Mg8 Si4 O16)
Reduced Formula: Mg2SiO4
abc   :   4.803000   6.048000  10.323000
angles:  90.000000  90.000000  90.000000
Sites (28)
  #  SP           a         b         c
---  ----  --------  --------  --------
  0  Mg    0         0         0
  1  Mg    0.5       0         0.5
  2  Mg    0.5       0.5       0.5
  3  Mg    0         0.5       0
  4  Mg    0.222736  0.75      0.491625
  5  Mg    0.277264  0.25      0.991625
  6  Mg    0.722736  0.75      0.008375
  7  Mg    0.777264  0.25      0.508375
  8  Si    0.093638  0.25      0.425974
  9  Si    0.406362  0.75      0.925974
 10  Si    0.593638  0.25      0.074026
 11  Si    0.906362  0.75      0.574026
 12  O     0.162835  0.033014  0.276946
 13  O     0.337165  0.966986  0.776946
 14  O     0.662835  0.466986  0.223054
 15  O     0.837165  0.533014  0.723054
 16  O     0.837165  0.966986  0.723054
 17  O     0.662835  0.033014  0.223054
 18  O     0.337165  0.533014  0.776946
 19  O     0.162835  0.466986  0.276946
 20  O     0.053218  0.75      0.722149
 21  O     0.446782  0.25      0.222149
 22  O     0.553218  0.75      0.777851
 23  O     0.946782  0.25      0.277851
 24  O     0.091677  0.25      0.765961
 25  O     0.408323  0.75      0.265961
 26  O     0.591677  0.25      0.734039
 27  O     0.908323  0.75      0.234039
299.868119712
3.1163884368 g

5. We've now streamlined Structure generation, but we can do better still. Using the Materials Project API, we can directly access the structures that we want and modify them from there. Read through the couple examples at the pymatgen REST API and find the actual API documentation and skim it. Then do the following using MPRester:

i. Get the Structure object for mp-134. Print it and compare it to the structure for the same material you made before. What is different? Why?

Keep in mind that we are using with MPRester() as mpr syntax. This is called a context manager.

This Al only has one site and the lattice is different, but the density is the same. The lattice vectors are printed below. You can see in the structure result that the angles are different and the lattice parameters are smaller as well. Tiling this structure in space gives the same structure as an fcc cell that is defined by 4 atoms.


In [10]:
from pymatgen import MPRester
with MPRester() as mpr:
    Al_api = mpr.get_structure_by_material_id('mp-134')
print(Al_api)    
print()
print(Al_api.lattice.matrix)
print(Al_api.volume)
print(Al_api.density)


Full Formula (Al1)
Reduced Formula: Al
abc   :   2.855955   2.855955   2.855955
angles:  60.000000  60.000000  60.000000
Sites (1)
  #  SP      a    b    c    coordination_no  forces
---  ----  ---  ---  ---  -----------------  ---------------
  0  Al      0    0    0                 12  [0.0, 0.0, 0.0]
()
[[ 2.47332919  0.          1.42797728]
 [ 0.82444306  2.33187713  1.42797728]
 [ 0.          0.          2.85595455]]
16.4717172192
2.72005022964 g

ii. Get the energy of mp-134.

Hint: since we specified the mp-id, we should use get_entry_by_material_id. If you wanted to use the formula, you could have used get_entry or get_data, but you would have had to find the right form of Al.


In [11]:
with MPRester() as mpr:
    result = mpr.get_entry_by_material_id('mp-134', property_data=['energy_per_atom'])
print(result.energy)
print(result.energy_per_atom)
# since we just saw that the structure only had one atom, this makes sense.


-3.74799675
-3.74799675

iii. Get all of the energies for C (carbon) structures as a dictionary

Here we actually do want to get the data for all structures for a formula, so we'll use get_data.


In [12]:
with MPRester() as mpr:
    result = mpr.get_data('C', prop='energy')
print(result)


[{u'energy': -18.23028394, u'material_id': u'mp-632329'}, {u'energy': -1043.58337059, u'material_id': u'mp-568028'}, {u'energy': -35.15284593, u'material_id': u'mp-1008374'}, {u'energy': -147.6075773, u'material_id': u'mp-568286'}, {u'energy': -72.64132214, u'material_id': u'mp-611426'}, {u'energy': -1242.76340292, u'material_id': u'mp-683919'}, {u'energy': -18.44360798, u'material_id': u'mp-937760'}, {u'energy': -6.46863693, u'material_id': u'mp-998866'}, {u'energy': -126.71494757, u'material_id': u'mp-569567'}, {u'energy': -530.2028216, u'material_id': u'mp-667273'}, {u'energy': -67.70347574, u'material_id': u'mp-570002'}, {u'energy': -18.44484253, u'material_id': u'mp-990448'}, {u'energy': -66.25122238, u'material_id': u'mp-579909'}, {u'energy': -36.88755236, u'material_id': u'mp-997182'}, {u'energy': -73.75439079, u'material_id': u'mp-568806'}, {u'energy': -31.70437838, u'material_id': u'mp-1018088'}, {u'energy': -18.17968607, u'material_id': u'mp-66'}, {u'energy': -110.66278207, u'material_id': u'mp-606949'}, {u'energy': -529.10330531, u'material_id': u'mp-680372'}, {u'energy': -145.35855192, u'material_id': u'mp-616440'}, {u'energy': -69.75276583, u'material_id': u'mp-568410'}, {u'energy': -18.44212036, u'material_id': u'mp-169'}, {u'energy': -63.76361783, u'material_id': u'mp-624889'}, {u'energy': -90.80287787, u'material_id': u'mp-569517'}, {u'energy': -36.89110618, u'material_id': u'mp-48'}, {u'energy': -109.00136766, u'material_id': u'mp-611448'}, {u'energy': -73.5733819, u'material_id': u'mp-569416'}, {u'energy': -36.88258572, u'material_id': u'mp-990424'}, {u'energy': -35.57474133, u'material_id': u'mp-1008395'}, {u'energy': -67.14506955, u'material_id': u'mp-24'}, {u'energy': -529.91904387, u'material_id': u'mp-630227'}, {u'energy': -36.25997986, u'material_id': u'mp-47'}, {u'energy': -36.78213314, u'material_id': u'mp-569304'}]

iv. Write a function that takes that dictionary and makes a list of energies (in any order)


In [13]:
def mp_dict_to_energies(d):
    """Return list of energies from a list of dictionaries `{'material_id':mp-id, 'energy': energy}`
    
    Parameters
    ----------
    d (list): List of dictionaries of the form `{'material_id':mp-id, 'energy': energy}`
    
    Returns
    -------
    list:
        List of energies from the input dictionary
    """
    energies = []
    for entry in d:
        energies.append(entry['energy'])
    return energies
print(mp_dict_to_energies(result))


[-18.23028394, -1043.58337059, -35.15284593, -147.6075773, -72.64132214, -1242.76340292, -18.44360798, -6.46863693, -126.71494757, -530.2028216, -67.70347574, -18.44484253, -66.25122238, -36.88755236, -73.75439079, -31.70437838, -18.17968607, -110.66278207, -529.10330531, -145.35855192, -69.75276583, -18.44212036, -63.76361783, -90.80287787, -36.89110618, -109.00136766, -73.5733819, -36.88258572, -35.57474133, -67.14506955, -529.91904387, -36.25997986, -36.78213314]

v. Do the same as above, except use a list comprehension instead of a function


In [14]:
energies = [entry['energy'] for entry in result]
print(energies)


[-18.23028394, -1043.58337059, -35.15284593, -147.6075773, -72.64132214, -1242.76340292, -18.44360798, -6.46863693, -126.71494757, -530.2028216, -67.70347574, -18.44484253, -66.25122238, -36.88755236, -73.75439079, -31.70437838, -18.17968607, -110.66278207, -529.10330531, -145.35855192, -69.75276583, -18.44212036, -63.76361783, -90.80287787, -36.89110618, -109.00136766, -73.5733819, -36.88258572, -35.57474133, -67.14506955, -529.91904387, -36.25997986, -36.78213314]

vi. What are the drawbacks of storing the energies in this way? Are there drawbacks for storing the data as two lists of ids and energies?

Variable answers. The idea was to think about differences between dicts and lists.

  • A dictionary is unordered (though they are now ordered by default in Python 3.6 and later).
  • Dictionaries excel when you need to drill down and look at all of the data for one structure.
  • When you want to compare a certain property for all structures, you more or less have to convert to a list first.
  • A database addresses both of these problems because you can query for specific entries or for a specific key/value for many entries.

6. Finally, we will practice using some of the methods of Structure objects to transform them. You are expected to read the documentation to see what these do. If the documentation is unclear, try clicking the [Source] button on the right to see the actual Python code. Print the result of each transformation to prove to yourself that you did it correctly. Note that some transformations modify the Structure object and have no return value while others the return the new object, leaving the original unchanged. You should keep track of this and make sure to update the same structure the whole way through, applying all of the transformations to the same structure.

i. Create a Structure of strontium ferrite, mp-510624. What is the chemical formula? What is the volume of the structure? The density?


In [15]:
with MPRester() as mpr:
    struct = mpr.get_structure_by_material_id('mp-510624')
print(struct)
print(struct.formula)
print(struct.volume)
print(struct.density)


Full Formula (Sr1 Fe1 O3)
Reduced Formula: SrFeO3
abc   :   3.911815   3.911815   3.911815
angles:  90.000000  90.000000  90.000000
Sites (5)
  #  SP           a         b         c    coordination_no  forces
---  ----  --------  --------  --------  -----------------  ---------------
  0  O     0.499999  0         0                         6  [0.0, 0.0, 0.0]
  1  O     0         0.499999  0                         6  [0.0, 0.0, 0.0]
  2  O     0         0         0.499999                  6  [0.0, 0.0, 0.0]
  3  Fe    0         0         0                         6  [0.0, 0.0, 0.0]
  4  Sr    0.499999  0.499999  0.499999                 12  [0.0, 0.0, 0.0]
Sr1 Fe1 O3
59.8597602378
5.31128285614 g

ii. Look at the band structure and band gap for that structure on the Materials Project website. Is this a metal, semiconductor or an insulator?

There is a gap in the bandstructure at about 5 eV above the Fermi energy. The gap is 0.332 eV. That means SrFeO3 is predicted to be a semiconductor

iii. Scale the volume to 56.965 cubic Angstrom


In [16]:
struct.scale_lattice(56.965)
print(struct.volume)


56.965

iv. Replace all of the Fe species with Co in one step


In [17]:
struct.replace_species({'Fe':'Co'})
print(struct)


Full Formula (Sr1 Co1 O3)
Reduced Formula: SrCoO3
abc   :   3.847713   3.847713   3.847713
angles:  90.000000  90.000000  90.000000
Sites (5)
  #  SP           a         b         c    coordination_no  forces
---  ----  --------  --------  --------  -----------------  ---------------
  0  O     0.499999  0         0                         6  [0.0, 0.0, 0.0]
  1  O     0         0.499999  0                         6  [0.0, 0.0, 0.0]
  2  O     0         0         0.499999                  6  [0.0, 0.0, 0.0]
  3  Co    0         0         0                         6  [0.0, 0.0, 0.0]
  4  Sr    0.499999  0.499999  0.499999                 12  [0.0, 0.0, 0.0]

v. Make a 2x2x2 supercell


In [18]:
struct.make_supercell([2,2,2]) # or just struct.make_supercell(2) works for this
print(struct)


Full Formula (Sr8 Co8 O24)
Reduced Formula: SrCoO3
abc   :   7.695427   7.695427   7.695427
angles:  90.000000  90.000000  90.000000
Sites (40)
  #  SP           a         b         c    coordination_no  forces
---  ----  --------  --------  --------  -----------------  ---------------
  0  O     0.25      0         0                         6  [0.0, 0.0, 0.0]
  1  O     0.25      0         0.5                       6  [0.0, 0.0, 0.0]
  2  O     0.25      0.5       0                         6  [0.0, 0.0, 0.0]
  3  O     0.25      0.5       0.5                       6  [0.0, 0.0, 0.0]
  4  O     0.749999  0         0                         6  [0.0, 0.0, 0.0]
  5  O     0.749999  0         0.5                       6  [0.0, 0.0, 0.0]
  6  O     0.749999  0.5       0                         6  [0.0, 0.0, 0.0]
  7  O     0.749999  0.5       0.5                       6  [0.0, 0.0, 0.0]
  8  O     0         0.25      0                         6  [0.0, 0.0, 0.0]
  9  O     0         0.25      0.5                       6  [0.0, 0.0, 0.0]
 10  O     0         0.749999  0                         6  [0.0, 0.0, 0.0]
 11  O     0         0.749999  0.5                       6  [0.0, 0.0, 0.0]
 12  O     0.5       0.25      0                         6  [0.0, 0.0, 0.0]
 13  O     0.5       0.25      0.5                       6  [0.0, 0.0, 0.0]
 14  O     0.5       0.749999  0                         6  [0.0, 0.0, 0.0]
 15  O     0.5       0.749999  0.5                       6  [0.0, 0.0, 0.0]
 16  O     0         0         0.25                      6  [0.0, 0.0, 0.0]
 17  O     0         0         0.749999                  6  [0.0, 0.0, 0.0]
 18  O     0         0.5       0.25                      6  [0.0, 0.0, 0.0]
 19  O     0         0.5       0.749999                  6  [0.0, 0.0, 0.0]
 20  O     0.5       0         0.25                      6  [0.0, 0.0, 0.0]
 21  O     0.5       0         0.749999                  6  [0.0, 0.0, 0.0]
 22  O     0.5       0.5       0.25                      6  [0.0, 0.0, 0.0]
 23  O     0.5       0.5       0.749999                  6  [0.0, 0.0, 0.0]
 24  Co    0         0         0                         6  [0.0, 0.0, 0.0]
 25  Co    0         0         0.5                       6  [0.0, 0.0, 0.0]
 26  Co    0         0.5       0                         6  [0.0, 0.0, 0.0]
 27  Co    0         0.5       0.5                       6  [0.0, 0.0, 0.0]
 28  Co    0.5       0         0                         6  [0.0, 0.0, 0.0]
 29  Co    0.5       0         0.5                       6  [0.0, 0.0, 0.0]
 30  Co    0.5       0.5       0                         6  [0.0, 0.0, 0.0]
 31  Co    0.5       0.5       0.5                       6  [0.0, 0.0, 0.0]
 32  Sr    0.25      0.25      0.25                     12  [0.0, 0.0, 0.0]
 33  Sr    0.25      0.25      0.749999                 12  [0.0, 0.0, 0.0]
 34  Sr    0.25      0.749999  0.25                     12  [0.0, 0.0, 0.0]
 35  Sr    0.25      0.749999  0.749999                 12  [0.0, 0.0, 0.0]
 36  Sr    0.749999  0.25      0.25                     12  [0.0, 0.0, 0.0]
 37  Sr    0.749999  0.25      0.749999                 12  [0.0, 0.0, 0.0]
 38  Sr    0.749999  0.749999  0.25                     12  [0.0, 0.0, 0.0]
 39  Sr    0.749999  0.749999  0.749999                 12  [0.0, 0.0, 0.0]

vi. Scale the volume up by 10%


In [19]:
print(struct.volume)
struct.scale_lattice(struct.volume*1.1)
print(struct.volume)


455.72
501.292

vii. Import and create a SpacegroupAnalyzer from pymatgen.symmetry.analyzer with your structure. Print the spacegroup symbol


In [20]:
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
sga = SpacegroupAnalyzer(struct)
print(sga.get_space_group_symbol())


Pm-3m

viii. Replace one of Co with an Fe. What is the chemical formula? What is the spacegroup symbol of this structure?

I chose the site manually from the site number printed above in the supercell.


In [21]:
struct.replace(24, 'Fe')
print(struct)
sga = SpacegroupAnalyzer(struct)
print(sga.get_space_group_symbol())


Full Formula (Sr8 Fe1 Co7 O24)
Reduced Formula: Sr8FeCo7O24
abc   :   7.943836   7.943836   7.943836
angles:  90.000000  90.000000  90.000000
Sites (40)
  #  SP           a         b         c    coordination_no  forces
---  ----  --------  --------  --------  -----------------  ---------------
  0  O     0.25      0         0                         6  [0.0, 0.0, 0.0]
  1  O     0.25      0         0.5                       6  [0.0, 0.0, 0.0]
  2  O     0.25      0.5       0                         6  [0.0, 0.0, 0.0]
  3  O     0.25      0.5       0.5                       6  [0.0, 0.0, 0.0]
  4  O     0.749999  0         0                         6  [0.0, 0.0, 0.0]
  5  O     0.749999  0         0.5                       6  [0.0, 0.0, 0.0]
  6  O     0.749999  0.5       0                         6  [0.0, 0.0, 0.0]
  7  O     0.749999  0.5       0.5                       6  [0.0, 0.0, 0.0]
  8  O     0         0.25      0                         6  [0.0, 0.0, 0.0]
  9  O     0         0.25      0.5                       6  [0.0, 0.0, 0.0]
 10  O     0         0.749999  0                         6  [0.0, 0.0, 0.0]
 11  O     0         0.749999  0.5                       6  [0.0, 0.0, 0.0]
 12  O     0.5       0.25      0                         6  [0.0, 0.0, 0.0]
 13  O     0.5       0.25      0.5                       6  [0.0, 0.0, 0.0]
 14  O     0.5       0.749999  0                         6  [0.0, 0.0, 0.0]
 15  O     0.5       0.749999  0.5                       6  [0.0, 0.0, 0.0]
 16  O     0         0         0.25                      6  [0.0, 0.0, 0.0]
 17  O     0         0         0.749999                  6  [0.0, 0.0, 0.0]
 18  O     0         0.5       0.25                      6  [0.0, 0.0, 0.0]
 19  O     0         0.5       0.749999                  6  [0.0, 0.0, 0.0]
 20  O     0.5       0         0.25                      6  [0.0, 0.0, 0.0]
 21  O     0.5       0         0.749999                  6  [0.0, 0.0, 0.0]
 22  O     0.5       0.5       0.25                      6  [0.0, 0.0, 0.0]
 23  O     0.5       0.5       0.749999                  6  [0.0, 0.0, 0.0]
 24  Fe    0         0         0
 25  Co    0         0         0.5                       6  [0.0, 0.0, 0.0]
 26  Co    0         0.5       0                         6  [0.0, 0.0, 0.0]
 27  Co    0         0.5       0.5                       6  [0.0, 0.0, 0.0]
 28  Co    0.5       0         0                         6  [0.0, 0.0, 0.0]
 29  Co    0.5       0         0.5                       6  [0.0, 0.0, 0.0]
 30  Co    0.5       0.5       0                         6  [0.0, 0.0, 0.0]
 31  Co    0.5       0.5       0.5                       6  [0.0, 0.0, 0.0]
 32  Sr    0.25      0.25      0.25                     12  [0.0, 0.0, 0.0]
 33  Sr    0.25      0.25      0.749999                 12  [0.0, 0.0, 0.0]
 34  Sr    0.25      0.749999  0.25                     12  [0.0, 0.0, 0.0]
 35  Sr    0.25      0.749999  0.749999                 12  [0.0, 0.0, 0.0]
 36  Sr    0.749999  0.25      0.25                     12  [0.0, 0.0, 0.0]
 37  Sr    0.749999  0.25      0.749999                 12  [0.0, 0.0, 0.0]
 38  Sr    0.749999  0.749999  0.25                     12  [0.0, 0.0, 0.0]
 39  Sr    0.749999  0.749999  0.749999                 12  [0.0, 0.0, 0.0]
Pm-3m

ix. Break the symmetry with a perturbation of 0.1 Angstrom. What is the spacegroup symbol of this structure?

Since we broke the symmetry, we see that all symmetry goes away (unless you had a 'lucky' perturbation) leaving you with a primitive Bravais and no symmetry.


In [22]:
struct.perturb(0.1)
sga = SpacegroupAnalyzer(struct)
print(sga.get_space_group_symbol())


P1

x. Explain what the difference is between mutable and immutable objects. What was the implication for these problems?

Mutable objects can be changed in place. They (usually) have a return value of None. In order for your structure to be updated, you run the method or function that updates the variable without you having to explictly set it again. The methods for the Structure class change the object's state so it is a mutable object. There is also an IStructure object, where I means immutable. You may have seen this in the documentation. Structure is a subclass of this object.

More examples of mutable objects are lists and dictionaries. Lists have append() and insert() methods that update the object for you. Dictionaries are similar with the update() method.

Immutable objects cannot be changed and if you want the value of a variable with an immutable object to change, you must get a new object. Methods usually return All of the methods for immutable objects return a new object. A main example is the string (str) object in Python. Strings cannot be changed so to update the variable, you have to set it again to the result of the method. An example of this is below, when we use the replace() method for a string, the return value is None.


In [23]:
my_string = 'Python is a scientific programming language'

print('Original string:')
print(my_string)
print('Try to mutate the string:')
my_string.replace('scientific', 'fun')
print(my_string)
print('It wasn\'t replaced!')
my_string = my_string.replace('scientific', 'fun')
print(my_string)
print('Now it has been replaced.')


Original string:
Python is a scientific programming language
Try to mutate the string:
Python is a scientific programming language
It wasn't replaced!
Python is a fun programming language
Now it has been replaced.