
# This code creates the user interface for the mesh editor.
#
# Copyright (c) 1997 Pacific Marketing and Consulting, Inc,
#       and ICEM Systems, GmbH.  All rights reserved.
# Author:  Wayne A. Christopher, wayne@icemcfd.com

# In case some of the solver interfaces use these variables

# get_solver_info was moved to guibase/family_boco.tclj
proc get_mesh_dir { } {
        global file_name
        return $file_name(mesh_dir)
}

set icem_fluent 0
set icem_powermesh 0

proc solution_select {} {
    global solution solver_info env options

    if {[info exists options(default_solver)] && ($options(default_solver) != "") && ($solution(solver) == "")} {
       set solution(solver) $options(default_solver)    
    }
    
    # If we have a family boco window up just make this button work like
    # the one on the form
    if [winfo exists .famboco] {
        famboco_set_solver .famboco.main
        return
    }
    
    get_solver_info
    
    set ch [choose_one "Select a solver." [lsort [array names solver_info]] \
                $solution(solver)]
    if {$ch == ""} return
    
    solution_set_solver $ch 1
}

proc solution_set_solver {ch getbc} {
    global solution solver_info env famboco_edit file_name options

    if {[info exists solution(solver)] && ($solution(solver) == $ch) && ($ch != "Fluent_V6")} return 
    if ![info exists solver_info] { get_solver_info }
    if {$ch == "Generic"} { set ch "" }
    if {$ch == "PRECISE"} { set ch "PRECISE (SI)" }
    if {$ch == ""} {
        mess "Current solver is undefined (generic)\n"
        return
    }
    
    if {$ch == "Fluent_V6"} {
        if {$options(default_solver) == "Fluent_V6"} {
            set options(default_solver) "ANSYS Fluent"
        }
        mess "Resetting solver \"$ch\" to solver \"ANSYS Fluent\"\n"
        set ch "ANSYS Fluent"
        set solution(solver) $ch
        set getbc 1
    }
    
    mess "Current solver is $ch\n"   
    if ![info exists solver_info($ch)] {
        mess "Unknown solver $ch in solution_set_solver\n" red
        return
    } 
    set si $solver_info($ch)
    set sol [lindex $si 1]
    set tdir [lindex $si 4]
    set proc ${sol}_write_input
    if ![file exists $tdir/$sol.tcl] {
        if [file exists ./$sol.tcl] {
            set tdir .
        } else {
            error "GUI file for $sol doesn't exist in either . or $tdir"
        }
    }
    uplevel #0 source [list $tdir/$sol.tcl]
    
    if $getbc {
        if [file exists $tdir/$sol.bcinfo] {
            famboco_load_bcinfo $tdir/$sol.bcinfo 1
        } elseif [file exists ./$sol.bcinfo] {
            famboco_load_bcinfo ./$sol.bcinfo
        } else {
            famboco_load_bcinfo ""
        }
    }
    set solution(solver) $ch    
    set famboco_edit(solver) $ch
    ic_boco_solver $ch
    ic_solver_mesh_info $ch
    catch { solution_update_buttons }
    if {[info exists file_name(settings)] && ($file_name(settings) != "")} {
        set ai [expr {[info exists ai_environment] && $ai_environment}]
        if $ai { aie_close_params }
        set no_par 1
        if {[info exists file_name(solver_params)] && ($file_name(solver_params) != "")} {set no_par 0}
        if $no_par {set file_name(solver_params) [file rootname $file_name(settings)].$sol.par}   
        if $ai { aie_close_attr }
        set no_fbc 1
        if {[info exists file_name(family_boco)] && ($file_name(family_boco) != "")} {set no_fbc 0}
        if $no_fbc {set file_name(family_boco) [file rootname $file_name(settings)].$sol.fbc}
    }
}

proc solution_params {} {
    error "Not yet implemented"
}

proc solution_input {args} {
    global solution solver_info env file_name batch_mode ai_environment

    set ai [expr {[info exists ai_environment] && $ai_environment}]   
    if {$solution(solver) == "" || $solution(solver) == "Generic"} {
        solution_select
        if {$solution(solver) == "" || $solution(solver) == "Generic"} return
    }

    if {![info exists file_name(family_boco)] || $file_name(family_boco) == "" || ![file exists $file_name(family_boco)]} {
        if $ai {
            aie_saveas_attr
        } else {
            file_savefamboco 0
        }
    }
    
    if !$batch_mode {
        if [file_needs_save any] {
            if {![info exists file_name(project_dir)] || $file_name(project_dir) == ""} {
                if $ai {
                    aie_saveProject 0
                } else {
                    file_saveproject 1
                }
            } else { 
                switch [tk_dialog .saveold Save "Save current project first?" "" -1 Yes No Cancel] {
                    0 {
                        if $ai {
                            aie_saveProject 0
                        } else {
                           file_saveproject 1
                        }
                    }
                    1 { }
                    2 { return 0 }
                }
            }
        }
    }
    
    set si $solver_info($solution(solver))
    set sol [lindex $si 1]
    set program [lindex $si 2]
    set tdir [lindex $si 4]
    set proc ${sol}_write_input
    if {[info procs $proc] == ""} {
        if ![file exists $tdir/$sol.tcl] {
            error "GUI file for $solver doesn't exist"
        }
        uplevel #0 source [list $tdir/$sol.tcl]
    }
    
    # Now we have to do tricks to get the old solver files to work
    global place current_solver ${sol}_output_path icem_powermesh confname
    global solver s2u_path superdomain_path merge_unstr_path
    
    set solver $solution(solver)
    set current_solver $sol
    if ![string compare $tdir $env(ICEM_ACN)/icemcfd/output-interfaces] {
        if {$solver != "CFX-TASCflow"} {
            if [catch {set ${sol}_output_path [get_program icemcfd/output-interfaces $program]} res] {
		        mess "Error : solver $solver is not available for this platform\n" red
		        return
		    }
	    } else {
            if [catch {set ${sol}_output_path [get_program icemcfd/output-interfaces/32bit $program]} res] {
		        mess "Error: solver $solver is not available for this platform\n" red
		        return
		    }	    
	    }
    } else {
        set ${sol}_output_path $tdir/$program
    }
    if [catch {set s2u_path [get_program icemcfd/output-interfaces str_to_unstr]} res] {
        mess "Warning: $res\n" red
    }
    if [catch {set superdomain_path [get_program icemcfd supdomain]} res] {
        mess "Warning: $res\n" red
    }
    if [catch {set merge_unstr_path [get_program icemcfd merge_unstr]} res] {
        mess "Warning: $res\n" red
    }
    set icem_powermesh 0
    set place $file_name(project_dir)
    set confname [file tail [file dirname $file_name(project_dir)]]
    if {($confname == "icemcfd") || ($confname == "mulcad") || ($confname == "") || ($confname == ".")} {
        set confname [file tail $file_name(project_dir)]
    }

    busy 1
    puts "$proc $args"
    if [catch {eval $proc $args} res] {
        mess $res\n red
    } else {
        mess "Done with translation.\n"
    }
    busy 0
}

proc solution_start {} {
    global solution solver_info
        
    if {$solution(solver) == ""} {
        solution_select
        if {$solution(solver) == ""} return
    }
    set sol $solution(solver)
    set proc [lindex $solver_info($sol) 1]_run_solver
    
    # Make sure proc exists before invocation
    
    if {[info procs $proc] == ""} {
        error "Proc \"$proc\" is not implemented"
    } else {
        $proc
    }
}

