예제 #1
0
def Execute_user_defined_cmd(cal_loc, user_defined_cmd_list, where_to_execute,
                             log_txt):
    """
    Execute commands listed in user_defined_cmd_list under where_to_execute and write log into log_txt.
    input arguments:
        - cal_loc (str): The absolute path of the calculation folder
        - user_defined_cmd_list (list of str): a list of cmds to be executed.
        - where_to_execute (str): an absolute path under which cmds will be executed.
        - log_txt (str): the file to which log is written. Note that the absolute path should be used.
    If cmds are successfully executed, return True; Otherwise, return False
    """
    if user_defined_cmd_list:
        for cmd_ in user_defined_cmd_list:
            if not decorated_os_system(cmd=cmd_,
                                       where_to_execute=where_to_execute):
                with open(log_txt, "a") as f:
                    f.write("{} Error: at {}\n".format(get_time_str(),
                                                       where_to_execute))
                    f.write(
                        "\t\t\tfail to execute user-defined-cmd {}\n".format(
                            cmd_))
                    f.write(
                        "\t\t\tcreate __manual__ into {}\n".format(cal_loc))
                open(os.path.join(cal_loc, "__manual__"))
                return False
        with open(log_txt, "a") as f:
            f.write("{} INFO: at {}\n".format(get_time_str(),
                                              where_to_execute))
            f.write(
                "\t\t\tsuccessfully execute user-defined-cmd as listed below:\n"
            )
            for cmd_ in user_defined_cmd_list:
                f.write("\t\t\t\t{}\n".format(cmd_))
    return True
예제 #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 pre_and_post_process(cif_filename, cif_folder, cal_folder, workflow):
    """
    Make pre-processes or post-processes of VASP calculations according to the input workflow
    input arguments:
        - cif_filename (str): the cif file of a structure.
        - cif_folder (str): the absolute path of the folder where cif_filename is stored.
        - cal_folder (str): Under cal_folder, a sub-folder will be created where a set of DFT calculations defined by workflow will be made.
                        Note that the absolute path should be provided.
        - workflow: the return of function parse_calculation_workflow, which define a set of DFT calculations and related pre- and post- processes
    """
    if not os.path.isdir(cal_folder):
        os.mkdir(cal_folder)

    mater_cal_folder = os.path.join(cal_folder, cif_filename.split(".")[0])
    if not os.path.isdir(mater_cal_folder):
        os.mkdir(mater_cal_folder)
        with open(os.path.join(mater_cal_folder, "log.txt"), "w") as f:
            f.write("{} INFO: Create this folder {}\n".format(
                get_time_str(), mater_cal_folder))

    current_firework = get_current_firework(mater_cal_folder=mater_cal_folder,
                                            workflow=workflow)
    prepare_input_files(cif_filename=cif_filename,
                        cif_folder=cif_folder,
                        mater_cal_folder=mater_cal_folder,
                        current_firework=current_firework,
                        workflow=workflow)
    post_process(mater_cal_folder=mater_cal_folder,
                 current_firework=current_firework,
                 workflow=workflow)
예제 #4
0
def Write_Vasp_POTCAR(cal_loc, structure_filename, workflow):
    """
    Write POTCAR in folder cal_loc as follows:
        If POTCAR is missing, write POTCAR using pymatgen.io.vasp.sets.MPRelaxSet
    Input arguments:
        cal_loc (str): the absolute path
        structure_filename (str): the file from which the structure is read using pymatgen.Structure.from_file
        workflow
    """

    firework = get_current_firework_from_cal_loc(cal_loc, workflow)
    log_txt_loc, firework_name = os.path.split(cal_loc)
    log_txt = os.path.join(log_txt_loc, "log.txt")

    if not os.path.isfile(os.path.join(cal_loc, "POTCAR")):
        structure = Structure.from_file(
            os.path.join(cal_loc, structure_filename))
        vis = MPRelaxSet(structure=structure)
        vis.potcar.write_file(filename=os.path.join(cal_loc, "POTCAR"))
        write_INCAR = True
        with open(log_txt, "a") as f:
            f.write("{} INFO: no POTCAR in {}\n".format(
                get_time_str(), firework_name))
            f.write(
                "\t\t\tuse pymatgen.io.vasp.sets.MPRelaxSet to write POTCAR\n")
