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,510 @@
|
|
|
1
|
+
"""Gross-Pitaevskii mean-field theory for trapped, rotating Bose-Einstein condensates.
|
|
2
|
+
|
|
3
|
+
Solves the time-dependent Gross-Pitaevskii equation (GPE)
|
|
4
|
+
|
|
5
|
+
.. math::
|
|
6
|
+
|
|
7
|
+
i\\partial_t\\psi = \\Big[-\\tfrac{1}{2}\\nabla^2 + V(\\mathbf{r}) + g|\\psi|^2 - \\Omega L_z\\Big]\\psi
|
|
8
|
+
|
|
9
|
+
in the rotating frame (units :math:`\\hbar=m=1`) by imaginary-time
|
|
10
|
+
propagation (:math:`\\tau=it`), which turns the Schrodinger-like evolution
|
|
11
|
+
into a gradient flow that relaxes any initial state toward a stationary
|
|
12
|
+
point of the rotating-frame energy. The kinetic and potential/interaction
|
|
13
|
+
terms are each handled exactly in their natural representation (spectral
|
|
14
|
+
and real-space respectively, split-step); the angular-momentum term
|
|
15
|
+
:math:`\\Omega L_z` is advanced explicitly via centered finite differences,
|
|
16
|
+
which is non-stiff at the small imaginary-time steps used here.
|
|
17
|
+
|
|
18
|
+
A single quantized vortex, imprinted by multiplying the wavefunction by
|
|
19
|
+
:math:`(x-x_0)+i(y-y_0)`, is used throughout as the worked example of a
|
|
20
|
+
"vortex lattice" building block: :func:`gpe_relax` finds it as a genuine
|
|
21
|
+
stationary GPE solution, and comparing its rotating-frame energy against
|
|
22
|
+
the vortex-free ground state reproduces the standard textbook criterion
|
|
23
|
+
for the critical rotation frequency :math:`\\Omega_c` above which nucleating
|
|
24
|
+
a vortex lowers the energy.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from __future__ import annotations
|
|
28
|
+
|
|
29
|
+
import numpy as np
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
"harmonic_trap_grid",
|
|
33
|
+
"gpe_imprint_vortex",
|
|
34
|
+
"gpe_relax",
|
|
35
|
+
"gpe_evolve",
|
|
36
|
+
"gpe_energy",
|
|
37
|
+
"count_vortices",
|
|
38
|
+
"casimir_mode_frequencies",
|
|
39
|
+
"casimir_energy_1d",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def harmonic_trap_grid(n: int, length: float) -> tuple:
|
|
44
|
+
"""Build a centered real-space and wavenumber grid for a 2D harmonic trap.
|
|
45
|
+
|
|
46
|
+
Parameters
|
|
47
|
+
----------
|
|
48
|
+
n : int
|
|
49
|
+
Number of grid points along each axis.
|
|
50
|
+
length : float
|
|
51
|
+
Physical domain size (the domain is ``[-length/2, length/2)``).
|
|
52
|
+
|
|
53
|
+
Returns
|
|
54
|
+
-------
|
|
55
|
+
X, Y : ndarray, shape (n, n)
|
|
56
|
+
Real-space coordinate grids, centered at the trap origin.
|
|
57
|
+
KX, KY : ndarray, shape (n, n)
|
|
58
|
+
Wavenumber grids.
|
|
59
|
+
K2 : ndarray, shape (n, n)
|
|
60
|
+
:math:`K_X^2 + K_Y^2`.
|
|
61
|
+
|
|
62
|
+
Examples
|
|
63
|
+
--------
|
|
64
|
+
>>> X, Y, KX, KY, K2 = harmonic_trap_grid(32, 12.0)
|
|
65
|
+
>>> float(X[0, 0])
|
|
66
|
+
-6.0
|
|
67
|
+
"""
|
|
68
|
+
x = np.linspace(-length / 2, length / 2, n, endpoint=False)
|
|
69
|
+
X, Y = np.meshgrid(x, x, indexing="ij")
|
|
70
|
+
k = 2 * np.pi * np.fft.fftfreq(n, d=length / n)
|
|
71
|
+
KX, KY = np.meshgrid(k, k, indexing="ij")
|
|
72
|
+
K2 = KX**2 + KY**2
|
|
73
|
+
return X, Y, KX, KY, K2
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def gpe_imprint_vortex(psi: np.ndarray, X: np.ndarray, Y: np.ndarray, positions) -> np.ndarray:
|
|
77
|
+
"""Imprint one singly-quantized vortex per position by multiplying in a phase winding.
|
|
78
|
+
|
|
79
|
+
Parameters
|
|
80
|
+
----------
|
|
81
|
+
psi : ndarray of complex, shape (n, n)
|
|
82
|
+
Wavefunction to imprint onto.
|
|
83
|
+
X, Y : ndarray, shape (n, n)
|
|
84
|
+
Real-space coordinate grids from :func:`harmonic_trap_grid`.
|
|
85
|
+
positions : sequence of tuple(float, float)
|
|
86
|
+
``(x0, y0)`` center of each vortex to imprint.
|
|
87
|
+
|
|
88
|
+
Returns
|
|
89
|
+
-------
|
|
90
|
+
ndarray of complex, shape (n, n)
|
|
91
|
+
``psi`` multiplied by :math:`\\prod_i [(x-x_{0,i}) + i(y-y_{0,i})]`,
|
|
92
|
+
renormalized to preserve the input norm.
|
|
93
|
+
|
|
94
|
+
Examples
|
|
95
|
+
--------
|
|
96
|
+
>>> import numpy as np
|
|
97
|
+
>>> X, Y, KX, KY, K2 = harmonic_trap_grid(32, 12.0)
|
|
98
|
+
>>> psi0 = np.exp(-0.5 * (X ** 2 + Y ** 2)).astype(complex)
|
|
99
|
+
>>> psi = gpe_imprint_vortex(psi0, X, Y, [(0.0, 0.0)])
|
|
100
|
+
>>> bool(abs(psi[16, 16]) < 1e-10)
|
|
101
|
+
True
|
|
102
|
+
"""
|
|
103
|
+
dx = X[1, 0] - X[0, 0]
|
|
104
|
+
norm0 = np.sum(np.abs(psi) ** 2) * dx * dx
|
|
105
|
+
out = psi.astype(complex).copy()
|
|
106
|
+
for x0, y0 in positions:
|
|
107
|
+
out = out * ((X - x0) + 1j * (Y - y0))
|
|
108
|
+
norm1 = np.sum(np.abs(out) ** 2) * dx * dx
|
|
109
|
+
return out * np.sqrt(norm0 / norm1)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def gpe_relax(
|
|
113
|
+
psi0: np.ndarray,
|
|
114
|
+
V: np.ndarray,
|
|
115
|
+
g: float,
|
|
116
|
+
dtau: float,
|
|
117
|
+
steps: int,
|
|
118
|
+
X: np.ndarray,
|
|
119
|
+
Y: np.ndarray,
|
|
120
|
+
K2: np.ndarray,
|
|
121
|
+
Omega: float = 0.0,
|
|
122
|
+
n_particles: float = 1.0,
|
|
123
|
+
) -> np.ndarray:
|
|
124
|
+
"""Relax a GPE initial condition toward a stationary state via imaginary-time propagation.
|
|
125
|
+
|
|
126
|
+
Parameters
|
|
127
|
+
----------
|
|
128
|
+
psi0 : ndarray of complex, shape (n, n)
|
|
129
|
+
Initial wavefunction.
|
|
130
|
+
V : ndarray, shape (n, n)
|
|
131
|
+
External trapping potential.
|
|
132
|
+
g : float
|
|
133
|
+
Interaction (nonlinearity) strength.
|
|
134
|
+
dtau : float
|
|
135
|
+
Imaginary-time step.
|
|
136
|
+
steps : int
|
|
137
|
+
Number of steps to advance.
|
|
138
|
+
X, Y, K2 : ndarray, shape (n, n)
|
|
139
|
+
Grids from :func:`harmonic_trap_grid` (``KX``, ``KY`` are not needed here).
|
|
140
|
+
Omega : float, default=0.0
|
|
141
|
+
Rotation frequency of the trap.
|
|
142
|
+
n_particles : float, default=1.0
|
|
143
|
+
Total particle number; the wavefunction is renormalized to this
|
|
144
|
+
value after every step (imaginary-time propagation does not
|
|
145
|
+
conserve norm on its own).
|
|
146
|
+
|
|
147
|
+
Returns
|
|
148
|
+
-------
|
|
149
|
+
ndarray of complex, shape (n, n)
|
|
150
|
+
The relaxed (approximately stationary) wavefunction.
|
|
151
|
+
|
|
152
|
+
See Also
|
|
153
|
+
--------
|
|
154
|
+
gpe_energy : Evaluate the energy of a relaxed state.
|
|
155
|
+
gpe_imprint_vortex : Seed an initial condition with quantized vortices.
|
|
156
|
+
|
|
157
|
+
Notes
|
|
158
|
+
-----
|
|
159
|
+
Energy decreases monotonically under this propagation whenever it is
|
|
160
|
+
implemented correctly (a basic sanity check worth verifying on any new
|
|
161
|
+
potential or parameter regime).
|
|
162
|
+
|
|
163
|
+
Examples
|
|
164
|
+
--------
|
|
165
|
+
Comparing the rotating-frame energy of the vortex-free ground state
|
|
166
|
+
against a state seeded with one centered vortex reproduces the
|
|
167
|
+
standard vortex-nucleation criterion: :math:`\\Omega_c = \\Delta E/\\Delta L_z`,
|
|
168
|
+
above which the vortex state has lower energy in the rotating frame:
|
|
169
|
+
|
|
170
|
+
>>> import numpy as np
|
|
171
|
+
>>> n, length, g = 64, 12.0, 4.0
|
|
172
|
+
>>> X, Y, KX, KY, K2 = harmonic_trap_grid(n, length)
|
|
173
|
+
>>> V = 0.5 * (X ** 2 + Y ** 2)
|
|
174
|
+
>>> psi_vf = gpe_relax(np.exp(-0.5 * (X**2 + Y**2)).astype(complex), V, g, dtau=5e-4, steps=4000, X=X, Y=Y, K2=K2)
|
|
175
|
+
>>> psi0_v = gpe_imprint_vortex(np.exp(-0.5 * (X**2 + Y**2)).astype(complex), X, Y, [(0.0, 0.0)])
|
|
176
|
+
>>> psi_v = gpe_relax(psi0_v, V, g, dtau=5e-4, steps=4000, X=X, Y=Y, K2=K2)
|
|
177
|
+
>>> E0, E1 = gpe_energy(psi_vf, V, g, X, Y, K2), gpe_energy(psi_v, V, g, X, Y, K2)
|
|
178
|
+
>>> Omega_c = (E1["total"] - E0["total"]) / (E1["angular_momentum"] - E0["angular_momentum"])
|
|
179
|
+
>>> bool(0.0 < Omega_c < 1.0)
|
|
180
|
+
True
|
|
181
|
+
"""
|
|
182
|
+
dx = X[1, 0] - X[0, 0]
|
|
183
|
+
psi = np.array(psi0, dtype=complex, copy=True)
|
|
184
|
+
norm = np.sum(np.abs(psi) ** 2) * dx * dx
|
|
185
|
+
psi *= np.sqrt(n_particles / norm)
|
|
186
|
+
for _ in range(steps):
|
|
187
|
+
psi *= np.exp(-dtau * (V + g * np.abs(psi) ** 2))
|
|
188
|
+
if Omega != 0.0:
|
|
189
|
+
dpsidx = (np.roll(psi, -1, axis=0) - np.roll(psi, 1, axis=0)) / (2 * dx)
|
|
190
|
+
dpsidy = (np.roll(psi, -1, axis=1) - np.roll(psi, 1, axis=1)) / (2 * dx)
|
|
191
|
+
psi = psi - 1j * dtau * Omega * (X * dpsidy - Y * dpsidx)
|
|
192
|
+
psi_hat = np.fft.fft2(psi)
|
|
193
|
+
psi_hat *= np.exp(-dtau * 0.5 * K2)
|
|
194
|
+
psi = np.fft.ifft2(psi_hat)
|
|
195
|
+
norm = np.sum(np.abs(psi) ** 2) * dx * dx
|
|
196
|
+
psi *= np.sqrt(n_particles / norm)
|
|
197
|
+
return psi
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def gpe_evolve(psi0: np.ndarray, V: np.ndarray, g: float, dt: float, steps: int, K2: np.ndarray, snapshot_stride: int = 1) -> tuple:
|
|
201
|
+
"""Real-time propagation of the 2D Gross-Pitaevskii / cubic NLS equation via split-step Fourier.
|
|
202
|
+
|
|
203
|
+
Solves :math:`i\\partial_t\\psi = [-\\tfrac{1}{2}\\nabla^2 + V + g|\\psi|^2]\\psi`
|
|
204
|
+
forward in *real* time (unlike :func:`gpe_relax`'s imaginary-time
|
|
205
|
+
relaxation, which only finds stationary states): the kinetic term is
|
|
206
|
+
exact in Fourier space, and the potential-plus-nonlinear term is exact
|
|
207
|
+
as a pointwise phase rotation in real space, the same split-step
|
|
208
|
+
structure as :func:`physicskit.fields.solitons.nls_evolve` generalized
|
|
209
|
+
to 2D and to an external potential. Real-time evolution is unitary and
|
|
210
|
+
conserves the norm on its own (no renormalization needed, unlike
|
|
211
|
+
imaginary time).
|
|
212
|
+
|
|
213
|
+
This one stepper serves two purposes, distinguished only by ``V`` and
|
|
214
|
+
the sign of ``g``:
|
|
215
|
+
|
|
216
|
+
- With a harmonic trap (``V = 0.5*(X**2+Y**2)``) and repulsive
|
|
217
|
+
interactions (``g > 0``), an off-center vortex genuinely precesses
|
|
218
|
+
around the trap under the density gradient -- real vortex dynamics,
|
|
219
|
+
as opposed to the static relaxed state :func:`gpe_relax` finds.
|
|
220
|
+
- With ``V = 0`` (or weak) and attractive interactions (``g < 0``
|
|
221
|
+
here, opposite sign convention from ``nls_evolve``'s ``g`` since this
|
|
222
|
+
module's equation carries a ``+g|psi|^2`` term), a sufficiently tall,
|
|
223
|
+
narrow initial packet self-focuses, concentrating into a narrower,
|
|
224
|
+
taller peak -- a numerical stand-in for wave collapse. True collapse
|
|
225
|
+
is a singularity in finite time; this integrator (like any
|
|
226
|
+
finite-grid scheme) cannot resolve it and the calculation should be
|
|
227
|
+
stopped once the peak density is still visibly growing, not carried
|
|
228
|
+
through the blow-up itself.
|
|
229
|
+
|
|
230
|
+
Parameters
|
|
231
|
+
----------
|
|
232
|
+
psi0 : ndarray of complex, shape (n, n)
|
|
233
|
+
Initial wavefunction.
|
|
234
|
+
V : ndarray, shape (n, n)
|
|
235
|
+
External potential (use ``np.zeros_like`` for the free/collapse case).
|
|
236
|
+
g : float
|
|
237
|
+
Interaction strength and sign (see above).
|
|
238
|
+
dt : float
|
|
239
|
+
Time step.
|
|
240
|
+
steps : int
|
|
241
|
+
Number of steps to advance.
|
|
242
|
+
K2 : ndarray, shape (n, n)
|
|
243
|
+
Wavenumber-squared grid from :func:`harmonic_trap_grid`.
|
|
244
|
+
snapshot_stride : int, default=1
|
|
245
|
+
Record a snapshot every this many steps (plus the initial condition).
|
|
246
|
+
|
|
247
|
+
Returns
|
|
248
|
+
-------
|
|
249
|
+
snapshots : ndarray of complex, shape (n_recorded, n, n)
|
|
250
|
+
Wavefunction at ``t=0`` and after every recorded step.
|
|
251
|
+
times : ndarray, shape (n_recorded,)
|
|
252
|
+
Time of each recorded snapshot.
|
|
253
|
+
|
|
254
|
+
See Also
|
|
255
|
+
--------
|
|
256
|
+
gpe_relax : Imaginary-time relaxation to a stationary state.
|
|
257
|
+
physicskit.fields.solitons.nls_evolve : The 1D analog (opposite sign convention for ``g``).
|
|
258
|
+
|
|
259
|
+
Examples
|
|
260
|
+
--------
|
|
261
|
+
Norm is conserved under real-time evolution, unlike the imaginary-time
|
|
262
|
+
propagation in :func:`gpe_relax` (which requires explicit renormalization):
|
|
263
|
+
|
|
264
|
+
>>> import numpy as np
|
|
265
|
+
>>> n, length = 48, 12.0
|
|
266
|
+
>>> X, Y, KX, KY, K2 = harmonic_trap_grid(n, length)
|
|
267
|
+
>>> dxg = X[1, 0] - X[0, 0]
|
|
268
|
+
>>> V = 0.5 * (X ** 2 + Y ** 2)
|
|
269
|
+
>>> psi0 = np.exp(-0.5 * (X ** 2 + Y ** 2)).astype(complex)
|
|
270
|
+
>>> psi0 *= 1.0 / np.sqrt(np.sum(np.abs(psi0) ** 2) * dxg * dxg)
|
|
271
|
+
>>> snaps, times = gpe_evolve(psi0, V, g=2.0, dt=1e-3, steps=200, K2=K2, snapshot_stride=50)
|
|
272
|
+
>>> norms = np.sum(np.abs(snaps) ** 2, axis=(1, 2)) * dxg * dxg
|
|
273
|
+
>>> bool(np.max(np.abs(norms - norms[0])) < 1e-6)
|
|
274
|
+
True
|
|
275
|
+
"""
|
|
276
|
+
psi = np.array(psi0, dtype=complex, copy=True)
|
|
277
|
+
lin_prop = np.exp(-1j * 0.5 * K2 * dt)
|
|
278
|
+
n_snap = steps // snapshot_stride + 1
|
|
279
|
+
snapshots = np.empty((n_snap, *psi.shape), dtype=complex)
|
|
280
|
+
times = np.empty(n_snap)
|
|
281
|
+
snapshots[0] = psi
|
|
282
|
+
times[0] = 0.0
|
|
283
|
+
idx = 1
|
|
284
|
+
for step in range(1, steps + 1):
|
|
285
|
+
psi_hat = np.fft.fft2(psi)
|
|
286
|
+
psi_hat *= lin_prop
|
|
287
|
+
psi = np.fft.ifft2(psi_hat)
|
|
288
|
+
psi *= np.exp(-1j * (V + g * np.abs(psi) ** 2) * dt)
|
|
289
|
+
if step % snapshot_stride == 0:
|
|
290
|
+
snapshots[idx] = psi
|
|
291
|
+
times[idx] = step * dt
|
|
292
|
+
idx += 1
|
|
293
|
+
return snapshots[:idx], times[:idx]
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def gpe_energy(psi: np.ndarray, V: np.ndarray, g: float, X: np.ndarray, Y: np.ndarray, K2: np.ndarray) -> dict:
|
|
297
|
+
"""Evaluate the energy and angular momentum of a GPE wavefunction.
|
|
298
|
+
|
|
299
|
+
Parameters
|
|
300
|
+
----------
|
|
301
|
+
psi : ndarray of complex, shape (n, n)
|
|
302
|
+
Wavefunction.
|
|
303
|
+
V : ndarray, shape (n, n)
|
|
304
|
+
External trapping potential.
|
|
305
|
+
g : float
|
|
306
|
+
Interaction strength.
|
|
307
|
+
X, Y, K2 : ndarray, shape (n, n)
|
|
308
|
+
Grids from :func:`harmonic_trap_grid` (``KX``, ``KY`` are not needed here).
|
|
309
|
+
|
|
310
|
+
Returns
|
|
311
|
+
-------
|
|
312
|
+
dict
|
|
313
|
+
``{"kinetic", "potential", "interaction", "angular_momentum", "total"}``,
|
|
314
|
+
where ``total`` is the lab-frame energy (kinetic + potential + interaction)
|
|
315
|
+
and ``angular_momentum`` is :math:`\\langle L_z \\rangle`. The
|
|
316
|
+
rotating-frame energy at rotation rate ``Omega`` is
|
|
317
|
+
``total - Omega * angular_momentum``.
|
|
318
|
+
|
|
319
|
+
Examples
|
|
320
|
+
--------
|
|
321
|
+
>>> import numpy as np
|
|
322
|
+
>>> X, Y, KX, KY, K2 = harmonic_trap_grid(48, 10.0)
|
|
323
|
+
>>> V = 0.5 * (X ** 2 + Y ** 2)
|
|
324
|
+
>>> psi = np.exp(-0.5 * (X ** 2 + Y ** 2)).astype(complex)
|
|
325
|
+
>>> psi *= 1.0 / np.sqrt(np.sum(np.abs(psi) ** 2) * (X[1, 0] - X[0, 0]) ** 2)
|
|
326
|
+
>>> E = gpe_energy(psi, V, g=0.0, X=X, Y=Y, K2=K2)
|
|
327
|
+
>>> round(float(E["kinetic"] + E["potential"]), 4)
|
|
328
|
+
1.0
|
|
329
|
+
"""
|
|
330
|
+
dx = X[1, 0] - X[0, 0]
|
|
331
|
+
n = X.shape[0]
|
|
332
|
+
psi_hat = np.fft.fft2(psi)
|
|
333
|
+
kinetic = np.sum(0.5 * K2 * np.abs(psi_hat) ** 2) / n**2 * dx * dx
|
|
334
|
+
dens = np.abs(psi) ** 2
|
|
335
|
+
potential = np.sum(V * dens) * dx * dx
|
|
336
|
+
interaction = 0.5 * g * np.sum(dens**2) * dx * dx
|
|
337
|
+
dpsidx = (np.roll(psi, -1, axis=0) - np.roll(psi, 1, axis=0)) / (2 * dx)
|
|
338
|
+
dpsidy = (np.roll(psi, -1, axis=1) - np.roll(psi, 1, axis=1)) / (2 * dx)
|
|
339
|
+
angular_momentum = float(np.real(np.sum(np.conj(psi) * (-1j) * (X * dpsidy - Y * dpsidx))) * dx * dx)
|
|
340
|
+
total = kinetic + potential + interaction
|
|
341
|
+
return {"kinetic": kinetic, "potential": potential, "interaction": interaction, "angular_momentum": angular_momentum, "total": total}
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def count_vortices(psi: np.ndarray, density_threshold: float = 0.05) -> np.ndarray:
|
|
345
|
+
"""Locate quantized vortices by summing the phase winding around each grid plaquette.
|
|
346
|
+
|
|
347
|
+
Plaquettes in very low density regions are excluded, since the phase
|
|
348
|
+
of a near-zero-amplitude wavefunction is dominated by numerical noise
|
|
349
|
+
and produces spurious windings there.
|
|
350
|
+
|
|
351
|
+
A vortex core that sits exactly on a grid vertex (rather than strictly
|
|
352
|
+
inside a plaquette) can go undetected, since its circulation is then
|
|
353
|
+
split ambiguously between the four plaquettes touching that vertex; in
|
|
354
|
+
practice this is avoided by seeding vortices at positions not exactly
|
|
355
|
+
on the grid.
|
|
356
|
+
|
|
357
|
+
Parameters
|
|
358
|
+
----------
|
|
359
|
+
psi : ndarray of complex, shape (n, n)
|
|
360
|
+
Wavefunction.
|
|
361
|
+
density_threshold : float, default=0.05
|
|
362
|
+
Plaquettes where :math:`|\\psi|^2` (relative to its maximum) falls
|
|
363
|
+
below this fraction are excluded from the search.
|
|
364
|
+
|
|
365
|
+
Returns
|
|
366
|
+
-------
|
|
367
|
+
ndarray of int, shape (n, n)
|
|
368
|
+
Integer winding number around each plaquette's corner ``(i, j)``;
|
|
369
|
+
nonzero entries mark a vortex core (``+1`` or ``-1`` for a
|
|
370
|
+
singly-quantized vortex/antivortex) enclosed by that plaquette.
|
|
371
|
+
|
|
372
|
+
Examples
|
|
373
|
+
--------
|
|
374
|
+
>>> import numpy as np
|
|
375
|
+
>>> X, Y, KX, KY, K2 = harmonic_trap_grid(48, 10.0)
|
|
376
|
+
>>> psi0 = np.exp(-0.5 * (X ** 2 + Y ** 2)).astype(complex)
|
|
377
|
+
>>> psi_vortex = gpe_imprint_vortex(psi0, X, Y, [(0.0, 0.0)])
|
|
378
|
+
>>> winding = count_vortices(psi_vortex)
|
|
379
|
+
>>> int(np.sum(np.abs(winding)))
|
|
380
|
+
1
|
|
381
|
+
"""
|
|
382
|
+
phase = np.angle(psi)
|
|
383
|
+
dphi_x = np.angle(np.exp(1j * (np.roll(phase, -1, axis=0) - phase)))
|
|
384
|
+
dphi_y = np.angle(np.exp(1j * (np.roll(phase, -1, axis=1) - phase)))
|
|
385
|
+
circ = dphi_x + np.roll(dphi_y, -1, axis=0) - np.roll(dphi_x, -1, axis=1) - dphi_y
|
|
386
|
+
winding = np.round(circ / (2 * np.pi)).astype(int)
|
|
387
|
+
dens = np.abs(psi) ** 2
|
|
388
|
+
mask = dens < density_threshold * dens.max()
|
|
389
|
+
winding[mask] = 0
|
|
390
|
+
return winding
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
# -- QFT vacuum fluctuations / Casimir effect (1D toy cavity) ----------------
|
|
394
|
+
#
|
|
395
|
+
# A simplified, standard textbook treatment, not a 3D electromagnetic
|
|
396
|
+
# calculation: a scalar field confined between two parallel "plates" a
|
|
397
|
+
# distance d apart has only the discrete standing-wave modes
|
|
398
|
+
# omega_n = n*pi*c/d (n=1,2,...) rather than a continuum, and the
|
|
399
|
+
# difference between this discrete zero-point sum and the continuum it
|
|
400
|
+
# approaches at large d is the (finite, physical) Casimir energy. The bare
|
|
401
|
+
# sum (1/2) * sum_n omega_n diverges and is regularized here by an
|
|
402
|
+
# exponential (Abel-summation) cutoff, exp(-omega_n * cutoff), with
|
|
403
|
+
# cutoff -> 0 taken as a limit; the leading cutoff^-2 divergence is the same
|
|
404
|
+
# one a plate-free continuum calculation would produce with the same
|
|
405
|
+
# regulator, so it is subtracted exactly (via the known Laurent expansion of
|
|
406
|
+
# the regularized sum) rather than fit numerically, leaving the finite,
|
|
407
|
+
# cutoff-independent remainder that is the physical (measurable) energy.
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
def casimir_mode_frequencies(d: float, c: float = 1.0, n_max: int = 200) -> np.ndarray:
|
|
411
|
+
"""Discrete standing-wave mode frequencies of a 1D cavity of plate separation ``d``.
|
|
412
|
+
|
|
413
|
+
Parameters
|
|
414
|
+
----------
|
|
415
|
+
d : float
|
|
416
|
+
Plate separation.
|
|
417
|
+
c : float, default=1.0
|
|
418
|
+
Wave speed (``=1`` in natural units; use the physical speed of
|
|
419
|
+
light for SI-unit frequencies).
|
|
420
|
+
n_max : int, default=200
|
|
421
|
+
Number of modes to return.
|
|
422
|
+
|
|
423
|
+
Returns
|
|
424
|
+
-------
|
|
425
|
+
ndarray, shape (n_max,)
|
|
426
|
+
:math:`\\omega_n = n\\pi c/d` for :math:`n=1,\\dots,n_{max}`.
|
|
427
|
+
|
|
428
|
+
See Also
|
|
429
|
+
--------
|
|
430
|
+
casimir_energy_1d : The regularized zero-point energy of this mode spectrum.
|
|
431
|
+
|
|
432
|
+
Examples
|
|
433
|
+
--------
|
|
434
|
+
>>> omega = casimir_mode_frequencies(d=2.0, c=1.0, n_max=3)
|
|
435
|
+
>>> [round(float(w), 4) for w in omega]
|
|
436
|
+
[1.5708, 3.1416, 4.7124]
|
|
437
|
+
"""
|
|
438
|
+
n = np.arange(1, n_max + 1)
|
|
439
|
+
return n * np.pi * c / d
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
def casimir_energy_1d(d: float, c: float = 1.0, cutoff: float | None = None) -> float:
|
|
443
|
+
"""Regularized zero-point (Casimir) energy of the discrete 1D cavity spectrum.
|
|
444
|
+
|
|
445
|
+
Uses the standard exponential-cutoff regularization: the sum
|
|
446
|
+
:math:`\\sum_n n x^n = x/(1-x)^2` (with :math:`x=e^{-a}`,
|
|
447
|
+
:math:`a=\\pi c\\,\\text{cutoff}/d`) has an exact closed form, so no
|
|
448
|
+
series truncation is needed. Its small-``cutoff`` (small-``a``)
|
|
449
|
+
expansion is :math:`\\tfrac{1}{4\\sinh^2(a/2)} = 1/a^2 - 1/12 + O(a^2)`;
|
|
450
|
+
the :math:`1/a^2` piece is the (unphysical, cutoff-scheme-dependent)
|
|
451
|
+
divergence that a continuum reference calculation regularized the same
|
|
452
|
+
way would also produce, so it is subtracted exactly, leaving the finite
|
|
453
|
+
remainder that survives as ``cutoff -> 0``:
|
|
454
|
+
|
|
455
|
+
.. math::
|
|
456
|
+
|
|
457
|
+
E(d) \\to -\\frac{\\pi c}{24 d}
|
|
458
|
+
|
|
459
|
+
the standard 1D massless-field Casimir energy (equivalently, the
|
|
460
|
+
Casimir energy of a CFT strip with central charge 1).
|
|
461
|
+
|
|
462
|
+
Parameters
|
|
463
|
+
----------
|
|
464
|
+
d : float
|
|
465
|
+
Plate separation.
|
|
466
|
+
c : float, default=1.0
|
|
467
|
+
Wave speed.
|
|
468
|
+
cutoff : float, optional
|
|
469
|
+
Regulator scale. Defaults to ``1e-3 * d / c``. This subtraction is
|
|
470
|
+
a difference of two large, nearly-equal floating-point terms
|
|
471
|
+
(:math:`\\propto 1/\\text{cutoff}^2`), so making ``cutoff`` too
|
|
472
|
+
small *loses* precision to cancellation rather than gaining it;
|
|
473
|
+
``1e-4*d/c`` to ``1e-2*d/c`` is the well-behaved range in double
|
|
474
|
+
precision.
|
|
475
|
+
|
|
476
|
+
Returns
|
|
477
|
+
-------
|
|
478
|
+
float
|
|
479
|
+
The regularized (finite, cutoff-subtracted) zero-point energy.
|
|
480
|
+
|
|
481
|
+
See Also
|
|
482
|
+
--------
|
|
483
|
+
casimir_mode_frequencies : The (bare, un-regularized) mode spectrum being summed.
|
|
484
|
+
|
|
485
|
+
Examples
|
|
486
|
+
--------
|
|
487
|
+
The cutoff-and-subtract result agrees with the known closed form
|
|
488
|
+
:math:`-\\pi c/(24d)`, and (within the well-behaved cutoff range noted
|
|
489
|
+
above) agrees more closely as the cutoff shrinks:
|
|
490
|
+
|
|
491
|
+
>>> d = 3.0
|
|
492
|
+
>>> exact = -np.pi * 1.0 / (24 * d)
|
|
493
|
+
>>> bool(abs(casimir_energy_1d(d, cutoff=3e-3 * d) - exact) < 1e-6)
|
|
494
|
+
True
|
|
495
|
+
>>> bool(abs(casimir_energy_1d(d, cutoff=7e-4 * d) - exact) < 1e-8)
|
|
496
|
+
True
|
|
497
|
+
|
|
498
|
+
The energy grows less negative (weaker confinement of vacuum energy)
|
|
499
|
+
as the plates separate, giving an attractive force :math:`-dE/dd < 0`:
|
|
500
|
+
|
|
501
|
+
>>> bool(casimir_energy_1d(1.0) < casimir_energy_1d(2.0) < 0)
|
|
502
|
+
True
|
|
503
|
+
"""
|
|
504
|
+
if cutoff is None:
|
|
505
|
+
cutoff = 1e-3 * d / c
|
|
506
|
+
a = np.pi * c * cutoff / d
|
|
507
|
+
x = np.exp(-a)
|
|
508
|
+
E_reg = (np.pi * c) / (2 * d) * x / (1 - x) ** 2
|
|
509
|
+
divergent = d / (2 * np.pi * c * cutoff**2)
|
|
510
|
+
return float(E_reg - divergent)
|