def modify_vasp_incar(cal_loc, new_tags={}, remove_tags=[], rename_old_incar=True): """ add new tags and remove obsolete tags in incar. input arguments: - cal_loc (str): the location of INCAR to be modified, <--required - new_tags (dict): new tags to be added, - remove_tags (list): incar tags that will be removed - rename_old_incar (bool or str): if rename_old_incar is True, rename the old INCAR as INCAR_0, INCAR_1, INCAR_2, etc. if rename_old_incar is False, the old INCAR will be overwritten by new INCAR. if rename_old_incar is a string, rename the old INCAR as the string. Default: True return the valid INCAR dictionary if no modification is made. """ new_tags = {key.upper(): value for key, value in new_tags.items()} remove_tags = [tag.upper() for tag in remove_tags] new_incar_tag_name = new_tags.keys() for tag in remove_tags: if tag in new_incar_tag_name: #import pprint print("\n\n**directory: {}".format(cal_loc)) print("**new_tags:") pprint.pprint(new_tags) print("**remove_tags:") pprint.pprint(remove_tags) Error_info = "***You are gonna remove an INCAR tag {} via remove_tags.".format( tag) Error_info += "This contradicts the simultaneous attempt to set {} via new_tags**\n\n".format( tag) print(Error_info) raise Exception("See the error information above.") incar_dict = {} with open(os.path.join(cal_loc, "INCAR"), "r") as incar_f: lines = [] for line in incar_f: pairs = line.strip().split("#")[0] pairs = pairs.strip().split("!")[0] if pairs.strip() == "": continue assert pairs.count( "=" ) == 1, "We ask you to set only one tag per line in INCAR, but there are more than one.\nwhere: {}\nline: {}".format( cal_loc, line) pairs = [tag_or_value.strip() for tag_or_value in pairs.split("=")] incar_dict[pairs[0].upper()] = pairs[1] incar_dict.update(new_tags) for remove_tag in remove_tags: if remove_tag in incar_dict.keys(): del incar_dict[remove_tag] if new_tags == {} and remove_tags == []: return incar_dict if isinstance(rename_old_incar, bool): if rename_old_incar: rename_old_incar = find_next_name(cal_loc=cal_loc, orig_name="INCAR")["next_name"] decorated_os_rename(loc=cal_loc, old_filename="INCAR", new_filename=rename_old_incar) #shutil.copyfile(os.path.join(cal_loc, "INCAR"), os.path.join(cal_loc, rename_old_incar)) elif isinstance(rename_old_incar, str): decorated_os_rename(loc=cal_loc, old_filename="INCAR", new_filename=rename_old_incar) #shutil.copyfile(os.path.join(cal_loc, "INCAR"), os.path.join(cal_loc, rename_old_incar)) else: raise Exception( "input argument rename_old_incar of modify_vasp_incar must be either bool or str." ) with open(os.path.join(cal_loc, "INCAR"), "w") as incar_f: for tag, value in sorted(incar_dict.items(), key=lambda key_value_pair: key_value_pair[0]): incar_f.write("{} = {}\n".format(tag, value))
def modify_vasp_incar0(cal_loc, new_tags={}, comment_tags=[], remove_tags=[], rename_old_incar=True): """ add new tags and comment obsolete tags in incar. input arguments: - cal_loc (str): the location of INCAR to be modified, <--required - new_tags (dict): new tags to be added, - comment_tags (list): tags that will be obsolete by commenting them with "#" - remove_tags (list): incar tags that will be removed - rename_old_incar (bool or str): if rename_old_incar is True, rename the old INCAR as INCAR_0, INCAR_1, INCAR_2, etc. if rename_old_incar is False, the old INCAR will be overwritten by new INCAR. if rename_old_incar is a string, rename the old INCAR as the string. Default: True return the valid INCAR dictionary if no modification is made. """ new_tags = {key.upper(): value for key, value in new_tags.items()} comment_tags = [tag.upper() for tag in comment_tags] remove_tags = [tag.upper() for tag in remove_tags] new_incar_tag_name = new_tags.keys() for tag in comment_tags + remove_tags: if tag in new_incar_tag_name: #import pprint print("\n\n**directory: {}".format(cal_loc)) print("**new_tags:") pprint.pprint(new_tags) print("**comment_tags:") pprint.pprint(comment_tags) print("**remove_tags:") pprint.pprint(remove_tags) Error_info = "***You are gonna comment of remove an INCAR tag {} via comment_tags/remove_tags.".format( tag) Error_info += "This contradicts the simultaneous attempt to set {} via new_tags**\n\n".format( tag) print(Error_info) raise Exception("See the error information above.") with open(os.path.join(cal_loc, "INCAR"), "r") as incar_f: lines = [] for line in incar_f: if line.strip() == "": continue pairs = line.strip().split("#")[0] pairs = pairs.strip().split("!")[0] #print(pairs, line) if "#" in line: comments = "#" + "#".join(line.strip().split("#")[1:]) elif "!" in line: comments = "#" + "!".join(line.strip().split("!")[1:]) else: comments = "" for pair in [ pair.strip() for pair in pairs.split(";") if pair.strip() ]: lines.append(pair) if len(comments.strip()) > 1: lines.append(comments) incar = [] for line in lines: if line.startswith("#"): incar.append(line) else: #print(line) key, value = line.split("=") key = key.strip().upper() value = value.strip() if key in remove_tags: continue elif key in comment_tags: incar.append("#" + line) else: incar.append([key, value]) valid_tag_ind_dict = {} for line_ind, line in enumerate(incar): if isinstance(line, list): valid_tag_ind_dict[line[0]] = line_ind for key, value in new_tags.items(): if key in valid_tag_ind_dict.keys(): incar[valid_tag_ind_dict[key]][1] = value else: incar.append([key, value]) #import pprint #pprint.pprint(incar) if new_tags == {} and comment_tags == [] and remove_tags == []: return {item[0]: item[1] for item in incar if isinstance(item, list)} if isinstance(rename_old_incar, bool): if rename_old_incar: rename_old_incar = find_next_name(cal_loc=cal_loc, orig_name="INCAR")["next_name"] decorated_os_rename(loc=cal_loc, old_filename="INCAR", new_filename=rename_old_incar) #shutil.copyfile(os.path.join(cal_loc, "INCAR"), os.path.join(cal_loc, rename_old_incar)) elif isinstance(rename_old_incar, str): decorated_os_rename(loc=cal_loc, old_filename="INCAR", new_filename=rename_old_incar) #shutil.copyfile(os.path.join(cal_loc, "INCAR"), os.path.join(cal_loc, rename_old_incar)) else: raise Exception( "input argument rename_old_incar of modify_vasp_incar must be either bool or str." ) with open(os.path.join(cal_loc, "INCAR"), "w") as incar_f: for line in incar: if isinstance(line, list): incar_f.write("{} = {}\n".format(line[0], line[1])) elif isinstance(line, str): incar_f.write(line + "\n")
def modify_vasp_kpoints_for_2D(cal_loc, kpoints_type, denser_kpoints=1, rename_old_kpoints=True, tolerance=1.0e-5): """ modify KPOINTS at cal_loc. input arguments: - cal_loc (str): the location of the calculation. - mode (str): 'MPRelaxSet', 'MPStaticSet', 'MPNonSCFSet_line', 'MPNonSCFSet_uniform', 'automatic' - 'MPRelaxSet': pymatgen.io.vasp.sets.MPRelaxSet generates KPOINTS. - 'MPStaticSet': pymatgen.io.vasp.sets.MPStaticSet generates KPOINTS. - 'MPNonSCFSet_uniform': pymatgen.io.vasp.sets.MPNonSCFSet generates KPOINTS in the uniform mode for DOS - 'MPNonSCFSet_line': pymatgen.io.vasp.sets.MPNonSCFSet generates KPOINTS in the line mode for band str - 'automatic': This option indicates that KPOINTS is automatically generated based on (gamma-centered) Monkhorst-Pack Scheme <--> 'MPRelaxSet', 'MPStaticSet' - 'Line-mode': Since function Write_line_mode_KPOINTS can write KPOINTS for either 3D or 2D materials, file KPOINTS remains unchanged. - denser_kpoints (float): this tag is inactive at kpoints_type='MPNonSCFSet_uniform' or 'MPNonSCFSet_line'. Default: 1 - rename_old_kpoints (bool or str): - if it is True, rename the old KPOINTS like KPOINTS_0, KPOINTS_1, KPINTS_2, ... - if it is False, the old KPOINTS will be overwritten - if it a string, the string is the new name of the old KPOINTS Default: True - tolerance (float): if abs(k_z) < tolerance for uniform and line modes, we think this kpoint is valid; otherwise remove it. Default: 1.0e-5 if old KPOINTS is saved, return the new name of the old KPOINTS. """ if kpoints_type.strip() not in [ "automatic", 'MPRelaxSet', 'MPStaticSet', 'MPNonSCFSet_line', 'MPNonSCFSet_uniform', "Line-mode" ]: print( "Error: for func modify_vasp_kpoints_for_2D, the input argument kpoints_tag must be on the those below:" ) print( "'MPRelaxSet', 'MPStaticSet', 'MPNonSCFSet_line', 'MPNonSCFSet_uniform', 'automatic'" ) raise Exception("See above for the error information") if kpoints_type == "Line-mode": return True with open(os.path.join(cal_loc, "KPOINTS"), "r") as f: kpoints = [line.strip() for line in f if line.strip()] if kpoints_type in ["automatic", 'MPRelaxSet', 'MPStaticSet']: assert "gam" in kpoints[2].lower() or "mon" in kpoints[2].lower( ), "Error: fail to modify KPOINTS generated by pymatgen at {}".format( cal_loc) nk_list = [int(int(k) * denser_kpoints) for k in kpoints[3].split()] if nk_list[2] != 1: nk_list[2] = 1 kpoints[3] = "{} {} {}".format(*nk_list) else: assert "reci" in kpoints[2].lower( ), "Error: fail to modify KPOINTS generated by pymatgen in the uniform/line mode at {}".format( cal_loc) new_kpoints = [] for kpoint in kpoints[3:]: k = kpoint.split() k = [float(k[0]), float(k[1]), float(k[2]), int(k[3])] if abs(k[2]) < tolerance: new_kpoints.append(kpoint) kpoints = kpoints[:3] + new_kpoints kpoints[1] = str(len(new_kpoints)) if isinstance(rename_old_kpoints, bool): if rename_old_kpoints: new_name = find_next_name(cal_loc=cal_loc, orig_name="KPOINTS")["next_name"] shutil.move(os.path.join(cal_loc, "KPOINTS"), os.path.join(cal_loc, new_name)) elif isinstance(rename_old_kpoints, str): shutil.move(os.path.join(cal_loc, "KPOINTS"), os.path.join(cal_loc, rename_old_kpoints)) else: raise Exception( "rename_old_kpoints must be either bool or str for func modify_vasp_kpoints_for_2D" ) with open(os.path.join(cal_loc, "KPOINTS"), "w") as f: for line in kpoints: f.write(line + "\n") if rename_old_kpoints == True: return new_name elif isinstance(rename_old_kpoints, str): return rename_old_kpoints
def modify_vasp_kpoints_for_2D(self, rename_old_kpoints=True, tolerance=1.0e-5): """ modify KPOINTS properly for 2D structures. support kpoints_type for KPOINTS modifications: 'MPRelaxSet', 'MPStaticSet', 'MPNonSCFSet_line', 'MPNonSCFSet_uniform', 'automatic' - 'MPRelaxSet': pymatgen.io.vasp.sets.MPRelaxSet generates KPOINTS. - 'MPStaticSet': pymatgen.io.vasp.sets.MPStaticSet generates KPOINTS. - 'MPNonSCFSet_uniform': pymatgen.io.vasp.sets.MPNonSCFSet generates KPOINTS in the uniform mode for DOS - 'MPNonSCFSet_line': pymatgen.io.vasp.sets.MPNonSCFSet generates KPOINTS in the line mode for band str input arguments: - rename_old_kpoints (bool or str): - if it is True, rename the old KPOINTS like KPOINTS_0, KPOINTS_1, KPINTS_2, ... - if it is False, the old KPOINTS will be overwritten - if it a string, the string is the new name of the old KPOINTS Default: True - tolerance (float): if abs(k_z) < tolerance for uniform and line modes, we think this kpoint is valid; otherwise remove it. Default: 1.0e-5 if old KPOINTS is saved, return the new name of the old KPOINTS. """ kpoints_type = self.current_firework["kpoints_type"] if kpoints_type.strip() not in ['MPRelaxSet', 'MPStaticSet', 'MPNonSCFSet_line', 'MPNonSCFSet_uniform']: print("Error: for func modify_vasp_kpoints_for_2D, the input argument kpoints_tag must be on the those below:") print("'MPRelaxSet', 'MPStaticSet', 'MPNonSCFSet_line', 'MPNonSCFSet_uniform'") raise Exception("See above for the error information") with open(os.path.join(self.cal_loc, "KPOINTS"), "r") as f: kpoints = [line.strip() for line in f if line.strip()] if kpoints_type in ['MPRelaxSet', 'MPStaticSet']: assert "gam" in kpoints[2].lower() or "mon" in kpoints[2].lower(), "Error: fail to modify KPOINTS generated by pymatgen at {}".format(cal_loc) nk_list = [int(k) for k in kpoints[3].split()] if nk_list[2] != 1: nk_list[2] = 1 kpoints[3] = "{} {} {}".format(*nk_list) else: assert "reci" in kpoints[2].lower(), "Error: fail to modify KPOINTS generated by pymatgen in the uniform/line mode at {}".format(cal_loc) new_kpoints = [] for kpoint in kpoints[3:]: k = kpoint.split() k = [float(k[0]), float(k[1]), float(k[2]), int(k[3])] if abs(k[2]) < tolerance: new_kpoints.append(kpoint) kpoints = kpoints[:3] + new_kpoints kpoints[1] = str(len(new_kpoints)) if isinstance(rename_old_kpoints, bool): if rename_old_kpoints: new_name = find_next_name(cal_loc=self.cal_loc, orig_name="KPOINTS")["next_name"] shutil.move(os.path.join(self.cal_loc, "KPOINTS"), os.path.join(self.cal_loc, new_name)) elif isinstance(rename_old_kpoints, str): shutil.move(os.path.join(self.cal_loc, "KPOINTS"), os.path.join(self.cal_loc, rename_old_kpoints)) else: raise Exception("rename_old_kpoints must be either bool or str for func modify_vasp_kpoints_for_2D") with open(os.path.join(self.cal_loc, "KPOINTS"), "w") as f: for line in kpoints: f.write(line+"\n") if rename_old_kpoints == True: return new_name elif isinstance(rename_old_kpoints, str): return rename_old_kpoints
def modify_vasp_incar(cal_loc, new_tags={}, comment_tags=[], remove_tags=[], rename_old_incar=True): """ add new tags and comment obsolete tags in incar. input arguments: - cal_loc (str): the location of INCAR to be modified, <--required - new_tags (dict): new tags to be added, - comment_tags (list): tags that will be obsolete by commenting them with "#" - remove_tags (list): incar tags that will be removed - rename_old_incar (bool or str): if rename_old_incar is True, rename the old INCAR as INCAR_0, INCAR_1, INCAR_2, etc. if rename_old_incar is False, the old INCAR will be overwritten by new INCAR. if rename_old_incar is a string, rename the old INCAR as the string. Default: True return the modified INCAR dictionary. """ new_tags = {key.upper(): value for key, value in new_tags.items()} comment_tags = [tag.upper() for tag in comment_tags] remove_tags = [tag.upper() for tag in remove_tags] Valid_tags, Commented_tags = {}, {} Ordered_tags = [] with open(os.path.join(cal_loc, "INCAR"), "r") as incar: for line in incar: items = [item.strip() for item in line.strip().split("=")] if len(items) >= 2: if items[0].startswith("#"): tag = items[0].strip("#").upper().strip() if tag in remove_tags: continue Commented_tags[tag] = items[1] Ordered_tags.append(tag) else: tag = items[0].upper() if tag in remove_tags: continue Valid_tags[items[0].upper()] = items[1] Ordered_tags.append(tag) for new_tag, value in new_tags.items(): Valid_tags[new_tag] = value if new_tag not in Ordered_tags: Ordered_tags.append(new_tag) for comment_tag in comment_tags: if comment_tag in Valid_tags.keys(): Commented_tags[comment_tag] = Valid_tags[comment_tag] del Valid_tags[comment_tag] if new_tags == {} and comment_tags == [] and remove_tags == []: return Valid_tags if isinstance(rename_old_incar, bool): if rename_old_incar: rename_old_incar = find_next_name(cal_loc=cal_loc, orig_name="INCAR")["next_name"] shutil.copyfile(os.path.join(cal_loc, "INCAR"), os.path.join(cal_loc, rename_old_incar)) elif isinstance(rename_old_incar, str): shutil.copyfile(os.path.join(cal_loc, "INCAR"), os.path.join(cal_loc, rename_old_incar)) else: raise Exception( "input argument rename_old_incar of modify_vasp_incar must be either bool or str." ) with open(os.path.join(cal_loc, "INCAR"), "w") as incar: for tag in Ordered_tags: if tag in Valid_tags.keys(): incar.write("{} = {}\n".format(tag, Valid_tags[tag])) else: incar.write("#{} = {}\n".format(tag, Commented_tags[tag]))