plasmon-modal-efficiency.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. #!/usr/bin/env python3
  2. # -*- coding: UTF-8 -*-
  3. import numpy as np
  4. import matplotlib.pyplot as plt
  5. import os
  6. from scipy.special import hankel2 as H2n
  7. c = 299792458.0
  8. eps_0 = 8.854187817e-12 # F/m
  9. pi = np.pi
  10. verbose = 6
  11. # r of monitor
  12. r = 146.513e-9
  13. #debug = True
  14. debug = False
  15. def read_data(dirname):
  16. data = {}
  17. WLs = []
  18. for r,d,f in os.walk(dirname):
  19. for fname in f:
  20. WLs.append(fname)
  21. for fname in WLs:
  22. fdata = np.transpose(
  23. np.genfromtxt(dirname+"/"+fname, delimiter=", ",skip_header=1
  24. ,dtype=None, encoding = None
  25. , converters={0: lambda s: complex(s),
  26. 1: lambda s: complex(s),
  27. 2: lambda s: complex(s.replace('i', 'j')),
  28. 3: lambda s: complex(s.replace('i', 'j')),
  29. 4: lambda s: complex(s.replace('i', 'j')),
  30. 5: lambda s: complex(s.replace('i', 'j')),
  31. 6: lambda s: complex(s.replace('i', 'j')),
  32. 7: lambda s: complex(s.replace('i', 'j')),
  33. 8: lambda s: complex(s.replace('i', 'j'))
  34. }
  35. )
  36. )
  37. data[float(fname[2:-4])]=fdata
  38. if debug: break
  39. return data
  40. def find_nearest(array,value):
  41. idx = (np.abs(array-value)).argmin()
  42. return array[idx],idx
  43. def get_WLs_idx(WLs, data):
  44. dist = 1 #mkm
  45. mmedia = 1 # vacuum
  46. shift = 1 # one mesh step
  47. WLs_idx = []
  48. for wl in WLs:
  49. val, idx = find_nearest(data[dist][mmedia][shift][0,:],wl*1e-9)
  50. WLs_idx.append(idx)
  51. return WLs_idx
  52. # def check_field_match(data_in_air, data_in_gold,wl_idx,z_vec,kappa1,kappa2,eps2):
  53. # z = z_vec[i]*1e-9
  54. # if verbose > 8: print("z =",z)
  55. # H1_0 = H1[i]/np.exp(-kappa1[wl_idx]*z)
  56. # H2_0 = H2[i]/np.exp(-kappa2[wl_idx]*z)
  57. # E1_0 = E1[i]/np.exp(-kappa1[wl_idx]*z)
  58. # E2_0 = E2[i]/np.exp(-kappa2[wl_idx]*z)
  59. # E2_0e = E2[i]/np.exp(-kappa2[wl_idx]*z)*eps2[wl_idx]
  60. # if verbose > 8:
  61. # print("H0 air (%5.4g %+5.4gj)"%(np.real(H1_0), np.imag(H1_0)),
  62. # " from H1 (%5.4g %+5.4gj)"%(np.real(H1[i]), np.imag(H1[i])))
  63. def analyze(data,wl):
  64. # print(data[0,:]) # all z values
  65. #data = "z, dip.power, Ex, Ey, Ez, Hx, Hy, Hz, n_Au"
  66. # 0, 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 "
  67. lambd = wl
  68. omega = 2*pi*c/lambd
  69. eps_d = complex(1) # air, z>0
  70. eps_m = data[8,0]**2 # metal, z<0
  71. dip_power = data[1,0]
  72. z = data[0,:]
  73. idx_d = np.nonzero(z>1e-10)
  74. idx_0 = np.nonzero(np.logical_and(z<=1e-10, z>=-1e-10))
  75. idx_m = np.nonzero(z<-1e-10)
  76. z_d = z[idx_d]
  77. z_0 = z[idx_0]
  78. z_m = z[idx_m]
  79. if (not np.array_equal(np.hstack((z_m, z_0, z_d)), z)):
  80. print("ERROR! loosing z values!")
  81. raise
  82. Ex = data[2,:]
  83. Ex_m = data[2,idx_m][0]
  84. Ey_m = data[3,idx_m][0]
  85. Ez_m = data[4,idx_m][0]
  86. Hx_m = data[5,idx_m][0]
  87. Hy_m = data[6,idx_m][0]
  88. Hz_m = data[7,idx_m][0]
  89. E_m = np.transpose(np.array([Ex_m,Ey_m,Ez_m]))
  90. H_m = np.transpose(np.array([Hx_m,Hy_m,Hz_m]))
  91. Ex_d = data[2,idx_d][0]
  92. Ey_d = data[3,idx_d][0]
  93. Ez_d = data[4,idx_d][0]
  94. Hx_d = data[5,idx_d][0]
  95. Hy_d = data[6,idx_d][0]
  96. Hz_d = data[7,idx_d][0]
  97. E_d = np.transpose(np.array([Ex_d,Ey_d,Ez_d]))
  98. H_d = np.transpose(np.array([Hx_d,Hy_d,Hz_d]))
  99. k_0 = omega/c #air
  100. k_sp = k_0*np.sqrt(eps_d*eps_m/(eps_d+eps_m)) # eq5, supmat
  101. chi_d = np.sqrt( eps_d*k_0**2 - k_sp**2 ) # desc. after eq6c, supmat
  102. chi_m = np.sqrt( eps_m*k_0**2 - k_sp**2 ) # desc. after eq6c, supmat
  103. h_sp_d = np.exp(1j*chi_d*z_d) # eq6a, supmat
  104. e_sp_x_d = chi_d/(omega*eps_0*eps_d)*np.exp(1j*chi_d*z_d) # eq6b, supmat
  105. e_sp_z_d = k_sp/(omega*eps_0*eps_d)*np.exp(1j*chi_d*z_d) # eq6c, supmat
  106. h_sp_m = np.exp(1j*-chi_m*z_m) # eq6a, supmat
  107. e_sp_x_m = -chi_m/(omega*eps_0*eps_m)*np.exp(1j*-chi_m*z_m) # eq6b, supmat
  108. e_sp_z_m = k_sp/(omega*eps_0*eps_m)*np.exp(1j*-chi_m*z_m) # eq6c, supmat
  109. zero_m = np.zeros(len(h_sp_m))
  110. zero_d = np.zeros(len(h_sp_d))
  111. E_minus_sp_0_m = np.transpose([1j*H2n(1,k_sp*r)*e_sp_x_m,
  112. zero_m,
  113. H2n(0,k_sp*r)*e_sp_z_m]) # eq11, supmat, replace E_plus to E_minus and H1n to H2n
  114. H_minus_sp_0_m = np.transpose([zero_m,
  115. 1j*H2n(1,k_sp*r)*h_sp_m,
  116. zero_m]) # eq11, supmat, replace E_plus to E_minus and H1n to H2n
  117. E_minus_sp_0_d = np.transpose([1j*H2n(1,k_sp*r)*e_sp_x_d,
  118. zero_d,
  119. H2n(0,k_sp*r)*e_sp_z_d]) # eq11, supmat, replace E_plus to E_minus and H1n to H2n
  120. H_minus_sp_0_d = np.transpose([zero_d,
  121. 1j*H2n(1,k_sp*r)*h_sp_d,
  122. zero_d]) # eq11, supmat, replace E_plus to E_minus and H1n to H2n
  123. # E_m H_m E_d H_d
  124. N_sp_0 = (((-1)**0) * (4.0j/(omega*eps_0*k_sp))
  125. * (eps_d**2 - eps_m**2) / ((eps_m*eps_d)**(3/2)) )
  126. tmp_m = np.cross(E_minus_sp_0_m,H_m) - np.cross(E_m, H_minus_sp_0_m)
  127. radail_pojeciton_m = np.transpose(tmp_m)[0]
  128. integrand_m = (2*pi/N_sp_0)*radail_pojeciton_m*r
  129. tmp_d = np.cross(E_minus_sp_0_d,H_d) - np.cross(E_d, H_minus_sp_0_d)
  130. radail_pojeciton_d = np.transpose(tmp_d)[0]
  131. integrand_d = (2*pi/N_sp_0)*radail_pojeciton_d*r
  132. A_sp_0_m = np.trapz(integrand_m, z_m)
  133. A_sp_0_d = np.trapz(integrand_d, z_d)
  134. A_sp_0 = A_sp_0_m + A_sp_0_d
  135. return np.absolute(A_sp_0)**2
  136. # print("S from full field",np.real(np.cross(E,np.conj(H))))
  137. # print("H0 air (%5.4g %+5.4gj)"%(np.real(H1_0[wl_idx]), np.imag(H1_0[wl_idx])),
  138. # " from H1 (%5.4g %+5.4gj)"%(np.real(H1[0][wl_idx]), np.imag(H1[0][wl_idx])))
  139. # #plasmon_power = 1.0/2.0 * np.real( E1[0] * np.conj(H1[0])) # TODO check minus sign!!
  140. # plasmon_power = -1.0/2.0 * 2.0*np.pi*R * ( # TODO check minus sign!!
  141. # np.real( E1_0 * np.conj(H1_0) )
  142. # / (2.0 * np.real(kappa1))
  143. # +
  144. # np.real( E2_0 * np.conj(H1_0) )
  145. # / (2.0 * np.real(kappa2))
  146. # )* np.exp( 2.0*np.imag(k_spp)*R ) # TODO check minus sign!!
  147. # #print(np.abs(plasmon_power/ dip_power))
  148. # eta0 = plasmon_power[0]/ dip_power[0] *100
  149. # ppw = plasmon_power[0]
  150. # print("\n")
  151. # print(dirname)
  152. # print("Power: plasmon %4.3g W of dipoles %4.3g W, efficiency %5.3g%% from:"%(ppw, float(np.abs(dip_power[0])),float(np.abs( eta0))), ppw, eta0)
  153. # plt.plot(lambd*1e9, plasmon_power/ dip_power)
  154. # plt.ylim(0,0.04)
  155. # plt.xlim(550,800)
  156. # #plt.plot(lambd*1e9, np.real(eps2))
  157. # # plt.plot(lambd*1e9, np.real(k_spp))
  158. # # plt.plot(lambd*1e9, k_0)
  159. # #plt.semilogy(lambd*1e9, np.absolute(plasmon_power/ dip_power))
  160. # # # legend = []
  161. # # # legend.append(zshift[shift]+"@"+str(WLs[i])+" nm")
  162. # # # plt.legend(legend)
  163. # # # #plt.xlabel(r'THz')
  164. # plt.xlabel(r'$\lambda$, nm')
  165. # plt.ylabel(r'$P_{spp}/P_{dipole}$',labelpad=-5)
  166. # #plt.title(' R = '+str(core_r)+' nm')
  167. # plt.savefig(dirname+"_power_ratio."+file_ext)
  168. # plt.clf()
  169. # plt.close()
  170. file_ext="pdf"
  171. def main ():
  172. if verbose > 5:
  173. print("r =",r)
  174. dirname="bigourdan-Au-sub-dipole-W.fsp.1D.monitor_1.results"
  175. data = read_data(dirname)
  176. WLs = []
  177. A2 = []
  178. for wl in data:
  179. WLs.append(wl)
  180. A2.append(analyze(data[wl],wl))
  181. #print(WLs)
  182. WLs1 = np.array(WLs)
  183. A21 = np.array(A2)
  184. dirname="bigourdan-Au-sub-Cyl-dipole-W.fsp.1D.monitor_1.results"
  185. data = read_data(dirname)
  186. WLs = []
  187. A2 = []
  188. for wl in data:
  189. WLs.append(wl)
  190. A2.append(analyze(data[wl],wl))
  191. #print(WLs)
  192. WLs2 = np.array(WLs)
  193. A22 = np.array(A2)
  194. # data = np.vstack((WLs,A2))
  195. # print(np.sort(data))
  196. plt.plot(WLs1*1e9, A21*275, linestyle='None', marker='o', color="black",label="x 275, no ant.")
  197. plt.plot(WLs2*1e9, A22, linestyle='None', marker='*', color="red", label="with antena")
  198. plt.legend()
  199. plt.xlabel(r'$\lambda$, nm')
  200. plt.ylim(0,0.2)
  201. plt.ylabel(r'$|A_{sp}|^2$',labelpad=-1)
  202. #plt.title(dirname)
  203. plt.savefig(dirname+"_A2."+file_ext)
  204. plt.clf()
  205. plt.close()
  206. main()