Source code for pymatgen.command_line.mcsqs_caller
import subprocess
import os
import numpy as np
import time
from threading import Timer
from pymatgen.io.vasp.inputs import Poscar
from pymatgen.io import atat
[docs]def run_mcsqs(structure, clusters, supercell=None, total_atoms=None, search_time=0.01):
"""
Helper function for calling mcsqs with different arguments
Args:
clusters (dict): dictionary of cluster interactions with entries in the form
# atoms: cutoff in angstroms
supercell (list): dimensions of the supercell in units of the original unit cell
total_atoms(int): total number of atoms in the final SQS. Choose either
this OR supercell
search_time (int): The time spent looking for the ideal SQS in minutes
Returns:
Pymatgen structure which is an SQS of the input structure
"""
num_atoms = len(structure)
if total_atoms is None:
total_atoms = num_atoms
if supercell is not None and total_atoms != num_atoms:
print("pick supercell OR number of atoms")
return
# Set supercell
cell = np.eye(3)
text_file = open("sqscell.out", "w")
text_file.write("1\n")
for i in range(len(cell)):
text_file.write("\n")
for j in range(len(cell[i])):
text_file.write(str(cell[i][j]) + " ")
text_file.close()
struccopy = structure.copy()
if supercell is not None:
struccopy.make_supercell(supercell)
struc = atat.Mcsqs(struccopy)
text_file = open("rndstr.in", "w")
text_file.write(struc.to_string())
text_file.close()
# Generate Clusters
command = ["mcsqs"]
for num in clusters:
command.append("-" + str(num) + "=" + str(clusters[num]))
p = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
close_fds=True,
)
p.communicate()
command = ["mcsqs", "-rc", "-n {}".format(len(structure))]
p = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
close_fds=True,
)
try:
p.communicate(timeout=search_time * 60)
except subprocess.TimeoutExpired:
p.kill()
p.communicate()
if os.path.exists("bestsqs.out"):
text_file = open("bestsqs.out", "r")
bestsqs = text_file.read()
text_file.close()
return atat.Mcsqs.structure_from_string(bestsqs)
else:
raise TimeoutError("Cluster expansion took too long.")
else:
struc = atat.Mcsqs(struccopy)
text_file = open("rndstr.in", "w")
text_file.write(struc.to_string())
text_file.close()
# Generate Clusters
command = ["mcsqs"]
for num in clusters:
command.append("-" + str(num) + "=" + str(clusters[num]))
p = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
close_fds=True,
)
p.communicate()
command = ["mcsqs", "-n {}".format(total_atoms)]
p = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
close_fds=True,
)
try:
p.communicate(timeout=search_time * 60)
except subprocess.TimeoutExpired:
p.kill()
p.communicate()
if os.path.exists("bestsqs.out"):
text_file = open("bestsqs.out", "r")
bestsqs = text_file.read()
text_file.close()
return atat.Mcsqs.structure_from_string(bestsqs)
else:
raise TimeoutError("Cluster expansion took too long.")