Source code for htesp.site_subs

#!/usr/bin/env python
#"""Writen by Niraj K. Nepal, Ph.D."""
"""Module to generate input files for substitutions"""
import os
import shutil
import subprocess
import sys
import warnings
from bsym.interface.pymatgen import unique_structure_substitutions as us
from pymatgen.io.vasp.inputs import Poscar
from pymatgen.io import pwscf
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
from pymatgen.core import structure
from htesp.cif_to_gsinput import pos_to_kpt
from htesp.write_potcar import poscar2potcar
from htesp.htepc import MpConnect
from htesp.check_json import config


[docs] def run_vasp_process(what, cwd=None): """Run ``vasp_process.py <what>`` without a shell, optionally in ``cwd``.""" # FIX(36): ``vasp_process.py`` was an executable only while 1.x put src/ on # $PATH. In 2.0 it is a module, so the bare name is a FileNotFoundError -- # "[Errno 2] No such file or directory: 'vasp_process.py'" -- and every # command routed through here died. workflow.py and oqmd_extract.py were # converted; these four call sites were missed. subprocess.run([sys.executable, "-m", "htesp.vasp_process", what], check=True, cwd=cwd)
[docs] def substitution(mpid,obj): """ Substitute elements using the bsym package. This function substitutes elements using the bsym package. It requires a 'substitute' key in the config.json file. Inside that, the user needs to define 'mode', 'elm', 'sub', and 'new_sub' as explained below: Parameters: - mpid (str): Materials ID. - obj: Object of the MpConnect class. 'substitute' dictionary: - 'mode' (int): 1 for unique_structure_substitutions, 2 for substituting each key by its value pair. - 'elm' (str): Element to be substituted. - 'sub' (dict or tuple): Dictionary for single substitution or tuple for multiple substitutions. - 'new_sub' (dict): Dictionary for new substitutions. If 'mode' is set to 1: - 'sub' (dict): Dictionary of elements to be substituted and their corresponding count. If 'mode' is set to 2: - 'new_sub' (dict): Dictionary of substitutions. Returns: None """ input_data = config() if mpid in ('help', 'h'): msg="""required package: bsym 'pip install bsym' put substitute dictionary file in the config.json file. Inside that define 'mode':2 # 'mode':1 for unique_structure_substitutions # 'mode':3 for new_structure_from_substitution function of bsym.interface.pymatgen 'elm':'X', (element to be substituted) 'sub':{'X':n1, 'Y':n2} (substitution) 'new_sub':{'A1':'A2', 'B1':'B2', 'C1':'C2'} for multiple substitution, put 'sub':sub1,sub2,.... suppose total number of X element is n then n2 of them is replaced by element Y""" print(msg) else: dft = sys.argv[2] orig_prefix=sys.argv[3] sb = input_data['substitute'] mode = sb['mode'] try: obj.structure = structure.Structure.from_file("R{}-{}/relax/POSCAR".format(mpid,orig_prefix)) except (OSError, ValueError): obj.structure = pwscf.PWInput.from_file("scf_dir/scf-{}.in".format(mpid)).structure structure_sym = SpacegroupAnalyzer(obj.structure, symprec=0.1).get_primitive_standard_structure() list_str = [] if mode == 1: if isinstance(sb['sub'],dict): list_str = us(structure_sym,sb['elm'],sb['sub']) elif isinstance(sb['sub'],list): list_str = [] for sub_i in sb['sub']: list_str += us(structure_sym,sb['elm'],sub_i) elif mode == 2: new_sub = sb['new_sub'] # FIX(18): the old loop assigned to ``structure_sym[i].specie.symbol``. # ``specie`` is a pymatgen ``Element``, an enum singleton shared by # the whole process, so that renamed the element itself -- every # other structure, and every later material handled by the same # process, saw the substituted name. ``replace_species`` changes # this structure and nothing else. present = {str(site.specie.symbol) for site in structure_sym} mapping = {old: new for old, new in new_sub.items() if old in present} missing = sorted(set(new_sub) - set(mapping)) if missing: warnings.warn( "substitute.new_sub names {} which are not in {}; " "they are ignored".format(missing, structure_sym.composition), RuntimeWarning) if mapping: structure_sym.replace_species(mapping) list_str = [structure_sym] else: print("wrong mode. Use either mode = 1 or 2 \n") os.makedirs("scf_dir", exist_ok=True) if not os.path.isfile('mpid-substitute.in'): entry = 0 else: with open('mpid-substitute.in', 'r') as mpid_read: lines = mpid_read.readlines() entry = len(lines) for i,struc in enumerate(list_str): if dft in ('vasp', 'VASP'): obj.prefix = struc.composition.alphabetical_formula.replace(" ","") poscar = Poscar(structure=struc,comment=obj.prefix) relax_dir = "R{}-{}-{}/relax".format(mpid,i+1,obj.prefix) os.makedirs(relax_dir, exist_ok=True) shutil.copy("R{}-{}/relax/INCAR".format(mpid,orig_prefix), relax_dir) poscar.write_file(filename="{}/POSCAR".format(relax_dir)) d = input_data['download'] evenkpt = d['inp']['evenkpt'] kptden = input_data['kptden'] if evenkpt: print("Even kpoint mesh is utilized\n") pos_to_kpt("{}/POSCAR".format(relax_dir),kptden,True) else: pos_to_kpt("{}/POSCAR".format(relax_dir),kptden) shutil.move("KPOINTS", "{}/KPOINTS".format(relax_dir)) # The POTCAR is written by poscar2potcar() below; the # MPRelaxSet round-trip here built a set nothing read. if os.path.isfile("vasp.in"): shutil.copy("vasp.in", relax_dir) if os.path.isfile("config.json"): shutil.copy("config.json", relax_dir) # poscar2potcar() works on the current directory; the chdir is # wrapped so an exception cannot leave the process inside the # substituted directory. pwd = os.getcwd() try: os.chdir(relax_dir) poscar2potcar() run_vasp_process("POSCAR") finally: os.chdir(pwd) else: magnetic = input_data['pwscf_in']['magnetic'] if magnetic: default_magmoms = input_data['magmom']['magmom'] struc.add_spin_by_element(default_magmoms) obj.structure = struc else: obj.structure = struc comp_list = [] for composition in struc.composition.elements: comp_list.append(str(composition)) obj.comp_list = comp_list obj.getkpt() evenkpt = input_data['download']['inp']['evenkpt'] if evenkpt: print("Utilizing even kpoint mesh\n") obj.getevenkpt() obj.maxecut_sssp_for_subs() obj.prefix = struc.composition.alphabetical_formula.replace(" ","") if magnetic: obj.setting_qeinput(magnetic=True,pseudo_dir='../../pp') else: obj.setting_qeinput(pseudo_dir='../../pp') shutil.move("scf-{}.in".format(obj.mpid), "scf_dir/scf-{}-{}.in".format(mpid,i+1)) print(mpid,obj.prefix) with open("mpid-substitute.in", "a") as mpid_append: mpid_append.write("v{}".format(entry+1+i) + " " + mpid + "-{}".format(i+1) + " " + obj.prefix + "\n")
[docs] def main(): """ main function """ mpid = sys.argv[1] obj = MpConnect() substitution(mpid,obj)
if __name__ == "__main__": main()