コード例 #1
0
ファイル: globchem.py プロジェクト: tsherwen/PyGChem
def read_globchem_dat(filename):
    """
    Read and parse the "globchem.dat" globchem_file (SMVGEARII syntax).

    Parameters
    ----------
    filename : string
        Filename or path to the global chemistry globchem_file (globchem.dat)

    Returns
    -------
    header : string
        header (commented text) of the file
    mb_groups : dict
        mass balance groups (id, status): used for mass balance capability of
        chemical solvers (SMVGEARII or KPP)
    species : dict
        chemical species
    reac_kn : dict
        list of chemical kinectic reactions
    reac_ph : dict
        list of photolysis reactions
    species_links : list of tuples
        links between species made by the kinectic reactions

    """

    species = dict()
    reac_kn = dict()
    reac_ph = dict()
    species_links = list()

    # keys of 'species' and 'reac' dictionnaries
    species_keys = [
        'ord_n', 'fline', 'status', 'id', 'absorption', 'atomic_mass',
        'init_concentration', 'mb_groups', 'formula', 'name'
    ]
    reac_keys = [
        'ord_n', 'fline', 'status', 'flag', 'comment', 'rate', 'reactants',
        'products', 'coefs'
    ]

    def sanatize_str_inlist(l):
        """
        clean (strip...) string items in a list
        """
        return ([x.strip() if type(x) is str else x for x in l])

    def go_2_begin(globchem_file, fline):
        """
        jump lines in the text file until reading the line
        with the word "BEGIN"
        """
        jumptext = ""
        while True:
            text = globchem_file.readline().strip()
            fline += 1
            if (text == "BEGIN"):
                break
            else:
                jumptext += text + '\n'
        return jumptext

    def convert_species_item(species_item, mb_groups):
        """
        Make the conversion (type and/or format), for each species, between
        the blocks of information encoded in the file globchem.dat and the
        dictionary items used in pygchem.
        """
        #species_item['absorption'] == bool(species_item['absorption'])
        species_item['absorption'] = False  # not used in GEOS-Chem
        species_item['atomic_mass'] = float(species_item['atomic_mass'])
        species_item['init_concentration'] = [
            float(i) for i in species_item['init_concentration']
        ]
        mb_vals = [int(i) for i in species_item['mb_groups']]
        species_item['mb_groups'] = dict(zip(mb_groups.keys(), mb_vals))

    def trim_rlist(reac_list):
        """
        Take a 'reaction list' (e.g. reactants, products or stoichiometric
        coefficients) and return a list with removed empty items
        """
        # filter below permits to take only items that are not '' (if string)
        # or 0 (if int or float) because bool('') and bool(0) both return False
        return filter(bool, reac_list)

    def read_reac(globchem_file, fline):
        """
        Reads a 'chemical reaction' bloc of lines in
        globchem.dat

        Returns
        -------
        - reac_item: dict
            an item of the reaction dictionnary (see ...)
        """

        reac_r1_fmt = FortranRecordReader('(A1,1X,I4,1X,ES8.2,1X,ES8.1,1X,'
                                          'I6,1X,I1,1X,A2,F6.2,1X,2(F6.0,1X),'
                                          'A20)')
        reac_r2_fmt = FortranRecordReader('(7X,ES8.2,1X,ES8.1,1X,I6,1X,I1,3X,'
                                          'F6.2,1X,2(F6.0,1X))')
        reac_eq_fmt = FortranRecordReader('(4(A1,0PF5.3,A14)/'
                                          '4(A1,0PF5.3,A14)/'
                                          '4(A1,0PF5.3,A14)/'
                                          '4(A1,0PF5.3,A14)/'
                                          '4(A1,0PF5.3,A14))')

        # re-arrange reaction rate parameters:
        # parameter names for values (one-line) read in globchem.dat
        # and correspondence between structure in globchem.dat and structure
        # of pygchem.globchem module, depending on the reaction flag.
        # note that reac_rates_keys are modified for additional lines of
        # parameters (e.g., for line 1, 'AR' becomes 'AR1')
        # TODO: move this information to a separate function to make it
        # available to export functions
        reac_rates_keys = ['AR', 'BR', 'CR', 'FCV', 'FCT1', 'FCT2']
        mod_ratep = {
            '': {
                'arr': ['AR', 'BR', 'CR']
            },
            'P': {
                'arrlow': ['AR', 'BR', 'CR'],
                'arrhigh': ['AR1', 'BR1', 'CR1'],
                'falloff': ['FCV', 'FCT1', 'FCT2']
            },
            'E': {
                'arr': ['AR', 'BR', 'CR']
            },
            'X': {
                'arrK0': ['AR', 'BR', 'CR'],
                'arrK2': ['AR1', 'BR1', 'CR1'],
                'arrK3': ['AR2', 'BR2', 'CR2']
            },
            'Y': {
                'arrK0': ['AR', 'BR', 'CR']
            },
            'Z': {
                'arrK1': ['AR', 'BR', 'CR'],
                'arrK2': ['AR1', 'BR1', 'CR1']
            },
            'A': {
                'arrK1': ['AR', 'BR', 'CR'],
                'xcarbon': 'AR1'
            },
            'B': {
                'arrK1': ['AR', 'BR', 'CR'],
                'xcarbon': 'AR1'
            },
            'C': {
                'arrK1': ['AR', 'BR', 'CR']
            },
            'D': {
                'arrK1': ['AR', 'BR', 'CR']
            },
            'V': {
                'arrK1': ['AR', 'BR', 'CR'],
                'arrK2': ['AR1', 'BR1', 'CR1']
            },
            'G': {
                'arrK1': ['AR', 'BR', 'CR'],
                'arrK2': ['AR1', 'BR1', 'CR1']
            },
        }

        # check if end of reaction list
        l_globchem = globchem_file.readline().strip()
        if (l_globchem[0:4] == "9999"):
            fline += 1
            return "end"

        # read reaction info
        reac_row1 = sanatize_str_inlist(reac_r1_fmt.read(l_globchem)) + [fline]
        reac_item = [reac_row1[i] for i in [1, -1, 0, 6, -2]]

        # read reaction rate parameters
        n_addrates = reac_row1.pop(5)
        reac_rates = dict(zip(reac_rates_keys,
                              reac_row1[2:5] + reac_row1[6:9]))
        if (n_addrates > 0):
            for i in range(0, n_addrates):
                new_keys = [s + str(i + 1) for s in reac_rates_keys]
                l_globchem = globchem_file.readline()
                fline += 1
                reac_row2 = reac_r2_fmt.read(l_globchem)
                del reac_row2[3]  # remove slot for number of rate coef lines
                reac_rates.update(dict(zip(new_keys, reac_row2)))

        # re-arrange rate parameters using corr_ratep
        reac_flag = reac_item[3].upper()
        mod_reac_rates = dict()
        if reac_flag in mod_ratep:
            for k, v in mod_ratep[reac_flag].items():
                if (isinstance(v, collections.Iterable)
                        and not isinstance(v, basestring)):
                    mod_reac_rates[k] = [reac_rates[n] for n in v]
                else:
                    mod_reac_rates[k] = reac_rates[v]
        else:
            mod_reac_rates.update(reac_rates)

        reac_item.append(mod_reac_rates)

        # read reaction equation
        l_globchem = ""
        for i in range(0, 5):
            l_globchem += globchem_file.readline()
            fline += 1
        reac_eq = sanatize_str_inlist(reac_eq_fmt.read(l_globchem))

        del reac_eq[0]
        if (reac_eq[-2] is None):
            reac_eq[-2] = 0.0

        reac_item.append(trim_rlist([reac_eq[i] for i in xrange(1, 13, 3)]))
        reac_item.append(trim_rlist([reac_eq[i] for i in xrange(13, 61, 3)]))
        reac_item.append(trim_rlist([reac_eq[i] for i in range(12, 60, 3)]))

        return reac_item

    # path to additional info files
    _dir_path = os.path.dirname(os.path.abspath(__file__))
    finfo_path = os.path.join(_dir_path, "..", "data")

    # read species.dat (get more info about species)
    species_info = {}
    s_fmt = FortranRecordReader('(A11,A32,A40)')
    f_species_dat = open(os.path.join(finfo_path, "species.dat"), "r")
    f_species_dat.readline()
    for line in f_species_dat:
        row = s_fmt.read(line)
        row = [s.strip() for s in row]
        species_info[row[0]] = row[1:]
    f_species_dat.close()
    species_info_blank = ['' for s in xrange(0, len(species_info.keys()[0]))]

    # globchem.dat file
    globchem_file = open(filename, "r")

    # get header/comments of globchem.dat
    fline = 1
    species_subheader = _format_subheader("Species List")
    header = go_2_begin(globchem_file, fline).replace(species_subheader, "")

    # read in species
    n_species = 0

    #    mass balance groups (id and status)
    species_mb_id_fmt = FortranRecordReader('20X,A3,8(1X,A3)')
    l_globchem = globchem_file.readline()
    mb_id = sanatize_str_inlist(species_mb_id_fmt.read(l_globchem))

    species_mb_st_fmt = FortranRecordReader('21X,A1,8(3X,A1)')
    l_globchem = globchem_file.readline()
    mb_st = sanatize_str_inlist(species_mb_st_fmt.read(l_globchem))

    mb_groups = dict(zip(mb_id, mb_st))
    fline += 2

    species_r1_fmt = FortranRecordReader('(A1,1X,A14,A2,1X,0PF6.2,4(1PE10.3))')
    while True:
        l_globchem = globchem_file.readline().strip()
        if (l_globchem == "END"):
            break

        species_r1 = sanatize_str_inlist(species_r1_fmt.read(l_globchem))
        species_this_key = species_r1[1]
        species_vals = ([n_species, fline] + species_r1[0:4] +
                        [species_r1[4:]] +
                        [[int(i) for i in globchem_file.readline().split()]])
        try:
            species_vals += species_info[species_this_key]
        except KeyError:
            species_vals += species_info_blank

        species[species_this_key] = dict(zip(species_keys, species_vals))
        convert_species_item(species[species_this_key], mb_groups)
        del species_vals
        n_species += 1
        fline += 2

    # read in reactions
    go_2_begin(globchem_file, fline)
    mem_p_ratep = dict()
    n_reac = 0
    while True:
        reac_vals = read_reac(globchem_file, fline)
        if (reac_vals == "end"):
            break
        else:
            # case for reaction with E special flag (reverse equilibrium)
            # --> add rate params of previous reaction with P flag
            reac_flag = reac_vals[3]
            if reac_flag == 'P':
                mem_p_ratep = reac_vals[5]
            elif reac_flag == 'E':
                reac_vals[5].update(mem_p_ratep)

            reac_kn[n_reac] = dict(zip(reac_keys, reac_vals))
            reac_kn[n_reac]['id'] = n_reac
            n_reac += 1
        del reac_vals

    go_2_begin(globchem_file, fline)
    n_reac = 0
    while True:
        reac_vals = read_reac(globchem_file, fline)
        if (reac_vals == "end"):
            break
        else:
            reac_ph[n_reac] = dict(zip(reac_keys, reac_vals))
            reac_ph[n_reac]['id'] = n_reac
            n_reac += 1
        del reac_vals

    # identify links between species (through reactions): parse reac_kn
    link_id = 0
    for reac_key, reac_vals in reac_kn.iteritems():
        for reactant in reac_vals['reactants']:
            if (reactant != '' and reactant != 'M'):
                for product in reac_vals['products']:
                    if (product != ''):
                        species_links.append(
                            (link_id, reac_key, reactant, product))
                        link_id += 1

    # close globchem_file
    globchem_file.close()

    return header, mb_groups, species, reac_kn, reac_ph
