예제 #1
0
파일: runner.py 프로젝트: yuang880/vasp
def in_queue(self):
    """Return True or False if the directory has a job in the queue."""
    if self.get_db('jobid') is None:
        log.debug('jobid not found for calculation.')
        return False
    else:
        # get the jobid
        jobid = self.get_db('jobid')
        # see if jobid is in queue
        _, jobids_in_queue, _ = getstatusoutput('qselect',
                                                stdout=subprocess.PIPE,
                                                stderr=subprocess.PIPE)

        if str(jobid) in jobids_in_queue.split('\n'):
            # get details on specific jobid in case it is complete
            status, output, err = getstatusoutput(['qstat', jobid],
                                                  stdout=subprocess.PIPE,
                                                  stderr=subprocess.PIPE)
            if status == 0:
                lines = output.split('\n')
                fields = lines[2].split()
                job_status = fields[4]
                if job_status == 'C':
                    return False
                else:
                    return True
        else:
            return False
예제 #2
0
def in_queue(self):
    """Return True or False if the directory has a job in the queue."""
    if self.get_db('jobid') is None:
        log.debug('jobid not found for calculation.')
        return False
    else:
        # get the jobid
        jobid = self.get_db('jobid')
        # see if jobid is in queue
        _, jobids_in_queue, _ = getstatusoutput('qselect',
                                                stdout=subprocess.PIPE,
                                                stderr=subprocess.PIPE)

        if str(jobid) in jobids_in_queue.split('\n'):
            # get details on specific jobid in case it is complete
            status, output, err = getstatusoutput(['qstat', jobid],
                                                  stdout=subprocess.PIPE,
                                                  stderr=subprocess.PIPE)
            if status == 0:
                lines = output.split('\n')
                fields = lines[2].split()
                job_status = fields[4]
                if job_status == 'C':
                    return False
                else:
                    return True
        else:
            return False
예제 #3
0
def read_neb_calculator():
    """Read calculator from the current working directory.

    Static method that returns a :mod:`jasp.Jasp` calculator.
    """
    log.debug('Entering read_neb_calculator in {0}'.format(os.getcwd()))

    calc = Vasp()
    calc.vaspdir = os.getcwd()
    calc.read_incar()
    calc.read_kpoints()

    if calc.in_queue():
        return ([None for i in range(calc.int_params['images'] + 2)],
                [None for i in range(calc.int_params['images'] + 2)])

    # set default functional
    # if both gga and xc are not specified
    if calc.string_params['gga'] is None:
        if calc.input_params['xc'] is None:
            calc.input_params['xc'] = 'PBE'

    images = []
    log.debug('calc.int_params[images] = %i', calc.int_params['images'])
    # Add 2 to IMAGES flag from INCAR to get
    # first and last images
    for i in range(calc.int_params['images'] + 2):
        log.debug('reading neb calculator: 0%i', i)
        cwd = os.getcwd()

        os.chdir('{0}'.format(str(i).zfill(2)))
        if os.path.exists('CONTCAR'):
            f = open('CONTCAR')
            if f.read() == '':
                log.debug('CONTCAR was empty, vasp probably still running')
                fname = 'POSCAR'
            else:
                fname = 'CONTCAR'
        else:
            fname = 'POSCAR'

        atoms = read(fname, format='vasp')

        f = open('ase-sort.dat')
        sort, resort = [], []
        for line in f:
            s, r = [int(x) for x in line.split()]
            sort.append(s)
            resort.append(r)

        images += [atoms[resort]]
        os.chdir(cwd)

    log.debug('len(images) = %i', len(images))

    calc.neb_images = images
    calc.neb_nimages = len(images) - 2
    calc.neb = True
    return calc
예제 #4
0
파일: neb.py 프로젝트: jkitchin/vasp
def read_neb_calculator():
    """Read calculator from the current working directory.

    Static method that returns a :mod:`jasp.Jasp` calculator.
    """
    log.debug('Entering read_neb_calculator in {0}'.format(os.getcwd()))

    calc = Vasp()
    calc.vaspdir = os.getcwd()
    calc.read_incar()
    calc.read_kpoints()

    if calc.in_queue():
        return ([None for i in range(calc.int_params['images'] + 2)],
                [None for i in range(calc.int_params['images'] + 2)])

    # set default functional
    # if both gga and xc are not specified
    if calc.string_params['gga'] is None:
        if calc.input_params['xc'] is None:
            calc.input_params['xc'] = 'PBE'

    images = []
    log.debug('calc.int_params[images] = %i', calc.int_params['images'])
    # Add 2 to IMAGES flag from INCAR to get
    # first and last images
    for i in range(calc.int_params['images'] + 2):
        log.debug('reading neb calculator: 0%i', i)
        cwd = os.getcwd()

        os.chdir('{0}'.format(str(i).zfill(2)))
        if os.path.exists('CONTCAR'):
            f = open('CONTCAR')
            if f.read() == '':
                log.debug('CONTCAR was empty, vasp probably still running')
                fname = 'POSCAR'
            else:
                fname = 'CONTCAR'
        else:
            fname = 'POSCAR'

        atoms = read(fname, format='vasp')

        f = open('ase-sort.dat')
        sort, resort = [], []
        for line in f:
            s, r = [int(x) for x in line.split()]
            sort.append(s)
            resort.append(r)

        images += [atoms[resort]]
        os.chdir(cwd)

    log.debug('len(images) = %i', len(images))

    calc.neb_images = images
    calc.neb_nimages = len(images) - 2
    calc.neb = True
    return calc
