Пример #1
0
 def make_KPOINTS_denser(self, denser_kpoints = []):
     """
     Modify KPOINTS such that the kpiont along the axes in certain directions is denser_kpoints denser. Rename old KPOINTS as KPOINTS.sparse
     input arguments:
         denser_kpoints (list of float): This tag is only active at kpoints_type='MPRelaxSet', 'MPStaticSet',
                                         namely only for automatically generated KPOINTS
         Note that denser_kpoints must consist of three float numbers:
             - The first number is associated to the 'x' axis
             - The second number is associated to the 'y' axis
             - The third number is associated to the 'z' axis
     """
     if self.current_firework["kpoints_type"] not in ['MPRelaxSet', 'MPStaticSet']:
         return False
     
     assert len(denser_kpoints) == 3, "Error: tag denser_kpoints must be three float/integer numbers separated by commas."
     
     with open(os.path.join(self.cal_loc, "KPOINTS"), "r") as f:
         kpoints = [line.strip() for line in f if line.strip()]
         
     assert "gam" in kpoints[2].lower() or "mon" in kpoints[2].lower(), "Error: fail to make KPOINTS denser at {}".format(self.cal_loc)
     nk_list = [int(k) for k in kpoints[3].split() if k]
     for i in range(3):
         nk_list[i] = int(round(nk_list[i]*denser_kpoints[i]))
         if nk_list[i] == 0:
             nk_list[i] = 1
                 
     kpoints[3] = "{} {} {}".format(*nk_list)
     decorated_os_rename(loc=self.cal_loc, old_filename="KPOINTS", new_filename="KPOINTS.sparse")
     
     with open(os.path.join(self.cal_loc, "KPOINTS"), "w") as f:
         for line in kpoints:
             f.write(line+"\n")
Пример #2
0
def update_killed_jobs_status(killed_jobs_list, workflow, max_error_times=5):
    """
    Update killed jobs's status. If the error in __killed__ can be fixed, fix it and __killed__ --> __ready__; 
        Ohterwise __killed__ --> __manual__
    input arguments:
        - killed_jobs_list (list): a list of absolute pathes of killed jobs.
        - workflow:  the output of func Parse_calculation_workflow.parse_calculation_workflow
        - max_error_times (int): the maximum error times. Beyond this value, __killed__ --> __manual__. Default: 5
    """
    
    #Error_type_dict = ["__unfinished_OUTCAR__", "__electronic_divergence__", 
    #                   "__ionic_divergence__", "__positive_energy__"]
    
    for killed_job in killed_jobs_list:
        #The killed job won't be processed until the stdout & stderr files of the queue system appear.
        if Queue_std_files(cal_loc=killed_job, workflow=workflow).find_std_files() == [None, None]:
            continue
        
        error_type = Write_and_read_error_tag(killed_job).read_error_tag("__killed__")
        error_checker = Vasp_Error_checker(cal_loc=killed_job, error_type=error_type, workflow=workflow)
        log_txt_loc, firework_name = os.path.split(killed_job)
        if Vasp_Error_Saver(cal_loc=killed_job, workflow=workflow).find_error_times() >= max_error_times:
            decorated_os_rename(loc=killed_job, old_filename="__killed__", new_filename="__manual__")
            #os.rename(os.path.join(killed_job, "__killed__"), os.path.join(killed_job, "__manual__"))
            with open(os.path.join(log_txt_loc, "log.txt"), "a") as f:
                f.write("{} Killed: {}\n".format(get_time_str(), killed_job))
                f.write("\t\t\tThe error times hit the max_error_times ({})\n".format(max_error_times))
                f.write("\t\t\t__killed__ -> __manual__\n")
        elif error_checker.correct():
            #Queue_std_files(cal_loc=killed_job, workflow=workflow).remove_std_files()
            #to_be_removed = ["OUTCAR", "OSZICAR", workflow[0]["vasp.out"]]
            #for file_ in to_be_removed:
            #    if os.path.isfile(os.path.join(killed_job, file_)):
            #        os.remove(os.path.join(killed_job, file_))
                    
            os.remove(os.path.join(killed_job, "__killed__"))
            open(os.path.join(killed_job, "__ready__"), "w").close()
            with open(os.path.join(log_txt_loc, "log.txt"), "a") as f:
                f.write("{} Killed: Successfully correct the error {} under {}\n".format(get_time_str(), error_type, firework_name))
                #f.write("\t\t\tremove stdout and stderr files\n")
                #for file_ in to_be_removed:
                #    f.write("\t\t\tremove {}\n".format(file_))
                f.write("\t\t\t__killed__ --> __ready__\n")
            
        else:
            decorated_os_rename(loc=killed_job, old_filename="__killed__", new_filename="__manual__")
            #os.rename(os.path.join(killed_job, "__killed__"), os.path.join(killed_job, "__manual__"))
            with open(os.path.join(log_txt_loc, "log.txt"), "a") as f:
                f.write("{} Killed: Fail to correct the error {} under {}\n".format(get_time_str(), error_type, firework_name))
                f.write("\t\t\t__killed__ --> __manual__\n")
