patch_shape_comparison.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. from charged_shells import expansion, potentials, patch_size
  2. import numpy as np
  3. from charged_shells.parameters import ModelParams
  4. from pathlib import Path
  5. from matplotlib.lines import Line2D
  6. import json
  7. import quadrupole_model_mappings
  8. from plot_settings import *
  9. def ic_cs_comparison():
  10. kappaR = 15
  11. params = ModelParams(R=150, kappaR=kappaR)
  12. sigma_m = 0.001
  13. sigma0 = 0.0001
  14. a_bar = 0.3
  15. theta = np.linspace(0, np.pi, 1001)
  16. phi = 0.
  17. dist = 1
  18. ex_cp = expansion.MappedExpansionQuad(a_bar=a_bar, kappaR=params.kappaR, sigma_tilde=sigma_m, l_max=30,
  19. sigma0=sigma0)
  20. potential_cp = potentials.charged_shell_potential(theta, phi, dist, ex_cp, params)
  21. potential_ic = potentials.inverse_patchy_particle_potential(theta, dist, a_bar, -2 * sigma_m + sigma0,
  22. (sigma_m, sigma_m), params, 30)
  23. fig, ax = plt.subplots()
  24. ax.scatter(theta[::50], 1000 * potential_ic.T[::50], marker='o', label='ICi', facecolors='none',
  25. edgecolors='tab:red')
  26. ax.plot(theta, 1000 * potential_cp.T, label='CSp - mapped', linewidth=2)
  27. # ax.plot(1000 * potential_ic.T - 1000 * potential_cp.T)
  28. ax.tick_params(which='both', direction='in', top=True, right=True, labelsize=12)
  29. ax.set_xlabel(r'$\theta$', fontsize=15)
  30. ax.set_ylabel(r'$\phi$ [mV]', fontsize=15)
  31. custom_ticks = [0, np.pi / 4, np.pi / 2, 3 * np.pi / 4, np.pi]
  32. custom_labels = ['0', r'$\pi/4$', r'$\pi/2$', r'$3\pi/4$', r'$\pi$']
  33. plt.axhline(y=0, color='black', linestyle=':')
  34. plt.xticks(custom_ticks, custom_labels, fontsize=13)
  35. plt.legend(fontsize=12)
  36. plt.tight_layout()
  37. # plt.savefig(Path("/home/andraz/ChargedShells/Figures/potential_shape_comparison_overcharged05.pdf"), dpi=300)
  38. plt.show()
  39. def models_comparison(save_data=False):
  40. target_patch_size = 0.92
  41. kappaR = 3
  42. params = ModelParams(R=150, kappaR=kappaR)
  43. sigma_m = 0.001
  44. sigma0 = 0 # taking this total charge parameter nonzero causes cap model to fail in finding the appropriate theta0
  45. def fn(x):
  46. return expansion.MappedExpansionQuad(a_bar=x, kappaR=params.kappaR, sigma_tilde=sigma_m, l_max=30, sigma0=sigma0)
  47. a_bar = patch_size.inverse_potential_patch_size(target_patch_size, fn, 0.5, params)
  48. ex_point = expansion.MappedExpansionQuad(a_bar=a_bar, kappaR=params.kappaR, sigma_tilde=sigma_m, l_max=30, sigma0=sigma0)
  49. ex_gauss = quadrupole_model_mappings.ic_to_gauss(sigma_m, a_bar, params, l_max=30, sigma0=sigma0)
  50. ex_cap = quadrupole_model_mappings.ic_to_cap(sigma_m, a_bar, params, l_max=50, sigma0=sigma0)
  51. theta = np.linspace(0, np.pi, 1001)
  52. phi = 0.
  53. dist = 1
  54. potential_ic = potentials.inverse_patchy_particle_potential(theta, dist, a_bar, -2 * sigma_m + sigma0,
  55. (sigma_m, sigma_m), params, 30)
  56. potential1 = potentials.charged_shell_potential(theta, phi, dist, ex_point, params)
  57. potential2 = potentials.charged_shell_potential(theta, phi, dist, ex_gauss, params)
  58. potential3 = potentials.charged_shell_potential(theta, phi, dist, ex_cap, params)
  59. # print(potential.shape)
  60. # print(potential)
  61. if save_data:
  62. with open(Path("/home/andraz/ChargedShells/charged-shells/config.json")) as config_file:
  63. config_data = json.load(config_file)
  64. np.savez(Path(config_data["figure_data"]).joinpath("fig_6_shape_models.npz"),
  65. ICi=np.stack((theta, potential_ic)).T,
  66. CSp_mapped=np.stack((theta, potential1)).T,
  67. CSp_gauss=np.stack((theta, potential2)).T,
  68. CSp_caps=np.stack((theta, potential3)).T)
  69. # expansion.plot_theta_profile_multiple([ex_point, ex_gauss, ex_cap], ['IC', 'Gauss', 'cap'], num=1000)
  70. fig, ax = plt.subplots()
  71. ax.scatter(theta[::50], 1000 * potential_ic.T[::50], marker='o', label='ICi', facecolors='none',
  72. edgecolors='tab:red')
  73. ax.plot(theta, 1000 * potential1.T, label='CSp - mapped', linewidth=2)
  74. # ax.plot(theta, potential_ic.T, label='IC', ls=':', linewidth=2, marker='o', markevery=50, mfc='none')
  75. ax.plot(theta, 1000 * potential2.T, label='CSp - Gauss', linewidth=2, ls='--')
  76. ax.plot(theta, 1000 * potential3.T, label='CSp - caps', linewidth=2, ls='--')
  77. ax.tick_params(which='both', direction='in', top=True, right=True, labelsize=12)
  78. ax.set_xlabel(r'$\theta$', fontsize=15)
  79. ax.set_ylabel(r'$\phi$ [mV]', fontsize=15)
  80. custom_ticks = [0, np.pi / 4, np.pi / 2, 3 * np.pi / 4, np.pi]
  81. custom_labels = ['0', r'$\pi/4$', r'$\pi/2$', r'$3\pi/4$', r'$\pi$']
  82. plt.axhline(y=0, color='black', linestyle=':')
  83. plt.axvline(x=target_patch_size, color='black', linestyle=':')
  84. plt.xticks(custom_ticks, custom_labels, fontsize=13)
  85. plt.legend(fontsize=12)
  86. plt.tight_layout()
  87. plt.savefig(Path("/home/andraz/ChargedShells/Figures/potential_shape_comparison.pdf"), dpi=300)
  88. plt.show()
  89. def abar_comparison():
  90. target_patch_sizes = [0.8, 0.85, 0.92]
  91. params = ModelParams(R=150, kappaR=3)
  92. sigma_m = 0.001
  93. theta = np.linspace(0, np.pi, 1001)
  94. phi = 0.
  95. dist = 1
  96. def fn1(x):
  97. return expansion.MappedExpansionQuad(a_bar=x, kappaR=params.kappaR, sigma_tilde=sigma_m, l_max=30)
  98. pots = []
  99. for ps in target_patch_sizes:
  100. a_bar = patch_size.inverse_potential_patch_size(ps, fn1, 0.5, params)
  101. ex_point = expansion.MappedExpansionQuad(a_bar=a_bar, kappaR=params.kappaR, sigma_tilde=sigma_m, l_max=30)
  102. pots.append(potentials.charged_shell_potential(theta, phi, dist, ex_point, params))
  103. fig, ax = plt.subplots(figsize=(4.125, 3))
  104. for pot, ps in zip(pots, target_patch_sizes):
  105. ax.plot(theta, 1000 * pot, label=fr'$\theta_0={180 / np.pi * ps:.1f}^o$', linewidth=2)
  106. ax.tick_params(which='both', direction='in', top=True, right=True, labelsize=12)
  107. ax.set_xlabel(r'$\theta$', fontsize=15)
  108. ax.set_ylabel(r'$\phi$ [mV]', fontsize=15)
  109. custom_ticks = [0, np.pi / 4, np.pi / 2, 3 * np.pi / 4, np.pi]
  110. custom_labels = ['0', r'$\pi/4$', r'$\pi/2$', r'$3\pi/4$', r'$\pi$']
  111. plt.axhline(y=0, color='black', linestyle=':')
  112. plt.xticks(custom_ticks, custom_labels, fontsize=15)
  113. plt.legend(fontsize=12)
  114. plt.tight_layout()
  115. # plt.savefig(Path("/home/andraz/ChargedShells/Figures/potential_amplitude_comparison.pdf"), dpi=300)
  116. plt.show()
  117. def charge_comparsion():
  118. charges = np.array([-0.001, 0, 0.001, 0.002])
  119. a_bar = 0.6
  120. params = ModelParams(R=150, kappaR=10)
  121. sigma_m = 0.001
  122. theta = np.linspace(0, np.pi, 1001)
  123. phi = 0.
  124. dist = 1
  125. ex_point = expansion.MappedExpansionQuad(a_bar=a_bar, kappaR=params.kappaR, sigma_tilde=sigma_m,
  126. l_max=30, sigma0=charges)
  127. pot = potentials.charged_shell_potential(theta, phi, dist, ex_point, params)
  128. fig, ax = plt.subplots(figsize=(4.125, 3))
  129. for p, lbl in zip(pot, [fr'$\sigma_0={c}$' for c in charges]):
  130. ax.plot(theta, 1000 * p, linewidth=2, label=lbl)
  131. ax.tick_params(which='both', direction='in', top=True, right=True, labelsize=12)
  132. ax.set_xlabel(r'$\theta$', fontsize=15)
  133. ax.set_ylabel(r'$\phi$ [mV]', fontsize=15)
  134. custom_ticks = [0, np.pi / 4, np.pi / 2, 3 * np.pi / 4, np.pi]
  135. custom_labels = ['0', r'$\pi/4$', r'$\pi/2$', r'$3\pi/4$', r'$\pi$']
  136. plt.axhline(y=0, color='black', linestyle=':')
  137. plt.xticks(custom_ticks, custom_labels, fontsize=15)
  138. plt.legend(fontsize=12)
  139. plt.tight_layout()
  140. # plt.savefig(Path("/home/andraz/ChargedShells/Figures/potential_charge_comparison.pdf"), dpi=300)
  141. plt.show()
  142. # TODO: comparison of patch shape at different kappaR and a neutral particle, with fixed patch size
  143. def ic_cs_comparison2(save_data=False):
  144. # target_patch_size = 0.92
  145. kappaR = 3
  146. params = ModelParams(R=150, kappaR=kappaR)
  147. sigma_m = 0.001
  148. sigma0_array = np.array([-0.0002, 0, 0.0002])
  149. theta = np.linspace(0, np.pi, 1201)
  150. phi = 0.
  151. dist = 1
  152. def fn1(x):
  153. return expansion.MappedExpansionQuad(a_bar=x, kappaR=params.kappaR, sigma_tilde=sigma_m, l_max=30, sigma0=0)
  154. # a_bar is determined only for a neutral particle (patch size only well-defined in this case)
  155. # a_bar = patch_size.inverse_potential_patch_size(target_patch_size, fn1, 0.5, params)
  156. # print(a_bar)
  157. a_bar = 0.5
  158. target_patch_size = patch_size.potential_patch_size(expansion.MappedExpansionQuad(a_bar=a_bar,
  159. kappaR=params.kappaR,
  160. sigma_tilde=sigma_m,
  161. l_max=30,
  162. sigma0=0),
  163. params)
  164. potential_ic = []
  165. potential_cs = []
  166. for sigma0 in sigma0_array:
  167. ex_point = expansion.MappedExpansionQuad(a_bar=a_bar, kappaR=params.kappaR,
  168. sigma_tilde=sigma_m, l_max=30, sigma0=sigma0)
  169. potential_ic.append(potentials.inverse_patchy_particle_potential(theta, dist, a_bar, -2 * sigma_m + sigma0,
  170. (sigma_m, sigma_m), params, 30))
  171. potential_cs.append(potentials.charged_shell_potential(theta, phi, dist, ex_point, params))
  172. if save_data:
  173. with open(Path("/home/andraz/ChargedShells/charged-shells/config.json")) as config_file:
  174. config_data = json.load(config_file)
  175. np.savez(Path(config_data["figure_data"]).joinpath("fig_6a.npz"),
  176. ICi_eta_neg=np.stack((theta, potential_ic[0])).T,
  177. ICi_eta_0=np.stack((theta, potential_ic[1])).T,
  178. ICi_eta_pos=np.stack((theta, potential_ic[2])).T,
  179. CSp_eta_neg=np.stack((theta, potential_cs[0])).T,
  180. CSp_eta_0=np.stack((theta, potential_cs[1])).T,
  181. CSp_eta_pos=np.stack((theta, potential_cs[2])).T)
  182. fig, ax = plt.subplots(figsize=(3, 2.5))
  183. lines = []
  184. # lines.append(plt.scatter([], [], marker='x', c='k', label='CSp'))
  185. # lines.append(plt.scatter([], [], marker='o', facecolor='none', edgecolor='k', label='ICi'))
  186. for p_ic, p_cs, charge in zip(potential_ic, potential_cs, sigma0_array):
  187. l, = ax.plot(theta, 1000 * p_cs.T, label=rf'$\eta = {charge/sigma_m}$', linewidth=2, zorder=0)
  188. l2, = ax.plot(theta, 1000 * p_cs.T, linewidth=2, zorder=0, c='k', ls='--', dashes=(5, 5))
  189. lines.append(l)
  190. # ax.scatter(theta[::100], 1000 * p_ic.T[::100], marker='o', facecolors='none', edgecolors='k', s=50)
  191. # ax.scatter(theta[::100], 1000 * p_cs.T[::100], marker='x', c='k', s=50)
  192. # ax.plot(theta, potential_ic.T, label='IC', ls=':', linewidth=2, marker='o', markevery=50, mfc='none')
  193. ax.tick_params(which='both', direction='in', top=True, right=True, labelsize=15)
  194. ax.set_xlabel(r'$\theta$', fontsize=15)
  195. ax.set_ylabel(r'$\phi [mV]$', fontsize=15)
  196. custom_ticks = [0, np.pi / 4, np.pi / 2, 3 * np.pi / 4, np.pi]
  197. custom_labels = ['$0$', r'$\pi/4$', r'$\pi/2$', r'$3\pi/4$', r'$\pi$']
  198. plt.axhline(y=0, color='black', linestyle=':')
  199. plt.axvline(x=target_patch_size, color='black', linestyle=':')
  200. plt.xticks(custom_ticks, custom_labels, fontsize=15)
  201. # lines.append(Line2D([0], [0], color='k', label='CSp'))
  202. # lines.append(plt.scatter([], [], marker='o', facecolor='none', edgecolor='red', label='ICi'))
  203. plt.legend(handles=lines, fontsize=14, handlelength=0.8, frameon=False,
  204. bbox_to_anchor=(0.57, 1.0), loc='upper center'
  205. )
  206. plt.tight_layout()
  207. plt.savefig(Path("/home/andraz/ChargedShells/Figures/final_figures/potential_ic_cs_comparison.png"), dpi=300)
  208. plt.show()
  209. def main():
  210. # models_comparison(save_data=False)
  211. # ic_cs_comparison()
  212. ic_cs_comparison2()
  213. # abar_comparison()
  214. # charge_comparsion()
  215. if __name__ == '__main__':
  216. main()