Skip to content

Commit 9dc2df7

Browse files
committed
Now saving core species concentration profiles for each reaction system.
We again use the xlwt package to save the concentration profiles as Excel spreadsheets, which lets us apply a bit of formatting to the data. Each round of simulation gets its own spreadsheet; these are placed in the new solver subdirectory. Each reaction system gets a sheet in the spreadsheet for that iteration. Some information about the reaction system is printed in the top few lines of each corresponding sheet. I tried to design it so that RMG would carry on if xlwt was not available. In the future we may want to make xlwt a required package.
1 parent a0e4a5f commit 9dc2df7

File tree

4 files changed

+73
-2
lines changed

4 files changed

+73
-2
lines changed

rmg.py

+21
Original file line numberDiff line numberDiff line change
@@ -242,11 +242,20 @@ def execute(args):
242242
except ImportError:
243243
logging.info('Optional package dependency "psutil" not found; memory profiling information will not be saved.')
244244

245+
# See if spreadsheet writing package is available
246+
saveConcentrationProfiles = False
247+
try:
248+
import xlwt
249+
saveConcentrationProfiles = True
250+
except ImportError:
251+
logging.info('Optional package dependency "xlwt" not found; reaction system concentration profiles will not be saved.')
252+
245253
# Make output subdirectories
246254
makeOutputSubdirectory('plot')
247255
makeOutputSubdirectory('species')
248256
makeOutputSubdirectory('pdep')
249257
makeOutputSubdirectory('chemkin')
258+
makeOutputSubdirectory('solver')
250259

251260
# Read input file
252261
reactionModel, coreSpecies, reactionSystems, database, seedMechanisms = readInputFile(inputFile)
@@ -291,11 +300,19 @@ def execute(args):
291300
done = False
292301
while not done:
293302

303+
if saveConcentrationProfiles:
304+
workbook = xlwt.Workbook()
305+
294306
done = True
295307
objectsToEnlarge = []
296308
allTerminated = True
297309
for index, reactionSystem in enumerate(reactionSystems):
298310

311+
if saveConcentrationProfiles:
312+
worksheet = workbook.add_sheet('#{0:d}'.format(index+1))
313+
else:
314+
worksheet = None
315+
299316
# Conduct simulation
300317
logging.info('Conducting simulation of reaction system %s...' % (index+1))
301318
terminated, obj = reactionSystem.simulate(
@@ -308,6 +325,7 @@ def execute(args):
308325
toleranceInterruptSimulation = reactionModel.fluxToleranceInterrupt,
309326
termination = reactionModel.termination,
310327
pdepNetworks = reactionModel.unirxnNetworks,
328+
worksheet = worksheet,
311329
)
312330
allTerminated = allTerminated and terminated
313331
logging.info('')
@@ -323,6 +341,9 @@ def execute(args):
323341
objectsToEnlarge.append(obj)
324342
done = False
325343

344+
if saveConcentrationProfiles:
345+
workbook.save(os.path.join(settings.outputDirectory, 'solver', 'simulation_{0:d}.xls'.format(len(reactionModel.core.species))))
346+
326347
if not done:
327348

328349
# If we reached our termination conditions, then try to prune

rmgpy/solver/base.pxd

+4-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ from pydas cimport DASSL
3232

3333
cdef class ReactionSystem(DASSL):
3434

35+
cdef public numpy.ndarray coreSpeciesConcentrations
3536
cdef public numpy.ndarray coreSpeciesRates
3637
cdef public numpy.ndarray coreReactionRates
3738
cdef public numpy.ndarray edgeSpeciesRates
@@ -44,9 +45,11 @@ cdef class ReactionSystem(DASSL):
4445

4546
cpdef initializeModel(self, list coreSpecies, list coreReactions, list edgeSpecies, list edgeReactions, list pdepNetworks=?)
4647

