physicskit 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (484) hide show
  1. physicskit/__init__.py +51 -0
  2. physicskit/astro/__init__.py +66 -0
  3. physicskit/astro/cosmic_web.py +395 -0
  4. physicskit/astro/galactic_dynamics.py +137 -0
  5. physicskit/astro/nbody.py +208 -0
  6. physicskit/astro/orbital_mechanics.py +220 -0
  7. physicskit/astro/stellar_dynamo.py +628 -0
  8. physicskit/astro/stellar_structure.py +198 -0
  9. physicskit/astro/tests/__init__.py +0 -0
  10. physicskit/astro/tests/conftest.py +7 -0
  11. physicskit/astro/tests/test_cosmic_web.py +159 -0
  12. physicskit/astro/tests/test_galactic_dynamics.py +46 -0
  13. physicskit/astro/tests/test_nbody.py +81 -0
  14. physicskit/astro/tests/test_orbital_mechanics.py +73 -0
  15. physicskit/astro/tests/test_stellar_dynamo.py +198 -0
  16. physicskit/astro/tests/test_stellar_structure.py +52 -0
  17. physicskit/astro/tests/test_visualizers.py +159 -0
  18. physicskit/astro/visualizers.py +628 -0
  19. physicskit/chaos/__init__.py +55 -0
  20. physicskit/chaos/core/__init__.py +3 -0
  21. physicskit/chaos/core/base_system.py +342 -0
  22. physicskit/chaos/core/integrators.py +40 -0
  23. physicskit/chaos/exceptions.py +24 -0
  24. physicskit/chaos/quantum/__init__.py +38 -0
  25. physicskit/chaos/quantum/billiards.py +274 -0
  26. physicskit/chaos/quantum/husimi.py +85 -0
  27. physicskit/chaos/quantum/maps.py +366 -0
  28. physicskit/chaos/systems/__init__.py +38 -0
  29. physicskit/chaos/systems/billiards.py +1131 -0
  30. physicskit/chaos/systems/continuous.py +1276 -0
  31. physicskit/chaos/systems/maps.py +557 -0
  32. physicskit/chaos/tests/__init__.py +0 -0
  33. physicskit/chaos/tests/test_basins.py +76 -0
  34. physicskit/chaos/tests/test_bifurcation.py +132 -0
  35. physicskit/chaos/tests/test_billiards.py +115 -0
  36. physicskit/chaos/tests/test_continuous.py +224 -0
  37. physicskit/chaos/tests/test_dimension.py +69 -0
  38. physicskit/chaos/tests/test_divergence.py +90 -0
  39. physicskit/chaos/tests/test_dynamic_plots.py +269 -0
  40. physicskit/chaos/tests/test_integrators.py +96 -0
  41. physicskit/chaos/tests/test_io.py +41 -0
  42. physicskit/chaos/tests/test_maps.py +110 -0
  43. physicskit/chaos/tests/test_metrics.py +115 -0
  44. physicskit/chaos/tests/test_phase_space.py +73 -0
  45. physicskit/chaos/tests/test_properties.py +116 -0
  46. physicskit/chaos/tests/test_quantum_billiards.py +94 -0
  47. physicskit/chaos/tests/test_quantum_maps.py +144 -0
  48. physicskit/chaos/tests/test_recurrence.py +51 -0
  49. physicskit/chaos/tests/test_repr_and_api_consistency.py +134 -0
  50. physicskit/chaos/tests/test_section.py +49 -0
  51. physicskit/chaos/tests/test_spectral.py +48 -0
  52. physicskit/chaos/tests/test_streamlit_app.py +45 -0
  53. physicskit/chaos/tests/test_timeseries.py +131 -0
  54. physicskit/chaos/tests/test_viewer3d.py +41 -0
  55. physicskit/chaos/utils/__init__.py +46 -0
  56. physicskit/chaos/utils/dimension.py +139 -0
  57. physicskit/chaos/utils/io.py +95 -0
  58. physicskit/chaos/utils/metrics.py +304 -0
  59. physicskit/chaos/utils/recurrence.py +122 -0
  60. physicskit/chaos/utils/spectral.py +69 -0
  61. physicskit/chaos/utils/timeseries.py +303 -0
  62. physicskit/chaos/visualizers/__init__.py +85 -0
  63. physicskit/chaos/visualizers/basins.py +185 -0
  64. physicskit/chaos/visualizers/bifurcation.py +273 -0
  65. physicskit/chaos/visualizers/divergence.py +374 -0
  66. physicskit/chaos/visualizers/dynamic_plots.py +1372 -0
  67. physicskit/chaos/visualizers/phase_space.py +133 -0
  68. physicskit/chaos/visualizers/quantum.py +299 -0
  69. physicskit/chaos/visualizers/recurrence.py +91 -0
  70. physicskit/chaos/visualizers/section.py +161 -0
  71. physicskit/chaos/visualizers/theme.py +31 -0
  72. physicskit/chaos/visualizers/viewer3d.py +82 -0
  73. physicskit/classical/__init__.py +55 -0
  74. physicskit/classical/core/__init__.py +17 -0
  75. physicskit/classical/core/base_system.py +510 -0
  76. physicskit/classical/core/integrators.py +397 -0
  77. physicskit/classical/systems/__init__.py +32 -0
  78. physicskit/classical/systems/chains.py +334 -0
  79. physicskit/classical/systems/hamiltonian.py +215 -0
  80. physicskit/classical/systems/lagrangian.py +308 -0
  81. physicskit/classical/systems/newtonian.py +536 -0
  82. physicskit/classical/systems/rotations.py +614 -0
  83. physicskit/classical/tests/__init__.py +0 -0
  84. physicskit/classical/tests/conftest.py +7 -0
  85. physicskit/classical/tests/test_base_system.py +113 -0
  86. physicskit/classical/tests/test_chains.py +84 -0
  87. physicskit/classical/tests/test_conservation.py +244 -0
  88. physicskit/classical/tests/test_conservation_utils.py +47 -0
  89. physicskit/classical/tests/test_hamiltonian.py +44 -0
  90. physicskit/classical/tests/test_integrators.py +123 -0
  91. physicskit/classical/tests/test_lagrangian.py +69 -0
  92. physicskit/classical/tests/test_newtonian.py +45 -0
  93. physicskit/classical/tests/test_rotations.py +160 -0
  94. physicskit/classical/tests/test_stepsize.py +149 -0
  95. physicskit/classical/tests/test_symbolic.py +125 -0
  96. physicskit/classical/tests/test_visualizers.py +172 -0
  97. physicskit/classical/utils/__init__.py +20 -0
  98. physicskit/classical/utils/conservation.py +126 -0
  99. physicskit/classical/utils/stepsize.py +187 -0
  100. physicskit/classical/utils/symbolic.py +235 -0
  101. physicskit/classical/visualizers/__init__.py +25 -0
  102. physicskit/classical/visualizers/animations.py +508 -0
  103. physicskit/classical/visualizers/interactive.py +113 -0
  104. physicskit/classical/visualizers/modal_analysis.py +97 -0
  105. physicskit/classical/visualizers/phase_space.py +214 -0
  106. physicskit/condensed/__init__.py +122 -0
  107. physicskit/condensed/anderson_localization.py +155 -0
  108. physicskit/condensed/correlated.py +284 -0
  109. physicskit/condensed/ginzburg_landau.py +220 -0
  110. physicskit/condensed/landau_levels.py +246 -0
  111. physicskit/condensed/laughlin.py +229 -0
  112. physicskit/condensed/models.py +627 -0
  113. physicskit/condensed/tests/__init__.py +0 -0
  114. physicskit/condensed/tests/test_condensed.py +518 -0
  115. physicskit/condensed/tests/test_visualizers.py +87 -0
  116. physicskit/condensed/tight_binding.py +445 -0
  117. physicskit/condensed/topological_insulator_3d.py +178 -0
  118. physicskit/condensed/topology.py +217 -0
  119. physicskit/condensed/visualizers.py +296 -0
  120. physicskit/condensed/weyl.py +180 -0
  121. physicskit/constants.py +184 -0
  122. physicskit/fields/__init__.py +111 -0
  123. physicskit/fields/electrodynamics.py +671 -0
  124. physicskit/fields/quantum_fields.py +510 -0
  125. physicskit/fields/solitons.py +527 -0
  126. physicskit/fields/tests/__init__.py +0 -0
  127. physicskit/fields/tests/conftest.py +7 -0
  128. physicskit/fields/tests/test_field_animations.py +154 -0
  129. physicskit/fields/tests/test_fields.py +439 -0
  130. physicskit/fields/tests/test_visualizers.py +101 -0
  131. physicskit/fields/visualizers.py +503 -0
  132. physicskit/fluids/__init__.py +134 -0
  133. physicskit/fluids/core/__init__.py +23 -0
  134. physicskit/fluids/core/grid.py +165 -0
  135. physicskit/fluids/core/timestepping.py +231 -0
  136. physicskit/fluids/exceptions.py +26 -0
  137. physicskit/fluids/systems/__init__.py +70 -0
  138. physicskit/fluids/systems/compressible_flow.py +281 -0
  139. physicskit/fluids/systems/instabilities.py +343 -0
  140. physicskit/fluids/systems/navier_stokes.py +221 -0
  141. physicskit/fluids/systems/potential_flow.py +440 -0
  142. physicskit/fluids/systems/viscous_flow.py +425 -0
  143. physicskit/fluids/systems/vortex_dynamics.py +304 -0
  144. physicskit/fluids/tests/__init__.py +0 -0
  145. physicskit/fluids/tests/conftest.py +7 -0
  146. physicskit/fluids/tests/test_compressible_flow.py +66 -0
  147. physicskit/fluids/tests/test_instabilities.py +115 -0
  148. physicskit/fluids/tests/test_navier_stokes.py +67 -0
  149. physicskit/fluids/tests/test_potential_flow.py +92 -0
  150. physicskit/fluids/tests/test_static_visualizers.py +91 -0
  151. physicskit/fluids/tests/test_utils.py +100 -0
  152. physicskit/fluids/tests/test_viscous_flow.py +110 -0
  153. physicskit/fluids/tests/test_visualizers.py +34 -0
  154. physicskit/fluids/tests/test_vortex_dynamics.py +88 -0
  155. physicskit/fluids/utils/__init__.py +18 -0
  156. physicskit/fluids/utils/dimensionless.py +239 -0
  157. physicskit/fluids/utils/spectral_analysis.py +142 -0
  158. physicskit/fluids/visualizers/__init__.py +14 -0
  159. physicskit/fluids/visualizers/compressible.py +39 -0
  160. physicskit/fluids/visualizers/flow_fields.py +252 -0
  161. physicskit/fluids/visualizers/potential_flow.py +51 -0
  162. physicskit/fluids/visualizers/spectra.py +62 -0
  163. physicskit/fluids/visualizers/theme.py +38 -0
  164. physicskit/integrators/__init__.py +52 -0
  165. physicskit/integrators/adaptive.py +199 -0
  166. physicskit/integrators/fixed_step.py +360 -0
  167. physicskit/integrators/tests/__init__.py +0 -0
  168. physicskit/integrators/tests/test_integrators.py +101 -0
  169. physicskit/optics/__init__.py +124 -0
  170. physicskit/optics/_compat.py +5 -0
  171. physicskit/optics/gaussian.py +382 -0
  172. physicskit/optics/quantum_optics.py +428 -0
  173. physicskit/optics/ray.py +469 -0
  174. physicskit/optics/tests/__init__.py +0 -0
  175. physicskit/optics/tests/test_diffraction_animation.py +38 -0
  176. physicskit/optics/tests/test_gaussian.py +170 -0
  177. physicskit/optics/tests/test_quantum_optics.py +147 -0
  178. physicskit/optics/tests/test_ray.py +177 -0
  179. physicskit/optics/tests/test_visualizers.py +58 -0
  180. physicskit/optics/tests/test_wave.py +146 -0
  181. physicskit/optics/visualizers.py +264 -0
  182. physicskit/optics/wave.py +365 -0
  183. physicskit/particle/__init__.py +152 -0
  184. physicskit/particle/collider.py +382 -0
  185. physicskit/particle/confinement.py +125 -0
  186. physicskit/particle/decays.py +357 -0
  187. physicskit/particle/electroweak.py +300 -0
  188. physicskit/particle/kinematics.py +271 -0
  189. physicskit/particle/neutrinos.py +84 -0
  190. physicskit/particle/nuclear.py +100 -0
  191. physicskit/particle/scattering.py +159 -0
  192. physicskit/particle/tests/__init__.py +0 -0
  193. physicskit/particle/tests/conftest.py +7 -0
  194. physicskit/particle/tests/test_collider.py +119 -0
  195. physicskit/particle/tests/test_confinement.py +42 -0
  196. physicskit/particle/tests/test_decays.py +112 -0
  197. physicskit/particle/tests/test_electroweak.py +97 -0
  198. physicskit/particle/tests/test_kinematics.py +138 -0
  199. physicskit/particle/tests/test_neutrinos.py +36 -0
  200. physicskit/particle/tests/test_nuclear.py +45 -0
  201. physicskit/particle/tests/test_scattering.py +64 -0
  202. physicskit/particle/tests/test_visualizers.py +214 -0
  203. physicskit/particle/visualizers/__init__.py +38 -0
  204. physicskit/particle/visualizers/animations.py +705 -0
  205. physicskit/particle/visualizers/static.py +101 -0
  206. physicskit/plasma/__init__.py +176 -0
  207. physicskit/plasma/acceleration.py +152 -0
  208. physicskit/plasma/instabilities.py +417 -0
  209. physicskit/plasma/kinetic.py +588 -0
  210. physicskit/plasma/mhd.py +463 -0
  211. physicskit/plasma/single_particle.py +562 -0
  212. physicskit/plasma/tests/__init__.py +0 -0
  213. physicskit/plasma/tests/conftest.py +7 -0
  214. physicskit/plasma/tests/test_new_time_domain_features.py +222 -0
  215. physicskit/plasma/tests/test_plasma.py +232 -0
  216. physicskit/plasma/tests/test_visualizers.py +79 -0
  217. physicskit/plasma/turbulence.py +219 -0
  218. physicskit/plasma/visualizers.py +868 -0
  219. physicskit/plasma/waves.py +549 -0
  220. physicskit/quantum/__init__.py +180 -0
  221. physicskit/quantum/_compat.py +20 -0
  222. physicskit/quantum/chapters/__init__.py +0 -0
  223. physicskit/quantum/chapters/entanglement.py +489 -0
  224. physicskit/quantum/chapters/harmonic_spin.py +517 -0
  225. physicskit/quantum/chapters/hydrogen_am.py +292 -0
  226. physicskit/quantum/chapters/perturbation.py +350 -0
  227. physicskit/quantum/chapters/potentials.py +997 -0
  228. physicskit/quantum/chapters/spin.py +306 -0
  229. physicskit/quantum/chapters/wave_packets.py +541 -0
  230. physicskit/quantum/core/__init__.py +0 -0
  231. physicskit/quantum/core/eigensolvers.py +311 -0
  232. physicskit/quantum/core/operators.py +296 -0
  233. physicskit/quantum/core/solvers.py +271 -0
  234. physicskit/quantum/tests/__init__.py +0 -0
  235. physicskit/quantum/tests/conftest.py +7 -0
  236. physicskit/quantum/tests/test_animations.py +225 -0
  237. physicskit/quantum/tests/test_compat.py +43 -0
  238. physicskit/quantum/tests/test_eigensolvers.py +24 -0
  239. physicskit/quantum/tests/test_entanglement.py +127 -0
  240. physicskit/quantum/tests/test_harmonic_spin.py +140 -0
  241. physicskit/quantum/tests/test_hydrogen_am.py +48 -0
  242. physicskit/quantum/tests/test_measure.py +110 -0
  243. physicskit/quantum/tests/test_operators.py +105 -0
  244. physicskit/quantum/tests/test_perturbation.py +112 -0
  245. physicskit/quantum/tests/test_physics_checks.py +131 -0
  246. physicskit/quantum/tests/test_potentials.py +191 -0
  247. physicskit/quantum/tests/test_solvers.py +70 -0
  248. physicskit/quantum/tests/test_spin.py +22 -0
  249. physicskit/quantum/tests/test_unitarity.py +84 -0
  250. physicskit/quantum/tests/test_wave_packets.py +53 -0
  251. physicskit/quantum/utils/__init__.py +0 -0
  252. physicskit/quantum/utils/measure.py +253 -0
  253. physicskit/quantum/visualizers/__init__.py +0 -0
  254. physicskit/quantum/visualizers/bloch_sphere.py +205 -0
  255. physicskit/quantum/visualizers/entanglement.py +58 -0
  256. physicskit/quantum/visualizers/orbitals.py +187 -0
  257. physicskit/quantum/visualizers/phase_space.py +179 -0
  258. physicskit/quantum/visualizers/wavefunctions.py +230 -0
  259. physicskit/relativity/__init__.py +61 -0
  260. physicskit/relativity/chapters/__init__.py +33 -0
  261. physicskit/relativity/chapters/cosmology.py +190 -0
  262. physicskit/relativity/chapters/gw_merger.py +399 -0
  263. physicskit/relativity/chapters/kerr.py +371 -0
  264. physicskit/relativity/chapters/lensing.py +196 -0
  265. physicskit/relativity/chapters/neutron_star.py +149 -0
  266. physicskit/relativity/chapters/schwarzschild.py +412 -0
  267. physicskit/relativity/chapters/timekeeping.py +133 -0
  268. physicskit/relativity/core/__init__.py +12 -0
  269. physicskit/relativity/core/geodesics.py +216 -0
  270. physicskit/relativity/core/kerr_raytracer.py +259 -0
  271. physicskit/relativity/core/raytracer.py +241 -0
  272. physicskit/relativity/core/tensors.py +468 -0
  273. physicskit/relativity/tests/__init__.py +0 -0
  274. physicskit/relativity/tests/test_conservations.py +54 -0
  275. physicskit/relativity/tests/test_constants.py +34 -0
  276. physicskit/relativity/tests/test_cosmology.py +61 -0
  277. physicskit/relativity/tests/test_gw_merger.py +117 -0
  278. physicskit/relativity/tests/test_kerr.py +116 -0
  279. physicskit/relativity/tests/test_kerr_raytracer.py +103 -0
  280. physicskit/relativity/tests/test_lensing.py +75 -0
  281. physicskit/relativity/tests/test_neutron_star.py +48 -0
  282. physicskit/relativity/tests/test_raytracer.py +67 -0
  283. physicskit/relativity/tests/test_schwarzschild.py +126 -0
  284. physicskit/relativity/tests/test_shadow_render.py +81 -0
  285. physicskit/relativity/tests/test_tensors.py +86 -0
  286. physicskit/relativity/tests/test_timekeeping.py +51 -0
  287. physicskit/relativity/tests/test_visualizers_misc.py +115 -0
  288. physicskit/relativity/utils/__init__.py +1 -0
  289. physicskit/relativity/utils/constants.py +232 -0
  290. physicskit/relativity/visualizers/__init__.py +46 -0
  291. physicskit/relativity/visualizers/interactive.py +127 -0
  292. physicskit/relativity/visualizers/shadow_render.py +367 -0
  293. physicskit/relativity/visualizers/spacetime_3d.py +92 -0
  294. physicskit/relativity/visualizers/spacetime_diagrams.py +198 -0
  295. physicskit/relativity/visualizers/wave_plots.py +185 -0
  296. physicskit/rmt/__init__.py +8 -0
  297. physicskit/rmt/ensembles/__init__.py +108 -0
  298. physicskit/rmt/ensembles/banded.py +114 -0
  299. physicskit/rmt/ensembles/base.py +135 -0
  300. physicskit/rmt/ensembles/bdg.py +218 -0
  301. physicskit/rmt/ensembles/chiral.py +308 -0
  302. physicskit/rmt/ensembles/circular.py +104 -0
  303. physicskit/rmt/ensembles/crossover.py +82 -0
  304. physicskit/rmt/ensembles/density_matrix.py +148 -0
  305. physicskit/rmt/ensembles/effective_hamiltonian.py +230 -0
  306. physicskit/rmt/ensembles/embedded.py +207 -0
  307. physicskit/rmt/ensembles/gaussian.py +153 -0
  308. physicskit/rmt/ensembles/ginibre.py +110 -0
  309. physicskit/rmt/ensembles/girko.py +190 -0
  310. physicskit/rmt/ensembles/graph_laplacian.py +92 -0
  311. physicskit/rmt/ensembles/haar.py +57 -0
  312. physicskit/rmt/ensembles/jacobi.py +182 -0
  313. physicskit/rmt/ensembles/poisson.py +77 -0
  314. physicskit/rmt/ensembles/polynomial.py +139 -0
  315. physicskit/rmt/ensembles/pt_symmetric.py +120 -0
  316. physicskit/rmt/ensembles/single_ring.py +170 -0
  317. physicskit/rmt/ensembles/sparse.py +95 -0
  318. physicskit/rmt/ensembles/syk.py +170 -0
  319. physicskit/rmt/ensembles/truncated_unitary.py +80 -0
  320. physicskit/rmt/ensembles/universality.py +92 -0
  321. physicskit/rmt/ensembles/wishart.py +88 -0
  322. physicskit/rmt/py.typed +0 -0
  323. physicskit/rmt/spectrum.py +82 -0
  324. physicskit/rmt/stats/__init__.py +160 -0
  325. physicskit/rmt/stats/characteristic_polynomial.py +77 -0
  326. physicskit/rmt/stats/circular_law.py +54 -0
  327. physicskit/rmt/stats/correlations.py +162 -0
  328. physicskit/rmt/stats/density.py +70 -0
  329. physicskit/rmt/stats/entanglement.py +36 -0
  330. physicskit/rmt/stats/free_probability.py +202 -0
  331. physicskit/rmt/stats/localization.py +338 -0
  332. physicskit/rmt/stats/marchenko_pastur.py +55 -0
  333. physicskit/rmt/stats/pt_symmetric.py +265 -0
  334. physicskit/rmt/stats/ratios.py +110 -0
  335. physicskit/rmt/stats/real_ginibre.py +134 -0
  336. physicskit/rmt/stats/rigidity.py +272 -0
  337. physicskit/rmt/stats/single_ring.py +95 -0
  338. physicskit/rmt/stats/spacing.py +150 -0
  339. physicskit/rmt/stats/tracy_widom.py +175 -0
  340. physicskit/rmt/stats/truncated_unitary.py +40 -0
  341. physicskit/rmt/stats/unfolding.py +37 -0
  342. physicskit/rmt/stats/wachter.py +67 -0
  343. physicskit/rmt/tests/__init__.py +0 -0
  344. physicskit/rmt/tests/cache_utils.py +107 -0
  345. physicskit/rmt/tests/conftest.py +8 -0
  346. physicskit/rmt/tests/test_banded.py +86 -0
  347. physicskit/rmt/tests/test_base.py +29 -0
  348. physicskit/rmt/tests/test_bdg.py +133 -0
  349. physicskit/rmt/tests/test_characteristic_polynomial.py +50 -0
  350. physicskit/rmt/tests/test_chiral.py +273 -0
  351. physicskit/rmt/tests/test_circular.py +225 -0
  352. physicskit/rmt/tests/test_crossover.py +72 -0
  353. physicskit/rmt/tests/test_density.py +23 -0
  354. physicskit/rmt/tests/test_density_matrix.py +181 -0
  355. physicskit/rmt/tests/test_effective_hamiltonian.py +140 -0
  356. physicskit/rmt/tests/test_embedded.py +169 -0
  357. physicskit/rmt/tests/test_free_probability.py +81 -0
  358. physicskit/rmt/tests/test_gaussian_ensembles.py +22 -0
  359. physicskit/rmt/tests/test_gaussian_semicircle.py +127 -0
  360. physicskit/rmt/tests/test_ginibre_circular_law.py +131 -0
  361. physicskit/rmt/tests/test_girko.py +178 -0
  362. physicskit/rmt/tests/test_graph_laplacian.py +102 -0
  363. physicskit/rmt/tests/test_haar.py +118 -0
  364. physicskit/rmt/tests/test_jacobi_wachter.py +136 -0
  365. physicskit/rmt/tests/test_localization.py +240 -0
  366. physicskit/rmt/tests/test_poisson.py +149 -0
  367. physicskit/rmt/tests/test_polynomial.py +107 -0
  368. physicskit/rmt/tests/test_pt_symmetric.py +178 -0
  369. physicskit/rmt/tests/test_random_state.py +19 -0
  370. physicskit/rmt/tests/test_real_ginibre.py +112 -0
  371. physicskit/rmt/tests/test_rigidity_universality.py +167 -0
  372. physicskit/rmt/tests/test_single_ring.py +132 -0
  373. physicskit/rmt/tests/test_spacing_and_ratios.py +122 -0
  374. physicskit/rmt/tests/test_sparse.py +71 -0
  375. physicskit/rmt/tests/test_spectrum.py +27 -0
  376. physicskit/rmt/tests/test_syk.py +136 -0
  377. physicskit/rmt/tests/test_tracy_widom.py +113 -0
  378. physicskit/rmt/tests/test_tridiagonal.py +41 -0
  379. physicskit/rmt/tests/test_truncated_unitary.py +80 -0
  380. physicskit/rmt/tests/test_validation_base.py +25 -0
  381. physicskit/rmt/tests/test_validation_misc.py +67 -0
  382. physicskit/rmt/tests/test_wishart_marchenko_pastur.py +120 -0
  383. physicskit/rmt/utils/__init__.py +0 -0
  384. physicskit/rmt/utils/haar.py +128 -0
  385. physicskit/rmt/utils/random_state.py +24 -0
  386. physicskit/rmt/utils/tridiagonal.py +167 -0
  387. physicskit/rmt/validation/__init__.py +36 -0
  388. physicskit/rmt/validation/base.py +126 -0
  389. physicskit/rmt/validation/circular_law.py +80 -0
  390. physicskit/rmt/validation/marchenko_pastur.py +53 -0
  391. physicskit/rmt/validation/ratio_distribution.py +53 -0
  392. physicskit/rmt/validation/real_ginibre.py +60 -0
  393. physicskit/rmt/validation/sine_kernel.py +57 -0
  394. physicskit/rmt/validation/single_ring.py +68 -0
  395. physicskit/rmt/validation/tracy_widom.py +89 -0
  396. physicskit/rmt/validation/universality.py +100 -0
  397. physicskit/rmt/validation/wachter.py +52 -0
  398. physicskit/rmt/validation/wigner_semicircle.py +40 -0
  399. physicskit/rmt/validation/wigner_surmise.py +58 -0
  400. physicskit/semiclassical/__init__.py +94 -0
  401. physicskit/semiclassical/_compat.py +5 -0
  402. physicskit/semiclassical/core/__init__.py +41 -0
  403. physicskit/semiclassical/core/gutzwiller.py +215 -0
  404. physicskit/semiclassical/core/path_integral.py +594 -0
  405. physicskit/semiclassical/core/propagators.py +579 -0
  406. physicskit/semiclassical/core/wkb.py +308 -0
  407. physicskit/semiclassical/systems/__init__.py +13 -0
  408. physicskit/semiclassical/systems/scarring.py +278 -0
  409. physicskit/semiclassical/tests/__init__.py +0 -0
  410. physicskit/semiclassical/tests/test_gutzwiller.py +35 -0
  411. physicskit/semiclassical/tests/test_path_integral.py +194 -0
  412. physicskit/semiclassical/tests/test_propagators.py +82 -0
  413. physicskit/semiclassical/tests/test_scarring.py +43 -0
  414. physicskit/semiclassical/tests/test_visualizers.py +89 -0
  415. physicskit/semiclassical/tests/test_wkb.py +30 -0
  416. physicskit/semiclassical/visualizers/__init__.py +17 -0
  417. physicskit/semiclassical/visualizers/gutzwiller.py +55 -0
  418. physicskit/semiclassical/visualizers/path_integral.py +195 -0
  419. physicskit/semiclassical/visualizers/propagators.py +89 -0
  420. physicskit/semiclassical/visualizers/scarring.py +146 -0
  421. physicskit/semiclassical/visualizers/wkb.py +55 -0
  422. physicskit/statphys/__init__.py +80 -0
  423. physicskit/statphys/chapters/__init__.py +43 -0
  424. physicskit/statphys/chapters/ehrenfest_urn.py +112 -0
  425. physicskit/statphys/chapters/ising_lattice.py +431 -0
  426. physicskit/statphys/chapters/kpz_growth.py +129 -0
  427. physicskit/statphys/chapters/molecular_dynamics.py +258 -0
  428. physicskit/statphys/chapters/nonequilibrium_work.py +146 -0
  429. physicskit/statphys/chapters/percolation.py +305 -0
  430. physicskit/statphys/chapters/random_walk.py +142 -0
  431. physicskit/statphys/chapters/renormalization.py +148 -0
  432. physicskit/statphys/chapters/sandpile.py +109 -0
  433. physicskit/statphys/chapters/spin_glass.py +275 -0
  434. physicskit/statphys/core/__init__.py +10 -0
  435. physicskit/statphys/core/kpz_engine.py +53 -0
  436. physicskit/statphys/core/md_engine.py +157 -0
  437. physicskit/statphys/core/monte_carlo.py +462 -0
  438. physicskit/statphys/core/random_walk_engine.py +68 -0
  439. physicskit/statphys/core/sandpile_engine.py +52 -0
  440. physicskit/statphys/tests/__init__.py +0 -0
  441. physicskit/statphys/tests/test_dynamics.py +66 -0
  442. physicskit/statphys/tests/test_ehrenfest_urn.py +44 -0
  443. physicskit/statphys/tests/test_finite_size_scaling.py +62 -0
  444. physicskit/statphys/tests/test_interactive.py +33 -0
  445. physicskit/statphys/tests/test_ising.py +68 -0
  446. physicskit/statphys/tests/test_kpz.py +55 -0
  447. physicskit/statphys/tests/test_landau_theory.py +49 -0
  448. physicskit/statphys/tests/test_md_engine.py +31 -0
  449. physicskit/statphys/tests/test_molecular_dynamics.py +72 -0
  450. physicskit/statphys/tests/test_nonequilibrium_work.py +33 -0
  451. physicskit/statphys/tests/test_partition_function.py +26 -0
  452. physicskit/statphys/tests/test_percolation.py +116 -0
  453. physicskit/statphys/tests/test_potts_model.py +46 -0
  454. physicskit/statphys/tests/test_random_walk.py +50 -0
  455. physicskit/statphys/tests/test_renormalization.py +44 -0
  456. physicskit/statphys/tests/test_sandpile.py +44 -0
  457. physicskit/statphys/tests/test_spin_glass.py +73 -0
  458. physicskit/statphys/tests/test_thermodynamics.py +121 -0
  459. physicskit/statphys/tests/test_xy_model.py +45 -0
  460. physicskit/statphys/utils/__init__.py +1 -0
  461. physicskit/statphys/utils/dynamics.py +100 -0
  462. physicskit/statphys/utils/finite_size_scaling.py +171 -0
  463. physicskit/statphys/utils/landau_theory.py +151 -0
  464. physicskit/statphys/utils/partition_function.py +109 -0
  465. physicskit/statphys/utils/thermodynamics.py +356 -0
  466. physicskit/statphys/visualizers/__init__.py +87 -0
  467. physicskit/statphys/visualizers/interactive.py +161 -0
  468. physicskit/statphys/visualizers/jarzynski_render.py +44 -0
  469. physicskit/statphys/visualizers/kpz_render.py +65 -0
  470. physicskit/statphys/visualizers/lattice_render.py +212 -0
  471. physicskit/statphys/visualizers/particle_render.py +121 -0
  472. physicskit/statphys/visualizers/random_walk_render.py +106 -0
  473. physicskit/statphys/visualizers/rg_render.py +45 -0
  474. physicskit/statphys/visualizers/sandpile_render.py +65 -0
  475. physicskit/statphys/visualizers/spin_glass_render.py +40 -0
  476. physicskit/statphys/visualizers/urn_render.py +38 -0
  477. physicskit/statphys/visualizers/vortex_render.py +84 -0
  478. physicskit/tests/__init__.py +0 -0
  479. physicskit/tests/test_constants.py +38 -0
  480. physicskit-0.1.0.dist-info/METADATA +196 -0
  481. physicskit-0.1.0.dist-info/RECORD +484 -0
  482. physicskit-0.1.0.dist-info/WHEEL +5 -0
  483. physicskit-0.1.0.dist-info/licenses/LICENSE +21 -0
  484. physicskit-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,208 @@
