Add current version of MixMaster to the Cython package

Note that this currently doesn't work at all, due to both Python 3 compatibility
issues as well as the changes to the Cantera Python API
This commit is contained in:
Ray Speth
2013-06-21 20:58:22 +00:00
parent 84aaec1417
commit 440bf4a8d1
45 changed files with 5340 additions and 0 deletions

View File

@@ -30,6 +30,8 @@ def add_dependencies(mod, ext):
localenv.Depends(ext, f)
for f in (mglob(localenv, 'cantera/test', 'py') +
mglob(localenv, 'cantera/mixmaster', 'py') +
mglob(localenv, 'cantera/mixmaster/Units', 'py') +
mglob(localenv, 'cantera/examples/tutorial', 'py') +
mglob(localenv, 'cantera/examples/equilibrium', 'py') +
mglob(localenv, 'cantera/examples/kinetics', 'py') +

View File

@@ -0,0 +1,244 @@
from Tkinter import *
from Cantera import *
from SpeciesInfo import SpeciesInfo
#from KineticsFrame import KineticsFrame
_CUTOFF = 1.e-15
_ATOL = 1.e-15
_RTOL = 1.e-7
class CompFrame(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(0)
self.controls.grid(column=1,row=0,sticky=W+E+N)
self.makeControls()
mf = self.master
def makeControls(self):
Radiobutton(self.controls,text='Moles',
variable=self.comp,value=0,
command=self.show).grid(column=0,row=0,sticky=W)
Radiobutton(self.controls,text='Mass',
variable=self.comp,value=1,
command=self.show).grid(column=0,row=1,sticky=W)
Radiobutton(self.controls,text='Concentration',
variable=self.comp,value=2,
command=self.show).grid(column=0,row=2,sticky=W)
Button(self.controls,text='Clear',
command=self.zero).grid(column=0,row=4,sticky=W+E)
Button(self.controls,text='Normalize',
command=self.norm).grid(column=0,row=5,sticky=W+E)
Checkbutton(self.controls,text='Hide Missing\nSpecies',
variable=self.hide,onvalue=1,
offvalue=0,command=self.master.redo).grid(column=0,
row=3,
sticky=W)
def norm(self):
mf = self.master
mf.update()
data = mf.comp
sum = 0.0
for sp in data:
sum += sp
for i in range(len(mf.comp)):
mf.comp[i] /= sum
self.show()
def set(self):
c = self.comp.get()
mix = self.top.mix
mf = self.master
g = mix.g
if c == 0:
mix.setMoles(mf.comp)
elif c == 1:
mix.setMass(mf.comp)
elif c == 2:
pass
self.top.thermo.setState()
self.top.kinetics.show()
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("Moles")
#mf.data = spdict(mix.g, mix.moles())
mf.comp = mix.moles()
elif c == 1:
mf.var.set("Mass")
#mf.data = spdict(mix.g,mix.mass())
mf.comp = mix.mass()
elif c == 2:
mf.var.set("Concentration")
mf.comp = mix.concentrations()
#mf.data = spdict(mix,mix,mf.comp)
for s in mf.variable.keys():
try:
k = g.speciesIndex(s)
if mf.comp[k] > _CUTOFF:
mf.variable[s].set(mf.comp[k])
else:
mf.variable[s].set(0.0)
except:
pass
def zero(self):
mf = self.master
mf.comp *= 0.0
self.show()
class MixtureFrame(Frame):
def __init__(self,master,top):
Frame.__init__(self,master)
self.config(relief=GROOVE, bd=4)
self.top = top
self.top.mixframe = self
self.g = self.top.mix.g
#self.scroll = Scrollbar(self)
self.entries=Frame(self)
#self.scroll.config(command=self.entries.xview)
#self.scroll.grid(column=0,row=1)
self.var = StringVar()
self.var.set("Moles")
self.comp = array(self.top.mix.moles())
self.names = self.top.mix.speciesNames()
self.nsp = len(self.names)
#self.data = self.top.mix.moleDict()
self.makeControls()
self.makeEntries()
self.entries.bind('<Double-l>',self.minimize)
self.ctype = 0
self.newcomp = 0
def makeControls(self):
self.c = CompFrame(self)
#self.k = KineticsFrame(self)
self.active = self.c
self.c.grid(column=1,row=0,sticky=E+W+N+S)
#self.k.grid(column=2,row=0,sticky=E+W+N+S)
def update(self):
self.newcomp = 0
for s in self.variable.keys():
k = self.g.speciesIndex(s)
current = self.comp[k]
val = self.variable[s].get()
dv = abs(val - current)
if dv > _RTOL*abs(current) + _ATOL:
self.comp[k] = val
self.newcomp = 1
def show(self):
self.active.show()
## for k in range(self.nsp):
## sp = self.names[k]
## if self.comp[k] > _CUTOFF:
## self.variable[sp].set(self.comp[k])
## else:
## self.variable[sp].set(0.0)
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()
if self.newcomp:
self.c.set()
self.c.show()
self.top.update()
#thermo.showState()
#self.top.kinetics.show()
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
equil = 0
if self.top.thermo:
equil = self.top.thermo.equil.get()
for sp in DATAKEYS:
s = sp # self.top.species[sp]
k = s.index
if row > 25:
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
if equil == 1:
entry1.config(state=DISABLED,bg='lightgray')
## if self.c.hide.get():
## b=Button(self.entries,height=1,command=self.maximize)
## else:
## b=Button(self.entries,command=self.minimize)
## b.grid(column=col,columnspan=2, row=row+1)

View File

@@ -0,0 +1,213 @@
from types import *
from Tkinter import *
from ScrolledText import ScrolledText
#import datawindow
#import filewindow
def ff():
print ' hi '
class ControlWindow(Frame):
fncs = [ff]*10
def __init__(self, title, master=None):
self.app = master
Frame.__init__(self,master)
self.grid(row=0,column=0,sticky=E+W+N+S)
self.master.title(title)
def addButtons(self, label, funcs):
self.buttonholder = Frame(self, relief=FLAT, bd=2)
self.buttonholder.pack(side=TOP,anchor=W)
b = Label(self.buttonholder,text=label)
b.pack(side=LEFT,fill=X)
for f in funcs:
b=Button(self.buttonholder,
text=f[0],command=f[1], padx=1,pady=1)
b.pack(side=LEFT,fill=X)
def disableButtons(self, *buttons):
for button in self.buttonholder.slaves():
if (button.cget('text') in buttons):
try:
button.config(state=DISABLED)
except:
pass
def enableButtons(self, *buttons):
for button in self.buttonholder.slaves():
if (button.cget('text') in buttons):
try:
button.config(state=NORMAL)
except:
pass
def newFrame(self, label, var):
fr = Frame(self, relief = RIDGE, bd = 2)
fr.pack(side=TOP,fill=X)
c = Checkbutton(fr, variable=var)
c.pack(side = LEFT, fill = X)
b = Label(fr,text=label,foreground="NavyBlue")
b.pack(side=LEFT,fill=X)
return fr
##creates a new Toplevel object
##options: transient=<callback for window close>,
## placement=(<screen x-coord>, <screen y-coord>)
def newWindow(self, master, title, **options):
new = Toplevel(master)
new.title(title)
#new.config(takefocus=0)
if 'transient' in options.keys():
new.transient(master)
if options['transient']:
new.protocol('WM_DELETE_WINDOW', options['transient'])
if 'placement' in options.keys():
new.geometry("+%d+%d" % tuple(options['placement']))
return new
##routes mouse and keyboard events to the window and
##waits for it to close before returning
def makemodal(self, window):
window.focus_set()
window.grab_set()
window.wait_window()
return
def PlotMenu(self, fr, label, funcs):
filebutton = Menubutton(fr,text=label, padx=3,pady=1)
filebutton.pack(side=LEFT)
filemenu = Menu(filebutton,tearoff=TRUE)
i = 0
for f in funcs:
filemenu.add_command(label=f[0], command=f[1])
i = i + 1
filebutton['menu']=filemenu
return filemenu
def testevent(event):
print 'event ',event.value
def make_menu(name, menubar, list):
nc = len(name)
button=Menubutton(menubar, text=name, width=nc+4, padx=3,pady=1)
button.pack(side=LEFT)
menu = Menu(button,tearoff=FALSE)
m = menu
i = 0
for entry in list:
i += 1
if entry == 'separator':
menu.add_separator({})
elif type(entry)==ListType:
for num in entry:
menu.entryconfig(num,state=DISABLED)
elif type(entry[1]) != ListType:
if i == 20:
i = 0
submenu = Menu(button,tearoff=FALSE)
m.add_cascade(label='More...',
menu=submenu)
m = submenu
if len(entry) == 2 or entry[2] == 'command':
m.add_command(label=entry[0],
command=entry[1])
elif entry[2] == 'check':
entry[3].set(0)
if len(entry) >= 5: val = entry[4]
else: val = 1
m.add_checkbutton(label=entry[0],
command=entry[1],
variable = entry[3],
onvalue=val)
else:
submenu=make_menu(entry[0], menu, entry[1])
m.add_cascade(label=entry[0],
menu=submenu)
button['menu']=menu
return button
def menuitem_state(button, *statelist):
for menu in button.children.keys():
if isinstance(button.children[menu], Menu):
for (commandnum, onoff) in statelist:
if onoff==0:
button.children[menu].entryconfig(commandnum,state=DISABLED)
if onoff==1:
button.children[menu].entryconfig(commandnum,state=NORMAL)
else:
pass
class ArgumentWindow(Toplevel):
import tkMessageBox
def __init__(self, sim, **options):
Toplevel.__init__(self, sim.cwin)
self.resizable(FALSE,FALSE)
self.protocol("WM_DELETE_WINDOW", lambda:0) #self.cancelled)
self.transient(sim.cwin)
if 'placement' in options.keys():
self.geometry("+%d+%d" % tuple(options['placement']))
self.title('Thermal Model Initialization')
self.sim = sim
self.make_options()
buttonframe = Frame(self)
buttonframe.pack(side=BOTTOM)
b1=Button(buttonframe, text='OK', command=self.callback)
b1.pack(side=LEFT)
#b2=Button(buttonframe, text='Cancel', command=self.cancelled)
#b2.pack(side=LEFT)
self.bind("<Return>", self.callback)
#self.bind("<Escape>", self.cancelled)
self.initial_focus = self
self.initial_focus.focus_set()
#self.wait_window(self)
def make_options(self):
pass
### must override this function ###
### with the entry forms ###
### be sure to use pack or a ###
### frame that is packed into self ###
def getArguments(self):
pass
### must override this function ###
### with the validation checking ###
### must return None if error, ###
### and non_null if ok ###
def callback(self, event=None):
g=self.getArguments()
if not g:
self.initial_focus.focus_set()
return
self.withdraw()
self.update_idletasks()
self.assign(g)
self.cancelled()
def assign(self, obj):
pass
### must override this function ###
### to do the assignment in sim ###
def cancelled(self,event=None):
self.sim.cwin.focus_set()
self.destroy()
if __name__=='__main__':
t = Tk()
ControlWindow(t).mainloop()

View File

@@ -0,0 +1,359 @@
import os, math, string
from Tkinter import *
from Cantera import *
from Cantera.num import *
from Cantera import num
from tkFileDialog import askopenfilename
from GraphFrame import Graph
from DataGraph import DataGraph, plotLimits
from ControlPanel import make_menu
U_LOC = 1
V_LOC = 2
T_LOC = 3
P_LOC = 4
Y_LOC = 5
def testit(e = None):
pass
class DataFrame(Frame):
def __init__(self,master,top):
# if master==None:
self.master = Toplevel()
self.master.protocol("WM_DELETE_WINDOW",self.hide)
#else:
# self.master = master
#self.vis = vis
Frame.__init__(self,self.master)
self.config(relief=GROOVE, bd=4)
self.top = top
self.mix = self.top.mix
self.g = self.top.mix.g
self.data = None
self.zdata = None
self.ydata = None
self.plt = None
#self.pltwhat = None
self.datasets = []
self.vars = []
self.whichsoln = IntVar()
self.loc = IntVar()
# self.loc.set(1)
self.lastloc = T_LOC # self.loc.get()
self.datafile = StringVar()
self.solnid = StringVar()
self.gr = Frame(self)
self.n = IntVar()
self.scframe = Frame(self)
self.sc = Scale(self.scframe, variable = self.n,
orient='horizontal',digits=0,
length=300,resolution=1,command=self.updateplot)
self.sc.config(cnf={'from':0,'to':1})
Label(self.scframe,text='Grid Point').grid(column=0,row=0)
self.sc.grid(row=0,column=1)
self.sc.bind('<ButtonRelease-1>',self.updateState)
self.gr.grid(row=4,column=0,columnspan=10)
self.grid(column=0,row=10)
self.makeMenu()
self.hide()
def makeMenu(self):
self.menubar = Frame(self, relief=GROOVE,bd=2)
self.menubar.grid(row=0,column=0,sticky=N+W+E,columnspan=10)
f = [('Open...',self.browseForDatafile)]
#make_menu('File',self.menubar,items)
make_menu('File',self.menubar,f)
make_menu('Dataset',self.menubar,self.datasets)
make_menu('Plot',self.menubar,self.vars)
def browseForDatafile(self, e=None):
pathname = askopenfilename(
filetypes=[("Data Files", ("*.xml","*.csv","*.dat")),
("All Files", "*.*")])
if pathname:
self.datafile.set(pathname)
self.show()
self.getSoln()
def getSoln(self):
fname = os.path.basename(self.datafile.get())
ff = os.path.splitext(fname)
self.datasets = []
if len(ff) == 2 and (ff[1] == '.xml' or ff[1] == '.ctml'):
x = XML.XML_Node('root',src=self.datafile.get())
c = x.child('ctml')
self.solns = c.children('simulation')
if len(self.solns) > 1:
i = 0
for soln in self.solns:
self.datasets.append((soln['id'],self.pickSoln,
'check',self.whichsoln,i))
i += 1
self.solnid.set(self.solns[-1]['id'])
self.soln = self.solns[-1]
self.importData()
elif len(ff) == 2 and (ff[1] == '.csv' or ff[1] == '.CSV'):
self.importCSV()
self.makeMenu()
if self.loc.get() <= 0:
self.loc.set(self.lastloc)
def importCSV(self):
self.lastloc = self.loc.get()
if self.lastloc <= 0: self.lastloc = T_LOC
self.vars = []
self.zdata = None
self.ydata = None
if self.plt:
self.plt.destroy()
f = open(self.datafile.get(),'r')
lines = f.readlines()
vars = string.split(lines[0],',')
nlines = len(lines)
self.np = nlines - 1
nv = len(vars)
vv = []
for n in range(nv):
nm = vars[n].split()
if n < nv - 1 or (len(nm) > 0 and nm[0].isalnum()):
vv.append(nm[0])
else:
break
nv = len(vv)
vars = vv
fdata = zeros((nv, self.np),'d')
for n in range(self.np):
v = string.split(lines[n+1],',')
for j in range(nv):
try:
fdata[j,n] = float(v[j])
except:
fdata[j,n] = 0.0
self.nsp = self.g.nSpecies()
self.y = zeros(self.nsp,'d')
self.data = zeros((self.nsp+6,self.np),'d')
self.data[0,:] = fdata[0,:]
self.label = ['-']*(self.nsp+6)
self.label[0] = vars[0]
w = []
for n in range(1,nv-1):
try:
k = self.g.speciesIndex(vars[n])
except:
k = -1
v2 = vars[n]
if v2 == 'T':
self.data[T_LOC,:] = fdata[n,:]
self.label[T_LOC] = vars[n]
w.append(('T', self.newplot, 'check', self.loc, T_LOC))
elif v2 == 'P':
self.data[P_LOC,:] = fdata[n,:]
self.label[P_LOC] = vars[n]
w.append((vars[n], self.newplot, 'check', self.loc, P_LOC))
elif v2 == 'u':
self.data[U_LOC,:] = fdata[n,:]
self.label[U_LOC] = vars[n]
w.append((vars[n], self.newplot, 'check', self.loc, U_LOC))
elif v2 == 'V':
self.data[V_LOC,:] = fdata[n,:]
self.label[V_LOC] = vars[n]
w.append((vars[n], self.newplot, 'check', self.loc, V_LOC))
elif k >= 0:
self.data[k+Y_LOC,:] = fdata[n,:]
self.label[k+Y_LOC] = vars[n]
w.append((vars[n], self.newplot, 'check', self.loc, k + Y_LOC))
if self.data[P_LOC,0] == 0.0:
self.data[P_LOC,:] = ones(self.np,'d')*OneAtm
print 'Warning: no pressure data. P set to 1 atm.'
self.sc.config(cnf={'from':0,'to':self.np-1})
if self.loc.get() <= 0:
self.loc.set(self.lastloc)
self.updateplot()
self.vars = w
#self.makeMenu()
self.scframe.grid(row=5,column=0,columnspan=10)
def pickSoln(self):
self.solnid.set(self.solns[self.whichsoln.get()]['id'])
self.soln = self.solns[self.whichsoln.get()]
# self.t.destroy()
self.importData()
def importData(self):
self.lastloc = self.loc.get()
if self.lastloc <= 0: self.lastloc = T_LOC
self.vars = []
self.zdata = None
self.ydata = None
if self.plt:
self.plt.destroy()
self.nsp = self.g.nSpecies()
self.label = ['-']*(self.nsp + 6)
self.y = zeros(self.nsp,'d')
gdata = self.soln.child('flowfield/grid_data')
xp = self.soln.child('flowfield').children('float')
p = 0.0
for x in xp:
if x['title'] == 'pressure':
p = float(x.value())
fa = gdata.children('floatArray')
self.np = int(fa[0]['size'])
self.data = zeros((self.nsp+6,self.np),'d')
w = []
for f in fa:
t = f['title']
try:
k = self.g.speciesIndex(t)
except:
k = -1
v = XML.getFloatArray(f)
if t == 'z' or t == 't':
self.data[0,:] = v
self.label[0] = t
elif k >= 0:
self.data[k + Y_LOC] = v
self.label[k + Y_LOC] = t
w.append((t, self.newplot, 'check', self.loc, k + Y_LOC))
elif t == 'T':
self.data[T_LOC,:] = v
self.label[T_LOC] = t
w.append((t, self.newplot, 'check', self.loc, T_LOC))
elif t == 'u':
self.data[U_LOC,:] = v
self.label[U_LOC] = t
w.append((t, self.newplot, 'check', self.loc, U_LOC))
elif t == 'V':
self.data[V_LOC,:] = v
self.label[V_LOC] = t
w.append((t, self.newplot, 'check', self.loc, V_LOC))
self.data[P_LOC,:] = ones(self.np,'d')*p
self.label[P_LOC] = 'P (Pa)'
self.sc.config(cnf={'from':0,'to':self.np-1})
if self.loc.get() <= 0:
self.loc.set(self.lastloc)
self.updateplot()
self.vars = w
self.scframe.grid(row=5,column=0,columnspan=10)
def hide(self):
#self.vis.set(0)
self.master.withdraw()
#if self.pltwhat: self.pltwhat.withdraw()
def show(self, e=None):
self.master.deiconify()
def updateState(self, e=None):
n = self.n.get()
if self.plt: self.plt.update()
for k in range(self.nsp):
self.y[k] = self.data[k+Y_LOC,n]
self.top.thermo.checkTPBoxes()
self.mix.setMass(self.y)
self.mix.set(temperature = self.data[T_LOC,n],
pressure = self.data[P_LOC,n])
self.top.update()
def newplot(self,e=0):
loc = self.loc.get()
self.zdata = self.data[0,:]
self.ydata = self.data[loc,:]
npts = len(self.zdata)
ylog = 0
if loc >= Y_LOC:
for n in range(npts):
if self.ydata[n] <= 0.0:
#print n, self.ydata[n]
self.ydata[n] = 1.0e-20
self.ydata = num.log10(self.ydata)
ylog = 1
self.gdata = []
zmin = self.zdata[0]
zmax = self.zdata[-1]
for n in range(npts):
self.gdata.append((self.zdata[n],self.ydata[n]))
ymin, ymax, dtick = plotLimits(self.ydata)
if loc > 0:
self.plt = DataGraph(self.gr,self.data, 0, loc,
title='',
label=(self.label[0],self.label[loc]),
logscale=(0,ylog),
pixelX=500,pixelY=400)
self.plt.canvas.config(bg='white')
self.plt.grid(row=1,column=0,columnspan=2,sticky=W+E)
n = self.n.get()
self.gdot = self.plt.plot(n,'red')
def updateplot(self,event=None):
if self.data == None: return
if self.zdata == None:
self.newplot()
n = self.n.get()
self.pnt = self.zdata[n], self.ydata[n]
if hasattr(self, 'gdot'):
self.plt.delete(self.gdot)
self.gdot = self.plt.plot(n,'red')
def plotLimits(self, xy):
ymax = -1.e10
ymin = 1.e10
for x, y in xy:
if y > ymax: ymax = y
if y < ymin: ymin = y
dy = abs(ymax - ymin)
if dy < 0.2*ymin:
ymin = ymin*.9
ymax = ymax*1.1
dy = abs(ymax - ymin)
else:
ymin = ymin - 0.1*dy
ymax = ymax + 0.1*dy
dy = abs(ymax - ymin)
p10 = math.floor(math.log10(0.1*dy))
fctr = math.pow(10.0, p10)
mm = [2.0, 2.5, 2.0]
i = 0
while dy/fctr > 5:
fctr = mm[i % 3]*fctr
i = i + 1
ymin = fctr*math.floor(ymin/fctr)
ymax = fctr*(math.floor(ymax/fctr + 1))
return (ymin, ymax, fctr)

View File

@@ -0,0 +1,229 @@
from Tkinter import *
import math
from Cantera.num import *
def plotLimits(ypts, f=0.0, ndiv=5, logscale=0):
"""Return plot limits that"""
if logscale:
threshold = 1.0e-19
else:
threshold = -1.0e20
ymax = -1.e20
ymin = 1.e20
for y in ypts:
if y > ymax: ymax = y
if y < ymin and y > threshold: ymin = y
dy = abs(ymax - ymin)
if logscale:
ymin = math.floor(math.log10(ymin))
ymax = math.floor(math.log10(ymax))+1
fctr = 1.0
## if dy < 0.2*ymin:
## ymin = ymin*.9
## ymax = ymax*1.1
## dy = abs(ymax - ymin)
## else:
else:
ymin = ymin - f*dy
ymax = ymax + f*dy
dy = abs(ymax - ymin)
try:
p10 = math.floor(math.log10(0.1*dy))
fctr = math.pow(10.0, p10)
except:
return (ymin -1.0, ymax + 1.0, 1.0)
mm = [2.0, 2.5, 2.0]
i = 0
while dy/fctr > ndiv:
fctr = mm[i % 3]*fctr
i = i + 1
ymin = fctr*math.floor(ymin/fctr)
ymax = fctr*(math.floor(ymax/fctr+0.999))
return (ymin, ymax, fctr)
class DataGraph(Frame):
def __init__(self,master,
data, ix=0, iy=0,
title='',
label = ('x-axis','y-axis'),
logscale = (0,0),
pixelX=500,
pixelY=500):
self.logscale = logscale
self.data = data
self.ix = ix
self.iy = iy
self.minX, self.maxX, self.dx = plotLimits(data[ix,:],
logscale=self.logscale[0])
self.minY, self.maxY, self.dy = plotLimits(data[iy,:],
logscale=self.logscale[1])
Frame.__init__(self,master, relief=RIDGE, bd=2)
self.title = Label(self,text=' ')
self.title.grid(row=0,column=1,sticky=W+E)
self.graph_w, self.graph_h = pixelX - 120, pixelY - 70
self.origin = (100, 20)
self.canvas = Canvas(self,
width=pixelX,
height=pixelY,
relief=SUNKEN,bd=1)
id = self.canvas.create_rectangle(self.origin[0],self.origin[1],
pixelX-20,pixelY-50)
self.canvas.grid(row=1,column=1,rowspan=2,sticky=N+S+E+W)
self.last_points=[]
self.ticks(self.minX, self.maxX, self.dx,
self.minY, self.maxY, self.dy, 10)
self.screendata()
self.draw()
self.canvas.create_text(self.origin[0] + self.graph_w/2,
self.origin[1] + self.graph_h + 30,
text=label[0],anchor=N)
self.canvas.create_text(self.origin[0] - 50,
self.origin[1] + self.graph_h/2,
text=label[1],anchor=E)
def writeValue(self, y):
yval = '%15.4f' % (y)
self.title.config(text = yval)
def delete(self, ids):
for id in ids:
self.canvas.delete(id)
def screendata(self):
self.xdata = array(self.data[self.ix,:])
self.ydata = array(self.data[self.iy,:])
npts = len(self.ydata)
if self.logscale[0] > 0:
self.xdata = log10(self.xdata)
if self.logscale[1] > 0:
self.ydata = log10(self.ydata)
f = float(self.graph_w)/(self.maxX-self.minX)
self.xdata = (self.xdata - self.minX)*f + self.origin[0]
f = float(self.graph_h)/(self.maxY-self.minY)
self.ydata = (self.maxY - self.ydata)*f + self.origin[1]
def toscreen(self,x,y):
if self.logscale[0] > 0:
x = log10(x)
if self.logscale[1] > 0:
y = log10(y)
f = float(self.graph_w)/(self.maxX-self.minX)
xx = (x - self.minX)*f + self.origin[0]
f = float(self.graph_h)/(self.maxY-self.minY)
yy = (self.maxY - y)*f + self.origin[1]
return (xx, yy)
def move(self, id, newpos, oldpos):
dxpt = (newpos[0] - oldpos[0])/(self.maxX-self.minX)*self.graph_w
dypt = -(newpos[1] - oldpos[1])/(self.maxY-self.minY)*self.graph_h
self.canvas.move(id, dxpt, dypt)
self.writeValue(newpos[1])
def plot(self,n,color='black'):
xpt, ypt = self.toscreen(self.data[self.ix,n],
self.data[self.iy,n])
#xpt = (x-self.minX)/(self.maxX-self.minX)*float(self.graph_w) + self.origin[0]
#ypt = (self.maxY-y)/(self.maxY-self.minY)*float(self.graph_h) + self.origin[1]
id_ycross = self.canvas.create_line(xpt,self.graph_h+self.origin[1],xpt,self.origin[1],fill = 'gray')
id_xcross = self.canvas.create_line(self.origin[0],ypt,self.graph_w+self.origin[0],ypt,fill = 'gray')
id = self.canvas.create_oval(xpt-2,ypt-2,xpt+2,ypt+2,fill=color)
#self.writeValue(y)
s = '(%g, %g)' % (self.data[self.ix,n],self.data[self.iy,n])
if n > 0 and self.data[self.iy,n] > self.data[self.iy,n-1]:
idt = self.canvas.create_text(xpt+5,ypt+5,text=s,anchor=NW)
else:
idt = self.canvas.create_text(xpt+5,ypt-5,text=s,anchor=SW)
return [id,id_xcross,id_ycross, idt]
def draw(self,color='red'):
npts = len(self.xdata)
for n in range(1,npts):
self.canvas.create_line(self.xdata[n-1],self.ydata[n-1],
self.xdata[n],self.ydata[n],fill=color)
def addLabel(self, y, orient=0):
if orient==0:
xpt, ypt = self.toscreen(y, 1.0)
ypt = self.origin[1] + self.graph_h + 5
self.canvas.create_text(xpt,ypt,text=y,anchor=N)
else:
xpt, ypt = self.toscreen(self.minX, y)
xpt = self.origin[0] - 5
self.canvas.create_text(xpt,ypt,text=y,anchor=E)
def addLegend(self,text,color=None):
m=Message(self,text=text,width=self.graph_w-10)
m.pack(side=BOTTOM)
if color:
m.config(fg=color)
def pauseWhenFinished(self):
self.wait_window()
def minorTicks(self, x0, x1, y, n, size, orient=0):
xtick = x0
dx = (x1 - x0)/float(n)
if orient == 0:
while xtick <= x1:
xx, yy = self.toscreen(xtick, y)
self.canvas.create_line(xx,yy,
xx,yy-size)
xtick += dx
else:
while xtick <= x1:
xx, yy = self.toscreen(y, xtick)
self.canvas.create_line(xx,yy,
xx+size,yy)
xtick += dx
def ticks(self, xmin, xmax, dx, ymin, ymax, dy, size):
if self.logscale[0]:
xmin = math.pow(10.0,xmin)
xmax = math.pow(10.0,xmax)
if self.logscale[1]:
ymin = math.pow(10.0,ymin)
ymax = math.pow(10.0,ymax)
n = 5
ytick = ymin
while ytick <= ymax:
xx, yy = self.toscreen(xmin, ytick)
self.canvas.create_line(xx, yy, xx + size,yy)
self.addLabel(ytick,1)
xx, yy = self.toscreen(xmax, ytick)
self.canvas.create_line(xx, yy, xx - size,yy)
ytick0 = ytick
if self.logscale[1]:
ytick *= 10.0
n = 10
else: ytick = ytick + dy
if ytick <= ymax:
self.minorTicks(ytick0, ytick, xmin, n, 5, 1)
self.minorTicks(ytick0, ytick, xmax, n, -5, 1)
n = 5
xtick = xmin
while xtick <= xmax:
xx, yy = self.toscreen(xtick, ymin)
self.canvas.create_line(xx, yy, xx, yy - size)
self.addLabel(xtick,0)
xx, yy = self.toscreen(xtick, ymax)
self.canvas.create_line(xx, yy, xx, yy + size)
if self.logscale[0]:
xtick *= 10.0
n = 10
else: xtick = xtick + dx
if xtick <= xmax:
self.minorTicks(xtick - dx, xtick, ymin, n, 5, 0)
self.minorTicks(xtick - dx, xtick, ymax, n, -5, 0)

View File

@@ -0,0 +1,193 @@
from Tkinter import *
from ElementFrame import getElements
from utilities import handleError
from Cantera import *
from config import *
from SpeciesFrame import getSpecies
def testit():
pass
class EditFrame(Frame):
def redraw(self):
try:
self.eframe.destroy()
self.sframe.destroy()
self.rframe.destroy()
except:
pass
self.addElementFrame()
self.addSpeciesFrame()
self.addReactionFrame()
def __init__(self, master, app):
Frame.__init__(self, master)
self.mix = app.mix
print self.mix, dir(self.mix)
self.app = app
self.master = master
self.master.title("Cantera Mechanism Editor")
self.redraw()
def addReactionFrame(self):
self.rframe = Frame(self)
self.rframe.config(relief=GROOVE,bd=4)
self.rframe.grid(row=2,column=0,columnspan=10,sticky=E+W)
b=Button(self.rframe,text='Reactions',command=testit)
b.grid(column=5, row=0)
def addElementFrame(self):
self.eframe = Frame(self)
self.eframe.config(relief=GROOVE,bd=4)
self.eframe.grid(row=0,column=0,columnspan=10,sticky=E+W)
self.element_labels = []
n = 0
for el in self.mix._mech.elementNames():
x = Label(self.eframe,text=el,fg='darkblue')
x.grid(column = n, row=0)
self.element_labels.append(x)
n = n + 1
b=Button(self.eframe,text='Element',command=self.chooseElements, default=ACTIVE)
b.grid(column=0, row=1, columnspan=10)
def addSpeciesFrame(self):
self.sframe = Frame(self)
self.sframe.config(relief=GROOVE,bd=4)
self.sframe.grid(row=1,column=0,columnspan=10,sticky=E+W)
r = 0
c = 0
splist = self.app.species
self.spcheck = []
self.spec = []
for i in range(self.app.mech.nSpecies()):
self.spec.append(IntVar())
self.spec[i].set(1)
self.spcheck.append( Checkbutton(self.sframe,
text=splist[i].name,
variable=self.spec[i],
onvalue = 1, offvalue = 0) )
self.spcheck[i].grid(row = r, column = c, sticky = N+W)
self.spcheck[i].bind("<Button-3>", self.editSpecies)
c = c + 1
if c > 4:
c, r = 0, r + 1
def getspecies(self):
print getSpecies(self.mix.speciesNames(),
self.mix.speciesNames())
def editSpecies(self, event=None):
e = Toplevel(event.widget.master)
w = event.widget
txt = w.cget('text')
sp = self.app.mix.species[txt]
# name, etc.
e1 = Frame(e, relief=FLAT)
self.addEntry(e1,'Name',0,0,sp.name)
self.addEntry(e1,'ID Tag',1,0,sp.id)
self.addEntry(e1,'Phase',2,0,sp.phase)
e1.grid(row=0,column=0)
# elements
elframe = Frame(e)
elframe.grid(row=1,column=0)
Label(elframe,text='Elemental Composition').grid(row=0,column=0,columnspan=2,sticky=E+W)
i = 0
for el in self.app.mech.elementNames():
self.addEntry(elframe,el,i,0,self.mech.nAtoms(sp, el))
i = i + 1
# thermo
thframe = Frame(e)
thframe.grid(row=0,rowspan=2,column=1)
thframe.config(relief=GROOVE,bd=4)
i = 0
Label(thframe,text='Thermodynamic Properties').grid(row=0,
column=0, columnspan=4, sticky=E+W)
if isinstance(sp.thermoParam(),NasaPolynomial):
Label(thframe,text='Parametrization:').grid(row=1,column=1)
self.addEntry(thframe,'',2,0,'NasaPolynomial')
Label(thframe,text='Temperatures (min, mid, max):').grid(row=3,column=1)
self.addEntry(thframe,'',4,0,`sp.minTemp`)
self.addEntry(thframe,'',5,0,`sp.midTemp`)
self.addEntry(thframe,'',6,0,`sp.maxTemp`)
low = Frame(thframe)
low.config(relief=GROOVE,bd=4)
low.grid(row=1,rowspan=6,column=3,columnspan=2)
Label(low,text='Coefficients for the Low\n Temperature Range').grid(row=0,column=0,columnspan=2,sticky=E+W)
c = sp.thermoParam().coefficients(sp.minTemp)
for j in range(7):
self.addEntry(low,'a'+`j`,j+3,0,`c[j]`)
high = Frame(thframe)
high.config(relief=GROOVE,bd=4)
high.grid(row=1,rowspan=6,column=5,columnspan=2)
Label(high,text='Coefficients for the High\n Temperature Range').grid(row=0,column=0,columnspan=2,sticky=E+W)
c = sp.thermoParam().coefficients(sp.maxTemp)
for j in range(7):
self.addEntry(high,'a'+`j`,j+3,0,`c[j]`)
com = Frame(e)
com.grid(row=10,column=0,columnspan=5)
ok = Button(com,text='OK',default=ACTIVE)
ok.grid(row=0,column=0)
ok.bind('<1>',self.modifySpecies)
Button(com,text='Cancel',command=e.destroy).grid(row=0,column=1)
self.especies = e
def modifySpecies(self,event=None):
button = event.widget
e = self.especies
for fr in e.children.values():
for item in fr.children.values():
try:
print item.cget('selection')
except:
pass
e.destroy()
def addEntry(self,master,name,row,column,text):
if name:
Label(master, text=name).grid(row=row, column=column)
nm = Entry(master)
nm.grid(row=row, column=column+1)
nm.insert(END,text)
def chooseElements(self):
oldel = self.mix.g.elementNames()
newel = getElements(self.mix.g.elementNames())
removeList = []
for el in oldel:
if not el in newel:
removeList.append(el)
#self.app.mech.removeElements(removeList)
addList = []
for el in newel:
if not el in oldel:
addList.append(el)
#self.app.mech.addElements(addList)
try:
self.redraw()
self.app.makeWindows()
except:
handleError('Edit err')
self.app.mix = IdealGasMixture(self.app.mech)
self.mix = self.app.mix
nn = self.mix.speciesList[0].name
self.mix.set(temperature = 300.0, pressure = 101325.0, moles = {nn:1.0})
for label in self.element_labels:
label.destroy()
self.element_labels = []
n = 0
for el in self.mix._mech.elementList():
x = Label(self.eframe,text=el.symbol(),fg='darkblue')
x.grid(column = n, row=0)
self.element_labels.append(x)
n = n + 1
self.app.makeWindows()

View File

@@ -0,0 +1,182 @@
#
# function getElements displays a periodic table, and returns a list of
# the selected elements
#
from Tkinter import *
from types import *
import tkMessageBox
import string
from Cantera import *
# (row,column) positions in the periodic table
_pos = {'H':(1,1), 'He':(1,18),
'Li':(2,1), 'Be':(2,2),
'B':(2,13), 'C':(2,14), 'N':(2,15), 'O':(2,16), 'F':(2,17), 'Ne':(2,18),
'Na':(3,1), 'Mg':(3,2),
'Al':(3,13), 'Si':(3,14), 'P':(3,15), 'S':(3,16), 'Cl':(3,17), 'Ar':(3,18),
'K':(4,1), 'Ca':(4,2),
'Sc':(4,3), 'Ti':(4,4), 'V':(4,5), 'Cr':(4,6), 'Mn':(4,7), 'Fe':(4,8),
'Co':(4,9), 'Ni':(4,10), 'Cu':(4,11), 'Zn':(4,12),
'Ga':(4,13), 'Ge':(4,14), 'As':(4,15), 'Se':(4,16), 'Br':(4,17), 'Kr':(4,18),
'Rb':(5,1), 'Sr':(5,2),
'Y':(5,3), 'Zr':(5,4), 'Nb':(5,5), 'Mo':(5,6), 'Tc':(5,7), 'Ru':(5,8),
'Rh':(5,9), 'Pd':(5,10), 'Ag':(5,11), 'Cd':(5,12),
'In':(5,13), 'Sn':(5,14), 'Sb':(5,15), 'Te':(5,16), 'I':(5,17), 'Xe':(5,18)
}
class PeriodicTable(Frame):
def __init__(self, master, selected=[]):
Frame.__init__(self,master)
self.master = master
self.control = Frame(self)
self.control.config(relief=GROOVE,bd=4)
Button(self.control, text = 'Display',command=self.show).pack(fill=X,pady=3, padx=10)
Button(self.control, text = 'Clear',command=self.clear).pack(fill=X,pady=3, padx=10)
Button(self.control, text = ' OK ',command=self.get).pack(side=BOTTOM,
fill=X,pady=3, padx=10)
Button(self.control, text = 'Cancel',command=self.master.quit).pack(side=BOTTOM,
fill=X,pady=3, padx=10)
self.entries = Frame(self)
self.entries.pack(side=LEFT)
self.control.pack(side=RIGHT,fill=Y)
self.c = {}
self.element = {}
self.selected = selected
n=0
ncol = 8
for el in _pos.keys():
self.element[el] = Frame(self.entries)
self.element[el].config(relief=GROOVE, bd=4, bg=self.color(el))
self.c[el] = Button(self.element[el],text=el,bg=self.color(el),width=3,relief=FLAT)
self.c[el].pack()
self.c[el].bind("<Button-1>",self.setColors)
self.element[el].grid(row=_pos[el][0]-1, column = _pos[el][1]-1,sticky=W+N+E+S)
n = n + 1
Label(self.entries,text='select the elements to be included, and then press OK.\nTo view the properties of the selected elements, press Display ').grid(row=0, column=2, columnspan=10, sticky=W)
def select(self, el):
e = string.capitalize(el)
self.c[e]['relief'] = RAISED
self.c[e]['bg'] = self.color(e, sel=1)
def deselect(self, el):
e = string.capitalize(el)
self.c[e]['relief'] = FLAT
self.c[e]['bg'] = self.color(e, sel=0)
def selectElements(self,ellist):
for el in ellist:
ename = el
self.select(ename)
def setColors(self,event):
el = event.widget['text']
if event.widget['relief'] == RAISED:
event.widget['relief'] = FLAT
back = self.color(el, sel=0)
elif event.widget['relief'] == FLAT:
event.widget['relief'] = RAISED
back = self.color(el, sel=1)
event.widget['bg'] = back
def color(self, el, sel=0):
_normal = ['#88dddd','#dddd88','#dd8888']
_selected = ['#aaffff','#ffffaa','#ffaaaa']
row, column = _pos[el]
if sel: list = _selected
else: list = _normal
if column < 3:
return list[0]
elif column > 12:
return list[1]
else:
return list[2]
def show(self):
elnames = _pos.keys()
elnames.sort()
selected = []
for el in elnames:
if self.c[el]['relief'] == RAISED:
selected.append(periodicTable[el])
showElementProperties(selected)
def get(self):
self.selected = []
names = _pos.keys()
names.sort()
for el in names:
if self.c[el]['relief'] == RAISED:
self.selected.append(periodicTable[el])
#self.master.quit()'
self.master.destroy()
def clear(self):
for el in _pos.keys():
self.c[el]['bg'] = self.color(el, sel=0)
self.c[el]['relief'] = FLAT
class ElementPropertyFrame(Frame):
def __init__(self,master,ellist):
Frame.__init__(self,master)
n = 1
ellist.sort()
Label(self,text='Name').grid(column=0,row=0,sticky=W+S,padx=10,pady=10)
Label(self,text='Atomic \nNumber').grid(column=1,row=0,sticky=W+S,padx=10,pady=10)
Label(self,
text='Atomic \nWeight').grid(column=2,
row=0,
sticky=W+S,
padx=10,
pady=10)
for el in ellist:
Label(self,
text=el.name).grid(column=0,
row=n,
sticky=W,
padx=10)
Label(self,
text=`el.atomicNumber`).grid(column=1,
row=n,
sticky=W,
padx=10)
Label(self,
text=`el.atomicWeight`).grid(column=2,
row=n,
sticky=W,
padx=10)
n = n + 1
# utility functions
def getElements(ellist=None):
master = Toplevel()
master.title('Periodic Table of the Elements')
t = PeriodicTable(master)
if ellist: t.selectElements(ellist)
t.pack()
t.focus_set()
t.grab_set()
t.wait_window()
try:
master.destroy()
except TclError:
pass
return t.selected
# display table of selected element properties in a window
def showElementProperties(ellist):
m = Tk()
m.title('Element Properties')
elem = []
ElementPropertyFrame(m, ellist).pack()
if __name__ == "__main__":
print getElements()

View File

@@ -0,0 +1,128 @@
from Tkinter import *
import math
class Graph(Frame):
def __init__(self,master,title,minX,maxX,minY,maxY,pixelX=250,pixelY=250):
Frame.__init__(self,master, relief=RIDGE, bd=2)
# self.pack()
self.title = Label(self,text=' ')
self.title.grid(row=0,column=1,sticky=W+E)
self.graph_w, self.graph_h = pixelX, pixelY
self.maxX, self.maxY = maxX, maxY #float(math.floor(maxX + 1)), \
#float(math.floor(maxY + 1))
self.minX, self.minY = minX, minY # float(math.floor(minX)), float(math.floor(minY))
self.canvas = Canvas(self,
width=self.graph_w,
height=self.graph_h,
relief=SUNKEN,bd=1)
ymintext = "%8.1f" % (self.minY)
ymaxtext = "%8.1f" % (self.maxY)
self.ml=Label(self, text=ymintext)
self.mr=Label(self, text=ymaxtext)
self.ml.grid(row=2,column=0,sticky=S+E)
self.mr.grid(row=1,column=0,sticky=N+E)
self.canvas.grid(row=1,column=1,rowspan=2,sticky=N+S+E+W)
self.last_points=[]
def writeValue(self, y):
yval = '%15.4f' % (y)
self.title.config(text = yval)
def delete(self, ids):
for id in ids:
self.canvas.delete(id)
def move(self, id, newpos, oldpos):
dxpt = (newpos[0] - oldpos[0])/(self.maxX-self.minX)*self.graph_w
dypt = -(newpos[1] - oldpos[1])/(self.maxY-self.minY)*self.graph_h
self.canvas.move(id, dxpt, dypt)
self.writeValue(newpos[1])
def plot(self,x,y,color='black'):
xpt = (x-self.minX)/(self.maxX-self.minX)*float(self.graph_w) + 1.5
ypt = (self.maxY-y)/(self.maxY-self.minY)*float(self.graph_h) - 1.5
id_ycross = self.canvas.create_line(xpt,self.graph_h,xpt,0,fill = 'gray')
id_xcross = self.canvas.create_line(0,ypt,self.graph_w,ypt,fill = 'gray')
id = self.canvas.create_oval(xpt-2,ypt-2,xpt+2,ypt+2,fill=color)
self.writeValue(y)
return [id,id_xcross,id_ycross]
def reset(self,minX,maxX,minY,maxY):
self.maxX, self.maxY = maxX, maxY
self.minX, self.minY = minX, minY
self.canvas.destroy()
self.canvas = Canvas(self,
width=self.graph_w,
height=self.graph_h,
relief=SUNKEN,bd=1)
self.canvas.create_text(4,2,text=self.maxY,anchor=NW)
self.canvas.create_text(4,self.graph_h,text=self.minY,anchor=SW)
self.ml["text"] = `minX`
self.mr["text"] = `maxX`
self.canvas.pack()
self.last_points = []
def join(self,point_list):
i = 0
for pt in point_list:
x, y, color = pt
if self.last_points == []:
last_x, last_y, last_color = pt
else:
last_x, last_y, last_color = self.last_points[i]
i = i + 1
xpt = (x - self.minX)/(float(self.maxX - self.minX)/self.graph_w) + 1.5
ypt = (self.maxY-y)/(float(self.maxY - self.minY)/self.graph_h) - 1.5
last_xpt = (last_x - self.minX)/(float(self.maxX - self.minX)/self.graph_w) + 1.5
last_ypt = (self.maxY-last_y)/(float(self.maxY - self.minY)/self.graph_h) - 1.5
self.canvas.create_line(last_xpt,last_ypt,
xpt,ypt,fill=color)
self.last_points = point_list
self.canvas.update()
return
def addLegend(self,text,color=None):
m=Message(self,text=text,width=self.graph_w-10)
m.pack(side=BOTTOM)
if color:
m.config(fg=color)
def pauseWhenFinished(self):
self.wait_window()
if __name__=='__main__':
root= Tk()
g = Graph(root,'graph1',0,10,0.01,120)
h = Graph(root,'graph2',0,15,0,20000)
g.pack(side=LEFT)
h.pack(side=RIGHT)
#root.protocol("WM_DELETE_WINDOW", root.destroy())
j = Graph(root,'Graph',0,1000,0,2000)
j.pack()
j.plot(0, 0, color='red')
j.last_points = [ (0, 0, 'red') ]
for i in range(100):
j.join( [ ( (i*10),(i*10+500), 'red' ) ] )
g.addLegend('An example of the GraphFrame')
h.addLegend('This is where the legend goes')
for i in range(100):
if root:
x,y = float(i)/10, i
g.plot(x,y,color='red')
h.plot(i,i**2)#(0,0)
#h.join([(i,i**2,'black')])
else:
break
#print("finished")
g.pauseWhenFinished()
h.pauseWhenFinished()
print g

View File

@@ -0,0 +1,123 @@
import os, math
from Tkinter import *
from Cantera import *
#from Cantera.ck2ctml import ck2ctml
from tkFileDialog import askopenfilename
class ImportFrame(Frame):
def __init__(self,top):
self.master = Toplevel()
self.master.title('Convert and Import CK File')
self.master.protocol("WM_DELETE_WINDOW",self.hide)
Frame.__init__(self,self.master)
self.config(relief=GROOVE, bd=4)
self.top = top
self.infile = StringVar()
Label(self,text="Input File").grid(row=0,column=0)
Entry(self, width=40,
textvariable=self.infile).grid(column=1,row=0)
Button(self, text='Browse',
command=self.browseForInput).grid(row=0,column=2)
self.thermo = StringVar()
Label(self,text="Thermodynamic Database").grid(row=1,column=0)
Entry(self, width=40,
textvariable=self.thermo).grid(column=1,row=1)
Button(self, text='Browse',
command=self.browseForThermo).grid(row=1,column=2)
self.transport = StringVar()
Label(self,text="Transport Database").grid(row=2,column=0)
Entry(self, width=40,
textvariable=self.transport).grid(column=1,row=2)
Button(self, text='Browse',
command=self.browseForTransport).grid(row=2,column=2)
bframe = Frame(self)
bframe.config(relief=GROOVE, bd=1)
bframe.grid(row=100,column=0)
Button(bframe, text='OK', width=8, command=self.importfile).grid(row=0,column=0)
self.grid(column=0,row=0)
Button(bframe, text='Cancel', width=8, command=self.hide).grid(row=0,column=1)
self.grid(column=0,row=0)
self.hide()
def browseForInput(self, e=None):
pathname = askopenfilename(
filetypes=[("Reaction Mechanism Files",
("*.inp","*.mech","*.ck2")),
("All Files", "*.*")])
if pathname:
self.infile.set(pathname)
self.show()
def browseForThermo(self, e=None):
pathname = askopenfilename(
filetypes=[("Thermodynamic Databases",
("*.dat","*.inp","*.therm")),
("All Files", "*.*")])
if pathname:
self.thermo.set(pathname)
self.show()
def browseForTransport(self, e=None):
pathname = askopenfilename(
filetypes=[("Transport Databases", "*.dat"),
("All Files", "*.*")])
if pathname:
self.transport.set(pathname)
self.show()
def importfile(self):
ckfile = self.infile.get()
thermdb = self.thermo.get()
trandb = self.transport.get()
p = os.path.normpath(os.path.dirname(ckfile))
fname = os.path.basename(ckfile)
ff = os.path.splitext(fname)
nm = ""
if len(ff) > 1: nm = ff[0]
else: nm = ff
outfile = p+os.sep+nm+'.xml'
try:
print 'not supported.'
#ck2ctml(infile = ckfile, thermo = thermdb,
# transport = trandb, outfile = outfile,
# id = nm)
self.hide()
return
except:
print 'Errors were encountered. See log file ck2ctml.log'
self.hide()
return
self.top.loadmech(nm,outfile,1)
self.hide()
## cmd = 'ck2ctml -i '+ckfile+' -o '+outfile
## if thermdb <> "":
## cmd += ' -t '+thermdb
## if trandb <> "":
## cmd += ' -tr '+trandb
## cmd += ' -id '+nm
## ok = os.system(cmd)
## if ok == 0:
## self.top.loadmech(nm,outfile,1)
def hide(self):
#self.vis.set(0)
self.master.withdraw()
def show(self):
#v = self.vis.get()
#if v == 0:
# self.hide()
# return
self.master.deiconify()

View File

@@ -0,0 +1,417 @@
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

View File

@@ -0,0 +1,81 @@
from Cantera import *
from Tkinter import *
from ControlPanel import ControlWindow
from ControlPanel import make_menu, menuitem_state
#from Cantera.Examples.Tk import _mechdir
import os
# automatically-loaded mechanisms
_autoload = [
(' GRI-Mech 3.0', 'gri30.cti'),
(' Air', 'air.cti'),
(' H/O/Ar', 'h2o2.cti')
]
def testit():
pass
class MechManager(Frame):
def __init__(self,master,app):
Frame.__init__(self,master)
#self.config(relief=GROOVE, bd=4)
self.app = app
self.master = master
self.mechindx = IntVar()
self.mechindx.set(1)
#m = Label(self, text = 'Loaded Mechanisms')
#m.grid(column=0,row=0)
# m.bind('<Double-1>',self.show)
# self.mechindx.set(0)
self.mechanisms = []
self.mlist = [ [] ]
i = 1
#for m in self.mechanisms:
# self.mlist.append((m[0], self.setMechanism, 'check', self.mechindx, i))
# i = i + 1
#self.mlist.append([])
self.mechmenu = make_menu('Mixtures', self, self.mlist)
self.mechmenu.grid(row=0,column=0,sticky=W)
self.mfr = None
def addMechanism(self, name, mech):
self.mechanisms.append((name, mech))
il = len(self.mechanisms)
self.mlist[-1] = (name, self.setMechanism, 'check', self.mechindx, il)
self.mlist.append([])
self.mechmenu = make_menu('Mixtures', self, self.mlist)
self.mechindx.set(il)
self.mechmenu.grid(row=0,column=0,sticky=W)
def delMechanism(self, mech):
self.mechanisms.remove(mech)
self.show()
## def show(self,event=None):
## print 'show'
## if self.mfr:
## self.mfr.destroy()
## self.mfr = Frame(self)
## self.mfr.grid(row=1,column=0)
## self.mfr.config(relief=GROOVE, bd=4)
## Label(self.mfr,text='jkl').grid(row=0,column=0)
## i = 0
## for name, mech in self.mechanisms:
## Radiobutton(self.mfr, text=name, variable=self.mechindx,
## value = i,
## command=self.setMechanism).grid(row=i,column=0)
## i = i + 1
## print 'end'
def setMechanism(self, event=None):
i = self.mechindx.get()
self.app.mech = self.mechanisms[i-1][1]
self.app.makeMix()
self.app.makeWindows()

View File

@@ -0,0 +1,138 @@
from Cantera import GasConstant, OneAtm
from Cantera.num import zeros, ones
from utilities import handleError
def spdict(phase, x):
nm = phase.speciesNames()
data = {}
for k in range(len(nm)):
data[nm[k]] = x[k]
return data
class Species:
def __init__(self,g,name):
self.g = g
t = g.temperature()
p = g.pressure()
x = g.moleFractions()
self.name = name
self.symbol = name
self.index = g.speciesIndex(name)
self.minTemp = g.minTemp(self.index)
self.maxTemp = g.maxTemp(self.index)
self.molecularWeight = g.molecularWeights()[self.index]
self.c = []
self.e = g.elementNames()
self.hf0 = self.enthalpy_RT(298.15)*GasConstant*298.15
g.setState_TPX(t,p,x)
for n in range(len(self.e)):
na = g.nAtoms(self.index, n)
if na > 0:
self.c.append((self.e[n],na))
def composition(self):
return self.c
def enthalpy_RT(self,t):
self.g.setTemperature(t)
return self.g.enthalpies_RT()[self.index]
def cp_R(self,t):
self.g.setTemperature(t)
return self.g.cp_R()[self.index]
def entropy_R(self,t):
self.g.setTemperature(t)
return self.g.entropies_R()[self.index]
class Mix:
def __init__(self,g):
self.g = g
self._mech = g
self.nsp = g.nSpecies()
self._moles = zeros(self.nsp,'d')
self.wt = g.molecularWeights()
def setMoles(self, m):
self._moles = m
self.g.setMoleFractions(self._moles)
def moles(self):
return self._moles
def totalMoles(self):
sum = 0.0
for k in range(self.nsp):
sum += self._moles[k]
return sum
def totalMass(self):
sum = 0.0
for k in range(self.nsp):
sum += self._moles[k]*self.wt[k]
return sum
def moleDict(self):
d = {}
nm = self.g.speciesNames()
for e in range(self.nsp):
d[nm[e]] = self._moles[e]
return d
def setMass(self, m):
self.setMoles( m/self.wt)
def mass(self):
return self.wt*self._moles
def speciesNames(self):
return self.g.speciesNames()
def massDict(self):
d = {}
nm = self.g.speciesNames()
for e in range(self.nsp):
d[nm[e]] = self._moles[e]*self.wt[e]
return d
def set(self, temperature = None, pressure = None,
density = None, enthalpy = None,
entropy = None, intEnergy = None, equil = 0):
total_mass = self.totalMass()
if temperature and pressure:
self.g.setState_TP(temperature, pressure)
if equil:
self.g.equilibrate('TP',solver=0)
elif temperature and density:
self.g.setState_TR(temperature, density)
if equil:
self.g.equilibrate('TV',solver=0)
elif pressure and enthalpy:
self.g.setState_HP(enthalpy, pressure)
if equil:
self.g.equilibrate('HP',solver=0)
elif pressure and entropy:
self.g.setState_SP(entropy, pressure)
if equil:
self.g.equilibrate('SP',solver=0)
elif density and entropy:
self.g.setState_SV(entropy, 1.0/density)
if equil:
self.g.equilibrate('SV',solver=0)
elif density and intEnergy:
self.g.setState_UV(intEnergy, 1.0/density)
if equil:
self.g.equilibrate('UV',solver=0)
# else:
# handleError('unsupported property pair', warning=1)
total_moles = total_mass/self.g.meanMolecularWeight()
self._moles = self.g.moleFractions()*total_moles

View File

@@ -0,0 +1,114 @@
from Tkinter import *
from Cantera import *
from SpeciesInfo import SpeciesInfo
_CUTOFF = 1.e-15
_ATOL = 1.e-15
_RTOL = 1.e-7
class NewFlowFrame(Frame):
def __init__(self,master):
Frame.__init__(self,master)
self.config(relief=GROOVE, bd=4)
self.app = self.master.app
self.controls=Frame(self)
self.hide = IntVar()
self.hide.set(0)
self.p = DoubleVar()
#self.comp.set(1.0)
self.controls.grid(column=1,row=0,sticky=W+E+N)
#self.makeControls()
mf = self.master
e1 = Entry(self)
e1.grid(column=0,row=0,sticky=E+W)
e1['textvariable'] = self.p
#e1.config(state=ENABLED)
e1.config(relief=RIDGE)
## def makeControls(self):
## Radiobutton(self.controls,text='Moles',
## variable=self.comp,value=0,command=self.show).grid(column=0,row=0,sticky=W)
## Radiobutton(self.controls,text='Mass',variable=self.comp,value=1,command=self.show).grid(column=0,row=1,sticky=W)
## Radiobutton(self.controls,text='Concentration',variable=self.comp,value=2,command=self.show).grid(column=0,row=2,sticky=W)
## Button(self.controls,text='Clear',command=self.zero).grid(column=0,row=4,sticky=W+E)
## Button(self.controls,text='Normalize',command=self.norm).grid(column=0,row=5,sticky=W+E)
## Checkbutton(self.controls,text='Hide Missing\nSpecies',
## variable=self.hide,onvalue=1,offvalue=0,command=self.master.redo).grid(column=0,row=3,sticky=W)
## def makeControls(self):
## self.c = CompFrame(self)
## self.c.grid(column=1,row=0,sticky=E+W+N+S)
## 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 makeEntries(self):
## self.entries.grid(row=0,column=0,sticky=W+N+S+E)
## self.entries.config(relief=GROOVE,bd=4)
## DATAKEYS = self.top.species
## self.variable = {}
## n=0
## ncol = 3
## col = 0
## row = 60
## presbox =
## for sp in DATAKEYS:
## s = sp # self.top.species[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
## if self.c.hide.get():
## b=Button(self.entries,height=1,command=self.maximize)
## else:
## b=Button(self.entries,command=self.minimize)
## b.grid(column=col,columnspan=2, row=row+1)

View File

@@ -0,0 +1,174 @@
#
# function getElements displays a periodic table, and returns a list of
# the selected elements
#
from Tkinter import *
from types import *
import tkMessageBox
from Cantera import *
class SpeciesFrame(Frame):
def __init__(self, master, speciesList = [], selected=[]):
Frame.__init__(self,master)
self.master = master
self.control = Frame(self)
self.species = {}
for sp in speciesList:
self.species[sp.name] = sp
self.control.config(relief=GROOVE,bd=4)
Button(self.control, text = 'Display',command=self.show).pack(fill=X,pady=3, padx=10)
Button(self.control, text = 'Clear',command=self.clear).pack(fill=X,pady=3, padx=10)
Button(self.control, text = ' OK ',command=self.get).pack(side=BOTTOM,
fill=X,pady=3, padx=10)
Button(self.control, text = 'Cancel',command=self.master.quit).pack(side=BOTTOM,
fill=X,pady=3, padx=10)
self.entries = Frame(self)
self.entries.pack(side=LEFT)
self.control.pack(side=RIGHT,fill=Y)
self.c = {}
self.selected = selected
n=0
ncol = 8
rw = 1
col = 0
list = self.species.values()
list.sort()
for sp in list:
el = sp.name
self.species[el] = Frame(self.entries)
self.species[el].config(relief=GROOVE, bd=4, bg=self.color(el))
self.c[el] = Button(self.species[el],text=el,bg=self.color(el),width=6,relief=FLAT)
self.c[el].pack()
self.c[el].bind("<Button-1>",self.setColors)
self.species[el].grid(row= rw, column = col,sticky=W+N+E+S)
col = col + 1
if col > ncol:
rw = rw + 1
col = 0
Label(self.entries,text='select the species to be included, and then press OK.\nTo view the properties of the selected species, press Display ').grid(row=0, column=2, columnspan=10, sticky=W)
def select(self, el):
self.c[el]['relief'] = RAISED
self.c[el]['bg'] = self.color(el, sel=1)
def deselect(self, el):
self.c[el]['relief'] = FLAT
self.c[el]['bg'] = self.color(el, sel=0)
def selectSpecies(self,splist):
for sp in splist:
spname = sp.name
self.select(spname)
def setColors(self,event):
el = event.widget['text']
if event.widget['relief'] == RAISED:
event.widget['relief'] = FLAT
back = self.color(el, sel=0)
fore = '#ffffff'
elif event.widget['relief'] == FLAT:
event.widget['relief'] = RAISED
fore = '#000000'
back = self.color(el, sel=1)
event.widget['bg'] = back
event.widget['fg'] = fore
def color(self, el, sel=0):
_normal = ['#88dddd','#005500','#dd8888']
_selected = ['#aaffff','#88dd88','#ffaaaa']
#row, column = _pos[el]
if sel: list = _selected
else: list = _normal
return list[1]
#if column < 3:
# return list[0]
#elif column > 12:
# return list[1]
#else:
# return list[2]
def show(self):
selected = []
for sp in self.species.values():
if self.c[sp.name]['relief'] == RAISED:
selected.append(sp)
#showElementProperties(selected)
def get(self):
self.selected = []
for sp in self.species.values():
if self.c[sp.name]['relief'] == RAISED:
self.selected.append(sp)
#self.master.quit()'
self.master.destroy()
def clear(self):
for sp in self.species.values():
self.c[sp]['bg'] = self.color(sp, sel=0)
self.c[sp]['relief'] = FLAT
## class ElementPropertyFrame(Frame):
## def __init__(self,master,ellist):
## Frame.__init__(self,master)
## n = 1
## ellist.sort()
## Label(self,text='Name').grid(column=0,row=0,sticky=W+S,padx=10,pady=10)
## Label(self,text='Atomic \nNumber').grid(column=1,row=0,sticky=W+S,padx=10,pady=10)
## Label(self,
## text='Atomic \nWeight').grid(column=2,
## row=0,
## sticky=W+S,
## padx=10,
## pady=10)
## for el in ellist:
## Label(self,
## text=el.name).grid(column=0,
## row=n,
## sticky=W,
## padx=10)
## Label(self,
## text=`el.atomicNumber`).grid(column=1,
## row=n,
## sticky=W,
## padx=10)
## Label(self,
## text=`el.atomicWeight`).grid(column=2,
## row=n,
## sticky=W,
## padx=10)
## n = n + 1
# utility functions
def getSpecies(splist=[],selected=[]):
master = Toplevel()
master.title('Species')
t = SpeciesFrame(master,splist,selected)
if splist: t.selectSpecies(splist)
t.pack()
t.focus_set()
t.grab_set()
t.wait_window()
try:
master.destroy()
except TclError:
pass
return t.selected
# display table of selected element properties in a window
def showElementProperties(ellist):
m = Tk()
m.title('Element Properties')
elem = []
ElementPropertyFrame(m, ellist).pack()
if __name__ == "__main__":
print getSpecies()

View File

@@ -0,0 +1,242 @@
from Tkinter import *
import re, math
from Cantera import *
from Units import temperature, specificEnergy, specificEntropy
from UnitChooser import UnitVar
from GraphFrame import Graph
def testit():
pass
class SpeciesInfo(Label):
def __init__(self,master,phase=None,species=None,**opt):
Label.__init__(self,master,opt)
self.sp = species
self.phase = phase
self.bind('<Double-1>', self.show)
self.bind('<Button-3>', self.show)
self.bind('<Any-Enter>', self.highlight)
self.bind('<Any-Leave>', self.nohighlight)
def highlight(self, event=None):
self.config(fg='yellow')
def nohighlight(self, event=None):
self.config(fg='darkblue')
def show(self, event):
self.new=Toplevel()
self.new.title(self.sp.symbol)
#self.new.transient(self.master)
self.new.bind("<Return>", self.update,"+")
self.cpr = 0.0
self.t = 0.0
self.cpl = 0.0
self.tl = 0.0
self.cpp = [[(0.0, 0.0, 'red')]]
# elemental composition
self.eframe = Frame(self.new)
self.eframe.config(relief=GROOVE,bd=4)
self.eframe.grid(row=0,column=0,columnspan=10,sticky=E+W)
r = 1
Label(self.eframe,text='Atoms:')\
.grid(row=0,column=0,sticky=N+W)
for el, c in self.sp.composition():
Label(self.eframe,text=`int(c)`+' '+el).grid(row=0,column=r)
r = r + 1
# thermodynamic properties
self.thermo = Frame(self.new)
self.thermo.config(relief=GROOVE,bd=4)
self.thermo.grid(row=1,column=0,columnspan=10,sticky=N+E+W)
Label(self.thermo,text = 'Standard Heat of Formation at 298 K: ').grid(row=0, column=0, sticky=W)
Label(self.thermo,text = '%8.2f kJ/mol' % (self.sp.hf0*1.0e-6)).grid(row=0, column=1, sticky=W)
Label(self.thermo,text = 'Molar Mass: ').grid(row=1, column=0, sticky=W)
Label(self.thermo,text = self.sp.molecularWeight).grid(row=1, column=1, sticky=W)
labels = ['Temperature', 'c_p', 'Enthalpy', 'Entropy']
units = [temperature, specificEntropy, specificEnergy, specificEntropy]
whichone = [0, 1, 1, 1]
r = 2
self.prop = []
for prop in labels:
Label(self.thermo,text=prop).grid(row=r,column=0,sticky=W)
p = UnitVar(self.thermo,units[r-2],whichone[r-2])
p.grid(row=r,column=1,sticky=W)
p.v.config(state=DISABLED,bg='lightgray')
self.prop.append(p)
r = r + 1
tmin = self.sp.minTemp
tmax = self.sp.maxTemp
cp = self.sp.cp_R(tmin)
hh = self.sp.enthalpy_RT(tmin)
ss = self.sp.entropy_R(tmin)
self.prop[0].bind("<Any-Enter>", self.decouple)
self.prop[0].bind("<Any-Leave>", self.update)
self.prop[0].bind("<Key>", self.update)
self.prop[0].v.config(state=NORMAL,bg='white')
self.prop[0].set(300.0)
self.graphs = Frame(self.new)
self.graphs.config(relief=GROOVE,bd=4)
self.graphs.grid(row=2,column=0,columnspan=10,sticky=E+W)
self.cpdata = []
self.hdata = []
self.sdata = []
t = tmin
n = int((tmax - tmin)/100.0)
while t <= tmax:
self.cpdata.append((t,self.sp.cp_R(t)))
self.hdata.append((t,self.sp.enthalpy_RT(t)))
self.sdata.append((t,self.sp.entropy_R(t)))
t = t + n
# specific heat
Label(self.graphs,text='c_p/R').grid(row=0,column=0,sticky=W+E)
ymin, ymax, dtick = self.plotLimits(self.cpdata)
self.cpg = Graph(self.graphs,'',tmin,tmax,ymin,ymax,
pixelX=150,pixelY=150)
self.cpg.canvas.config(bg='white')
self.cpg.grid(row=1,column=0,columnspan=2,sticky=W+E)
self.ticks(ymin, ymax, dtick, tmin, tmax, self.cpg)
# enthalpy
Label(self.graphs,text='enthalpy/RT').grid(row=0,column=3,sticky=W+E)
ymin, ymax, dtick = self.plotLimits(self.hdata)
self.hg = Graph(self.graphs,'',tmin,tmax,ymin,ymax,
pixelX=150,pixelY=150)
self.hg.canvas.config(bg='white')
self.hg.grid(row=1,column=3,columnspan=2,sticky=W+E)
self.ticks(ymin, ymax, dtick, tmin, tmax, self.hg)
# entropy
Label(self.graphs,text='entropy/R').grid(row=0,column=5,sticky=W+E)
ymin, ymax, dtick = self.plotLimits(self.sdata)
self.sg = Graph(self.graphs,'',tmin,tmax,ymin,ymax,
pixelX=150,pixelY=150)
self.sg.canvas.config(bg='white')
self.sg.grid(row=1,column=5,columnspan=2,sticky=W+E)
self.ticks(ymin, ymax, dtick, tmin, tmax, self.sg)
n = int((tmax - tmin)/100.0)
t = tmin
self.cpp = []
for t, cp in self.cpdata:
self.cpg.join([(t,cp,'red')])
for t, h in self.hdata:
self.hg.join([(t,h,'green')])
for t, s in self.sdata:
self.sg.join([(t,s,'blue')])
self.cpdot = self.cpg.plot(tmin,cp,'red')
self.hdot = self.hg.plot(tmin,hh,'green')
self.sdot = self.sg.plot(tmin,ss,'blue')
b=Button(self.new,text=' OK ',command=self.finished, default=ACTIVE)
#ed=Button(self.new,text='Edit',command=testit)
b.grid(column=0, row=4,sticky=W)
#ed.grid(column=1,row=4,sticky=W)
self.scfr = Frame(self.new)
self.scfr.config(relief=GROOVE,bd=4)
self.scfr.grid(row=3,column=0,columnspan=10,sticky=N+E+W)
self.sc = Scale(self.scfr,command=self.update,variable = self.prop[0].x,
orient='horizontal',digits=7,length=400)
self.sc.config(cnf={'from':tmin,'to':tmax})
self.sc.bind('<Any-Enter>',self.couple)
self.scfr.bind('<Any-Leave>',self.decouple)
self.sc.grid(row=0,column=0,columnspan=10)
def decouple(self,event=None):
d = DoubleVar()
xx = self.prop[0].get()
d.set(xx)
self.sc.config(variable = d)
def couple(self,event=None):
self.sc.config(variable = self.prop[0].x)
#self.update()
def update(self,event=None):
try:
tmp = self.prop[0].get()
cnd = self.sp.cp_R(tmp)
cc = cnd*GasConstant
self.prop[1].set(cc)
hnd = self.sp.enthalpy_RT(tmp)
hh = hnd*tmp*GasConstant
self.prop[2].set(hh)
snd = self.sp.entropy_R(tmp)
ss = snd*tmp*GasConstant
self.prop[3].set(ss)
self.cppoint = tmp, cnd
self.hpoint = tmp, hnd
self.spoint = tmp, snd
if hasattr(self, 'cpdot'):
self.cpg.delete(self.cpdot)
self.cpdot = self.cpg.plot(self.cppoint[0], self.cppoint[1],'red')
self.hg.delete(self.hdot)
self.hdot = self.hg.plot(self.hpoint[0], self.hpoint[1],'green')
self.sg.delete(self.sdot)
self.sdot = self.sg.plot(self.spoint[0], self.spoint[1],'blue')
except:
pass
def plotLimits(self, xy):
ymax = -1.e10
ymin = 1.e10
for x, y in xy:
if y > ymax: ymax = y
if y < ymin: ymin = y
dy = abs(ymax - ymin)
if dy < 0.2*ymin:
ymin = ymin*.9
ymax = ymax*1.1
dy = abs(ymax - ymin)
else:
ymin = ymin - 0.1*dy
ymax = ymax + 0.1*dy
dy = abs(ymax - ymin)
p10 = math.floor(math.log10(0.1*dy))
fctr = math.pow(10.0, p10)
mm = [2.0, 2.5, 2.0]
i = 0
while dy/fctr > 5:
fctr = mm[i % 3]*fctr
i = i + 1
ymin = fctr*math.floor(ymin/fctr)
ymax = fctr*(math.floor(ymax/fctr + 1))
return (ymin, ymax, fctr)
def ticks(self, ymin, ymax, dtick, tmin, tmax, plot):
ytick = ymin
eps = 1.e-3
while ytick <= ymax:
if abs(ytick) < eps:
plot.join([(tmin, ytick, 'gray')])
plot.join([(tmax, ytick, 'gray')])
plot.last_points = []
else:
plot.join([(tmin, ytick, 'gray')])
plot.join([(tmin + 0.05*(tmax - tmin), ytick, 'gray')])
plot.last_points = []
plot.join([(2.0*tmax, ytick, 'gray')])
plot.join([(tmax - 0.05*(tmax - tmin), ytick, 'gray')])
plot.last_points = []
ytick = ytick + dtick
def finished(self,event=None):
self.new.destroy()

View File

@@ -0,0 +1,143 @@
from Cantera import *
from Tkinter import *
from Units import temperature, pressure, density, specificEnergy, specificEntropy
from UnitChooser import UnitVar
from ThermoProp import ThermoProp
from utilities import handleError
_PRESSURE = 1
_TEMPERATURE = 0
_DENSITY = 2
_INTENERGY = 3
_ENTHALPY = 4
_ENTROPY = 5
class ThermoFrame(Frame):
def __init__(self,master,top):
Frame.__init__(self,master)
self.config(relief=GROOVE, bd=4)
self.top = top
self.mix = self.top.mix
self.warn = 0
self.internal = Frame(self)
self.internal.pack(side=LEFT,anchor=N+W,padx=2,pady=2)
self.controls=Frame(self.internal)
self.controls.pack(side=LEFT,anchor=N+W,padx=4,pady=5)
self.entries=Frame(self.internal)
self.entries.pack(side=LEFT,anchor=N,padx=4,pady=2)
self.makeEntries()
self.makeControls()
self.showState()
def makeControls(self):
Button(self.controls,text='Set State', width=15,
command=self.setState).grid(column=0,row=0)
self.equil = IntVar()
self.equil.set(0)
Button(self.controls,text='Equilibrate', width=15,
command=self.eqset).grid(column=0,row=1)
## Radiobutton(self.controls,text='Frozen',variable = self.equil,
## command=self.freeze,value=0).grid(column=0,row=2,sticky='W')
## Radiobutton(self.controls,text='Equilibrium',
## variable=self.equil,
## command=self.eqset,value=1).grid(column=0,row=3,sticky='W')
def eqset(self):
self.equil.set(1)
self.setState()
self.equil.set(0)
#if self.top.mixframe:
# self.top.mixframe.redo()
def freeze(self):
self.equil.set(0)
if self.top.mixframe:
self.top.mixframe.redo()
def makeEntries(self):
self.entries.pack()
self.variable = {}
self.prop = []
props = ['Temperature', 'Pressure', 'Density',
'Internal Energy', 'Enthalpy', 'Entropy']
units = [temperature, pressure, density, specificEnergy,
specificEnergy, specificEntropy]
defaultunit = [0, 2, 0, 1, 1, 1]
for i in range(len(props)):
self.prop.append(ThermoProp(self.entries, self, i, props[i],
0.0, units[i], defaultunit[i]))
#self.prop[-1].entry.bind("<Any-Leave>",self.setState)
self.last2 = self.prop[3]
self.last1 = self.prop[2]
self.prop[0].checked.set(1)
self.prop[0].check()
self.prop[1].checked.set(1)
self.prop[1].check()
self.showState()
def checkTPBoxes(self):
if not self.prop[0].isChecked():
self.prop[0].checked.set(1)
self.prop[0].check()
if not self.prop[1].isChecked():
self.prop[1].checked.set(1)
self.prop[1].check()
def showState(self):
self.prop[_TEMPERATURE].set(self.mix.g.temperature())
self.prop[_PRESSURE].set(self.mix.g.pressure())
self.prop[_DENSITY].set(self.mix.g.density())
self.prop[_INTENERGY].set(self.mix.g.intEnergy_mass())
self.prop[_ENTHALPY].set(self.mix.g.enthalpy_mass())
self.prop[_ENTROPY].set(self.mix.g.entropy_mass())
def setState(self,event=None):
if event:
self.warn = 0
else:
self.warn = 1
self.top.mixfr.update()
i = self.equil.get()
optlist = ['frozen','equilibrium']
opt = [optlist[i]]
if self.prop[_PRESSURE].isChecked() \
and self.prop[_TEMPERATURE].isChecked():
self.mix.set(
temperature = self.prop[_TEMPERATURE].get(),
pressure = self.prop[_PRESSURE].get(),
equil=i)
elif self.prop[_DENSITY].isChecked() \
and self.prop[_TEMPERATURE].isChecked():
self.mix.set(
temperature = self.prop[_TEMPERATURE].get(),
density = self.prop[_DENSITY].get(),
equil=i)
elif self.prop[_ENTROPY].isChecked() \
and self.prop[_PRESSURE].isChecked():
self.mix.set(pressure = self.prop[_PRESSURE].get(),
entropy = self.prop[_ENTROPY].get(),
equil=i)
elif self.prop[_ENTHALPY].isChecked() \
and self.prop[_PRESSURE].isChecked():
self.mix.set(pressure = self.prop[_PRESSURE].get(),
enthalpy = self.prop[_ENTHALPY].get(),
equil=i)
elif self.prop[_INTENERGY].isChecked() \
and self.prop[_DENSITY].isChecked():
self.mix.set(density = self.prop[_DENSITY].get(),
intEnergy = self.prop[_INTENERGY].get(),
equil=i)
else:
if self.warn > 0:
handleError("unsupported property pair")
self.top.update()

View File

@@ -0,0 +1,66 @@
from Tkinter import *
from UnitChooser import UnitVar
_tv = ['Temperature','Internal Energy','Enthalpy']
_pv = ['Pressure', 'Density']
def badpair(a,b):
if a.name in _tv:
if not b.name in _pv:
return 1
else:
if not b.name in _tv:
return 1
class ThermoProp:
def __init__(self, master, thermoframe, row, name, value, units, defaultunit=0):
self.value = DoubleVar()
self.thermoframe = thermoframe
self.entry = UnitVar(master,units,defaultunit)
self.entry.grid(column=1,row=row,sticky=W)
self.entry.v.config(state=DISABLED,bg='lightgray')
self.checked=IntVar()
self.checked.set(0)
self.name = name
self.c=Checkbutton(master,
text=name,
variable=self.checked,
onvalue=1,
offvalue=0,
command=self.check
)
self.c.grid(column=0,row=row, sticky=W+N)
def check(self):
if self == self.thermoframe.last1:
self.checked.set(1)
return
elif self == self.thermoframe.last2:
self.checked.set(1)
self.thermoframe.last2 = self.thermoframe.last1
self.thermoframe.last1 = self
return
# elif badpair(self, self.thermoframe.last1):
# self.checked.set(0)
# return
self._check()
self.thermoframe.last2.checked.set(0)
self.thermoframe.last2._check()
self.thermoframe.last2 = self.thermoframe.last1
self.thermoframe.last1 = self
def _check(self):
if self.isChecked():
self.entry.v.config(state=NORMAL,bg='white')
else:
self.entry.v.config(state=DISABLED,bg='lightgray')
def isChecked(self):
return self.checked.get()
def set(self, value):
self.entry.set(value)
def get(self):
return self.entry.get()

View File

@@ -0,0 +1,34 @@
from Tkinter import *
class TransportFrame(Frame):
def show(self, i, frame, row, col):
if self.checked[i].get():
frame.grid(row=row,column=col,sticky=N+E+S+W)
else:
frame.grid_forget()
def showcomp(self):
self.show(0, self.top.mixfr, 8, 0)
def showthermo(self):
self.show(1, self.top.thermo, 7, 0)
def __init__(self,master,top):
self.top = top
self.c = []
self.checked = []
Frame.__init__(self,master)
self.config(relief=GROOVE, bd=4)
lbl = ['multicomponent', 'mixture-averaged']
cmds = [self.showcomp, self.showthermo]
for i in range(2):
self.checked.append(IntVar())
self.checked[i].set(0)
self.c.append(Checkbutton(self,
text=lbl[i],
variable=self.checked[i],
onvalue=1,
offvalue=0,
command=cmds[i]
))
self.c[i].grid(column=i,row=0, sticky=W+N)

View File

@@ -0,0 +1,82 @@
from Tkinter import *
import re
class UnitVar(Frame):
def __init__(self,master,unitmod,defaultunit=0):
Frame.__init__(self,master)
self.x = DoubleVar()
self.xsi = 0.0
self.x.set(0.0)
self.unitmod = unitmod
try:
self.unitlist = self.unitmod.units
except:
self.unitlist = []
unitlist=dir(self.unitmod)
for it in unitlist:
if it[0] != '_':
self.unitlist.append(it)
self.v = Entry(self,textvariable=self.x)
self.s = StringVar()
tmp = re.sub('__',' / ',self.unitlist[defaultunit])
self.s.set(tmp)
self.conv = eval('self.unitmod.'+re.sub(' / ','__',self.s.get())).value
self.u = Label(self)
self.u.config(textvariable=self.s,fg='darkblue')
self.u.bind('<Double-1>', self.select)
self.u.bind('<Any-Enter>',self.highlight)
self.u.bind('<Any-Leave>',self.nohighlight)
self.v.grid(row=0,column=0)
self.u.grid(row=0,column=1)
def highlight(self, event=None):
self.u.config(fg='yellow')
def nohighlight(self, event=None):
self.u.config(fg='darkblue')
def select(self, event):
self.new=Toplevel()
self.new.title("Units")
self.new.transient(self.master)
self.new.bind("<Return>", self.finished,"+")
r=0
c=0
for each in self.unitlist:
if each[0] != '_' and each[:1] != '__' and each != 'SI':
each = re.sub('__',' / ',each)
Radiobutton(self.new,
text=each,
variable=self.u['textvariable'],
value=each,
command=self.update,
).grid(column=c, row=r, sticky=W)
r=r+1
if (r>10):
r=0
c=c+1
r=r+1
b=Button(self.new,text='OK',command=self.finished, default=ACTIVE)
b.grid(column=c, row=r)
self.new.grab_set()
self.new.focus_set()
self.new.wait_window()
def finished(self,event=None):
self.new.destroy()
def update(self):
self.xsi = self.x.get() * self.conv
self.conv = eval('self.unitmod.'+re.sub(' / ','__',self.s.get())).value
self.x.set(self.xsi/self.conv)
def get(self):
self.xsi = self.x.get() * self.conv
return self.xsi
def set(self,value):
self.xsi = value
self.x.set(value/self.conv)

View File

@@ -0,0 +1,113 @@
#!/usr/bin/env python
from unit import unit, dimensionless
#
# The basic SI units
#
meter = unit(1.0, (1, 0, 0, 0, 0, 0, 0))
kilogram = unit(1.0, (0, 1, 0, 0, 0, 0, 0))
second = unit(1.0, (0, 0, 1, 0, 0, 0, 0))
ampere = unit(1.0, (0, 0, 0, 1, 0, 0, 0))
kelvin = unit(1.0, (0, 0, 0, 0, 1, 0, 0))
mole = unit(1.0, (0, 0, 0, 0, 0, 1, 0))
candela = unit(1.0, (0, 0, 0, 0, 0, 0, 1))
#
# The 21 derived SI units with special names
#
radian = dimensionless # plane angle
steradian = dimensionless # solid angle
hertz = 1/second # frequency
newton = meter*kilogram/second**2 # force
pascal = newton/meter**2 # pressure
joule = newton*meter # work, heat
watt = joule/second # power, radiant flux
coulomb = ampere*second # electric charge
volt = watt/ampere # electric potential difference
farad = coulomb/volt # capacitance
ohm = volt/ampere # electric resistance
siemens = ampere/volt # electric conductance
weber = volt*second # magnetic flux
tesla = weber/meter**2 # magnetic flux density
henry = weber/ampere # inductance
celsius = kelvin # Celsius temperature
lumen = candela*steradian # luminous flux
lux = lumen/meter**2 # illuminance
becquerel = 1/second # radioactivity
gray = joule/kilogram # absorbed dose
sievert = joule/kilogram # dose equivalent
#
# The prefixes
#
yotta = 1e24
zetta = 1e21
exa = 1e18
peta = 1e15
tera = 1e12
giga = 1e9
mega = 1e6
kilo = 1000
hecto = 100
deka = 10
deci = .1
centi = .01
milli = .001
micro = 1e-6
nano = 1e-9
pico = 1e-12
femto = 1e-15
atto = 1e-18
zepto = 1e-21
yocto = 1e-24
#
# Test
#
if __name__ == "__main__":
print "The 7 base SI units:"
print " meter: %s" % meter
print " kilogram: %s" % kilogram
print " second: %s" % second
print " ampere: %s" % ampere
print " kelvin: %s" % kelvin
print " mole: %s" % mole
print " candela: %s" % candela
print
print "The 21 SI derived units with special names:"
print " radian: %s" % radian
print " steradian: %s" % steradian
print " hertz: %s" % hertz
print " newton: %s" % newton
print " pascal: %s" % pascal
print " joule: %s" % joule
print " watt: %s" % watt
print " coulomb: %s" % coulomb
print " volt: %s" % volt
print " farad: %s" % farad
print " ohm: %s" % ohm
print " siemens: %s" % siemens
print " weber: %s" % weber
print " tesla: %s" % tesla
print " henry: %s" % henry
print " degree Celsius: %s" % celsius
print " lumen: %s" % lumen
print " lux: %s" % lux
print " becquerel: %s" % becquerel
print " gray: %s" % gray
print " sievert: %s" % sievert

View File

@@ -0,0 +1,18 @@
from length import meter, centimeter, inch, foot, mile
#
# Definitions of common area units
# Data taken from Appendix F of Halliday, Resnick, Walker, "Fundamentals of Physics",
# fourth edition, John Willey and Sons, 1993
square_meter = meter**2
square_centimeter = centimeter**2
square_foot = foot**2
square_inch = inch**2
square_mile = mile**2
acre = 43560 * square_foot
hectare = 1000 * square_meter
barn = 1e-28 * square_meter

View File

@@ -0,0 +1,11 @@
import SI, math
#
# Definitions of common density units
# Data taken from Appendix F of Halliday, Resnick, Walker, "Fundamentals of Physics",
# fourth edition, John Willey and Sons, 1993
units = ['kg__m3', 'g__m3', 'g__cm3']
kg__m3 = SI.kilogram/(SI.meter * SI.meter * SI.meter)
g__m3 = 1.e-3*kg__m3
g__cm3 = 1.e3*kg__m3

View File

@@ -0,0 +1,18 @@
from SI import joule
#
# Definitions of common energy units
# Data taken from Appendix F of Halliday, Resnick, Walker, "Fundamentals of Physics",
# fourth edition, John Willey and Sons, 1993
Btu = 1055 * joule
erg = 1e-7 * joule
foot_pound = 1.356 * joule
horse_power_hour = 2.685e6 * joule
calorie = 4.186 * joule
Calorie = 1000 * calorie
kilowatt_hour = 3.6e6 * joule
electron_volt = 1.602e-19 * joule

View File

@@ -0,0 +1,6 @@
from SI import meter
#
# Definitions of common force units
# Data taken from Appendix F of Halliday, Resnick, Walker, "Fundamentals of Physics",
# fourth edition, John Willey and Sons, 1993

View File

@@ -0,0 +1,26 @@
from SI import meter
from SI import nano, milli, centi, kilo
#
# Definitions of common length units
# Data taken from Appendix F of Halliday, Resnick, Walker, "Fundamentals of Physics",
# fourth edition, John Willey and Sons, 1993
nanometer = nano * meter
millimeter = milli * meter
centimeter = centi * meter
kilometer = kilo * meter
inch = 2.540 * centimeter
foot = 12 * inch
yard = 3 * foot
mile = 5280 * foot
fathom = 6 * foot
nautical_mile = 6076 * foot
angstrom = 1e-10 * meter
fermi = 1e-15 * meter
light_year = 9.460e12 * kilometer
parsec = 3.084e13 * kilometer

View File

@@ -0,0 +1,14 @@
from SI import kilogram
#
# Definitions of common mass units
# Data taken from Appendix F of Halliday, Resnick, Walker, "Fundamentals of Physics",
# fourth edition, John Willey and Sons, 1993
gram = 1e-3 * kilogram
metric_ton = 1000 * kilogram
ounce = 28.35 * gram
pound = 16 * ounce
ton = 2000 * pound

View File

@@ -0,0 +1,9 @@
from SI import watt, kilo
#
# Definitions of common power units
# Data taken from Appendix F of Halliday, Resnick, Walker, "Fundamentals of Physics",
# fourth edition, John Willey and Sons, 1993
kilowatt = kilo * watt
horsepower = 745.7 * watt

View File

@@ -0,0 +1,13 @@
import SI
#
# Definitions of common pressure units
# Data taken from Appendix F of Halliday, Resnick, Walker, "Fundamentals of Physics",
# fourth edition, John Willey and Sons, 1993
bar = 1e5 * SI.pascal
mbar = 100 * SI.pascal
Pa = SI.pascal
torr = 133.3 * SI.pascal
atm = 1.01325e5 * SI.pascal

View File

@@ -0,0 +1,14 @@
import SI, energy, mass
#
# Definitions of common energy units
# Data taken from Appendix F of Halliday, Resnick, Walker, "Fundamentals of Physics",
# fourth edition, John Willey and Sons, 1993
units = ['J__kg', 'kJ__kg', 'Btu__lbm', 'cal__g', 'kcal__g', 'kcal__kg']
J__kg = SI.joule/SI.kilogram
kJ__kg = 1000.0*J__kg
Btu__lbm = energy.Btu/mass.pound
cal__g = energy.calorie/mass.gram
kcal__g = 1000.0*cal__g
kcal__kg = cal__g

View File

@@ -0,0 +1,7 @@
import SI, energy, mass
units = ['J__kg_K', 'kJ__kg_K', 'cal__g_K']
J__kg_K = SI.joule/(SI.kilogram * SI.kelvin)
kJ__kg_K = 1000.0*J__kg_K
cal__g_K = energy.calorie/(mass.gram * SI.kelvin)

View File

@@ -0,0 +1,10 @@
from time import hour
from length import nautical_mile
#
# Definitions of common speed units
# Data taken from Appendix F of Halliday, Resnick, Walker, "Fundamentals of Physics",
# fourth edition, John Willey and Sons, 1993
knot = nautical_mile/hour

View File

@@ -0,0 +1,4 @@
import SI
K = SI.kelvin
R = (9.0/5.0)*K

View File

@@ -0,0 +1,11 @@
from SI import second
#
# Definitions of common time units
# Data taken from Appendix F of Halliday, Resnick, Walker, "Fundamentals of Physics",
# fourth edition, John Willey and Sons, 1993
minute = 60 * second
hour = 60 * minute
day = 24 * hour
year = 365.25 * day

View File

@@ -0,0 +1,107 @@
import operator
class unit:
_zero = (0,) * 7
_negativeOne = (-1, ) * 7
_labels = ('m', 'kg', 's', 'A', 'K', 'mol', 'cd')
def __init__(self, value, derivation):
self.value = value
self.derivation = derivation
return
def __add__(self, other):
if not self.derivation == other.derivation:
raise ImcompatibleUnits(self, other)
return unit(self.value + other.value, self.derivation)
def __sub__(self, other):
if not self.derivation == other.derivation:
raise ImcompatibleUnits(self, other)
return unit(self.value - other.value, self.derivation)
def __mul__(self, other):
if type(other) == type(0) or type(other) == type(0.0):
return unit(other*self.value, self.derivation)
value = self.value * other.value
derivation = tuple(map(operator.add, self.derivation, other.derivation))
return unit(value, derivation)
def __div__(self, other):
if type(other) == type(0) or type(other) == type(0.0):
return unit(self.value/other, self.derivation)
value = self.value / other.value
derivation = tuple(map(operator.sub, self.derivation, other.derivation))
return unit(value, derivation)
def __pow__(self, other):
if type(other) != type(0) and type(other) != type(0.0):
raise BadOperation
value = self.value ** other
derivation = tuple(map(operator.mul, [other]*7, self.derivation))
return unit(value, derivation)
def __pos__(self): return self
def __neg__(self): return unit(-self.value, self.derivation)
def __abs__(self): return unit(abs(self.value), self.derivation)
def __invert__(self):
value = 1./self.value
derivation = tuple(map(operator.mul, self._negativeOne, self.derivation))
return unit(value, derivation)
def __rmul__(self, other):
return unit.__mul__(self, other)
def __rdiv__(self, other):
if type(other) != type(0) and type(other) != type(0.0):
raise BadOperation(self, other)
value = other/self.value
derivation = tuple(map(operator.mul, self._negativeOne, self.derivation))
return unit(value, derivation)
def __float__(self):
return self.value
#if self.derivation == self._zero: return self.value
#raise BadConversion(self)
def __str__(self):
str = "%g" % self.value
for i in range(0, 7):
exponent = self.derivation[i]
if exponent == 0: continue
if exponent == 1:
str = str + " %s" % (self._labels[i])
else:
str = str + " %s^%d" % (self._labels[i], exponent)
return str
dimensionless = unit(1, unit._zero)

View File

@@ -0,0 +1,18 @@
from length import meter, centimeter, foot, inch
#
# Definitions of common volume units
# Data taken from Appendix F of Halliday, Resnick, Walker, "Fundamentals of Physics",
# fourth edition, John Willey and Sons, 1993
cubic_meter = meter**3
cubic_centimeter = centimeter**3
cubic_foot = foot**3
cubic_inch = inch**3
liter = 1000 * cubic_centimeter
us_fluid_ounce = 231./128 * cubic_inch
us_pint = 16 * us_fluid_ounce
us_fluid_quart = 2 * us_pint
us_fluid_gallon = 4 * us_fluid_quart

View File

@@ -0,0 +1,4 @@
# from Cantera import *
from main import MixMaster

View File

@@ -0,0 +1,5 @@
from Cantera import *
# thermo parametrizations
#from Cantera.Species.Thermo.NasaPolynomial import NasaPolynomial

View File

@@ -0,0 +1,55 @@
# functionality imports
from Tkinter import *
from Cantera.gui import menu, newflow
class App:
def __init__(self, master):
try:
self.root = master.root
except:
self.root = master
self.frame = Frame(master)
self.frame.grid(row = 0, column = 0)
self.makemenu(self.frame)
self.quitbutton = Button(self.frame, text = "Quit",
command = self.frame.quit)
self.quitbutton.grid(row = 1, column = 0)
self.newbutton = Button(self.frame, text = "New...",
command = self.notyet)
self.newbutton.grid(row = 1, column = 1)
def notyet(self):
print 'not yet!'
def newflow(self):
n = newflow.NewFlowDialog(self.root)
def makemenu(self,frame):
self.menubar = Frame(frame, relief=FLAT, bd=0)
self.menubar.grid(row = 0, column = 0)
self.filemenu = menu.make_menu('File', self.menubar,
[('New...', self.newflow),
('Open...', self.notyet),
('Save As...', self.notyet),
'separator',
('Exit', frame.quit),
[]
])
root = Tk()
app = App(root)
root.mainloop()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,325 @@
#############################################################################
#
# MixMaster
#
#############################################################################
# options
_app_title = 'MixMaster'
_app_version = '1.0'
# functionality imports
from Tkinter import *
import tkMessageBox
import sys, os, string
# Cantera imports
from Cantera import *
from Cantera.num import zeros
import utilities
from Cantera.gases import IdealGasMix
# local imports
from TransportFrame import TransportFrame
from CompositionFrame import MixtureFrame
from ThermoFrame import ThermoFrame
from ImportFrame import ImportFrame
from DataFrame import DataFrame
from KineticsFrame import SpeciesKineticsFrame, ReactionKineticsFrame, ReactionPathFrame
#from Edit import EditFrame
from MechManager import MechManager, _autoload
from UnitChooser import UnitVar
from ControlPanel import ControlWindow
from ControlPanel import make_menu, menuitem_state
from Mix import Mix, Species
def testit():
return
class MixMaster:
def stop(self):
sys.exit(0)
def openmech(self):
from tkFileDialog import askopenfilename
pathname = askopenfilename(filetypes=[("Cantera Input Files", "*.cti"),
("XML Files", "*.xml *.ctml"),
("All Files", "*.*")])
if pathname:
self.loadmech('', pathname)
def loadmech(self, mechname, pathname, mw=1):
p = os.path.normpath(os.path.dirname(pathname))
self.fname = os.path.basename(pathname)
ff = os.path.splitext(self.fname)
try:
self.mech = IdealGasMix(pathname)
self.mechname = ff[0]
except:
utilities.handleError('could not create gas mixture object: '
+ff[0]+'\n')
self.mechname = 'Error'
return
self.makeMix()
if not mechname:
mechname = self.mechname
self.mechframe.addMechanism(mechname, self.mech)
if mw==1:
self.makeWindows()
def addWindow(self, name, w):
"""Add a new window, or replace an existing one."""
wstate = ''
if self._windows.has_key(name):
try:
wstate = self._windows[name].master.state()
self._windows[name].master.destroy()
except:
pass
else:
wstate = 'withdrawn'
self._windows[name] = w
self._vis[name] = IntVar()
if wstate == 'withdrawn':
self._windows[name].master.withdraw()
else:
self._windows[name].show()
def update(self):
"""Update all windows to reflect the current mixture state."""
for w in self._windows.keys():
try:
m = self._windows[w].master
if m.state() != 'withdrawn':
self._windows[w].show()
except:
pass
self.thermo.showState()
self.mixfr.show()
def makeMix(self):
self.mix = Mix(self.mech)
nsp = self.mech.nSpecies()
self.species = []
nm = self.mech.speciesNames()
for k in range(nsp):
self.species.append(Species(self.mech, nm[k]))
x = self.mech.moleFractions()
self.mix.setMoles(x)
self.mix.set(temperature = self.mech.temperature(),
pressure = self.mech.pressure())
def __init__(self, master=None):
"""
Create a new Application instance.
Usually this is only called once.
"""
if master:
self.master = master
else:
t = Tk()
self.master = t
self._windows = {}
self._vis = {}
self.windows = []
self.cwin = ControlWindow(_app_title,self.master)
self.cwin.master.resizable(FALSE,FALSE)
self.menubar = Frame(self.cwin, relief=GROOVE,bd=2)
self.menubar.grid(row=0,column=0,sticky=N+W+E)
self.mixfr = None
self.thermo = None
self.transport = None
self.kinetics = None
self.rxndata = None
self.rxnpaths = None
self.edit = None
self.fname = None
self.mechframe = MechManager(self.cwin, self)
self.mechframe.grid(row=1,column=0,sticky=N+W)
fileitems = [('Load Mixture...', self.openmech),
('Import Mechanism File...',self.importfile),
'separator',
('Load Data File...',self.showdata),
'separator',
('Exit', self.stop),
[]
]
self.filemenu = make_menu('File', self.menubar, fileitems)
self.vtherm = IntVar()
self.vcomp = IntVar()
self.vtran = IntVar()
self.vkin = IntVar()
self.vrxn = IntVar()
self.vrxn.set(0)
self.vtherm.set(1)
self.vedit = IntVar()
dataitems = [(' Import Flame Data', testit),
(' Import CSV Data', testit),
[]]
#self.datamenu = make_menu('Data', self.menubar, dataitems)
#toolitems = [(' Convert...', self.importfile),
# []]
#self.toolmenu = make_menu('Tools', self.menubar, toolitems)
w = [(' Thermodynamic State', self.showthermo, 'check', self.vtherm),
(' Composition', self.showcomp, 'check', self.vcomp),
'separator',
(' Kinetics', self.showkinetics, 'check', self.vkin),
(' Reactions...', self.showrxns),
(' Reaction Paths...', self.showrpaths),
[]]
self.viewmenu = make_menu('Windows', self.menubar, w)
self.helpmenu = make_menu('Help', self.menubar,
[('About '+_app_title+'...', self.aboutmix),
('About Cantera...', testit),
[]
])
# load the preloaded mechanisms
for m in _autoload:
self.loadmech(m[0],m[1],0)
self.makeWindows()
self.addWindow('import',ImportFrame(self))
self.vtherm.set(1)
self.showthermo()
## self.vcomp.set(1)
## self.showcomp()
self.master.iconify()
self.master.update()
self.master.deiconify()
self.cwin.mainloop()
def importfile(self):
#self.vimport.set(1)
w = self._windows['import']
w.show()
def makeWindows(self):
# if self.mixfr:
for w in self.windows:
try:
w.destroy()
except:
pass
fr = [MixtureFrame, ThermoFrame, TransportFrame]
self.mixfr = MixtureFrame(self.cwin, self)
self.thermo = ThermoFrame(self.cwin, self)
# self.transport = TransportFrame(self.cwin, self)
self.kinetics = SpeciesKineticsFrame(self.cwin, self)
self.addWindow('rxndata',ReactionKineticsFrame(self.vrxn, self))
self.addWindow('rxnpaths',ReactionPathFrame(self))
self.addWindow('dataset',DataFrame(None, self))
#self.edit = EditFrame(t, self)
self.windows = [self.mixfr,
self.thermo, self.transport,
self.kinetics]
self.showthermo()
self.showcomp()
#self.showtransport()
self.showkinetics()
#self.showrxns()
#self.showrpaths()
#self.showdata()
if self.mech:
self.mechframe.grid(row=1,column=0)
else:
self.mechframe.grid_forget()
#self.showedit()
def show(self, frame, vis, row, col):
if vis:
frame.grid(row=row,column=col,sticky=N+E+S+W)
else:
frame.grid_forget()
def showthermo(self):
if self.thermo:
self.show(self.thermo, self.vtherm.get(), 7, 0)
def showcomp(self):
if self.mixfr:
self.show(self.mixfr, self.vcomp.get(), 8, 0)
def showkinetics(self):
if self.kinetics:
self.show(self.kinetics, self.vkin.get(), 10, 0)
def showrxns(self):
self._windows['rxndata'].show()
def showrpaths(self):
self._windows['rxnpaths'].show()
def showdata(self):
self._windows['dataset'].browseForDatafile()
def aboutmix(self):
m = tkMessageBox.showinfo(title = 'About MixMaster',
message = """
MixMaster
version """+_app_version+"""
written by:
Prof. David G. Goodwin
California Institute of Technology
copyright 2003
California Institute of Technology
""")
if __name__ == "__main__":
MixMaster()

View File

@@ -0,0 +1,31 @@
from Tkinter import *
def make_menu(name, menubar, list):
from types import *
button=Menubutton(menubar, text=name, padx=3,pady=1)
button.pack(side=LEFT, anchor=W)
menu = Menu(button,tearoff=FALSE)
for entry in list:
if entry == 'separator':
menu.add_separator({})
elif type(entry)==ListType:
for num in entry:
menu.entryconfig(num,state=DISABLED)
elif type(entry[1]) != ListType:
if len(entry) == 2 or entry[2] == 'command':
menu.add_command(label=entry[0],
command=entry[1])
elif entry[2] == 'check':
entry[3].set(0)
if len(entry) >= 5: val = entry[4]
else: val = 1
menu.add_checkbutton(label=entry[0],
command=entry[1], variable = entry[3],
onvalue=val)
else:
submenu=make_menu(entry[0],menu, entry[1])
menu.add_cascade(label=entry[0],
menu=submenu)
button['menu']=menu
return button

View File

@@ -0,0 +1,130 @@
from Tkinter import *
from tkFileDialog import askopenfilename
import tkMessageBox
from Cantera.gases import IdealGasMix
from Cantera import *
class NewFlowDialog:
def __init__(self, parent):
top = self.top = Toplevel(parent)
pl = Label(top, text='Pressure')
pl.grid(row = 0, column = 0)
geom = Frame(top, bd=2, relief=GROOVE)
geom.grid(row = 1, column = 0)
lb = Listbox(geom)
for item in ["One-Dimensional", "Stagnation"]:
lb.insert(END, item)
lb.grid(row = 0, column = 0)
glb = Listbox(geom)
for item in ["Axisymmetric","2D"]:
glb.insert(END, item)
glb.grid(row = 1, column = 0)
# ------------- pressure input ----------------
self.p = DoubleVar()
self.pbox = Entry(top, textvariable = self.p)
self.pbox.grid(row = 0, column = 1)
# ------------- gas file name input -----------
gasf = Frame(top, bd=2, relief=GROOVE)
gasf.grid(row = 4, column = 0, columnspan=2)
gl = Label(gasf, text='Gas Mixture Specification')
gl.grid(row = 0, column = 0)
self.infile = StringVar()
Label(gasf, text='Mixture Input File').grid(row = 1, column = 0)
Entry(gasf, textvariable = self.infile).grid(row = 1, column = 1)
Button(gasf, text='Browse..', command=self.getinfile).grid(row = 1,
column = 2)
self.spfile = StringVar()
Label(gasf, text='Species Database').grid(row = 2, column = 0)
Entry(gasf, textvariable = self.spfile).grid(row = 2, column = 1)
Button(gasf, text='Browse..', command=self.getspfile).grid(row = 2,
column = 2)
self.trfile = StringVar()
Label(gasf, text='Transport Database').grid(row = 3, column = 0)
Entry(gasf, textvariable = self.trfile).grid(row = 3, column = 1)
Button(gasf, text='Browse..', command=self.gettrfile).grid(row = 3,
column = 2)
# ------------- grid -------------------------
gf = Frame(top, bd=2, relief=GROOVE)
gf.grid(row = 5, column = 0, columnspan=2)
gr = Label(gf, text='Initial Grid')
gr.grid(row = 0, column = 0)
self.zleft = DoubleVar()
self.zright = DoubleVar()
ll = Label(gf, text='Left boundary at ')
rl = Label(gf, text='Right boundary at ')
lbb = Entry(gf, textvariable = self.zleft)
rbb = Entry(gf, textvariable = self.zright)
ll.grid(row = 1, column = 0)
rl.grid(row = 2, column = 0)
lbb.grid(row = 1, column = 1)
rbb.grid(row = 2, column = 1)
ok = Button(top, text = 'OK', command=self.ok)
ok.grid(row = 20, column = 20)
def ok(self):
p = self.p.get()
try:
infile = self.infile.get()
spfile = self.spfile.get()
trfile = self.trfile.get()
if spfile and trfile:
self.gas = IdealGasMix(import_file = infile,
thermo_db = spfile,
transport_db = trfile)
elif spfile:
self.gas = IdealGasMix(import_file = infile,
thermo_db = spfile)
else:
self.gas = IdealGasMix(import_file = infile)
except:
tkMessageBox.showerror('Create Gas',
'Error reading file %s. See log file for more information.' % infile)
#self.flow = Flow1D(flow_type = ftype, flow_geom = fgeom,
# pressure = p, grid = gr, gas = g)
self.top.destroy()
def getinfile(self):
pathname = askopenfilename(filetypes=[
("Input Files", "*.xml *.inp"),
("All Files", "*.*")])
self.infile.set(pathname)
def getspfile(self):
pathname = askopenfilename(filetypes=[
("Species Data Files", "*.xml *.dat"),
("All Files", "*.*")])
self.spfile.set(pathname)
def gettrfile(self):
pathname = askopenfilename(filetypes=[
("Transport Data Files", "*.xml *.dat"),
("All Files", "*.*")])
self.trfile.set(pathname)

View File

@@ -0,0 +1,39 @@
import string
import os, sys
import types, traceback
try:
from Tkinter import Tk
import tkMessageBox
_hasTk = 1
except:
_hasTk = 0
def write_CSV(f,x):
"""write list x to file f in comma-separated-value format."""
for e in x:
f.write( `e`+',')
f.write('\n')
def _print_value(name, value, unitstr):
print string.rjust(name, 15)+ \
string.rjust('%10.5e' %value, 15) + ' ' + \
string.ljust(unitstr,5),
def hasTk():
try:
import tkMessageBox
return 1
except:
return 0
def handleError(message = '<error>', window = None,
fatal = 0, warning = 0, options = None):
if warning:
tkMessageBox.showwarning(title = 'Warning', message = message,
parent = window)
else:
m = tkMessageBox.showerror(title = 'Error', message = message,
parent = window)

View File

@@ -22,6 +22,8 @@ setup(name="Cantera",
'cantera.data',
'cantera.test',
'cantera.test.data',
'cantera.mixmaster',
'cantera.mixmaster.Units',
'cantera.examples'],
scripts=[@py_ctml_writer@,
@py_ck2cti@],