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,549 @@
|
|
|
1
|
+
"""Cold plasma waves: the Stix dielectric tensor, dispersion relations, and CMA mapping.
|
|
2
|
+
|
|
3
|
+
Linearizes the multi-fluid cold-plasma equations around a uniform
|
|
4
|
+
background threaded by a uniform :math:`\\mathbf{B}_0` to get the
|
|
5
|
+
dielectric tensor components :math:`S`, :math:`D`, :math:`P` (Stix, 1962)
|
|
6
|
+
in :func:`stix_parameters`, then solves the general dispersion relation
|
|
7
|
+
:math:`\\mathbf{n}\\times(\\mathbf{n}\\times\\mathbf{E}) + \\mathbf{K}\\cdot\\mathbf{E}=0`
|
|
8
|
+
for the refractive index :math:`n=ck/\\omega` at any propagation angle
|
|
9
|
+
:math:`\\theta` to :math:`\\mathbf{B}_0` with :func:`cold_plasma_dispersion`.
|
|
10
|
+
Every named mode -- the parallel-propagating R- and L-waves, the
|
|
11
|
+
perpendicular O- and X-modes, and the low-frequency whistler branch -- is
|
|
12
|
+
a special case of that one quartic in :math:`n^2`.
|
|
13
|
+
:func:`cma_coordinates` maps a plasma state onto the two dimensionless
|
|
14
|
+
axes of the Clemmow-Mullaly-Allis diagram that organizes all of them.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import numpy as np
|
|
20
|
+
|
|
21
|
+
from physicskit import constants as _const
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"QE",
|
|
25
|
+
"ME",
|
|
26
|
+
"MP",
|
|
27
|
+
"EPS0",
|
|
28
|
+
"plasma_frequency",
|
|
29
|
+
"stix_parameters",
|
|
30
|
+
"rl_parameters",
|
|
31
|
+
"cold_plasma_dispersion",
|
|
32
|
+
"whistler_dispersion",
|
|
33
|
+
"cma_coordinates",
|
|
34
|
+
"ion_acoustic_soliton_profile",
|
|
35
|
+
"ion_acoustic_soliton_evolve",
|
|
36
|
+
"alfven_wave_pulse_ic",
|
|
37
|
+
"simulate_alfven_wave",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
QE = _const.ELEMENTARY_CHARGE
|
|
41
|
+
"""Elementary charge, in Coulombs."""
|
|
42
|
+
|
|
43
|
+
ME = _const.ELECTRON_MASS
|
|
44
|
+
"""Electron mass, in kilograms."""
|
|
45
|
+
|
|
46
|
+
MP = _const.PROTON_MASS
|
|
47
|
+
"""Proton mass, in kilograms."""
|
|
48
|
+
|
|
49
|
+
EPS0 = _const.VACUUM_PERMITTIVITY
|
|
50
|
+
"""Vacuum permittivity, in F/m."""
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def plasma_frequency(n: float, q: float = QE, m: float = ME) -> float:
|
|
54
|
+
"""Species plasma frequency :math:`\\omega_p = \\sqrt{nq^2/(\\varepsilon_0 m)}`.
|
|
55
|
+
|
|
56
|
+
The natural oscillation frequency of a species displaced from
|
|
57
|
+
quasineutrality: the restoring electric field it builds up is
|
|
58
|
+
proportional to the displacement, making every unmagnetized plasma a
|
|
59
|
+
harmonic oscillator at this frequency -- the very phenomenon Langmuir
|
|
60
|
+
identified in 1928.
|
|
61
|
+
|
|
62
|
+
Parameters
|
|
63
|
+
----------
|
|
64
|
+
n : float
|
|
65
|
+
Number density in m^-3.
|
|
66
|
+
q : float, default=QE
|
|
67
|
+
Species charge magnitude in Coulombs.
|
|
68
|
+
m : float, default=ME
|
|
69
|
+
Species mass in kilograms.
|
|
70
|
+
|
|
71
|
+
Returns
|
|
72
|
+
-------
|
|
73
|
+
float
|
|
74
|
+
Angular plasma frequency in rad/s.
|
|
75
|
+
|
|
76
|
+
Examples
|
|
77
|
+
--------
|
|
78
|
+
>>> round(float(plasma_frequency(1e19)) / 1e9, 3)
|
|
79
|
+
178.399
|
|
80
|
+
"""
|
|
81
|
+
return np.sqrt(n * q**2 / (EPS0 * m))
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def stix_parameters(omega: float, B: float, species) -> tuple:
|
|
85
|
+
"""Stix cold-plasma dielectric tensor components :math:`S`, :math:`D`, :math:`P`.
|
|
86
|
+
|
|
87
|
+
Summing each species' contribution to the linearized fluid response
|
|
88
|
+
gives the Hermitian dielectric tensor
|
|
89
|
+
|
|
90
|
+
.. math::
|
|
91
|
+
|
|
92
|
+
\\mathbf{K} = \\begin{pmatrix} S & -iD & 0 \\\\ iD & S & 0 \\\\ 0 & 0 & P \\end{pmatrix},
|
|
93
|
+
\\qquad
|
|
94
|
+
S = 1 - \\sum_s \\frac{\\omega_{ps}^2}{\\omega^2-\\omega_{cs}^2}, \\quad
|
|
95
|
+
D = \\sum_s \\frac{\\omega_{cs}}{\\omega}\\frac{\\omega_{ps}^2}{\\omega^2-\\omega_{cs}^2}, \\quad
|
|
96
|
+
P = 1 - \\sum_s \\frac{\\omega_{ps}^2}{\\omega^2},
|
|
97
|
+
|
|
98
|
+
with each species' signed cyclotron frequency :math:`\\omega_{cs}=q_sB/m_s`
|
|
99
|
+
entering :math:`D` with its own sign -- the source of the
|
|
100
|
+
circular-polarization asymmetry between the R- and L-waves.
|
|
101
|
+
|
|
102
|
+
Parameters
|
|
103
|
+
----------
|
|
104
|
+
omega : float
|
|
105
|
+
Wave angular frequency in rad/s.
|
|
106
|
+
B : float
|
|
107
|
+
Background magnetic field magnitude in Tesla.
|
|
108
|
+
species : sequence of (float, float, float)
|
|
109
|
+
``(n, q, m)`` for each plasma species: number density in m^-3,
|
|
110
|
+
signed charge in Coulombs, mass in kilograms.
|
|
111
|
+
|
|
112
|
+
Returns
|
|
113
|
+
-------
|
|
114
|
+
S, D, P : float
|
|
115
|
+
Stix dielectric tensor components (dimensionless).
|
|
116
|
+
|
|
117
|
+
See Also
|
|
118
|
+
--------
|
|
119
|
+
cold_plasma_dispersion : Solves the dispersion relation built from these.
|
|
120
|
+
rl_parameters : The right/left-hand combinations :math:`R=S+D`, :math:`L=S-D`.
|
|
121
|
+
|
|
122
|
+
Examples
|
|
123
|
+
--------
|
|
124
|
+
>>> electrons = (1e19, -QE, ME)
|
|
125
|
+
>>> ions = (1e19, QE, MP)
|
|
126
|
+
>>> S, D, P = stix_parameters(omega=2e9, B=1.0, species=[electrons, ions])
|
|
127
|
+
>>> round(S, 4), round(D, 4), round(P, 4)
|
|
128
|
+
(-2.3143, 90.6954, -7959.8516)
|
|
129
|
+
"""
|
|
130
|
+
S, D, P = 1.0, 0.0, 1.0
|
|
131
|
+
for n, q, m in species:
|
|
132
|
+
wp2 = n * q**2 / (EPS0 * m)
|
|
133
|
+
wc = q * B / m
|
|
134
|
+
S -= wp2 / (omega**2 - wc**2)
|
|
135
|
+
D += (wc / omega) * wp2 / (omega**2 - wc**2)
|
|
136
|
+
P -= wp2 / omega**2
|
|
137
|
+
return S, D, P
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def rl_parameters(S: float, D: float) -> tuple:
|
|
141
|
+
"""Right- and left-hand Stix parameters :math:`R = S+D`, :math:`L = S-D`.
|
|
142
|
+
|
|
143
|
+
:math:`R` and :math:`L` are the dielectric response seen by a purely
|
|
144
|
+
right- or left-hand circularly polarized wave propagating exactly
|
|
145
|
+
along :math:`\\mathbf{B}_0`; the R-wave resonates at the electron
|
|
146
|
+
cyclotron frequency and the L-wave at the ion cyclotron frequency.
|
|
147
|
+
|
|
148
|
+
Parameters
|
|
149
|
+
----------
|
|
150
|
+
S, D : float
|
|
151
|
+
Stix parameters from :func:`stix_parameters`.
|
|
152
|
+
|
|
153
|
+
Returns
|
|
154
|
+
-------
|
|
155
|
+
R, L : float
|
|
156
|
+
Right- and left-hand dielectric parameters.
|
|
157
|
+
|
|
158
|
+
Examples
|
|
159
|
+
--------
|
|
160
|
+
>>> rl_parameters(S=1.0, D=0.5)
|
|
161
|
+
(1.5, 0.5)
|
|
162
|
+
"""
|
|
163
|
+
return S + D, S - D
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def cold_plasma_dispersion(theta: float, S: float, D: float, P: float) -> tuple:
|
|
167
|
+
"""Solve the cold-plasma dispersion relation for the squared refractive index :math:`n^2`.
|
|
168
|
+
|
|
169
|
+
Substituting a plane wave into
|
|
170
|
+
:math:`\\mathbf{n}\\times(\\mathbf{n}\\times\\mathbf{E})+\\mathbf{K}\\cdot\\mathbf{E}=0`
|
|
171
|
+
for propagation at angle :math:`\\theta` to :math:`\\mathbf{B}_0` gives
|
|
172
|
+
the Appleton-Hartree biquadratic :math:`An^4 - Bn^2 + C = 0` with
|
|
173
|
+
|
|
174
|
+
.. math::
|
|
175
|
+
|
|
176
|
+
A = S\\sin^2\\theta + P\\cos^2\\theta, \\quad
|
|
177
|
+
B = RL\\sin^2\\theta + PS(1+\\cos^2\\theta), \\quad
|
|
178
|
+
C = PRL,
|
|
179
|
+
|
|
180
|
+
which reduces at :math:`\\theta=0` to the decoupled R- and L-waves
|
|
181
|
+
(:math:`n^2=R` or :math:`L`) and at :math:`\\theta=\\pi/2` to the
|
|
182
|
+
O-mode (:math:`n^2=P`) and X-mode (:math:`n^2=RL/S`).
|
|
183
|
+
|
|
184
|
+
Parameters
|
|
185
|
+
----------
|
|
186
|
+
theta : float
|
|
187
|
+
Angle between the wavevector and :math:`\\mathbf{B}_0`, in radians.
|
|
188
|
+
S, D, P : float
|
|
189
|
+
Stix parameters from :func:`stix_parameters`.
|
|
190
|
+
|
|
191
|
+
Returns
|
|
192
|
+
-------
|
|
193
|
+
n_sq_plus, n_sq_minus : float
|
|
194
|
+
The two roots of the biquadratic (the two cold-plasma wave
|
|
195
|
+
branches at this angle and frequency). A negative root means that
|
|
196
|
+
branch is evanescent rather than propagating.
|
|
197
|
+
|
|
198
|
+
See Also
|
|
199
|
+
--------
|
|
200
|
+
stix_parameters : Supplies ``S``, ``D``, ``P``.
|
|
201
|
+
|
|
202
|
+
Examples
|
|
203
|
+
--------
|
|
204
|
+
Parallel propagation recovers the pure R- and L-wave refractive indices:
|
|
205
|
+
|
|
206
|
+
>>> import numpy as np
|
|
207
|
+
>>> S, D, P = -2.314262935091991, 90.69535621969021, -7959.851640342367
|
|
208
|
+
>>> n2_plus, n2_minus = cold_plasma_dispersion(theta=0.0, S=S, D=D, P=P)
|
|
209
|
+
>>> R, L = rl_parameters(S, D)
|
|
210
|
+
>>> bool(np.isclose(sorted([n2_plus, n2_minus]), sorted([R, L])).all())
|
|
211
|
+
True
|
|
212
|
+
"""
|
|
213
|
+
R, L = rl_parameters(S, D)
|
|
214
|
+
A = S * np.sin(theta) ** 2 + P * np.cos(theta) ** 2
|
|
215
|
+
Bc = R * L * np.sin(theta) ** 2 + P * S * (1.0 + np.cos(theta) ** 2)
|
|
216
|
+
C = P * R * L
|
|
217
|
+
disc = Bc**2 - 4.0 * A * C
|
|
218
|
+
sqrt_disc = np.sqrt(disc)
|
|
219
|
+
return (Bc + sqrt_disc) / (2.0 * A), (Bc - sqrt_disc) / (2.0 * A)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def whistler_dispersion(omega: float, wpe: float, wce: float) -> float:
|
|
223
|
+
"""Electron-only, parallel-propagation whistler-mode refractive index :math:`n^2 = \\omega_{pe}^2/[\\omega(\\omega_{ce}-\\omega)]`.
|
|
224
|
+
|
|
225
|
+
The low-frequency (:math:`\\omega \\ll \\omega_{ce}`), right-hand
|
|
226
|
+
circularly polarized branch of the R-wave, with ion motion neglected.
|
|
227
|
+
Because :math:`n^2` grows without bound as :math:`\\omega\\to\\omega_{ce}`,
|
|
228
|
+
whistlers slow down sharply as they approach the electron cyclotron
|
|
229
|
+
frequency -- the falling-tone "whistle" heard in radio receivers after
|
|
230
|
+
a lightning stroke launches a broadband pulse that disperses along
|
|
231
|
+
Earth's field lines, with the highest frequencies (closest to
|
|
232
|
+
:math:`\\omega_{ce}`) arriving last.
|
|
233
|
+
|
|
234
|
+
Parameters
|
|
235
|
+
----------
|
|
236
|
+
omega : float
|
|
237
|
+
Wave angular frequency in rad/s, with :math:`\\omega \\ll \\omega_{ce}`.
|
|
238
|
+
wpe : float
|
|
239
|
+
Electron plasma frequency in rad/s, from :func:`plasma_frequency`.
|
|
240
|
+
wce : float
|
|
241
|
+
Electron cyclotron frequency in rad/s (positive).
|
|
242
|
+
|
|
243
|
+
Returns
|
|
244
|
+
-------
|
|
245
|
+
float
|
|
246
|
+
Squared refractive index :math:`n^2`.
|
|
247
|
+
|
|
248
|
+
See Also
|
|
249
|
+
--------
|
|
250
|
+
cold_plasma_dispersion : The general dispersion relation this is a limit of.
|
|
251
|
+
|
|
252
|
+
Examples
|
|
253
|
+
--------
|
|
254
|
+
Well below the electron cyclotron frequency, it agrees closely with
|
|
255
|
+
the exact electron-only R-wave root of :func:`cold_plasma_dispersion`:
|
|
256
|
+
|
|
257
|
+
>>> wpe, wce = 1.784e11, 1.759e11
|
|
258
|
+
>>> omega = 0.001 * wce
|
|
259
|
+
>>> S, D, P = stix_parameters(omega, B=1.0, species=[(wpe ** 2 * EPS0 * ME / QE ** 2, -QE, ME)])
|
|
260
|
+
>>> R, _ = rl_parameters(S, D)
|
|
261
|
+
>>> n2_approx = whistler_dispersion(omega, wpe, wce)
|
|
262
|
+
>>> round(abs(n2_approx - R) / R, 2)
|
|
263
|
+
0.0
|
|
264
|
+
"""
|
|
265
|
+
return wpe**2 / (omega * (wce - omega))
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def cma_coordinates(omega: float, wpe: float, wce: float) -> tuple:
|
|
269
|
+
"""Dimensionless :math:`(X, Y)` coordinates of the Clemmow-Mullaly-Allis (CMA) diagram.
|
|
270
|
+
|
|
271
|
+
The CMA diagram partitions the plane :math:`X=\\omega_{pe}^2/\\omega^2`
|
|
272
|
+
(density axis) vs. :math:`Y=\\omega_{ce}/\\omega` (field-strength axis)
|
|
273
|
+
into regions of distinct wave topology -- cutoffs, resonances, and the
|
|
274
|
+
number and polarization of propagating modes -- giving a single map
|
|
275
|
+
of every cold-plasma wave regime from ordinary light waves
|
|
276
|
+
(:math:`X, Y \\to 0`) to the Alfven wave and whistler branches
|
|
277
|
+
(:math:`Y \\gg 1`).
|
|
278
|
+
|
|
279
|
+
Parameters
|
|
280
|
+
----------
|
|
281
|
+
omega : float
|
|
282
|
+
Wave angular frequency in rad/s.
|
|
283
|
+
wpe : float
|
|
284
|
+
Electron plasma frequency in rad/s.
|
|
285
|
+
wce : float
|
|
286
|
+
Electron cyclotron frequency in rad/s.
|
|
287
|
+
|
|
288
|
+
Returns
|
|
289
|
+
-------
|
|
290
|
+
X, Y : float
|
|
291
|
+
CMA diagram coordinates.
|
|
292
|
+
|
|
293
|
+
Examples
|
|
294
|
+
--------
|
|
295
|
+
>>> cma_coordinates(omega=1.0, wpe=2.0, wce=3.0)
|
|
296
|
+
(4.0, 3.0)
|
|
297
|
+
"""
|
|
298
|
+
return (wpe / omega) ** 2, wce / omega
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def ion_acoustic_soliton_profile(x: np.ndarray, speed: float, x0: float = 0.0) -> np.ndarray:
|
|
302
|
+
"""Exact single-soliton solution of the ion-acoustic Korteweg-de Vries reduction.
|
|
303
|
+
|
|
304
|
+
The reductive-perturbation (Washimi & Taniuti, 1966) expansion of the
|
|
305
|
+
cold-ion-fluid/Boltzmann-electron equations in the weakly nonlinear,
|
|
306
|
+
weakly dispersive limit reduces the ion-acoustic wave problem to the
|
|
307
|
+
KdV equation for the normalized density (or potential) perturbation
|
|
308
|
+
:math:`u` in a frame moving at the ion-sound speed; after the standard
|
|
309
|
+
rescaling of the stretched coordinates it takes the canonical form
|
|
310
|
+
:math:`u_t + 6uu_\\xi + u_{\\xi\\xi\\xi} = 0` -- the same normal form
|
|
311
|
+
every weakly-dispersive weakly-nonlinear wave problem reduces to,
|
|
312
|
+
with the ion-acoustic-specific physics (electron Boltzmann response
|
|
313
|
+
supplying the nonlinearity, ion inertia and Debye-length dispersion
|
|
314
|
+
supplying the :math:`\\partial_\\xi^3` term) fixing only the physical
|
|
315
|
+
unit conversions between :math:`u,\\xi,t` and density, position, and
|
|
316
|
+
time in the ion-sound-speed frame. Its exact traveling-wave solution
|
|
317
|
+
is a single soliton of speed :math:`c` (in the stretched frame) and
|
|
318
|
+
amplitude :math:`c/2`, propagating without change of shape --
|
|
319
|
+
consistent with a real ion-acoustic soliton, whose speed always
|
|
320
|
+
exceeds the linear sound speed by an amount set by its amplitude.
|
|
321
|
+
|
|
322
|
+
Parameters
|
|
323
|
+
----------
|
|
324
|
+
x : ndarray
|
|
325
|
+
Spatial grid, in the stretched (ion-sound-speed) frame.
|
|
326
|
+
speed : float
|
|
327
|
+
Soliton speed :math:`c` in the stretched frame (amplitude
|
|
328
|
+
:math:`=c/2`); must be positive.
|
|
329
|
+
x0 : float, default=0.0
|
|
330
|
+
Initial center position.
|
|
331
|
+
|
|
332
|
+
Returns
|
|
333
|
+
-------
|
|
334
|
+
ndarray
|
|
335
|
+
:math:`u(x, 0) = \\tfrac{c}{2}\\,\\mathrm{sech}^2\\!\\big(\\tfrac{\\sqrt{c}}{2}(x-x_0)\\big)`.
|
|
336
|
+
|
|
337
|
+
See Also
|
|
338
|
+
--------
|
|
339
|
+
ion_acoustic_soliton_evolve : Propagate this (or any) initial condition forward in time.
|
|
340
|
+
|
|
341
|
+
Examples
|
|
342
|
+
--------
|
|
343
|
+
>>> round(float(ion_acoustic_soliton_profile(0.0, speed=4.0)), 6)
|
|
344
|
+
2.0
|
|
345
|
+
"""
|
|
346
|
+
return (speed / 2.0) * (1.0 / np.cosh(np.sqrt(speed) / 2.0 * (x - x0))) ** 2
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def _ion_acoustic_kdv_rhs_hat(u_hat: np.ndarray, k: np.ndarray) -> np.ndarray:
|
|
350
|
+
u = np.real(np.fft.ifft(u_hat))
|
|
351
|
+
ux = np.real(np.fft.ifft(1j * k * u_hat))
|
|
352
|
+
return np.fft.fft(-6.0 * u * ux)
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def ion_acoustic_soliton_evolve(u0: np.ndarray, x: np.ndarray, dt: float, steps: int) -> np.ndarray:
|
|
356
|
+
"""Evolve an ion-acoustic KdV initial condition forward in time on a periodic domain.
|
|
357
|
+
|
|
358
|
+
A pseudo-spectral Strang-split scheme: the stiff linear dispersion
|
|
359
|
+
:math:`\\partial_\\xi^3` is advanced exactly in Fourier space, and the
|
|
360
|
+
non-stiff nonlinear advection :math:`6uu_\\xi` with RK4 in between --
|
|
361
|
+
structurally the standard splitting for any KdV-type equation, applied
|
|
362
|
+
here directly to the ion-acoustic reduction rather than by importing a
|
|
363
|
+
generic KdV solver, since the physical field this equation governs
|
|
364
|
+
(a Debye-length-normalized density/potential perturbation moving at
|
|
365
|
+
order the ion-sound speed) is specific to this module.
|
|
366
|
+
|
|
367
|
+
Parameters
|
|
368
|
+
----------
|
|
369
|
+
u0 : ndarray
|
|
370
|
+
Initial field, sampled on the periodic grid ``x``.
|
|
371
|
+
x : ndarray
|
|
372
|
+
Uniformly spaced periodic spatial grid.
|
|
373
|
+
dt : float
|
|
374
|
+
Time step.
|
|
375
|
+
steps : int
|
|
376
|
+
Number of steps to advance.
|
|
377
|
+
|
|
378
|
+
Returns
|
|
379
|
+
-------
|
|
380
|
+
ndarray
|
|
381
|
+
Field after ``steps * dt`` time units.
|
|
382
|
+
|
|
383
|
+
See Also
|
|
384
|
+
--------
|
|
385
|
+
ion_acoustic_soliton_profile : Exact traveling-wave solution this reproduces.
|
|
386
|
+
|
|
387
|
+
Examples
|
|
388
|
+
--------
|
|
389
|
+
A soliton launched at speed :math:`c=4` has advanced by very close to
|
|
390
|
+
:math:`c\\cdot(\\text{steps}\\cdot dt)` and kept its amplitude, since
|
|
391
|
+
KdV solitons propagate without changing shape:
|
|
392
|
+
|
|
393
|
+
>>> import numpy as np
|
|
394
|
+
>>> N, L = 512, 60.0
|
|
395
|
+
>>> x = np.linspace(-L / 2, L / 2, N, endpoint=False)
|
|
396
|
+
>>> u0 = ion_acoustic_soliton_profile(x, speed=4.0, x0=-15.0)
|
|
397
|
+
>>> u = ion_acoustic_soliton_evolve(u0, x, dt=0.0005, steps=4000)
|
|
398
|
+
>>> shift = x[np.argmax(u)] - x[np.argmax(u0)]
|
|
399
|
+
>>> bool(abs(shift - 4.0 * 4000 * 0.0005) < 0.5)
|
|
400
|
+
True
|
|
401
|
+
>>> bool(abs(u.max() - u0.max()) < 0.05)
|
|
402
|
+
True
|
|
403
|
+
"""
|
|
404
|
+
k = 2.0 * np.pi * np.fft.fftfreq(len(x), d=x[1] - x[0])
|
|
405
|
+
ik3 = 1j * k**3
|
|
406
|
+
u_hat = np.fft.fft(u0)
|
|
407
|
+
for _ in range(steps):
|
|
408
|
+
u_hat = u_hat * np.exp(ik3 * dt / 2.0)
|
|
409
|
+
k1 = _ion_acoustic_kdv_rhs_hat(u_hat, k)
|
|
410
|
+
k2 = _ion_acoustic_kdv_rhs_hat(u_hat + dt / 2.0 * k1, k)
|
|
411
|
+
k3 = _ion_acoustic_kdv_rhs_hat(u_hat + dt / 2.0 * k2, k)
|
|
412
|
+
k4 = _ion_acoustic_kdv_rhs_hat(u_hat + dt * k3, k)
|
|
413
|
+
u_hat = u_hat + dt / 6.0 * (k1 + 2.0 * k2 + 2.0 * k3 + k4)
|
|
414
|
+
u_hat = u_hat * np.exp(ik3 * dt / 2.0)
|
|
415
|
+
return np.real(np.fft.ifft(u_hat))
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def alfven_wave_pulse_ic(x: np.ndarray, x0: float, width: float, amplitude: float) -> tuple:
|
|
419
|
+
"""Initial condition for a transverse Alfven-wave pulse launched from rest.
|
|
420
|
+
|
|
421
|
+
A Gaussian transverse-field pulse :math:`B_y(x,0)=B_1 e^{-[(x-x_0)/w]^2}`
|
|
422
|
+
with the transverse velocity perturbation initially zero -- a "plucked
|
|
423
|
+
string" initial condition. Because the linearized ideal-MHD Alfven-wave
|
|
424
|
+
equations (:func:`simulate_alfven_wave`) are the same non-dispersive wave
|
|
425
|
+
equation a string obeys, a disturbance released from rest splits exactly
|
|
426
|
+
in half and propagates as two identical, oppositely directed pulses at
|
|
427
|
+
:math:`\\pm v_A` -- exactly the field-line-plucking picture Alfven's
|
|
428
|
+
original 1942 analogy describes.
|
|
429
|
+
|
|
430
|
+
Parameters
|
|
431
|
+
----------
|
|
432
|
+
x : ndarray
|
|
433
|
+
Spatial grid (periodic).
|
|
434
|
+
x0 : float
|
|
435
|
+
Pulse center.
|
|
436
|
+
width : float
|
|
437
|
+
Gaussian pulse width.
|
|
438
|
+
amplitude : float
|
|
439
|
+
Peak transverse field perturbation :math:`B_1`.
|
|
440
|
+
|
|
441
|
+
Returns
|
|
442
|
+
-------
|
|
443
|
+
By0, vy0 : ndarray
|
|
444
|
+
Initial transverse magnetic field and velocity perturbations, same
|
|
445
|
+
shape as `x` (`vy0` identically zero).
|
|
446
|
+
|
|
447
|
+
See Also
|
|
448
|
+
--------
|
|
449
|
+
simulate_alfven_wave : Evolves this initial condition forward in time.
|
|
450
|
+
|
|
451
|
+
Examples
|
|
452
|
+
--------
|
|
453
|
+
>>> import numpy as np
|
|
454
|
+
>>> x = np.linspace(-10, 10, 64, endpoint=False)
|
|
455
|
+
>>> By0, vy0 = alfven_wave_pulse_ic(x, x0=0.0, width=1.0, amplitude=0.1)
|
|
456
|
+
>>> bool(np.all(vy0 == 0.0))
|
|
457
|
+
True
|
|
458
|
+
"""
|
|
459
|
+
By0 = amplitude * np.exp(-(((x - x0) / width) ** 2))
|
|
460
|
+
vy0 = np.zeros_like(x)
|
|
461
|
+
return By0, vy0
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def _alfven_rhs(By: np.ndarray, vy: np.ndarray, k: np.ndarray, B0: float, rho0: float, mu0: float) -> tuple:
|
|
465
|
+
dBy_dx = np.real(np.fft.ifft(1j * k * np.fft.fft(By)))
|
|
466
|
+
dvy_dx = np.real(np.fft.ifft(1j * k * np.fft.fft(vy)))
|
|
467
|
+
dBy_dt = B0 * dvy_dx
|
|
468
|
+
dvy_dt = (B0 / (mu0 * rho0)) * dBy_dx
|
|
469
|
+
return dBy_dt, dvy_dt
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
def simulate_alfven_wave(By0: np.ndarray, vy0: np.ndarray, x: np.ndarray, dt: float, steps: int, B0: float, rho0: float, mu0: float = 1.0) -> dict:
|
|
473
|
+
"""Time-step the linearized 1D ideal-MHD Alfven-wave equations with a pseudo-spectral RK4 scheme.
|
|
474
|
+
|
|
475
|
+
Advances the coupled transverse induction and momentum equations
|
|
476
|
+
|
|
477
|
+
.. math::
|
|
478
|
+
|
|
479
|
+
\\partial_t B_y = B_0\\,\\partial_x v_y, \\qquad
|
|
480
|
+
\\rho_0\\,\\partial_t v_y = \\frac{B_0}{\\mu_0}\\,\\partial_x B_y,
|
|
481
|
+
|
|
482
|
+
which combine into the non-dispersive wave equation
|
|
483
|
+
:math:`\\partial_t^2 B_y = v_A^2\\,\\partial_x^2 B_y` with
|
|
484
|
+
:math:`v_A=B_0/\\sqrt{\\mu_0\\rho_0}` (:func:`physicskit.plasma.mhd.alfven_speed`).
|
|
485
|
+
Spatial derivatives are evaluated exactly via FFT (as elsewhere in this
|
|
486
|
+
package's periodic-domain solvers) and advanced in time with classical
|
|
487
|
+
RK4; a uniform background field and density are assumed throughout
|
|
488
|
+
(linear, ideal, cold-background MHD -- no thermal pressure term enters
|
|
489
|
+
a purely transverse, incompressible perturbation like this one).
|
|
490
|
+
|
|
491
|
+
Unlike :func:`physicskit.plasma.mhd.alfven_speed` (SI units), this
|
|
492
|
+
solver defaults to normalized units (``mu0=1.0``, matching order-unity
|
|
493
|
+
`B0`/`rho0`) since with the true SI :math:`\\mu_0\\approx1.26\\times10^{-6}`
|
|
494
|
+
a Tesla-scale field gives an Alfven speed of order :math:`10^5`-:math:`10^6`
|
|
495
|
+
m/s, requiring correspondingly tiny time steps to satisfy the CFL bound
|
|
496
|
+
below; pass ``mu0=physicskit.plasma.mhd.MU0`` explicitly for SI-consistent
|
|
497
|
+
parameters and scale `dt` accordingly.
|
|
498
|
+
|
|
499
|
+
Parameters
|
|
500
|
+
----------
|
|
501
|
+
By0, vy0 : ndarray
|
|
502
|
+
Initial transverse field and velocity perturbations, e.g. from
|
|
503
|
+
:func:`alfven_wave_pulse_ic`.
|
|
504
|
+
x : ndarray
|
|
505
|
+
Uniformly spaced periodic spatial grid.
|
|
506
|
+
dt : float
|
|
507
|
+
Time step; the CFL condition :math:`v_A\\,dt \\le dx` should be
|
|
508
|
+
respected for the explicit RK4 stepping to remain stable.
|
|
509
|
+
steps : int
|
|
510
|
+
Number of RK4 steps to advance.
|
|
511
|
+
B0 : float
|
|
512
|
+
Background field magnitude.
|
|
513
|
+
rho0 : float
|
|
514
|
+
Background mass density.
|
|
515
|
+
mu0 : float, default=1.0
|
|
516
|
+
Vacuum permeability (normalized units by default; see above).
|
|
517
|
+
|
|
518
|
+
Returns
|
|
519
|
+
-------
|
|
520
|
+
dict
|
|
521
|
+
``{"By": final transverse field, "vy": final transverse velocity}``.
|
|
522
|
+
|
|
523
|
+
See Also
|
|
524
|
+
--------
|
|
525
|
+
alfven_wave_pulse_ic : Builds the initial condition consumed here.
|
|
526
|
+
physicskit.plasma.mhd.alfven_speed : The propagation speed this recovers.
|
|
527
|
+
|
|
528
|
+
Examples
|
|
529
|
+
--------
|
|
530
|
+
>>> import numpy as np
|
|
531
|
+
>>> x = np.linspace(-20, 20, 256, endpoint=False)
|
|
532
|
+
>>> By0, vy0 = alfven_wave_pulse_ic(x, x0=0.0, width=1.0, amplitude=0.1)
|
|
533
|
+
>>> result = simulate_alfven_wave(By0, vy0, x, dt=0.002, steps=2000, B0=1.0, rho0=1.0)
|
|
534
|
+
>>> result["By"].shape
|
|
535
|
+
(256,)
|
|
536
|
+
>>> bool(np.isfinite(result["By"]).all())
|
|
537
|
+
True
|
|
538
|
+
"""
|
|
539
|
+
k = 2.0 * np.pi * np.fft.fftfreq(len(x), d=x[1] - x[0])
|
|
540
|
+
By = np.array(By0, dtype=float, copy=True)
|
|
541
|
+
vy = np.array(vy0, dtype=float, copy=True)
|
|
542
|
+
for _ in range(steps):
|
|
543
|
+
k1B, k1v = _alfven_rhs(By, vy, k, B0, rho0, mu0)
|
|
544
|
+
k2B, k2v = _alfven_rhs(By + dt / 2 * k1B, vy + dt / 2 * k1v, k, B0, rho0, mu0)
|
|
545
|
+
k3B, k3v = _alfven_rhs(By + dt / 2 * k2B, vy + dt / 2 * k2v, k, B0, rho0, mu0)
|
|
546
|
+
k4B, k4v = _alfven_rhs(By + dt * k3B, vy + dt * k3v, k, B0, rho0, mu0)
|
|
547
|
+
By = By + dt / 6 * (k1B + 2 * k2B + 2 * k3B + k4B)
|
|
548
|
+
vy = vy + dt / 6 * (k1v + 2 * k2v + 2 * k3v + k4v)
|
|
549
|
+
return {"By": By, "vy": vy}
|