Beispiel #1
0
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))
Beispiel #2
0
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
Beispiel #4
0
   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]))