materialsproject / pymatgen

Python Materials Genomics (pymatgen) is a robust materials analysis code that defines classes for structures and molecules with support for many electronic structure codes. It powers the Materials Project.
https://pymatgen.org
Other
1.52k stars 868 forks source link

Structure.make_supercell() hangs #522

Closed jmhow119 closed 7 years ago

jmhow119 commented 7 years ago

System

Summary

Example code

This will not complete:

wurzite_structure = Structure.from_file("project/tmp/Cd_2_Te_2_Se_0/POSCAR")
for encut in range(100, 700, 100):
    for supercell_size in range(1, 4, 1):
        wurzite_structure.make_supercell([supercell_size, supercell_size, supercell_size])

This will not complete:

wurzite_structure = Structure.from_file("project/tmp/Cd_2_Te_2_Se_0/POSCAR")
for encut in range(100, 700, 100):
    for supercell_size in range(1, 4, 1):
        new_structure = wurzite_structure
        new_structure.make_supercell([supercell_size, supercell_size, supercell_size])

This will:

for encut in range(100, 700, 100):
    for supercell_size in range(1, 4, 1):
        wurzite_structure = Structure.from_file("project/tmp/Cd_2_Te_2_Se_0/POSCAR")
        wurzite_structure.make_supercell([supercell_size, supercell_size, supercell_size])

Suggested solution (if any)

Files (if any)

This file was downloaded from the materials explorer

CdTe wurtzite
1.0
4.684303 0.000000 0.000000
-2.342151 4.056725 0.000000
0.000000 0.000000 7.673695
Cd Te
2 2
direct
0.333333 0.666667 0.000092 Cd
0.666667 0.333333 0.500092 Cd
0.333333 0.666667 0.374908 Te
0.666667 0.333333 0.874908 Te
shyuep commented 7 years ago

This is not a bug. make_supercell actually modifies the structure in place. For the non-working codes, you are effectively iteratively building larger and larger supercells within the same structure. That is why it never completes. The last example you wrote actually recreates the structure before making a supercell, which is why it works. If you want to use the first two examples, you need to do

new_structure = wurzite_structure.copy()

Just simply doing the assigning only creates a reference to the original structure. Please consult Python's documentation about passing by reference.

jmhow119 commented 7 years ago

thank you for the reminder on pass by reference (or call-by-object more precisely). I haven't dealt with this specific case of passing objects by reference in awhile.