示例#1
0
    def to_atom_list(self, atoms=None):
        """
        Return list of atom indices that this Table represents.

        Indices returns are 0-based or 1-based depending on value of
        :func:`~quippy.get_fortran_indexing`.

        If `atoms` is not present, the Atoms object passed to
        Table.from_atom_indices is used, or an exception is raised if this
        Table was not created in that way.
        """
        if atoms is None:
            if not hasattr(self, 'atoms'):
                raise AttributeError(
                    'Table missing "atoms" attribute, probably' +
                    ' not created by Table.from_atom_indices()')
            atoms = self.atoms()
            if atoms is None:
                raise ValueError('weakref to Table.atoms has expired')

        if get_fortran_indexing():
            first_column = 1
        else:
            first_column = 0
        indices = self.int[first_column, :].copy()
        if not get_fortran_indexing():
            indices[:] -= 1
        return list(set(list(indices)))  # remove duplicates
示例#2
0
    def __getitem__(self, i):
        if not self.initialised:
            if self is self.parent.hysteretic_connect:
                self.calc_connect_hysteretic(self.parent)
            else:
                self.calc_connect(self.parent)

        distance = farray(0.0)
        diff = fzeros(3)
        cosines = fzeros(3)
        shift = fzeros(3, dtype=np.int32)

        res = []
        if not get_fortran_indexing():
            i = i + 1  # convert to 1-based indexing

        for n in frange(self.n_neighbours(i)):
            j = self.neighbour(self.parent, i, n, distance, diff, cosines,
                               shift)
            if not get_fortran_indexing():
                j = j - 1
            res.append(NeighbourInfo(j, distance, diff, cosines, shift))

        if get_fortran_indexing():
            res = farray(res)  # to give 1-based indexing
        return res
示例#3
0
    def from_atom_indices(cls,
                          atoms,
                          mask=None,
                          list=None,
                          force_fortran_indexing=True):
        """
        Construct a new Table containing atomic indices from a list or mask

        The new table will include 4 integer columns, for indices plus
        shifts, and is suitable for passing to bfs_step,
        construct_hysteretic_region, etc.

        If force_fortran_indexing is True (the default), all atom indices
        are converted to Fortran 1-based indexing.
        """
        orig_fortran_indexing = get_fortran_indexing()
        set_fortran_indexing(force_fortran_indexing)

        try:
            if mask is None and list is None:
                raise ValueError('Either mask or list must be present.')

            if list is not None and force_fortran_indexing and not orig_fortran_indexing:
                # we were given 0-based atom indices, convert to 1-based indices
                list = np.array(list) + 1

            if mask is not None:
                if len(mask) != len(atoms):
                    raise ValueError('size of mask must equal number of atoms')
                mask = mask.astype(bool)
                # use indexing style given by force_fortran_indexing
                list = atoms.indices[mask]

            self = cls(4, 0, 0, 0)
            self.append(blank_rows=len(list))
            self.int[:, :] = 0

            if get_fortran_indexing():
                first_column = 1
            else:
                first_column = 0
            self.int[first_column, :] = list

        finally:
            set_fortran_indexing(orig_fortran_indexing)

        self.atoms = weakref.ref(atoms)
        return self
示例#4
0
 def get_atom(self, i):
     """Return a dictionary containing the properties of the atom with
        index `i`. If fortran_indexing=True (the default), `i` should be in
        range 1..self.n, otherwise it should be in range 0..(self.n-1)."""
     if (get_fortran_indexing() and (i < 1 or i > self.n)) or \
         (not get_fortran_indexing() and (i < 0 or i > self.n-1)):
         raise IndexError('Atoms index out of range')
     atom = {}
     atom['_index'] = i
     atom['atoms'] = self
     for k in self.properties.keys():
         v = self.properties[k][..., i]
         if isinstance(v, np.ndarray):
             if v.dtype.kind == 'S':
                 v = ''.join(v).strip()
             elif v.shape == ():
                 v = v.item()
         atom[k.lower()] = v
     return atom
示例#5
0
文件: atomeye.py 项目: albapa/AtomEye
 def get_visible(self):
     """Return list of indices of atoms currently visible in this viewer."""
     indices = self._atomeye.get_visible()
     at = self.gcat()
     if np.any(indices > len(at)):
         # atoms duplicated due to narrow cell (n->small_cell_err_handler == 1)
         indices = list(set([idx % len(at) for idx in indices ]))
     if get_fortran_indexing():
         indices = [idx+1 for idx in indices]
     return indices
