示例#1
0
def load_run_input():
    from pylada.vasp import read_input
    #  options, args = load_options()
    rin = "run_input.py"
    run_input = read_input("input_generic.py")
#  run_input.update(read_input(options.run_input_name))
    run_input.update(read_input(rin))
    return run_input
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)
示例#3
0
def create(input='input.py'):
  """ Load ga into ipython. """
  from os.path import exists
  from pickle import dump
  from pylada.vasp import read_input
  from pylada.ga.xgsgo.functional import Functional
  from pylada.jobfolder import JobFolder

  input = read_input(input)


  root = JobFolder()
  for trial in xrange(input.trials):
    folder = root / "results" / str(trial)
    folder.functional = Functional( functional        = input.vasp, 
                                    species           = input.species,
                                    natoms            = input.natoms,
                                    rate              = input.rate,
                                    popsize           = input.popsize,
                                    cns_rate          = input.cns_rate,
                                    mix_atoms_rate    = input.mix_atoms_rate,
                                    mix_poscar_rate   = input.mix_poscar_rate,
                                    mutation_rate = input.mutation_rate )
  return root
示例#4
0
文件: test.py 项目: mdavezac/LaDa
import pylada
pylada.pylada_with_mpi = False
from pylada.vasp import read_input

input = read_input("input.py")
input.structure.name = "has a name"

