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,62 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from physicskit.statphys.utils.finite_size_scaling import (
|
|
5
|
+
binder_cumulant_crossing,
|
|
6
|
+
estimate_beta_over_nu,
|
|
7
|
+
estimate_gamma_over_nu,
|
|
8
|
+
estimate_nu_from_binder_slope,
|
|
9
|
+
power_law_exponent,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_power_law_exponent_recovers_known_power():
|
|
14
|
+
x = np.array([1.0, 2.0, 4.0, 8.0, 16.0, 32.0])
|
|
15
|
+
y = 3.0 * x**1.5
|
|
16
|
+
p, A = power_law_exponent(x, y)
|
|
17
|
+
assert p == pytest.approx(1.5, abs=1e-6)
|
|
18
|
+
assert pytest.approx(3.0, abs=1e-6) == A
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_estimate_gamma_over_nu():
|
|
22
|
+
L = np.array([8.0, 16.0, 32.0, 64.0])
|
|
23
|
+
chi_max = 2.0 * L**1.75 # exact 2D Ising gamma/nu = 7/4
|
|
24
|
+
assert estimate_gamma_over_nu(L, chi_max) == pytest.approx(1.75, abs=1e-6)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_estimate_beta_over_nu():
|
|
28
|
+
L = np.array([8.0, 16.0, 32.0, 64.0])
|
|
29
|
+
m_tc = 1.5 * L ** (-0.125) # exact 2D Ising beta/nu = 1/8
|
|
30
|
+
assert estimate_beta_over_nu(L, m_tc) == pytest.approx(0.125, abs=1e-6)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_estimate_nu_from_binder_slope_with_synthetic_data():
|
|
34
|
+
# Construct U4(T) curves whose slope at T_c scales as L^(1/nu) with nu=1.
|
|
35
|
+
T_c = 2.269
|
|
36
|
+
L_values = [8, 16, 32]
|
|
37
|
+
T_grids, U4_grids = [], []
|
|
38
|
+
for L in L_values:
|
|
39
|
+
T = np.linspace(T_c - 1.0, T_c + 1.0, 21)
|
|
40
|
+
slope_at_tc = -(L ** (1.0 / 1.0)) # nu = 1
|
|
41
|
+
U4 = 0.6 + slope_at_tc * (T - T_c)
|
|
42
|
+
T_grids.append(T)
|
|
43
|
+
U4_grids.append(U4)
|
|
44
|
+
nu = estimate_nu_from_binder_slope(L_values, T_grids, U4_grids, T_c)
|
|
45
|
+
assert nu == pytest.approx(1.0, rel=0.05)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_binder_cumulant_crossing_finds_known_intersection():
|
|
49
|
+
T = np.linspace(2.0, 2.5, 100)
|
|
50
|
+
U4_by_L = {
|
|
51
|
+
16: 0.6 - 0.5 * (T - 2.25),
|
|
52
|
+
32: 0.6 - 1.5 * (T - 2.25),
|
|
53
|
+
}
|
|
54
|
+
T_cross = binder_cumulant_crossing(T, U4_by_L)
|
|
55
|
+
assert T_cross == pytest.approx(2.25, abs=0.01)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_binder_cumulant_crossing_raises_without_intersection():
|
|
59
|
+
T = np.linspace(2.0, 2.5, 50)
|
|
60
|
+
U4_by_L = {16: np.full(50, 0.5), 32: np.full(50, 0.7)}
|
|
61
|
+
with pytest.raises(ValueError):
|
|
62
|
+
binder_cumulant_crossing(T, U4_by_L)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import plotly.graph_objects as go
|
|
2
|
+
|
|
3
|
+
from physicskit.statphys.chapters.ising_lattice import Ising2D, XYModel2D
|
|
4
|
+
from physicskit.statphys.chapters.molecular_dynamics import LennardJonesGas
|
|
5
|
+
from physicskit.statphys.visualizers.interactive import (
|
|
6
|
+
interactive_particle_snapshot,
|
|
7
|
+
interactive_temperature_sweep,
|
|
8
|
+
interactive_vortex_field,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_interactive_temperature_sweep_builds_figure():
|
|
13
|
+
model = Ising2D(L=8, seed=0)
|
|
14
|
+
result = model.run_temperature_sweep([2.0, model.T_C, 2.5], n_equil=10, n_measure=10)
|
|
15
|
+
fig = interactive_temperature_sweep(result, T_c=model.T_C)
|
|
16
|
+
assert isinstance(fig, go.Figure)
|
|
17
|
+
assert len(fig.data) > 0
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_interactive_vortex_field_builds_figure():
|
|
21
|
+
model = XYModel2D(L=10, seed=1)
|
|
22
|
+
model.sweep(beta=1.0, n_sweeps=5)
|
|
23
|
+
fig = interactive_vortex_field(model.theta)
|
|
24
|
+
assert isinstance(fig, go.Figure)
|
|
25
|
+
assert len(fig.data) >= 1
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_interactive_particle_snapshot_builds_figure():
|
|
29
|
+
gas = LennardJonesGas(n_particles=25, box_size=10.0, seed=2)
|
|
30
|
+
gas.step(n_steps=10)
|
|
31
|
+
fig = interactive_particle_snapshot(gas)
|
|
32
|
+
assert isinstance(fig, go.Figure)
|
|
33
|
+
assert len(fig.data) == 1
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from physicskit.statphys.chapters.ising_lattice import Ising2D
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_critical_temperature_constant():
|
|
8
|
+
model = Ising2D(J=1.0, kB=1.0)
|
|
9
|
+
assert pytest.approx(2.0 / np.log(1.0 + np.sqrt(2.0)), rel=1e-10) == model.T_C
|
|
10
|
+
assert pytest.approx(2.269, abs=1e-3) == model.T_C
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_sweep_changes_configuration():
|
|
14
|
+
model = Ising2D(L=16, seed=0)
|
|
15
|
+
before = model.spins.copy()
|
|
16
|
+
model.sweep(beta=1.0, n_sweeps=5)
|
|
17
|
+
assert not np.array_equal(before, model.spins)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_energy_and_magnetization_bounds():
|
|
21
|
+
model = Ising2D(L=10, seed=1)
|
|
22
|
+
n = model.n_sites
|
|
23
|
+
model.sweep(beta=0.5, n_sweeps=20)
|
|
24
|
+
assert -4 * n <= model.energy() <= 4 * n
|
|
25
|
+
assert -n <= model.magnetization() <= n
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_zero_temperature_ground_state_is_uniform():
|
|
29
|
+
model = Ising2D(L=10, seed=2)
|
|
30
|
+
model.reset(ordered=True)
|
|
31
|
+
assert np.all(model.spins == 1)
|
|
32
|
+
model.sweep(beta=50.0, n_sweeps=50)
|
|
33
|
+
# at very low T, essentially no spin should have flipped away from consensus
|
|
34
|
+
assert abs(model.magnetization()) >= 0.9 * model.n_sites
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_default_reset_draws_random_disordered_configuration():
|
|
38
|
+
model = Ising2D(L=20, seed=4)
|
|
39
|
+
model.reset(ordered=True)
|
|
40
|
+
model.reset() # default ordered=False
|
|
41
|
+
assert set(np.unique(model.spins)) <= {-1, 1}
|
|
42
|
+
# a T=infinity draw on a 20x20 lattice should not be uniform
|
|
43
|
+
assert not np.all(model.spins == model.spins.flat[0])
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_wolff_cluster_flip_reports_positive_size():
|
|
47
|
+
model = Ising2D(L=16, seed=3)
|
|
48
|
+
size = model.sweep(beta=1.0 / model.T_C, algorithm="wolff", n_sweeps=1)
|
|
49
|
+
assert size >= 1
|
|
50
|
+
assert size <= model.n_sites
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_invalid_algorithm_raises():
|
|
54
|
+
model = Ising2D(L=8, seed=0)
|
|
55
|
+
with pytest.raises(ValueError):
|
|
56
|
+
model.sweep(beta=1.0, algorithm="bogus")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_susceptibility_peaks_near_critical_temperature():
|
|
60
|
+
"""Onsager's exact result: chi(T) diverges (peaks, at finite L) at T_C ≈ 2.269."""
|
|
61
|
+
model = Ising2D(L=14, J=1.0, kB=1.0, seed=42)
|
|
62
|
+
T_C = model.T_C
|
|
63
|
+
temperatures = np.linspace(T_C - 1.0, T_C + 1.0, 9)[::-1] # anneal from hot to cold
|
|
64
|
+
result = model.run_temperature_sweep(temperatures, n_equil=60, n_measure=120, algorithm="wolff")
|
|
65
|
+
peak_T = result["T"][np.argmax(result["chi"])]
|
|
66
|
+
assert peak_T == pytest.approx(T_C, abs=1.0)
|
|
67
|
+
# heat capacity should also show elevated fluctuations near T_C
|
|
68
|
+
assert result["C_v"].max() > result["C_v"].min()
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from physicskit.statphys.chapters.kpz_growth import KPZInterface
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_initial_heights_are_zero():
|
|
7
|
+
interface = KPZInterface(L=64, seed=0)
|
|
8
|
+
assert np.all(interface.heights == 0)
|
|
9
|
+
assert interface.width() == 0.0
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_rsos_constraint_is_maintained_after_growth():
|
|
13
|
+
interface = KPZInterface(L=64, seed=1)
|
|
14
|
+
interface.grow(n_sweeps=500)
|
|
15
|
+
h = interface.heights
|
|
16
|
+
diffs = np.abs(h - np.roll(h, -1))
|
|
17
|
+
assert diffs.max() <= 1
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_width_grows_from_zero():
|
|
21
|
+
interface = KPZInterface(L=64, seed=2)
|
|
22
|
+
interface.grow(n_sweeps=200)
|
|
23
|
+
assert interface.width() > 0.0
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_time_advances_with_grow():
|
|
27
|
+
interface = KPZInterface(L=32, seed=3)
|
|
28
|
+
interface.grow(n_sweeps=10)
|
|
29
|
+
assert interface.time == 10
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_run_growth_curve_shapes_and_monotonic_time():
|
|
33
|
+
interface = KPZInterface(L=64, seed=4)
|
|
34
|
+
times, widths = interface.run_growth_curve(t_max=500, n_points=20)
|
|
35
|
+
assert times.shape == widths.shape
|
|
36
|
+
assert np.all(np.diff(times) > 0)
|
|
37
|
+
assert np.all(widths >= 0.0)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_run_growth_curve_linearly_spaced_checkpoints():
|
|
41
|
+
interface = KPZInterface(L=64, seed=5)
|
|
42
|
+
times, widths = interface.run_growth_curve(t_max=200, n_points=10, log_spaced=False)
|
|
43
|
+
assert times.shape == widths.shape
|
|
44
|
+
assert np.all(np.diff(times) > 0)
|
|
45
|
+
# linearly (not logarithmically) spaced: consecutive gaps stay within
|
|
46
|
+
# +/-1 of each other after integer rounding, unlike the geometrically
|
|
47
|
+
# growing gaps of the log-spaced default.
|
|
48
|
+
assert np.ptp(np.diff(times)) <= 1
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_mean_height_grows_with_deposition():
|
|
52
|
+
interface = KPZInterface(L=64, seed=6)
|
|
53
|
+
assert interface.mean_height() == 0.0
|
|
54
|
+
interface.grow(n_sweeps=200)
|
|
55
|
+
assert interface.mean_height() > 0.0
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from physicskit.statphys.utils.landau_theory import (
|
|
5
|
+
landau_equilibrium_magnetization,
|
|
6
|
+
landau_free_energy,
|
|
7
|
+
landau_susceptibility,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_equilibrium_magnetization_zero_above_tc():
|
|
12
|
+
m = landau_equilibrium_magnetization(T=3.0, Tc=2.0, a=1.0, b=1.0, h=0.0)
|
|
13
|
+
assert m == pytest.approx(0.0)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_equilibrium_magnetization_matches_closed_form_below_tc():
|
|
17
|
+
T, Tc, a, b = 1.0, 2.0, 1.0, 1.0
|
|
18
|
+
m = landau_equilibrium_magnetization(T=T, Tc=Tc, a=a, b=b, h=0.0)
|
|
19
|
+
expected = np.sqrt(a * (Tc - T) / (2 * b))
|
|
20
|
+
assert abs(m) == pytest.approx(expected, rel=1e-6)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_equilibrium_magnetization_vectorized_over_temperature():
|
|
24
|
+
T = np.array([1.0, 1.5, 2.0, 2.5, 3.0])
|
|
25
|
+
m = landau_equilibrium_magnetization(T, Tc=2.0)
|
|
26
|
+
assert m.shape == T.shape
|
|
27
|
+
assert np.all(m[T >= 2.0] == pytest.approx(0.0))
|
|
28
|
+
assert np.all(np.abs(m[T < 2.0]) > 0.0)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_susceptibility_diverges_approaching_tc_from_both_sides():
|
|
32
|
+
chi_far_above = landau_susceptibility(3.0, Tc=2.0)
|
|
33
|
+
chi_near_above = landau_susceptibility(2.01, Tc=2.0)
|
|
34
|
+
chi_far_below = landau_susceptibility(1.0, Tc=2.0)
|
|
35
|
+
chi_near_below = landau_susceptibility(1.99, Tc=2.0)
|
|
36
|
+
assert chi_near_above > chi_far_above
|
|
37
|
+
assert chi_near_below > chi_far_below
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_free_energy_at_zero_field_zero_magnetization_is_zero():
|
|
41
|
+
assert landau_free_energy(m=0.0, T=1.0, Tc=2.0, h=0.0) == pytest.approx(0.0)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_equilibrium_magnetization_minimizes_free_energy():
|
|
45
|
+
T, Tc, a, b, h = 1.0, 2.0, 1.0, 1.0, 0.0
|
|
46
|
+
m_eq = landau_equilibrium_magnetization(T, Tc, a, b, h)
|
|
47
|
+
F_eq = landau_free_energy(m_eq, T, Tc, a, b, h)
|
|
48
|
+
F_zero = landau_free_energy(0.0, T, Tc, a, b, h)
|
|
49
|
+
assert F_eq <= F_zero
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Tests for physicskit.statphys.core.md_engine.initialize_maxwell_boltzmann_velocities,
|
|
2
|
+
which is otherwise only exercised via its doctest (not part of the
|
|
3
|
+
regular pytest/coverage run). lj_forces and velocity_verlet_step are
|
|
4
|
+
exercised indirectly through LennardJonesGas in test_molecular_dynamics.py.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
from physicskit.statphys.core.md_engine import initialize_maxwell_boltzmann_velocities
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_initialize_maxwell_boltzmann_velocities_has_zero_net_momentum():
|
|
15
|
+
rng = np.random.default_rng(0)
|
|
16
|
+
v = initialize_maxwell_boltzmann_velocities(200, temperature=1.5, mass=1.0, kB=1.0, rng=rng)
|
|
17
|
+
assert v.shape == (200, 2)
|
|
18
|
+
np.testing.assert_allclose(v.mean(axis=0), 0.0, atol=1e-9)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_initialize_maxwell_boltzmann_velocities_uses_default_rng_when_none_given():
|
|
22
|
+
v = initialize_maxwell_boltzmann_velocities(50, temperature=1.0)
|
|
23
|
+
assert v.shape == (50, 2)
|
|
24
|
+
assert np.all(np.isfinite(v))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_initialize_maxwell_boltzmann_velocities_variance_scales_with_temperature():
|
|
28
|
+
rng = np.random.default_rng(1)
|
|
29
|
+
v_cold = initialize_maxwell_boltzmann_velocities(5000, temperature=0.5, mass=1.0, kB=1.0, rng=rng)
|
|
30
|
+
v_hot = initialize_maxwell_boltzmann_velocities(5000, temperature=4.0, mass=1.0, kB=1.0, rng=rng)
|
|
31
|
+
assert v_hot.var() > v_cold.var()
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from physicskit.statphys.chapters.molecular_dynamics import LennardJonesGas
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_particles_start_inside_box():
|
|
8
|
+
gas = LennardJonesGas(n_particles=36, box_size=12.0, seed=0)
|
|
9
|
+
assert np.all(gas.positions >= 0.0)
|
|
10
|
+
assert np.all(gas.positions < 12.0)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_zero_net_momentum_initially():
|
|
14
|
+
gas = LennardJonesGas(n_particles=50, box_size=15.0, seed=1)
|
|
15
|
+
assert np.allclose(gas.velocities.mean(axis=0), 0.0, atol=1e-9)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_maxwell_boltzmann_initial_velocity_distribution_has_zero_net_momentum():
|
|
19
|
+
gas = LennardJonesGas(n_particles=50, box_size=15.0, initial_velocity_distribution="maxwell_boltzmann", seed=7)
|
|
20
|
+
assert np.allclose(gas.velocities.mean(axis=0), 0.0, atol=1e-9)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_invalid_initial_velocity_distribution_raises():
|
|
24
|
+
with pytest.raises(ValueError):
|
|
25
|
+
LennardJonesGas(n_particles=10, box_size=10.0, initial_velocity_distribution="bogus", seed=0)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_step_advances_time_and_keeps_particles_in_box():
|
|
29
|
+
gas = LennardJonesGas(n_particles=36, box_size=12.0, dt=0.005, seed=2)
|
|
30
|
+
gas.step(n_steps=20)
|
|
31
|
+
assert gas.time == pytest.approx(20 * 0.005)
|
|
32
|
+
assert np.all(gas.positions >= 0.0)
|
|
33
|
+
assert np.all(gas.positions < 12.0)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_energy_is_approximately_conserved():
|
|
37
|
+
gas = LennardJonesGas(n_particles=36, box_size=14.0, dt=0.002, seed=3)
|
|
38
|
+
E0 = gas.total_energy()
|
|
39
|
+
gas.step(n_steps=300)
|
|
40
|
+
E1 = gas.total_energy()
|
|
41
|
+
assert pytest.approx(E0, rel=0.05) == E1
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_h_function_is_finite():
|
|
45
|
+
gas = LennardJonesGas(n_particles=64, box_size=16.0, seed=4)
|
|
46
|
+
H = gas.h_function()
|
|
47
|
+
assert np.isfinite(H)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_run_returns_expected_history_shape():
|
|
51
|
+
gas = LennardJonesGas(n_particles=49, box_size=14.0, seed=5)
|
|
52
|
+
history = gas.run(n_steps=100, steps_per_record=25)
|
|
53
|
+
assert history["H"].shape == (5,)
|
|
54
|
+
assert history["time"][0] == 0.0
|
|
55
|
+
assert history["time"][-1] == pytest.approx(100 * gas.dt)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_h_theorem_relaxation_direction():
|
|
59
|
+
"""A far-from-equilibrium delta-function velocity distribution should see H
|
|
60
|
+
decrease (or stay flat) on average as the gas thermalizes toward Maxwell-Boltzmann."""
|
|
61
|
+
gas = LennardJonesGas(
|
|
62
|
+
n_particles=100,
|
|
63
|
+
box_size=18.0,
|
|
64
|
+
temperature_init=1.0,
|
|
65
|
+
initial_velocity_distribution="delta",
|
|
66
|
+
dt=0.003,
|
|
67
|
+
seed=6,
|
|
68
|
+
)
|
|
69
|
+
history = gas.run(n_steps=1500, steps_per_record=100)
|
|
70
|
+
early_H = history["H"][:3].mean()
|
|
71
|
+
late_H = history["H"][-3:].mean()
|
|
72
|
+
assert late_H <= early_H + 0.05
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from physicskit.statphys.chapters.nonequilibrium_work import JarzynskiHarmonicTrap
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_run_protocol_returns_one_work_sample_per_trajectory():
|
|
8
|
+
model = JarzynskiHarmonicTrap(seed=0)
|
|
9
|
+
work = model.run_protocol(lambda_0=0.0, lambda_1=1.0, tau=2.0, n_steps=100, n_trajectories=50)
|
|
10
|
+
assert work.shape == (50,)
|
|
11
|
+
assert np.all(np.isfinite(work))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_jarzynski_estimate_of_constant_work_is_exact():
|
|
15
|
+
model = JarzynskiHarmonicTrap(kB=1.0, T=1.0)
|
|
16
|
+
work = np.full(1000, 2.5)
|
|
17
|
+
assert model.jarzynski_free_energy_estimate(work) == pytest.approx(2.5)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_jarzynski_equality_recovers_zero_free_energy_for_harmonic_trap():
|
|
21
|
+
# Only the trap center moves, never the stiffness, so the true
|
|
22
|
+
# equilibrium free energy difference is exactly zero regardless of the
|
|
23
|
+
# (finite-speed, dissipative) protocol used to drag it there.
|
|
24
|
+
model = JarzynskiHarmonicTrap(k=1.0, gamma=1.0, kB=1.0, T=1.0, seed=7)
|
|
25
|
+
work = model.run_protocol(lambda_0=0.0, lambda_1=2.0, tau=3.0, n_steps=300, n_trajectories=3000)
|
|
26
|
+
dF_estimate = model.jarzynski_free_energy_estimate(work)
|
|
27
|
+
assert dF_estimate == pytest.approx(0.0, abs=0.3)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_second_law_mean_work_exceeds_free_energy_difference():
|
|
31
|
+
model = JarzynskiHarmonicTrap(k=1.0, gamma=1.0, kB=1.0, T=1.0, seed=8)
|
|
32
|
+
work = model.run_protocol(lambda_0=0.0, lambda_1=2.0, tau=1.0, n_steps=200, n_trajectories=2000)
|
|
33
|
+
assert work.mean() > 0.0
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from physicskit.statphys.utils.partition_function import ising_partition_polynomial, yang_lee_zeros
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@pytest.mark.parametrize("N", [4, 8, 12])
|
|
8
|
+
@pytest.mark.parametrize("periodic", [True, False])
|
|
9
|
+
def test_yang_lee_zeros_lie_on_unit_circle_for_ferromagnet(N, periodic):
|
|
10
|
+
g = ising_partition_polynomial(N, beta=0.4, J=1.0, periodic=periodic)
|
|
11
|
+
zeros = yang_lee_zeros(g)
|
|
12
|
+
assert zeros.shape == (N,)
|
|
13
|
+
assert np.max(np.abs(np.abs(zeros) - 1.0)) < 1e-8
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_partition_polynomial_coefficients_are_positive():
|
|
17
|
+
g = ising_partition_polynomial(6, beta=0.5, J=1.0, periodic=True)
|
|
18
|
+
assert g.shape == (7,)
|
|
19
|
+
assert np.all(g > 0.0)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_partition_polynomial_symmetric_for_periodic_chain():
|
|
23
|
+
# A periodic ferromagnetic chain is symmetric under global spin flip,
|
|
24
|
+
# so g_k (k up-spins) equals g_(N-k) (k down-spins).
|
|
25
|
+
g = ising_partition_polynomial(8, beta=0.3, J=1.0, periodic=True)
|
|
26
|
+
assert np.allclose(g, g[::-1])
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from physicskit.statphys.chapters.percolation import Percolation2D, hoshen_kopelman
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_hoshen_kopelman_simple_shape():
|
|
8
|
+
grid = np.array(
|
|
9
|
+
[
|
|
10
|
+
[True, True, False],
|
|
11
|
+
[False, True, False],
|
|
12
|
+
[False, False, True],
|
|
13
|
+
]
|
|
14
|
+
)
|
|
15
|
+
labels = hoshen_kopelman(grid)
|
|
16
|
+
assert labels[0, 0] == labels[0, 1] == labels[1, 1]
|
|
17
|
+
assert labels[0, 0] != 0
|
|
18
|
+
assert labels[2, 2] != 0
|
|
19
|
+
assert labels[2, 2] != labels[0, 0]
|
|
20
|
+
assert labels[0, 2] == 0 and labels[1, 0] == 0 and labels[2, 0] == 0 and labels[2, 1] == 0
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_fully_occupied_lattice_is_one_cluster():
|
|
24
|
+
grid = np.ones((10, 10), dtype=bool)
|
|
25
|
+
labels = hoshen_kopelman(grid)
|
|
26
|
+
assert len(np.unique(labels)) == 1
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_empty_lattice_has_no_clusters():
|
|
30
|
+
grid = np.zeros((10, 10), dtype=bool)
|
|
31
|
+
labels = hoshen_kopelman(grid)
|
|
32
|
+
assert np.all(labels == 0)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_low_probability_rarely_spans():
|
|
36
|
+
perc = Percolation2D(L=40, p=0.1, mode="site", seed=0)
|
|
37
|
+
assert not perc.spans()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_full_occupation_always_spans():
|
|
41
|
+
perc = Percolation2D(L=20, p=1.0, mode="site", seed=1)
|
|
42
|
+
assert perc.spans()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_spanning_probability_increases_with_p():
|
|
46
|
+
perc = Percolation2D(L=25, mode="site", seed=2)
|
|
47
|
+
_p_values, P_span = perc.spanning_probability([0.3, perc.p_c, 0.85], n_trials=30)
|
|
48
|
+
assert P_span[0] <= P_span[1] <= P_span[2]
|
|
49
|
+
assert P_span[2] > P_span[0]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_bond_percolation_threshold_is_half():
|
|
53
|
+
perc = Percolation2D(L=10, mode="bond", seed=3)
|
|
54
|
+
assert perc.p_c == pytest.approx(0.5)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def test_bond_percolation_full_occupation_always_spans():
|
|
58
|
+
perc = Percolation2D(L=10, p=1.0, mode="bond", seed=3)
|
|
59
|
+
assert perc.spans()
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def test_bond_percolation_low_probability_rarely_spans():
|
|
63
|
+
perc = Percolation2D(L=20, p=0.05, mode="bond", seed=3)
|
|
64
|
+
assert not perc.spans()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def test_largest_cluster_size_grows_with_p():
|
|
68
|
+
perc = Percolation2D(L=30, p=0.2, mode="site", seed=4)
|
|
69
|
+
small = perc.largest_cluster_size()
|
|
70
|
+
perc.generate(p=0.9)
|
|
71
|
+
large = perc.largest_cluster_size()
|
|
72
|
+
assert large > small
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_invalid_mode_raises():
|
|
76
|
+
with pytest.raises(ValueError):
|
|
77
|
+
Percolation2D(L=10, mode="triangle")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def test_cluster_size_distribution_empty_for_no_occupation():
|
|
81
|
+
perc = Percolation2D(L=15, p=0.0, mode="site", seed=5)
|
|
82
|
+
assert perc.cluster_size_distribution().size == 0
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_cluster_size_distribution_single_cluster_for_full_occupation():
|
|
86
|
+
perc = Percolation2D(L=15, p=1.0, mode="site", seed=6)
|
|
87
|
+
sizes = perc.cluster_size_distribution()
|
|
88
|
+
assert sizes.size == 1
|
|
89
|
+
assert sizes[0] == 15 * 15
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def test_cluster_size_distribution_matches_largest_cluster_size():
|
|
93
|
+
perc = Percolation2D(L=30, p=0.55, mode="site", seed=7)
|
|
94
|
+
sizes = perc.cluster_size_distribution()
|
|
95
|
+
assert sizes.max() == perc.largest_cluster_size()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def test_cluster_size_distribution_sums_to_occupied_sites():
|
|
99
|
+
perc = Percolation2D(L=25, p=0.6, mode="site", seed=8)
|
|
100
|
+
sizes = perc.cluster_size_distribution()
|
|
101
|
+
n_occupied = int(np.sum(perc._real_labels() != 0))
|
|
102
|
+
assert sizes.sum() == n_occupied
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def test_fractal_dimension_is_a_positive_finite_estimate():
|
|
106
|
+
# 2D percolation universality class predicts d_f = 91/48 ~= 1.896, but
|
|
107
|
+
# this simple per-realization log(size)/log(Rg) estimator, averaged
|
|
108
|
+
# directly over trials rather than pooled via regression, is known to
|
|
109
|
+
# be sensitive to individual small-Rg outliers and can be biased well
|
|
110
|
+
# above the naive d_f<=2 embedding bound at these lattice sizes; this
|
|
111
|
+
# is a property of the estimator (see its docstring), not something a
|
|
112
|
+
# unit test should paper over with a false-precision assertion, so this
|
|
113
|
+
# only checks it returns a sane, finite, positive estimate.
|
|
114
|
+
perc = Percolation2D(L=60, mode="site", seed=9)
|
|
115
|
+
d_f = perc.fractal_dimension(n_trials=15)
|
|
116
|
+
assert 0.0 < d_f < 5.0
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from physicskit.statphys.chapters.ising_lattice import PottsModel2D
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_critical_temperature_formula():
|
|
8
|
+
model = PottsModel2D(q=3, J=1.0, kB=1.0)
|
|
9
|
+
assert pytest.approx(1.0 / np.log(1.0 + np.sqrt(3.0)), rel=1e-10) == model.T_C
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_states_in_valid_range():
|
|
13
|
+
model = PottsModel2D(L=12, q=5, seed=0)
|
|
14
|
+
assert model.spins.min() >= 0
|
|
15
|
+
assert model.spins.max() < 5
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_order_parameter_bounds():
|
|
19
|
+
model = PottsModel2D(L=12, q=3, seed=1)
|
|
20
|
+
m = model.order_parameter()
|
|
21
|
+
assert 0.0 <= m <= 1.0 + 1e-9
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_ordered_state_has_order_parameter_one():
|
|
25
|
+
model = PottsModel2D(L=10, q=4, seed=2)
|
|
26
|
+
model.spins[:] = 0
|
|
27
|
+
assert model.order_parameter() == pytest.approx(1.0)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_sweep_reduces_energy_at_low_temperature():
|
|
31
|
+
model = PottsModel2D(L=12, q=3, seed=3)
|
|
32
|
+
E0 = model.energy()
|
|
33
|
+
model.sweep(beta=20.0, n_sweeps=50)
|
|
34
|
+
E1 = model.energy()
|
|
35
|
+
assert E1 <= E0
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_run_temperature_sweep_returns_expected_keys_and_shapes():
|
|
39
|
+
model = PottsModel2D(L=8, q=3, seed=4)
|
|
40
|
+
temperatures = np.array([0.5, model.T_C, 2.0])
|
|
41
|
+
result = model.run_temperature_sweep(temperatures, n_equil=5, n_measure=5, measure_every=1)
|
|
42
|
+
assert set(result.keys()) == {"T", "E", "m", "C_v"}
|
|
43
|
+
for key in result:
|
|
44
|
+
assert result[key].shape == temperatures.shape
|
|
45
|
+
np.testing.assert_allclose(result["T"], temperatures)
|
|
46
|
+
assert np.all((result["m"] >= 0.0) & (result["m"] <= 1.0 + 1e-9))
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from physicskit.statphys.chapters.random_walk import RandomWalk
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_lattice_walk_shape():
|
|
8
|
+
walk = RandomWalk(n_walkers=10, n_steps=50, dim=2, kind="lattice", seed=0)
|
|
9
|
+
traj = walk.run()
|
|
10
|
+
assert traj.shape == (51, 10, 2)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_walks_start_at_origin():
|
|
14
|
+
walk = RandomWalk(n_walkers=20, n_steps=30, dim=3, kind="gaussian", seed=1)
|
|
15
|
+
traj = walk.run()
|
|
16
|
+
assert np.all(traj[0] == 0.0)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_msd_increases_with_time():
|
|
20
|
+
walk = RandomWalk(n_walkers=200, n_steps=200, dim=2, kind="lattice", seed=1)
|
|
21
|
+
_t, msd = walk.mean_squared_displacement()
|
|
22
|
+
assert msd[-1] > msd[10]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_diffusion_coefficient_positive():
|
|
26
|
+
walk = RandomWalk(n_walkers=300, n_steps=300, dim=1, kind="gaussian", step_std=1.0, seed=2)
|
|
27
|
+
assert walk.diffusion_coefficient() > 0
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_gaussian_walk_diffusion_coefficient_matches_theory():
|
|
31
|
+
# For 1D Gaussian steps with std sigma, D = sigma^2 / 2 (Einstein relation, dt=1).
|
|
32
|
+
walk = RandomWalk(n_walkers=3000, n_steps=500, dim=1, kind="gaussian", step_std=1.5, seed=3)
|
|
33
|
+
D = walk.diffusion_coefficient()
|
|
34
|
+
assert pytest.approx(1.5**2 / 2.0, rel=0.2) == D
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_invalid_kind_raises():
|
|
38
|
+
walk = RandomWalk(n_walkers=5, n_steps=10, kind="bogus")
|
|
39
|
+
with pytest.raises(ValueError):
|
|
40
|
+
walk.run()
|
|
41
|
+
|
|
42
|
+
with pytest.raises(ValueError):
|
|
43
|
+
walk.mean_squared_displacement()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_final_displacement_histogram_normalizes():
|
|
47
|
+
walk = RandomWalk(n_walkers=500, n_steps=100, dim=2, kind="lattice", seed=4)
|
|
48
|
+
centers, density = walk.final_displacement_histogram(bins=30)
|
|
49
|
+
width = centers[1] - centers[0]
|
|
50
|
+
assert np.sum(density) * width == pytest.approx(1.0, abs=0.05)
|