def get_bloch_eigensystem(plot=False): """docstring for get_bloch_eigensystem""" # get Bloch eigensystem K, _, ev, _, v, _ = bloch.get_eigensystem(return_eigenvectors=True, return_velocities=True, verbose=True, neumann=False) K0, K1 = K[0], K[1] ev0, ev1 = ev[0,:], ev[1,:] print "chi.shape", ev0.shape if plot: y = np.linspace(0, 1, len(ev0)) plt.plot(y, np.abs(ev0)**2, "r-") plt.plot(y, np.abs(ev1)**2, "g-") plt.xlim(0, 1) plt.show() z = ev0.view(dtype=float) np.savetxt("eigensystem.dat", zip(ev0.real, ev0.imag, np.ones_like(z)*K0.real, np.ones_like(z)*K0.imag, ev1.real, ev1.imag, np.ones_like(z)*K1.real, np.ones_like(z)*K1.imag), header=('y Re(ev0) Im(ev0) Re(K0) Im(K0) Re(ev1)' 'Im(ev1) Re(K1) Im(K1)'))
def raster_eps_delta(N=2.6, pphw=300, eta=0.1, W=1.0, xml="input.xml", xml_template="input.xml_template", eps=[0.01, 0.1, 30], delta=[0.3, 0.7, 50], dryrun=False): # k_x for modes 0 and 1 k0, k1 = [np.sqrt(N**2 - n**2)*np.pi for n in (1, 2)] kr = k0 - k1 # ranges eps_range = np.linspace(*eps) delta_range = np.linspace(*delta) print "eps_range", eps_range print "delta_range", delta_range # check if eps/delta values can be resolved r_ny_eps = (eps_range*(N*pphw+1)).astype(int) r_nx_L = (abs(2.*np.pi/(kr + delta_range))*(N*pphw+1)).astype(int) print "grid-points per full amplitude eps", r_ny_eps print "grid-points per length L", r_nx_L print_diff_warning(r_ny_eps, "epsilon") print_diff_warning(r_nx_L, "length") if dryrun: sys.exit() def update_boundary(eps, delta): L = abs(2*np.pi/(kr + delta)) # choose discretization such that r_nx < len(x_range) r_nx_L = (L*(N*pphw + 1)).astype(int) x_range = np.linspace(0, L, r_nx_L) # no Delta-phase necessary if looking at loop_type constant! WG = Dirichlet(loop_type='Constant', N=N, L=L, W=W, eta=eta) xi_lower, xi_upper = WG.get_boundary(x=x_range, eps=eps, delta=delta) print "lower.boundary.shape", xi_lower.shape np.savetxt("lower.boundary", zip(x_range, xi_lower)) np.savetxt("upper.boundary", zip(x_range, xi_upper)) N_file_boundary = len(x_range) replacements = {'NAME': CALC_NAME, 'LENGTH': str(L), 'WIDTH': str(W), 'MODES': str(N), 'PPHW': str(pphw), 'GAMMA0': str(eta), 'NEUMANN': "0", 'N_FILE_BOUNDARY': str(N_file_boundary), 'BOUNDARY_UPPER': 'upper.boundary', 'BOUNDARY_LOWER': 'lower.boundary'} replace_in_file(xml_template, xml, **replacements) # parameters, eigenvalues and eigenvectors eps, delta, ev0, ev1 = [[] for n in range(4)] for e in eps_range: for d in delta_range: update_boundary(e, d) run_code() try: # bloch_evals = bloch.get_eigensystem() # TODO: why column 0 and not 1 to access right moving modes? # bloch_evals = np.array(bloch_evals)[0, :2] # if bloch.get_eigensystem is not called with modes, dx, etc., # these values are read from the xml file evalsfile = 'Evals.' + CALC_NAME + '.dat' bloch_evals, _ = bloch.get_eigensystem(evalsfile=evalsfile) bloch_evals = np.array(bloch_evals)[:2] ev0.append(bloch_evals[0]) ev1.append(bloch_evals[1]) eps.append(e) delta.append(d) with open(TMP, "a") as f: f.write("{} {} {} {} {} {}\n".format(e, d, bloch_evals[0].real, bloch_evals[0].imag, bloch_evals[1].real, bloch_evals[1].imag)) # backup output files eps_delta_id = "eps_{:.6f}_delta_{:.6f}".format(e, d) evals_file = "evals_" + eps_delta_id + ".dat" archive("Evals." + CALC_NAME + ".dat", evals_file) xml_file = "xml_" + eps_delta_id + ".dat" archive("input.xml", xml_file, delete=False) os.remove("Evecs." + CALC_NAME + ".dat") os.remove("Evecs." + CALC_NAME + ".abs") except Exception as ex: print "Evals, evecs or xml file not found: {}".format(ex) eps, delta, ev0, ev1 = [np.array(x) for x in (eps, delta, ev0, ev1)] np.savetxt("bloch_modes.dat", zip(eps, delta, ev0.real, ev0.imag, ev1.real, ev1.imag))
def raster_eps_delta(N=2.6, pphw=300, eta=0.1, W=1.0, xml="input.xml", xml_template="input.xml_template", eps=[0.01, 0.1, 30], delta=[0.3, 0.7, 50], dryrun=False, neumann=0): # k_x for modes 0 and 1 if not neumann: k0, k1 = [np.sqrt(N**2 - n**2)*np.pi for n in (1, 2)] else: k0, k1 = [np.sqrt(N**2 - n**2)*np.pi for n in (0, 1)] kr = k0 - k1 # ranges eps_range = np.linspace(*eps) delta_range = np.linspace(*delta) print "eps_range", eps_range print "delta_range", delta_range # check if eps/delta values can be resolved r_ny_eps = (eps_range*(N*pphw+1)).astype(int) r_nx_L = (abs(2.*np.pi/(kr + delta_range))*(N*pphw+1)).astype(int) print "grid-points per full amplitude eps", r_ny_eps print "grid-points per length L", r_nx_L print_diff_warning(r_ny_eps, "epsilon") print_diff_warning(r_nx_L, "length") if dryrun: sys.exit() def update_boundary(eps, delta): L = abs(2*np.pi/(kr + delta)) # choose discretization such that r_nx < len(x_range) # r_nx_L = (abs(2*np.pi/(kr + delta))*(N*pphw + 1)).astype(int) r_nx_L = (L(N*pphw + 1)).astype(int) x_range = np.linspace(0, L, r_nx_L) if not neumann: WG = Dirichlet(loop_type='Constant', N=N, L=L, W=W, eta=eta) else: WG = Neumann(loop_type='Constant', N=N, L=L, W=W, eta=eta) xi_lower, xi_upper = WG.get_boundary(x=x_range, eps=eps, delta=delta) print "lower.boundary.shape", xi_lower.shape np.savetxt("lower.boundary", zip(x_range, xi_lower)) np.savetxt("upper.boundary", zip(x_range, xi_upper)) N_file_boundary = len(x_range) replacements = {'LENGTH': str(L), 'WIDTH': str(W), 'MODES': str(N), 'PPHW': str(pphw), 'GAMMA0': str(eta), 'NEUMANN': neumann, 'N_FILE_BOUNDARY': str(N_file_boundary), 'BOUNDARY_UPPER': 'upper.boundary', 'BOUNDARY_LOWER': 'lower.boundary'} replace_in_file(xml_template, xml, **replacements) # parameters, eigenvalues and eigenvectors # eps, delta, ev0, ev1, overlap = [ [] for n in range(5) ] eps, delta, ev0, ev1, overlap = []*5 tmp = "bloch.tmp" for e in eps_range: for d in delta_range: update_boundary(e, d) run_code() try: # bloch_evals = bloch.get_eigensystem() # TODO: why column 0 and not 1 to access right moving modes? # bloch_evals = np.array(bloch_evals)[0, :2] # if bloch.get_eigensystem is not called with modes, dx, etc., # these values are read from the xml file bloch_evals, _, bloch_evecs, _ = bloch.get_eigensystem(return_eigenvectors=True, neumann=neumann) bloch_evals, bloch_evecs = [np.array(x)[:2] for x in (bloch_evals, bloch_evecs)] bloch_evecs_overlap = (np.abs(bloch_evecs[0]-bloch_evecs[1])**2).sum() print "overlap", bloch_evecs_overlap ev0.append(bloch_evals[0]) ev1.append(bloch_evals[1]) overlap.append(bloch_evecs_overlap) eps.append(e) delta.append(d) with open(tmp, "a") as f: f.write("{} {} {} {} {} {}\n".format(e, d, bloch_evals[0].real, bloch_evals[0].imag, bloch_evals[1].real, bloch_evals[1].imag)) # backup output files evals_file = "evals_eps_{:.8f}_delta_{:.8f}.dat".format(e, d) archive("Evals.complex_potential.dat", evals_file) os.remove("Evecs.complex_potential.dat") os.remove("Evecs.complex_potential.abs") xml_file = "xml_eps_{:.8f}_delta_{:.8f}.dat".format(e, d) archive("input.xml", xml_file, delete=False) except: print "Evals, evecs or xml file not found!" # tmp.out is not written if job is part of a job-array tmp_file = "tmp_eps_{:.8f}_delta_{:.8f}.out".format(e, d) archive("tmp.out", tmp_file) # be backwards compatible in case no jpg is written jpg_file = "jpg_eps_{:.8f}_delta_{:.8f}.jpg".format(e, d) archive("pic.geometry.complex_potential.1.jpg", jpg_file) eps, delta, ev0, ev1, overlap = [np.array(x) for x in (eps, delta, ev0, ev1, overlap)] np.savetxt("bloch_modes.dat", zip(eps, delta, ev0.real, ev0.imag, ev1.real, ev1.imag, overlap))
def run_single_job(n, xn, epsn, deltan, eta=None, pphw=None, XML=None, N=None, WG=None, loop_direction=None, neumann=None): """Calculate the Bloch eigensystem in a separate directory and extract the eigenvalues and eigenvectors. Returns: -------- K0, K1: complex eigenvalues ev0, ev1: (N,) ndarray eigenvectors """ ID = "n_{:03}_xn_{:08.4f}".format(n, xn) print print ID CWD = os.getcwd() DIR = os.path.join(CWD, ID) os.makedirs(ID) os.chdir(DIR) # prepare waveguide and profile profile_kwargs = {'eps': epsn, 'delta': deltan, 'pphw': pphw, 'input_xml': XML, 'custom_directory': os.getcwd(), 'neumann': neumann} wg_kwargs_n = {'N': N, 'eta': eta, 'L': 2*np.pi/(WG.kr + deltan), 'init_phase': 0.0, 'loop_direction': loop_direction, 'loop_type': 'Constant'} profile_kwargs.update(wg_kwargs_n) ep.profile.Generate_Profiles(**profile_kwargs) # run code cmd = "solve_xml_mumps_dev" greens_code = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE) greens_code.communicate() try: # get Bloch eigensystem K, _, ev, _, v, _ = bloch.get_eigensystem(return_eigenvectors=True, return_velocities=True, verbose=True, neumann=neumann) # remove eigenvalue files # os.remove("Evecs.sine_boundary.dat") # os.remove("Evecs.sine_boundary.abs") # if np.real(v[0]) < 0. or np.real(v[1]) < 0.: # sys.exit("Error: group velocities are negative!" + 180*"-") K0, K1 = K[0], K[1] ev0, ev1 = ev[0,:], ev[1,:] print "chi.shape", ev0.shape z = ev0.view(dtype=float) np.savetxt("eigensystem.dat", zip(ev0.real, ev0.imag, np.ones_like(z)*K0.real, np.ones_like(z)*K0.imag, ev1.real, ev1.imag, np.ones_like(z)*K1.real, np.ones_like(z)*K1.imag), header=('y Re(ev0) Im(ev0) Re(K0) Im(K0) Re(ev1)' 'Im(ev1) Re(K1) Im(K1)')) os.chdir(CWD) # subprocess.call("gzip -r {}".format(DIR).split()) # shutil.rmtree(DIR) print "xn", xn, "epsn", epsn, "deltan", deltan, "K0", K0, "K1", K1 return K0, K1, ev0, ev1 except: os.chdir(CWD) print traceback.print_exc() return
parameters = [ (n,m) for n in x0, x1 for m in y0, y1 ] # order: (x0, y0) -> (x_i, y_i) # (x0, y1) -> (x_i, y_i+1) # (x1, y0) -> (x_i+1, y_i) # (x1, y1) -> (x_i+1, y_i+1) if 1: for n, (x, y) in enumerate(parameters): # we dont need the values lambda_n(x_i+1, y_i+1) if n < 3: print "n,m", x, y self._check_numerical_resolution(x) self._update_boundary(x, y) self._run_code() # take the first two right-movers & k1 -> k1 mod kr # TODO: why column 0 and not 1 to access the right moving modes? bloch_modes = np.array(bloch.get_eigensystem())[0,:2] F = np.abs(bloch_modes[0] - bloch_modes[1]) print F == np.abs(np.array([1,-1]).dot(bloch_modes)) eigenvalues.append(F) else: # alternative pass self.evals.append([bloch_modes[0], bloch_modes[1]]) delta = 0.01 F = np.asarray(eigenvalues).T gradient = np.array([[-1, 0, 1], [-1, 1, 0]])