Пример #3
0
def post_process(mater_cal_folder, current_firework, workflow):
    """
    Carry out the post-process defined in firework of workflow at index firework_ind.
    """
    current_cal_loc = os.path.join(mater_cal_folder,
                                   current_firework["firework_folder_name"])
    log_txt = os.path.join(mater_cal_folder, "log.txt")

    if os.path.isfile(os.path.join(current_cal_loc, "__post_process_done__")):
        return True

    if os.path.isfile(os.path.join(current_cal_loc, "__post_process__")):
        remove_files = current_firework["remove_after_cal"]
        with open(log.txt, "a") as f:
            f.write("{} INFO: remove files from {}:\n\t\t\t".format(
                get_time_str(), current_firework["firework_folder_name"]))
            [f.write("{}\t").format(file_) for file_ in remove_files]
            f.write("\n")
        for file in remove_files:
            if os.path.isfile(os.path.join(current_cal_loc, file)):
                os.remove(os.path.join(current_cal_loc, file))

        input_args_list = {
            "cal_loc":
            current_cal_loc,
            "user_defined_cmd_list":
            current_firework["user_defined_postprocess_cmd"],
            "where_to_execute":
            current_cal_loc,
            "log_txt":
            log_txt
        }
        if not Execute_user_defined_cmd(**input_args_list):
            return False

        decorated_os_rename(loc=current_cal_loc,
                            old_filename="__post_process__",
                            new_filename="__post_process_done__")
def post_process_after_cal(mater_cal_folder, firework_ind, workflow):
    """
    Carry out the post-process defined in firework of workflow at index firework_ind.
    """
    firework = workflow[firework_ind]
    firework_folder = os.path.join(mater_cal_folder,
                                   firework["firework_folder_name"])
    if os.path.isfile(os.path.join(firework_folder, "__removed__")):
        return True

    if os.path.isfile(os.path.join(firework_folder, "__remove__")):
        remove_files = firework["remove_after_cal"]
        with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f:
            f.write("{} INFO: remove files from {}:\n\t\t".format(
                get_time_str(), firework_folder))
            [f.write("{}\t").format(file_) for file_ in remove_files]
            f.write("\n")
        for file in remove_files:
            if os.path.isfile(os.path.join(firework_folder, file)):
                os.remove(os.path.join(firework_folder, file))
        decorated_os_rename(loc=firework_folder,
                            old_filename="__remove__",
                            new_filename="__removed__")
