def setup_train(self, trainingRoot, species): from os import path, remove from glob import glob from aBuild.calculators.vasp import VASP from aBuild.fitting.mtp import MTP from aBuild.jobs import Job from aBuild.database.dataset import dataset # 1. Pull all VASP data and compile into file train.cfg # 2. Copy/Build a blank potential file called pot.mtp # 3. Build a submission script with chdir(trainingRoot): enumdirs = glob("E.*") # activedirs = [] activedirs = glob("A.*") #puredirs = glob("pure*") dirs = [path.join(trainingRoot, x) for x in enumdirs + activedirs] if dirs != []: print('Building dataset') trainingSet = dataset(dirs, species, calculator='VASP') ##### if path.isfile(path.join(self.root, 'train.cfg')): msg.info( 'train.cfg file found! Deleting and building from scratch.') remove(path.join(self.root, 'train.cfg')) with open(path.join(self.root, 'train.cfg'), 'a+') as f: for crystal in trainingSet.crystals: if crystal.results["fEnth"] < 100 and crystal.minDist > 1.5: print("Building: {}".format(crystal.title)) f.writelines('\n'.join(crystal.lines('mtptrain'))) else: print( "Not adding structure {}. Seems like an extreme one.". format(crystal.title)) print("Energy: {}".format(crystal.results["energyF"])) print("MinDist: {}".format(crystal.minDist)) self.write_blank_pot(len(species)) self.train(self.settings["execution"])
def read(context, yfile): """Reads in the specified YAML file, following any additional file directives to compile a full representation of the template hierarchy for the root file. Args: context (str): path to the root folder where the yaml file is located. Needed for relative paths of file links. yfile (str): name of the template YAML file *relative* to `context`. Should *not* include the `.yaml` or `.yml` extension. """ with chdir(context): if yfile[0] == ":": root = path.abspath(yfile[1:]) else: root = path.abspath(yfile) if path.isfile(root + ".yml"): target = root + ".yml" else: emsg = ("The specified template file '{}' was not found relative " "to the given context directory ('{}'). Note that all files" " should use the `.yml` extension, *not* `.yaml`.") raise ValueError(emsg.format(yfile, context)) with open(target, 'r') as stream: result = yaml.load(stream) #Determine the new context for recursive file links within the values of #this file. ncontext = path.dirname(target) #The specification allows for a "local" context that describes folder #locations for specific items within the template. lcontext = None if isinstance(result, dict) and "context" in result: lcontext = result["context"] del result["context"] #The unpacking command will mutate the values in result so that file links #are expanded to be full-fledged python objects from their YAML files. _unpack_obj(ncontext, result, lcontext) return result
def _unpack_obj(context, obj, lcontext=None): """Unpacks each item of the specified object recursively so that all dictionary values are visited and all list items are also visited. .. warning:: `obj` will be mutated if any value it considers turns out to be a link (according to :func:`is_link`). In that case, the file descriptor will be placed by the actual contents of the YAML file that the link points to. Args: context (str): path to the root folder where the yaml file is located. Needed for relative paths of file links. lcontext (dict): local context for the items in `obj`. Keys are the names of keys in `obj`; values are relative folder paths that should be used as the context for reads within that item. """ if isinstance(obj, dict): result = obj for k, o in obj.items(): ncontext = context #If the template specifies a relative context for this item, #then switch out the context for all of its children. if lcontext is not None and k in lcontext: with chdir(context): ncontext = path.abspath(lcontext[k]) if is_link(o): result[k] = read(ncontext, o) else: result[k] = _unpack_obj(ncontext, o) elif isinstance(obj, (list, set, tuple)): result = [] for o in obj: if is_link(o): result.append(read(context, o)) else: result.append(_unpack_obj(context, o)) else: result = obj return result
def read_results(self, allElectronic = False, allIonic=False): if self.directory is not None and self.status() in ['done','unconverged']: with chdir(self.directory): self.crystal.results = {} self.crystal.results["warning"] = False self.crystal.results["energyF"],self.crystal.results["energyZ"] = self.read_energy(allElectronic=allElectronic) self.crystal.results["forces"] = self.read_forces(allIonic=allIonic) self.crystal.results["stress"] = self.read_stress() #self.POTCAR = POTCAR.from_POTCAR() self.crystal.results["species"] = self.POTCAR.species self.crystal.results["energypatom"] = self.crystal.results["energyF"]/self.crystal.nAtoms if abs(self.crystal.results["energyF"]) > 1000: self.crystal.results["warning"] = True if 'pure' not in self.directory: self.crystal.results["fEnth"] = self.formationEnergy else: self.crystal.results["fEnth"] = 0 else: print(self.status(), 'not reading results') self.crystal.results = None msg.info("Unable to extract necessary information from directory! ({})".format(self.directory))
def statusReport(self): from os import path, listdir, remove from glob import glob from aBuild.calculators.vasp import VASP from aBuild.calculators.aflow import AFLOW from numpy import argsort trainingRoot = path.join(self.root, 'validation_set') with chdir(trainingRoot): enumdirs = glob("E.*") activedirs = glob("A.*") delFiles = glob("status.*") for i in delFiles: remove(i) dirs = [path.join(trainingRoot, x) for x in enumdirs + activedirs] nDirs = len(dirs) numdirs = [int(y.split('.')[-1]) for y in dirs] count = 0 for idx, directory in enumerate([dirs[x] for x in argsort(numdirs)]): if count % 100 == 0: print("checking directories {} - {}".format( dirs[argsort(numdirs)[count + 1]], dirs[argsort(numdirs)[count + 100 if count + 100 < nDirs else nDirs - 1]])) count += 1 if 'aflow.in' in listdir(directory): thisAFLOW = AFLOW.from_path(directory, self.species) thisStat = thisAFLOW.status() else: thisVASP = VASP.from_path(directory, self.species) thisStat = thisVASP.status() if thisStat == 'errors' or thisStat == 'running': msg.info("Directory {} is {} ".format(directory, thisStat)) with open('status.' + thisStat, 'a') as f: f.write(directory.split('/')[-1] + ' ')
def buildFolders(self, buildpath, calculator, runGetKpoints=True, foldername='A', onlyCloseToHull=False, distToHull=5e-3): from os import path from aBuild.calculators.vasp import VASP from aBuild.calculators.aflow import AFLOW from aBuild.calculators.lammps import LAMMPS from aBuild.calculators.espresso import ESPRESSO from aBuild.jobs import Job from math import floor import os print("Building folders in {}".format(buildpath)) if not path.isdir(buildpath): os.mkdir(buildpath) print('Made path:', buildpath) configIndex = startPoint = self.starting_point(buildpath) lookupCalc = { 'aflow': lambda specs: AFLOW.from_dictionary(specs), 'vasp': lambda specs: VASP.from_dictionary(specs), 'qe': lambda specs: ESPRESSO(specs, self.species), 'lammps': lambda specs: LAMMPS(specs, self.species) } lookupBuild = { 'aflow': lambda obj: obj.buildFolder(), 'vasp': lambda obj: obj.buildFolder(runGetKPoints=runGetKpoints), 'qe': lambda obj: obj.buildFolder(), 'lammps': lambda obj: obj.buildFolder() } for crystal in self.crystals: if onlyCloseToHull: if crystal.results["distToHull"] is None: msg.fatal( "You asked only for cystals that are close to the hull, but I don't have a value for that distance." ) elif crystal.results["distToHull"] > distToHull: continue print("Building crystal {}".format(crystal.title)) runpath = path.join(buildpath, foldername + ".{}".format(configIndex)) #Augment the existing dictionary in preparation for sending it in calculator[calculator["active"]]["crystal"] = crystal calculator[calculator["active"]]["directory"] = runpath # Initialize the calculation object print('initializing VASP object') thisCalc = lookupCalc[calculator["active"]]( calculator[calculator["active"]]) # Build the path if not path.isdir(runpath): os.mkdir(runpath) else: msg.fatal( "I'm gonna write over top of a current directory. ({}) I think I'll stop instead." .format(runpath)) # Change the directory and build the folder print("Building folder for structure: {}".format(crystal.title)) with chdir(runpath): success = lookupBuild[calculator["active"]](thisCalc) if not success: if calculator["active"] == 'aflow': retryCalc = lookupCalc["vasp"](calculator['vasp']) with chdir(runpath): success = lookupBuild["vasp"](retryCalc) if not success: msg.fatal( "I tried building an aflow dir and it failed, then I tried building a VASP dir and it failed too. I give up" ) else: msg.warn( "VASP(??) directory build failed, and I'm not sure why" ) configIndex += 1 # Build the submission script exdir = path.join(buildpath, 'A.') if calculator['active'] == 'aflow': calculator["execution"]["exec_path"] = "aflow --run" elif calculator["active"] == 'vasp': calculator["execution"]["exec_path"] = "vasp6_serial" startAdder = int(floor(startPoint / 1000)) * 1000 endAdder = int(floor((configIndex - 1) / 1000)) * 1000 if startAdder == endAdder: # Don't need to submit two jobs in this case. Just one, but we might have to add an offset if the numbers are too high. msg.info("Building one job submission file") calculator["execution"]["offset"] = startAdder mljob = Job(calculator["execution"], exdir, calculator["execution"]["exec_path"], arrayStart=startPoint - startAdder, arrayEnd=configIndex - 1 - endAdder) with chdir(buildpath): print('Building job file') mljob.write_jobfile('jobscript_vasp.sh') else: # We're going to have to submit two jobs to span the whole job array. msg.info("Building two job submission files") #First job.. calculator["execution"]["offset"] = startAdder mljob = Job(calculator["execution"], exdir, calculator["execution"]["exec_path"], arrayStart=startPoint - startAdder, arrayEnd=999) with chdir(buildpath): print('Building job file') mljob.write_jobfile('jobscript_vasp_1.sh') calculator["execution"]["offset"] = endAdder - 1 mljob = Job(calculator["execution"], exdir, calculator["execution"]["exec_path"], arrayStart=1, arrayEnd=configIndex - endAdder) with chdir(buildpath): print('Building job file') mljob.write_jobfile('jobscript_vasp_2.sh')
<<<<<<< HEAD dSet = dataset(newTraining,self.species,lFormat = 'mlp') ======= ############################################################################3 self.special_settings["eps"] = 5e-2 #epsilon for checking if atoms are in same layer ############################################################################ dSet = dataset(newTraining,self.species,special_settings = self.special_settings,lFormat = 'mlpselect')######### ADDED SPECIAL_SETTINGS >>>>>>> 03893ba98eddd6991de841e54e88613fa8b4165d dSet.buildFolders(trainingRoot,self.calculator,foldername = 'A') def statusReport(self): from os import path from glob import glob from aBuild.calculators.vasp import VASP trainingRoot = path.join(self.root, 'training_set') with chdir(trainingRoot): enumdirs = glob("E.*") activedirs = glob("A.*") dirs = [path.join(trainingRoot,x) for x in enumdirs + activedirs] <<<<<<< HEAD stat = {'done':[],'running':[], 'not started': [], 'too long':[], 'not setup':[],'warning':[],'idk':[],'unconverged':[],'sgrcon':[],'error':[]} ======= stat = {'done':[],'running':[], 'not started': [], 'too long':[], 'not setup':[],'warning':[],'idk':[],'unconverged':[]} >>>>>>> 03893ba98eddd6991de841e54e88613fa8b4165d for dir in dirs: thisVASP = VASP(dir,systemSpecies = self.species) stat[thisVASP.status()].append(dir.split('/')[-1]) # msg.info("Status of directory {} is {} ".format(dir,thisVASP.status())) msg.info('Done (' + str(len(stat['done'])) + ')') msg.info(' '.join(stat['done']))
def buildFolders(self, buildpath, calculator, runGetKpoints=True, foldername='E'): from os import path from aBuild.calculators.vasp import VASP from aBuild.calculators.lammps import LAMMPS from aBuild.calculators.espresso import ESPRESSO from aBuild.jobs import Job import os print("Building folders in {}".format(buildpath)) if not path.isdir(buildpath): os.mkdir(buildpath) print('Made path:', buildpath) configIndex = startPoint = self.starting_point(buildpath) lookupCalc = { 'vasp': lambda specs: VASP(specs), 'qe': lambda specs: ESPRESSO(specs, self.species), 'lammps': lambda specs: LAMMPS(specs, self.species) } lookupSpecs = { 'vasp': lambda crystal: { "incar": calculator["vasp"]["incar"], "kpoints": calculator["vasp"]["kpoints"], 'potcar': calculator["vasp"]["potcars"], "crystal": crystal }, 'qe': lambda crystal: { "crystal": crystal, "pseudopotentials": calculator["qe"]["pseudopotentials"] }, 'lammps': lambda crystal: { "crystal": crystal, "potential": calculator["lammps"]["potential"] } } lookupBuild = { 'vasp': lambda obj: obj.buildFolder(runGetKPoints=runGetKpoints), 'qe': lambda obj: obj.buildFolder(), 'lammps': lambda obj: obj.buildFolder() } for crystal in self.crystals: print("Building crystal {}".format(crystal.title)) #Augment the existing dictionary in preparation for sending it in calculator[calculator["active"]]["crystal"] = crystal calculator[calculator["active"]]["species"] = self.species # Initialize the calculation object print(calculator[calculator["active"]], 'check here') thisCalc = lookupCalc[calculator["active"]]( calculator[calculator["active"]]) # thisCalc = lookupCalc[calculator["active"]](lookupSpecs[calculator["active"]](crystal)) if 'AFM' in calculator[calculator[ "active"]] and thisCalc.crystal.AFMPlanes == None: msg.info( "Skipping this structure because I can't find the AFM planes" ) continue # Build the path runpath = path.join(buildpath, foldername + ".{}".format(configIndex)) if not path.isdir(runpath): os.mkdir(runpath) else: msg.fatal( "I'm gonna write over top of a current directory. ({}) I think I'll stop instead." .format(runpath)) # Change the directory and build the folder print("Building folder for structure: {}".format(crystal.title)) with chdir(runpath): lookupBuild[calculator["active"]](thisCalc) configIndex += 1 # Build the submission script exdir = path.join(buildpath, 'A.') mljob = Job(calculator["execution"], exdir, calculator["execution"]["exec_path"], arrayStart=startPoint, arrayEnd=configIndex - 1) with chdir(buildpath): print('Building job file') mljob.write_jobfile('jobscript_vasp.sh')
>>>>>>> 03893ba98eddd6991de841e54e88613fa8b4165d # Build the path runpath = path.join(buildpath,foldername + ".{}".format(configIndex) ) if not path.isdir(runpath): os.mkdir(runpath) else: msg.fatal("I'm gonna write over top of a current directory. ({}) I think I'll stop instead.".format(runpath)) <<<<<<< HEAD # Change the directory and build the folder print("Building folder for structure: {}".format(crystal.title) ) ======= # Change the directory and build the folder print("Building folder {} for structure: {}".format(configIndex,crystal.title) ) >>>>>>> 03893ba98eddd6991de841e54e88613fa8b4165d with chdir(runpath): lookupBuild[calculator["active"]](thisCalc) configIndex += 1 # Build the submission script exdir = path.join(buildpath,'E.') mljob = Job(calculator["execution"],exdir,calculator["execution"]["exec_path"], arrayStart = startPoint,arrayEnd = configIndex - 1) with chdir(buildpath): print('Building job file') mljob.write_jobfile('jobscript_vasp.sh')
def status(self): from os import path from time import time from aBuild.utility import grep import os fTagStatic = '------------------------ aborting loop because EDIFF is reached ----------------------------------------\n' fTagRelax = ' writing wavefunctions' ctime = time() print('checking directory {}'.format(self.directory)) with chdir(self.directory): outcar = self._check_file_exists('OUTCAR') incar = self._check_file_exists('INCAR') kpoints = self._check_file_exists('KPOINTS') potcar = self._check_file_exists('POTCAR') poscar = self._check_file_exists('POSCAR') output = self._check_file_exists('vasp_output') oszicar = self._check_file_exists('OSZICAR') inputs = incar and kpoints and potcar and poscar ''' Check to see if the input files are present if they aren't, no need to proceed, just return 'not setup' ''' if not inputs: return 'not setup' ''' If the OUTCAR file is present, we know that we're either running, finished successfully, or finished with errors! ''' elif outcar: # OUTCAR present sgrcon = grep('vasp_output','SGRCON') tooclose = grep('vasp_output','HOPE') finalenergyline = grep('OUTCAR','free energy') generalerror = grep('vasp_output','ERROR') # Check to make sure I've converged electonically. if grep('OSZICAR','DAV:') != []: electronicIteration = int(grep('OSZICAR','DAV:')[-1].split()[1]) else: electronicIteration = 0 if grep('INCAR','nsw') != []: nsw = int(grep('INCAR','nsw')[0].split('=')[1]) if nsw == 0: nsw = 1 else: nsw = 1 if grep('OSZICAR','F=') != []: ionicIteration = int(grep('OSZICAR','F=')[-1].split()[0]) else: ionicIteration = 1 if grep('INCAR','nelm') != []: maxelectronic = grep('INCAR','nelm')[0].split('=')[1] else: maxelectronic = 60 if ionicIteration == nsw and int(electronicIteration) == int(maxelectronic): return 'unconverged' ''' Let's first check to see if this is a static calculation or a relaxation because the tag to check for is different.''' if incar: relax = grep('INCAR','IBRION') if '-1' not in relax or relax is []: static = True else: static = False else: return 'not setup' ''' Check finish tag for static calc''' if static and self._check_tag_exists('OUTCAR', fTagStatic): #finish tag found if finalenergyline != []: #Let's double check return 'done' else: # Apparently not, why? return 'idk' ''' Check finish tag for relax calc''' elif self._check_tag_exists('OUTCAR',fTagRelax): #Looks like it's done if finalenergyline != []: # Let's double check return 'done' else: # Apparently not, why? return 'idk' else: ''' Check how long since the last file write. If it was recent then we're probably running.''' time = path.getmtime('OUTCAR') if (ctime - time) < 3600: # If the OUTCAR was modified in the last hour # the calculation is probably still running. return 'running' elif sgrcon: return 'sgrcon' elif generalerror: return 'error' elif tooclose: return 'warning' else: return 'too long' else: return 'not started' if output: warning = grep('output','RRRRR') != [] or grep('output','AAAAAA') != [] if warning: return 'warning' return folderstat