def distance2(self, x1, x2, option='reduced', radius=20, limits=None): # Compute the vector from x1 to x2 dv = np.array(x2) - np.array(x1) # If we are not in reduced coordinates, # Convert into them if option != 'reduced': dred = self.cartesian2reduced(dv) else: dred = dv dwrap = wrap2_pmhalf(dred) if limits is None: limits = np.zeros(3, dtype=int) corners = self.get_wigner_seitz_container() limits[0] = min(int(ceil(max(1e-14 + abs(np.array([corners[x][0] for x in corners]))))), 5) limits[1] = min(int(ceil(max(1e-14 + abs(np.array([corners[x][1] for x in corners]))))), 5) limits[2] = min(int(ceil(max(1e-14 + abs(np.array([corners[x][2] for x in corners]))))), 5) ret = {} for i0 in np.arange(-limits[0], limits[0] + 1): for i1 in np.arange(-limits[1], limits[1] + 1): for i2 in np.arange(-limits[2], limits[2] + 1): dtot = dwrap + np.array([i0, i1, i2]) norm2 = np.dot(np.dot(dtot, self.metric), dtot) if norm2 < radius * radius: ret[(i0, i1, i2)] = {'distance': sqrt(norm2), 'image': dtot} return ret
def distance2(self, x1, x2, option='reduced', radius=20, limits=None): # Compute the vector from x1 to x2 dv = np.array(x2) - np.array(x1) # If we are not in reduced coordinates, # Convert into them if option != 'reduced': dred = self.cartesian2reduced(dv) else: dred = dv dwrap = wrap2_pmhalf(dred) if limits is None: limits = np.zeros(3, dtype=int) corners = self.get_wigner_seitz_container() limits[0] = min(int(ceil(max(1e-14 + abs(np.array([corners[x][0] for x in corners]))))), 5) limits[1] = min(int(ceil(max(1e-14 + abs(np.array([corners[x][1] for x in corners]))))), 5) limits[2] = min(int(ceil(max(1e-14 + abs(np.array([corners[x][2] for x in corners]))))), 5) ret = {} for i0 in np.arange(-limits[0], limits[0] + 1): for i1 in np.arange(-limits[1], limits[1] + 1): for i2 in np.arange(-limits[2], limits[2] + 1): dtot = dwrap + np.array([i0, i1, i2]) norm2 = np.dot(np.dot(dtot, self.metric), dtot) if norm2 < radius * radius: ret[(i0, i1, i2)] = {'distance': sqrt(norm2), 'image': dtot} return ret
def distance2(self, x1, x2, option='reduced'): # Compute the vector from x1 to x2 dv = _np.array(x2)-_np.array(x1) # If we are not in reduced coordinates, # Convert into them if option != 'reduced': dred = self.cartesian2reduced(dv) else: dred = dv dwrap = wrap2_pmhalf(dred) limits = _np.zeros(3) corners = self.get_wigner_seitz_container() #for key, value in corners.iteritems(): # print key, value limits[0] = int(math.ceil(max(1e-14+abs(_np.array([corners[x][0] for x in corners]))))) limits[1] = int(math.ceil(max(1e-14+abs(_np.array([corners[x][1] for x in corners]))))) limits[2] = int(math.ceil(max(1e-14+abs(_np.array([corners[x][2] for x in corners]))))) #print limits ret = {} for i0 in _np.arange(-limits[0], limits[0]+1): for i1 in _np.arange(-limits[1], limits[1]+1): for i2 in _np.arange(-limits[2], limits[2]+1): dtot = dwrap+_np.array([i0, i1, i2]) norm2 = _np.dot(_np.dot(dtot, self.metric), dtot) ret[(i0, i1, i2)] = {'distance': math.sqrt(norm2), 'image': dtot} return ret
def distances_in_sphere(self, x1, x2, radius, option='reduced', exclude_out_sphere=True, sort_by_distance=True): """ Returns all the distances between two positions x1 and x2 taking into account the periodicity of the cell :param sort_by_distance: :param exclude_out_sphere: :param x1: :param x2: :param radius: :param option: :return: """ # Compute the vector from x1 to x2 dv = np.array(x2) - np.array(x1) # If the positions are not in reduced coordinates,convert into them if option != 'reduced': dred = self.cartesian2reduced(dv) else: dred = dv dwrap = wrap2_pmhalf(dred) # log.debug('The wrap vector is: %7.3f %7.3f %7.3f' % tuple(dwrap)) # We need to compute the distances between equivalent faces # For that we to compute the perpendicular distance between # two faces, the reciprocal lattice produces the inverse of # those distances recp_len = np.array(self.reciprocal().lengths) # The reciprocal (2*pi) is not necessary limits = np.ceil(radius * recp_len).astype(int) # log.debug('The limits are: %d %d %d' % tuple(limits)) ret = {} # The total size is the product of the number in the 3 directions # that is double the limits plus 1 to include the zero total_size = np.prod(2 * limits + 1) # log.debug('The total size is: %d' % total_size) ret['distance'] = np.zeros(total_size) ret['image'] = np.zeros((total_size, 3), dtype=int) ret['dwrap'] = dwrap ret['limits'] = limits index = 0 for i0 in np.arange(-limits[0], limits[0] + 1): for i1 in np.arange(-limits[1], limits[1] + 1): for i2 in np.arange(-limits[2], limits[2] + 1): dtot = dwrap + np.array([i0, i1, i2]) norm2 = np.dot(np.dot(dtot, self.metric), dtot) ret['distance'][index] = sqrt(norm2) ret['image'][index] = np.array([i0, i1, i2]) index += 1 # Exclude distances out of sphere if exclude_out_sphere: inside_sphere = ret['distance'] <= radius if sum(inside_sphere) > 0: ret['distance'] = ret['distance'][inside_sphere] ret['image'] = ret['image'][inside_sphere] if sort_by_distance: sorted_indices = np.argsort(ret['distance']) ret['distance'] = ret['distance'][sorted_indices] ret['image'] = ret['image'][sorted_indices] return ret
def distances_in_sphere(self, x1, x2, radius, option='reduced', exclude_out_sphere=True, sort_by_distance=True): """ Returns all the distances between two positions x1 and x2 taking into account the periodicity of the cell :param sort_by_distance: :param exclude_out_sphere: :param x1: :param x2: :param radius: :param option: :return: """ # Compute the vector from x1 to x2 dv = np.array(x2) - np.array(x1) # If the positions are not in reduced coordinates,convert into them if option != 'reduced': dred = self.cartesian2reduced(dv) else: dred = dv dwrap = wrap2_pmhalf(dred) # log.debug('The wrap vector is: %7.3f %7.3f %7.3f' % tuple(dwrap)) # We need to compute the distances between equivalent faces # For that we to compute the perpendicular distance between # two faces, the reciprocal lattice produces the inverse of # those distances recp_len = np.array(self.reciprocal().lengths) # The reciprocal (2*pi) is not necessary limits = np.ceil(radius * recp_len).astype(int) # log.debug('The limits are: %d %d %d' % tuple(limits)) ret = {} # The total size is the product of the number in the 3 directions # that is double the limits plus 1 to include the zero total_size = np.prod(2 * limits + 1) # log.debug('The total size is: %d' % total_size) ret['distance'] = np.zeros(total_size) ret['image'] = np.zeros((total_size, 3), dtype=int) ret['dwrap'] = dwrap ret['limits'] = limits index = 0 for i0 in np.arange(-limits[0], limits[0] + 1): for i1 in np.arange(-limits[1], limits[1] + 1): for i2 in np.arange(-limits[2], limits[2] + 1): dtot = dwrap + np.array([i0, i1, i2]) norm2 = np.dot(np.dot(dtot, self.metric), dtot) ret['distance'][index] = sqrt(norm2) ret['image'][index] = np.array([i0, i1, i2]) index += 1 # Exclude distances out of sphere if exclude_out_sphere: inside_sphere = ret['distance'] <= radius if sum(inside_sphere) > 0: ret['distance'] = ret['distance'][inside_sphere] ret['image'] = ret['image'][inside_sphere] if sort_by_distance: sorted_indices = np.argsort(ret['distance']) ret['distance'] = ret['distance'][sorted_indices] ret['image'] = ret['image'][sorted_indices] return ret