def test_dipoleRadiation(): ''' Plots the Electric field in the x,y plane from both a z and y oriented dipole. Right now, the y-dipole plots |E| -- ultimately this should be a vector plot to highlight the loop pattern. ''' wl = 2 #z-oriented dipole P = np.array([0, 0, 1]) res = 100 x = np.linspace(-5, 5, res) y = np.linspace(-5, 5, res) z = 0 X, Y = np.meshgrid(x, y) Z = X * 0 r = np.array([X, Y, Z]) r = np.swapaxes(r, 0, 2) E = dipoleRadiation(wl, P, r) Ez = E[:, :, 2] vmax = 10 #np.amax(abs(Ez)) vmin = -vmax plt.imshow(Ez.real, extent=putil.getExtent(x, y), cmap='RdBu', vmax=vmax, vmin=vmin) plt.colorbar() # y-oriented dipole P = np.array([0, 1, 0]) E = dipoleRadiation(wl, P, r) Etot = np.array([np.linalg.norm(i) for i in E.reshape(res**2, 3)]).reshape(res, res) plt.figure() plt.imshow(Etot.T, extent=putil.getExtent(x, y), cmap='hot', vmax=vmax, vmin=0) # plt.imshow(E[:,:,1].real.T,extent=putil.getExtent(x,y),cmap='RdBu',vmax=vmax,vmin=vmin) plt.colorbar() plt.show()
def test_dipoleRadiation(): ''' ''' wl = 2 P = 1 x = np.linspace(-5, 5, 100) y = np.linspace(-5, 5, 100) X, Y = np.meshgrid(y, x) r = sqrt(X**2 + Y**2) Fz = dipoleRadiation(wl, P, r) vmax = 1 vmin = -vmax plt.imshow(Fz.real, extent=putil.getExtent(x, y), cmap='RdBu', vmax=vmax, vmin=vmin) plt.colorbar() plt.show()
def test_addDipoles(): wl = 1 d1 = [-wl / 4., 0, 0] d2 = [wl / 4., 0, 0] ds = np.array([d1, d2]) p1 = [0, 0, 1] p2 = [0, 0, 1] ps = np.array([p1, p2]) res = 100 xs = np.linspace(-5, 5, res) ys = np.linspace(-5, 5, res) targets = np.array([[i, j, 0] for i in xs for j in ys]) E = [addDipoles(wl, ds, ps, t) for t in targets] E = np.array(E) Ez = E[:, 2].reshape(res, res) vmax = 50 vmin = -vmax plt.imshow(Ez.real.T, extent=putil.getExtent(xs, ys), cmap='RdBu', vmax=vmax, vmin=vmin) plt.show()
def plotField(self, xmin, xmax, ymin, ymax, xres=100, yres=100): xs = np.linspace(xmin, xmax, xres) ys = np.linspace(ymin, ymax, yres) X, Y = np.meshgrid(xs, ys) Fz = np.zeros((len(xs), len(ys)), dtype=complex) # loop over all dipoles and sum contribution to scattered field for n in range(self.N): print 'plotField: processing dipole %u of %u' % (n, self.N) i = self.x[n] j = self.y[n] r = sqrt((X - i)**2 + (Y - j)**2) Fz += dipoleRadiation(self.wl, self.P[n], r) Fz_crop = Fz * ( (abs(X) > self.width) + (abs(Y) > self.height) == 1) # field with resonator removed vmax = np.amax(abs(Fz_crop)**2) # vmax = None plt.figure() # plt.imshow(Fz.real,cmap='RdBu',vmax=vmax,vmin=-vmax) plt.imshow(abs(Fz)**2, extent=putil.getExtent(xs, ys), cmap='hot', vmax=vmax, vmin=0) # plt.imshow(Fz.real,extent=putil.getExtent(xs,ys),cmap='RdBu',vmax=vmax,vmin=-vmax) plt.colorbar()
def test_PW(): ''' ''' angle = 25. wl = 2. x = np.linspace(-10, 10, 1000) y = np.linspace(-10, 10, 1000) X, Y = np.meshgrid(x, y) pw = PW(X, Y, angle, wl) plt.imshow(pw.real, extent=putil.getExtent(x, y), cmap='RdBu') plt.colorbar() plt.show()
def main(): ''' Simulation Parameters ''' wl = 4 pol = 'Hz' # Resonator Properties AR = 1 # height / width w = 2.2 h = .36 # h = w * AR l = 100 * wl # w *= 1. # h *= 1. # Mode indices m = 4 n = 1 # Simulation Grid fieldRes = 30 FFres = 200 FFR = 20 * wl a = wl / 100. # dipole lattice spacing ''' Get Dipole positions and polarizations ''' x = np.arange(-w / 2., w / 2., a) y = np.arange(-h / 2., h / 2., a) # z = np.arange(-l/2.,l/2.,a) z = np.array([0]) # center array to ensure symmetry shift = lambda x: (x % a) / 2. x += shift(w) y += shift(h) z += shift(l) print 'Number of Dipoles = %u' % (len(x) * len(y) * len(z)) dipoles = [[i, j, k] for i in x for j in y for k in z] dipoles = np.array(dipoles) amplitude = sin(m * pi / w * (dipoles[:, 0] + w / 2.)) * sin(n * pi / h * (dipoles[:, 1] + h / 2.)) Ps = [np.array([0, 0, a]) for a in amplitude] ''' FF plot ''' theta, pwr = FF(wl, dipoles, Ps, R=FFR, res=FFres) plt.figure() plt.subplot(111, polar=True) plt.gca().grid(True) plt.plot(theta, pwr, color='r', lw=2) plt.figure() plt.plot(theta * 180 / pi - 90, pwr, color='r', lw=2) plt.xlim(0, 90) ''' Plot Dipole Arrangement ''' plt.figure() plt.imshow(amplitude.reshape(len(x), len(y), len(z))[:, :, 0].T, extent=putil.getExtent(x, y)) plt.show() return 0
def main(): ''' Complex slab mode solver based on "Exact Solution To Guided Wave Propagation in Lossy Films" by Nagel et al, Optics Express 2011 Currently supports TE even modes only. ''' hlam = 0.5 nf = 2 + 0.5j nc = 1.5 wl = 1 h = hlam * wl k = 2 * pi / wl kf = nf * k kc = nc * k def f(kx): return kx * tan(kx * h) - sqrt(kf**2 - kc**2 - kx**2) f_vector = np.vectorize(f) def phi(wavevectors): b, a = wavevectors kx = b + 1j * a return np.real(f(kx) * f(kx).conj()) def phiPlotter(kx): return np.real(10 * sp.log10(f(kx) * f(kx).conj())) phiPlotter = np.vectorize(phiPlotter) ''' Find zeros in residue, convert to propagation constants ''' # Generate residue for complex plane kmax = abs(kf) kres = 100 a = np.linspace(0, kmax / 2, kres) b = np.linspace(0, 2 * kmax, kres) ## Use to match Fig 2 from paper # a = np.linspace(-1.5,1.5,20) # b = np.linspace(0,10,20) B, A = np.meshgrid(b, a) kx = B + 1j * A # Look for sign changes in real and imaginary parts of f(kx) fkx = f_vector(kx) sign_fr = np.sign(fkx.real) sign_fi = np.sign(fkx.imag) diff_fr = np.diff(sign_fr) diff_fi = np.diff(sign_fi) # Zeros must occur when both Real and Imag change sign simultaneously cross = np.abs(diff_fr) + np.abs(diff_fi) pts = np.where((cross == 4)) guesses = kx[pts] # Find minimum residual near initial guess. Returns OptimizeResult object for g in guesses: res = sp.optimize.minimize(phi, [g.real, g.imag]) if res.success: bx_min, ax_min = res.x else: print 'Minimize fail.' exit() kx_min = bx_min + 1j * ax_min # Find corresponding Beta (from equation A4) B = sqrt(kf**2 - kx_min**2) print 'kx: %.3f + %.3fi' % (kx_min.real, kx_min.imag) print 'Beta: %.3f + %.3fi' % (B.real, B.imag) ''' # Pretty pictures ''' ext = np.array(putil.getExtent(b, a)) asp = 'auto' fig, ax = plt.subplots(2, 2, figsize=(7, 7), sharex=True, sharey=True) # Residue plot ax[0, 0].set_title(r'$10\log_{10}(|f|^{2})$') resIm = ax[0, 0].imshow(phiPlotter(kx), extent=ext, vmax=40, vmin=-20, aspect=asp) #Colorbar # resmag = make_axes_locatable(ax[0]) # cres = resmag.append_axes("right", size="2%", pad=0.05) # cbarres = plt.colorbar(resIm,cax=cres,format='%u') ax[0, 1].set_title(r'$\Delta$Sign $Re\{f\}$') ax[1, 1].set_title(r'$\Delta$Sign $Im\{f\}$') ax[1, 0].set_title(r'Crossings') ax[0, 1].imshow(diff_fr, extent=ext, aspect=asp, cmap='coolwarm') ax[1, 1].imshow(diff_fi, extent=ext, aspect=asp, cmap='coolwarm') ax[1, 0].imshow(cross, extent=ext, aspect=asp, cmap='afmhot') ax[1, 0].set_xlabel(r'$\beta_{x} \lambda_{o}$') ax[1, 1].set_xlabel(r'$\beta_{x} \lambda_{o}$') ax[0, 0].set_ylabel(r'$\alpha_{x}\lambda_{o}$') ax[1, 0].set_ylabel(r'$\alpha_{x}\lambda_{o}$') # Beta(n,d,wl=wl,pol=pol,polarity='even',Nmodes=None,plot=True) # fig.colorbar(ima) plt.show() return
def example(): #--------------------------------# # Parameters #--------------------------------# # Simulation wl = 400. k = 2*pi/wl w = 200 h = 800 m = 1 n = 2 # Plotting res = 500 xmax = 800 Ro = 1. #distance to measure field (m) angle_res = 100 #--------------------------------# # Algorithm dipoles = getDipoles(m,n,w,h) xs = ys = np.linspace(-xmax,xmax,res) X,Y = np.meshgrid(xs,ys) for di,d in enumerate(dipoles): R = getR(d[0],d[1],X,Y) phi = pi*(getPhase(m,n,di)) if di==0: Fz = 1/R*exp(1j*(k*R + phi)) else: Fz += 1/R*exp(1j*(k*R + phi)) # Plot Real Field fig = plt.figure() ax = fig.add_subplot(111) Fz *= -1 #flip values so plot color matches dipole color Fz /= np.amax(abs(Fz)) scale = 0.01 im = ax.imshow(Fz.real,extent=putil.getExtent(xs,ys),vmax=scale,vmin=-1*scale,cmap='RdBu') fig.colorbar(im) drawDipoleBox(m,n,w,h,ax) for di,d in enumerate(dipoles): p = getPhase(m,n,di) ax.add_patch(Circle(d,15,facecolor=colors[p])) # Power plot fig = plt.figure() ax = fig.add_subplot(111) P = abs(Fz)**2 P /= np.amax(P) im = ax.imshow(P,extent=putil.getExtent(xs,ys),vmax=sqrt(scale),cmap='hot') fig.colorbar(im) # Plot Farfield ff_fig = plt.figure() ff_ax = ff_fig.add_subplot(111,polar=True) ff_ax.grid(True) FFplot(ff_ax,wl,w,h,m,n,Ro=Ro,angle_res=angle_res) print getFF(wl,w,h,m,n,0) plt.show() return 0
def overlay(modes='horizontal', asym=False, noLines=True): ''' Display cavity mode map over FDFD results NOTES: - There is a reversal in polarization convention between FDFD and waveguides ''' Q_TE_n4 = 'parameter sweeps/Q_TE_n4_45deg.pickle' Q_TM_n4 = 'parameter sweeps/Q_TM_n4_45deg.pickle' Q_TE_n4_0_deg = 'parameter sweeps/Q_TE_n4_0deg.pickle' Q_TE_n4_lossy = 'parameter sweeps/lossy/Q_TE_n4_k0_1_45deg.pickle' Qabs_TE_n4_lossy = 'parameter sweeps/lossy/Qabs_TE_n4_k0_1_45deg.pickle' Q_TE_n4_nsub2 = 'parameter sweeps/w_substrate/Q_TE_n4_nsub2_45deg.pickle' Q_TE_n4_metalsub = 'parameter sweeps/w_substrate/Q_TE_n4_esub-100_45deg.pickle' Q_TE_n4_metalsides = 'parameter sweeps/sidewalls/Q_TE_n4_nsides10j_wref_100.pickle' Q_TM_n4_metalsides = 'parameter sweeps/sidewalls/Q_TM_n4_nsides10j_wref_100.pickle' # Load FDFD data with open(PATH + Q_TM_n4, 'rb') as f: fdfd = pickle.load(f) ds = np.linspace(0.02, 3., 100) if not noLines: # Generate resonance map ds, ws = rect_cavity_modes( ncore=4, nclad=1, nsub=1, ms=np.array([3]), wmodes=7, pol='TM', linemap=False, colormap=False, usePhase=True #0.5*(pi+phase(ds,pol='TM',mode=0,nsub=1))*pi/180. ) if asym and not (modes == 'horizontal' or modes == 'vertical'): #do vertical modes ds, wsv = rect_cavity_modes(ncore=4, nclad=1, nsub=1, ms=np.array([1]), wmodes=7, pol='TM', linemap=False, colormap=False, usePhase=True) else: wsv = ws fig = plt.figure(figsize=(6.5, 5)) ax = fig.add_subplot(111) ext = putil.getExtent(ds, ds) vmax = 50 vmin = 0 im = ax.imshow(fdfd, extent=ext, vmin=vmin, vmax=vmax) fig.colorbar(im) if noLines: ax.set_xlabel(r'Width / $\lambda$') ax.set_ylabel(r'Height / $\lambda$') ax.set_title('Truncated Dielectric Slab Resonances') plt.show() exit() for i in range(len(ws[0, :, 0, 0])): for j in range(len(ws[0, 0, :, 0])): for k in range(5): if modes == 'horizontal': if i % 2 == 0: ax.plot(ws[:, i, j, k], ds, color='w', lw=3, ls='-') if i % 2 == 1: ax.plot(ws[:, i, j, k], ds, color='w', lw=3, ls=':') if modes == 'vertical': ax.plot(ds, ws[:, i, j, k], color='w', lw=3, ls='-') if modes == 'both': ax.plot(ds, wsv[:, i, j, k], color='w', lw=2, ls='-') #vert ax.plot(ws[:, i, j, k], ds, color='w', lw=2, ls='-') #horiz ax.set_xlim(0.02, 3) ax.set_ylim(0.02, 3) ax.set_xlabel(r'Width / $\lambda$') ax.set_ylabel(r'Height / $\lambda$') ax.set_title('Truncated Dielectric Slab Resonances') #ax.set_title(r'$Q_{abs}$',fontsize=18) plt.show()