"""
Date: 03/26/2023
Author: Martin E. Liza
File: aero_optics.py
Def: Contains aero optics functions.
"""
from ambiance import Atmosphere
import numpy as np
import scipy.constants as s_consts
# My Packages
from haot import aerodynamics as aero
from haot import constants_tables
from haot import quantum_mechanics as quantum
[docs]
def gas_density(density_dict): # density_dict [kg/m^3]
gas_amu_weight = aero.air_atomic_molar_mass() # [g/mol]
gas_density = {}
for i in density_dict:
gas_density[i] = (
density_dict[i] * 10**3 * s_consts.N_A / gas_amu_weight[i]
) # [particles/m^3]
return gas_density # [particles/m^3]
[docs]
def index_of_refraction(gas_density_dict):
pol_consts = constants_tables.polarizability() # [m^3]
dielectric_const_0 = s_consts.epsilon_0 # [F/m]
density = gas_density(gas_density_dict) # [particles/m3]
n_const = {} # [ ]
# Convert cgs to SI
alpha_si = lambda x: x * (4 * np.pi * dielectric_const_0) # [F m2]
for i in gas_density_dict:
# Convert alpha_cgs to alpha_si
alpha = alpha_si(pol_consts[i])
n_const[i] = alpha * density[i] # (a_i N_i)
# add all n_i
temp = 0.0
for i in n_const.values():
temp += i
n_return = {}
n_return["dilute"] = 1 + temp / (2 * dielectric_const_0)
n_temp = temp / (3 * dielectric_const_0)
n_return["dense"] = ((2 * n_temp + 1) / (1 - n_temp)) ** 0.5
return n_return
[docs]
def dielectric_material_const(n_const):
# n ~ sqrt(e_r)
dielectric_const_0 = s_consts.epsilon_0 # [F/m]
dielectric = {}
dielectric["dilute"] = dielectric_const_0 * n_const["dilute"] ** 2
dielectric["dense"] = dielectric_const_0 * n_const["dense"] ** 2
return dielectric
[docs]
def optical_path_length(n_solution, distance):
OPL = {}
OPL["dilute"] = n_solution["dilute"] * distance
OPL["dense"] = n_solution["dense"] * distance
#TODO: Missing implementation
return OPL
[docs]
def tropina_aproximation(vibrational_number, rotational_number, molecule):
electron_mass = s_consts.m_e
electron_charge = s_consts.e
spectroscopy_const = constants_tables.spectroscopy_constants(molecule)
# resonance_distance = omega_gi - omega
#TODO: Missing implementation
print("TODO: Missing this implementation")
# Calculate polarizability (uses equation 4 from the paper)
[docs]
def buldakov_expansion(vibrational_number, rotational_number, molecule):
# Load constants
spectroscopy_const = constants_tables.spectroscopy_constants(molecule)
derivative_const = constants_tables.polarizability_derivatives(molecule)
be_we = spectroscopy_const["B_e"] / spectroscopy_const["omega_e"]
# Dunham potential energy constants
(a_0, a_1, a_2) = quantum.potential_dunham_coef_012(molecule)
a_3 = quantum.potential_dunham_coeff_m(a_1, a_2, 3)
rotational_degeneracy = rotational_number * (rotational_number + 1)
vibrational_degeneracy = 2 * vibrational_number + 1
# Split in terms
tmp_1 = be_we
tmp_1 *= -3 * a_1 * derivative_const["first"] + derivative_const["second"]
tmp_1 *= vibrational_degeneracy
tmp_1 *= 1 / 2
tmp_2 = be_we**2
tmp_2 *= derivative_const["first"]
tmp_2 *= rotational_degeneracy
tmp_2 *= 4
tmp_31a = 7
tmp_31a += 15 * vibrational_degeneracy**2
tmp_31a *= a_1**3
tmp_31a *= -3 / 8
tmp_31b = 23
tmp_31b += 39 * vibrational_degeneracy**2
tmp_31b *= a_2
tmp_31b *= a_1
tmp_31b *= 1 / 4
tmp_31c = 5
tmp_31c += vibrational_degeneracy**2
tmp_31c *= a_3
tmp_31c *= -15 / 4
tmp_31 = derivative_const["first"] * (tmp_31a + tmp_31b + tmp_31c)
tmp_32a = 7
tmp_32a += 15 * vibrational_degeneracy**2
tmp_32a *= a_1**2
tmp_32a *= 1 / 8
tmp_32b = 5
tmp_32b += vibrational_degeneracy**2
tmp_32b *= a_2
tmp_32b * --3 / 4
tmp_32 = derivative_const["second"] * (tmp_32a + tmp_32b)
tmp_33 = 7
tmp_33 += 15 * vibrational_degeneracy**2
tmp_33 *= a_1
tmp_33 *= derivative_const["third"]
tmp_33 *= -1 / 24
tmp_3 = (tmp_31 + tmp_32 + tmp_33) * be_we**2
tmp_41 = 1 - a_2
tmp_41 *= 24
tmp_41 += 27 * a_1 * (1 + a_1)
tmp_41 *= derivative_const["first"]
tmp_42 = 1 + 3 * a_1
tmp_42 *= derivative_const["second"]
tmp_42 *= -3
tmp_43 = 1 / 8 * derivative_const["third"]
tmp_4 = tmp_41 + tmp_42 + tmp_43
tmp_4 *= rotational_degeneracy
tmp_4 *= vibrational_degeneracy
tmp_4 *= be_we**3
return derivative_const["zeroth"] + tmp_1 + tmp_2 + tmp_3 + tmp_4
# Calculate polarizability as temperature
"""
DOI: 10.1002/bbpc.19920960517
DOI: 10.1134/BF03355985
"""
[docs]
def kerl_polarizability_temperature(*args, **kargs):
if args:
temperature_K = args[0]
molecule = args[1]
wavelength_nm = args[2]
if kargs:
temperature_K = kargs["temperature_K"]
molecule = kargs["molecule"]
wavelength_nm = kargs["wavelength_nm"]
# Check sizes
mean_const = constants_tables.kerl_interpolation(molecule)
angular_frequency = 2 * np.pi * s_consts.speed_of_light / (wavelength_nm * 1e-9)
tmp = mean_const["c"] * temperature_K**2
tmp += mean_const["b"] * temperature_K
tmp += 1
tmp *= mean_const["groundPolarizability"]
tmp /= 1 - (angular_frequency / mean_const["groundFrequency"]) ** 2
return tmp
# http://walter.bislins.ch/bloge/index.asp?page=Deriving+Equations+for+Atmospheric+Refraction
[docs]
def atmospheric_index_of_refraction(altitude, vaporPressure=0):
atmospheric_prop = Atmosphere(altitude)
temperature = atmospheric_prop.temperature # [K]
pressure = atmospheric_prop.pressure * 0.01 # [mbar]
K_1 = 79 # [K/mbar]
K_2 = 4800 # [K]
refractivity = K_2 * vaporPressure / temperature
refractivity += pressure
refractivity *= K_1 / temperature
refractivity *= 10**-6
return refractivity + 1
[docs]
def atmospheric_gladstone_dale(altitude=0.0, gas_composition_dict=None):
gladstone_const = gladstone_dale() # [m3/kg]
if gas_composition_dict is None:
gas_composition_dict = {}
gas_composition_dict["N"] = 0.0
gas_composition_dict["O"] = 0.0
gas_composition_dict["NO"] = 0.0
gas_composition_dict["N2"] = 0.79
gas_composition_dict["O2"] = 0.21
tmp = 0
for i in gas_composition_dict.keys():
tmp += gas_composition_dict[i] * gladstone_const[i]
return tmp
[docs]
def gladstone_dale(gas_density_dict=None): # [kg/m3
gas_amu_weight = aero.air_atomic_molar_mass() # [g/mol]
avogadro_number = s_consts.N_A # [particles/mol]
dielectric_const = s_consts.epsilon_0 # [F/m]
pol_consts = constants_tables.polarizability() # [m^3]
# Convert CGS to SI
pol_consts.update(
{n: 4 * np.pi * dielectric_const * pol_consts[n] for n in pol_consts.keys()}
) # [Fm^2]
# Calculate Gladstone dale
gladstone_dale_const = {}
for i in pol_consts:
gladstone_dale_const[i] = (
pol_consts[i]
/ (2 * dielectric_const)
* (avogadro_number / gas_amu_weight[i])
* 1e3
) # [m3/kg]
gladstone_dale_dict = {}
if not gas_density_dict:
return gladstone_dale_const # [m^3/kg]
else:
gladstone_dale_dict["gladstone_dale"] = 0.0
for i in gas_density_dict:
gladstone_dale_dict[i] = (
gladstone_dale_const[i] * gas_density_dict[i]
) / sum(gas_density_dict.values())
gladstone_dale_dict["gladstone_dale"] += (
gladstone_dale_const[i] * gas_density_dict[i]
)
gladstone_dale_dict["gladstone_dale"] /= sum(gas_density_dict.values())
return gladstone_dale_dict # [m3/kg]