Пример #5
0
    def submit(self):
        if os.path.isfile(
                os.path.join(self.cal_loc,
                             self.workflow[0]["where_to_parse_queue_id"])):
            try:
                if self.is_cal_in_queue():
                    signal_file = "__ready__" if os.path.isfile(
                        os.path.join(self.cal_loc,
                                     "__ready__")) else "__prior_ready__"
                    decorated_os_rename(loc=self.cal_loc,
                                        old_filename=signal_file,
                                        new_filename="__running__")
                    with open(self.log_txt, "a") as f:
                        f.write("{} Submit: at {}\n".format(
                            get_time_str(), self.firework_name))
                        f.write(
                            "\t\t\tThe job has been found in the queue system. No need to submit again.\n"
                        )
                        f.write(
                            "\t\t\t{} --> __running__\n".format(signal_file))
                    return True
            except Exception as err:
                with open(self.log_txt, "a") as f:
                    f.write("{} Submit: at {}\n".format(
                        get_time_str(), self.firework_name))
                    f.write("\t\t\tAn error raises: {}\n".format(err))
                    f.write("\t\t\tcreate __manual__\n")
                open(os.path.join(self.cal_loc, "__manual__"), "w").close()
                return False

        error_checking_files = [
            "OUTCAR", "OSZICAR", self.workflow[0]["vasp.out"]
        ]
        with open(self.log_txt, "a") as f:
            f.write("{} Submission: at {}\n".format(get_time_str(),
                                                    self.firework_name))
            f.write(
                "\t\t\tBefore the job submission, remove certain VASP files from which error checkers check errors.\n"
            )
            for file_ in error_checking_files:
                if os.path.isfile(os.path.join(self.cal_loc, file_)):
                    os.remove(os.path.join(self.cal_loc, file_))
                    f.write("\t\t\t\tremove {}\n".format(file_))
            f.write(
                "\t\t\t\tremove the queue stdout and stderr files if found\n")
            Queue_std_files(cal_loc=self.cal_loc,
                            workflow=self.workflow).remove_std_files()

        dir0 = os.getcwd()
        os.chdir(self.cal_loc)
        assert os.path.isfile("INCAR"), "Error: no INCAR under {}".format(
            job_folder)
        assert os.path.isfile("POTCAR"), "Error: no POTCAR under {}".format(
            job_folder)
        assert os.path.isfile("KPOINTS"), "Error: no KPOINTS under {}".format(
            job_folder)
        assert os.path.isfile("POSCAR"), "Error: no POSCAR under {}".format(
            job_folder)
        os.chdir(dir0)

        job_submission_script = os.path.split(
            self.firework["job_submission_script"])[1]
        if not os.path.isfile(os.path.join(self.cal_loc,
                                           job_submission_script)):
            if os.path.isfile(self.firework["job_submission_script"]):
                shutil.copyfile(
                    self.firework["job_submission_script"],
                    os.path.join(self.cal_loc, job_submission_script))
                with open(self.log_txt, "a") as f:
                    f.write("{} INFO: copy {} from {}\n".format(
                        get_time_str(), job_submission_script,
                        self.firework["job_submission_script"]))
            else:
                assert 1 == 2, "Error: Cannot find job submission script"

        signal_file = "__ready__" if os.path.isfile(
            os.path.join(self.cal_loc, "__ready__")) else "__prior_ready__"
        exist_status_list, error_list = self._decorated_os_system(
            cmd=self.firework["job_submission_command"])
        ind_dict = {0: "1st", 1: "2nd", 2: "3rd"}
        ind_dict.update({i: '{}th'.format(i + 1) for i in range(3, 10)})
        with open(self.log_txt, "a") as f:
            f.write("{} Submit: move to {}\n".format(get_time_str(),
                                                     self.firework_name))
            f.write("\t\ttry to submit job via cmd {}\n".format(
                self.firework["job_submission_command"]))
            for ind, exist_status in enumerate(exist_status_list):
                f.write("\t\t\t{} try:\n".format(ind_dict[ind]))
                f.write("\t\t\t\t\texist-status: {}\n".format(exist_status))
                f.write("\t\t\t\t\terror: {}\n".format(error_list[ind]))
            if exist_status_list[-1] == 0:
                f.write("\t\t\tSuccessfully submit the job.\n")
                f.write("\t\t\t{} --> __running__\n".format(signal_file))
            else:
                f.write(
                    "\t\t\tThe cmd execution hits the maximum times (10)\n")
                f.write("\t\t\t{} --> __manual__\n".format(signal_file))
            f.write("\t\t\tmove back\n")
        if exist_status_list[-1] == 0:
            decorated_os_rename(loc=self.cal_loc,
                                old_filename=signal_file,
                                new_filename="__running__")
        else:
            decorated_os_rename(loc=self.cal_loc,
                                old_filename=signal_file,
                                new_filename="__manual__")
            return False

        try:
            self.find_queue_id()
        except:
            with open(self.log_txt, "a") as f:
                f.write("{} Error: {}\n".format(get_time_str(), self.cal_loc))
                if not os.path.isfile(
                        os.path.join(self.cal_loc, "__fail_to_find_job_id__")):
                    f.write(
                        "\t\t\tCannot find job id in {} after the job submission for the first time\n"
                        .format(self.workflow[0]["vasp.out"]))
                    f.write(
                        "\t\t\tcreate file named __fail_to_find_job_id__\n")
                    open(os.path.join(self.cal_loc, "__fail_to_find_job_id__"),
                         "w").close()
                else:
                    f.write(
                        "\t\t\tThis is the second time to fail to dinf the job id in {} after job submissions\n"
                        .format(self.workflow[0]["vasp.out"]))
                    decorated_os_rename(loc=self.cal_loc,
                                        old_filename="__running__",
                                        new_filename="__error__")
                    #os.rename(os.path.join(self.cal_loc, signal_file), os.path.join(self.cal_loc, "__error__"))
                    f.write("\t\t\t__running__ --> __error__\n".format(
                        signal_file))
            return False
