def make_KPOINTS_denser(self, denser_kpoints = []): """ Modify KPOINTS such that the kpiont along the axes in certain directions is denser_kpoints denser. Rename old KPOINTS as KPOINTS.sparse input arguments: denser_kpoints (list of float): This tag is only active at kpoints_type='MPRelaxSet', 'MPStaticSet', namely only for automatically generated KPOINTS Note that denser_kpoints must consist of three float numbers: - The first number is associated to the 'x' axis - The second number is associated to the 'y' axis - The third number is associated to the 'z' axis """ if self.current_firework["kpoints_type"] not in ['MPRelaxSet', 'MPStaticSet']: return False assert len(denser_kpoints) == 3, "Error: tag denser_kpoints must be three float/integer numbers separated by commas." with open(os.path.join(self.cal_loc, "KPOINTS"), "r") as f: kpoints = [line.strip() for line in f if line.strip()] assert "gam" in kpoints[2].lower() or "mon" in kpoints[2].lower(), "Error: fail to make KPOINTS denser at {}".format(self.cal_loc) nk_list = [int(k) for k in kpoints[3].split() if k] for i in range(3): nk_list[i] = int(round(nk_list[i]*denser_kpoints[i])) if nk_list[i] == 0: nk_list[i] = 1 kpoints[3] = "{} {} {}".format(*nk_list) decorated_os_rename(loc=self.cal_loc, old_filename="KPOINTS", new_filename="KPOINTS.sparse") with open(os.path.join(self.cal_loc, "KPOINTS"), "w") as f: for line in kpoints: f.write(line+"\n")
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 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 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 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 modify_vasp_incar(cal_loc, new_tags={}, remove_tags=[], rename_old_incar=True): """ add new tags and remove obsolete tags in incar. input arguments: - cal_loc (str): the location of INCAR to be modified, <--required - new_tags (dict): new tags to be added, - remove_tags (list): incar tags that will be removed - rename_old_incar (bool or str): if rename_old_incar is True, rename the old INCAR as INCAR_0, INCAR_1, INCAR_2, etc. if rename_old_incar is False, the old INCAR will be overwritten by new INCAR. if rename_old_incar is a string, rename the old INCAR as the string. Default: True return the valid INCAR dictionary if no modification is made. """ new_tags = {key.upper(): value for key, value in new_tags.items()} remove_tags = [tag.upper() for tag in remove_tags] new_incar_tag_name = new_tags.keys() for tag in remove_tags: if tag in new_incar_tag_name: #import pprint print("\n\n**directory: {}".format(cal_loc)) print("**new_tags:") pprint.pprint(new_tags) print("**remove_tags:") pprint.pprint(remove_tags) Error_info = "***You are gonna remove an INCAR tag {} via remove_tags.".format( tag) Error_info += "This contradicts the simultaneous attempt to set {} via new_tags**\n\n".format( tag) print(Error_info) raise Exception("See the error information above.") incar_dict = {} with open(os.path.join(cal_loc, "INCAR"), "r") as incar_f: lines = [] for line in incar_f: pairs = line.strip().split("#")[0] pairs = pairs.strip().split("!")[0] if pairs.strip() == "": continue assert pairs.count( "=" ) == 1, "We ask you to set only one tag per line in INCAR, but there are more than one.\nwhere: {}\nline: {}".format( cal_loc, line) pairs = [tag_or_value.strip() for tag_or_value in pairs.split("=")] incar_dict[pairs[0].upper()] = pairs[1] incar_dict.update(new_tags) for remove_tag in remove_tags: if remove_tag in incar_dict.keys(): del incar_dict[remove_tag] if new_tags == {} and remove_tags == []: return incar_dict if isinstance(rename_old_incar, bool): if rename_old_incar: rename_old_incar = find_next_name(cal_loc=cal_loc, orig_name="INCAR")["next_name"] decorated_os_rename(loc=cal_loc, old_filename="INCAR", new_filename=rename_old_incar) #shutil.copyfile(os.path.join(cal_loc, "INCAR"), os.path.join(cal_loc, rename_old_incar)) elif isinstance(rename_old_incar, str): decorated_os_rename(loc=cal_loc, old_filename="INCAR", new_filename=rename_old_incar) #shutil.copyfile(os.path.join(cal_loc, "INCAR"), os.path.join(cal_loc, rename_old_incar)) else: raise Exception( "input argument rename_old_incar of modify_vasp_incar must be either bool or str." ) with open(os.path.join(cal_loc, "INCAR"), "w") as incar_f: for tag, value in sorted(incar_dict.items(), key=lambda key_value_pair: key_value_pair[0]): incar_f.write("{} = {}\n".format(tag, value))
def modify_vasp_incar0(cal_loc, new_tags={}, comment_tags=[], remove_tags=[], rename_old_incar=True): """ add new tags and comment obsolete tags in incar. input arguments: - cal_loc (str): the location of INCAR to be modified, <--required - new_tags (dict): new tags to be added, - comment_tags (list): tags that will be obsolete by commenting them with "#" - remove_tags (list): incar tags that will be removed - rename_old_incar (bool or str): if rename_old_incar is True, rename the old INCAR as INCAR_0, INCAR_1, INCAR_2, etc. if rename_old_incar is False, the old INCAR will be overwritten by new INCAR. if rename_old_incar is a string, rename the old INCAR as the string. Default: True return the valid INCAR dictionary if no modification is made. """ new_tags = {key.upper(): value for key, value in new_tags.items()} comment_tags = [tag.upper() for tag in comment_tags] remove_tags = [tag.upper() for tag in remove_tags] new_incar_tag_name = new_tags.keys() for tag in comment_tags + remove_tags: if tag in new_incar_tag_name: #import pprint print("\n\n**directory: {}".format(cal_loc)) print("**new_tags:") pprint.pprint(new_tags) print("**comment_tags:") pprint.pprint(comment_tags) print("**remove_tags:") pprint.pprint(remove_tags) Error_info = "***You are gonna comment of remove an INCAR tag {} via comment_tags/remove_tags.".format( tag) Error_info += "This contradicts the simultaneous attempt to set {} via new_tags**\n\n".format( tag) print(Error_info) raise Exception("See the error information above.") with open(os.path.join(cal_loc, "INCAR"), "r") as incar_f: lines = [] for line in incar_f: if line.strip() == "": continue pairs = line.strip().split("#")[0] pairs = pairs.strip().split("!")[0] #print(pairs, line) if "#" in line: comments = "#" + "#".join(line.strip().split("#")[1:]) elif "!" in line: comments = "#" + "!".join(line.strip().split("!")[1:]) else: comments = "" for pair in [ pair.strip() for pair in pairs.split(";") if pair.strip() ]: lines.append(pair) if len(comments.strip()) > 1: lines.append(comments) incar = [] for line in lines: if line.startswith("#"): incar.append(line) else: #print(line) key, value = line.split("=") key = key.strip().upper() value = value.strip() if key in remove_tags: continue elif key in comment_tags: incar.append("#" + line) else: incar.append([key, value]) valid_tag_ind_dict = {} for line_ind, line in enumerate(incar): if isinstance(line, list): valid_tag_ind_dict[line[0]] = line_ind for key, value in new_tags.items(): if key in valid_tag_ind_dict.keys(): incar[valid_tag_ind_dict[key]][1] = value else: incar.append([key, value]) #import pprint #pprint.pprint(incar) if new_tags == {} and comment_tags == [] and remove_tags == []: return {item[0]: item[1] for item in incar if isinstance(item, list)} if isinstance(rename_old_incar, bool): if rename_old_incar: rename_old_incar = find_next_name(cal_loc=cal_loc, orig_name="INCAR")["next_name"] decorated_os_rename(loc=cal_loc, old_filename="INCAR", new_filename=rename_old_incar) #shutil.copyfile(os.path.join(cal_loc, "INCAR"), os.path.join(cal_loc, rename_old_incar)) elif isinstance(rename_old_incar, str): decorated_os_rename(loc=cal_loc, old_filename="INCAR", new_filename=rename_old_incar) #shutil.copyfile(os.path.join(cal_loc, "INCAR"), os.path.join(cal_loc, rename_old_incar)) else: raise Exception( "input argument rename_old_incar of modify_vasp_incar must be either bool or str." ) with open(os.path.join(cal_loc, "INCAR"), "w") as incar_f: for line in incar: if isinstance(line, list): incar_f.write("{} = {}\n".format(line[0], line[1])) elif isinstance(line, str): incar_f.write(line + "\n")
def 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 update_running_jobs_status(running_jobs_list, workflow): """ Update jobs's status. for the running jobs, if any errors are detected, change __running__ to __error__ and the error type will be written into __error__. input arguments: - running_jobs_list (list): a list of absolute pathes of running jobs. - workflow: the output of func Parse_calculation_workflow.parse_calculation_workflow """ #Check_after_cal = ["__electronic_divergence__", "__positive_energy__", "__ionic_divergence__"] #Check_on_the_fly = ["__electronic_divergence__", "__positive_energy__"] job_status_str = Job_management.check_jobs_in_queue_system(workflow=workflow, return_a_str=True) #print() #print(get_time_str()) #print(job_status_str) #job_status_str = "" #if job_status_list: # for i in range(1, len(job_status_list)): # job_status_str += job_status_list[i] for job_path in running_jobs_list: find_error = False if Queue_std_files(cal_loc=job_path, workflow=workflow).find_std_files() != [None, None]: #for func Vasp_Error_checker, error_type=["after_cal"] will automatically check errors after cal. #If found, __running__ --> __error__ and the error info will be written into __error__ and return False #If not found, return True if Vasp_Error_checker(error_type=["after_cal"], cal_loc=job_path, workflow=workflow): log_txt_loc, firework_name = os.path.split(job_path) with open(os.path.join(log_txt_loc, "log.txt"), "a") as f: f.write("{} INFO: Calculation successfully finishes at {}\n".format(get_time_str(), firework_name)) f.write("\t\t\t__running__ --> __done__\n") decorated_os_rename(loc=job_path, old_filename="__running__", new_filename="__done__") #os.rename(os.path.join(job_path, "__running__"), os.path.join(job_path, "__done__")) else: #for func Vasp_Error_checker, error_type=["on_the_fly"] will automatically check errors on the fly. #If found, __running__ --> __error__ and the error info will be written into __error__ and return False #If not found, return True Vasp_Error_checker(error_type=["on_the_fly"], cal_loc=job_path, workflow=workflow) if os.path.isfile(os.path.join(job_path, "__running__")): if Queue_std_files(cal_loc=job_path, workflow=workflow).find_std_files() != [None, None]: continue queue_id = Job_management(cal_loc=job_path, workflow=workflow).find_queue_id() #print(queue_id, queue_id in job_status_str) if queue_id not in job_status_str: if not os.path.isfile(os.path.join(cal_loc, "__no_of_times_not_in_queue__")): with open(os.path.join(cal_loc, "__no_of_times_not_in_queue__"), "w") as f: f.write("1") else: with open(os.path.join(cal_loc, "__no_of_times_not_in_queue__"), "r") as f: times = int(next(f).strip()) if times <= 5: with open(os.path.join(cal_loc, "__no_of_times_not_in_queue__"), "w") as f: f.write(str(times+1)) continue log_txt_loc, firework_name = os.path.split(job_path) with open(os.path.join(log_txt_loc, "log.txt"), "a") as f: f.write("{} Queue Error: {}\n".format(get_time_str(), job_path)) f.write("\t\t\tThe running job is not found in queue.\n") f.write("\t\t\t__running__ --> __manual__\n") f.write("\t\t\tCreate file __running_job_not_in_queue__.\n") open(os.path.join(job_path, "__running_job_not_in_queue__"), "w").close() decorated_os_rename(loc=job_path, old_filename="__running__", new_filename="__manual__") #os.rename(os.path.join(job_path, "__running__"), os.path.join(job_path, "__manual__")) else: if os.path.isfile(os.path.join(cal_loc, "__no_of_times_not_in_queue__")): os.remove(os.path.join(cal_loc, "__no_of_times_not_in_queue__"))
def prepare_input_files(cif_filename, mater_cal_folder, current_firework_ind, workflow): """ prepare input files for dft calculations according to the defined firework in workflow at position current_firework_ind """ firework = workflow[current_firework_ind] firework_folder = os.path.join(mater_cal_folder, firework["firework_folder_name"]) if not os.path.isdir(firework_folder): os.mkdir(firework_folder) open(os.path.join(firework_folder, "__vis__"), "w").close() with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f: f.write( "\n\n***************************************************************************************\n" ) f.write( "***************************************************************************************\n" ) f.write("{} INFO: create sub-folder {} under {}\n".format( get_time_str(), firework["firework_folder_name"], mater_cal_folder)) f.write("\t\t\tcreate __vis__ under this sub-folder.\n") if os.path.isfile(os.path.join(firework_folder, "__vis__")): #print(firework_folder) write_kpoints = False if workflow[current_firework_ind]["extra_copy"]: with open(os.path.join(mater_cal_folder, 'log.txt'), "a") as f: f.write("{} INFO: extra copy to dst {}\n".format( get_time_str(), firework_folder)) for file in workflow[current_firework_ind]["extra_copy"]: filename = os.path.split(file)[1] shutil.copyfile(src=file, dst=os.path.join(firework_folder, filename)) f.write("\t\t{}\n".format(file)) if current_firework_ind == 0: Write_MPRelax_vasp_input_set( cif_filename=cif_filename, where_to_write=firework_folder, sort_structure=workflow[0]["sort_structure"], force_gamma=workflow[0]["force_gamma"]) write_kpoints = True with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f: f.write("{} INFO: VASP input sets generated by ".format( get_time_str())) f.write("pymatgen.io.vasp.sets.MPRelaxSet under folder {}\n". format(firework["firework_folder_name"])) if workflow[0]["sort_structure"] == False: f.write( "\t\t\tsort_structure is off, so POSCAR generated by pymatgen is overwritten by the copy below\n" ) f.write("\t\t\tsrc: {}\n".format(cif_filename)) f.write("\t\t\tdst: {}\n".format( os.path.join(firework_folder, "POSCAR"))) #if workflow[0]["2d_system"]: # modify_vasp_kpoints_for_2D(cal_loc=firework_folder, kpoints_type=workflow[0]["kpoints_type"], rename_old_kpoints="KPOINTS.pymatgen") # with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f: # f.write("{} INFO: Because it is a 2D system, KPONITS is modified so that K_z = 0 for all kpoints\n".format(get_time_str())) # f.write("\t\t\tKPOINTS --> KPOINTS.pymatgen\n") else: copy_files = firework["copy_from_prev_cal"] move_files = firework["move_from_prev_cal"] contcar_to_poscar = firework["contcar_to_poscar"] src_step_name = "step_{}_".format(firework["copy_which_step"]) for src_firework in workflow: if src_step_name in src_firework["firework_folder_name"]: break src_dir = os.path.join(mater_cal_folder, src_firework["firework_folder_name"]) non_existent_files = copy_and_move_files( src_dir=src_dir, dst_dir=firework_folder, copy_files=copy_files, move_files=move_files, contcar_to_poscar=contcar_to_poscar) with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f: f.write( "{} INFO: copy and move files from src folder to dst\n". format(get_time_str())) f.write("\t\t\tsrc: {}\n".format(src_dir)) f.write("\t\t\tdst: {}\n".format(firework_folder)) if copy_files: f.write("\t\t\tcopy files:") [f.write("{}\t".format(file_)) for file_ in copy_files] f.write("\n") if non_existent_files["copy_files"]: f.write( "Error: fail to copy files below because they are not existent:" ) [ f.write("{}\t".format(file_)) for file_ in non_existent_files["copy_files"] ] if move_files: f.write("\t\tmove files:") [f.write("{}\t".format(file_)) for file_ in move_files] f.write("\n") if non_existent_files["move_files"]: f.write( "Error: \t\tfail to move files below because they are not existent:" ) [ f.write("{}\t".format(file_)) for file_ in non_existent_files["copy_files"] ] if contcar_to_poscar: f.write("\t\trename CONTCAR as POSCAR under dst folder\n") new_incar_tags = firework["new_incar_tags"] comment_incar_tags = firework["comment_incar_tags"] remove_incar_tags = firework["remove_incar_tags"] #print(new_incar_tags, comment_incar_tags, remove_incar_tags) if new_incar_tags or comment_incar_tags or remove_incar_tags: if current_firework_ind == 0: modify_vasp_incar( cal_loc=firework_folder, new_tags=new_incar_tags, comment_tags=comment_incar_tags, rename_old_incar="INCAR.pymatgen", remove_tags=remove_incar_tags, ) else: modify_vasp_incar(cal_loc=firework_folder, new_tags=new_incar_tags, comment_tags=comment_incar_tags, remove_tags=remove_incar_tags) with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f: f.write("{} INFO: modify INCAR:\n".format(get_time_str())) if new_incar_tags: f.write("\t\tnew incar tags:\n") [ f.write("\t\t\t{}={}\n".format(key_, value_)) for key_, value_ in new_incar_tags.items() ] if comment_incar_tags: f.write("\t\tcomment incar tags:") [ f.write("{}\t".format(tag_)) for tag_ in comment_incar_tags ] f.write("\n") if remove_incar_tags: f.write("\t\tremove incar tags: ") [ f.write("{}\t".format(tag_)) for tag_ in remove_incar_tags ] f.write("\n") if not os.path.isfile(os.path.join(firework_folder, "KPOINTS")): if firework["kpoints_type"] == "Line-mode": Write_line_mode_KPOINTS( cal_loc=firework_folder, structure_filename=os.path.join(firework_folder, "POSCAR"), intersections=firework["intersections"], twoD_system=workflow[0]["2d_system"]) with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f: f.write( "{} INFO: write KPOINTS in the line mode based on pymatgen.symmetry.bandstructure.HighSymmKpath\n" .format(get_time_str())) elif firework["kpoints_type"] == "MPNonSCFSet_uniform": Write_NONSCF_KPOINTS( structure_filename=os.path.join(firework_folder, "POSCAR"), mode="uniform", reciprocal_density=firework["reciprocal_density"]) write_kpoints = True elif firework["kpoints_type"] == 'MPNonSCFSet_line': Write_NONSCF_KPOINTS( structure_filename=os.path.join(firework_folder, "POSCAR"), mode="line", kpoints_line_density=firework["kpoints_line_density"]) write_kpoints = True elif firework["kpoints_type"] == "MPRelaxSet" and firework[ "step_no"] != 1: Write_MPRelax_KPOINTS(structure_filename=os.path.join( firework_folder, "POSCAR"), force_gamma=workflow[0]["force_gamma"]) write_kpoints = True elif firework["kpoints_type"] == "MPStaticSet": Write_MPStatic_KPOINTS(structure_filename=os.path.join( firework_folder, "POSCAR"), force_gamma=workflow[0]["force_gamma"]) write_kpoints = True if write_kpoints and workflow[0]["2d_system"]: new_name = modify_vasp_kpoints_for_2D( cal_loc=firework_folder, kpoints_type=firework["kpoints_type"], rename_old_kpoints="KPOINTS.pymatgen_" + firework["kpoints_type"]) if write_kpoints: with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f: f.write("{} INFO: use pymatgen.io.vasp.{} ".format( get_time_str(), firework["kpoints_type"])) f.write("to write KPOINTS under {}\n".format( firework["firework_folder_name"])) if workflow[0]["2d_system"]: f.write( "{} INFO: Because it is a 2D system, KPOINTS is modified so that K_z = 0 for all kponits\n" .format(get_time_str())) f.write("\t\t\tKPOINTS --> {}\n".format(new_name)) if abs(firework["denser_kpoints"] - 1) > 1.0e-4: new_name = modify_vasp_kpoints_for_2D( cal_loc=firework_folder, kpoints_type="automatic", rename_old_kpoints="KPOINTS.sparse", denser_kpoints=firework["denser_kpoints"]) with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f: f.write( "{} INFO: for {}, tag denser_kpoints has been set to {}\n". format(get_time_str(), firework["firework_folder_name"], firework["denser_kpoints"])) f.write("\t\t\tChange KPOINTS according to denser_kpoints\n") f.write("\t\t\told KPOINTS --> {}\n".format(new_name)) if workflow[current_firework_ind]["final_extra_copy"]: with open(os.path.join(mater_cal_folder, 'log.txt'), "a") as f: f.write("{} INFO: final extra copy to dst {}\n".format( get_time_str(), firework_folder)) for file in workflow[current_firework_ind]["final_extra_copy"]: filename = os.path.split(file)[1] shutil.copyfile(src=file, dst=os.path.join(firework_folder, filename)) f.write("\t\t{}\n".format(file)) if os.path.isfile(os.path.join(firework_folder, "__manual__")): os.remove(os.path.join(firework_folder, "__vis__")) with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f: f.write("{} INFO: {}\n".format( get_time_str(), firework["firework_folder_name"])) f.write( "\t\t\t__manual__ has been created during the preparation of VASP input files.\n" ) f.write("\t\t\tMust be handled manually.\n") f.write("\t\t\tremove __vis__\n") elif os.path.isfile(os.path.join(firework_folder, "__prior_ready__")): os.remove(os.path.join(firework_folder, "__vis__")) with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f: f.write("{} INFO: {}\n".format( get_time_str(), firework["firework_folder_name"])) f.write("\t\t\tAll VASP input files are ready.\n") f.write( "\t\t\t__prior_ready__ has been found. So this calculation will be submitted earlier than those labelled by __ready__\n" ) f.write("\t\t\tremove __vis__\n") else: decorated_os_rename(loc=firework_folder, old_filename="__vis__", new_filename="__ready__") #os.rename(os.path.join(firework_folder, "__vis__"), os.path.join(firework_folder, "__ready__")) with open(os.path.join(mater_cal_folder, "log.txt"), "a") as f: f.write( "{} INFO: All VASP input files are ready at {}\n".format( get_time_str(), firework["firework_folder_name"])) f.write("\t\t\t__vis__ --> __ready__\n")