def bringup(self, structure, outdir, **kwargs): """ Creates all input files necessary to run results. Performs the following actions. - Writes POSCAR_ file. - Writes INCAR_ file. - Writes KPOINTS_ file. - Creates POTCAR_ file """ from os.path import join from ..crystal import specieset from ..misc import chdir, local_path from . import files logger.info('vasp/functional bringup: outdir: %s ' % outdir) logger.debug('vasp/functional bringup: structure:\n%s' % repr(structure)) logger.debug('vasp/functional bringup: kwargs: %s' % repr(kwargs)) with chdir(outdir): # creates INCAR file (and POSCAR via istruc). fpath = join(outdir, files.INCAR) logger.debug("vasp/functional bringup: incar fpath: %s " % fpath) self.write_incar(structure, path=fpath, outdir=outdir, **kwargs) # creates kpoints file logger.debug("vasp/functional bringup: files.KPOINTS: %s " % files.KPOINTS) with open(files.KPOINTS, "w") as kp_file: self.write_kpoints(kp_file, structure) # creates POTCAR file logger.debug("vasp/functional bringup: files.POTCAR: %s " % files.POTCAR) with open(files.POTCAR, 'w') as potcar: for s in specieset(structure): outLines = self.species[s].read_potcar() potcar.writelines(outLines) # Add is running file marker. local_path(outdir).join('.pylada_is_running').ensure(file=True) self._copy_additional_files(outdir)
def write_kpoints(self, file, structure, kpoints=None): """ Writes kpoints to a stream. """ logger.info("vasp/functional write_kpoints: file: %s " % file) logger.debug("vasp/functional write_kpoints: kpoints: %s " % kpoints) if kpoints == None: kpoints = self.kpoints if isinstance(self.kpoints, str): file.write(self.kpoints) elif hasattr(self.kpoints, "__call__"): self.write_kpoints(file, structure, self.kpoints(self, structure)) else: # numpy array or such. outLine = "Explicit list of kpoints.\n{0}\nCartesian\n".format( len(self.kpoints)) file.write(outLine) for kpoint in self.kpoints: outLine = "{0[0]} {0[1]} {0[2]} {1}\n".format( kpoint, 1 if len(kpoint) == 3 else kpoint[3]) file.write(outLine)
def write_incar(self, structure, path=None, **kwargs): """ Writes incar file. """ from os.path import dirname from ..misc import RelativePath from .files import INCAR logger.debug("vasp/functional write_incar: path: %s " % path) logger.debug("vasp/functional write_incar: structure:\n%s" % repr(structure)) logger.debug("vasp/functional write_incar: kwargs: %s" % repr(kwargs)) # check what type path is. # if not a file, opens one an does recurrent call. if path is None: path = INCAR if not hasattr(path, "write"): with open(RelativePath(path).path, "w") as file: self.write_incar(structure, path=file, **kwargs) return if kwargs.get('outdir', None) is None: kwargs['outdir'] = dirname(path.name) self.output_map(structure=structure, vasp=self, **kwargs) # twice, in-case some parameters change others. # At this point (vasp==self)._input is a map of the incar parameters. # The values may be primitives or callables. # Example: self._input['foobar'] = 'FOOBARED' map = self.output_map(structure=structure, vasp=self, **kwargs) length = max(len(u) for u in map) for key, value in map.items(): if value is True: outLine = '{0: >{length}} = .TRUE.\n'.format(key.upper(), length=length) elif value is False: outLine = '{0: >{length}} = .FALSE.\n'.format(key.upper(), length=length) else: outLine = '{0: >{length}} = {1}\n'.format(key.upper(), value, length=length) path.write(outLine)
def iter(self, structure, outdir=None, comm=None, overwrite=False, **kwargs): """ Allows asynchronous vasp calculations This is a generator which is equivalent to the following: .. code:: python yield Program(program="Vasp", outdir=outdir) yield Extract(outdir=outdir) - :py:class:`~pylada.process.program.ProgramProcess`: once started, this process will run an actual VASP_ calculation. - :py:attr:`Extract`: once the program has been runned, and extraction object is yielded, in order that the results of the run can be analyzed. This generator function makes it possible to run different instances of VASP_ simultaneously. It also makes it possible to create more complex calculations which necessitate more than one actual call to VASP_ (see :py:class:`~pylada.vasp.relax.iter_relax`), while retaining the ability to run multiple VASP_ programs simultaneously. If successful results (see :py:attr:`Extract.success`) already exist in outdir, Pylada defaults to *not* repeating the calculations. In that case, the first object described above is *skipped* and only an extraction object is yielded. The :py:meth:`__call__` method loops over this generator and makes actual VASP_ calls. Looking at its code is a good place to start, if you want to understand this looping business. The benefit of this approach can be seen in :py:class:`~pylada.vasp.relax.iter_relax` (more complex calculations) and :py:class:`pylada.process.jobfolder.JobFolderProcess`. :param structure: :py:class:`~pylada.crystal.Structure` structure to compute. :param outdir: Output directory where the results should be stored. This directory will be checked for restart status, eg whether calculations already exist. If None, then results are stored in current working directory. :param comm: Holds arguments for executing VASP externally. :param overwrite: If True, will overwrite pre-existing results. If False, will check whether a successful calculation exists. If one does, then does not execute. :param kwargs: Any attribute of the VASP instance can be overridden for the duration of this call by passing it as keyword argument: >>> for program in vasp.iter(structure, outdir, sigma=0.5): ... The above would call VASP_ with smearing of 0.5 eV (unless a successfull calculation already exists, in which case the calculations are *not* overwritten). :yields: A process and/or an extraction object, as described above. :raise RuntimeError: when computations do not complete. :raise IOError: when outdir exists but is not a directory. .. note:: This function is stateless. It expects that self and structure can be deepcopied correctly. .. warning:: This will never overwrite successfull VASP calculation, even if the parameters to the call are different. """ from ..process.program import ProgramProcess from .extract import Extract as ExtractVasp logger.info('vasp/functional iter: outdir: %s' % outdir) logger.debug('vasp/functional iter: structure:\n%s' % repr(structure)) # check for pre-existing and successful run. if not overwrite: # Check with this instance's Extract, cos it is this calculation we shall # do here. Derived instance's Extract might be checking for other stuff. extract = Vasp.Extract(outdir) if extract.success: yield extract # in which case, returns extraction object. return # copies/creates file environment for calculation. self.bringup(structure, outdir, comm=comm, overwrite=overwrite) # figures out what program to call. vaspProgram = getattr(self, 'program', None) if (vaspProgram == None): import pylada vaspProgram = pylada.vasp_program if vaspProgram == None: raise RuntimeError('program was not set in the vasp functional') if testValidProgram != None: vaspProgram = testValidProgram if hasattr(vaspProgram, '__call__'): vaspProgram = vaspProgram(self, structure, comm) # creates a process with a callback to bring-down environment once it is # done. def onfinish(process, error): self.bringdown(outdir, structure) onfail = self.OnFail(Vasp.Extract(outdir)) yield ProgramProcess(vaspProgram, cmdline=[], outdir=outdir, onfinish=onfinish, onfail=onfail, stdout='stdout', stderr='stderr', dompi=comm is not None) # yields final extraction object. yield ExtractVasp(outdir)