예제 #5
0
def Write_Vasp_KPOINTS(cal_loc, structure_filename, workflow):
    """
    Write or modify KPOINTS in cal_loc as follows:
        step I: Check the presence of file KPOINTS in folder cal_loc.
                If present, no need to write KPOINTS,
                If missing, write KPOINTS according to tag kpoints_tag
        step II: If KPOINTS is written and the system is 2D according to tag 2d_system, modify KPOINTS such that K_z = 0 for all kpoints
        step III: tag denser_kpoints defaults to (1, 1, 1). If denser_kpoints is set, then modfiy KPOINTS accordingly and save the old
                KPOINTS as KPOINTS.sparse. Note that this function is only active for automatically generated KPOINTS, namely,
                kpoints_type = "MPRelaxSet" or "MPStaticSet"
    Input arguments:
        cal_loc (str): the absolute path
        structure_filename (str): the file from which the structure is read using pymatgen.Structure.from_file
        workflow
    """
    vasp_kpoints = Vasp_Kpoints(cal_loc, structure_filename, workflow)
    firework = vasp_kpoints.current_firework
    
    #If file KPOINTS is present in cal_loc folder, no need to write KPOINTS
    if os.path.isfile(os.path.join(cal_loc, "KPOINTS")):
        kpoints_type = None 
    else:
        kpoints_type = vasp_kpoints.current_firework["kpoints_type"]
        
    if kpoints_type == "Line-mode":
        vasp_kpoints.Write_line_mode_KPOINTS(intersections=firework["intersections"], twoD_system=workflow[0]["2d_system"])
        with open(vasp_kpoints.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()))
            if workflow[0]["2d_system"]:
                f.write("\t\t\tKPOINTS is already suitable for 2D systems\n")
    elif kpoints_type == 'MPNonSCFSet_line':
        vasp_kpoints.Write_NONSCF_KPOINTS(mode="line", kpoints_line_density=firework["kpoints_line_density"])
    elif kpoints_type == "MPNonSCFSet_uniform":
        vasp_kpoints.Write_NONSCF_KPOINTS(mode="uniform", reciprocal_density=firework["reciprocal_density"])
    elif kpoints_type == "MPRelaxSet":
        vasp_kpoints.Write_MPRelax_KPOINTS(force_gamma=workflow[0]["force_gamma"])
    elif kpoints_type == "MPStaticSet":
        vasp_kpoints.Write_MPStatic_KPOINTS(force_gamma=workflow[0]["force_gamma"])
    
    if kpoints_type in ['MPNonSCFSet_line', "MPNonSCFSet_uniform", "MPRelaxSet", "MPStaticSet"]:
        with open(vasp_kpoints.log_txt, "a") as f:
            f.write("{} INFO: use pymatgen.io.vasp.{} ".format(get_time_str(),kpoints_type))
            f.write("to write KPOINTS under {}\n".format(vasp_kpoints.firework_name))
        
        if workflow[0]["2d_system"]:
            new_name = vasp_kpoints.modify_vasp_kpoints_for_2D(rename_old_kpoints="KPOINTS.pymatgen_"+kpoints_type)
            with open(vasp_kpoints.log_txt, "a") as f:
                f.write("\t\t\tKPOINTS is modified for 2D systems\n")
                f.write("\t\t\t\told KPOINTS --> {}\n".format(new_name))
    
    kpoints_type = firework["kpoints_type"]
    #tag denser_kpoints consists of integers by default. If this tag is set, the three numbers are float.
    if isinstance(firework["denser_kpoints"][0], float) and (kpoints_type in ["MPRelaxSet", "MPStaticSet"]):
        vasp_kpoints.make_KPOINTS_denser(denser_kpoints = firework["denser_kpoints"])
        with open(vasp_kpoints.log_txt, "a") as f:
            f.write("\t\t\ttag denser_kpoints has been set to {}\n".format(firework["denser_kpoints"]))
            f.write("\t\t\t\tSo change KPOINTS according to denser_kpoints\n")
            f.write("\t\t\t\told KPOINTS --> KPOINTS.sparse\n")
def append_info_to_a_file(firework_name,
                          cal_loc,
                          file_list=[
                              "WAVECAR", "CHGCAR", "CONTCAR", "POSCAR",
                              "KPOINTS", "INCAR"
                          ]):
    shutil.copyfile(os.path.join(cal_loc, "POSCAR"),
                    os.path.join(cal_loc, "CONTCAR"))
    for filename in file_list:
        with open(os.path.join(cal_loc, filename), "a") as f:
            f.write("#{}: {} of {}\n".format(get_time_str(), filename,
                                             firework_name))