proc solution_visual3 {{opts ""} {nhosts ""}} {
    global env black_and_white use_xwindows file_name
    
    if ![info exists env(ICEM_V3_17)] {
       global tcl_platform host_vendor
        
          # for visual3p executable -------------

       if ![info exists env(VISUAL3P_ROOT)] {
           set env(VISUAL3P_ROOT) $env(ICEM_ACN)
       }
       set v3p_app [file join $env(VISUAL3P_ROOT) bin visual3p]
       if {$tcl_platform(platform) == "windows"} {
          append v3p_app \.exe
       }
       if ![file executable $v3p_app] {
          error "Can't find Visual3p executable $v3p_app"
       }

          # for PVM stuff ----------------

       if ![info exists  env(PVM_ROOT)] {
          set env(PVM_ROOT) [file join $env(ICEM_ACN) pvm3]
       }
       if {$tcl_platform(platform) == "windows"} {
          set env(V3P_ARCH) win40
          set env(PVM_ARCH) WIN32
          set env(PVM_TMP) c:\\tmp
          set env(PVM_DPATH) \
             [file join $env(PVM_ROOT) lib $env(PVM_ARCH) pvmd3.exe]
       } else {
          switch -- $tcl_platform(os) {
             IRIX - IRIX64 {
                set rr [exec file $v3p_app]
                if {[lsearch $rr "64-bit"] < 0} {
                   if {[lsearch $rr "mips-4"] < 0} {
                      set env(V3P_ARCH) sgi6
                   } else {
                      set env(V3P_ARCH) mips4
                   }
                   set env(PVM_ARCH) SGI6
                } else {
                   set env(V3P_ARCH) mips64
                   set env(PVM_ARCH) SGI64
                }
             }
             HP-UX {
                set rr [exec file $v3p_app]
                if {[lsearch $rr "ELF-64"] < 0} {
                   set env(V3P_ARCH) hp10
                   set env(PVM_ARCH) HPPA
                } else {
                   set env(V3P_ARCH) hp11
                   set env(PVM_ARCH) HPPA64
                }
             }
             SunOs {
                set rr [exec file $v3p_app]
                if {[lsearch $rr "ELF-64"] < 0} {
                   set env(V3P_ARCH) sol7
                   set env(PVM_ARCH) SUN4SOL2
                } else {
                   set env(V3P_ARCH) sol64
                   set env(PVM_ARCH) SUN64
                }
             }
             default {
                set env(V3P_ARCH) $host_vendor
                set env(PVM_ARCH) \
                      [exec [file join $env(PVM_ROOT) lib pvmgetarch]]
             }
          }
          set env(PVM_DPATH) \
             [file join $env(PVM_ROOT) lib $env(PVM_ARCH) pvmd3]
       }
       if ![file executable $env(PVM_DPATH)] {
          error "Can't find PVM daemon $env(PVM_DPATH)"
       }

          # set pV3_* used in pV3 libs ------------

       if {$tcl_platform(platform) == "windows"} {
          if {![info exists env(pV3_Group)] && [info exists env(LOGNAME)]} {
             set env(pV3_Group) "pV3_$env(LOGNAME)"
          }
       }
       set env(pV3_TO) 62208000

          # to skip setup hosts etc.  --------------

       if {$tcl_platform(platform) == "windows"} {
          set env(V3PUSEDEFAULTHOSTS) 1
       } else {
          if {$nhosts == ""} {
             if ![info exists env(V3PUSEDEFAULTHOSTS)] {
                 set env(V3PUSEDEFAULTHOSTS) 1
             }
          } else {
             catch {unset env(V3PUSEDEFAULTHOSTS)}
          }
       }

       if ![info exists env(VISUAL3P_START)] {
           set env(VISUAL3P_START) 1
       }

          # to specify v3pclient dir  --------------

       if ![info exists env(V3PCLIENT_DIR)] {
          set env(V3PCLIENT_DIR) $env(ICEM_ACN)
       }

          # for readers ----------------

       set platform [set tcl_platform(platform)]
       if [string compare $platform "windows"] {
          if [info exists env(LD_LIBRARY_PATH)] {
             if {[string first $env(LD_LIBRARY_PATH) "result-interfaces"] == -1 } {
                set env(LD_LIBRARY_PATH) \
                        $env(LD_LIBRARY_PATH):$env(ICEM_ACN)/icemcfd/result-interfaces
             }
          } else {
             set env(LD_LIBRARY_PATH) $env(ICEM_ACN)/icemcfd/result-interfaces
          }
 
          if [info exists env(LD_LIBRARYN32_PATH)] {
             if { [string first $env(LD_LIBRARYN32_PATH) "result-interfaces"] == -1 } {
                set env(LD_LIBRARYN32_PATH) \
                    $env(LD_LIBRARYN32_PATH):$env(ICEM_ACN)/icemcfd/result-interfaces
             }
          } else {
             set env(LD_LIBRARYN32_PATH) $env(ICEM_ACN)/icemcfd/result-interfaces
          }
 
          if [info exists env(LD_LIBRARY64_PATH)] {
             if { [string first $env(LD_LIBRARY64_PATH) "result-interfaces"] == -1 } {
                set env(LD_LIBRARY64_PATH) \
                  $env(LD_LIBRARY64_PATH):$env(ICEM_ACN)/icemcfd/result-interfaces
             }
             if {[string first $env(LD_LIBRARY64_PATH) $env(ICEM_ACN)/lib] == -1 } {
                switch -- $tcl_platform(os) {
                    IRIX - IRIX64 {
                        set rr [exec file $v3p_app]
                        if {[lsearch $rr "64-bit"] >= 0} {
                            set env(LD_LIBRARY64_PATH) $env(LD_LIBRARY64_PATH):$env(ICEM_ACN)/lib
                        }
                    }
                    default {
                    }
                }
             }
          } else {
             set env(LD_LIBRARY64_PATH) $env(ICEM_ACN)/icemcfd/result-interfaces
             switch -- $tcl_platform(os) {
                 IRIX - IRIX64 {
                     set rr [exec file $v3p_app]
                     if {[lsearch $rr "64-bit"] >= 0} {
                         set env(LD_LIBRARY64_PATH) $env(LD_LIBRARY64_PATH):$env(ICEM_ACN)/lib
                     }
                 }
                 default {
                 }
             }
          }

          if [info exists env(SHLIB_PATH)] {
             if {[string first $env(SHLIB_PATH) $env(SHLIB_PATH)/lib] == -1 } {
                set env(SHLIB_PATH) $env(SHLIB_PATH):$env(ICEM_ACN)/lib
             }
          } else {
             set env(SHLIB_PATH) $env(ICEM_ACN)/lib
          }
       }

          # for window manager's options ------------

       if [info exist env(ICEM_ONE_WINDOW)] {
          set env(ICEM_ONE_WINDOW_used) $env(ICEM_ONE_WINDOW)
       } else {
          set env(ICEM_ONE_WINDOW) 1
       }
       if [info exist env(ICEM_GRAY_BACKGROUND)] {
          set env(ICEM_GRAY_BACKGROUND_used) $env(ICEM_GRAY_BACKGROUND)
       } else {
          set env(ICEM_GRAY_BACKGROUND) 1 
       }

          # to set gsys -----------------

       if $black_and_white { set bw -bw } else { set bw "" }
       switch $use_xwindows {
            0 { set x "" }
            1 { set x -x }
            2 { set x -ogl }
       }

          # to set starting directories --------------

       set olddir [pwd]
       set newdir [file join [pwd] $file_name(project_dir)]

       if ![info exists env(V3PCLIENT_START_DIR)] {
           mess "Visual3p working directory is $newdir\n"
           set env(V3PCLIENT_START_DIR) $newdir
       } else {
           mess "Visual3p working directory is $env(V3PCLIENT_START_DIR)\n"
       }

       if [catch {cd $newdir} res] {
            mess "Can't change directory: $res\n"
       } 

       if [file readable $env(ICEM_ACN)/icemcfd/version] {
          set fp [open $env(ICEM_ACN)/icemcfd/version]
          if {$fp != ""} {
             set ver_n [string trim [read $fp]]
             close $fp
             if {[llength $ver_n] == 1} {set ver_n [lindex $ver_n 0]}
             if {[llength $ver_n] == 1} {set ver_n [lindex $ver_n 0]}
             set env(VISUAL3_WHOAMI) "$ver_n (Visual3p)"
             set env(VISUAL3_TOOLNAME) Visual3p
          }
       }


         # to start visual3p  ---------------

       catch {
          set outfile ""
          if {[info exist env(VISUAL3P_DEVELOPE)] && \
                    ($env(VISUAL3P_DEVELOPE) == 1)} {
             set outfile [file join $olddir visual3p.out]
             eval exec "\"$v3p_app\" $x $bw $opts" >& $outfile
          } else {
             eval exec "\"$v3p_app\" $x $bw $opts" &
          }

         # run_application_command "$v3p_app $x $bw $opts" $outfile 0
       }

         # to restore window manager options after visual3p exits ------

       if [info exist env(ICEM_GRAY_BACKGROUND_used)] {
           set env(ICEM_GRAY_BACKGROUND) $env(ICEM_GRAY_BACKGROUND_used)
           catch {unset env(ICEM_GRAY_BACKGROUND_used)}
       } else {
           catch {unset env(ICEM_GRAY_BACKGROUND)}
       }
       if [info exist env(ICEM_ONE_WINDOW_used)] {
           set env(ICEM_ONE_WINDOW) $env(ICEM_ONE_WINDOW_used)
           catch {unset env(ICEM_ONE_WINDOW_used)}
       } else {
           catch {unset env(ICEM_ONE_WINDOW)}
       } 
       cd $olddir
    
    } else {
        if ![info exists env(VISUAL3_DIR)] { set env(VISUAL3_DIR) $env(ICEM_ACN) }
        
        if $black_and_white { set bw -bw } else { set bw "" }
        switch $use_xwindows {
            0 { set x "" }
            1 { set x -x }
            2 { set x -ogl }
        }
        set olddir [pwd]
        set newdir [file_select "New directory" \
                        $olddir "Directory to start visual3 in?" 1 1]
        if {$newdir == ""} return
        
        if [catch {cd $newdir} res] {
            mess "Can't change directory: $res\n"
        } else {
            mess "New working directory is $newdir\n"
        }
        catch {
            set app [get_program bin visual3]
            run_application_command "$app $x $bw $opt"
        }
        cd $olddir
    }
}

