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.48k stars 850 forks source link

Generate random ordered structures from disordered structure #3049

Open exenGT opened 1 year ago

exenGT commented 1 year ago

Problem

For molecular dynamics simulation and machine learning data generation of random structures, one might desire to have a routine that transforms a given disordered structure $S$ to a set of randomly ordered structures $\{S'_i\}$, where each randomly ordered structure $S'_i$ has the same overall composition as the disordered structure $S$.

Currently for this purpose, there exists OrderDisorderedStructureTransformation in transformations/standard_transformations.py. However, this function over-complicates the problem by using the Ewald energy to rank the generated randomly ordered structures. When the structure in question is very large (e.g. >= thousands of atoms in a typical MD simulation), this approach simply won't work due to the combinatorially increasing search space. Instead, what we actually want is very simple: a set of randomly ordered structures. The energy ranking is not of concern here.

Proposed Solution

We have implemented a new standard transformation routine, named RandomStructureTransformation. Given a disordered structure, and a number num_copies, its method apply_transformation returns a set of num_copies copies of randomly ordered structures. This routine distinguishes between inequivalent sublattices of the crystal.

Additional Info

The following example shows the usage of this routine:

from mp_api.client import MPRester

from pymatgen.transformations.standard_transformations \
  import RandomStructureTransformation

# put your api_key here
api_key = "*****"

with MPRester(api_key) as mpr:
    struct = mpr.get_structure_by_material_id("mp-2534", conventional_unit_cell=True)  # GaAs

struct[0:4] = {"Ga": 0.5, "In": 0.5}
struct[4:] = {"P": 0.5, "As": 0.5}

struct.make_supercell([3, 3, 3])

# random structure transformation
trans = RandomStructureTransformation()
new_structs = trans.apply_transformation(structure = struct,
                                         num_copies = 5)

# save structures to files
for i_struct, new_struct in enumerate(new_structs):
    new_struct.to("random_structure_{}.cif".format(i_struct))

Below are the screenshots of the generated random structures:

Screenshot 2023-06-06 at 1 37 52 AM Screenshot 2023-06-06 at 1 37 48 AM Screenshot 2023-06-06 at 1 37 38 AM Screenshot 2023-06-06 at 1 37 34 AM Screenshot 2023-06-06 at 1 37 28 AM

If this feature is desired, I can initiate a pull request.

mkhorton commented 1 year ago

Could you share how this differs from EnumerateStructureTransformation backed by enumlib?

mkhorton commented 1 year ago

Also, thank you for the clearly described and illustrated issue.

exenGT commented 1 year ago

Hi @mkhorton, thank you very much for your comment! I just found out about EnumerateStructureTransformation. Upon checking the documentation, it seems that this transformation requires enumlib and some other arguments (I'm not quite familiar with what these arguments do). It seems also that EnumerateStructureTransformation has some kind of ordering using either Ewald or M3GNet energy. These features are not present in RandomStructureTransformation, but it uses random.shuffle to randomly assign site elements. Does this answer your question somewhat?

HegemonyTao commented 1 year ago

hello, exenGT, I'm wondering how did you show the crystal strucuture in this Issue, please inform me, thank you very much !!!

exenGT commented 1 year ago

Hi @HegemonyTao, sorry for my late reply. The crystal structures here are visualized with VESTA. Hope that helps!