Пример #6
0
    def kill(self):
        queue_id = self.find_queue_id()
        if Queue_std_files(
                cal_loc=self.cal_loc,
                workflow=self.workflow).find_std_files() == [None, None]:
            if not os.path.isfile(os.path.join(self.cal_loc, "__error__")):
                print("\n{} Kill: {}".format(get_time_str(), self.cal_loc))
                print(
                    "\t\t\tTo kill this running job, file named __error__ must be present.\n"
                )
                raise Exception("See error information above.")

            exist_status_list, error_list = self._decorated_os_system(
                cmd=self.job_killing_cmd + " " + queue_id)
            stdout_file, stderr_file = Queue_std_files(
                cal_loc=self.cal_loc, workflow=self.workflow).find_std_files()
            ind_dict = {0: "1st", 1: "2nd", 2: "3rd"}
            ind_dict.update({i: '{}th'.format(i + 1) for i in range(3, 10)})
            with open(self.log_txt, "a") as f:
                f.write("{} Kill: move to {}\n".format(get_time_str(),
                                                       self.firework_name))
                f.write("\t\ttry to kill job via cmd {}\n".format(
                    self.job_killing_cmd + " " + queue_id))
                for ind, exist_status in enumerate(exist_status_list):
                    f.write("\t\t\t{} try:\n".format(ind_dict[ind]))
                    f.write(
                        "\t\t\t\t\texist-status: {}\n".format(exist_status))
                    f.write("\t\t\t\t\terror: {}\n".format(error_list[ind]))
                if exist_status_list[-1] == 0:
                    f.write("\t\t\tSuccessfully kill the job.\n")
                    f.write("\t\t\t__error__ --> __killed__\n")
                else:
                    f.write(
                        "\t\t\tThe cmd execution hits the maximum times (10)\n"
                    )
                    if [stdout_file, stderr_file] != [None, None]:
                        f.write("\t\t\tBut ")
                        [
                            f.write("{} ".format(f_name))
                            for f_name in [stdout_file, stderr_file]
                            if f_name != None
                        ]
                        f.write(
                            "is|are detected. So the job has been killed somehow...\n"
                        )
                        f.write("\t\t\t__error__ --> __killed__\n")
                        #f.write("***Let's create __manual__ for test purpose***\n")
                        #open(os.path.join(self.cal_loc, "__manual__"), "w").close()
                    else:
                        f.write("\t\t\t__error__ --> __manual__\n")
                f.write("\t\t\tmove back\n")
            if exist_status_list[-1] == 0 or [stdout_file, stderr_file
                                              ] != [None, None]:
                decorated_os_rename(loc=self.cal_loc,
                                    old_filename="__error__",
                                    new_filename="__killed__")
            else:
                decorated_os_rename(loc=self.cal_loc,
                                    old_filename="__error__",
                                    new_filename="__manual__")
        else:
            decorated_os_rename(loc=self.cal_loc,
                                old_filename="__error__",
                                new_filename="__killed__")
            #os.rename(os.path.join(self.cal_loc, "__error__"), os.path.join(self.cal_loc, "__killed__"))
            with open(self.log_txt, "a") as f:
                f.write(
                    "{} Kill: the job has been terminated under {}\n".format(
                        get_time_str(), self.firework_name))
                f.write("\t\t\tSo no need to kill\n")
                f.write("\t\t\t__error__ --> __killed__\n")
