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')
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)
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)
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