patch_size.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import numpy as np
  2. from scipy.optimize import bisect
  3. import expansion
  4. from matplotlib import pyplot as plt
  5. import parameters
  6. import potentials
  7. from pathlib import Path
  8. Expansion = expansion.Expansion
  9. Array = np.ndarray
  10. ModelParams = parameters.ModelParams
  11. @expansion.map_over_expansion
  12. def charge_patch_size(ex: Expansion, phi: float = 0, theta0: Array | float = 0, theta1: Array | float = np.pi / 2):
  13. return bisect(lambda theta: ex.charge_value(theta, phi), theta0, theta1)
  14. def potential_patch_size(ex: Expansion, params: ModelParams,
  15. phi: float = 0, theta0: Array | float = 0, theta1: Array | float = np.pi / 2,
  16. match_expansion_axis_to_params: int = None):
  17. # this is more complicate to map over leading axes of the expansion as potential also depends on model parameters,
  18. # with some, such as kappaR, also being the parameters of the expansion in the first place. When mapping,
  19. # we must therefore provide the expansion axis that should match the collection of parameters in params.
  20. meap = match_expansion_axis_to_params # just a shorter variable name
  21. @expansion.map_over_expansion
  22. def potential_zero(exp: Expansion, prms: ModelParams):
  23. return bisect(lambda theta: potentials.charged_shell_potential(theta, phi, 1, exp, prms), theta0, theta1)
  24. params_list = params.unravel()
  25. if meap is not None:
  26. expansion_list = [Expansion(ex.l_array, np.take(ex.coefs, i, axis=meap)) for i in range(ex.shape[meap])]
  27. else:
  28. expansion_list = [ex for _ in params_list]
  29. if not len(expansion_list) == len(params_list):
  30. raise ValueError(f'Axis of expansion that is supposed to match params does not have the same length, got '
  31. f'len(params.unravel()) = {len(params_list)} and '
  32. f'expansion.shape[{meap}] = {len(expansion_list)}')
  33. results = []
  34. for exp, prms in zip(expansion_list, params_list):
  35. results.append(potential_zero(exp, prms))
  36. if meap is not None:
  37. return np.array(results).swapaxes(0, meap) # return the params-matched axis to where it belongs
  38. return np.squeeze(np.array(results))
  39. if __name__ == '__main__':
  40. a_bar = np.linspace(0.2, 0.8, 100)
  41. kappaR = np.array([0.26, 1, 3, 10, 26])
  42. params = ModelParams(R=150, kappaR=kappaR)
  43. ex = expansion.MappedExpansionQuad(a_bar=a_bar[:, None], sigma_m=0.001, l_max=30, kappaR=kappaR[None, :])
  44. # patch_size = charge_patch_size(ex)
  45. patch_size = potential_patch_size(ex, params, match_expansion_axis_to_params=1)
  46. fig, ax = plt.subplots()
  47. for patch, kR in zip(patch_size.T, kappaR):
  48. ax.plot(a_bar, patch * 180 / np.pi, label=rf'$\kappa$ = {kR}')
  49. ax.tick_params(which='both', direction='in', top=True, right=True, labelsize=12)
  50. ax.set_xlabel(r'$\bar a$', fontsize=13)
  51. ax.set_ylabel(r'$\theta$', fontsize=13)
  52. plt.legend(fontsize=12)
  53. plt.savefig(Path("/home/andraz/ChargedShells/Figures/patch_size_potential.png"), dpi=600)
  54. plt.show()