コード例 #2
0
ファイル: globchem.py プロジェクト: benbovy/PyGChem
def read_globchem_dat(filename):
    """
    Read and parse the "globchem.dat" globchem_file (SMVGEARII syntax).

    Parameters
    ----------
    filename : string
        Filename or path to the global chemistry globchem_file (globchem.dat)

    Returns
    -------
    header : string
        header (commented text) of the file
    mb_groups : dict
        mass balance groups (id, status): used for mass balance capability of
        chemical solvers (SMVGEARII or KPP)
    species : dict
        chemical species
    reac_kn : dict
        list of chemical kinectic reactions
    reac_ph : dict
        list of photolysis reactions
    species_links : list of tuples
        links between species made by the kinectic reactions

    """

    species = dict()
    reac_kn = dict()
    reac_ph = dict()
    species_links = list()

    # keys of 'species' and 'reac' dictionnaries
    species_keys = ['ord_n', 'fline', 'status', 'id', 'absorption',
                    'atomic_mass', 'init_concentration', 'mb_groups',
                    'formula', 'name']
    reac_keys = ['ord_n', 'fline', 'status', 'flag', 'comment',
                 'rate', 'reactants', 'products', 'coefs']

    def sanatize_str_inlist(l):
        """
        clean (strip...) string items in a list
        """
        return([x.strip() if type(x) is str else x for x in l])

    def go_2_begin(globchem_file, fline):
        """
        jump lines in the text file until reading the line
        with the word "BEGIN"
        """
        jumptext = ""
        while True:
            text = globchem_file.readline().strip()
            fline += 1
            if(text == "BEGIN"):
                break
            else:
                jumptext += text + '\n'
        return jumptext

    def convert_species_item(species_item, mb_groups):
        """
        Make the conversion (type and/or format), for each species, between
        the blocks of information encoded in the file globchem.dat and the
        dictionary items used in pygchem.
        """
        #species_item['absorption'] == bool(species_item['absorption'])
        species_item['absorption'] = False  # not used in GEOS-Chem
        species_item['atomic_mass'] = float(species_item['atomic_mass'])
        species_item['init_concentration'] = [float(i) for i in
                                            species_item['init_concentration']]
        mb_vals = [int(i) for i in species_item['mb_groups']]
        species_item['mb_groups'] = dict(zip(mb_groups.keys(), mb_vals))

    def trim_rlist(reac_list):
        """
        Take a 'reaction list' (e.g. reactants, products or stoichiometric
        coefficients) and return a list with removed empty items
        """
        # filter below permits to take only items that are not '' (if string)
        # or 0 (if int or float) because bool('') and bool(0) both return False
        return filter(bool, reac_list)

    def read_reac(globchem_file, fline):
        """
        Reads a 'chemical reaction' bloc of lines in
        globchem.dat

        Returns
        -------
        - reac_item: dict
            an item of the reaction dictionnary (see ...)
        """

        reac_r1_fmt = FortranRecordReader('(A1,1X,I4,1X,ES8.2,1X,ES8.1,1X,'
                                          'I6,1X,I1,1X,A2,F6.2,1X,2(F6.0,1X),'
                                          'A20)')
        reac_r2_fmt = FortranRecordReader('(7X,ES8.2,1X,ES8.1,1X,I6,1X,I1,3X,'
                                          'F6.2,1X,2(F6.0,1X))')
        reac_eq_fmt = FortranRecordReader('(4(A1,0PF5.3,A14)/'
                                          '4(A1,0PF5.3,A14)/'
                                          '4(A1,0PF5.3,A14)/'
                                          '4(A1,0PF5.3,A14)/'
                                          '4(A1,0PF5.3,A14))')

        # re-arrange reaction rate parameters:
        # parameter names for values (one-line) read in globchem.dat
        # and correspondence between structure in globchem.dat and structure
        # of pygchem.globchem module, depending on the reaction flag.
        # note that reac_rates_keys are modified for additional lines of
        # parameters (e.g., for line 1, 'AR' becomes 'AR1')
        # TODO: move this information to a separate function to make it 
        # available to export functions
        reac_rates_keys = ['AR', 'BR', 'CR', 'FCV', 'FCT1', 'FCT2']
        mod_ratep = {'' : {'arr': ['AR', 'BR', 'CR']},
                     'P': {'arrlow': ['AR', 'BR', 'CR'],
                           'arrhigh': ['AR1', 'BR1', 'CR1'],
                           'falloff': ['FCV', 'FCT1', 'FCT2']},
                     'E': {'arr': ['AR', 'BR', 'CR']},
                     'X': {'arrK0': ['AR', 'BR', 'CR'],
                           'arrK2': ['AR1', 'BR1', 'CR1'],
                           'arrK3': ['AR2', 'BR2', 'CR2']},
                     'Y': {'arrK0': ['AR', 'BR', 'CR']},
                     'Z': {'arrK1': ['AR', 'BR', 'CR'],
                           'arrK2': ['AR1', 'BR1', 'CR1']},
                     'A': {'arrK1': ['AR', 'BR', 'CR'],
                           'xcarbon': 'AR1'},
                     'B': {'arrK1': ['AR', 'BR', 'CR'],
                           'xcarbon': 'AR1'},
                     'C': {'arrK1': ['AR', 'BR', 'CR']},
                     'D': {'arrK1': ['AR', 'BR', 'CR']},
                     'V': {'arrK1': ['AR', 'BR', 'CR'],
                           'arrK2': ['AR1', 'BR1', 'CR1']},
                     'G': {'arrK1': ['AR', 'BR', 'CR'],
                           'arrK2': ['AR1', 'BR1', 'CR1']},
                    }

        # check if end of reaction list
        l_globchem = globchem_file.readline().strip()
        if(l_globchem[0:4] == "9999"):
            fline += 1
            return "end"

        # read reaction info
        reac_row1 = sanatize_str_inlist(reac_r1_fmt.read(l_globchem)) + [fline]
        reac_item = [reac_row1[i] for i in [1, -1, 0, 6, -2]]

        # read reaction rate parameters
        n_addrates = reac_row1.pop(5)
        reac_rates = dict(zip(reac_rates_keys,
                              reac_row1[2:5] + reac_row1[6:9]))
        if(n_addrates > 0):
            for i in range(0, n_addrates):
                new_keys = [s + str(i + 1) for s in reac_rates_keys]
                l_globchem = globchem_file.readline()
                fline += 1
                reac_row2 = reac_r2_fmt.read(l_globchem)
                del reac_row2[3]  # remove slot for number of rate coef lines
                reac_rates.update(dict(zip(new_keys, reac_row2)))

        # re-arrange rate parameters using corr_ratep
        reac_flag = reac_item[3].upper()
        mod_reac_rates = dict()
        if reac_flag in mod_ratep:
            for k, v in mod_ratep[reac_flag].items():
                if (isinstance(v, collections.Iterable)
                    and not isinstance(v, basestring)):
                    mod_reac_rates[k] = [reac_rates[n] for n in v]
                else:
                    mod_reac_rates[k] = reac_rates[v]
        else:
           mod_reac_rates.update(reac_rates)

        reac_item.append(mod_reac_rates)

        # read reaction equation
        l_globchem = ""
        for i in range(0, 5):
            l_globchem += globchem_file.readline()
            fline += 1
        reac_eq = sanatize_str_inlist(reac_eq_fmt.read(l_globchem))

        del reac_eq[0]
        if(reac_eq[-2] is None):
            reac_eq[-2] = 0.0

        reac_item.append(trim_rlist([reac_eq[i] for i in xrange(1, 13, 3)]))
        reac_item.append(trim_rlist([reac_eq[i] for i in xrange(13, 61, 3)]))
        reac_item.append(trim_rlist([reac_eq[i] for i in range(12, 60, 3)]))

        return reac_item

    # path to additional info files
    _dir_path = os.path.dirname(os.path.abspath(__file__))
    finfo_path = os.path.join(_dir_path, "..", "data")

    # read species.dat (get more info about species)
    species_info = {}
    s_fmt = FortranRecordReader('(A11,A32,A40)')
    f_species_dat = open(os.path.join(finfo_path, "species.dat"), "r")
    f_species_dat.readline()
    for line in f_species_dat:
        row = s_fmt.read(line)
        row = [s.strip() for s in row]
        species_info[row[0]] = row[1:]
    f_species_dat.close()
    species_info_blank = ['' for s in xrange(0, len(species_info.keys()[0]))]

    # globchem.dat file
    globchem_file = open(filename, "r")

    # get header/comments of globchem.dat
    fline = 1
    species_subheader = _format_subheader("Species List")
    header = go_2_begin(globchem_file, fline).replace(species_subheader, "")

    # read in species
    n_species = 0

    #    mass balance groups (id and status)
    species_mb_id_fmt = FortranRecordReader('20X,A3,8(1X,A3)')
    l_globchem = globchem_file.readline()
    mb_id = sanatize_str_inlist(species_mb_id_fmt.read(l_globchem))

    species_mb_st_fmt = FortranRecordReader('21X,A1,8(3X,A1)')
    l_globchem = globchem_file.readline()
    mb_st = sanatize_str_inlist(species_mb_st_fmt.read(l_globchem))

    mb_groups = dict(zip(mb_id, mb_st))
    fline += 2

    species_r1_fmt = FortranRecordReader('(A1,1X,A14,A2,1X,0PF6.2,4(1PE10.3))')
    while True:
        l_globchem = globchem_file.readline().strip()
        if(l_globchem == "END"):
            break

        species_r1 = sanatize_str_inlist(species_r1_fmt.read(l_globchem))
        species_this_key = species_r1[1]
        species_vals = ([n_species, fline] +
                        species_r1[0:4] +
                        [species_r1[4:]] +
                        [[int(i) for i in globchem_file.readline().split()]])
        try:
            species_vals += species_info[species_this_key]
        except KeyError:
            species_vals += species_info_blank

        species[species_this_key] = dict(zip(species_keys, species_vals))
        convert_species_item(species[species_this_key], mb_groups)
        del species_vals
        n_species += 1
        fline += 2

    # read in reactions
    go_2_begin(globchem_file, fline)
    mem_p_ratep = dict()
    n_reac = 0
    while True:
        reac_vals = read_reac(globchem_file, fline)
        if(reac_vals == "end"):
            break
        else:
            # case for reaction with E special flag (reverse equilibrium)
            # --> add rate params of previous reaction with P flag
            reac_flag = reac_vals[3]
            if reac_flag == 'P':
                mem_p_ratep = reac_vals[5]
            elif reac_flag == 'E':
                reac_vals[5].update(mem_p_ratep)

            reac_kn[n_reac] = dict(zip(reac_keys, reac_vals))
            reac_kn[n_reac]['id'] = n_reac
            n_reac += 1
        del reac_vals

    go_2_begin(globchem_file, fline)
    n_reac = 0
    while True:
        reac_vals = read_reac(globchem_file, fline)
        if(reac_vals == "end"):
            break
        else:
            reac_ph[n_reac] = dict(zip(reac_keys, reac_vals))
            reac_ph[n_reac]['id'] = n_reac
            n_reac += 1
        del reac_vals

    # identify links between species (through reactions): parse reac_kn
    link_id = 0
    for reac_key, reac_vals in reac_kn.iteritems():
        for reactant in reac_vals['reactants']:
            if(reactant != '' and reactant != 'M'):
                for product in reac_vals['products']:
                    if(product != ''):
                        species_links.append((link_id, reac_key,
                                              reactant, product))
                        link_id += 1

    # close globchem_file
    globchem_file.close()

    return header, mb_groups, species, reac_kn, reac_ph