예제 #5
0
파일: getters.py 프로젝트: hightemp/vasp
def get_ados(self, atom_index, orbital, spin=1, efermi=None):
    """Return Atom projected DOS for atom index, orbital and spin.

    orbital: string ['s', 'p', 'd']

    If efermi is not None, use this value as 0.0.

    :returns: (energies, ados)

    """
    self.update()

    with open(os.path.join(self.directory,
                           'vasprun.xml')) as f:
        tree = ElementTree.parse(f)

    path = "/".join(['calculation', 'dos',
                     'partial',
                     'array',
                     'set',
                     'set[@comment="ion {}"]',
                     'set[@comment="spin {}"]',
                     "r"])

    us = [k[1] for k in
          sorted([[j, i]
                  for i, j in enumerate(self.resort)])]

    path = path.format(us.index(atom_index) + 1, spin)
    log.debug(path)

    results = [[float(x) for x in el.text.split()]
               for el in tree.findall(path)]

    if efermi is None:
        efermi = self.get_fermi_level()
    else:
        efermi = 0.0

    energy = np.array([x[0] for x in results]) - efermi
    ados = np.array([x['spd'.index(orbital) + 1] for x in results])

    return [energy, ados]
예제 #6
0
def set(self, **kwargs):
    """Set parameters with keyword=value pairs.

    calc.set(xc='PBE')

    A few special kwargs are handled separately to expand them
    prior to setting the parameters. This is done to enable one
    set to track changes.

    """
    log.debug('Setting {}'.format(kwargs))
    if 'xc' in kwargs:
        kwargs.update(self.set_xc_dict(kwargs['xc']))

    if 'ispin' in kwargs:
        kwargs.update(self.set_ispin_dict(kwargs['ispin']))

    if 'ldau_luj' in kwargs:
        kwargs.update(self.set_ldau_luj_dict(kwargs['ldau_luj']))

    original_params = self.parameters

    changed_parameters = FileIOCalculator.set(self, **kwargs)

    # If we are implementing special setups, the ppp_list needs
    # to be updated so the POSCAR and POTCAR can be written correctly.
    if 'setups' in changed_parameters.keys():
        self.sort_atoms(self.atoms)

    # we don't consider None values to be changed if the keyword was
    # not originally in the parameters.
    cp = {
        k: v
        for k, v in changed_parameters.items()
        if v is not None and k not in original_params
    }

    if cp != {}:
        log.debug('resetting because {} changed.'.format(cp))
        self.reset()
    return changed_parameters
예제 #7
0
    def calculation_required(self, atoms=None, properties=['energy']):
        """Returns if a calculation is needed."""

        if atoms is None:
            atoms = self.get_atoms()

        system_changes = self.check_state(atoms)
        if system_changes:
            log.debug('Calculation needed for {}'.format(system_changes))
            return True
        for name in properties:
            if name not in self.results:
                log.debug('{} not in {}. Calc required.'.format(name,
                                                                self.results))
                return True

        # if the calculation is finished we do not need to run.
        if os.path.exists(self.outcar):
            with open(self.outcar) as f:
                lines = f.readlines()
                if 'Voluntary context switches:' in lines[-1]:
                    return False
예제 #8
0
파일: vasp_core.py 프로젝트: yuang880/vasp
    def calculation_required(self, atoms=None, properties=['energy']):
        """Returns if a calculation is needed."""

        if atoms is None:
            atoms = self.get_atoms()

        system_changes = self.check_state(atoms)
        if system_changes:
            log.debug('Calculation needed for {}'.format(system_changes))
            return True
        for name in properties:
            if name not in self.results:
                log.debug('{} not in {}. Calc required.'.format(
                    name, self.results))
                return True

        # if the calculation is finished we do not need to run.
        if os.path.exists(self.outcar):
            with open(self.outcar) as f:
                lines = f.readlines()
                if 'Voluntary context switches:' in lines[-1]:
                    return False
예제 #9
0
파일: setters.py 프로젝트: hightemp/vasp
def set(self, **kwargs):
    """Set parameters with keyword=value pairs.

    calc.set(xc='PBE')

    A few special kwargs are handled separately to expand them
    prior to setting the parameters. This is done to enable one
    set to track changes.

    """
    log.debug('Setting {}'.format(kwargs))
    if 'xc' in kwargs:
        kwargs.update(self.set_xc_dict(kwargs['xc']))

    if 'ispin' in kwargs:
        kwargs.update(self.set_ispin_dict(kwargs['ispin']))

    if 'ldau_luj' in kwargs:
        kwargs.update(self.set_ldau_luj_dict(kwargs['ldau_luj']))

    if 'nsw' in kwargs:
        kwargs.update(self.set_nsw_dict(kwargs['nsw']))

    original_params = self.parameters

    changed_parameters = FileIOCalculator.set(self, **kwargs)

    # we don't consider None values to be changed if the keyword was
    # not originally in the parameters.
    cp = {
        k: v
        for k, v in changed_parameters.iteritems()
        if v is not None and k not in original_params
    }

    if cp != {}:
        log.debug('resetting because {} changed.'.format(cp))
        self.reset()
    return changed_parameters