示例#6
0
 def get_visible(self):
     """Return list of indices of atoms currently visible in this viewer."""
     indices = self._atomeye.get_visible()
     at = self.gcat()
     if np.any(indices > len(at)):
         # atoms duplicated due to narrow cell (n->small_cell_err_handler == 1)
         indices = list(set([idx % len(at) for idx in indices]))
     if get_fortran_indexing():
         indices = [idx + 1 for idx in indices]
     return indices
示例#7
0
 def _get_array_shape(self, name):
     if name in ('int', 'real', 'logical'):
         if get_fortran_indexing():
             return (slice(None), slice(1, self.n))
         else:
             return (slice(None), slice(0, self.n))
     elif name == 'str':
         return (slice(None), slice(None), slice(1, self.n))
     else:
         return None
示例#8
0
    def _indices(self):
        """Return array of atoms indices

        If global ``fortran_indexing`` is True, returns FortranArray containing
        numbers 1..self.n.  Otherwise, returns a standard numpuy array
        containing numbers in range 0..(self.n-1)."""

        if get_fortran_indexing():
            return farray(list(frange(len(self))))
        else:
            return np.array(list(range(len(self))))
示例#9
0
    def get_array(self, key):
        "Return a _reference_ to an array stored in this Dictionary"""

        import _quippy, arraydata
        if key in self and self.get_type_and_size(key)[0] in Dictionary._array_types:
            a = arraydata.get_array(self._fpointer, _quippy.qp_dictionary_get_array, key)
            if get_fortran_indexing():
                a = FortranArray(a, parent=self)
            return a
        else:
            raise KeyError('Key "%s" does not correspond to an array entry' % key)
示例#10
0
文件: atomeye.py 项目: albapa/AtomEye
 def on_click(mod, iw, idx):
     if (mod,iw) not in viewers:
         raise RuntimeError('Unexpected module id %d or window id %d' % (mod, iw))
     self = viewers[(mod,iw)]
     at = self.gcat()
     
     if at is None:
         return
     if idx >= len(at):
         idx = idx % len(at)
     if get_fortran_indexing():
         idx = idx + 1 # atomeye uses zero based indices
     self._click_hook(at, idx)
示例#11
0
    def on_click(mod, iw, idx):
        if (mod, iw) not in viewers:
            raise RuntimeError('Unexpected module id %d or window id %d' %
                               (mod, iw))
        self = viewers[(mod, iw)]
        at = self.gcat()

        if at is None:
            return
        if idx >= len(at):
            idx = idx % len(at)
        if get_fortran_indexing():
            idx = idx + 1  # atomeye uses zero based indices
        self._click_hook(at, idx)
示例#12
0
 def __getattr__(self, name):
     if self.netcdf_file is not None:
         try:
             return self.netcdf_file.__getattr__(name)
         except AttributeError:
             try:
                 a = self.netcdf_file.variables[name][:]
                 if get_fortran_indexing():
                     a = farray(a)
                 return a
             except KeyError:
                 raise AttributeError('Attribute %s not found' % name)
     else:
         raise AttributeError('Attribute %s not found' % name)
示例#13
0
    def to_atom_mask(self, atoms=None):
        """
        Return mask for atom indices that this Table represents

        Result is either an array of an FortranArray, depending on
        value of :func:`~quippy.get_fortran_indexing`.

        If `atoms` is not present, the Atoms object passed to
        Table.from_atom_indices is used, or an exception is raised if this
        Table was not created in that way.
        """

        mask = np.zeros(len(atoms), dtype=bool)
        if get_fortran_indexing():
            mask = mask.view(FortranArray)
        mask[self.to_atom_list(atoms)] = True
        return mask
