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,579 @@
|
|
|
1
|
+
r"""Semiclassical propagators: the Van Vleck-Morette determinant and Herman-Kluk frozen Gaussians.
|
|
2
|
+
|
|
3
|
+
Both propagators here reconstruct the quantum time-evolution operator
|
|
4
|
+
from *classical* trajectories alone. Van Vleck-Morette theory
|
|
5
|
+
(:func:`van_vleck_propagator_1d`) uses a single trajectory connecting a
|
|
6
|
+
fixed start and end point, dressed with a stability prefactor built from
|
|
7
|
+
its **monodromy matrix** -- the linearized map
|
|
8
|
+
:math:`(\delta q_0,\delta p_0)\mapsto(\delta q_t,\delta p_t)` obtained by
|
|
9
|
+
propagating small deviations alongside the trajectory
|
|
10
|
+
(:func:`propagate_trajectory_monodromy_action`). Herman and Kluk's 1984
|
|
11
|
+
frozen-Gaussian method (:func:`herman_kluk_propagate_wavepacket`) instead
|
|
12
|
+
sums the contributions of *many* such trajectories, one launched from
|
|
13
|
+
each point of a phase-space grid under the initial wavepacket, each one
|
|
14
|
+
carrying its own rigid (frozen-width) Gaussian, monodromy-built
|
|
15
|
+
prefactor, and classical action phase.
|
|
16
|
+
|
|
17
|
+
Right-hand-side functions passed to the trajectory/monodromy integrator
|
|
18
|
+
must be module-level ``@njit`` functions with signature
|
|
19
|
+
``dVdx(q, params) -> float`` / ``d2Vdx2(q, params) -> float`` /
|
|
20
|
+
``V(q, params) -> float``, with ``params`` a ``float64`` array -- the
|
|
21
|
+
same convention used throughout this package's Numba-accelerated
|
|
22
|
+
integrators, letting a single compiled kernel serve any potential.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import numpy as np
|
|
28
|
+
from numba import njit
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
"propagate_trajectory_monodromy_action",
|
|
32
|
+
"van_vleck_prefactor",
|
|
33
|
+
"count_caustics",
|
|
34
|
+
"van_vleck_propagator_1d",
|
|
35
|
+
"frozen_gaussian_1d",
|
|
36
|
+
"coherent_state_overlap",
|
|
37
|
+
"herman_kluk_prefactor",
|
|
38
|
+
"herman_kluk_propagate_wavepacket",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@njit(cache=True)
|
|
43
|
+
def _rhs(state, dVdx, d2Vdx2, V, m, params):
|
|
44
|
+
q, p, M00, M01, M10, M11, _S = state
|
|
45
|
+
d2V = d2Vdx2(q, params)
|
|
46
|
+
out = np.empty(7)
|
|
47
|
+
out[0] = p / m
|
|
48
|
+
out[1] = -dVdx(q, params)
|
|
49
|
+
out[2] = M10 / m
|
|
50
|
+
out[3] = M11 / m
|
|
51
|
+
out[4] = -d2V * M00
|
|
52
|
+
out[5] = -d2V * M01
|
|
53
|
+
out[6] = p * p / (2.0 * m) - V(q, params)
|
|
54
|
+
return out
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@njit(cache=True)
|
|
58
|
+
def _rk4_step(state, dt, dVdx, d2Vdx2, V, m, params):
|
|
59
|
+
k1 = _rhs(state, dVdx, d2Vdx2, V, m, params)
|
|
60
|
+
k2 = _rhs(state + 0.5 * dt * k1, dVdx, d2Vdx2, V, m, params)
|
|
61
|
+
k3 = _rhs(state + 0.5 * dt * k2, dVdx, d2Vdx2, V, m, params)
|
|
62
|
+
k4 = _rhs(state + dt * k3, dVdx, d2Vdx2, V, m, params)
|
|
63
|
+
return state + (dt / 6.0) * (k1 + 2.0 * k2 + 2.0 * k3 + k4)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@njit(cache=True)
|
|
67
|
+
def _integrate(q0, p0, dt, steps, dVdx, d2Vdx2, V, m, params):
|
|
68
|
+
state = np.array([q0, p0, 1.0, 0.0, 0.0, 1.0, 0.0])
|
|
69
|
+
Mqp_hist = np.empty(steps + 1)
|
|
70
|
+
Mqp_hist[0] = 0.0
|
|
71
|
+
for i in range(steps):
|
|
72
|
+
state = _rk4_step(state, dt, dVdx, d2Vdx2, V, m, params)
|
|
73
|
+
Mqp_hist[i + 1] = state[3]
|
|
74
|
+
return state, Mqp_hist
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def propagate_trajectory_monodromy_action(q0: float, p0: float, dVdx, d2Vdx2, V, m: float, dt: float, steps: int, params: np.ndarray | None = None):
|
|
78
|
+
r"""Integrate a classical trajectory together with its monodromy matrix and Hamilton principal function.
|
|
79
|
+
|
|
80
|
+
Advances the Hamilton equations :math:`\dot q=p/m,\ \dot p=-V'(q)`
|
|
81
|
+
together with the variational (tangent) equations for small
|
|
82
|
+
deviations, :math:`\dot{\delta q}=\delta p/m,\ \dot{\delta p}
|
|
83
|
+
=-V''(q)\delta q`, whose solution operator is the monodromy matrix
|
|
84
|
+
:math:`M(t)=\begin{pmatrix}\partial q_t/\partial q_0 &
|
|
85
|
+
\partial q_t/\partial p_0\\ \partial p_t/\partial q_0 &
|
|
86
|
+
\partial p_t/\partial p_0\end{pmatrix}`, and accumulates the
|
|
87
|
+
classical action (Hamilton's principal function)
|
|
88
|
+
:math:`S(t)=\int_0^t\left[\tfrac{p^2}{2m}-V(q)\right]dt'` along the
|
|
89
|
+
way -- everything :func:`van_vleck_propagator_1d` and
|
|
90
|
+
:func:`herman_kluk_propagate_wavepacket` need from one trajectory,
|
|
91
|
+
computed in a single RK4 pass.
|
|
92
|
+
|
|
93
|
+
Because the flow is Hamiltonian, :math:`\det M(t)=1` exactly for all
|
|
94
|
+
:math:`t` (Liouville's theorem); this is a good numerical sanity
|
|
95
|
+
check on any trajectory this function returns.
|
|
96
|
+
|
|
97
|
+
Parameters
|
|
98
|
+
----------
|
|
99
|
+
q0, p0 : float
|
|
100
|
+
Initial position and momentum.
|
|
101
|
+
dVdx : callable
|
|
102
|
+
Numba-jitted force law ``dVdx(q, params) -> float``, :math:`V'(q)`.
|
|
103
|
+
d2Vdx2 : callable
|
|
104
|
+
Numba-jitted curvature ``d2Vdx2(q, params) -> float``, :math:`V''(q)`.
|
|
105
|
+
V : callable
|
|
106
|
+
Numba-jitted potential ``V(q, params) -> float``.
|
|
107
|
+
m : float
|
|
108
|
+
Particle mass.
|
|
109
|
+
dt : float
|
|
110
|
+
Time step.
|
|
111
|
+
steps : int
|
|
112
|
+
Number of RK4 steps (total propagation time is ``dt * steps``).
|
|
113
|
+
params : ndarray, optional
|
|
114
|
+
Parameter vector passed through to ``dVdx``/``d2Vdx2``/``V``.
|
|
115
|
+
Defaults to an empty array.
|
|
116
|
+
|
|
117
|
+
Returns
|
|
118
|
+
-------
|
|
119
|
+
q_t, p_t : float
|
|
120
|
+
Final position and momentum.
|
|
121
|
+
M : ndarray, shape (2, 2)
|
|
122
|
+
Monodromy matrix at time ``t = dt * steps``.
|
|
123
|
+
S : float
|
|
124
|
+
Classical action accumulated along the trajectory.
|
|
125
|
+
Mqp_history : ndarray, shape (steps + 1,)
|
|
126
|
+
:math:`\partial q_t/\partial p_0` at every step, for
|
|
127
|
+
:func:`count_caustics`.
|
|
128
|
+
|
|
129
|
+
See Also
|
|
130
|
+
--------
|
|
131
|
+
van_vleck_prefactor : Turns ``M`` into a propagator amplitude.
|
|
132
|
+
count_caustics : Turns ``Mqp_history`` into a Maslov index.
|
|
133
|
+
|
|
134
|
+
Examples
|
|
135
|
+
--------
|
|
136
|
+
For the harmonic oscillator, the monodromy matrix has the exact
|
|
137
|
+
closed form :math:`\begin{pmatrix}\cos\omega t & \sin(\omega
|
|
138
|
+
t)/(m\omega)\\ -m\omega\sin\omega t & \cos\omega t\end{pmatrix}`:
|
|
139
|
+
|
|
140
|
+
>>> import numpy as np
|
|
141
|
+
>>> from numba import njit
|
|
142
|
+
>>> m, omega = 1.0, 1.0
|
|
143
|
+
>>> params = np.array([m * omega ** 2])
|
|
144
|
+
>>> dVdx = njit(lambda q, params: params[0] * q, cache=False)
|
|
145
|
+
>>> d2Vdx2 = njit(lambda q, params: params[0], cache=False)
|
|
146
|
+
>>> V = njit(lambda q, params: 0.5 * params[0] * q ** 2, cache=False)
|
|
147
|
+
>>> t = 1.3
|
|
148
|
+
>>> q_t, p_t, M, S, _ = propagate_trajectory_monodromy_action(1.0, 0.3, dVdx, d2Vdx2, V, m, dt=t / 4000, steps=4000, params=params)
|
|
149
|
+
>>> M_exact = np.array([[np.cos(t), np.sin(t)], [-np.sin(t), np.cos(t)]])
|
|
150
|
+
>>> bool(np.max(np.abs(M - M_exact)) < 1e-6)
|
|
151
|
+
True
|
|
152
|
+
>>> round(float(np.linalg.det(M)), 8)
|
|
153
|
+
1.0
|
|
154
|
+
"""
|
|
155
|
+
if params is None:
|
|
156
|
+
params = np.empty(0)
|
|
157
|
+
state, Mqp_hist = _integrate(float(q0), float(p0), float(dt), int(steps), dVdx, d2Vdx2, V, float(m), params)
|
|
158
|
+
q_t, p_t = state[0], state[1]
|
|
159
|
+
M = np.array([[state[2], state[3]], [state[4], state[5]]])
|
|
160
|
+
S = state[6]
|
|
161
|
+
return q_t, p_t, M, S, Mqp_hist
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def van_vleck_prefactor(Mqp: float, hbar: float = 1.0) -> float:
|
|
165
|
+
r"""Van Vleck-Morette amplitude :math:`\sqrt{1/(2\pi\hbar\,|\partial q_t/\partial p_0|)}`.
|
|
166
|
+
|
|
167
|
+
The prefactor is the square root of (minus) the mixed second
|
|
168
|
+
derivative of the classical action,
|
|
169
|
+
:math:`\left|\partial^2S/\partial q_0\partial q_t\right| =
|
|
170
|
+
1/|\partial q_t/\partial p_0|` -- large where nearby trajectories
|
|
171
|
+
stay close together (many classical paths reinforce the same
|
|
172
|
+
endpoint) and formally divergent at a focal point
|
|
173
|
+
(:math:`\partial q_t/\partial p_0=0`, where infinitesimally
|
|
174
|
+
different initial momenta all reconverge on the same final position).
|
|
175
|
+
|
|
176
|
+
Parameters
|
|
177
|
+
----------
|
|
178
|
+
Mqp : float
|
|
179
|
+
The :math:`(0,1)` element of the monodromy matrix,
|
|
180
|
+
:math:`\partial q_t/\partial p_0`, from
|
|
181
|
+
:func:`propagate_trajectory_monodromy_action`.
|
|
182
|
+
hbar : float, default=1.0
|
|
183
|
+
Value of :math:`\hbar` to use.
|
|
184
|
+
|
|
185
|
+
Returns
|
|
186
|
+
-------
|
|
187
|
+
float
|
|
188
|
+
The (real, non-negative) prefactor amplitude.
|
|
189
|
+
|
|
190
|
+
Examples
|
|
191
|
+
--------
|
|
192
|
+
>>> round(van_vleck_prefactor(Mqp=1.0, hbar=1.0), 6)
|
|
193
|
+
0.398942
|
|
194
|
+
"""
|
|
195
|
+
return float(np.sqrt(1.0 / (2.0 * np.pi * hbar * abs(Mqp))))
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def count_caustics(Mqp_history: np.ndarray) -> int:
|
|
199
|
+
r"""Count sign changes of :math:`\partial q_t/\partial p_0` along a trajectory -- the Maslov index.
|
|
200
|
+
|
|
201
|
+
Each time :math:`\partial q_t/\partial p_0` passes through zero, the
|
|
202
|
+
trajectory crosses a focal point (conjugate point / caustic), and the
|
|
203
|
+
semiclassical propagator picks up an extra phase of :math:`-\pi/2`
|
|
204
|
+
(Gutzwiller 1967; see also the :math:`-\pi/4` phase at a single WKB
|
|
205
|
+
turning point in :func:`physicskit.semiclassical.core.wkb.wkb_wavefunction`,
|
|
206
|
+
which is this same phenomenon in the time-independent picture).
|
|
207
|
+
|
|
208
|
+
Parameters
|
|
209
|
+
----------
|
|
210
|
+
Mqp_history : ndarray
|
|
211
|
+
:math:`\partial q_t/\partial p_0` sampled along the trajectory,
|
|
212
|
+
from :func:`propagate_trajectory_monodromy_action`; the first
|
|
213
|
+
entry (always 0, at :math:`t=0`) is ignored.
|
|
214
|
+
|
|
215
|
+
Returns
|
|
216
|
+
-------
|
|
217
|
+
int
|
|
218
|
+
The Maslov index :math:`\mu`.
|
|
219
|
+
|
|
220
|
+
See Also
|
|
221
|
+
--------
|
|
222
|
+
van_vleck_propagator_1d : Uses this to fix the propagator's overall phase.
|
|
223
|
+
|
|
224
|
+
Examples
|
|
225
|
+
--------
|
|
226
|
+
>>> count_caustics(np.array([0.0, 1.0, 0.5, -0.3, -0.8, 0.2]))
|
|
227
|
+
2
|
|
228
|
+
"""
|
|
229
|
+
nonzero = Mqp_history[1:]
|
|
230
|
+
nonzero = nonzero[nonzero != 0]
|
|
231
|
+
return int(np.sum(np.diff(np.sign(nonzero)) != 0))
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def van_vleck_propagator_1d(q0: float, p0: float, dVdx, d2Vdx2, V, m: float, dt: float, steps: int, hbar: float = 1.0, params: np.ndarray | None = None):
|
|
235
|
+
r"""Semiclassical (Van Vleck-Morette) propagator amplitude along one classical trajectory.
|
|
236
|
+
|
|
237
|
+
.. math::
|
|
238
|
+
|
|
239
|
+
K(q_t,t;q_0,0) \approx \sqrt{\frac{1}{2\pi\hbar\,|\partial q_t/\partial p_0|}}\,
|
|
240
|
+
\exp\!\left[\frac{i}{\hbar}S(t) - i\frac{\pi}{4} - i\mu\frac{\pi}{2}\right],
|
|
241
|
+
|
|
242
|
+
the leading-order (:math:`\hbar\to0`) approximation to the quantum
|
|
243
|
+
propagator, exact whenever the potential is at most quadratic (the
|
|
244
|
+
free particle and the harmonic oscillator), since then the WKB
|
|
245
|
+
expansion this formula comes from truncates exactly.
|
|
246
|
+
|
|
247
|
+
Parameters
|
|
248
|
+
----------
|
|
249
|
+
q0, p0 : float
|
|
250
|
+
Initial position and momentum. ``p0`` fixes which trajectory
|
|
251
|
+
(and hence which final position ``q_t``) is used; this function
|
|
252
|
+
does not solve the two-point boundary-value problem of finding
|
|
253
|
+
the ``p0`` that reaches a *prescribed* ``q_t``.
|
|
254
|
+
dVdx, d2Vdx2, V : callable
|
|
255
|
+
Numba-jitted potential derivatives and the potential itself, as
|
|
256
|
+
in :func:`propagate_trajectory_monodromy_action`.
|
|
257
|
+
m : float
|
|
258
|
+
Particle mass.
|
|
259
|
+
dt : float
|
|
260
|
+
Time step.
|
|
261
|
+
steps : int
|
|
262
|
+
Number of RK4 steps.
|
|
263
|
+
hbar : float, default=1.0
|
|
264
|
+
Value of :math:`\hbar` to use.
|
|
265
|
+
params : ndarray, optional
|
|
266
|
+
Parameter vector passed through to ``dVdx``/``d2Vdx2``/``V``.
|
|
267
|
+
|
|
268
|
+
Returns
|
|
269
|
+
-------
|
|
270
|
+
q_t : float
|
|
271
|
+
The trajectory's final position.
|
|
272
|
+
K : complex
|
|
273
|
+
The semiclassical propagator amplitude :math:`K(q_t,t;q_0,0)`.
|
|
274
|
+
|
|
275
|
+
See Also
|
|
276
|
+
--------
|
|
277
|
+
propagate_trajectory_monodromy_action : Supplies the trajectory, monodromy, and action.
|
|
278
|
+
herman_kluk_propagate_wavepacket : Sums many such trajectories into a full wavepacket propagator.
|
|
279
|
+
|
|
280
|
+
Examples
|
|
281
|
+
--------
|
|
282
|
+
A free particle's semiclassical propagator matches the exact quantum
|
|
283
|
+
propagator :math:`\sqrt{m/(2\pi i\hbar t)}\exp[im(q_t-q_0)^2/(2\hbar t)]` exactly:
|
|
284
|
+
|
|
285
|
+
>>> import numpy as np
|
|
286
|
+
>>> from numba import njit
|
|
287
|
+
>>> zero = njit(lambda q, params: 0.0, cache=False)
|
|
288
|
+
>>> q_t, K = van_vleck_propagator_1d(q0=0.0, p0=1.0, dVdx=zero, d2Vdx2=zero, V=zero, m=1.0, dt=1.0 / 2000, steps=2000)
|
|
289
|
+
>>> K_exact = np.sqrt(1.0 / (2j * np.pi * 1.0)) * np.exp(1j * (q_t - 0.0) ** 2 / 2.0)
|
|
290
|
+
>>> bool(abs(K - K_exact) < 1e-6)
|
|
291
|
+
True
|
|
292
|
+
|
|
293
|
+
A harmonic-oscillator trajectory that has not yet crossed a focal
|
|
294
|
+
point (:math:`t<\pi/\omega`) matches the exact Van Vleck (Mehler)
|
|
295
|
+
propagator just as closely:
|
|
296
|
+
|
|
297
|
+
>>> m, omega = 1.0, 1.0
|
|
298
|
+
>>> params = np.array([m * omega ** 2])
|
|
299
|
+
>>> dVdx = njit(lambda q, params: params[0] * q, cache=False)
|
|
300
|
+
>>> d2Vdx2 = njit(lambda q, params: params[0], cache=False)
|
|
301
|
+
>>> V = njit(lambda q, params: 0.5 * params[0] * q ** 2, cache=False)
|
|
302
|
+
>>> q0, p0, t = 1.0, 0.3, 1.3
|
|
303
|
+
>>> q_t, K = van_vleck_propagator_1d(q0, p0, dVdx, d2Vdx2, V, m, dt=t / 4000, steps=4000, params=params)
|
|
304
|
+
>>> K_exact = (np.sqrt(m * omega / (2j * np.pi * np.sin(omega * t)))
|
|
305
|
+
... * np.exp(1j * m * omega / (2 * np.sin(omega * t)) * ((q_t ** 2 + q0 ** 2) * np.cos(omega * t) - 2 * q_t * q0)))
|
|
306
|
+
>>> bool(abs(K - K_exact) < 1e-5)
|
|
307
|
+
True
|
|
308
|
+
"""
|
|
309
|
+
q_t, _p_t, M, S, Mqp_hist = propagate_trajectory_monodromy_action(q0, p0, dVdx, d2Vdx2, V, m, dt, steps, params)
|
|
310
|
+
mu = count_caustics(Mqp_hist)
|
|
311
|
+
prefactor = van_vleck_prefactor(M[0, 1], hbar)
|
|
312
|
+
phase = S / hbar - np.pi / 4.0 - mu * np.pi / 2.0
|
|
313
|
+
K = prefactor * np.exp(1j * phase)
|
|
314
|
+
return q_t, K
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def frozen_gaussian_1d(x: np.ndarray, qc: float, pc: float, gamma: float, hbar: float = 1.0) -> np.ndarray:
|
|
318
|
+
r"""A normalized, fixed-width ("frozen") Gaussian wavepacket (coherent state).
|
|
319
|
+
|
|
320
|
+
.. math::
|
|
321
|
+
|
|
322
|
+
g_{q_c,p_c}(x) = \left(\frac{2\gamma}{\pi}\right)^{1/4}
|
|
323
|
+
\exp\!\left[-\gamma(x-q_c)^2 + \frac{i}{\hbar}p_c(x-q_c)\right].
|
|
324
|
+
|
|
325
|
+
The building block of the Herman-Kluk method: every trajectory
|
|
326
|
+
carries one of these, always at the fixed width set by :math:`\gamma`
|
|
327
|
+
(hence "frozen"), riding on top of its classical phase-space point
|
|
328
|
+
:math:`(q_c,p_c)`.
|
|
329
|
+
|
|
330
|
+
Parameters
|
|
331
|
+
----------
|
|
332
|
+
x : ndarray
|
|
333
|
+
Positions at which to evaluate the wavepacket.
|
|
334
|
+
qc, pc : float
|
|
335
|
+
Center of the Gaussian in position and momentum.
|
|
336
|
+
gamma : float
|
|
337
|
+
Width parameter (inverse squared length); larger :math:`\gamma`
|
|
338
|
+
means a narrower, more position-localized packet.
|
|
339
|
+
hbar : float, default=1.0
|
|
340
|
+
Value of :math:`\hbar` to use.
|
|
341
|
+
|
|
342
|
+
Returns
|
|
343
|
+
-------
|
|
344
|
+
ndarray of complex
|
|
345
|
+
:math:`g_{q_c,p_c}(x)`, same shape as ``x``.
|
|
346
|
+
|
|
347
|
+
See Also
|
|
348
|
+
--------
|
|
349
|
+
coherent_state_overlap : The closed-form overlap of two such Gaussians.
|
|
350
|
+
|
|
351
|
+
Examples
|
|
352
|
+
--------
|
|
353
|
+
>>> import numpy as np
|
|
354
|
+
>>> x = np.linspace(-20, 20, 4000)
|
|
355
|
+
>>> psi = frozen_gaussian_1d(x, qc=1.0, pc=2.0, gamma=0.5)
|
|
356
|
+
>>> round(float(np.trapezoid(np.abs(psi) ** 2, x)), 8)
|
|
357
|
+
1.0
|
|
358
|
+
"""
|
|
359
|
+
norm = (2.0 * gamma / np.pi) ** 0.25
|
|
360
|
+
return norm * np.exp(-gamma * (x - qc) ** 2 + 1j * pc * (x - qc) / hbar)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def coherent_state_overlap(q1: float, p1: float, q2: float, p2: float, gamma: float, hbar: float = 1.0) -> complex:
|
|
364
|
+
r"""Closed-form overlap :math:`\langle g_{q_1,p_1}|g_{q_2,p_2}\rangle` of two equal-width frozen Gaussians.
|
|
365
|
+
|
|
366
|
+
.. math::
|
|
367
|
+
|
|
368
|
+
\langle g_1|g_2\rangle = \exp\!\left[-\frac{\gamma}{2}(q_1-q_2)^2
|
|
369
|
+
- \frac{(p_1-p_2)^2}{8\gamma\hbar^2}
|
|
370
|
+
+ \frac{i}{2\hbar}(q_1-q_2)(p_1+p_2)\right].
|
|
371
|
+
|
|
372
|
+
Parameters
|
|
373
|
+
----------
|
|
374
|
+
q1, p1 : float
|
|
375
|
+
Phase-space center of the bra state.
|
|
376
|
+
q2, p2 : float
|
|
377
|
+
Phase-space center of the ket state.
|
|
378
|
+
gamma : float
|
|
379
|
+
Shared width parameter, as in :func:`frozen_gaussian_1d`.
|
|
380
|
+
hbar : float, default=1.0
|
|
381
|
+
Value of :math:`\hbar` to use.
|
|
382
|
+
|
|
383
|
+
Returns
|
|
384
|
+
-------
|
|
385
|
+
complex
|
|
386
|
+
The overlap :math:`\langle g_1|g_2\rangle`.
|
|
387
|
+
|
|
388
|
+
See Also
|
|
389
|
+
--------
|
|
390
|
+
frozen_gaussian_1d : The states being overlapped.
|
|
391
|
+
|
|
392
|
+
Examples
|
|
393
|
+
--------
|
|
394
|
+
Matches direct numerical integration of the two wavepackets:
|
|
395
|
+
|
|
396
|
+
>>> import numpy as np
|
|
397
|
+
>>> x = np.linspace(-40, 40, 20000)
|
|
398
|
+
>>> gamma = 1.0
|
|
399
|
+
>>> psi1 = frozen_gaussian_1d(x, qc=0.3, pc=0.7, gamma=gamma)
|
|
400
|
+
>>> psi2 = frozen_gaussian_1d(x, qc=-0.2, pc=1.1, gamma=gamma)
|
|
401
|
+
>>> numeric = np.trapezoid(np.conj(psi1) * psi2, x)
|
|
402
|
+
>>> closed_form = coherent_state_overlap(0.3, 0.7, -0.2, 1.1, gamma)
|
|
403
|
+
>>> bool(abs(numeric - closed_form) < 1e-6)
|
|
404
|
+
True
|
|
405
|
+
|
|
406
|
+
A state's overlap with itself is 1:
|
|
407
|
+
|
|
408
|
+
>>> round(float(abs(coherent_state_overlap(1.0, 2.0, 1.0, 2.0, gamma=0.8))), 8)
|
|
409
|
+
1.0
|
|
410
|
+
"""
|
|
411
|
+
return np.exp(-gamma / 2.0 * (q1 - q2) ** 2 - (p1 - p2) ** 2 / (8.0 * gamma * hbar**2) + 1j * (q1 - q2) * (p1 + p2) / (2.0 * hbar))
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def herman_kluk_prefactor(M: np.ndarray, gamma: float, hbar: float = 1.0) -> complex:
|
|
415
|
+
r"""Herman-Kluk prefactor :math:`C_t(q_0,p_0)` built from the monodromy matrix.
|
|
416
|
+
|
|
417
|
+
.. math::
|
|
418
|
+
|
|
419
|
+
C_t = \sqrt{\frac{1}{2}\left(M_{qq} + M_{pp}
|
|
420
|
+
- i\hbar\gamma M_{qp} + \frac{i}{\hbar\gamma}M_{pq}\right)},
|
|
421
|
+
|
|
422
|
+
which reduces to :math:`C_t=1` at :math:`t=0` (:math:`M=\mathbb{1}`),
|
|
423
|
+
consistent with the frozen Gaussian basis's resolution of the
|
|
424
|
+
identity, :math:`\int \tfrac{dq\,dp}{2\pi\hbar}\,|g_{q,p}\rangle\langle
|
|
425
|
+
g_{q,p}| = \hat{1}`.
|
|
426
|
+
|
|
427
|
+
Parameters
|
|
428
|
+
----------
|
|
429
|
+
M : ndarray, shape (2, 2)
|
|
430
|
+
Monodromy matrix from :func:`propagate_trajectory_monodromy_action`.
|
|
431
|
+
gamma : float
|
|
432
|
+
Frozen-Gaussian width parameter, as in :func:`frozen_gaussian_1d`.
|
|
433
|
+
hbar : float, default=1.0
|
|
434
|
+
Value of :math:`\hbar` to use.
|
|
435
|
+
|
|
436
|
+
Returns
|
|
437
|
+
-------
|
|
438
|
+
complex
|
|
439
|
+
The prefactor :math:`C_t`.
|
|
440
|
+
|
|
441
|
+
Examples
|
|
442
|
+
--------
|
|
443
|
+
>>> import numpy as np
|
|
444
|
+
>>> complex(herman_kluk_prefactor(np.eye(2), gamma=1.0))
|
|
445
|
+
(1+0j)
|
|
446
|
+
"""
|
|
447
|
+
Mqq, Mqp, Mpq, Mpp = M[0, 0], M[0, 1], M[1, 0], M[1, 1]
|
|
448
|
+
val = 0.5 * (Mqq + Mpp - 1j * hbar * gamma * Mqp + 1j * Mpq / (hbar * gamma))
|
|
449
|
+
return np.sqrt(val + 0j)
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
def herman_kluk_propagate_wavepacket(
|
|
453
|
+
qc0: float,
|
|
454
|
+
pc0: float,
|
|
455
|
+
gamma: float,
|
|
456
|
+
dVdx,
|
|
457
|
+
d2Vdx2,
|
|
458
|
+
V,
|
|
459
|
+
m: float,
|
|
460
|
+
dt: float,
|
|
461
|
+
steps: int,
|
|
462
|
+
x_eval: np.ndarray,
|
|
463
|
+
hbar: float = 1.0,
|
|
464
|
+
n_grid: int = 41,
|
|
465
|
+
n_sigma: float = 6.0,
|
|
466
|
+
params: np.ndarray | None = None,
|
|
467
|
+
) -> np.ndarray:
|
|
468
|
+
r"""Propagate an initial frozen-Gaussian wavepacket with the multi-trajectory Herman-Kluk method.
|
|
469
|
+
|
|
470
|
+
Launches one classical trajectory from every point of a regular grid
|
|
471
|
+
covering the initial coherent state's phase-space support, and sums
|
|
472
|
+
their frozen-Gaussian contributions
|
|
473
|
+
|
|
474
|
+
.. math::
|
|
475
|
+
|
|
476
|
+
\psi(x,t) \approx \int\!\frac{dq_0\,dp_0}{2\pi\hbar}\,
|
|
477
|
+
C_t(q_0,p_0)\,e^{iS(t)/\hbar}\,
|
|
478
|
+
\langle g_{q_0,p_0}|\psi_0\rangle\, g_{q_t,p_t}(x),
|
|
479
|
+
|
|
480
|
+
approximating the integral over initial conditions by a Riemann sum
|
|
481
|
+
on a grid spanning :math:`\pm n_\sigma` standard deviations of the
|
|
482
|
+
initial coherent state's own phase-space Gaussian
|
|
483
|
+
(:math:`\sigma_q=1/(2\sqrt\gamma)`, :math:`\sigma_p=\hbar\sqrt\gamma`).
|
|
484
|
+
The per-trajectory classical propagation
|
|
485
|
+
(:func:`propagate_trajectory_monodromy_action`) is Numba-compiled,
|
|
486
|
+
since it is called once per grid point -- the dominant cost for any
|
|
487
|
+
reasonably fine grid.
|
|
488
|
+
|
|
489
|
+
In the :math:`t\to0` limit this reduces to the frozen-Gaussian
|
|
490
|
+
resolution of the identity and reconstructs the initial wavepacket
|
|
491
|
+
essentially exactly; away from that limit, this quadrature-grid
|
|
492
|
+
evaluation of the Herman-Kluk integral does not exactly conserve
|
|
493
|
+
:math:`\int|\psi|^2\,dx` (the true continuous phase-space integral
|
|
494
|
+
does, for at-most-quadratic potentials) -- convergence in ``n_grid``,
|
|
495
|
+
``n_sigma``, and ``gamma`` should be checked for any serious use.
|
|
496
|
+
|
|
497
|
+
Parameters
|
|
498
|
+
----------
|
|
499
|
+
qc0, pc0 : float
|
|
500
|
+
Center of the initial frozen-Gaussian wavepacket.
|
|
501
|
+
gamma : float
|
|
502
|
+
Width parameter shared by the initial state and every frozen
|
|
503
|
+
Gaussian in the propagation.
|
|
504
|
+
dVdx, d2Vdx2, V : callable
|
|
505
|
+
Numba-jitted potential derivatives and the potential itself, as
|
|
506
|
+
in :func:`propagate_trajectory_monodromy_action`.
|
|
507
|
+
m : float
|
|
508
|
+
Particle mass.
|
|
509
|
+
dt : float
|
|
510
|
+
Time step for each trajectory's RK4 integration.
|
|
511
|
+
steps : int
|
|
512
|
+
Number of RK4 steps (propagation time is ``dt * steps``).
|
|
513
|
+
x_eval : ndarray
|
|
514
|
+
Positions at which to evaluate the propagated wavepacket.
|
|
515
|
+
hbar : float, default=1.0
|
|
516
|
+
Value of :math:`\hbar` to use.
|
|
517
|
+
n_grid : int, default=41
|
|
518
|
+
Number of grid points along each of the :math:`q_0`, :math:`p_0` axes.
|
|
519
|
+
n_sigma : float, default=6.0
|
|
520
|
+
Half-width of the sampling grid, in standard deviations of the
|
|
521
|
+
initial state's phase-space Gaussian.
|
|
522
|
+
params : ndarray, optional
|
|
523
|
+
Parameter vector passed through to ``dVdx``/``d2Vdx2``/``V``.
|
|
524
|
+
|
|
525
|
+
Returns
|
|
526
|
+
-------
|
|
527
|
+
ndarray of complex, shape matching ``x_eval``
|
|
528
|
+
The propagated wavepacket :math:`\psi(x,t)`.
|
|
529
|
+
|
|
530
|
+
See Also
|
|
531
|
+
--------
|
|
532
|
+
van_vleck_propagator_1d : The single-trajectory propagator this sums many copies of.
|
|
533
|
+
frozen_gaussian_1d : The initial state and the basis each trajectory carries.
|
|
534
|
+
|
|
535
|
+
Examples
|
|
536
|
+
--------
|
|
537
|
+
At very short times the sum reduces to the frozen-Gaussian
|
|
538
|
+
resolution of the identity and reproduces the (unpropagated) initial
|
|
539
|
+
coherent state to high accuracy:
|
|
540
|
+
|
|
541
|
+
>>> import numpy as np
|
|
542
|
+
>>> from numba import njit
|
|
543
|
+
>>> m, omega = 1.0, 1.0
|
|
544
|
+
>>> params = np.array([m * omega ** 2])
|
|
545
|
+
>>> dVdx = njit(lambda q, params: params[0] * q, cache=False)
|
|
546
|
+
>>> d2Vdx2 = njit(lambda q, params: params[0], cache=False)
|
|
547
|
+
>>> V = njit(lambda q, params: 0.5 * params[0] * q ** 2, cache=False)
|
|
548
|
+
>>> x = np.linspace(-6, 6, 400)
|
|
549
|
+
>>> psi = herman_kluk_propagate_wavepacket(
|
|
550
|
+
... 1.0, 0.0, gamma=1.0, dVdx=dVdx, d2Vdx2=d2Vdx2, V=V, m=m, dt=1e-6, steps=1, x_eval=x, n_grid=61, n_sigma=7.0, params=params
|
|
551
|
+
... )
|
|
552
|
+
>>> psi0 = frozen_gaussian_1d(x, qc=1.0, pc=0.0, gamma=1.0)
|
|
553
|
+
>>> fidelity = abs(np.trapezoid(np.conj(psi0) * psi, x)) ** 2
|
|
554
|
+
>>> bool(fidelity > 0.999)
|
|
555
|
+
True
|
|
556
|
+
"""
|
|
557
|
+
if params is None:
|
|
558
|
+
params = np.empty(0)
|
|
559
|
+
sigma_q = 1.0 / (2.0 * np.sqrt(gamma))
|
|
560
|
+
sigma_p = hbar * np.sqrt(gamma)
|
|
561
|
+
q0_grid = np.linspace(qc0 - n_sigma * sigma_q, qc0 + n_sigma * sigma_q, n_grid)
|
|
562
|
+
p0_grid = np.linspace(pc0 - n_sigma * sigma_p, pc0 + n_sigma * sigma_p, n_grid)
|
|
563
|
+
dq0 = q0_grid[1] - q0_grid[0]
|
|
564
|
+
dp0 = p0_grid[1] - p0_grid[0]
|
|
565
|
+
measure = dq0 * dp0 / (2.0 * np.pi * hbar)
|
|
566
|
+
|
|
567
|
+
psi = np.zeros_like(x_eval, dtype=complex)
|
|
568
|
+
for q0 in q0_grid:
|
|
569
|
+
# pragma: no cover on the inner loop below -- coverage.py mismeasures
|
|
570
|
+
# this whole clause as unreached even though it demonstrably runs
|
|
571
|
+
# (verified by direct print-instrumentation), under
|
|
572
|
+
# test_herman_kluk_reconstructs_initial_state_at_short_time and
|
|
573
|
+
# test_herman_kluk_defaults_params_to_an_empty_array_when_unused.
|
|
574
|
+
for p0 in p0_grid: # pragma: no cover
|
|
575
|
+
q_t, p_t, M, S, _ = propagate_trajectory_monodromy_action(q0, p0, dVdx, d2Vdx2, V, m, dt, steps, params)
|
|
576
|
+
C = herman_kluk_prefactor(M, gamma, hbar)
|
|
577
|
+
ov = coherent_state_overlap(q0, p0, qc0, pc0, gamma, hbar)
|
|
578
|
+
psi += measure * C * np.exp(1j * S / hbar) * ov * frozen_gaussian_1d(x_eval, q_t, p_t, gamma, hbar)
|
|
579
|
+
return psi
|