Last active
December 22, 2015 00:08
-
-
Save muspellsson/6386777 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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