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,161 @@
|
|
|
1
|
+
"""Interactive Plotly visualizations.
|
|
2
|
+
|
|
3
|
+
Every other module in :mod:`physicskit.statphys.visualizers` produces static Matplotlib
|
|
4
|
+
figures, well suited to publication and to this documentation's example
|
|
5
|
+
gallery. This module offers the same information as pan/zoom/hover-enabled
|
|
6
|
+
Plotly figures instead -- convenient for interactively exploring a parameter
|
|
7
|
+
sweep or a dense vector field in a Jupyter notebook, or for embedding in a
|
|
8
|
+
standalone HTML page.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import numpy as np
|
|
14
|
+
import plotly.graph_objects as go
|
|
15
|
+
from plotly.subplots import make_subplots
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"interactive_particle_snapshot",
|
|
19
|
+
"interactive_temperature_sweep",
|
|
20
|
+
"interactive_vortex_field",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def interactive_temperature_sweep(result, T_c=None):
|
|
25
|
+
"""Build an interactive 2x2 subplot figure of a temperature sweep result.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
result : dict of str -> ndarray
|
|
30
|
+
Output of e.g. ``Ising2D.run_temperature_sweep`` or
|
|
31
|
+
``PottsModel2D.run_temperature_sweep``.
|
|
32
|
+
T_c : float, optional
|
|
33
|
+
Critical temperature to mark with a vertical line on every panel.
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
plotly.graph_objects.Figure
|
|
38
|
+
A 2x2 subplot figure with hoverable energy, order-parameter,
|
|
39
|
+
specific-heat, and susceptibility traces.
|
|
40
|
+
|
|
41
|
+
Examples
|
|
42
|
+
--------
|
|
43
|
+
>>> from physicskit.statphys.chapters.ising_lattice import Ising2D
|
|
44
|
+
>>> model = Ising2D(L=10, seed=0)
|
|
45
|
+
>>> result = model.run_temperature_sweep([2.0, 2.269, 2.5], n_equil=10, n_measure=10)
|
|
46
|
+
>>> fig = interactive_temperature_sweep(result, T_c=model.T_C)
|
|
47
|
+
>>> len(fig.data) > 0
|
|
48
|
+
True
|
|
49
|
+
"""
|
|
50
|
+
T = result["T"]
|
|
51
|
+
panels = [
|
|
52
|
+
("E", "Energy per site"),
|
|
53
|
+
("M" if "M" in result else "m", "Order parameter"),
|
|
54
|
+
("C_v", "Specific heat"),
|
|
55
|
+
("chi", "Susceptibility"),
|
|
56
|
+
]
|
|
57
|
+
fig = make_subplots(rows=2, cols=2, subplot_titles=[label for _, label in panels])
|
|
58
|
+
positions = [(1, 1), (1, 2), (2, 1), (2, 2)]
|
|
59
|
+
for (key, label), (row, col) in zip(panels, positions):
|
|
60
|
+
if key not in result:
|
|
61
|
+
continue
|
|
62
|
+
fig.add_trace(go.Scatter(x=T, y=result[key], mode="lines+markers", name=label), row=row, col=col)
|
|
63
|
+
if T_c is not None:
|
|
64
|
+
fig.add_vline(x=T_c, line_dash="dash", line_color="black", row=row, col=col)
|
|
65
|
+
fig.update_layout(title="Temperature sweep", showlegend=False, height=600)
|
|
66
|
+
return fig
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def interactive_vortex_field(theta, vorticity=None, step=1):
|
|
70
|
+
"""Build an interactive XY spin field plot with vortex/antivortex markers.
|
|
71
|
+
|
|
72
|
+
Parameters
|
|
73
|
+
----------
|
|
74
|
+
theta : ndarray of shape (L, L)
|
|
75
|
+
XY model spin angles, e.g. ``XYModel2D.theta``.
|
|
76
|
+
vorticity : ndarray of shape (L, L), optional
|
|
77
|
+
Precomputed plaquette vorticity; computed from ``theta`` if omitted.
|
|
78
|
+
step : int, default=1
|
|
79
|
+
Subsampling factor for the arrow field.
|
|
80
|
+
|
|
81
|
+
Returns
|
|
82
|
+
-------
|
|
83
|
+
plotly.graph_objects.Figure
|
|
84
|
+
"""
|
|
85
|
+
if vorticity is None:
|
|
86
|
+
from physicskit.statphys.core.monte_carlo import xy_plaquette_vorticity
|
|
87
|
+
|
|
88
|
+
vorticity = xy_plaquette_vorticity(theta)
|
|
89
|
+
|
|
90
|
+
L = theta.shape[0]
|
|
91
|
+
idx = np.arange(0, L, step)
|
|
92
|
+
ii, jj = np.meshgrid(idx, idx, indexing="ij")
|
|
93
|
+
sub_theta = theta[np.ix_(idx, idx)]
|
|
94
|
+
|
|
95
|
+
scale = 0.4 * step
|
|
96
|
+
xs, ys = [], []
|
|
97
|
+
for a, b, t in zip(ii.ravel(), jj.ravel(), sub_theta.ravel()):
|
|
98
|
+
xs += [float(b), float(b) + scale * np.cos(t), None]
|
|
99
|
+
ys += [float(a), float(a) + scale * np.sin(t), None]
|
|
100
|
+
|
|
101
|
+
fig = go.Figure()
|
|
102
|
+
fig.add_trace(
|
|
103
|
+
go.Scatter(
|
|
104
|
+
x=xs,
|
|
105
|
+
y=ys,
|
|
106
|
+
mode="lines",
|
|
107
|
+
line={"color": "steelblue"},
|
|
108
|
+
showlegend=False,
|
|
109
|
+
hoverinfo="skip",
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
vi, vj = np.nonzero(vorticity > 0.5)
|
|
113
|
+
ai, aj = np.nonzero(vorticity < -0.5)
|
|
114
|
+
fig.add_trace(go.Scatter(x=vj, y=vi, mode="markers", marker={"color": "red", "size": 10}, name="vortex"))
|
|
115
|
+
fig.add_trace(
|
|
116
|
+
go.Scatter(
|
|
117
|
+
x=aj,
|
|
118
|
+
y=ai,
|
|
119
|
+
mode="markers",
|
|
120
|
+
marker={"color": "blue", "size": 10, "symbol": "x"},
|
|
121
|
+
name="antivortex",
|
|
122
|
+
)
|
|
123
|
+
)
|
|
124
|
+
fig.update_yaxes(autorange="reversed", scaleanchor="x", scaleratio=1)
|
|
125
|
+
fig.update_layout(title="XY spin field and vortices", height=600)
|
|
126
|
+
return fig
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def interactive_particle_snapshot(gas):
|
|
130
|
+
"""Build an interactive scatter plot of a Lennard-Jones gas snapshot, colored by speed.
|
|
131
|
+
|
|
132
|
+
Parameters
|
|
133
|
+
----------
|
|
134
|
+
gas : LennardJonesGas
|
|
135
|
+
Simulation instance to render.
|
|
136
|
+
|
|
137
|
+
Returns
|
|
138
|
+
-------
|
|
139
|
+
plotly.graph_objects.Figure
|
|
140
|
+
"""
|
|
141
|
+
speeds = gas.speeds()
|
|
142
|
+
fig = go.Figure(
|
|
143
|
+
data=go.Scatter(
|
|
144
|
+
x=gas.positions[:, 0],
|
|
145
|
+
y=gas.positions[:, 1],
|
|
146
|
+
mode="markers",
|
|
147
|
+
marker={
|
|
148
|
+
"color": speeds,
|
|
149
|
+
"colorscale": "Plasma",
|
|
150
|
+
"showscale": True,
|
|
151
|
+
"size": 8,
|
|
152
|
+
"colorbar": {"title": "speed"},
|
|
153
|
+
},
|
|
154
|
+
text=[f"speed={s:.2f}" for s in speeds],
|
|
155
|
+
hoverinfo="text",
|
|
156
|
+
)
|
|
157
|
+
)
|
|
158
|
+
fig.update_xaxes(range=[0, gas.box_size])
|
|
159
|
+
fig.update_yaxes(range=[0, gas.box_size], scaleanchor="x", scaleratio=1)
|
|
160
|
+
fig.update_layout(title=f"Lennard-Jones gas, t={gas.time:.2f}", height=600)
|
|
161
|
+
return fig
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Visualizations of the Jarzynski equality: nonequilibrium work distributions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import matplotlib.pyplot as plt
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
__all__ = ["plot_work_distribution"]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def plot_work_distribution(work, dF_true=0.0, dF_estimate=None, ax=None, bins=50):
|
|
12
|
+
"""Histogram nonequilibrium work samples against the true and Jarzynski-estimated free energy.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
work : array_like
|
|
17
|
+
Work samples, e.g. from :meth:`JarzynskiHarmonicTrap.run_protocol`.
|
|
18
|
+
dF_true : float, default=0.0
|
|
19
|
+
Known equilibrium free energy difference, marked with a solid line.
|
|
20
|
+
dF_estimate : float, optional
|
|
21
|
+
Jarzynski-equality estimate of the free energy (e.g. from
|
|
22
|
+
:meth:`JarzynskiHarmonicTrap.jarzynski_free_energy_estimate`),
|
|
23
|
+
marked with a dashed line if given.
|
|
24
|
+
ax : matplotlib.axes.Axes, optional
|
|
25
|
+
Axes to draw into.
|
|
26
|
+
bins : int, default=50
|
|
27
|
+
Number of histogram bins.
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
matplotlib.axes.Axes
|
|
32
|
+
"""
|
|
33
|
+
work = np.asarray(work)
|
|
34
|
+
if ax is None:
|
|
35
|
+
_, ax = plt.subplots(figsize=(6, 4))
|
|
36
|
+
ax.hist(work, bins=bins, density=True, alpha=0.6, label="work samples")
|
|
37
|
+
ax.axvline(work.mean(), color="tab:blue", linestyle=":", label=rf"$\langle W \rangle$={work.mean():.2f}")
|
|
38
|
+
ax.axvline(dF_true, color="black", linewidth=2, label=rf"$\Delta F$={dF_true:.2f}")
|
|
39
|
+
if dF_estimate is not None:
|
|
40
|
+
ax.axvline(dF_estimate, color="tab:red", linestyle="--", label=rf"Jarzynski $\Delta F$={dF_estimate:.2f}")
|
|
41
|
+
ax.set_xlabel("work W")
|
|
42
|
+
ax.set_ylabel("density")
|
|
43
|
+
ax.legend()
|
|
44
|
+
return ax
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Visualizations of KPZ/RSOS interface growth: height profiles and width scaling."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import matplotlib.pyplot as plt
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
__all__ = ["plot_interface_profile", "plot_width_growth"]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def plot_interface_profile(interface, ax=None):
|
|
12
|
+
"""Plot the current 1D interface height profile.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
interface : KPZInterface
|
|
17
|
+
Interface instance to render.
|
|
18
|
+
ax : matplotlib.axes.Axes, optional
|
|
19
|
+
Axes to draw into. A new figure and axes are created if not given.
|
|
20
|
+
|
|
21
|
+
Returns
|
|
22
|
+
-------
|
|
23
|
+
matplotlib.axes.Axes
|
|
24
|
+
"""
|
|
25
|
+
if ax is None:
|
|
26
|
+
_, ax = plt.subplots(figsize=(7, 3))
|
|
27
|
+
x = np.arange(interface.L)
|
|
28
|
+
ax.plot(x, interface.heights, drawstyle="steps-mid")
|
|
29
|
+
ax.set_xlabel("site")
|
|
30
|
+
ax.set_ylabel("height h(x)")
|
|
31
|
+
ax.set_title(f"RSOS interface at t={interface.time:.0f} sweeps")
|
|
32
|
+
return ax
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def plot_width_growth(times, widths, ax=None, show_theory=True, beta=1.0 / 3.0):
|
|
36
|
+
"""Log-log plot of interface width vs. time, with a t^beta growth reference line.
|
|
37
|
+
|
|
38
|
+
Parameters
|
|
39
|
+
----------
|
|
40
|
+
times, widths : array_like
|
|
41
|
+
Growth curve, e.g. from :meth:`KPZInterface.run_growth_curve`.
|
|
42
|
+
ax : matplotlib.axes.Axes, optional
|
|
43
|
+
Axes to draw into.
|
|
44
|
+
show_theory : bool, default=True
|
|
45
|
+
Overlay a :math:`t^\\beta` reference line (matched in amplitude to
|
|
46
|
+
the first data point) for the KPZ growth exponent.
|
|
47
|
+
beta : float, default=1/3
|
|
48
|
+
Growth exponent for the reference line (the 1+1D KPZ value).
|
|
49
|
+
|
|
50
|
+
Returns
|
|
51
|
+
-------
|
|
52
|
+
matplotlib.axes.Axes
|
|
53
|
+
"""
|
|
54
|
+
times = np.asarray(times)
|
|
55
|
+
widths = np.asarray(widths)
|
|
56
|
+
if ax is None:
|
|
57
|
+
_, ax = plt.subplots(figsize=(5, 4))
|
|
58
|
+
ax.loglog(times, widths, marker="o", ms=3, linestyle="none", label="simulation")
|
|
59
|
+
if show_theory:
|
|
60
|
+
amplitude = widths[0] / times[0] ** beta
|
|
61
|
+
ax.loglog(times, amplitude * times**beta, linestyle="--", label=rf"$t^{{{beta:.2f}}}$")
|
|
62
|
+
ax.set_xlabel("t (sweeps)")
|
|
63
|
+
ax.set_ylabel("interface width w(t)")
|
|
64
|
+
ax.legend()
|
|
65
|
+
return ax
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"""Static and animated visualizations of lattice spin configurations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import matplotlib.pyplot as plt
|
|
6
|
+
import numpy as np
|
|
7
|
+
from matplotlib.animation import FuncAnimation
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"animate_lattice_sweeps",
|
|
11
|
+
"plot_cluster_size_distribution",
|
|
12
|
+
"plot_percolation_clusters",
|
|
13
|
+
"plot_spin_grid",
|
|
14
|
+
"plot_thermodynamics",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def plot_spin_grid(spins, ax=None, cmap="coolwarm", title=None, colorbar=False):
|
|
19
|
+
"""Render a spin (or Potts state) configuration as a heatmap.
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
spins : ndarray of shape (L, L)
|
|
24
|
+
Spin configuration, e.g. ``Ising2D.spins`` or ``PottsModel2D.spins``.
|
|
25
|
+
ax : matplotlib.axes.Axes, optional
|
|
26
|
+
Axes to draw into. A new figure and axes are created if not given.
|
|
27
|
+
cmap : str, default="coolwarm"
|
|
28
|
+
Matplotlib colormap name.
|
|
29
|
+
title : str, optional
|
|
30
|
+
Axes title.
|
|
31
|
+
colorbar : bool, default=False
|
|
32
|
+
Whether to attach a colorbar.
|
|
33
|
+
|
|
34
|
+
Returns
|
|
35
|
+
-------
|
|
36
|
+
matplotlib.axes.Axes
|
|
37
|
+
|
|
38
|
+
Examples
|
|
39
|
+
--------
|
|
40
|
+
>>> from physicskit.statphys.chapters import Ising2D
|
|
41
|
+
>>> model = Ising2D(L=16, seed=0)
|
|
42
|
+
>>> ax = plot_spin_grid(model.spins)
|
|
43
|
+
"""
|
|
44
|
+
if ax is None:
|
|
45
|
+
_, ax = plt.subplots(figsize=(4, 4))
|
|
46
|
+
im = ax.imshow(spins, cmap=cmap, interpolation="nearest")
|
|
47
|
+
ax.set_xticks([])
|
|
48
|
+
ax.set_yticks([])
|
|
49
|
+
if title:
|
|
50
|
+
ax.set_title(title)
|
|
51
|
+
if colorbar:
|
|
52
|
+
plt.colorbar(im, ax=ax, fraction=0.046, pad=0.04)
|
|
53
|
+
return ax
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def animate_lattice_sweeps(model, beta, n_frames=100, sweeps_per_frame=1, algorithm="metropolis", cmap="coolwarm"):
|
|
57
|
+
"""Animate a lattice model relaxing under repeated Monte Carlo sweeps.
|
|
58
|
+
|
|
59
|
+
Parameters
|
|
60
|
+
----------
|
|
61
|
+
model : Ising2D or PottsModel2D
|
|
62
|
+
A model instance exposing a ``sweep(beta, ...)`` method and a
|
|
63
|
+
``spins`` attribute.
|
|
64
|
+
beta : float
|
|
65
|
+
Inverse temperature at which to sweep.
|
|
66
|
+
n_frames : int, default=100
|
|
67
|
+
Number of animation frames.
|
|
68
|
+
sweeps_per_frame : int, default=1
|
|
69
|
+
Sweeps performed between consecutive frames.
|
|
70
|
+
algorithm : str, default="metropolis"
|
|
71
|
+
Forwarded to ``model.sweep`` when supported (``Ising2D`` only).
|
|
72
|
+
cmap : str, default="coolwarm"
|
|
73
|
+
Matplotlib colormap name.
|
|
74
|
+
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
matplotlib.animation.FuncAnimation
|
|
78
|
+
"""
|
|
79
|
+
fig, ax = plt.subplots(figsize=(4, 4))
|
|
80
|
+
im = ax.imshow(model.spins, cmap=cmap, interpolation="nearest")
|
|
81
|
+
ax.set_xticks([])
|
|
82
|
+
ax.set_yticks([])
|
|
83
|
+
title = ax.set_title("sweep 0")
|
|
84
|
+
|
|
85
|
+
def update(frame):
|
|
86
|
+
try:
|
|
87
|
+
model.sweep(beta, algorithm=algorithm, n_sweeps=sweeps_per_frame)
|
|
88
|
+
except TypeError:
|
|
89
|
+
model.sweep(beta, n_sweeps=sweeps_per_frame)
|
|
90
|
+
im.set_data(model.spins)
|
|
91
|
+
title.set_text(f"sweep {(frame + 1) * sweeps_per_frame}")
|
|
92
|
+
return im, title
|
|
93
|
+
|
|
94
|
+
return FuncAnimation(fig, update, frames=n_frames, blit=False, interval=50)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def plot_thermodynamics(result, T_c=None, ax=None):
|
|
98
|
+
"""Plot energy, magnetization, specific heat, and susceptibility versus temperature.
|
|
99
|
+
|
|
100
|
+
Parameters
|
|
101
|
+
----------
|
|
102
|
+
result : dict of str -> ndarray
|
|
103
|
+
Output of ``Ising2D.run_temperature_sweep`` (or the analogous Potts
|
|
104
|
+
method, in which case ``"M"``/``"chi"`` keys may be absent).
|
|
105
|
+
T_c : float, optional
|
|
106
|
+
Critical temperature to mark with a vertical dashed line on every
|
|
107
|
+
panel.
|
|
108
|
+
ax : ndarray of matplotlib.axes.Axes, optional
|
|
109
|
+
A ``(2, 2)`` array of axes to draw into. A new figure is created if
|
|
110
|
+
not given.
|
|
111
|
+
|
|
112
|
+
Returns
|
|
113
|
+
-------
|
|
114
|
+
ndarray of matplotlib.axes.Axes
|
|
115
|
+
"""
|
|
116
|
+
if ax is None:
|
|
117
|
+
_, ax = plt.subplots(2, 2, figsize=(9, 7), sharex=True)
|
|
118
|
+
T = result["T"]
|
|
119
|
+
|
|
120
|
+
panels = [
|
|
121
|
+
(ax[0, 0], "E", "Energy per site"),
|
|
122
|
+
(ax[0, 1], "M" if "M" in result else "m", "Magnetization / order parameter"),
|
|
123
|
+
(ax[1, 0], "C_v", "Specific heat"),
|
|
124
|
+
(ax[1, 1], "chi", "Susceptibility"),
|
|
125
|
+
]
|
|
126
|
+
for axis, key, label in panels:
|
|
127
|
+
if key not in result:
|
|
128
|
+
axis.axis("off")
|
|
129
|
+
continue
|
|
130
|
+
axis.plot(T, result[key], marker="o", ms=3)
|
|
131
|
+
axis.set_ylabel(label)
|
|
132
|
+
axis.set_xlabel("Temperature")
|
|
133
|
+
if T_c is not None:
|
|
134
|
+
axis.axvline(T_c, color="k", linestyle="--", linewidth=1, alpha=0.6)
|
|
135
|
+
plt.tight_layout()
|
|
136
|
+
return ax
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def plot_percolation_clusters(percolation, ax=None, highlight_spanning=True, cmap="nipy_spectral"):
|
|
140
|
+
"""Render a percolation lattice with each connected cluster in a distinct color.
|
|
141
|
+
|
|
142
|
+
Parameters
|
|
143
|
+
----------
|
|
144
|
+
percolation : Percolation2D
|
|
145
|
+
Percolation instance whose current ``labels`` should be drawn.
|
|
146
|
+
ax : matplotlib.axes.Axes, optional
|
|
147
|
+
Axes to draw into. A new figure and axes are created if not given.
|
|
148
|
+
highlight_spanning : bool, default=True
|
|
149
|
+
Whether to redraw spanning clusters (if any) in solid black on top
|
|
150
|
+
of the color-coded background.
|
|
151
|
+
cmap : str, default="nipy_spectral"
|
|
152
|
+
Colormap used to distinguish clusters. Unoccupied sites are drawn in
|
|
153
|
+
white.
|
|
154
|
+
|
|
155
|
+
Returns
|
|
156
|
+
-------
|
|
157
|
+
matplotlib.axes.Axes
|
|
158
|
+
"""
|
|
159
|
+
if ax is None:
|
|
160
|
+
_, ax = plt.subplots(figsize=(5, 5))
|
|
161
|
+
labels = percolation.labels
|
|
162
|
+
display = np.ma.masked_equal(labels, 0)
|
|
163
|
+
cmap_obj = plt.get_cmap(cmap).copy()
|
|
164
|
+
cmap_obj.set_bad("white")
|
|
165
|
+
ax.imshow(display, cmap=cmap_obj, interpolation="nearest")
|
|
166
|
+
if highlight_spanning:
|
|
167
|
+
spanning = percolation.spanning_labels()
|
|
168
|
+
if len(spanning):
|
|
169
|
+
mask = np.isin(labels, spanning)
|
|
170
|
+
spanning_display = np.ma.masked_where(~mask, mask.astype(float))
|
|
171
|
+
ax.imshow(spanning_display, cmap="Greys", vmin=0, vmax=1, alpha=0.7, interpolation="nearest")
|
|
172
|
+
ax.set_xticks([])
|
|
173
|
+
ax.set_yticks([])
|
|
174
|
+
ax.set_title(f"{percolation.mode} percolation, p = {percolation.p:.3f}")
|
|
175
|
+
return ax
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def plot_cluster_size_distribution(sizes, ax=None, bins=30, tau_theory=187 / 91):
|
|
179
|
+
"""Log-log histogram of percolation cluster sizes against the theoretical Fisher exponent.
|
|
180
|
+
|
|
181
|
+
Parameters
|
|
182
|
+
----------
|
|
183
|
+
sizes : array_like
|
|
184
|
+
Cluster sizes, e.g. from ``Percolation2D.cluster_size_distribution``.
|
|
185
|
+
ax : matplotlib.axes.Axes, optional
|
|
186
|
+
Axes to draw into.
|
|
187
|
+
bins : int, default=30
|
|
188
|
+
Number of logarithmically spaced bins.
|
|
189
|
+
tau_theory : float, default=187/91
|
|
190
|
+
Theoretical Fisher exponent to overlay as a reference power law.
|
|
191
|
+
Pass ``None`` to omit it.
|
|
192
|
+
|
|
193
|
+
Returns
|
|
194
|
+
-------
|
|
195
|
+
matplotlib.axes.Axes
|
|
196
|
+
"""
|
|
197
|
+
sizes = np.asarray(sizes)
|
|
198
|
+
sizes = sizes[sizes > 0]
|
|
199
|
+
if ax is None:
|
|
200
|
+
_, ax = plt.subplots(figsize=(5, 4))
|
|
201
|
+
log_bins = np.logspace(0, np.log10(sizes.max()), bins)
|
|
202
|
+
counts, edges = np.histogram(sizes, bins=log_bins, density=True)
|
|
203
|
+
centers = np.sqrt(edges[:-1] * edges[1:])
|
|
204
|
+
mask = counts > 0
|
|
205
|
+
ax.loglog(centers[mask], counts[mask], marker="o", ms=3, linestyle="none", label="simulation")
|
|
206
|
+
if tau_theory is not None and np.any(mask):
|
|
207
|
+
ref = counts[mask][0] * (centers[mask] / centers[mask][0]) ** (-tau_theory)
|
|
208
|
+
ax.loglog(centers[mask], ref, linestyle="--", color="k", label=f"$s^{{-{tau_theory:.3f}}}$")
|
|
209
|
+
ax.set_xlabel("cluster size s")
|
|
210
|
+
ax.set_ylabel("P(s)")
|
|
211
|
+
ax.legend()
|
|
212
|
+
return ax
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""Visualizations of the Lennard-Jones gas: particle snapshots and velocity statistics."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import matplotlib.pyplot as plt
|
|
6
|
+
import numpy as np
|
|
7
|
+
from matplotlib.animation import FuncAnimation
|
|
8
|
+
|
|
9
|
+
from physicskit.statphys.utils.thermodynamics import maxwell_boltzmann_speed_pdf
|
|
10
|
+
|
|
11
|
+
__all__ = ["animate_gas", "plot_particle_snapshot", "plot_velocity_histogram"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def plot_particle_snapshot(gas, ax=None, show_velocities=False, color_by_speed=True):
|
|
15
|
+
"""Draw a single snapshot of the particle gas's positions.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
gas : LennardJonesGas
|
|
20
|
+
Simulation instance to render.
|
|
21
|
+
ax : matplotlib.axes.Axes, optional
|
|
22
|
+
Axes to draw into. A new figure and axes are created if not given.
|
|
23
|
+
show_velocities : bool, default=False
|
|
24
|
+
Whether to overlay velocity vectors as arrows.
|
|
25
|
+
color_by_speed : bool, default=True
|
|
26
|
+
Whether to color particles by their instantaneous speed.
|
|
27
|
+
|
|
28
|
+
Returns
|
|
29
|
+
-------
|
|
30
|
+
matplotlib.axes.Axes
|
|
31
|
+
"""
|
|
32
|
+
if ax is None:
|
|
33
|
+
_, ax = plt.subplots(figsize=(5, 5))
|
|
34
|
+
speeds = gas.speeds()
|
|
35
|
+
c = speeds if color_by_speed else "steelblue"
|
|
36
|
+
scatter = ax.scatter(gas.positions[:, 0], gas.positions[:, 1], c=c, cmap="plasma", s=25)
|
|
37
|
+
if color_by_speed:
|
|
38
|
+
plt.colorbar(scatter, ax=ax, fraction=0.046, pad=0.04, label="speed")
|
|
39
|
+
if show_velocities:
|
|
40
|
+
ax.quiver(
|
|
41
|
+
gas.positions[:, 0],
|
|
42
|
+
gas.positions[:, 1],
|
|
43
|
+
gas.velocities[:, 0],
|
|
44
|
+
gas.velocities[:, 1],
|
|
45
|
+
color="black",
|
|
46
|
+
alpha=0.5,
|
|
47
|
+
scale_units="xy",
|
|
48
|
+
angles="xy",
|
|
49
|
+
scale=1.0,
|
|
50
|
+
)
|
|
51
|
+
ax.set_xlim(0, gas.box_size)
|
|
52
|
+
ax.set_ylim(0, gas.box_size)
|
|
53
|
+
ax.set_aspect("equal")
|
|
54
|
+
ax.set_title(f"t = {gas.time:.2f}, T = {gas.temperature():.2f}")
|
|
55
|
+
return ax
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def plot_velocity_histogram(gas, ax=None, bins=40, show_theory=True):
|
|
59
|
+
"""Plot the current speed histogram against the theoretical Maxwell-Boltzmann curve.
|
|
60
|
+
|
|
61
|
+
Parameters
|
|
62
|
+
----------
|
|
63
|
+
gas : LennardJonesGas
|
|
64
|
+
Simulation instance to render.
|
|
65
|
+
ax : matplotlib.axes.Axes, optional
|
|
66
|
+
Axes to draw into.
|
|
67
|
+
bins : int, default=40
|
|
68
|
+
Histogram bin count.
|
|
69
|
+
show_theory : bool, default=True
|
|
70
|
+
Whether to overlay the equilibrium Maxwell-Boltzmann density at the
|
|
71
|
+
gas's instantaneous kinetic temperature.
|
|
72
|
+
|
|
73
|
+
Returns
|
|
74
|
+
-------
|
|
75
|
+
matplotlib.axes.Axes
|
|
76
|
+
"""
|
|
77
|
+
if ax is None:
|
|
78
|
+
_, ax = plt.subplots(figsize=(5, 4))
|
|
79
|
+
speeds = gas.speeds()
|
|
80
|
+
ax.hist(speeds, bins=bins, density=True, alpha=0.6, color="steelblue", label="simulation")
|
|
81
|
+
if show_theory:
|
|
82
|
+
v = np.linspace(0, speeds.max() * 1.2, 200)
|
|
83
|
+
pdf = maxwell_boltzmann_speed_pdf(v, gas.temperature(), mass=gas.mass, kB=gas.kB, dim=2)
|
|
84
|
+
ax.plot(v, pdf, color="crimson", linewidth=2, label="Maxwell-Boltzmann")
|
|
85
|
+
ax.set_xlabel("speed")
|
|
86
|
+
ax.set_ylabel("probability density")
|
|
87
|
+
ax.legend()
|
|
88
|
+
return ax
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def animate_gas(gas, n_frames=200, steps_per_frame=5):
|
|
92
|
+
"""Animate the particle gas evolving under Velocity Verlet dynamics.
|
|
93
|
+
|
|
94
|
+
Parameters
|
|
95
|
+
----------
|
|
96
|
+
gas : LennardJonesGas
|
|
97
|
+
Simulation instance to animate; advanced in place.
|
|
98
|
+
n_frames : int, default=200
|
|
99
|
+
Number of animation frames.
|
|
100
|
+
steps_per_frame : int, default=5
|
|
101
|
+
Integration steps performed between consecutive frames.
|
|
102
|
+
|
|
103
|
+
Returns
|
|
104
|
+
-------
|
|
105
|
+
matplotlib.animation.FuncAnimation
|
|
106
|
+
"""
|
|
107
|
+
fig, ax = plt.subplots(figsize=(5, 5))
|
|
108
|
+
scatter = ax.scatter(gas.positions[:, 0], gas.positions[:, 1], c=gas.speeds(), cmap="plasma", s=25)
|
|
109
|
+
ax.set_xlim(0, gas.box_size)
|
|
110
|
+
ax.set_ylim(0, gas.box_size)
|
|
111
|
+
ax.set_aspect("equal")
|
|
112
|
+
title = ax.set_title(f"t = {gas.time:.2f}")
|
|
113
|
+
|
|
114
|
+
def update(_frame):
|
|
115
|
+
gas.step(steps_per_frame)
|
|
116
|
+
scatter.set_offsets(gas.positions)
|
|
117
|
+
scatter.set_array(gas.speeds())
|
|
118
|
+
title.set_text(f"t = {gas.time:.2f}, T = {gas.temperature():.2f}")
|
|
119
|
+
return scatter, title
|
|
120
|
+
|
|
121
|
+
return FuncAnimation(fig, update, frames=n_frames, blit=False, interval=40)
|