예제 #10
0
파일: setters.py 프로젝트: jkitchin/vasp
def set(self, **kwargs):
    """Set parameters with keyword=value pairs.

    calc.set(xc='PBE')

    A few special kwargs are handled separately to expand them
    prior to setting the parameters. This is done to enable one
    set to track changes.

    """
    log.debug('Setting {}'.format(kwargs))
    if 'xc' in kwargs:
        kwargs.update(self.set_xc_dict(kwargs['xc']))

    if 'ispin' in kwargs:
        kwargs.update(self.set_ispin_dict(kwargs['ispin']))

    if 'ldau_luj' in kwargs:
        kwargs.update(self.set_ldau_luj_dict(kwargs['ldau_luj']))

    original_params = self.parameters

    changed_parameters = FileIOCalculator.set(self, **kwargs)

    # If we are implementing special setups, the ppp_list needs
    # to be updated so the POSCAR and POTCAR can be written correctly.
    if 'setups' in changed_parameters.keys():
        self.sort_atoms(self.atoms)

    # we don't consider None values to be changed if the keyword was
    # not originally in the parameters.
    cp = {k: v for k, v in changed_parameters.iteritems()
          if v is not None and k not in original_params}

    if cp != {}:
        log.debug('resetting because {} changed.'.format(cp))
        self.reset()
    return changed_parameters
예제 #11
0
def set(self, **kwargs):
    """Set parameters with keyword=value pairs.

    calc.set(xc='PBE')

    A few special kwargs are handled separately to expand them
    prior to setting the parameters. This is done to enable one
    set to track changes.

    """
    log.debug('Setting {}'.format(kwargs))
    if 'xc' in kwargs:
        kwargs.update(self.set_xc_dict(kwargs['xc']))

    if 'ispin' in kwargs:
        kwargs.update(self.set_ispin_dict(kwargs['ispin']))

    if 'ldau_luj' in kwargs:
        kwargs.update(self.set_ldau_luj_dict(kwargs['ldau_luj']))

    if 'nsw' in kwargs:
        kwargs.update(self.set_nsw_dict(kwargs['nsw']))

    original_params = self.parameters

    changed_parameters = FileIOCalculator.set(self, **kwargs)

    # we don't consider None values to be changed if the keyword was
    # not originally in the parameters.
    cp = {k: v for k, v in changed_parameters.iteritems()
          if v is not None and k not in original_params}

    if cp != {}:
        log.debug('resetting because {} changed.'.format(cp))
        self.reset()
    return changed_parameters
예제 #12
0
    def sort_atoms(self, atoms=None):
        """Generate resort list, and make list of POTCARs to use.

        Returns None.

        """
        self.resort = None
        self.ppp_list = None
        self.symbol_count = None

        if atoms is None:
            log.debug('Atoms was none.')
            return
        self.atoms = atoms

        # Now we sort the atoms and generate the list of POTCARS
        # We end up with ppp = [(index_or_symbol, potcar_file, count)]
        # and resort_indices
        setups = self.parameters.get('setups', [])
        pp = self.parameters['pp']

        ppp = []  # [(index_or_symbol, potcar_file, count)]

        # indices of original atoms needed to make sorted atoms list
        sort_indices = []

        # First the numeric index setups
        for setup in [x for x in setups if isinstance(x[0], int)]:
            ppp += [[setup[0],
                     'potpaw_{}/{}{}/POTCAR'.format(pp, atoms[setup[0]].symbol,
                                                    setup[1]),
                     1]]
            sort_indices += [setup[0]]

        # now the rest of the setups. These are atom symbols
        for setup in [x for x in setups if not isinstance(x[0], int)]:
            symbol = setup[0]
            count = 0
            for i, atom in enumerate(atoms):
                if atom.symbol == symbol and i not in sort_indices:
                    count += 1
                    sort_indices += [i]

            ppp += [[symbol,
                     'potpaw_{}/{}{}/POTCAR'.format(pp, symbol, setup[1]),
                     count]]
        # now the remaining atoms use default potentials
        # First get the chemical symbols that remain
        symbols = []
        for atom in atoms or []:
            if (atom.symbol not in symbols and
                atom.symbol not in [x[0] for x in ppp]):
                symbols += [atom.symbol]

        for symbol in symbols:
            count = 0
            for i, atom in enumerate(atoms):
                if atom.symbol == symbol and i not in sort_indices:
                    sort_indices += [i]
                    count += 1
            if count > 0:
                ppp += [[symbol,
                         'potpaw_{}/{}/POTCAR'.format(pp, symbol),
                         count]]

        assert len(sort_indices) == len(atoms), \
            'Sorting error. sort_indices={}'.format(sort_indices)

        assert sum([x[2] for x in ppp]) == len(atoms)
        self.sort = sort_indices

        # This list is used to convert Vasp ordering back to the
        # user-defined order.
        self.resort = [k[1] for k in
                       sorted([[j, i] for i, j in enumerate(sort_indices)])]

        # June 23, 2016. Jake Boes found a bug in how sorting is
        # done. We fixed it, but the fix is not backwards compatible
        # with the old resort we stored in DB.db. It appears we can
        # detect an old case if there is inconsistency with what is
        # stored and calculated here.  We check here to see if we are
        # consistent, and if not fix the issue. This should only occur
        # once.
        if (self.resort is not None
            and self.get_db('resort') is not None
            and self.resort != list(self.get_db('resort'))):
            ns =  [k[1] for k in
                   sorted([[j, i]
                           for i, j in enumerate(self.get_db('resort'))])]
            from ase.db import connect
            with connect(os.path.join(self.directory, 'DB.db')) as con:
                tatoms = con.get_atoms(id=1)
            self.write_db(atoms=tatoms, data={'resort': ns})
            print('Fixed resort issue in {}. '
                  'You should not see this message'
                  ' again'.format(self.directory))
            self.resort = ns
            sort_indices = [k[1] for k in
                            sorted([[j, i]
                                    for i, j in enumerate(ns)])]

        self.ppp_list = ppp
        self.atoms_sorted = atoms[sort_indices]
        self.symbol_count = [(x[0] if isinstance(x[0], str)
                              else atoms[x[0]].symbol,
                              x[2]) for x in ppp]
