Skip to content

Instantly share code, notes, and snippets.

@muspellsson
Last active December 22, 2015 00:08
Show Gist options
  • Save muspellsson/6386777 to your computer and use it in GitHub Desktop.
Save muspellsson/6386777 to your computer and use it in GitHub Desktop.
# We need it for serious work
package require Tk 8.6
# We need it for fun
package require snack
package require snackogg
# Gas constant
set R 8.3144621
###########################################################################
###########################################################################
# We don't want any fun by default
set fun 0
# Check if someone wants his fun
foreach arg $::argv {
set wantFun [regexp -nocase fun $arg]
if $wantFun {set fun 1}
}
# So, you want your fun...
if $fun {
# Animation interval
set interval 30
# "Sun" x and y coordinates
set sx 0
set sy 10
# Sun's horizontal and vertical velocities
set dx 1
set dy 1
# Number of clouds
set numclouds 5
# We need some canvas to draw our sun on
canvas .c -height 80 -background #6495ed
# Open image for sun
image create photo imSun -format png \
-file [file join [file dirname [info script]] sun.png]
# Open image for clouds
image create photo imCloud -format png \
-file [file join [file dirname [info script]] cloud.png]
# Dimensions of canvas
set cwidth [expr [.c cget -width]]
set cheight [expr [.c cget -height]]
# Generate coordinates and horizontal velocities for each cloud
for {set i 0} {$i < $numclouds} {incr i} {
# Coordinates
set clx$i [expr int(rand()*$cwidth)]
set cly$i [expr int(rand()*($cheight))]
# Horizontal velocities
set cldx$i [expr 1+rand()*2]
}
# Command for drawing the sun
proc sun {x y} {
# For now our sun is simply the image
.c create image $x $y -image imSun
}
# Do the hard work of animation
proc animate {} {
# Animation interval
global interval
# Sun coordinates
global sx sy
# Sun velocities
global dx dy
# Canvas dimensions
global cwidth cheight
# Number of clouds
global numclouds
# Generate bindings for cloud coords and velocities
for {set i 0} {$i < 5} {incr i} {
global clx$i cly$i
global cldx$i
}
# Clear canvas before each frame
.c delete all
# Redraw clouds
for {set i 0} {$i < $numclouds} {incr i} {
# Pass cloud coordinates...
upvar clx$i clx
upvar cly$i cly
# ...and velocity
upvar cldx$i cldx
# Draw cloud
.c create image $clx $cly -image imCloud
# Check if we're out of canvas
if {$clx > $cwidth + 64} {
#Oh, God, we are!
# Put the cloud at the beginning...
set clx -64
# ...with random y coordinate...
set cly [expr int(rand()*($cheight))]
# ...and random velocity
set cldx [expr 1+rand()*2]
}
# Move the cloud forward
incr clx [expr int($cldx)]
}
# We're done with clouds, draw the sun
sun $sx $sy
# Sun reflection
if {$sy + 30 > $cheight} {set dy -1}
if {$sy < 30} {set dy 1}
if {$sx + 30 > $cwidth} {set dx -1}
if {$sx < 30} {set dx 1}
# Advance sun coordinates
incr sx $dx
incr sy $dy
# Draw next frame
after $interval animate
}
# Bind animation proc
bind .c <Map> animate
# Pack canvas
pack .c
# Oh, you want a sound!
# Let's create some snack object
snack::sound music
# Open our sound file
music configure -file [file join [file dirname [info script]] music.ogg]
# Looping sound procedure
proc play-sound {} {music play -command play-sound}
# Start extra-fun!
play-sound
}
###########################################################################
###########################################################################
# Indices of concentrations
set xs [list F D B]
# Feed concentration
set xF 0.4
# Concentration in reflux drum
set xD 0.95
# Concentration in reboiler
set xB 0.05
# Check if values got are proper doubles >= 0 and < 1
proc check-x {x i} {
# We need to know if we've got a number
set isDouble [string is double -strict $x]
# Ok, looks great, check boundaries
if $isDouble {
return [expr ($x >= 0.0) && ($x < 1.0)]
} else {
# So terrible :(
return 0
}
}
# Recalculate if changed
foreach idx $xs {
proc update-$idx args {recalc}
# Bind traces
trace variable x$idx w update-$idx
}
# Frame for concentrations input
frame .x
# Cool info label
label .x.label -text "Concentrations"
pack .x.label
# Generate concentration entries
foreach idx $xs {
# Frame
frame .x.x$idx
# Cool label
label .x.x$idx.label -text x$idx
pack .x.x$idx.label
# Extra-cool entry with validation
entry .x.x$idx.entry -textvar x$idx \
-validate key -vcmd {check-x %P $idx}
pack .x.x$idx.entry
# Pack everything
pack .x.x$idx -side left
}
pack .x
###########################################################################
# Misc variable indices
set vars [list Rphi alpha r]
# Reflux ratio
set Rphi 1.5
# Relative volatility ratio
set alpha 1.5
# Molar boiling heat
set r 10000
# Check if reflux ratio is a positive number
proc check-Rphi {val} {
# Is it a number at all?
set isDouble [string is double -strict $val]
# Thanks God, it's a number
if $isDouble {return [expr $val > 0.0]} else {return 0}
}
# Check if volatility is above 1
proc check-alpha {val} {
# Again?!
set isDouble [string is double -strict $val]
# Good, let's check it
if $isDouble {return [expr $val > 1.0]} else {return 0}
}
# The same as for reflux ratio
proc check-r {val} {
# More and more...
set isDouble [string is double -strict $val]
# ...and more
if $isDouble {return [expr $val > 0.0]} else {return 0}
}
# Recalculate mass-transfer coefficient if something changes
foreach var $vars {
proc update-$var args {recalc}
# Bind, bind, bind
trace variable $var w update-$var
}
# Frame for variables input
frame .vars
# Not 'so' cool label
label .vars.label -text "Various parameters"
pack .vars.label
# Generate entries
foreach var $vars {
# A frame
frame .vars.v$var
# This label is pretty cool...
label .vars.v$var.label -text $var
pack .vars.v$var.label
# ...but no as much as this entry
entry .vars.v$var.entry -textvar $var \
-validate key -vcmd {check-$var %P}
pack .vars.v$var.entry
# Let's pack it all!
pack .vars.v$var -side left
}
pack .vars
###########################################################################
# Feed flow is very important
set gF 10
# Good 'ol checking
proc check-gF {val} {
# Still the same
set isDouble [string is double -strict $val]
# I like to see ya, guys
if $isDouble {return [expr $val >= 0.0]} else {return 0}
}
# The same recalulating
proc update-gF args {recalc}
# Another little bind
trace variable gF w update-gF
# Frame for feed flow
frame .g
# Cool but lonely label
label .g.label -text "Flow"
pack .g.label
# Inner frame
frame .g.g
# This label is even more lonely
label .g.g.label -text "gF"
pack .g.g.label
# Just like this entry
entry .g.g.entry -textvar gF -width 61 \
-validate key -vcmd {check-gF %P}
pack .g.g.entry
# Pack it and do the work
pack .g.g
pack .g
###########################################################################
# Mass-transfer coefficient is what we need
set k 0
# I've got a frame for you...
frame .k
# ...and a label...
label .k.label -text "Mass-transfer coefficient"
pack .k.label
# ...and another frame...
frame .k.k
# ...and another label...
label .k.k.label -text "k"
pack .k.k.label
# ...and our best entry-friend...
entry .k.k.entry -textvar k -state readonly -width 61
pack .k.k.entry
# ...holding together
pack .k.k
pack .k
###########################################################################
# The main math
# 'Dirty' procedure
proc recalc-k {} {
# All variables and constants we need
global R xF xD xB Rphi alpha r gF k
# Vapour flow
set V [expr $gF * ($Rphi + 1)]
# Selection share
set eps [expr ($xF - $xB) / ($xD - $xB)]
# Flow in reflux drum
set gD [expr $gF * $eps]
# Flow in reboiler
set gB [expr $gF * (1 - $eps)]
# Auxaux values
set I11 [expr $xD * log($alpha * $xD / (1 + ($alpha - 1) * $xD))]
set I12 [expr $xB * log($alpha * $xB / (1 + ($alpha - 1) * $xB))]
set I13 [expr log((1 + ($alpha - 1) * $xD) / (1 + ($alpha - 1) * $xB))]
# Integral number 1
set I1 [expr $I11 - $I12 - $I13]
# Another auxaux values
set I21 [expr $xB * (1 - log($xB))]
set I22 [expr $gB * ($xF - $xB) / $V + $xF]
set I23 [expr 1 - log($I22)]
set I24 [expr $gB / $V + 1]
# Integral number 2
set I2 [expr ($I21 - $I22 * $I23) / $I24]
# Even more auxaux values
set I31 [expr $xD * (1 - log($xD))]
set I32 [expr $gD * ($xD - $xF) / $V + $xF]
set I33 [expr 1 - log($I32)]
set I34 [expr $gD / $V - 1]
# Integral number 3
set I3 [expr ($I31 - $I32 * $I33) / $I34]
# Mass-transfer coefficient
set k [expr ($V * ($xD - $xB)) / ($R * ($I1 - $I2 - $I3))]
}
# Clear procedure
proc recalc {} {
# Recalc and check if something was going wrong
if {[catch recalc-k]} {
# All is bad, paint it red
.k.k.entry configure -readonlybackground #cd5c5c
} else {
# Never clean, paint it green
.k.k.entry configure -readonlybackground #5ccd5c
}
}
# The first calculation EVER
recalc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment