def chem_scheme_SMILES_extr(sch_name, xml_name, chem_scheme_markers): # inputs: ------------------------------------------ # sch_name - path to chemical scheme # xml_name - path to xml name # chem_scheme_markers - markers for chemical scheme # ---------------------------------------------------- # initiate with empty error message err_mess = '' f_open_eqn = open(sch_name, mode='r') # open the chemical scheme file # read the file and store everything into a list total_list_eqn = f_open_eqn.readlines() f_open_eqn.close() # close file # interrogate scheme to list equations [eqn_list, aqeqn_list, eqn_num, rrc, rrc_name, RO2_names] = sch_interr.sch_interr(total_list_eqn, chem_scheme_markers) # interrogate xml to list all component names and SMILES [comp_smil, comp_name] = xml_interr.xml_interr(xml_name) comp_namelist = [ ] # list for chemical scheme names of components in the chemical scheme comp_list = [ ] # list for the SMILE strings of components present in the chemical scheme for eqn_step in range(eqn_num[0]): # loop through gas-phase reactions line = eqn_list[eqn_step] # extract this line # work out whether equation or reaction rate coefficient part comes first eqn_start = str('.*\\' + chem_scheme_markers[10]) rrc_start = str('.*\\' + chem_scheme_markers[9]) # get index of these markers, note span is the property of the match object that # gives the location of the marker eqn_start_indx = (re.match(eqn_start, line)).span()[1] rrc_start_indx = (re.match(rrc_start, line)).span()[1] if (eqn_start_indx > rrc_start_indx): eqn_sec = 1 # equation is second part else: eqn_sec = 0 # equation is first part # split the line into 2 parts: equation and rate coefficient # . means match with anything except a new line character., when followed by a * # means match zero or more times (so now we match with all characters in the line # except for new line characters, so final part is stating the character(s) we # are specifically looking for, \\ ensures the marker is recognised if eqn_sec == 1: eqn_markers = str('\\' + chem_scheme_markers[10] + '.*\\' + chem_scheme_markers[11]) else: # end of equation part is start of reaction rate coefficient part eqn_markers = str('\\' + chem_scheme_markers[10] + '.*\\' + chem_scheme_markers[9]) # extract the equation as a string ([0] extracts the equation section and # [1:-1] removes the bounding markers) eqn = re.findall(eqn_markers, line)[0][1:-1].strip() eqn_split = eqn.split() eqmark_pos = eqn_split.index('=') # reactants with stoichiometry number and omit any photon reactants = [ i for i in eqn_split[:eqmark_pos] if i != '+' and i != 'hv' ] # products with stoichiometry number products = [t for t in eqn_split[eqmark_pos + 1:] if t != '+'] stoich_regex = r"^\d*\.\d*|^\d*" # necessary for checking for stoichiometries for reactant in reactants: # left hand side of equations (losses) if (re.findall(stoich_regex, reactant)[0] != ''): # when stoichiometry included # name with no stoichiometry number name_only = re.sub(stoich_regex, '', reactant) elif (re.findall( stoich_regex, reactant)[0] == ''): # when stoichiometry excluded name_only = reactant if (name_only not in comp_namelist): # if new component encountered comp_namelist.append( name_only) # add to chemical scheme name list # convert MCM chemical names to SMILES if (name_only in comp_name): # index where xml file name matches reaction component name name_indx = comp_name.index(name_only) name_SMILE = comp_smil[name_indx] # SMILES of component comp_list.append(name_SMILE) # list SMILE names else: err_mess = str('Error - chemical scheme name ' + str(name_only) + ' not found in xml file') return (comp_namelist, comp_list, err_mess, H2Oi) for product in products: # right hand side of equations (gains) if (re.findall(stoich_regex, product)[0] != ''): # when stoichiometry included # name with no stoichiometry number name_only = re.sub(stoich_regex, '', product) elif (re.findall(stoich_regex, product)[0] == ''): # when stoichiometry excluded name_only = product if (name_only not in comp_namelist): # if new component encountered comp_namelist.append( name_only) # add to chemical scheme name list # convert MCM chemical names to SMILES # index where xml file name matches reaction component name if name_only in comp_name: name_indx = comp_name.index(name_only) name_SMILE = comp_smil[name_indx] comp_list.append(name_SMILE) # list SMILE names else: err_mess = str('Error - chemical scheme name ' + str(name_only) + ' not found in xml file') return (comp_namelist, comp_list, err_mess, H2Oi) # check for water presence in chemical scheme via its SMILE string # count on components indx = -1 for single_chem in comp_list: indx += 1 # ensure this is water rather than single oxygen (e.g. due to ozone photolysis # (O is the MCM chemical scheme name for single oxygen)) if (single_chem == 'O' and comp_namelist[indx] != 'O'): H2Oi = indx else: # if not in chemical scheme, water would be the next component appended to component list H2Oi = len(comp_list) comp_namelist.append('H2O') return (comp_namelist, comp_list, err_mess, H2Oi)
def extr_mech(sch_name, chem_sch_mrk, xml_name, photo_path, con_infl_nam, int_tol, wall_on, num_sb, const_comp, drh_str, erh_str): # inputs: ---------------------------------------------------- # sch_name - file name of chemical scheme # chem_sch_mrk - markers to identify different sections of # the chemical scheme # xml_name - name of xml file # photo_path - path to file containing absorption # cross-sections and quantum yields # con_infl_nam - chemical scheme names of components with # constant influx # int_tol - integration tolerances # wall_on - marker for whether to include wall partitioning # num_sb - number of size bins (including any wall) # const_comp - chemical scheme name of components with # constant concentration # drh_str - string from user inputs describing # deliquescence RH (fraction 0-1) as function of temperature (K) # erh_str - string from user inputs describing # efflorescence RH (fraction 0-1) as function of temperature (K) # ------------------------------------------------------------ f_open_eqn = open(sch_name, mode='r') # open the chemical scheme file # read the file and store everything into a list total_list_eqn = f_open_eqn.readlines() f_open_eqn.close() # close file # interrogate scheme to list equations [eqn_list, aqeqn_list, eqn_num, rrc, rrc_name, RO2_names] = sch_interr.sch_interr(total_list_eqn, chem_sch_mrk) # interrogate xml to list all component names and SMILES [comp_smil, comp_name] = xml_interr.xml_interr(xml_name) # get equation information for chemical reactions [ rindx_g, rstoi_g, pindx_g, pstoi_g, reac_coef_g, nreac_g, nprod_g, jac_stoi_g, jac_den_indx_g, njac_g, jac_indx_g, y_arr_g, y_rind_g, uni_y_rind_g, y_pind_g, uni_y_pind_g, reac_col_g, prod_col_g, rstoi_flat_g, pstoi_flat_g, rr_arr_g, rr_arr_p_g, rindx_aq, rstoi_aq, pindx_aq, pstoi_aq, reac_coef_aq, nreac_aq, nprod_aq, jac_stoi_aq, jac_den_indx_aq, njac_aq, jac_indx_aq, y_arr_aq, y_rind_aq, uni_y_rind_aq, y_pind_aq, uni_y_pind_aq, reac_col_aq, prod_col_aq, rstoi_flat_aq, pstoi_flat_aq, rr_arr_aq, rr_arr_p_aq, comp_namelist, comp_list, Pybel_objects, comp_num ] = eqn_interr.eqn_interr(eqn_num, eqn_list, aqeqn_list, chem_sch_mrk, comp_name, comp_smil, num_sb, wall_on) [rowvals, colptrs, jac_indx_g, jac_indx_aq, jac_part_indx, jac_wall_indx ] = jac_setup.jac_setup(jac_den_indx_g, njac_g, comp_num, num_sb, eqn_num, nreac_g, nprod_g, rindx_g, pindx_g, jac_indx_g, wall_on, nreac_aq, nprod_aq, rindx_aq, pindx_aq, jac_indx_aq, (num_sb - wall_on)) # prepare aqueous-phase reaction matrices for applying to reaction rate calculation if (eqn_num[1] > 0): # if aqueous-phase reactions present [ rindx_aq, rstoi_aq, pindx_aq, pstoi_aq, reac_coef_aq, nprod_aq, jac_stoi_aq, njac_aq, jac_den_indx_aq, jac_indx_aq, y_arr_aq, y_rind_aq, uni_y_rind_aq, y_pind_aq, uni_y_pind_aq, reac_col_aq, prod_col_aq, rstoi_flat_aq, pstoi_flat_aq, rr_arr_aq, rr_arr_p_aq ] = aq_mat_prep.aq_mat_prep( rindx_aq, rstoi_aq, pindx_aq, pstoi_aq, reac_coef_aq, nprod_aq, jac_stoi_aq, njac_aq, jac_den_indx_aq, jac_indx_aq, y_arr_aq, y_rind_aq, uni_y_rind_aq, y_pind_aq, uni_y_pind_aq, reac_col_aq, prod_col_aq, rstoi_flat_aq, pstoi_flat_aq, rr_arr_aq, rr_arr_p_aq, num_sb, wall_on, eqn_num[1], comp_num) # get index of components with constant influx/concentration ----------- # empty array for storing index of components with constant influx con_infl_indx = np.zeros((len(con_infl_nam))) con_C_indx = np.zeros((len(const_comp))) for i in range(len(con_infl_nam)): # index of where constant components occur in list of components con_infl_indx[i] = comp_namelist.index(con_infl_nam[i]) for i in range(len(const_comp)): # index of where constant concnetration components occur in list # of components con_C_indx[i] = comp_namelist.index(const_comp[i]) # --------------------------------------------------------------------- # call function to generate ordinary differential equation (ODE) # solver module, add two to comp_num to account for water and core component write_ode_solv.ode_gen(con_infl_indx, int_tol, rowvals, wall_on, comp_num + 2, (num_sb - wall_on), con_C_indx, 0, eqn_num) # call function to generate reaction rate calculation module write_rate_file.write_rate_file(reac_coef_g, reac_coef_aq, rrc, rrc_name, 0) # call function to generate module that tracks change tendencies # of certain components write_dydt_rec.write_dydt_rec() # write the module for estimating deliquescence and efflorescence # relative humidities as a function of temperature write_hyst_eq.write_hyst_eq(drh_str, erh_str) # get index of components in the peroxy radical list RO2_indx = RO2_indices.RO2_indices(comp_namelist, RO2_names) # get number of photolysis equations Jlen = photo_num.photo_num(photo_path) return (rindx_g, pindx_g, rstoi_g, pstoi_g, nreac_g, nprod_g, jac_stoi_g, njac_g, jac_den_indx_g, jac_indx_g, y_arr_g, y_rind_g, uni_y_rind_g, y_pind_g, uni_y_pind_g, reac_col_g, prod_col_g, rstoi_flat_g, pstoi_flat_g, rr_arr_g, rr_arr_p_g, rowvals, colptrs, jac_wall_indx, jac_part_indx, comp_num, RO2_indx, comp_list, Pybel_objects, eqn_num, comp_namelist, Jlen, rindx_aq, rstoi_aq, pindx_aq, pstoi_aq, reac_coef_aq, nreac_aq, nprod_aq, jac_stoi_aq, jac_den_indx_aq, njac_aq, jac_indx_aq, y_arr_aq, y_rind_aq, uni_y_rind_aq, y_pind_aq, uni_y_pind_aq, reac_col_aq, prod_col_aq, rstoi_flat_aq, pstoi_flat_aq, rr_arr_aq, rr_arr_p_aq, comp_name, comp_smil)
except: # when calling from GMD paper Results folder output_by_sim = str(cwd + '/fig07_data/Gaswall_sens_Cw0_kw1e2') # required outputs (num_sb, num_comp, Cfac, y, Ndry, rbou_rec, xfm, t_array, comp_names, y_mw, N, _, y_MV, _, wall_on, space_mode) = retr_out.retr_out(output_by_sim) # required outputs from full-moving (num_sb, num_comp, Cfac, y, Ndry, rbou_rec, xfm, t_array, comp_names, y_mw, N, _, y_MV, _, wall_on, space_mode) = retr_out.retr_out(output_by_sim) # get all SMILE strings from the xml file # interrogate xml to list component names and SMILES try: # when calling from the PyCHAM home directory [comp_smil, comp_name] = xml_interr.xml_interr(str(cwd + '/PyCHAM/input/example_xml.xml')) except: # when calling from the GMD paper Results folder [comp_smil, comp_name] = xml_interr.xml_interr(str(cwd + '/example_xml.xml')) # convert chemical scheme component names into SMILEs comp_smiles = [] # holder for name in comp_names[0:-2]: # omit H20 and core at end of comp_names comp_smiles.append(comp_smil[comp_name.index(name)]) SOA0 = 0. for i in range(1, num_sb): # calculate SOA (*1.0E-12 to convert from g/cc (air) to ug/m3 (air)) SOA0 += (((y[:, num_comp*i:num_comp*(i+1)-2]/si.N_A)*y_mw[0:-2]*1.0e12).sum(axis=1)) Pybel_objects = [] # holder for Pybel object names for i in range(num_comp-2): # component loop
def extr_mech(sch_name, chem_sch_mrk, xml_name, photo_path, con_infl_nam, int_tol, wall_on, num_sb, const_comp, drh_str, erh_str, dil_fac, sav_nam, pcont): # inputs: ---------------------------------------------------- # sch_name - file name of chemical scheme # chem_sch_mrk - markers to identify different sections of # the chemical scheme # xml_name - name of xml file # photo_path - path to file containing absorption # cross-sections and quantum yields # con_infl_nam - chemical scheme names of components with # constant influx # int_tol - integration tolerances # wall_on - marker for whether to include wall partitioning # num_sb - number of size bins (including any wall) # const_comp - chemical scheme name of components with # constant concentration # drh_str - string from user inputs describing # deliquescence RH (fraction 0-1) as function of temperature (K) # erh_str - string from user inputs describing # efflorescence RH (fraction 0-1) as function of temperature (K) # dil_fac - fraction of chamber air extracted/s # sav_nam - name of folder to save results to # pcont - flag for whether seed particle injection is # instantaneous (0) or continuous (1) # ------------------------------------------------------------ # starting error flag and message (assumes no errors) erf = 0 err_mess = '' f_open_eqn = open(sch_name, mode='r') # open the chemical scheme file # read the file and store everything into a list total_list_eqn = f_open_eqn.readlines() f_open_eqn.close() # close file # interrogate scheme to list equations [eqn_list, aqeqn_list, eqn_num, rrc, rrc_name, RO2_names] = sch_interr.sch_interr(total_list_eqn, chem_sch_mrk) # interrogate xml to list all component names and SMILES [comp_smil, comp_name] = xml_interr.xml_interr(xml_name) # get equation information for chemical reactions [ rindx_g, rstoi_g, pindx_g, pstoi_g, reac_coef_g, nreac_g, nprod_g, jac_stoi_g, jac_den_indx_g, njac_g, jac_indx_g, y_arr_g, y_rind_g, uni_y_rind_g, y_pind_g, uni_y_pind_g, reac_col_g, prod_col_g, rstoi_flat_g, pstoi_flat_g, rr_arr_g, rr_arr_p_g, rindx_aq, rstoi_aq, pindx_aq, pstoi_aq, reac_coef_aq, nreac_aq, nprod_aq, jac_stoi_aq, jac_den_indx_aq, njac_aq, jac_indx_aq, y_arr_aq, y_rind_aq, uni_y_rind_aq, y_pind_aq, uni_y_pind_aq, reac_col_aq, prod_col_aq, rstoi_flat_aq, pstoi_flat_aq, rr_arr_aq, rr_arr_p_aq, comp_namelist, comp_list, Pybel_objects, comp_num, RO_indx ] = eqn_interr.eqn_interr(eqn_num, eqn_list, aqeqn_list, chem_sch_mrk, comp_name, comp_smil, num_sb, wall_on) [ rowvals, colptrs, jac_indx_g, jac_indx_aq, jac_part_indx, jac_wall_indx, jac_extr_indx ] = jac_setup.jac_setup(jac_den_indx_g, njac_g, comp_num, num_sb, eqn_num, nreac_g, nprod_g, rindx_g, pindx_g, jac_indx_g, wall_on, nreac_aq, nprod_aq, rindx_aq, pindx_aq, jac_indx_aq, (num_sb - wall_on), dil_fac) # prepare aqueous-phase reaction matrices for applying to reaction rate calculation if (eqn_num[1] > 0): # if aqueous-phase reactions present [ rindx_aq, rstoi_aq, pindx_aq, pstoi_aq, reac_coef_aq, nprod_aq, jac_stoi_aq, njac_aq, jac_den_indx_aq, jac_indx_aq, y_arr_aq, y_rind_aq, uni_y_rind_aq, y_pind_aq, uni_y_pind_aq, reac_col_aq, prod_col_aq, rstoi_flat_aq, pstoi_flat_aq, rr_arr_aq, rr_arr_p_aq ] = aq_mat_prep.aq_mat_prep( rindx_aq, rstoi_aq, pindx_aq, pstoi_aq, reac_coef_aq, nprod_aq, jac_stoi_aq, njac_aq, jac_den_indx_aq, jac_indx_aq, y_arr_aq, y_rind_aq, uni_y_rind_aq, y_pind_aq, uni_y_pind_aq, reac_col_aq, prod_col_aq, rstoi_flat_aq, pstoi_flat_aq, rr_arr_aq, rr_arr_p_aq, num_sb, wall_on, eqn_num[1], comp_num) # get index of components with constant influx/concentration ----------- # empty array for storing index of components with constant influx con_infl_indx = np.zeros((len(con_infl_nam))) con_C_indx = np.zeros((len(const_comp))).astype('int') for i in range(len(con_infl_nam)): # water not included explicitly in chemical schemes but accounted for later in init_conc if (con_infl_nam[i] == 'H2O'): con_infl_indx[i] = comp_num continue try: # index of where components with constant influx occur in list of components con_infl_indx[i] = comp_namelist.index(con_infl_nam[i]) except: erf = 1 # raise error err_mess = str( 'Error: constant influx component with name ' + str(con_infl_nam[i]) + ' has not been identified in the chemical scheme, please check it is present and the chemical scheme markers are correct' ) for i in range(len(const_comp)): try: # index of where constant concentration components occur in list # of components con_C_indx[i] = comp_namelist.index(const_comp[i]) except: erf = 1 # raise error err_mess = str( 'Error: constant concentration component with name ' + str(const_comp[i]) + ' has not been identified in the chemical scheme, please check it is present and the chemical scheme markers are correct' ) # --------------------------------------------------------------------- # call function to generate ordinary differential equation (ODE) # solver module, add two to comp_num to account for water and core component write_ode_solv.ode_gen(con_infl_indx, int_tol, rowvals, wall_on, comp_num + 2, (num_sb - wall_on), 0, eqn_num, dil_fac, sav_nam, pcont) # call function to generate reaction rate calculation module write_rate_file.write_rate_file(reac_coef_g, reac_coef_aq, rrc, rrc_name, 0) # call function to generate module that tracks change tendencies # of certain components write_dydt_rec.write_dydt_rec() # write the module for estimating deliquescence and efflorescence # relative humidities as a function of temperature write_hyst_eq.write_hyst_eq(drh_str, erh_str) # get index of components in the peroxy radical list RO2_indx = RO2_indices.RO2_indices(comp_namelist, RO2_names) # get index of HOM-RO2 radicals HOMRO2_indx = RO2_indices.HOMRO2_indices(comp_namelist) # get number of photolysis equations Jlen = photo_num.photo_num(photo_path) return (rindx_g, pindx_g, rstoi_g, pstoi_g, nreac_g, nprod_g, jac_stoi_g, njac_g, jac_den_indx_g, jac_indx_g, y_arr_g, y_rind_g, uni_y_rind_g, y_pind_g, uni_y_pind_g, reac_col_g, prod_col_g, rstoi_flat_g, pstoi_flat_g, rr_arr_g, rr_arr_p_g, rowvals, colptrs, jac_wall_indx, jac_part_indx, jac_extr_indx, comp_num, RO2_indx, RO_indx, HOMRO2_indx, comp_list, Pybel_objects, eqn_num, comp_namelist, Jlen, rindx_aq, rstoi_aq, pindx_aq, pstoi_aq, reac_coef_aq, nreac_aq, nprod_aq, jac_stoi_aq, jac_den_indx_aq, njac_aq, jac_indx_aq, y_arr_aq, y_rind_aq, uni_y_rind_aq, y_pind_aq, uni_y_pind_aq, reac_col_aq, prod_col_aq, rstoi_flat_aq, pstoi_flat_aq, rr_arr_aq, rr_arr_p_aq, comp_name, comp_smil, erf, err_mess, con_C_indx)