예제 #7
0
    def Write_line_mode_KPOINTS(self, intersections, twoD_system=False):
        """
        Write a kpath along the high symmetry kpoints in the line mode into KPOINTS under dir cal_loc for the band structure calculation.
        input arguments:
            - intersections (int): For every segment, there are intersections equally spaced kpionts, including the starting and ending high symmetry k-points
            - twoD_system (bool): If True, the kpath only includes the kpoints whose z component are zero. Default: False
        see https://cms.mpi.univie.ac.at/vasp/vasp/Strings_k_points_bandstructure_calculations.html
        Note that the reciprocal coordinates are adopted.
        Note that if twoD_system is True, the vacuum layer is assumed to be along the Z direction and the lattice vector c must be normal to the surface.
        """
        try:
            kpath = HighSymmKpath(structure=self.structure).get_kpoints(
                line_density=1, coords_are_cartesian=False)
        except Exception as e:
            with open(os.path.join(self.log_txt), "a") as f:
                f.write("{} Error: {}\n".format(get_time_str(),
                                                self.firework_name))
                f.write(
                    "\t\tfail to find high-symmetry kpoints using pymatgen's HighSymmKpath\n"
                )
                f.write("\t\t{}\n".format(e))
                f.write(
                    "\t\tcreate __manual__ and write down '__HighSymmKpath__'.\n"
                )
            with open(os.path.join(self.cal_loc, "__manual__"), "w") as f:
                f.write("__HighSymmKpath__")
            return False
        kpoints = []
        for k_, k_label in zip(*kpath):
            if k_label:
                kpoints.append(list(k_) + [k_label])

        starting_kpoints = kpoints[::2]
        ending_kpoints = kpoints[1::2]

        with open(os.path.join(self.cal_loc, "KPOINTS"), "w") as f:
            f.write("k-points along high symmetry lines\n")
            f.write("{}\n".format(intersections))
            f.write("Line-mode\n")
            f.write("rec\n")
            for start_k, end_k in zip(starting_kpoints, ending_kpoints):
                if twoD_system and (abs(start_k[2]) + abs(end_k[2])) > 1.0e-5:
                    continue

                f.write("    {}  {}  {}    {}\n".format(*start_k))
                f.write("    {}  {}  {}    {}\n".format(*end_k))
                f.write("\n")
예제 #8
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__")
예제 #10
0
def get_partial_charge_tags(cal_loc, firework, workflow):
    if firework["eint_wrt_cbm"] != None:
        step_folder_for_band_edge = workflow[
            firework["which_step_to_read_cbm_vbm"] - 1]["firework_folder_name"]
        vbm_cbm_efermi_path = os.path.join(
            os.path.split(cal_loc)[0], step_folder_for_band_edge)
        VBM, CBM, VBM_occ, CBM_occ, efermi = read_CBM_VBM_Efermi_from_vasprun(
            cal_loc=vbm_cbm_efermi_path)
        CBM_ = CBM - efermi
        EINT_lower, EINT_top = firework["eint_wrt_cbm"]
        new_incar_tags = {
            "EINT": "{}  {}".format(EINT_lower + CBM_, EINT_top + CBM_),
            "NBMOD": -3,
            "LPARD": ".TRUE."
        }
        with open(os.path.join(cal_loc, "log.txt"), "a") as f:
            f.write(
                "{} INFO: partial_charge_cal is set to Yes-->following actions are taken\n"
                .format(get_time_str()))
            f.write(
                "\t\tread band edge information and the Fermi level from {}\n".
                format(vbm_cbm_efermi_path))
            f.write("\t\tCBM={}\tVBM={}\tCBM_occ={}\tVBM_occ={}\tEfermi={}\n".
                    format(CBM, VBM, CBM_occ, VBM_occ, efermi))
            f.write(
                "\t\tbased on these and EINT_wrt_CBM={}, the following tags are generated and added:\n"
                .format(str(EINT_lower) + "  " + str(EINT_top)))
            f.write("\t\t\tEINT={}\tNBMOD=-3\tLPARD=.TRUE.\n".format(
                new_incar_tags["EINT"]))
        return new_incar_tags
    elif firework["eint_wrt_vbm"] != None:
        step_folder_for_band_edge = workflow[
            firework["which_step_to_read_cbm_vbm"] - 1]["firework_folder_name"]
        vbm_cbm_efermi_path = os.path.join(
            os.path.split(cal_loc)[0], step_folder_for_band_edge)
        VBM, CBM, VBM_occ, CBM_occ, efermi = read_CBM_VBM_Efermi_from_vasprun(
            cal_loc=vbm_cbm_efermi_path)
        VBM_ = VBM - efermi
        EINT_lower, EINT_top = firework["eint_wrt_vbm"]
        new_incar_tags = {
            "EINT": "{}  {}".format(EINT_lower + VBM_, EINT_top + VBM_),
            "NBMOD": -3,
            "LPARD": ".TRUE."
        }
        with open(os.path.join(cal_loc, "log.txt"), "a") as f:
            f.write(
                "{} INFO: partial_charge_cal is set to Yes-->following actions are taken\n"
                .format(get_time_str()))
            f.write(
                "\t\tread band edge information and the Fermi level from {}\n".
                format(vbm_cbm_efermi_path))
            f.write("\t\tCBM={}\tVBM={}\tCBM_occ={}\tVBM_occ={}\tEfermi={}\n".
                    format(CBM, VBM, CBM_occ, VBM_occ, efermi))
            f.write(
                "\t\tbased on these and EINT_wrt_VBM={}, the following tags are generated and added:\n"
                .format(str(EINT_lower) + "  " + str(EINT_top)))
            f.write("\t\t\tEINT={}\tNBMOD=-3\TLPARD=.TRUE.\n".format(
                new_incar_tags["EINT"]))
        return new_incar_tags
    else:
        return {}
