def __init__(self, configdir=None, auto = True, sort = True): """ Construct a VASP relaxation job object. Args: configdir: path to configuration auto: True if using pbs module's JobDB to manage pbs jobs """ if configdir == None: configdir = os.getcwd() print "Reading CASM settings" self.casm_settings = casm.casm_settings(configdir) if self.casm_settings == None: raise vaspwrapper.VaspWrapperError("Not in a CASM project. The file '.casm' directory was not found.") print "Constructing a CASM VASPWrapper Relax object" sys.stdout.flush() print " Setting up directories" sys.stdout.flush() # store path to .../config, if not existing raise self.configdir = os.path.abspath(configdir) if not os.path.isdir(self.configdir): raise vasp.VaspError("Error in casm.vasp.relax: Did not find directory: " + self.configdir) sys.stdout.flush() # store path to .../config/calctype.name, and create if not existing self.calcdir = os.path.join(self.configdir, self.casm_settings["curr_calctype"]) try: os.mkdir(self.calcdir) except: pass # read the settings json file print " Reading relax.json settings file" sys.stdout.flush() setfile = casm.settings_path("relax.json",self.casm_settings["curr_calctype"],self.configdir) if setfile == None: raise vaspwrapper.VaspWrapperError("Could not find .../settings/" + self.casm_settings["curr_calctype"] + "/relax.json file.") sys.stdout.flush() self.settings = vaspwrapper.read_settings(setfile) # add required keys to settings if not present if not "ncore" in self.settings: self.settings["ncore"] = None if not "npar" in self.settings: self.settings["npar"] = None if not "kpar" in self.settings: self.settings["kpar"] = None if not "vasp_cmd" in self.settings: self.settings["vasp_cmd"] = None if not "ncpus" in self.settings: self.settings["ncpus"] = None if not "run_limit" in self.settings: self.settings["run_limit"] = None self.auto = auto self.sort = sort print "VASP Relax object constructed\n" sys.stdout.flush()
def submit(self): """Submit a PBS job for this VASP relaxation""" # first, check if the job has already been submitted and is not completed db = pbs.JobDB() print "rundir", self.calcdir id = db.select_regex_id("rundir", self.calcdir) print "id:", id sys.stdout.flush() if id != []: for j in id: job = db.select_job(j) # taskstatus = ["Incomplete","Complete","Continued","Check","Error:.*","Aborted"] # jobstatus = ["C","Q","R","E","W","H","M"] if job["jobstatus"] != "C": print "JobID:", job["jobid"], " Jobstatus:", job["jobstatus"], " Not submitting." sys.stdout.flush() return #elif job["taskstatus"] in ["Complete", "Check"] or re.match( "Error:.*", job["taskstatus"]): # print "JobID:", job["jobid"], " Taskstatus:", job["taskstatus"], " Not submitting." # sys.stdout.flush() # return # second, only submit a job if relaxation status is "incomplete" # construct the Relax object relaxation = vasp.Relax(self.calcdir, self.run_settings()) # check the current status (status, task) = relaxation.status() if status == "complete": print "Status:", status, " Not submitting." sys.stdout.flush() # ensure job marked as complete in db if self.auto: for j in id: job = db.select_job(j) if job["taskstatus"] == "Incomplete": try: pbs.complete_job(jobid=j) except (pbs.PBSError, pbs.JobDBError, pbs.EligibilityError) as e: print str(e) sys.stdout.flush() # ensure results report written if not os.path.isfile(os.path.join(self.calcdir, "properties.calc.json")): self.report() return elif status == "not_converging": print "Status:", status, " Not submitting." sys.stdout.flush() return elif status != "incomplete": raise vaspwrapper.VaspWrapperError("unexpected relaxation status: '" + status + "' and task: '" + task + "'") sys.stdout.flush() return print "Preparing to submit a VASP relaxation PBS job" sys.stdout.flush() # cd to configdir, submit jobs from configdir, then cd back to currdir currdir = os.getcwd() os.chdir(self.calcdir) # determine the number of atoms in the configuration print " Counting atoms in the POSCAR" sys.stdout.flush() pos = vasp.io.Poscar(os.path.join(self.configdir,"POS")) N = len(pos.basis) print " Constructing a PBS job" sys.stdout.flush() # construct a pbs.Job job = pbs.Job(name=casm.jobname(self.configdir),\ account=self.settings["account"],\ nodes=int(math.ceil(float(N)/float(self.settings["atom_per_proc"])/float(self.settings["ppn"]))),\ ppn=int(self.settings["ppn"]),\ walltime=self.settings["walltime"],\ pmem=self.settings["pmem"],\ qos=self.settings["qos"],\ queue=self.settings["queue"],\ message=self.settings["message"],\ email=self.settings["email"],\ priority=self.settings["priority"],\ command="python -c \"import casm.vaspwrapper; casm.vaspwrapper.Relax('" + self.configdir + "').run()\"",\ auto=self.auto) print " Submitting" sys.stdout.flush() # submit the job job.submit() # return to current directory os.chdir(currdir) print "CASM VASPWrapper relaxation PBS job submission complete\n" sys.stdout.flush()
def run(self): """ Setup input files, run a vasp relaxation, and report results """ # construct the Relax object relaxation = vasp.Relax(self.calcdir, self.run_settings()) # check the current status (status, task) = relaxation.status() if status == "complete": print "Status:", status sys.stdout.flush() # mark job as complete in db if self.auto: try: pbs.complete_job() except (pbs.PBSError, pbs.JobDBError, pbs.EligibilityError) as e: print str(e) sys.stdout.flush() # write results to output.VASP self.report() return elif status == "not_converging": print "Status:", status print "Returning" sys.stdout.flush() return elif status == "incomplete": if task == "setup": self.setup() (status, task) = relaxation.run() else: raise vaspwrapper.VaspWrapperError("unexpected relaxation status: '" + status + "' and task: '" + task + "'") sys.stdout.flush() # once the run is done, update database records accordingly if status == "not_converging": # mark error if self.auto: try: pbs.error_job("Not converging") except (pbs.PBSError, pbs.JobDBError) as e: print str(e) sys.stdout.flush() print "Not Converging!" sys.stdout.flush() # print a local settings file, so that the run_limit can be extended if the # convergence problems are fixed try: os.makedirs(os.path.join(self.configdir, "settings", self.casm_settings["curr_calctype"])) except: pass settingsfile = os.path.join(self.configdir, "settings", self.casm_settings["curr_calctype"], "relax.json") vaspwrapper.write_settings(self.settings, settingsfile) print "Writing:", settingsfile print "Edit the 'run_limit' property if you wish to continue." sys.stdout.flush() return elif status == "complete": # mark job as complete in db if self.auto: try: pbs.complete_job() except (pbs.PBSError, pbs.JobDBError, pbs.EligibilityError) as e: print str(e) sys.stdout.flush() # write results to output.VASP self.report() else: raise vaspwrapper.VaspWrapperError("vasp relaxation complete with unexpected status: '" + status + "' and task: '" + task + "'") sys.stdout.flush()
def __init__(self, configdir=None, auto=True, sort=True): """ Construct a VASP relaxation job object. Arguments ---------- configdir: str, optional, default=None Path to configuration directory. If None, uses the current working directory auto: boolean, optional, default=True, Use True to use the pbs module's JobDB to manage pbs jobs sort: boolean, optional, default=True, Use True to sort atoms in POSCAR by type """ print "Construct a casm.vaspwrapper.Relax instance:" if configdir is None: configdir = os.getcwd() print " Input directory:", configdir # get the configname from the configdir path _res = os.path.split(configdir) self.configname = os.path.split(_res[0])[1] + "/" + _res[1] print " Configuration:", self.configname print " Reading CASM settings" self.casm_directories = casm.project.DirectoryStructure(configdir) self.casm_settings = casm.project.ProjectSettings(configdir) if self.casm_settings is None: raise vaspwrapper.VaspWrapperError( "Not in a CASM project. The file '.casm' directory was not found." ) if os.path.abspath(configdir) != self.configdir: print "" print "input configdir:", configdir print "determined configname:", self.configname print "expected configdir given configname:", self.configdir raise vaspwrapper.VaspWrapperError( "Mismatch between configname and configdir") # fixed to default_clex for now self.clex = self.casm_settings.default_clex # store path to .../config/calctype.name, and create if not existing self.calcdir = self.casm_directories.calctype_dir( self.configname, self.clex) try: os.mkdir(self.calcdir) except: pass print " Calculations directory:", self.calcdir # read the settings json file print " Reading relax.json settings file" sys.stdout.flush() setfile = self.casm_directories.settings_path_crawl( "relax.json", self.configname, self.clex) if setfile is None: raise vaspwrapper.VaspWrapperError( "Could not find \"relax.json\" in an appropriate \"settings\" directory" ) sys.stdout.flush() else: print " Read settings from:", setfile self.settings = vaspwrapper.read_settings(setfile) # set default settings if not present if not "ncore" in self.settings: self.settings["ncore"] = None if not "npar" in self.settings: self.settings["npar"] = None if not "kpar" in self.settings: self.settings["kpar"] = None if not "vasp_cmd" in self.settings: self.settings["vasp_cmd"] = None if not "ncpus" in self.settings: self.settings["ncpus"] = None if not "run_limit" in self.settings: self.settings["run_limit"] = None if not "prerun" in self.settings: self.settings["prerun"] = None if not "postrun" in self.settings: self.settings["postrun"] = None self.auto = auto self.sort = sort print " DONE\n" sys.stdout.flush()