예제 #13
0
파일: vasp_core.py 프로젝트: yuang880/vasp
    def check_state(self, atoms=None):
        """Check if any changes exist that require new calculations."""
        if atoms is None:
            atoms = self.get_atoms()

        log.debug('atoms IMM: {}'.format(atoms.get_initial_magnetic_moments()))
        system_changes = FileIOCalculator.check_state(self, atoms)
        # Ignore boundary conditions:
        if 'pbc' in system_changes:
            system_changes.remove('pbc')

        s = 'FileIOCalculator reports these changes: {}'
        log.debug(s.format(system_changes))
        # if dir is empty, there is nothing to read here.
        if self.get_state() == Vasp.EMPTY:
            return system_changes

        # Check if the parameters have changed
        file_params = {}
        file_params.update(self.read_incar())

        if 'rwigs' in file_params:
            # This gets read as a list.
            with open(self.potcar) as f:
                lines = f.readlines()

            # symbols are in the # FIXME: first line of each potcar
            symbols = [lines[0].split()[1]]
            for i, line in enumerate(lines):
                if 'End of Dataset' in line and i != len(lines) - 1:
                    symbols += [lines[i + 1].split()[1]]

            file_params['rwigs'] = dict(zip(symbols, file_params['rwigs']))
        file_params.update(self.read_potcar())
        file_params.update(self.read_kpoints())

        xc_keys = sorted(Vasp.xc_defaults,
                         key=lambda k: len(Vasp.xc_defaults[k]),
                         reverse=True)

        for ex in xc_keys:
            pd = {k: file_params.get(k, None) for k in Vasp.xc_defaults[ex]}
            if pd == Vasp.xc_defaults[ex]:
                file_params['xc'] = ex.lower()
                break

        # reconstruct ldau_luj if necessary
        if 'ldauu' in file_params:
            ldaul = file_params['ldaul']
            ldauj = file_params['ldauj']
            ldauu = file_params['ldauu']

            with open(self.potcar) as f:
                lines = f.readlines()

            # symbols are in the first line of each potcar
            symbols = [lines[0].split()[1]]
            for i, line in enumerate(lines):
                if 'End of Dataset' in line and i != len(lines) - 1:
                    symbols += [lines[i + 1].split()[1]]

            ldau_luj = {}
            for sym, l, j, u in zip(symbols, ldaul, ldauj, ldauu):
                ldau_luj[sym] = {'L': l, 'U': u, 'J': j}

            file_params['ldau_luj'] = ldau_luj

        if not {k: v
                for k, v in self.parameters.iteritems()
                if v is not None} == file_params:
            new_keys = set(self.parameters.keys()) - set(file_params.keys())
            missing_keys = (set(file_params.keys()) -
                            set(self.parameters.keys()))
            log.debug('New keys: {}'.format(new_keys))
            log.debug('Missing keys: {}'.format(missing_keys))
            log.debug('params_on_file do not match.')
            log.debug('file-params: {}'.format(file_params))
            log.debug('compared to: {}'.format({
                k: v
                for k, v in self.parameters.iteritems() if v is not None
            }))
            system_changes += ['params_on_file']

        log.debug('System changes: {}'.format(system_changes))
        return system_changes
예제 #14
0
파일: vasp_core.py 프로젝트: yuang880/vasp
 def reset(self):
     """overwrite to avoid killing self.atoms."""
     log.debug('Resetting calculator.')
     self.results = {}
예제 #15
0
파일: vasp_core.py 프로젝트: yuang880/vasp
    def sort_atoms(self, atoms=None):
        """Generate resort list, and make list of POTCARs to use.

        Returns None.

        """
        self.resort = None
        self.ppp_list = None
        self.symbol_count = None

        if atoms is None:
            log.debug('Atoms was none.')
            return
        self.atoms = atoms

        # Now we sort the atoms and generate the list of POTCARS
        # We end up with ppp = [(index_or_symbol, potcar_file, count)]
        # and resort_indices
        setups = self.parameters.get('setups', [])
        pp = self.parameters['pp']

        ppp = []  # [(index_or_symbol, potcar_file, count)]

        # indices of original atoms needed to make sorted atoms list
        sort_indices = []

        # First the numeric index setups
        for setup in [x for x in setups if isinstance(x[0], int)]:
            ppp += [[setup[1], 'potpaw_{}/{}/POTCAR'.format(pp, setup[1]), 1]]
            sort_indices += [setup[0]]

        # now the rest of the setups. These are atom symbols
        for setup in [x for x in setups if not isinstance(x[0], int)]:
            symbol = setup[0]
            count = 0
            for i, atom in enumerate(atoms):
                if atom.symbol == symbol and i not in sort_indices:
                    count += 1
                    sort_indices += [i]

            ppp += [[
                symbol, 'potpaw_{}/{}{}/POTCAR'.format(pp, symbol, setup[1]),
                count
            ]]
        # now the remaining atoms use default potentials
        # First get the chemical symbols that remain
        symbols = []
        for atom in atoms or []:
            if atom.symbol not in symbols:
                symbols += [atom.symbol]

        for symbol in symbols:
            count = 0
            for i, atom in enumerate(atoms):
                if atom.symbol == symbol and i not in sort_indices:
                    sort_indices += [i]
                    count += 1
            if count > 0:
                ppp += [[
                    symbol, 'potpaw_{}/{}/POTCAR'.format(pp, symbol), count
                ]]

        assert len(sort_indices) == len(atoms), \
            'Sorting error. sort_indices={}'.format(sort_indices)

        assert sum([x[2] for x in ppp]) == len(atoms)
        self.sort = sort_indices

        # This list is used to convert Vasp ordering back to the
        # user-defined order.
        self.resort = [
            k[1] for k in sorted([[j, i] for i, j in enumerate(sort_indices)])
        ]

        # June 23, 2016. Jake Boes found a bug in how sorting is
        # done. We fixed it, but the fix is not backwards compatible
        # with the old resort we stored in DB.db. It appears we can
        # detect an old case if there is inconsistency with what is
        # stored and calculated here.  We check here to see if we are
        # consistent, and if not fix the issue. This should only occur
        # once.
        if (self.resort is not None and self.get_db('resort') is not None
                and self.resort != list(self.get_db('resort'))):
            ns = [
                k[1]
                for k in sorted([[j, i]
                                 for i, j in enumerate(self.get_db('resort'))])
            ]
            from ase.db import connect
            with connect(os.path.join(self.directory, 'DB.db')) as con:
                tatoms = con.get_atoms(id=1)
            self.write_db(atoms=tatoms, data={'resort': ns})
            print('Fixed resort issue in {}. '
                  'You should not see this message'
                  ' again'.format(self.directory))
            self.resort = ns
            sort_indices = [
                k[1] for k in sorted([[j, i] for i, j in enumerate(ns)])
            ]

        self.ppp_list = ppp
        self.atoms_sorted = atoms[sort_indices]
        self.symbol_count = [
            (x[0] if isinstance(x[0], str) else atoms[x[0]].symbol, x[2])
            for x in ppp
        ]
