sEE_minimum.py 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. from charged_shells import expansion, interactions, mapping, charge_distributions
  4. from charged_shells.parameters import ModelParams
  5. from functools import partial
  6. from config import *
  7. from matplotlib import cm
  8. from mpl_toolkits.axes_grid1 import make_axes_locatable
  9. from labellines import labelLine, labelLines
  10. from matplotlib.colors import TwoSlopeNorm
  11. from matplotlib.ticker import FuncFormatter
  12. Expansion = expansion.Expansion
  13. def sEE_minimum(ex: Expansion, params: ModelParams, accuracy=1e-2, dist=2., match_expansion_axis_to_params=None,
  14. angle_start: float = 0, angle_stop: float = np.pi / 2):
  15. ex2 = ex.clone()
  16. angle_range = np.linspace(angle_start, angle_stop, int((angle_stop - angle_start) / accuracy), endpoint=True)
  17. # angle_range = np.linspace(0.1, 0.7, int(1 / accuracy), endpoint=True)
  18. ex.rotate_euler(alpha=0, beta=angle_range, gamma=0)
  19. ex2.rotate_euler(alpha=0, beta=angle_range, gamma=0)
  20. if match_expansion_axis_to_params is not None:
  21. match_expansion_axis_to_params += 1
  22. energy_fn = mapping.parameter_map_two_expansions(partial(interactions.charged_shell_energy, dist=dist),
  23. match_expansion_axis_to_params)
  24. energy = energy_fn(ex, ex2, params)
  25. min_idx = np.argmin(energy, axis=0)
  26. min_energy = np.min(energy, axis=0)
  27. return min_energy, angle_range[min_idx]
  28. def contours():
  29. kappaR = np.linspace(1, 10, 20)
  30. a_bar = np.linspace(0.2, 0.6, 20)
  31. params = ModelParams(R=150, kappaR=kappaR)
  32. ex = charge_distributions.create_mapped_quad_expansion(a_bar[:, None], kappaR[None, :], 0.001)
  33. min_energy, min_angle = sEE_minimum(ex, params, match_expansion_axis_to_params=1, accuracy=0.01)
  34. kR_mesh, a_mesh = np.meshgrid(kappaR, a_bar)
  35. print(np.min(min_angle), np.max(min_angle))
  36. print(np.min(min_energy), np.max(min_energy))
  37. plt.contourf(kR_mesh, a_mesh, min_angle)
  38. # plt.imshow(min_angle)
  39. plt.show()
  40. plt.contourf(kR_mesh, a_mesh, min_energy, np.array([-9, -5, -2.5, -1, -0.5, -0.2, 0]))
  41. # plt.imshow(min_energy)
  42. plt.show()
  43. def kappaR_dependence(kappaR, save_as=None, cmap=cm.jet):
  44. a_bar = np.linspace(0.12, 0.8, 15)
  45. params = ModelParams(R=150, kappaR=kappaR)
  46. ex = charge_distributions.create_mapped_quad_expansion(a_bar[None, :], kappaR[:, None], 0.001)
  47. min_energy, min_angle = sEE_minimum(ex, params, match_expansion_axis_to_params=0, accuracy=0.001,
  48. angle_start=0.5, angle_stop=1.)
  49. kappaR_alt = np.array([0.01, 2, 5, 10, 50])
  50. params_alt = ModelParams(R=150, kappaR=kappaR_alt)
  51. a_bar_alt = np.linspace(np.min(a_bar) - 0.05, np.max(a_bar) + 0.05, 20)
  52. ex2 = charge_distributions.create_mapped_quad_expansion(a_bar_alt[:, None], kappaR_alt[None, :], 0.001)
  53. min_energy_alt, min_angle_alt = sEE_minimum(ex2, params_alt, match_expansion_axis_to_params=1, accuracy=0.001,
  54. angle_start=0.5, angle_stop=1.)
  55. colors = cmap(np.linspace(0, 1, len(a_bar)))
  56. sm = cm.ScalarMappable(cmap=cmap, norm=plt.Normalize(vmin=np.min(a_bar), vmax=np.max(a_bar)))
  57. sm.set_array([])
  58. # Transformation to the position along our quadrupolar rotational path
  59. min_angle = np.pi - min_angle
  60. min_angle_alt = np.pi - min_angle_alt
  61. kappaR_labels = [rf'$\kappa R={kR:.1f}$' for kR in kappaR_alt]
  62. fig, ax = plt.subplots(figsize=plt.figaspect(0.5))
  63. for me, ma, lbl in zip(min_energy_alt.T, min_angle_alt.T, kappaR_labels):
  64. ax.plot(ma, me, ls=':', c='k', label=lbl)
  65. labelLines(ax.get_lines(), align=False, fontsize=15, xvals=(2.35, 2.65))
  66. for me, ma, lbl, c in zip(min_energy.T, min_angle.T, [rf'$\bar a={a:.2f}$' for a in a_bar], colors):
  67. ax.plot(ma, me, label=lbl, c=c)
  68. # ax.plot(min_angle, min_energy)
  69. # ax.legend(fontsize=17)
  70. ax.tick_params(which='both', direction='in', top=True, right=True, labelsize=15)
  71. ax.set_xlabel('pry angle', fontsize=20)
  72. ax.set_ylabel('U', fontsize=20)
  73. ax.set_xlim(2.2, 2.65)
  74. ax.set_ylim(-31, 1)
  75. divider = make_axes_locatable(ax)
  76. cax = divider.append_axes('right', size='5%', pad=0.05)
  77. cax.tick_params(labelsize=15)
  78. cbar = fig.colorbar(sm, cax=cax, orientation='vertical')
  79. cbar.set_label(r'$\bar a$', rotation=0, labelpad=15, fontsize=20)
  80. plt.tight_layout()
  81. if save_as is not None:
  82. plt.savefig(save_as, dpi=600)
  83. plt.show()
  84. def IC_kappaR_dependence(which_kappa_lines: list,
  85. save_as=None, cmap=cm.jet, file_suffix=""):
  86. em_data_path = ICI_DATA_PATH.joinpath("FIG_SUPP_sEE")
  87. em_data = np.load(em_data_path.joinpath(f"fig9{file_suffix}.npz"))['arr_0']
  88. # print(em_data.shape)
  89. a_bar, indices, counts = np.unique(em_data[:, 0], return_counts=True, return_inverse=True)
  90. print(a_bar)
  91. if not np.all(counts == counts[0]):
  92. raise ValueError("Data not reshapable.")
  93. colors = cmap(np.linspace(0, 1, len(a_bar)))
  94. sm = cm.ScalarMappable(cmap=cmap, norm=plt.Normalize(vmin=np.min(a_bar), vmax=np.max(a_bar)))
  95. sm.set_array([])
  96. min_energy = em_data[:, 3].reshape(-1, counts[0])
  97. min_angle = em_data[:, 2].reshape(-1, counts[0])
  98. kappa_line_energy = []
  99. kappa_line_angle = []
  100. kappaR_labels = []
  101. for kappa in which_kappa_lines:
  102. ind = em_data[:, 1] == kappa
  103. if np.sum(ind) == 0:
  104. print(f'No lines with kR={kappa} in data. Available values: {np.unique(em_data[:, 1])}')
  105. continue
  106. kappa_line_energy.append(em_data[:, 3][ind])
  107. kappa_line_angle.append(em_data[:, 2][ind])
  108. kappaR_labels.append(rf'$\kappa R={kappa:.1f}$')
  109. fig, ax = plt.subplots(figsize=plt.figaspect(0.5))
  110. for me, ma, lbl in zip(kappa_line_energy, kappa_line_angle, kappaR_labels):
  111. sort = np.argsort(ma)
  112. ax.plot(ma[sort], me[sort], ls=':', c='k', label=lbl)
  113. labelLines(ax.get_lines(), align=False, fontsize=15, xvals=(2.4, 2.65))
  114. for me, ma, lbl, c in zip(min_energy, min_angle, [rf'$\bar a={a:.2f}$' for a in a_bar], colors):
  115. ax.plot(ma, me, label=lbl, c=c)
  116. # ax.plot(min_angle, min_energy)
  117. # ax.legend(fontsize=17)
  118. ax.tick_params(which='both', direction='in', top=True, right=True, labelsize=15)
  119. ax.set_xlabel('pry angle', fontsize=20)
  120. ax.set_ylabel('U', fontsize=20)
  121. ax.set_xlim(2.2, 2.65)
  122. ax.set_ylim(-41, 1)
  123. divider = make_axes_locatable(ax)
  124. cax = divider.append_axes('right', size='5%', pad=0.05)
  125. cax.tick_params(labelsize=15)
  126. cbar = fig.colorbar(sm, cax=cax, orientation='vertical')
  127. cbar.set_label(r'$\bar a$', rotation=0, labelpad=15, fontsize=20)
  128. plt.tight_layout()
  129. if save_as is not None:
  130. plt.savefig(save_as, dpi=600)
  131. plt.show()
  132. # def charge_dependence(charge, save_as=None):
  133. #
  134. # a_bar = np.array([0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8])
  135. # params = ModelParams(R=150, kappaR=kappaR)
  136. #
  137. # ex = expansion.MappedExpansionQuad(a_bar[None, :], kappaR[:, None], 0.001)
  138. # min_energy, min_angle = sEE_minimum(ex, params, match_expansion_axis_to_params=0, accuracy=0.001,
  139. # angle_start=0.5, angle_stop=1.)
  140. #
  141. # kappaR_alt = np.array([0.01, 2, 5, 10, 50])
  142. # params_alt = ModelParams(R=150, kappaR=kappaR_alt)
  143. # a_bar_alt = np.linspace(np.min(a_bar) - 0.05, np.max(a_bar) + 0.05, 20)
  144. # ex2 = expansion.MappedExpansionQuad(a_bar_alt[:, None], kappaR_alt[None, :], 0.001)
  145. # min_energy_alt, min_angle_alt = sEE_minimum(ex2, params_alt, match_expansion_axis_to_params=1, accuracy=0.001,
  146. # angle_start=0.5, angle_stop=1.)
  147. #
  148. # fig, ax = plt.subplots(figsize=plt.figaspect(0.5))
  149. # for me, ma, lbl in zip(min_energy_alt.T, min_angle_alt.T, [rf'$\bar a={a:.2f}$' for a in a_bar]):
  150. # ax.plot(ma, me, ls=':', c='k')
  151. # for me, ma, lbl in zip(min_energy.T, min_angle.T, [rf'$\bar a={a:.2f}$' for a in a_bar]):
  152. # ax.plot(ma, me, label=lbl)
  153. # # ax.plot(min_angle, min_energy)
  154. # ax.legend(fontsize=17)
  155. # ax.tick_params(which='both', direction='in', top=True, right=True, labelsize=12)
  156. # ax.set_xlabel('angle', fontsize=15)
  157. # ax.set_ylabel('U', fontsize=20)
  158. # ax.set_xlim(0.56, 0.93)
  159. # ax.set_ylim(-20, 1)
  160. # plt.tight_layout()
  161. # if save_as is not None:
  162. # plt.savefig(save_as, dpi=600)
  163. # plt.show()
  164. def main():
  165. # contours()
  166. # kappaR_dependence(kappaR=np.linspace(0.1, 30, 20),
  167. # save_as=Path(config_data["figures"]).joinpath('sEE_min_kappaR_abar.png')
  168. # )
  169. IC_kappaR_dependence(which_kappa_lines=[0.01, 3., 5., 10., 50.], file_suffix="_1",
  170. # save_as=FIGURES_PATH.joinpath("ICi_data").joinpath('IC_sEE_min_kappaR_abar.png')
  171. )
  172. if __name__ == '__main__':
  173. main()