示例#14
0
文件: atomeye.py 项目: albapa/AtomEye
    def on_redraw(mod, iw):
        if (mod, iw) not in viewers:
            raise RuntimeError('Unexpected window id %d' % iw)
        self = viewers[(mod,iw)]

        # keep a reference to old atoms around so memory doesn't get free'd prematurely
        self._previous_atoms = self._current_atoms
        if self._previous_atoms is not None:
            self._exit_hook(self._previous_atoms)
        self._current_atoms = None
        
        if self.atoms is None:
            title = '(null)'
            n_atom = 0
            cell = None
            arrays = None
            redraw = 0
        else:
            name = 'Atoms'
            if hasattr(self._current_atoms, 'filename') and self._current_atoms.filename is not None:
                name = self._current_atoms.filename
            if hasattr(self._current_atoms, 'name') and self._current_atoms.name is not None:
                name = self._current_atoms.name
            self._current_atoms = self.gcat(update=True)
            if hasattr(self.atoms, '__iter__'):
                fmt = "%%0%dd" % ceil(log10(len(self.atoms)+1))
                title = '%s frame %s length %s' % (name, fmt % self._frame, fmt % len(self.atoms))
            else:
                title = name

            self._enter_hook(self._current_atoms)
            n_atom = len(self._current_atoms)

            cell = self._current_atoms.get_cell()
            pbc = self._current_atoms.get_pbc()
            pos = self._current_atoms.positions
            
            for i, p in enumerate(pbc):
                if not p:
                    cell[i,i] = max(cell[i,i], max(1.0, 2*(pos[:,i].max()-pos[:,i].min())))

            try:
                arrays = self._current_atoms.properties
            except AttributeError:
                arrays = {}
                for key,value in self._current_atoms.arrays.iteritems():
                    arrays[name_map.get(key,key)] = value

            redraw = 1 # FIXME, we should decide if we really have to redraw here

        if redraw and self.verbose:
            print '-'*len(title)
            print title
            print '-'*len(title)
            print 'Number of atoms: %d' % n_atom
            print 'Fortran indexing: %r' % get_fortran_indexing()
            print 'Unit cell:'
            print cell
            self._redraw_hook(self._current_atoms)
            print '\n'
            sys.stdout.flush()
        
        return (redraw, title, n_atom, cell, arrays)
示例#15
0
    def calculate(self, atoms, properties, system_changes):
        Calculator.calculate(self, atoms, properties, system_changes)

        # we will do the calculation in place, to minimise number of copies,
        # unless atoms is not a quippy Atoms
        if isinstance(atoms, Atoms):
            self.quippy_atoms = weakref.proxy(atoms)
        else:
            potlog.debug(
                'Potential atoms is not quippy.Atoms instance, copy forced!')
            self.quippy_atoms = Atoms(atoms)
        initial_arrays = self.quippy_atoms.arrays.keys()
        initial_info = self.quippy_atoms.info.keys()

        if properties is None:
            properties = ['energy', 'forces', 'stress']

        # Add any default properties
        properties = set(self.get_default_properties() + properties)

        if len(properties) == 0:
            raise RuntimeError('Nothing to calculate')

        if not self.calculation_required(atoms, properties):
            return

        args_map = {
            'energy': {
                'energy': None
            },
            'energies': {
                'local_energy': None
            },
            'forces': {
                'force': None
            },
            'stress': {
                'virial': None
            },
            'numeric_forces': {
                'force': 'numeric_force',
                'force_using_fd': True,
                'force_fd_delta': 1.0e-5
            },
            'stresses': {
                'local_virial': None
            },
            'elastic_constants': {},
            'unrelaxed_elastic_constants': {}
        }

        # list of properties that require a call to Potential.calc()
        calc_properties = [
            'energy', 'energies', 'forces', 'numeric_forces', 'stress',
            'stresses'
        ]

        # list of other properties we know how to calculate
        other_properties = ['elastic_constants', 'unrelaxed_elastic_constants']

        calc_args = {}
        calc_required = False
        for property in properties:
            if property in calc_properties:
                calc_required = True
                calc_args.update(args_map[property])
            elif property not in other_properties:
                raise RuntimeError(
                    "Don't know how to calculate property '%s'" % property)

        if calc_required:
            self.calc(self.quippy_atoms, args_str=dict_to_args_str(calc_args))

        if 'energy' in properties:
            self.results['energy'] = float(self.quippy_atoms.energy)
        if 'energies' in properties:
            self.results['energies'] = self.quippy_atoms.local_energy.copy(
            ).view(np.ndarray)
        if 'forces' in properties:
            self.results['forces'] = self.quippy_atoms.force.copy().view(
                np.ndarray).T
        if 'numeric_forces' in properties:
            self.results[
                'numeric_forces'] = self.quippy_atoms.numeric_force.copy(
                ).view(np.ndarray).T
        if 'stress' in properties:
            stress = -self.quippy_atoms.virial.copy().view(
                np.ndarray) / self.quippy_atoms.get_volume()
            # convert to 6-element array in Voigt order
            self.results['stress'] = np.array([
                stress[0, 0], stress[1, 1], stress[2, 2], stress[1, 2],
                stress[0, 2], stress[0, 1]
            ])
        if 'stresses' in properties:
            lv = np.array(self.quippy_atoms.local_virial)  # make a copy
            vol_per_atom = self.get(
                'vol_per_atom',
                self.quippy_atoms.get_volume() / len(atoms))
            if isinstance(vol_per_atom, basestring):
                vol_per_atom = self.quippy_atoms.arrays[vol_per_atom]
            self.results['stresses'] = -lv.T.reshape(
                (len(atoms), 3, 3), order='F') / vol_per_atom

        if 'elastic_constants' in properties:
            cij_dx = self.get('cij_dx', 1e-2)
            cij = fzeros((6, 6))
            self.calc_elastic_constants(self.quippy_atoms,
                                        fd=cij_dx,
                                        args_str=self.get_calc_args_str(),
                                        c=cij,
                                        relax_initial=False,
                                        return_relaxed=False)
            if not get_fortran_indexing():
                cij = cij.view(np.ndarray)
            self.results['elastic_constants'] = cij

        if 'unrelaxed_elastic_constants' in properties:
            cij_dx = self.get('cij_dx', 1e-2)
            c0ij = fzeros((6, 6))
            self.calc_elastic_constants(self.quippy_atoms,
                                        fd=cij_dx,
                                        args_str=self.get_calc_args_str(),
                                        c0=c0ij,
                                        relax_initial=False,
                                        return_relaxed=False)
            if not get_fortran_indexing():
                c0ij = c0ij.view(np.ndarray)
            self.results['unrelaxed_elastic_constants'] = c0ij

        # copy back any additional output data to results dictionary
        skip_keys = ['energy', 'force', 'virial', 'numeric_force']
        for key in self.quippy_atoms.arrays.keys():
            if key not in initial_arrays and key not in skip_keys:
                self.results[key] = self.quippy_atoms.arrays[key].copy()
        for key in self.quippy_atoms.info.keys():
            if key not in initial_info and key not in skip_keys:
                if isinstance(self.quippy_atoms.info[key], np.ndarray):
                    self.results[key] = self.quippy_atoms.info[key].copy()
                else:
                    self.results[key] = self.quippy_atoms.info[key]