예제 #16
0
def get_neb(self, npi=1):
    """Returns images, energies if available or runs the job.

    npi = cores per image for running the calculations. Default=1

    show: if True show an NEB plot
    """
    if self.in_queue():
        return self.neb, [None for a in self.neb]

    calc_required = False

    # check for OUTCAR in each image dir
    for i in range(1, len(self.neb) - 1):
        wf = '{0}/OUTCAR'.format(str(i).zfill(2))
        wf = os.path.join(self.directory, wf)
        if not os.path.exists(wf):
            calc_required = True
            break
        else:
            # there was an OUTCAR, now we need to check for
            # convergence.
            done = False
            with open(wf) as f:
                for line in f:
                    if ('reached required accuracy - stopping structural'
                            ' energy minimisation') in line:
                        done = True
                        break
            if not done:
                calc_required = True
                break

    if calc_required:
        # this creates the directories and files if needed.  write out
        # all the images, including initial and final
        if not os.path.isdir(self.directory):
            os.makedirs(self.directory)

        self.set(images=len(self.neb) - 2)
        self.write_incar()
        self.write_kpoints()
        self.write_potcar()
        self.write_db()

        for i, atoms in enumerate(self.neb):
            # zero-padded directory name
            image_dir = os.path.join(self.directory, str(i).zfill(2))
            if not os.path.isdir(image_dir):
                # create if needed.
                os.makedirs(image_dir)
                write_vasp('{0}/POSCAR'.format(image_dir),
                           atoms[self.resort],
                           symbol_count=self.symbol_count)

        # The first and last images need to have real calculators on
        # them so we can write out a DB entry. We need this so we can
        # get the energies on the end-points. Otherwise, there doesn't
        # seem to be a way to do that short of cloning the whole
        # calculation into the end-point directories.

        self.write_db(os.path.join(self.directory, '00/DB.db'), self.neb[0])

        # print(self.neb)
        # import sys
        # sys.exit()
        self.write_db(
            os.path.join(self.directory,
                         '{:02}/DB.db'.format(len(self.neb) - 1)),
            self.neb[-1])

        VASPRC['queue.ppn'] = npi * (len(self.neb) - 2)
        log.debug('Running on %i cores', VASPRC['queue.ppn'])

        self.calculate()  # this will raise VaspSubmitted
        return self.neb, [None for a in self.neb]

    #############################################
    # now we are just retrieving results
    energies = []
    import ase.io
    atoms0 = ase.io.read(os.path.join(self.directory, '00', 'DB.db'))
    energies += [atoms0.get_potential_energy()]

    for i in range(1, len(self.neb) - 1):
        atoms = ase.io.read(
            os.path.join(self.directory,
                         str(i).zfill(2), 'CONTCAR'))[self.resort]
        self.neb[i].positions = atoms.positions
        self.neb[i].cell = atoms.cell

        energy = None
        with open(os.path.join(self.directory,
                               str(i).zfill(2), 'OUTCAR')) as f:
            for line in f:
                if 'free energy    TOTEN  =' in line:
                    energy = float(line.split()[4])

        energies += [energy]

    fname = os.path.join(self.directory, '0{}/DB.db'.format(len(self.neb) - 1))
    atoms_end = ase.io.read(fname)
    energies += [atoms_end.get_potential_energy()]

    energies = np.array(energies)
    energies -= energies[0]

    return (self.neb, np.array(energies))
