Skip to content

Commit 4264070

Browse files
committed
This might screw things up
2 parents 7958631 + 0270027 commit 4264070

File tree

171 files changed

+18386
-1474
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

171 files changed

+18386
-1474
lines changed

colradpy/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from .colradpy_class import *
2+
from .ionization_balance_class import *
3+
import numpy as np
4+
import matplotlib.pyplot as plt

colradpy/__init__.py~

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from colradpy_class import colradpy
2+
from ionization_balance import ionization_balance
3+

colradpy/adf04_file_paths.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import urllib.request
2+
import numpy as np
3+
4+
5+
url = "http://open.adas.ac.uk/download/adf04/"
6+
h_arr = np.array(['[adas][1/ha00_ls][h0.dat','adas][1/ha00_ls][h1.dat'])
7+
h_file = np.array(['h0_adf04','h1_adf04'])
8+
9+
he_arr = np.array(['adas][2/mom97_ls][he0.dat','adas][2/mom97_ls][he1.dat'])
10+
he_file = np.array(['he0_adf04','he1_adf04'])
11+
12+
li_arr = np.array(['adas][3/cpb02_ls][li0.dat','adas][3/cpb02_ls][li1.dat','adas][3/cpb02_ls][li2.dat'])
13+
li_file = np.array(['li0_adf04','li1_adf04','li2_adf04'])
14+
15+
be_arr = np.array(['adas][4/cpb03_ls][be0.dat','adas][4/cpb03_ls][be1.dat','adas][4/cpb03_ls][be2.dat','adas][4/cpb03_ls][be3.dat'])
16+
be_file = np.array(['be0_adf04','be1_adf04','be2_adf04','be3_adf04'])
17+
18+
19+
be_arr = np.array(['adas][4/cpb03_ls][be0.dat','adas][4/cpb03_ls][be1.dat','adas][4/cpb03_ls][be2.dat','adas][4/cpb03_ls][be3.dat'])
20+
be_file = np.array(['be0_adf04','be1_adf04','be2_adf04','be3_adf04'])
21+
22+
b_arr = np.array(['cophps][b/dw/ls][b0.dat','copaw][be/belike_lfm14][b1.dat','copaw][li/lilike_lgy10][b2.dat','cophps][he/dw/ls][b3.dat','hlike/hlike_cpb02][b4.dat'])
23+
b_file = np.array(['b0_adf04','b1_adf04','b2_adf04','b3_adf04'])
24+
25+
26+
27+
28+
29+
30+
urllib.request.urlretrieve(url+h_arr[1], 'h1_adf04')
31+
32+
33+
34+
35+
def fix_whitespace(fname):
36+
""" Fix whitespace in a file """
37+
with open(fname, "rb") as fo:
38+
original_contents = fo.read()
39+
# "rU" Universal line endings to Unix
40+
with open(fname, "rU") as fo:
41+
contents = fo.read()
42+
lines = contents.split("\n")
43+
fixed = 0
44+
for k, line in enumerate(lines):
45+
new_line = line.rstrip()
46+
if len(line) != len(new_line):
47+
lines[k] = new_line
48+
fixed += 1
49+
with open(fname, "wb") as fo:
50+
fo.write("\n".join(lines))
51+
if fixed or contents != original_contents:
52+
print("************* %s" % os.path.basename(fname))
53+
if fixed:
54+
slines = "lines" if fixed > 1 else "line"
55+
print("Fixed trailing whitespace on %d %s" \
56+
% (fixed, slines))
57+
if contents != original_contents:
58+
print("Fixed line endings to Unix (\\n)")
Lines changed: 570 additions & 131 deletions
Large diffs are not rendered by default.