proc solution_mom3d {} {
    global env black_and_white use_xwindows file_name
       
    if ![info exists env(MOM3D_DIR)] { set env(MOM3D_DIR) $env(ICEM_ACN) }
    
    set dir $file_name(project_dir)
    if {[file pathtype $dir] == "relative"} { set dir [pwd]/$dir }
    
    set command "-dir $dir"
    
    # is a domain name loaded
    
    if {$file_name(domain) != ""} {
        append command " -dom $file_name(domain)"
    }
    
    # is a tetin file loaded?
    
    if {$file_name(tetin) != ""} {
        append command " -tetin $file_name(tetin)"
    }
    
    # is a family topo loaded?
    
    if {$file_name(family_topo) != ""} {
        append command " -famtopo $file_name(family_topo)"
    }
    
    # is a topo mulcad out loaded?
    
    if {$file_name(topo_mulcad_out) != ""} {
        append command " -topo $file_name(topo_mulcad_out)"
    }
    
    # is a family boco name parsed?
    
    if [ic_geo_is_loaded] {
        if {$file_name(family_boco) != ""} {
            append command " -boco $file_name(family_boco)"
        }
    }
    
    ic_run_application_command . icemcfd mom3d_gui $command
}

proc movemesh_param_init {} {
    global movemesh
    
    set movemesh(init) 1
    set movemesh(hexsmooth) [ic_smooth_decide_post_smoother]
    set movemesh(smooth) [smooth_decide_uns_smoother]
    
    if [catch {set max_ratio [lindex \
            [ic_uns_metric all compute_diagnostic "Aspect ratio"] 3]}] {
        set max_ratio .25
    }
    set movemesh(maxratio) [expr $max_ratio*.75]
}

proc solution_movemesh {} {
    global env file_name movemesh movemesh_forms
       
    if ![ic_uns_is_loaded] { error "No current mesh to move" }
    
    if ![info exists movemesh(init)] {
        movemesh_param_init
    }

    set buts [list [list Apply "movemesh_apply"] \
                  [list Reset "movemesh_param_init"] dismiss]
    
    set d [form_init .movemesh_model "Moving Mesh Params" "" $buts]
    if {$d != ""} {
        form_label $d.rotaxis_l "Axis of Rotation" {1 0 -cols 2}
        form_entry $d.rotaxis movemesh(axis) "" {1 2}
        
        form_label $d.rotorigin_l "Rotation Origin" {2 0 -cols 2}
        form_entry $d.rotorigin movemesh(origin) "" {2 2}
        form_button $d.rotaxis_sel "Select" \
            "disp_get_location movemesh(origin); movemesh_update" {2 3}
                
        form_checkbutton $d.rotpoint "Rotation Vector" \
            movemesh(axptactive) {3 0 -cols 2}
        form_entry $d.rotpoint2 movemesh(vectaxis) "" {3 2} \
            movemesh(axptactive)
        form_button $d.rotpoint2_sel "Select" \
            "disp_get_location movemesh(vectaxis); movemesh_update" \
            {3 3} movemesh(axptactive)
                
        form_label $d.trans_l "Translation of Origin" {4 0 -cols 2} \
            movemesh(tranptinactive)
        form_entry $d.trans movemesh(trans) "" {4 2} \
            movemesh(tranptinactive)
        form_button $d.trans_sel "Select" \
            "disp_get_location movemesh(trans)" {4 3} \
            movemesh(tranptinactive)
                    
        form_checkbutton $d.tranpoint \
            "Translation Vector of\nRotation Origin" \
            movemesh(tranptactive) {5 0 -cols 2} "" "movemesh_update"
        form_entry $d.tranpoint2 movemesh(vecttran) "" {5 2} \
            movemesh(tranptactive)
        form_button $d.tranpoint2_sel "Select" \
            "disp_get_location movemesh(vecttran); movemesh_update" \
            {5 3} movemesh(tranptactive)
                
        form_label $d.theta_l "Rotation (degrees)" {10 0 -cols 2}
        form_entry $d.theta movemesh(theta) float {10 2}
        
        form_checkbutton $d.uns "Standard Uns Smoother" \
            movemesh(smooth) {11 0 -cols 2 -fill both} "" movemesh_update
        
        form_checkbutton $d.post "Post Smoother" \
            movemesh(hexsmooth) "12 0 -cols 2 -fill both" "" movemesh_update
        
        form_button $d.pref "Preferences..." \
            "movemesh_preferences" {17 0 -cols 2 -fill both}
        
        form_label $d.surffams_l "Moving Surfaces" {20 0 -cols 2 -fill both}
        form_frame $d.surffams flat 1 {21 0 -cols 2 -fill both}
        set movemesh_forms(surffams) $d.surffams
        
        form_label $d.fluidfams_l "Floating Node Surfaces" \
            {22 0 -cols 2 -fill both}
        form_frame $d.fluidfams flat 1 {23 0 -cols 2 -fill both}
        set movemesh_forms(fluidfams) $d.fluidfams
        
        form_label $d.volfams_l "Fluids" {24 0 -cols 2 -fill both}
        form_frame $d.volfams flat 1 {25 0 -cols 2 -fill both}
        set movemesh_forms(volfams) $d.volfams
        
        form_finish bot
    }
    movemesh_update
    movemesh_families

    # Now put in the families
    
    form_wait .movemesh_model
}

