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,417 @@
|
|
|
1
|
+
"""Time-evolving current-sheet instabilities: magnetic reconnection and Weibel filamentation.
|
|
2
|
+
|
|
3
|
+
Both problems in this module involve a current-carrying layer that breaks up
|
|
4
|
+
under a collective instability, but at opposite ends of the fluid-kinetic
|
|
5
|
+
spectrum. Magnetic reconnection (:func:`reconnection_harris_ic`,
|
|
6
|
+
:func:`simulate_reconnection`) is treated here as a *kinematic resistive-MHD*
|
|
7
|
+
problem: the induction equation for the flux function :math:`\\psi(x,y,t)` is
|
|
8
|
+
evolved with a prescribed inflow velocity rather than a self-consistently
|
|
9
|
+
solved momentum equation, which is the standard first simplification made
|
|
10
|
+
before attempting full two-fluid or MHD reconnection (the prescribed-flow
|
|
11
|
+
approximation underlying, e.g., the original Sweet-Parker and Petschek
|
|
12
|
+
estimates in :mod:`physicskit.plasma.mhd`). The Weibel/filamentation
|
|
13
|
+
instability (:func:`weibel_growth_rate`, :func:`simulate_weibel_filamentation`)
|
|
14
|
+
is treated as a *reduced linear/quasi-linear* problem: rather than extending
|
|
15
|
+
the 1D-space/1D-velocity PIC machinery of :mod:`physicskit.plasma.kinetic` to
|
|
16
|
+
a full 2D-in-velocity, electromagnetic PIC code (a much larger undertaking),
|
|
17
|
+
a spectrum of transverse-current Fourier modes is seeded with random phases
|
|
18
|
+
and each mode's amplitude is evolved analytically according to the known
|
|
19
|
+
linear Weibel growth rate -- exact for as long as the linear approximation
|
|
20
|
+
holds, and sufficient to show the characteristic real-space current
|
|
21
|
+
filaments forming and growing.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import numpy as np
|
|
27
|
+
|
|
28
|
+
from physicskit import constants as _const
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
"reconnection_harris_ic",
|
|
32
|
+
"reconnection_inflow_velocity",
|
|
33
|
+
"reconnection_field_from_flux",
|
|
34
|
+
"simulate_reconnection",
|
|
35
|
+
"weibel_growth_rate",
|
|
36
|
+
"weibel_fastest_growing_mode",
|
|
37
|
+
"simulate_weibel_filamentation",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def reconnection_harris_ic(nx: int, ny: int, Lx: float, Ly: float, sheet_width: float, perturbation_amplitude: float, k_modes: int = 1) -> np.ndarray:
|
|
42
|
+
"""Flux-function initial condition: a Harris current sheet with an X-point-seeding ripple.
|
|
43
|
+
|
|
44
|
+
The unperturbed Harris sheet :math:`\\psi_0(y) = -B_0 L\\ln\\cosh(y/L)`
|
|
45
|
+
gives an antiparallel reconnecting field
|
|
46
|
+
:math:`B_x = -\\partial_y\\psi_0 = B_0\\tanh(y/L)` that reverses sign
|
|
47
|
+
across :math:`y=0` -- the classic current-sheet configuration in which
|
|
48
|
+
reconnection is normally studied. Adding a small ripple
|
|
49
|
+
:math:`\\psi_1 = \\epsilon\\cos(k x)\\,\\mathrm{sech}^2(y/L)`, localized to
|
|
50
|
+
the sheet and periodic in :math:`x`, is the standard tearing-mode-like
|
|
51
|
+
seed: it breaks the translational symmetry along the sheet just enough
|
|
52
|
+
to create one X-point/O-point pair per wavelength, without which the
|
|
53
|
+
sheet would stay a stationary equilibrium forever regardless of
|
|
54
|
+
resistivity.
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
nx, ny : int
|
|
59
|
+
Grid points along `x` (periodic, along the sheet) and `y`
|
|
60
|
+
(across the sheet).
|
|
61
|
+
Lx, Ly : float
|
|
62
|
+
Domain size in `x` and `y`; the domain spans
|
|
63
|
+
``[0, Lx) x [-Ly/2, Ly/2)``.
|
|
64
|
+
sheet_width : float
|
|
65
|
+
Current-sheet half-thickness :math:`L` (with :math:`B_0=1` in these
|
|
66
|
+
normalized units).
|
|
67
|
+
perturbation_amplitude : float
|
|
68
|
+
Amplitude :math:`\\epsilon` of the seeding ripple.
|
|
69
|
+
k_modes : int, default=1
|
|
70
|
+
Number of full wavelengths of the ripple fit into `Lx`.
|
|
71
|
+
|
|
72
|
+
Returns
|
|
73
|
+
-------
|
|
74
|
+
ndarray, shape (nx, ny)
|
|
75
|
+
Flux function :math:`\\psi(x, y)`.
|
|
76
|
+
|
|
77
|
+
See Also
|
|
78
|
+
--------
|
|
79
|
+
simulate_reconnection : Evolves this initial condition forward in time.
|
|
80
|
+
|
|
81
|
+
Examples
|
|
82
|
+
--------
|
|
83
|
+
>>> psi0 = reconnection_harris_ic(64, 64, Lx=20.0, Ly=20.0, sheet_width=1.0, perturbation_amplitude=0.1)
|
|
84
|
+
>>> psi0.shape
|
|
85
|
+
(64, 64)
|
|
86
|
+
"""
|
|
87
|
+
x = np.linspace(0.0, Lx, nx, endpoint=False)
|
|
88
|
+
y = np.linspace(-Ly / 2.0, Ly / 2.0, ny, endpoint=False)
|
|
89
|
+
X, Y = np.meshgrid(x, y, indexing="ij")
|
|
90
|
+
psi0 = -sheet_width * np.log(np.cosh(Y / sheet_width))
|
|
91
|
+
k = 2.0 * np.pi * k_modes / Lx
|
|
92
|
+
psi1 = perturbation_amplitude * np.cos(k * X) / np.cosh(Y / sheet_width) ** 2
|
|
93
|
+
return psi0 + psi1
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def reconnection_inflow_velocity(X: np.ndarray, Y: np.ndarray, v0: float, Lx: float, Ly: float) -> tuple:
|
|
97
|
+
"""Prescribed stagnation-point inflow/outflow velocity field around the reconnection X-point.
|
|
98
|
+
|
|
99
|
+
A simple incompressible stagnation flow, :math:`v_x=+v_0 x'/L_x`,
|
|
100
|
+
:math:`v_y=-v_0 y'/L_y` (with :math:`x', y'` measured from the nearest
|
|
101
|
+
X-point at the domain center), that converges onto the X-point from
|
|
102
|
+
above and below and squirts back out sideways as reconnection outflow
|
|
103
|
+
"jets" -- exactly the inflow/outflow pattern Sweet-Parker and Petschek
|
|
104
|
+
reconnection assume, here imposed directly rather than derived from a
|
|
105
|
+
momentum equation (see the module docstring).
|
|
106
|
+
|
|
107
|
+
Parameters
|
|
108
|
+
----------
|
|
109
|
+
X, Y : ndarray
|
|
110
|
+
Coordinate grids, as built by :func:`reconnection_harris_ic`.
|
|
111
|
+
v0 : float
|
|
112
|
+
Characteristic inflow speed.
|
|
113
|
+
Lx, Ly : float
|
|
114
|
+
Domain size in `x` and `y`, used to center the stagnation point.
|
|
115
|
+
|
|
116
|
+
Returns
|
|
117
|
+
-------
|
|
118
|
+
vx, vy : ndarray
|
|
119
|
+
Velocity components, same shape as `X`.
|
|
120
|
+
|
|
121
|
+
Examples
|
|
122
|
+
--------
|
|
123
|
+
>>> import numpy as np
|
|
124
|
+
>>> X, Y = np.meshgrid(np.linspace(0, 20, 8, endpoint=False), np.linspace(-10, 10, 8, endpoint=False), indexing="ij")
|
|
125
|
+
>>> vx, vy = reconnection_inflow_velocity(X, Y, v0=0.1, Lx=20.0, Ly=20.0)
|
|
126
|
+
>>> vx.shape
|
|
127
|
+
(8, 8)
|
|
128
|
+
"""
|
|
129
|
+
Xc = np.mod(X - Lx / 2.0 + Lx / 2.0, Lx) - Lx / 2.0
|
|
130
|
+
vx = v0 * Xc / (Lx / 2.0)
|
|
131
|
+
vy = -v0 * Y / (Ly / 2.0)
|
|
132
|
+
return vx, vy
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def reconnection_field_from_flux(psi: np.ndarray, dx: float, dy: float) -> tuple:
|
|
136
|
+
"""Recover the in-plane magnetic field :math:`(B_x, B_y) = (\\partial_y\\psi, -\\partial_x\\psi)` from the flux function.
|
|
137
|
+
|
|
138
|
+
Parameters
|
|
139
|
+
----------
|
|
140
|
+
psi : ndarray, shape (nx, ny)
|
|
141
|
+
Flux function, periodic in both directions.
|
|
142
|
+
dx, dy : float
|
|
143
|
+
Grid spacing along `x` and `y`.
|
|
144
|
+
|
|
145
|
+
Returns
|
|
146
|
+
-------
|
|
147
|
+
Bx, By : ndarray, shape (nx, ny)
|
|
148
|
+
In-plane magnetic field components.
|
|
149
|
+
|
|
150
|
+
Examples
|
|
151
|
+
--------
|
|
152
|
+
>>> import numpy as np
|
|
153
|
+
>>> psi = reconnection_harris_ic(32, 32, Lx=20.0, Ly=20.0, sheet_width=1.0, perturbation_amplitude=0.0)
|
|
154
|
+
>>> Bx, By = reconnection_field_from_flux(psi, dx=20.0 / 32, dy=20.0 / 32)
|
|
155
|
+
>>> bool(np.all(Bx[:, 16] * Bx[:, 15] <= 0))
|
|
156
|
+
True
|
|
157
|
+
"""
|
|
158
|
+
dpsi_dy = (np.roll(psi, -1, axis=1) - np.roll(psi, 1, axis=1)) / (2.0 * dy)
|
|
159
|
+
dpsi_dx = (np.roll(psi, -1, axis=0) - np.roll(psi, 1, axis=0)) / (2.0 * dx)
|
|
160
|
+
return dpsi_dy, -dpsi_dx
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _laplacian_periodic(f: np.ndarray, dx: float, dy: float) -> np.ndarray:
|
|
164
|
+
d2x = (np.roll(f, -1, axis=0) - 2.0 * f + np.roll(f, 1, axis=0)) / dx**2
|
|
165
|
+
d2y = (np.roll(f, -1, axis=1) - 2.0 * f + np.roll(f, 1, axis=1)) / dy**2
|
|
166
|
+
return d2x + d2y
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def simulate_reconnection(psi0: np.ndarray, eta: float, v0: float, dt: float, steps: int, Lx: float, Ly: float) -> dict:
|
|
170
|
+
"""Time-step the kinematic resistive induction equation :math:`\\partial_t\\psi = \\eta\\nabla^2\\psi - \\mathbf{v}\\cdot\\nabla\\psi`.
|
|
171
|
+
|
|
172
|
+
A doubly periodic, second-order central-difference, explicit (forward
|
|
173
|
+
Euler in time) finite-difference solve. With a prescribed velocity
|
|
174
|
+
field rather than one obtained from solving the momentum equation
|
|
175
|
+
(see the module docstring), this reduces reconnection to pure flux
|
|
176
|
+
transport-and-diffusion: the inflow (:func:`reconnection_inflow_velocity`)
|
|
177
|
+
advects oppositely directed flux into the X-point, where resistive
|
|
178
|
+
diffusion (the :math:`\\eta\\nabla^2\\psi` term) is the only mechanism
|
|
179
|
+
that can actually break and reconnect field lines -- exactly Faraday's
|
|
180
|
+
law with an Ohmic (rather than ideal) Ohm's law, restricted to the
|
|
181
|
+
kinematic (fixed-flow) limit.
|
|
182
|
+
|
|
183
|
+
Explicit forward-Euler time-stepping is only conditionally stable:
|
|
184
|
+
the diffusive term requires :math:`\\eta\\,dt \\lesssim \\tfrac{1}{4}\\min(dx,dy)^2`
|
|
185
|
+
and the advective term requires the Courant condition
|
|
186
|
+
:math:`v_0\\,dt \\lesssim \\min(dx, dy)`. Both are the caller's
|
|
187
|
+
responsibility to satisfy by choosing `dt` appropriately; unstable
|
|
188
|
+
combinations manifest as exponentially growing grid-scale noise.
|
|
189
|
+
|
|
190
|
+
Parameters
|
|
191
|
+
----------
|
|
192
|
+
psi0 : ndarray, shape (nx, ny)
|
|
193
|
+
Initial flux function, e.g. from :func:`reconnection_harris_ic`.
|
|
194
|
+
eta : float
|
|
195
|
+
Resistivity (magnetic diffusivity).
|
|
196
|
+
v0 : float
|
|
197
|
+
Characteristic inflow speed for :func:`reconnection_inflow_velocity`.
|
|
198
|
+
dt : float
|
|
199
|
+
Time step.
|
|
200
|
+
steps : int
|
|
201
|
+
Number of forward-Euler steps to advance.
|
|
202
|
+
Lx, Ly : float
|
|
203
|
+
Domain size in `x` and `y`.
|
|
204
|
+
|
|
205
|
+
Returns
|
|
206
|
+
-------
|
|
207
|
+
dict
|
|
208
|
+
``{"psi": final flux function, "Bx": ..., "By": ...}``.
|
|
209
|
+
|
|
210
|
+
See Also
|
|
211
|
+
--------
|
|
212
|
+
reconnection_harris_ic : Builds the initial condition consumed here.
|
|
213
|
+
physicskit.plasma.mhd.sweet_parker_rate : The steady-state reconnection
|
|
214
|
+
rate this kinematic model is a simplified, time-dependent analogue of.
|
|
215
|
+
|
|
216
|
+
Examples
|
|
217
|
+
--------
|
|
218
|
+
>>> import numpy as np
|
|
219
|
+
>>> psi0 = reconnection_harris_ic(48, 48, Lx=20.0, Ly=20.0, sheet_width=1.0, perturbation_amplitude=0.2)
|
|
220
|
+
>>> result = simulate_reconnection(psi0, eta=0.02, v0=0.05, dt=0.02, steps=50, Lx=20.0, Ly=20.0)
|
|
221
|
+
>>> result["psi"].shape
|
|
222
|
+
(48, 48)
|
|
223
|
+
>>> bool(np.all(np.isfinite(result["psi"])))
|
|
224
|
+
True
|
|
225
|
+
"""
|
|
226
|
+
nx, ny = psi0.shape
|
|
227
|
+
dx, dy = Lx / nx, Ly / ny
|
|
228
|
+
x = np.linspace(0.0, Lx, nx, endpoint=False)
|
|
229
|
+
y = np.linspace(-Ly / 2.0, Ly / 2.0, ny, endpoint=False)
|
|
230
|
+
X, Y = np.meshgrid(x, y, indexing="ij")
|
|
231
|
+
vx, vy = reconnection_inflow_velocity(X, Y, v0, Lx, Ly)
|
|
232
|
+
|
|
233
|
+
psi = np.array(psi0, dtype=float, copy=True)
|
|
234
|
+
for _ in range(steps):
|
|
235
|
+
dpsi_dx = (np.roll(psi, -1, axis=0) - np.roll(psi, 1, axis=0)) / (2.0 * dx)
|
|
236
|
+
dpsi_dy = (np.roll(psi, -1, axis=1) - np.roll(psi, 1, axis=1)) / (2.0 * dy)
|
|
237
|
+
rhs = eta * _laplacian_periodic(psi, dx, dy) - (vx * dpsi_dx + vy * dpsi_dy)
|
|
238
|
+
psi = psi + dt * rhs
|
|
239
|
+
|
|
240
|
+
Bx, By = reconnection_field_from_flux(psi, dx, dy)
|
|
241
|
+
return {"psi": psi, "Bx": Bx, "By": By}
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def weibel_growth_rate(k: np.ndarray, wpe: float, temperature_anisotropy: float, c: float = _const.C) -> np.ndarray:
|
|
245
|
+
"""Linear growth rate of the (non-relativistic, cold-parallel-limit) Weibel/filamentation instability.
|
|
246
|
+
|
|
247
|
+
For an electron distribution anisotropic between the direction of
|
|
248
|
+
wave propagation (temperature :math:`T_\\parallel`, taken cold here)
|
|
249
|
+
and the transverse direction (temperature :math:`T_\\perp`), the
|
|
250
|
+
electromagnetic mode with wavevector :math:`\\mathbf{k}` transverse to
|
|
251
|
+
the anisotropy axis is purely growing (Weibel, 1959) with
|
|
252
|
+
|
|
253
|
+
.. math::
|
|
254
|
+
|
|
255
|
+
\\gamma(k)^2 = \\omega_{pe}^2\\left(\\frac{T_\\perp}{T_\\parallel}-1\\right) - k^2 c^2,
|
|
256
|
+
|
|
257
|
+
unstable for :math:`T_\\perp > T_\\parallel` and only up to the cutoff
|
|
258
|
+
:math:`k_{max} = (\\omega_{pe}/c)\\sqrt{T_\\perp/T_\\parallel - 1}` --
|
|
259
|
+
beyond which the field's magnetic tension (the :math:`k^2c^2` term)
|
|
260
|
+
overcomes the free energy the anisotropy supplies. Growing transverse
|
|
261
|
+
magnetic perturbations pinch counter-streaming electron sub-populations
|
|
262
|
+
into spatially separated current channels: the filaments this
|
|
263
|
+
instability is named for.
|
|
264
|
+
|
|
265
|
+
Parameters
|
|
266
|
+
----------
|
|
267
|
+
k : ndarray or float
|
|
268
|
+
Wavenumber(s), transverse to the anisotropy axis.
|
|
269
|
+
wpe : float
|
|
270
|
+
Electron plasma frequency.
|
|
271
|
+
temperature_anisotropy : float
|
|
272
|
+
The ratio :math:`T_\\perp/T_\\parallel`; must exceed 1 for any
|
|
273
|
+
instability.
|
|
274
|
+
c : float, default=physicskit.constants.C
|
|
275
|
+
Speed of light, in the same units `k` and `wpe` combine to give
|
|
276
|
+
(SI by default).
|
|
277
|
+
|
|
278
|
+
Returns
|
|
279
|
+
-------
|
|
280
|
+
ndarray or float
|
|
281
|
+
Growth rate :math:`\\gamma(k)`, clipped to zero for stable (real
|
|
282
|
+
or imaginary-:math:`\\gamma^2<0`) wavenumbers.
|
|
283
|
+
|
|
284
|
+
See Also
|
|
285
|
+
--------
|
|
286
|
+
weibel_fastest_growing_mode : The wavenumber maximizing this growth rate.
|
|
287
|
+
simulate_weibel_filamentation : Superposes modes growing at this rate.
|
|
288
|
+
|
|
289
|
+
Examples
|
|
290
|
+
--------
|
|
291
|
+
>>> import numpy as np
|
|
292
|
+
>>> round(float(weibel_growth_rate(k=0.0, wpe=1.0, temperature_anisotropy=4.0)), 6)
|
|
293
|
+
1.732051
|
|
294
|
+
>>> bool(weibel_growth_rate(k=1e10, wpe=1.0, temperature_anisotropy=4.0) == 0.0)
|
|
295
|
+
True
|
|
296
|
+
"""
|
|
297
|
+
k = np.asarray(k, dtype=float)
|
|
298
|
+
gamma_sq = wpe**2 * (temperature_anisotropy - 1.0) - (k * c) ** 2
|
|
299
|
+
return np.sqrt(np.clip(gamma_sq, 0.0, None))
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def weibel_fastest_growing_mode(wpe: float, temperature_anisotropy: float, c: float = _const.C) -> tuple:
|
|
303
|
+
"""Wavenumber and growth rate of the fastest-growing Weibel mode.
|
|
304
|
+
|
|
305
|
+
For the growth-rate law of :func:`weibel_growth_rate`,
|
|
306
|
+
:math:`\\gamma(k)^2` is maximized at :math:`k=0` (long wavelength,
|
|
307
|
+
where the stabilizing field-tension term vanishes), giving
|
|
308
|
+
:math:`\\gamma_{max}=\\omega_{pe}\\sqrt{T_\\perp/T_\\parallel-1}` -- the
|
|
309
|
+
growth rate used to set the overall filament-growth timescale in
|
|
310
|
+
:func:`simulate_weibel_filamentation`, even though the *dominant
|
|
311
|
+
filament spacing* in a real (finite-seed) simulation is set by which
|
|
312
|
+
finite-:math:`k` modes happen to be seeded with the largest initial
|
|
313
|
+
amplitude, since every :math:`k` below cutoff grows, just more slowly
|
|
314
|
+
farther from :math:`k=0`.
|
|
315
|
+
|
|
316
|
+
Parameters
|
|
317
|
+
----------
|
|
318
|
+
wpe : float
|
|
319
|
+
Electron plasma frequency.
|
|
320
|
+
temperature_anisotropy : float
|
|
321
|
+
The ratio :math:`T_\\perp/T_\\parallel`; must exceed 1.
|
|
322
|
+
c : float, default=physicskit.constants.C
|
|
323
|
+
Speed of light.
|
|
324
|
+
|
|
325
|
+
Returns
|
|
326
|
+
-------
|
|
327
|
+
k_max_growth, gamma_max : float
|
|
328
|
+
The (zero) wavenumber of maximum growth and the corresponding
|
|
329
|
+
growth rate, and the cutoff wavenumber :func:`weibel_growth_rate`
|
|
330
|
+
vanishes beyond.
|
|
331
|
+
|
|
332
|
+
Examples
|
|
333
|
+
--------
|
|
334
|
+
>>> k0, gamma_max = weibel_fastest_growing_mode(wpe=1.0, temperature_anisotropy=4.0)
|
|
335
|
+
>>> k0
|
|
336
|
+
0.0
|
|
337
|
+
>>> round(gamma_max, 6)
|
|
338
|
+
1.732051
|
|
339
|
+
"""
|
|
340
|
+
if temperature_anisotropy <= 1.0:
|
|
341
|
+
return 0.0, 0.0
|
|
342
|
+
gamma_max = wpe * np.sqrt(temperature_anisotropy - 1.0)
|
|
343
|
+
return 0.0, float(gamma_max)
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
def simulate_weibel_filamentation(
|
|
347
|
+
x: np.ndarray, t: np.ndarray, wpe: float, temperature_anisotropy: float, n_modes: int = 12, k_max_factor: float = 0.9, seed: int = 0
|
|
348
|
+
) -> np.ndarray:
|
|
349
|
+
"""Reduced quasi-linear Weibel filamentation model: a spectrum of independently growing current modes.
|
|
350
|
+
|
|
351
|
+
Seeds `n_modes` transverse-current Fourier modes with small random
|
|
352
|
+
amplitudes and phases, spanning wavenumbers up to
|
|
353
|
+
``k_max_factor`` times the linear cutoff :math:`k_{max}` of
|
|
354
|
+
:func:`weibel_growth_rate`, and evolves each mode's amplitude
|
|
355
|
+
independently as :math:`a_k(t) = a_k(0)\\,e^{\\gamma(k)t}` -- exact
|
|
356
|
+
linear theory, valid until the fastest-growing filaments approach
|
|
357
|
+
nonlinear saturation (order-unity current perturbation), at which
|
|
358
|
+
point real filamentation departs from this superposition (mode
|
|
359
|
+
coupling, filament merging) that this reduced model does not capture.
|
|
360
|
+
This stands in for a full 2D-in-velocity electromagnetic PIC
|
|
361
|
+
simulation; see the module docstring for why.
|
|
362
|
+
|
|
363
|
+
Parameters
|
|
364
|
+
----------
|
|
365
|
+
x : ndarray, shape (nx,)
|
|
366
|
+
Spatial grid (periodic).
|
|
367
|
+
t : ndarray, shape (nt,)
|
|
368
|
+
Times at which to evaluate the current pattern.
|
|
369
|
+
wpe : float
|
|
370
|
+
Electron plasma frequency.
|
|
371
|
+
temperature_anisotropy : float
|
|
372
|
+
The ratio :math:`T_\\perp/T_\\parallel`; must exceed 1.
|
|
373
|
+
n_modes : int, default=12
|
|
374
|
+
Number of Fourier modes to seed.
|
|
375
|
+
k_max_factor : float, default=0.9
|
|
376
|
+
Fraction of the linear cutoff wavenumber up to which modes are
|
|
377
|
+
seeded (kept below 1 so every seeded mode is genuinely unstable).
|
|
378
|
+
seed : int, default=0
|
|
379
|
+
Random seed for the initial mode amplitudes and phases.
|
|
380
|
+
|
|
381
|
+
Returns
|
|
382
|
+
-------
|
|
383
|
+
ndarray, shape (nt, nx)
|
|
384
|
+
Transverse current density :math:`J_y(x, t)`, in units where the
|
|
385
|
+
initial per-mode amplitude is order unity (i.e. a normalized,
|
|
386
|
+
not absolute, current).
|
|
387
|
+
|
|
388
|
+
See Also
|
|
389
|
+
--------
|
|
390
|
+
weibel_growth_rate : The per-mode growth rate used here.
|
|
391
|
+
|
|
392
|
+
Examples
|
|
393
|
+
--------
|
|
394
|
+
>>> import numpy as np
|
|
395
|
+
>>> x = np.linspace(0, 20.0, 128, endpoint=False)
|
|
396
|
+
>>> t = np.linspace(0, 5.0, 10)
|
|
397
|
+
>>> J = simulate_weibel_filamentation(x, t, wpe=1.0, temperature_anisotropy=4.0, n_modes=6, seed=0)
|
|
398
|
+
>>> J.shape
|
|
399
|
+
(10, 128)
|
|
400
|
+
>>> bool(np.std(J[-1]) > np.std(J[0]))
|
|
401
|
+
True
|
|
402
|
+
"""
|
|
403
|
+
rng = np.random.default_rng(seed)
|
|
404
|
+
c = _const.C
|
|
405
|
+
k_max = (wpe / c) * np.sqrt(max(temperature_anisotropy - 1.0, 1e-12))
|
|
406
|
+
k_modes = np.linspace(k_max / n_modes, k_max_factor * k_max, n_modes)
|
|
407
|
+
amplitudes0 = rng.uniform(0.5, 1.0, n_modes)
|
|
408
|
+
phases = rng.uniform(0.0, 2.0 * np.pi, n_modes)
|
|
409
|
+
gammas = weibel_growth_rate(k_modes, wpe, temperature_anisotropy, c=c)
|
|
410
|
+
|
|
411
|
+
t = np.asarray(t, dtype=float)
|
|
412
|
+
x = np.asarray(x, dtype=float)
|
|
413
|
+
growth = np.exp(np.outer(t, gammas))
|
|
414
|
+
amplitudes = amplitudes0[None, :] * growth
|
|
415
|
+
phase_arg = k_modes[None, None, :] * x[None, :, None] + phases[None, None, :]
|
|
416
|
+
J = np.sum(amplitudes[:, None, :] * np.cos(phase_arg), axis=2)
|
|
417
|
+
return J
|