Source code for aero_optics

#!/opt/homebrew/bin/python3.9
'''
    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.src import aerodynamic_functions as aero
from haot.src import constants_tables 
from haot.src import quantum_mechanics as quantum

[docs] def gas_density(density_dict): # density_dict [kg/m^3] gas_amu_weight = aero.air_atomic_mass() # [g/mol] avogadro_number = s_consts.N_A # [particles/mol] gas_density = { } for i in density_dict: gas_density[i] = (density_dict[i] * 10**3 * avogadro_number / 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 # Note np.sqrt(-1) does not detect complex 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 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 # 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_gladstoneDaleConstant(altitude=0.0, gas_composition_dict=None): atmospheric_prop = Atmosphere(altitude) density = atmospheric_prop.density * 1E3 #[g/m3] num_density = atmospheric_prop.number_density #[particles/m3] gladstone_const = Gladstone_Dale() #[m3/kg] avogadro_number = s_consts.N_A #[particles/mol] if gas_composition_dict == 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_mass() # [g/mol] avogadro_number = s_consts.N_A # [particles/mol] dielectric_const = s_consts.epsilon_0 # [F/m] gd_consts = constants_tables.karl_2003() # [m3/kg] 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]