def iso_sample_H(self, part=np.real, xmin=None, xmax=None, xN=None, ymin=None, ymax=None, yN=None, zN=None): """Sample local eigenvalue geometry of H implicitly. Parameters: ----------- xN, yN, zN: int Number of sampling points in x, y and z direction. Returns: -------- X, Y, Z, F: (N,N,N) ndarray """ if xN is None: xN = 5*10**2 if yN is None: yN = xN if zN is None: zN = xN x = np.linspace(xmin, xmax, xN) y = np.linspace(ymin, ymax, yN) # x = np.linspace(self.x_EP - 1.1*self.x_R0, # self.x_EP + 1.1*self.x_R0, xN) # y = np.linspace(self.y_EP - 1.1*self.y_R0, # self.y_EP + 1.1*self.y_R0, yN) z = np.linspace(-1, 1, zN) if part is np.real: print "real" f = lambda x, E: 1j*np.sign(x)*np.imag(E) else: print "imag" z = 1j*z f = lambda x, E: np.sign(x)*np.real(E) X, Y, Z = np.meshgrid(x, y, z, indexing='ij') X, Y = [np.real(N) for N in X, Y] E = np.zeros((xN, yN, 2), dtype=complex) F = np.zeros((xN, yN, zN), dtype=complex) for i, xi in enumerate(x): for j, yj in enumerate(y): H = self.H(0, x=xi, y=yj) E[i, j, :] = c_eig(H)[0] char_poly = np.poly(H) for k, zk in enumerate(z): F[i, j, k] = np.polyval(char_poly, (zk + 1j*np.sign(zk) * np.imag(E[i, j, 0]))) return X, Y, Z, F
def get_c_eigensystem(self): """Calculate the instantaneous eigenvalues and eigenvectors for all times t=0,...,T and remove any discontinuities.""" # allocate temporary vectors eVals = np.zeros_like(self.eVals) eVecs_r = np.zeros_like(self.eVecs_r) eVecs_l = np.zeros_like(self.eVecs_l) # get eigenvalues and (left and right) eigenvectors at t=tn for n, tn in enumerate(self.t): eVals[n, :], eVecs_l[n, :, :], eVecs_r[n, :, :] = c_eig(self.H(tn), left=True) # check for discontinuities of first eigenvalue # and switch eigenvalues/eigenvectors accordingly: # 1) get differences between array components diff = np.diff(eVals[:, 0]) # 2) if difference exceeds epsilon, switch epsilon = 1e-1 mask = abs(diff) > epsilon # 3) assemble the arrays in a piecewise fashion at points # where eigenvalue-jumps occur for k in mask.nonzero()[0]: # correct phase to obtain continuous wavefunction phase_0_R = np.angle(eVecs_r[k, :, 0]) - np.angle(eVecs_r[k+1, :, 1]) phase_0_L = np.angle(eVecs_l[k, :, 0]) - np.angle(eVecs_l[k+1, :, 1]) phase_1_R = np.angle(eVecs_r[k+1, :, 0]) - np.angle(eVecs_r[k, :, 1]) phase_1_L = np.angle(eVecs_l[k+1, :, 0]) - np.angle(eVecs_l[k, :, 1]) # account for phase-jump v0(k) -> v1(k+1) eVecs_r[k+1:,:,1] *= np.exp(+1j*phase_0_R) eVecs_l[k+1:,:,1] *= np.exp(+1j*phase_0_L) # account for phase-jump v1(k) -> v0(k+1) eVecs_r[:k+1,:,1] *= np.exp(+1j*phase_1_R) eVecs_l[:k+1,:,1] *= np.exp(+1j*phase_1_L) for e in eVals, eVecs_r, eVecs_l: e[...,0], e[...,1] = (np.concatenate((e[:k+1,...,0], e[k+1:,...,1])), np.concatenate((e[:k+1,...,1], e[k+1:,...,0]))) #print np.einsum('ijk,ijk -> ik', eVecs_l, eVecs_r) self.eVals = eVals self.eVecs_l = eVecs_l self.eVecs_r = eVecs_r
def sample_H_eigenvectors(self, xmin=None, xmax=None, xN=None, ymin=None, ymax=None, yN=None, verbose=False): """Sample local eigenvectors of Hamiltonian H. Parameters: ----------- xmin, xmax: float Dimensions in x-direction. ymin, ymax: float Dimensions in y-direction. xN, yN: int Number of sampling points in x and y direction. verbose: bool Show additional output. Returns: -------- X, Y: (N,N) ndarray Spatial (mesh)grids. Z: (N,N,2,2) ndarray Eigenvectors evaluated on the X/Y grid. """ if xN is None: xN = 5*10**2 if yN is None: yN = 5*10**2 # if xmin is None or xmax is None: # xmin = self.x_EP - 0.15*self.x_R0 # xmax = self.x_EP + 0.15*self.x_R0 # # if ymin is None or ymax is None: # ymin = self.y_EP - 0.15*self.y_R0 # ymax = self.y_EP + 0.15*self.y_R0 x = np.linspace(xmin, xmax, xN) y = np.linspace(ymin, ymax, yN) X, Y = np.meshgrid(x, y, indexing='ij') Z = np.zeros((xN, yN, 2, 2), dtype=complex) for i, xi in enumerate(x): for j, yj in enumerate(y): if verbose: print "(i,j) =", i, j H = self.H(0, x=xi, y=yj) Z[i, j, :, :] = c_eig(H)[1] return X, Y, Z
def _get_loss_matrix(self, x=None, y=None): # dyadic product evals, evecs = c_eig(self.Dirichlet.H(0, x, y)) v1, v2 = [evecs[:, n] for n in (0, 1)] if y >= 0: v = v2 else: v = v1 G = np.outer(v, v.conj()) if self.verbose: print "G\n", G return G
def get_nodes(self, x=None, y=None, return_evecs=False): """Return the nodes of the Bloch-eigenvector in the unit cell.""" if not self.loop_type == 'Constant': raise Exception("Error: loop_type not 'Constant'!") k = self.k kr = self.kr W = self.W evals, evecs = c_eig(self.H(0, x, y)) j0 = 0 j1 = 1 b1, b2 = [evecs[i, j0] for i in (0, 1)] # if b1.imag > 0 or b2.imag < 0: if y <= 0: b1, b2 = [evecs[i, j1] for i in (0, 1)] evecs[:, 0], evecs[:, 1] = evecs[:, 1], evecs[:, 0] evals[0], evals[1] = evals[1], evals[0] # # write eigensystem to file # with open("evecs_{}_{}.dat".format(self.loop_direction, # self.init_state), "a") as f: # ev = evals # e = evecs # data = (ev[0].real, ev[0].imag, ev[1].real, ev[1].imag, # e[0,0].real, e[0,0].imag, e[1,0].real, e[1,0].imag, # e[0,1].real, e[0,1].imag, e[1,1].real, e[1,1].imag) # np.savetxt(f, data, newline=" ", fmt='%.5e') # f.write("\n") def x0(s): """Return x-coordinates in unit cell. Only valid for boundary phase parameter vartheta = 0.""" return (2.*pi/kr * (1+s)/2 - 1j/kr * np.log(-s*np.exp(-1j*np.pi/2)*b1*b2.conj() / (abs(b1)*abs(b2)))) # def x0(s): # """Return x-coordinates in unit cell. Only valid for boundary # phase parameter vartheta = 0.""" # return s*np.pi/(2.*kr) + (1.-s)/2. * 2.*pi/kr def y0(s): """Return y-coordinates in unit cell.""" return W/pi*np.arccos(s*0.5*np.sqrt(k(2)/k(1))*abs(b1/b2)) xn = np.asarray([x0(n) for n in (+1, -1)]) yn = np.asarray([y0(n) for n in (-1, +1)]) # # write coordinates to file # with open("coords_{}_{}.dat".format(self.loop_direction, # self.init_state), "a") as f: # data = (xn[0], yn[0], xn[1], yn[1]) # np.savetxt(f, data, newline=" ", fmt='%.5e') # f.write("\n") # mark invalid node coordinates with np.nan # -> caught in DirichletPositionDependentLoss._get_EP_coordinates where # G is set to zero for invalid points # if np.any(xn < 0.) or np.any(xn > 2.*pi/kr) : # xn *= np.nan # if np.any(yn < 0.) or np.any(yn > W): # yn *= np.nan if self.verbose: print "evec_x =", b1 print "evec_y =", b2 print "node xn", xn print "node yn", yn if not return_evecs: return np.asarray(zip(xn, yn)) else: return evecs