input.vasp(input.structure, outdir="results", comm={'n': 2, 'ppn': 1})
示例#5
0
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)
示例#6
0
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)
示例#7
0
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 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)
示例#9
0
def pointdefect_wave(path=None, inputpath=None, **kwargs):
  """ Creates point-defect wave using ground-state job-dictionary. 

      :Parameters:
        path : str or None
          Path where the modified job-dictionary will be saved. Calculations will be
          performed in the parent directory of this file. If None, will use the
          current job-dictionary 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 a point-defect wave from the materials computed in the
      magnetic and non-magnetic waves. Usage is fairly simple. If the pickle
      for the magnetic/non-magnetic wave is called ``magnetic_wave``, then one
      need only open it and call the ``pointdefect_wave``.

      >>> explore all magnetic_wave 
      >>> import test
      >>> test.magnetic_wave()
      >>> launch scattered

      The above will add point-defect calculations for all meterials and
      lattices of the ``magnetic_wave`` job-dictionary and save it (to the same 
      path unless an argument is provided to ``magnetic_wave``). Note that
      changing the location of the current job-dictionary has no effect. It
      would be possible but sounds too error prone:

      >>> explore all magnetic_wave 
      >>> goto /Fe2AlO4 # has no effect on what point-defects are added.
      >>> goto /Al2FeO4 # has no effect on what point-defects are added.
      >>> import test
      >>> # creates point-defects for both Fe2AlO4 and Al2FeO4: location does not matter.
      >>> test.magnetic_wave() 
      >>> launch scattered

      Point-defects calculations are added to
      a material if and only if all existing magnetic/non-magnetic jobs for
      that material have completed successfully. Furthermore, only untagged
      materials are accepted. Hence, to disable Fe2AlO4 lattices from having
      point-defects added to it, one can simply tag it:

      >>> explore all magnetic_wave 
      >>> jobparams["/Fe2AlO4"] = 'off'
      >>> import test
      >>> test.magnetic_wave()
      >>> launch scattered

      Similarly to make sure point-defect calculations are *not* created for
      the b5 lattice of the Fe2AlO4 material, one could tag it as follows:

      >>> explore all magnetic_wave 
      >>> current_jobfolder["/Fe2AlO4/b5"].tag()
      >>> import test
      >>> test.magnetic_wave()
      >>> launch scattered
  """
  from tempfile import NamedTemporaryFile
  from os.path import dirname, normpath, relpath, join
  from IPython.ipapi import get as get_ipy
  from numpy import array, sum, abs
  from pylada.jobs import JobFolder
  from pylada.vasp import read_input
  from pylada.opt import Input
  from pylada.crystal import defects as ptd

  # Loads job-folder and path as requested. 
  ip = get_ipy()
  if "current_jobfolder" not in ip.user_ns: 
    print "No current job-dictionary." 
    return
  jobfolder = ip.user_ns["current_jobfolder"].root
  if path is None:
    if "current_jobfolder_path" not in ip.user_ns:
      print "No known path for current dictionary and no path specified on input."
      return
    path = ip.user_ns["current_jobfolder_path"]
  basedir = dirname(path)

  # create input dictionary. First reads non-magnetic input, then magnetic
  # input, then kwargs. Order of precedence is exact opposite.
  input = Input()
  if hasattr(jobfolder, "nonmaginput"):
    with NamedTemporaryFile() as file: 
      file.write(jobfolder.nonmaginput)
      file.flush()
      input.update(read_input(file.name))
  if hasattr(jobfolder, "maginput"):
    with NamedTemporaryFile() as file: 
      file.write(jobfolder.nonmaginput)
      file.flush()
      input.update(read_input(file.name))
  if inputpath is not None:
    input.update(read_input(inputpath))
    with open(inputpath, "r") as file: jobfolder.maginput = file.read()
  input.update(kwargs)

  # saves inputfile to jobfolderioanry if needed.
  if inputpath is not None:
    input.update(read_input(inputpath))
    with open(inputpath, "r") as file: jobfolder.pointdefectinput = file.read()
  # saves current script tof file.
  with open(__file__, "r") as file: jobfolder.pointdefectscript = file.read()

  if hasattr(input, 'coord_tolerance'): coord_tolerance = input.coord_tolerance
  
  nb_new_jobs = 0
  # loops over completed structural jobs.
  for name in magnetic_groundstates():
    # gets the ground-states job-dictionary.
    groundstate = jobfolder[name]
    # checks that the lattice and material are not tagged. 
    if groundstate[".."].is_tagged: continue
    if groundstate["../.."].is_tagged: continue
    # extracts the structure from it.
    superstructure, lattice = create_superstructure(groundstate, input)
    # extracts material.
    material = groundstate.material
    print 'Working on ', groundstate.name, groundstate.name.split('/')[1]
    # extracts description of species.
    species = groundstate.functional.vasp.species

    # loop over substitutees.
    for structure, defect, B in ptd.iterdefects(superstructure, lattice, input.point_defects, tolerance=coord_tolerance):
      # loop over oxidations states.
      for nb_extrae, oxname in charged_states(input.vasp.species, material, defect.type, B):
        
        # creates list of moments. 
        new_moments = deduce_moment(defect.type, species) 
        if len(new_moments) > 1: 
          moments = [ (min(new_moments), "/ls"), (max(new_moments), "/hs") ]
        else:
          moments = [ (max(new_moments), "") ]
        # loop  over moments.
        for moment, suffix in moments:
          name =  "PointDefects/{1}/{2}{0}".format(suffix, structure.name, oxname)
          
          # checks if job already exists. Does not change job if it exists!
          if name in groundstate[".."]: continue

          # creates new job.
          jobfolder = groundstate["../"] / name
          jobfolder.functional = input.relaxer
          jobfolder.jobparams  = groundstate.jobparams.copy()
          jobfolder.jobparams["structure"] = structure.deepcopy()
          jobfolder.jobparams["nelect"] = nb_extrae
          jobfolder.jobparams["relaxation"] = "ionic"
          jobfolder.jobparams["ispin"] = 2
          jobfolder.jobparams["set_symmetries"] = "off"
          jobfolder.lattice  = lattice
          jobfolder.material = material
          jobfolder.defect   = defect
          # adds, modifies, or remove moment depending on defect type.
          if hasattr(superstructure, "magmom") or abs(moment) > 1e-12: 
            jstruct = jobfolder.jobparams["structure"]
            # construct initial magmom
            if hasattr(superstructure, "magmom"):
              jstruct.magmom = [u for u in superstructure.magmom]
            else: 
              jstruct.magmom = [0 for u in superstructure.atoms]
            # now modifies according to structure.
            if B is None or B.lower() == 'none': # interstitial:
              jstruct.magmom.append(moment)
            elif defect.type is None or defect.type.lower() == 'none':
              vacancy_moment(input.vasp.species, jstruct, defect, B, nb_extrae)
            else: 
              jstruct.magmom[defect.index] = moment
            # only keep moment if there are moments. 
            if sum(abs(jstruct.magmom)) < 1e-12 * float(len(jstruct.atoms)): del jstruct.magmom

          nb_new_jobs += 1

  # now saves new job folder
  print "Created {0} new jobs.".format(nb_new_jobs)
  if nb_new_jobs == 0: return
  ip.user_ns["current_jobfolder"] = jobfolder.root
  ip.magic("savejobs " + path)