def setup(self, initdir, settings): """ mv all files and directories (besides initdir) into initdir """ infilename = settings["infilename"] print "Moving files into initial run directory:", initdir initdir = os.path.abspath(initdir) for p in os.listdir(self.relaxdir): if (p in ([infilename] + self.settings["extra_input_files"])) and ( os.path.join(self.relaxdir, p) != initdir): os.rename(os.path.join(self.relaxdir, p), os.path.join(initdir, p)) print "" sys.stdout.flush() # Keep a backup copy of the base Infile shutil.copyfile(os.path.join(initdir, infilename), os.path.join(self.relaxdir, infilename + ".base")) # If an initial infile is called for, copy it in and set the appropriate flag if (self.settings["initial"] != None) and (os.path.isfile( os.path.join(self.relaxdir, self.settings["initial"]))): new_values = qeio.Infile( os.path.join(self.relaxdir, self.settings["initial"])).tags qeio.set_infile_tag(new_values, infilename, initdir) print " Set Infile tags:", new_values, "\n" sys.stdout.flush()
def run(self): """ Perform a series of quantum espresso jobs to relax a structure. Performs a series of quantum espresso calculations until convergence is reached according to the criteria in 'status()'. Then performs a final constant volume run """ print "Begin Quantum Espresso relaxation run" sys.stdout.flush() # get current status of the relaxation: (status, task) = self.status() print "\n++ status:", status, " next task:", task sys.stdout.flush() infilename = self.settings["infilename"] outfilename = self.settings["outfilename"] while status == "incomplete": if task == "setup": self.add_rundir() self.setup(self.rundir[-1], self.settings) elif task == "relax": self.add_rundir() quantumespresso.continue_job(self.rundir[-2], self.rundir[-1], self.settings) elif task == "constant": self.add_rundir() quantumespresso.continue_job(self.rundir[-2], self.rundir[-1], self.settings) # set Infile to calculation = relax if (self.settings["final"] != None) and (os.path.isfile( os.path.join(self.relaxdir, self.settings["final"]))): new_values = qeio.Infile( os.path.join(self.relaxdir, self.settings["final"])).tags else: new_values = {"calculation": "'relax'"} # set Infile title tag to denote 'final' if qeio.get_infile_tag("title", infilename, self.rundir[-1]) is None: new_values["title"] = "'final'" else: new_values["title"] = "'{}'".format( qeio.get_infile_tag("title", self.rundir[-1]) + " final") qeio.set_infile_tag(new_values, infilename, self.rundir[-1]) print " Set Infile tags:", new_values, "\n" sys.stdout.flush() else: # probably hit walltime self.add_rundir() quantumespresso.continue_job(self.rundir[-2], self.rundir[-1], self.settings) while True: # run quantum espresso result = quantumespresso.run( infilename, outfilename, self.rundir[-1], command=self.settings["qe_cmd"], ncpus=self.settings["ncpus"], err_types=self.settings["err_types"]) # if no errors, continue if result == None or self.not_converging(): break # else, attempt to fix first error self.add_errdir() os.mkdir(self.rundir[-1]) # self.add_rundir() err = result.itervalues().next() print "\n++ status:", "error", " next task:", "fix_error" sys.stdout.flush() print "Attempting to fix error:", str(err) err.fix(self.errdir[-1], self.rundir[-1], self.settings) print "" sys.stdout.flush() if (self.settings["backup"] != None) and len(self.rundir) > 1: print "Restoring from backups:" for f in self.settings["backup"]: if os.path.isfile( os.path.join(self.rundir[-2], f + "_BACKUP.gz")): f_in = gzip.open( os.path.join(self.rundir[-2], f + "_BACKUP.gz", 'rb')) f_out = open(os.path.join(self.rundir[-1], f, 'wb')) f_out.write(f_in.read()) f_in.close() f_out.close() print f, " restored!" sys.stdout.flush() (status, task) = self.status() print "\n++ status:", status, " next task:", task sys.stdout.flush() if status == "complete": if not os.path.isdir(self.finaldir): # mv final results to relax.final print "mv", os.path.basename( self.rundir[-1]), os.path.basename(self.finaldir) sys.stdout.flush() os.rename(self.rundir[-1], self.finaldir) self.rundir.pop() quantumespresso.complete_job(self.finaldir, self.settings) return (status, task)
def continue_job(jobdir, contdir, settings): # def continue_job(jobdir,\ # contdir,\ # move = io.DEFAULT_VASP_MOVE_LIST,\ # copy = io.DEFAULT_VASP_COPY_LIST,\ # remove = io.DEFAULT_VASP_REMOVE_LIST,\ # compress = [], backup = []): """Use the files in vasp job directory 'jobdir', to setup a vasp job in directory 'contdir'. Args: jobdir: path to current job directory contdir: path to new directory to continue the job Settings: copy: Files copied from 'jobdir' to 'contdir' It also copies either CONTCAR, or if that does not exist POSCAR. move: Files moved from 'jobdir' to 'contdir' keep: Files (along with those in 'copy') to keep in 'jobdir'. The rest are removed. Do not include "POSCAR" or "CONTCAR" in 'move' or 'copy'. jobdir/CONTCAR is copied to contdir/POSCAR, unless it does not exist, in which case jobdir/POSCAR is copied to contdir/POSCAR. jobdir/POSCAR and jobdir/CONTCAR are always kept. """ print "Continue Quantum Espresso job:\n Original: " + jobdir + "\n Continuation: " + contdir sys.stdout.flush() infilename = settings["infilename"] outfilename = settings["outfilename"] # remove duplicates move = list(set(settings['move'] + settings['extra_input_files'])) copy = list(set(settings['copy'] + [infilename])) remove = list(set(settings['remove'])) compress = list(set(settings['compress'])) backup = list(set(settings['backup'])) # Check that necessary files are being moved/copied if not infilename in (move + copy): warnings.warn( "Warning: Infile not found in either 'move' or 'copy'. Copying " + infilename + " by default", QuantumEspressoWarning) copy += [infilename] # Check that the user isn't being contradictory or silly for f in move: if f in remove: warnings.warn( "Warning: %s found in both 'move' and 'remove'. The file will not be removed." % f, QuantumEspressoWarning) remove = list(set(remove) - set([f])) if f in copy: warnings.warn( "Warning: %s found in both 'move' and 'copy'. The file will be copied only." % f, QuantumEspressoWarning) move = list(set(move) - set([f])) if f in compress: raise QuantumEspressoError( "Error in casm.quantumespresso.continue_job(). %s found in both 'move' and 'compress', but these options contradict. Did you mean 'backup'?" % f) for f in copy: if re.match(".*.wfc.*", f) or re.match(".*.igk.*", f): warnings.warn( "Warning: %s can be rather huge. It is suggested to include %s in 'move', rather than 'copy'. If you're worried about corruption due to interrupted runs, add %s to 'backup' as well." % (f, f, f), QuantumEspressoWarning) if f in remove: warnings.warn( "Warning: %sfound in 'copy' and 'remove', which is the same as 'move'." % f, QuantumEspressoWarning) move += f copy = list(set(copy) - set([f])) remove = list(set(copy) - set([f])) if f in compress: warnings.warn( "Warning: %s found in 'copy' and 'compress'. It is suggested to include %s in 'move' and 'backup' instead." % (f, f), QuantumEspressoWarning) if f in backup: warnings.warn( "Warning: %s found in 'copy' and 'backup'. This will result in three copies of your file being made (old, old_BACKUP.gz, and copy)!" % f, QuantumEspressoWarning) for f in remove: if f in compress: warnings.warn( "Warning: %s found in both 'compress' and 'remove'. Defaulting to 'compress' only!" % f, QuantumEspressoWarning) remove = list(set(remove) - set([f])) for f in compress: if f in backup: warnings.warn( "Warning: %s found in 'compress' and 'backup'. Defaulting to ompressing only!" % f, QuantumEspressoWarning) backup = list(set(backup) - set([f])) for f in backup: if (f not in move) and (f in remove): warnings.warn( "Warning: 'backup' is meant for files being moved, but %s is found under 'remove' only. Did you maybe mean 'compress'?", QuantumEspressoWarning) elif (f not in move): warnings.warn( "Warning: %s not found in 'move', so you'll just end up with 2 copies of the file..." % f, QuantumEspressoWarning) # make the new contdir try: os.mkdir(contdir) except: pass # make compressed backups of files sensitive to corruption print " backup:" for file in backup: if os.path.isfile(os.path.join(jobdir, file)): print file, # Open target file, target file.gz f_in = open(os.path.join(jobdir, file), 'rb') f_out = gzip.open(os.path.join(jobdir, file) + '_BACKUP.gz', 'wb') # Compress, close files f_out.writelines(f_in) f_out.close() f_in.close() print "" # move files print " mv:", for file in move: print file, os.rename(os.path.join(jobdir, file), os.path.join(contdir, file)) print "" # copy files print " cp:", for file in copy: print file, shutil.copyfile(os.path.join(jobdir, file), os.path.join(contdir, file)) print "" # Rewrite new positions into infile if necessary if os.path.isfile(os.path.join(jobdir, outfilename)) and os.path.isfile( os.path.join(contdir, infilename)): postpos = qeio.Poscar(os.path.join(jobdir, outfilename)) newinfile = qeio.Infile(os.path.join(contdir, infilename)) newinfile.rewrite_poscar_info(postpos) newinfile.write(os.path.join(contdir, infilename)) print "Overwrote " + infilename + " positions and lattice with positions and lattice from " + outfilename else: print " no calculated positions to overwrite" # remove files print " rm:", for file in remove: if os.path.isfile(os.path.join(jobdir, file)): print file, os.remove(os.path.join(jobdir, file)) print "" # compress files print " gzip:", for file in compress: if os.path.isfile(os.path.join(jobdir, file)): print file, # Open target file, target file.gz f_in = open(os.path.join(jobdir, file), 'rb') f_out = gzip.open(os.path.join(jobdir, file) + '.gz', 'wb') # Compress, close files f_out.writelines(f_in) f_out.close() f_in.close() # Remove original target file os.remove(os.path.join(jobdir, file)) print "" print "" sys.stdout.flush()