1
2
3 """
4 Running Chemistry and managing output from Chemistry.
5
6 Author: M. Van de Sande (based on MCMax.py of R. Lombaert)
7
8 """
9
10 import os
11 import subprocess
12 from glob import glob
13
14 import cc.path
15 from cc.tools.io import DataIO, Database
16 from cc.modeling.codes.ModelingSession import ModelingSession
17
18
19
20
22
23 """
24 Class that includes all methods required for creating an Chemistry model.
25
26 """
27
28 - def __init__(self,path_chemistry='runTest',replace_db_entry=0,db=None,\
29 single_session=0):
30
31 """
32 Initializing an instance of ModelingSession.
33
34 @keyword db: the Chemistry database
35
36 (default: None)
37 @type db: Database()
38 @keyword replace_db_entry: replace an entry in the Chemistry database with
39 a newly calculated model with a new model id
40 (for instance if some general data not
41 included in the inputfiles is changed)
42
43 (default: 0)
44 @type replace_db_entry: bool
45 @keyword path_chemistry: modeling folder in Chemistry home
46
47 (default: 'runTest')
48 @type path_chemistry: string
49 @keyword new_entries: The new model_ids when replace_db_entry is 1
50 of other models in the grid. These are not
51 replaced!
52
53 (default: [])
54 @type new_entries: list[str]
55 @keyword single_session: If this is the only CC session. Speeds up db
56 check.
57
58 (default: 0)
59 @type single_session: bool
60
61 """
62
63 super(Chemistry, self).__init__(code='Chemistry',path=path_chemistry,\
64 replace_db_entry=replace_db_entry,\
65 single_session=single_session)
66
67 cc.path.cout = os.path.join(cc.path.chemistry,self.path)
68
69
70 self.db = db
71
72
73
74 self.in_progress = False
75
76
77
78 self.inputfilename = os.path.join(cc.path.aux,'inputChemistry.dat')
79 self.standard_inputfile = DataIO.readDict(self.inputfilename,\
80 convert_floats=1,\
81 convert_ints=1,\
82 comment_chars=['#','*'])
83 chemistry_keys = os.path.join(cc.path.aux,'Input_Keywords_Chemistry.dat')
84 self.chemistry_keywords = [line.strip()
85 for line in DataIO.readFile(chemistry_keys)
86 if line]
87
88
89
90
91 - def setCommandKey(self,comm_key,star,star_key=None,alternative=None):
92
93 '''
94 Try setting a key in the command_list from a star instance.
95
96 If the key is unknown, it is left open and will be filled in from the
97 standard gastronoom inputfile.
98
99 @param comm_key: the name of the keyword in the command list
100 @type comm_key: string
101 @param star: Parameter set for this session
102 @type star: Star()
103
104 @keyword star_key: the name of the keyword in Star() (minus '_%s'
105 %key_type (DUST or GAS), which is added as well in a
106 second attempt if the first without the addition is
107 not found). If None, it's equal to comm_key
108
109 (default: None)
110 @type star_key: string
111 @keyword alternative: a default value passed from the standard
112 inputfile that is used if the keyword or the
113 keyword + '_%s'%key_type is not found in Star().
114
115 (default: None)
116 @type alternative: string
117
118 @return: Success?
119 @rtype: bool
120
121 '''
122
123 keyword_int_list = ['PERFORM_ROUTINE']
124 if comm_key.lower() in keyword_int_list: make_int = 1
125 else: make_int = 0
126 return super(Chemistry, self).setCommandKey(comm_key,star,'DUST',\
127 star_key,alternative,\
128 make_int)
129
130
131
132
133
134 - def cCL(self,*args,**kwargs):
135
136 '''
137 Short-hand helper function for compareCommandLists.
138
139 '''
140
141 return self.compareCommandLists(*args,**kwargs)
142
143
144
146
147 """
148 Checking Chemistry database.
149
150 @return: The presence of the Chemistry model in the database
151 @rtype: bool
152
153 """
154
155
156
157
158
159
160 if not self.single_session: self.db.sync()
161 chem_dbfile = self.db._open('r')
162 db_ids = sorted(self.db.keys())
163 for i,model_id in enumerate(db_ids):
164 chem_dict = self.db[model_id]
165 model_bool = self.compareCommandLists(self.command_list.copy(),\
166 chem_dict, 'chemistry')
167 if model_bool:
168 if chem_dict.has_key('IN_PROGRESS'):
169 self.in_progress = True
170 print 'Chemistry model is currently being calculated in a ' +\
171 'different CC modeling session with ID %s'\
172 %(model_id)
173 self.model_id = model_id
174 finished = 1
175 break
176 elif self.replace_db_entry \
177 and model_id not in self.new_entries:
178 print 'Replacing Chemistry database entry for old ID %s'\
179 %model_id
180 del self.db[model_id]
181 finished = 0
182 break
183 else:
184 print 'Chemistry model has been calculated ' + \
185 'before with ID %s'%model_id
186 self.model_id = model_id
187 finished = 1
188 break
189
190
191
192
193 if i == len(self.db)-1:
194 print 'No match found in Chemistry database. ' + \
195 'Calculating new model.'
196 finished = 0
197
198
199 if not self.db.keys():
200 print 'No match found in Chemistry database. Calculating new model.'
201 finished = 0
202
203
204 if finished == 0:
205 self.model_id = self.makeNewId()
206 self.db[self.model_id] = self.command_list.copy()
207 self.db[self.model_id]['IN_PROGRESS'] = 1
208
209
210 if not self.db.keys():
211 print 'No match found in Chemistry database. Calculating new model.'
212 finished = 0
213
214
215 chem_dbfile.close()
216 if not self.single_session: self.db.sync()
217 return finished
218
219
220
222
223 """
224 Running Chemistry.
225
226 @param star: The parameter set for this session
227 @type star: Star()
228
229 """
230
231 print '***********************************'
232
233 print '** Making input file for Chemistry'
234
235
236 if self.model_id:
237 self.new_entries.append(self.model_id)
238 self.model_id = ''
239 self.command_list = dict()
240
241
242
243
244 if star['PERFORM_ROUTINE'] == 0:
245 self.command_list['ROUTINE_RADIUS'] = 0
246 else:
247 self.command_list['ROUTINE_RADIUS'] = star['ROUTINE_RADIUS']
248
249 self.command_list['R_STAR'] = star['R_STAR']*star.Rsun
250
251
252
253
254
255 self.command_list['REACTIONS_FILE'] = '"'+os.path.join(cc.path.csource,\
256 'rates',star['REACTIONS_FILE'])+'"'
257 self.command_list['SPECIES_FILE'] = '"'+os.path.join(cc.path.csource,\
258 'specs',star['SPECIES_FILE'])+'"'
259 self.command_list['FILECO'] = '"'+os.path.join(cc.path.csource,\
260 'shielding',star['FILECO'])+'"'
261 self.command_list['FILEN2'] = '"'+os.path.join(cc.path.csource,\
262 star['FILEN2'])+'"'
263
264 add_keys = [k
265 for k in self.standard_inputfile.keys()
266 if not self.command_list.has_key(k)]
267 [self.setCommandKey(k,star,star_key=k.upper(),\
268 alternative=self.standard_inputfile[k])
269 for k in add_keys]
270
271 print '** DONE!'
272 print '***********************************'
273
274
275 modelbool = self.checkDatabase()
276
277
278
279 if not modelbool:
280 input_dict = self.command_list.copy()
281 input_lines = []
282 orig = DataIO.readFile(self.inputfilename)
283 for i,s in enumerate(orig):
284 split = s.split()
285 if s[0] == '!':
286 input_lines.append(s)
287 else:
288 input_lines.append(" ".join(split[0:2])+' '+\
289 str(self.command_list[split[0]]))
290 output_folder = os.path.join(cc.path.cout,'models',self.model_id)
291 DataIO.testFolderExistence(output_folder)
292 input_lines.append('OUTPUT_FOLDER = "' +\
293 output_folder+'/"')
294
295 input_filename = os.path.join(cc.path.cout,'models',\
296 'inputChemistry_%s.txt'%self.model_id)
297
298 DataIO.writeFile(filename=input_filename,input_lines=input_lines)
299
300
301 subprocess.call(' '.join([os.path.join(cc.path.csource,'csmodel'),input_filename]),shell=True)
302
303
304
305 testf1 = os.path.join(output_folder,'cscoldens.out')
306 testf2 = os.path.join(output_folder,'csfrac.out')
307 if os.path.exists(testf1) and os.path.exists(testf2) and \
308 os.path.isfile(testf1) and os.path.isfile(testf2):
309 del self.db[self.model_id]['IN_PROGRESS']
310 self.db.addChangedKey(self.model_id)
311 else:
312 print '** Model calculation failed. No entry is added to ' + \
313 'the database.'
314 del self.db[self.model_id]
315 self.model_id = ''
316 if not self.single_session: self.db.sync()
317
318
319
320 print '***********************************'
321