Example #1
0
    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
Example #2
0
    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
Example #3
0
    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
Example #4
0
    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
Example #5
0
    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