Skip to content

Commit

Permalink
Refactor reaction generation and processing for reactEdge phase
Browse files Browse the repository at this point in the history
Motivation:
- processNewReactions requires a newSpecies argument which was not
being properly identified after multiprocessing changes in #1459

Background:
- The newSpecies argument is retained from early RMG when reactions
were generated right after adding a new species to the core.
- Hence, newSpecies referred to the newly added core species which
was used to generate the new reactions.
- The overall model generation algorithm has since changed, so
identifying newSpecies is not as straightforward.
- The multiprocessing PR changed newSpecies to be any core species,
missing the original purpose of identifying the species from which
the reaction was generated.

Changes:
- Use the species tuples created during reaction generation to
keep track of which species were used to generate the reaction
- Update unit tests which are affected by the changes in return values
from react and react_all
  • Loading branch information
mliu49 committed Jul 17, 2019
1 parent 58c1a06 commit 20b1467
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 24 deletions.
20 changes: 12 additions & 8 deletions rmgpy/rmg/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -599,14 +599,18 @@ def enlarge(self, newObject=None, reactEdge=False,
numOldEdgeReactions -= len(reactionsMovedFromEdge)

else:
# We are reacting the edge
rxns = react_all(self.core.species, numOldCoreSpecies,
unimolecularReact, bimolecularReact, trimolecularReact=trimolecularReact, procnum=procnum)

spcs = [self.retrieve_species(rxn) for rxn in rxns]

for rxn, spc in zip(rxns, spcs):
self.processNewReactions([rxn], spc, generateThermo=False)
# Generate reactions between all core species which have not been
# reacted yet and exceed the reaction filter thresholds
rxnLists, spcsTuples = react_all(self.core.species, numOldCoreSpecies,
unimolecularReact, bimolecularReact,
trimolecularReact=trimolecularReact,
procnum=procnum)

for rxnList, spcTuple in zip(rxnLists, spcsTuples):
# Identify a core species which was used to generate the reaction
# For consistency, pick the one with the smallest index
spc = sorted(spcTuple, key=lambda x: x.index)[0]
self.processNewReactions(rxnList, spc, generateThermo=False)

################################################################
# Begin processing the new species and reactions
Expand Down
6 changes: 3 additions & 3 deletions rmgpy/rmg/modelTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ class item:
spcs = [Species().fromSMILES('CC'), Species().fromSMILES('[CH3]')]
spcTuples = [((spcA, spc), ['H_Abstraction']) for spc in spcs]

rxns = list(react(spcTuples, procnum))
rxns += list(react([((spcs[0], spcs[1]), ['H_Abstraction'])], procnum))
rxns = react(spcTuples, procnum, flatten=True)
rxns += react([((spcs[0], spcs[1]), ['H_Abstraction'])], procnum, flatten=True)

for rxn in rxns:
cerm.makeNewReaction(rxn)
Expand Down Expand Up @@ -246,7 +246,7 @@ def testMakeNewReaction(self):
spcs = [Species().fromSMILES('CC'), Species().fromSMILES('[CH3]')]
spcTuples = [((spcA, spc), ['H_Abstraction']) for spc in spcs]

rxns = list(react(spcTuples, procnum))
rxns = react(spcTuples, procnum, flatten=True)

cerm = CoreEdgeReactionModel()

Expand Down
2 changes: 1 addition & 1 deletion rmgpy/rmg/parreactTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def generate():
spcTuples = [(spcA, spc) for spc in spcs]
procnum = 2

reactionList = list(react(spcTuples, procnum))
reactionList = react(spcTuples, procnum, flatten=True)

if not reactionList: return False

Expand Down
17 changes: 13 additions & 4 deletions rmgpy/rmg/react.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
from multiprocessing import Pool

################################################################################
def react(spc_tuples, procnum=1):
def react(spc_tuples, procnum=1, flatten=False):
"""
Generate reactions between the species in the
list of species tuples for all the reaction families available.
Expand All @@ -52,7 +52,9 @@ def react(spc_tuples, procnum=1):
Possible combinations between the first spc in the tuple, and the second species in the tuple
is obtained by taking the combinatorial product of the two generated [(Molecule, index)] lists.
Returns a flat generator object containing the generated Reaction objects.
Returns a list of lists of reactions generated from each species tuple.
If ``flatten=True``, return a flat list of reactions.
"""
# Execute multiprocessing map. It blocks until the result is ready.
# This method chops the iterable into a number of chunks which it
Expand All @@ -67,7 +69,10 @@ def react(spc_tuples, procnum=1):
p.close()
p.join()

return itertools.chain.from_iterable(reactions)
if flatten:
return list(itertools.chain.from_iterable(reactions))
else:
return reactions


def _react_species_star(args):
Expand All @@ -92,6 +97,10 @@ def react_all(core_spc_list, numOldCoreSpecies, unimolecularReact, bimolecularRe
"""
Reacts the core species list via uni-, bi-, and trimolecular
reactions and splits reaction families per task for improved load balancing in parallel runs.
Returns:
a list of lists of reactions generated from each species tuple
a list of species tuples
"""
# Select reactive species that can undergo unimolecular reactions:
spc_tuples = [(core_spc_list[i],)
Expand Down Expand Up @@ -147,5 +156,5 @@ def react_all(core_spc_list, numOldCoreSpecies, unimolecularReact, bimolecularRe
else:
spc_fam_tuples.append((spc_tuple, ))

return list(react(spc_fam_tuples, procnum))
return react(spc_fam_tuples, procnum), [fam_tuple[0] for fam_tuple in spc_fam_tuples]

25 changes: 17 additions & 8 deletions rmgpy/rmg/reactTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
# #
###############################################################################

import itertools
import os
import unittest
import numpy as np
Expand Down Expand Up @@ -76,7 +77,7 @@ def testReact(self):
spcs = [Species().fromSMILES('CC'), Species().fromSMILES('[CH3]')]
spc_tuples = [((spc_a, spc), ['H_Abstraction']) for spc in spcs]

reaction_list = list(react(spc_tuples, procnum))
reaction_list = react(spc_tuples, procnum, flatten=True)
self.assertIsNotNone(reaction_list)
self.assertEqual(len(reaction_list), 3)
self.assertTrue(all([isinstance(rxn, TemplateReaction) for rxn in reaction_list]))
Expand All @@ -93,7 +94,7 @@ def testReactParallel(self):
spcs = [Species().fromSMILES('CC'), Species().fromSMILES('[CH3]')]
spc_tuples = [((spc_a, spc), ['H_Abstraction']) for spc in spcs]

reaction_list = list(react(spc_tuples, procnum))
reaction_list = react(spc_tuples, procnum, flatten=True)
self.assertIsNotNone(reaction_list)
self.assertEqual(len(reaction_list), 3)
self.assertTrue(all([isinstance(rxn, TemplateReaction) for rxn in reaction_list]))
Expand All @@ -112,10 +113,14 @@ def testReactAll(self):
]

n = len(spcs)
reaction_list = react_all(spcs, n, np.ones(n), np.ones([n, n]), np.ones([n, n, n]), procnum)
reaction_list, spc_tuples = react_all(spcs, n, np.ones(n), np.ones([n, n]), np.ones([n, n, n]), procnum)
self.assertIsNotNone(reaction_list)
self.assertEqual(len(reaction_list), 44)
self.assertTrue(all([isinstance(rxn, TemplateReaction) for rxn in reaction_list]))
self.assertEqual(len(reaction_list), 34)
self.assertEqual(len(spc_tuples), 34)

flat_rxn_list = list(itertools.chain.from_iterable(reaction_list))
self.assertEqual(len(flat_rxn_list), 44)
self.assertTrue(all([isinstance(rxn, TemplateReaction) for rxn in flat_rxn_list]))

def testReactAllParallel(self):
"""
Expand All @@ -133,10 +138,14 @@ def testReactAllParallel(self):
]

n = len(spcs)
reaction_list = react_all(spcs, n, np.ones(n), np.ones([n, n]), np.ones([n, n, n]), procnum)
reaction_list, spc_tuples = react_all(spcs, n, np.ones(n), np.ones([n, n]), np.ones([n, n, n]), procnum)
self.assertIsNotNone(reaction_list)
self.assertEqual(len(reaction_list), 44)
self.assertTrue(all([isinstance(rxn, TemplateReaction) for rxn in reaction_list]))
self.assertEqual(len(reaction_list), 94)
self.assertEqual(len(spc_tuples), 94)

flat_rxn_list = list(itertools.chain.from_iterable(reaction_list))
self.assertEqual(len(flat_rxn_list), 44)
self.assertTrue(all([isinstance(rxn, TemplateReaction) for rxn in flat_rxn_list]))

def tearDown(self):
"""
Expand Down

0 comments on commit 20b1467

Please sign in to comment.