Пример #7
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))
Пример #8
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")
Пример #9
0
def prepare_input_files(cif_filename, cif_folder, mater_cal_folder,
                        current_firework, workflow):
    """
    prepare input files for dft calculations according to the defined firework in workflow at position current_firework_ind
    Input arguments:
        -cif_filename (str): the file from which the to-be-calculated structure is read using pymatgen.Structure.from_file
                        Of course, it might not be a cif file. Other formats supported by pymatgen.Structure.from_file are available
        -cif_folder (str): the absolute path of the folder where structure named cif_filename can be accessed.
        -mater_cal_folder (str): the absolute path of the folder where a series of sub-folders will be created to make a series of
                                calculations defined in workflow for the structure stored in file cif_filename
        -current_firework, workflow
            
    """
    log_txt = os.path.join(mater_cal_folder, "log.txt")
    current_cal_loc = os.path.join(mater_cal_folder,
                                   current_firework["firework_folder_name"])
    if not os.path.isdir(current_cal_loc):
        os.mkdir(current_cal_loc)
        open(os.path.join(current_cal_loc, "__vis__"), "w").close()
        with open(log_txt, "a") as f:
            f.write(
                "\n\n***************************************************************************************\n"
            )
            f.write(
                "***************************************************************************************\n"
            )
            f.write("{} INFO: under {}\n".format(get_time_str(),
                                                 mater_cal_folder))
            f.write("\t\tCreate sub-folder {}\n".format(
                current_firework["firework_folder_name"]))
            f.write("\t\tcreate __vis__ under {}\n".format(
                current_firework["firework_folder_name"]))

    if os.path.isfile(os.path.join(current_cal_loc, "__vis__")):

        if current_firework["extra_copy"]:
            with open(log_txt, "a") as f:
                f.write(
                    "{} INFO: copy defined by tag extra_tag to {}\n".format(
                        get_time_str(),
                        current_firework["firework_folder_name"]))
            for file in current_firework["extra_copy"]:
                filename = os.path.split(file)[1]
                shutil.copyfile(src=file,
                                dst=os.path.join(current_cal_loc, filename))
                with open(log_txt, "a") as f:
                    f.write("\t\t\t{}\n".format(file))

        if current_firework["step_no"] == 1:
            Write_Vasp_POSCAR(cal_loc=current_cal_loc,
                              structure_filename=cif_filename,
                              structure_file_folder=cif_folder,
                              workflow=workflow)
        else:
            copy_files = current_firework["copy_from_prev_cal"]
            move_files = current_firework["move_from_prev_cal"]
            contcar_to_poscar = current_firework["contcar_to_poscar"]
            prev_firework = workflow[current_firework["copy_which_step"] - 1]
            prev_cal_loc = os.path.join(mater_cal_folder,
                                        prev_firework["firework_folder_name"])
            non_existent_files = copy_and_move_files(
                src_dir=prev_cal_loc,
                dst_dir=current_cal_loc,
                copy_files=copy_files,
                move_files=move_files,
                contcar_to_poscar=contcar_to_poscar)
            file_dict = {
                "copy files: ":
                copy_files,
                "move files: ":
                move_files,
                "Fail to move files below because they are not existent: ":
                non_existent_files
            }
            with open(log_txt, "a") as f:
                f.write(
                    "{} INFO: copy and move files from src to dst\n".format(
                        get_time_str()))
                f.write("\t\t\tsrc: {}\n".format(
                    prev_firework["firework_folder_name"]))
                f.write("\t\t\tdst: {}\n".format(
                    current_firework["firework_folder_name"]))
                for file_type, file_list in file_dict.items():
                    if file_list:
                        f.write("\t\t\t{}".format(file_type))
                        [f.write("{}\t".format(file_)) for file_ in file_list]
                        f.write("\n")
                if contcar_to_poscar:
                    f.write("\t\t\tCONTCAR --> POSCAR under dst folder\n")
        assert os.path.isfile(os.path.join(
            current_cal_loc, "POSCAR")), "Error: POSCAR is missing!"

        input_args_list = {
            "cal_loc": current_cal_loc,
            "user_defined_cmd_list": current_firework["user_defined_cmd"],
            "where_to_execute": current_cal_loc,
            "log_txt": log_txt
        }
        if not Execute_user_defined_cmd(**input_args_list):
            return False

        Write_Vasp_INCAR(cal_loc=current_cal_loc,
                         structure_filename="POSCAR",
                         workflow=workflow)
        Write_Vasp_KPOINTS(cal_loc=current_cal_loc,
                           structure_filename="POSCAR",
                           workflow=workflow)
        Write_Vasp_POTCAR(cal_loc=current_cal_loc,
                          structure_filename="POSCAR",
                          workflow=workflow)

        if current_firework["final_extra_copy"]:
            with open(log_txt, "a") as f:
                f.write("{} INFO: tag final_extra_copy is not empty for {}\n".
                        format(get_time_str(),
                               current_firework["firework_folder_name"]))
                f.write("\t\tSo copy files listed below to {}:\n".format(
                    current_firework["firework_folder_name"]))
            for file in current_firework["final_extra_copy"]:
                filename = os.path.split(file)[1]
                shutil.copyfile(src=file,
                                dst=os.path.join(current_cal_loc, filename))
                with open(log_txt, "a") as f:
                    f.write("\t\t\t{}\n".format(file))

        input_args_list = {
            "cal_loc": current_cal_loc,
            "user_defined_cmd_list":
            current_firework["final_user_defined_cmd"],
            "where_to_execute": current_cal_loc,
            "log_txt": log_txt
        }
        if not Execute_user_defined_cmd(**input_args_list):
            return False

        decorated_os_rename(loc=current_cal_loc,
                            old_filename="__vis__",
                            new_filename="__ready__")
        with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f:
            f.write("{} INFO: All VASP input files are ready at {}\n".format(
                get_time_str(), current_firework["firework_folder_name"]))
            f.write("\t\t\t__vis__ --> __ready__\n")
