calc-SiAgSi-Qabs.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. #!/usr/bin/env python
  2. # -*- coding: UTF-8 -*-
  3. #
  4. # Copyright (C) 2009-2015 Ovidio Peña Rodríguez <ovidio@bytesfall.com>
  5. #
  6. # This file is part of python-scattnlay
  7. #
  8. # This program is free software: you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation, either version 3 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. #
  18. # The only additional remark is that we expect that all publications
  19. # describing work using this software, or all commercial products
  20. # using it, cite the following reference:
  21. # [1] O. Pena and U. Pal, "Scattering of electromagnetic radiation by
  22. # a multilayered sphere," Computer Physics Communications,
  23. # vol. 180, Nov. 2009, pp. 2348-2354.
  24. #
  25. # You should have received a copy of the GNU General Public License
  26. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  27. # This test case calculates the electric field in the
  28. # E-k plane, for an spherical Si-Ag-Si nanoparticle.
  29. import scattnlay
  30. from scattnlay import fieldnlay
  31. from scattnlay import scattnlay
  32. import numpy as np
  33. import cmath
  34. from fieldplot import GetFlow3D
  35. from fieldplot import GetField
  36. ###############################################################################
  37. def SetXM(design):
  38. """ design value:
  39. 1: AgSi - a1
  40. 2: SiAgSi - a1, b1
  41. 3: SiAgSi - a1, b2
  42. """
  43. epsilon_Si = 18.4631066585 + 0.6259727805j
  44. epsilon_Ag = -8.5014154589 + 0.7585845411j
  45. index_Si = np.sqrt(epsilon_Si)
  46. index_Ag = np.sqrt(epsilon_Ag)
  47. isSiAgSi=True
  48. isBulk = False
  49. if design==1:
  50. #36 5.62055 0 31.93 4.06 49 5.62055 500
  51. isSiAgSi=False
  52. WL=500 #nm
  53. core_width = 0.0 #nm Si
  54. inner_width = 31.93 #nm Ag
  55. outer_width = 4.06 #nm Si
  56. elif design==2:
  57. #62.5 4.48866 29.44 10.33 22.73 0 4.48866 500
  58. WL=500 #nm
  59. core_width = 29.44 #nm Si
  60. inner_width = 10.33 #nm Ag
  61. outer_width = 22.73 #nm Si
  62. elif design == 3:
  63. #81.4 3.14156 5.27 8.22 67.91 0 3.14156 500
  64. WL=500 #nm
  65. core_width = 5.27 #nm Si
  66. inner_width = 8.22 #nm Ag
  67. outer_width = 67.91 #nm Si
  68. elif design==4:
  69. WL=800 #nm
  70. epsilon_Si = 13.64 + 0.047j
  71. epsilon_Ag = -28.05 + 1.525j
  72. core_width = 17.74 #nm Si
  73. inner_width = 23.31 #nm Ag
  74. outer_width = 22.95 #nm Si
  75. elif design==5:
  76. WL=354 #nm
  77. core_r = WL/20.0
  78. epsilon_Ag = -2.0 + 0.28j #original
  79. index_Ag = np.sqrt(epsilon_Ag)
  80. x = np.ones((1), dtype = np.float64)
  81. x[0] = 2.0*np.pi*core_r/WL
  82. m = np.ones((1), dtype = np.complex128)
  83. m[0] = index_Ag
  84. # x = np.ones((2), dtype = np.float64)
  85. # x[0] = 2.0*np.pi*core_r/WL/4.0*3.0
  86. # x[1] = 2.0*np.pi*core_r/WL
  87. # m = np.ones((2), dtype = np.complex128)
  88. # m[0] = index_Ag
  89. # m[1] = index_Ag
  90. return x, m, WL
  91. core_r = core_width
  92. inner_r = core_r+inner_width
  93. outer_r = inner_r+outer_width
  94. nm = 1.0
  95. if isSiAgSi:
  96. x = np.ones((3), dtype = np.float64)
  97. x[0] = 2.0*np.pi*core_r/WL
  98. x[1] = 2.0*np.pi*inner_r/WL
  99. x[2] = 2.0*np.pi*outer_r/WL
  100. m = np.ones((3), dtype = np.complex128)
  101. m[0] = index_Si/nm
  102. m[1] = index_Ag/nm
  103. # m[0, 1] = index_Si/nm
  104. m[2] = index_Si/nm
  105. else:
  106. # bilayer
  107. x = np.ones((2), dtype = np.float64)
  108. x[0] = 2.0*np.pi*inner_r/WL
  109. x[1] = 2.0*np.pi*outer_r/WL
  110. m = np.ones((2), dtype = np.complex128)
  111. m[0] = index_Ag/nm
  112. m[1] = index_Si/nm
  113. return x, m, WL
  114. ###############################################################################
  115. #design = 1 #AgSi
  116. #design = 2
  117. #design = 3
  118. #design = 4 # WL=800
  119. design = 5 # Bulk Ag
  120. x, m, WL = SetXM(design)
  121. WL_units='nm'
  122. comment='P-SiAgSi-flow'
  123. comment='bulk-P-Ag-flow'
  124. print "x =", x
  125. print "m =", m
  126. npts = 101
  127. factor=2.2
  128. flow_total = 3
  129. #flow_total = 0
  130. crossplane='XZ'
  131. #crossplane='YZ'
  132. #crossplane='XY'
  133. Ec, Hc, P, coordX, coordZ = GetField(crossplane, npts, factor, x, m)
  134. Er = np.absolute(Ec)
  135. Hr = np.absolute(Hc)
  136. # |E|/|Eo|
  137. Eabs = np.sqrt(Er[ :, 0]**2 + Er[ :, 1]**2 + Er[ :, 2]**2)
  138. Eangle = np.angle(Ec[ :, 0])/np.pi*180
  139. Habs= np.sqrt(Hr[ :, 0]**2 + Hr[ :, 1]**2 + Hr[ :, 2]**2)
  140. Hangle = np.angle(Hc[ :, 1])/np.pi*180
  141. try:
  142. import matplotlib.pyplot as plt
  143. from matplotlib import cm
  144. from matplotlib.colors import LogNorm
  145. Eabs_data = np.resize(P, (npts, npts)).T
  146. #Eabs_data = np.resize(Pabs, (npts, npts)).T
  147. # Eangle_data = np.resize(Eangle, (npts, npts)).T
  148. # Habs_data = np.resize(Habs, (npts, npts)).T
  149. # Hangle_data = np.resize(Hangle, (npts, npts)).T
  150. fig, ax = plt.subplots(1,1)
  151. # Rescale to better show the axes
  152. scale_x = np.linspace(min(coordX)*WL/2.0/np.pi, max(coordX)*WL/2.0/np.pi, npts)
  153. scale_z = np.linspace(min(coordZ)*WL/2.0/np.pi, max(coordZ)*WL/2.0/np.pi, npts)
  154. # Define scale ticks
  155. min_tick = np.amin(Eabs_data[~np.isnan(Eabs_data)])
  156. max_tick = np.amax(Eabs_data[~np.isnan(Eabs_data)])
  157. scale_ticks = np.linspace(min_tick, max_tick, 6)
  158. # Interpolation can be 'nearest', 'bilinear' or 'bicubic'
  159. ax.set_title('Pabs')
  160. cax = ax.imshow(Eabs_data, interpolation = 'nearest', cmap = cm.jet,
  161. origin = 'lower'
  162. , vmin = min_tick, vmax = max_tick
  163. , extent = (min(scale_x), max(scale_x), min(scale_z), max(scale_z))
  164. #,norm = LogNorm()
  165. )
  166. ax.axis("image")
  167. # Add colorbar
  168. cbar = fig.colorbar(cax, ticks = [a for a in scale_ticks])
  169. cbar.ax.set_yticklabels(['%5.3g' % (a) for a in scale_ticks]) # vertically oriented colorbar
  170. pos = list(cbar.ax.get_position().bounds)
  171. #fig.text(pos[0] - 0.02, 0.925, '|E|/|E$_0$|', fontsize = 14)
  172. if crossplane=='XZ':
  173. plt.xlabel('Z, '+WL_units)
  174. plt.ylabel('X, '+WL_units)
  175. elif crossplane=='YZ':
  176. plt.xlabel('Z, '+WL_units)
  177. plt.ylabel('Y, '+WL_units)
  178. elif crossplane=='XY':
  179. plt.xlabel('Y, '+WL_units)
  180. plt.ylabel('X, '+WL_units)
  181. # # This part draws the nanoshell
  182. from matplotlib import patches
  183. from matplotlib.path import Path
  184. for xx in x:
  185. r= xx*WL/2.0/np.pi
  186. s1 = patches.Arc((0, 0), 2.0*r, 2.0*r, angle=0.0, zorder=1.8,
  187. theta1=0.0, theta2=360.0, linewidth=1, color='black')
  188. ax.add_patch(s1)
  189. #
  190. # for flow in range(0,flow_total):
  191. # flow_x, flow_z = GetFlow(scale_x, scale_z, Ec, Hc,
  192. # min(scale_x)+flow*(scale_x[-1]-scale_x[0])/(flow_total-1),
  193. # min(scale_z),
  194. # #0.0,
  195. # npts*16)
  196. # verts = np.vstack((flow_z, flow_x)).transpose().tolist()
  197. # #codes = [Path.CURVE4]*len(verts)
  198. # codes = [Path.LINETO]*len(verts)
  199. # codes[0] = Path.MOVETO
  200. # path = Path(verts, codes)
  201. # patch = patches.PathPatch(path, facecolor='none', lw=1, edgecolor='yellow')
  202. # ax.add_patch(patch)
  203. if (crossplane=='XZ' or crossplane=='YZ') and flow_total>0:
  204. from matplotlib.path import Path
  205. scanSP = np.linspace(-factor*x[-1], factor*x[-1], npts)
  206. min_SP = -factor*x[-1]
  207. step_SP = 2.0*factor*x[-1]/(flow_total-1)
  208. x0, y0, z0 = 0, 0, 0
  209. max_length=factor*x[-1]*15
  210. #max_length=factor*x[-1]*5
  211. max_angle = np.pi/200
  212. #for flow in range(0,flow_total*2+1):
  213. for flow in range(0,flow_total):
  214. if crossplane=='XZ':
  215. #x0 = min_SP*2 + flow*step_SP
  216. x0 = min_SP + flow*step_SP
  217. z0 = min_SP
  218. #y0 = x[-1]/20
  219. elif crossplane=='YZ':
  220. #y0 = min_SP*2 + flow*step_SP
  221. y0 = min_SP + flow*step_SP
  222. z0 = min_SP
  223. #x0 = x[-1]/20
  224. flow_xSP, flow_ySP, flow_zSP = GetFlow3D(x0, y0, z0, max_length, max_angle, x, m)
  225. if crossplane=='XZ':
  226. flow_z_plot = flow_zSP*WL/2.0/np.pi
  227. flow_f_plot = flow_xSP*WL/2.0/np.pi
  228. elif crossplane=='YZ':
  229. flow_z_plot = flow_zSP*WL/2.0/np.pi
  230. flow_f_plot = flow_ySP*WL/2.0/np.pi
  231. verts = np.vstack((flow_z_plot, flow_f_plot)).transpose().tolist()
  232. codes = [Path.LINETO]*len(verts)
  233. codes[0] = Path.MOVETO
  234. path = Path(verts, codes)
  235. #patch = patches.PathPatch(path, facecolor='none', lw=0.2, edgecolor='white',zorder = 2.7)
  236. patch = patches.PathPatch(path, facecolor='none', lw=1, edgecolor='white',zorder = 1.9)
  237. ax.add_patch(patch)
  238. ax.plot(flow_z_plot, flow_f_plot, 'x',ms=2, mew=0.1, linewidth=0.5, color='k', fillstyle='none')
  239. plt.savefig(comment+"-R"+str(int(round(x[-1]*WL/2.0/np.pi)))+"-"+crossplane+".svg")
  240. plt.draw()
  241. # plt.show()
  242. plt.clf()
  243. plt.close()
  244. finally:
  245. terms, Qext, Qsca, Qabs, Qbk, Qpr, g, Albedo, S1, S2 = scattnlay(np.array([x]),
  246. np.array([m]))
  247. print("Qabs = "+str(Qabs));
  248. #