示例#16
0
文件: atomeye.py 项目: albapa/AtomEye
 def find_atom(self, i):
     """
     Set the anchor to the atom with index `i`.
     """
     if get_fortran_indexing(): i = i-1
     self.run_command("find_atom %d" % i)
示例#17
0
 def find_atom(self, i):
     """
     Set the anchor to the atom with index `i`.
     """
     if get_fortran_indexing(): i = i - 1
     self.run_command("find_atom %d" % i)
示例#18
0
    def on_redraw(mod, iw):
        if (mod, iw) not in viewers:
            raise RuntimeError('Unexpected window id %d' % iw)
        self = viewers[(mod, iw)]

        # keep a reference to old atoms around so memory doesn't get free'd prematurely
        self._previous_atoms = self._current_atoms
        if self._previous_atoms is not None:
            self._exit_hook(self._previous_atoms)
        self._current_atoms = None

        if self.atoms is None:
            title = '(null)'
            n_atom = 0
            cell = None
            arrays = None
            redraw = 0
        else:
            name = 'Atoms'
            if hasattr(
                    self._current_atoms,
                    'filename') and self._current_atoms.filename is not None:
                name = self._current_atoms.filename
            if hasattr(self._current_atoms,
                       'name') and self._current_atoms.name is not None:
                name = self._current_atoms.name
            self._current_atoms = self.gcat(update=True)
            if hasattr(self.atoms, '__iter__'):
                fmt = "%%0%dd" % ceil(log10(len(self.atoms) + 1))
                title = '%s frame %s length %s' % (name, fmt % self._frame,
                                                   fmt % len(self.atoms))
            else:
                title = name

            self._enter_hook(self._current_atoms)
            n_atom = len(self._current_atoms)

            cell = self._current_atoms.get_cell()
            pbc = self._current_atoms.get_pbc()
            pos = self._current_atoms.positions

            for i, p in enumerate(pbc):
                if not p:
                    cell[i, i] = max(
                        cell[i, i],
                        max(1.0, 2 * (pos[:, i].max() - pos[:, i].min())))

            try:
                arrays = self._current_atoms.properties
            except AttributeError:
                arrays = {}
                for key, value in self._current_atoms.arrays.iteritems():
                    arrays[name_map.get(key, key)] = value

            redraw = 1  # FIXME, we should decide if we really have to redraw here

        if redraw and self.verbose:
            print '-' * len(title)
            print title
            print '-' * len(title)
            print 'Number of atoms: %d' % n_atom
            print 'Fortran indexing: %r' % get_fortran_indexing()
            print 'Unit cell:'
            print cell
            self._redraw_hook(self._current_atoms)
            print '\n'
            sys.stdout.flush()

        return (redraw, title, n_atom, cell, arrays)
