patch_shape_comparison.py 12 KB

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