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,275 @@
|
|
|
1
|
+
"""Spin glasses: quenched disorder, frustration, and replica symmetry breaking.
|
|
2
|
+
|
|
3
|
+
Unlike the pure Ising model, where every bond has the same sign, a spin
|
|
4
|
+
glass's bond couplings are themselves random variables, fixed ("quenched")
|
|
5
|
+
for the lifetime of a given sample rather than fluctuating with the spins.
|
|
6
|
+
A plaquette with an odd number of antiferromagnetic bonds is *frustrated*:
|
|
7
|
+
no spin configuration can satisfy every one of its bonds simultaneously.
|
|
8
|
+
This produces a rugged, many-valley energy landscape and, below a spin-glass
|
|
9
|
+
transition temperature, a frozen but disordered ground state -- detected not
|
|
10
|
+
by a conventional magnetization but by the Edwards-Anderson order
|
|
11
|
+
parameter, the overlap between two independently thermalized replicas of
|
|
12
|
+
the same disorder realization.
|
|
13
|
+
|
|
14
|
+
:class:`EdwardsAndersonSpinGlass2D` is the short-range, nearest-neighbor
|
|
15
|
+
version of this story on a 2D lattice. :class:`SherringtonKirkpatrick` is
|
|
16
|
+
its infinite-range completion: every spin couples to every other spin, the
|
|
17
|
+
model Sherrington and Kirkpatrick introduced in 1975 and that Giorgio
|
|
18
|
+
Parisi's 1979-1980 replica-symmetry-breaking solution ultimately resolved,
|
|
19
|
+
revealing an equilibrium phase built not from one ground state but from a
|
|
20
|
+
hierarchy of infinitely many, organized by a nontrivial overlap
|
|
21
|
+
distribution :math:`P(q)` rather than a single frozen value.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import numpy as np
|
|
27
|
+
|
|
28
|
+
from physicskit.statphys.core.monte_carlo import (
|
|
29
|
+
metropolis_sweep_sk,
|
|
30
|
+
metropolis_sweep_spin_glass,
|
|
31
|
+
seed_numba_random,
|
|
32
|
+
sk_total_energy,
|
|
33
|
+
spin_glass_total_energy,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
__all__ = ["EdwardsAndersonSpinGlass2D", "SherringtonKirkpatrick"]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class EdwardsAndersonSpinGlass2D:
|
|
40
|
+
"""The 2D +/-J Edwards-Anderson Ising spin glass on a periodic L x L lattice.
|
|
41
|
+
|
|
42
|
+
Parameters
|
|
43
|
+
----------
|
|
44
|
+
L : int, default=32
|
|
45
|
+
Linear lattice size.
|
|
46
|
+
J : float, default=1.0
|
|
47
|
+
Bond magnitude; each bond independently takes the value ``+J`` or
|
|
48
|
+
``-J`` with equal probability (the "bimodal" Edwards-Anderson
|
|
49
|
+
glass).
|
|
50
|
+
kB : float, default=1.0
|
|
51
|
+
Boltzmann constant.
|
|
52
|
+
seed : int, optional
|
|
53
|
+
Seed for the quenched disorder realization, the initial spin
|
|
54
|
+
configuration, and the Metropolis dynamics.
|
|
55
|
+
|
|
56
|
+
Attributes
|
|
57
|
+
----------
|
|
58
|
+
spins : ndarray of shape (L, L)
|
|
59
|
+
Current spin configuration, values in ``{-1, +1}``.
|
|
60
|
+
J_right, J_down : ndarray of shape (L, L)
|
|
61
|
+
Quenched bond couplings; see
|
|
62
|
+
:func:`physicskit.statphys.core.monte_carlo.metropolis_sweep_spin_glass` for
|
|
63
|
+
their indexing convention. Fixed for the model's lifetime.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
def __init__(self, L=32, J=1.0, kB=1.0, seed=None):
|
|
67
|
+
self.L = L
|
|
68
|
+
self.J = J
|
|
69
|
+
self.kB = kB
|
|
70
|
+
self.n_sites = L * L
|
|
71
|
+
self._rng = np.random.default_rng(seed)
|
|
72
|
+
if seed is not None:
|
|
73
|
+
seed_numba_random(seed)
|
|
74
|
+
self.spins = self._rng.choice(np.array([-1, 1], dtype=np.int64), size=(L, L))
|
|
75
|
+
self.J_right = self._rng.choice(np.array([-J, J]), size=(L, L))
|
|
76
|
+
self.J_down = self._rng.choice(np.array([-J, J]), size=(L, L))
|
|
77
|
+
|
|
78
|
+
def sweep(self, beta, n_sweeps=1):
|
|
79
|
+
"""Advance the spins by ``n_sweeps`` Metropolis-Hastings sweeps (bonds are fixed).
|
|
80
|
+
|
|
81
|
+
Parameters
|
|
82
|
+
----------
|
|
83
|
+
beta : float
|
|
84
|
+
Inverse temperature.
|
|
85
|
+
n_sweeps : int, default=1
|
|
86
|
+
Number of sweeps to perform.
|
|
87
|
+
"""
|
|
88
|
+
for _ in range(n_sweeps):
|
|
89
|
+
metropolis_sweep_spin_glass(self.spins, beta, self.J_right, self.J_down)
|
|
90
|
+
|
|
91
|
+
def energy(self):
|
|
92
|
+
"""Total energy :math:`-\\sum_{\\langle i,j\\rangle} J_{ij} s_i s_j` of the current configuration."""
|
|
93
|
+
return spin_glass_total_energy(self.spins, self.J_right, self.J_down)
|
|
94
|
+
|
|
95
|
+
def frustration_density(self):
|
|
96
|
+
"""Fraction of elementary plaquettes that are frustrated.
|
|
97
|
+
|
|
98
|
+
A plaquette is frustrated when the product of its four bond
|
|
99
|
+
couplings is negative -- no spin configuration can satisfy all four
|
|
100
|
+
bonds at once. This is a fixed geometric property of the quenched
|
|
101
|
+
disorder, independent of the current spin configuration.
|
|
102
|
+
|
|
103
|
+
Returns
|
|
104
|
+
-------
|
|
105
|
+
float
|
|
106
|
+
"""
|
|
107
|
+
product = self.J_right * np.roll(self.J_down, -1, axis=1) * np.roll(self.J_right, -1, axis=0) * self.J_down
|
|
108
|
+
return float(np.mean(product < 0))
|
|
109
|
+
|
|
110
|
+
def edwards_anderson_order_parameter(self, beta, n_equil=200, n_measure=200, measure_every=1):
|
|
111
|
+
"""Estimate :math:`\\langle q^2 \\rangle`, the mean-squared Edwards-Anderson replica overlap.
|
|
112
|
+
|
|
113
|
+
Two independently initialized and thermalized replicas, sharing the
|
|
114
|
+
*same* quenched bonds, are compared via their spin overlap
|
|
115
|
+
:math:`q = \\frac{1}{N}\\sum_i s_i^{(1)} s_i^{(2)}`. Even though
|
|
116
|
+
each replica's spins keep fluctuating, below the spin-glass
|
|
117
|
+
transition they fluctuate around the same disorder-selected frozen
|
|
118
|
+
pattern, so :math:`\\langle q^2 \\rangle` stays nonzero; above it,
|
|
119
|
+
the replicas decorrelate and :math:`\\langle q^2 \\rangle \\to 0`.
|
|
120
|
+
|
|
121
|
+
Parameters
|
|
122
|
+
----------
|
|
123
|
+
beta : float
|
|
124
|
+
Inverse temperature.
|
|
125
|
+
n_equil : int, default=200
|
|
126
|
+
Equilibration sweeps for each replica.
|
|
127
|
+
n_measure : int, default=200
|
|
128
|
+
Number of overlap measurements.
|
|
129
|
+
measure_every : int, default=1
|
|
130
|
+
Sweeps between successive measurements.
|
|
131
|
+
|
|
132
|
+
Returns
|
|
133
|
+
-------
|
|
134
|
+
float
|
|
135
|
+
Estimated :math:`\\langle q^2 \\rangle \\in [0, 1]`.
|
|
136
|
+
"""
|
|
137
|
+
replica_a = self._rng.choice(np.array([-1, 1], dtype=np.int64), size=(self.L, self.L))
|
|
138
|
+
replica_b = self._rng.choice(np.array([-1, 1], dtype=np.int64), size=(self.L, self.L))
|
|
139
|
+
for _ in range(n_equil):
|
|
140
|
+
metropolis_sweep_spin_glass(replica_a, beta, self.J_right, self.J_down)
|
|
141
|
+
metropolis_sweep_spin_glass(replica_b, beta, self.J_right, self.J_down)
|
|
142
|
+
|
|
143
|
+
overlaps = np.empty(n_measure)
|
|
144
|
+
for k in range(n_measure):
|
|
145
|
+
for _ in range(measure_every):
|
|
146
|
+
metropolis_sweep_spin_glass(replica_a, beta, self.J_right, self.J_down)
|
|
147
|
+
metropolis_sweep_spin_glass(replica_b, beta, self.J_right, self.J_down)
|
|
148
|
+
overlaps[k] = np.mean(replica_a * replica_b)
|
|
149
|
+
return float(np.mean(overlaps**2))
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class SherringtonKirkpatrick:
|
|
153
|
+
"""The infinite-range Sherrington-Kirkpatrick Ising spin glass on N fully-connected spins.
|
|
154
|
+
|
|
155
|
+
Every pair of spins is coupled by an independent Gaussian random bond,
|
|
156
|
+
|
|
157
|
+
.. math::
|
|
158
|
+
|
|
159
|
+
H = -\\sum_{i<j} J_{ij}\\, s_i s_j, \\qquad
|
|
160
|
+
J_{ij} \\sim \\mathcal{N}\\!\\left(0, \\frac{J^2}{N}\\right),
|
|
161
|
+
|
|
162
|
+
where the :math:`1/N` variance scaling is what keeps the energy
|
|
163
|
+
extensive as :math:`N \\to \\infty`. Rather than attempt Parisi's
|
|
164
|
+
analytic replica-symmetry-breaking solution, :meth:`overlap_distribution`
|
|
165
|
+
measures its numerically observable fingerprint directly: the
|
|
166
|
+
distribution :math:`P(q)` of the replica overlap
|
|
167
|
+
:math:`q = \\frac{1}{N}\\sum_i s_i^{(1)} s_i^{(2)}`, pooled over many
|
|
168
|
+
independent disorder realizations. A single sharp peak at :math:`q=0`
|
|
169
|
+
signals the trivial (replica-symmetric) paramagnetic phase; a broad,
|
|
170
|
+
non-Gaussian, non-self-averaging :math:`P(q)` is the finite-size
|
|
171
|
+
signature of the many-valley spin-glass phase that Parisi's solution
|
|
172
|
+
describes exactly in the :math:`N \\to \\infty` limit.
|
|
173
|
+
|
|
174
|
+
Parameters
|
|
175
|
+
----------
|
|
176
|
+
N : int, default=128
|
|
177
|
+
Number of spins. Note one sweep costs :math:`O(N^2)`, since every
|
|
178
|
+
spin couples to every other one.
|
|
179
|
+
J : float, default=1.0
|
|
180
|
+
Coupling scale; bond strengths are drawn from :math:`\\mathcal{N}(0,
|
|
181
|
+
J^2/N)`.
|
|
182
|
+
kB : float, default=1.0
|
|
183
|
+
Boltzmann constant.
|
|
184
|
+
seed : int, optional
|
|
185
|
+
Seed for the quenched disorder, initial spins, and dynamics.
|
|
186
|
+
|
|
187
|
+
Attributes
|
|
188
|
+
----------
|
|
189
|
+
spins : ndarray of shape (N,)
|
|
190
|
+
Current spin configuration, values in ``{-1, +1}``.
|
|
191
|
+
J : ndarray of shape (N, N)
|
|
192
|
+
Quenched, symmetric coupling matrix with zero diagonal. Fixed for
|
|
193
|
+
the model's lifetime.
|
|
194
|
+
"""
|
|
195
|
+
|
|
196
|
+
def __init__(self, N=128, J=1.0, kB=1.0, seed=None):
|
|
197
|
+
self.N = N
|
|
198
|
+
self.J_scale = J
|
|
199
|
+
self.kB = kB
|
|
200
|
+
self._rng = np.random.default_rng(seed)
|
|
201
|
+
if seed is not None:
|
|
202
|
+
seed_numba_random(seed)
|
|
203
|
+
self.spins = self._rng.choice(np.array([-1, 1], dtype=np.int64), size=N)
|
|
204
|
+
bonds = self._rng.normal(loc=0.0, scale=J / np.sqrt(N), size=(N, N))
|
|
205
|
+
upper = np.triu(bonds, k=1)
|
|
206
|
+
self.J = upper + upper.T
|
|
207
|
+
|
|
208
|
+
def sweep(self, beta, n_sweeps=1):
|
|
209
|
+
"""Advance the spins by ``n_sweeps`` Metropolis-Hastings sweeps (bonds are fixed).
|
|
210
|
+
|
|
211
|
+
Parameters
|
|
212
|
+
----------
|
|
213
|
+
beta : float
|
|
214
|
+
Inverse temperature.
|
|
215
|
+
n_sweeps : int, default=1
|
|
216
|
+
Number of sweeps to perform.
|
|
217
|
+
"""
|
|
218
|
+
for _ in range(n_sweeps):
|
|
219
|
+
metropolis_sweep_sk(self.spins, beta, self.J)
|
|
220
|
+
|
|
221
|
+
def energy(self):
|
|
222
|
+
"""Total energy :math:`-\\sum_{i<j} J_{ij} s_i s_j` of the current configuration."""
|
|
223
|
+
return sk_total_energy(self.spins, self.J)
|
|
224
|
+
|
|
225
|
+
def overlap_distribution(self, beta, n_disorder=30, n_equil=300, n_measure=100, measure_every=1):
|
|
226
|
+
"""Sample the replica-overlap distribution P(q), pooled over independent disorder realizations.
|
|
227
|
+
|
|
228
|
+
For each of ``n_disorder`` independent bond realizations, two
|
|
229
|
+
replicas are initialized randomly, thermalized under that shared
|
|
230
|
+
disorder, and their overlap :math:`q = \\frac{1}{N}\\sum_i
|
|
231
|
+
s_i^{(1)} s_i^{(2)}` recorded repeatedly. Pooling samples across
|
|
232
|
+
many disorder realizations (rather than just many measurements of
|
|
233
|
+
one realization) is essential here: unlike the Edwards-Anderson
|
|
234
|
+
model's single well-defined :math:`\\langle q^2 \\rangle`, the SK
|
|
235
|
+
spin glass's overlap distribution is sample-dependent (it does not
|
|
236
|
+
self-average) below the transition, and it is exactly this
|
|
237
|
+
sample-to-sample variability that Parisi's solution organizes into
|
|
238
|
+
a hierarchy of pure states.
|
|
239
|
+
|
|
240
|
+
Parameters
|
|
241
|
+
----------
|
|
242
|
+
beta : float
|
|
243
|
+
Inverse temperature.
|
|
244
|
+
n_disorder : int, default=30
|
|
245
|
+
Number of independent quenched-disorder realizations to sample.
|
|
246
|
+
n_equil : int, default=300
|
|
247
|
+
Equilibration sweeps per replica, for each disorder realization.
|
|
248
|
+
n_measure : int, default=100
|
|
249
|
+
Number of overlap measurements per disorder realization.
|
|
250
|
+
measure_every : int, default=1
|
|
251
|
+
Sweeps between successive measurements.
|
|
252
|
+
|
|
253
|
+
Returns
|
|
254
|
+
-------
|
|
255
|
+
ndarray of shape (n_disorder * n_measure,)
|
|
256
|
+
Pooled overlap samples :math:`q \\in [-1, 1]`.
|
|
257
|
+
"""
|
|
258
|
+
samples = np.empty(n_disorder * n_measure)
|
|
259
|
+
idx = 0
|
|
260
|
+
for _ in range(n_disorder):
|
|
261
|
+
bonds = self._rng.normal(loc=0.0, scale=self.J_scale / np.sqrt(self.N), size=(self.N, self.N))
|
|
262
|
+
upper = np.triu(bonds, k=1)
|
|
263
|
+
J = upper + upper.T
|
|
264
|
+
replica_a = self._rng.choice(np.array([-1, 1], dtype=np.int64), size=self.N)
|
|
265
|
+
replica_b = self._rng.choice(np.array([-1, 1], dtype=np.int64), size=self.N)
|
|
266
|
+
for _ in range(n_equil):
|
|
267
|
+
metropolis_sweep_sk(replica_a, beta, J)
|
|
268
|
+
metropolis_sweep_sk(replica_b, beta, J)
|
|
269
|
+
for _ in range(n_measure):
|
|
270
|
+
for _ in range(measure_every):
|
|
271
|
+
metropolis_sweep_sk(replica_a, beta, J)
|
|
272
|
+
metropolis_sweep_sk(replica_b, beta, J)
|
|
273
|
+
samples[idx] = np.mean(replica_a * replica_b)
|
|
274
|
+
idx += 1
|
|
275
|
+
return samples
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""Low-level, Numba-accelerated simulation kernels.
|
|
2
|
+
|
|
3
|
+
:mod:`physicskit.statphys.core.monte_carlo` holds the Metropolis-Hastings and Wolff
|
|
4
|
+
lattice-update kernels used by :mod:`physicskit.statphys.chapters.ising_lattice`.
|
|
5
|
+
:mod:`physicskit.statphys.core.md_engine` holds the Lennard-Jones force evaluation and
|
|
6
|
+
Velocity Verlet integrator used by :mod:`physicskit.statphys.chapters.molecular_dynamics`.
|
|
7
|
+
|
|
8
|
+
These functions operate on plain NumPy arrays and carry no state; the
|
|
9
|
+
stateful, user-facing model classes live in :mod:`physicskit.statphys.chapters`.
|
|
10
|
+
"""
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Numba-accelerated Restricted Solid-On-Solid (RSOS) growth dynamics.
|
|
2
|
+
|
|
3
|
+
The RSOS model is the standard discrete lattice realization of the
|
|
4
|
+
Kardar-Parisi-Zhang universality class in 1+1 dimensions: a local growth
|
|
5
|
+
rule with no free parameters to tune, whose interface width nonetheless
|
|
6
|
+
reproduces the continuum KPZ equation's universal roughness, growth, and
|
|
7
|
+
dynamic exponents.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
from numba import njit
|
|
14
|
+
|
|
15
|
+
__all__ = ["run_rsos"]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@njit(cache=True)
|
|
19
|
+
def run_rsos(heights, n_attempts, L):
|
|
20
|
+
"""Attempt ``n_attempts`` random single-site RSOS deposition events, in place.
|
|
21
|
+
|
|
22
|
+
At each attempt, a uniformly random site ``i`` is chosen and its height
|
|
23
|
+
tentatively raised by one. The move is accepted only if it keeps the
|
|
24
|
+
restricted solid-on-solid constraint :math:`|h_i - h_{i\\pm1}| \\le 1`
|
|
25
|
+
satisfied with both periodic neighbors; otherwise the site is left
|
|
26
|
+
unchanged. This single local constraint -- with no explicit surface
|
|
27
|
+
tension or nonlinear term written anywhere -- is enough to place the
|
|
28
|
+
resulting interface in the KPZ universality class.
|
|
29
|
+
|
|
30
|
+
Parameters
|
|
31
|
+
----------
|
|
32
|
+
heights : ndarray of shape (L,), dtype int64
|
|
33
|
+
Interface height profile. Modified in place.
|
|
34
|
+
n_attempts : int
|
|
35
|
+
Number of random deposition attempts to perform. One Monte Carlo
|
|
36
|
+
sweep conventionally corresponds to ``n_attempts = L``, i.e. one
|
|
37
|
+
attempt per site on average.
|
|
38
|
+
L : int
|
|
39
|
+
Number of sites (periodic boundary conditions).
|
|
40
|
+
|
|
41
|
+
Returns
|
|
42
|
+
-------
|
|
43
|
+
ndarray of shape (L,)
|
|
44
|
+
The same array passed in.
|
|
45
|
+
"""
|
|
46
|
+
for _ in range(n_attempts):
|
|
47
|
+
i = np.random.randint(0, L)
|
|
48
|
+
left = heights[(i - 1) % L]
|
|
49
|
+
right = heights[(i + 1) % L]
|
|
50
|
+
new_h = heights[i] + 1
|
|
51
|
+
if abs(new_h - left) <= 1 and abs(new_h - right) <= 1:
|
|
52
|
+
heights[i] = new_h
|
|
53
|
+
return heights
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""Numba-accelerated molecular dynamics engine: Lennard-Jones forces and Velocity Verlet.
|
|
2
|
+
|
|
3
|
+
Implements a minimal-image, periodic-boundary N-body simulator for a 2D
|
|
4
|
+
Lennard-Jones gas. The pairwise force evaluation is the O(N^2) inner loop and
|
|
5
|
+
is the part that benefits from JIT compilation; everything else is thin
|
|
6
|
+
Python bookkeeping around it.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
from numba import njit
|
|
13
|
+
|
|
14
|
+
__all__ = ["initialize_maxwell_boltzmann_velocities", "lj_forces", "velocity_verlet_step"]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@njit(cache=True)
|
|
18
|
+
def lj_forces(positions, box_size, epsilon=1.0, sigma=1.0, cutoff=2.5):
|
|
19
|
+
"""Pairwise Lennard-Jones forces and potential energy under minimum-image PBC.
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
positions : ndarray of shape (N, 2)
|
|
24
|
+
Particle positions, expected in ``[0, box_size)``.
|
|
25
|
+
box_size : float
|
|
26
|
+
Side length of the square periodic simulation box.
|
|
27
|
+
epsilon : float, default=1.0
|
|
28
|
+
Lennard-Jones well depth.
|
|
29
|
+
sigma : float, default=1.0
|
|
30
|
+
Lennard-Jones length scale (zero-crossing distance).
|
|
31
|
+
cutoff : float, default=2.5
|
|
32
|
+
Interaction cutoff radius, in the same length units as ``sigma``.
|
|
33
|
+
|
|
34
|
+
Returns
|
|
35
|
+
-------
|
|
36
|
+
forces : ndarray of shape (N, 2)
|
|
37
|
+
Net force on each particle.
|
|
38
|
+
potential_energy : float
|
|
39
|
+
Total (uncut-shifted) Lennard-Jones potential energy of the
|
|
40
|
+
configuration.
|
|
41
|
+
|
|
42
|
+
Notes
|
|
43
|
+
-----
|
|
44
|
+
The Lennard-Jones potential is
|
|
45
|
+
:math:`V(r) = 4\\epsilon\\left[(\\sigma/r)^{12} - (\\sigma/r)^{6}\\right]`,
|
|
46
|
+
giving the force magnitude
|
|
47
|
+
:math:`f(r) = 24\\epsilon\\left[2(\\sigma/r)^{12} - (\\sigma/r)^{6}\\right] / r`.
|
|
48
|
+
"""
|
|
49
|
+
n = positions.shape[0]
|
|
50
|
+
forces = np.zeros((n, 2), dtype=np.float64)
|
|
51
|
+
potential_energy = 0.0
|
|
52
|
+
cutoff2 = cutoff * cutoff
|
|
53
|
+
sigma2 = sigma * sigma
|
|
54
|
+
for a in range(n):
|
|
55
|
+
xa = positions[a, 0]
|
|
56
|
+
ya = positions[a, 1]
|
|
57
|
+
for b in range(a + 1, n):
|
|
58
|
+
dx = xa - positions[b, 0]
|
|
59
|
+
dy = ya - positions[b, 1]
|
|
60
|
+
dx -= box_size * np.round(dx / box_size)
|
|
61
|
+
dy -= box_size * np.round(dy / box_size)
|
|
62
|
+
r2 = dx * dx + dy * dy
|
|
63
|
+
if 1e-12 < r2 < cutoff2:
|
|
64
|
+
inv_r2 = sigma2 / r2
|
|
65
|
+
inv_r6 = inv_r2 * inv_r2 * inv_r2
|
|
66
|
+
inv_r12 = inv_r6 * inv_r6
|
|
67
|
+
f_over_r2 = 24.0 * epsilon * (2.0 * inv_r12 - inv_r6) / r2
|
|
68
|
+
fx = f_over_r2 * dx
|
|
69
|
+
fy = f_over_r2 * dy
|
|
70
|
+
forces[a, 0] += fx
|
|
71
|
+
forces[a, 1] += fy
|
|
72
|
+
forces[b, 0] -= fx
|
|
73
|
+
forces[b, 1] -= fy
|
|
74
|
+
potential_energy += 4.0 * epsilon * (inv_r12 - inv_r6)
|
|
75
|
+
return forces, potential_energy
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def velocity_verlet_step(positions, velocities, forces, dt, box_size, mass=1.0, **lj_kwargs):
|
|
79
|
+
"""Advance positions and velocities by one Velocity Verlet step.
|
|
80
|
+
|
|
81
|
+
Parameters
|
|
82
|
+
----------
|
|
83
|
+
positions : ndarray of shape (N, 2)
|
|
84
|
+
Current positions. Not modified; a new array is returned.
|
|
85
|
+
velocities : ndarray of shape (N, 2)
|
|
86
|
+
Current velocities.
|
|
87
|
+
forces : ndarray of shape (N, 2)
|
|
88
|
+
Forces evaluated at the current positions (from the previous step's
|
|
89
|
+
call, so the force is only ever computed once per step).
|
|
90
|
+
dt : float
|
|
91
|
+
Integration time step.
|
|
92
|
+
box_size : float
|
|
93
|
+
Side length of the periodic simulation box.
|
|
94
|
+
mass : float, default=1.0
|
|
95
|
+
Common particle mass.
|
|
96
|
+
**lj_kwargs
|
|
97
|
+
Extra keyword arguments (``epsilon``, ``sigma``, ``cutoff``) forwarded
|
|
98
|
+
to :func:`lj_forces`.
|
|
99
|
+
|
|
100
|
+
Returns
|
|
101
|
+
-------
|
|
102
|
+
new_positions : ndarray of shape (N, 2)
|
|
103
|
+
Positions after one step, wrapped into ``[0, box_size)``.
|
|
104
|
+
new_velocities : ndarray of shape (N, 2)
|
|
105
|
+
Velocities after one step.
|
|
106
|
+
new_forces : ndarray of shape (N, 2)
|
|
107
|
+
Forces evaluated at ``new_positions``, ready for the next call.
|
|
108
|
+
potential_energy : float
|
|
109
|
+
Potential energy at ``new_positions``.
|
|
110
|
+
"""
|
|
111
|
+
new_positions = positions + velocities * dt + 0.5 * (forces / mass) * dt * dt
|
|
112
|
+
new_positions = np.mod(new_positions, box_size)
|
|
113
|
+
new_forces, potential_energy = lj_forces(new_positions, box_size, **lj_kwargs)
|
|
114
|
+
new_velocities = velocities + 0.5 * (forces + new_forces) / mass * dt
|
|
115
|
+
return new_positions, new_velocities, new_forces, potential_energy
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def initialize_maxwell_boltzmann_velocities(n_particles, temperature, mass=1.0, kB=1.0, rng=None):
|
|
119
|
+
"""Draw initial 2D velocities from the Maxwell-Boltzmann distribution and remove drift.
|
|
120
|
+
|
|
121
|
+
Each velocity component is drawn i.i.d. from
|
|
122
|
+
:math:`\\mathcal{N}(0, k_B T / m)`, then the center-of-mass velocity is
|
|
123
|
+
subtracted so the total momentum is zero.
|
|
124
|
+
|
|
125
|
+
Parameters
|
|
126
|
+
----------
|
|
127
|
+
n_particles : int
|
|
128
|
+
Number of particles.
|
|
129
|
+
temperature : float
|
|
130
|
+
Target temperature.
|
|
131
|
+
mass : float, default=1.0
|
|
132
|
+
Particle mass.
|
|
133
|
+
kB : float, default=1.0
|
|
134
|
+
Boltzmann constant, in whatever unit system is being used.
|
|
135
|
+
rng : numpy.random.Generator, optional
|
|
136
|
+
Random number generator. A fresh default generator is created if not
|
|
137
|
+
given.
|
|
138
|
+
|
|
139
|
+
Returns
|
|
140
|
+
-------
|
|
141
|
+
ndarray of shape (n_particles, 2)
|
|
142
|
+
Initial velocities with zero net momentum.
|
|
143
|
+
|
|
144
|
+
Examples
|
|
145
|
+
--------
|
|
146
|
+
>>> v = initialize_maxwell_boltzmann_velocities(100, temperature=1.5, rng=np.random.default_rng(0))
|
|
147
|
+
>>> v.shape
|
|
148
|
+
(100, 2)
|
|
149
|
+
>>> np.allclose(v.mean(axis=0), 0.0)
|
|
150
|
+
True
|
|
151
|
+
"""
|
|
152
|
+
if rng is None:
|
|
153
|
+
rng = np.random.default_rng()
|
|
154
|
+
std = np.sqrt(kB * temperature / mass)
|
|
155
|
+
velocities = rng.normal(loc=0.0, scale=std, size=(n_particles, 2))
|
|
156
|
+
velocities -= velocities.mean(axis=0, keepdims=True)
|
|
157
|
+
return velocities
|