示例#19
0
    def calculate(self, atoms, quantities=None):
        """
        Perform a calculation of `quantities` for `atoms` using this Potential.

        Automatically determines if a new calculation is required or if previous
        results are still appliciable (i.e. if the atoms haven't moved since last call)
        Called internally by :meth:`get_potential_energy`, :meth:`get_forces`, etc.
        """
        if quantities is None:
            quantities = ['energy', 'forces', 'stress']

        # Add any default quantities
        quantities = set(self.get_default_quantities() + quantities)

        if len(quantities) == 0:
            raise RuntimeError('Nothing to calculate')

        if not self.calculation_required(atoms, quantities):
            return

        args_map = {
            'energy': {
                'energy': None
            },
            'energies': {
                'local_energy': None
            },
            'forces': {
                'force': None
            },
            'stress': {
                'virial': None
            },
            'numeric_forces': {
                'force': 'numeric_force',
                'force_using_fd': True,
                'force_fd_delta': 1.0e-5
            },
            'stresses': {
                'local_virial': None
            },
            'elastic_constants': {},
            'unrelaxed_elastic_constants': {}
        }

        # list of quantities that require a call to Potential.calc()
        calc_quantities = [
            'energy', 'energies', 'forces', 'numeric_forces', 'stress',
            'stresses'
        ]

        # list of other quantities we know how to calculate
        other_quantities = ['elastic_constants', 'unrelaxed_elastic_constants']

        calc_args = {}
        calc_required = False
        for quantity in quantities:
            if quantity in calc_quantities:
                calc_required = True
                calc_args.update(args_map[quantity])
            elif quantity not in other_quantities:
                raise RuntimeError(
                    "Don't know how to calculate quantity '%s'" % quantity)

        if calc_required:
            self.calc(self.atoms, args_str=dict_to_args_str(calc_args))

        if 'energy' in quantities:
            self.energy = float(self.atoms.energy)
        if 'energies' in quantities:
            self.energies = self.atoms.local_energy.view(np.ndarray)
        if 'forces' in quantities:
            self.forces = self.atoms.force.view(np.ndarray).T
        if 'numeric_forces' in quantities:
            self.numeric_forces = self.atoms.numeric_force.view(np.ndarray).T
        if 'stress' in quantities:
            stress = -self.atoms.virial.view(
                np.ndarray) / self.atoms.get_volume()
            # convert to 6-element array in Voigt order
            self.stress = np.array([
                stress[0, 0], stress[1, 1], stress[2, 2], stress[1, 2],
                stress[0, 2], stress[0, 1]
            ])
        if 'stresses' in quantities:
            lv = np.array(self.atoms.local_virial)  # make a copy
            vol_per_atom = self.get('vol_per_atom',
                                    self.atoms.get_volume() / len(atoms))
            if isinstance(vol_per_atom, basestring):
                vol_per_atom = self.atoms.arrays[vol_per_atom]
            self.stresses = -lv.T.reshape(
                (len(atoms), 3, 3), order='F') / vol_per_atom

        if 'elastic_constants' in quantities:
            cij_dx = self.get('cij_dx', 1e-2)
            cij = fzeros((6, 6))
            self.calc_elastic_constants(self.atoms,
                                        fd=cij_dx,
                                        args_str=self.get_calc_args_str(),
                                        c=cij,
                                        relax_initial=False,
                                        return_relaxed=False)
            if not get_fortran_indexing():
                cij = cij.view(np.ndarray)
            self.elastic_constants = cij

        if 'unrelaxed_elastic_constants' in quantities:
            cij_dx = self.get('cij_dx', 1e-2)
            c0ij = fzeros((6, 6))
            self.calc_elastic_constants(self.atoms,
                                        fd=cij_dx,
                                        args_str=self.get_calc_args_str(),
                                        c0=c0ij,
                                        relax_initial=False,
                                        return_relaxed=False)
            if not get_fortran_indexing():
                c0ij = c0ij.view(np.ndarray)
            self.unrelaxed_elastic_constants = c0ij