コード例 #3
0
ファイル: globchem.py プロジェクト: tsherwen/PyGChem
    def read_reac(globchem_file, fline):
        """
        Reads a 'chemical reaction' bloc of lines in
        globchem.dat

        Returns
        -------
        - reac_item: dict
            an item of the reaction dictionnary (see ...)
        """

        reac_r1_fmt = FortranRecordReader('(A1,1X,I4,1X,ES8.2,1X,ES8.1,1X,'
                                          'I6,1X,I1,1X,A2,F6.2,1X,2(F6.0,1X),'
                                          'A20)')
        reac_r2_fmt = FortranRecordReader('(7X,ES8.2,1X,ES8.1,1X,I6,1X,I1,3X,'
                                          'F6.2,1X,2(F6.0,1X))')
        reac_eq_fmt = FortranRecordReader('(4(A1,0PF5.3,A14)/'
                                          '4(A1,0PF5.3,A14)/'
                                          '4(A1,0PF5.3,A14)/'
                                          '4(A1,0PF5.3,A14)/'
                                          '4(A1,0PF5.3,A14))')

        # re-arrange reaction rate parameters:
        # parameter names for values (one-line) read in globchem.dat
        # and correspondence between structure in globchem.dat and structure
        # of pygchem.globchem module, depending on the reaction flag.
        # note that reac_rates_keys are modified for additional lines of
        # parameters (e.g., for line 1, 'AR' becomes 'AR1')
        # TODO: move this information to a separate function to make it
        # available to export functions
        reac_rates_keys = ['AR', 'BR', 'CR', 'FCV', 'FCT1', 'FCT2']
        mod_ratep = {
            '': {
                'arr': ['AR', 'BR', 'CR']
            },
            'P': {
                'arrlow': ['AR', 'BR', 'CR'],
                'arrhigh': ['AR1', 'BR1', 'CR1'],
                'falloff': ['FCV', 'FCT1', 'FCT2']
            },
            'E': {
                'arr': ['AR', 'BR', 'CR']
            },
            'X': {
                'arrK0': ['AR', 'BR', 'CR'],
                'arrK2': ['AR1', 'BR1', 'CR1'],
                'arrK3': ['AR2', 'BR2', 'CR2']
            },
            'Y': {
                'arrK0': ['AR', 'BR', 'CR']
            },
            'Z': {
                'arrK1': ['AR', 'BR', 'CR'],
                'arrK2': ['AR1', 'BR1', 'CR1']
            },
            'A': {
                'arrK1': ['AR', 'BR', 'CR'],
                'xcarbon': 'AR1'
            },
            'B': {
                'arrK1': ['AR', 'BR', 'CR'],
                'xcarbon': 'AR1'
            },
            'C': {
                'arrK1': ['AR', 'BR', 'CR']
            },
            'D': {
                'arrK1': ['AR', 'BR', 'CR']
            },
            'V': {
                'arrK1': ['AR', 'BR', 'CR'],
                'arrK2': ['AR1', 'BR1', 'CR1']
            },
            'G': {
                'arrK1': ['AR', 'BR', 'CR'],
                'arrK2': ['AR1', 'BR1', 'CR1']
            },
        }

        # check if end of reaction list
        l_globchem = globchem_file.readline().strip()
        if (l_globchem[0:4] == "9999"):
            fline += 1
            return "end"

        # read reaction info
        reac_row1 = sanatize_str_inlist(reac_r1_fmt.read(l_globchem)) + [fline]
        reac_item = [reac_row1[i] for i in [1, -1, 0, 6, -2]]

        # read reaction rate parameters
        n_addrates = reac_row1.pop(5)
        reac_rates = dict(zip(reac_rates_keys,
                              reac_row1[2:5] + reac_row1[6:9]))
        if (n_addrates > 0):
            for i in range(0, n_addrates):
                new_keys = [s + str(i + 1) for s in reac_rates_keys]
                l_globchem = globchem_file.readline()
                fline += 1
                reac_row2 = reac_r2_fmt.read(l_globchem)
                del reac_row2[3]  # remove slot for number of rate coef lines
                reac_rates.update(dict(zip(new_keys, reac_row2)))

        # re-arrange rate parameters using corr_ratep
        reac_flag = reac_item[3].upper()
        mod_reac_rates = dict()
        if reac_flag in mod_ratep:
            for k, v in mod_ratep[reac_flag].items():
                if (isinstance(v, collections.Iterable)
                        and not isinstance(v, basestring)):
                    mod_reac_rates[k] = [reac_rates[n] for n in v]
                else:
                    mod_reac_rates[k] = reac_rates[v]
        else:
            mod_reac_rates.update(reac_rates)

        reac_item.append(mod_reac_rates)

        # read reaction equation
        l_globchem = ""
        for i in range(0, 5):
            l_globchem += globchem_file.readline()
            fline += 1
        reac_eq = sanatize_str_inlist(reac_eq_fmt.read(l_globchem))

        del reac_eq[0]
        if (reac_eq[-2] is None):
            reac_eq[-2] = 0.0

        reac_item.append(trim_rlist([reac_eq[i] for i in xrange(1, 13, 3)]))
        reac_item.append(trim_rlist([reac_eq[i] for i in xrange(13, 61, 3)]))
        reac_item.append(trim_rlist([reac_eq[i] for i in range(12, 60, 3)]))

        return reac_item
