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
physicskit/__init__.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""physicskit: unified scientific toolkit for computational physics.
|
|
2
|
+
|
|
3
|
+
Import as ``pk`` by convention::
|
|
4
|
+
|
|
5
|
+
import physicskit as pk
|
|
6
|
+
pk.condensed.compute_chern_number(...)
|
|
7
|
+
pk.chaos.systems.maps.LogisticMap(...)
|
|
8
|
+
pk.fields.nls_dark_soliton(...)
|
|
9
|
+
pk.optics.GaussianBeam(wavelength=1.064e-3, w0=0.05)
|
|
10
|
+
pk.particle.FourVector(E=1.0, px=0.0, py=0.0, pz=0.6)
|
|
11
|
+
pk.astro.PolytropicStar(n=1.5, K=1.0, rho_c=1.0)
|
|
12
|
+
pk.plasma.alfven_speed(B=1.0, rho=1e-6)
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from physicskit import (
|
|
16
|
+
astro,
|
|
17
|
+
chaos,
|
|
18
|
+
classical,
|
|
19
|
+
condensed,
|
|
20
|
+
constants,
|
|
21
|
+
fields,
|
|
22
|
+
integrators,
|
|
23
|
+
optics,
|
|
24
|
+
particle,
|
|
25
|
+
plasma,
|
|
26
|
+
quantum,
|
|
27
|
+
relativity,
|
|
28
|
+
rmt,
|
|
29
|
+
semiclassical,
|
|
30
|
+
statphys,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
__version__ = "0.1.0"
|
|
34
|
+
|
|
35
|
+
__all__ = [
|
|
36
|
+
"astro",
|
|
37
|
+
"chaos",
|
|
38
|
+
"classical",
|
|
39
|
+
"condensed",
|
|
40
|
+
"constants",
|
|
41
|
+
"fields",
|
|
42
|
+
"integrators",
|
|
43
|
+
"optics",
|
|
44
|
+
"particle",
|
|
45
|
+
"plasma",
|
|
46
|
+
"quantum",
|
|
47
|
+
"relativity",
|
|
48
|
+
"rmt",
|
|
49
|
+
"semiclassical",
|
|
50
|
+
"statphys",
|
|
51
|
+
]
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""physicskit.astro: stellar structure, N-body dynamics, orbital mechanics, and galactic dynamics.
|
|
2
|
+
|
|
3
|
+
Uses **gravitational units with** :math:`G=1` by default throughout
|
|
4
|
+
(every function that needs it accepts ``G`` as a keyword argument), the
|
|
5
|
+
same convention :mod:`physicskit.relativity` uses for its own
|
|
6
|
+
geometrized units.
|
|
7
|
+
|
|
8
|
+
- :mod:`physicskit.astro.stellar_structure` -- polytropic stellar models
|
|
9
|
+
via the Lane-Emden equation, the Chandrasekhar mass limit, and the
|
|
10
|
+
main-sequence mass-luminosity relation.
|
|
11
|
+
- :mod:`physicskit.astro.nbody` -- direct-summation N-body gravitational
|
|
12
|
+
dynamics with a symplectic leapfrog integrator.
|
|
13
|
+
- :mod:`physicskit.astro.orbital_mechanics` -- classical orbital elements,
|
|
14
|
+
state-vector conversion, and Hohmann transfers.
|
|
15
|
+
- :mod:`physicskit.astro.galactic_dynamics` -- the NFW dark matter halo
|
|
16
|
+
profile and the rotation curves it produces.
|
|
17
|
+
- :mod:`physicskit.astro.visualizers` -- N-body, Lane-Emden, and
|
|
18
|
+
rotation-curve plots.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from physicskit.astro.galactic_dynamics import circular_velocity, nfw_density, nfw_enclosed_mass, nfw_potential
|
|
22
|
+
from physicskit.astro.nbody import NBodySystem, gravitational_acceleration, leapfrog_step
|
|
23
|
+
from physicskit.astro.orbital_mechanics import (
|
|
24
|
+
hohmann_transfer,
|
|
25
|
+
orbital_elements_from_state,
|
|
26
|
+
orbital_period,
|
|
27
|
+
state_from_orbital_elements,
|
|
28
|
+
vis_viva_speed,
|
|
29
|
+
)
|
|
30
|
+
from physicskit.astro.stellar_structure import (
|
|
31
|
+
PolytropicStar,
|
|
32
|
+
chandrasekhar_mass,
|
|
33
|
+
lane_emden,
|
|
34
|
+
main_sequence_luminosity,
|
|
35
|
+
)
|
|
36
|
+
from physicskit.astro.visualizers import plot_lane_emden, plot_nbody_trajectories, plot_rotation_curve
|
|
37
|
+
|
|
38
|
+
__version__ = "0.1.0"
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
"__version__",
|
|
42
|
+
# stellar_structure
|
|
43
|
+
"lane_emden",
|
|
44
|
+
"PolytropicStar",
|
|
45
|
+
"chandrasekhar_mass",
|
|
46
|
+
"main_sequence_luminosity",
|
|
47
|
+
# nbody
|
|
48
|
+
"gravitational_acceleration",
|
|
49
|
+
"leapfrog_step",
|
|
50
|
+
"NBodySystem",
|
|
51
|
+
# orbital_mechanics
|
|
52
|
+
"orbital_period",
|
|
53
|
+
"vis_viva_speed",
|
|
54
|
+
"orbital_elements_from_state",
|
|
55
|
+
"state_from_orbital_elements",
|
|
56
|
+
"hohmann_transfer",
|
|
57
|
+
# galactic_dynamics
|
|
58
|
+
"nfw_density",
|
|
59
|
+
"nfw_enclosed_mass",
|
|
60
|
+
"nfw_potential",
|
|
61
|
+
"circular_velocity",
|
|
62
|
+
# visualizers
|
|
63
|
+
"plot_nbody_trajectories",
|
|
64
|
+
"plot_lane_emden",
|
|
65
|
+
"plot_rotation_curve",
|
|
66
|
+
]
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
r"""The Zel'dovich (1970) approximation and the formation of the cosmic web.
|
|
2
|
+
|
|
3
|
+
In an expanding universe, small density perturbations do not stay small
|
|
4
|
+
forever: gravity amplifies them until they collapse along their fastest-
|
|
5
|
+
contracting direction first, producing the sheets ("pancakes"), filaments,
|
|
6
|
+
and dense nodes that together make up the observed large-scale structure of
|
|
7
|
+
the universe -- the *cosmic web*. Zel'dovich (1970, *Astronomy and
|
|
8
|
+
Astrophysics* 5, "Gravitational instability: An approximate theory for
|
|
9
|
+
large density perturbations") gave the classic, mathematically clean
|
|
10
|
+
description of this process: to first order in the displacement of matter
|
|
11
|
+
away from a uniform background, each fluid element simply moves in a
|
|
12
|
+
straight line (in comoving coordinates) at a rate set by the local gradient
|
|
13
|
+
of a fixed potential. The approximation is exact in one dimension and
|
|
14
|
+
remains an excellent guide to the onset of nonlinear structure in more
|
|
15
|
+
dimensions, which is why it is still the standard way to generate the
|
|
16
|
+
initial conditions of cosmological N-body simulations today.
|
|
17
|
+
|
|
18
|
+
This module works in a flat, matter-dominated (Einstein-de Sitter)
|
|
19
|
+
background, where the scale factor grows as :math:`a(t)\propto t^{2/3}`
|
|
20
|
+
and the linear growth factor of density perturbations is proportional to
|
|
21
|
+
the scale factor, :math:`D(t)\propto a(t)`. Rather than tracking time
|
|
22
|
+
directly, every function here is parametrized by the growth factor
|
|
23
|
+
:math:`D` itself, which increases monotonically from :math:`D=0` at the
|
|
24
|
+
initial (unperturbed) time.
|
|
25
|
+
|
|
26
|
+
Given a fixed Lagrangian ("unperturbed") position :math:`\mathbf{q}` and a
|
|
27
|
+
scalar displacement potential :math:`\Phi(\mathbf{q})`, the Zel'dovich
|
|
28
|
+
approximation maps :math:`\mathbf{q}` to a comoving Eulerian position
|
|
29
|
+
|
|
30
|
+
.. math::
|
|
31
|
+
|
|
32
|
+
\mathbf{x}(\mathbf{q}, D) = \mathbf{q} - D\,\nabla\Phi(\mathbf{q}),
|
|
33
|
+
|
|
34
|
+
i.e. every fluid element streams away from its starting point along a
|
|
35
|
+
straight line, in the fixed direction :math:`-\nabla\Phi(\mathbf{q})`, at a
|
|
36
|
+
rate that grows linearly with :math:`D`. This module builds :math:`\Phi` as
|
|
37
|
+
a sum of a modest number of plane waves -- a simple stand-in for a
|
|
38
|
+
realistic Gaussian random field, exactly as used pedagogically --
|
|
39
|
+
|
|
40
|
+
.. math::
|
|
41
|
+
|
|
42
|
+
\Phi(\mathbf{q}) = \sum_{n=1}^{N} A_n\cos(\mathbf{k}_n\cdot\mathbf{q}+\varphi_n),
|
|
43
|
+
|
|
44
|
+
with random wavevectors :math:`\mathbf{k}_n`, amplitudes :math:`A_n`, and
|
|
45
|
+
phases :math:`\varphi_n`. Because mass is conserved as fluid elements move,
|
|
46
|
+
the local density contrast follows directly from the Jacobian of the
|
|
47
|
+
mapping :math:`\mathbf{q}\mapsto\mathbf{x}`:
|
|
48
|
+
|
|
49
|
+
.. math::
|
|
50
|
+
|
|
51
|
+
\frac{\rho(\mathbf{x})}{\bar\rho} = \frac{1}{\left|\det\left(I - D\,H_\Phi(\mathbf{q})\right)\right|},
|
|
52
|
+
|
|
53
|
+
where :math:`H_\Phi` is the Hessian of :math:`\Phi`. This formally
|
|
54
|
+
diverges -- a caustic, i.e. a "pancake" -- the first time :math:`D` reaches
|
|
55
|
+
:math:`1/\lambda_{\max}(\mathbf{q})`, where :math:`\lambda_{\max}(\mathbf{q})`
|
|
56
|
+
is the largest eigenvalue of :math:`H_\Phi` at that point. The very first
|
|
57
|
+
caustic anywhere in the field therefore forms at
|
|
58
|
+
|
|
59
|
+
.. math::
|
|
60
|
+
|
|
61
|
+
D_{\rm collapse} = \frac{1}{\max_{\mathbf{q}}\lambda_{\max}(\mathbf{q})}.
|
|
62
|
+
|
|
63
|
+
For a single plane-wave potential this is exact and closed-form
|
|
64
|
+
(:math:`D_{\rm collapse}=1/(A|\mathbf{k}|^2)`), which makes it a clean,
|
|
65
|
+
directly testable prediction; see the test suite for the exact derivation.
|
|
66
|
+
|
|
67
|
+
- :func:`random_displacement_potential` -- draw a random multi-mode
|
|
68
|
+
displacement potential :math:`\Phi`.
|
|
69
|
+
- :func:`zeldovich_displacement` -- the analytic gradient
|
|
70
|
+
:math:`\nabla\Phi(\mathbf{q})`.
|
|
71
|
+
- :func:`zeldovich_position` -- the Zel'dovich mapping
|
|
72
|
+
:math:`\mathbf{x}(\mathbf{q}, D)`.
|
|
73
|
+
- :func:`zeldovich_hessian_eigenvalues` -- the eigenvalues of
|
|
74
|
+
:math:`H_\Phi(\mathbf{q})`, which control local collapse.
|
|
75
|
+
- :func:`first_caustic_time` -- the growth factor at which the first
|
|
76
|
+
pancake forms anywhere in the field.
|
|
77
|
+
- :func:`lagrangian_grid` -- a regular grid of Lagrangian tracer particles
|
|
78
|
+
to evolve under the mapping.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
from __future__ import annotations
|
|
82
|
+
|
|
83
|
+
import numpy as np
|
|
84
|
+
|
|
85
|
+
__all__ = [
|
|
86
|
+
"random_displacement_potential",
|
|
87
|
+
"zeldovich_displacement",
|
|
88
|
+
"zeldovich_position",
|
|
89
|
+
"zeldovich_hessian_eigenvalues",
|
|
90
|
+
"first_caustic_time",
|
|
91
|
+
"lagrangian_grid",
|
|
92
|
+
]
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def random_displacement_potential(n_modes, k_min, k_max, amplitude_scale, seed=None, ndim=2):
|
|
96
|
+
r"""Draw a random multi-mode displacement potential :math:`\Phi(\mathbf{q})`.
|
|
97
|
+
|
|
98
|
+
Builds :math:`\Phi(\mathbf{q}) = \sum_{n=1}^{N}A_n\cos(\mathbf{k}_n\cdot
|
|
99
|
+
\mathbf{q}+\varphi_n)` -- a simple stand-in for a realistic Gaussian
|
|
100
|
+
random field -- with wavevectors :math:`\mathbf{k}_n` of random
|
|
101
|
+
orientation and magnitude drawn uniformly from :math:`[k_{\min},
|
|
102
|
+
k_{\max}]`, amplitudes drawn uniformly from :math:`[0,
|
|
103
|
+
\text{amplitude\_scale}]`, and phases drawn uniformly from
|
|
104
|
+
:math:`[0, 2\pi)`.
|
|
105
|
+
|
|
106
|
+
Parameters
|
|
107
|
+
----------
|
|
108
|
+
n_modes : int
|
|
109
|
+
Number of plane-wave modes, :math:`N`.
|
|
110
|
+
k_min, k_max : float
|
|
111
|
+
Lower and upper bounds on the wavenumber magnitude
|
|
112
|
+
:math:`|\mathbf{k}_n|`, setting the band of scales structure forms
|
|
113
|
+
at.
|
|
114
|
+
amplitude_scale : float
|
|
115
|
+
Upper bound on each mode's amplitude :math:`A_n`.
|
|
116
|
+
seed : int, optional
|
|
117
|
+
Random seed, for reproducibility.
|
|
118
|
+
ndim : int, default=2
|
|
119
|
+
Spatial dimension. Only ``ndim=2`` is supported; the analytic
|
|
120
|
+
gradient/Hessian machinery in this module is 2D-specific.
|
|
121
|
+
|
|
122
|
+
Returns
|
|
123
|
+
-------
|
|
124
|
+
k_vectors : ndarray, shape (n_modes, ndim)
|
|
125
|
+
Wavevectors :math:`\mathbf{k}_n`.
|
|
126
|
+
amplitudes : ndarray, shape (n_modes,)
|
|
127
|
+
Amplitudes :math:`A_n`.
|
|
128
|
+
phases : ndarray, shape (n_modes,)
|
|
129
|
+
Phases :math:`\varphi_n`, in :math:`[0, 2\pi)`.
|
|
130
|
+
|
|
131
|
+
Raises
|
|
132
|
+
------
|
|
133
|
+
ValueError
|
|
134
|
+
If ``ndim != 2``, ``n_modes < 1``, or ``k_max < k_min``.
|
|
135
|
+
|
|
136
|
+
Examples
|
|
137
|
+
--------
|
|
138
|
+
>>> k_vectors, amplitudes, phases = random_displacement_potential(8, k_min=1.0, k_max=3.0, amplitude_scale=0.1, seed=0)
|
|
139
|
+
>>> k_vectors.shape, amplitudes.shape, phases.shape
|
|
140
|
+
((8, 2), (8,), (8,))
|
|
141
|
+
>>> bool(np.all(amplitudes >= 0.0) and np.all(amplitudes <= 0.1))
|
|
142
|
+
True
|
|
143
|
+
"""
|
|
144
|
+
if ndim != 2:
|
|
145
|
+
raise ValueError("random_displacement_potential only supports ndim=2.")
|
|
146
|
+
if n_modes < 1:
|
|
147
|
+
raise ValueError("n_modes must be >= 1.")
|
|
148
|
+
if k_max < k_min:
|
|
149
|
+
raise ValueError("k_max must be >= k_min.")
|
|
150
|
+
|
|
151
|
+
rng = np.random.default_rng(seed)
|
|
152
|
+
k_mag = rng.uniform(k_min, k_max, n_modes)
|
|
153
|
+
angle = rng.uniform(0.0, 2.0 * np.pi, n_modes)
|
|
154
|
+
k_vectors = np.stack([k_mag * np.cos(angle), k_mag * np.sin(angle)], axis=-1)
|
|
155
|
+
amplitudes = rng.uniform(0.0, amplitude_scale, n_modes)
|
|
156
|
+
phases = rng.uniform(0.0, 2.0 * np.pi, n_modes)
|
|
157
|
+
return k_vectors, amplitudes, phases
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _phase_argument(q, k_vectors, phases):
|
|
161
|
+
"""``k_n . q_i + phase_n`` for every particle ``i`` and mode ``n``, shape (n_particles, n_modes)."""
|
|
162
|
+
q = np.atleast_2d(np.asarray(q, dtype=float))
|
|
163
|
+
k_vectors = np.asarray(k_vectors, dtype=float)
|
|
164
|
+
phases = np.asarray(phases, dtype=float)
|
|
165
|
+
return q @ k_vectors.T + phases[None, :]
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def zeldovich_displacement(q, k_vectors, amplitudes, phases):
|
|
169
|
+
r"""The analytic displacement field :math:`\nabla\Phi(\mathbf{q})`.
|
|
170
|
+
|
|
171
|
+
.. math::
|
|
172
|
+
|
|
173
|
+
\nabla\Phi(\mathbf{q}) = \sum_n -A_n\,\mathbf{k}_n\,
|
|
174
|
+
\sin(\mathbf{k}_n\cdot\mathbf{q}+\varphi_n)
|
|
175
|
+
|
|
176
|
+
Vectorized over all particles and modes at once (no explicit loops).
|
|
177
|
+
|
|
178
|
+
Parameters
|
|
179
|
+
----------
|
|
180
|
+
q : ndarray, shape (n_particles, 2)
|
|
181
|
+
Lagrangian (unperturbed) positions.
|
|
182
|
+
k_vectors : ndarray, shape (n_modes, 2)
|
|
183
|
+
amplitudes : ndarray, shape (n_modes,)
|
|
184
|
+
phases : ndarray, shape (n_modes,)
|
|
185
|
+
Potential parameters, e.g. from :func:`random_displacement_potential`.
|
|
186
|
+
|
|
187
|
+
Returns
|
|
188
|
+
-------
|
|
189
|
+
ndarray, shape (n_particles, 2)
|
|
190
|
+
:math:`\nabla\Phi` evaluated at each ``q``.
|
|
191
|
+
|
|
192
|
+
Examples
|
|
193
|
+
--------
|
|
194
|
+
>>> import numpy as np
|
|
195
|
+
>>> k_vectors = np.array([[1.0, 0.0]])
|
|
196
|
+
>>> amplitudes = np.array([2.0])
|
|
197
|
+
>>> phases = np.array([np.pi / 2]) # sin(pi/2) = 1
|
|
198
|
+
>>> grad = zeldovich_displacement(np.array([[0.0, 0.0]]), k_vectors, amplitudes, phases)
|
|
199
|
+
>>> np.round(grad + 0.0, 6) # "+ 0.0" avoids a printed "-0." for exact zeros
|
|
200
|
+
array([[-2., 0.]])
|
|
201
|
+
"""
|
|
202
|
+
k_vectors = np.asarray(k_vectors, dtype=float)
|
|
203
|
+
amplitudes = np.asarray(amplitudes, dtype=float)
|
|
204
|
+
theta = _phase_argument(q, k_vectors, phases)
|
|
205
|
+
weighted_sin = np.sin(theta) * amplitudes[None, :]
|
|
206
|
+
return -(weighted_sin @ k_vectors)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def zeldovich_position(q, D, k_vectors, amplitudes, phases):
|
|
210
|
+
r"""The Zel'dovich mapping :math:`\mathbf{x}(\mathbf{q}, D) = \mathbf{q} - D\,\nabla\Phi(\mathbf{q})`.
|
|
211
|
+
|
|
212
|
+
Parameters
|
|
213
|
+
----------
|
|
214
|
+
q : ndarray, shape (n_particles, 2)
|
|
215
|
+
Lagrangian (unperturbed) positions.
|
|
216
|
+
D : float
|
|
217
|
+
Linear growth factor (dimensionless "time"), :math:`D=0` at the
|
|
218
|
+
initial, unperturbed time.
|
|
219
|
+
k_vectors : ndarray, shape (n_modes, 2)
|
|
220
|
+
amplitudes : ndarray, shape (n_modes,)
|
|
221
|
+
phases : ndarray, shape (n_modes,)
|
|
222
|
+
Potential parameters, e.g. from :func:`random_displacement_potential`.
|
|
223
|
+
|
|
224
|
+
Returns
|
|
225
|
+
-------
|
|
226
|
+
ndarray, shape (n_particles, 2)
|
|
227
|
+
Comoving Eulerian positions :math:`\mathbf{x}`.
|
|
228
|
+
|
|
229
|
+
See Also
|
|
230
|
+
--------
|
|
231
|
+
zeldovich_displacement : The gradient field used here.
|
|
232
|
+
|
|
233
|
+
Examples
|
|
234
|
+
--------
|
|
235
|
+
>>> import numpy as np
|
|
236
|
+
>>> q = np.array([[0.3, 0.7], [1.1, -0.4]])
|
|
237
|
+
>>> k_vectors, amplitudes, phases = random_displacement_potential(4, 1.0, 2.0, 0.1, seed=1)
|
|
238
|
+
>>> x0 = zeldovich_position(q, 0.0, k_vectors, amplitudes, phases)
|
|
239
|
+
>>> bool(np.allclose(x0, q))
|
|
240
|
+
True
|
|
241
|
+
"""
|
|
242
|
+
q = np.atleast_2d(np.asarray(q, dtype=float))
|
|
243
|
+
grad_phi = zeldovich_displacement(q, k_vectors, amplitudes, phases)
|
|
244
|
+
return q - D * grad_phi
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def zeldovich_hessian_eigenvalues(q, k_vectors, amplitudes, phases):
|
|
248
|
+
r"""Eigenvalues of the analytic Hessian :math:`H_\Phi(\mathbf{q})`.
|
|
249
|
+
|
|
250
|
+
The Hessian components follow directly from differentiating the
|
|
251
|
+
plane-wave sum twice,
|
|
252
|
+
|
|
253
|
+
.. math::
|
|
254
|
+
|
|
255
|
+
\frac{\partial^2\Phi}{\partial q_i\partial q_j}
|
|
256
|
+
= \sum_n -A_n\,k_{n,i}k_{n,j}\cos(\mathbf{k}_n\cdot\mathbf{q}+\varphi_n),
|
|
257
|
+
|
|
258
|
+
and its two eigenvalues follow from the closed-form 2x2 symmetric
|
|
259
|
+
formula
|
|
260
|
+
|
|
261
|
+
.. math::
|
|
262
|
+
|
|
263
|
+
\lambda_\pm = \frac{(\Phi_{xx}+\Phi_{yy}) \pm
|
|
264
|
+
\sqrt{(\Phi_{xx}-\Phi_{yy})^2+4\Phi_{xy}^2}}{2},
|
|
265
|
+
|
|
266
|
+
computed directly as arrays (no per-particle ``numpy.linalg.eigh``
|
|
267
|
+
calls).
|
|
268
|
+
|
|
269
|
+
Parameters
|
|
270
|
+
----------
|
|
271
|
+
q : ndarray, shape (n_particles, 2)
|
|
272
|
+
Lagrangian (unperturbed) positions.
|
|
273
|
+
k_vectors : ndarray, shape (n_modes, 2)
|
|
274
|
+
amplitudes : ndarray, shape (n_modes,)
|
|
275
|
+
phases : ndarray, shape (n_modes,)
|
|
276
|
+
Potential parameters, e.g. from :func:`random_displacement_potential`.
|
|
277
|
+
|
|
278
|
+
Returns
|
|
279
|
+
-------
|
|
280
|
+
ndarray, shape (n_particles, 2)
|
|
281
|
+
The two eigenvalues of :math:`H_\Phi` at each ``q``, sorted
|
|
282
|
+
ascending along the last axis.
|
|
283
|
+
|
|
284
|
+
See Also
|
|
285
|
+
--------
|
|
286
|
+
first_caustic_time : The growth factor at which the largest of these
|
|
287
|
+
eigenvalues, maximized over all ``q``, first causes a caustic.
|
|
288
|
+
|
|
289
|
+
Examples
|
|
290
|
+
--------
|
|
291
|
+
>>> import numpy as np
|
|
292
|
+
>>> k_vectors = np.array([[2 * np.pi, 0.0]])
|
|
293
|
+
>>> amplitudes = np.array([1.0])
|
|
294
|
+
>>> phases = np.array([np.pi]) # cos(phase) = -1 at q=0: the compression maximum
|
|
295
|
+
>>> eigs = zeldovich_hessian_eigenvalues(np.array([[0.0, 0.0]]), k_vectors, amplitudes, phases)
|
|
296
|
+
>>> np.round(eigs, 6)
|
|
297
|
+
array([[ 0. , 39.478418]])
|
|
298
|
+
"""
|
|
299
|
+
k_vectors = np.asarray(k_vectors, dtype=float)
|
|
300
|
+
amplitudes = np.asarray(amplitudes, dtype=float)
|
|
301
|
+
theta = _phase_argument(q, k_vectors, phases)
|
|
302
|
+
weighted_cos = np.cos(theta) * amplitudes[None, :]
|
|
303
|
+
|
|
304
|
+
kx = k_vectors[:, 0]
|
|
305
|
+
ky = k_vectors[:, 1]
|
|
306
|
+
Pxx = -(weighted_cos @ (kx * kx))
|
|
307
|
+
Pyy = -(weighted_cos @ (ky * ky))
|
|
308
|
+
Pxy = -(weighted_cos @ (kx * ky))
|
|
309
|
+
|
|
310
|
+
trace = Pxx + Pyy
|
|
311
|
+
disc = np.sqrt((Pxx - Pyy) ** 2 + 4.0 * Pxy**2)
|
|
312
|
+
lambda_lo = 0.5 * (trace - disc)
|
|
313
|
+
lambda_hi = 0.5 * (trace + disc)
|
|
314
|
+
return np.stack([lambda_lo, lambda_hi], axis=-1)
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def first_caustic_time(q, k_vectors, amplitudes, phases):
|
|
318
|
+
r"""The growth factor :math:`D_{\rm collapse}` at which the first caustic forms.
|
|
319
|
+
|
|
320
|
+
.. math::
|
|
321
|
+
|
|
322
|
+
D_{\rm collapse} = \frac{1}{\max_{\mathbf{q}}\lambda_{\max}(\mathbf{q})}
|
|
323
|
+
|
|
324
|
+
evaluated over the sampled points ``q`` (the true collapse time is a
|
|
325
|
+
supremum over the *continuous* field, so this is a lower bound that
|
|
326
|
+
tightens toward the true value as ``q`` samples the field more
|
|
327
|
+
finely).
|
|
328
|
+
|
|
329
|
+
Parameters
|
|
330
|
+
----------
|
|
331
|
+
q : ndarray, shape (n_particles, 2)
|
|
332
|
+
Lagrangian (unperturbed) sample points, e.g. from
|
|
333
|
+
:func:`lagrangian_grid`.
|
|
334
|
+
k_vectors : ndarray, shape (n_modes, 2)
|
|
335
|
+
amplitudes : ndarray, shape (n_modes,)
|
|
336
|
+
phases : ndarray, shape (n_modes,)
|
|
337
|
+
Potential parameters, e.g. from :func:`random_displacement_potential`.
|
|
338
|
+
|
|
339
|
+
Returns
|
|
340
|
+
-------
|
|
341
|
+
float
|
|
342
|
+
:math:`D_{\rm collapse}`, the growth factor at which the first
|
|
343
|
+
pancake forms anywhere among the sampled points.
|
|
344
|
+
|
|
345
|
+
See Also
|
|
346
|
+
--------
|
|
347
|
+
zeldovich_hessian_eigenvalues : Supplies the per-point eigenvalues
|
|
348
|
+
this is maximized over.
|
|
349
|
+
|
|
350
|
+
Examples
|
|
351
|
+
--------
|
|
352
|
+
>>> import numpy as np
|
|
353
|
+
>>> k_vectors = np.array([[2 * np.pi, 0.0]])
|
|
354
|
+
>>> amplitudes = np.array([1.0])
|
|
355
|
+
>>> phases = np.array([np.pi])
|
|
356
|
+
>>> round(first_caustic_time(np.array([[0.0, 0.0]]), k_vectors, amplitudes, phases), 6)
|
|
357
|
+
0.02533
|
|
358
|
+
"""
|
|
359
|
+
eigs = zeldovich_hessian_eigenvalues(q, k_vectors, amplitudes, phases)
|
|
360
|
+
return float(1.0 / np.max(eigs[:, -1]))
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def lagrangian_grid(n_side, box_size):
|
|
364
|
+
r"""A regular grid of Lagrangian tracer particles over :math:`[0, L)^2`.
|
|
365
|
+
|
|
366
|
+
The standard starting point for a Zel'dovich visualization: an
|
|
367
|
+
initially perfectly uniform grid of tracer particles, whose progressive
|
|
368
|
+
deformation into filaments, sheets, and nodes under
|
|
369
|
+
:func:`zeldovich_position` is itself part of what makes the
|
|
370
|
+
visualization compelling.
|
|
371
|
+
|
|
372
|
+
Parameters
|
|
373
|
+
----------
|
|
374
|
+
n_side : int
|
|
375
|
+
Number of grid points along each axis.
|
|
376
|
+
box_size : float
|
|
377
|
+
Side length :math:`L` of the (periodic) comoving box.
|
|
378
|
+
|
|
379
|
+
Returns
|
|
380
|
+
-------
|
|
381
|
+
ndarray, shape (n_side * n_side, 2)
|
|
382
|
+
Lagrangian positions ``q``, tiling :math:`[0, L)^2` on a regular
|
|
383
|
+
grid.
|
|
384
|
+
|
|
385
|
+
Examples
|
|
386
|
+
--------
|
|
387
|
+
>>> q = lagrangian_grid(4, 1.0)
|
|
388
|
+
>>> q.shape
|
|
389
|
+
(16, 2)
|
|
390
|
+
>>> bool(np.all((q >= 0.0) & (q < 1.0)))
|
|
391
|
+
True
|
|
392
|
+
"""
|
|
393
|
+
coords = np.linspace(0.0, box_size, n_side, endpoint=False)
|
|
394
|
+
qx, qy = np.meshgrid(coords, coords, indexing="ij")
|
|
395
|
+
return np.stack([qx.ravel(), qy.ravel()], axis=-1)
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
r"""The Navarro-Frenk-White dark matter halo profile and rotation curves.
|
|
2
|
+
|
|
3
|
+
Uses **gravitational units with** :math:`G=1` by default -- every function
|
|
4
|
+
accepts ``G`` as a keyword argument, the same convention
|
|
5
|
+
:mod:`physicskit.relativity` uses for its own geometrized units.
|
|
6
|
+
|
|
7
|
+
- :func:`nfw_density`, :func:`nfw_enclosed_mass`, :func:`nfw_potential`
|
|
8
|
+
-- the NFW halo profile and its enclosed mass and potential.
|
|
9
|
+
- :func:`circular_velocity` -- the rotation curve produced by any
|
|
10
|
+
enclosed-mass profile.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
|
|
17
|
+
__all__ = ["nfw_density", "nfw_enclosed_mass", "nfw_potential", "circular_velocity"]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def nfw_density(r, rho_s, r_s):
|
|
21
|
+
r"""The Navarro-Frenk-White density profile.
|
|
22
|
+
|
|
23
|
+
.. math::
|
|
24
|
+
|
|
25
|
+
\rho_{\rm NFW}(r) = \frac{\rho_s}{(r/r_s)(1+r/r_s)^2}
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
r : array_like
|
|
30
|
+
Radius.
|
|
31
|
+
rho_s : float
|
|
32
|
+
Characteristic density.
|
|
33
|
+
r_s : float
|
|
34
|
+
Scale radius.
|
|
35
|
+
|
|
36
|
+
Returns
|
|
37
|
+
-------
|
|
38
|
+
ndarray or float
|
|
39
|
+
|
|
40
|
+
Examples
|
|
41
|
+
--------
|
|
42
|
+
>>> round(float(nfw_density(1.0, rho_s=1.0, r_s=1.0)), 6)
|
|
43
|
+
0.25
|
|
44
|
+
"""
|
|
45
|
+
x = np.asarray(r, dtype=float) / r_s
|
|
46
|
+
return rho_s / (x * (1.0 + x) ** 2)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def nfw_enclosed_mass(r, rho_s, r_s, G=1.0):
|
|
50
|
+
r"""Mass enclosed within radius ``r`` for an NFW halo.
|
|
51
|
+
|
|
52
|
+
.. math::
|
|
53
|
+
|
|
54
|
+
M(<r) = 4\pi\rho_s r_s^3\left[\ln\!\left(1+\frac{r}{r_s}\right)
|
|
55
|
+
- \frac{r/r_s}{1+r/r_s}\right]
|
|
56
|
+
|
|
57
|
+
``G`` is accepted for interface consistency with the rest of this
|
|
58
|
+
module but is not used by this formula.
|
|
59
|
+
|
|
60
|
+
Parameters
|
|
61
|
+
----------
|
|
62
|
+
r : array_like
|
|
63
|
+
Radius.
|
|
64
|
+
rho_s : float
|
|
65
|
+
Characteristic density.
|
|
66
|
+
r_s : float
|
|
67
|
+
Scale radius.
|
|
68
|
+
G : float, default=1.0
|
|
69
|
+
Unused; accepted for a consistent function signature.
|
|
70
|
+
|
|
71
|
+
Returns
|
|
72
|
+
-------
|
|
73
|
+
ndarray or float
|
|
74
|
+
|
|
75
|
+
Examples
|
|
76
|
+
--------
|
|
77
|
+
>>> round(float(nfw_enclosed_mass(1.0, rho_s=1.0, r_s=1.0)), 6)
|
|
78
|
+
2.427159
|
|
79
|
+
"""
|
|
80
|
+
del G
|
|
81
|
+
x = np.asarray(r, dtype=float) / r_s
|
|
82
|
+
return 4.0 * np.pi * rho_s * r_s**3 * (np.log(1.0 + x) - x / (1.0 + x))
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def nfw_potential(r, rho_s, r_s, G=1.0):
|
|
86
|
+
r"""The NFW gravitational potential.
|
|
87
|
+
|
|
88
|
+
.. math::
|
|
89
|
+
|
|
90
|
+
\Phi(r) = -\frac{4\pi G\rho_sr_s^3}{r}\ln\!\left(1+\frac{r}{r_s}\right)
|
|
91
|
+
|
|
92
|
+
Parameters
|
|
93
|
+
----------
|
|
94
|
+
r : array_like
|
|
95
|
+
Radius.
|
|
96
|
+
rho_s : float
|
|
97
|
+
Characteristic density.
|
|
98
|
+
r_s : float
|
|
99
|
+
Scale radius.
|
|
100
|
+
G : float, default=1.0
|
|
101
|
+
Gravitational constant.
|
|
102
|
+
|
|
103
|
+
Returns
|
|
104
|
+
-------
|
|
105
|
+
ndarray or float
|
|
106
|
+
"""
|
|
107
|
+
r = np.asarray(r, dtype=float)
|
|
108
|
+
x = r / r_s
|
|
109
|
+
return -4.0 * np.pi * G * rho_s * r_s**3 * np.log(1.0 + x) / r
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def circular_velocity(r, mass_enclosed_func, G=1.0):
|
|
113
|
+
r"""Circular orbital speed for any enclosed-mass profile, :math:`v_c(r)=\sqrt{GM(<r)/r}`.
|
|
114
|
+
|
|
115
|
+
Parameters
|
|
116
|
+
----------
|
|
117
|
+
r : array_like
|
|
118
|
+
Radius.
|
|
119
|
+
mass_enclosed_func : callable
|
|
120
|
+
``mass_enclosed_func(r) -> mass``, e.g.
|
|
121
|
+
``lambda r: nfw_enclosed_mass(r, rho_s, r_s)``.
|
|
122
|
+
G : float, default=1.0
|
|
123
|
+
Gravitational constant.
|
|
124
|
+
|
|
125
|
+
Returns
|
|
126
|
+
-------
|
|
127
|
+
ndarray or float
|
|
128
|
+
|
|
129
|
+
Examples
|
|
130
|
+
--------
|
|
131
|
+
>>> M0 = 5.0
|
|
132
|
+
>>> round(float(circular_velocity(2.0, lambda r: M0, G=1.0)), 6)
|
|
133
|
+
1.581139
|
|
134
|
+
"""
|
|
135
|
+
r = np.asarray(r, dtype=float)
|
|
136
|
+
M = mass_enclosed_func(r)
|
|
137
|
+
return np.sqrt(G * M / r)
|