예제 #11
0
def Write_Vasp_INCAR(cal_loc, structure_filename, workflow):
    """
    Write or modify INCAR in folder cal_loc as follows:
        step I: If no INCAR in cal_loc, write INCAR using pymatgen.io.vasp.sets.MPRelaxSet
        step II: Modify INCAR according to new_incar_tags and remove_incar_tags.
    Input arguments:
        cal_loc (str): the absolute path
        structure_filename (str): the file from which the structure is read using pymatgen.Structure.from_file
        workflow
    """

    firework = get_current_firework_from_cal_loc(cal_loc, workflow)
    firework_name = os.path.split(cal_loc)[-1]
    log_txt = os.path.join(cal_loc, "log.txt")

    write_INCAR = False
    if not os.path.isfile(os.path.join(cal_loc, "INCAR")):
        structure = Structure.from_file(
            os.path.join(cal_loc, structure_filename))
        vis = MPRelaxSet(structure=structure)
        vis.incar.write_file(filename=os.path.join(cal_loc, "INCAR"))
        write_INCAR = True
        with open(log_txt, "a") as f:
            f.write("{} INFO: no INCAR in {}\n".format(get_time_str(),
                                                       firework_name))
            f.write(
                "\t\t\tuse pymatgen.io.vasp.sets.MPRelaxSet to write INCAR\n")

    new_incar_tags = dict([
        (incar_tag, incar_value)
        for incar_tag, incar_value in firework["new_incar_tags"].items()
    ])
    remove_incar_tags = firework["remove_incar_tags"]
    #Tags related to partial charge calculations.
    if firework["partial_charge_cal"]:
        new_incar_tags.update(
            get_partial_charge_tags(cal_loc=cal_loc,
                                    firework=firework,
                                    workflow=workflow))
    if firework["ldau_cal"]:
        new_incar_tags.update(
            generate_Hubbard_U_J_INCAR_tags(
                cal_loc=cal_loc,
                U_J_table_filename=firework["ldau_u_j_table"]))
    if new_incar_tags or remove_incar_tags:
        if write_INCAR:
            modify_vasp_incar(cal_loc=cal_loc,
                              new_tags=new_incar_tags,
                              rename_old_incar="INCAR.pymatgen",
                              remove_tags=remove_incar_tags)
        else:
            modify_vasp_incar(cal_loc=cal_loc,
                              new_tags=new_incar_tags,
                              remove_tags=remove_incar_tags)
        with open(log_txt, "a") as f:
            f.write("{} INFO: modify INCAR in {}\n".format(
                get_time_str(), firework_name))
            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 remove_incar_tags:
                f.write("\t\tremove incar tags: ")
                [f.write("{}\t".format(tag_)) for tag_ in remove_incar_tags]
                f.write("\n")
            if write_INCAR:
                f.write("\t\told INCAR --> INCAR.pymatgen\n")

    if firework["bader_charge"]:
        if firework["step_no"] == 1:
            with open(log_txt, "a") as f:
                f.write("{} INFO: in {}\n".format(get_time_str(),
                                                  firework_name))
                f.write("\t\t\t'bader_charge' is on\n")
                f.write(
                    "\t\t\tBut this is the first step. Cannot find NGXF, NGYF, NGZF\n"
                )
                f.write(
                    "\t\t\tLet's make a calculation without this INCAR tags first to get the default NGXF, NGYF and NGZF\n"
                )
        else:
            prev_cal = os.path.join(
                os.path.split(cal_loc)[0],
                workflow[firework["copy_which_step"] -
                         1]["firework_folder_name"])
            new_incar_tags = get_bader_charge_tags(cal_loc=prev_cal)
            modify_vasp_incar(cal_loc=cal_loc,
                              new_tags=new_incar_tags,
                              rename_old_incar="INCAR.no_bader_charge")
            with open(log_txt, "a") as f:
                f.write("{} INFO: in {}\n".format(get_time_str(),
                                                  firework_name))
                f.write("\t\t\t'bader_charge' is on\n")
                f.write(
                    "\t\t\tretrieve NGXF, NGYF, NGZF from {} and double them\n"
                    .format(os.path.split(prev_cal)[1]))
                f.write("\t\tnew incar tags:\n")
                [
                    f.write("\t\t\t{}={}\n".format(key_, value_))
                    for key_, value_ in new_incar_tags.items()
                ]
