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,119 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from physicskit.particle.collider import (
|
|
5
|
+
charged_track_points,
|
|
6
|
+
cluster_into_jets,
|
|
7
|
+
flatten_shower,
|
|
8
|
+
parton_shower,
|
|
9
|
+
shower_leaves,
|
|
10
|
+
simple_shower,
|
|
11
|
+
)
|
|
12
|
+
from physicskit.particle.kinematics import FourVector
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_simple_shower_stops_immediately_when_daughter_masses_would_exceed_parent():
|
|
16
|
+
# daughter_fraction >= 0.5 means m1 + m2 >= m_parent for every split, so
|
|
17
|
+
# the shower must stop at the root without ever branching.
|
|
18
|
+
root = simple_shower(50.0, daughter_fraction=0.6, E_threshold=1.0, rng=np.random.default_rng(0))
|
|
19
|
+
assert root.is_leaf
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_simple_shower_conserves_energy_momentum_at_every_vertex():
|
|
23
|
+
rng = np.random.default_rng(0)
|
|
24
|
+
root = simple_shower(100.0, E_threshold=5.0, rng=rng)
|
|
25
|
+
for node in flatten_shower(root):
|
|
26
|
+
if not node.is_leaf:
|
|
27
|
+
c1, c2 = node.children
|
|
28
|
+
total = c1.four_vector + c2.four_vector
|
|
29
|
+
assert total.E == pytest.approx(node.four_vector.E, abs=1e-6)
|
|
30
|
+
assert total.p_vec == pytest.approx(node.four_vector.p_vec, abs=1e-6)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_simple_shower_leaves_reconstruct_total_four_momentum():
|
|
34
|
+
rng = np.random.default_rng(1)
|
|
35
|
+
root = simple_shower(80.0, E_threshold=4.0, rng=rng)
|
|
36
|
+
leaves = shower_leaves(root)
|
|
37
|
+
assert len(leaves) >= 2
|
|
38
|
+
total_leaf = None
|
|
39
|
+
for leaf in leaves:
|
|
40
|
+
total_leaf = leaf.four_vector if total_leaf is None else total_leaf + leaf.four_vector
|
|
41
|
+
assert total_leaf.E == pytest.approx(root.four_vector.E, abs=1e-6)
|
|
42
|
+
assert total_leaf.p_vec == pytest.approx(root.four_vector.p_vec, abs=1e-6)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_simple_shower_all_leaves_below_threshold_or_at_generation_cap():
|
|
46
|
+
rng = np.random.default_rng(2)
|
|
47
|
+
root = simple_shower(60.0, E_threshold=6.0, max_generations=6, rng=rng)
|
|
48
|
+
for leaf in shower_leaves(root):
|
|
49
|
+
assert leaf.four_vector.E < 6.0 or leaf.generation >= 6 or leaf.four_vector.mass < 1e-8
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_parton_shower_conserves_four_momentum():
|
|
53
|
+
rng = np.random.default_rng(3)
|
|
54
|
+
root = parton_shower(100.0, E_threshold=5.0, rng=rng)
|
|
55
|
+
leaves = shower_leaves(root)
|
|
56
|
+
total_leaf = None
|
|
57
|
+
for leaf in leaves:
|
|
58
|
+
total_leaf = leaf.four_vector if total_leaf is None else total_leaf + leaf.four_vector
|
|
59
|
+
assert total_leaf.E == pytest.approx(root.four_vector.E, abs=1e-6)
|
|
60
|
+
assert total_leaf.p_vec == pytest.approx(root.four_vector.p_vec, abs=1e-6)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_parton_shower_flavor_conservation_rules():
|
|
64
|
+
rng = np.random.default_rng(4)
|
|
65
|
+
root = parton_shower(100.0, flavor0="q", E_threshold=5.0, rng=rng)
|
|
66
|
+
for node in flatten_shower(root):
|
|
67
|
+
if not node.is_leaf:
|
|
68
|
+
f1, f2 = node.children[0].flavor, node.children[1].flavor
|
|
69
|
+
if node.flavor in ("q", "qbar"):
|
|
70
|
+
assert node.flavor in (f1, f2)
|
|
71
|
+
assert "g" in (f1, f2)
|
|
72
|
+
elif node.flavor == "g":
|
|
73
|
+
assert {f1, f2} in ({"g"}, {"q", "qbar"})
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def test_cluster_into_jets_splits_back_to_back_particles_correctly():
|
|
77
|
+
rng = np.random.default_rng(5)
|
|
78
|
+
root = parton_shower(100.0, E_threshold=8.0, rng=rng)
|
|
79
|
+
leaves = shower_leaves(root)
|
|
80
|
+
jets = cluster_into_jets(leaves, n_jets=2)
|
|
81
|
+
assert len(jets) == 2
|
|
82
|
+
assert sum(len(j) for j in jets) == len(leaves)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_charged_track_points_neutral_particle_is_a_straight_line():
|
|
86
|
+
p = FourVector(10.0, 3.0, 4.0, 5.0)
|
|
87
|
+
pts = charged_track_points(p, charge=0.0, B=1.0, path_length=2.5, n_points=10)
|
|
88
|
+
assert pts.shape == (10, 2)
|
|
89
|
+
direction = np.array([3.0, 4.0]) / 5.0
|
|
90
|
+
assert pts[-1] == pytest.approx(direction * 2.5)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def test_charged_track_points_charged_particle_curves_with_correct_radius():
|
|
94
|
+
p = FourVector(10.0, 3.0, 0.0, 5.0) # pT = 3
|
|
95
|
+
B = 2.0
|
|
96
|
+
charge = 1.0
|
|
97
|
+
r_expected = 3.0 / (charge * B)
|
|
98
|
+
pts = charged_track_points(p, charge=charge, B=B, path_length=r_expected * 0.5, n_points=50)
|
|
99
|
+
|
|
100
|
+
# reconstruct the radius of curvature from three points on the arc
|
|
101
|
+
# (the circumradius of any three points on a circle equals its radius).
|
|
102
|
+
def circumradius(a, b, c):
|
|
103
|
+
ab, bc, ca = np.linalg.norm(a - b), np.linalg.norm(b - c), np.linalg.norm(c - a)
|
|
104
|
+
s = (ab + bc + ca) / 2
|
|
105
|
+
area = max(s * (s - ab) * (s - bc) * (s - ca), 0.0) ** 0.5
|
|
106
|
+
return (ab * bc * ca) / (4 * area) if area > 0 else np.inf
|
|
107
|
+
|
|
108
|
+
r_reconstructed = circumradius(pts[0], pts[len(pts) // 2], pts[-1])
|
|
109
|
+
assert r_reconstructed == pytest.approx(r_expected, rel=1e-2)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def test_charged_track_points_initial_direction_matches_momentum():
|
|
113
|
+
p = FourVector(10.0, 3.0, 4.0, 0.0)
|
|
114
|
+
for charge in (1.0, -1.0):
|
|
115
|
+
pts = charged_track_points(p, charge=charge, B=1.0, path_length=0.1, n_points=1000)
|
|
116
|
+
step = pts[1] - pts[0]
|
|
117
|
+
step_dir = step / np.linalg.norm(step)
|
|
118
|
+
expected_dir = np.array([3.0, 4.0]) / 5.0
|
|
119
|
+
assert step_dir == pytest.approx(expected_dir, abs=1e-2)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from physicskit.particle.confinement import string_break_chain, string_tension_energy
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_string_tension_energy_is_linear_in_r():
|
|
8
|
+
assert string_tension_energy(2.0, kappa=0.9) == pytest.approx(1.8)
|
|
9
|
+
assert string_tension_energy(-3.0, kappa=0.5) == pytest.approx(1.5)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_string_break_chain_rejects_superluminal_speed():
|
|
13
|
+
with pytest.raises(ValueError):
|
|
14
|
+
string_break_chain(np.array([0.0, 1.0]), v=1.5, kappa=1.0, m_q=1.0)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_string_break_chain_break_times_hit_exact_energy_threshold():
|
|
18
|
+
kappa, m_q, v = 1.0, 1.0, 0.5
|
|
19
|
+
fine_t = np.linspace(0, 20, 5000)
|
|
20
|
+
sim = string_break_chain(fine_t, v=v, kappa=kappa, m_q=m_q, n_breaks=3)
|
|
21
|
+
break_times = sim["break_times"]
|
|
22
|
+
assert len(break_times) == 3
|
|
23
|
+
|
|
24
|
+
# evaluate exactly at the analytic break times: total stored energy
|
|
25
|
+
# kappa*r must equal 2*m_q*k for the k-th break (k=1,2,3).
|
|
26
|
+
sim_at_breaks = string_break_chain(break_times, v=v, kappa=kappa, m_q=m_q, n_breaks=3)
|
|
27
|
+
for k in range(1, len(break_times) + 1):
|
|
28
|
+
assert sim_at_breaks["energy_total"][k - 1] == pytest.approx(2.0 * m_q * k, abs=1e-8)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_string_break_chain_segment_count_increases_monotonically():
|
|
32
|
+
sim = string_break_chain(np.linspace(0, 20, 500), v=0.5, kappa=1.0, m_q=1.0, n_breaks=3)
|
|
33
|
+
assert np.all(np.diff(sim["n_segments"]) >= 0)
|
|
34
|
+
assert sim["n_segments"][0] == 1
|
|
35
|
+
assert sim["n_segments"][-1] <= 4
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_string_break_chain_energy_per_segment_never_much_exceeds_threshold():
|
|
39
|
+
sim = string_break_chain(np.linspace(0, 20, 2000), v=0.5, kappa=1.0, m_q=1.0, n_breaks=5)
|
|
40
|
+
# each segment's energy share should stay close to (at most a hair above) 2*m_q
|
|
41
|
+
# right up until the *next* break instantaneously resets the count.
|
|
42
|
+
assert np.all(sim["energy_per_segment"] <= 2.0 * sim["m_q"] + 1e-6)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from physicskit.particle.decays import (
|
|
5
|
+
activity,
|
|
6
|
+
bateman_decay_chain,
|
|
7
|
+
decay_constant,
|
|
8
|
+
half_life,
|
|
9
|
+
michel_spectrum,
|
|
10
|
+
muon_decay_event,
|
|
11
|
+
radioactive_decay_number,
|
|
12
|
+
sample_michel_electron_energies,
|
|
13
|
+
two_body_decay,
|
|
14
|
+
two_body_decay_momentum,
|
|
15
|
+
)
|
|
16
|
+
from physicskit.particle.kinematics import invariant_mass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_two_body_decay_momentum_forbidden_raises():
|
|
20
|
+
with pytest.raises(ValueError):
|
|
21
|
+
two_body_decay_momentum(1.0, 0.6, 0.6)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_two_body_decay_reconstructs_parent_mass_and_is_back_to_back():
|
|
25
|
+
cases = [
|
|
26
|
+
(1.0, 0.4, 0.4, 1.0, 0.0),
|
|
27
|
+
(1.0, 0.4, 0.4, 0.0, 1.5),
|
|
28
|
+
(2.0, 0.5, 1.0, -0.3, 2.0),
|
|
29
|
+
(1.5, 0.1, 0.2, 0.7, 4.0),
|
|
30
|
+
]
|
|
31
|
+
for M, m1, m2, cos_theta, phi in cases:
|
|
32
|
+
p1, p2 = two_body_decay(M, m1, m2, cos_theta, phi)
|
|
33
|
+
assert invariant_mass([p1, p2]) == pytest.approx(M)
|
|
34
|
+
assert (p1.p_vec + p2.p_vec) == pytest.approx([0.0, 0.0, 0.0], abs=1e-10)
|
|
35
|
+
assert p1.mass == pytest.approx(m1, abs=1e-8)
|
|
36
|
+
assert p2.mass == pytest.approx(m2, abs=1e-8)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_decay_constant_half_life_roundtrip():
|
|
40
|
+
t_half = 5.0
|
|
41
|
+
lam = decay_constant(t_half)
|
|
42
|
+
assert half_life(lam) == pytest.approx(t_half)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_radioactive_decay_number_matches_exponential_law():
|
|
46
|
+
N0, lam, t = 1000.0, 0.05, np.linspace(0, 20, 5)
|
|
47
|
+
N = radioactive_decay_number(N0, lam, t)
|
|
48
|
+
assert N == pytest.approx(N0 * np.exp(-lam * t))
|
|
49
|
+
assert radioactive_decay_number(N0, lam, 0.0) == pytest.approx(N0)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_activity():
|
|
53
|
+
assert activity(200.0, 0.02) == pytest.approx(4.0)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_bateman_chain_species_one_matches_simple_exponential():
|
|
57
|
+
N0, lam1, lam2 = 500.0, 0.3, 0.1
|
|
58
|
+
t = np.linspace(0, 10, 6)
|
|
59
|
+
N = bateman_decay_chain(N0, [lam1, lam2], t)
|
|
60
|
+
assert N[0] == pytest.approx(radioactive_decay_number(N0, lam1, t))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_bateman_two_species_matches_textbook_closed_form():
|
|
64
|
+
N0, lam1, lam2 = 500.0, 0.3, 0.1
|
|
65
|
+
t = np.linspace(0, 10, 6)
|
|
66
|
+
N = bateman_decay_chain(N0, [lam1, lam2], t)
|
|
67
|
+
N2_expected = N0 * lam1 / (lam2 - lam1) * (np.exp(-lam1 * t) - np.exp(-lam2 * t))
|
|
68
|
+
assert N[1] == pytest.approx(N2_expected)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def test_bateman_three_species_chain_shape_and_positivity():
|
|
72
|
+
N = bateman_decay_chain(1000.0, [0.5, 0.3, 0.1], np.linspace(0, 5, 10))
|
|
73
|
+
assert N.shape == (3, 10)
|
|
74
|
+
assert np.all(N >= -1e-8)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_michel_spectrum_normalized_and_bounds():
|
|
78
|
+
x = np.linspace(0, 1, 200001)
|
|
79
|
+
assert np.trapezoid(michel_spectrum(x), x) == pytest.approx(1.0, abs=1e-4)
|
|
80
|
+
assert michel_spectrum(0.0) == pytest.approx(0.0)
|
|
81
|
+
assert michel_spectrum(1.0) == pytest.approx(2.0)
|
|
82
|
+
assert np.all(michel_spectrum(x) >= -1e-12)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_sample_michel_electron_energies_matches_theoretical_mean():
|
|
86
|
+
rng = np.random.default_rng(42)
|
|
87
|
+
xs = sample_michel_electron_energies(50_000, rng=rng)
|
|
88
|
+
assert xs.min() >= 0.0
|
|
89
|
+
assert xs.max() <= 1.0
|
|
90
|
+
# <x> = integral x * 2x^2(3-2x) dx from 0 to 1 = 2*(3/4-2/5) = 7/10
|
|
91
|
+
assert xs.mean() == pytest.approx(0.7, abs=0.02)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def test_muon_decay_event_conserves_energy_momentum_and_is_massless_neutrinos():
|
|
95
|
+
m_mu = 105.658
|
|
96
|
+
rng = np.random.default_rng(7)
|
|
97
|
+
for _ in range(20):
|
|
98
|
+
p_e, p_numu_bar, p_nue = muon_decay_event(m_mu, rng=rng)
|
|
99
|
+
total = p_e + p_numu_bar + p_nue
|
|
100
|
+
assert total.E == pytest.approx(m_mu, abs=1e-6)
|
|
101
|
+
assert total.p_vec == pytest.approx([0.0, 0.0, 0.0], abs=1e-6)
|
|
102
|
+
assert p_numu_bar.mass == pytest.approx(0.0, abs=1e-6)
|
|
103
|
+
assert p_nue.mass == pytest.approx(0.0, abs=1e-6)
|
|
104
|
+
assert 0.0 <= p_e.E <= m_mu / 2.0 + 1e-6
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def test_muon_decay_event_electron_energy_spectrum_matches_michel_mean():
|
|
108
|
+
m_mu = 105.658
|
|
109
|
+
rng = np.random.default_rng(3)
|
|
110
|
+
E_e = np.array([muon_decay_event(m_mu, rng=rng)[0].E for _ in range(20_000)])
|
|
111
|
+
x = 2.0 * E_e / m_mu
|
|
112
|
+
assert x.mean() == pytest.approx(0.7, abs=0.02)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from physicskit.particle.electroweak import (
|
|
5
|
+
cp_asymmetry,
|
|
6
|
+
higgs_field_rollover,
|
|
7
|
+
higgs_potential,
|
|
8
|
+
higgs_vev,
|
|
9
|
+
meson_decay_rates_cp_eigenstate,
|
|
10
|
+
qed_dsigma_domega_mumu,
|
|
11
|
+
qed_total_cross_section_mumu,
|
|
12
|
+
)
|
|
13
|
+
from physicskit.particle.scattering import ALPHA_FS
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_higgs_potential_symmetric_and_zero_at_origin():
|
|
17
|
+
phi = np.linspace(-2, 2, 21)
|
|
18
|
+
assert higgs_potential(0.0, a=1.0, b=1.0) == pytest.approx(0.0)
|
|
19
|
+
assert higgs_potential(phi, a=1.0, b=1.0) == pytest.approx(higgs_potential(-phi, a=1.0, b=1.0))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_higgs_vev_is_the_potential_minimum():
|
|
23
|
+
a, b = 2.0, 0.7
|
|
24
|
+
v = higgs_vev(a, b)
|
|
25
|
+
# V'(v) = -2a v + 4 b v^3 should vanish at the true minimum.
|
|
26
|
+
assert -2 * a * v + 4 * b * v**3 == pytest.approx(0.0, abs=1e-8)
|
|
27
|
+
assert higgs_potential(v, a, b) < higgs_potential(0.0, a, b)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_higgs_field_rolls_from_unstable_point_into_a_true_vacuum():
|
|
31
|
+
a, b = 1.0, 1.0
|
|
32
|
+
t = np.linspace(0, 60, 600)
|
|
33
|
+
phi, phidot = higgs_field_rollover(1e-3, 0.0, a, b, t_eval=t, damping=0.08)
|
|
34
|
+
v = higgs_vev(a, b)
|
|
35
|
+
assert abs(phi[0]) < 1e-2
|
|
36
|
+
assert abs(abs(phi[-1]) - v) < 0.05
|
|
37
|
+
assert abs(phidot[-1]) < 0.1 # settled (small residual ringing), not still oscillating at full amplitude
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_higgs_field_symmetric_perturbation_sign_picks_the_side():
|
|
41
|
+
a, b = 1.0, 1.0
|
|
42
|
+
t = np.linspace(0, 60, 600)
|
|
43
|
+
phi_pos, _ = higgs_field_rollover(1e-3, 0.0, a, b, t_eval=t, damping=0.08)
|
|
44
|
+
phi_neg, _ = higgs_field_rollover(-1e-3, 0.0, a, b, t_eval=t, damping=0.08)
|
|
45
|
+
assert phi_pos[-1] > 0
|
|
46
|
+
assert phi_neg[-1] < 0
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_qed_dsigma_domega_symmetric_forward_backward():
|
|
50
|
+
vals_fwd = qed_dsigma_domega_mumu(np.array([0.3, 0.9]), sqrt_s=10.0)
|
|
51
|
+
vals_bwd = qed_dsigma_domega_mumu(np.array([-0.3, -0.9]), sqrt_s=10.0)
|
|
52
|
+
assert vals_fwd == pytest.approx(vals_bwd)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_qed_dsigma_domega_integrates_to_total_cross_section():
|
|
56
|
+
sqrt_s = 15.0
|
|
57
|
+
cos_theta = np.linspace(-1, 1, 4001)
|
|
58
|
+
dsigma = qed_dsigma_domega_mumu(cos_theta, sqrt_s)
|
|
59
|
+
# integral over solid angle: 2*pi (azimuthal) * integral dcos_theta
|
|
60
|
+
sigma_numeric = 2 * np.pi * np.trapezoid(dsigma, cos_theta)
|
|
61
|
+
sigma_formula = qed_total_cross_section_mumu(sqrt_s)
|
|
62
|
+
assert sigma_numeric == pytest.approx(sigma_formula, rel=1e-4)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def test_qed_total_cross_section_matches_alpha_fs_default():
|
|
66
|
+
sqrt_s = 20.0
|
|
67
|
+
expected = 4 * np.pi * ALPHA_FS**2 / (3 * sqrt_s**2)
|
|
68
|
+
assert qed_total_cross_section_mumu(sqrt_s) == pytest.approx(expected)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def test_cp_asymmetry_vanishes_without_cp_violation():
|
|
72
|
+
t = np.linspace(0, 10, 50)
|
|
73
|
+
A = cp_asymmetry(t, delta_m=0.5, gamma_s=1.0, gamma_l=0.1, epsilon=0.0)
|
|
74
|
+
assert A == pytest.approx(np.zeros_like(t))
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_meson_decay_rates_are_equal_without_cp_violation():
|
|
78
|
+
t = np.linspace(0, 10, 50)
|
|
79
|
+
g, gbar = meson_decay_rates_cp_eigenstate(t, delta_m=0.5, gamma_s=1.0, gamma_l=0.1, epsilon=0.0)
|
|
80
|
+
assert g == pytest.approx(gbar)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def test_cp_asymmetry_nonzero_and_bounded_with_cp_violation():
|
|
84
|
+
t = np.linspace(0, 10, 200)
|
|
85
|
+
eps = 0.002 * np.exp(1j * 0.7)
|
|
86
|
+
A = cp_asymmetry(t, delta_m=0.5, gamma_s=1.0, gamma_l=0.1, epsilon=eps)
|
|
87
|
+
assert np.any(np.abs(A) > 1e-6)
|
|
88
|
+
assert np.all(np.abs(A) <= 1.0 + 1e-8)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def test_cp_asymmetry_decays_at_late_times_when_gamma_s_dominates():
|
|
92
|
+
t_early = np.array([0.1])
|
|
93
|
+
t_late = np.array([50.0])
|
|
94
|
+
eps = 0.01
|
|
95
|
+
A_early = cp_asymmetry(t_early, delta_m=1.0, gamma_s=5.0, gamma_l=0.05, epsilon=eps)
|
|
96
|
+
A_late = cp_asymmetry(t_late, delta_m=1.0, gamma_s=5.0, gamma_l=0.05, epsilon=eps)
|
|
97
|
+
assert abs(A_late[0]) < abs(A_early[0])
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from physicskit.particle.kinematics import FourVector, boost, boost_generic, boost_to_com, invariant_mass, rapidity
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_mass_of_rest_particle():
|
|
8
|
+
p = FourVector(1.5, 0.0, 0.0, 0.0)
|
|
9
|
+
assert p.mass == pytest.approx(1.5)
|
|
10
|
+
assert p.beta == pytest.approx(0.0)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_boost_of_rest_frame_reproduces_boosted_energy_momentum():
|
|
14
|
+
m = 1.0
|
|
15
|
+
beta = 0.6
|
|
16
|
+
gamma = 1.0 / np.sqrt(1 - beta**2)
|
|
17
|
+
p_rest = FourVector(m, 0.0, 0.0, 0.0)
|
|
18
|
+
p_boosted = boost(p_rest, beta, axis="z")
|
|
19
|
+
assert p_boosted.E == pytest.approx(gamma * m)
|
|
20
|
+
assert p_boosted.pz == pytest.approx(gamma * m * beta)
|
|
21
|
+
assert p_boosted.mass == pytest.approx(m)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_boost_is_invertible():
|
|
25
|
+
p = FourVector(3.0, 0.5, -0.2, 1.1)
|
|
26
|
+
beta = 0.4
|
|
27
|
+
for axis in ("x", "y", "z"):
|
|
28
|
+
p_back = boost(boost(p, beta, axis), -beta, axis)
|
|
29
|
+
assert p_back.E == pytest.approx(p.E)
|
|
30
|
+
assert p_back.px == pytest.approx(p.px)
|
|
31
|
+
assert p_back.py == pytest.approx(p.py)
|
|
32
|
+
assert p_back.pz == pytest.approx(p.pz)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_invariant_mass_of_two_back_to_back_photons_like_particles():
|
|
36
|
+
p1 = FourVector(1.0, 0.0, 0.0, 0.6)
|
|
37
|
+
p2 = FourVector(1.0, 0.0, 0.0, -0.6)
|
|
38
|
+
assert invariant_mass([p1, p2]) == pytest.approx(2.0)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_rapidity_is_additive_under_boost_along_same_axis():
|
|
42
|
+
p = FourVector(2.0, 0.1, 0.2, 1.0)
|
|
43
|
+
beta = 0.5
|
|
44
|
+
y0 = rapidity(p, axis="z")
|
|
45
|
+
y1 = rapidity(boost(p, beta, axis="z"), axis="z")
|
|
46
|
+
assert y1 == pytest.approx(y0 + np.arctanh(beta))
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_boost_to_com_of_symmetric_pair_is_zero():
|
|
50
|
+
p1 = FourVector(2.0, 0.0, 0.0, 1.0)
|
|
51
|
+
p2 = FourVector(2.0, 0.0, 0.0, -1.0)
|
|
52
|
+
beta_com = boost_to_com([p1, p2])
|
|
53
|
+
assert beta_com == pytest.approx([0.0, 0.0, 0.0])
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_boost_to_com_of_asymmetric_pair():
|
|
57
|
+
p1 = FourVector(2.0, 0.0, 0.0, 1.0)
|
|
58
|
+
p2 = FourVector(1.0, 0.0, 0.0, 0.0)
|
|
59
|
+
beta_com = boost_to_com([p1, p2])
|
|
60
|
+
assert beta_com == pytest.approx([0.0, 0.0, 1.0 / 3.0])
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_gamma_raises_for_massless_vector():
|
|
64
|
+
p = FourVector(1.0, 0.0, 0.0, 1.0)
|
|
65
|
+
assert p.mass == pytest.approx(0.0)
|
|
66
|
+
with pytest.raises(ZeroDivisionError):
|
|
67
|
+
_ = p.gamma
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_gamma_equals_energy_over_mass_for_massive_vector():
|
|
71
|
+
p = FourVector(2.0, 0.0, 0.0, 1.0)
|
|
72
|
+
assert p.gamma == pytest.approx(p.E / p.mass)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_four_vector_repr_shows_components():
|
|
76
|
+
p = FourVector(1.0, 2.0, 3.0, 4.0)
|
|
77
|
+
assert repr(p) == "FourVector(E=1, px=2, py=3, pz=4)"
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def test_boost_rejects_invalid_beta_and_axis():
|
|
81
|
+
p = FourVector(1.0, 0.0, 0.0, 0.0)
|
|
82
|
+
with pytest.raises(ValueError, match="beta"):
|
|
83
|
+
boost(p, 1.5)
|
|
84
|
+
with pytest.raises(ValueError, match="axis"):
|
|
85
|
+
boost(p, 0.5, axis="w")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_boost_generic_matches_axis_boost_when_aligned():
|
|
89
|
+
p = FourVector(3.0, 0.5, -0.2, 1.1)
|
|
90
|
+
beta = 0.45
|
|
91
|
+
for axis, vec in [("x", [beta, 0, 0]), ("y", [0, beta, 0]), ("z", [0, 0, beta])]:
|
|
92
|
+
pb_axis = boost(p, beta, axis=axis)
|
|
93
|
+
pb_generic = boost_generic(p, vec)
|
|
94
|
+
assert pb_generic.E == pytest.approx(pb_axis.E)
|
|
95
|
+
assert pb_generic.px == pytest.approx(pb_axis.px)
|
|
96
|
+
assert pb_generic.py == pytest.approx(pb_axis.py)
|
|
97
|
+
assert pb_generic.pz == pytest.approx(pb_axis.pz)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def test_boost_generic_of_rest_particle_along_arbitrary_direction():
|
|
101
|
+
m = 2.0
|
|
102
|
+
beta_vec = np.array([0.3, -0.4, 0.2])
|
|
103
|
+
beta = np.linalg.norm(beta_vec)
|
|
104
|
+
gamma = 1.0 / np.sqrt(1 - beta**2)
|
|
105
|
+
p_rest = FourVector(m, 0.0, 0.0, 0.0)
|
|
106
|
+
pb = boost_generic(p_rest, beta_vec)
|
|
107
|
+
assert pb.E == pytest.approx(gamma * m)
|
|
108
|
+
assert pb.p_vec == pytest.approx(gamma * m * beta_vec)
|
|
109
|
+
assert pb.mass == pytest.approx(m)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def test_boost_generic_is_invertible():
|
|
113
|
+
p = FourVector(3.0, 0.5, -0.2, 1.1)
|
|
114
|
+
beta_vec = np.array([0.1, 0.2, -0.3])
|
|
115
|
+
p_back = boost_generic(boost_generic(p, beta_vec), -beta_vec)
|
|
116
|
+
assert p_back.E == pytest.approx(p.E)
|
|
117
|
+
assert p_back.p_vec == pytest.approx(p.p_vec)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def test_boost_generic_zero_velocity_is_identity():
|
|
121
|
+
p = FourVector(3.0, 0.5, -0.2, 1.1)
|
|
122
|
+
pb = boost_generic(p, [0.0, 0.0, 0.0])
|
|
123
|
+
assert pb.E == pytest.approx(p.E)
|
|
124
|
+
assert pb.p_vec == pytest.approx(p.p_vec)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def test_boost_generic_rejects_superluminal_velocity():
|
|
128
|
+
with pytest.raises(ValueError):
|
|
129
|
+
boost_generic(FourVector(1.0, 0, 0, 0), [0.9, 0.9, 0.0])
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def test_add_and_sub():
|
|
133
|
+
p1 = FourVector(1.0, 0.1, 0.2, 0.3)
|
|
134
|
+
p2 = FourVector(2.0, -0.1, 0.0, 0.1)
|
|
135
|
+
s = p1 + p2
|
|
136
|
+
assert (s.E, s.px, s.py, s.pz) == pytest.approx((3.0, 0.0, 0.2, 0.4))
|
|
137
|
+
d = p1 - p2
|
|
138
|
+
assert (d.E, d.px, d.py, d.pz) == pytest.approx((-1.0, 0.2, 0.2, 0.2))
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from physicskit.particle.neutrinos import oscillation_probability, survival_probability
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_oscillation_probability_vanishes_at_zero_baseline():
|
|
8
|
+
assert oscillation_probability(0.0, 1.0, theta=0.4, delta_m2=2.5e-3) == pytest.approx(0.0)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_oscillation_probability_reaches_maximal_value_at_maximal_mixing():
|
|
12
|
+
theta = np.pi / 4 # sin^2(2 theta) = 1
|
|
13
|
+
delta_m2 = 2.5e-3
|
|
14
|
+
E = 1.0
|
|
15
|
+
L = (np.pi / 2) / (1.267 * delta_m2 / E) # argument = pi/2 -> sin^2 = 1
|
|
16
|
+
assert oscillation_probability(L, E, theta, delta_m2) == pytest.approx(1.0, abs=1e-8)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_probabilities_sum_to_one():
|
|
20
|
+
L = np.linspace(0, 2000, 50)
|
|
21
|
+
P_mu = oscillation_probability(L, E=1.0, theta=0.5, delta_m2=2.5e-3)
|
|
22
|
+
P_e = survival_probability(L, E=1.0, theta=0.5, delta_m2=2.5e-3)
|
|
23
|
+
assert P_mu + P_e == pytest.approx(np.ones_like(L))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_no_mixing_gives_no_oscillation():
|
|
27
|
+
L = np.linspace(0, 1000, 20)
|
|
28
|
+
P_mu = oscillation_probability(L, E=1.0, theta=0.0, delta_m2=2.5e-3)
|
|
29
|
+
assert P_mu == pytest.approx(np.zeros_like(L))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_oscillation_probability_is_periodic_in_L():
|
|
33
|
+
theta, delta_m2, E = 0.5, 2.5e-3, 1.0
|
|
34
|
+
period = np.pi * E / (1.267 * delta_m2)
|
|
35
|
+
L0 = 137.0
|
|
36
|
+
assert oscillation_probability(L0, E, theta, delta_m2) == pytest.approx(oscillation_probability(L0 + period, E, theta, delta_m2))
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from physicskit.particle.nuclear import binding_energy_per_nucleon, q_value, semf_binding_energy
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_iron_56_binding_energy_per_nucleon_near_known_maximum():
|
|
7
|
+
bpn = binding_energy_per_nucleon(26, 56)
|
|
8
|
+
assert 8.0 < bpn < 9.0
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_binding_energy_per_nucleon_lower_for_heavy_nucleus():
|
|
12
|
+
# Heavy nuclei (large Coulomb repulsion) are less tightly bound per
|
|
13
|
+
# nucleon than the iron-group peak.
|
|
14
|
+
bpn_fe = binding_energy_per_nucleon(26, 56)
|
|
15
|
+
bpn_u = binding_energy_per_nucleon(92, 238)
|
|
16
|
+
assert bpn_u < bpn_fe
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_binding_energy_per_nucleon_lower_for_very_light_nucleus():
|
|
20
|
+
bpn_fe = binding_energy_per_nucleon(26, 56)
|
|
21
|
+
bpn_he = binding_energy_per_nucleon(2, 4)
|
|
22
|
+
assert bpn_he < bpn_fe
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_pairing_term_sign():
|
|
26
|
+
# Even-even vs. odd-odd nuclei at the same A=14 differ only by the
|
|
27
|
+
# pairing term: Z=6 (N=8, even-even) should be more bound than
|
|
28
|
+
# Z=7 (N=7, odd-odd).
|
|
29
|
+
even_even = semf_binding_energy(6, 14)
|
|
30
|
+
odd_odd = semf_binding_energy(7, 14)
|
|
31
|
+
assert even_even > odd_odd
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_pairing_term_is_zero_for_odd_mass_number():
|
|
35
|
+
# A odd (mixed Z/N parity) takes the "no pairing correction" branch,
|
|
36
|
+
# unlike the even-even/odd-odd cases above.
|
|
37
|
+
N15 = semf_binding_energy(7, 15) # Z=7 odd, N=8 even
|
|
38
|
+
O15 = semf_binding_energy(8, 15) # Z=8 even, N=7 odd
|
|
39
|
+
assert N15 > 0 and O15 > 0
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_q_value_positive_for_dt_fusion():
|
|
43
|
+
Q = q_value([2.014102, 3.016049], [4.002602, 1.008665])
|
|
44
|
+
assert Q == pytest.approx(0.018884, abs=1e-6)
|
|
45
|
+
assert Q > 0
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from physicskit.particle.kinematics import FourVector
|
|
5
|
+
from physicskit.particle.scattering import (
|
|
6
|
+
ALPHA_FS,
|
|
7
|
+
impact_parameter,
|
|
8
|
+
mandelstam_s,
|
|
9
|
+
mandelstam_t,
|
|
10
|
+
mandelstam_u,
|
|
11
|
+
rutherford_dsigma_domega,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_mandelstam_sum_rule_for_a_2to2_process():
|
|
16
|
+
# elastic head-on-ish scattering: 1+2 -> 3+4, all equal mass m,
|
|
17
|
+
# constructed so that energy-momentum is manifestly conserved.
|
|
18
|
+
m = 0.5
|
|
19
|
+
E = 2.0
|
|
20
|
+
p = np.sqrt(E**2 - m**2)
|
|
21
|
+
p1 = FourVector(E, 0.0, 0.0, p)
|
|
22
|
+
p2 = FourVector(E, 0.0, 0.0, -p)
|
|
23
|
+
# outgoing particles rotated by some angle theta in the CM frame,
|
|
24
|
+
# same energy/momentum magnitude by symmetry (equal masses, elastic).
|
|
25
|
+
theta = 0.7
|
|
26
|
+
p3 = FourVector(E, p * np.sin(theta), 0.0, p * np.cos(theta))
|
|
27
|
+
p4 = FourVector(E, -p * np.sin(theta), 0.0, -p * np.cos(theta))
|
|
28
|
+
|
|
29
|
+
s = mandelstam_s(p1, p2)
|
|
30
|
+
t = mandelstam_t(p1, p3)
|
|
31
|
+
u = mandelstam_u(p1, p4)
|
|
32
|
+
mass_sum = p1.mass**2 + p2.mass**2 + p3.mass**2 + p4.mass**2
|
|
33
|
+
assert s + t + u == pytest.approx(mass_sum, abs=1e-8)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_mandelstam_s_of_symmetric_pair():
|
|
37
|
+
p1 = FourVector(1.0, 0.0, 0.0, 0.6)
|
|
38
|
+
p2 = FourVector(1.0, 0.0, 0.0, -0.6)
|
|
39
|
+
assert mandelstam_s(p1, p2) == pytest.approx(4.0)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_rutherford_functional_form_sin4_law():
|
|
43
|
+
thetas = np.linspace(0.2, 2.5, 8)
|
|
44
|
+
vals = rutherford_dsigma_domega(thetas, Z1=2, Z2=79, E_kin=5.0)
|
|
45
|
+
normalized = vals * np.sin(thetas / 2.0) ** 4
|
|
46
|
+
assert normalized == pytest.approx(normalized[0])
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_rutherford_diverges_at_zero_angle():
|
|
50
|
+
val = rutherford_dsigma_domega(0.0, Z1=1, Z2=1, E_kin=1.0)
|
|
51
|
+
assert np.isinf(val)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_impact_parameter_limits():
|
|
55
|
+
b_head_on = impact_parameter(np.pi, Z1=1, Z2=79, E_kin=5.0)
|
|
56
|
+
assert b_head_on == pytest.approx(0.0, abs=1e-10)
|
|
57
|
+
|
|
58
|
+
b_small_angle = impact_parameter(1e-3, Z1=1, Z2=79, E_kin=5.0)
|
|
59
|
+
b_larger_angle = impact_parameter(1e-2, Z1=1, Z2=79, E_kin=5.0)
|
|
60
|
+
assert b_small_angle > b_larger_angle > 0
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_alpha_fs_value():
|
|
64
|
+
assert ALPHA_FS == pytest.approx(1 / 137.035999084)
|