48+
cpdef writeWorksheetHeader(self, worksheet)
49+
4750
cpdef simulate(self, list coreSpecies, list coreReactions, list edgeSpecies, list edgeReactions,
4851
double toleranceKeepInEdge, double toleranceMoveToCore, double toleranceInterruptSimulation,
49-
list termination, list pdepNetworks=?)
52+
list termination, list pdepNetworks=?, worksheet=?)
5053

5154
cpdef logRates(self, double charRate, object species, double speciesRate, object network, double networkRate)
5255

rmgpy/solver/base.pyx

+32-1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ cdef class ReactionSystem(DASSL):
5050
def __init__(self):
5151
DASSL.__init__(self)
5252
# The reaction and species rates at the current time (in mol/m^3*s)
53+
self.coreSpeciesConcentrations = None
5354
self.coreSpeciesRates = None
5455
self.coreReactionRates = None
5556
self.edgeSpeciesRates = None
@@ -76,6 +77,7 @@ cdef class ReactionSystem(DASSL):
7677
numEdgeReactions = len(edgeReactions)
7778
numPdepNetworks = len(pdepNetworks)
7879

80+
self.coreSpeciesConcentrations = numpy.zeros((numCoreSpecies), numpy.float64)
7981
self.coreReactionRates = numpy.zeros((numCoreReactions), numpy.float64)
8082
self.edgeReactionRates = numpy.zeros((numEdgeReactions), numpy.float64)
8183
self.coreSpeciesRates = numpy.zeros((numCoreSpecies), numpy.float64)
@@ -85,10 +87,20 @@ cdef class ReactionSystem(DASSL):
8587
self.maxEdgeSpeciesRates = numpy.zeros((numEdgeSpecies), numpy.float64)
8688
self.maxNetworkLeakRates = numpy.zeros((numPdepNetworks), numpy.float64)
8789

