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,179 @@
|
|
|
1
|
+
r"""Wigner quasi-probability distribution :math:`W(x,p)` and 3D phase-space plots."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
import matplotlib.pyplot as plt
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
__all__ = ["wigner_transform", "WignerVisualizer"]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def wigner_transform(x: np.ndarray, psi: np.ndarray, hbar: float = 1.0, n_p: int = 200, p_max: float | None = None):
|
|
14
|
+
r"""Compute the Wigner quasi-probability distribution.
|
|
15
|
+
|
|
16
|
+
.. math::
|
|
17
|
+
|
|
18
|
+
W(x,p) = \frac{1}{\pi\hbar} \int_{-\infty}^{\infty}
|
|
19
|
+
\psi^*(x+y)\,\psi(x-y)\, e^{2ipy/\hbar}\, dy,
|
|
20
|
+
|
|
21
|
+
on the same x-grid the wavefunction is given on, by direct quadrature
|
|
22
|
+
over the shift :math:`y=k\,dx` (:math:`\psi` is treated as zero outside
|
|
23
|
+
the grid).
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
x : numpy.ndarray
|
|
28
|
+
Positions the wavefunction is sampled on (uniform grid).
|
|
29
|
+
psi : numpy.ndarray
|
|
30
|
+
Complex-valued wavefunction sampled on ``x``.
|
|
31
|
+
hbar : float, default=1.0
|
|
32
|
+
Value of :math:`\hbar` to use.
|
|
33
|
+
n_p : int, default=200
|
|
34
|
+
Number of momentum grid points.
|
|
35
|
+
p_max : float or None, optional
|
|
36
|
+
Half-width of the momentum grid; defaults to the Nyquist limit set
|
|
37
|
+
by the position-grid spacing, :math:`\pi\hbar/(2\,dx)`.
|
|
38
|
+
|
|
39
|
+
Returns
|
|
40
|
+
-------
|
|
41
|
+
x : numpy.ndarray
|
|
42
|
+
The (unchanged) position grid.
|
|
43
|
+
p : numpy.ndarray
|
|
44
|
+
The momentum grid, shape ``(n_p,)``.
|
|
45
|
+
W : numpy.ndarray
|
|
46
|
+
The Wigner function, shape ``(len(x), n_p)``.
|
|
47
|
+
"""
|
|
48
|
+
x = np.asarray(x)
|
|
49
|
+
psi = np.asarray(psi, dtype=complex)
|
|
50
|
+
N = x.shape[0]
|
|
51
|
+
dx = x[1] - x[0]
|
|
52
|
+
if p_max is None:
|
|
53
|
+
# The transform's kernel is e^{2ipy/hbar} with y=k*dx, so the
|
|
54
|
+
# conjugate variable is 2p/hbar; its Nyquist limit pi/dx gives
|
|
55
|
+
# p_max = pi*hbar/(2*dx) (using the full pi*hbar/dx aliases W(x,p)
|
|
56
|
+
# periodically back onto itself well before that point).
|
|
57
|
+
p_max = np.pi * hbar / (2 * dx)
|
|
58
|
+
|
|
59
|
+
p = np.linspace(-p_max, p_max, n_p)
|
|
60
|
+
W = np.zeros((N, n_p))
|
|
61
|
+
|
|
62
|
+
for i in range(N):
|
|
63
|
+
kmax = min(i, N - 1 - i)
|
|
64
|
+
k = np.arange(-kmax, kmax + 1)
|
|
65
|
+
integrand = np.conj(psi[i + k]) * psi[i - k]
|
|
66
|
+
phase = np.exp(2j * np.outer(p, k * dx) / hbar) # (n_p, len(k))
|
|
67
|
+
W[i, :] = (dx / (np.pi * hbar)) * np.real(phase @ integrand)
|
|
68
|
+
|
|
69
|
+
return x, p, W
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@dataclass
|
|
73
|
+
class WignerVisualizer:
|
|
74
|
+
"""Convenience wrapper around :func:`wigner_transform` with plotting helpers.
|
|
75
|
+
|
|
76
|
+
Parameters
|
|
77
|
+
----------
|
|
78
|
+
hbar : float, default=1.0
|
|
79
|
+
Value of :math:`\\hbar` to use.
|
|
80
|
+
n_p : int, default=200
|
|
81
|
+
Number of momentum grid points.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
hbar: float = 1.0
|
|
85
|
+
n_p: int = 200
|
|
86
|
+
|
|
87
|
+
def compute(self, x: np.ndarray, psi: np.ndarray, p_max: float | None = None):
|
|
88
|
+
"""See :func:`wigner_transform`.
|
|
89
|
+
|
|
90
|
+
Parameters
|
|
91
|
+
----------
|
|
92
|
+
x : numpy.ndarray
|
|
93
|
+
psi : numpy.ndarray
|
|
94
|
+
p_max : float or None, optional
|
|
95
|
+
|
|
96
|
+
Returns
|
|
97
|
+
-------
|
|
98
|
+
x, p, W : numpy.ndarray
|
|
99
|
+
"""
|
|
100
|
+
return wigner_transform(x, psi, self.hbar, self.n_p, p_max)
|
|
101
|
+
|
|
102
|
+
def position_marginal(self, p: np.ndarray, W: np.ndarray) -> np.ndarray:
|
|
103
|
+
r"""Integrate :math:`W(x,p)` over :math:`p`.
|
|
104
|
+
|
|
105
|
+
Should recover :math:`\lvert\psi(x)\rvert^2` -- a standard
|
|
106
|
+
correctness check for a Wigner-function implementation.
|
|
107
|
+
|
|
108
|
+
Parameters
|
|
109
|
+
----------
|
|
110
|
+
p : numpy.ndarray
|
|
111
|
+
Momentum grid.
|
|
112
|
+
W : numpy.ndarray
|
|
113
|
+
Wigner function, shape ``(len(x), len(p))``.
|
|
114
|
+
|
|
115
|
+
Returns
|
|
116
|
+
-------
|
|
117
|
+
numpy.ndarray
|
|
118
|
+
"""
|
|
119
|
+
dp = p[1] - p[0]
|
|
120
|
+
return np.sum(W, axis=1) * dp
|
|
121
|
+
|
|
122
|
+
def plot_surface(self, x: np.ndarray, p: np.ndarray, W: np.ndarray, ax=None, cmap: str = "RdBu_r"):
|
|
123
|
+
"""3D surface plot of :math:`W(x,p)`.
|
|
124
|
+
|
|
125
|
+
Uses a diverging colormap so the negative (non-classical
|
|
126
|
+
interference) regions stand out from the positive ones.
|
|
127
|
+
|
|
128
|
+
Parameters
|
|
129
|
+
----------
|
|
130
|
+
x, p : numpy.ndarray
|
|
131
|
+
Position and momentum grids.
|
|
132
|
+
W : numpy.ndarray
|
|
133
|
+
Wigner function, shape ``(len(x), len(p))``.
|
|
134
|
+
ax : matplotlib.axes.Axes or None, optional
|
|
135
|
+
A 3D axis to draw on; a new figure/axis is created if omitted.
|
|
136
|
+
cmap : str, default='RdBu_r'
|
|
137
|
+
Diverging colormap name.
|
|
138
|
+
|
|
139
|
+
Returns
|
|
140
|
+
-------
|
|
141
|
+
matplotlib.axes.Axes
|
|
142
|
+
"""
|
|
143
|
+
if ax is None:
|
|
144
|
+
fig = plt.figure(figsize=(8, 6))
|
|
145
|
+
ax = fig.add_subplot(111, projection="3d")
|
|
146
|
+
X, P = np.meshgrid(x, p, indexing="ij")
|
|
147
|
+
vmax = np.abs(W).max()
|
|
148
|
+
ax.plot_surface(X, P, W, cmap=cmap, vmin=-vmax, vmax=vmax, linewidth=0, antialiased=True)
|
|
149
|
+
ax.set_xlabel("x")
|
|
150
|
+
ax.set_ylabel("p")
|
|
151
|
+
ax.set_zlabel("W(x,p)")
|
|
152
|
+
return ax
|
|
153
|
+
|
|
154
|
+
def plot_contour(self, x: np.ndarray, p: np.ndarray, W: np.ndarray, ax=None, cmap: str = "RdBu_r"):
|
|
155
|
+
"""2D filled-contour plot of :math:`W(x,p)`.
|
|
156
|
+
|
|
157
|
+
Parameters
|
|
158
|
+
----------
|
|
159
|
+
x, p : numpy.ndarray
|
|
160
|
+
Position and momentum grids.
|
|
161
|
+
W : numpy.ndarray
|
|
162
|
+
Wigner function, shape ``(len(x), len(p))``.
|
|
163
|
+
ax : matplotlib.axes.Axes or None, optional
|
|
164
|
+
Axis to draw on; a new figure/axis is created if omitted.
|
|
165
|
+
cmap : str, default='RdBu_r'
|
|
166
|
+
Diverging colormap name.
|
|
167
|
+
|
|
168
|
+
Returns
|
|
169
|
+
-------
|
|
170
|
+
matplotlib.axes.Axes
|
|
171
|
+
"""
|
|
172
|
+
if ax is None:
|
|
173
|
+
_, ax = plt.subplots(figsize=(6, 5))
|
|
174
|
+
vmax = np.abs(W).max()
|
|
175
|
+
cs = ax.contourf(x, p, W.T, levels=60, cmap=cmap, vmin=-vmax, vmax=vmax)
|
|
176
|
+
ax.set_xlabel("x")
|
|
177
|
+
ax.set_ylabel("p")
|
|
178
|
+
plt.colorbar(cs, ax=ax, label="W(x,p)")
|
|
179
|
+
return ax
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
r"""Phase-colored HSV complex wavefunction plots and density animations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
import matplotlib.colors as mcolors
|
|
8
|
+
import matplotlib.pyplot as plt
|
|
9
|
+
import numpy as np
|
|
10
|
+
from matplotlib.animation import FuncAnimation
|
|
11
|
+
|
|
12
|
+
__all__ = ["complex_to_rgb", "plot_complex_wavefunction", "animate_density", "animate_density_2d"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def complex_to_rgb(psi: np.ndarray, max_abs: Optional[float] = None) -> np.ndarray:
|
|
16
|
+
r"""Map a complex array to RGB: hue = phase, value = amplitude.
|
|
17
|
+
|
|
18
|
+
.. math::
|
|
19
|
+
|
|
20
|
+
\text{hue} = \frac{\arg\psi + \pi}{2\pi}, \qquad
|
|
21
|
+
\text{value} = \min\!\left(\frac{\lvert\psi\rvert}{\max\lvert\psi\rvert}, 1\right).
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
psi : numpy.ndarray
|
|
26
|
+
Complex-valued array.
|
|
27
|
+
max_abs : float or None, optional
|
|
28
|
+
Amplitude that maps to full brightness; defaults to ``abs(psi).max()``.
|
|
29
|
+
|
|
30
|
+
Returns
|
|
31
|
+
-------
|
|
32
|
+
numpy.ndarray
|
|
33
|
+
RGB array of shape ``(..., 3)``, suitable for ``imshow``/plotting.
|
|
34
|
+
"""
|
|
35
|
+
amp = np.abs(psi)
|
|
36
|
+
phase = np.angle(psi)
|
|
37
|
+
if max_abs is None:
|
|
38
|
+
max_abs = amp.max() if amp.max() > 0 else 1.0
|
|
39
|
+
hue = (phase + np.pi) / (2 * np.pi)
|
|
40
|
+
saturation = np.ones_like(hue)
|
|
41
|
+
value = np.clip(amp / max_abs, 0, 1)
|
|
42
|
+
hsv = np.stack([hue, saturation, value], axis=-1)
|
|
43
|
+
return mcolors.hsv_to_rgb(hsv)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def plot_complex_wavefunction(x: np.ndarray, psi: np.ndarray, ax=None, density_scale: float = 1.0):
|
|
47
|
+
r"""Plot a phase-colored probability density curve.
|
|
48
|
+
|
|
49
|
+
Plots :math:`\lvert\psi(x)\rvert^2` as a filled curve, colored by the
|
|
50
|
+
local phase :math:`\arg\psi(x)` (HSV hue) -- a compact way to show both
|
|
51
|
+
the probability density and the complex phase of a wavefunction at once.
|
|
52
|
+
|
|
53
|
+
Parameters
|
|
54
|
+
----------
|
|
55
|
+
x : numpy.ndarray
|
|
56
|
+
Positions.
|
|
57
|
+
psi : numpy.ndarray
|
|
58
|
+
Complex-valued wavefunction sampled on ``x``.
|
|
59
|
+
ax : matplotlib.axes.Axes or None, optional
|
|
60
|
+
Axis to draw on; a new figure/axis is created if omitted.
|
|
61
|
+
density_scale : float, default=1.0
|
|
62
|
+
Multiplicative scale factor applied to the plotted density.
|
|
63
|
+
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
matplotlib.axes.Axes
|
|
67
|
+
"""
|
|
68
|
+
if ax is None:
|
|
69
|
+
_, ax = plt.subplots(figsize=(7, 4))
|
|
70
|
+
|
|
71
|
+
density = np.abs(psi) ** 2 * density_scale
|
|
72
|
+
colors = complex_to_rgb(psi)
|
|
73
|
+
|
|
74
|
+
for i in range(len(x) - 1):
|
|
75
|
+
ax.fill_between(x[i : i + 2], 0, density[i : i + 2], color=colors[i], linewidth=0)
|
|
76
|
+
|
|
77
|
+
ax.set_xlabel("x")
|
|
78
|
+
ax.set_ylabel(r"$|\psi(x)|^2$")
|
|
79
|
+
|
|
80
|
+
sm = plt.cm.ScalarMappable(cmap=_phase_colormap(), norm=mcolors.Normalize(-np.pi, np.pi))
|
|
81
|
+
sm.set_array([])
|
|
82
|
+
cbar = plt.colorbar(sm, ax=ax, pad=0.02)
|
|
83
|
+
cbar.set_label(r"$\arg\,\psi(x)$")
|
|
84
|
+
return ax
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _phase_colormap():
|
|
88
|
+
hues = np.linspace(0, 1, 256)
|
|
89
|
+
rgb = mcolors.hsv_to_rgb(np.stack([hues, np.ones_like(hues), np.ones_like(hues)], axis=-1))
|
|
90
|
+
return mcolors.ListedColormap(rgb)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def animate_density(
|
|
94
|
+
x: np.ndarray, frames: np.ndarray, times: np.ndarray | None = None, interval: int = 30, phase_colored: bool = True, ax=None
|
|
95
|
+
) -> FuncAnimation:
|
|
96
|
+
"""Animate a stack of wavefunction snapshots over time.
|
|
97
|
+
|
|
98
|
+
Parameters
|
|
99
|
+
----------
|
|
100
|
+
x : numpy.ndarray
|
|
101
|
+
Positions.
|
|
102
|
+
frames : numpy.ndarray
|
|
103
|
+
Wavefunction snapshots, shape ``(n_frames, len(x))``. May be complex
|
|
104
|
+
(density and phase both shown via :func:`complex_to_rgb`) or real
|
|
105
|
+
(plain probability density curve).
|
|
106
|
+
times : numpy.ndarray or None, optional
|
|
107
|
+
Time of each frame, used to label the animation title.
|
|
108
|
+
interval : int, default=30
|
|
109
|
+
Delay between frames, in milliseconds.
|
|
110
|
+
phase_colored : bool, default=True
|
|
111
|
+
Whether to color the curve by phase (only applies if ``frames`` is
|
|
112
|
+
complex).
|
|
113
|
+
ax : matplotlib.axes.Axes or None, optional
|
|
114
|
+
Axis to draw on; a new figure/axis is created if omitted.
|
|
115
|
+
|
|
116
|
+
Returns
|
|
117
|
+
-------
|
|
118
|
+
matplotlib.animation.FuncAnimation
|
|
119
|
+
"""
|
|
120
|
+
if ax is None:
|
|
121
|
+
fig, ax = plt.subplots(figsize=(7, 4))
|
|
122
|
+
else:
|
|
123
|
+
fig = ax.figure
|
|
124
|
+
|
|
125
|
+
density = np.abs(frames) ** 2
|
|
126
|
+
ymax = density.max() * 1.1
|
|
127
|
+
|
|
128
|
+
if phase_colored and np.iscomplexobj(frames):
|
|
129
|
+
line_collections = []
|
|
130
|
+
|
|
131
|
+
def init():
|
|
132
|
+
ax.set_xlim(x.min(), x.max())
|
|
133
|
+
ax.set_ylim(0, ymax)
|
|
134
|
+
ax.set_xlabel("x")
|
|
135
|
+
ax.set_ylabel(r"$|\psi(x,t)|^2$")
|
|
136
|
+
return []
|
|
137
|
+
|
|
138
|
+
def update(i):
|
|
139
|
+
for coll in line_collections:
|
|
140
|
+
coll.remove()
|
|
141
|
+
line_collections.clear()
|
|
142
|
+
colors = complex_to_rgb(frames[i], max_abs=np.abs(frames).max())
|
|
143
|
+
for j in range(len(x) - 1):
|
|
144
|
+
line_collections.append(ax.fill_between(x[j : j + 2], 0, density[i, j : j + 2], color=colors[j], linewidth=0))
|
|
145
|
+
title = f"t = {times[i]:.3f}" if times is not None else f"frame {i}"
|
|
146
|
+
ax.set_title(title)
|
|
147
|
+
return line_collections
|
|
148
|
+
|
|
149
|
+
return FuncAnimation(fig, update, init_func=init, frames=len(frames), interval=interval, blit=False)
|
|
150
|
+
|
|
151
|
+
(line,) = ax.plot(x, density[0])
|
|
152
|
+
ax.set_xlim(x.min(), x.max())
|
|
153
|
+
ax.set_ylim(0, ymax)
|
|
154
|
+
ax.set_xlabel("x")
|
|
155
|
+
ax.set_ylabel(r"$|\psi(x,t)|^2$")
|
|
156
|
+
|
|
157
|
+
def update_simple(i):
|
|
158
|
+
line.set_ydata(density[i])
|
|
159
|
+
title = f"t = {times[i]:.3f}" if times is not None else f"frame {i}"
|
|
160
|
+
ax.set_title(title)
|
|
161
|
+
return (line,)
|
|
162
|
+
|
|
163
|
+
return FuncAnimation(fig, update_simple, frames=len(frames), interval=interval, blit=False)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def animate_density_2d(
|
|
167
|
+
X: np.ndarray,
|
|
168
|
+
Y: np.ndarray,
|
|
169
|
+
frames: np.ndarray,
|
|
170
|
+
times: np.ndarray | None = None,
|
|
171
|
+
interval: int = 30,
|
|
172
|
+
phase_colored: bool = True,
|
|
173
|
+
cmap: str = "viridis",
|
|
174
|
+
ax=None,
|
|
175
|
+
) -> FuncAnimation:
|
|
176
|
+
"""Animate a stack of 2D wavefunction/density snapshots via ``imshow``.
|
|
177
|
+
|
|
178
|
+
Parameters
|
|
179
|
+
----------
|
|
180
|
+
X, Y : numpy.ndarray
|
|
181
|
+
Coordinate meshgrid (``indexing='ij'``), e.g.
|
|
182
|
+
``SplitOperatorSolver2D.X/.Y``.
|
|
183
|
+
frames : numpy.ndarray
|
|
184
|
+
Snapshots, shape ``(n_frames, *X.shape)``. May be complex
|
|
185
|
+
(density and phase both shown via :func:`complex_to_rgb`) or real
|
|
186
|
+
(a plain probability-density heatmap).
|
|
187
|
+
times : numpy.ndarray or None, optional
|
|
188
|
+
Time of each frame, used to label the animation title.
|
|
189
|
+
interval : int, default=30
|
|
190
|
+
Delay between frames, in milliseconds.
|
|
191
|
+
phase_colored : bool, default=True
|
|
192
|
+
Whether to color by phase (only applies if ``frames`` is complex).
|
|
193
|
+
cmap : str, default='viridis'
|
|
194
|
+
Colormap used when not phase-colored.
|
|
195
|
+
ax : matplotlib.axes.Axes or None, optional
|
|
196
|
+
Axis to draw on; a new figure/axis is created if omitted.
|
|
197
|
+
|
|
198
|
+
Returns
|
|
199
|
+
-------
|
|
200
|
+
matplotlib.animation.FuncAnimation
|
|
201
|
+
"""
|
|
202
|
+
if ax is None:
|
|
203
|
+
fig, ax = plt.subplots(figsize=(6, 5))
|
|
204
|
+
else:
|
|
205
|
+
fig = ax.figure
|
|
206
|
+
|
|
207
|
+
extent = [X.min(), X.max(), Y.min(), Y.max()]
|
|
208
|
+
is_complex = phase_colored and np.iscomplexobj(frames)
|
|
209
|
+
|
|
210
|
+
if is_complex:
|
|
211
|
+
max_abs = np.abs(frames).max()
|
|
212
|
+
im = ax.imshow(np.transpose(complex_to_rgb(frames[0], max_abs=max_abs), (1, 0, 2)), origin="lower", extent=extent, aspect="auto")
|
|
213
|
+
else:
|
|
214
|
+
density = np.abs(frames) ** 2 if np.iscomplexobj(frames) else frames
|
|
215
|
+
vmax = density.max() * 1.1
|
|
216
|
+
im = ax.imshow(density[0].T, origin="lower", extent=extent, aspect="auto", cmap=cmap, vmin=0, vmax=vmax)
|
|
217
|
+
|
|
218
|
+
ax.set_xlabel("x")
|
|
219
|
+
ax.set_ylabel("y")
|
|
220
|
+
|
|
221
|
+
def update(i):
|
|
222
|
+
if is_complex:
|
|
223
|
+
im.set_data(np.transpose(complex_to_rgb(frames[i], max_abs=np.abs(frames).max()), (1, 0, 2)))
|
|
224
|
+
else:
|
|
225
|
+
im.set_data(density[i].T)
|
|
226
|
+
title = f"t = {times[i]:.3f}" if times is not None else f"frame {i}"
|
|
227
|
+
ax.set_title(title)
|
|
228
|
+
return (im,)
|
|
229
|
+
|
|
230
|
+
return FuncAnimation(fig, update, frames=len(frames), interval=interval, blit=False)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""physicskit.relativity: fast, visually captivating numerical General Relativity.
|
|
2
|
+
|
|
3
|
+
``physicskit.relativity`` brings curved spacetime geometry, black hole physics,
|
|
4
|
+
ray-traced gravitational lensing, and gravitational wave dynamics into an
|
|
5
|
+
interactive, computational Python framework, in geometrized units
|
|
6
|
+
(:math:`G = c = 1`; see :mod:`physicskit.relativity.utils.constants`):
|
|
7
|
+
|
|
8
|
+
- **Black hole physics** (:mod:`physicskit.relativity.chapters.schwarzschild`,
|
|
9
|
+
:mod:`physicskit.relativity.chapters.kerr`): timelike orbits, perihelion precession, the
|
|
10
|
+
innermost stable circular orbit (ISCO), the photon sphere, light
|
|
11
|
+
deflection and the Shapiro delay, disk redshift, tidal forces, frame
|
|
12
|
+
dragging, the ergosphere, and the Penrose process.
|
|
13
|
+
- **Spacetime geometry** (:mod:`physicskit.relativity.core.tensors`): a numerical
|
|
14
|
+
differential geometry engine computing Christoffel symbols and curvature
|
|
15
|
+
tensors for arbitrary metrics (Schwarzschild, Kerr, Reissner-Nordstrom,
|
|
16
|
+
FLRW, the Alcubierre warp drive).
|
|
17
|
+
- **Gravitational lensing** (:mod:`physicskit.relativity.core.raytracer`,
|
|
18
|
+
:mod:`physicskit.relativity.core.kerr_raytracer`, :mod:`physicskit.relativity.visualizers.shadow_render`,
|
|
19
|
+
:mod:`physicskit.relativity.chapters.lensing`): Numba-accelerated backward photon
|
|
20
|
+
ray-tracers (Schwarzschild and Kerr) rendering black hole shadows and
|
|
21
|
+
redshift-shaded lensed accretion disks, plus point-source Einstein rings,
|
|
22
|
+
multiple images, and microlensing magnification.
|
|
23
|
+
- **Gravitational waves** (:mod:`physicskit.relativity.chapters.gw_merger`): binary black
|
|
24
|
+
hole inspiral chirps and ringdown, and Hulse-Taylor-style orbital decay.
|
|
25
|
+
- **Cosmology & compact objects** (:mod:`physicskit.relativity.chapters.cosmology`,
|
|
26
|
+
:mod:`physicskit.relativity.chapters.neutron_star`): the FLRW Friedmann equations for
|
|
27
|
+
cosmic expansion, and the Tolman-Oppenheimer-Volkoff equations for
|
|
28
|
+
neutron star structure and the maximum neutron star mass.
|
|
29
|
+
- **Relativity in everyday technology** (:mod:`physicskit.relativity.chapters.timekeeping`):
|
|
30
|
+
the GPS satellite relativistic clock correction.
|
|
31
|
+
|
|
32
|
+
Examples
|
|
33
|
+
--------
|
|
34
|
+
>>> from physicskit.relativity.chapters import SchwarzschildBlackHole
|
|
35
|
+
>>> bh = SchwarzschildBlackHole(M=1.0)
|
|
36
|
+
>>> bh.isco_radius
|
|
37
|
+
6.0
|
|
38
|
+
>>> bh.photon_sphere_radius
|
|
39
|
+
3.0
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
from physicskit.relativity.chapters import (
|
|
43
|
+
BinaryMerger,
|
|
44
|
+
FLRWCosmology,
|
|
45
|
+
KerrBlackHole,
|
|
46
|
+
NeutronStar,
|
|
47
|
+
PointMassLens,
|
|
48
|
+
SchwarzschildBlackHole,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
__version__ = "0.2.0"
|
|
52
|
+
|
|
53
|
+
__all__ = [
|
|
54
|
+
"BinaryMerger",
|
|
55
|
+
"FLRWCosmology",
|
|
56
|
+
"KerrBlackHole",
|
|
57
|
+
"NeutronStar",
|
|
58
|
+
"PointMassLens",
|
|
59
|
+
"SchwarzschildBlackHole",
|
|
60
|
+
"__version__",
|
|
61
|
+
]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Physics chapters: user-facing model classes built on :mod:`physicskit.relativity.core`.
|
|
2
|
+
|
|
3
|
+
- :mod:`physicskit.relativity.chapters.schwarzschild` -- orbits, precession, the photon
|
|
4
|
+
sphere, light deflection, the Shapiro delay, disk redshift, and tidal
|
|
5
|
+
forces.
|
|
6
|
+
- :mod:`physicskit.relativity.chapters.kerr` -- frame dragging, the ergosphere, the ISCO,
|
|
7
|
+
and the Penrose process.
|
|
8
|
+
- :mod:`physicskit.relativity.chapters.lensing` -- Einstein rings, multiple images, and
|
|
9
|
+
microlensing magnification.
|
|
10
|
+
- :mod:`physicskit.relativity.chapters.gw_merger` -- binary black hole inspiral chirps,
|
|
11
|
+
ringdown, and Hulse-Taylor-style orbital decay.
|
|
12
|
+
- :mod:`physicskit.relativity.chapters.cosmology` -- FLRW cosmic expansion and redshift.
|
|
13
|
+
- :mod:`physicskit.relativity.chapters.neutron_star` -- the Tolman-Oppenheimer-Volkoff
|
|
14
|
+
equations and the neutron star maximum mass.
|
|
15
|
+
- :mod:`physicskit.relativity.chapters.timekeeping` -- relativistic satellite clock
|
|
16
|
+
corrections (GPS).
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from physicskit.relativity.chapters.cosmology import FLRWCosmology
|
|
20
|
+
from physicskit.relativity.chapters.gw_merger import BinaryMerger
|
|
21
|
+
from physicskit.relativity.chapters.kerr import KerrBlackHole
|
|
22
|
+
from physicskit.relativity.chapters.lensing import PointMassLens
|
|
23
|
+
from physicskit.relativity.chapters.neutron_star import NeutronStar
|
|
24
|
+
from physicskit.relativity.chapters.schwarzschild import SchwarzschildBlackHole
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"BinaryMerger",
|
|
28
|
+
"FLRWCosmology",
|
|
29
|
+
"KerrBlackHole",
|
|
30
|
+
"NeutronStar",
|
|
31
|
+
"PointMassLens",
|
|
32
|
+
"SchwarzschildBlackHole",
|
|
33
|
+
]
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"""FLRW cosmology: the Friedmann equations, cosmic expansion, and redshift.
|
|
2
|
+
|
|
3
|
+
The Friedmann-Lemaitre-Robertson-Walker (FLRW) metric is the unique
|
|
4
|
+
spacetime describing a homogeneous, isotropic universe -- an excellent
|
|
5
|
+
approximation to our own on large scales. Plugging it into Einstein's field
|
|
6
|
+
equations yields the Friedmann equation, which governs how the universe's
|
|
7
|
+
scale factor :math:`a(t)` evolves under the combined gravity of radiation,
|
|
8
|
+
matter, curvature, and dark energy (:math:`\\Lambda`). This single equation
|
|
9
|
+
explains Hubble's 1929 discovery of cosmic expansion, predicts the
|
|
10
|
+
universe's age, and -- through the distance-redshift relation -- underlies
|
|
11
|
+
the 1998 discovery (via observations of distant supernovae) that this
|
|
12
|
+
expansion is accelerating.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import numpy as np
|
|
18
|
+
from scipy.integrate import quad
|
|
19
|
+
|
|
20
|
+
from physicskit.relativity.utils.constants import C_SI, PARSEC_M
|
|
21
|
+
|
|
22
|
+
__all__ = ["FLRWCosmology"]
|
|
23
|
+
|
|
24
|
+
_MPC_M = PARSEC_M * 1.0e6
|
|
25
|
+
_GYR_S = 365.25 * 24.0 * 3600.0 * 1.0e9
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class FLRWCosmology:
|
|
29
|
+
"""A flat or curved FLRW universe with radiation, matter, curvature, and dark energy.
|
|
30
|
+
|
|
31
|
+
Parameters
|
|
32
|
+
----------
|
|
33
|
+
H0 : float, default=70.0
|
|
34
|
+
Hubble constant today, in km/s/Mpc.
|
|
35
|
+
Omega_m : float, default=0.3
|
|
36
|
+
Matter density parameter today.
|
|
37
|
+
Omega_r : float, default=1e-4
|
|
38
|
+
Radiation density parameter today.
|
|
39
|
+
Omega_Lambda : float, default=0.7
|
|
40
|
+
Dark energy (cosmological constant) density parameter today.
|
|
41
|
+
|
|
42
|
+
Attributes
|
|
43
|
+
----------
|
|
44
|
+
Omega_k : float
|
|
45
|
+
Curvature density parameter, :math:`1 - \\Omega_m - \\Omega_r - \\Omega_\\Lambda`
|
|
46
|
+
(computed so all density parameters sum to 1, as required by the
|
|
47
|
+
Friedmann equation at :math:`a=1`).
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(self, H0=70.0, Omega_m=0.3, Omega_r=1.0e-4, Omega_Lambda=0.7):
|
|
51
|
+
self.H0 = H0
|
|
52
|
+
self.Omega_m = Omega_m
|
|
53
|
+
self.Omega_r = Omega_r
|
|
54
|
+
self.Omega_Lambda = Omega_Lambda
|
|
55
|
+
self.Omega_k = 1.0 - Omega_m - Omega_r - Omega_Lambda
|
|
56
|
+
|
|
57
|
+
def _H0_si(self):
|
|
58
|
+
return self.H0 * 1.0e3 / _MPC_M # km/s/Mpc -> 1/s
|
|
59
|
+
|
|
60
|
+
def E(self, a):
|
|
61
|
+
"""Dimensionless expansion rate :math:`E(a) = H(a)/H_0`.
|
|
62
|
+
|
|
63
|
+
.. math::
|
|
64
|
+
|
|
65
|
+
E(a) = \\sqrt{\\Omega_r a^{-4} + \\Omega_m a^{-3} + \\Omega_k a^{-2} + \\Omega_\\Lambda}
|
|
66
|
+
|
|
67
|
+
Parameters
|
|
68
|
+
----------
|
|
69
|
+
a : float or array_like
|
|
70
|
+
Scale factor (:math:`a=1` today).
|
|
71
|
+
|
|
72
|
+
Returns
|
|
73
|
+
-------
|
|
74
|
+
float or ndarray
|
|
75
|
+
"""
|
|
76
|
+
a = np.asarray(a, dtype=np.float64)
|
|
77
|
+
return np.sqrt(self.Omega_r * a**-4 + self.Omega_m * a**-3 + self.Omega_k * a**-2 + self.Omega_Lambda)
|
|
78
|
+
|
|
79
|
+
def hubble_parameter(self, a):
|
|
80
|
+
"""Hubble parameter :math:`H(a) = H_0 E(a)`, in km/s/Mpc.
|
|
81
|
+
|
|
82
|
+
Parameters
|
|
83
|
+
----------
|
|
84
|
+
a : float or array_like
|
|
85
|
+
Scale factor.
|
|
86
|
+
|
|
87
|
+
Returns
|
|
88
|
+
-------
|
|
89
|
+
float or ndarray
|
|
90
|
+
"""
|
|
91
|
+
return self.H0 * self.E(a)
|
|
92
|
+
|
|
93
|
+
def redshift_to_scale_factor(self, z):
|
|
94
|
+
"""Convert redshift to scale factor, :math:`a = 1/(1+z)`."""
|
|
95
|
+
return 1.0 / (1.0 + np.asarray(z, dtype=np.float64))
|
|
96
|
+
|
|
97
|
+
def scale_factor_to_redshift(self, a):
|
|
98
|
+
"""Convert scale factor to redshift, :math:`z = 1/a - 1`."""
|
|
99
|
+
return 1.0 / np.asarray(a, dtype=np.float64) - 1.0
|
|
100
|
+
|
|
101
|
+
def comoving_distance_mpc(self, z):
|
|
102
|
+
"""Comoving distance to redshift ``z``, in Mpc.
|
|
103
|
+
|
|
104
|
+
.. math::
|
|
105
|
+
|
|
106
|
+
D_C(z) = c \\int_0^z \\frac{dz'}{H(z')}
|
|
107
|
+
|
|
108
|
+
Parameters
|
|
109
|
+
----------
|
|
110
|
+
z : float
|
|
111
|
+
Redshift.
|
|
112
|
+
|
|
113
|
+
Returns
|
|
114
|
+
-------
|
|
115
|
+
float
|
|
116
|
+
"""
|
|
117
|
+
H0_si = self._H0_si()
|
|
118
|
+
|
|
119
|
+
def integrand(zp):
|
|
120
|
+
a = 1.0 / (1.0 + zp)
|
|
121
|
+
return 1.0 / (H0_si * self.E(a))
|
|
122
|
+
|
|
123
|
+
distance_m = C_SI * quad(integrand, 0.0, z)[0]
|
|
124
|
+
return distance_m / _MPC_M
|
|
125
|
+
|
|
126
|
+
def luminosity_distance_mpc(self, z):
|
|
127
|
+
"""Luminosity distance to redshift ``z``, in Mpc, :math:`D_L = (1+z) D_C` (flat-sky FLRW).
|
|
128
|
+
|
|
129
|
+
Parameters
|
|
130
|
+
----------
|
|
131
|
+
z : float
|
|
132
|
+
Redshift.
|
|
133
|
+
|
|
134
|
+
Returns
|
|
135
|
+
-------
|
|
136
|
+
float
|
|
137
|
+
"""
|
|
138
|
+
return (1.0 + z) * self.comoving_distance_mpc(z)
|
|
139
|
+
|
|
140
|
+
def age_gyr(self, a=1.0):
|
|
141
|
+
"""Cosmic age at scale factor ``a``, in Gyr.
|
|
142
|
+
|
|
143
|
+
.. math::
|
|
144
|
+
|
|
145
|
+
t(a) = \\int_0^a \\frac{da'}{a' H(a')}
|
|
146
|
+
|
|
147
|
+
Parameters
|
|
148
|
+
----------
|
|
149
|
+
a : float, default=1.0
|
|
150
|
+
Scale factor at which to evaluate the age (``a=1`` gives the
|
|
151
|
+
current age of the universe).
|
|
152
|
+
|
|
153
|
+
Returns
|
|
154
|
+
-------
|
|
155
|
+
float
|
|
156
|
+
|
|
157
|
+
Examples
|
|
158
|
+
--------
|
|
159
|
+
>>> cosmo = FLRWCosmology(H0=70.0, Omega_m=0.3, Omega_r=0.0, Omega_Lambda=0.7)
|
|
160
|
+
>>> 12.0 < cosmo.age_gyr() < 15.0
|
|
161
|
+
True
|
|
162
|
+
"""
|
|
163
|
+
H0_si = self._H0_si()
|
|
164
|
+
|
|
165
|
+
def integrand(ap):
|
|
166
|
+
return 1.0 / (ap * H0_si * self.E(ap))
|
|
167
|
+
|
|
168
|
+
age_s = quad(integrand, 1.0e-8, a, limit=200)[0]
|
|
169
|
+
return age_s / _GYR_S
|
|
170
|
+
|
|
171
|
+
def scale_factor_history(self, n_points=200, a_min=1.0e-3, a_max=3.0):
|
|
172
|
+
"""Tabulate the age of the universe at a range of scale factors, for plotting :math:`a(t)`.
|
|
173
|
+
|
|
174
|
+
Parameters
|
|
175
|
+
----------
|
|
176
|
+
n_points : int, default=200
|
|
177
|
+
Number of scale-factor grid points.
|
|
178
|
+
a_min, a_max : float
|
|
179
|
+
Range of scale factors to tabulate.
|
|
180
|
+
|
|
181
|
+
Returns
|
|
182
|
+
-------
|
|
183
|
+
t_gyr : ndarray of shape (n_points,)
|
|
184
|
+
Cosmic age at each scale factor, in Gyr.
|
|
185
|
+
a : ndarray of shape (n_points,)
|
|
186
|
+
The scale factor grid.
|
|
187
|
+
"""
|
|
188
|
+
a_grid = np.linspace(a_min, a_max, n_points)
|
|
189
|
+
t_gyr = np.array([self.age_gyr(a) for a in a_grid])
|
|
190
|
+
return t_gyr, a_grid
|