#!/usr/local/tcl/bin/wish -f
#
# This script uses tcl/tk to provide an x-windows interface for setting up
# parameters
wm title . "Solver Setup"

frame .menu -relief raised -borderwidth 1

pack append . .menu { top fill }

#
# default values
set itm "gmres"
set svm "ilu"

set itoptnames {}
set itoptvalues {}
set itoptvars  {}
set maxit 101
set tol   1.0e-5
set gmresrestart 20

set svoptnames  {}
set svoptvalues {}
set svoptvars   {}
set nd    "4"
set fill  "0"
set rfill "0"
set omega "1.0"
set order "nd"
set use2d "No"
set svinner "ilu"
set itinner "preonly"

set resmethod ""

set probsize 3

proc runexample {} {
    global svm itm maxit nd tol svinner itinner order fill resmethod probsize \
	   use2d
    if {[string compare $svm "lu" ] == 0} {
	msgtty .output [ exec example3 -n $probsize -svmethod $svm -ordering $order ]
	} else {
    # this could be smarter about not issuing ignored values
    set specialargs {}
    if {[string compare $svm "osm" ] == 0 || \
	[string compare $svm "bdd" ] == 0} {
	set specialargs "-svinner $svinner -itinner $itinner -nd $nd"
	if {[string compare $use2d "Yes"] == 0} { 
	    set specialargs "$specialargs -2d"
	    }
	}
    msgtty .output [ exec example3 -n $probsize -sv $svm -itmethod $itm -maxit $maxit -tol $tol $specialargs -ilufill $fill $resmethod ]
    }
}

proc setsv s { 
    global svm svoptnames svoptvalues svoptvars
    set svm $s
    set svoptnames {}
    set svoptvalues {}
    set svoptvars {}
    # Set solver specific options
    if {[ string compare $svm "osm" ] == 0 || \
        [ string compare $svm "bdd" ] == 0} {
        set svoptnames {{Number of Domains:} {Use 2d?} {InnerSolver:} {InnerIt:}}
	set svoptvalues {"4" "No" "ilu" "preonly"}
	set svoptvars   {nd use2d svinner itinner}
        }
    if {[string compare $svm "ilu" ] == 0} {
	# valid values are nonnegative
	set svoptnames { {Level of Fill:} }
	set svoptvalues {0}
	set svoptvars   {fill}
        }
    if {[string compare $svm "ssor" ] == 0} {
	# valid values are 0-2"
	set svoptnames {Omega:}
	set svoptvalues {1.0}
	set svoptvars   {omega}
        }
    if {[string compare $svm "lu" ] == 0} {
	# valid values are "nd rcm qmd 1wd"
	set svoptnames  {Ordering:}
	set svoptvalues {nd}
	set svoptvars   {order}
	}
}

proc setit s {
    global itm itoptnames itoptvalues itoptvars
    set itm $s  
    set itoptnames {}
    set itoptvalues {}
    set itoptvars  {}
    # set iterative method specific options
    if {[ string compare $itm "gmres" ] == 0} {
	set itoptnames {Restart:}
	set itoptvalues {20}
	set itoptvars  {gmresrestart}
	}
}

#
# Put up a message for a window (w is name of the window to be created)
proc msgtext {w text} {
    catch {destroy $w}
    toplevel $w
#    wm geometry $w +0+0
    wm title $w "Message"
    wm iconname $w "Message"

    frame $w.frame1 -relief raised -bd 2
    button $w.ok -text "OK" -command "destroy $w"
    pack append $w $w.frame1 {top fill} \
	    $w.ok {bottom pady 10 frame center fillx}
    message $w.frame1.m -font *-Times-Medium-R-Normal-*-180-* -aspect 500 \
	    -text "$text"
    pack append $w.frame1 $w.frame1.m {frame center}
    }

#
# Put up a message for a window (w is name of the window to be created)
proc msgtty {w text} {
    catch {destroy $w}
    toplevel $w
#    wm geometry $w +0+0
    wm title $w "Message"
    wm iconname $w "Message"

    frame $w.frame1 -relief raised -bd 2
    button $w.ok -text "OK" -command "destroy $w"
    pack append $w $w.frame1 {top fill} \
	    $w.ok {bottom pady 10 frame center fillx}
    message $w.frame1.m -font *-fixed-Medium-R-Normal-*-120-* -aspect 900 \
	    -text "$text"
    pack append $w.frame1 $w.frame1.m {frame center}
    }

proc dialogset {w names} {
set cnt 0
foreach i $names {
    global $i
    set $i [$w.$cnt.entry get]
    set cnt [ expr $cnt+1 ]
    }
destroy   $w
}

# Given a window name w, and variabls names, values, and actual var names,
# get the new values from the user.
# The PROBLEM with this is that it uses the DEFAULT values (in values)
# rather than the CURRENT values (in vars)
proc dialog { w names values vars } {
    global $vars
    toplevel $w
    bind $w <Return> "dialogset $w {$vars}"
    wm title $w "Iterative Options"
    set cnt 0
    foreach name $vars {
	frame $w.$cnt
	pack append $w $w.$cnt { top pady 4 frame e }
	label $w.$cnt.label -text [lindex $names $cnt] -anchor e
	entry $w.$cnt.entry -width 30 -relief sunken
	$w.$cnt.entry insert end [lindex $values $cnt]
#	$w.$cnt.entry insert end [lindex $vars $cnt]
	bind $w.$cnt.entry <Return> "dialogset $w {$vars}"
	bind $w.$cnt.label <Return> "dialogset $w {$vars}"
	pack append $w.$cnt $w.$cnt.entry right $w.$cnt.label right
	set cnt [ expr $cnt+1 ]
	}
    button $w.ok -text OK -command "dialogset $w {$vars}"
    button $w.cancel -text Cancel -command "destroy $w"
    pack append $w $w.ok { bottom left fillx expand } \
	           $w.cancel { bottom right fillx expand }
}