proc movemesh_preferences {} {
    global movemesh
    
    if ![info exists movemesh(init)] {
        movemesh_param_init
    }
    
    set buts [list dismiss]
    set d [form_init .movemesh_prefer "Preferences" "" $buts]
    if {$d != ""} {
        set row 0
        form_label $d.nmoves_l "Number of Moves" "$row 0 -cols 2"
        form_entry $d.nmoves movemesh(nmoves) int "$row 2"
        incr row
        
        form_label $d.maxiter_l "Max Tries" "$row 0 -cols 2"
        form_entry $d.maxiter movemesh(maxiter) int "$row 2"
        incr row
    
        form_label $d.maxsol_l "Max Solution Iter" "$row 0 -cols 2"
        form_entry $d.maxsol movemesh(maxsoliter) int "$row 2"
        incr row
    
        form_label $d.eigentol_l "Distortion Min" " $row 0 -cols 2"
        form_entry $d.eigentol movemesh(eigentol) float "$row 2"
        incr row
    
        form_label $d.method_l "Method" "$row 0 -cols 2"
        form_frame $d.solvemet flat 0 "$row 2 -cols 2"
        form_radiobutton $d.solvemet.methods "Simple" movemesh(method) \
                simple "0 0"

        form_radiobutton $d.solvemet.methodlf "Laplace" movemesh(method) \
                laplace "0 1"

        form_radiobutton $d.solvemet.methodef "Elastic" movemesh(method) \
                elastic "0 2"
        incr row

        form_checkbutton $d.uns "Standard Uns Smoother" \
            movemesh(smooth) "$row 0 -cols 2" "" movemesh_update
        incr row
        
        form_label $d.maxratio_l "Smooth to" "$row 0 -cols 2" movemesh(smooth)
        form_entry $d.maxratio movemesh(maxratio) "" "$row 2" \
            movemesh(smooth)
        incr row
        
        form_label $d.niter_l "Number of iterations" "$row 0 -cols 2" \
            movemesh(smooth)
        form_entry $d.niter movemesh(niter) "" "$row 2" \
            movemesh(smooth)
        incr row
        
        form_checkbutton $d.nodeonly "Node Movement Only" \
            movemesh(onlynode) "$row 0 -cols 2" movemesh(smooth) \
            "movemesh_update"
        incr row
        
        # form_checkbutton $d.prisms "Include Pyramids" \
            # movemesh(smoothpyra) "4 0 -cols 2"
        
        form_checkbutton $d.prisms "Include Prisms" \
            movemesh(smoothprism) "$row 0 -cols 2" movemesh(smooth)
        incr row
        
        # form_checkbutton $d.prisms "Include Hexas" \
            # movemesh(smoothhexa) "4 0 -cols 2"
        
        form_checkbutton $d.coarsen "Coarsening" \
            movemesh(coarsen) "$row 0 -cols 2" movemesh(smoothmodsactive) \
            "movemesh_update"
        incr row
        
        form_checkbutton $d.swap "Swapping" \
            movemesh(swap) "$row 0 -cols 2" movemesh(swapactive)
        incr row
        
        form_checkbutton $d.refine "Refinement" \
            movemesh(refine) "$row 0 -cols 2" movemesh(smoothmodsactive)
        incr row
        
        form_checkbutton $d.post "Post Smoother" \
            movemesh(hexsmooth) "$row 0 -cols 2" "" movemesh_update
        incr row
        
        form_label $d.upto_l "Post Smooth Up To" "$row 0 -cols 2" \
            movemesh(hexsmooth)
        form_entry $d.upto movemesh(upto) float "$row 2" \
            movemesh(hexsmooth)
        incr row
        
        form_label $d.metric_l "Post Smooth Metric" "$row 0 -cols 2" \
            movemesh(hexsmooth)
        incr row
        
        form_radiobutton $d.det "Determinant" movemesh(metric) \
            determinant "$row 0" movemesh(hexsmooth)
        
        form_radiobutton $d.mangle "Min Angle" movemesh(metric) \
            min_angle "$row 1" movemesh(hexsmooth)
        
        form_radiobutton $d.warp "Warp" movemesh(metric) \
            warp "$row 2" movemesh(hexsmooth)
        
        form_radiobutton $d.lap "Laplace" movemesh(metric) \
            laplace "$row 3" movemesh(hexsmooth)
        incr row
        
        form_radiobutton $d.qual "Quality" movemesh(metric) \
            quality "$row 0" movemesh(hexsmooth)
        
        form_radiobutton $d.skw "Skew" movemesh(metric) \
            skew "$row 1" movemesh(hexsmooth)
        
        form_radiobutton $d.asp "Aspect Ratio" movemesh(metric) \
            aspect_ratio "$row 2" movemesh(hexsmooth)
        incr row
        
        form_checkbutton $d.surf "Surface Fitting" movemesh(sfit) \
            "$row 0 -cols 2" movemesh(hexsmooth)
        incr row
        
        form_checkbutton $d.pp "Ignore Pre Points" movemesh(ignorepp) \
            "$row 0 -cols 2" movemesh(hexsmooth)
        form_finish bot
    }
    movemesh_update
    form_wait .movemesh_prefer 1
}

proc movemesh_search_on {list fam} {
    if {[lsearch $list $fam] == -1} { return 0 }
    return 1
}

proc movemesh_eliminate_fams {arr list} {
    global $arr
    
    foreach f [array names $arr] {
        set fam [set ${arr}($f)]
        if {[lsearch $list $fam] < 0} {
            catch {unset ${arr}($f)}
        }
    }
}