Пример #10
0
def update_running_jobs_status(running_jobs_list, workflow):
    """
    Update jobs's status. for the running jobs, if any errors are detected, change __running__ to __error__ and 
        the error type will be written into __error__.
    input arguments:
        - running_jobs_list (list): a list of absolute pathes of running jobs.
        - workflow:  the output of func Parse_calculation_workflow.parse_calculation_workflow
    """
    #Check_after_cal = ["__electronic_divergence__", "__positive_energy__", "__ionic_divergence__"]
    #Check_on_the_fly = ["__electronic_divergence__", "__positive_energy__"]
    
    job_status_str = Job_management.check_jobs_in_queue_system(workflow=workflow, return_a_str=True)
    #print()
    #print(get_time_str())
    #print(job_status_str)
    #job_status_str = ""
    #if job_status_list:
    #    for i in range(1, len(job_status_list)):
    #        job_status_str += job_status_list[i]
    
    for job_path in running_jobs_list:
        
        
        find_error = False
        if Queue_std_files(cal_loc=job_path, workflow=workflow).find_std_files() != [None, None]:
            #for func Vasp_Error_checker, error_type=["after_cal"] will automatically check errors after cal.
            #If found, __running__ --> __error__ and the error info will be written into __error__ and return False
            #If not found, return True
            if Vasp_Error_checker(error_type=["after_cal"], cal_loc=job_path, workflow=workflow):
                log_txt_loc, firework_name = os.path.split(job_path)
                with open(os.path.join(log_txt_loc, "log.txt"), "a") as f:
                    f.write("{} INFO: Calculation successfully finishes at {}\n".format(get_time_str(), firework_name))
                    f.write("\t\t\t__running__ --> __done__\n")
                    decorated_os_rename(loc=job_path, old_filename="__running__", new_filename="__done__")
                    #os.rename(os.path.join(job_path, "__running__"), os.path.join(job_path, "__done__"))
        else:
            #for func Vasp_Error_checker, error_type=["on_the_fly"] will automatically check errors on the fly.
            #If found, __running__ --> __error__ and the error info will be written into __error__ and return False
            #If not found, return True
            Vasp_Error_checker(error_type=["on_the_fly"], cal_loc=job_path, workflow=workflow)
            
        if os.path.isfile(os.path.join(job_path, "__running__")):
            if Queue_std_files(cal_loc=job_path, workflow=workflow).find_std_files() != [None, None]:
                continue
                
            
                    
                
            queue_id = Job_management(cal_loc=job_path, workflow=workflow).find_queue_id()
            #print(queue_id, queue_id in job_status_str)
            if queue_id not in job_status_str:
                if not os.path.isfile(os.path.join(cal_loc, "__no_of_times_not_in_queue__")):
                    with open(os.path.join(cal_loc, "__no_of_times_not_in_queue__"), "w") as f:
                        f.write("1")
                else:
                    with open(os.path.join(cal_loc, "__no_of_times_not_in_queue__"), "r") as f:
                        times = int(next(f).strip())
                    if times <= 5:
                        with open(os.path.join(cal_loc, "__no_of_times_not_in_queue__"), "w") as f:
                            f.write(str(times+1))
                        continue
                
                log_txt_loc, firework_name = os.path.split(job_path)
                with open(os.path.join(log_txt_loc, "log.txt"), "a") as f:
                    f.write("{} Queue Error: {}\n".format(get_time_str(), job_path))
                    f.write("\t\t\tThe running job is not found in queue.\n")
                    f.write("\t\t\t__running__ --> __manual__\n")
                    f.write("\t\t\tCreate file __running_job_not_in_queue__.\n")
                    open(os.path.join(job_path, "__running_job_not_in_queue__"), "w").close()
                    decorated_os_rename(loc=job_path, old_filename="__running__", new_filename="__manual__")
                    #os.rename(os.path.join(job_path, "__running__"), os.path.join(job_path, "__manual__"))                
            else:
                if os.path.isfile(os.path.join(cal_loc, "__no_of_times_not_in_queue__")):
                    os.remove(os.path.join(cal_loc, "__no_of_times_not_in_queue__"))
