cantera/interfaces/python/MixMaster/KineticsFrame.py
Ray Speth 2528df0f75 Reorganized source tree structure
These changes make it unnecessary to copy header files around during
the build process, which tends to confuse IDEs and debuggers. The
headers which comprise Cantera's external C++ interface are now in
the 'include' directory.

All of the samples and demos are now in the 'samples' subdirectory.
2012-02-12 02:27:14 +00:00

418 lines
11 KiB
Python

import os, math
from Tkinter import *
from Cantera import *
from SpeciesInfo import SpeciesInfo
from Cantera import rxnpath
import webbrowser
_CUTOFF = 1.e-15
_ATOL = 1.e-15
_RTOL = 1.e-7
def showsvg():
f = open('_rp_svg.html','w')
f.write('<embed src="rxnpath.svg" name="rxnpath" height=500\n')
f.write('type="image/svg-xml" pluginspage="http://www.adobe.com/svg/viewer/install/">\n')
f.close()
webbrowser.open('file:///'+os.getcwd()+'/_rp_svg.html')
def showpng():
f = open('_rp_png.html','w')
f.write('<img src="rxnpath.png" height=500/>\n')
f.close()
webbrowser.open('file:///'+os.getcwd()+'/_rp_png.html')
class KineticsFrame(Frame):
def __init__(self,master):
Frame.__init__(self,master)
self.config(relief=FLAT, bd=4)
self.top = self.master.top
self.controls=Frame(self)
self.hide = IntVar()
self.hide.set(0)
self.comp = IntVar()
self.comp.set(2)
self.controls.grid(column=1,row=0,sticky=W+E+N)
self.makeControls()
mf = self.master
def makeControls(self):
Radiobutton(self.controls,text='Creation Rates',
variable=self.comp,value=0,
command=self.show).grid(column=0,row=0,sticky=W)
Radiobutton(self.controls,text='Destruction Rates',
variable=self.comp,value=1,
command=self.show).grid(column=0,row=1,sticky=W)
Radiobutton(self.controls,text='Net Production Rates',
variable=self.comp,value=2,
command=self.show).grid(column=0,row=2,sticky=W)
def show(self):
mf = self.master
mf.active = self
c = self.comp.get()
mix = self.top.mix
g = mix.g
if c == 0:
mf.var.set("Creation Rates")
#mf.data = spdict(mix.g, mix.moles())
mf.comp = g.creationRates()
elif c == 1:
mf.var.set("Destruction Rates")
#mf.data = spdict(mix.g,mix.mass())
mf.comp = g.destructionRates()
elif c == 2:
mf.var.set("Net Production Rates")
mf.comp = g.netProductionRates()
#mf.data = spdict(mix,mix,mf.comp)
for s in mf.variable.keys():
try:
k = g.speciesIndex(s)
if mf.comp[k] > _CUTOFF or -mf.comp[k] > _CUTOFF:
mf.variable[s].set(mf.comp[k])
else:
mf.variable[s].set(0.0)
except:
pass
class SpeciesKineticsFrame(Frame):
def __init__(self,master,top):
Frame.__init__(self,master)
self.config(relief=GROOVE, bd=4)
self.top = top
self.top.kinetics = self
self.g = self.top.mix.g
self.entries=Frame(self)
self.var = StringVar()
self.var.set("Net Production Rates")
self.names = self.top.mix.speciesNames()
self.nsp = len(self.names)
self.comp = [0.0]*self.nsp
self.makeControls()
self.makeEntries()
self.entries.bind('<Double-l>',self.minimize)
self.ctype = 0
def makeControls(self):
self.c = KineticsFrame(self)
#self.rr = ReactionKineticsFrame(self, self.top)
self.c.grid(column=1,row=0,sticky=E+W+N+S)
#self.rr.grid(column=0,row=1,sticky=E+W+N+S)
def show(self):
self.c.show()
def redo(self):
self.update()
self.entries.destroy()
self.entries=Frame(self)
self.makeEntries()
def minimize(self,Event=None):
self.c.hide.set(1)
self.redo()
self.c.grid_forget()
self.entries.bind("<Double-1>",self.maximize)
def maximize(self,Event=None):
self.c.hide.set(0)
self.redo()
self.c.grid(column=1,row=0,sticky=E+W+N+S)
self.entries.bind("<Double-1>",self.minimize)
def up(self, x):
self.update()
def makeEntries(self):
self.entries.grid(row=0,column=0,sticky=W+N+S+E)
self.entries.config(relief=FLAT,bd=4)
DATAKEYS = self.top.species
self.variable = {}
n=0
ncol = 3
col = 0
row = 60
for sp in DATAKEYS:
s = sp
k = s.index
if row > 15:
row = 0
col = col + 2
l = Label(self.entries,text='Species')
l.grid(column=col,row=row,sticky=E+W)
e1 = Entry(self.entries)
e1.grid(column=col+1,row=row,sticky=E+W)
e1['textvariable'] = self.var
e1.config(state=DISABLED)
e1.config(bg='lightyellow',relief=RIDGE)
row = row + 1
spname = s.name
val = self.comp[k]
if not self.c.hide.get() or val: showit = 1
else: showit = 0
l=SpeciesInfo(self.entries,species=s,
text=spname,relief=FLAT,justify=RIGHT,
fg='darkblue')
entry1 = Entry(self.entries)
self.variable[spname] = DoubleVar()
self.variable[spname].set(self.comp[k])
entry1['textvariable']=self.variable[spname]
entry1.bind('<Any-Leave>',self.up)
if showit:
l.grid(column= col ,row=row,sticky=E)
entry1.grid(column=col+1,row=row)
n=n+1
row = row + 1
entry1.config(state=DISABLED,bg='lightgray')
class ReactionKineticsFrame(Frame):
def __init__(self,vis,top):
self.master = Toplevel()
self.master.protocol("WM_DELETE_WINDOW",self.hide)
self.vis = vis
Frame.__init__(self,self.master)
self.config(relief=GROOVE, bd=4)
self.top = top
self.g = self.top.mix.g
nr = self.g.nReactions()
self.eqs=Text(self,width=40,height=30)
self.data = []
self.start = DoubleVar()
if nr > 30:
self.end = self.start.get()+30
else:
self.end = self.start.get()+nr
for i in range(4):
self.data.append(Text(self,width=15,height=30))
for n in range(nr):
s = self.g.reactionEqn(n)
self.eqs.insert(END,s+'\n')
self.eqs.grid(column=0,row=1,sticky=W+E+N)
for i in range(4):
self.data[i].grid(column=i+1,row=1,sticky=W+E+N)
Label(self, text='Reaction').grid(column=0,row=0,sticky=W+E+N)
Label(self, text='Fwd ROP').grid(column=1,row=0,sticky=W+E+N)
Label(self, text='Rev ROP').grid(column=2,row=0,sticky=W+E+N)
Label(self, text='Net ROP').grid(column=3,row=0,sticky=W+E+N)
Label(self, text='Kp').grid(column=4,row=0,sticky=W+E+N)
self.scfr = Frame(self)
self.scfr.config(relief=GROOVE,bd=4)
## self.sc = Scrollbar(self.scfr,command=self.show,
## variable = self.start,
## orient='horizontal',length=400)
self.sc = Scale(self.scfr,command=self.show,
variable=self.start,
orient='vertical',length=400)
# self.sc.config(cnf={'from':0,'to':nr},variable = self.start)
#self.sc.bind('<Any-Enter>',self.couple)
#self.scfr.bind('<Any-Leave>',self.decouple)
self.sc.pack(side=RIGHT,fill=Y)
self.scfr.grid(row=0,column=6,rowspan=10,sticky=N+E+W)
self.grid(column=0,row=0)
self.hide()
## def decouple(self,event=None):
## d = DoubleVar()
## xx = self.start.get()
## d.set(xx)
## self.sc.config(variable = d)
## def couple(self,event=None):
## self.sc.config(variable = self.start)
def hide(self):
# self.vis.set(0)
self.master.withdraw()
def show(self,e=None,b=None,c=None):
v = self.vis.get()
print e,b,c
#if v == 0:
# self.hide()
# return
self.master.deiconify()
nr = self.g.nReactions()
frop = self.g.fwdRatesOfProgress()
rrop = self.g.revRatesOfProgress()
kp = self.g.equilibriumConstants()
self.data[0].delete(1.0,END)
self.data[1].delete(1.0,END)
self.data[2].delete(1.0,END)
self.data[3].delete(1.0,END)
self.eqs.delete(1.0,END)
n0 = int(self.start.get())
nn = nr - n0
if nn > 30: nn = 30
for n in range(n0, nn+n0):
s = '%12.5e \n' % (frop[n],)
self.data[0].insert(END,s)
s = '%12.5e \n' % (rrop[n],)
self.data[1].insert(END,s)
s = '%12.5e \n' % (frop[n] - rrop[n],)
self.data[2].insert(END,s)
s = '%12.5e \n' % (kp[n],)
self.data[3].insert(END,s)
self.eqs.insert(END, self.g.reactionEqn(n)+'\n')
class ReactionPathFrame(Frame):
def __init__(self,top):
self.master = Toplevel()
self.master.protocol("WM_DELETE_WINDOW",self.hide)
#self.vis = vis
Frame.__init__(self,self.master)
self.config(relief=GROOVE, bd=4)
self.grid(column=0,row=0)
self.top = top
self.g = self.top.mix.g
self.el = IntVar()
self.el.set(0)
self.thresh = DoubleVar()
scframe = Frame(self)
self.sc = Scale(scframe,variable = self.thresh,
orient='horizontal',digits=3,length=300,resolution=0.01)
self.sc.config(cnf={'from':-6,'to':0})
Label(scframe,text='log10 Threshold').grid(column=0,row=0)
self.sc.grid(row=0,column=1,columnspan=10)
self.sc.bind('<ButtonRelease-1>',self.show)
scframe.grid(row=3,column=0,columnspan=10)
enames = self.g.elementNames()
self.nel = len(enames)
i = 1
eframe = Frame(self)
Label(eframe,text='Element').grid(column=0,row=0,sticky=W)
for e in enames:
Radiobutton(eframe,text=e,
variable=self.el,value=i-1,
command=self.show).grid(column=i,row=0,sticky=W)
i += 1
eframe.grid(row=0,column=0)
self.detailed = IntVar()
Checkbutton(self, text = 'Show details', variable=self.detailed,
command=self.show).grid(column=1,row=0)
self.net = IntVar()
Checkbutton(self, text = 'Show net flux',
variable=self.net,
command=self.show).grid(column=2,row=0)
self.local = StringVar()
Label(self,text='Species').grid(column=1,row=1,sticky=E)
sp = Entry(self, textvariable=self.local,
width=15)
sp.grid(column=2,row=1)
sp.bind('<Any-Leave>',self.show)
self.b = rxnpath.PathBuilder(self.g)
self.fmt = StringVar()
self.fmt.set('svg')
i = 1
fmtframe = Frame(self)
fmtframe.config(relief=GROOVE, bd=4)
self.browser = IntVar()
self.browser.set(0)
Checkbutton(fmtframe, text = 'Display in Web Browser',
variable=self.browser,
command=self.show).grid(column=0,columnspan=6,row=0)
Label(fmtframe,text='Format').grid(column=0,row=1,sticky=W)
for e in ['svg', 'png', 'gif', 'jpg']:
Radiobutton(fmtframe,text=e,
variable=self.fmt,value=e,
command=self.show).grid(column=i,row=1,sticky=W)
i += 1
fmtframe.grid(row=5,column=0,columnspan=10,sticky=E+W)
self.cv = Canvas(self,relief=SUNKEN,bd=1)
self.cv.grid(column=0,row=4,sticky=W+E+N,columnspan=10)
pframe = Frame(self)
pframe.config(relief=GROOVE, bd=4)
self.dot = StringVar()
self.dot.set('dot -Tgif rxnpath.dot > rxnpath.gif')
Label(pframe,text='DOT command:').grid(column=0,row=0,sticky=W)
Entry(pframe,width=60,textvariable=self.dot).grid(column=0,
row=1,sticky=W)
pframe.grid(row=6,column=0,columnspan=10,sticky=E+W)
self.thresh.set(-2.0)
self.hide()
def hide(self):
#self.vis.set(0)
self.master.withdraw()
def show(self,e=None):
self.master.deiconify()
el = self.g.elementName(self.el.get())
det = 'false'
if self.detailed.get() == 1: det = 'true'
flow = 'one_way'
if self.net.get() == 1: flow = 'net'
self.d = rxnpath.PathDiagram(arrow_width=-2,
flow_type=flow,
detailed = det,
threshold=math.pow(10.0,
self.thresh.get()))
node = self.local.get()
try:
k = self.g.speciesIndex(node)
self.d.displayOnly(k)
except:
self.d.displayOnly()
self.b.build(element = el, diagram = self.d,
dotfile = 'rxnpath.dot', format = 'dot')
#self.b.build(element = el, diagram = self.d,
# dotfile = 'rxnpath.txt', format = 'plain')
if self.browser.get() == 1:
fmt = self.fmt.get()
os.system('dot -T'+fmt+' rxnpath.dot > rxnpath.'+fmt)
if fmt == 'svg': showsvg()
elif fmt == 'png': showpng()
else:
path = 'file:///'+os.getcwd()+'/rxnpath.'+fmt
webbrowser.open(path)
try:
self.cv.delete(self.image)
except:
pass
self.cv.configure(width=0, height=0)
else:
os.system(self.dot.get())
self.rp = None
try:
self.cv.delete(self.image)
except:
pass
try:
self.rp = PhotoImage(file='rxnpath.gif')
self.cv.configure(width=self.rp.width(),
height=self.rp.height())
self.image = self.cv.create_image(0,0,anchor=NW,
image=self.rp)
except:
pass