コード例 #4
0
ファイル: globchem.py プロジェクト: benbovy/PyGChem
    def read_reac(globchem_file, fline):
        """
        Reads a 'chemical reaction' bloc of lines in
        globchem.dat

        Returns
        -------
        - reac_item: dict
            an item of the reaction dictionnary (see ...)
        """

        reac_r1_fmt = FortranRecordReader('(A1,1X,I4,1X,ES8.2,1X,ES8.1,1X,'
                                          'I6,1X,I1,1X,A2,F6.2,1X,2(F6.0,1X),'
                                          'A20)')
        reac_r2_fmt = FortranRecordReader('(7X,ES8.2,1X,ES8.1,1X,I6,1X,I1,3X,'
                                          'F6.2,1X,2(F6.0,1X))')
        reac_eq_fmt = FortranRecordReader('(4(A1,0PF5.3,A14)/'
                                          '4(A1,0PF5.3,A14)/'
                                          '4(A1,0PF5.3,A14)/'
                                          '4(A1,0PF5.3,A14)/'
                                          '4(A1,0PF5.3,A14))')

        # re-arrange reaction rate parameters:
        # parameter names for values (one-line) read in globchem.dat
        # and correspondence between structure in globchem.dat and structure
        # of pygchem.globchem module, depending on the reaction flag.
        # note that reac_rates_keys are modified for additional lines of
        # parameters (e.g., for line 1, 'AR' becomes 'AR1')
        # TODO: move this information to a separate function to make it 
        # available to export functions
        reac_rates_keys = ['AR', 'BR', 'CR', 'FCV', 'FCT1', 'FCT2']
        mod_ratep = {'' : {'arr': ['AR', 'BR', 'CR']},
                     'P': {'arrlow': ['AR', 'BR', 'CR'],
                           'arrhigh': ['AR1', 'BR1', 'CR1'],
                           'falloff': ['FCV', 'FCT1', 'FCT2']},
                     'E': {'arr': ['AR', 'BR', 'CR']},
                     'X': {'arrK0': ['AR', 'BR', 'CR'],
                           'arrK2': ['AR1', 'BR1', 'CR1'],
                           'arrK3': ['AR2', 'BR2', 'CR2']},
                     'Y': {'arrK0': ['AR', 'BR', 'CR']},
                     'Z': {'arrK1': ['AR', 'BR', 'CR'],
                           'arrK2': ['AR1', 'BR1', 'CR1']},
                     'A': {'arrK1': ['AR', 'BR', 'CR'],
                           'xcarbon': 'AR1'},
                     'B': {'arrK1': ['AR', 'BR', 'CR'],
                           'xcarbon': 'AR1'},
                     'C': {'arrK1': ['AR', 'BR', 'CR']},
                     'D': {'arrK1': ['AR', 'BR', 'CR']},
                     'V': {'arrK1': ['AR', 'BR', 'CR'],
                           'arrK2': ['AR1', 'BR1', 'CR1']},
                     'G': {'arrK1': ['AR', 'BR', 'CR'],
                           'arrK2': ['AR1', 'BR1', 'CR1']},
                    }

        # check if end of reaction list
        l_globchem = globchem_file.readline().strip()
        if(l_globchem[0:4] == "9999"):
            fline += 1
            return "end"

        # read reaction info
        reac_row1 = sanatize_str_inlist(reac_r1_fmt.read(l_globchem)) + [fline]
        reac_item = [reac_row1[i] for i in [1, -1, 0, 6, -2]]

        # read reaction rate parameters
        n_addrates = reac_row1.pop(5)
        reac_rates = dict(zip(reac_rates_keys,
                              reac_row1[2:5] + reac_row1[6:9]))
        if(n_addrates > 0):
            for i in range(0, n_addrates):
                new_keys = [s + str(i + 1) for s in reac_rates_keys]
                l_globchem = globchem_file.readline()
                fline += 1
                reac_row2 = reac_r2_fmt.read(l_globchem)
                del reac_row2[3]  # remove slot for number of rate coef lines
                reac_rates.update(dict(zip(new_keys, reac_row2)))

        # re-arrange rate parameters using corr_ratep
        reac_flag = reac_item[3].upper()
        mod_reac_rates = dict()
        if reac_flag in mod_ratep:
            for k, v in mod_ratep[reac_flag].items():
                if (isinstance(v, collections.Iterable)
                    and not isinstance(v, basestring)):
                    mod_reac_rates[k] = [reac_rates[n] for n in v]
                else:
                    mod_reac_rates[k] = reac_rates[v]
        else:
           mod_reac_rates.update(reac_rates)

        reac_item.append(mod_reac_rates)

        # read reaction equation
        l_globchem = ""
        for i in range(0, 5):
            l_globchem += globchem_file.readline()
            fline += 1
        reac_eq = sanatize_str_inlist(reac_eq_fmt.read(l_globchem))

        del reac_eq[0]
        if(reac_eq[-2] is None):
            reac_eq[-2] = 0.0

        reac_item.append(trim_rlist([reac_eq[i] for i in xrange(1, 13, 3)]))
        reac_item.append(trim_rlist([reac_eq[i] for i in xrange(13, 61, 3)]))
        reac_item.append(trim_rlist([reac_eq[i] for i in range(12, 60, 3)]))

        return reac_item