def getStatic(self): ''' calculate the static matrix for the specified temperature''' temperature = self.Temperature z = self.Z ionList = [] chIons = [] evolver = np.zeros((z + 1, z + 1), 'float64') for ion in range(1, z + 2): ions = util.zion2name(z, ion) ionList.append(ions) # print z, ion, ions atom = ch.ion(ions, temperature=temperature) atom.ionizRate() atom.recombRate() chIons.append(atom) for stage in range(0, z): atom = chIons[stage] # if type(atom.IonizRate) != types.NoneType: evolver[stage, stage] -= atom.IonizRate['rate'] atom = chIons[stage + 1] evolver[stage, stage + 1] += atom.RecombRate['rate'] # evolver[stage-2,stage] += atom.IonizRate['rate'] for stage in range(1, z + 1): atom = chIons[stage] # if type(atom.RecombRate) != types.NoneType: evolver[stage, stage] -= atom.RecombRate['rate'] atom = chIons[stage - 1] evolver[stage, stage - 1] += atom.IonizRate['rate'] # evolver[stage-1,stage-2] += atom.RecombRate['rate'] # include normalization of ionization stages for stage in range(0, z + 1): evolver[0, stage] = 1. self.Static = evolver
def getStatic(self): ''' calculate the static matrix for the specified temperature''' temperature = self.Temperature z = self.Z ionList=[] chIons=[] evolver = np.zeros((z+1,z+1),'float64') for ion in range(1, z+2): ions=util.zion2name(z, ion) ionList.append(ions) # print z, ion, ions atom=ch.ion(ions, temperature=temperature) atom.ionizRate() atom.recombRate() chIons.append(atom) for stage in range(0,z): atom = chIons[stage] # if type(atom.IonizRate) != types.NoneType: evolver[stage,stage] -= atom.IonizRate['rate'] atom = chIons[stage+1] evolver[stage,stage+1] += atom.RecombRate['rate'] # evolver[stage-2,stage] += atom.IonizRate['rate'] for stage in range(1,z+1): atom = chIons[stage] # if type(atom.RecombRate) != types.NoneType: evolver[stage,stage] -= atom.RecombRate['rate'] atom = chIons[stage-1] evolver[stage,stage-1] += atom.IonizRate['rate'] # evolver[stage-1,stage-2] += atom.RecombRate['rate'] # include normalization of ionization stages for stage in range(0,z+1): evolver[0,stage] = 1. self.Static = evolver
def match_line(ion_name, wvls, s_flux, tmax, density): # t = 10**((tmax - 0.3) + 0.001*np.arange(600)) lowtemp = 4.0 hightemp = 8.0 npoints = 1000 t = 10**(np.linspace(lowtemp, hightemp, npoints)) ion_n = ch.ion(ion_name, temperature=t, eDensity=density) ion_n.gofnt(wvlRange=[min(wvls) - 1, max(wvls) + 1]) return ion_n.Gofnt
def sum_match_lines(ion_name,wvls,t,density,search_width = 1.0): ion_n = ch.ion(ion_name, temperature=t, eDensity=density) intensity = t.copy()*0.0 print(wvls) for wvl in wvls: ion_n.intensity(wvlRange=[min(wvls)-search_width,max(wvls)+search_width]) if wvl in(ion_n.Intensity['wvl']): intensity_s = ion_n.Intensity['intensity'][:,(ion_n.Intensity['wvl'] == wvl)] intensity += np.array(intensity_s.T[0]) print('match') else: print('Something is wrong - cannot find matching line! for {} {}'.format(ion_name,wvl)) intensity += 0 return intensity
def getIoneq(self): ''' get the ionization equilibrium for this ion at the specified temperature getIoneqFromEvolver does the same but is a bit less accurate''' z = self.Z temperature = self.Temperature ionList = [] chIons = [] for ion in range(1, z + 2): ions = util.zion2name(z, ion) ionList.append(ions) # print z, ion, ions atom = ch.ion(ions, temperature=temperature, setup=0) atom.ionizRate() atom.recombRate() chIons.append(atom) ioneq = np.zeros((z + 1), 'float64') factor = [] for anIon in chIons: if type(anIon.IonizRate) != type(None) and type( anIon.RecombRate) != type(None): rat = anIon.IonizRate['rate'] / anIon.RecombRate['rate'] factor.append(rat**2 + rat**(-2)) else: factor.append(0.) factor[0] = max(factor) factor[-1] = max(factor) ionmax = factor.index(min(factor)) ioneq[ionmax] = 1. # for iz in range(ionmax + 1, z + 1): ionrate = chIons[iz - 1].IonizRate['rate'] recrate = chIons[iz].RecombRate['rate'] ioneq[iz] = ionrate * ioneq[iz - 1] / recrate # print ' iz, ioneq = ',iz,ioneq[iz] # for iz in range(ionmax - 1, -1, -1): ionrate = chIons[iz].IonizRate['rate'] recrate = chIons[iz + 1].RecombRate['rate'] ioneq[iz] = recrate * ioneq[iz + 1] / ionrate # print ' iz, ioneq = ',iz,ioneq[iz] ionsum = ioneq.sum() # print ' ionsum = ', ionsum ioneq = ioneq / ionsum self.Ioneq = ioneq
def getIoneq(self): ''' get the ionization equilibrium for this ion at the specified temperature getIoneqFromEvolver does the same but is a bit less accurate''' z = self.Z temperature = self.Temperature ionList=[] chIons=[] for ion in range(1, z+2): ions=util.zion2name(z, ion) ionList.append(ions) # print z, ion, ions atom=ch.ion(ions, temperature=temperature, setup=0) atom.ionizRate() atom.recombRate() chIons.append(atom) ioneq=np.zeros((z+1), 'float64') factor=[] for anIon in chIons: if type(anIon.IonizRate) != type(None) and type(anIon.RecombRate) != type(None): rat=anIon.IonizRate['rate']/anIon.RecombRate['rate'] factor.append(rat**2 + rat**(-2)) else: factor.append(0.) factor[0]=max(factor) factor[-1]=max(factor) ionmax=factor.index(min(factor)) ioneq[ionmax]=1. # for iz in range(ionmax+1, z+1): ionrate=chIons[iz-1].IonizRate['rate'] recrate=chIons[iz].RecombRate['rate'] ioneq[iz]=ionrate*ioneq[iz-1]/recrate # print ' iz, ioneq = ',iz,ioneq[iz] # for iz in range(ionmax-1, -1, -1): ionrate=chIons[iz].IonizRate['rate'] recrate=chIons[iz+1].RecombRate['rate'] ioneq[iz]=recrate*ioneq[iz+1]/ionrate # print ' iz, ioneq = ',iz,ioneq[iz] ionsum=ioneq.sum() # print ' ionsum = ', ionsum ioneq=ioneq/ionsum self.Ioneq=ioneq
def old_find_tm(ion_name): h = 6.626068e-34 c = 299792458 k = 1.3806503e-23 ion_state = int(ion_name.rsplit('_')[1]) t = 10**(3.8 + 0.01 * np.arange(400)) ion = ch.ion(ion_name, temperature=t) ioneq = ion.IoneqOne W = h * c * ion.Elvlc['ecm'][ion_state - 1] * 100 gt = ioneq * (t**-0.5) * np.exp(-W / (k * t)) tm = t[np.argmax(gt)] return np.log10(tm)
def old_e_measure(ion_name, wvls, s_flux, tmax, star_dist, star_radius, density): rs = 6.96e10 pc = 3.08567758e18 t = 10**((tmax - 0.3) + 0.001 * np.arange(600)) ion_n = ch.ion(ion_name, temperature=t, eDensity=density) ion_n.gofnt(wvlRange=[min(wvls) - 1, max(wvls) + 1]) star_dist = star_dist * pc star_radius = star_radius * rs flux = s_flux * (star_dist / star_radius)**2.0 print('ANYONE THERE?!') quit() ion_n.Gofnt['emeasure'] = (flux / density) / (2 * np.pi * ion_n.Gofnt['gofnt']) return ion_n.Gofnt
def getEvolver(self, temperature, density, time): ''' calculate the evolver matrix for the new temperature''' self.NewTemperature = temperature z = self.Z ionList = [] chIons = [] evolver = np.zeros((z + 1, z + 1), 'float64') for ion in range(1, z + 2): ions = util.zion2name(z, ion) ionList.append(ions) # print z, ion, ions atom = ch.ion(ions, temperature=temperature, setup=0) atom.ionizRate() atom.recombRate() chIons.append(atom) for stage in range(0, z): # atom = chIons[stage] # if type(atom.IonizRate) != types.NoneType: evolver[stage, stage] -= chIons[stage].IonizRate['rate'] # atom = chIons[stage+1] evolver[stage, stage + 1] += chIons[stage + 1].RecombRate['rate'] # evolver[stage-2,stage] += atom.IonizRate['rate'] for stage in range(1, z + 1): # atom = chIons[stage] # if type(atom.RecombRate) != types.NoneType: evolver[stage, stage] -= chIons[stage].RecombRate['rate'] # atom = chIons[stage-1] evolver[stage, stage - 1] += chIons[stage - 1].IonizRate['rate'] # evolver[stage-1,stage-2] += atom.RecombRate['rate'] # include normalization of ionization stages # for stage in range(0,z+1): # evolver[0,stage] = 1. # this is the first order Euler solution # implicitEvolver = np.invert(np.identity(z+1,'float64') - evolver) implicitEvolver = np.dual.inv( np.identity(z + 1, 'float64') - density * time * evolver) self.Evolver = implicitEvolver
def getEvolver(self,temperature,density,time): ''' calculate the evolver matrix for the new temperature''' self.NewTemperature = temperature z = self.Z ionList=[] chIons=[] evolver = np.zeros((z+1,z+1),'float64') for ion in range(1, z+2): ions=util.zion2name(z, ion) ionList.append(ions) # print z, ion, ions atom=ch.ion(ions, temperature=temperature, setup=0) atom.ionizRate() atom.recombRate() chIons.append(atom) for stage in range(0,z): # atom = chIons[stage] # if type(atom.IonizRate) != types.NoneType: evolver[stage,stage] -= chIons[stage].IonizRate['rate'] # atom = chIons[stage+1] evolver[stage,stage+1] += chIons[stage+1].RecombRate['rate'] # evolver[stage-2,stage] += atom.IonizRate['rate'] for stage in range(1,z+1): # atom = chIons[stage] # if type(atom.RecombRate) != types.NoneType: evolver[stage,stage] -= chIons[stage].RecombRate['rate'] # atom = chIons[stage-1] evolver[stage,stage-1] += chIons[stage-1].IonizRate['rate'] # evolver[stage-1,stage-2] += atom.RecombRate['rate'] # include normalization of ionization stages # for stage in range(0,z+1): # evolver[0,stage] = 1. # this is the first order Euler solution # implicitEvolver = np.invert(np.identity(z+1,'float64') - evolver) implicitEvolver = np.dual.inv(np.identity(z+1,'float64') - density*time*evolver) self.Evolver = implicitEvolver
def read_chianti(symbol, ion_number, level_observed=True, temperatures = np.linspace(2000, 50000, 20)): ion_data = ch.ion('{0}_{1:d}'.format(symbol.lower(), ion_number+1)) levels_data = {} levels_data['level_number'] = ion_data.Elvlc['lvl'] temperatures = np.array(temperatures) if level_observed: levels_data['energy'] = units.Unit('cm').to('eV', 1 / np.array(ion_data.Elvlc['ecm']), units.spectral()) else: levels_data['energy'] = units.Unit('cm').to('eV', 1 / np.array(ion_data.Elvlc['ecmth']), units.spectral()) levels_data['g'] = 2*np.array(ion_data.Elvlc['j']) + 1 if levels_data['energy'][0] != 0.0: raise ValueError('Level 0 energy is not 0.0') levels_data = pd.DataFrame(levels_data) levels_data.set_index('level_number', inplace=True) last_bound_level = levels_data[levels_data['energy'] < ion_data.Ip].index[-1] levels_data = levels_data.ix[:last_bound_level] lines_data = {} lines_data['wavelength'] = ion_data.Wgfa['wvl'] lines_data['level_number_lower'] = ion_data.Wgfa['lvl1'] lines_data['level_number_upper'] = ion_data.Wgfa['lvl2'] lines_data['A_ul'] = ion_data.Wgfa['avalue'] nu = units.Unit('angstrom').to('Hz', lines_data['wavelength'], units.spectral()) lines_data = pd.DataFrame(lines_data) g_lower = levels_data['g'].ix[lines_data['level_number_lower'].values].values g_upper = levels_data['g'].ix[lines_data['level_number_upper'].values].values A_coeff = (8 * np.pi**2 * constants.e.gauss.value**2 * nu**2)/ (constants.m_e.cgs.value * constants.c.cgs.value**3) lines_data['f_ul'] = lines_data['A_ul'] / A_coeff lines_data['f_lu'] = (lines_data['A_ul'] * g_upper) / (A_coeff * g_lower) lines_data['loggf'] = np.log10(lines_data['f_lu'] * g_lower) lines_data['wavelength'] = lines_data['wavelength']# / (1.0 + 2.735182E-4 + 131.4182 / lines_data['wavelength']**2 # + 2.76249E8 / lines_data['wavelength']**4) lines_data = lines_data[lines_data['level_number_upper'] <= last_bound_level] collision_data_index = pd.MultiIndex.from_arrays((ion_data.Splups['lvl1'], ion_data.Splups['lvl2'])) c_lvl1 = [] c_lvl2 = [] c_upper_lowers = [] g_ratios = [] delta_es = [] for i, (lvl1, lvl2) in enumerate(zip(ion_data.Splups['lvl1'], ion_data.Splups['lvl2'])): if lvl2 > last_bound_level: continue c_lvl1.append(lvl1) c_lvl2.append(lvl2) c_upper_lower, g_ratio, delta_e = calculate_collisional_strength(ion_data.Splups, i, temperatures, levels_data) c_upper_lowers.append(c_upper_lower) g_ratios.append(g_ratio) delta_es.append(delta_e) c_upper_lowers = np.array(c_upper_lowers) g_ratios = np.array(g_ratios) delta_es = np.array(delta_es) collision_data = pd.DataFrame(c_upper_lowers, index=collision_data_index) collision_data['g_ratio'] = g_ratios #CAREFUL!!! delta_e has already been divided by k!! collision_data['delta_e'] = delta_es collision_data['level_number_lower'] = c_lvl1 collision_data['level_number_upper'] = c_lvl2 lines_data = lines_data[lines_data.wavelength>0] return levels_data, lines_data, collision_data
init_values['de'][:] = 1e-30 init_values = ion_by_ion.convert_to_mass_density(init_values) else: # start CIE import chianti.core as ch import chianti.util as chu for s in sorted(ion_by_ion.required_species): if s.name != 'ge': if s.name == 'de': continue else: print s.name, s.free_electrons + 1 ion_name = chu.zion2name(np.int(s.number), np.int(s.free_electrons + 1)) ion = ch.ion(ion_name, temperature=init_values['T']) ion.ioneqOne() ion_frac = ion.IoneqOne init_values[s.name] = ion_frac * init_array * ion.Abundance # in case something is negative or super small: init_values[s.name][init_values[s.name] < tiny] = tiny init_values['de'] = init_array * 0.0 # total_density = combined.calculate_total_density(init_values, ("OI",)) # init_values["OI"] = init_array.copy() - total_density init_values = ion_by_ion.convert_to_mass_density(init_values) init_values['de'] = ion_by_ion.calculate_free_electrons(init_values) init_values['density'] = ion_by_ion.calculate_total_density(init_values) number_density = ion_by_ion.calculate_number_density(init_values)
def rec_rate(network): ion = ch.ion(ion_name, temperature = network.T) ion.recombRate() vals = ion.RecombRate['rate'] return vals
def ion_rate(network): ion = ch.ion(ion_name, temperature = network.T) ion.ionizRate() vals = ion.IonizRate['rate'] return vals
def __init__(self, ion_name): self.ion = ch.ion(ion_name) self._levels = None self._lines = None self._collisions = None
""" import ares import numpy as np import matplotlib.pyplot as pl import chianti.core as cc pl.rcParams['legend.fontsize'] = 14 # dims = 32 T = np.logspace(2, 7, dims) # # Chianti rates h1 = cc.ion('h_1', T) h2 = cc.ion('h_2', T) he1 = cc.ion('he_1', T) he2 = cc.ion('he_2', T) he3 = cc.ion('he_3', T) # Analytic fits coeff = ares.physics.RateCoefficients() """ Plot collisional ionization rate coefficients. """ h1.diRate() he1.diRate() he2.diRate()