proc movemesh_families {{dolist all}} {
    global movemesh movemesh_surfs movemesh_fsurfs movemesh_vols fam_visible
    global movemesh_forms
    
    set allfamilies [lsort [ic_uns_list_families]]
    set volfamilies [ic_uns_list_families 3]
    
    movemesh_eliminate_fams movemesh_surfs $allfamilies
    movemesh_eliminate_fams movemesh_fsurfs $allfamilies
    movemesh_eliminate_fams movemesh_vols $allfamilies
    
    set movemesh_forms(surfs) ""
    set movemesh_forms(fsurfs) ""
    set movemesh_forms(vols) ""
    
    if [info exists movemesh(on_surfs)] {
        # puts "os = $movemesh(on_surfs), ofs=$movemesh(on_fsurfs) \
        #        ov=$movemesh(on_vols)"
    }

    set nsurfs 0
    set nvols 0
    set visability [array names fam_visible]
    foreach f $allfamilies {
        set col [family_color_for_name $f]
        set entry [list $f -text $f -selectbackground $col \
                -foreground $col]
        
        if {[lsearch $volfamilies $f] == -1} {
            lappend movemesh_forms(surfs) $entry
            lappend movemesh_forms(fsurfs) $entry
            
            # only turn on surface families that are visible as a default
            
            if ![info exists movemesh(on_surfs)] {
                if {[lsearch $visability $f] == -1} {
                    set movemesh_surfs($f) 0
                } else {
                    set movemesh_surfs($f) $fam_visible($f)
                }
            } else {
                set movemesh_surfs($f) \
                        [movemesh_search_on $movemesh(on_surfs) $f]
            }
            
                # No fluid (projective) surfs as default
            
            if ![info exists movemesh(on_fsurfs)] {
                set movemesh_fsurfs($f) 0
            } else {
                set movemesh_fsurfs($f) \
                        [movemesh_search_on $movemesh(on_fsurfs) $f]
            }
                    
            incr nsurfs
        } else {
            lappend movemesh_forms(vols) $entry
            if ![info exists movemesh(on_vols)] {
                set movemesh_vols($f) 1
            } else {
                set movemesh_vols($f) \
                        [movemesh_search_on $movemesh(on_vols) $f]
            }
            incr nvols
        }
    }
    
    if {$nsurfs > 5} {set nsurfs 5}
    if {$nvols > 5} {set nvols 5}
    
    if {$dolist == "all"} {set dolist "surfs fsurfs vols"}   
    foreach l $dolist {
        switch $l {
            surfs {
                check_box $movemesh_forms(surffams) \
                    $movemesh_forms(surfs) $nsurfs movemesh_surfs
            }
            
            fsurfs {
                check_box $movemesh_forms(fluidfams) \
                    $movemesh_forms(fsurfs) $nsurfs movemesh_fsurfs
            }
            
            vols {
                check_box $movemesh_forms(volfams) $movemesh_forms(vols) \
                    $nvols movemesh_vols
            }
        }
    }
}

proc movemesh_update {} {
    global movemesh
    
    if $movemesh(axptactive) {
        set axis ""
        for {set i 0} {$i < 3} {incr i} {
            set xi  [lindex $movemesh(vectaxis) $i]
            set xi0 [lindex $movemesh(origin) $i]
            lappend axis [expr $xi - $xi0]
        }
        set movemesh(axis) $axis
    }
    
    set movemesh(tranptinactive) [expr !$movemesh(tranptactive)]
    if $movemesh(tranptactive) {
        set axis ""
        for {set i 0} {$i < 3} {incr i} {
            set xi  [lindex $movemesh(vecttran) $i]
            set xi0 [lindex $movemesh(origin) $i]
            lappend axis [expr $xi - $xi0]
        }
        set movemesh(trans) $axis
    }
    set movemesh(smoothmodsactive) \
        [expr !$movemesh(onlynode) && $movemesh(smooth)]
    
    set movemesh(swapactive) \
        [expr $movemesh(smoothmodsactive) && !$movemesh(coarsen) && \
            $movemesh(smooth)]
}

proc movemesh_smooth_cmd {{geofixed 0}} {
    global movemesh batch_mode
    
    set smoothcmd ""
    if $movemesh(smooth) {
        set smoothcmd "-smooth -maxratio $movemesh(maxratio) -niter \
 $movemesh(niter)"
        if $movemesh(smoothpyra) {
            append smoothcmd " -smoothpyra"
        } else {
            append smoothcmd " -fixpyra"
        }
        
        if $movemesh(smoothprism) {
            append smoothcmd " -smoothprism"
        } else {
            append smoothcmd " -fixprism"
        }
        
        if {$movemesh(smoothhexa) || $movemesh(hexsmooth)} {
            append smoothcmd " -smoothhexa"
        } else {
            append smoothcmd " -fixhexa"
        }
        
        if $movemesh(onlynode) {
            append smoothcmd " -onlynode"
        } else {
            append smoothcmd " -noonlynode"
            
            # allow coarsening.  If not allow edge swapping?
            
            if $movemesh(coarsen) {
                append smoothcmd " -coarsen"
            } elseif $movemesh(swap) {
                append smoothcmd " -swap"
            }
            
            if $movemesh(refine) { append smoothcmd " -refine"}
        }
    } else {
        set smoothcmd "-nosmooth"
    }
    
    if {$movemesh(hexsmooth)} {
        append smoothcmd " -hexsmooth -metric $movemesh(metric) \
 -upto $movemesh(upto)"
        if $movemesh(ignorepp) { append smoothcmd " -ignorepp" }
        if $movemesh(sfit) { append smoothcmd " -sfit" }
    }
    
    if $batch_mode { append smoothcmd " -batch" }  
    if $geofixed { append smoothcmd " -geofixed" }
    
    return $smoothcmd
}
        
proc movemesh_preferences_cmd {{geofixed 0}} {
    global movemesh file_name
    
    return [list -nmoves $movemesh(nmoves) -ntries $movemesh(maxiter) \
                -method $movemesh(method) -maxsoliter $movemesh(maxsoliter) \
                -eigentol $movemesh(eigentol) \
                -projdir $file_name(project_dir) \
                [movemesh_smooth_cmd $geofixed]]
}

proc movemesh_apply {} {
    global movemesh
    
    movemesh_update
    
    # extract list of all family names that are turned on
    
    set surfs [movemesh_extract_families movemesh_surfs]
    set fsurfs [movemesh_extract_families movemesh_fsurfs]
    set vols [movemesh_extract_families movemesh_vols]
    
    set movemesh(on_surfs) $surfs
    set movemesh(on_fsurfs) $fsurfs
    set movemesh(on_vols) $vols

    # convert to radians
    
    set theta [expr $movemesh(theta) * 3.141596/180.]
    
    # create the smoothing command
    
    set movemesh_cmd [movemesh_preferences_cmd 0]
    
    # move the mesh
    
    busy 1
    set rethrow [catch {ic_uns_move_mesh $movemesh(origin) \
                            $movemesh(axis) $movemesh(trans) $theta \
                            $movemesh_cmd $surfs $fsurfs $vols} msg]
    busy 0
    if {$rethrow} { error $msg }
}

proc movemesh_extract_families {var} {
    global $var
    
    set ret ""
    foreach idx [array names $var] {
        if [eval set ${var}($idx)] {
            lappend ret $idx
        }
    }
    return $ret
}

