def save_job(path, inputpath="input.py", **kwargs): """ Jobs to explore possible ground-states. :Parameters: path Path where the job-folder will be saved. Calculations will be performed in the parent directory of this file. Calculations will be performed in same directory as this file. inputpath Path to an input file. Defaults to input.py. kwargs Any keyword/value pair to take precedence over anything in the input file. Creates a high-throughput job-folder to compute the non-magnetic ground-state of a host-material. The new job-folder is loaded into memory automatically. No need to call explore. It is save to the path provided on input. """ import re from IPython.core.interactiveshell import InteractiveShell from copy import deepcopy from pylada.vasp import read_input from pylada.jobfolder import JobFolder from pylada import interactive from pylada.misc import setBugLev setBugLev(0) # set global debug level from pylada.misc import bugLev # reads input. input = read_input(inputpath) input.update(kwargs) # Job dictionary. jobfolder = JobFolder() # loop over material-lattice pairs. for (material, lattice) in input.matLatPairs: structure = deepcopy(lattice) # job folder for this lattice. lat_jobfolder = jobfolder / material job = lat_jobfolder / lattice.name / "basin_hoping" job.functional = input.calc job.params["structure"] = structure job.params["ispin"] = 1 job.params["vasp"] = input.vasp job.params["programs"] = input.programs job.params["func_param"] = input.func_param # saves some stuff for future reference. job.material = material job.lattice = lattice #print ' test/hi/test: job: ', job #print ' test/hi/test: === job.functional ===\n%s\n=== end functional === ' % (job.functional,) interactive.jobfolder = jobfolder InteractiveShell.instance().magic("savefolders " + path)
def calcGW( path=None, inputpath='inputGW.py', **kwargs): """ Runs GW calcs on all subfolders. :Parameters: path : str or None Path where the modified job-folder will be saved. Calculations will be performed in the parent directory of this file. If None, will use the current job-folder path. inputpath : str or None Path to an input file. kwargs Any keyword/value pair to take precedence over anything in the input file. """ from tempfile import NamedTemporaryFile from os.path import dirname, normpath, relpath, join from IPython.core.interactiveshell import InteractiveShell from pylada.vasp import read_input from pylada.jobfolder import JobFolder from pylada import interactive import pickle, random from pylada.misc import setBugLev setBugLev(0) # set global debug level from pylada.misc import bugLev with open(path) as fin: jobfolder = pickle.load( fin) basedir = dirname( path) jobfolder_path = join( basedir, jobfolder.name) # Loads job-folder and path as requested. if jobfolder is None: print "No current job-folder." return if jobfolder_path is None: print "No path for current job-folder." return input = read_input(inputpath) print ' test/hi/test gw: inputpath: ', inputpath print ' test/hi/test gw: input.vasp.relaxation: ', input.vasp.relaxation # will loop over all folders, looking for all successfull calculations. nb_new_folders = 0 for name, pjob in jobfolder.iteritems(): if bugLev >= 1: print "test/hi/test gw: name: %s pjob: %s" % (name, pjob,) # avoid tagged folders. if pjob.is_tagged: continue basename = normpath("/" + name + "/../") if bugLev >= 1: print "test/hi/test gw: basename: %s" % (basename,) # check for success and avoid failures. extractPath = join(basedir, name) extract = pjob.functional.Extract( extractPath) if bugLev >= 1: print "test/hi/test gw: extractPath: %s" % (extractPath,) print "test/hi/test gw: extract.success: %s" % (extract.success,) print "test/hi/test gw: extract: %s" % (extract,) print "test/hi/test gw: dir(extract): %s" % (dir(extract),) if not extract.success: continue if bugLev >= 1: print 'test/hi/test gw ========== A' print "test/hi/test gw: nonmag structure: %s" % (pjob.structure,) print 'test/hi/test gw ========== B' print "test/hi/test gw: extract.structure: %s" % (extract.structure,) print 'test/hi/test gw ========== C' print "test/hi/test gw: extract.species: %s" % (extract.species,) print "test/hi/test gw: extract functional species: %s" \ % (extract.functional.species,) print 'test/hi/test gw ========== D' print "test/hi/test gw: dir(pjob): %s" % (dir(pjob),) print 'test/hi/test gw ========== E' # loads lattice and material from previous job. material = pjob.material lattice = pjob.lattice if bugLev >= 1: print "test/hi/test gw: material: %s" % (material,) print "test/hi/test gw: lattice: %s" % (lattice,) jobname = pjob.name + '/gwcalc' structure = extract.structure.copy() structure.name = "{0} in {1}, GW.".format(material, lattice.name) if bugLev >= 1: print "test/hi/test gw: jobname: %s" % (jobname,) print "test/hi/test gw: structure.name: %s" % (structure.name,) job = jobfolder / jobname if bugLev >= 1: print "test/hi/test gw: job: %s" % (job,) job.functional = input.vasp job.params["structure"] = structure.copy() job.params["magmom"] = True job.params["ispin"] = 2 # saves some stuff for future reference. job.material = material job.lattice = lattice print "test/hi/test gw: created ferro jobname: %s" % (jobname,) nb_new_folders += 1 # now saves new job folder print "Created {0} new folders.".format(nb_new_folders) if nb_new_folders == 0: return interactive.jobfolder = jobfolder.root InteractiveShell.instance().magic("savefolders " + path)
def nonmagnetic_wave(path, inputpath="input.py", **kwargs): """ Jobs to explore possible ground-states. :Parameters: path Path where the job-folder will be saved. Calculations will be performed in the parent directory of this file. Calculations will be performed in same directory as this file. inputpath Path to an input file. Defaults to input.py. kwargs Any keyword/value pair to take precedence over anything in the input file. Creates a high-throughput job-folder to compute the non-magnetic ground-state of a host-material. The new job-folder is loaded into memory automatically. No need to call explore. It is save to the path provided on input. """ import re from IPython.core.interactiveshell import InteractiveShell from copy import deepcopy from pylada.vasp import read_input from pylada.jobfolder import JobFolder from pylada import interactive from pylada.misc import setBugLev setBugLev(0) # set global debug level from pylada.misc import bugLev # reads input. input = read_input(inputpath) print ' test/hi/test nonmag: inputpath: ', inputpath print ' test/hi/test nonmag: input.vasp.relaxation: ', input.vasp.relaxation input.update(kwargs) # """ Materials to compute. """ # materials = [ "Al2MgO4"] # # """ Number of random anti-ferro trials. """ # nbantiferro = 8 # nbrandom = 3 # do_ferro = False # do_antiferro = False # # from pylada.crystal import A2BX4 # lattices = [A2BX4.b5(), A2BX4.b21()] # # mlen = len( materials) # llen = len( lattices) # matLatPairs = (mlen * llen) * [None] # print " test/hi/test nonmag: mlen: ", mlen # print " test/hi/test nonmag: llen: ", llen # print " test/hi/test nonmag: pairs len: ", len(matLatPairs) # # kk = 0 # for mat in materials: # print " test/hi/test nonmag: mat: ", mat # for lat in lattices: # print " test/hi/test nonmag: lat: ", lat # matLatPairs[kk] = (mat, lat,) # kk += 1 # # print "test/hi/test nonmag: mats len: %d lats len: %d matLatPairs len: %d" \ # % (mlen, llen, len( matLatPairs),) # Job dictionary. jobfolder = JobFolder() # loop over material-lattice pairs. for (material,lattice) in input.matLatPairs: if bugLev >= 1: print ' test/hi/test nonmag: start material: ', material print ' test/hi/test nonmag: start lattice: ', lattice print '' if bugLev >= 5: print ' test/hi/test nonmag: ========== species ==========' skeys = input.vasp.species.keys() skeys.sort() for skey in skeys: print ' test/hi/test nonmag: species[%s]: %s' \ % (skey, input.vasp.species[skey], ) print '' if getattr( input, 'useInputCif', None) == True: structure = deepcopy(lattice) else: # Check material regex = "([A-Z][a-z]?)2([A-Z][a-z]?)([A-Z][a-z]?)4" match = re.match( regex, material) if match == None: raise RuntimeError("Incorrect material: \"%s\"" % (material,)) # Checks species are known to vasp functional for i in range(1, 4): assert match.group(i) in input.vasp.species,\ RuntimeError("No pseudo-potential defined for {0}.".format( match.group(i))) # actually creates dictionary. species_dict = {"A": match.group(1), "B": match.group(2), "X": match.group(3)} #print ' test/hi/test nonmag: species_dict: ', species_dict # Check lattice name if len(getattr(lattice, 'name', '').strip()) == 0: raise ValueError("Lattice has no name.") # creates a structure. structure = deepcopy(lattice) # changes atomic species, from ABX to real element names. # from: Atom(0.5, 0.5, 0.5, 'A') # to: Atom(0.5, 0.5, 0.5, 'Al') for atom in structure: atom.type = species_dict[atom.type] # assigns it a name. structure.name = "{0} in {1}, spin-unpolarized.".format( material, lattice.name) # gets its scale. structure.scale = input.scale(structure) # job folder for this lattice. lat_jobfolder = jobfolder / material job = lat_jobfolder / lattice.name / "non-magnetic" job.functional = input.vasp job.params["structure"] = structure job.params["ispin"] = 1 # saves some stuff for future reference. job.material = material job.lattice = lattice #print ' test/hi/test nonmag: job: ', job #print ' test/hi/test nonmag: === job.functional ===\n%s\n=== end functional === ' % (job.functional,) interactive.jobfolder = jobfolder InteractiveShell.instance().magic("savefolders " + path)
def magnetic_wave( path=None, inputpath='input.py', **kwargs): """ Creates magnetic wave for current job-folder. :Parameters: path : str or None Path where the modified job-folder will be saved. Calculations will be performed in the parent directory of this file. If None, will use the current job-folder path. inputpath : str or None Path to an input file. If not present, then no input file is read and all parameters are taken from the non-magnetic wave. kwargs Any keyword/value pair to take precedence over anything in the input file. Creates magnetic wave from pre-existing non-magnetic wave. If no input file is given on input, then all parameters are obtained from the corresponding non-magnetic wave. The new job-folder is loaded into memory automatically. No need to call explore. It is save to the path provided on input (or to the current job-folder path ifnot provided). It will contain magnetic and non-magnetic calculations both. Pre-existing magnetic calculations will *not* be overwritten. However, additional anti-ferro configurations can be calculated by giving a large enough ``nbantiferro`` on input. """ from tempfile import NamedTemporaryFile from os.path import dirname, normpath, relpath, join from IPython.core.interactiveshell import InteractiveShell from pylada.vasp import read_input from pylada.jobfolder import JobFolder from pylada import interactive import pickle, random from pylada.misc import setBugLev setBugLev(0) # set global debug level from pylada.misc import bugLev with open(path) as fin: jobfolder = pickle.load( fin) basedir = dirname( path) jobfolder_path = join( basedir, jobfolder.name) # Loads job-folder and path as requested. if jobfolder is None: print "No current job-folder." return if jobfolder_path is None: print "No path for current job-folder." return input = read_input(inputpath) print ' test/hi/test mag: inputpath: ', inputpath print ' test/hi/test mag: input.vasp.relaxation: ', input.vasp.relaxation # will loop over all folders, looking for *successfull* *non-magnetic* calculations. # Only magnetic folders which do NOT exist are added at that point. nonmagname = "non-magnetic" nb_new_folders = 0 for name, nonmagjob in jobfolder.iteritems(): if bugLev >= 1: print "test/hi/test mag: name: %s nonmagjob: %s" % (name, nonmagjob,) # avoid tagged folders. if nonmagjob.is_tagged: continue # avoid other folders (eg magnetic folders). basename = normpath("/" + name + "/../") if bugLev >= 1: print "test/hi/test mag: basename: %s" % (basename,) if relpath(name, basename[1:]) != nonmagname: continue # check for success and avoid failures. extractPath = join(basedir, name) # xxx use contcar extract = nonmagjob.functional.Extract( extractPath) if bugLev >= 1: print "test/hi/test mag: extractPath: %s" % (extractPath,) print "test/hi/test mag: extract.success: %s" % (extract.success,) print "test/hi/test mag: extract: %s" % (extract,) print "test/hi/test mag: dir(extract): %s" % (dir(extract),) print "test/hi/test mag: extract.functional: %s" % (extract.functional,) if not extract.success: continue if bugLev >= 1: print 'test/hi/test mag ========== A' print "test/hi/test mag: nonmag structure: %s" % (nonmagjob.structure,) print 'test/hi/test mag ========== B' print "test/hi/test mag: extract.structure: %s" % (extract.structure,) print 'test/hi/test mag ========== C' print "test/hi/test mag: extract.species: %s" % (extract.species,) print 'test/hi/test mag ========== D' if not is_magnetic_system(extract.structure, extract.functional.species): continue # loads lattice and material from non-magnetic job. material = nonmagjob.material lattice = nonmagjob.lattice if bugLev >= 1: print "test/hi/test mag: material: %s" % (material,) print "test/hi/test mag: lattice: %s" % (lattice,) # figures out whether we have both high and low spins. if bugLev >= 1: print "test/hi/test mag: extract structure: %s" % (extract.structure,) print "test/hi/test mag: extract species: %s" \ % (extract.functional.species,) if has_high_and_low(extract.structure, extract.functional.species): hnl = [(min, "ls-"), (max, "hs-")] else: hnl = [(min, "")] # now loops over moments. for func, prefix in hnl: if bugLev >= 1: print "test/hi/test mag: func: %s prefix: %s" % (func, prefix,) # Either func=min,prefix="ls-", or func=max,prefix="hs-" # Now tries and creates high-spin ferro folders # if it does not already exist. jobname = normpath("{0}/{1}ferro".format(basename, prefix)) structure, magmom = ferro( extract.structure, extract.functional.species, func) if bugLev >= 1: print "test/hi/test mag: structure: %s" % (structure,) print "test/hi/test mag: jobfolder: %s" % (jobfolder,) print "test/hi/test mag: jobname: %s" % (jobname,) print "test/hi/test mag: magmom: %s" % (magmom,) print "test/hi/test mag: input.do_ferro: %s" % (input.do_ferro,) if magmom and jobname not in jobfolder and input.do_ferro: structure.name = "{0} in {1}, {2}ferro."\ .format(material, lattice.name, prefix) job = jobfolder / jobname if bugLev >= 1: print "test/hi/test mag: structure.name: %s" % (structure.name,) print "test/hi/test mag: job: %s" % (job,) job.functional = input.vasp job.params["structure"] = structure.copy() job.params["magmom"] = True job.params["ispin"] = 2 # saves some stuff for future reference. job.material = material job.lattice = lattice print "test/hi/test mag: created ferro jobname: %s" % (jobname,) nb_new_folders += 1 # Now tries and creates anti-ferro-lattices folders # if it does not already exist. structure, magmom = species_antiferro( extract.structure, extract.functional.species, func) jobname = normpath("{0}/{1}anti-ferro-0".format(basename, prefix)) if magmom and jobname not in jobfolder and input.do_antiferro: structure.name = "{0} in {1}, {2}specie-anti-ferro."\ .format(material, lattice.name, prefix) job = jobfolder / jobname job.functional = input.vasp job.params["structure"] = structure.copy() job.params["magmom"] = True job.params["ispin"] = 2 # saves some stuff for future reference. job.material = material job.lattice = lattice print "test/hi/test mag: created anti ferro jobname: %s" % (jobname,) nb_new_folders += 1 # Random anti-ferro, or all possible anti-ferro. magIxs = [] # indices of magnetic atoms for ii in range( len( extract.structure)): atom = extract.structure[ii] if len(deduce_moment(atom, extract.functional.species)) > 1: magIxs.append( ii) numMagAtom = len( magIxs) # Total num tests = 2**numMagAtom, but each one is counted # twice, since ddd == uuu, and ddu == uud, etc., # where d = spin down, u = spin up. # So the num unique tests = 2**numMagAtom / 2 numUnique = 2 ** (numMagAtom - 1) # If the user asked for at least half the total num unique tests, # we may as well do them all print "test/hi/test mag: numMagAtom: %d numUnique: %d input.nbantiferro: %d" \ % ( numMagAtom, numUnique, input.nbantiferro,) if input.nbantiferro >= numUnique / 2: # Do all possible combinations print 'test/hi/test mag: Do all possible antiferro combinations' for itest in range( numUnique): jobname = runAntiFerroTest( bugLev, jobfolder, material, lattice, inputpath, input, magIxs, extract, basename, func, prefix, itest, itest) print "test/hi/test mag: created all anti ferro jobname: %s" \ % (jobname,) nb_new_folders += 1 else: # Only run a few random combinations print 'test/hi/test mag: Do a random selection of antiferro combinations' doneMap = {} ix = 0 while True: itest = random.randint( 0, numUnique - 1) if itest not in doneMap: doneMap[itest] = True jobname = runAntiFerroTest( bugLev, jobfolder, material, lattice, inputpath, input, magIxs, extract, basename, func, prefix, ix, itest) print "test/hi/test mag: created random anti ferro jobname: %s" \ % (jobname,) nb_new_folders += 1 ix += 1 if ix >= input.nbantiferro: break # now saves new job folder print "Created {0} new folders.".format(nb_new_folders) if nb_new_folders == 0: return interactive.jobfolder = jobfolder.root InteractiveShell.instance().magic("savefolders " + path)
def main(): import re from sys import path as python_path from os.path import exists from argparse import ArgumentParser from pylada import jobfolder from pylada.process.mpi import create_global_comm import pylada # below would go additional imports. parser = ArgumentParser( prog="runone", description = re.sub("\\s+", " ", __doc__[1:])) parser.add_argument('--bugLev', dest="bugLev", default=0, type=int,\ help="Debug level.") parser.add_argument('--testValidProgram', dest="testValidProgram", default=None, type=str, help="testValidProgram") parser.add_argument( "--jobid", dest="names", nargs='+', type=str, \ help="Job name", metavar="N" ) parser.add_argument( "--ppath", dest="ppath", default=None, \ help="Directory to add to python path", metavar="Directory" ) parser.add_argument('--nbprocs', dest="nbprocs", default=pylada.default_comm['n'], type=int,\ help="Number of processors with which to launch job.") parser.add_argument('--ppn', dest="ppn", default=pylada.default_comm['ppn'], type=int,\ help="Number of processors with which to launch job.") parser.add_argument('--timeout', dest="timeout", default=300, type=int,\ help="Time to wait for job-dictionary to becom available " "before timing out (in seconds). A negative or null " "value implies forever. Defaults to 5mn.") parser.add_argument('pickle', metavar='FILE', type=str, help='Path to a job-folder.') try: options = parser.parse_args() except SystemExit: return from pylada.misc import setBugLev setBugLev( options.bugLev) # set global debug level from pylada.misc import bugLev # must import after calling setBugLev from pylada.misc import setTestValidProgram tstPgm = options.testValidProgram if tstPgm.lower() == 'none': tstPgm = None setTestValidProgram( tstPgm) from pylada.misc import testValidProgram # additional path to look into. if options.ppath is not None: python_path.append(options.ppath) if not exists(options.pickle): print "Could not find file {0}.".format(options.pickle) return # Set up mpi processes. pylada.default_comm['ppn'] = options.ppn pylada.default_comm['n'] = options.nbprocs if testValidProgram == None: create_global_comm(options.nbprocs) # Sets pylada.default_comm else: pylada.default_comm = None # use testValidProgram timeout = None if options.timeout <= 0 else options.timeout jobfolder = jobfolder.load(options.pickle, timeout=timeout) print ' ipy/lau/scattered_script: jobfolder: ', jobfolder print ' ipy/lau/scattered_script: options: ', options for name in options.names: if bugLev >= 1: print ' ipy/lau/scattered_script: testValidProgram: %s' \ % ( testValidProgram,) print ' ipy/lau/scattered_script: name: %s' % ( name,) print ' ipy/lau/scattered_script: jobfolder[name]: %s' \ % ( jobfolder[name],) print ' ipy/lau/scattered_script: type(jobfolder[name]): %s' \ % ( type(jobfolder[name]),) print ' ipy/lau/scattered_script: jobfolder[name].compute: %s' \ % ( jobfolder[name].compute,) print ' ipy/lau/scattered_script: type(jobfolder[name].compute): %s' \ % ( type(jobfolder[name].compute),) print ' ipy/lau/scattered_script: before compute for name: %s' \ % ( name,) comm = pylada.default_comm if testValidProgram != None: comm = None jobfolder[name].compute(comm=comm, outdir=name) if bugLev >= 1: print ' ipy/lau/scattered_script: after compute for name: %s' \ % ( name,)
def save_job(path, inputpath="input.py", **kwargs): """ Jobs to explore possible ground-states. :Parameters: path Path where the job-folder will be saved. Calculations will be performed in the parent directory of this file. Calculations will be performed in same directory as this file. inputpath Path to an input file. Defaults to input.py. kwargs Any keyword/value pair to take precedence over anything in the input file. Creates a high-throughput job-folder to compute the non-magnetic ground-state of a host-material. The new job-folder is loaded into memory automatically. No need to call explore. It is save to the path provided on input. """ import re from IPython.core.interactiveshell import InteractiveShell from copy import deepcopy from pylada.vasp import read_input from pylada.jobfolder import JobFolder from pylada import interactive from pylada.misc import setBugLev setBugLev(0) # set global debug level from pylada.misc import bugLev # reads input. input = read_input(inputpath) input.update(kwargs) # Job dictionary. jobfolder = JobFolder() # loop over material-lattice pairs. for (material,lattice) in input.matLatPairs: structure = deepcopy(lattice) # job folder for this lattice. lat_jobfolder = jobfolder / material job = lat_jobfolder / lattice.name / "basin_hoping" job.functional = input.calc job.params["structure"] = structure job.params["ispin"] = 1 job.params["vasp"] = input.vasp job.params["programs"] = input.programs job.params["func_param"] = input.func_param # saves some stuff for future reference. job.material = material job.lattice = lattice #print ' test/hi/test: job: ', job #print ' test/hi/test: === job.functional ===\n%s\n=== end functional === ' % (job.functional,) interactive.jobfolder = jobfolder InteractiveShell.instance().magic("savefolders " + path)