def prepare_input_files(cif_filename, mater_cal_folder, current_firework_ind,
                        workflow):
    """
    prepare input files for dft calculations according to the defined firework in workflow at position current_firework_ind
    """
    firework = workflow[current_firework_ind]
    firework_folder = os.path.join(mater_cal_folder,
                                   firework["firework_folder_name"])
    if not os.path.isdir(firework_folder):
        os.mkdir(firework_folder)
        open(os.path.join(firework_folder, "__vis__"), "w").close()
        with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f:
            f.write(
                "\n\n***************************************************************************************\n"
            )
            f.write(
                "***************************************************************************************\n"
            )
            f.write("{} INFO: create sub-folder {} under {}\n".format(
                get_time_str(), firework["firework_folder_name"],
                mater_cal_folder))
            f.write("\t\t\tcreate __vis__ under this sub-folder.\n")

    if os.path.isfile(os.path.join(firework_folder, "__vis__")):
        #print(firework_folder)
        write_kpoints = False

        if workflow[current_firework_ind]["extra_copy"]:
            with open(os.path.join(mater_cal_folder, 'log.txt'), "a") as f:
                f.write("{} INFO: extra copy to dst {}\n".format(
                    get_time_str(), firework_folder))
                for file in workflow[current_firework_ind]["extra_copy"]:
                    filename = os.path.split(file)[1]
                    shutil.copyfile(src=file,
                                    dst=os.path.join(firework_folder,
                                                     filename))
                    f.write("\t\t{}\n".format(file))

        if current_firework_ind == 0:
            Write_MPRelax_vasp_input_set(
                cif_filename=cif_filename,
                where_to_write=firework_folder,
                sort_structure=workflow[0]["sort_structure"],
                force_gamma=workflow[0]["force_gamma"])
            write_kpoints = True
            with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f:
                f.write("{} INFO: VASP input sets generated by ".format(
                    get_time_str()))
                f.write("pymatgen.io.vasp.sets.MPRelaxSet under folder {}\n".
                        format(firework["firework_folder_name"]))
                if workflow[0]["sort_structure"] == False:
                    f.write(
                        "\t\t\tsort_structure is off, so POSCAR generated by pymatgen is overwritten by the copy below\n"
                    )
                    f.write("\t\t\tsrc: {}\n".format(cif_filename))
                    f.write("\t\t\tdst: {}\n".format(
                        os.path.join(firework_folder, "POSCAR")))
            #if workflow[0]["2d_system"]:
            #    modify_vasp_kpoints_for_2D(cal_loc=firework_folder, kpoints_type=workflow[0]["kpoints_type"], rename_old_kpoints="KPOINTS.pymatgen")
            #    with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f:
            #        f.write("{} INFO: Because it is a 2D system, KPONITS is modified so that K_z = 0 for all kpoints\n".format(get_time_str()))
            #        f.write("\t\t\tKPOINTS --> KPOINTS.pymatgen\n")
        else:
            copy_files = firework["copy_from_prev_cal"]
            move_files = firework["move_from_prev_cal"]
            contcar_to_poscar = firework["contcar_to_poscar"]
            src_step_name = "step_{}_".format(firework["copy_which_step"])
            for src_firework in workflow:
                if src_step_name in src_firework["firework_folder_name"]:
                    break
            src_dir = os.path.join(mater_cal_folder,
                                   src_firework["firework_folder_name"])
            non_existent_files = copy_and_move_files(
                src_dir=src_dir,
                dst_dir=firework_folder,
                copy_files=copy_files,
                move_files=move_files,
                contcar_to_poscar=contcar_to_poscar)
            with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f:
                f.write(
                    "{} INFO: copy and move files from src folder to dst\n".
                    format(get_time_str()))
                f.write("\t\t\tsrc: {}\n".format(src_dir))
                f.write("\t\t\tdst: {}\n".format(firework_folder))
                if copy_files:
                    f.write("\t\t\tcopy files:")
                    [f.write("{}\t".format(file_)) for file_ in copy_files]
                    f.write("\n")
                if non_existent_files["copy_files"]:
                    f.write(
                        "Error: fail to copy files below because they are not existent:"
                    )
                    [
                        f.write("{}\t".format(file_))
                        for file_ in non_existent_files["copy_files"]
                    ]

                if move_files:
                    f.write("\t\tmove files:")
                    [f.write("{}\t".format(file_)) for file_ in move_files]
                    f.write("\n")
                if non_existent_files["move_files"]:
                    f.write(
                        "Error: \t\tfail to move files below because they are not existent:"
                    )
                    [
                        f.write("{}\t".format(file_))
                        for file_ in non_existent_files["copy_files"]
                    ]

                if contcar_to_poscar:
                    f.write("\t\trename CONTCAR as POSCAR under dst folder\n")

        new_incar_tags = firework["new_incar_tags"]
        comment_incar_tags = firework["comment_incar_tags"]
        remove_incar_tags = firework["remove_incar_tags"]
        #print(new_incar_tags, comment_incar_tags, remove_incar_tags)
        if new_incar_tags or comment_incar_tags or remove_incar_tags:
            if current_firework_ind == 0:
                modify_vasp_incar(
                    cal_loc=firework_folder,
                    new_tags=new_incar_tags,
                    comment_tags=comment_incar_tags,
                    rename_old_incar="INCAR.pymatgen",
                    remove_tags=remove_incar_tags,
                )
            else:
                modify_vasp_incar(cal_loc=firework_folder,
                                  new_tags=new_incar_tags,
                                  comment_tags=comment_incar_tags,
                                  remove_tags=remove_incar_tags)

            with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f:
                f.write("{} INFO: modify INCAR:\n".format(get_time_str()))
                if new_incar_tags:
                    f.write("\t\tnew incar tags:\n")
                    [
                        f.write("\t\t\t{}={}\n".format(key_, value_))
                        for key_, value_ in new_incar_tags.items()
                    ]
                if comment_incar_tags:
                    f.write("\t\tcomment incar tags:")
                    [
                        f.write("{}\t".format(tag_))
                        for tag_ in comment_incar_tags
                    ]
                    f.write("\n")
                if remove_incar_tags:
                    f.write("\t\tremove incar tags: ")
                    [
                        f.write("{}\t".format(tag_))
                        for tag_ in remove_incar_tags
                    ]
                    f.write("\n")

        if not os.path.isfile(os.path.join(firework_folder, "KPOINTS")):
            if firework["kpoints_type"] == "Line-mode":
                Write_line_mode_KPOINTS(
                    cal_loc=firework_folder,
                    structure_filename=os.path.join(firework_folder, "POSCAR"),
                    intersections=firework["intersections"],
                    twoD_system=workflow[0]["2d_system"])
                with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f:
                    f.write(
                        "{} INFO: write KPOINTS in the line mode based on pymatgen.symmetry.bandstructure.HighSymmKpath\n"
                        .format(get_time_str()))
            elif firework["kpoints_type"] == "MPNonSCFSet_uniform":
                Write_NONSCF_KPOINTS(
                    structure_filename=os.path.join(firework_folder, "POSCAR"),
                    mode="uniform",
                    reciprocal_density=firework["reciprocal_density"])
                write_kpoints = True
            elif firework["kpoints_type"] == 'MPNonSCFSet_line':
                Write_NONSCF_KPOINTS(
                    structure_filename=os.path.join(firework_folder, "POSCAR"),
                    mode="line",
                    kpoints_line_density=firework["kpoints_line_density"])
                write_kpoints = True
            elif firework["kpoints_type"] == "MPRelaxSet" and firework[
                    "step_no"] != 1:
                Write_MPRelax_KPOINTS(structure_filename=os.path.join(
                    firework_folder, "POSCAR"),
                                      force_gamma=workflow[0]["force_gamma"])
                write_kpoints = True
            elif firework["kpoints_type"] == "MPStaticSet":
                Write_MPStatic_KPOINTS(structure_filename=os.path.join(
                    firework_folder, "POSCAR"),
                                       force_gamma=workflow[0]["force_gamma"])
                write_kpoints = True

        if write_kpoints and workflow[0]["2d_system"]:
            new_name = modify_vasp_kpoints_for_2D(
                cal_loc=firework_folder,
                kpoints_type=firework["kpoints_type"],
                rename_old_kpoints="KPOINTS.pymatgen_" +
                firework["kpoints_type"])

        if write_kpoints:
            with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f:
                f.write("{} INFO: use pymatgen.io.vasp.{} ".format(
                    get_time_str(), firework["kpoints_type"]))
                f.write("to write KPOINTS under {}\n".format(
                    firework["firework_folder_name"]))
                if workflow[0]["2d_system"]:
                    f.write(
                        "{} INFO: Because it is a 2D system, KPOINTS is modified so that K_z = 0 for all kponits\n"
                        .format(get_time_str()))
                    f.write("\t\t\tKPOINTS --> {}\n".format(new_name))

        if abs(firework["denser_kpoints"] - 1) > 1.0e-4:
            new_name = modify_vasp_kpoints_for_2D(
                cal_loc=firework_folder,
                kpoints_type="automatic",
                rename_old_kpoints="KPOINTS.sparse",
                denser_kpoints=firework["denser_kpoints"])
            with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f:
                f.write(
                    "{} INFO: for {}, tag denser_kpoints has been set to {}\n".
                    format(get_time_str(), firework["firework_folder_name"],
                           firework["denser_kpoints"]))
                f.write("\t\t\tChange KPOINTS according to denser_kpoints\n")
                f.write("\t\t\told KPOINTS --> {}\n".format(new_name))

        if workflow[current_firework_ind]["final_extra_copy"]:
            with open(os.path.join(mater_cal_folder, 'log.txt'), "a") as f:
                f.write("{} INFO: final extra copy to dst {}\n".format(
                    get_time_str(), firework_folder))
                for file in workflow[current_firework_ind]["final_extra_copy"]:
                    filename = os.path.split(file)[1]
                    shutil.copyfile(src=file,
                                    dst=os.path.join(firework_folder,
                                                     filename))
                    f.write("\t\t{}\n".format(file))

        if os.path.isfile(os.path.join(firework_folder, "__manual__")):
            os.remove(os.path.join(firework_folder, "__vis__"))
            with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f:
                f.write("{} INFO: {}\n".format(
                    get_time_str(), firework["firework_folder_name"]))
                f.write(
                    "\t\t\t__manual__ has been created during the preparation of VASP input files.\n"
                )
                f.write("\t\t\tMust be handled manually.\n")
                f.write("\t\t\tremove __vis__\n")
        elif os.path.isfile(os.path.join(firework_folder, "__prior_ready__")):
            os.remove(os.path.join(firework_folder, "__vis__"))
            with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f:
                f.write("{} INFO: {}\n".format(
                    get_time_str(), firework["firework_folder_name"]))
                f.write("\t\t\tAll VASP input files are ready.\n")
                f.write(
                    "\t\t\t__prior_ready__ has been found. So this calculation will be submitted earlier than those labelled by __ready__\n"
                )
                f.write("\t\t\tremove __vis__\n")
        else:
            decorated_os_rename(loc=firework_folder,
                                old_filename="__vis__",
                                new_filename="__ready__")
            #os.rename(os.path.join(firework_folder, "__vis__"), os.path.join(firework_folder, "__ready__"))
            with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f:
                f.write(
                    "{} INFO: All VASP input files are ready at {}\n".format(
                        get_time_str(), firework["firework_folder_name"]))
                f.write("\t\t\t__vis__ --> __ready__\n")