コード例 #1
0
    def test_make_new_species(self):
        """
        Test that CoreEdgeReactionModel.make_new_species method correctly stores the unique species.
        """

        # adding 3 unique species:
        cerm = CoreEdgeReactionModel()

        spcs = [
            Species().from_smiles('[OH]'),
            Species().from_smiles('CC'),
            Species().from_smiles('[CH3]')
        ]

        for spc in spcs:
            cerm.make_new_species(spc)

        self.assertEquals(len(cerm.species_dict), len(spcs))
        self.assertEquals(len(cerm.index_species_dict), len(spcs))

        # adding 3 unique, and 1 already existing species:
        cerm = CoreEdgeReactionModel()

        spcs = [
            Species().from_smiles('[OH]'),
            Species().from_smiles('CC'),
            Species().from_smiles('[CH3]'),
            Species().from_smiles('CC')
        ]  # duplicate species

        for spc in spcs:
            cerm.make_new_species(spc)

        self.assertEquals(len(cerm.species_dict), len(spcs) - 1)
        self.assertEquals(len(cerm.index_species_dict), len(spcs) - 1)
コード例 #2
0
    def test_append_unreactive_structure(self):
        """
        Test that CERM.make_new_species correctly recognizes a non-representative resonance structure
        """

        cerm = CoreEdgeReactionModel()

        spcs = [
            Species().from_smiles('CCO'),  # a control species
            Species().from_smiles('[N]=O'),
            Species().from_adjacency_list(
                """1 O u1 p2 c0 {2,S}
                                               2 N u0 p2 c0 {1,S}"""
            ),  # a non-representative structure of '[N]=O'
        ]

        for spc in spcs:
            cerm.make_new_species(spc)

        self.assertEquals(len(cerm.species_dict), 2)
        self.assertEquals(len(cerm.index_species_dict), 2)
        self.assertEquals(len(cerm.index_species_dict[1].molecule), 1)
        self.assertTrue(cerm.index_species_dict[1].molecule[0].reactive)
        self.assertEquals(len(cerm.index_species_dict[2].molecule), 1)
        self.assertTrue(cerm.index_species_dict[2].molecule[0].reactive)
