Exemple #1
0
def test_class_unit():
    assert np.allclose(units.convert('J', 'J', 'J'), 1)

    assert approx(units.convert('kg', 'g')) == 1.e3
    assert approx(units.convert('eV', 'J')) == 1.60217733e-19
    assert approx(units.convert('J', 'eV')) == 1/1.60217733e-19
    assert approx(units.convert('J^2', 'eV**2')) == (1/1.60217733e-19) ** 2
    assert approx(units.convert('J/2', 'eV/2')) == (1/1.60217733e-19)
    assert approx(units.convert('J', 'eV/2')) == (1/1.60217733e-19) * 2
    assert approx(units.convert('J2', '2eV')) == (1/1.60217733e-19)
    assert approx(units.convert('J2', 'eV')) == (1/1.60217733e-19) * 2
    assert approx(units.convert('J/m', 'eV/Ang')) == unit_convert('J', 'eV') / unit_convert('m', 'Ang')
    units('J**eV', 'eV**eV')
    units('J/m', 'eV/m')
Exemple #2
0
    def _r_geometry_omx(self, *args, **kwargs):
        """ Returns `Geometry` """
        sc = self.read_supercell(order=['omx'])

        na = self.get('Atoms.Number', default=0)
        conv = self.get('Atoms.SpeciesAndCoordinates.Unit', default='Ang')
        data = self.get('Atoms.SpeciesAndCoordinates')
        if data is None:
            raise SislError('Cannot find key: Atoms.SpeciesAndCoordinates')

        if na == 0:
            # Default to the size of the labels
            na = len(data)

        # Reduce to the number of atoms.
        data = data[:na]

        atoms = self.read_basis(order=['omx'])

        def find_atom(tag):
            if atoms is None:
                return Atom(tag)
            for atom in atoms:
                if atom.tag == tag:
                    return atom
            raise SislError(
                'Error when reading the basis for atomic tag: {}.'.format(tag))

        xyz = []
        atom = []
        for dat in data:
            d = dat.split()
            atom.append(find_atom(d[1]))
            xyz.append(list(map(float, dat.split()[2:5])))
        xyz = _a.arrayd(xyz)

        if conv == 'AU':
            xyz *= units('Bohr', 'Ang')
        elif conv == 'FRAC':
            xyz = np.dot(xyz, sc.cell)

        return Geometry(xyz, atom=atom, sc=sc)
Exemple #3
0
    def _r_supercell_omx(self, *args, **kwargs):
        """ Returns `SuperCell` object from the omx file """
        conv = self.get('Atoms.UnitVectors.Unit', default='Ang')
        if conv.upper() == 'AU':
            conv = units('Bohr', 'Ang')
        else:
            conv = 1.

        # Read in cell
        cell = np.empty([3, 3], np.float64)

        lc = self.get('Atoms.UnitVectors')
        if not lc is None:
            for i in range(3):
                cell[i, :] = [float(k) for k in lc[i].split()[:3]]
        else:
            raise SileError('Could not find Atoms.UnitVectors in file')
        cell *= conv

        return SuperCell(cell)
Exemple #4
0
        def _call(self, *args, **kwargs):
            data_axis = kwargs.pop('data_axis', None)
            grid_unit = kwargs.pop('grid_unit', 'b')

            func = getattr(self.parent, self._bz_attr)
            wrap = allow_kwargs('parent', 'k', 'weight')(kwargs.pop('wrap', _do_nothing))
            eta = tqdm_eta(len(self), self.__class__.__name__ + '.asgrid',
                           'k', kwargs.pop('eta', False))
            parent = self.parent
            k = self.k
            w = self.weight

            # Extract information from the MP grid, these values
            # define the Grid size, etc.
            diag = self._diag.copy()
            if not np.all(self._displ == 0):
                raise SislError(self.__class__.__name__ + '.{} requires the displacement to be 0 for all k-points.'.format(self._bz_attr))
            displ = self._displ.copy()
            size = self._size.copy()
            steps = size / diag
            if self._centered:
                offset = np.where(diag % 2 == 0, steps, steps / 2)
            else:
                offset = np.where(diag % 2 == 0, steps / 2, steps)

            # Instead of doing
            #    _in_primitive(k) + 0.5 - offset
            # we can do it here
            #    _in_primitive(k) + offset'
            offset -= 0.5

            # Check the TRS direction
            trs_axis = self._trs
            _in_primitive = self.in_primitive
            _rint = np.rint
            _int32 = np.int32
            def k2idx(k):
                # In case TRS is applied two indices may be returned
                return _rint((_in_primitive(k) - offset) / steps).astype(_int32)
                # To find the opposite k-point, do this
                #  idx[i] = [diag[i] - idx[i] - 1, idx[i]
                # with i in [0, 1, 2]

            # Create cell from the reciprocal cell.
            if grid_unit == 'b':
                cell = np.diag(self._size)
            else:
                cell = parent.sc.rcell * self._size.reshape(1, -1) / units('Ang', grid_unit)

            # Find the grid origo
            origo = -(cell * 0.5).sum(0)

            # Calculate first k-point (to get size and dtype)
            v = wrap(func(*args, k=k[0], **kwargs), parent=parent, k=k[0], weight=w[0])

            if data_axis is None:
                if v.size != 1:
                    raise SislError(self.__class__.__name__ + '.{} requires one value per-kpoint because of the 3D grid values'.format(self._bz_attr))

            else:

                # Check the weights
                weights = self.grid(diag[data_axis], displ[data_axis], size[data_axis],
                                    centered=self._centered, trs=trs_axis == data_axis)[1]

                # Correct the Grid size
                diag[data_axis] = len(v)
                # Create the orthogonal cell direction to ensure it is orthogonal
                # Since array axis is cyclic for negative numbers, we simply do this
                cell[data_axis, :] = cross(cell[data_axis-1, :], cell[data_axis-2, :])
                # Check whether we should rotate it
                if cart2spher(cell[data_axis, :])[2] > pi / 4:
                    cell[data_axis, :] *= -1

            # Correct cell for the grid
            if trs_axis >= 0:
                origo[trs_axis] = 0.
                # Correct offset since we only have the positive halve
                if self._diag[trs_axis] % 2 == 0 and not self._centered:
                    offset[trs_axis] = steps[trs_axis] / 2
                else:
                    offset[trs_axis] = 0.

                # Find number of points
                if trs_axis != data_axis:
                    diag[trs_axis] = len(self.grid(diag[trs_axis], displ[trs_axis], size[trs_axis],
                                                   centered=self._centered, trs=True)[1])

            # Create the grid in the reciprocal cell
            sc = SuperCell(cell, origo=origo)
            grid = Grid(diag, sc=sc, dtype=v.dtype)
            if data_axis is None:
                grid[k2idx(k[0])] = v
            else:
                idx = k2idx(k[0]).tolist()
                weight = weights[idx[data_axis]]
                idx[data_axis] = slice(None)
                grid[idx] = v * weight

            del v

            # Now perform calculation
            if data_axis is None:
                for i in range(1, len(k)):
                    grid[k2idx(k[i])] = wrap(func(*args, k=k[i], **kwargs),
                                             parent=parent, k=k[i], weight=w[i])
                    eta.update()
            else:
                for i in range(1, len(k)):
                    idx = k2idx(k[i]).tolist()
                    weight = weights[idx[data_axis]]
                    idx[data_axis] = slice(None)
                    grid[idx] = wrap(func(*args, k=k[i], **kwargs),
                                     parent=parent, k=k[i], weight=w[i]) * weight
                    eta.update()
            eta.close()
            return grid