#!/usr/bin/env python3 """ Create a test generator and files to copy for an EquilibriumCrystalStructure_Unconstrained_TypeLabels test for core-shell models from a nonbonded EquilibriumCrystalStructure test generator Args: List of type labels to consider Read from STDIN: Nonbonded test generator file Printed to STDOUT: Test generator line """ from crystal_genome_util.property_util.equilibrium_crystal_structure import ELEMENTS from crystal_genome_util.aflow_util import AFLOW import sys, os, pathlib import random import json from copy import copy MODELTYPE = "core-shell" KIM_USER_ID = "4ad03136-ed7f-4316-b586-1e94ccceb311" MATCHING_MODELS = "[\"born/coul/long/cs\"]" # relative to script file location, will be converted to absolute TEST_DIR_PATH = "../Tests/coreshell" SYM_FILE_PATH="symfiles/cs/sym.txt" def get_random_kim_id() -> str: """ Returns random 12-digit numerical string Returns: Random 12-digit numerical string """ return "".join(["{}".format(random.randint(0, 9)) for num in range(12)]) if __name__ == "__main__": available_type_labels = sys.argv[1:] is_polarized_dict = {} for type_label in available_type_labels: if type_label in ELEMENTS: assert ((type_label+"S") not in available_type_labels), "both unpolarized %s and its shell are in the argument list!" % type_label assert ((type_label+"C") not in available_type_labels), "both unpolarized %s and its core are in the argument list!" % type_label is_polarized_dict[type_label] = False else: assert (type_label[:-1] in ELEMENTS), "Prefix %s is not an element!" % type_label[:-1] if type_label[-1] == "C": assert ((type_label[:-1]+"S") in available_type_labels), "core %s is missing its corresponding shell in the argument list!" % type_label elif type_label[-1] == "S": assert ((type_label[:-1]+"C") in available_type_labels), "shell %s is missing its corresponding core in the argument list!" % type_label else: raise RuntimeError("Type label %s is neither a core or a shell!") is_polarized_dict[type_label[:-1]] = True for line in sys.stdin: test_generator_source=json.loads(line) assert all(species in is_polarized_dict for species in test_generator_source["species"]) # Create list of atom type labels for this particular test atom_type_labels_list=[] for species in test_generator_source["species"]: if is_polarized_dict[species]: atom_type_labels_list.append(species+"C") atom_type_labels_list.append(species+"S") else: atom_type_labels_list.append(species) material = ":".join([test_generator_source["prototype_label"]]+test_generator_source["species"]) test_generator = { "species":test_generator_source["species"], "prototype_label":test_generator_source["prototype_label"], "material":material, "modeltype":MODELTYPE, "matching_models":MATCHING_MODELS, "version":"000", "kimnum":get_random_kim_id(), "kim_user_id":KIM_USER_ID, "FILES_TO_COPY":[os.path.join(pathlib.Path(__file__).parent.resolve(),SYM_FILE_PATH)], "comment":"Initial geometry obtained from the following URL(s):", "source_citations":[ " \"title\" \"AFLOWLIB.ORG: A distributed materials properties repository from high-throughput ab initio calculations\"\n \"journal\" \"Computational Materials Science\"\n \"volume\" \"58\"\n \"pages\" \"227-235\"\n \"year\" \"2012\"\n \"issn\" \"0927-0256\"\n \"doi\" \"https://doi.org/10.1016/j.commatsci.2012.02.002\"\n \"url\" \"https://www.sciencedirect.com/science/article/pii/S0927025612000687\"\n \"author\" \"Stefano Curtarolo and Wahyu Setyawan and Shidong Wang and Junkai Xue and Kesong Yang and Richard H. Taylor and Lance J. Nelson and Gus L.W. Hart and Stefano Sanvito and Marco Buongiorno-Nardelli and Natalio Mingo and Ohad Levy\"\n \"keywords\" \"High-throughput, Combinatorial materials science, Ab initio, AFLOW, Materials genome initiative\"\n \"abstract\" \"Empirical databases of crystal structures and thermodynamic properties are fundamental tools for materials research. Recent rapid proliferation of computational data on materials properties presents the possibility to complement and extend the databases where the experimental data is lacking or difficult to obtain. Enhanced repositories that integrate both computational and empirical approaches open novel opportunities for structure discovery and optimization, including uncovering of unsuspected compounds, metastable structures and correlations between various characteristics. The practical realization of these opportunities depends on a systematic compilation and classification of the generated data in addition to an accessible interface for the materials science community. In this paper we present an extensive repository, aflowlib.org, comprising phase-diagrams, electronic structure and magnetic properties, generated by the high-throughput framework AFLOW. This continuously updated compilation currently contains over 150,000 thermodynamic entries for alloys, covering the entire composition range of more than 650 binary systems, 13,000 electronic structure analyses of inorganic compounds, and 50,000 entries for novel potential magnetic and spintronics systems. The repository is available for the scientific community on the website of the materials research consortium, aflowlib.org.\"\n \"recordtype\" \"article\"" ], "atom_type_labels": " ".join(atom_type_labels_list) } test_dir = os.path.join(pathlib.Path(__file__).parent.resolve(),TEST_DIR_PATH,material.replace(":","_")) pathlib.Path(test_dir).mkdir(parents=True, exist_ok=True) aflow = AFLOW() for i,parameter_set in enumerate(test_generator_source["parameter_sets"]): test_generator["comment"] += " " + parameter_set["url"] destfile = os.path.join(test_dir,"input"+str(i)+".dat") test_generator["FILES_TO_COPY"].append(destfile) atoms = aflow.build_atoms_from_prototype(test_generator_source["species"],test_generator_source["prototype_label"],parameter_set["parameter_values"],verbose=False) atoms.write("tmp.dat",format="lammps-data",atom_style="full") cell_lines = [] atom_lines_as_lists = [] reading_atoms = False with open("tmp.dat") as f: for line in f: if line.strip() == "": continue if reading_atoms: atom_lines_as_lists.append(line.split()) # convert to type label right away atom_lines_as_lists[-1][2] = test_generator_source["species"][int(atom_lines_as_lists[-1][2])-1] elif line.strip() == "Atoms": reading_atoms = True elif line.split()[-1] in ["xhi","yhi","zhi","yz"]: cell_lines.append(line.strip()) bond_lines = [] additional_atom_lines_as_lists=[] bond_labels = set() for atom_line_as_list in atom_lines_as_lists: element = atom_line_as_list[2] if is_polarized_dict[element]: # it's polarizable, so we have to split into two particles. Core stays in current list, shell goes into additional list additional_atom_lines_as_lists.append(copy(atom_line_as_list)) # 1-based indices in LAMMPS, so get the index as length after appending shell_atom_number=len(atom_lines_as_lists)+len(additional_atom_lines_as_lists) additional_atom_lines_as_lists[-1][0] = str(shell_atom_number) additional_atom_lines_as_lists[-1][2] += "S" core_atom_number = atom_line_as_list[0] atom_line_as_list[2] += "C" bond_label = element+"C-"+element+"S" bond_labels.add(bond_label) bond_lines.append(" ".join([str(len(bond_lines)+1),bond_label,str(core_atom_number),str(shell_atom_number)])) with open(destfile,"w") as f: f.write("Core-shell LAMMPS data with labels\n\n") f.write(str(len(atom_lines_as_lists)+len(additional_atom_lines_as_lists))+" atoms\n") f.write(str(len(atom_type_labels_list))+" atom types\n") f.write(str(len(bond_lines))+" bonds\n") f.write(str(len(bond_labels))+" bond types\n\n") for cell_line in cell_lines: f.write(cell_line+"\n") # because atoms and bonds are typed by strings, their correspondence to integer types here doesn't matter at all! # the beauty of type labels. f.write("\nAtom Type Labels\n\n") for i,type_label in enumerate(atom_type_labels_list): f.write(str(i+1)+" "+type_label+"\n") f.write("\nBond Type Labels\n\n") for i,type_label in enumerate(bond_labels): f.write(str(i+1)+" "+type_label+"\n") f.write("\nAtoms # full\n\n") for line_as_list in atom_lines_as_lists: f.write(" ".join(line_as_list)+"\n") for line_as_list in additional_atom_lines_as_lists: f.write(" ".join(line_as_list)+"\n") f.write("\nBonds\n\n") for line in bond_lines: f.write(line+"\n") print(json.dumps(test_generator))