#Iterative options menu
proc itopts2 {} {
    global svm itoptnames itoptvalues itoptvars tol maxit
    if {[ string compare $svm "lu" ] == 0} {
	msgtext .menu.itoptions.message \
	        "No iterative options for LU factorization"
        } \
    else {
	set names "Tolerance: {Max Iterations:} $itoptnames"
	set values "{$tol} {$maxit} $itoptvalues"
	set vars   "tol maxit $itoptvars" 
	dialog .itoptions $names $values $vars
	}
}

proc svopts2 {} {
    global svm svoptnames svoptvalues svoptvars
    set names "$svoptnames"
    set values "$svoptvalues"
    set vars   "$svoptvars" 
    dialog .itoptions $names $values $vars
}

proc setsize {} {
     global probsize
     dialog .szoptions {Mesh size:} $probsize probsize
     }

menubutton .menu.solvers -text "Solver Method" -menu .menu.solvers.m
menu .menu.solvers.m
.menu.solvers.m add radio -label "LU" -command "setsv lu" \
	-variable svsv -value lu
.menu.solvers.m add radio -label "ILU" -command "setsv ilu" \
	-variable svsv -value ilu
.menu.solvers.m add radio -label "OSM" -command "setsv osm" \
	-variable svsv -value osm
.menu.solvers.m add radio -label "BDD" -command "setsv bdd" \
	-variable svsv -value bdd
.menu.solvers.m add radio -label "SSOR" -command "setsv ssor" \
	-variable svsv -value ssor
.menu.solvers.m add radio -label "ICC" -command "setsv icc" \
	-variable svsv -value icc
.menu.solvers.m add radio -label "ICCJP" -command "setsv iccjp" \
	-variable svsv -value iccjp
.menu.solvers.m add radio -label "NoPre" -command "setsv nopre" \
	-variable svsv -value nopre
.menu.solvers.m add radio -label "Jacobi"  -command "setsv jacobi" \
	-variable svsv -value jacobi
.menu.solvers.m invoke 1
# ilu

menubutton .menu.itmethod -text "Iterative Method" -menu .menu.itmethod.m
menu .menu.itmethod.m
.menu.itmethod.m add radio -label "GMRES" -command "setit gmres" \
	-variable itit -value gmres
.menu.itmethod.m add radio -label "CG"    -command "setit cg" \
	-variable itit -value cg
.menu.itmethod.m add radio -label "BCGS"  -command "setit bcgs" \
	-variable itit -value bcgs
.menu.itmethod.m add radio -label "TFQMR"  -command "setit tfqmr" \
	-variable itit -value tfqmr
.menu.itmethod.m add radio -label "TCQMR"  -command "setit tcqmr" \
	-variable itit -value tcqmr
.menu.itmethod.m add radio -label "Richardson"  -command "setit richardson" \
	-variable itit -value richardson
.menu.itmethod.m add radio -label "Chebychev"  -command "setit chebychev" \
	-variable itit -value chebychev
.menu.itmethod.m add radio -label "CGS"  -command "setit cgs" \
	-variable itit -value cgs
.menu.itmethod.m invoke 0
# gmres

button .menu.itoptions -relief flat -text "Iterative options" -command itopts2
button .menu.svoptions -relief flat -text "Solver options" -command svopts2

menubutton .menu.residual -text "Residual Display" -menu .menu.residual.m
menu .menu.residual.m
.menu.residual.m add radio -label "None"        -command {set resmethod ""} \
	-variable rmeth -value none
.menu.residual.m add radio -label "Print Norm"  \
	-command "set resmethod -dpres" -variable rmeth -value prnt
.menu.residual.m add radio -label "Graph Norm" -command "set resmethod -dres" \
	-variable rmeth -value grph
.menu.residual.m add radio -label "Graph Residual" \
	-command "set resmethod -dresv" -variable rmeth -value gres
.menu.residual.m invoke 0
# gmres

button .menu.size -relief flat -text "Problem Size" -command setsize

button .menu.quit -relief flat -text "Quit" -command "destroy ."
button .menu.apply -relief flat -text "Apply" -command "runexample"

pack append .menu .menu.solvers {top fillx} .menu.svoptions {top fillx} \
	.menu.itmethod {top fillx} .menu.itoptions {top fillx} \
    .menu.residual {top fillx} .menu.size {top fillx} \
    .menu.quit {top fillx} .menu.apply {top fillx}

#
# Eventually, we'll add the creation of a window for the residual graph
# display, and then pass the window id to the application (we'll need
# to add a routine to xtools/quick/qxbase to set the window from a
# given window id, using XBQuickWindowFromWindow (in xtools/init.c).
# This should probably be a XBArgInit( &argc, argv ) call, with arg
# -winid nnnn
# Then when the graphics display options are selected, the frame can be
# repacked to contain the message display window and the graphics output.
