naturedynamics 1.1__tar.gz
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.
- naturedynamics-1.1/LICENSE +21 -0
- naturedynamics-1.1/PKG-INFO +88 -0
- naturedynamics-1.1/README.md +49 -0
- naturedynamics-1.1/naturedynamics/__init__.py +5 -0
- naturedynamics-1.1/naturedynamics/applications/__init__.py +0 -0
- naturedynamics-1.1/naturedynamics/applications/energy.py +124 -0
- naturedynamics-1.1/naturedynamics/applications/engineering.py +100 -0
- naturedynamics-1.1/naturedynamics/applications/environmental.py +111 -0
- naturedynamics-1.1/naturedynamics/applications/medical.py +70 -0
- naturedynamics-1.1/naturedynamics/astrophysics/__init__.py +0 -0
- naturedynamics-1.1/naturedynamics/astrophysics/atmospheric.py +77 -0
- naturedynamics-1.1/naturedynamics/astrophysics/cosmology.py +284 -0
- naturedynamics-1.1/naturedynamics/astrophysics/galactic.py +212 -0
- naturedynamics-1.1/naturedynamics/astrophysics/magnetism.py +64 -0
- naturedynamics-1.1/naturedynamics/astrophysics/photometry.py +184 -0
- naturedynamics-1.1/naturedynamics/astrophysics/planetary.py +257 -0
- naturedynamics-1.1/naturedynamics/astrophysics/stellar.py +298 -0
- naturedynamics-1.1/naturedynamics/astrophysics/tidal.py +97 -0
- naturedynamics-1.1/naturedynamics/biophysics/__init__.py +0 -0
- naturedynamics-1.1/naturedynamics/biophysics/biomechanics.py +60 -0
- naturedynamics-1.1/naturedynamics/biophysics/diffusion.py +51 -0
- naturedynamics-1.1/naturedynamics/biophysics/membrane.py +51 -0
- naturedynamics-1.1/naturedynamics/biophysics/neuroscience.py +58 -0
- naturedynamics-1.1/naturedynamics/biophysics/photosynthesis.py +86 -0
- naturedynamics-1.1/naturedynamics/computational/__init__.py +0 -0
- naturedynamics-1.1/naturedynamics/computational/finite_elements.py +158 -0
- naturedynamics-1.1/naturedynamics/computational/monte_carlo.py +307 -0
- naturedynamics-1.1/naturedynamics/computational/numerical_methods.py +198 -0
- naturedynamics-1.1/naturedynamics/computational/optimization.py +408 -0
- naturedynamics-1.1/naturedynamics/constants.py +641 -0
- naturedynamics-1.1/naturedynamics/data/CIE_CMF.py +408 -0
- naturedynamics-1.1/naturedynamics/data/__init__.py +0 -0
- naturedynamics-1.1/naturedynamics/data/materials/__init__.py +0 -0
- naturedynamics-1.1/naturedynamics/data/materials/materials.py +225 -0
- naturedynamics-1.1/naturedynamics/data/spectroscopic_data/__init__.py +1 -0
- naturedynamics-1.1/naturedynamics/data/spectroscopic_data/spectra.py +254 -0
- naturedynamics-1.1/naturedynamics/electromagnetism/__init__.py +48 -0
- naturedynamics-1.1/naturedynamics/electromagnetism/circuits.py +315 -0
- naturedynamics-1.1/naturedynamics/electromagnetism/electrostatics.py +201 -0
- naturedynamics-1.1/naturedynamics/electromagnetism/magnetostatics.py +239 -0
- naturedynamics-1.1/naturedynamics/electromagnetism/maxwell.py +281 -0
- naturedynamics-1.1/naturedynamics/electromagnetism/optics.py +138 -0
- naturedynamics-1.1/naturedynamics/electromagnetism/waves.py +294 -0
- naturedynamics-1.1/naturedynamics/experimental/__init__.py +0 -0
- naturedynamics-1.1/naturedynamics/experimental/data_analysis.py +179 -0
- naturedynamics-1.1/naturedynamics/experimental/error_analysis.py +58 -0
- naturedynamics-1.1/naturedynamics/experimental/instrumentation.py +52 -0
- naturedynamics-1.1/naturedynamics/experimental/measurement.py +35 -0
- naturedynamics-1.1/naturedynamics/laws/__init__.py +1 -0
- naturedynamics-1.1/naturedynamics/laws/conservation.py +57 -0
- naturedynamics-1.1/naturedynamics/laws/electromagnetic.py +102 -0
- naturedynamics-1.1/naturedynamics/laws/momentum.py +33 -0
- naturedynamics-1.1/naturedynamics/laws/newtons_laws.py +80 -0
- naturedynamics-1.1/naturedynamics/laws/work_energy.py +51 -0
- naturedynamics-1.1/naturedynamics/mathematical/__init__.py +0 -0
- naturedynamics-1.1/naturedynamics/mathematical/complex_analysis.py +45 -0
- naturedynamics-1.1/naturedynamics/mathematical/differential_equations.py +182 -0
- naturedynamics-1.1/naturedynamics/mathematical/group_theory.py +133 -0
- naturedynamics-1.1/naturedynamics/mathematical/mathematical_neuroscience.py +74 -0
- naturedynamics-1.1/naturedynamics/mathematical/special_functions.py +16 -0
- naturedynamics-1.1/naturedynamics/mathematical/tensor_calculus.py +134 -0
- naturedynamics-1.1/naturedynamics/mechanics/__init__.py +1 -0
- naturedynamics-1.1/naturedynamics/mechanics/continuum.py +165 -0
- naturedynamics-1.1/naturedynamics/mechanics/dynamics.py +46 -0
- naturedynamics-1.1/naturedynamics/mechanics/fluid_mechanics.py +54 -0
- naturedynamics-1.1/naturedynamics/mechanics/kinematics.py +58 -0
- naturedynamics-1.1/naturedynamics/mechanics/lagrangian.py +164 -0
- naturedynamics-1.1/naturedynamics/mechanics/rotational_mechanics.py +65 -0
- naturedynamics-1.1/naturedynamics/mechanics/sound.py +18 -0
- naturedynamics-1.1/naturedynamics/mechanics/statics.py +147 -0
- naturedynamics-1.1/naturedynamics/mechanics/stress_strain.py +196 -0
- naturedynamics-1.1/naturedynamics/nuclear/__init__.py +1 -0
- naturedynamics-1.1/naturedynamics/nuclear/binding_energy.py +261 -0
- naturedynamics-1.1/naturedynamics/nuclear/decay.py +261 -0
- naturedynamics-1.1/naturedynamics/nuclear/fission_fusion.py +302 -0
- naturedynamics-1.1/naturedynamics/nuclear/particles.py +258 -0
- naturedynamics-1.1/naturedynamics/nuclear/reactions.py +217 -0
- naturedynamics-1.1/naturedynamics/oscillations/__init__.py +1 -0
- naturedynamics-1.1/naturedynamics/oscillations/acoustics.py +100 -0
- naturedynamics-1.1/naturedynamics/oscillations/coupled_oscillators.py +94 -0
- naturedynamics-1.1/naturedynamics/oscillations/shm.py +100 -0
- naturedynamics-1.1/naturedynamics/oscillations/vibrations.py +118 -0
- naturedynamics-1.1/naturedynamics/oscillations/wave_oscillation.py +41 -0
- naturedynamics-1.1/naturedynamics/plasma/__init__.py +0 -0
- naturedynamics-1.1/naturedynamics/plasma/basic.py +35 -0
- naturedynamics-1.1/naturedynamics/plasma/kinetic.py +42 -0
- naturedynamics-1.1/naturedynamics/plasma/magnetohydrodynamics.py +52 -0
- naturedynamics-1.1/naturedynamics/plasma/waves.py +61 -0
- naturedynamics-1.1/naturedynamics/quantum/__init__.py +1 -0
- naturedynamics-1.1/naturedynamics/quantum/harmonic_oscillator.py +173 -0
- naturedynamics-1.1/naturedynamics/quantum/hydrogen_atom.py +50 -0
- naturedynamics-1.1/naturedynamics/quantum/operators.py +175 -0
- naturedynamics-1.1/naturedynamics/quantum/perturbation.py +94 -0
- naturedynamics-1.1/naturedynamics/quantum/spin.py +32 -0
- naturedynamics-1.1/naturedynamics/quantum/statistics.py +119 -0
- naturedynamics-1.1/naturedynamics/quantum/tunneling.py +30 -0
- naturedynamics-1.1/naturedynamics/quantum/wave_functions.py +173 -0
- naturedynamics-1.1/naturedynamics/relativity/__init__.py +0 -0
- naturedynamics-1.1/naturedynamics/relativity/cosmology.py +53 -0
- naturedynamics-1.1/naturedynamics/relativity/general.py +37 -0
- naturedynamics-1.1/naturedynamics/relativity/spacetime.py +45 -0
- naturedynamics-1.1/naturedynamics/relativity/special.py +30 -0
- naturedynamics-1.1/naturedynamics/solidstate/__init__.py +0 -0
- naturedynamics-1.1/naturedynamics/solidstate/crystal_structure.py +99 -0
- naturedynamics-1.1/naturedynamics/solidstate/electronic.py +47 -0
- naturedynamics-1.1/naturedynamics/solidstate/magnetic.py +50 -0
- naturedynamics-1.1/naturedynamics/solidstate/phonons.py +45 -0
- naturedynamics-1.1/naturedynamics/solidstate/superconductivity.py +53 -0
- naturedynamics-1.1/naturedynamics/solutions/__init__.py +1 -0
- naturedynamics-1.1/naturedynamics/solutions/atomic.py +65 -0
- naturedynamics-1.1/naturedynamics/solutions/field_theory.py +207 -0
- naturedynamics-1.1/naturedynamics/solutions/molecular.py +110 -0
- naturedynamics-1.1/naturedynamics/solutions/operators.py +216 -0
- naturedynamics-1.1/naturedynamics/solutions/statistical.py +188 -0
- naturedynamics-1.1/naturedynamics/statistical_mechanics/__init__.py +1 -0
- naturedynamics-1.1/naturedynamics/statistical_mechanics/critical_phenomena.py +48 -0
- naturedynamics-1.1/naturedynamics/statistical_mechanics/distributions.py +107 -0
- naturedynamics-1.1/naturedynamics/statistical_mechanics/partition_functions.py +121 -0
- naturedynamics-1.1/naturedynamics/statistical_mechanics/quantum_statistics.py +44 -0
- naturedynamics-1.1/naturedynamics/thermodynamics/__init__.py +1 -0
- naturedynamics-1.1/naturedynamics/thermodynamics/heat_engines.py +146 -0
- naturedynamics-1.1/naturedynamics/thermodynamics/heat_transfer.py +147 -0
- naturedynamics-1.1/naturedynamics/thermodynamics/laws.py +168 -0
- naturedynamics-1.1/naturedynamics/thermodynamics/phase_transitions.py +123 -0
- naturedynamics-1.1/naturedynamics/tools/__init__.py +0 -0
- naturedynamics-1.1/naturedynamics/tools/calculators.py +26 -0
- naturedynamics-1.1/naturedynamics/tools/exporters.py +35 -0
- naturedynamics-1.1/naturedynamics/tools/simulators.py +133 -0
- naturedynamics-1.1/naturedynamics/tools/visualizers.py +154 -0
- naturedynamics-1.1/naturedynamics/utils/__init__.py +1 -0
- naturedynamics-1.1/naturedynamics/utils/conversions.py +396 -0
- naturedynamics-1.1/naturedynamics/utils/decorators.py +152 -0
- naturedynamics-1.1/naturedynamics/utils/plotting.py +303 -0
- naturedynamics-1.1/naturedynamics/utils/units.py +319 -0
- naturedynamics-1.1/naturedynamics/utils/validators.py +57 -0
- naturedynamics-1.1/naturedynamics.egg-info/PKG-INFO +88 -0
- naturedynamics-1.1/naturedynamics.egg-info/SOURCES.txt +140 -0
- naturedynamics-1.1/naturedynamics.egg-info/dependency_links.txt +1 -0
- naturedynamics-1.1/naturedynamics.egg-info/requires.txt +13 -0
- naturedynamics-1.1/naturedynamics.egg-info/top_level.txt +1 -0
- naturedynamics-1.1/pyproject.toml +66 -0
- naturedynamics-1.1/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Shaikh Umer
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: naturedynamics
|
|
3
|
+
Version: 1.1
|
|
4
|
+
Summary: A comprehensive physics library providing constants, equations, and formulas
|
|
5
|
+
Author-email: Fabian Schober <reach@fabianschober.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/schobernoise/naturedynamics
|
|
8
|
+
Project-URL: Repository, https://github.com/schobernoise/naturedynamics
|
|
9
|
+
Project-URL: Issues, https://github.com/schobernoise/naturedynamics/issues
|
|
10
|
+
Keywords: physics,science,constants,equations,mechanics,quantum
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Intended Audience :: Education
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Operating System :: OS Independent
|
|
23
|
+
Requires-Python: >=3.8
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: numpy>=1.19.0
|
|
27
|
+
Requires-Dist: scipy>=1.7.0
|
|
28
|
+
Requires-Dist: matplotlib>=3.3.0
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-cov>=2.10; extra == "dev"
|
|
32
|
+
Requires-Dist: black>=21.0; extra == "dev"
|
|
33
|
+
Requires-Dist: flake8>=3.8; extra == "dev"
|
|
34
|
+
Requires-Dist: mypy>=0.812; extra == "dev"
|
|
35
|
+
Requires-Dist: build>=0.7; extra == "dev"
|
|
36
|
+
Requires-Dist: twine>=3.4; extra == "dev"
|
|
37
|
+
Requires-Dist: wheel>=0.36; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# naturedynamics — A Comprehensive Physics Library in Python
|
|
41
|
+
|
|
42
|
+
**naturedynamics** is a Python library that offers an extensive collection of physical constants, equations, and formulas. It is a fork of https://github.com/reumer06/fphysics. @reumer06 did an amazing job in compiling an exhaustive collection of laws and formulas. This was exactly what I envisioned too, so I am very grateful to build on that and extend it in all kind of directions.
|
|
43
|
+
|
|
44
|
+
## Key Features
|
|
45
|
+
|
|
46
|
+
### Constants Database
|
|
47
|
+
Includes essential physical constants — SI base units, quantum constants, astronomical parameters, and more.
|
|
48
|
+
|
|
49
|
+
### Modular Formula Collections
|
|
50
|
+
Separate modules for mechanics, thermodynamics, electromagnetism, atomic physics, nuclear physics, relativity, statistical mechanics, and beyond.
|
|
51
|
+
|
|
52
|
+
### Unit Conversion
|
|
53
|
+
Convert seamlessly between SI, CGS, and natural units.
|
|
54
|
+
|
|
55
|
+
### Built for Learning and Worldbuilding
|
|
56
|
+
Perfect for integration into scientific calculators, simulations and teaching aids.
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
## Quick Start
|
|
61
|
+
```python
|
|
62
|
+
import naturedynamics as nd
|
|
63
|
+
from naturedynamics.relativity.general import schwarzschild_radius
|
|
64
|
+
from naturedynamics.thermodynamics.heat_engines import carnot_efficiency
|
|
65
|
+
|
|
66
|
+
# Access fundamental constants
|
|
67
|
+
print(nd.constants.SPEED_OF_LIGHT)
|
|
68
|
+
|
|
69
|
+
# Calculate Schwarzschild radius
|
|
70
|
+
print(schwarzschild_radius(10))
|
|
71
|
+
|
|
72
|
+
#Calulate the Carnot Efficiency
|
|
73
|
+
print(carnot_efficiency(500, 300))
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Contributing
|
|
77
|
+
|
|
78
|
+
I welcome all contributions — from adding new formulas to refining documentation.
|
|
79
|
+
|
|
80
|
+
1. **Fork** the repository
|
|
81
|
+
2. **Create** a feature branch
|
|
82
|
+
3. **Submit** a pull request
|
|
83
|
+
4. **Report** issues or suggest enhancements
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# naturedynamics — A Comprehensive Physics Library in Python
|
|
2
|
+
|
|
3
|
+
**naturedynamics** is a Python library that offers an extensive collection of physical constants, equations, and formulas. It is a fork of https://github.com/reumer06/fphysics. @reumer06 did an amazing job in compiling an exhaustive collection of laws and formulas. This was exactly what I envisioned too, so I am very grateful to build on that and extend it in all kind of directions.
|
|
4
|
+
|
|
5
|
+
## Key Features
|
|
6
|
+
|
|
7
|
+
### Constants Database
|
|
8
|
+
Includes essential physical constants — SI base units, quantum constants, astronomical parameters, and more.
|
|
9
|
+
|
|
10
|
+
### Modular Formula Collections
|
|
11
|
+
Separate modules for mechanics, thermodynamics, electromagnetism, atomic physics, nuclear physics, relativity, statistical mechanics, and beyond.
|
|
12
|
+
|
|
13
|
+
### Unit Conversion
|
|
14
|
+
Convert seamlessly between SI, CGS, and natural units.
|
|
15
|
+
|
|
16
|
+
### Built for Learning and Worldbuilding
|
|
17
|
+
Perfect for integration into scientific calculators, simulations and teaching aids.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
```python
|
|
23
|
+
import naturedynamics as nd
|
|
24
|
+
from naturedynamics.relativity.general import schwarzschild_radius
|
|
25
|
+
from naturedynamics.thermodynamics.heat_engines import carnot_efficiency
|
|
26
|
+
|
|
27
|
+
# Access fundamental constants
|
|
28
|
+
print(nd.constants.SPEED_OF_LIGHT)
|
|
29
|
+
|
|
30
|
+
# Calculate Schwarzschild radius
|
|
31
|
+
print(schwarzschild_radius(10))
|
|
32
|
+
|
|
33
|
+
#Calulate the Carnot Efficiency
|
|
34
|
+
print(carnot_efficiency(500, 300))
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Contributing
|
|
38
|
+
|
|
39
|
+
I welcome all contributions — from adding new formulas to refining documentation.
|
|
40
|
+
|
|
41
|
+
1. **Fork** the repository
|
|
42
|
+
2. **Create** a feature branch
|
|
43
|
+
3. **Submit** a pull request
|
|
44
|
+
4. **Report** issues or suggest enhancements
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
## License
|
|
48
|
+
|
|
49
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
File without changes
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import math
|
|
2
|
+
from ..constants import *
|
|
3
|
+
|
|
4
|
+
def solar_cell_efficiency(power_out, solar_irradiance, cell_area):
|
|
5
|
+
"""Solar cell efficiency"""
|
|
6
|
+
power_in = solar_irradiance * cell_area
|
|
7
|
+
return power_out / power_in
|
|
8
|
+
|
|
9
|
+
def photovoltaic_current(photon_flux, quantum_efficiency, charge=ELEMENTARY_CHARGE):
|
|
10
|
+
"""Photovoltaic current calculation"""
|
|
11
|
+
return photon_flux * quantum_efficiency * charge
|
|
12
|
+
|
|
13
|
+
def carnot_efficiency(hot_temp, cold_temp):
|
|
14
|
+
"""Carnot cycle efficiency"""
|
|
15
|
+
return 1 - cold_temp / hot_temp
|
|
16
|
+
|
|
17
|
+
def wind_power(air_density, swept_area, wind_speed, power_coefficient=0.4):
|
|
18
|
+
"""Wind turbine power output"""
|
|
19
|
+
return 0.5 * air_density * swept_area * wind_speed**3 * power_coefficient
|
|
20
|
+
|
|
21
|
+
def hydroelectric_power(flow_rate, head, efficiency=0.9):
|
|
22
|
+
"""Hydroelectric power calculation"""
|
|
23
|
+
return flow_rate * WATER_DENSITY * EARTH_GRAVITY * head * efficiency
|
|
24
|
+
|
|
25
|
+
def fuel_cell_voltage(gibbs_free_energy, electrons_transferred=2):
|
|
26
|
+
"""Fuel cell theoretical voltage"""
|
|
27
|
+
return -gibbs_free_energy / (electrons_transferred * ELEMENTARY_CHARGE)
|
|
28
|
+
|
|
29
|
+
def battery_energy_density(voltage, capacity, mass):
|
|
30
|
+
"""Battery energy density"""
|
|
31
|
+
energy = voltage * capacity * 3600
|
|
32
|
+
return energy / mass
|
|
33
|
+
|
|
34
|
+
def thermal_conductivity_insulation(heat_flux, thickness, temperature_diff):
|
|
35
|
+
"""Thermal conductivity from insulation performance"""
|
|
36
|
+
return heat_flux * thickness / temperature_diff
|
|
37
|
+
|
|
38
|
+
def heat_pump_cop(heat_delivered, work_input):
|
|
39
|
+
"""Heat pump coefficient of performance"""
|
|
40
|
+
return heat_delivered / work_input
|
|
41
|
+
|
|
42
|
+
def stirling_engine_power(pressure_amplitude, volume_amplitude, frequency):
|
|
43
|
+
"""Stirling engine power approximation"""
|
|
44
|
+
return pressure_amplitude * volume_amplitude * frequency
|
|
45
|
+
|
|
46
|
+
def nuclear_binding_energy(mass_number, binding_energy_per_nucleon=8.5):
|
|
47
|
+
"""Nuclear binding energy"""
|
|
48
|
+
return mass_number * binding_energy_per_nucleon * ELECTRON_VOLT * 1e6
|
|
49
|
+
|
|
50
|
+
def fission_energy_release(fissile_mass):
|
|
51
|
+
"""Energy released in nuclear fission"""
|
|
52
|
+
energy_per_fission = 200e6 * ELECTRON_VOLT
|
|
53
|
+
nuclei_per_gram = AVOGADRO_NUMBER / 235
|
|
54
|
+
return fissile_mass * nuclei_per_gram * energy_per_fission
|
|
55
|
+
|
|
56
|
+
def fusion_energy_release(fuel_mass, q_value=17.6e6):
|
|
57
|
+
"""Energy released in nuclear fusion"""
|
|
58
|
+
return fuel_mass * q_value * ELECTRON_VOLT / (4 * ATOMIC_MASS_UNIT)
|
|
59
|
+
|
|
60
|
+
def blackbody_power_density(temperature):
|
|
61
|
+
"""Blackbody power density"""
|
|
62
|
+
return STEFAN_BOLTZMANN_CONSTANT * temperature**4
|
|
63
|
+
|
|
64
|
+
def wien_peak_wavelength(temperature):
|
|
65
|
+
"""Wien's displacement law"""
|
|
66
|
+
return WIEN_DISPLACEMENT_CONSTANT / temperature
|
|
67
|
+
|
|
68
|
+
def photon_energy(wavelength):
|
|
69
|
+
"""Photon energy from wavelength"""
|
|
70
|
+
return PLANCK_CONSTANT * SPEED_OF_LIGHT / wavelength
|
|
71
|
+
|
|
72
|
+
def solar_constant_distance(distance_au=1.0):
|
|
73
|
+
"""Solar constant at given distance"""
|
|
74
|
+
return SOLAR_LUMINOSITY / (4 * PI * (distance_au * ASTRONOMICAL_UNIT)**2)
|
|
75
|
+
|
|
76
|
+
def geothermal_gradient_power(gradient, area, thermal_conductivity):
|
|
77
|
+
"""Geothermal power from temperature gradient"""
|
|
78
|
+
return gradient * area * thermal_conductivity
|
|
79
|
+
|
|
80
|
+
def piezoelectric_power(force, displacement, coupling_coefficient):
|
|
81
|
+
"""Piezoelectric power generation"""
|
|
82
|
+
return force * displacement * coupling_coefficient
|
|
83
|
+
|
|
84
|
+
def thermoelectric_power(seebeck_coeff, temperature_diff, resistance):
|
|
85
|
+
"""Thermoelectric power generation"""
|
|
86
|
+
voltage = seebeck_coeff * temperature_diff
|
|
87
|
+
return voltage**2 / resistance
|
|
88
|
+
|
|
89
|
+
def biomass_energy_content(mass, heating_value=15e6):
|
|
90
|
+
"""Biomass energy content"""
|
|
91
|
+
return mass * heating_value
|
|
92
|
+
|
|
93
|
+
def tidal_power(tidal_range, basin_area, water_density=1025):
|
|
94
|
+
"""Tidal energy potential"""
|
|
95
|
+
return 0.5 * water_density * EARTH_GRAVITY * basin_area * tidal_range**2
|
|
96
|
+
|
|
97
|
+
def wave_power(wave_height, wave_period, water_depth):
|
|
98
|
+
"""Ocean wave power per unit width"""
|
|
99
|
+
wavelength = EARTH_GRAVITY * wave_period**2 / (2 * PI)
|
|
100
|
+
group_velocity = math.sqrt(EARTH_GRAVITY * wavelength / (2 * PI)) / 2
|
|
101
|
+
return (WATER_DENSITY * EARTH_GRAVITY * wave_height**2 * group_velocity) / 8
|
|
102
|
+
|
|
103
|
+
def energy_storage_time(capacity, power_rating):
|
|
104
|
+
"""Energy storage duration"""
|
|
105
|
+
return capacity / power_rating
|
|
106
|
+
|
|
107
|
+
def round_trip_efficiency(energy_out, energy_in):
|
|
108
|
+
"""Energy storage round-trip efficiency"""
|
|
109
|
+
return energy_out / energy_in
|
|
110
|
+
|
|
111
|
+
def grid_frequency_regulation(power_imbalance, system_inertia):
|
|
112
|
+
"""Grid frequency change from power imbalance"""
|
|
113
|
+
return power_imbalance / system_inertia
|
|
114
|
+
|
|
115
|
+
def transmission_line_losses(resistance, current):
|
|
116
|
+
"""Transmission line power losses"""
|
|
117
|
+
return resistance * current**2
|
|
118
|
+
|
|
119
|
+
def transformer_efficiency(primary_voltage, primary_current, secondary_voltage, secondary_current):
|
|
120
|
+
"""Transformer efficiency"""
|
|
121
|
+
power_in = primary_voltage * primary_current
|
|
122
|
+
power_out = secondary_voltage * secondary_current
|
|
123
|
+
return power_out / power_in
|
|
124
|
+
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import math
|
|
2
|
+
from ..constants import *
|
|
3
|
+
|
|
4
|
+
def stress(force, area):
|
|
5
|
+
"""Calculate stress"""
|
|
6
|
+
return force / area
|
|
7
|
+
|
|
8
|
+
def strain(delta_length, original_length):
|
|
9
|
+
"""Calculate strain"""
|
|
10
|
+
return delta_length / original_length
|
|
11
|
+
|
|
12
|
+
def young_modulus(stress, strain):
|
|
13
|
+
"""Calculate Young's modulus"""
|
|
14
|
+
return stress / strain
|
|
15
|
+
|
|
16
|
+
def thermal_expansion(length, alpha, delta_temp):
|
|
17
|
+
"""Linear thermal expansion"""
|
|
18
|
+
return length * alpha * delta_temp
|
|
19
|
+
|
|
20
|
+
def heat_transfer_conduction(k, area, delta_temp, thickness):
|
|
21
|
+
"""Heat transfer by conduction"""
|
|
22
|
+
return k * area * delta_temp / thickness
|
|
23
|
+
|
|
24
|
+
def reynolds_number(density, velocity, length, viscosity):
|
|
25
|
+
"""Calculate Reynolds number"""
|
|
26
|
+
return density * velocity * length / viscosity
|
|
27
|
+
|
|
28
|
+
def drag_force(drag_coeff, density, velocity, area):
|
|
29
|
+
"""Calculate drag force"""
|
|
30
|
+
return 0.5 * drag_coeff * density * velocity**2 * area
|
|
31
|
+
|
|
32
|
+
def lift_force(lift_coeff, density, velocity, area):
|
|
33
|
+
"""Calculate lift force"""
|
|
34
|
+
return 0.5 * lift_coeff * density * velocity**2 * area
|
|
35
|
+
|
|
36
|
+
def moment_of_inertia_rectangle(width, height):
|
|
37
|
+
"""Moment of inertia for rectangular cross-section"""
|
|
38
|
+
return width * height**3 / 12
|
|
39
|
+
|
|
40
|
+
def critical_buckling_load(e_modulus, moment_inertia, length):
|
|
41
|
+
"""Euler critical buckling load"""
|
|
42
|
+
return PI**2 * e_modulus * moment_inertia / length**2
|
|
43
|
+
|
|
44
|
+
def fatigue_life(stress_amplitude, fatigue_strength_coeff, fatigue_strength_exp):
|
|
45
|
+
"""S-N fatigue life estimation"""
|
|
46
|
+
return (stress_amplitude / fatigue_strength_coeff)**(1/fatigue_strength_exp)
|
|
47
|
+
|
|
48
|
+
def shear_stress_circular(torque, radius, polar_moment):
|
|
49
|
+
"""Shear stress in circular shaft"""
|
|
50
|
+
return torque * radius / polar_moment
|
|
51
|
+
|
|
52
|
+
def deflection_cantilever(force, length, e_modulus, moment_inertia):
|
|
53
|
+
"""Deflection of cantilever beam"""
|
|
54
|
+
return force * length**3 / (3 * e_modulus * moment_inertia)
|
|
55
|
+
|
|
56
|
+
def natural_frequency_beam(e_modulus, moment_inertia, mass_per_length, length):
|
|
57
|
+
"""Natural frequency of beam"""
|
|
58
|
+
return (1.875**2 / (2 * PI)) * math.sqrt(e_modulus * moment_inertia / (mass_per_length * length**4))
|
|
59
|
+
|
|
60
|
+
def thermal_stress(e_modulus, alpha, delta_temp):
|
|
61
|
+
"""Thermal stress in constrained material"""
|
|
62
|
+
return e_modulus * alpha * delta_temp
|
|
63
|
+
|
|
64
|
+
def pressure_vessel_hoop_stress(pressure, radius, thickness):
|
|
65
|
+
"""Hoop stress in thin-walled pressure vessel"""
|
|
66
|
+
return pressure * radius / thickness
|
|
67
|
+
|
|
68
|
+
def creep_rate(stress, temperature, activation_energy, stress_exponent=5):
|
|
69
|
+
"""Creep rate equation"""
|
|
70
|
+
return stress**stress_exponent * math.exp(-activation_energy / (BOLTZMANN_CONSTANT * temperature))
|
|
71
|
+
|
|
72
|
+
def fracture_toughness_critical_length(k_ic, stress, shape_factor=1):
|
|
73
|
+
"""Critical crack length from fracture toughness"""
|
|
74
|
+
return (k_ic / (shape_factor * stress))**2 / PI
|
|
75
|
+
|
|
76
|
+
def electrical_resistance(resistivity, length, area):
|
|
77
|
+
"""Electrical resistance"""
|
|
78
|
+
return resistivity * length / area
|
|
79
|
+
|
|
80
|
+
def power_dissipation(current, resistance):
|
|
81
|
+
"""Power dissipation in resistor"""
|
|
82
|
+
return current**2 * resistance
|
|
83
|
+
|
|
84
|
+
def capacitance_parallel_plate(permittivity, area, distance):
|
|
85
|
+
"""Capacitance of parallel plate capacitor"""
|
|
86
|
+
return permittivity * area / distance
|
|
87
|
+
|
|
88
|
+
def inductance_solenoid(permeability, turns, area, length):
|
|
89
|
+
"""Inductance of solenoid"""
|
|
90
|
+
return permeability * turns**2 * area / length
|
|
91
|
+
|
|
92
|
+
def skin_depth(frequency, conductivity, permeability):
|
|
93
|
+
"""Electromagnetic skin depth"""
|
|
94
|
+
return math.sqrt(2 / (2 * PI * frequency * conductivity * permeability))
|
|
95
|
+
|
|
96
|
+
def doppler_shift(source_freq, source_velocity, observer_velocity, wave_speed):
|
|
97
|
+
"""Doppler frequency shift"""
|
|
98
|
+
return source_freq * (wave_speed + observer_velocity) / (wave_speed - source_velocity)
|
|
99
|
+
|
|
100
|
+
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import math
|
|
2
|
+
from ..constants import *
|
|
3
|
+
|
|
4
|
+
def atmospheric_pressure_altitude(altitude):
|
|
5
|
+
"""Atmospheric pressure at altitude"""
|
|
6
|
+
return ATMOSPHERIC_PRESSURE * math.exp(-altitude / 8400)
|
|
7
|
+
|
|
8
|
+
def air_density_altitude(altitude, temperature=288.15):
|
|
9
|
+
"""Air density at altitude"""
|
|
10
|
+
pressure = atmospheric_pressure_altitude(altitude)
|
|
11
|
+
return pressure / (287 * temperature)
|
|
12
|
+
|
|
13
|
+
def sound_speed_air(temperature):
|
|
14
|
+
"""Speed of sound in air at given temperature"""
|
|
15
|
+
return 331.3 * math.sqrt(temperature / 273.15)
|
|
16
|
+
|
|
17
|
+
def greenhouse_effect_temperature(solar_constant, albedo, emissivity=1.0):
|
|
18
|
+
"""Greenhouse effect temperature calculation"""
|
|
19
|
+
absorbed_power = solar_constant * (1 - albedo) / 4
|
|
20
|
+
return (absorbed_power / (emissivity * STEFAN_BOLTZMANN_CONSTANT))**(1/4)
|
|
21
|
+
|
|
22
|
+
def solar_irradiance(solar_constant, zenith_angle):
|
|
23
|
+
"""Solar irradiance at surface"""
|
|
24
|
+
return solar_constant * math.cos(zenith_angle)
|
|
25
|
+
|
|
26
|
+
def photosynthetic_photon_flux(irradiance, wavelength=550e-9):
|
|
27
|
+
"""Photosynthetic photon flux density"""
|
|
28
|
+
photon_energy = PLANCK_CONSTANT * SPEED_OF_LIGHT / wavelength
|
|
29
|
+
return irradiance / photon_energy
|
|
30
|
+
|
|
31
|
+
def clausius_clapeyron(temperature, latent_heat):
|
|
32
|
+
"""Clausius-Clapeyron equation for vapor pressure"""
|
|
33
|
+
reference_temp = 273.15
|
|
34
|
+
reference_pressure = 611.2
|
|
35
|
+
return reference_pressure * math.exp((latent_heat / GAS_CONSTANT) * (1/reference_temp - 1/temperature))
|
|
36
|
+
|
|
37
|
+
def mixing_ratio(vapor_pressure, total_pressure):
|
|
38
|
+
"""Water vapor mixing ratio"""
|
|
39
|
+
return 0.622 * vapor_pressure / (total_pressure - vapor_pressure)
|
|
40
|
+
|
|
41
|
+
def potential_temperature(temperature, pressure, reference_pressure=100000):
|
|
42
|
+
"""Potential temperature"""
|
|
43
|
+
return temperature * (reference_pressure / pressure)**(0.286)
|
|
44
|
+
|
|
45
|
+
def richardson_number(gravity, temperature_gradient, wind_shear, reference_temp):
|
|
46
|
+
"""Richardson number for atmospheric stability"""
|
|
47
|
+
return (gravity / reference_temp) * temperature_gradient / wind_shear**2
|
|
48
|
+
|
|
49
|
+
def coriolis_parameter(latitude):
|
|
50
|
+
"""Coriolis parameter"""
|
|
51
|
+
omega = 2 * PI / 86400
|
|
52
|
+
return 2 * omega * math.sin(math.radians(latitude))
|
|
53
|
+
|
|
54
|
+
def geostrophic_wind(pressure_gradient, density, latitude):
|
|
55
|
+
"""Geostrophic wind speed"""
|
|
56
|
+
f = coriolis_parameter(latitude)
|
|
57
|
+
return pressure_gradient / (density * f)
|
|
58
|
+
|
|
59
|
+
def ozone_depletion_potential(concentration, reaction_rate, lifetime):
|
|
60
|
+
"""Ozone depletion potential"""
|
|
61
|
+
return concentration * reaction_rate * lifetime
|
|
62
|
+
|
|
63
|
+
def radiative_forcing(delta_concentration, forcing_efficiency):
|
|
64
|
+
"""Radiative forcing calculation"""
|
|
65
|
+
return forcing_efficiency * math.log(delta_concentration)
|
|
66
|
+
|
|
67
|
+
def heat_island_intensity(urban_temp, rural_temp):
|
|
68
|
+
"""Urban heat island intensity"""
|
|
69
|
+
return urban_temp - rural_temp
|
|
70
|
+
|
|
71
|
+
def albedo_feedback(initial_albedo, temperature_change, feedback_coefficient):
|
|
72
|
+
"""Albedo feedback mechanism"""
|
|
73
|
+
return initial_albedo - feedback_coefficient * temperature_change
|
|
74
|
+
|
|
75
|
+
def photolysis_rate(solar_zenith, absorption_cross_section, quantum_yield):
|
|
76
|
+
"""Photolysis rate calculation"""
|
|
77
|
+
actinic_flux = 1e15 * math.cos(solar_zenith)
|
|
78
|
+
return absorption_cross_section * quantum_yield * actinic_flux
|
|
79
|
+
|
|
80
|
+
def aerosol_optical_depth(extinction_coeff, path_length):
|
|
81
|
+
"""Aerosol optical depth"""
|
|
82
|
+
return extinction_coeff * path_length
|
|
83
|
+
|
|
84
|
+
def scattering_coefficient(particle_concentration, scattering_cross_section):
|
|
85
|
+
"""Aerosol scattering coefficient"""
|
|
86
|
+
return particle_concentration * scattering_cross_section
|
|
87
|
+
|
|
88
|
+
def visibility_range(extinction_coeff, contrast_threshold=0.02):
|
|
89
|
+
"""Visibility range from extinction"""
|
|
90
|
+
return -math.log(contrast_threshold) / extinction_coeff
|
|
91
|
+
|
|
92
|
+
def settling_velocity(particle_diameter, particle_density, air_density=1.2, viscosity=1.8e-5):
|
|
93
|
+
"""Particle settling velocity"""
|
|
94
|
+
return (particle_diameter**2 * (particle_density - air_density) * EARTH_GRAVITY) / (18 * viscosity)
|
|
95
|
+
|
|
96
|
+
def diffusion_coefficient_atmospheric(temperature, pressure, molecular_weight):
|
|
97
|
+
"""Atmospheric diffusion coefficient"""
|
|
98
|
+
return 1e-5 * (temperature / 273.15)**(1.75) * (101325 / pressure) * (29 / molecular_weight)**0.5
|
|
99
|
+
|
|
100
|
+
def residence_time(total_mass, removal_rate):
|
|
101
|
+
"""Atmospheric residence time"""
|
|
102
|
+
return total_mass / removal_rate
|
|
103
|
+
|
|
104
|
+
def carbon_cycle_flux(concentration_gradient, transfer_velocity):
|
|
105
|
+
"""Carbon cycle flux calculation"""
|
|
106
|
+
return concentration_gradient * transfer_velocity
|
|
107
|
+
|
|
108
|
+
def photochemical_equilibrium(production_rate, loss_rate):
|
|
109
|
+
"""Photochemical equilibrium concentration"""
|
|
110
|
+
return production_rate / loss_rate
|
|
111
|
+
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import math
|
|
2
|
+
from ..constants import *
|
|
3
|
+
|
|
4
|
+
def radiation_dose_rate(activity, distance, gamma_constant=0.5):
|
|
5
|
+
"""Calculate radiation dose rate"""
|
|
6
|
+
return gamma_constant * activity / (distance ** 2)
|
|
7
|
+
|
|
8
|
+
def half_value_layer(attenuation_coeff):
|
|
9
|
+
"""Calculate half-value layer thickness"""
|
|
10
|
+
return math.log(2) / attenuation_coeff
|
|
11
|
+
|
|
12
|
+
def ct_number(mu_tissue, mu_water):
|
|
13
|
+
"""Calculate CT Hounsfield number"""
|
|
14
|
+
return 1000 * (mu_tissue - mu_water) / mu_water
|
|
15
|
+
|
|
16
|
+
def mri_relaxation(t, t1):
|
|
17
|
+
"""MRI T1 relaxation recovery"""
|
|
18
|
+
return 1 - math.exp(-t / t1)
|
|
19
|
+
|
|
20
|
+
def ultrasound_intensity(power, beam_area):
|
|
21
|
+
"""Calculate ultrasound intensity"""
|
|
22
|
+
return power / beam_area
|
|
23
|
+
|
|
24
|
+
def radioactive_decay(n0, decay_constant, time):
|
|
25
|
+
"""Radioactive decay law"""
|
|
26
|
+
return n0 * math.exp(-decay_constant * time)
|
|
27
|
+
|
|
28
|
+
def linear_energy_transfer(energy_loss, path_length):
|
|
29
|
+
"""Calculate linear energy transfer (LET)"""
|
|
30
|
+
return energy_loss / path_length
|
|
31
|
+
|
|
32
|
+
def relative_biological_effectiveness(dose_test, dose_reference):
|
|
33
|
+
"""Calculate relative biological effectiveness (RBE)"""
|
|
34
|
+
return dose_reference / dose_test
|
|
35
|
+
|
|
36
|
+
def bragg_peak_range(energy, density=1.0, z_eff=7.4):
|
|
37
|
+
"""Approximate Bragg peak range for protons"""
|
|
38
|
+
return 0.31 * (energy ** 1.8) / (density * z_eff)
|
|
39
|
+
|
|
40
|
+
def compton_scatter_energy(incident_energy, scatter_angle):
|
|
41
|
+
"""Compton scattered photon energy"""
|
|
42
|
+
electron_rest_energy = ELECTRON_MASS * SPEED_OF_LIGHT**2 / ELECTRON_VOLT
|
|
43
|
+
denominator = 1 + (incident_energy / electron_rest_energy) * (1 - math.cos(scatter_angle))
|
|
44
|
+
return incident_energy / denominator
|
|
45
|
+
|
|
46
|
+
def tissue_air_ratio(depth, field_size, energy):
|
|
47
|
+
"""Simplified tissue-air ratio calculation"""
|
|
48
|
+
mu = 0.05 * energy**(-0.5)
|
|
49
|
+
return math.exp(-mu * depth) * (1 + 0.1 * field_size)
|
|
50
|
+
|
|
51
|
+
def percent_depth_dose(depth, ssd=100, field_size=10, energy=6):
|
|
52
|
+
"""Percent depth dose calculation"""
|
|
53
|
+
dmax = 0.9 + 0.15 * energy
|
|
54
|
+
if depth <= dmax:
|
|
55
|
+
return 100
|
|
56
|
+
return 100 * math.exp(-0.05 * (depth - dmax))
|
|
57
|
+
|
|
58
|
+
def monitor_unit_calculation(prescribed_dose, dose_rate, field_factors=1.0):
|
|
59
|
+
"""Calculate monitor units for treatment"""
|
|
60
|
+
return prescribed_dose / (dose_rate * field_factors)
|
|
61
|
+
|
|
62
|
+
def biological_effective_dose(physical_dose, alpha_beta_ratio, dose_per_fraction):
|
|
63
|
+
"""Calculate biological effective dose"""
|
|
64
|
+
return physical_dose * (1 + dose_per_fraction / alpha_beta_ratio)
|
|
65
|
+
|
|
66
|
+
def effective_dose(absorbed_dose, radiation_weighting, tissue_weighting):
|
|
67
|
+
"""Calculate effective dose"""
|
|
68
|
+
equivalent_dose = absorbed_dose * radiation_weighting
|
|
69
|
+
return equivalent_dose * tissue_weighting
|
|
70
|
+
|
|
File without changes
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import math
|
|
2
|
+
from ..constants import *
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def column_number_density(pressure, gravity, molar_mass):
|
|
6
|
+
"""Molecules per m^2 in a hydrostatic column: P/(g*m_molecule).
|
|
7
|
+
|
|
8
|
+
Args: surface pressure (Pa), gravity (m/s^2), mean molar mass (kg/mol).
|
|
9
|
+
"""
|
|
10
|
+
molecule_mass = molar_mass / AVOGADRO_NUMBER
|
|
11
|
+
return pressure / (gravity * molecule_mass)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def rayleigh_cross_section(wavelength_nm, refractivity, king_factor=1.0):
|
|
15
|
+
"""Rayleigh scattering cross-section (m^2) per molecule at a wavelength.
|
|
16
|
+
|
|
17
|
+
refractivity is (n - 1) at STP; king_factor corrects for molecular
|
|
18
|
+
anisotropy. Scales as 1/lambda^4, which is why skies are blue.
|
|
19
|
+
"""
|
|
20
|
+
lam = wavelength_nm * 1e-9
|
|
21
|
+
n = 1.0 + refractivity
|
|
22
|
+
factor = ((n**2 - 1.0) / (n**2 + 2.0)) ** 2
|
|
23
|
+
return (
|
|
24
|
+
24.0
|
|
25
|
+
* math.pi**3
|
|
26
|
+
/ (lam**4 * LOSCHMIDT_NUMBER**2)
|
|
27
|
+
* factor
|
|
28
|
+
* king_factor
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def rayleigh_optical_depth(wavelength_nm, refractivity, king_factor, column_density):
|
|
33
|
+
"""Dimensionless Rayleigh optical depth through a molecular column."""
|
|
34
|
+
cross_section = rayleigh_cross_section(wavelength_nm, refractivity, king_factor)
|
|
35
|
+
return cross_section * column_density
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def beer_lambert_transmission(optical_depth, air_mass=1.0):
|
|
39
|
+
"""Fraction of a beam surviving a slab: exp(-tau/mu_0).
|
|
40
|
+
|
|
41
|
+
air_mass is 1/cos(solar zenith angle); 1.0 is the overhead sun.
|
|
42
|
+
"""
|
|
43
|
+
return math.exp(-optical_depth / air_mass)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def single_scatter_fraction(optical_depth, air_mass=1.0):
|
|
47
|
+
"""Fraction of a beam scattered out of it along a path: 1 - T.
|
|
48
|
+
|
|
49
|
+
The single-scattering approximation: a photon that leaves the direct
|
|
50
|
+
beam is counted as entering the diffuse field exactly once, and nothing
|
|
51
|
+
scatters back out again. Spectrally this is what makes a sky blue --
|
|
52
|
+
the Rayleigh cross-section goes as lambda^-4, so short wavelengths are
|
|
53
|
+
removed from the beam and appear overhead instead.
|
|
54
|
+
|
|
55
|
+
It holds while the optical depth is small: Earth's zenith Rayleigh
|
|
56
|
+
depth is about 0.1 at 550 nm. For a thick atmosphere it overstates the
|
|
57
|
+
diffuse field, because multiple scattering redistributes light and,
|
|
58
|
+
with absorption present, removes some of it entirely.
|
|
59
|
+
|
|
60
|
+
Args: optical depth (dimensionless), air mass (1/cos of the zenith
|
|
61
|
+
angle; 1.0 looks straight up).
|
|
62
|
+
"""
|
|
63
|
+
return 1.0 - beer_lambert_transmission(optical_depth, air_mass)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def mixture_refractivity(composition, refractivity_table):
|
|
67
|
+
"""Mole-fraction-weighted refractivity of a gas mixture.
|
|
68
|
+
|
|
69
|
+
composition maps species key -> percentage; refractivity is additive.
|
|
70
|
+
"""
|
|
71
|
+
total = sum(composition.values())
|
|
72
|
+
if total <= 0:
|
|
73
|
+
return 0.0
|
|
74
|
+
return sum(
|
|
75
|
+
percent / total * refractivity_table[species]
|
|
76
|
+
for species, percent in composition.items()
|
|
77
|
+
)
|