예제 #12
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")
예제 #13
0
def Write_Vasp_POSCAR(cal_loc, structure_filename, structure_file_folder,
                      workflow):
    """
    Write POSCAR in folder cal_loc as follows:
        If no POSCAR in cal_loc, write POSCAR:
            If tag sort_structure is on, struture_filename under structure_file_folder is assumed in the form of POSCAR.
                In this case, just copy the file and rename it as POSCAR
            If tag sort_structure is off, write POSCAR using pymatgen.Structure
        If POSCAR is present, nothing has been done.
    Input arguments:
        cal_loc (str): the absolute path of the calculation folders
        structure_filename (str): the file from which the structure is read using pymatgen.Structure.from_file
        structure_file_folder (str): the absolute path of the folder where structure_filename can accessed.
        workflow
    """

    #firework = get_current_firework_from_cal_loc(cal_loc, workflow)
    firework_name = os.path.split(cal_loc)[-1]
    log_txt = os.path.join(cal_loc, "log.txt")

    if not os.path.isfile(os.path.join(cal_loc, "POSCAR")):

        if workflow[0]["sort_structure"]:
            structure = Structure.from_file(
                os.path.join(structure_file_folder, structure_filename))
            structure = structure.get_sorted_structure()
            structure.to(fmt="poscar",
                         filename=os.path.join(cal_loc, "POSCAR"))
            with open(log_txt, "a") as f:
                f.write("{} INFO: no POSCAR in {}\n".format(
                    get_time_str(), firework_name))
                f.write("\t\t\tsrc: {}\n".format(
                    os.path.join(structure_file_folder, structure_filename)))
                f.write("\t\t\ttag sort_structure is on\n")
                f.write(
                    "\t\t\tSo write a sorted structure into POSCAR using pymatgen.Structure\n"
                    .format(
                        os.path.join(structure_file_folder,
                                     structure_filename)))
        else:
            if Is_Vasp_POSCAR(structure_filename=structure_filename,
                              structure_file_folder=structure_file_folder):
                src = os.path.join(structure_file_folder, structure_filename)
                dst = os.path.join(cal_loc, "POSCAR")
                shutil.copyfile(src=src, dst=dst)
                with open(log_txt, "a") as f:
                    f.write("{} INFO: no POSCAR in {}\n".format(
                        get_time_str(), firework_name))
                    f.write(
                        "\t\t\tWe find that src is POSCAR-formated and tag sort_structure is off\n"
                        .format(src))
                    f.write("\t\t\tSo write POSCAR by copying\n")
                    f.write("\t\t\t\t\tsrc: {}\n".format(src))
                    f.write("\t\t\t\t\tdst: {}\n".format(dst))
            else:
                structure = Structure.from_file(
                    os.path.join(structure_file_folder, structure_filename))
                structure.to(fmt="poscar",
                             filename=os.path.join(cal_loc, "POSCAR"))
                with open(log_txt, "a") as f:
                    f.write("{} INFO: no POSCAR in {}\n".format(
                        get_time_str(), firework_name))
                    f.write("\t\t\tsrc: {}".format(
                        os.path.join(structure_file_folder,
                                     structure_filename)))
                    f.write("\t\t\tSeems src is not POSCAR-formated\n")
                    f.write("\t\t\ttag sort_structure is off\n")
                    f.write(
                        "\t\t\tSo write an unsorted structure into POSCAR using pymatgen.Structure\n"
                    )
예제 #14
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__"))
예제 #15
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")
예제 #16
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
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")