1
+ r"""Direct-summation N-body gravitational dynamics.
2
+
3
+ Uses **gravitational units with** :math:`G=1` by default -- every function
4
+ accepts ``G`` as a keyword argument, the same convention
5
+ :mod:`physicskit.relativity` uses for its own geometrized units.
6
+
7
+ - :func:`gravitational_acceleration` -- pairwise Plummer-softened gravity.
8
+ - :func:`leapfrog_step` -- one symplectic kick-drift-kick integration step.
9
+ - :class:`NBodySystem` -- a stateful N-body simulation with energy and
10
+ angular-momentum diagnostics.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import numpy as np
16
+ from numba import njit
17
+
18
+ from physicskit.integrators.fixed_step import leapfrog_step as _leapfrog_step
19
+
20
+ __all__ = ["gravitational_acceleration", "leapfrog_step", "NBodySystem", "figure_eight_initial_conditions"]
21
+
22
+
23
+ @njit(cache=True)
24
+ def _pairwise_acceleration(positions, masses, G, softening):
25
+ n = positions.shape[0]
26
+ acc = np.zeros((n, 3))
27
+ eps2 = softening**2
28
+ for i in range(n):
29
+ ax, ay, az = 0.0, 0.0, 0.0
30
+ for j in range(n):
31
+ if i == j:
32
+ continue
33
+ dx = positions[j, 0] - positions[i, 0]
34
+ dy = positions[j, 1] - positions[i, 1]
35
+ dz = positions[j, 2] - positions[i, 2]
36
+ dist2 = dx * dx + dy * dy + dz * dz + eps2
37
+ inv_dist3 = dist2 ** (-1.5)
38
+ f = G * masses[j] * inv_dist3
39
+ ax += f * dx
40
+ ay += f * dy
41
+ az += f * dz
42
+ acc[i, 0] = ax
43
+ acc[i, 1] = ay
44
+ acc[i, 2] = az
45
+ return acc
46
+
47
+
48
+ def gravitational_acceleration(positions, masses, G=1.0, softening=0.0):
49
+ r"""Pairwise Plummer-softened gravitational acceleration.
50
+
51
+ .. math::
52
+
53
+ \vec a_i = G\sum_{j\neq i} m_j\,
54
+ \frac{\vec r_j-\vec r_i}{\left(|\vec r_j-\vec r_i|^2+\epsilon^2\right)^{3/2}}
55
+
56
+ Parameters
57
+ ----------
58
+ positions : ndarray of shape (N, 3)
59
+ masses : ndarray of shape (N,)
60
+ G : float, default=1.0
61
+ softening : float, default=0.0
62
+ Plummer softening length :math:`\epsilon`.
63
+
64
+ Returns
65
+ -------
66
+ ndarray of shape (N, 3)
67
+
68
+ Examples
69
+ --------
70
+ >>> import numpy as np
71
+ >>> pos = np.array([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0]])
72
+ >>> m = np.array([1.0, 1.0])
73
+ >>> acc = gravitational_acceleration(pos, m)
74
+ >>> round(float(acc[0, 0]), 6)
75
+ 1.0
76
+ """
77
+ positions = np.ascontiguousarray(positions, dtype=np.float64)
78
+ masses = np.ascontiguousarray(masses, dtype=np.float64)
79
+ return _pairwise_acceleration(positions, masses, float(G), float(softening))
80
+
81
+
82
+ @njit(cache=True)
83
+ def _nbody_accel(positions, t, params):
84
+ """Adapt :func:`_pairwise_acceleration` to the shared ``force(pos, t,
85
+ params) -> acc`` convention, packing ``masses``, ``G`` and ``softening``
86
+ into a single ``params`` vector (``masses`` followed by ``[G,
87
+ softening]``) so it can be passed as a first-class function into
88
+ :func:`physicskit.integrators.leapfrog_step`."""
89
+ n = positions.shape[0]
90
+ masses = params[:n]
91
+ G = params[n]
92
+ softening = params[n + 1]
93
+ return _pairwise_acceleration(positions, masses, G, softening)
94
+
95
+
96
+ def leapfrog_step(positions, velocities, masses, dt, G=1.0, softening=0.0):
97
+ """One kick-drift-kick leapfrog (symplectic) integration step.
98
+
99
+ Delegates to the shared :func:`physicskit.integrators.leapfrog_step`.
100
+
101
+ Parameters
102
+ ----------
103
+ positions : ndarray of shape (N, 3)
104
+ velocities : ndarray of shape (N, 3)
105
+ masses : ndarray of shape (N,)
106
+ dt : float
107
+ Timestep.
108
+ G : float, default=1.0
109
+ softening : float, default=0.0
110
+
111
+ Returns
112
+ -------
113
+ new_positions, new_velocities : ndarray of shape (N, 3)
114
+ """
115
+ positions = np.ascontiguousarray(positions, dtype=np.float64)
116
+ velocities = np.ascontiguousarray(velocities, dtype=np.float64)
117
+ masses = np.ascontiguousarray(masses, dtype=np.float64)
118
+ params = np.concatenate((masses, np.array([G, softening], dtype=np.float64)))
119
+ return _leapfrog_step(_nbody_accel, positions, velocities, 0.0, dt, params)
120
+
121
+
122
+ class NBodySystem:
123
+ """A stateful direct-summation N-body gravitational simulation.
124
+
125
+ Parameters
126
+ ----------
127
+ positions : ndarray of shape (N, 3)
128
+ velocities : ndarray of shape (N, 3)
129
+ masses : ndarray of shape (N,)
130
+ G : float, default=1.0
131
+ softening : float, default=0.0
132
+ """
133
+
134
+ def __init__(self, positions, velocities, masses, G=1.0, softening=0.0):
135
+ self.positions = np.array(positions, dtype=np.float64, copy=True)
136
+ self.velocities = np.array(velocities, dtype=np.float64, copy=True)
137
+ self.masses = np.array(masses, dtype=np.float64, copy=True)
138
+ self.G = G
139
+ self.softening = softening
140
+
141
+ def step(self, dt):
142
+ """Advance the system's stored state by one leapfrog step, in place."""
143
+ self.positions, self.velocities = leapfrog_step(self.positions, self.velocities, self.masses, dt, self.G, self.softening)
144
+
145
+ def simulate(self, dt, n_steps):
146
+ """Advance ``n_steps`` steps, returning the position history.
147
+
148
+ Returns
149
+ -------
150
+ ndarray of shape (n_steps + 1, N, 3)
151
+ """
152
+ n = self.positions.shape[0]
153
+ history = np.zeros((n_steps + 1, n, 3))
154
+ history[0] = self.positions
155
+ for k in range(n_steps):
156
+ self.step(dt)
157
+ history[k + 1] = self.positions
158
+ return history
159
+
160
+ def total_energy(self):
161
+ r"""Kinetic plus (softened) gravitational potential energy, at the current state."""
162
+ kinetic = 0.5 * np.sum(self.masses[:, None] * self.velocities**2)
163
+ n = self.positions.shape[0]
164
+ potential = 0.0
165
+ eps2 = self.softening**2
166
+ for i in range(n):
167
+ for j in range(i + 1, n):
168
+ d = np.linalg.norm(self.positions[i] - self.positions[j])
169
+ potential -= self.G * self.masses[i] * self.masses[j] / np.sqrt(d**2 + eps2)
170
+ return float(kinetic + potential)
171
+
172
+ def total_angular_momentum(self):
173
+ r"""Total angular momentum, :math:`\vec L=\sum_im_i\,\vec r_i\times\vec v_i`."""
174
+ L = np.sum(self.masses[:, None] * np.cross(self.positions, self.velocities), axis=0)
175
+ return L
176
+
177
+
178
+ def figure_eight_initial_conditions():
179
+ r"""Initial conditions for the equal-mass planar figure-eight three-body choreography.
180
+
181
+ Three equal masses, in :math:`G=1` units, chase each other forever
182
+ around a single figure-eight-shaped curve -- a periodic solution
183
+ discovered numerically by Moore (1993) and proven to exist by
184
+ Chenciner & Montgomery (2000, *Annals of Mathematics* 152). Unlike
185
+ typical three-body configurations it is planar, collision-free, and
186
+ exactly periodic, making it a clean, visually striking demo for
187
+ :class:`NBodySystem`.
188
+
189
+ Returns
190
+ -------
191
+ positions : ndarray of shape (3, 3)
192
+ velocities : ndarray of shape (3, 3)
193
+ masses : ndarray of shape (3,)
194
+
195
+ Examples
196
+ --------
197
+ >>> positions, velocities, masses = figure_eight_initial_conditions()
198
+ >>> system = NBodySystem(positions, velocities, masses)
199
+ >>> history = system.simulate(dt=0.001, n_steps=100)
200
+ >>> history.shape
201
+ (101, 3, 3)
202
+ """
203
+ r1 = np.array([0.9700436, -0.24308753, 0.0])
204
+ v3 = np.array([0.93240737, 0.86473146, 0.0])
205
+ positions = np.array([r1, -r1, [0.0, 0.0, 0.0]])
206
+ velocities = np.array([-0.5 * v3, -0.5 * v3, v3])
207
+ masses = np.array([1.0, 1.0, 1.0])
208
+ return positions, velocities, masses
@@ -0,0 +1,220 @@
1
+ r"""Two-body Keplerian orbital mechanics: elements, state vectors, and transfers.
2
+
3
+ Uses **gravitational units with** :math:`G=1` by default; the standard
4
+ gravitational parameter :math:`\mu=GM` appears directly as a function
5
+ argument, the normal convention in orbital mechanics regardless of unit
6
+ system (the same style :mod:`physicskit.relativity` uses for its own
7
+ geometrized units).
8
+
9
+ - :func:`orbital_period`, :func:`vis_viva_speed` -- Kepler's third law and
10
+ the vis-viva equation.
11
+ - :func:`orbital_elements_from_state`, :func:`state_from_orbital_elements`
12
+ -- converting between Cartesian state vectors and the six classical
13
+ orbital elements.
14
+ - :func:`hohmann_transfer` -- the two-burn transfer between circular orbits.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import numpy as np
20
+
21
+ __all__ = [
22
+ "orbital_period",
23
+ "vis_viva_speed",
24
+ "orbital_elements_from_state",
25
+ "state_from_orbital_elements",
26
+ "hohmann_transfer",
27
+ ]
28
+
29
+
30
+ def orbital_period(a, mu):
31
+ r"""Kepler's third law, :math:`T=2\pi\sqrt{a^3/\mu}`.
32
+
33
+ Parameters
34
+ ----------
35
+ a : float
36
+ Semi-major axis (bound orbit, ``a > 0``).
37
+ mu : float
38
+ Gravitational parameter, :math:`\mu=GM`.
39
+
40
+ Returns
41
+ -------
42
+ float
43
+
44
+ Examples
45
+ --------
46
+ >>> round(orbital_period(1.0, 1.0) / (2 * np.pi), 6)
47
+ 1.0
48
+ """
49
+ return float(2.0 * np.pi * np.sqrt(a**3 / mu))
50
+
51
+
52
+ def vis_viva_speed(r, a, mu):
53
+ r"""The vis-viva equation, :math:`v=\sqrt{\mu\left(2/r-1/a\right)}`.
54
+
55
+ Works for ``a > 0`` (ellipse), ``a < 0`` (hyperbola), and ``a = inf``
56
+ (parabolic escape trajectory, where the formula reduces to
57
+ :math:`v=\sqrt{2\mu/r}`).
58
+
59
+ Parameters
60
+ ----------
61
+ r : float
62
+ Current orbital radius.
63
+ a : float
64
+ Semi-major axis.
65
+ mu : float
66
+ Gravitational parameter.
67
+
68
+ Returns
69
+ -------
70
+ float
71
+
72
+ Examples
73
+ --------
74
+ >>> round(vis_viva_speed(1.0, np.inf, 1.0), 6)
75
+ 1.414214
76
+ """
77
+ return float(np.sqrt(mu * (2.0 / r - 1.0 / a)))
78
+
79
+
80
+ def orbital_elements_from_state(r_vec, v_vec, mu):
81
+ r"""Classical (Keplerian) orbital elements from a Cartesian state vector.
82
+
83
+ Returns semi-major axis, eccentricity, inclination, right ascension of
84
+ the ascending node, argument of periapsis, and true anomaly (angles
85
+ in radians). For a near-equatorial orbit (:math:`i\approx0` or
86
+ :math:`\pi`), the node vector is near zero and ``raan`` is undefined;
87
+ this implementation returns ``raan=0.0`` in that case rather than
88
+ raising -- a documented simplification, not a fully general
89
+ equatorial-orbit treatment.
90
+
91
+ Parameters
92
+ ----------
93
+ r_vec, v_vec : ndarray of shape (3,)
94
+ Position and velocity.
95
+ mu : float
96
+ Gravitational parameter.
97
+
98
+ Returns
99
+ -------
100
+ a, e, i, raan, argp, nu : float
101
+
102
+ Examples
103
+ --------
104
+ >>> r_vec, v_vec = state_from_orbital_elements(1.0, 0.3, 0.5, 1.0, 0.7, 1.2, mu=1.0)
105
+ >>> a, e, i, raan, argp, nu = orbital_elements_from_state(r_vec, v_vec, mu=1.0)
106
+ >>> [round(x, 6) for x in (a, e, i, raan, argp, nu)]
107
+ [1.0, 0.3, 0.5, 1.0, 0.7, 1.2]
108
+ """
109
+ r_vec = np.asarray(r_vec, dtype=float)
110
+ v_vec = np.asarray(v_vec, dtype=float)
111
+ r = np.linalg.norm(r_vec)
112
+ v = np.linalg.norm(v_vec)
113
+
114
+ h_vec = np.cross(r_vec, v_vec)
115
+ h = np.linalg.norm(h_vec)
116
+ n_vec = np.cross([0.0, 0.0, 1.0], h_vec)
117
+ n = np.linalg.norm(n_vec)
118
+ e_vec = np.cross(v_vec, h_vec) / mu - r_vec / r
119
+ e = np.linalg.norm(e_vec)
120
+
121
+ energy = v**2 / 2.0 - mu / r
122
+ a = np.inf if abs(e - 1.0) < 1e-12 else -mu / (2.0 * energy)
123
+
124
+ i = float(np.arccos(np.clip(h_vec[2] / h, -1.0, 1.0)))
125
+
126
+ if n > 1e-12:
127
+ raan = float(np.arccos(np.clip(n_vec[0] / n, -1.0, 1.0)))
128
+ if n_vec[1] < 0:
129
+ raan = 2 * np.pi - raan
130
+ else:
131
+ raan = 0.0
132
+
133
+ if n > 1e-12 and e > 1e-12:
134
+ argp = float(np.arccos(np.clip(np.dot(n_vec, e_vec) / (n * e), -1.0, 1.0)))
135
+ if e_vec[2] < 0:
136
+ argp = 2 * np.pi - argp
137
+ else:
138
+ argp = 0.0
139
+
140
+ if e > 1e-12:
141
+ nu = float(np.arccos(np.clip(np.dot(e_vec, r_vec) / (e * r), -1.0, 1.0)))
142
+ if np.dot(r_vec, v_vec) < 0:
143
+ nu = 2 * np.pi - nu
144
+ else:
145
+ nu = 0.0
146
+
147
+ return float(a), float(e), i, raan, argp, nu
148
+
149
+
150
+ def state_from_orbital_elements(a, e, i, raan, argp, nu, mu):
151
+ """The inverse of :func:`orbital_elements_from_state`.
152
+
153
+ Parameters
154
+ ----------
155
+ a, e, i, raan, argp, nu : float
156
+ Classical orbital elements (angles in radians).
157
+ mu : float
158
+ Gravitational parameter.
159
+
160
+ Returns
161
+ -------
162
+ r_vec, v_vec : ndarray of shape (3,)
163
+ """
164
+ p = a * (1.0 - e**2)
165
+ r = p / (1.0 + e * np.cos(nu))
166
+ r_pf = np.array([r * np.cos(nu), r * np.sin(nu), 0.0])
167
+ v_pf = np.sqrt(mu / p) * np.array([-np.sin(nu), e + np.cos(nu), 0.0])
168
+
169
+ cO, sO = np.cos(raan), np.sin(raan)
170
+ ci, si = np.cos(i), np.sin(i)
171
+ cw, sw = np.cos(argp), np.sin(argp)
172
+
173
+ # 3-1-3 Euler rotation (raan, i, argp): perifocal -> reference frame.
174
+ R = np.array(
175
+ [
176
+ [cO * cw - sO * sw * ci, -cO * sw - sO * cw * ci, sO * si],
177
+ [sO * cw + cO * sw * ci, -sO * sw + cO * cw * ci, -cO * si],
178
+ [sw * si, cw * si, ci],
179
+ ]
180
+ )
181
+ return R @ r_pf, R @ v_pf
182
+
183
+
184
+ def hohmann_transfer(r1, r2, mu):
185
+ r"""The two burns and transfer time for a Hohmann transfer.
186
+
187
+ Parameters
188
+ ----------
189
+ r1 : float
190
+ Initial circular orbit radius.
191
+ r2 : float
192
+ Final circular orbit radius.
193
+ mu : float
194
+ Gravitational parameter.
195
+
196
+ Returns
197
+ -------
198
+ delta_v1 : float
199
+ Speed change (magnitude) to leave the initial circular orbit and
200
+ enter the transfer ellipse.
201
+ delta_v2 : float
202
+ Speed change (magnitude) to circularize at ``r2``.
203
+ transfer_time : float
204
+ Time to complete the transfer, half the transfer ellipse's period.
205
+
206
+ Examples
207
+ --------
208
+ >>> dv1, dv2, t = hohmann_transfer(1.0, 4.0, mu=1.0)
209
+ >>> dv1 > 0 and dv2 > 0 and t > 0
210
+ True
211
+ """
212
+ a_t = (r1 + r2) / 2.0
213
+ v1_circular = vis_viva_speed(r1, r1, mu)
214
+ v1_transfer = vis_viva_speed(r1, a_t, mu)
215
+ v2_transfer = vis_viva_speed(r2, a_t, mu)
216
+ v2_circular = vis_viva_speed(r2, r2, mu)
217
+ delta_v1 = abs(v1_transfer - v1_circular)
218
+ delta_v2 = abs(v2_circular - v2_transfer)
219
+ transfer_time = orbital_period(a_t, mu) / 2.0
220
+ return float(delta_v1), float(delta_v2), float(transfer_time)