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
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")
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)
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")
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))
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")
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__")
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 {}
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() ]
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")
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" )
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 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")
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")