proc solution_yplus {} {
    global yplus movemesh_forms movemesh
       
    set yplus(ct4) [expr [ic_count_elements TETRA_4] > 0]   
    if ![info exists movemesh(init)] {
        movemesh_param_init
        set yplus(fixedele) 0
        
        if $yplus(ct4) {
            foreach et {HEXA_8 PENTA_6 PYRA_5} {
                set yplus(fixedele) \
                    [expr $yplus(fixedele) || [ic_count_elements $et] > 0]
            }
        }
    } elseif !$yplus(ct4) {
        
        # if no tetras, force fixedele to be OFF.  Otherwise won't
        # no way to move mesh filled completely with fixed elements
        
        set yplus(fixedele) 0
    }

    set buttons {{Apply yplus_apply} {Done {form_accept_hack .yplus}} cancel}
    set w [form_init .yplus "Y+" "" $buttons]
    
    yplus_set_state
    ic_cache_nodepos
    if {$w != ""} {
        form_label $w.value_l "Target Value" {0 0 -cols 2}
        form_entry $w.value yplus(value) float {0 2}
        
        form_label $w.load_l "Load Y+ From" {1 0 -cols 2}
        form_frame $w.load flat 1 {1 2 -cols 2}
        form_button $w.load.result "Result" \
            yplus_result_file {0 0 -fill both}
        form_button $w.load.file "Map" \
            yplus_ascii_file {0 1 -fill both}
        
        form_label $w.result_on_l "Y+ Value is" {3 0 -cols 2}
        form_radiobutton $w.cc "Cell Centered" yplus(result_on) \
            cellcenter {3 2} "" yplus_set_state
        form_radiobutton $w.node "Node" yplus(result_on) \
            node {4 2} "" yplus_set_state
        form_radiobutton $w.mpnode "Map to Surface Node" yplus(result_on) \
            maptosurf {5 2 -cols 2} "" yplus_set_state
        
        form_checkbutton $w.script "Execute Script --> file" \
            yplus(execscript) {6 0 -cols 2}
        
        form_label $w.script_file_l "Script File" {7 0 -cols 2} \
            yplus(execscript)
        file_select_entry $w.script_file yplus(script_file) 0 0 \
            "Script File" {7 2} yplus(execscript)
        
        form_checkbutton $w.uns "Standard Uns Smoother" \
            movemesh(smooth) {8 0 -cols 2 -fill both} "" movemesh_update
        
        form_checkbutton $w.post "Post Smoother" \
            movemesh(hexsmooth) "9 0 -cols 2 -fill both" "" movemesh_update
        
        form_label $w.pref_l "Preferences..." {10 0 -cols 2}
        form_frame $w.pref flat 1 {10 2 -cols 2}
        
        form_button $w.pref.yplus "Y+" yplus_preferences \
            {0 0 -fill both}
        
        form_button $w.pref.mm "Moving Mesh" \
            "movemesh_preferences" {0 1 -fill both}
   
        form_label $w.fluidfams_l "Y+ Surfaces" {20 0 -cols 2 -fill both}
        form_frame $w.fluidfams flat 1 {21 0 -cols 2 -fill both}
        set movemesh_forms(fluidfams) $w.fluidfams
        
        form_finish +300+300
    }
    movemesh_families fsurfs
    
    if [form_wait .yplus] {
        yplus_apply
    }
    ic_free_nodecache
}

proc yplus_apply {} {
    global yplus movemesh
    
    set exist {{Script script_file execscript}}
    yplus_check_exist $exist
    
    # use the script to create the result file if one specified
    
    if $yplus(execscript) {
        
        # if the result file exists, save it off as a temporary
        # file
        
        set savedresult ""
        if [file exists $yplus(result_file)] {
            set savedresult oldypresult
            cmd_cp $yplus(result_file) $savedresult
            cmd_rm $yplus(result_file)
        }
        
        catch {exec $yplus(script_file)}
        
        if ![file exist $yplus(result_file)] {
            if {$savedresult != ""} {
                cmd_cp $savedresult $yplus(result_file)
            }
            error "Result file \"$yplus(result_file)\" was not created."
        }
    }
    
    set ypsurfs [movemesh_extract_families movemesh_fsurfs]
    set movemesh(on_fsurfs) $ypsurfs
    
    set movemesh_cmd [movemesh_preferences_cmd 1]
    set resmode -$yplus(result_on)
    set avemode -$yplus(ave_method)
    
    busy 1
    set rethrow \
        [catch {ic_yplus $ypsurfs -allfluidsurfs -allfluids \
                    $movemesh_cmd $yplus(value) $resmode \
                    $yplus(result_be) $yplus(result_file) \
                    $yplus(fileismap) $yplus(vertoff) \
                    $yplus(result_var) $yplus(conv) $yplus(iter) \
                    $avemode $yplus(use_corr) $yplus(corr_threshold) \
                    $yplus(distance)} msg]
    busy 0
    
    if $rethrow {error $msg}
}

proc yplus_check_notempty {notempty} {
    global yplus
    
    foreach c $notempty {
        set title [lindex $c 0]
        set idx [lindex $c 1]
        if {$yplus($idx) == ""} {
            error "Entry $title cannot be empty"
        }
    }
        
}

proc yplus_check_exist {exist} {
    global yplus
    
    foreach c $exist {
        set title [lindex $c 0]
        set idx [lindex $c 1]
        set fidx [lindex $c 2]
        set file $yplus($idx)
        if {$file == "" || ![file readable $file]} {
            if {$fidx == "" || $yplus($fidx)} {
                error "$title file \"$file\" not readable"
            }
        }
    }
}

proc yplus_result_file {} {
    global yplus backend_reader
    
    set base_w .yplus_result
    set buttons {{Done {form_accept_hack .yplus_result}} cancel}
    set w [form_init $base_w "Y+ Result File" "" $buttons]
    
    set key [v3readers_available]
    set rlist ""
    foreach a $key {
        set stats [lindex $a 1]
        lappend rlist [lindex $stats 0]
    }
    
    if {$w != ""} {
        form_label $w.backl "Reader" {0 0} 
        futil_menuentry $w.back backend_reader "list $rlist" {0 1}
        
        form_label $w.rf_l "Result File" {1 0}
        file_select_entry $w.rf yplus(result_file) 0 0 \
            "Result file" {1 1}
        
        form_label $w.rv_l "Y+ variable" {2 0}
        form_entry $w.rv yplus(result_var) "" {2 1}
        
        # form_checkbutton $w.use_reader "Use specified Reader" \
            \# yplus(result_fe) {3 0 -cols 2}
        
        # form_label $w.reader_l "Reader" {4 0} yplus(result_fe)
        # file_select_entry $w.reader yplus(result_reader) 0 0 \
            \# "Reader" {4 1} yplus(result_fe)
        
        form_finish +300+300
    }
    
    if [form_wait $base_w] {
        
        set yplus(result_be) [v3reader_backend_for $backend_reader]
        set notempty {{"Backend" result_be} {"Y+ Variable" result_var}}
        # set exist {{"Reader" result_reader result_fe}}
        
        set rfile {"Result" result_file}
        if $yplus(execscript) {
            lappend notempty $rfile
        } else {
            lappend exist $rfile
        }
            
        yplus_check_notempty $notempty
        yplus_check_exist $exist
        set yplus(fileismap) 0
    }
}

proc yplus_ascii_file {} {
    global yplus
    
    set base_w .yplus_ascii
    set buttons {{Done {form_accept_hack .yplus_ascii}} cancel}
    set w [form_init $base_w "Y+ Result File" "" $buttons]
    
    if {$w != ""} {
        form_label $w.rf_l "Result File" {0 0}
        file_select_entry $w.rf yplus(result_file) 0 0 \
            "Result file" {0 1}
        
        form_label $w.off_l "Vertex offset" {1 0} yplus(use_node)
        form_entry $w.off yplus(vertoff) int {1 1} yplus(use_node)
        form_finish +300+300
    }
    
    if [form_wait $base_w] {
        set exist {{"Result" result_file}}        
        yplus_check_exist $exist
        set yplus(fileismap) 1
    }
}