コード例 #3
0
    def test_thermo_filter_down(self):
        """
        test that thermo_filter_down with maximum_edge_species = 1 reduces
        the edge to one species
        """
        cerm = CoreEdgeReactionModel()

        spcs = [
            Species().from_smiles('[OH]'),
            Species().from_smiles('C'),
            Species().from_smiles('[CH3]'),
            Species().from_smiles('[CH2]'),
            Species().from_smiles('O')
        ]

        for spc in spcs:
            cerm.make_new_species(spc, label=spc.molecule[0].to_smiles())
            spc.label = spc.molecule[0].to_smiles()

        thermo_dict = {
            '[OH]':
            NASA(polynomials=[
                NASAPolynomial(coeffs=[
                    3.51457, 2.92787e-05, -5.32168e-07, 1.0195e-09,
                    -3.85947e-13, 3414.25, 2.10435
                ],
                               Tmin=(100, 'K'),
                               Tmax=(1145.75, 'K')),
                NASAPolynomial(coeffs=[
                    3.07194, 0.000604014, -1.39775e-08, -2.13448e-11,
                    2.48067e-15, 3579.39, 4.578
                ],
                               Tmin=(1145.75, 'K'),
                               Tmax=(5000, 'K'))
            ],
                 Tmin=(100, 'K'),
                 Tmax=(5000, 'K'),
                 E0=(28.3945, 'kJ/mol'),
                 Cp0=(29.1007, 'J/(mol*K)'),
                 CpInf=(37.4151, 'J/(mol*K)'),
                 label="""OH(D)""",
                 comment="""Thermo library: primaryThermoLibrary"""),
            'C':
            NASA(polynomials=[
                NASAPolynomial(coeffs=[
                    4.20541, -0.00535551, 2.51121e-05, -2.1376e-08,
                    5.97513e-12, -10161.9, -0.921259
                ],
                               Tmin=(100, 'K'),
                               Tmax=(1084.13, 'K')),
                NASAPolynomial(coeffs=[
                    0.908298, 0.011454, -4.57171e-06, 8.29185e-10,
                    -5.66309e-14, -9719.99, 13.9929
                ],
                               Tmin=(1084.13, 'K'),
                               Tmax=(5000, 'K'))
            ],
                 Tmin=(100, 'K'),
                 Tmax=(5000, 'K'),
                 E0=(-84.435, 'kJ/mol'),
                 Cp0=(33.2579, 'J/(mol*K)'),
                 CpInf=(108.088, 'J/(mol*K)'),
                 label="""CH4""",
                 comment="""Thermo library: primaryThermoLibrary"""),
            '[CH3]':
            NASA(polynomials=[
                NASAPolynomial(coeffs=[
                    3.67359, 0.00201095, 5.73022e-06, -6.87117e-09,
                    2.54386e-12, 16445, 1.60456
                ],
                               Tmin=(200, 'K'),
                               Tmax=(1000, 'K')),
                NASAPolynomial(coeffs=[
                    2.28572, 0.0072399, -2.98714e-06, 5.95685e-10,
                    -4.67154e-14, 16775.6, 8.48007
                ],
                               Tmin=(1000, 'K'),
                               Tmax=(3500, 'K'))
            ],
                 Tmin=(200, 'K'),
                 Tmax=(3500, 'K'),
                 E0=(136.42, 'kJ/mol'),
                 Cp0=(33.2579, 'J/(mol*K)'),
                 CpInf=(83.1447, 'J/(mol*K)'),
                 label="""CH3""",
                 comment="""Thermo library: GRI-Mech3.0"""),
            '[CH2]':
            NASA(polynomials=[
                NASAPolynomial(coeffs=[
                    4.01192, -0.000154978, 3.26298e-06, -2.40422e-09,
                    5.69497e-13, 45867.7, 0.533201
                ],
                               Tmin=(100, 'K'),
                               Tmax=(1104.62, 'K')),
                NASAPolynomial(coeffs=[
                    3.14983, 0.00296674, -9.76056e-07, 1.54115e-10,
                    -9.50338e-15, 46058.1, 4.77808
                ],
                               Tmin=(1104.62, 'K'),
                               Tmax=(5000, 'K'))
            ],
                 Tmin=(100, 'K'),
                 Tmax=(5000, 'K'),
                 E0=(381.37, 'kJ/mol'),
                 Cp0=(33.2579, 'J/(mol*K)'),
                 CpInf=(58.2013, 'J/(mol*K)'),
                 label="""CH2(T)""",
                 comment="""Thermo library: primaryThermoLibrary"""),
            'O':
            NASA(polynomials=[
                NASAPolynomial(coeffs=[
                    4.05764, -0.000787936, 2.90877e-06, -1.47519e-09,
                    2.12842e-13, -30281.6, -0.311364
                ],
                               Tmin=(100, 'K'),
                               Tmax=(1130.24, 'K')),
                NASAPolynomial(coeffs=[
                    2.84325, 0.00275109, -7.81031e-07, 1.07244e-10,
                    -5.79392e-15, -29958.6, 5.91042
                ],
                               Tmin=(1130.24, 'K'),
                               Tmax=(5000, 'K'))
            ],
                 Tmin=(100, 'K'),
                 Tmax=(5000, 'K'),
                 E0=(-251.755, 'kJ/mol'),
                 Cp0=(33.2579, 'J/(mol*K)'),
                 CpInf=(58.2013, 'J/(mol*K)'),
                 label="""H2O""",
                 comment="""Thermo library: primaryThermoLibrary"""),
        }

        for spc in spcs[:3]:
            cerm.add_species_to_core(spc)

        reaction = TemplateReaction(reactants=[spcs[0], spcs[2]],
                                    products=[spcs[-1], spcs[-2]],
                                    degeneracy=1,
                                    reversible=True,
                                    family='H_Abstraction')

        cerm.process_new_reactions(new_reactions=[reaction],
                                   new_species=[])  # add CH2 and O to edge

        for spc in cerm.core.species + cerm.edge.species:
            spc.thermo = thermo_dict[
                spc.molecule[0].to_smiles()]  # assign thermo

        cerm.set_thermodynamic_filtering_parameters(
            Tmax=300.0,
            thermo_tol_keep_spc_in_edge=1000.0,
            min_core_size_for_prune=0,
            maximum_edge_species=1,
            reaction_systems=[])

        difset = set([
            x.molecule[0].to_smiles() for x in cerm.edge.species
        ]) - set([x.molecule[0].to_smiles() for x in cerm.core.species])

        self.assertEquals(
            len(difset),
            2)  # no change because toleranceThermoKeepSpeciesInEdge is high

        cerm.thermo_filter_down(maximum_edge_species=1)

        difset = set([
            x.molecule[0].to_smiles() for x in cerm.edge.species
        ]) - set([x.molecule[0].to_smiles() for x in cerm.core.species])

        self.assertEquals(
            len(difset), 1
        )  # should be one because we thermo filtered down to one edge species
