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,425 @@
|
|
|
1
|
+
"""Classic exact solutions of the viscous (Navier-Stokes) equations.
|
|
2
|
+
|
|
3
|
+
Four textbook problems simple enough to solve in closed form (or, for
|
|
4
|
+
Blasius, by reducing an entire boundary layer to a single ordinary
|
|
5
|
+
differential equation): plane Couette flow, plane Poiseuille flow, Stokes
|
|
6
|
+
drag on a sphere, and the Blasius laminar boundary layer. Each is a limit
|
|
7
|
+
where the full nonlinear Navier-Stokes equations collapse to something
|
|
8
|
+
tractable -- steady unidirectional shear flow (Couette, Poiseuille),
|
|
9
|
+
vanishing Reynolds number (Stokes), or a self-similar boundary layer
|
|
10
|
+
(Blasius) -- and each remains a standard benchmark for validating a general
|
|
11
|
+
solver, since it is one of the few cases where "the answer" is known exactly.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import numpy as np
|
|
17
|
+
from numba import njit
|
|
18
|
+
from numpy.typing import ArrayLike, NDArray
|
|
19
|
+
|
|
20
|
+
from physicskit.fluids.exceptions import InvalidParameterError
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"couette_flow_velocity",
|
|
24
|
+
"poiseuille_flow_velocity",
|
|
25
|
+
"poiseuille_flow_rate",
|
|
26
|
+
"stokes_drag",
|
|
27
|
+
"blasius_solve",
|
|
28
|
+
"blasius_boundary_layer_thickness",
|
|
29
|
+
"blasius_skin_friction_coefficient",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def couette_flow_velocity(y: ArrayLike, U_wall: float, h: float) -> NDArray[np.float64]:
|
|
34
|
+
"""Velocity profile of steady plane Couette flow.
|
|
35
|
+
|
|
36
|
+
The flow between two infinite parallel plates, the lower one at rest
|
|
37
|
+
and the upper one (at ``y = h``) moving at speed `U_wall`, with no
|
|
38
|
+
imposed pressure gradient. The steady Navier-Stokes equations reduce to
|
|
39
|
+
:math:`\\mu\\, d^2u/dy^2 = 0`, whose solution subject to no-slip at both
|
|
40
|
+
walls is the linear profile below -- shear stress
|
|
41
|
+
:math:`\\tau = \\mu\\,U_{wall}/h` is exactly uniform across the gap.
|
|
42
|
+
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
y : array_like of float
|
|
46
|
+
Height above the lower (stationary) plate, ``0 <= y <= h``.
|
|
47
|
+
U_wall : float
|
|
48
|
+
Speed of the upper, moving plate.
|
|
49
|
+
h : float
|
|
50
|
+
Gap between the plates.
|
|
51
|
+
|
|
52
|
+
Returns
|
|
53
|
+
-------
|
|
54
|
+
ndarray of float
|
|
55
|
+
Velocity :math:`u(y) = U_{wall}\\,y/h`.
|
|
56
|
+
|
|
57
|
+
Raises
|
|
58
|
+
------
|
|
59
|
+
InvalidParameterError
|
|
60
|
+
If `h` is not positive.
|
|
61
|
+
|
|
62
|
+
Examples
|
|
63
|
+
--------
|
|
64
|
+
>>> couette_flow_velocity(y=[0.0, 0.5, 1.0], U_wall=2.0, h=1.0)
|
|
65
|
+
array([0., 1., 2.])
|
|
66
|
+
"""
|
|
67
|
+
if h <= 0:
|
|
68
|
+
raise InvalidParameterError(f"h must be positive, got {h}")
|
|
69
|
+
y = np.asarray(y, dtype=np.float64)
|
|
70
|
+
return U_wall * y / h
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def poiseuille_flow_velocity(y: ArrayLike, dpdx: float, mu: float, h: float) -> NDArray[np.float64]:
|
|
74
|
+
"""Velocity profile of steady plane Poiseuille flow.
|
|
75
|
+
|
|
76
|
+
The flow between two stationary infinite parallel plates driven by a
|
|
77
|
+
constant imposed pressure gradient `dpdx`. The steady Navier-Stokes
|
|
78
|
+
equations reduce to :math:`\\mu\\,d^2u/dy^2 = dp/dx`, whose solution
|
|
79
|
+
subject to no-slip at both walls (``y=0`` and ``y=h``) is the parabolic
|
|
80
|
+
profile below, maximal at the channel centerline.
|
|
81
|
+
|
|
82
|
+
Parameters
|
|
83
|
+
----------
|
|
84
|
+
y : array_like of float
|
|
85
|
+
Height above the lower plate, ``0 <= y <= h``.
|
|
86
|
+
dpdx : float
|
|
87
|
+
Imposed pressure gradient (negative drives flow in ``+x``).
|
|
88
|
+
mu : float
|
|
89
|
+
Dynamic viscosity.
|
|
90
|
+
h : float
|
|
91
|
+
Gap between the plates.
|
|
92
|
+
|
|
93
|
+
Returns
|
|
94
|
+
-------
|
|
95
|
+
ndarray of float
|
|
96
|
+
Velocity :math:`u(y) = -\\frac{1}{2\\mu}\\frac{dp}{dx}\\,y\\,(h-y)`.
|
|
97
|
+
|
|
98
|
+
Raises
|
|
99
|
+
------
|
|
100
|
+
InvalidParameterError
|
|
101
|
+
If `mu` or `h` is not positive.
|
|
102
|
+
|
|
103
|
+
See Also
|
|
104
|
+
--------
|
|
105
|
+
poiseuille_flow_rate : The volumetric flow rate driven by this profile.
|
|
106
|
+
|
|
107
|
+
Examples
|
|
108
|
+
--------
|
|
109
|
+
>>> y = np.linspace(0, 1, 5)
|
|
110
|
+
>>> u = poiseuille_flow_velocity(y, dpdx=-8.0, mu=1.0, h=1.0)
|
|
111
|
+
>>> round(float(u[2]), 4) # peak at centerline
|
|
112
|
+
1.0
|
|
113
|
+
>>> bool(u[0] == 0.0 and u[-1] == 0.0) # no-slip at both walls
|
|
114
|
+
True
|
|
115
|
+
"""
|
|
116
|
+
if mu <= 0:
|
|
117
|
+
raise InvalidParameterError(f"mu must be positive, got {mu}")
|
|
118
|
+
if h <= 0:
|
|
119
|
+
raise InvalidParameterError(f"h must be positive, got {h}")
|
|
120
|
+
y = np.asarray(y, dtype=np.float64)
|
|
121
|
+
return -(1.0 / (2.0 * mu)) * dpdx * y * (h - y)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def poiseuille_flow_rate(dpdx: float, mu: float, h: float) -> float:
|
|
125
|
+
"""Volumetric flow rate per unit depth of plane Poiseuille flow.
|
|
126
|
+
|
|
127
|
+
The integral of :func:`poiseuille_flow_velocity` across the channel:
|
|
128
|
+
|
|
129
|
+
.. math::
|
|
130
|
+
|
|
131
|
+
Q = -\\frac{h^3}{12\\mu}\\frac{dp}{dx}
|
|
132
|
+
|
|
133
|
+
Parameters
|
|
134
|
+
----------
|
|
135
|
+
dpdx : float
|
|
136
|
+
Imposed pressure gradient.
|
|
137
|
+
mu : float
|
|
138
|
+
Dynamic viscosity.
|
|
139
|
+
h : float
|
|
140
|
+
Gap between the plates.
|
|
141
|
+
|
|
142
|
+
Returns
|
|
143
|
+
-------
|
|
144
|
+
float
|
|
145
|
+
Volumetric flow rate per unit depth, `Q`.
|
|
146
|
+
|
|
147
|
+
Raises
|
|
148
|
+
------
|
|
149
|
+
InvalidParameterError
|
|
150
|
+
If `mu` or `h` is not positive.
|
|
151
|
+
|
|
152
|
+
Examples
|
|
153
|
+
--------
|
|
154
|
+
>>> round(poiseuille_flow_rate(dpdx=-12.0, mu=1.0, h=1.0), 4)
|
|
155
|
+
1.0
|
|
156
|
+
"""
|
|
157
|
+
if mu <= 0:
|
|
158
|
+
raise InvalidParameterError(f"mu must be positive, got {mu}")
|
|
159
|
+
if h <= 0:
|
|
160
|
+
raise InvalidParameterError(f"h must be positive, got {h}")
|
|
161
|
+
return -(h**3 / (12.0 * mu)) * dpdx
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def stokes_drag(mu: float, radius: float, velocity: float) -> float:
|
|
165
|
+
"""Stokes' law: drag force on a sphere at low Reynolds number.
|
|
166
|
+
|
|
167
|
+
.. math::
|
|
168
|
+
|
|
169
|
+
F_D = 6\\pi\\mu R v
|
|
170
|
+
|
|
171
|
+
Valid in the creeping-flow limit :math:`Re = 2R|v|/\\nu \\ll 1`, where
|
|
172
|
+
the nonlinear advection term in Navier-Stokes is negligible next to
|
|
173
|
+
viscous diffusion, leaving the linear Stokes equations
|
|
174
|
+
:math:`\\mu\\nabla^2\\mathbf{u}=\\nabla p` -- George Stokes' 1851 exact
|
|
175
|
+
solution for uniform flow past a sphere.
|
|
176
|
+
|
|
177
|
+
Parameters
|
|
178
|
+
----------
|
|
179
|
+
mu : float
|
|
180
|
+
Dynamic viscosity.
|
|
181
|
+
radius : float
|
|
182
|
+
Sphere radius.
|
|
183
|
+
velocity : float
|
|
184
|
+
Relative speed between the sphere and the fluid far away.
|
|
185
|
+
|
|
186
|
+
Returns
|
|
187
|
+
-------
|
|
188
|
+
float
|
|
189
|
+
Drag force magnitude :math:`F_D`.
|
|
190
|
+
|
|
191
|
+
Raises
|
|
192
|
+
------
|
|
193
|
+
InvalidParameterError
|
|
194
|
+
If `mu` or `radius` is not positive.
|
|
195
|
+
|
|
196
|
+
Examples
|
|
197
|
+
--------
|
|
198
|
+
>>> round(stokes_drag(mu=1.0, radius=1.0, velocity=1.0), 4)
|
|
199
|
+
18.8496
|
|
200
|
+
"""
|
|
201
|
+
if mu <= 0:
|
|
202
|
+
raise InvalidParameterError(f"mu must be positive, got {mu}")
|
|
203
|
+
if radius <= 0:
|
|
204
|
+
raise InvalidParameterError(f"radius must be positive, got {radius}")
|
|
205
|
+
return 6.0 * np.pi * mu * radius * velocity
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@njit(cache=True)
|
|
209
|
+
def _blasius_rhs(state: NDArray[np.float64]) -> NDArray[np.float64]:
|
|
210
|
+
"""Blasius ODE as a first-order system: ``(f, f', f'')' = (f', f'', -f f''/2)``.
|
|
211
|
+
|
|
212
|
+
Parameters
|
|
213
|
+
----------
|
|
214
|
+
state : ndarray of float, shape (3,)
|
|
215
|
+
``(f, f', f'')`` at the current similarity coordinate `eta`.
|
|
216
|
+
|
|
217
|
+
Returns
|
|
218
|
+
-------
|
|
219
|
+
ndarray of float, shape (3,)
|
|
220
|
+
Derivative of `state` with respect to `eta`.
|
|
221
|
+
"""
|
|
222
|
+
f, fp, fpp = state[0], state[1], state[2]
|
|
223
|
+
out = np.empty(3)
|
|
224
|
+
out[0] = fp
|
|
225
|
+
out[1] = fpp
|
|
226
|
+
out[2] = -0.5 * f * fpp
|
|
227
|
+
return out
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
@njit(cache=True)
|
|
231
|
+
def _blasius_integrate(fpp0: float, eta_max: float, n_points: int) -> NDArray[np.float64]:
|
|
232
|
+
"""Integrate the Blasius ODE with RK4 from ``eta=0`` given a guessed ``f''(0)``.
|
|
233
|
+
|
|
234
|
+
Parameters
|
|
235
|
+
----------
|
|
236
|
+
fpp0 : float
|
|
237
|
+
Guessed shooting parameter :math:`f''(0)`.
|
|
238
|
+
eta_max : float
|
|
239
|
+
Similarity coordinate at which to stop integrating.
|
|
240
|
+
n_points : int
|
|
241
|
+
Number of output points (including ``eta=0``).
|
|
242
|
+
|
|
243
|
+
Returns
|
|
244
|
+
-------
|
|
245
|
+
ndarray of float, shape (n_points, 3)
|
|
246
|
+
``(f, f', f'')`` at each of `n_points` equally spaced `eta` in
|
|
247
|
+
``[0, eta_max]``.
|
|
248
|
+
"""
|
|
249
|
+
states = np.empty((n_points, 3))
|
|
250
|
+
state = np.array([0.0, 0.0, fpp0])
|
|
251
|
+
states[0] = state
|
|
252
|
+
deta = eta_max / (n_points - 1)
|
|
253
|
+
for i in range(n_points - 1):
|
|
254
|
+
k1 = _blasius_rhs(state)
|
|
255
|
+
k2 = _blasius_rhs(state + 0.5 * deta * k1)
|
|
256
|
+
k3 = _blasius_rhs(state + 0.5 * deta * k2)
|
|
257
|
+
k4 = _blasius_rhs(state + deta * k3)
|
|
258
|
+
state = state + (deta / 6.0) * (k1 + 2.0 * k2 + 2.0 * k3 + k4)
|
|
259
|
+
states[i + 1] = state
|
|
260
|
+
return states
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def blasius_solve(eta_max: float = 10.0, n_points: int = 2001, tol: float = 1e-10, max_iter: int = 100) -> dict[str, NDArray[np.float64]]:
|
|
264
|
+
"""Solve the Blasius laminar boundary-layer equation by shooting.
|
|
265
|
+
|
|
266
|
+
The Blasius similarity reduction of the steady, 2D, zero-pressure-gradient
|
|
267
|
+
boundary-layer equations collapses them to the single third-order ODE
|
|
268
|
+
|
|
269
|
+
.. math::
|
|
270
|
+
|
|
271
|
+
f''' + \\tfrac{1}{2} f f'' = 0, \\qquad
|
|
272
|
+
f(0) = f'(0) = 0, \\qquad f'(\\infty) = 1,
|
|
273
|
+
|
|
274
|
+
for the dimensionless streamfunction :math:`f(\\eta)` of the similarity
|
|
275
|
+
variable :math:`\\eta = y\\sqrt{U_\\infty/(\\nu x)}`; the streamwise
|
|
276
|
+
velocity is :math:`u/U_\\infty = f'(\\eta)`. Since :math:`f''(0)` (rather
|
|
277
|
+
than the far-field condition) is the free parameter needed to start an
|
|
278
|
+
initial-value integration, this is a two-point boundary value problem
|
|
279
|
+
solved here by shooting: bisect on :math:`f''(0)` until the resulting
|
|
280
|
+
:func:`_blasius_integrate` solution satisfies :math:`f'(\\eta_{max})
|
|
281
|
+
\\approx 1`.
|
|
282
|
+
|
|
283
|
+
Parameters
|
|
284
|
+
----------
|
|
285
|
+
eta_max : float, default 10.0
|
|
286
|
+
Similarity coordinate treated as "infinity"; large enough that
|
|
287
|
+
:math:`f'` has converged to 1 to within `tol`.
|
|
288
|
+
n_points : int, default 2001
|
|
289
|
+
Number of output points between ``eta=0`` and `eta_max`.
|
|
290
|
+
tol : float, default 1e-10
|
|
291
|
+
Bisection tolerance on :math:`f'(\\eta_{max}) - 1`.
|
|
292
|
+
max_iter : int, default 100
|
|
293
|
+
Maximum number of bisection iterations.
|
|
294
|
+
|
|
295
|
+
Returns
|
|
296
|
+
-------
|
|
297
|
+
dict
|
|
298
|
+
``{"eta": ..., "f": ..., "fp": ..., "fpp": ...}``, each an array of
|
|
299
|
+
length `n_points`. ``fpp[0]`` is the classic Blasius constant,
|
|
300
|
+
:math:`f''(0) \\approx 0.332`.
|
|
301
|
+
|
|
302
|
+
Examples
|
|
303
|
+
--------
|
|
304
|
+
>>> result = blasius_solve()
|
|
305
|
+
>>> round(float(result["fpp"][0]), 3)
|
|
306
|
+
0.332
|
|
307
|
+
>>> round(float(result["fp"][-1]), 4)
|
|
308
|
+
1.0
|
|
309
|
+
"""
|
|
310
|
+
lo, hi = 0.1, 1.0
|
|
311
|
+
solution = _blasius_integrate(hi, eta_max, n_points)
|
|
312
|
+
while solution[-1, 1] < 1.0:
|
|
313
|
+
hi *= 2.0
|
|
314
|
+
solution = _blasius_integrate(hi, eta_max, n_points)
|
|
315
|
+
|
|
316
|
+
for _ in range(max_iter):
|
|
317
|
+
mid = 0.5 * (lo + hi)
|
|
318
|
+
solution = _blasius_integrate(mid, eta_max, n_points)
|
|
319
|
+
residual = solution[-1, 1] - 1.0
|
|
320
|
+
if abs(residual) < tol:
|
|
321
|
+
break
|
|
322
|
+
if residual > 0:
|
|
323
|
+
hi = mid
|
|
324
|
+
else:
|
|
325
|
+
lo = mid
|
|
326
|
+
|
|
327
|
+
eta = np.linspace(0.0, eta_max, n_points)
|
|
328
|
+
return {"eta": eta, "f": solution[:, 0], "fp": solution[:, 1], "fpp": solution[:, 2]}
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def blasius_boundary_layer_thickness(x: ArrayLike, U_inf: float, nu: float, eta_99: float = 4.91) -> NDArray[np.float64]:
|
|
332
|
+
"""Blasius laminar boundary-layer thickness :math:`\\delta_{99}(x)`.
|
|
333
|
+
|
|
334
|
+
The height at which :math:`u/U_\\infty` first reaches 0.99 occurs, in
|
|
335
|
+
similarity coordinates, at :math:`\\eta \\approx 4.91` (a property of
|
|
336
|
+
the Blasius profile from :func:`blasius_solve`, not re-derived here), so
|
|
337
|
+
|
|
338
|
+
.. math::
|
|
339
|
+
|
|
340
|
+
\\delta_{99}(x) = \\eta_{99}\\sqrt{\\frac{\\nu x}{U_\\infty}}
|
|
341
|
+
\\propto \\sqrt{x}.
|
|
342
|
+
|
|
343
|
+
The boundary layer's parabolic-looking growth with downstream distance
|
|
344
|
+
-- much slower than the layer's own streamwise extent -- is exactly the
|
|
345
|
+
"thin layer" assumption Ludwig Prandtl's 1904 boundary-layer theory
|
|
346
|
+
used to simplify Navier-Stokes into the boundary-layer equations Blasius
|
|
347
|
+
then solved.
|
|
348
|
+
|
|
349
|
+
Parameters
|
|
350
|
+
----------
|
|
351
|
+
x : array_like of float
|
|
352
|
+
Downstream distance from the leading edge; must be positive.
|
|
353
|
+
U_inf : float
|
|
354
|
+
Free-stream speed.
|
|
355
|
+
nu : float
|
|
356
|
+
Kinematic viscosity.
|
|
357
|
+
eta_99 : float, default 4.91
|
|
358
|
+
Similarity coordinate at which :math:`f'(\\eta)=0.99`.
|
|
359
|
+
|
|
360
|
+
Returns
|
|
361
|
+
-------
|
|
362
|
+
ndarray of float
|
|
363
|
+
Boundary-layer thickness :math:`\\delta_{99}(x)`.
|
|
364
|
+
|
|
365
|
+
Raises
|
|
366
|
+
------
|
|
367
|
+
InvalidParameterError
|
|
368
|
+
If `U_inf` or `nu` is not positive, or any entry of `x` is not positive.
|
|
369
|
+
|
|
370
|
+
Examples
|
|
371
|
+
--------
|
|
372
|
+
>>> round(float(blasius_boundary_layer_thickness(x=1.0, U_inf=1.0, nu=1e-4)), 4)
|
|
373
|
+
0.0491
|
|
374
|
+
"""
|
|
375
|
+
if U_inf <= 0:
|
|
376
|
+
raise InvalidParameterError(f"U_inf must be positive, got {U_inf}")
|
|
377
|
+
if nu <= 0:
|
|
378
|
+
raise InvalidParameterError(f"nu must be positive, got {nu}")
|
|
379
|
+
x = np.asarray(x, dtype=np.float64)
|
|
380
|
+
if np.any(x <= 0):
|
|
381
|
+
raise InvalidParameterError("x must be positive (measured from the leading edge)")
|
|
382
|
+
return eta_99 * np.sqrt(nu * x / U_inf)
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
def blasius_skin_friction_coefficient(reynolds_x: ArrayLike, fpp0: float = 0.33206) -> NDArray[np.float64]:
|
|
386
|
+
"""Local skin-friction coefficient of the Blasius boundary layer.
|
|
387
|
+
|
|
388
|
+
The wall shear stress :math:`\\tau_w = \\mu U_\\infty f''(0)\\sqrt{U_\\infty/(\\nu x)}`
|
|
389
|
+
gives a local skin-friction coefficient
|
|
390
|
+
|
|
391
|
+
.. math::
|
|
392
|
+
|
|
393
|
+
c_f(x) = \\frac{\\tau_w}{\\tfrac{1}{2}\\rho U_\\infty^2}
|
|
394
|
+
= \\frac{2 f''(0)}{\\sqrt{Re_x}}, \\qquad
|
|
395
|
+
Re_x = \\frac{U_\\infty x}{\\nu},
|
|
396
|
+
|
|
397
|
+
the classic :math:`c_f \\propto Re_x^{-1/2}` scaling of a laminar
|
|
398
|
+
boundary layer.
|
|
399
|
+
|
|
400
|
+
Parameters
|
|
401
|
+
----------
|
|
402
|
+
reynolds_x : array_like of float
|
|
403
|
+
Local Reynolds number :math:`Re_x = U_\\infty x/\\nu`; must be positive.
|
|
404
|
+
fpp0 : float, default 0.33206
|
|
405
|
+
The Blasius constant :math:`f''(0)`, as returned by :func:`blasius_solve`.
|
|
406
|
+
|
|
407
|
+
Returns
|
|
408
|
+
-------
|
|
409
|
+
ndarray of float
|
|
410
|
+
Local skin-friction coefficient :math:`c_f(x)`.
|
|
411
|
+
|
|
412
|
+
Raises
|
|
413
|
+
------
|
|
414
|
+
InvalidParameterError
|
|
415
|
+
If any entry of `reynolds_x` is not positive.
|
|
416
|
+
|
|
417
|
+
Examples
|
|
418
|
+
--------
|
|
419
|
+
>>> round(float(blasius_skin_friction_coefficient(reynolds_x=1e4)), 5)
|
|
420
|
+
0.00664
|
|
421
|
+
"""
|
|
422
|
+
reynolds_x = np.asarray(reynolds_x, dtype=np.float64)
|
|
423
|
+
if np.any(reynolds_x <= 0):
|
|
424
|
+
raise InvalidParameterError("reynolds_x must be positive")
|
|
425
|
+
return 2.0 * fpp0 / np.sqrt(reynolds_x)
|