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.
- physicskit/__init__.py +51 -0
- physicskit/astro/__init__.py +66 -0
- physicskit/astro/cosmic_web.py +395 -0
- physicskit/astro/galactic_dynamics.py +137 -0
- physicskit/astro/nbody.py +208 -0
- physicskit/astro/orbital_mechanics.py +220 -0
- physicskit/astro/stellar_dynamo.py +628 -0
- physicskit/astro/stellar_structure.py +198 -0
- physicskit/astro/tests/__init__.py +0 -0
- physicskit/astro/tests/conftest.py +7 -0
- physicskit/astro/tests/test_cosmic_web.py +159 -0
- physicskit/astro/tests/test_galactic_dynamics.py +46 -0
- physicskit/astro/tests/test_nbody.py +81 -0
- physicskit/astro/tests/test_orbital_mechanics.py +73 -0
- physicskit/astro/tests/test_stellar_dynamo.py +198 -0
- physicskit/astro/tests/test_stellar_structure.py +52 -0
- physicskit/astro/tests/test_visualizers.py +159 -0
- physicskit/astro/visualizers.py +628 -0
- physicskit/chaos/__init__.py +55 -0
- physicskit/chaos/core/__init__.py +3 -0
- physicskit/chaos/core/base_system.py +342 -0
- physicskit/chaos/core/integrators.py +40 -0
- physicskit/chaos/exceptions.py +24 -0
- physicskit/chaos/quantum/__init__.py +38 -0
- physicskit/chaos/quantum/billiards.py +274 -0
- physicskit/chaos/quantum/husimi.py +85 -0
- physicskit/chaos/quantum/maps.py +366 -0
- physicskit/chaos/systems/__init__.py +38 -0
- physicskit/chaos/systems/billiards.py +1131 -0
- physicskit/chaos/systems/continuous.py +1276 -0
- physicskit/chaos/systems/maps.py +557 -0
- physicskit/chaos/tests/__init__.py +0 -0
- physicskit/chaos/tests/test_basins.py +76 -0
- physicskit/chaos/tests/test_bifurcation.py +132 -0
- physicskit/chaos/tests/test_billiards.py +115 -0
- physicskit/chaos/tests/test_continuous.py +224 -0
- physicskit/chaos/tests/test_dimension.py +69 -0
- physicskit/chaos/tests/test_divergence.py +90 -0
- physicskit/chaos/tests/test_dynamic_plots.py +269 -0
- physicskit/chaos/tests/test_integrators.py +96 -0
- physicskit/chaos/tests/test_io.py +41 -0
- physicskit/chaos/tests/test_maps.py +110 -0
- physicskit/chaos/tests/test_metrics.py +115 -0
- physicskit/chaos/tests/test_phase_space.py +73 -0
- physicskit/chaos/tests/test_properties.py +116 -0
- physicskit/chaos/tests/test_quantum_billiards.py +94 -0
- physicskit/chaos/tests/test_quantum_maps.py +144 -0
- physicskit/chaos/tests/test_recurrence.py +51 -0
- physicskit/chaos/tests/test_repr_and_api_consistency.py +134 -0
- physicskit/chaos/tests/test_section.py +49 -0
- physicskit/chaos/tests/test_spectral.py +48 -0
- physicskit/chaos/tests/test_streamlit_app.py +45 -0
- physicskit/chaos/tests/test_timeseries.py +131 -0
- physicskit/chaos/tests/test_viewer3d.py +41 -0
- physicskit/chaos/utils/__init__.py +46 -0
- physicskit/chaos/utils/dimension.py +139 -0
- physicskit/chaos/utils/io.py +95 -0
- physicskit/chaos/utils/metrics.py +304 -0
- physicskit/chaos/utils/recurrence.py +122 -0
- physicskit/chaos/utils/spectral.py +69 -0
- physicskit/chaos/utils/timeseries.py +303 -0
- physicskit/chaos/visualizers/__init__.py +85 -0
- physicskit/chaos/visualizers/basins.py +185 -0
- physicskit/chaos/visualizers/bifurcation.py +273 -0
- physicskit/chaos/visualizers/divergence.py +374 -0
- physicskit/chaos/visualizers/dynamic_plots.py +1372 -0
- physicskit/chaos/visualizers/phase_space.py +133 -0
- physicskit/chaos/visualizers/quantum.py +299 -0
- physicskit/chaos/visualizers/recurrence.py +91 -0
- physicskit/chaos/visualizers/section.py +161 -0
- physicskit/chaos/visualizers/theme.py +31 -0
- physicskit/chaos/visualizers/viewer3d.py +82 -0
- physicskit/classical/__init__.py +55 -0
- physicskit/classical/core/__init__.py +17 -0
- physicskit/classical/core/base_system.py +510 -0
- physicskit/classical/core/integrators.py +397 -0
- physicskit/classical/systems/__init__.py +32 -0
- physicskit/classical/systems/chains.py +334 -0
- physicskit/classical/systems/hamiltonian.py +215 -0
- physicskit/classical/systems/lagrangian.py +308 -0
- physicskit/classical/systems/newtonian.py +536 -0
- physicskit/classical/systems/rotations.py +614 -0
- physicskit/classical/tests/__init__.py +0 -0
- physicskit/classical/tests/conftest.py +7 -0
- physicskit/classical/tests/test_base_system.py +113 -0
- physicskit/classical/tests/test_chains.py +84 -0
- physicskit/classical/tests/test_conservation.py +244 -0
- physicskit/classical/tests/test_conservation_utils.py +47 -0
- physicskit/classical/tests/test_hamiltonian.py +44 -0
- physicskit/classical/tests/test_integrators.py +123 -0
- physicskit/classical/tests/test_lagrangian.py +69 -0
- physicskit/classical/tests/test_newtonian.py +45 -0
- physicskit/classical/tests/test_rotations.py +160 -0
- physicskit/classical/tests/test_stepsize.py +149 -0
- physicskit/classical/tests/test_symbolic.py +125 -0
- physicskit/classical/tests/test_visualizers.py +172 -0
- physicskit/classical/utils/__init__.py +20 -0
- physicskit/classical/utils/conservation.py +126 -0
- physicskit/classical/utils/stepsize.py +187 -0
- physicskit/classical/utils/symbolic.py +235 -0
- physicskit/classical/visualizers/__init__.py +25 -0
- physicskit/classical/visualizers/animations.py +508 -0
- physicskit/classical/visualizers/interactive.py +113 -0
- physicskit/classical/visualizers/modal_analysis.py +97 -0
- physicskit/classical/visualizers/phase_space.py +214 -0
- physicskit/condensed/__init__.py +122 -0
- physicskit/condensed/anderson_localization.py +155 -0
- physicskit/condensed/correlated.py +284 -0
- physicskit/condensed/ginzburg_landau.py +220 -0
- physicskit/condensed/landau_levels.py +246 -0
- physicskit/condensed/laughlin.py +229 -0
- physicskit/condensed/models.py +627 -0
- physicskit/condensed/tests/__init__.py +0 -0
- physicskit/condensed/tests/test_condensed.py +518 -0
- physicskit/condensed/tests/test_visualizers.py +87 -0
- physicskit/condensed/tight_binding.py +445 -0
- physicskit/condensed/topological_insulator_3d.py +178 -0
- physicskit/condensed/topology.py +217 -0
- physicskit/condensed/visualizers.py +296 -0
- physicskit/condensed/weyl.py +180 -0
- physicskit/constants.py +184 -0
- physicskit/fields/__init__.py +111 -0
- physicskit/fields/electrodynamics.py +671 -0
- physicskit/fields/quantum_fields.py +510 -0
- physicskit/fields/solitons.py +527 -0
- physicskit/fields/tests/__init__.py +0 -0
- physicskit/fields/tests/conftest.py +7 -0
- physicskit/fields/tests/test_field_animations.py +154 -0
- physicskit/fields/tests/test_fields.py +439 -0
- physicskit/fields/tests/test_visualizers.py +101 -0
- physicskit/fields/visualizers.py +503 -0
- physicskit/fluids/__init__.py +134 -0
- physicskit/fluids/core/__init__.py +23 -0
- physicskit/fluids/core/grid.py +165 -0
- physicskit/fluids/core/timestepping.py +231 -0
- physicskit/fluids/exceptions.py +26 -0
- physicskit/fluids/systems/__init__.py +70 -0
- physicskit/fluids/systems/compressible_flow.py +281 -0
- physicskit/fluids/systems/instabilities.py +343 -0
- physicskit/fluids/systems/navier_stokes.py +221 -0
- physicskit/fluids/systems/potential_flow.py +440 -0
- physicskit/fluids/systems/viscous_flow.py +425 -0
- physicskit/fluids/systems/vortex_dynamics.py +304 -0
- physicskit/fluids/tests/__init__.py +0 -0
- physicskit/fluids/tests/conftest.py +7 -0
- physicskit/fluids/tests/test_compressible_flow.py +66 -0
- physicskit/fluids/tests/test_instabilities.py +115 -0
- physicskit/fluids/tests/test_navier_stokes.py +67 -0
- physicskit/fluids/tests/test_potential_flow.py +92 -0
- physicskit/fluids/tests/test_static_visualizers.py +91 -0
- physicskit/fluids/tests/test_utils.py +100 -0
- physicskit/fluids/tests/test_viscous_flow.py +110 -0
- physicskit/fluids/tests/test_visualizers.py +34 -0
- physicskit/fluids/tests/test_vortex_dynamics.py +88 -0
- physicskit/fluids/utils/__init__.py +18 -0
- physicskit/fluids/utils/dimensionless.py +239 -0
- physicskit/fluids/utils/spectral_analysis.py +142 -0
- physicskit/fluids/visualizers/__init__.py +14 -0
- physicskit/fluids/visualizers/compressible.py +39 -0
- physicskit/fluids/visualizers/flow_fields.py +252 -0
- physicskit/fluids/visualizers/potential_flow.py +51 -0
- physicskit/fluids/visualizers/spectra.py +62 -0
- physicskit/fluids/visualizers/theme.py +38 -0
- physicskit/integrators/__init__.py +52 -0
- physicskit/integrators/adaptive.py +199 -0
- physicskit/integrators/fixed_step.py +360 -0
- physicskit/integrators/tests/__init__.py +0 -0
- physicskit/integrators/tests/test_integrators.py +101 -0
- physicskit/optics/__init__.py +124 -0
- physicskit/optics/_compat.py +5 -0
- physicskit/optics/gaussian.py +382 -0
- physicskit/optics/quantum_optics.py +428 -0
- physicskit/optics/ray.py +469 -0
- physicskit/optics/tests/__init__.py +0 -0
- physicskit/optics/tests/test_diffraction_animation.py +38 -0
- physicskit/optics/tests/test_gaussian.py +170 -0
- physicskit/optics/tests/test_quantum_optics.py +147 -0
- physicskit/optics/tests/test_ray.py +177 -0
- physicskit/optics/tests/test_visualizers.py +58 -0
- physicskit/optics/tests/test_wave.py +146 -0
- physicskit/optics/visualizers.py +264 -0
- physicskit/optics/wave.py +365 -0
- physicskit/particle/__init__.py +152 -0
- physicskit/particle/collider.py +382 -0
- physicskit/particle/confinement.py +125 -0
- physicskit/particle/decays.py +357 -0
- physicskit/particle/electroweak.py +300 -0
- physicskit/particle/kinematics.py +271 -0
- physicskit/particle/neutrinos.py +84 -0
- physicskit/particle/nuclear.py +100 -0
- physicskit/particle/scattering.py +159 -0
- physicskit/particle/tests/__init__.py +0 -0
- physicskit/particle/tests/conftest.py +7 -0
- physicskit/particle/tests/test_collider.py +119 -0
- physicskit/particle/tests/test_confinement.py +42 -0
- physicskit/particle/tests/test_decays.py +112 -0
- physicskit/particle/tests/test_electroweak.py +97 -0
- physicskit/particle/tests/test_kinematics.py +138 -0
- physicskit/particle/tests/test_neutrinos.py +36 -0
- physicskit/particle/tests/test_nuclear.py +45 -0
- physicskit/particle/tests/test_scattering.py +64 -0
- physicskit/particle/tests/test_visualizers.py +214 -0
- physicskit/particle/visualizers/__init__.py +38 -0
- physicskit/particle/visualizers/animations.py +705 -0
- physicskit/particle/visualizers/static.py +101 -0
- physicskit/plasma/__init__.py +176 -0
- physicskit/plasma/acceleration.py +152 -0
- physicskit/plasma/instabilities.py +417 -0
- physicskit/plasma/kinetic.py +588 -0
- physicskit/plasma/mhd.py +463 -0
- physicskit/plasma/single_particle.py +562 -0
- physicskit/plasma/tests/__init__.py +0 -0
- physicskit/plasma/tests/conftest.py +7 -0
- physicskit/plasma/tests/test_new_time_domain_features.py +222 -0
- physicskit/plasma/tests/test_plasma.py +232 -0
- physicskit/plasma/tests/test_visualizers.py +79 -0
- physicskit/plasma/turbulence.py +219 -0
- physicskit/plasma/visualizers.py +868 -0
- physicskit/plasma/waves.py +549 -0
- physicskit/quantum/__init__.py +180 -0
- physicskit/quantum/_compat.py +20 -0
- physicskit/quantum/chapters/__init__.py +0 -0
- physicskit/quantum/chapters/entanglement.py +489 -0
- physicskit/quantum/chapters/harmonic_spin.py +517 -0
- physicskit/quantum/chapters/hydrogen_am.py +292 -0
- physicskit/quantum/chapters/perturbation.py +350 -0
- physicskit/quantum/chapters/potentials.py +997 -0
- physicskit/quantum/chapters/spin.py +306 -0
- physicskit/quantum/chapters/wave_packets.py +541 -0
- physicskit/quantum/core/__init__.py +0 -0
- physicskit/quantum/core/eigensolvers.py +311 -0
- physicskit/quantum/core/operators.py +296 -0
- physicskit/quantum/core/solvers.py +271 -0
- physicskit/quantum/tests/__init__.py +0 -0
- physicskit/quantum/tests/conftest.py +7 -0
- physicskit/quantum/tests/test_animations.py +225 -0
- physicskit/quantum/tests/test_compat.py +43 -0
- physicskit/quantum/tests/test_eigensolvers.py +24 -0
- physicskit/quantum/tests/test_entanglement.py +127 -0
- physicskit/quantum/tests/test_harmonic_spin.py +140 -0
- physicskit/quantum/tests/test_hydrogen_am.py +48 -0
- physicskit/quantum/tests/test_measure.py +110 -0
- physicskit/quantum/tests/test_operators.py +105 -0
- physicskit/quantum/tests/test_perturbation.py +112 -0
- physicskit/quantum/tests/test_physics_checks.py +131 -0
- physicskit/quantum/tests/test_potentials.py +191 -0
- physicskit/quantum/tests/test_solvers.py +70 -0
- physicskit/quantum/tests/test_spin.py +22 -0
- physicskit/quantum/tests/test_unitarity.py +84 -0
- physicskit/quantum/tests/test_wave_packets.py +53 -0
- physicskit/quantum/utils/__init__.py +0 -0
- physicskit/quantum/utils/measure.py +253 -0
- physicskit/quantum/visualizers/__init__.py +0 -0
- physicskit/quantum/visualizers/bloch_sphere.py +205 -0
- physicskit/quantum/visualizers/entanglement.py +58 -0
- physicskit/quantum/visualizers/orbitals.py +187 -0
- physicskit/quantum/visualizers/phase_space.py +179 -0
- physicskit/quantum/visualizers/wavefunctions.py +230 -0
- physicskit/relativity/__init__.py +61 -0
- physicskit/relativity/chapters/__init__.py +33 -0
- physicskit/relativity/chapters/cosmology.py +190 -0
- physicskit/relativity/chapters/gw_merger.py +399 -0
- physicskit/relativity/chapters/kerr.py +371 -0
- physicskit/relativity/chapters/lensing.py +196 -0
- physicskit/relativity/chapters/neutron_star.py +149 -0
- physicskit/relativity/chapters/schwarzschild.py +412 -0
- physicskit/relativity/chapters/timekeeping.py +133 -0
- physicskit/relativity/core/__init__.py +12 -0
- physicskit/relativity/core/geodesics.py +216 -0
- physicskit/relativity/core/kerr_raytracer.py +259 -0
- physicskit/relativity/core/raytracer.py +241 -0
- physicskit/relativity/core/tensors.py +468 -0
- physicskit/relativity/tests/__init__.py +0 -0
- physicskit/relativity/tests/test_conservations.py +54 -0
- physicskit/relativity/tests/test_constants.py +34 -0
- physicskit/relativity/tests/test_cosmology.py +61 -0
- physicskit/relativity/tests/test_gw_merger.py +117 -0
- physicskit/relativity/tests/test_kerr.py +116 -0
- physicskit/relativity/tests/test_kerr_raytracer.py +103 -0
- physicskit/relativity/tests/test_lensing.py +75 -0
- physicskit/relativity/tests/test_neutron_star.py +48 -0
- physicskit/relativity/tests/test_raytracer.py +67 -0
- physicskit/relativity/tests/test_schwarzschild.py +126 -0
- physicskit/relativity/tests/test_shadow_render.py +81 -0
- physicskit/relativity/tests/test_tensors.py +86 -0
- physicskit/relativity/tests/test_timekeeping.py +51 -0
- physicskit/relativity/tests/test_visualizers_misc.py +115 -0
- physicskit/relativity/utils/__init__.py +1 -0
- physicskit/relativity/utils/constants.py +232 -0
- physicskit/relativity/visualizers/__init__.py +46 -0
- physicskit/relativity/visualizers/interactive.py +127 -0
- physicskit/relativity/visualizers/shadow_render.py +367 -0
- physicskit/relativity/visualizers/spacetime_3d.py +92 -0
- physicskit/relativity/visualizers/spacetime_diagrams.py +198 -0
- physicskit/relativity/visualizers/wave_plots.py +185 -0
- physicskit/rmt/__init__.py +8 -0
- physicskit/rmt/ensembles/__init__.py +108 -0
- physicskit/rmt/ensembles/banded.py +114 -0
- physicskit/rmt/ensembles/base.py +135 -0
- physicskit/rmt/ensembles/bdg.py +218 -0
- physicskit/rmt/ensembles/chiral.py +308 -0
- physicskit/rmt/ensembles/circular.py +104 -0
- physicskit/rmt/ensembles/crossover.py +82 -0
- physicskit/rmt/ensembles/density_matrix.py +148 -0
- physicskit/rmt/ensembles/effective_hamiltonian.py +230 -0
- physicskit/rmt/ensembles/embedded.py +207 -0
- physicskit/rmt/ensembles/gaussian.py +153 -0
- physicskit/rmt/ensembles/ginibre.py +110 -0
- physicskit/rmt/ensembles/girko.py +190 -0
- physicskit/rmt/ensembles/graph_laplacian.py +92 -0
- physicskit/rmt/ensembles/haar.py +57 -0
- physicskit/rmt/ensembles/jacobi.py +182 -0
- physicskit/rmt/ensembles/poisson.py +77 -0
- physicskit/rmt/ensembles/polynomial.py +139 -0
- physicskit/rmt/ensembles/pt_symmetric.py +120 -0
- physicskit/rmt/ensembles/single_ring.py +170 -0
- physicskit/rmt/ensembles/sparse.py +95 -0
- physicskit/rmt/ensembles/syk.py +170 -0
- physicskit/rmt/ensembles/truncated_unitary.py +80 -0
- physicskit/rmt/ensembles/universality.py +92 -0
- physicskit/rmt/ensembles/wishart.py +88 -0
- physicskit/rmt/py.typed +0 -0
- physicskit/rmt/spectrum.py +82 -0
- physicskit/rmt/stats/__init__.py +160 -0
- physicskit/rmt/stats/characteristic_polynomial.py +77 -0
- physicskit/rmt/stats/circular_law.py +54 -0
- physicskit/rmt/stats/correlations.py +162 -0
- physicskit/rmt/stats/density.py +70 -0
- physicskit/rmt/stats/entanglement.py +36 -0
- physicskit/rmt/stats/free_probability.py +202 -0
- physicskit/rmt/stats/localization.py +338 -0
- physicskit/rmt/stats/marchenko_pastur.py +55 -0
- physicskit/rmt/stats/pt_symmetric.py +265 -0
- physicskit/rmt/stats/ratios.py +110 -0
- physicskit/rmt/stats/real_ginibre.py +134 -0
- physicskit/rmt/stats/rigidity.py +272 -0
- physicskit/rmt/stats/single_ring.py +95 -0
- physicskit/rmt/stats/spacing.py +150 -0
- physicskit/rmt/stats/tracy_widom.py +175 -0
- physicskit/rmt/stats/truncated_unitary.py +40 -0
- physicskit/rmt/stats/unfolding.py +37 -0
- physicskit/rmt/stats/wachter.py +67 -0
- physicskit/rmt/tests/__init__.py +0 -0
- physicskit/rmt/tests/cache_utils.py +107 -0
- physicskit/rmt/tests/conftest.py +8 -0
- physicskit/rmt/tests/test_banded.py +86 -0
- physicskit/rmt/tests/test_base.py +29 -0
- physicskit/rmt/tests/test_bdg.py +133 -0
- physicskit/rmt/tests/test_characteristic_polynomial.py +50 -0
- physicskit/rmt/tests/test_chiral.py +273 -0
- physicskit/rmt/tests/test_circular.py +225 -0
- physicskit/rmt/tests/test_crossover.py +72 -0
- physicskit/rmt/tests/test_density.py +23 -0
- physicskit/rmt/tests/test_density_matrix.py +181 -0
- physicskit/rmt/tests/test_effective_hamiltonian.py +140 -0
- physicskit/rmt/tests/test_embedded.py +169 -0
- physicskit/rmt/tests/test_free_probability.py +81 -0
- physicskit/rmt/tests/test_gaussian_ensembles.py +22 -0
- physicskit/rmt/tests/test_gaussian_semicircle.py +127 -0
- physicskit/rmt/tests/test_ginibre_circular_law.py +131 -0
- physicskit/rmt/tests/test_girko.py +178 -0
- physicskit/rmt/tests/test_graph_laplacian.py +102 -0
- physicskit/rmt/tests/test_haar.py +118 -0
- physicskit/rmt/tests/test_jacobi_wachter.py +136 -0
- physicskit/rmt/tests/test_localization.py +240 -0
- physicskit/rmt/tests/test_poisson.py +149 -0
- physicskit/rmt/tests/test_polynomial.py +107 -0
- physicskit/rmt/tests/test_pt_symmetric.py +178 -0
- physicskit/rmt/tests/test_random_state.py +19 -0
- physicskit/rmt/tests/test_real_ginibre.py +112 -0
- physicskit/rmt/tests/test_rigidity_universality.py +167 -0
- physicskit/rmt/tests/test_single_ring.py +132 -0
- physicskit/rmt/tests/test_spacing_and_ratios.py +122 -0
- physicskit/rmt/tests/test_sparse.py +71 -0
- physicskit/rmt/tests/test_spectrum.py +27 -0
- physicskit/rmt/tests/test_syk.py +136 -0
- physicskit/rmt/tests/test_tracy_widom.py +113 -0
- physicskit/rmt/tests/test_tridiagonal.py +41 -0
- physicskit/rmt/tests/test_truncated_unitary.py +80 -0
- physicskit/rmt/tests/test_validation_base.py +25 -0
- physicskit/rmt/tests/test_validation_misc.py +67 -0
- physicskit/rmt/tests/test_wishart_marchenko_pastur.py +120 -0
- physicskit/rmt/utils/__init__.py +0 -0
- physicskit/rmt/utils/haar.py +128 -0
- physicskit/rmt/utils/random_state.py +24 -0
- physicskit/rmt/utils/tridiagonal.py +167 -0
- physicskit/rmt/validation/__init__.py +36 -0
- physicskit/rmt/validation/base.py +126 -0
- physicskit/rmt/validation/circular_law.py +80 -0
- physicskit/rmt/validation/marchenko_pastur.py +53 -0
- physicskit/rmt/validation/ratio_distribution.py +53 -0
- physicskit/rmt/validation/real_ginibre.py +60 -0
- physicskit/rmt/validation/sine_kernel.py +57 -0
- physicskit/rmt/validation/single_ring.py +68 -0
- physicskit/rmt/validation/tracy_widom.py +89 -0
- physicskit/rmt/validation/universality.py +100 -0
- physicskit/rmt/validation/wachter.py +52 -0
- physicskit/rmt/validation/wigner_semicircle.py +40 -0
- physicskit/rmt/validation/wigner_surmise.py +58 -0
- physicskit/semiclassical/__init__.py +94 -0
- physicskit/semiclassical/_compat.py +5 -0
- physicskit/semiclassical/core/__init__.py +41 -0
- physicskit/semiclassical/core/gutzwiller.py +215 -0
- physicskit/semiclassical/core/path_integral.py +594 -0
- physicskit/semiclassical/core/propagators.py +579 -0
- physicskit/semiclassical/core/wkb.py +308 -0
- physicskit/semiclassical/systems/__init__.py +13 -0
- physicskit/semiclassical/systems/scarring.py +278 -0
- physicskit/semiclassical/tests/__init__.py +0 -0
- physicskit/semiclassical/tests/test_gutzwiller.py +35 -0
- physicskit/semiclassical/tests/test_path_integral.py +194 -0
- physicskit/semiclassical/tests/test_propagators.py +82 -0
- physicskit/semiclassical/tests/test_scarring.py +43 -0
- physicskit/semiclassical/tests/test_visualizers.py +89 -0
- physicskit/semiclassical/tests/test_wkb.py +30 -0
- physicskit/semiclassical/visualizers/__init__.py +17 -0
- physicskit/semiclassical/visualizers/gutzwiller.py +55 -0
- physicskit/semiclassical/visualizers/path_integral.py +195 -0
- physicskit/semiclassical/visualizers/propagators.py +89 -0
- physicskit/semiclassical/visualizers/scarring.py +146 -0
- physicskit/semiclassical/visualizers/wkb.py +55 -0
- physicskit/statphys/__init__.py +80 -0
- physicskit/statphys/chapters/__init__.py +43 -0
- physicskit/statphys/chapters/ehrenfest_urn.py +112 -0
- physicskit/statphys/chapters/ising_lattice.py +431 -0
- physicskit/statphys/chapters/kpz_growth.py +129 -0
- physicskit/statphys/chapters/molecular_dynamics.py +258 -0
- physicskit/statphys/chapters/nonequilibrium_work.py +146 -0
- physicskit/statphys/chapters/percolation.py +305 -0
- physicskit/statphys/chapters/random_walk.py +142 -0
- physicskit/statphys/chapters/renormalization.py +148 -0
- physicskit/statphys/chapters/sandpile.py +109 -0
- physicskit/statphys/chapters/spin_glass.py +275 -0
- physicskit/statphys/core/__init__.py +10 -0
- physicskit/statphys/core/kpz_engine.py +53 -0
- physicskit/statphys/core/md_engine.py +157 -0
- physicskit/statphys/core/monte_carlo.py +462 -0
- physicskit/statphys/core/random_walk_engine.py +68 -0
- physicskit/statphys/core/sandpile_engine.py +52 -0
- physicskit/statphys/tests/__init__.py +0 -0
- physicskit/statphys/tests/test_dynamics.py +66 -0
- physicskit/statphys/tests/test_ehrenfest_urn.py +44 -0
- physicskit/statphys/tests/test_finite_size_scaling.py +62 -0
- physicskit/statphys/tests/test_interactive.py +33 -0
- physicskit/statphys/tests/test_ising.py +68 -0
- physicskit/statphys/tests/test_kpz.py +55 -0
- physicskit/statphys/tests/test_landau_theory.py +49 -0
- physicskit/statphys/tests/test_md_engine.py +31 -0
- physicskit/statphys/tests/test_molecular_dynamics.py +72 -0
- physicskit/statphys/tests/test_nonequilibrium_work.py +33 -0
- physicskit/statphys/tests/test_partition_function.py +26 -0
- physicskit/statphys/tests/test_percolation.py +116 -0
- physicskit/statphys/tests/test_potts_model.py +46 -0
- physicskit/statphys/tests/test_random_walk.py +50 -0
- physicskit/statphys/tests/test_renormalization.py +44 -0
- physicskit/statphys/tests/test_sandpile.py +44 -0
- physicskit/statphys/tests/test_spin_glass.py +73 -0
- physicskit/statphys/tests/test_thermodynamics.py +121 -0
- physicskit/statphys/tests/test_xy_model.py +45 -0
- physicskit/statphys/utils/__init__.py +1 -0
- physicskit/statphys/utils/dynamics.py +100 -0
- physicskit/statphys/utils/finite_size_scaling.py +171 -0
- physicskit/statphys/utils/landau_theory.py +151 -0
- physicskit/statphys/utils/partition_function.py +109 -0
- physicskit/statphys/utils/thermodynamics.py +356 -0
- physicskit/statphys/visualizers/__init__.py +87 -0
- physicskit/statphys/visualizers/interactive.py +161 -0
- physicskit/statphys/visualizers/jarzynski_render.py +44 -0
- physicskit/statphys/visualizers/kpz_render.py +65 -0
- physicskit/statphys/visualizers/lattice_render.py +212 -0
- physicskit/statphys/visualizers/particle_render.py +121 -0
- physicskit/statphys/visualizers/random_walk_render.py +106 -0
- physicskit/statphys/visualizers/rg_render.py +45 -0
- physicskit/statphys/visualizers/sandpile_render.py +65 -0
- physicskit/statphys/visualizers/spin_glass_render.py +40 -0
- physicskit/statphys/visualizers/urn_render.py +38 -0
- physicskit/statphys/visualizers/vortex_render.py +84 -0
- physicskit/tests/__init__.py +0 -0
- physicskit/tests/test_constants.py +38 -0
- physicskit-0.1.0.dist-info/METADATA +196 -0
- physicskit-0.1.0.dist-info/RECORD +484 -0
- physicskit-0.1.0.dist-info/WHEEL +5 -0
- physicskit-0.1.0.dist-info/licenses/LICENSE +21 -0
- physicskit-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,628 @@
|
|
|
1
|
+
"""Plotting helpers: N-body trajectories, Lane-Emden profiles, and rotation curves.
|
|
2
|
+
|
|
3
|
+
Matplotlib is used throughout. Every function returns its figure object
|
|
4
|
+
rather than calling ``show()``, so it composes cleanly into larger
|
|
5
|
+
figures or headless pipelines.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import matplotlib.colors as mcolors
|
|
11
|
+
import matplotlib.pyplot as plt
|
|
12
|
+
import numpy as np
|
|
13
|
+
from matplotlib.animation import FuncAnimation
|
|
14
|
+
from matplotlib.collections import LineCollection
|
|
15
|
+
|
|
16
|
+
from .cosmic_web import zeldovich_position
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"plot_nbody_trajectories",
|
|
20
|
+
"plot_lane_emden",
|
|
21
|
+
"plot_rotation_curve",
|
|
22
|
+
"animate_nbody_trajectories",
|
|
23
|
+
"animate_zeldovich_collapse",
|
|
24
|
+
"plot_zeldovich_snapshot",
|
|
25
|
+
"animate_stellar_convection",
|
|
26
|
+
"animate_dynamo_wave",
|
|
27
|
+
"plot_dynamo_butterfly_diagram",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def plot_nbody_trajectories(history, ax=None):
|
|
32
|
+
"""Plot the (x, y) trajectories of every body in an N-body simulation.
|
|
33
|
+
|
|
34
|
+
Parameters
|
|
35
|
+
----------
|
|
36
|
+
history : ndarray of shape (n_steps + 1, N, 3)
|
|
37
|
+
Position history, e.g. from
|
|
38
|
+
:meth:`physicskit.astro.nbody.NBodySystem.simulate`.
|
|
39
|
+
ax : matplotlib.axes.Axes, optional
|
|
40
|
+
Axes to draw into; a new figure is created if omitted.
|
|
41
|
+
|
|
42
|
+
Returns
|
|
43
|
+
-------
|
|
44
|
+
fig : matplotlib.figure.Figure
|
|
45
|
+
ax : matplotlib.axes.Axes
|
|
46
|
+
|
|
47
|
+
Examples
|
|
48
|
+
--------
|
|
49
|
+
>>> import numpy as np
|
|
50
|
+
>>> from physicskit.astro.nbody import NBodySystem
|
|
51
|
+
>>> pos = np.array([[1.0, 0.0, 0.0], [-1.0, 0.0, 0.0]])
|
|
52
|
+
>>> vel = np.array([[0.0, 0.5, 0.0], [0.0, -0.5, 0.0]])
|
|
53
|
+
>>> system = NBodySystem(pos, vel, np.array([1.0, 1.0]))
|
|
54
|
+
>>> history = system.simulate(dt=0.01, n_steps=50)
|
|
55
|
+
>>> fig, ax = plot_nbody_trajectories(history)
|
|
56
|
+
>>> isinstance(fig, plt.Figure)
|
|
57
|
+
True
|
|
58
|
+
"""
|
|
59
|
+
if ax is None:
|
|
60
|
+
fig, ax = plt.subplots()
|
|
61
|
+
else:
|
|
62
|
+
fig = ax.figure
|
|
63
|
+
n_bodies = history.shape[1]
|
|
64
|
+
for b in range(n_bodies):
|
|
65
|
+
ax.plot(history[:, b, 0], history[:, b, 1], label=f"body {b + 1}")
|
|
66
|
+
ax.set_xlabel("x")
|
|
67
|
+
ax.set_ylabel("y")
|
|
68
|
+
ax.set_aspect("equal", adjustable="datalim")
|
|
69
|
+
ax.legend()
|
|
70
|
+
return fig, ax
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def plot_lane_emden(xi, theta, ax=None):
|
|
74
|
+
r"""Plot the Lane-Emden function :math:`\theta(\xi)`.
|
|
75
|
+
|
|
76
|
+
Parameters
|
|
77
|
+
----------
|
|
78
|
+
xi, theta : ndarray
|
|
79
|
+
From :func:`physicskit.astro.stellar_structure.lane_emden`.
|
|
80
|
+
ax : matplotlib.axes.Axes, optional
|
|
81
|
+
Axes to draw into; a new figure is created if omitted.
|
|
82
|
+
|
|
83
|
+
Returns
|
|
84
|
+
-------
|
|
85
|
+
fig : matplotlib.figure.Figure
|
|
86
|
+
ax : matplotlib.axes.Axes
|
|
87
|
+
|
|
88
|
+
Examples
|
|
89
|
+
--------
|
|
90
|
+
>>> from physicskit.astro.stellar_structure import lane_emden
|
|
91
|
+
>>> xi, theta = lane_emden(1.5)
|
|
92
|
+
>>> fig, ax = plot_lane_emden(xi, theta)
|
|
93
|
+
>>> isinstance(fig, plt.Figure)
|
|
94
|
+
True
|
|
95
|
+
"""
|
|
96
|
+
if ax is None:
|
|
97
|
+
fig, ax = plt.subplots()
|
|
98
|
+
else:
|
|
99
|
+
fig = ax.figure
|
|
100
|
+
ax.plot(xi, theta)
|
|
101
|
+
ax.axhline(0.0, color="k", linewidth=0.5)
|
|
102
|
+
ax.scatter([xi[-1]], [theta[-1]], color="C1", zorder=3, label="surface")
|
|
103
|
+
ax.set_xlabel(r"$\xi$")
|
|
104
|
+
ax.set_ylabel(r"$\theta(\xi)$")
|
|
105
|
+
ax.legend()
|
|
106
|
+
return fig, ax
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def plot_rotation_curve(r, v_model, ax=None, v_observed=None):
|
|
110
|
+
"""Plot a galactic rotation curve, optionally overlaid with observed data.
|
|
111
|
+
|
|
112
|
+
Parameters
|
|
113
|
+
----------
|
|
114
|
+
r : ndarray
|
|
115
|
+
Radii.
|
|
116
|
+
v_model : ndarray
|
|
117
|
+
Model circular velocity, e.g. from
|
|
118
|
+
:func:`physicskit.astro.galactic_dynamics.circular_velocity`.
|
|
119
|
+
ax : matplotlib.axes.Axes, optional
|
|
120
|
+
Axes to draw into; a new figure is created if omitted.
|
|
121
|
+
v_observed : ndarray, optional
|
|
122
|
+
Observed velocities to overlay as points.
|
|
123
|
+
|
|
124
|
+
Returns
|
|
125
|
+
-------
|
|
126
|
+
fig : matplotlib.figure.Figure
|
|
127
|
+
ax : matplotlib.axes.Axes
|
|
128
|
+
|
|
129
|
+
Examples
|
|
130
|
+
--------
|
|
131
|
+
>>> import numpy as np
|
|
132
|
+
>>> r = np.linspace(1, 20, 30)
|
|
133
|
+
>>> v = np.sqrt(1.0 / r)
|
|
134
|
+
>>> fig, ax = plot_rotation_curve(r, v)
|
|
135
|
+
>>> isinstance(fig, plt.Figure)
|
|
136
|
+
True
|
|
137
|
+
"""
|
|
138
|
+
if ax is None:
|
|
139
|
+
fig, ax = plt.subplots()
|
|
140
|
+
else:
|
|
141
|
+
fig = ax.figure
|
|
142
|
+
ax.plot(r, v_model, label="model")
|
|
143
|
+
if v_observed is not None:
|
|
144
|
+
ax.scatter(r, v_observed, color="C1", s=15, label="observed")
|
|
145
|
+
ax.set_xlabel("r")
|
|
146
|
+
ax.set_ylabel(r"$v_c(r)$")
|
|
147
|
+
ax.legend()
|
|
148
|
+
return fig, ax
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def animate_nbody_trajectories(history, interval: int = 30, trail: int = 200, skip: int = 1, colors=None, title: str | None = None):
|
|
152
|
+
"""Animate an N-body simulation's real-space trajectories being traced out.
|
|
153
|
+
|
|
154
|
+
Draws each body's ``(x, y)`` path (the ``z`` component, if any, is
|
|
155
|
+
ignored) with a fading trail -- older trail segments are more
|
|
156
|
+
transparent -- and a bright marker at the body's current position, in
|
|
157
|
+
a distinct color per body.
|
|
158
|
+
|
|
159
|
+
Parameters
|
|
160
|
+
----------
|
|
161
|
+
history : ndarray of shape (n_steps + 1, N, 3)
|
|
162
|
+
Position history, e.g. from :meth:`physicskit.astro.nbody.NBodySystem.simulate`.
|
|
163
|
+
interval : int, default 30
|
|
164
|
+
Delay between animation frames, in milliseconds.
|
|
165
|
+
trail : int, default 200
|
|
166
|
+
Number of most-recent steps kept visible as each body's trail.
|
|
167
|
+
skip : int, default 1
|
|
168
|
+
Number of simulation steps advanced per animation frame; increase
|
|
169
|
+
for long simulations so the animation covers them in a reasonable
|
|
170
|
+
number of frames.
|
|
171
|
+
colors : list, optional
|
|
172
|
+
Per-body colors; a `tab10` sweep is used if omitted.
|
|
173
|
+
title : str, optional
|
|
174
|
+
Axes title.
|
|
175
|
+
|
|
176
|
+
Returns
|
|
177
|
+
-------
|
|
178
|
+
matplotlib.animation.FuncAnimation
|
|
179
|
+
Assign it to a variable to keep it alive, and display it with
|
|
180
|
+
``plt.show()`` or save it with ``anim.save(...)``.
|
|
181
|
+
|
|
182
|
+
Examples
|
|
183
|
+
--------
|
|
184
|
+
>>> from physicskit.astro.nbody import NBodySystem, figure_eight_initial_conditions
|
|
185
|
+
>>> pos, vel, masses = figure_eight_initial_conditions()
|
|
186
|
+
>>> system = NBodySystem(pos, vel, masses)
|
|
187
|
+
>>> history = system.simulate(dt=0.002, n_steps=200)
|
|
188
|
+
>>> anim = animate_nbody_trajectories(history)
|
|
189
|
+
>>> anim.__class__.__name__
|
|
190
|
+
'FuncAnimation'
|
|
191
|
+
"""
|
|
192
|
+
history = np.asarray(history, dtype=np.float64)
|
|
193
|
+
n_steps_plus1, n_bodies, _ = history.shape
|
|
194
|
+
xy = history[:, :, :2]
|
|
195
|
+
|
|
196
|
+
if colors is None:
|
|
197
|
+
cmap = plt.get_cmap("tab10")
|
|
198
|
+
colors = [cmap(i) for i in range(n_bodies)]
|
|
199
|
+
base_rgba = [np.array(mcolors.to_rgba(c)) for c in colors]
|
|
200
|
+
|
|
201
|
+
fig, ax = plt.subplots(figsize=(6.5, 6.5))
|
|
202
|
+
pad = 0.1 * (np.abs(xy).max() + 1e-12)
|
|
203
|
+
ax.set_xlim(xy[..., 0].min() - pad, xy[..., 0].max() + pad)
|
|
204
|
+
ax.set_ylim(xy[..., 1].min() - pad, xy[..., 1].max() + pad)
|
|
205
|
+
ax.set_aspect("equal")
|
|
206
|
+
if title:
|
|
207
|
+
ax.set_title(title)
|
|
208
|
+
|
|
209
|
+
trail_collections = []
|
|
210
|
+
markers = []
|
|
211
|
+
for b in range(n_bodies):
|
|
212
|
+
lc = LineCollection([], colors=[base_rgba[b]], linewidths=1.5)
|
|
213
|
+
ax.add_collection(lc)
|
|
214
|
+
trail_collections.append(lc)
|
|
215
|
+
(marker,) = ax.plot([], [], "o", color=colors[b], markersize=8, label=f"body {b + 1}")
|
|
216
|
+
markers.append(marker)
|
|
217
|
+
ax.legend(loc="upper right", fontsize=8)
|
|
218
|
+
|
|
219
|
+
frame_ends = np.arange(skip, n_steps_plus1 + skip, skip)
|
|
220
|
+
frame_ends[-1] = n_steps_plus1
|
|
221
|
+
|
|
222
|
+
def update(frame: int):
|
|
223
|
+
end = int(frame_ends[frame])
|
|
224
|
+
lo = max(0, end - trail)
|
|
225
|
+
artists = []
|
|
226
|
+
for b in range(n_bodies):
|
|
227
|
+
pts = xy[lo:end, b, :]
|
|
228
|
+
if pts.shape[0] >= 2:
|
|
229
|
+
segments = np.stack([pts[:-1], pts[1:]], axis=1)
|
|
230
|
+
n_seg = segments.shape[0]
|
|
231
|
+
seg_colors = np.tile(base_rgba[b], (n_seg, 1))
|
|
232
|
+
seg_colors[:, 3] = np.linspace(0.05, 1.0, n_seg)
|
|
233
|
+
trail_collections[b].set_segments(segments)
|
|
234
|
+
trail_collections[b].set_color(seg_colors)
|
|
235
|
+
else:
|
|
236
|
+
trail_collections[b].set_segments([])
|
|
237
|
+
markers[b].set_data([xy[end - 1, b, 0]], [xy[end - 1, b, 1]])
|
|
238
|
+
artists += [trail_collections[b], markers[b]]
|
|
239
|
+
return artists
|
|
240
|
+
|
|
241
|
+
anim = FuncAnimation(fig, update, frames=len(frame_ends), interval=interval, blit=False)
|
|
242
|
+
return anim
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def _local_density_on_grid(xy, x_edges, y_edges):
|
|
246
|
+
"""Local point-density proxy: the 2D-histogram bin count each point of
|
|
247
|
+
``xy`` falls into, evaluated against a shared, precomputed set of bin
|
|
248
|
+
edges so densities are comparable across an animation's frames.
|
|
249
|
+
|
|
250
|
+
Chosen over a KD-tree nearest-neighbor density estimate (e.g.
|
|
251
|
+
``scipy.spatial.cKDTree``, used elsewhere in this codebase) for
|
|
252
|
+
:func:`animate_zeldovich_collapse` and :func:`plot_zeldovich_snapshot`
|
|
253
|
+
because it needs no tree queries, no per-particle neighbor-count
|
|
254
|
+
hyperparameter, and directly reflects the same coarse-grained
|
|
255
|
+
overdensity -- particles piling up into the same small region of space
|
|
256
|
+
-- that the eye picks out in the scatter plot as filaments and nodes.
|
|
257
|
+
"""
|
|
258
|
+
counts, _, _ = np.histogram2d(xy[:, 0], xy[:, 1], bins=[x_edges, y_edges])
|
|
259
|
+
n_bins_x = len(x_edges) - 1
|
|
260
|
+
n_bins_y = len(y_edges) - 1
|
|
261
|
+
ix = np.clip(np.digitize(xy[:, 0], x_edges) - 1, 0, n_bins_x - 1)
|
|
262
|
+
iy = np.clip(np.digitize(xy[:, 1], y_edges) - 1, 0, n_bins_y - 1)
|
|
263
|
+
return counts[ix, iy]
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def animate_zeldovich_collapse(q, D_values, k_vectors, amplitudes, phases, interval=80, s=2):
|
|
267
|
+
r"""Animate the Zel'dovich approximation's collapse of a Lagrangian grid into the cosmic web.
|
|
268
|
+
|
|
269
|
+
Shows a scatter plot of :func:`physicskit.astro.cosmic_web.zeldovich_position`
|
|
270
|
+
evaluated at each growth factor in ``D_values``, frame by frame -- the
|
|
271
|
+
initially regular grid of tracer particles progressively streaming
|
|
272
|
+
together into filaments, sheets ("pancakes"), and dense nodes at
|
|
273
|
+
filament intersections. Points are colored by a local point-density
|
|
274
|
+
proxy (see :func:`_local_density_on_grid`): a fixed 2D histogram of the
|
|
275
|
+
particle positions, shared across all frames, so density colors are
|
|
276
|
+
directly comparable as structure grows in from D_values[0] to
|
|
277
|
+
D_values[-1].
|
|
278
|
+
|
|
279
|
+
Parameters
|
|
280
|
+
----------
|
|
281
|
+
q : ndarray, shape (n_particles, 2)
|
|
282
|
+
Lagrangian tracer positions, e.g. from
|
|
283
|
+
:func:`physicskit.astro.cosmic_web.lagrangian_grid`.
|
|
284
|
+
D_values : array_like
|
|
285
|
+
Growth-factor values to animate through, one frame each.
|
|
286
|
+
k_vectors : ndarray, shape (n_modes, 2)
|
|
287
|
+
amplitudes : ndarray, shape (n_modes,)
|
|
288
|
+
phases : ndarray, shape (n_modes,)
|
|
289
|
+
Displacement-potential parameters, e.g. from
|
|
290
|
+
:func:`physicskit.astro.cosmic_web.random_displacement_potential`.
|
|
291
|
+
interval : int, default=80
|
|
292
|
+
Delay between animation frames, in milliseconds.
|
|
293
|
+
s : float, default=2
|
|
294
|
+
Marker size.
|
|
295
|
+
|
|
296
|
+
Returns
|
|
297
|
+
-------
|
|
298
|
+
matplotlib.animation.FuncAnimation
|
|
299
|
+
Assign it to a variable to keep it alive, and display it with
|
|
300
|
+
``plt.show()`` or save it with ``anim.save(...)``.
|
|
301
|
+
|
|
302
|
+
See Also
|
|
303
|
+
--------
|
|
304
|
+
plot_zeldovich_snapshot : The single-frame, non-animated companion.
|
|
305
|
+
|
|
306
|
+
Examples
|
|
307
|
+
--------
|
|
308
|
+
>>> import numpy as np
|
|
309
|
+
>>> from physicskit.astro.cosmic_web import lagrangian_grid, random_displacement_potential, first_caustic_time
|
|
310
|
+
>>> q = lagrangian_grid(20, 1.0)
|
|
311
|
+
>>> k_vectors, amplitudes, phases = random_displacement_potential(6, k_min=2 * np.pi, k_max=6 * np.pi, amplitude_scale=0.02, seed=0)
|
|
312
|
+
>>> D_collapse = first_caustic_time(q, k_vectors, amplitudes, phases)
|
|
313
|
+
>>> D_values = np.linspace(0.0, 1.2 * D_collapse, 10)
|
|
314
|
+
>>> anim = animate_zeldovich_collapse(q, D_values, k_vectors, amplitudes, phases)
|
|
315
|
+
>>> anim.__class__.__name__
|
|
316
|
+
'FuncAnimation'
|
|
317
|
+
"""
|
|
318
|
+
q = np.atleast_2d(np.asarray(q, dtype=float))
|
|
319
|
+
D_values = np.asarray(D_values, dtype=float)
|
|
320
|
+
n_frames = D_values.shape[0]
|
|
321
|
+
n_particles = q.shape[0]
|
|
322
|
+
|
|
323
|
+
positions = np.empty((n_frames, n_particles, 2))
|
|
324
|
+
for i, D in enumerate(D_values):
|
|
325
|
+
positions[i] = zeldovich_position(q, D, k_vectors, amplitudes, phases)
|
|
326
|
+
|
|
327
|
+
x_min, x_max = positions[..., 0].min(), positions[..., 0].max()
|
|
328
|
+
y_min, y_max = positions[..., 1].min(), positions[..., 1].max()
|
|
329
|
+
pad_x = 0.03 * (x_max - x_min + 1e-12)
|
|
330
|
+
pad_y = 0.03 * (y_max - y_min + 1e-12)
|
|
331
|
+
x_min, x_max = x_min - pad_x, x_max + pad_x
|
|
332
|
+
y_min, y_max = y_min - pad_y, y_max + pad_y
|
|
333
|
+
|
|
334
|
+
n_bins = max(20, int(np.sqrt(n_particles)))
|
|
335
|
+
x_edges = np.linspace(x_min, x_max, n_bins + 1)
|
|
336
|
+
y_edges = np.linspace(y_min, y_max, n_bins + 1)
|
|
337
|
+
|
|
338
|
+
log_density = np.empty((n_frames, n_particles))
|
|
339
|
+
for i in range(n_frames):
|
|
340
|
+
log_density[i] = np.log10(_local_density_on_grid(positions[i], x_edges, y_edges) + 1.0)
|
|
341
|
+
vmax = max(float(log_density.max()), 1e-12)
|
|
342
|
+
|
|
343
|
+
fig, ax = plt.subplots(figsize=(6.5, 6.5))
|
|
344
|
+
ax.set_xlim(x_min, x_max)
|
|
345
|
+
ax.set_ylim(y_min, y_max)
|
|
346
|
+
ax.set_aspect("equal")
|
|
347
|
+
ax.set_xlabel("x")
|
|
348
|
+
ax.set_ylabel("y")
|
|
349
|
+
|
|
350
|
+
scatter = ax.scatter(positions[0, :, 0], positions[0, :, 1], c=log_density[0], cmap="inferno", s=s, vmin=0.0, vmax=vmax)
|
|
351
|
+
title = ax.set_title(f"D = {D_values[0]:.4f}")
|
|
352
|
+
fig.colorbar(scatter, ax=ax, label=r"local density (log$_{10}$ scale)")
|
|
353
|
+
|
|
354
|
+
def update(frame):
|
|
355
|
+
scatter.set_offsets(positions[frame])
|
|
356
|
+
scatter.set_array(log_density[frame])
|
|
357
|
+
title.set_text(f"D = {D_values[frame]:.4f}")
|
|
358
|
+
return scatter, title
|
|
359
|
+
|
|
360
|
+
anim = FuncAnimation(fig, update, frames=n_frames, interval=interval, blit=False)
|
|
361
|
+
return anim
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
def plot_zeldovich_snapshot(q, D, k_vectors, amplitudes, phases, ax=None, s=2):
|
|
365
|
+
r"""A single static snapshot of the Zel'dovich-evolved particle field at one growth factor.
|
|
366
|
+
|
|
367
|
+
The non-animated companion to :func:`animate_zeldovich_collapse`,
|
|
368
|
+
using the same 2D-histogram local-density coloring.
|
|
369
|
+
|
|
370
|
+
Parameters
|
|
371
|
+
----------
|
|
372
|
+
q : ndarray, shape (n_particles, 2)
|
|
373
|
+
Lagrangian tracer positions, e.g. from
|
|
374
|
+
:func:`physicskit.astro.cosmic_web.lagrangian_grid`.
|
|
375
|
+
D : float
|
|
376
|
+
Growth factor at which to evaluate the Zel'dovich mapping.
|
|
377
|
+
k_vectors : ndarray, shape (n_modes, 2)
|
|
378
|
+
amplitudes : ndarray, shape (n_modes,)
|
|
379
|
+
phases : ndarray, shape (n_modes,)
|
|
380
|
+
Displacement-potential parameters, e.g. from
|
|
381
|
+
:func:`physicskit.astro.cosmic_web.random_displacement_potential`.
|
|
382
|
+
ax : matplotlib.axes.Axes, optional
|
|
383
|
+
Axes to draw into; a new figure is created if omitted.
|
|
384
|
+
s : float, default=2
|
|
385
|
+
Marker size.
|
|
386
|
+
|
|
387
|
+
Returns
|
|
388
|
+
-------
|
|
389
|
+
fig : matplotlib.figure.Figure
|
|
390
|
+
ax : matplotlib.axes.Axes
|
|
391
|
+
|
|
392
|
+
See Also
|
|
393
|
+
--------
|
|
394
|
+
animate_zeldovich_collapse : The animated version of this snapshot.
|
|
395
|
+
|
|
396
|
+
Examples
|
|
397
|
+
--------
|
|
398
|
+
>>> import numpy as np
|
|
399
|
+
>>> from physicskit.astro.cosmic_web import lagrangian_grid, random_displacement_potential, first_caustic_time
|
|
400
|
+
>>> q = lagrangian_grid(20, 1.0)
|
|
401
|
+
>>> k_vectors, amplitudes, phases = random_displacement_potential(6, k_min=2 * np.pi, k_max=6 * np.pi, amplitude_scale=0.02, seed=0)
|
|
402
|
+
>>> D_collapse = first_caustic_time(q, k_vectors, amplitudes, phases)
|
|
403
|
+
>>> fig, ax = plot_zeldovich_snapshot(q, D_collapse, k_vectors, amplitudes, phases)
|
|
404
|
+
>>> isinstance(fig, plt.Figure)
|
|
405
|
+
True
|
|
406
|
+
"""
|
|
407
|
+
q = np.atleast_2d(np.asarray(q, dtype=float))
|
|
408
|
+
x = zeldovich_position(q, D, k_vectors, amplitudes, phases)
|
|
409
|
+
n_particles = x.shape[0]
|
|
410
|
+
|
|
411
|
+
x_min, x_max = x[:, 0].min(), x[:, 0].max()
|
|
412
|
+
y_min, y_max = x[:, 1].min(), x[:, 1].max()
|
|
413
|
+
pad_x = 0.03 * (x_max - x_min + 1e-12)
|
|
414
|
+
pad_y = 0.03 * (y_max - y_min + 1e-12)
|
|
415
|
+
x_edges = np.linspace(x_min - pad_x, x_max + pad_x, max(20, int(np.sqrt(n_particles))) + 1)
|
|
416
|
+
y_edges = np.linspace(y_min - pad_y, y_max + pad_y, max(20, int(np.sqrt(n_particles))) + 1)
|
|
417
|
+
|
|
418
|
+
log_density = np.log10(_local_density_on_grid(x, x_edges, y_edges) + 1.0)
|
|
419
|
+
|
|
420
|
+
if ax is None:
|
|
421
|
+
fig, ax = plt.subplots(figsize=(6.5, 6.5))
|
|
422
|
+
else:
|
|
423
|
+
fig = ax.figure
|
|
424
|
+
scatter = ax.scatter(x[:, 0], x[:, 1], c=log_density, cmap="inferno", s=s)
|
|
425
|
+
fig.colorbar(scatter, ax=ax, label=r"local density (log$_{10}$ scale)")
|
|
426
|
+
ax.set_xlabel("x")
|
|
427
|
+
ax.set_ylabel("y")
|
|
428
|
+
ax.set_aspect("equal", adjustable="datalim")
|
|
429
|
+
ax.set_title(f"D = {D:.4f}")
|
|
430
|
+
return fig, ax
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
def animate_stellar_convection(times, omega_snapshots, T_snapshots, interval=80):
|
|
434
|
+
"""Animate 2D convective rolls: vorticity and temperature side by side.
|
|
435
|
+
|
|
436
|
+
Two panels sharing a time axis -- vorticity on the left, temperature
|
|
437
|
+
perturbation on the right -- each redrawn frame by frame from
|
|
438
|
+
:func:`physicskit.astro.stellar_dynamo.simulate_stellar_convection`'s
|
|
439
|
+
output, showing the small initial noise roll up into churning
|
|
440
|
+
convective plumes.
|
|
441
|
+
|
|
442
|
+
Parameters
|
|
443
|
+
----------
|
|
444
|
+
times : ndarray, shape (n_saved,)
|
|
445
|
+
omega_snapshots : ndarray, shape (n_saved, ny, nx)
|
|
446
|
+
Vorticity field snapshots.
|
|
447
|
+
T_snapshots : ndarray, shape (n_saved, ny, nx)
|
|
448
|
+
Temperature-perturbation field snapshots.
|
|
449
|
+
interval : int, default=80
|
|
450
|
+
Delay between animation frames, in milliseconds.
|
|
451
|
+
|
|
452
|
+
Returns
|
|
453
|
+
-------
|
|
454
|
+
matplotlib.animation.FuncAnimation
|
|
455
|
+
Assign it to a variable to keep it alive, and display it with
|
|
456
|
+
``plt.show()`` or save it with ``anim.save(...)``.
|
|
457
|
+
|
|
458
|
+
Examples
|
|
459
|
+
--------
|
|
460
|
+
>>> import numpy as np
|
|
461
|
+
>>> from physicskit.astro.stellar_dynamo import simulate_stellar_convection
|
|
462
|
+
>>> times, omega_snaps, T_snaps = simulate_stellar_convection(
|
|
463
|
+
... 24, 24, 2 * np.pi, 2 * np.pi, n_steps=20, save_every=10, seed=0)
|
|
464
|
+
>>> anim = animate_stellar_convection(times, omega_snaps, T_snaps)
|
|
465
|
+
>>> anim.__class__.__name__
|
|
466
|
+
'FuncAnimation'
|
|
467
|
+
"""
|
|
468
|
+
omega_snapshots = np.asarray(omega_snapshots, dtype=np.float64)
|
|
469
|
+
T_snapshots = np.asarray(T_snapshots, dtype=np.float64)
|
|
470
|
+
times = np.asarray(times, dtype=np.float64)
|
|
471
|
+
|
|
472
|
+
omega_max = np.abs(omega_snapshots).max() + 1e-12
|
|
473
|
+
T_max = np.abs(T_snapshots).max() + 1e-12
|
|
474
|
+
|
|
475
|
+
fig, (ax_omega, ax_T) = plt.subplots(1, 2, figsize=(11, 5))
|
|
476
|
+
im_omega = ax_omega.imshow(omega_snapshots[0], origin="lower", cmap="RdBu_r", vmin=-omega_max, vmax=omega_max, aspect="auto")
|
|
477
|
+
im_T = ax_T.imshow(T_snapshots[0], origin="lower", cmap="inferno", vmin=-T_max, vmax=T_max, aspect="auto")
|
|
478
|
+
ax_omega.set_title("vorticity $\\omega$")
|
|
479
|
+
ax_T.set_title("temperature perturbation $T'$")
|
|
480
|
+
for ax in (ax_omega, ax_T):
|
|
481
|
+
ax.set_xlabel("x")
|
|
482
|
+
ax.set_ylabel("y")
|
|
483
|
+
fig.colorbar(im_omega, ax=ax_omega, fraction=0.046)
|
|
484
|
+
fig.colorbar(im_T, ax=ax_T, fraction=0.046)
|
|
485
|
+
suptitle = fig.suptitle(f"t = {times[0]:.3f}")
|
|
486
|
+
fig.tight_layout()
|
|
487
|
+
|
|
488
|
+
def update(frame):
|
|
489
|
+
im_omega.set_data(omega_snapshots[frame])
|
|
490
|
+
im_T.set_data(T_snapshots[frame])
|
|
491
|
+
suptitle.set_text(f"t = {times[frame]:.3f}")
|
|
492
|
+
return im_omega, im_T, suptitle
|
|
493
|
+
|
|
494
|
+
anim = FuncAnimation(fig, update, frames=omega_snapshots.shape[0], interval=interval, blit=False)
|
|
495
|
+
return anim
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
def animate_dynamo_wave(times, A_snapshots, B_snapshots, x, interval=80):
|
|
499
|
+
"""Animate the alpha-omega dynamo's poloidal and toroidal fields as traveling, growing waves.
|
|
500
|
+
|
|
501
|
+
Draws :math:`A(x)` and :math:`B(x)` as two line plots sharing an
|
|
502
|
+
axis, redrawn frame by frame from
|
|
503
|
+
:func:`physicskit.astro.stellar_dynamo.simulate_alpha_omega_dynamo`'s
|
|
504
|
+
output. In the unstable/growing regime, both the growing amplitude
|
|
505
|
+
and the lateral migration of the wave pattern across `x` -- the
|
|
506
|
+
dynamo wave whose space-time trace is the solar butterfly diagram --
|
|
507
|
+
are visible as the animation runs; the y-axis is rescaled each frame
|
|
508
|
+
to the current amplitude so the growing wave doesn't run off scale.
|
|
509
|
+
|
|
510
|
+
Parameters
|
|
511
|
+
----------
|
|
512
|
+
times : ndarray, shape (n_saved,)
|
|
513
|
+
A_snapshots, B_snapshots : ndarray, shape (n_saved, nx)
|
|
514
|
+
Poloidal-flux-proxy and toroidal-field snapshots.
|
|
515
|
+
x : ndarray, shape (nx,)
|
|
516
|
+
Spatial grid the snapshots live on.
|
|
517
|
+
interval : int, default=80
|
|
518
|
+
Delay between animation frames, in milliseconds.
|
|
519
|
+
|
|
520
|
+
Returns
|
|
521
|
+
-------
|
|
522
|
+
matplotlib.animation.FuncAnimation
|
|
523
|
+
Assign it to a variable to keep it alive, and display it with
|
|
524
|
+
``plt.show()`` or save it with ``anim.save(...)``.
|
|
525
|
+
|
|
526
|
+
See Also
|
|
527
|
+
--------
|
|
528
|
+
plot_dynamo_butterfly_diagram : The static space-time summary of the same wave.
|
|
529
|
+
|
|
530
|
+
Examples
|
|
531
|
+
--------
|
|
532
|
+
>>> import numpy as np
|
|
533
|
+
>>> from physicskit.astro.stellar_dynamo import simulate_alpha_omega_dynamo
|
|
534
|
+
>>> Lx = 2 * np.pi
|
|
535
|
+
>>> x = np.linspace(0, Lx, 32, endpoint=False)
|
|
536
|
+
>>> A0 = 1e-3 * np.cos(x)
|
|
537
|
+
>>> B0 = np.zeros_like(A0)
|
|
538
|
+
>>> times, A_snaps, B_snaps = simulate_alpha_omega_dynamo(A0, B0, alpha=1.0, shear=5.0, eta=0.05, Lx=Lx, dt=0.01, n_steps=20, save_every=5)
|
|
539
|
+
>>> anim = animate_dynamo_wave(times, A_snaps, B_snaps, x)
|
|
540
|
+
>>> anim.__class__.__name__
|
|
541
|
+
'FuncAnimation'
|
|
542
|
+
"""
|
|
543
|
+
times = np.asarray(times, dtype=np.float64)
|
|
544
|
+
A_snapshots = np.asarray(A_snapshots, dtype=np.float64)
|
|
545
|
+
B_snapshots = np.asarray(B_snapshots, dtype=np.float64)
|
|
546
|
+
x = np.asarray(x, dtype=np.float64)
|
|
547
|
+
|
|
548
|
+
fig, ax = plt.subplots(figsize=(7, 4.5))
|
|
549
|
+
(line_A,) = ax.plot(x, A_snapshots[0], label="$A(x)$ (poloidal-flux proxy)")
|
|
550
|
+
(line_B,) = ax.plot(x, B_snapshots[0], label="$B(x)$ (toroidal field)")
|
|
551
|
+
ax.set_xlabel("x (latitude/radius proxy)")
|
|
552
|
+
ax.set_ylabel("field amplitude")
|
|
553
|
+
ax.set_xlim(x.min(), x.max())
|
|
554
|
+
ax.legend(loc="upper right")
|
|
555
|
+
title = ax.set_title(f"t = {times[0]:.3f}")
|
|
556
|
+
|
|
557
|
+
def update(frame):
|
|
558
|
+
a, b = A_snapshots[frame], B_snapshots[frame]
|
|
559
|
+
line_A.set_ydata(a)
|
|
560
|
+
line_B.set_ydata(b)
|
|
561
|
+
ymax = max(np.abs(a).max(), np.abs(b).max(), 1e-12) * 1.2
|
|
562
|
+
ax.set_ylim(-ymax, ymax)
|
|
563
|
+
title.set_text(f"t = {times[frame]:.3f}")
|
|
564
|
+
return line_A, line_B, title
|
|
565
|
+
|
|
566
|
+
anim = FuncAnimation(fig, update, frames=A_snapshots.shape[0], interval=interval, blit=False)
|
|
567
|
+
return anim
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
def plot_dynamo_butterfly_diagram(times, B_snapshots, x, ax=None):
|
|
571
|
+
"""Static space-time (Hovmoller) plot of the alpha-omega dynamo wave: the "butterfly diagram".
|
|
572
|
+
|
|
573
|
+
Displays :math:`B(x,t)` as an image with time along the x-axis and
|
|
574
|
+
the spatial coordinate `x` (standing in for stellar latitude) along
|
|
575
|
+
the y-axis. In the unstable regime, the migrating dynamo wave shows
|
|
576
|
+
up as diagonal stripes of alternating sign drifting across the
|
|
577
|
+
plot -- the same characteristic pattern, and the same underlying
|
|
578
|
+
alpha-omega mechanism, behind the real Sun's sunspot-latitude
|
|
579
|
+
butterfly diagram.
|
|
580
|
+
|
|
581
|
+
Parameters
|
|
582
|
+
----------
|
|
583
|
+
times : ndarray, shape (n_saved,)
|
|
584
|
+
B_snapshots : ndarray, shape (n_saved, nx)
|
|
585
|
+
Toroidal-field snapshots, e.g. from
|
|
586
|
+
:func:`physicskit.astro.stellar_dynamo.simulate_alpha_omega_dynamo`.
|
|
587
|
+
x : ndarray, shape (nx,)
|
|
588
|
+
Spatial grid the snapshots live on.
|
|
589
|
+
ax : matplotlib.axes.Axes, optional
|
|
590
|
+
Axes to draw into; a new figure is created if omitted.
|
|
591
|
+
|
|
592
|
+
Returns
|
|
593
|
+
-------
|
|
594
|
+
fig : matplotlib.figure.Figure
|
|
595
|
+
ax : matplotlib.axes.Axes
|
|
596
|
+
|
|
597
|
+
See Also
|
|
598
|
+
--------
|
|
599
|
+
animate_dynamo_wave : The animated, time-domain view of the same field.
|
|
600
|
+
|
|
601
|
+
Examples
|
|
602
|
+
--------
|
|
603
|
+
>>> import numpy as np
|
|
604
|
+
>>> from physicskit.astro.stellar_dynamo import simulate_alpha_omega_dynamo
|
|
605
|
+
>>> Lx = 2 * np.pi
|
|
606
|
+
>>> x = np.linspace(0, Lx, 32, endpoint=False)
|
|
607
|
+
>>> A0 = 1e-3 * np.cos(x)
|
|
608
|
+
>>> B0 = np.zeros_like(A0)
|
|
609
|
+
>>> times, A_snaps, B_snaps = simulate_alpha_omega_dynamo(A0, B0, alpha=1.0, shear=5.0, eta=0.05, Lx=Lx, dt=0.01, n_steps=200, save_every=5)
|
|
610
|
+
>>> fig, ax = plot_dynamo_butterfly_diagram(times, B_snaps, x)
|
|
611
|
+
>>> isinstance(fig, plt.Figure)
|
|
612
|
+
True
|
|
613
|
+
"""
|
|
614
|
+
times = np.asarray(times, dtype=np.float64)
|
|
615
|
+
B_snapshots = np.asarray(B_snapshots, dtype=np.float64)
|
|
616
|
+
x = np.asarray(x, dtype=np.float64)
|
|
617
|
+
|
|
618
|
+
if ax is None:
|
|
619
|
+
fig, ax = plt.subplots(figsize=(7, 4.5))
|
|
620
|
+
else:
|
|
621
|
+
fig = ax.figure
|
|
622
|
+
vmax = np.abs(B_snapshots).max() + 1e-12
|
|
623
|
+
mesh = ax.pcolormesh(times, x, B_snapshots.T, cmap="RdBu_r", vmin=-vmax, vmax=vmax, shading="auto")
|
|
624
|
+
fig.colorbar(mesh, ax=ax, label="$B(x, t)$")
|
|
625
|
+
ax.set_xlabel("time")
|
|
626
|
+
ax.set_ylabel("x (latitude/radius proxy)")
|
|
627
|
+
ax.set_title("Dynamo wave butterfly diagram")
|
|
628
|
+
return fig, ax
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""physicskit.chaos: visual analysis and simulation of chaotic dynamical systems and 2D billiards."""
|
|
2
|
+
|
|
3
|
+
from physicskit.chaos.core.base_system import BilliardSystem, DiscreteMap, DynamicalSystem
|
|
4
|
+
from physicskit.chaos.exceptions import ChaoskitError, InvalidParameterError
|
|
5
|
+
from physicskit.chaos.quantum.billiards import QuantumBilliard
|
|
6
|
+
from physicskit.chaos.quantum.maps import QuantumBakersMap, QuantumKickedRotor
|
|
7
|
+
from physicskit.chaos.systems.billiards import (
|
|
8
|
+
BunimovichStadium,
|
|
9
|
+
CircleBilliard,
|
|
10
|
+
EllipseBilliard,
|
|
11
|
+
RectangleBilliard,
|
|
12
|
+
SinaiBilliard,
|
|
13
|
+
TruncatedCircleBilliard,
|
|
14
|
+
)
|
|
15
|
+
from physicskit.chaos.systems.continuous import (
|
|
16
|
+
Chua,
|
|
17
|
+
DoublePendulum,
|
|
18
|
+
Duffing,
|
|
19
|
+
Lorenz,
|
|
20
|
+
MagneticPendulum,
|
|
21
|
+
RestrictedThreeBody,
|
|
22
|
+
Rossler,
|
|
23
|
+
)
|
|
24
|
+
from physicskit.chaos.systems.maps import BakersMap, HenonMap, LogisticMap, StandardMap
|
|
25
|
+
|
|
26
|
+
__version__ = "0.1.0"
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
"BakersMap",
|
|
30
|
+
"BilliardSystem",
|
|
31
|
+
"BunimovichStadium",
|
|
32
|
+
"ChaoskitError",
|
|
33
|
+
"Chua",
|
|
34
|
+
"CircleBilliard",
|
|
35
|
+
"DiscreteMap",
|
|
36
|
+
"DoublePendulum",
|
|
37
|
+
"Duffing",
|
|
38
|
+
"DynamicalSystem",
|
|
39
|
+
"EllipseBilliard",
|
|
40
|
+
"HenonMap",
|
|
41
|
+
"InvalidParameterError",
|
|
42
|
+
"LogisticMap",
|
|
43
|
+
"Lorenz",
|
|
44
|
+
"MagneticPendulum",
|
|
45
|
+
"QuantumBakersMap",
|
|
46
|
+
"QuantumBilliard",
|
|
47
|
+
"QuantumKickedRotor",
|
|
48
|
+
"RectangleBilliard",
|
|
49
|
+
"RestrictedThreeBody",
|
|
50
|
+
"Rossler",
|
|
51
|
+
"SinaiBilliard",
|
|
52
|
+
"StandardMap",
|
|
53
|
+
"TruncatedCircleBilliard",
|
|
54
|
+
"__version__",
|
|
55
|
+
]
|