proc yplus_preferences {} {
    global yplus yplus_cactive movemesh
    
    set yplus_cactive 0
    set buttons {reset {Done {form_accept_hack .yplus_pref}} cancel}
    
    set f .yplus_pref
    set w [form_init $f "Y+ Preferences" "" $buttons]
    yplus_set_state
    if {$w != ""} {
        form_label $w.relax_l "Relaxation" {0 0}
        form_entry $w.relax yplus(relax) float {0 1}
        form_label $w.iter_l "Max Iterations" {1 0}
        form_entry $w.iter yplus(iter) int {1 1}
        form_label $w.conv_l "Convergence" {2 0}
        form_entry $w.conv yplus(conv) float {2 1}
        
        form_checkbutton $w.fixedele "Move Fixed Elements in Parallel" \
            yplus(fixedele) {3 0 -cols 2} yplus(ct4)
        
        form_label $w.avg_l "Averaging Method" {4 0}
        form_radiobutton $w.neigh "Neighbors" yplus(ave_method) \
            aveneigh {4 1} "" yplus_set_state
        form_radiobutton $w.box "Box" yplus(ave_method) \
            avebox {5 1} "" yplus_set_state
        form_radiobutton $w.gauss "Gaussian" yplus(ave_method) \
            avegauss {6 1} "" yplus_set_state
        
        form_frame $w.dist ridge 1 {10 0 -cols 2 -fill both}
        form_checkbutton $w.dist.ucorr "Use Correlation Threshold" \
            yplus(use_corr) {0 0} yplus_cactive
#            yplus(use_corr) {0 0 -cols 2} yplus(use_distance)
        form_label $w.dist.corrthresh_l "Correlation Threshold" \
            {1 0} yplus(use_corr)
        form_entry $w.dist.corrthresh yplus(corr_threshold) float {1 1} \
            yplus(use_corr)
        form_label $w.dist.distance_l "Characteristic Distance" \
            {2 0} yplus(use_distance)
        form_entry $w.dist.distance yplus(distance) float {2 1} \
            yplus(use_distance)
        
        form_finish bot
    }
    
    form_wait $f 1
}
    
proc yplus_set_state {} {
    global yplus
    
    set yplus(use_distance) 0
    switch $yplus(ave_method) {
        avebox -
        avegauss { set yplus(use_distance) 1 }
        
        aveneigh -
        default {}
    }
    
    switch $yplus(result_on) {
        node { set yplus(use_node) 1 }
        maptosurf {
            set yplus(use_node) 1
            set yplus(maptosurf) 1
        }
        default { set yplus(use_node) 0 }
    }
}
        
proc solution_update_buttons {} {
    global solution solver_info env batch_mode param_info

    if $batch_mode return
    
    set w .v.top.panel2.output
    
    set sol $solution(solver)

    if {$sol == ""} {
        foreach p {params input start} {
            catch {$w.$p configure -text "(no solver)"}
        }
        return
    }
    
    get_solver_info
    
    if ![info exists solver_info($sol)] {
        foreach p {params input start} {
            catch {$w.$p configure -text "(no solver)"}
        }
        return
    }
    
    set s [lindex [split $sol " /"] 0]
    set proc [lindex $solver_info($sol) 1]_run_solver
    set rstat normal
    set data_available(can_run_solver) 1
    if {[info procs $proc] == ""} {
        set rstat disabled
        set data_available(can_run_solver) 0
    }
    
    if [winfo exists $w.input] {
        $w.input configure -text "$s input"
        bubble_define $w.input "Write out the current mesh in\n$sol format."
        
        if [info exists param_info] {
            set stat normal
        } else {
            set stat disabled
        }
        
        $w.params configure -text "$s params" -state $stat
        bubble_define $w.params "Edit parameters for\n$sol."
        
        $w.start configure -text "Run $s" -state $rstat
        bubble_define $w.start "Run $sol."
    }
    
    command_set_text "Solver input" "$s input" "$s input" \
        "Write out the current mesh in\n$sol format." ""
    command_set_text "Solver params" "$s params" "$s params" \
        "Write out the current mesh in\n$sol format." ""
    command_set_text "Start solver" "Start $s" "Start $s" \
        "Run the $sol program." ""
}

# ---------------------------------------------------------------------