예제 #17
0
    def check_state(self, atoms=None):
        """Check if any changes exist that require new calculations."""
        if atoms is None:
            atoms = self.get_atoms()

        log.debug('atoms IMM: {}'.format(atoms.get_initial_magnetic_moments()))
        system_changes = FileIOCalculator.check_state(self, atoms)
        # Ignore boundary conditions:
        if 'pbc' in system_changes:
            system_changes.remove('pbc')

        s = 'FileIOCalculator reports these changes: {}'
        log.debug(s.format(system_changes))
        # if dir is empty, there is nothing to read here.
        if self.get_state() == Vasp.EMPTY:
            return system_changes

        # Check if the parameters have changed
        file_params = {}
        file_params.update(self.read_incar())
        file_params.update(self.read_potcar())
        file_params.update(self.read_kpoints())

        xc_keys = sorted(Vasp.xc_defaults,
                         key=lambda k: len(Vasp.xc_defaults[k]),
                         reverse=True)

        for ex in xc_keys:
            pd = {k: file_params.get(k, None)
                  for k in Vasp.xc_defaults[ex]}
            if pd == Vasp.xc_defaults[ex]:
                file_params['xc'] = ex.lower()
                break

        # reconstruct ldau_luj if necessary
        if 'ldauu' in file_params:
            ldaul = file_params['ldaul']
            ldauj = file_params['ldauj']
            ldauu = file_params['ldauu']

            with open(self.potcar) as f:
                lines = f.readlines()

            # symbols are in the first line of each potcar
            symbols = [lines[0].split()[1]]
            for i, line in enumerate(lines):
                if 'End of Dataset' in line and i != len(lines) - 1:
                    symbols += [lines[i + 1].split()[1]]

            ldau_luj = {}
            for sym, l, j, u in zip(symbols, ldaul, ldauj, ldauu):
                ldau_luj[sym] = {'L': l, 'U': u, 'J': j}

            file_params['ldau_luj'] = ldau_luj

        if not {k: v for k, v in self.parameters.iteritems()
                if v is not None} == file_params:
            new_keys = set(self.parameters.keys()) - set(file_params.keys())
            missing_keys = (set(file_params.keys()) -
                            set(self.parameters.keys()))
            log.debug('New keys: {}'.format(new_keys))
            log.debug('Missing keys: {}'.format(missing_keys))
            log.debug('params_on_file do not match.')
            log.debug('file-params: {}'.format(file_params))
            log.debug('compared to: {}'.format({k: v for k, v in
                                                self.parameters.iteritems()
                                                if v is not None}))
            system_changes += ['params_on_file']

        log.debug('System changes: {}'.format(system_changes))
        return system_changes
예제 #18
0
 def reset(self):
     """overwrite to avoid killing self.atoms."""
     log.debug('Resetting calculator.')
     self.results = {}
예제 #19
0
파일: runner.py 프로젝트: yuang880/vasp
def calculate(self, atoms=None, properties=['energy'],
              system_changes=None):
    """Monkey patch to submit job through the queue.
    If this is called, then the calculator thinks a job should be run.
    If we are in the queue, we should run it, otherwise, a job should
    be submitted.
    """
    log.debug('In queue: {}'.format(self.in_queue()))
    if self.in_queue():
        raise VaspQueued('{} Queued: {}'.format(self.directory,
                                                self.get_db('jobid')))

    if VASPRC['mode'] is None:
        log.debug('mode is None. not running')
        return

    if (not self.calculation_required(atoms, ['energy'])
        and not self.check_state()):
        print('No calculation_required.')
        self.read_results()
        return

    # The subclass implementation should first call this
    # implementation to set the atoms attribute.
    Calculator.calculate(self, atoms, properties, system_changes)

    self.write_input(atoms, properties, system_changes)
    if self.parameters.get('luse_vdw', False):
        kernel = os.path.join(self.directory, 'vdw_kernel.bindat')
        if not os.path.exists(kernel):
            os.symlink(VASPRC['vdw_kernel.bindat'], kernel)

    # if we are in the queue and vasp is called or if we want to use
    # mode='run' , we should just run the job. First, we consider how.
    if 'PBS_O_WORKDIR' in os.environ or VASPRC['mode'] == 'run':
        if 'PBS_NODEFILE' in os.environ:
            # we are in the queue. determine if we should run serial
            # or parallel
            NPROCS = len(open(os.environ['PBS_NODEFILE']).readlines())
            log.debug('Found {0} PROCS'.format(NPROCS))
            if NPROCS == 1:
                # no question. running in serial.
                vaspcmd = VASPRC['vasp.executable.serial']
                log.debug('NPROCS = 1. running in serial')
                exitcode = os.system(vaspcmd)
                return exitcode
            else:
                # vanilla MPI run. multiprocessing does not work on more
                # than one node, and you must specify in VASPRC to use it
                if (VASPRC['queue.nodes'] > 1
                    or (VASPRC['queue.nodes'] == 1
                        and VASPRC['queue.ppn'] > 1
                        and (VASPRC['multiprocessing.cores_per_process']
                             == 'None'))):
                    s = 'queue.nodes = {0}'.format(VASPRC['queue.nodes'])
                    log.debug(s)
                    log.debug('queue.ppn = {0}'.format(VASPRC['queue.ppn']))
                    mpc = VASPRC['multiprocessing.cores_per_process']
                    log.debug('multiprocessing.cores_per_process'
                              '= {0}'.format(mpc))
                    log.debug('running vanilla MPI job')

                    log.debug('MPI NPROCS = {}'.format(NPROCS))
                    vaspcmd = VASPRC['vasp.executable.parallel']
                    parcmd = 'mpirun -np %i %s' % (NPROCS, vaspcmd)
                    exitcode = os.system(parcmd)
                    return exitcode
                else:
                    # we need to run an MPI job on cores_per_process
                    if VASPRC['multiprocessing.cores_per_process'] == 1:
                        log.debug('running single core multiprocessing job')
                        vaspcmd = VASPRC['vasp.executable.serial']
                        exitcode = os.system(vaspcmd)
                    elif VASPRC['multiprocessing.cores_per_process'] > 1:
                        log.debug('running mpi multiprocessing job')
                        NPROCS = VASPRC['multiprocessing.cores_per_process']

                        vaspcmd = VASPRC['vasp.executable.parallel']
                        parcmd = 'mpirun -np %i %s' % (NPROCS, vaspcmd)
                        exitcode = os.system(parcmd)
                        return exitcode
        else:
            # probably running at cmd line, in serial.
            try:
                cwd = os.getcwd()
                os.chdir(self.directory)
                vaspcmd = VASPRC['vasp.executable.serial']
                status, output, err = getstatusoutput(vaspcmd,
                                                      stdout=subprocess.PIPE,
                                                      stderr=subprocess.PIPE)
                if status == 0:
                    self.read_results()
                    return True
                else:
                    return output
            finally:
                os.chdir(cwd)
        # end

    # if you get here, a job is getting submitted
    CWD = os.getcwd()
    VASPDIR = self.directory
    script = """
#!/bin/bash
cd {CWD}  # this is the current working directory
cd {VASPDIR}  # this is the vasp directory
runvasp.py     # this is the vasp command
#end""".format(**locals())

    jobname = VASPDIR
    log.debug('{0} will be the jobname.'.format(jobname))
    log.debug('-l nodes={0}:ppn={1}'.format(VASPRC['queue.nodes'],
                                            VASPRC['queue.ppn']))

    cmdlist = ['{0}'.format(VASPRC['queue.command'])]
    cmdlist += ['-o', VASPDIR]
    cmdlist += [option for option in VASPRC['queue.options'].split()]
    cmdlist += ['-N', '{0}'.format(jobname),
                '-l', 'walltime={0}'.format(VASPRC['queue.walltime']),
                '-l', 'nodes={0}:ppn={1}'.format(VASPRC['queue.nodes'],
                                              VASPRC['queue.ppn']),
                '-l', 'mem={0}'.format(VASPRC['queue.mem'])]
    log.debug('{0}'.format(' '.join(cmdlist)))
    p = subprocess.Popen(cmdlist,
                         stdin=subprocess.PIPE,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)

    log.debug(script)

    out, err = p.communicate(script)

    if out == '' or err != '':
        raise Exception('something went wrong in qsub:\n\n{0}'.format(err))

    self.write_db(data={'jobid': out.strip()})

    raise VaspSubmitted('{} submitted: {}'.format(self.directory,
                                                  out.strip()))