ecip_rates.py renamed to colradpy/ecip_rates.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import numpy as np
2-
from r8necip import *
2+
from .r8necip import *
33
####################################################################################################
44
def ecip_rates(energy,ion_pot,zpla,zpla1,charge_state,temp_grid):
55
"""This function gives energy levels to r8necip for ECIP ionization to be
@@ -29,11 +29,12 @@ def ecip_rates(energy,ion_pot,zpla,zpla1,charge_state,temp_grid):
2929
"""
3030
ecip = np.zeros((len(energy),len(ion_pot),len(temp_grid)))
3131
for p in range(0,len(ion_pot)):
32-
#there was a stupid problem beacuse {X} only designates ecip not other ionization
33-
ion_inds = np.where( zpla[:,p] > -1)[0]
34-
ion_inds2 = np.where( zpla1 == p +1)[0]
35-
ion_inds = np.intersect1d(ion_inds,ion_inds2)
36-
ecip[ion_inds,p,:] = r8ecip(charge_state, ion_pot[p],
32+
#there was a stupid problem beacuse {X} only designates ecip not other ionization
33+
ion_inds = np.where( zpla[:,p] > -1)[0]
34+
ion_inds2 = np.where( zpla1 == p +1)[0]
35+
ion_inds = np.intersect1d(ion_inds,ion_inds2)
36+
37+
ecip[ion_inds,p,:] = r8ecip(charge_state, ion_pot[p],
3738
energy[ion_inds],zpla[ion_inds,p],
3839
temp_grid*11604.5)
39-
return ecip
40+
return ecip

colradpy/ionization_balance.py

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
import numpy as np
2+
from .colradpy_class import colradpy
3+
from .solve_matrix_exponential import *
4+
5+
class ionization_balance():
6+
7+
def __init__(self,fils,metas,temp_grid, dens_grid,use_ionization=True,
8+
suppliment_with_ecip=True, use_recombination_three_body=True,use_recombination=True,
9+
keep_species_data=False):
10+
11+
""" Sets up the dictionaries to hold the data.
12+
13+
"""
14+
self.data = {}
15+
self.data['gcrs'] = {}
16+
17+
self.data['user'] = {}
18+
self.data['user']['temp_grid'] = np.asarray(temp_grid) #eV
19+
self.data['user']['dens_grid'] = np.asarray(dens_grid)#cm-3
20+
self.data['user']['use_ionization'] = use_ionization
21+
self.data['user']['suppliment_with_ecip'] = suppliment_with_ecip
22+
self.data['user']['use_recombination_three_body'] = use_recombination_three_body
23+
self.data['user']['use_recombination'] = use_recombination
24+
self.data['user']['keep_species_data'] = keep_species_data
25+
26+
#default is to not keep all of the data from the CR calculations
27+
#this can take up a lot of memory and the general use case for this class only
28+
#calls for the use of GCR coefficients so its kind of a waste to keep all the data
29+
if(keep_species_data):
30+
self.data['stage_data'] = {}
31+
#cycle over all of the ion stages that the user chose and run the CR calculation
32+
#to get the GCR coefficients for that stage
33+
for i in range(0,len(fils)):
34+
#default is for user to just give metastables of the ground state and then
35+
#choose metastables just based off of ionization potentials in adf04 file
36+
#the user can also give a list of metastable states for every ionstage
37+
#and this will override the metastables in the adf04 files
38+
if(type(metas) == list):
39+
meta = metas[i]
40+
else:
41+
if(i == 0):
42+
meta = metas
43+
else:
44+
m = np.shape(self.data['gcrs'][str(i -1)]['scd'])[1]
45+
meta = np.linspace(0,m-1,m,dtype=int)
46+
#setup the CR
47+
48+
tmp = colradpy(str(fils[i]),meta,temp_grid,dens_grid,use_ionization,
49+
suppliment_with_ecip,use_recombination_three_body,use_recombination)
50+
tmp.solve_cr()
51+
#keep the data if requested
52+
if(keep_species_data):
53+
self.data['stage_data'][str(i)] = tmp.data
54+
#keeping all of the GCR data, ionization can be run from this data only
55+
self.data['gcrs'][str(i)] = {}
56+
self.data['gcrs'][str(i)]['qcd'] = tmp.data['processed']['qcd']
57+
self.data['gcrs'][str(i)]['scd'] = tmp.data['processed']['scd']
58+
self.data['gcrs'][str(i)]['acd'] = tmp.data['processed']['acd']
59+
self.data['gcrs'][str(i)]['xcd'] = tmp.data['processed']['xcd']
60+
61+
def populate_ion_matrix(self):
62+
"""This will populate the ionization matrix from the various GCR coefficients
63+
for all of the ionization stages
64+
65+
This matrix in mostly zeros because we don't have ways to connect charge states
66+
that are more than one change away. For example if only ground states are included
67+
this matrix becomes diagonal.
68+
69+
QCDs bring the atom between metastables states in a charge state
70+
SCDS bring the atom to the next charge state
71+
ACDS bring the atom to the previous charge state
72+
XCDS bring the atom to next charge state between the metastables of that level,
73+
through the previous charge state
74+
75+
The columns of this matrix sum to zero
76+
"""
77+
#finding the total number of states to be tracked (metastables)
78+
m = np.shape(self.data['gcrs']['0']['qcd'])[0]#num metastables in ground
79+
m = m + np.shape(self.data['gcrs']['0']['scd'])[1]#num metastables in plus
80+
81+
for i in range(1,len(self.data['gcrs'])):
82+
m = m + np.shape(self.data['gcrs'][str(i)]['scd'])[1]#num of metastales in the plus loop
83+
#create an empty matrix to hold the GCR rates
84+
self.data['ion_matrix'] = np.zeros((m, m,len(self.data['user']['temp_grid']), len(self.data['user']['dens_grid'])))
85+
86+
m = 0
87+
for i in range(0,len(self.data['gcrs'])):
88+
num_met = np.shape(self.data['gcrs'][str(i)]['qcd'])[0]
89+
num_ion = np.shape(self.data['gcrs'][str(i)]['scd'])[1]
90+
diag_met = np.diag_indices(num_met)
91+
diag_ion = np.diag_indices(num_ion)
92+
93+
#populate QCDs in ion balance
94+
self.data['ion_matrix'][m+diag_met[0],m+diag_met[1]] = self.data['ion_matrix'][m+diag_met[0],m+diag_met[1]] \
95+
-np.sum(self.data['gcrs'][str(i)]['qcd'],axis=1)
96+
97+
self.data['ion_matrix'][m:m+num_met,m:m+num_met,:,:]=self.data['ion_matrix'][m:m+num_met,m:m+num_met,:,:]\
98+
+self.data['gcrs'][str(i)]['qcd'].transpose(1,0,2,3)
99+
100+
#populate SCDs in ion balance
101+
self.data['ion_matrix'][m+diag_met[0],m+diag_met[1]] = self.data['ion_matrix'][m+diag_met[0],m+diag_met[1]]\
102+
-np.sum(self.data['gcrs'][str(i)]['scd'],axis=1)
103+
104+
self.data['ion_matrix'][m+num_met:m+num_met+num_ion,m:m+num_met,:,:] = \
105+
self.data['ion_matrix'][m+num_met:m+num_met+num_ion,m:m+num_met,:,:] \
106+
+self.data['gcrs'][str(i)]['scd'].transpose(1,0,2,3)
107+
108+
#populate ACDs in ion balance
109+
self.data['ion_matrix'][m+num_met+diag_ion[0], m+num_met+diag_ion[1] ] = \
110+
self.data['ion_matrix'][m+num_met+diag_ion[0], m+num_met+diag_ion[1] ]-\
111+
np.sum(self.data['gcrs'][str(i)]['acd'],axis=0)
112+
113+
self.data['ion_matrix'][m:m+num_met,m+num_met:m+num_met+num_ion,:,:] = \
114+
self.data['ion_matrix'][m:m+num_met,m+num_met:m+num_met+num_ion,:,:] \
115+
+ self.data['gcrs'][str(i)]['acd']
116+
117+
#populate XCD in ion balance
118+
self.data['ion_matrix'][m+num_met+diag_ion[0], m+num_met+diag_ion[1] ] = \
119+
self.data['ion_matrix'][m+num_met+diag_ion[0], m+num_met+diag_ion[1] ]-\
120+
np.sum(self.data['gcrs'][str(i)]['xcd'],axis=1)
121+
122+
self.data['ion_matrix'][m+num_met:m+num_met+num_ion,m+num_met:m+num_met+num_ion,:,:]=\
123+
self.data['ion_matrix'][m+num_met:m+num_met+num_ion,m+num_met:m+num_met+num_ion,:,:] + \
124+
self.data['gcrs'][str(i)]['xcd'].transpose(1,0,2,3)
125+
126+
m = m + num_met
127+
#self.data['ion_matrix'][m+num_met:m+num_met+num_ion,m:m+num_met,:,:]\
128+
129+
def solve_no_source(self,n0,td_t):
130+
"""Solves the ionization balance matrix given an initial populations and times
131+
132+
:param n0: The initial populations of levels at t=0
133+
:type n0: float array
134+
135+
:param td_t: Solution times
136+
:type td_t: float array
137+
138+
139+
populates the pops, eigen_val and eigen_vec
140+
141+
"""
142+
self.data['pops'],self.data['eigen_val'],self.data['eigen_vec'] = solve_matrix_exponential(
143+
np.einsum('ijkl,l->ijkl',self.data['ion_matrix'],self.data['user']['dens_grid']),n0,td_t)
144+
145+
def solve_source(self,n0,s0,td_t):
146+
"""Solves the ionization balance matrix given an initial populations and times when a source term is present
147+
148+
:param n0: The initial populations of levels at t=0
149+
:type n0: float array
150+
151+
:param td_t: Solution times
152+
:type td_t: float array
153+
154+
155+
populates the pops, eigen_val and eigen_vec
156+
157+
"""
158+
self.data['pops'],self.data['eigen_val'],self.data['eigen_vec'] = solve_matrix_exponential_source(
159+
np.einsum('ijkl,l->ijkl',self.data['ion_matrix'],self.data['user']['dens_grid']),n0,s0,td_t)
160+

0 commit comments

Comments
 (0)