proc domain_select_some_struct {mess} {
    global file_name struct_domains_selected
    
    set opts [glob -nocomplain $file_name(domains_dir)/*Multiblock]
    if {[llength $opts] > 1} {
        mess "Found multiple Multiblock files. Select one\n" blue
        set fm [lindex $opts 0]
        set fm [tk_getOpenFile -initialdir $file_name(domains_dir) \
            -filetypes {{{Structured Mesh Files} {.Multiblock}} {{All files} *}} \
		    -initialfile [file tail $fm] -parent .]
		if {$fm == ""} { return "" }
		set pref [file rootname [file tail $fm]].

    } else {
        set pref [file rootname [file tail $file_name(settings)]].
    }
    if ![llength [glob -nocomplain $file_name(domains_dir)/${pref}domain.*]] {
        set pref ""
    }
    catch { unset struct_domains_selected }
    foreach p [glob -nocomplain $file_name(domains_dir)/${pref}domain.*] {
        set n [string range [file extension $p] 1 end]
        set struct_domains_selected($n) 1
    }
    if ![info exists struct_domains_selected] {
        user_error "There are no structured domains in this project."
        return ""
    }
    set nums [lsort -integer [array names struct_domains_selected]]
    catch { destroy .domain_struct_select }
    if ![check_box_form .domain_struct_select "Select domains with project prefix\
         \"[file rootname $pref]\" to $mess." $nums 10 struct_domains_selected] {
        return ""
    }
    set ret ""
    foreach n $nums {
        if $struct_domains_selected($n) {
            lappend ret $file_name(domains_dir)/${pref}domain.$n
        }
    }
    return $ret
}

proc get_boco_topo {} {
    global file_name
    
    if {$file_name(family_boco) != ""} {
        set bc $file_name(family_boco)    
    } elseif {$file_name(mesh_dir) != ""} {
        set bc ""
        set opts [glob -nocomplain $file_name(mesh_dir)/*.fbc]
        if {$opts != ""} {
            set bc [lindex $opts 0]
        }
        if {$bc == ""} {
            if {[file exists $file_name(mesh_dir)/family_boco.fbc]} {
                set bc $file_name(mesh_dir)/family_boco.fbc
            } elseif {[file exists $file_name(mesh_dir)/family_boco]} {
                set bc $file_name(mesh_dir)/family_boco
            } elseif {[file exists $file_name(mesh_dir)/boco]} {
                set bc $file_name(mesh_dir)/boco
            } elseif {[file exists $file_name(mesh_dir)/boco_info]} {
                set bc $file_name(mesh_dir)/boco_info
            } else {
                set bc $file_name(mesh_dir)/
            }
        }
    } elseif [ic_uns_is_loaded] {
        set bc [create_trivial_famboco]
    } else {
        set bc ./
    }
    uplevel 1 set bocofile \"$bc\"
    
    # ---------------------
    
    if {$file_name(topo_mulcad_out) != ""} {
        set top $file_name(topo_mulcad_out)
    } elseif {$file_name(settings) != ""} {
	    set top [file rootname $file_name(settings)].top
    } else {
        set top ""
    }
    uplevel 1 set topofile \"$top\"
    
    # ---------------------
    
    if {$file_name(family_topo) != ""} {
        set fto $file_name(family_topo)
    } elseif {$file_name(settings) != ""} {
        set fto [file rootname $file_name(settings)].fto
    } else {
        set fto ""
    }
    uplevel 1 set ftopofile \"$fto\"
}

proc create_trivial_famboco {} {
    global file_name
    
    # the body of this function has largely been moved to:
    #    ic_boco_create_trivial
    set bocofilename $file_name(mesh_dir)/family_boco_trivial    
    return [ic_boco_create_trivial "./$bocofilename"]
}


proc domain_cmp {dom1 dom2} {
    set n1 [file extension $dom1]
    set n2 [file extension $dom2]
    if {![regexp {\.([0-9]+)$} $n1 dummy num1] ||
        ![regexp {\.([0-9]+)$} $n2 dummy num2] ||
        ([file root $dom1] != [file root $dom2])} {
            if {$dom1 == $dom2} { return 0 } \
                elseif {$dom1 > $dom2} { return 1 } \
                else { return -1 }
        }
    return [expr {$num1 - $num2}]
}

proc run_editor {file} { edit_file $file }

proc runxcom {title cmd catfile hitreturn back} {

    update
	if [ic_wb2_is_running] {
	    aie_set_global wb2_icemcfd_running 1
	}
    mess "Running: $cmd\n"
    busy 1
    mess [eval ic_exec $cmd]\n blue
    busy 0
	if [ic_wb2_is_running] {
        aie_unset_global wb2_icemcfd_running
	}
    mess Done\n
}

proc runcom {cmd { catfile "" } } {

    update
	if [ic_wb2_is_running] {
	    aie_set_global wb2_icemcfd_running 1
	}
    mess "Running: $cmd\n"
    busy 1
    mess [eval ic_exec $cmd]\n blue
    busy 0
	if [ic_wb2_is_running] {
        aie_unset_global wb2_icemcfd_running
	}
    mess Done\n
}

# ---------------------------------------------------------------------

proc output_g2u {} {
    error "not supported"
    
}

proc output_s2u {} {
    global file_name
    
    if {$file_name(domains_dir) == ""} {
        errormsg "The project directory is not set."
        return
    }
    set domdir $file_name(domains_dir)
    set seldoms [domain_select_some_struct "convert to unstructured"]
    if {$seldoms == {}} return
    set numbers ""
    foreach d $seldoms {
        lappend numbers [string range [file extension $d] 1 end]
    }
    # need to get the prefix if there is one.  This is hacky
    set prefix [file rootname [file tail [lindex $seldoms 0]]]
    if {$prefix == "domain"} {
        set prefix ""
    } else {
        set prefix [file rootname $prefix].
    }
    
    get_boco_topo

    set outfile struct_merge.uns
    set set_tol 0
    set tol 0.00001
    set new_version 0
    set familyPerDomainFlag 1
    set familyPerSubfaceFlag 0
    set familyPerEdgeFlag 0
    set familyPerVertexFlag 0
    
    set family_boco $bocofile
    set family_topo $ftopofile
    set bocofile $file_name(mesh_dir)/boco
    set boco_type 1
    set nomerge 0
    set alltypes 1
    set noORFN 0
    set standard 0
    
    if {![dialog .s2u "Structured -> Unstructured" \
          "Please edit the following options for Structured -> Unstructured" {
              {topofile -type path -title "Topology file" -help "Topo file"}
              {boco_type -opt {{"family_boco" 1} {"none" 0}} \
                -title "Type of boundary conditions file"}
              {family_boco -type path -active {$boco_type==1} \
                -title "Name of family_boco file"}
              {outfile -type string -title "Output domain" -help "Output domain"}
              {alltypes -opt {{"All types" 1} {"Triangles only" 0}} \
                  -title "Element types" -help "Element types to use"}
              {set_tol -active {!$alltypes} -opt {{"Yes" 1} {"No" 0}} \
                        -title "set a merging tolerance"
                        -help  "set a merging tolerance"}
              {tol -type string -active {$set_tol} -title "Merging tolerance" \
                        -help "enter a merging tolerance"}
              {nomerge -opt {{"Yes" 0} {"No" 1}} -title "Merge degenerated elements?"}
              {standard -opt {{"No" 0} {"Yes" 1}} -title "New node dim sections?"}
              {noORFN -opt {{"No" 0} {"Yes" 1}} -title "Remove ORFN elements?"}

          }]} return
    
    if {![file exists $topofile]} {
        warningmsg "Topology file doesn't exist!"
        return
    }
    
    if ![string compare $family_boco $bocofile] {
        if {![file exists $family_topo]} {
            errormsg "family_topo file doesn't exist!"
            return
        }
    }
    
    set unsfile $file_name(domains_dir)/$outfile
    
    set options ""
    set use_bocofile ""
    set use_famtopo ""
    if {$boco_type} {
        set new_version 1
    }

    if {$new_version} {
        lappend options -new
        set use_bocofile $family_boco
        if [file exists $family_topo] { set use_famtopo $family_topo }
    }
    
    if !$alltypes { lappend options -tria }
    if $set_tol   { lappend options -tol $tol }
    if $nomerge   { lappend options -nomerge }
    if $standard  { lappend options -standard }
    if $noORFN    { lappend options -delorfn }
    
    ic_convert_struct_to_unstruct $file_name(domains_dir) $numbers \
        $topofile $use_famtopo $use_bocofile $unsfile $options $prefix
}

# Note that this routine returns the name of the created superdomain.

proc output_super {} {
    global file_name

    if {$file_name(domains_dir) == ""} {
        errormsg "The project directory is not set."
        return ""
    }
    
    set sel [domain_select_some_struct "convert to a superdomain"]
    if {$sel == {}} return
    
    set numbers ""
    foreach d $sel {
        lappend numbers [string range [file extension $d] 1 end]
    }
    
    set supername $file_name(domains_dir)/super_domain.1

    get_boco_topo
    set listname $file_name(transfer_dir)/sup_domain_list
    
    if {![dialog .super "Create superdomain" \
              "Please edit the following options for the superdomain program." {
                  {topofile -type path -title "Topology file" -help "Topo file"}
                  {supername -type path -title "Superdomain file" -help "Superdomain"}
                  {listname -type path -title "Index list file" -help "Index list file"}
              }]} {return ""}
    
    if {![file exists $topofile]} {
        errormsg "File $topofile doesn't exist"
        return ""
    }

    set pref [file rootname [file tail $file_name(settings)]].
    if ![llength [glob -nocomplain $file_name(domains_dir)/${pref}domain.*]] {
        set pref ""
    }
    ic_convert_struct_to_super $file_name(domains_dir) $numbers $topofile \
        $supername $listname $pref
    
    return $supername
}

proc get_tetin_file {place} {
    return [med_file_select tetin 0 $place/tetin1 use]
}

proc multiblock_domain_list {{fm ""}} {
    global file_name ai_environment
    set ai [expr {[info exists ai_environment] && $ai_environment}]
    if {$fm == "" } {set fm $file_name(domain)}
    if {$fm == ""} return ""
    set dir [file dir $fm]
    if {[file tail $fm] == "Multiblock"} {
        set domain "$dir/domain"
    } else {
        set prj [file root [file tail $fm]]
        set domain "$dir/$prj.domain"
    }
    ic_mess "Loading multiblock mesh $domain.*\n"
    set files [glob -nocomplain $domain.*]
    set files [lsort -command domain_cmp $files]
    return $files
}


