def test_special_constructors(): for dtype in dtypes: for shape in some_shapes: assert ta.zeros(shape, dtype) == np.zeros(shape, dtype) assert ta.ones(shape, dtype) == np.ones(shape, dtype) for n in [0, 1, 2, 3, 17]: assert ta.identity(n, dtype) == np.identity(n, dtype)
def test_special_constructors(): for dtype in dtypes: for shape in some_shapes: assert_equal(ta.zeros(shape, dtype), np.zeros(shape, dtype)) assert_equal(ta.ones(shape, dtype), np.ones(shape, dtype)) for n in [0, 1, 2, 3, 17]: assert_equal(ta.identity(n, dtype), np.identity(n, dtype))
def find_rotamer_nearest(at_pos, idatm_type, atom, neighbor, check_dist): # find atom that approaches nearest to a methyl-type rotamer n_pos = neighbor._addh_coord v = at_pos - n_pos try: geom = type_info[idatm_type].geometry except KeyError: geom = 4 bond_len = bond_with_H_length(atom, geom) from numpy.linalg import norm v *= cos70_5 * bond_len / norm(v) center = at_pos + v from chimerax.geometry import Plane plane = Plane(center, normal=v) radius = sin70_5 * bond_len check_dist += radius nearby = search_tree.search(center, check_dist) near_pos = n = near_atom = None for nb in nearby: if nb._addh_coord in [at_pos, n_pos]: # exclude atoms from identical-copy structure also... continue if nb.structure != atom.structure and ( atom.structure.id is None or (len(nb.structure.id) > 1 and (nb.structure.id[:-1] == atom.structure.id[:-1])) or nb.structure in ident_pos_models[atom.structure]): # (1) unopen models only "clash" with themselves # (2) don't consider atoms in sibling submodels continue candidates = [(nb, vdw_radius(nb))] # only heavy atoms in tree... for nbb in nb.neighbors: if nbb.element.number != 1: continue if nbb == neighbor: continue candidates.append((nbb, h_rad)) from tinyarray import zeros all_zero = zeros(3) for candidate, a_rad in candidates: c_pos = candidate._addh_coord # project into plane... proj = plane.nearest(c_pos) # find nearest approach of circle... cv = proj - center if cv == all_zero: continue cv *= radius / norm(cv) app = center + cv d = norm(c_pos - app) - a_rad if near_pos is None or d < n: near_pos = c_pos n = d near_atom = candidate return near_pos, n, near_atom
def __init__(self, prim_vecs, offset=None, name='', norbs=None): prim_vecs = ta.array(prim_vecs, float) if prim_vecs.ndim != 2: raise ValueError('``prim_vecs`` must be a 2d array-like object.') dim = prim_vecs.shape[1] if name is None: name = '' if prim_vecs.shape[0] > dim: raise ValueError('Number of primitive vectors exceeds ' 'the space dimensionality.') if offset is None: offset = ta.zeros(dim) else: offset = ta.array(offset, float) if offset.shape != (dim, ): raise ValueError('Dimensionality of offset does not match ' 'that of the space.') msg = '{0}({1}, {2}, {3}, {4})' cl = self.__module__ + '.' + self.__class__.__name__ canonical_repr = msg.format(cl, short_array_repr(prim_vecs), short_array_repr(offset), repr(name), repr(norbs)) super().__init__(canonical_repr, name, norbs) self.sublattices = [self] self._prim_vecs = prim_vecs self.inv_pv = ta.array(np.linalg.pinv(prim_vecs)) self.offset = offset # Precalculation of auxiliary arrays for real space calculations. self.reduced_vecs, self.transf = lll.lll(prim_vecs) self.voronoi = ta.dot(lll.voronoi(self.reduced_vecs), self.transf) self.dim = dim self.lattice_dim = len(prim_vecs) if name != '': msg = "<Monatomic lattice {0}{1}>" orbs = ' with {0} orbitals'.format( self.norbs) if self.norbs else '' self.cached_str = msg.format(name, orbs) else: msg = "<unnamed Monatomic lattice, vectors {0}, origin [{1}]{2}>" orbs = ', with {0} orbitals'.format(norbs) if norbs else '' self.cached_str = msg.format(short_array_str(self._prim_vecs), short_array_str(self.offset), orbs)
def __init__(self, prim_vecs, offset=None, name='', norbs=None): prim_vecs = ta.array(prim_vecs, float) if prim_vecs.ndim != 2: raise ValueError('``prim_vecs`` must be a 2d array-like object.') dim = prim_vecs.shape[1] if name is None: name = '' if prim_vecs.shape[0] > dim: raise ValueError('Number of primitive vectors exceeds ' 'the space dimensionality.') if offset is None: offset = ta.zeros(dim) else: offset = ta.array(offset, float) if offset.shape != (dim,): raise ValueError('Dimensionality of offset does not match ' 'that of the space.') msg = '{0}({1}, {2}, {3}, {4})' cl = self.__module__ + '.' + self.__class__.__name__ canonical_repr = msg.format(cl, short_array_repr(prim_vecs), short_array_repr(offset), repr(name), repr(norbs)) super().__init__(canonical_repr, name, norbs) self.sublattices = [self] self._prim_vecs = prim_vecs self.inv_pv = ta.array(np.linalg.pinv(prim_vecs)) self.offset = offset # Precalculation of auxiliary arrays for real space calculations. self.reduced_vecs, self.transf = lll.lll(prim_vecs) self.voronoi = ta.dot(lll.voronoi(self.reduced_vecs), self.transf) self.dim = dim self.lattice_dim = len(prim_vecs) if name != '': msg = "<Monatomic lattice {0}{1}>" orbs = ' with {0} orbitals'.format(self.norbs) if self.norbs else '' self.cached_str = msg.format(name, orbs) else: msg = "<unnamed Monatomic lattice, vectors {0}, origin [{1}]{2}>" orbs = ', with {0} orbitals'.format(norbs) if norbs else '' self.cached_str = msg.format(short_array_str(self._prim_vecs), short_array_str(self.offset), orbs)
def test_sizeof(): obj = object() word_size = machine_wordsize() for shape in some_shapes: for dtype in dtypes: a = ta.zeros(shape, dtype) sizeof = a.__sizeof__() # basic buffer size n_elements = a.size # if the array is > 1D then the shape is stored # at the start of the buffer if len(a.shape) > 1: n_elements += (a.ndim * machine_wordsize() + dtype_size[dtype] - 1) // dtype_size[dtype] buffer_size = n_elements * dtype_size[dtype] # basic Python object has 3 pointer-sized members sizeof_should_be = buffer_size + 3 * machine_wordsize() print(dtype, shape) assert_equal(sizeof, sizeof_should_be)
def test_sizeof(): obj = object() word_size = machine_wordsize() for shape in some_shapes: for dtype in dtypes: a = ta.zeros(shape, dtype) sizeof = a.__sizeof__() # basic buffer size n_elements = a.size # if the array is > 1D then the shape is stored # at the start of the buffer if len(a.shape) > 1: n_elements += (a.ndim * machine_wordsize() + dtype_size[dtype] - 1) // dtype_size[dtype] buffer_size = n_elements * dtype_size[dtype] # A Basic Python object has 3 pointer-sized members, or 5 if in # debug mode. debug = hasattr(sys, "gettotalrefcount") sizeof_should_be = (buffer_size + machine_wordsize() * (5 if debug else 3)) assert sizeof == sizeof_should_be
def test_conversion(): for src_dtype in dtypes: for dest_dtype in dtypes: src = ta.zeros(3, src_dtype) tsrc = tuple(src) npsrc = np.array(tsrc) impossible = src_dtype is complex and dest_dtype in [int, float] for s in [src, tsrc, npsrc]: if impossible: raises(TypeError, ta.array, s, dest_dtype) else: dest = ta.array(s, dest_dtype) assert isinstance(dest[0], dest_dtype) assert src == dest # Check for overflow. long_overflow = [1e300, np.array([1e300])] # This check only works for Python 2. if 18446744073709551615 > sys.maxsize: long_overflow.extend([np.array([18446744073709551615], np.uint64), 18446744073709551615]) for s in long_overflow: raises(OverflowError, ta.array, s, int)
def test_conversion(): for src_dtype in dtypes: for dest_dtype in dtypes: src = ta.zeros(3, src_dtype) tsrc = tuple(src) npsrc = np.array(tsrc) impossible = src_dtype is complex and dest_dtype in [int, float] for s in [src, tsrc, npsrc]: if impossible: assert_raises(TypeError, ta.array, s, dest_dtype) else: dest = ta.array(s, dest_dtype) assert isinstance(dest[0], dest_dtype) assert_equal(src, dest) # Check for overflow. long_overflow = [1e300, np.array([1e300])] # This check only works for Python 2. if 18446744073709551615 > sys.maxsize: long_overflow.extend([np.array([18446744073709551615], np.uint64), 18446744073709551615]) for s in long_overflow: assert_raises(OverflowError, ta.array, s, int)
def test_ModesLead_and_SelfEnergyLead(): lat = builder.SimpleSiteFamily() hoppings = [ builder.HoppingKind((1, 0), lat), builder.HoppingKind((0, 1), lat) ] rng = Random(123) L = 5 t = 1 energies = [0.9, 1.7] syst = builder.Builder() for x in range(L): for y in range(L): syst[lat(x, y)] = 4 * t + rng.random() - 0.5 syst[hoppings] = -t # Attach a lead from the left. lead = builder.Builder(VerySimpleSymmetry(-1)) for y in range(L): lead[lat(0, y)] = 4 * t lead[hoppings] = -t syst.attach_lead(lead) # Make the right lead and attach it. lead = builder.Builder(VerySimpleSymmetry(1)) for y in range(L): lead[lat(0, y)] = 4 * t lead[hoppings] = -t syst.attach_lead(lead) fsyst = syst.finalized() ts = [kwant.smatrix(fsyst, e).transmission(1, 0) for e in energies] # Replace lead with it's finalized copy. lead = fsyst.leads[1] interface = [lat(L - 1, lead.sites[i].tag[1]) for i in range(L)] # Re-attach right lead as ModesLead. syst.leads[1] = builder.ModesLead(lead.modes, interface) fsyst = syst.finalized() ts2 = [kwant.smatrix(fsyst, e).transmission(1, 0) for e in energies] assert_almost_equal(ts2, ts) # Re-attach right lead as ModesLead with old-style modes API # that does not take a 'params' keyword parameter. syst.leads[1] = builder.ModesLead( lambda energy, args: lead.modes(energy, args), interface) fsyst = syst.finalized() ts2 = [kwant.smatrix(fsyst, e).transmission(1, 0) for e in energies] assert_almost_equal(ts2, ts) # Re-attach right lead as SelfEnergyLead. syst.leads[1] = builder.SelfEnergyLead(lead.selfenergy, interface) fsyst = syst.finalized() ts2 = [ kwant.greens_function(fsyst, e).transmission(1, 0) for e in energies ] assert_almost_equal(ts2, ts) # Re-attach right lead as SelfEnergyLead with old-style selfenergy API # that does not take a 'params' keyword parameter. syst.leads[1] = builder.SelfEnergyLead( lambda energy, args: lead.selfenergy(energy, args), interface) fsyst = syst.finalized() ts2 = [ kwant.greens_function(fsyst, e).transmission(1, 0) for e in energies ] assert_almost_equal(ts2, ts) # Append a virtual (=zero self energy) lead. This should have no effect. # Also verifies that the selfenergy callback function can return exotic # arraylikes. syst.leads.append( builder.SelfEnergyLead(lambda *args: list(ta.zeros((L, L))), interface)) fsyst = syst.finalized() ts2 = [ kwant.greens_function(fsyst, e).transmission(1, 0) for e in energies ] assert_almost_equal(ts2, ts)
def discretize_landau(hamiltonian, N, momenta=None, grid_spacing=1): """Discretize a Hamiltonian in a basis of Landau levels. Parameters ---------- hamiltonian : str or sympy expression N : positive integer The number of Landau levels in the basis. momenta : sequence of str (optional) The momenta defining the plane perpendicular to the magnetic field. If not provided, "k_x" and "k_y" are used. grid_spacing : float, default: 1 The grid spacing to use when discretizing the normal direction (parallel to the magnetic field). Returns ------- builder : `~kwant.builder.Builder` 'hamiltonian' discretized in a basis of Landau levels in the plane defined by 'momenta'. If a third coordinate is present in 'hamiltonian', then this also has a translational symmetry in that coordinate direction. The builder has a parameter 'B' in addition to any other parameters present in the provided 'hamiltonian'. Notes ----- The units of magnetic field are :math:`ϕ₀ / 2 π a²` with :math:`ϕ₀ = h/e` the magnetic flux quantum and :math:`a` the unit length. """ if N <= 0: raise ValueError("N must be positive") hamiltonian, momenta, normal_coordinate = to_landau_basis(hamiltonian, momenta) # Discretize in normal direction and split terms for onsites/hoppings into # monomials in ladder operators. tb_hamiltonian, _ = kwant.continuum.discretize_symbolic( hamiltonian, coords=[normal_coordinate.name] ) tb_hamiltonian = { key: kwant.continuum._common.monomials(value, gens=(ladder_lower, ladder_raise)) for key, value in tb_hamiltonian.items() } # Replace ladder operator monomials by tuple of integers: # e.g. a^\dagger a^2 -> (+1, -2). tb_hamiltonian = { outer_key: { _ladder_term(inner_key): inner_value for inner_key, inner_value in outer_value.items() } for outer_key, outer_value in tb_hamiltonian.items() } # Construct map from LandauLattice HoppingKinds to a sequence of pairs # that encode the ladder operators and multiplying expression. tb_hoppings = collections.defaultdict(list) for outer_key, outer_value in tb_hamiltonian.items(): for inner_key, inner_value in outer_value.items(): tb_hoppings[(*outer_key, sum(inner_key))] += [(inner_key, inner_value)] # Extract the number of orbitals on each site/hopping random_element = next(iter(tb_hoppings.values()))[0][1] norbs = 1 if isinstance(random_element, sympy.Expr) else random_element.shape[0] tb_onsite = tb_hoppings.pop((0, 0), None) # Construct Builder if _has_coordinate(normal_coordinate, hamiltonian): sym = kwant.lattice.TranslationalSymmetry([grid_spacing, 0]) else: sym = kwant.system.NoSymmetry() lat = LandauLattice(grid_spacing, norbs=norbs) syst = kwant.Builder(sym) # Add onsites landau_sites = (lat(0, j) for j in range(N)) if tb_onsite is None: syst[landau_sites] = ta.zeros((norbs, norbs)) else: syst[landau_sites] = _builder_value( tb_onsite, normal_coordinate.name, grid_spacing, is_onsite=True ) # Add zero hoppings between adjacent Landau levels. # Necessary to be able to use the Landau level builder # to populate another builder using builder.fill(). syst[kwant.builder.HoppingKind((0, 1), lat)] = ta.zeros((norbs, norbs)) # Add the hoppings from the Hamiltonian for hopping, parts in tb_hoppings.items(): syst[kwant.builder.HoppingKind(hopping, lat)] = _builder_value( parts, normal_coordinate.name, grid_spacing, is_onsite=False ) return syst
def neighbors(self, n=1, eps=1e-8): """Return n-th nearest neighbor hoppings. Parameters ---------- n : integer Order of the hoppings to return. Note that the zeroth neighbor is the site itself or any other sites with the same position. eps : float Tolerance relative to the length of the shortest lattice vector for when to consider lengths to be approximately equal. Returns ------- hoppings : list of kwant.builder.HopplingKind objects The n-th nearest neighbor hoppings. Notes ----- The hoppings are ordered lexicographically according to sublattice from which they originate, sublattice on which they end, and their lattice coordinates. Out of the two equivalent hoppings (a hopping and its reverse) only the lexicographically larger one is returned. """ # This algorithm is not designed to be fast and can be improved, # however there is no real need. Site = system.Site sls = self.sublattices shortest_hopping = sls[0].n_closest( sls[0].pos(([0] * sls[0].lattice_dim)), 2)[-1] rtol = eps eps *= np.linalg.norm(self.vec(shortest_hopping)) nvec = len(self._prim_vecs) sublat_pairs = [(i, j) for (i, j) in product(sls, sls) if sls.index(j) >= sls.index(i)] def first_nonnegative(tag): for i in tag: if i < 0: return False elif i > 0: return True else: continue return True # Find the `n` closest neighbors (with multiplicity) for each # pair of lattices, this surely includes the `n` closest neighbors overall. sites = [] for i, j in sublat_pairs: origin = Site(j, ta.zeros(nvec)).pos tags = i.n_closest(origin, n=n + 1, group_by_length=True, rtol=rtol) ij_dist = [ np.linalg.norm(Site(i, tag).pos - origin) for tag in tags ] sites.append((tags, (j, i), ij_dist)) distances = np.r_[tuple((i[2] for i in sites))] distances = np.sort(distances) group_boundaries = np.where(np.diff(distances) > eps)[0] # Find distance in `n`-th group. if len(group_boundaries) == n: n_dist = distances[-1] else: n_dist = distances[group_boundaries[n]] # We now have all the required sites, select the ones in `n`-th group. result = [] for group in sites: tags, distance = group[0], group[2] i, j = group[1] tags = np.array([ tag for tag, dist in zip(tags, distance) if abs(dist - n_dist) < eps ]) if len(tags): # Sort the tags. tags = tags[np.lexsort(tags.T[::-1])][::-1] # Throw away equivalent hoppings if # two sublattices are the same. if i == j and len(tags) > 1: tags = tags[:len(tags) // 2] for tag in tags: result.append(builder.HoppingKind(tag, j, i)) return result
def neighbors(self, n=1, eps=1e-8): """Return n-th nearest neighbor hoppings. Parameters ---------- n : integer Order of the hoppings to return. eps : float Tolerance relative to the length of the shortest lattice vector for when to consider lengths to be approximately equal. Returns ------- hoppings : list of kwant.builder.HopplingKind objects The n-th nearest neighbor hoppings. Notes ----- The hoppings are ordered lexicographically according to sublattice from which they originate, sublattice on which they end, and their lattice coordinates. Out of the two equivalent hoppings (a hopping and its reverse) only the lexicographically larger one is returned. """ # This algorithm is not designed to be fast and can be improved, # however there is no real need. Site = builder.Site sls = self.sublattices shortest_hopping = sls[0].n_closest( Site(sls[0], ([0] * sls[0].dim)).pos, 2)[-1] eps *= np.linalg.norm(self.vec(shortest_hopping)) nvec = len(self._prim_vecs) sublat_pairs = [(i, j) for (i, j) in product(sls, sls) if sls.index(j) >= sls.index(i)] def first_nonnegative(tag): for i in tag: if i < 0: return False elif i > 0: return True else: continue return True # Find the correct number of neighbors to calculate on each lattice. cutoff = n + 2 while True: max_dist = [] sites = [] for i, j in sublat_pairs: origin = Site(j, ta.zeros(nvec)).pos tags = i.n_closest(origin, n=cutoff**nvec) ij_dist = [np.linalg.norm(Site(i, tag).pos - origin) for tag in tags] sites.append((tags, (j, i), ij_dist)) max_dist = [i[2][-1] for i in sites] distances = np.r_[tuple((i[2] for i in sites))] distances = np.sort(distances) group_boundaries = np.argwhere(np.diff(distances) > eps) if len(group_boundaries) < n: cutoff += 1 continue try: n_dist = distances[group_boundaries[n]] except IndexError: cutoff += 1 continue if np.all(max_dist > n_dist): break cutoff += 1 # We now have all the required sites, we need to find n-th. result = [] for group in sites: tags, distance = group[0], group[2] i, j = group[1] tags = np.array([tag for tag, dist in zip(tags, distance) if abs(dist - n_dist) < eps]) if len(tags): # Sort the tags. tags = tags[np.lexsort(tags.T[::-1])][::-1] # Throw away equivalent hoppings if # two sublattices are the same. if i == j and len(tags) > 1: tags = tags[: len(tags) // 2] for tag in tags: result.append(builder.HoppingKind(tag, j, i)) return result
def neighbors(self, n=1, eps=1e-8): """Return n-th nearest neighbor hoppings. Parameters ---------- n : integer Order of the hoppings to return. eps : float Tolerance relative to the length of the shortest lattice vector for when to consider lengths to be approximately equal. Returns ------- hoppings : list of kwant.builder.HopplingKind objects The n-th nearest neighbor hoppings. Notes ----- The hoppings are ordered lexicographically according to sublattice from which they originate, sublattice on which they end, and their lattice coordinates. Out of the two equivalent hoppings (a hopping and its reverse) only the lexicographically larger one is returned. """ # This algorithm is not designed to be fast and can be improved, # however there is no real need. Site = builder.Site sls = self.sublattices shortest_hopping = sls[0].n_closest( sls[0].pos(([0] * sls[0].lattice_dim)), 2)[-1] eps *= np.linalg.norm(self.vec(shortest_hopping)) nvec = len(self._prim_vecs) sublat_pairs = [(i, j) for (i, j) in product(sls, sls) if sls.index(j) >= sls.index(i)] def first_nonnegative(tag): for i in tag: if i < 0: return False elif i > 0: return True else: continue return True # Find the correct number of neighbors to calculate on each lattice. cutoff = n + 2 while True: max_dist = [] sites = [] for i, j in sublat_pairs: origin = Site(j, ta.zeros(nvec)).pos tags = i.n_closest(origin, n=cutoff**nvec) ij_dist = [ np.linalg.norm(Site(i, tag).pos - origin) for tag in tags ] sites.append((tags, (j, i), ij_dist)) max_dist = [i[2][-1] for i in sites] distances = np.r_[tuple((i[2] for i in sites))] distances = np.sort(distances) group_boundaries = np.argwhere(np.diff(distances) > eps) if len(group_boundaries) < n: cutoff += 1 continue try: n_dist = distances[group_boundaries[n]] except IndexError: cutoff += 1 continue if np.all(max_dist > n_dist): break cutoff += 1 # We now have all the required sites, we need to find n-th. result = [] for group in sites: tags, distance = group[0], group[2] i, j = group[1] tags = np.array([ tag for tag, dist in zip(tags, distance) if abs(dist - n_dist) < eps ]) if len(tags): # Sort the tags. tags = tags[np.lexsort(tags.T[::-1])][::-1] # Throw away equivalent hoppings if # two sublattices are the same. if i == j and len(tags) > 1: tags = tags[:len(tags) // 2] for tag in tags: result.append(builder.HoppingKind(tag, j, i)) return result
def __init__(self, position): velocity = ta.zeros(len(position)) super().__init__(position, velocity)