plasmon-modal-efficiency.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. #!/usr/bin/env python3
  2. # -*- coding: UTF-8 -*-
  3. from scipy.special import hankel2 as H2n
  4. import matplotlib.pyplot as plt
  5. import numpy as np
  6. import os
  7. import scipy.io
  8. c = 299792458.0
  9. eps_0 = 8.854187817e-12 # F/m
  10. pi = np.pi
  11. # r of monitor
  12. #r = 146.513e-9
  13. r = 800e-9
  14. # debug = True
  15. # verbose = 7
  16. debug = False
  17. verbose = 6
  18. def read_data_mat(fname):
  19. #data = "z, dip.power, Ex, Ey, Ez, Hx, Hy, Hz, n_Au"
  20. # 0, 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 "
  21. mat = scipy.io.loadmat(fname)
  22. lambd = np.reshape(mat["lambda"],(-1))
  23. dippower = np.reshape(mat["dippower"],(-1))
  24. vacpower = np.reshape(mat["vacpower"],(-1))
  25. z = np.reshape(mat["z"],(-1))
  26. n_Au = np.reshape(mat["n_fdtd"],(-1))
  27. onez = np.ones((len(z)))
  28. data1 = {}
  29. r1 = mat["mon1_E"][0,0][4][0,0]
  30. E1 = mat["mon1_E"][0,0][0]
  31. H1 = mat["mon1_H"][0,0][0]
  32. data2 = {}
  33. r2 = mat["mon2_E"][0,0][4][0,0]
  34. E2 = mat["mon2_E"][0,0][0]
  35. H2 = mat["mon2_H"][0,0][0]
  36. for i in range(len(lambd)):
  37. fdata = np.vstack(( z.astype(np.complex128), dippower[i]*onez.astype(np.complex128)
  38. ,E1[:,0,i], E1[:,1,i], E1[:,2,i]
  39. ,H1[:,0,i], H1[:,1,i], H1[:,2,i]
  40. ,n_Au[i]*onez.astype(np.complex128), dippower[i]*onez.astype(np.complex128)
  41. ))
  42. data1[lambd[i]]=fdata
  43. fdata = np.vstack(( z.astype(np.complex128), dippower[i]*onez.astype(np.complex128)
  44. ,E2[:,0,i], E2[:,1,i], E2[:,2,i]
  45. ,H2[:,0,i], H2[:,1,i], H2[:,2,i]
  46. ,n_Au[i]*onez.astype(np.complex128), dippower[i]*onez.astype(np.complex128)
  47. ))
  48. data2[lambd[i]]=fdata
  49. if debug: break
  50. return ((r1,data1),(r2,data2))
  51. def read_data(dirname):
  52. data = {}
  53. WLs = []
  54. for r,d,f in os.walk(dirname):
  55. for fname in f:
  56. WLs.append(fname)
  57. for fname in WLs:
  58. fdata = np.transpose(
  59. np.genfromtxt(dirname+"/"+fname, delimiter=", ",skip_header=1
  60. ,dtype=None, encoding = None
  61. , converters={0: lambda s: complex(s),
  62. 1: lambda s: complex(s),
  63. 2: lambda s: complex(s.replace('i', 'j')),
  64. 3: lambda s: complex(s.replace('i', 'j')),
  65. 4: lambda s: complex(s.replace('i', 'j')),
  66. 5: lambda s: complex(s.replace('i', 'j')),
  67. 6: lambda s: complex(s.replace('i', 'j')),
  68. 7: lambda s: complex(s.replace('i', 'j')),
  69. 8: lambda s: complex(s.replace('i', 'j'))
  70. }
  71. )
  72. )
  73. data[float(fname[2:-4])]=fdata
  74. if debug: break
  75. return data
  76. def find_nearest(array,value):
  77. idx = (np.abs(array-value)).argmin()
  78. return array[idx],idx
  79. def get_WLs_idx(WLs, data):
  80. dist = 1 #mkm
  81. mmedia = 1 # vacuum
  82. shift = 1 # one mesh step
  83. WLs_idx = []
  84. for wl in WLs:
  85. val, idx = find_nearest(data[dist][mmedia][shift][0,:],wl*1e-9)
  86. WLs_idx.append(idx)
  87. return WLs_idx
  88. # def check_field_match(data_in_air, data_in_gold,wl_idx,z_vec,kappa1,kappa2,eps2):
  89. # z = z_vec[i]*1e-9
  90. # if verbose > 8: print("z =",z)
  91. # H1_0 = H1[i]/np.exp(-kappa1[wl_idx]*z)
  92. # H2_0 = H2[i]/np.exp(-kappa2[wl_idx]*z)
  93. # E1_0 = E1[i]/np.exp(-kappa1[wl_idx]*z)
  94. # E2_0 = E2[i]/np.exp(-kappa2[wl_idx]*z)
  95. # E2_0e = E2[i]/np.exp(-kappa2[wl_idx]*z)*eps2[wl_idx]
  96. # if verbose > 8:
  97. # print("H0 air (%5.4g %+5.4gj)"%(np.real(H1_0), np.imag(H1_0)),
  98. # " from H1 (%5.4g %+5.4gj)"%(np.real(H1[i]), np.imag(H1[i])))
  99. def cross(a, b):
  100. c = [a[1]*b[2] - a[2]*b[1],
  101. a[2]*b[0] - a[0]*b[2],
  102. a[0]*b[1] - a[1]*b[0]]
  103. return c
  104. def analyze(data,wl):
  105. # print(data[0,:]) # all z values
  106. #data = "z, dip.power, Ex, Ey, Ez, Hx, Hy, Hz, n_Au, vac. power"
  107. # 0, 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9"
  108. lambd = wl
  109. omega = 2*pi*c/lambd
  110. eps_d = complex(1) # air, z>0
  111. eps_m = data[8,0]**2 # metal, z<0
  112. dip_power = data[1,0]
  113. vac_power = data[9,0]
  114. z = data[0,:]
  115. idx_d = np.nonzero(z>1e-10)
  116. idx_0 = np.nonzero(np.logical_and(z<=1e-10, z>=-1e-10))
  117. idx_m = np.nonzero(z<-1e-10)
  118. z_d = z[idx_d]
  119. z_0 = z[idx_0]
  120. z_m = z[idx_m]
  121. if (not np.array_equal(np.hstack((z_m, z_0, z_d)), z)):
  122. print("ERROR! loosing z values!")
  123. raise
  124. Ex_m = data[2,idx_m][0]
  125. Ey_m = data[3,idx_m][0]
  126. Ez_m = data[4,idx_m][0]
  127. Hx_m = data[5,idx_m][0]
  128. Hy_m = data[6,idx_m][0]
  129. Hz_m = data[7,idx_m][0]
  130. E_m = np.transpose(np.array([Ex_m,Ey_m,Ez_m]))
  131. H_m = np.transpose(np.array([Hx_m,Hy_m,Hz_m]))
  132. Ex_d = data[2,idx_d][0]
  133. Ey_d = data[3,idx_d][0]
  134. Ez_d = data[4,idx_d][0]
  135. Hx_d = data[5,idx_d][0]
  136. Hy_d = data[6,idx_d][0]
  137. Hz_d = data[7,idx_d][0]
  138. E_d = np.transpose(np.array([Ex_d,Ey_d,Ez_d]))
  139. H_d = np.transpose(np.array([Hx_d,Hy_d,Hz_d]))
  140. k_0 = omega/c #air
  141. k_sp = k_0*np.sqrt(eps_d*eps_m/(eps_d+eps_m)) # eq5, supmat
  142. chi_d = np.sqrt( eps_d*k_0**2 - k_sp**2 ) # desc. after eq6c, supmat
  143. chi_m = np.sqrt( eps_m*k_0**2 - k_sp**2 ) # desc. after eq6c, supmat
  144. # # TODO!!! alt
  145. # chi_d = np.sqrt( k_sp**2 - eps_d*k_0**2 ) # desc. after eq6c, supmat
  146. # chi_m = np.sqrt( k_sp**2 - eps_m*k_0**2 ) # desc. after eq6c, supmat
  147. mul = -1 #TODO!!! minus???
  148. h_sp_d = np.exp(mul*1j*chi_d*z_d) # eq6a, supmat
  149. e_sp_x_d = chi_d/(omega*eps_0*eps_d)*np.exp(mul*1j*chi_d*z_d) # eq6b, supmat
  150. e_sp_z_d = -k_sp/(omega*eps_0*eps_d)*np.exp(mul*1j*chi_d*z_d) # eq6c, supmat
  151. h_sp_m = np.exp(1j*-chi_m*z_m) # eq6a, supmat
  152. e_sp_x_m = -chi_m/(omega*eps_0*eps_m)*np.exp(1j*-chi_m*z_m) # eq6b, supmat
  153. e_sp_z_m = -k_sp/(omega*eps_0*eps_m)*np.exp(1j*-chi_m*z_m) # eq6c, supmat
  154. if verbose > 8:
  155. print("WL =",1e9*wl)
  156. # if 1e9*wl > 763 and 1e9*wl < 766:
  157. print(1j*1e9/chi_d)
  158. print(1j*1e9/chi_m)
  159. print("_d")
  160. print(1e9*z_d)
  161. print(h_sp_d)
  162. print("_m")
  163. print(1e9*z_m)
  164. print(h_sp_m)
  165. zero_m = np.zeros(len(h_sp_m))
  166. zero_d = np.zeros(len(h_sp_d))
  167. E_minus_sp_0_m = np.transpose([1j*H2n(1,k_sp*r)*e_sp_x_m,
  168. zero_m,
  169. H2n(0,k_sp*r)*e_sp_z_m]) # eq11, supmat, replace E_plus to E_minus and H1n to H2n
  170. H_minus_sp_0_m = np.transpose([zero_m,
  171. 1j*H2n(1,k_sp*r)*h_sp_m,
  172. zero_m]) # eq11, supmat, replace E_plus to E_minus and H1n to H2n
  173. E_minus_sp_0_d = np.transpose([1j*H2n(1,k_sp*r)*e_sp_x_d,
  174. zero_d,
  175. H2n(0,k_sp*r)*e_sp_z_d]) # eq11, supmat, replace E_plus to E_minus and H1n to H2n
  176. H_minus_sp_0_d = np.transpose([zero_d,
  177. 1j*H2n(1,k_sp*r)*h_sp_d,
  178. zero_d]) # eq11, supmat, replace E_plus to E_minus and H1n to H2n
  179. # E_m H_m E_d H_d
  180. N_sp_0 = ( ((-1)**0) * (4.0j / (omega*eps_0*k_sp))
  181. * (eps_d**2 - eps_m**2) / ((eps_m*eps_d)**(3/2)) )
  182. tmp_m = np.cross(E_minus_sp_0_m,H_m) - np.cross(E_m, H_minus_sp_0_m)
  183. #tmp_m = np.cross(E_minus_sp_0_m,np.conj(H_m)) + np.cross(np.conj(E_m), H_minus_sp_0_m)
  184. radail_pojeciton_m = np.transpose(tmp_m)[0]
  185. integrand_m = (2*pi/N_sp_0)*radail_pojeciton_m*r
  186. # a = E_minus_sp_0_m[0]*1e9
  187. # print("\n\nE_minus:", a )
  188. # b = H_m[0]*1e9
  189. # print("H_m:",b)
  190. # print("\ncross:",np.cross(E_minus_sp_0_m*1e9,H_m*1e9)[0])
  191. # print("cross:",np.array(cross(a,b)))
  192. tmp_d = np.cross(E_minus_sp_0_d,H_d) - np.cross(E_d, H_minus_sp_0_d)
  193. #tmp_d = np.cross(E_minus_sp_0_d,np.conj(H_d)) + np.cross(np.conj(E_d), H_minus_sp_0_d)
  194. radail_pojeciton_d = np.transpose(tmp_d)[0]
  195. integrand_d = (2*pi/N_sp_0)*radail_pojeciton_d*r
  196. A_sp_0_m = np.trapz(integrand_m, z_m)
  197. A_sp_0_d = np.trapz(integrand_d, z_d)
  198. A_sp_0 = A_sp_0_m + A_sp_0_d
  199. return np.absolute(A_sp_0)**2
  200. # print("S from full field",np.real(np.cross(E,np.conj(H))))
  201. # print("H0 air (%5.4g %+5.4gj)"%(np.real(H1_0[wl_idx]), np.imag(H1_0[wl_idx])),
  202. # " from H1 (%5.4g %+5.4gj)"%(np.real(H1[0][wl_idx]), np.imag(H1[0][wl_idx])))
  203. # #plasmon_power = 1.0/2.0 * np.real( E1[0] * np.conj(H1[0])) # TODO check minus sign!!
  204. # plasmon_power = -1.0/2.0 * 2.0*np.pi*R * ( # TODO check minus sign!!
  205. # np.real( E1_0 * np.conj(H1_0) )
  206. # / (2.0 * np.real(kappa1))
  207. # +
  208. # np.real( E2_0 * np.conj(H1_0) )
  209. # / (2.0 * np.real(kappa2))
  210. # )* np.exp( 2.0*np.imag(k_spp)*R ) # TODO check minus sign!!
  211. # #print(np.abs(plasmon_power/ dip_power))
  212. # eta0 = plasmon_power[0]/ dip_power[0] *100
  213. # ppw = plasmon_power[0]
  214. # print("\n")
  215. # print(dirname)
  216. # 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)
  217. # plt.plot(lambd*1e9, plasmon_power/ dip_power)
  218. # plt.ylim(0,0.04)
  219. # plt.xlim(550,800)
  220. # #plt.plot(lambd*1e9, np.real(eps2))
  221. # # plt.plot(lambd*1e9, np.real(k_spp))
  222. # # plt.plot(lambd*1e9, k_0)
  223. # #plt.semilogy(lambd*1e9, np.absolute(plasmon_power/ dip_power))
  224. # # # legend = []
  225. # # # legend.append(zshift[shift]+"@"+str(WLs[i])+" nm")
  226. # # # plt.legend(legend)
  227. # # # #plt.xlabel(r'THz')
  228. # plt.xlabel(r'$\lambda$, nm')
  229. # plt.ylabel(r'$P_{spp}/P_{dipole}$',labelpad=-5)
  230. # #plt.title(' R = '+str(core_r)+' nm')
  231. # plt.savefig(dirname+"_power_ratio."+file_ext)
  232. # plt.clf()
  233. # plt.close()
  234. file_ext="pdf"
  235. def main (monitor_index):
  236. #dirname="bigourdan-Au-sub-dipole-W.fsp.1D.monitor_1.results"
  237. #dirname="bigourdan-Au-sub-dipole-W-2mon.fsp.1D.monitor_2.results"
  238. #data = read_data(dirname)
  239. #filename = 'bigourdan-Au-sub-dipole-W-2mon.fsp.1D.mat'
  240. filename="bg-Au-sub-dipole-Au.fsp.1D.mat"
  241. data2 = read_data_mat(filename)
  242. r,data = data2[monitor_index]
  243. if verbose > 5:
  244. print("r =",r)
  245. WLs = []
  246. A2 = []
  247. for wl in data:
  248. WLs.append(wl)
  249. A2.append(analyze(data[wl],wl))
  250. WLs1 = np.array(WLs)
  251. A21 = np.array(A2)
  252. #return
  253. # #dirname="bigourdan-Au-sub-Cyl-dipole-W.fsp.1D.monitor_1.results"
  254. # dirname="bigourdan-Au-sub-Cyl-dipole-W-2mon.fsp.1D.monitor_2.results"
  255. # data = read_data(dirname)
  256. #filename = 'bg-Au-sub-Au-dipole-Au.fsp.1D.mat'
  257. filename = 'bg-Au-sub-Si-dipole-Au.fsp.1D.mat'
  258. data2 = read_data_mat(filename)
  259. r,data = data2[monitor_index]
  260. WLs = []
  261. A2 = []
  262. for wl in data:
  263. WLs.append(wl)
  264. A2.append(analyze(data[wl],wl))
  265. #print(WLs)
  266. WLs2 = np.array(WLs)
  267. A22 = np.array(A2)
  268. # data = np.vstack((WLs,A2))
  269. # print(np.sort(data))
  270. plt.plot(WLs1*1e9, A22/A21, color="black",label="eff.")
  271. # plt.plot(WLs1*1e9, A21, color="black",label="x 275, no ant.")
  272. # plt.plot(WLs2*1e9, A22, color="red", label="with antena")
  273. plt.legend()
  274. plt.xlabel(r'$\lambda$, nm')
  275. # if monitor_index == 0:
  276. # plt.ylim(0,2)
  277. # else:
  278. # plt.ylim(0,0.32)
  279. #plt.ylim(0,2)
  280. plt.ylabel(r'$^{|A^{ant}_{sp}|^2}/_{|A^0_{sp}|^2}$',labelpad=1,size=14)
  281. plt.title("r = %4.1f nm"%(r*1e9))
  282. plt.savefig(filename+str(monitor_index)+"_A2."+file_ext)
  283. plt.clf()
  284. plt.close()
  285. main(0)
  286. main(1)