예제 #20
0
def calculate(self, atoms=None, properties=['energy'],
              system_changes=None):
    """Monkey patch to submit job through the queue.
    If this is called, then the calculator thinks a job should be run.
    If we are in the queue, we should run it, otherwise, a job should
    be submitted.
    """
    log.debug('In queue: {}'.format(self.in_queue()))
    if self.in_queue():
        raise VaspQueued('{} Queued: {}'.format(self.directory,
                                                self.get_db('jobid')))

    if VASPRC['mode'] is None:
        log.debug('mode is None. not running')
        return

    if (not self.calculation_required(atoms, ['energy'])
        and not self.check_state()):
        print('No calculation_required.')
        self.read_results()
        return

    # The subclass implementation should first call this
    # implementation to set the atoms attribute.
    Calculator.calculate(self, atoms, properties, system_changes)

    self.write_input(atoms, properties, system_changes)
    if self.parameters.get('luse_vdw', False):
        kernel = os.path.join(self.directory, 'vdw_kernel.bindat')
        if not os.path.exists(kernel):
            os.symlink(VASPRC['vdw_kernel.bindat'], kernel)

    # if we are in the queue and vasp is called or if we want to use
    # mode='run' , we should just run the job. First, we consider how.
    if 'PBS_O_WORKDIR' in os.environ or VASPRC['mode'] == 'run':
        if 'PBS_NODEFILE' in os.environ:
            # we are in the queue. determine if we should run serial
            # or parallel
            NPROCS = len(open(os.environ['PBS_NODEFILE']).readlines())
            log.debug('Found {0} PROCS'.format(NPROCS))
            if NPROCS == 1:
                # no question. running in serial.
                vaspcmd = VASPRC['vasp.executable.serial']
                log.debug('NPROCS = 1. running in serial')
                exitcode = os.system(vaspcmd)
                return exitcode
            else:
                # vanilla MPI run. multiprocessing does not work on more
                # than one node, and you must specify in VASPRC to use it
                if (VASPRC['queue.nodes'] > 1
                    or (VASPRC['queue.nodes'] == 1
                        and VASPRC['queue.ppn'] > 1
                        and (VASPRC['multiprocessing.cores_per_process']
                             == 'None'))):
                    s = 'queue.nodes = {0}'.format(VASPRC['queue.nodes'])
                    log.debug(s)
                    log.debug('queue.ppn = {0}'.format(VASPRC['queue.ppn']))
                    mpc = VASPRC['multiprocessing.cores_per_process']
                    log.debug('multiprocessing.cores_per_process'
                              '= {0}'.format(mpc))
                    log.debug('running vanilla MPI job')

                    log.debug('MPI NPROCS = {}'.format(NPROCS))
                    vaspcmd = VASPRC['vasp.executable.parallel']
                    parcmd = 'mpirun -np %i %s' % (NPROCS, vaspcmd)
                    exitcode = os.system(parcmd)
                    return exitcode
                else:
                    # we need to run an MPI job on cores_per_process
                    if VASPRC['multiprocessing.cores_per_process'] == 1:
                        log.debug('running single core multiprocessing job')
                        vaspcmd = VASPRC['vasp.executable.serial']
                        exitcode = os.system(vaspcmd)
                    elif VASPRC['multiprocessing.cores_per_process'] > 1:
                        log.debug('running mpi multiprocessing job')
                        NPROCS = VASPRC['multiprocessing.cores_per_process']

                        vaspcmd = VASPRC['vasp.executable.parallel']
                        parcmd = 'mpirun -np %i %s' % (NPROCS, vaspcmd)
                        exitcode = os.system(parcmd)
                        return exitcode
        else:
            # probably running at cmd line, in serial.
            try:
                cwd = os.getcwd()
                os.chdir(self.directory)
                vaspcmd = VASPRC['vasp.executable.serial']
                status, output, err = getstatusoutput(vaspcmd,
                                                      stdout=subprocess.PIPE,
                                                      stderr=subprocess.PIPE)
                if status == 0:
                    self.read_results()
                    return True
                else:
                    return output
            finally:
                os.chdir(cwd)
        # end

    # if you get here, a job is getting submitted
    CWD = os.getcwd()
    VASPDIR = self.directory
    script = """
#!/bin/bash
cd {CWD}  # this is the current working directory
cd {VASPDIR}  # this is the vasp directory
runvasp.py     # this is the vasp command
#end""".format(**locals())

    jobname = VASPDIR
    log.debug('{0} will be the jobname.'.format(jobname))
    log.debug('-l nodes={0}:ppn={1}'.format(VASPRC['queue.nodes'],
                                            VASPRC['queue.ppn']))

    cmdlist = ['{0}'.format(VASPRC['queue.command'])]
    cmdlist += ['-o', VASPDIR]
    cmdlist += [option for option in VASPRC['queue.options'].split()]
    cmdlist += ['-N', '{0}'.format(jobname),
                '-l walltime={0}'.format(VASPRC['queue.walltime']),
                '-l nodes={0}:ppn={1}'.format(VASPRC['queue.nodes'],
                                              VASPRC['queue.ppn']),
                '-l mem={0}'.format(VASPRC['queue.mem'])]
    log.debug('{0}'.format(' '.join(cmdlist)))
    p = subprocess.Popen(cmdlist,
                         stdin=subprocess.PIPE,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)

    log.debug(script)

    out, err = p.communicate(script)

    if out == '' or err != '':
        raise Exception('something went wrong in qsub:\n\n{0}'.format(err))

    self.write_db(data={'jobid': out.strip()})

    raise VaspSubmitted('{} submitted: {}'.format(self.directory,
                                                  out.strip()))