90+
91+
cpdef writeWorksheetHeader(self, worksheet):
92+
"""
93+
Write some descriptive information about the reaction system to the
94+
first two rows of the given `worksheet`.
95+
"""
96+
import xlwt
97+
style0 = xlwt.easyxf('font: bold on')
98+
worksheet.write(0, 0, 'Reaction System', style0)
99+
88100
@cython.boundscheck(False)
89101
cpdef simulate(self, list coreSpecies, list coreReactions, list edgeSpecies, list edgeReactions,
90102
double toleranceKeepInEdge, double toleranceMoveToCore, double toleranceInterruptSimulation,
91-
list termination, list pdepNetworks=None):
103+
list termination, list pdepNetworks=None, worksheet=None):
92104
"""
93105
Simulate the reaction system with the provided reaction model,
94106
consisting of lists of core species, core reactions, edge species, and
@@ -109,6 +121,7 @@ cdef class ReactionSystem(DASSL):
109121
cdef numpy.ndarray[numpy.float64_t, ndim=1] maxCoreSpeciesRates, maxEdgeSpeciesRates, maxNetworkLeakRates
110122
cdef bint terminated
111123
cdef object maxSpecies, maxNetwork
124+
cdef int iteration, i
112125

113126
pdepNetworks = pdepNetworks or []
114127

@@ -130,6 +143,7 @@ cdef class ReactionSystem(DASSL):
130143
maxNetworkIndex = -1
131144
maxNetwork = None
132145
maxNetworkRate = 0.0
146+
iteration = 0
133147

134148
maxCoreSpeciesRates = self.maxCoreSpeciesRates
135149
maxEdgeSpeciesRates = self.maxEdgeSpeciesRates
@@ -138,11 +152,28 @@ cdef class ReactionSystem(DASSL):
138152
# Copy the initial conditions to use in evaluating conversions
139153
y0 = self.y.copy()
140154

155+
if worksheet:
156+
import xlwt
157+
self.writeWorksheetHeader(worksheet)
158+
style0 = xlwt.easyxf('font: bold on')
159+
style1 = xlwt.easyxf(num_format_str='0.000E+00')
160+
worksheet.write(3, 0, 'Time (s)', style0)
161+
worksheet.write(3, 1, 'Concentrations (mol/m^3)', style0)
162+
for i in range(numCoreSpecies):
163+
worksheet.write(4, i+1, str(coreSpecies[i]), style0)
164+
141165
stepTime = 1e-12
142166
while not terminated:
143167
# Integrate forward in time by one time step
144168
self.step(stepTime)
145169

170+
iteration += 1
171+
172+
if worksheet:
173+
worksheet.write(iteration+4, 0, self.t, style1)
174+
for i in range(numCoreSpecies):
175+
worksheet.write(iteration+4, i+1, self.coreSpeciesConcentrations[i], style1)
176+
146177
# Get the characteristic flux
147178
charRate = sqrt(numpy.sum(self.coreSpeciesRates * self.coreSpeciesRates))
148179

rmgpy/solver/simple.pyx

+16
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,22 @@ cdef class SimpleReactor(ReactionSystem):
144144
y0 = numpy.zeros((numCoreSpecies), numpy.float64)
145145
for spec, moleFrac in self.initialMoleFractions.iteritems():
146146
y0[speciesIndex[spec]] = moleFrac * (self.P / constants.R / self.T)
147+
self.coreSpeciesConcentrations[speciesIndex[spec]] = y0[speciesIndex[spec]]
147148

148149
# Initialize the model
149150
dydt0 = - self.residual(t0, y0, numpy.zeros((numCoreSpecies), numpy.float64))[0]
150151
DASSL.initialize(self, t0, y0, dydt0)
151152

153+
cpdef writeWorksheetHeader(self, worksheet):
154+
"""
155+
Write some descriptive information about the reaction system to the
156+
first two rows of the given `worksheet`.
157+
"""
158+
import xlwt
159+
style0 = xlwt.easyxf('font: bold on')
160+
worksheet.write(0, 0, 'Simple Reactor', style0)
161+
worksheet.write(1, 0, 'T = {0:g} K, P = {1:g} bar'.format(self.T, self.P/1e5))
162+
152163
@cython.boundscheck(False)
153164
def residual(self, double t, numpy.ndarray[numpy.float64_t, ndim=1] y, numpy.ndarray[numpy.float64_t, ndim=1] dydt):
154165

@@ -178,12 +189,16 @@ cdef class SimpleReactor(ReactionSystem):
178189
numEdgeReactions = len(self.edgeReactionRates)
179190
numPdepNetworks = len(self.networkLeakRates)
180191

192+
coreSpeciesConcentrations = numpy.zeros_like(self.coreSpeciesConcentrations)
181193
coreSpeciesRates = numpy.zeros_like(self.coreSpeciesRates)
182194
coreReactionRates = numpy.zeros_like(self.coreReactionRates)
183195
edgeSpeciesRates = numpy.zeros_like(self.edgeSpeciesRates)
184196
edgeReactionRates = numpy.zeros_like(self.edgeReactionRates)
185197
networkLeakRates = numpy.zeros_like(self.networkLeakRates)
186198

199+
for j in range(y.shape[0]):
200+
coreSpeciesConcentrations[j] = y[j]
201+
187202
for j in range(ir.shape[0]):
188203
k = kf[j]
189204
if ir[j,0] >= numCoreSpecies or ir[j,1] >= numCoreSpecies or ir[j,2] >= numCoreSpecies:
@@ -264,6 +279,7 @@ cdef class SimpleReactor(ReactionSystem):
264279
reactionRate = k * y[inet[j,0]] * y[inet[j,1]] * y[inet[j,2]]
265280
networkLeakRates[j] = reactionRate
266281

282+
self.coreSpeciesConcentrations = coreSpeciesConcentrations
267283
self.coreSpeciesRates = coreSpeciesRates
268284
self.coreReactionRates = coreReactionRates
269285
self.edgeSpeciesRates = edgeSpeciesRates

0 commit comments

Comments
 (0)