field-Ag-flow.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. #!/usr/bin/env python
  2. # -*- coding: UTF-8 -*-
  3. #
  4. # Copyright (C) 2009-2015 Ovidio Peña Rodríguez <ovidio@bytesfall.com>
  5. # Copyright (C) 2013-2015 Konstantin Ladutenko <kostyfisik@gmail.com>
  6. #
  7. # This file is part of python-scattnlay
  8. #
  9. # This program is free software: you can redistribute it and/or modify
  10. # it under the terms of the GNU General Public License as published by
  11. # the Free Software Foundation, either version 3 of the License, or
  12. # (at your option) any later version.
  13. #
  14. # This program is distributed in the hope that it will be useful,
  15. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. # GNU General Public License for more details.
  18. #
  19. # The only additional remark is that we expect that all publications
  20. # describing work using this software, or all commercial products
  21. # using it, cite the following reference:
  22. # [1] O. Pena and U. Pal, "Scattering of electromagnetic radiation by
  23. # a multilayered sphere," Computer Physics Communications,
  24. # vol. 180, Nov. 2009, pp. 2348-2354.
  25. #
  26. # You should have received a copy of the GNU General Public License
  27. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  28. # This test case calculates the electric field in the
  29. # E-k plane, for an spherical Ag nanoparticle.
  30. import scattnlay
  31. from scattnlay import fieldnlay
  32. from scattnlay import scattnlay
  33. from fieldplot import fieldplot
  34. import numpy as np
  35. import cmath
  36. <<<<<<< HEAD
  37. def get_index(array,value):
  38. idx = (np.abs(array-value)).argmin()
  39. return idx
  40. #Ec = np.resize(Ec, (npts, npts)).T
  41. def GetFlow(scale_x, scale_z, Ec, Hc, a, b, nmax):
  42. # Initial position
  43. flow_x = [a]
  44. flow_z = [b]
  45. x_pos = flow_x[-1]
  46. z_pos = flow_z[-1]
  47. x_idx = get_index(scale_x, x_pos)
  48. z_idx = get_index(scale_z, z_pos)
  49. S=np.cross(Ec[npts*z_idx+x_idx], Hc[npts*z_idx+x_idx].conjugate()).real
  50. #if (np.linalg.norm(S)> 1e-4):
  51. Snorm_prev=S/np.linalg.norm(S)
  52. Snorm_prev=Snorm_prev.real
  53. for n in range(0, nmax):
  54. #Get the next position
  55. #1. Find Poynting vector and normalize it
  56. x_pos = flow_x[-1]
  57. z_pos = flow_z[-1]
  58. x_idx = get_index(scale_x, x_pos)
  59. z_idx = get_index(scale_z, z_pos)
  60. Epoint = Ec[npts*z_idx+x_idx]
  61. Hpoint = Hc[npts*z_idx+x_idx]
  62. S=np.cross(Epoint, Hpoint.conjugate())
  63. #if (np.linalg.norm(S)> 1e-4):
  64. Snorm=S.real/np.linalg.norm(S)
  65. #Snorm=Snorm.real
  66. #2. Evaluate displacement = half of the discrete and new position
  67. dpos = abs(scale_z[0]-scale_z[1])/2.0
  68. dx = dpos*Snorm[0];
  69. dz = dpos*Snorm[2];
  70. x_pos = x_pos+dx
  71. z_pos = z_pos+dz
  72. #3. Save result
  73. flow_x.append(x_pos)
  74. flow_z.append(z_pos)
  75. return flow_x, flow_z
  76. =======
  77. >>>>>>> feb3ad9a4b3aa424f2e1087b4bc7b9bc52598810
  78. # # a)
  79. #WL=400 #nm
  80. #core_r = WL/20.0
  81. #epsilon_Ag = -2.0 + 10.0j
  82. # # b)
  83. #WL=400 #nm
  84. #core_r = WL/20.0
  85. #epsilon_Ag = -2.0 + 1.0j
  86. # c)
  87. WL=354 #nm
  88. core_r = WL/20.0
  89. epsilon_Ag = -2.0 + 0.28j
  90. # d)
  91. #WL=367 #nm
  92. #core_r = WL/20.0
  93. #epsilon_Ag = -2.71 + 0.25j
  94. index_Ag = np.sqrt(epsilon_Ag)
  95. # n1 = 1.53413
  96. # n2 = 0.565838 + 7.23262j
  97. nm = 1.0
  98. x = np.ones((2), dtype = np.float64)
  99. x[0] = 2.0*np.pi*core_r/WL/4.0*3.0
  100. x[1] = 2.0*np.pi*core_r/WL
  101. m = np.ones((2), dtype = np.complex128)
  102. m[0] = index_Ag/nm
  103. m[1] = index_Ag/nm
  104. print "x =", x
  105. print "m =", m
  106. <<<<<<< HEAD
  107. npts = 281
  108. factor=3
  109. scan = np.linspace(-factor*x[0, 0], factor*x[0, 0], npts)
  110. coordX, coordZ = np.meshgrid(scan, scan)
  111. coordX.resize(npts*npts)
  112. coordZ.resize(npts*npts)
  113. coordY = np.zeros(npts*npts, dtype = np.float64)
  114. coord = np.vstack((coordX, coordY, coordZ)).transpose()
  115. #coord = np.vstack((coordY, coordX, coordZ)).transpose()
  116. terms, Qext, Qsca, Qabs, Qbk, Qpr, g, Albedo, S1, S2 = scattnlay(x, m)
  117. terms, E, H = fieldnlay(x, m, coord)
  118. P = np.array(map(lambda n: np.linalg.norm(np.cross(E[0][n], H[0][n].conjugate())).real, range(0, len(E[0]))))
  119. Ec = E[0, :, :]
  120. Hc = H[0, :, :]
  121. try:
  122. import matplotlib.pyplot as plt
  123. from matplotlib import cm
  124. from matplotlib.colors import LogNorm
  125. # min_tick = 0.0
  126. # max_tick = 1.0
  127. Eabs_data = np.resize(P, (npts, npts)).T
  128. #Eabs_data = np.resize(Eabs, (npts, npts)).T
  129. #Eabs_data = np.resize(Eangle, (npts, npts)).T
  130. #Eabs_data = np.resize(Habs, (npts, npts)).T
  131. #Eabs_data = np.resize(Hangle, (npts, npts)).T
  132. fig, ax = plt.subplots(1, 1)#, sharey=True, sharex=True)
  133. #idxs = np.where(np.abs(coordX) < 1e-10)
  134. #print H[0, idxs][0, :, 1]
  135. #axs[0].errorbar(coordZ[idxs]*WL/2.0/np.pi/nm, P[idxs], fmt = 'r', label = 'Poynting vector')
  136. #axs[0].errorbar(coordZ[idxs]*WL/2.0/np.pi/nm, np.linalg.norm(E[0, idxs][0], axis = 1), fmt = 'g', label = 'E')
  137. # axs[0].errorbar(coordZ[idxs]*WL/2.0/np.pi/nm, np.linalg.norm(H[0, idxs][0], axis = 1), fmt = 'b', label = 'H')
  138. # axs[0].errorbar(coordZ[idxs]*WL/2.0/np.pi/nm, H[0, idxs][0, :, 1].real, fmt = 'k', label = 'H.r')
  139. # axs[0].errorbar(coordZ[idxs]*WL/2.0/np.pi/nm, H[0, idxs][0, :, 1].imag, fmt = 'b', label = 'H.i')
  140. #axs[0].errorbar(coordZ[idxs]*WL/2.0/np.pi/nm, H[0, idxs][0, :, 0].real, fmt = 'b', label = 'Px')
  141. #axs[0].errorbar(coordZ[idxs]*WL/2.0/np.pi/nm, H[0, idxs][0, :, 1].real, fmt = 'k', label = 'Py')
  142. #axs[0].errorbar(coordZ[idxs]*WL/2.0/np.pi/nm, H[0, idxs][0, :, 2].real, fmt = 'b', label = 'Pz')
  143. #axs[0].legend()
  144. #fig.tight_layout()
  145. # Rescale to better show the axes
  146. scale_x = np.linspace(min(coordX)*WL/2.0/np.pi/nm, max(coordX)*WL/2.0/np.pi/nm, npts)
  147. scale_z = np.linspace(min(coordZ)*WL/2.0/np.pi/nm, max(coordZ)*WL/2.0/np.pi/nm, npts)
  148. # Define scale ticks
  149. min_tick = np.amin(Eabs_data)
  150. max_tick = np.amax(Eabs_data)
  151. # scale_ticks = np.power(10.0, np.linspace(np.log10(min_tick), np.log10(max_tick), 6))
  152. scale_ticks = np.linspace(min_tick, max_tick, 11)
  153. # Interpolation can be 'nearest', 'bilinear' or 'bicubic'
  154. ax.set_title(r'$Re(E \times H^*)$')
  155. cax = ax.imshow(Eabs_data, interpolation = 'nearest', cmap = cm.jet,
  156. origin = 'lower'
  157. #, vmin = min_tick, vmax = max_tick
  158. , extent = (min(scale_x), max(scale_x), min(scale_z), max(scale_z))
  159. #,norm = LogNorm()
  160. )
  161. ax.axis("image")
  162. # # Add colorbar
  163. cbar = fig.colorbar(cax, ticks = [a for a in scale_ticks])
  164. cbar.ax.set_yticklabels(['%5.3g' % (a) for a in scale_ticks]) # vertically oriented colorbar
  165. # pos = list(cbar.ax.get_position().bounds)
  166. # fig.text(pos[0] - 0.02, 0.925, '|E|/|E$_0$|', fontsize = 14)
  167. plt.xlabel('Z, nm')
  168. plt.ylabel('X, nm')
  169. # This part draws the nanoshell
  170. from matplotlib import patches
  171. s1 = patches.Arc((0, 0), 2.0*core_r, 2.0*core_r, angle=0.0, zorder=2,
  172. theta1=0.0, theta2=360.0, linewidth=1, color='black')
  173. ax.add_patch(s1)
  174. from matplotlib.path import Path
  175. #import matplotlib.patches as patches
  176. flow_total = 39
  177. for flow in range(0,flow_total):
  178. flow_x, flow_z = GetFlow(scale_x, scale_z, Ec, Hc,
  179. min(scale_x)+flow*(scale_x[-1]-scale_x[0])/(flow_total-1),
  180. min(scale_z),
  181. #0.0,
  182. npts*16)
  183. verts = np.vstack((flow_z, flow_x)).transpose().tolist()
  184. #codes = [Path.CURVE4]*len(verts)
  185. codes = [Path.LINETO]*len(verts)
  186. codes[0] = Path.MOVETO
  187. path = Path(verts, codes)
  188. patch = patches.PathPatch(path, facecolor='none', lw=1, edgecolor='white')
  189. ax.add_patch(patch)
  190. # # Start powerflow lines in the middle of the image
  191. # flow_total = 131
  192. # for flow in range(0,flow_total):
  193. # flow_x, flow_z = GetFlow(scale_x, scale_z, Ec, Hc,
  194. # min(scale_x)+flow*(scale_x[-1]-scale_x[0])/(flow_total-1),
  195. # 15.0, #min(scale_z),
  196. # npts*6)
  197. # verts = np.vstack((flow_z, flow_x)).transpose().tolist()
  198. # #codes = [Path.CURVE4]*len(verts)
  199. # codes = [Path.LINETO]*len(verts)
  200. # codes[0] = Path.MOVETO
  201. # path = Path(verts, codes)
  202. # patch = patches.PathPatch(path, facecolor='none', lw=1, edgecolor='white')
  203. # ax.add_patch(patch)
  204. plt.savefig("Ag-flow.png")
  205. plt.draw()
  206. plt.show()
  207. plt.clf()
  208. plt.close()
  209. finally:
  210. print("Qabs = "+str(Qabs));
  211. #
  212. =======
  213. comment='bulk-Ag-flow'
  214. WL_units='nm'
  215. npts = 501
  216. factor=2.1
  217. flow_total = 39
  218. #flow_total = 21
  219. #flow_total = 0
  220. crossplane='XZ'
  221. #crossplane='YZ'
  222. #crossplane='XY'
  223. # Options to plot: Eabs, Habs, Pabs, angleEx, angleHy
  224. field_to_plot='Pabs'
  225. #field_to_plot='angleEx'
  226. fieldplot(x,m, WL, comment, WL_units, crossplane, field_to_plot, npts, factor, flow_total, is_flow_extend=False)
  227. >>>>>>> feb3ad9a4b3aa424f2e1087b4bc7b9bc52598810