예제 #21
0
파일: neb.py 프로젝트: jkitchin/vasp
def get_neb(self, npi=1):
    """Returns images, energies if available or runs the job.

    npi = cores per image for running the calculations. Default=1

    show: if True show an NEB plot
    """
    if self.in_queue():
        return self.neb, [None for a in self.neb]

    calc_required = False

    # check for OUTCAR in each image dir
    for i in range(1, len(self.neb) - 1):
        wf = '{0}/OUTCAR'.format(str(i).zfill(2))
        wf = os.path.join(self.directory, wf)
        if not os.path.exists(wf):
            calc_required = True
            break
        else:
            # there was an OUTCAR, now we need to check for
            # convergence.
            done = False
            with open(wf) as f:
                for line in f:
                    if ('reached required accuracy - stopping structural'
                        ' energy minimisation') in line:
                        done = True
                        break
            if not done:
                calc_required = True
                break

    if calc_required:
        # this creates the directories and files if needed.  write out
        # all the images, including initial and final
        if not os.path.isdir(self.directory):
            os.makedirs(self.directory)

        self.set(images=len(self.neb) - 2)
        self.write_incar()
        self.write_kpoints()
        self.write_potcar()
        self.write_db()

        for i, atoms in enumerate(self.neb):
            # zero-padded directory name
            image_dir = os.path.join(self.directory, str(i).zfill(2))
            if not os.path.isdir(image_dir):
                # create if needed.
                os.makedirs(image_dir)
                write_vasp('{0}/POSCAR'.format(image_dir),
                           atoms[self.resort],
                           symbol_count=self.symbol_count)

        # The first and last images need to have real calculators on
        # them so we can write out a DB entry. We need this so we can
        # get the energies on the end-points. Otherwise, there doesn't
        # seem to be a way to do that short of cloning the whole
        # calculation into the end-point directories.

        self.write_db(os.path.join(self.directory,
                                   '00/DB.db'),
                      self.neb[0])

        # print(self.neb)
        # import sys
        # sys.exit()
        self.write_db(os.path.join(self.directory,
                                   '{:02}/DB.db'.format(len(self.neb) - 1)),
                      self.neb[-1])

        VASPRC['queue.ppn'] = npi * (len(self.neb) - 2)
        log.debug('Running on %i cores', VASPRC['queue.ppn'])

        self.calculate()  # this will raise VaspSubmitted
        return self.neb, [None for a in self.neb]

    #############################################
    # now we are just retrieving results
    energies = []
    import ase.io
    atoms0 = ase.io.read(os.path.join(self.directory,
                                      '00',
                                      'DB.db'))
    energies += [atoms0.get_potential_energy()]

    for i in range(1, len(self.neb) - 1):
        atoms = ase.io.read(os.path.join(self.directory,
                                         str(i).zfill(2),
                                         'CONTCAR'))[self.resort]
        self.neb[i].positions = atoms.positions
        self.neb[i].cell = atoms.cell

        energy = None
        with open(os.path.join(self.directory,
                               str(i).zfill(2),
                               'OUTCAR')) as f:
            for line in f:
                if 'free energy    TOTEN  =' in line:
                    energy = float(line.split()[4])

        energies += [energy]

    fname = os.path.join(self.directory,
                         '0{}/DB.db'.format(len(self.neb) - 1))
    atoms_end = ase.io.read(fname)
    energies += [atoms_end.get_potential_energy()]

    energies = np.array(energies)
    energies -= energies[0]

    return (self.neb, np.array(energies))