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,258 @@
|
|
|
1
|
+
"""N-body Lennard-Jones gas: Velocity Verlet dynamics and Boltzmann's H-theorem.
|
|
2
|
+
|
|
3
|
+
:class:`LennardJonesGas` simulates a 2D periodic gas of Lennard-Jones
|
|
4
|
+
particles and lets it relax toward equilibrium from an arbitrary initial
|
|
5
|
+
velocity distribution. Along the way it tracks Boltzmann's H-function, whose
|
|
6
|
+
monotonic decrease is the classic microscopic demonstration that
|
|
7
|
+
time-reversible molecular dynamics nonetheless produces macroscopic
|
|
8
|
+
irreversibility (an arrow of time) as the velocity distribution relaxes to
|
|
9
|
+
the Maxwell-Boltzmann form.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import numpy as np
|
|
15
|
+
|
|
16
|
+
from physicskit.statphys.core.md_engine import lj_forces, velocity_verlet_step
|
|
17
|
+
|
|
18
|
+
__all__ = ["LennardJonesGas"]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class LennardJonesGas:
|
|
22
|
+
"""A 2D N-particle Lennard-Jones gas in a periodic square box.
|
|
23
|
+
|
|
24
|
+
Particles are initialized on a lattice (to avoid the divergent
|
|
25
|
+
Lennard-Jones repulsion of random overlapping placements) and given
|
|
26
|
+
velocities drawn from an arbitrary, generally non-equilibrium initial
|
|
27
|
+
distribution, then integrated with the symplectic Velocity Verlet
|
|
28
|
+
scheme.
|
|
29
|
+
|
|
30
|
+
Parameters
|
|
31
|
+
----------
|
|
32
|
+
n_particles : int, default=100
|
|
33
|
+
Number of particles. Rounded up internally so that
|
|
34
|
+
``ceil(sqrt(n_particles))**2`` particles fit on a square starting
|
|
35
|
+
lattice; the requested count is used for all physical averages.
|
|
36
|
+
box_size : float, default=20.0
|
|
37
|
+
Side length of the square periodic simulation box.
|
|
38
|
+
temperature_init : float, default=1.0
|
|
39
|
+
Nominal temperature used to set the initial velocity scale (see
|
|
40
|
+
``initial_velocity_distribution``).
|
|
41
|
+
mass : float, default=1.0
|
|
42
|
+
Common particle mass.
|
|
43
|
+
dt : float, default=0.005
|
|
44
|
+
Integration time step.
|
|
45
|
+
epsilon : float, default=1.0
|
|
46
|
+
Lennard-Jones well depth.
|
|
47
|
+
sigma : float, default=1.0
|
|
48
|
+
Lennard-Jones length scale.
|
|
49
|
+
cutoff : float, default=2.5
|
|
50
|
+
Interaction cutoff radius.
|
|
51
|
+
initial_velocity_distribution : {"maxwell_boltzmann", "uniform", "delta"}, default="uniform"
|
|
52
|
+
Shape of the initial (generally non-equilibrium) velocity
|
|
53
|
+
distribution. ``"uniform"`` and ``"delta"`` are useful starting
|
|
54
|
+
points for watching relaxation toward Maxwell-Boltzmann via the
|
|
55
|
+
H-theorem; ``"maxwell_boltzmann"`` starts already at equilibrium.
|
|
56
|
+
kB : float, default=1.0
|
|
57
|
+
Boltzmann constant.
|
|
58
|
+
seed : int, optional
|
|
59
|
+
Seed for the initial configuration.
|
|
60
|
+
|
|
61
|
+
Attributes
|
|
62
|
+
----------
|
|
63
|
+
positions : ndarray of shape (N, 2)
|
|
64
|
+
velocities : ndarray of shape (N, 2)
|
|
65
|
+
forces : ndarray of shape (N, 2)
|
|
66
|
+
Forces at the current ``positions``, kept up to date across calls to
|
|
67
|
+
:meth:`step` so each step costs one force evaluation.
|
|
68
|
+
time : float
|
|
69
|
+
Elapsed simulation time.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
def __init__(
|
|
73
|
+
self,
|
|
74
|
+
n_particles=100,
|
|
75
|
+
box_size=20.0,
|
|
76
|
+
temperature_init=1.0,
|
|
77
|
+
mass=1.0,
|
|
78
|
+
dt=0.005,
|
|
79
|
+
epsilon=1.0,
|
|
80
|
+
sigma=1.0,
|
|
81
|
+
cutoff=2.5,
|
|
82
|
+
initial_velocity_distribution="uniform",
|
|
83
|
+
kB=1.0,
|
|
84
|
+
seed=None,
|
|
85
|
+
):
|
|
86
|
+
self.n_particles = n_particles
|
|
87
|
+
self.box_size = box_size
|
|
88
|
+
self.mass = mass
|
|
89
|
+
self.dt = dt
|
|
90
|
+
self.epsilon = epsilon
|
|
91
|
+
self.sigma = sigma
|
|
92
|
+
self.cutoff = cutoff
|
|
93
|
+
self.kB = kB
|
|
94
|
+
self.time = 0.0
|
|
95
|
+
self._rng = np.random.default_rng(seed)
|
|
96
|
+
|
|
97
|
+
self.positions = self._lattice_positions(n_particles, box_size, self._rng)
|
|
98
|
+
self.velocities = self._initial_velocities(n_particles, temperature_init, mass, kB, initial_velocity_distribution, self._rng)
|
|
99
|
+
self.forces, self._potential_energy = lj_forces(self.positions, box_size, epsilon=epsilon, sigma=sigma, cutoff=cutoff)
|
|
100
|
+
|
|
101
|
+
@staticmethod
|
|
102
|
+
def _lattice_positions(n_particles, box_size, rng):
|
|
103
|
+
n_side = int(np.ceil(np.sqrt(n_particles)))
|
|
104
|
+
spacing = box_size / n_side
|
|
105
|
+
xs, ys = np.meshgrid((np.arange(n_side) + 0.5) * spacing, (np.arange(n_side) + 0.5) * spacing)
|
|
106
|
+
lattice = np.column_stack([xs.ravel(), ys.ravel()])
|
|
107
|
+
jitter = rng.uniform(-0.05 * spacing, 0.05 * spacing, size=lattice.shape)
|
|
108
|
+
return (lattice + jitter)[:n_particles]
|
|
109
|
+
|
|
110
|
+
@staticmethod
|
|
111
|
+
def _initial_velocities(n_particles, temperature, mass, kB, distribution, rng):
|
|
112
|
+
std = np.sqrt(kB * temperature / mass)
|
|
113
|
+
if distribution == "maxwell_boltzmann":
|
|
114
|
+
v = rng.normal(0.0, std, size=(n_particles, 2))
|
|
115
|
+
elif distribution == "uniform":
|
|
116
|
+
limit = std * np.sqrt(3.0)
|
|
117
|
+
v = rng.uniform(-limit, limit, size=(n_particles, 2))
|
|
118
|
+
elif distribution == "delta":
|
|
119
|
+
speed = std * np.sqrt(2.0)
|
|
120
|
+
angles = rng.uniform(0.0, 2.0 * np.pi, size=n_particles)
|
|
121
|
+
v = speed * np.column_stack([np.cos(angles), np.sin(angles)])
|
|
122
|
+
else:
|
|
123
|
+
raise ValueError("initial_velocity_distribution must be 'maxwell_boltzmann', 'uniform', or 'delta'")
|
|
124
|
+
v -= v.mean(axis=0, keepdims=True)
|
|
125
|
+
return v
|
|
126
|
+
|
|
127
|
+
def step(self, n_steps=1):
|
|
128
|
+
"""Advance the simulation by ``n_steps`` Velocity Verlet integration steps.
|
|
129
|
+
|
|
130
|
+
Parameters
|
|
131
|
+
----------
|
|
132
|
+
n_steps : int, default=1
|
|
133
|
+
Number of integration steps to perform.
|
|
134
|
+
"""
|
|
135
|
+
for _ in range(n_steps):
|
|
136
|
+
self.positions, self.velocities, self.forces, self._potential_energy = velocity_verlet_step(
|
|
137
|
+
self.positions,
|
|
138
|
+
self.velocities,
|
|
139
|
+
self.forces,
|
|
140
|
+
self.dt,
|
|
141
|
+
self.box_size,
|
|
142
|
+
mass=self.mass,
|
|
143
|
+
epsilon=self.epsilon,
|
|
144
|
+
sigma=self.sigma,
|
|
145
|
+
cutoff=self.cutoff,
|
|
146
|
+
)
|
|
147
|
+
self.time += self.dt
|
|
148
|
+
|
|
149
|
+
def kinetic_energy(self):
|
|
150
|
+
"""Total kinetic energy :math:`\\sum_i \\frac{1}{2} m v_i^2`."""
|
|
151
|
+
return 0.5 * self.mass * np.sum(self.velocities**2)
|
|
152
|
+
|
|
153
|
+
def potential_energy(self):
|
|
154
|
+
"""Total Lennard-Jones potential energy at the current configuration."""
|
|
155
|
+
return self._potential_energy
|
|
156
|
+
|
|
157
|
+
def total_energy(self):
|
|
158
|
+
"""Total (kinetic + potential) energy, conserved up to integration error."""
|
|
159
|
+
return self.kinetic_energy() + self.potential_energy()
|
|
160
|
+
|
|
161
|
+
def temperature(self):
|
|
162
|
+
"""Instantaneous kinetic temperature from equipartition, :math:`T = \\langle m v^2 \\rangle / (d\\, k_B)`.
|
|
163
|
+
|
|
164
|
+
With :math:`d=2` spatial dimensions and 2 degrees of freedom removed
|
|
165
|
+
for the fixed center-of-mass momentum.
|
|
166
|
+
"""
|
|
167
|
+
dof = 2 * self.n_particles - 2
|
|
168
|
+
return 2.0 * self.kinetic_energy() / (dof * self.kB)
|
|
169
|
+
|
|
170
|
+
def speeds(self):
|
|
171
|
+
"""Instantaneous particle speeds :math:`|v_i|`."""
|
|
172
|
+
return np.linalg.norm(self.velocities, axis=1)
|
|
173
|
+
|
|
174
|
+
def h_function(self, bins=40, v_max=None):
|
|
175
|
+
"""Estimate Boltzmann's H-function from the instantaneous speed histogram.
|
|
176
|
+
|
|
177
|
+
.. math::
|
|
178
|
+
|
|
179
|
+
H(t) = \\int_0^\\infty f(v, t) \\ln f(v, t) \\, dv
|
|
180
|
+
|
|
181
|
+
estimated by binning the current particle speeds into a normalized
|
|
182
|
+
density histogram. :math:`H` decreases monotonically (on average) as
|
|
183
|
+
an arbitrary initial velocity distribution relaxes toward the
|
|
184
|
+
Maxwell-Boltzmann equilibrium, which minimizes :math:`H` at fixed
|
|
185
|
+
energy -- the microscopic root of the second law of thermodynamics.
|
|
186
|
+
|
|
187
|
+
Parameters
|
|
188
|
+
----------
|
|
189
|
+
bins : int, default=40
|
|
190
|
+
Number of histogram bins.
|
|
191
|
+
v_max : float, optional
|
|
192
|
+
Upper edge of the speed histogram. Defaults to
|
|
193
|
+
``1.5 * speeds().max()``.
|
|
194
|
+
|
|
195
|
+
Returns
|
|
196
|
+
-------
|
|
197
|
+
float
|
|
198
|
+
The estimated value of :math:`H(t)`.
|
|
199
|
+
"""
|
|
200
|
+
speeds = self.speeds()
|
|
201
|
+
if v_max is None:
|
|
202
|
+
v_max = 1.5 * speeds.max() if speeds.max() > 0 else 1.0
|
|
203
|
+
density, edges = np.histogram(speeds, bins=bins, range=(0.0, v_max), density=True)
|
|
204
|
+
widths = np.diff(edges)
|
|
205
|
+
mask = density > 0
|
|
206
|
+
return float(np.sum(density[mask] * np.log(density[mask]) * widths[mask]))
|
|
207
|
+
|
|
208
|
+
def run(self, n_steps, steps_per_record=10, bins=40):
|
|
209
|
+
"""Integrate forward while recording a time series of thermodynamic observables.
|
|
210
|
+
|
|
211
|
+
Parameters
|
|
212
|
+
----------
|
|
213
|
+
n_steps : int
|
|
214
|
+
Total number of integration steps to perform.
|
|
215
|
+
steps_per_record : int, default=10
|
|
216
|
+
Number of integration steps between recorded samples.
|
|
217
|
+
bins : int, default=40
|
|
218
|
+
Histogram bins used for each :meth:`h_function` estimate.
|
|
219
|
+
|
|
220
|
+
Returns
|
|
221
|
+
-------
|
|
222
|
+
dict of str -> ndarray
|
|
223
|
+
Keys ``"time"``, ``"H"``, ``"temperature"``, ``"kinetic_energy"``,
|
|
224
|
+
``"potential_energy"``, ``"total_energy"``, each a 1D array
|
|
225
|
+
sampled every ``steps_per_record`` steps (including the initial
|
|
226
|
+
state).
|
|
227
|
+
|
|
228
|
+
Examples
|
|
229
|
+
--------
|
|
230
|
+
>>> gas = LennardJonesGas(n_particles=64, box_size=15.0, seed=0)
|
|
231
|
+
>>> history = gas.run(n_steps=200, steps_per_record=50)
|
|
232
|
+
>>> history["H"].shape[0]
|
|
233
|
+
5
|
|
234
|
+
"""
|
|
235
|
+
n_records = n_steps // steps_per_record + 1
|
|
236
|
+
history = {
|
|
237
|
+
"time": np.empty(n_records),
|
|
238
|
+
"H": np.empty(n_records),
|
|
239
|
+
"temperature": np.empty(n_records),
|
|
240
|
+
"kinetic_energy": np.empty(n_records),
|
|
241
|
+
"potential_energy": np.empty(n_records),
|
|
242
|
+
"total_energy": np.empty(n_records),
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
def _record(idx):
|
|
246
|
+
history["time"][idx] = self.time
|
|
247
|
+
history["H"][idx] = self.h_function(bins=bins)
|
|
248
|
+
history["temperature"][idx] = self.temperature()
|
|
249
|
+
history["kinetic_energy"][idx] = self.kinetic_energy()
|
|
250
|
+
history["potential_energy"][idx] = self.potential_energy()
|
|
251
|
+
history["total_energy"][idx] = self.total_energy()
|
|
252
|
+
|
|
253
|
+
_record(0)
|
|
254
|
+
for idx in range(1, n_records):
|
|
255
|
+
self.step(steps_per_record)
|
|
256
|
+
_record(idx)
|
|
257
|
+
|
|
258
|
+
return history
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""Jarzynski's equality: exact free energies from irreversible, nonequilibrium work.
|
|
2
|
+
|
|
3
|
+
The second law only bounds the *average* work done driving a system between
|
|
4
|
+
two equilibrium states: :math:`\\langle W \\rangle \\ge \\Delta F`, with
|
|
5
|
+
equality only in the reversible, infinitely slow limit. Jarzynski (1997)
|
|
6
|
+
found a remarkable equality hiding behind this inequality: averaging not
|
|
7
|
+
:math:`W` itself but :math:`e^{-\\beta W}` over an ensemble of repeated
|
|
8
|
+
*arbitrarily fast*, arbitrarily irreversible realizations of the same
|
|
9
|
+
protocol recovers the equilibrium free energy difference exactly,
|
|
10
|
+
|
|
11
|
+
.. math::
|
|
12
|
+
|
|
13
|
+
e^{-\\beta \\Delta F} = \\left\\langle e^{-\\beta W} \\right\\rangle,
|
|
14
|
+
|
|
15
|
+
no matter how far from equilibrium any individual trajectory is driven.
|
|
16
|
+
Jensen's inequality applied to this identity immediately reproduces the
|
|
17
|
+
second law, :math:`\\langle W \\rangle \\ge \\Delta F`, as a corollary
|
|
18
|
+
rather than an independent postulate -- nonequilibrium work fluctuations
|
|
19
|
+
turn out to carry exact equilibrium information, not just a biased,
|
|
20
|
+
dissipation-corrupted estimate of it.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import numpy as np
|
|
26
|
+
|
|
27
|
+
__all__ = ["JarzynskiHarmonicTrap"]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class JarzynskiHarmonicTrap:
|
|
31
|
+
"""A Brownian particle in a harmonic trap dragged at finite speed, verifying the Jarzynski equality.
|
|
32
|
+
|
|
33
|
+
A single overdamped particle sits in the potential :math:`U(x,
|
|
34
|
+
\\lambda) = \\frac{1}{2} k (x - \\lambda)^2`, whose center
|
|
35
|
+
:math:`\\lambda` is the control parameter. :meth:`run_protocol` drags
|
|
36
|
+
:math:`\\lambda` linearly from one value to another over a finite time
|
|
37
|
+
:math:`\\tau`, for many independent realizations starting from thermal
|
|
38
|
+
equilibrium, integrating the overdamped Langevin equation
|
|
39
|
+
|
|
40
|
+
.. math::
|
|
41
|
+
|
|
42
|
+
\\gamma\\, dx = -k(x - \\lambda)\\, dt + \\sqrt{2\\gamma k_B T}\\, dW_t,
|
|
43
|
+
|
|
44
|
+
and accumulating each trajectory's thermodynamic work :math:`W =
|
|
45
|
+
\\int \\frac{\\partial U}{\\partial \\lambda}\\, \\dot\\lambda\\, dt =
|
|
46
|
+
-\\int k(x - \\lambda)\\, d\\lambda`. Because the trap's stiffness never
|
|
47
|
+
changes -- only its center moves -- the true equilibrium free energy is
|
|
48
|
+
identical before and after the protocol, :math:`\\Delta F = 0` exactly,
|
|
49
|
+
by translational invariance. This makes the harmonic trap the cleanest
|
|
50
|
+
possible test case: any protocol speed dissipates heat and drives
|
|
51
|
+
:math:`\\langle W \\rangle` strictly positive (the second law), while
|
|
52
|
+
the exponential average of the *same* work samples should recover
|
|
53
|
+
:math:`\\Delta F = 0` regardless of how fast or slow the drag is.
|
|
54
|
+
|
|
55
|
+
Parameters
|
|
56
|
+
----------
|
|
57
|
+
k : float, default=1.0
|
|
58
|
+
Trap stiffness.
|
|
59
|
+
gamma : float, default=1.0
|
|
60
|
+
Friction (drag) coefficient.
|
|
61
|
+
kB : float, default=1.0
|
|
62
|
+
Boltzmann constant.
|
|
63
|
+
T : float, default=1.0
|
|
64
|
+
Temperature.
|
|
65
|
+
seed : int, optional
|
|
66
|
+
Seed for the initial equilibrium sampling and the thermal noise.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
def __init__(self, k=1.0, gamma=1.0, kB=1.0, T=1.0, seed=None):
|
|
70
|
+
self.k = k
|
|
71
|
+
self.gamma = gamma
|
|
72
|
+
self.kB = kB
|
|
73
|
+
self.T = T
|
|
74
|
+
self._rng = np.random.default_rng(seed)
|
|
75
|
+
|
|
76
|
+
def run_protocol(self, lambda_0=0.0, lambda_1=3.0, tau=5.0, n_steps=1000, n_trajectories=5000):
|
|
77
|
+
"""Drag the trap center from lambda_0 to lambda_1 over time tau, recording each trajectory's work.
|
|
78
|
+
|
|
79
|
+
Every trajectory starts from an independent sample of the
|
|
80
|
+
equilibrium Boltzmann distribution at the initial trap position,
|
|
81
|
+
:math:`x_0 \\sim \\mathcal{N}(\\lambda_0, k_B T / k)`, then is
|
|
82
|
+
integrated forward by Euler-Maruyama while the trap center advances
|
|
83
|
+
linearly in time.
|
|
84
|
+
|
|
85
|
+
Parameters
|
|
86
|
+
----------
|
|
87
|
+
lambda_0, lambda_1 : float, default=0.0, 3.0
|
|
88
|
+
Initial and final trap-center positions.
|
|
89
|
+
tau : float, default=5.0
|
|
90
|
+
Protocol duration. Smaller ``tau`` drags the system further
|
|
91
|
+
from equilibrium and dissipates more heat, but should not
|
|
92
|
+
change the Jarzynski free-energy estimate.
|
|
93
|
+
n_steps : int, default=1000
|
|
94
|
+
Number of Euler-Maruyama integration steps.
|
|
95
|
+
n_trajectories : int, default=5000
|
|
96
|
+
Number of independent realizations. The exponential average
|
|
97
|
+
underlying the Jarzynski estimator is dominated by rare,
|
|
98
|
+
low-work trajectories, so it converges slowly (more
|
|
99
|
+
trajectories are needed for a longer or more violent protocol).
|
|
100
|
+
|
|
101
|
+
Returns
|
|
102
|
+
-------
|
|
103
|
+
ndarray of shape (n_trajectories,)
|
|
104
|
+
Accumulated work :math:`W` for each realization.
|
|
105
|
+
"""
|
|
106
|
+
dt = tau / n_steps
|
|
107
|
+
D = self.kB * self.T / self.gamma
|
|
108
|
+
noise_scale = np.sqrt(2.0 * D * dt)
|
|
109
|
+
centers = np.linspace(lambda_0, lambda_1, n_steps + 1)
|
|
110
|
+
|
|
111
|
+
x = self._rng.normal(loc=lambda_0, scale=np.sqrt(self.kB * self.T / self.k), size=n_trajectories)
|
|
112
|
+
work = np.zeros(n_trajectories)
|
|
113
|
+
|
|
114
|
+
for step in range(n_steps):
|
|
115
|
+
lam, lam_next = centers[step], centers[step + 1]
|
|
116
|
+
d_lambda = lam_next - lam
|
|
117
|
+
work += -self.k * (x - lam) * d_lambda
|
|
118
|
+
force = -self.k * (x - lam)
|
|
119
|
+
x = x + (force / self.gamma) * dt + noise_scale * self._rng.standard_normal(n_trajectories)
|
|
120
|
+
|
|
121
|
+
return work
|
|
122
|
+
|
|
123
|
+
def jarzynski_free_energy_estimate(self, work):
|
|
124
|
+
"""Estimate :math:`\\Delta F = -k_B T \\ln \\langle e^{-\\beta W} \\rangle` from work samples.
|
|
125
|
+
|
|
126
|
+
Uses the log-sum-exp trick for numerical stability, since
|
|
127
|
+
individual :math:`e^{-\\beta W}` terms can otherwise under- or
|
|
128
|
+
overflow long before the average itself does.
|
|
129
|
+
|
|
130
|
+
Parameters
|
|
131
|
+
----------
|
|
132
|
+
work : array_like
|
|
133
|
+
Work samples, e.g. from :meth:`run_protocol`.
|
|
134
|
+
|
|
135
|
+
Returns
|
|
136
|
+
-------
|
|
137
|
+
float
|
|
138
|
+
Estimated free energy difference. For :class:`JarzynskiHarmonicTrap`,
|
|
139
|
+
the true value is exactly 0 regardless of the protocol.
|
|
140
|
+
"""
|
|
141
|
+
work = np.asarray(work, dtype=np.float64)
|
|
142
|
+
beta = 1.0 / (self.kB * self.T)
|
|
143
|
+
exponents = -beta * work
|
|
144
|
+
m = np.max(exponents)
|
|
145
|
+
log_mean = m + np.log(np.mean(np.exp(exponents - m)))
|
|
146
|
+
return float(-self.kB * self.T * log_mean)
|