Source code for gyroid.grid

# -*- coding: utf-8 -*-
"""
gyroid.grid
===============

:copyright: (c) 2012 by Yi-Xin Liu
:license: BSD, see LICENSE for more details.

"""

import numpy as np
from numpy.linalg import inv

from .common import BRAVAIS,CARTESIAN
from .common import EPS,SMALL,LARGE

__all__ = ["Grid","wave_norm"]

[docs]class Grid(object): """ Discrete form of a unit cell in reciprocal space. """ def __init__(self,ngrid,g): """ ngrid must be a length dim vector containing positive integers. ngrid must be a numpy.ndarray. g is a Group instance. """ self.dim = g.dim if np.size(ngrid) != g.dim: raise ValueError("Dimension and ngrid not match.") self.N = ngrid self.shape = g.shape self.__create_waves(g)
[docs] def to_BZ(self,G): if np.size(G) != self.dim: raise ValueError("""The wave vector and Dimension of the grid not match in to_BZ.""") low = -1 high = 1 G_try = G G_min = G Gsq_min = LARGE if self.dim == 1: for i in np.arange(high,low-1,-1): G_try = G + np.array([i]) * self.N Gsq = wave_norm(G_try,self.shape) if Gsq < Gsq_min: Gsq_min, G_min = Gsq, G_try if self.dim == 2: for i in np.arange(high,low-1,-1): for j in np.arange(high,low-1,-1): G_try = G + np.array([i,j]) * self.N Gsq = wave_norm(G_try,self.shape) if Gsq < Gsq_min: Gsq_min, G_min = Gsq, G_try if self.dim == 3: for i in np.arange(high,low-1,-1): for j in np.arange(high,low-1,-1): for k in np.arange(high,low-1,-1): G_try = G + np.array([i,j,k]) * self.N Gsq = wave_norm(G_try,self.shape) if Gsq < Gsq_min: Gsq_min, G_min = Gsq, G_try return G_min
[docs] def is_wave_cancel(self,G,g): """ A wave is canceled if and only if following conditions are met: 1) Leaves G invariant (i.e. G.R == G), and 2) Produces a non-zero phase, such that G.t % 1.0 != 0 """ for i in np.arange(g.order): Gp = np.dot(G,g.symm[i].R) # Pseudo-Spetral method Gp = self.to_BZ(Gp) if np.all(np.abs(Gp-G) < EPS): phase = np.dot(G,g.symm[i].t) % 1.0 # for cases phase=-1.0 - SMALL # (-1.0 - SMALL) % 1.0 ~ (1.0 - SMALL) if np.abs(phase-1.0) < EPS: phase -= 1.0 # wave canceled if phase not equal 0 if np.abs(phase) > EPS: return True return False
@property
[docs] def max_Gabs(self): length = SMALL if self.dim == 1: for (i,) in np.ndindex(self.N[0]): G = np.array([i]) tmp = wave_norm(self.to_BZ(G),self.shape) if tmp > length: length = tmp if self.dim == 2: for (i,j) in np.ndindex(self.N[0],self.N[1]): G = np.array([i,j]) tmp = wave_norm(self.to_BZ(G),self.shape) if tmp > length: length = tmp if self.dim == 3: for (i,j,k) in np.ndindex(self.N[0],self.N[1],self.N[2]): G = np.array([i,j,k]) tmp = wave_norm(self.to_BZ(G),self.shape) if tmp > length: length = tmp return np.sqrt(length)
def __create_waves(self,g): #Gsq_max = self.max_Gabs * self.max_Gabs #G_max = np.zeros(self.dim) #for i in np.arange(self.dim): # aa = np.sqrt(np.dot(self.shape.h[i],self.shape.h[i])) # G_max[i] = int(self.max_Gabs * aa / (2.0 * np.pi)) + 1 # Calculate number of effective waves # Pseudo-Spectral method if self.dim == 1: n = 0 for (i,) in np.ndindex(self.N[0]): ivec = self.to_BZ(np.array([i])) if not self.is_wave_cancel(ivec,g): n += 1 Nw = n w = np.zeros((self.dim,Nw)) G2 = np.zeros(Nw) n = 0 for (i,) in np.ndindex(self.N[0]): ivec = self.to_BZ(np.array([i])) if not self.is_wave_cancel(ivec,g): w[:,n] = ivec G2[n] = wave_norm(ivec,self.shape) n += 1 if self.dim == 2: n = 0 for (i,j) in np.ndindex(self.N[0],self.N[1]): ivec = self.to_BZ(np.array([i,j])) if not self.is_wave_cancel(ivec,g): n += 1 Nw = n w = np.zeros((self.dim,Nw)) G2 = np.zeros(Nw) n = 0 for (i,j) in np.ndindex(self.N[0],self.N[1]): ivec = self.to_BZ(np.array([i,j])) if not self.is_wave_cancel(ivec,g): w[:,n] = ivec G2[n] = wave_norm(ivec,self.shape) n += 1 if self.dim == 3: n = 0 for (i,j,k) in np.ndindex(self.N[0],self.N[1],self.N[2]): ivec = self.to_BZ(np.array([i,j,k])) if not self.is_wave_cancel(ivec,g): n += 1 Nw = n w = np.zeros((self.dim,Nw)) G2 = np.zeros(Nw) n = 0 for (i,j,k) in np.ndindex(self.N[0],self.N[1],self.N[2]): ivec = self.to_BZ(np.array([i,j,k])) if not self.is_wave_cancel(ivec,g): w[:,n] = ivec G2[n] = wave_norm(ivec,self.shape) n += 1 # Sort G2 in ascending order, returned the corresponding indices ind = np.argsort(G2) self.Nw = Nw self.waves = w[:,ind] self.Gsq = G2[ind]
[docs]def wave_norm(G,shape): """ G is a wave vector with 1, 2, or 3 elements shape is a shape matrix """ v = np.dot(G,shape.g) return np.dot(v,v)