コード例 #4
0
    def execute(self,
                output_file,
                plot,
                file_format='pdf',
                print_summary=True,
                species_list=None,
                thermo_library=None,
                kinetics_library=None):
        """Execute an ExplorerJob"""
        logging.info('Exploring network...')

        rmg = RMG()

        rmg.species_constraints = {
            'allowed':
            ['input species', 'seed mechanisms', 'reaction libraries'],
            'maximumRadicalElectrons': self.maximum_radical_electrons,
            'explicitlyAllowedMolecules': []
        }

        rmgpy.rmg.input.rmg = rmg

        reaction_model = CoreEdgeReactionModel()

        reaction_model.pressure_dependence = self.pdepjob

        reaction_model.pressure_dependence.rmgmode = True

        if output_file:
            reaction_model.pressure_dependence.output_file = os.path.dirname(
                output_file)

        kinetics_database = get_db('kinetics')
        thermo_database = get_db('thermo')

        thermo_database.libraries['thermojobs'] = thermo_library
        thermo_database.library_order.insert(0, 'thermojobs')

        kinetics_database.libraries['kineticsjobs'] = kinetics_library
        kinetics_database.library_order.insert(
            0, ('kineticsjobs', 'Reaction Library'))

        self.job_rxns = [rxn for rxn in reaction_model.core.reactions]

        if output_file is not None:
            if not os.path.exists(
                    os.path.join(
                        reaction_model.pressure_dependence.output_file,
                        'pdep')):
                os.mkdir(
                    os.path.join(
                        reaction_model.pressure_dependence.output_file,
                        'pdep'))
            else:
                shutil.rmtree(
                    os.path.join(
                        reaction_model.pressure_dependence.output_file,
                        'pdep'))
                os.mkdir(
                    os.path.join(
                        reaction_model.pressure_dependence.output_file,
                        'pdep'))

        # get the molecular formula for the network
        mmol = None
        for spc in self.source:
            if mmol:
                mmol = mmol.merge(spc.molecule[0])
            else:
                mmol = spc.molecule[0].copy(deep=True)

        form = mmol.get_formula()

        for spec in list(self.bath_gas.keys()) + self.source:
            nspec, is_new = reaction_model.make_new_species(spec,
                                                            reactive=False)
            flags = np.array([
                s.molecule[0].get_formula() == form
                for s in reaction_model.core.species
            ])
            reaction_model.enlarge(nspec,
                                   react_edge=False,
                                   unimolecular_react=flags,
                                   bimolecular_react=np.zeros(
                                       (len(reaction_model.core.species),
                                        len(reaction_model.core.species))))

        reaction_model.add_seed_mechanism_to_core('kineticsjobs')

        for lib in kinetics_database.library_order:
            if lib[0] != 'kineticsjobs':
                reaction_model.add_reaction_library_to_edge(lib[0])

        for spc in reaction_model.core.species:
            for i, item in enumerate(self.source):
                if spc.is_isomorphic(item):
                    self.source[i] = spc

        # react initial species
        if len(self.source) == 1:
            flags = np.array([
                s.molecule[0].get_formula() == form
                for s in reaction_model.core.species
            ])
            biflags = np.zeros((len(reaction_model.core.species),
                                len(reaction_model.core.species)))
        elif len(self.source) == 2:
            flags = np.array([False for s in reaction_model.core.species])
            biflags = np.array(
                [[False for i in range(len(reaction_model.core.species))]
                 for j in range(len(reaction_model.core.species))])
            biflags[reaction_model.core.species.index(self.source[0]),
                    reaction_model.core.species.index(self.source[1])] = True
        else:
            raise ValueError(
                "Reactant channels with greater than 2 reactants not supported"
            )

        reaction_model.enlarge(react_edge=True,
                               unimolecular_react=flags,
                               bimolecular_react=biflags)

        # find the networks we're interested in
        networks = []
        for nwk in reaction_model.network_list:
            if set(nwk.source) == set(self.source):
                self.source = nwk.source
                networks.append(nwk)

        if len(networks) == 0:
            raise ValueError(
                'Did not generate a network with the requested source. This usually means no unimolecular '
                'reactions were generated for the source. Note that library reactions that are not '
                'properly flagged as elementary_high_p can replace RMG generated reactions that would '
                'otherwise be part of networks.')
        for network in networks:
            network.bath_gas = self.bath_gas

        self.networks = networks

        # determine T and P combinations

        if self.pdepjob.Tlist:
            t_list = self.pdepjob.Tlist.value_si
        else:
            t_list = np.linspace(self.pdepjob.Tmin.value_si,
                                 self.pdepjob.Tmax.value_si,
                                 self.pdepjob.Tcount)

        if self.pdepjob.Plist:
            p_list = self.pdepjob.Plist.value_si
        else:
            p_list = np.linspace(self.pdepjob.Pmin.value_si,
                                 self.pdepjob.Pmax.value_si,
                                 self.pdepjob.Pcount)

        # generate the network

        forbidden_structures = get_db('forbidden')
        incomplete = True
        checked_species = []

        while incomplete:
            incomplete = False
            for temperature in t_list:
                for pressure in p_list:
                    for network in self.networks:
                        # compute the characteristic rate coefficient by summing all rate coefficients
                        # from the reactant channel
                        for spc in reaction_model.edge.species:
                            if spc in checked_species:
                                continue
                            if forbidden_structures.is_molecule_forbidden(
                                    spc.molecule[0]):
                                reaction_model.remove_species_from_edge(
                                    reaction_model.reaction_systems, spc)
                                reaction_model.remove_empty_pdep_networks()
                            else:
                                checked_species.append(spc)

                        kchar = 0.0
                        for rxn in network.net_reactions:  # reaction_model.core.reactions+reaction_model.edge.reactions
                            if (set(rxn.reactants) == set(self.source) and
                                    rxn.products[0].molecule[0].get_formula()
                                    == form):
                                kchar += rxn.kinetics.get_rate_coefficient(
                                    T=temperature, P=pressure)
                            elif (set(rxn.products) == set(self.source) and
                                  rxn.reactants[0].molecule[0].get_formula()
                                  == form):
                                kchar += rxn.generate_reverse_rate_coefficient(
                                    network_kinetics=True
                                ).get_rate_coefficient(T=temperature,
                                                       P=pressure)

                        if network.get_leak_coefficient(
                                T=temperature,
                                P=pressure) > self.explore_tol * kchar:
                            incomplete = True
                            spc = network.get_maximum_leak_species(
                                T=temperature, P=pressure)
                            logging.info(
                                'adding new isomer {0} to network'.format(spc))
                            flags = np.array([
                                s.molecule[0].get_formula() == form
                                for s in reaction_model.core.species
                            ])
                            reaction_model.enlarge(
                                (network, spc),
                                react_edge=False,
                                unimolecular_react=flags,
                                bimolecular_react=np.zeros(
                                    (len(reaction_model.core.species),
                                     len(reaction_model.core.species))))

                            flags = np.array([
                                s.molecule[0].get_formula() == form
                                for s in reaction_model.core.species
                            ])
                            reaction_model.enlarge(
                                react_edge=True,
                                unimolecular_react=flags,
                                bimolecular_react=np.zeros(
                                    (len(reaction_model.core.species),
                                     len(reaction_model.core.species))))
        for network in self.networks:
            rm_rxns = []
            for rxn in network.path_reactions:  # remove reactions with forbidden species
                for r in rxn.reactants + rxn.products:
                    if forbidden_structures.is_molecule_forbidden(
                            r.molecule[0]):
                        rm_rxns.append(rxn)

            for rxn in rm_rxns:
                logging.info('Removing forbidden reaction: {0}'.format(rxn))
                network.path_reactions.remove(rxn)

            # clean up output files
            if output_file is not None:
                path = os.path.join(
                    reaction_model.pressure_dependence.output_file, 'pdep')
                for name in os.listdir(path):
                    if name.endswith('.py') and '_' in name:
                        if name.split('_')[-1].split('.')[0] != str(
                                len(network.isomers)):
                            os.remove(os.path.join(path, name))
                        else:
                            os.rename(
                                os.path.join(path, name),
                                os.path.join(
                                    path, 'network_full{}.py'.format(
                                        self.networks.index(network))))

        warns = []

        for rxn in self.job_rxns:
            if rxn not in network.path_reactions:
                warns.append(
                    'Reaction {0} in the input file was not explored during network expansion and was '
                    'not included in the full network.  This is likely because your explore_tol value is '
                    'too high.'.format(rxn))

        # reduction process
        for network in self.networks:
            if self.energy_tol != np.inf or self.flux_tol != 0.0:

                rxn_set = None
                product_set = None

                for temperature in t_list:
                    if self.energy_tol != np.inf:
                        rxns = network.get_energy_filtered_reactions(
                            temperature, self.energy_tol)
                        if rxn_set is not None:
                            rxn_set &= set(rxns)
                        else:
                            rxn_set = set(rxns)

                    for pressure in p_list:
                        if self.flux_tol != 0.0:
                            products = network.get_rate_filtered_products(
                                temperature, pressure, self.flux_tol)
                            products = [tuple(x) for x in products]
                            if product_set is not None:
                                product_set &= set(products)
                            else:
                                product_set = set(products)

                if rxn_set:
                    logging.info('removing reactions during reduction:')
                    for rxn in rxn_set:
                        logging.info(rxn)
                    rxn_set = list(rxn_set)
                if product_set:
                    logging.info('removing products during reduction:')
                    for prod in product_set:
                        logging.info([x.label for x in prod])
                    product_set = list(product_set)

                network.remove_reactions(reaction_model,
                                         rxns=rxn_set,
                                         prods=product_set)

                for rxn in self.job_rxns:
                    if rxn not in network.path_reactions:
                        warns.append(
                            'Reaction {0} in the input file was not included in the reduced model.'
                            .format(rxn))

        self.networks = networks
        for p, network in enumerate(self.networks):
            self.pdepjob.network = network

            if len(self.networks) > 1:
                root, file_name = os.path.split(output_file)
                s1, s2 = file_name.split(".")
                ind = str(self.networks.index(network))
                stot = os.path.join(root, s1 + "{}.".format(ind) + s2)
            else:
                stot = output_file

            self.pdepjob.execute(stot,
                                 plot,
                                 file_format='pdf',
                                 print_summary=True)
            if os.path.isfile('network.pdf'):
                os.rename('network.pdf', 'network' + str(p) + '.pdf')

            if warns:
                logging.info('\nOUTPUT WARNINGS:\n')
                for w in warns:
                    logging.warning(w)