
# This code creates the user interface for the smoothing manager.
#
# Stuff for smoothing.
# Copyright (c) 1998 1999 Pacific Marketing and Consulting, Inc.
#       	All rights reserved.
# Author:  Jari Spaete jsp@icemcfd.de

proc struct_smooth_callback {mess pct} {
    mess "$pct done, $mess\n"
    return 1
}

proc struct_smooth {} {  
  if ![ic_geo_is_loaded] {
      mess "Please load a geometry file in order to smooth the mesh.\n" red
      file_loadtetin "" 0
      if ![ic_geo_is_loaded] {
	  mess "Cannot smooth the mesh without geometry data!\n" red
	  return
      }
  }
  busy 1
  etm_Main
  busy 0
}

proc etm_Main {} {
  if ![winfo exists .methods] {
    etm_SetMode
    etm_LoadMethods
    etm_SetColors
    etm_LoadStructMesh
    etm_DefaultParameter
    etm_DefaultParameterPost
    etm_MainWin
  } else {
    top_destroy .methods
    etm_MainWin
  }
}   

proc etm_LoadMethods {} {
global etmMethod etmMode
  
  set etmMethod(all) {}
  lappend etmMethod(all)  "Thomas & Middlecoff"
  lappend etmMethod(all)  "Laplace"
  lappend etmMethod(all)  "Interpolation"
  lappend etmMethod(all)  "Mesh Calculated"
  lappend etmMethod(all)  "Sorenson - Thomas & Middlecoff"  
  lappend etmMethod(all)  "Sorenson - Laplace"
  lappend etmMethod(all)  "Hilgenstock - Thomas & Middlecoff"
  lappend etmMethod(all)  "Hilgenstock - Laplace"
  
  set "etmMethod(Thomas & Middlecoff)" $etmMode(SmoothThomasMiddlecoff)
  set "etmMethod(Laplace)" $etmMode(SmoothLaplace)
  set "etmMethod(Interpolation)" $etmMode(SmoothInterpolation)
  set "etmMethod(Mesh Calculated)" $etmMode(SmoothMeshCalculated)
  set "etmMethod(Sorenson - Thomas & Middlecoff)" $etmMode(SmoothSor_ThM)
  set "etmMethod(Sorenson - Laplace)" $etmMode(SmoothSor_Lap)
  set "etmMethod(Hilgenstock - Thomas & Middlecoff)" $etmMode(SmoothHilgenstock_ThM)
  set "etmMethod(Hilgenstock - Laplace)" $etmMode(SmoothHilgenst)
  set "etmMethod(Face Methods)" $etmMode(SmoothFaceMethods)
  
  set "etmMethod(None)" $etmMode(SmoothNone)
  set "etmMethod(Deformation)" $etmMode(SmoothDeformation)
    
  set "etmMethod(Sorenson Hybrid - Thomas & Middlecoff)" $etmMethod(Sorenson - Thomas & Middlecoff)
  set "etmMethod(Sorenson Hybrid - Laplace)" $etmMethod(Sorenson - Laplace)
  set "etmMethod(Hilgenstock Hybrid - Thomas & Middlecoff)" $etmMethod(Hilgenstock - Thomas & Middlecoff)
  set "etmMethod(Hilgenstock Hybrid - Laplace)" $etmMethod(Hilgenstock - Laplace)

  set etmMethod(2D) [list "Sorenson Hybrid" "Thomas & Middlecoff" "Laplace" \
  			  "Interpolation" "Hilgenstock Hybrid"]
  
  set etmMethod(3D) [list "Sorenson Hybrid" "Thomas & Middlecoff" "Laplace" \
  			  "Interpolation" "Hilgenstock Hybrid"] 

  set etmMethod(Mix) [list "Thomas & Middlecoff" "Laplace" \
  			   "Interpolation" \
			   "Sorenson - Thomas & Middlecoff" \
			   "Sorenson - Laplace" \
 			   "Hilgenstock - Thomas & Middlecoff" \
                           "Hilgenstock - Laplace" ]
}

proc etm_MainWin {} {
global etm etmParam etmMethod etmFlag etmList etmSmoother 
global etmMode guibase_dir env etm_runs
 
  set etm_runs 1
  if [winfo exists .methods] { top_destroy .methods }
  set buttons {
    {" Smooth " "etm_ProgSelect"}
    {"  Done  " "etm_done_smooth"}
  }  

  for {set i 0 } {$i < [ic_str_num_entities domain]} {incr i} {
    if ![info exists etmFlag($i)] {
      set etmFlag($i) 0
    }
    if ![info exists etmParam(2D,$i)] {
      set etmParam(2D,$i) "Sorenson - Laplace"
    }
    if ![info exists etmParam(3D,$i)] {
      set etmParam(3D,$i) "Sorenson - Laplace"
    }
    if ![info exists etmParam(Unselected,$i)] {
      set etmParam(Unselected,$i) "Deformation"
    }
  }

  set mwidth 13

  set w [form_init .methods "Smooth" "" $buttons] 
  if {$w != ""} {
    set row 1
    form_frame $w.1 flat 1 "$row 0 -pady 3"
    form_menubutton $w.1.1 "Methods" $w.1.1.m "0 0 -padx 3 -ipadx 2 -ipady 2"
    $w.1.1 configure -relief raised -bd 3 -indicatoron 1 -width $mwidth
    menu $w.1.1.m -tearoff 0
    set etm(prog_select) $etmMode(ProgSingleSmooth)
    $w.1.1.m add radiobutton -label "Single" -variable etm(prog_select) -value \
    	$etmMode(ProgSingleSmooth) -command etm_SetFunctionsState
    if !$etmSmoother(2D) {
      $w.1.1.m add radiobutton -label "3D global" -variable etm(prog_select) -value \
    	$etmMode(Prog3DGlobal) -command etm_SetFunctionsState
    }
    $w.1.1.m add radiobutton -label "Post" -variable etm(prog_select) -value \
    	$etmMode(ProgImprover) -command etm_SetFunctionsState
    $w.1.1.m add radiobutton -label "Global" -variable etm(prog_select) -value \
    	$etmMode(ProgGlobalSmooth) -command etm_SetFunctionsState
    if !$etmSmoother(2D) {
      $w.1.1.m add radiobutton -label "Predefined" -variable etm(prog_select) -value \
    	$etmMode(ProgPredefinedMesh) -command etm_SetFunctionsState
    }

    form_menubutton $w.1.2 "Select" $w.1.2.m "0 1 -padx 3 -ipadx 2 -ipady 2"
    $w.1.2 configure -relief raised -bd 3 -indicatoron 1 -width $mwidth
    menu $w.1.2.m -tearoff 0
    $w.1.2.m add cascade -label "Domains" -menu $w.1.2.m.1
    if !$etmSmoother(2D) {
      $w.1.2.m add cascade -label "Subfaces" -menu $w.1.2.m.2
    }
    $w.1.2.m add cascade -label "Edges" -menu $w.1.2.m.3
    $w.1.2.m add cascade -label "Vertices" -menu $w.1.2.m.4
    $w.1.2.m add cascade -label "IJK Zones" -menu $w.1.2.m.5
    menu $w.1.2.m.1 -tearoff 0
    set com "etm_SelectbyWhat domain RelaxationDomain relaxation"
    $w.1.2.m.1 add command -label "Relaxation" -command "$com"
    set com "etm_SelectbyWhat domain NonRelaxationDomain non-relaxation"
    $w.1.2.m.1 add command -label "Non-relaxation" -command "$com"
    if !$etmSmoother(2D) {
      menu $w.1.2.m.2 -tearoff 0
      set com "etm_SelectbyWhat subface RelaxationSubface relaxation"
      $w.1.2.m.2 add command -label "Relaxation" -command "$com"
      set com "etm_SelectbyWhat subface NonRelaxationSubface non-relaxation"
      $w.1.2.m.2 add command -label "Non-relaxation" -command "$com"
      set com "etm_SelectbyWhat subface CoefficientsSubface3D \"hold cell height\""
      $w.1.2.m.2 add command -label "Hold cell height" -command "$com"
      set com "etm_SelectbyWhat subface NonCoefficientsSubface3D \"release cell height\""
      $w.1.2.m.2 add command -label "Release cell height" -command "$com"
      set com "etm_SelectbyWhat subface BladeBoundary \"blade boundary\""
      $w.1.2.m.2 add command -label "Blade boundary" -command "$com"
    }
    menu $w.1.2.m.3 -tearoff 0
    set com "etm_SelectbyWhat edge EdgeGlobal globel"
    $w.1.2.m.3 add command -label "Global" -command "$com"
    set com "etm_SelectbyWhat edge EdgeFrozen fixed"
    $w.1.2.m.3 add command -label "Fixed" -command "$com"
    set com "etm_SelectbyWhat edge EdgeBunching \"fixed distribution\""
    $w.1.2.m.3 add command -label "Fixed distribution" -command "$com"
    set com "etm_SelectbyWhat edge NonEdgeBunching \"release distribution\""
    $w.1.2.m.3 add command -label "Release distribution" -command "$com"
    set com "etm_SelectbyWhat edge EdgeViolate violate"
    $w.1.2.m.3 add command -label "Violate" -command "$com"
    menu $w.1.2.m.4 -tearoff 0
    set com "etm_SelectbyWhat vertex VertexGlobal global"
    $w.1.2.m.4 add command -label "Global" -command "$com"
    set com "etm_SelectbyWhat vertex VertexLayer global"
    $w.1.2.m.4 add command -label "Layer" -command "$com"
###    set com "etm_SelectbyWhat vertex VertexFixed fixed"
###    $w.1.2.m.4 add command -label "Fixed" -command "$com"
    menu $w.1.2.m.5 -tearoff 0
    set com "etm_SelectObjects subface Zones RelaxationZone"
    $w.1.2.m.5 add command -label "Relaxation" -command "$com"
    set com "etm_SelectObjects subface Zones NonRelaxationZone"
    $w.1.2.m.5 add command -label "Non-relaxation" -command "$com"

    form_menubutton $w.1.3 "Parameters" $w.1.3.m "0 2 -padx 3 -ipadx 2 -ipady 2"
    $w.1.3 configure -relief raised -bd 3 -indicatoron 1 -width $mwidth
    menu $w.1.3.m -tearoff 0
    $w.1.3.m add command -label "Smoothing" -command "etm_SmoothingParameter"
    if !$etmSmoother(2D) {
      $w.1.3.m add command -label "Expert" -command "etm_SmoothingParameterExpert"
      $w.1.3.m add command -label "Plane" -command "etm_PlaneSmoothing All"
      $w.1.3.m add command -label "Predefined" -command "etm_PredefinedMeshParameter"
    }
    $w.1.3.m add command -label "Post" -command "etm_PostParameters"

    incr row
    form_frame $w.2 flat 3 "$row 0 -pady 1"
    form_menubutton $w.2.1 "List selected entities" $w.2.1.m "0 0 -padx 3 -ipadx 2 -ipady 2"
    $w.2.1 configure -relief raised -bd 3 -indicatoron 1 -width 20
    menu $w.2.1.m -tearoff 0
    $w.2.1.m add command -label "All domains" -command "etm_ListSelectedEntities domain"
    if !$etmSmoother(2D) {
      $w.2.1.m add command -label "All subfaces" -command "etm_ListSelectedEntities subface"
    }
    $w.2.1.m add command -label "All edges" -command "etm_ListSelectedEntities edge"
    $w.2.1.m add command -label "All vertices" -command "etm_ListSelectedEntities vertex"
    $w.2.1.m add command -label "All IJK zones" -command "etm_ListSelectedEntities zone"
    $w.2.1.m add command -label "Clear list" -command "etm_ListSelectedEntities clear"
    
    incr row
    form_frame $w.c flat 3 "$row 0 -pady 1"
    set etm(Main,Canvas) [form_canvas $w.c.1 410x100 sunken 3 "0 0" 1 1]
    
    incr row
    form_frame $w.3 flat 3 "$row 0 -pady 1"
    form_menubutton $w.3.1 "Clear selection" $w.3.1.m "0 0 -padx 3 -ipadx 2 -ipady 2"
    $w.3.1 configure -relief raised -bd 3 -indicatoron 1 -width $mwidth
    menu $w.3.1.m -tearoff 0
    set com "etm_ClearSelections; "
    append com "etm_SelectObjects subface None BladeBoundary; "
    append com "etm_SelectObjects subface None CoefficientsSubface3D; "
    append com "etm_SelectObjects domain All NonRelaxationDomain; "
    append com "etm_ClearSelectedEntities all"
    $w.3.1.m add command -label "All" -command "$com"
    set com "etm_ClearSelectedEntities domain; "
    append com "etm_SelectObjects domain All NonRelaxationDomain"
    $w.3.1.m add command -label "All domains" -command "$com"
    if !$etmSmoother(2D) {
      set com "etm_SelectObjects subface None RelaxationSubface; "
      append com "etm_SelectObjects subface None NonRelaxationSubface; "
      append com "etm_SelectObjects subface None BladeBoundary; "
      append com "etm_SelectObjects subface None CoefficientsSubface3D; "
      append com "etm_UnsetParameterPredefinedSubface; "
      append com "etm_ClearSelectedEntities subface"
      $w.3.1.m add command -label "All subfaces" -command "$com"
    }
    set com "etm_SelectObjects edge None EdgeBunching; "
    append com "etm_SelectObjects edge None EdgeFrozen; "
    append com "etm_SelectObjects edge None EdgeGlobal; "
    append com "etm_ClearViolateEdge; "
    append com "etm_ClearSelectedEntities edge"
    $w.3.1.m add command -label "All edges" -command "$com"
    set com "etm_SelectObjects vertex None VertexGlobal; "
    append com "etm_SelectObjects vertex None VertexLayer; "
    append com "etm_SelectObjects vertex None VertexFixed; "
    append com "etm_ClearSelectedEntities vertex"
    $w.3.1.m add command -label "All vertices" -command "$com"
    set com "etm_DeleteAllRegionZones RelaxationZone; "
    append com "etm_UnsetRelaxZone RelaxationZone; "
    append com "etm_DeleteAllRegionZones NonRelaxationZone; "
    append com "etm_UnsetRelaxZone NonRelaxationZone; "
    append com "etm_ClearSelectedEntities zone"    
    $w.3.1.m add command -label "All zones" -command "$com"
    form_menubutton $w.3.2 "Settings" $w.3.2.m "0 1 -padx 3 -ipadx 2 -ipady 2"
    $w.3.2 configure -relief raised -bd 3 -indicatoron 1 -width $mwidth
    menu $w.3.2.m -tearoff 0
    $w.3.2.m add command -label "Load..." -command "etm_Settings Load"
    $w.3.2.m add command -label "Save..." -command "etm_Settings Save"
    form_menubutton $w.3.3 "Display" $w.3.3.m "0 2 -padx 3 -ipadx 2 -ipady 2"
    $w.3.3 configure -relief raised -bd 3 -indicatoron 1 -width $mwidth
    menu $w.3.3.m -tearoff 0
    $w.3.3.m add radiobutton -label "On" -variable etmSmoother(DisplayOn) \
    	-value 1
    $w.3.3.m add radiobutton -label "Off" -variable etmSmoother(DisplayOn) \
    	-value 0
    trace variable etmSmoother(DisplayOn) w "etm_SetDisplayOnOff; list"
    incr row    
    form_frame $w.4 ridge 3 "$row 0 -pady 1"
    form_label $w.4.1 "Number of iterations" "0 0 -padx 3 -pady 3"
    form_entry $w.4.1e etm(nItera) float "0 1 -padx 3 -pady 3"
    form_button $w.4.1up "" "etm_SetArrow Up etm nItera" "0 2 -padx 3 \
    	-pady 3 -ipadx 3 -ipady 3" ""
    $w.4.1up configure -bitmap @$guibase_dir/goup.xbm
    form_button $w.4.1do "" "etm_SetArrow Down etm nItera" "0 3 -padx 3 \
    	-pady 3 -ipadx 3 -ipady 3" ""
    $w.4.1do configure -bitmap @$guibase_dir/godown.xbm
    form_label $w.4.2 "" "0 4 -padx 30 -pady 3"; $w.4.2 configure -width 5
    form_finish -20-20 1 0
  }
  etm_SetFunctionsState
  catch {wm protocol .methods WM_DELETE_WINDOW "etm_done_smooth"}
  catch {wm deiconify .methods}
}

proc etm_SetFunctionsState {} {
global etm etmMode etmSmoother
  
  if {$etm(prog_select) == $etmMode(ProgSingleSmooth) || \
      $etm(prog_select) == $etmMode(ProgGlobalSmooth)} {
    .methods.main.1.2.m entryconfigure 1 -state normal
    .methods.main.1.2.m entryconfigure 2 -state normal
    .methods.main.1.2.m entryconfigure 3 -state normal
    if !$etmSmoother(2D) {
      .methods.main.1.2.m entryconfigure 4 -state normal
      .methods.main.1.2.m.2 entryconfigure 2 -state normal
      .methods.main.1.2.m.2 entryconfigure 3 -state normal
    }    
    .methods.main.1.2.m.3 entryconfigure 0 -state normal
    .methods.main.1.2.m.3 entryconfigure 1 -state normal
    .methods.main.1.2.m.3 entryconfigure 2 -state normal
    .methods.main.1.2.m.3 entryconfigure 3 -state normal
    .methods.main.1.2.m.3 entryconfigure 4 -state disabled
    if $etmSmoother(2D) {
      .methods.main.1.3.m entryconfigure 0 -state normal
      .methods.main.1.3.m entryconfigure 1 -state disabled
    } else {
      .methods.main.1.3.m entryconfigure 0 -state normal
      .methods.main.1.3.m entryconfigure 1 -state normal
      if {$etm(prog_select) == $etmMode(ProgGlobalSmooth)} {
        .methods.main.1.3.m entryconfigure 2 -state disabled
      } else {
        .methods.main.1.3.m entryconfigure 2 -state normal
      }
      .methods.main.1.3.m entryconfigure 3 -state disabled
      .methods.main.1.3.m entryconfigure 4 -state disabled
    }
  } elseif {$etm(prog_select) == $etmMode(ProgImprover)} {
    if $etmSmoother(2D) {
      .methods.main.1.2.m entryconfigure 2 -state disabled
      .methods.main.1.2.m entryconfigure 3 -state disabled
    } else {
      .methods.main.1.2.m entryconfigure 1 -state normal
      .methods.main.1.2.m entryconfigure 2 -state normal
      .methods.main.1.2.m entryconfigure 3 -state disabled
      .methods.main.1.2.m entryconfigure 4 -state normal
      .methods.main.1.2.m.2 entryconfigure 2 -state disabled
      .methods.main.1.2.m.2 entryconfigure 3 -state disabled
    }
    .methods.main.1.2.m.3 entryconfigure 0 -state disabled
    .methods.main.1.2.m.3 entryconfigure 1 -state normal
    .methods.main.1.2.m.3 entryconfigure 2 -state normal
    .methods.main.1.2.m.3 entryconfigure 3 -state disabled
    .methods.main.1.2.m.3 entryconfigure 4 -state normal
    if $etmSmoother(2D) {
      .methods.main.1.3.m entryconfigure 0 -state disabled
      .methods.main.1.3.m entryconfigure 1 -state normal
    } else {
      .methods.main.1.3.m entryconfigure 0 -state disabled
      .methods.main.1.3.m entryconfigure 1 -state disabled
      .methods.main.1.3.m entryconfigure 2 -state disabled
      .methods.main.1.3.m entryconfigure 3 -state disabled
      .methods.main.1.3.m entryconfigure 4 -state normal
    }
  } elseif {$etm(prog_select) == $etmMode(ProgPredefinedMesh)} {
    .methods.main.1.2.m entryconfigure 1 -state disabled
    .methods.main.1.2.m entryconfigure 2 -state disabled
    .methods.main.1.2.m entryconfigure 3 -state disabled
     if !$etmSmoother(2D) {
       .methods.main.1.2.m entryconfigure 4 -state disabled
     }
    .methods.main.1.2.m.3 entryconfigure 4 -state disabled
    .methods.main.1.3.m entryconfigure 0 -state disabled
    .methods.main.1.3.m entryconfigure 1 -state disabled
    .methods.main.1.3.m entryconfigure 2 -state disabled
    .methods.main.1.3.m entryconfigure 3 -state normal
    .methods.main.1.3.m entryconfigure 4 -state disabled
  }
}

proc etm_ListSelectedEntities {type} {
global etmList etmFlag etmRelaxSubface etmEdgeAttr etmEdgeGlobal
global etmParam etmRelaxZone etmSmoother etmMethod etmMode etm
global etmVertexGlobal etmVertexFixed etmViolGeomZone etmRelaxCoeff

  etm_ClearSelectedEntities all
  if {$type == "clear"} { return }
  
  if {$type != "zone"} {
    set last [ic_str_num_entities $type]
  } else {
    set last [ic_str_num_entities domain]
  }
  
  set etm(Entities) $type
  set c $etm(Main,Canvas) 
  set n 0
  
  if {$type == "domain"} {
    set list $etmList(Domains)
    for {set i -1} {$i < $last} {incr i} {
      if {$type == "domain"} {
        if {$i == -1} {
          set fr [frame $c.win$n]
          $c create window 0 [expr $n * 20] -window $fr -anchor nw
          label $fr.label1$n -text "#" -width 8 -anchor w -bg white
          label $fr.label2$n -text "Domain type" -width 12 -anchor w -bg white
          label $fr.label3$n -text "Volume method" -anchor w -bg white
          set tmp(volume) $fr.label3$n
          if !$etmSmoother(2D) {
            label $fr.label4$n -text "Face method" -anchor w -bg white
            set tmp(face) $fr.label4$n
            label $fr.label5$n -text "Hold cell height" -width 16 -anchor w -bg white
          }
          if !$etmSmoother(2D) {
            etm_PackWidget $c.win$n left [list label1$n label2$n label3$n label4$n label5$n]
          } else {
            etm_PackWidget $c.win$n left [list label1$n label2$n label3$n]
          }
          incr n
          continue
        }
        if $etmFlag($i) {
          set fr [frame $c.win$n]
          $c create window 0 [expr $n * 20] -window $fr -anchor nw
          set ent [lindex [lindex $list $i] 1]
          set min [lindex [lindex $list $i] 2]
          set max [lindex [lindex $list $i] 3]
          label $fr.ent$n -text "$ent" -width 8 -anchor w -bg white
          etm_PackWidget $c.win$n left [list ent$n]
          set dom [expr $i + 1]
          set relax "Relaxation"
          label $fr.relax$n -text "$relax" -width 12 -anchor w -bg white
          etm_PackWidget $c.win$n left [list relax$n]
          if $etmSmoother(2D) {
            set method $etmParam(2D,$i)
          } else {
            set method $etmParam(3D,$i)
          }
          set len [expr [string length $method]]
          if [info exists tmp(volume)] {
            $tmp(volume) configure -width $len
            unset tmp(volume)
          }
          label $fr.method$n -text "$method" -width $len -anchor w -bg white
          etm_PackWidget $c.win$n left [list method$n]
          set method ""
          if !$etmSmoother(2D) {
            if [info exists etmParam(Mix,$i)] {
              set x 0
              set isMixed 0
              set isMethod [lindex $etmParam(Mix,$i) 0]
              foreach item {imin imax jmin jmax kmin kmax} {
                set txtMethod [lindex $etmParam(Mix,$i) $x]
                if {$etmMode(SmoothThomasMiddlecoff) == $txtMethod} {
                  set text "Thomas & Middlecoff"
                } elseif {$etmMode(SmoothLaplace) == $txtMethod} {
                   set text "Laplace"
                } elseif {$etmMode(SmoothInterpolation) == $txtMethod} {
                   set text "Interpolation"
                } elseif {$etmMode(SmoothSor_ThM) == $txtMethod} {
                   set text "Sorenson - Thomas & Middlecoff"
                } elseif {$etmMode(SmoothSor_Lap) == $txtMethod} {
                  set text "Sorenson - Laplace"
                } elseif {$etmMode(SmoothHilgenstock_ThM) == $txtMethod} {
                  set text "Hilgenstock - Thomas & Middlecoff"
                } elseif {$etmMode(SmoothHilgenst) == $txtMethod} {
                  set text "Hilgenstock - Laplace"
                }
                append method "$item - $text  "
                if {$isMethod != $txtMethod} { set isMixed 1 }
                incr x
              }
              if !$isMixed {
                set method "$etmParam(2D,$i)"
                set len [expr [string length $method]]
              } else {
                set len 400
              }
            } else {
              set method "$etmParam(2D,$i)"
              set len [expr [string length $method]]
            }
            label $fr.face$n -text "$method" -width $len -anchor w -bg white
            if [info exists tmp(face)] {
              $tmp(face) configure -width $len
              unset tmp(face)
            }
            etm_PackWidget $c.win$n left [list face$n]
            set m 0
            if [info exists etmList(etmRelaxCoeff,3D,outer,$i)] {
              foreach item {"i min" "i max" "j min" "j max" "k min" "k max"} {
                set coeff "$item [lindex $etmList(etmRelaxCoeff,3D,outer,$i) $m]"
                label $fr.coeff${n}_$m -text "$coeff" -anchor w -relief ridge -bg white
                etm_PackWidget $c.win$n left [list coeff${n}_$m]
                incr m
              }
            } else {
              foreach item {"i min" "i max" "j min" "j max" "k min" "k max"} {
                set coeff "$item 0"
                label $fr.coeff${n}_$m -text "$coeff" -anchor w -relief ridge -bg white
                etm_PackWidget $c.win$n left [list coeff${n}_$m]
                incr m
              }            
            }
          }
          incr n
        }
      }
    }
    set end $n
  } elseif {$type == "subface"} {
    set relax_label 0
    set abs_label 0
    set coeff_label 0 
    set grid_label 0 
    for {set i 1} {$i <= $last} {incr i} {
      if {[info exists etmRelaxSubface($i)]} {
        set relax_label 1
      }
      if {[info exists etm(sf,$i,abs_dist_bnd)] && $etm(sf,$i,abs_dist_bnd) != "-1"} {
        set abs_label 1
      }
      if {[info exists etm(sf,$i,relaxcoeff)] && $etm(sf,$i,relaxcoeff)} {
        set coeff_label 1
      }
      if {[info exists etm(sf,$i,grid_exp_rate_subf_perp)] && \
           $etm(sf,$i,grid_exp_rate_subf_perp) != -1} {
        set grid_label 1
      }
    }
    set len 0
    if {$relax_label} { set len [expr $len + 15] }
    if {$abs_label} { set len [expr $len + 15] }
    if {$coeff_label} { set len [expr $len + 15] }
    if {$etm(prog_select) != $etmMode(ProgPredefinedMesh)} {
      for {set i 0} {$i <= $last} {incr i} {
        if !$i {
          set fr [frame $c.win$n]
          $c create window 0 [expr $n * 20] -window $fr -anchor nw
          label $fr.label1$n -text "#" -width 5 -anchor w -bg white
          label $fr.label2$n -text "Subface type(s)" -width $len -anchor w -bg white
          label $fr.label3$n -text "Domain(s)" -width 15 -anchor w -bg white
          etm_PackWidget $c.win$n left [list label1$n label2$n label3$n ]
          if $abs_label {
            label $fr.label4$n -text "Distance" -width 8 -anchor w -bg white
            label $fr.label5$n -text "# of nodes" -width 10 -anchor w -bg white
            etm_PackWidget $c.win$n left [list label4$n label5$n]
          }
          if $coeff_label {
            label $fr.label6$n -text "Hold cell height" -width 16 -anchor w -bg white
            etm_PackWidget $c.win$n left [list label6$n]
          }
          if $grid_label {
            label $fr.label7$n -text "Perpendicular/Other" -width 20 -anchor w -bg white
            etm_PackWidget $c.win$n left [list label7$n]
          }
          incr n
          continue
        }
        if {[info exists etmRelaxSubface($i)] || \
            ([info exists etm(sf,$i,abs_dist_bnd)] && $etm(sf,$i,abs_dist_bnd) != "-1") || \
            ([info exists etm(sf,$i,relaxcoeff)] && $etm(sf,$i,relaxcoeff))} {
          set fr [frame $c.win$n]
          $c create window 0 [expr $n * 20] -window $fr -anchor nw
          set ent $i
          label $fr.ent$n -text "$ent" -width 5 -anchor w -bg white
          etm_PackWidget $c.win$n left [list ent$n]
          set dinfo [ic_str_get_topo_info subface $ent 1]
          set dnum ""
          foreach ti $dinfo {
            append dnum "DOM[lindex $ti 4] "
          }
          if [info exists etmRelaxSubface($i)] {
            if [lindex $etmRelaxSubface($i) 1] {
              set relax "Relaxation"
            } else {
              set relax "Non-relaxation"
            }
          } else {
            set relax ""
          }
          if [info exists etm(sf,$i,abs_dist_bnd)] {
            set abs $etm(sf,$i,abs_dist_bnd)
            set nabs $etm(sf,$i,n_points_abs_dist_bnd)           
          } else {
            set abs -1.0
            set nabs -1
          }
          if {$abs != -1} {
            if {$relax == ""} {
              append relax "Blade boundary"
            } else {
              append relax " / Blade boundary"
            }
          }
          if [info exists etm(sf,$i,relaxcoeff)] {
            set coeff $etm(sf,$i,relaxcoeff)
          } else {
            set coeff 0
          }
          if [info exists etm(sf,$i,grid_exp_rate_subf_perp)] {
            set gridp $etm(sf,$i,grid_exp_rate_subf_perp)
            set grido $etm(sf,$i,grid_exp_rate_subf_1)
          } else {
            set gridp -1
            set grido -1
          }
          if {$coeff != 0} {
            if {$relax == ""} {
              append relax "Hold cell height"
            } else {
              append relax " / Hold cell height"
            }
          }
          label $fr.relax$n -text "$relax" -width $len -anchor w -bg white
          etm_PackWidget $c.win$n left [list relax$n]
          label $fr.dnum$n -text "$dnum" -width 15 -anchor w -bg white
          etm_PackWidget $c.win$n left [list dnum$n]
          if $abs_label {
            label $fr.abs$n -text "$abs" -width 8 -anchor w -bg white
            etm_PackWidget $c.win$n left [list abs$n]
            label $fr.nabs$n -text "$nabs" -width 10 -anchor w -bg white
            etm_PackWidget $c.win$n left [list nabs$n]
          }
          if $coeff_label {
            label $fr.coeff$n -text "$coeff" -width 16 -anchor w -bg white
            etm_PackWidget $c.win$n left [list coeff$n]
            label $fr.grid$n -text "$gridp / $grido" -width 16 -anchor w -bg white
            etm_PackWidget $c.win$n left [list grid$n]
          }           
          incr n
        }
      }
    } else {
      for {set i 1} {$i <= $last} {incr i} {
        foreach item $etm(BaseSubfacesNo) {
          if {$item == $i} { set tmp($i) 1 }
        }    
      }
      for {set i 0} {$i <= $last} {incr i} {
        if !$i {
          set fr [frame $c.win$n]
          $c create window 0 [expr $n * 20] -window $fr -anchor nw
          label $fr.label1$n -text "#" -width 5 -anchor w -bg white
          label $fr.label2$n -text "Subface type" -width 20 -anchor w -bg white
          label $fr.label3$n -text "Domain" -anchor w -bg white
          etm_PackWidget $c.win$n left [list label1$n label2$n label3$n]
          incr n
          continue
        }
        if [info exists tmp($i)] {
          set fr [frame $c.win$n]
          $c create window 0 [expr $n * 20] -window $fr -anchor nw
          set ent $i
          label $fr.ent$n -text "$ent" -width 5 -anchor w -bg white
          etm_PackWidget $c.win$n left [list ent$n]
          set dinfo [ic_str_get_topo_info subface $ent 1]
          set dnum ""
          foreach ti $dinfo {
            append dnum "DOM[lindex $ti 4] "
          }
          label $fr.base$n -text "predefined base" -width 20 -anchor w -bg white
          etm_PackWidget $c.win$n left [list base$n]
          label $fr.dnum$n -text "$dnum" -width 22 -anchor w -bg white
          etm_PackWidget $c.win$n left [list dnum$n]
          incr n
        }
      }      
    }
    set end $n
  } elseif {$type == "edge"} {
    for {set i 0} {$i <= $last} {incr i} {   
      if !$i {
        set fr [frame $c.win$n]
        $c create window 0 [expr $n * 20] -window $fr -anchor nw
        label $fr.label1$n -text "#" -width 5 -anchor w -bg white
        label $fr.label2$n -text "Edge type(s)" -width 22 -anchor w -bg white
        etm_PackWidget $c.win$n left [list label1$n label2$n]
        incr n
        continue
      }
      if {[info exists etmEdgeAttr($i)] || [info exists etmEdgeGlobal($i)] || \
          [info exists tmp($i)]} {
        set fr [frame $c.win$n]
        $c create window 0 [expr $n * 20] -window $fr -anchor nw
        label $fr.ent$n -text "$i" -width 5 -anchor w -bg white
        etm_PackWidget $c.win$n left [list ent$n]
        if [info exists etmEdgeAttr($i)] {
          if {[lindex $etmEdgeAttr($i) 1] == "1"} {
            set val "fixed distribution"
          } elseif {[lindex $etmEdgeAttr($i) 1] == "2"} {
            set val "fixed"
          } elseif {[lindex $etmEdgeAttr($i) 1] == "3"} {
            set val "fixed + fixed distribution"
          } else {
            set val "release distribution"
          }
          set len [expr [string length $val] + 1]
          label $fr.val$n -text "$val" -width $len -anchor w -bg white
          etm_PackWidget $c.win$n left [list val$n]
        }
        if [info exists etmEdgeGlobal($i)] {
          label $fr.global$n -text "global" -width 8 -anchor w -bg white
          etm_PackWidget $c.win$n left [list global$n]
        }
        if [info exists tmp($i)] {
          label $fr.violate$n -text "violate geometry" -width 22 -anchor w -bg white
          etm_PackWidget $c.win$n left [list violate$n]
        }
        incr n
      }
    }
    set end $n
  } elseif {$type == "zone"} {
    for {set i 0} {$i <= $last} {incr i} {
      if !$i {
        set fr [frame $c.win$n]
        $c create window 0 [expr $n * 20] -window $fr -anchor nw
        label $fr.label1$n -text "#" -width 7 -anchor w -bg white
        label $fr.label2$n -text "IJK zone type" -width 15 -anchor w -bg white
        etm_PackWidget $c.win$n left [list label1$n label2$n]
        foreach mm {"i min" "j min" "k min" "i max" "j max" "k max"} {
          set mm2 [string replace $mm 1 1 ""]
          label $fr.label3$mm2 -text "$mm" -width 5 -anchor w -bg white
          etm_PackWidget $c.win$n left [list label3$mm2 ]
        }
        incr n
        continue
      }
      foreach item [array names etmRelaxZone $i,*] {
        set fr [frame $c.win$n]
        $c create window 0 [expr $n * 20] -window $fr -anchor nw
        set ent "DOM$i"
        label $fr.ent$n -text "$ent" -width 7 -anchor w -bg white
        etm_PackWidget $c.win$n left [list ent$n]
        if [lindex $etmRelaxZone($item) 3] {
          set relax "Relaxation"
        } else {
          set relax "Non-relaxation"
        }        
        label $fr.relax$n -text "$relax" -width 15 -anchor w -bg white
        etm_PackWidget $c.win$n left [list relax$n]
        set min [lindex $etmRelaxZone($item) 1]
        set max [lindex $etmRelaxZone($item) 2]
        set imin "[format %5s [lindex $min 0]]"
        set jmin "[format %5s [lindex $min 1]]"
        set kmin "[format %5s [lindex $min 2]]"
        set imax "[format %5s [lindex $max 0]]"
        set jmax "[format %5s [lindex $max 1]]"
        set kmax "[format %5s [lindex $max 2]]"
        label $fr.imin$n -text "$imin" -anchor w -bg white -width 5
        label $fr.jmin$n -text "$jmin" -anchor w -bg white -width 5
        label $fr.kmin$n -text "$kmin" -anchor w -bg white -width 5
        etm_PackWidget $c.win$n left [list imin$n jmin$n kmin$n]
        label $fr.imax$n -text "$imax" -anchor w -bg white -width 5
        label $fr.jmax$n -text "$jmax" -anchor w -bg white -width 5
        label $fr.kmax$n -text "$kmax" -anchor w -bg white -width 5
        etm_PackWidget $c.win$n left [list imax$n jmax$n kmax$n]
        incr n
      }
    }
    set end $n
  } elseif {$type == "vertex"} {
    if [info exists etmList(VertexLayer)] {
      for {set i 1} {$i <= $last} {incr i} {
        foreach item $etmList(VertexLayer) {
          if {[lindex $item 0] == $i} {
            if {([lindex $item 1] != -1) || ([lindex $item 2] != -1)} {
              set tmp($i) [list [lindex $item 1] [lindex $item 2]]
            }
          }
        }    
      }
    }
    for {set i 0} {$i <= $last} {incr i} {
      if !$i {
        set fr [frame $c.win$n]
        $c create window 0 [expr $n * 20] -window $fr -anchor nw
        label $fr.label1$n -text "#" -width 5 -anchor w -bg white
        label $fr.label2$n -text "Vertex type(s)" -width 14 -anchor w -bg white
        if [info exists tmp] {
          label $fr.label3$n -text "Distance" -width 8 -anchor w -bg white
          etm_PackWidget $c.win$n left [list label1$n label2$n label3$n]  
        } else {
          etm_PackWidget $c.win$n left [list label1$n label2$n]
        }
        incr n
        continue
      }
      if {[info exists etmVertexGlobal($i)] || [info exists tmp($i)]} {
        set fr [frame $c.win$n]
        $c create window 0 [expr $n * 20] -window $fr -anchor nw
        label $fr.ent$n -text "$i" -width 5 -anchor w -bg white
        etm_PackWidget $c.win$n left [list ent$n]
        set val ""
        if [info exists etmVertexGlobal($i)] {
          append val "global"
        }
        if [info exists tmp($i)] {
          if {$val != ""} {
            append val " / layer"
          } else {
            append val "layer"
          }
        }
        label $fr.types$n -text "$val" -width 14 -anchor w -bg white
        etm_PackWidget $c.win$n left [list types$n]
        if [info exists tmp($i)] {  
          set dist [lindex $tmp($i) 0]
          set angle [lindex $tmp($i) 1]
          label $fr.dist$n -text "$dist" -width 8 -anchor w -bg white
          etm_PackWidget $c.win$n left [list dist$n]
        }
        incr n
      }
    }
    set end $n
  }
  if $etmSmoother(2D) {
    set add 400
  } else {
    set add 1200
  }
  set sh [expr 20 * $end]
  set rw [expr [winfo reqwidth $c] + $add]
  $c configure -scrollregion "0 0 $rw $sh"
  
  if {$n == "1"} {
    mess "No ${type} selected.\n"
    etm_ClearSelectedEntities all
  }
}

proc etm_ClearSelectedEntities {what} {
global etm
  
  set c $etm(Main,Canvas)
  if {$what == "all"} {  
    foreach item [winfo children $c] { 
      top_destroy $item
    }
    if [info exists etm(Entities)] {
      unset etm(Entities)
    }
  } else {
    if [info exists etm(Entities)] { 
      if {"$what" == "$etm(Entities)"} {
        foreach item [winfo children $c] {
          top_destroy $item
        }
        unset etm(Entities)
      }
    }    
  }
}

proc etm_ProgSelect {} {
global etm
  
  etm_Perform $etm(prog_select)
}

proc etm_SelectbyWhat {what which label} {
global tmp

  if {$which == "VertexLayer"} {
    global etmList
    set available 1
    if {![info exists etmList(SmoothDir)] || $etmList(SmoothDir) == ""} {
      set available 0
    } elseif {[lsearch $etmList(SmoothDir) 0] >= 0} {
      set available 0
    }
    if !$available {
      mess "Only available if \"Parameters->Plane->Plane smoothing method\"\
        is set to I, J or K.\n" red
      return
    }
  }
  
  set buttons {
    {"Apply" "etm_ApplySelectbyWhat"}
    {"Cancel" "top_destroy .selectwhat"}
  }
  
  set tmp(select) Select
  set tmp(what) $what
  set tmp(which) $which
  set win .selectwhat
  if [winfo exists $win] { top_destroy $win }
  set w [form_init $win "Select" "" $buttons] 
  if { $w != "" } {
    set row 1
    form_frame $w.1 ridge 3 "0 0 -pady 3"
    form_label $w.1.1 "Select $label $what" "$row 0 -padx 3 -pady 3"
    incr row
    form_frame $w.2 ridge 3 "1 0 -pady 3"
    form_radiobutton $w.2.1 "Select on screen" tmp(select) Select "0 0" "" ""
    if {$what == "edge" || $what == "domain" || $what == "vertex"} {
      form_radiobutton $w.2.2 "All" tmp(select) All "1 0" "" ""
    }
    if {$what == "subface" && ($which == "RelaxationSubface" || \
    			       $which == "NonRelaxationSubface" || \
    			       $which == "CoefficientsSubface3D") || \
    			       $which == "NonCoefficientsSubface3D"} {
      form_radiobutton $w.2.3 "All Blockinterfaces" tmp(select) Blockinterfaces "2 0" "" ""
    }
    if {$what == "subface" && ($which == "RelaxationSubface" || \
    			       $which == "NonRelaxationSubface" || \
    			       $which == "CoefficientsSubface3D" || \
    			       $which == "NonCoefficientsSubface3D" || \
    			       $which == "BladeBoundary")} {    
      form_radiobutton $w.2.4 "All Boundaries" tmp(select) Boundaries "3 0" "" ""
    }
    if {$what == "subface" && ($which == "CoefficientsSubface3D" || \
                               $which == "NonCoefficientsSubface3D" || \
   			       $which == "BladeBoundary") } {
      form_radiobutton $w.2.5 "By Domains..." tmp(select) Domains "4 0" "" ""
    }
    if {($what == "subface" || $what == "edge" || $what == "domain" || $what == "vertex") && \
    	($which != "EdgeViolate")} {
      form_radiobutton $w.2.6 "By Families..." tmp(select) Families "5 0" "" ""
    }
    if {$what == "domain"} {
      form_radiobutton $w.2.7 "By Number..." tmp(select) ByNumber "6 0" "" ""
    }
    if {$what != "domain" && ($which != "CoefficientsSubface3D" && \
                              $which != "NonCoefficientsSubface3D" && \
                              $which != "BladeBoundary" && \
                              $which != "EdgeViolate" && \
                              $which != "NonEdgeBunching")} {
      form_radiobutton $w.2.8 "Deselect" tmp(select) Deselect "7 0" "" ""
    }
    form_finish +400+400 1 0
  }
}

proc etm_ApplySelectbyWhat {} {
global tmp etm

  top_destroy .selectwhat
  if ![info exists etm(overall_visible,$tmp(what))] {
    busy 1
    disp_change_overall_visible $tmp(what)
    set etm(overall_visible,$tmp(what)) 1
    busy 0
  }
  if {$tmp(which) == "CoefficientsSubface3D" && $tmp(select) == "Domains"} {
    etm_RelaxationCoefficients 3D outer 1
  } elseif {$tmp(which) == "NonCoefficientsSubface3D" && $tmp(select) == "Domains"} {
    etm_RelaxationCoefficients 3D outer 0
  } elseif {$tmp(which) == "BladeBoundary" && $tmp(select) == "Domains"} {
    etm_BladeBoundaryByDomain
  } elseif {$tmp(what) == "domain" && $tmp(select) == "ByNumber"} {
    etm_SelectDomainsByNumber $tmp(which)
  } else {
    etm_SelectObjects $tmp(what) $tmp(select) $tmp(which)
  }
  if [info exists etm(Entities)] {
    if {"$tmp(what)" == "$etm(Entities)"} {
      etm_ListSelectedEntities $etm(Entities)
    } elseif {"$tmp(which)" == "NonCoefficientsSubface3D"} {
      if {"subface" == "$etm(Entities)"} {
        etm_ListSelectedEntities $etm(Entities)
      }
    }
  }
}

proc etm_SelectDomainsByNumber {type} {
global etmList etmFlag tmp

  if [winfo exists .dombynumber] {top_destroy .dombynumber}
  set buttons {
    {accept}
  }
  set height 20
  set last [ic_str_num_entities domain]
  for { set i 0 } { $i < $last } { incr i } {
    set tmp(last,$i) $etmFlag($i)
  }
  if {$type == "NonRelaxationDomain"} {
    set label Non-relaxation
  } elseif {$type == "RelaxationDomain"} {
    set label Relaxation
  }
  set list $etmList(Domains)
  disp_set_visible domain 1 
  set w [form_init .dombynumber "$label domains by number" "" $buttons]
  if {$w != ""} {
    form_frame $w.1 ridge 3 "0 0 -pady 3" 
    set mc [form_canvas $w.1.c 200x110 sunken 3 "0 0" 0 1]
    for {set i 0} {$i < $last} {incr i} {
      form_frame $mc.win$i flat 0 "[expr $i + 1] 0"; set fr $mc.win$i
      $mc create window 0 [expr $i * $height] -window $fr -anchor nw
      set name [lindex [lindex $list $i] 1]
      if {$type == "NonRelaxationDomain"} {
        if $etmFlag($i) {
          set tmp(flag,$i) 0
        } else {
          set tmp(flag,$i) 1
        }
      } elseif {$type == "RelaxationDomain"} {
        set tmp(flag,$i) $etmFlag($i)
      }
      set cmd "etm_SelectDomainsByNumberShow $type $i"
      form_checkbutton $fr.name$i "$name" tmp(flag,$i) "$i 0" "" "$cmd"
      $fr.name$i configure -width 20
    }
    form_finish +400+400 1 0
  }  
  set sh [expr $height * $last]
  set rw [winfo reqwidth $mc]
  $mc configure -width 200 -scrollregion "0 0 $rw $sh"

  if ![form_wait .dombynumber] { form_kill .dombynumber }
     
  disp_set_visible domain 0
  if {$type == "NonRelaxationDomain"} {
    set on 0
  } elseif {$type == "RelaxationDomain"} {
    set on 1
  }
  for { set i 0 } { $i < $last } { incr i } {
    if {$type == "NonRelaxationDomain"} {
      if $tmp(flag,$i) {
        set etmFlag($i) 0
      } else {
        set etmFlag($i) 1
      }
    } elseif {$type == "RelaxationDomain"} {
      if $tmp(flag,$i) {
        set etmFlag($i) 1
      } else {
        set etmFlag($i) 0
      }
    }
    unset tmp(last,$i)
    unset tmp(flag,$i)
  }
  disp_set_visible domain 1
}

proc etm_SelectDomainsByNumberShow {type i} {
global tmp etmColors

  if {$type == "NonRelaxationDomain"} {
    if $tmp(flag,$i) {
      set on 0
    } else {
      set on 1
    }
    set type RelaxationDomain
  } elseif {$type == "RelaxationDomain"} {
    if $tmp(flag,$i) {
      set on 1
    } else {
      set on 0
    }
  }  
  etm_ShowOneImage domain $type [expr $i + 1] $on $etmColors($type)
  disp_set_visible domain 1
}

proc etm_UnselectedDomainsSingle {} {
global etmList etmParam etmMethod

  if [winfo exists .unseldom] {top_destroy .unseldom}  
  set buttons {
    {accept}
    {cancel}
  }
  set height 20
  set last [ic_str_num_entities domain]
  set list $etmList(Domains)
  set w [form_init .unseldom "Unselected domain" "" $buttons]
  if {$w != ""} {
    form_frame $w.1 ridge 3 "0 0 -pady 3"
    set mc [form_canvas $w.1.c 300x100 sunken 3 "0 0" 0 1]
    for {set i 0} {$i < $last} {incr i} {
      form_frame $mc.win$i flat 0 "[expr $i + 1] 0"; set fr $mc.win$i
      $mc create window 0 [expr $i * $height] -window $fr -anchor nw
      set name [lindex [lindex $list $i] 1]
      if ![info exists etmParam(Unselected,$i)] {
        set etmParam(Unselected,$i) "Deformation"
      }
      form_label $fr.name$i "$name" "$i 0"
      form_menubutton $fr.method3d$i "$etmParam(Unselected,$i)" $fr.method3d$i.m "$i 1"
      $fr.method3d$i configure -width 30 -textvariable etmParam(Unselected,$i)
      menu $fr.method3d$i.m -tearoff 0; set m3 $fr.method3d$i.m
      foreach v $etmMethod(3D) {
        if {[string match "Sorenson *" $v ]} {
          set com "etm_ShowHybridWin \"$v\" $i 4"
          $m3 add command -label "Sorenson Hybrid..." -command "$com"
        } else {      
          if {[string match "Hilgenstock *" $v] } {
            set com "etm_ShowHybridWin \"$v\" $i 4"
            $m3 add command -label "Hilgenstock Hybrid..." -command "$com"
          } else {      
            $m3 add radiobutton -label $v -variable etmParam(Unselected,$i) -value $v
          }
        }
      }
      $m3 add radiobutton -label "None" -variable etmParam(Unselected,$i) -value "None"
      $m3 add radiobutton -label "Deformation" -variable etmParam(Unselected,$i) -value "Deformation"
    }
    form_finish +400+400 1 0
  }
  set sh [expr $height * $last]
  set rw [winfo reqwidth $mc]
  $mc configure -width 400 -scrollregion "0 0 $rw $sh"
  if ![form_wait .unseldom] {
    for {set i 0} {$i < [ic_str_num_entities domain]} {incr i} {
      set etmParam(Unselected,$i) "Deformation"
    }    
  }
  top_destroy .unseldom
}

proc etm_UnselectedDomainsAll {} {
global etmMode etmParam etm etmMethod
  
  if [winfo exists .unseldom] {top_destroy .unseldom}
  if ![info exists etm(varUnselDom)] {
    set etm(varUnselDom) $etmMode(SmoothDeformation)
  }
  set buttons {
    {accept}
    {cancel}
  }
  set w [form_init .unseldom "Unselected domains" "" $buttons] 
  if { $w != "" } {
    set row 1
    form_frame $w.1 ridge 3 "0 0 -pady 3"
    form_label $w.1.1 "Choose method for all domains" "$row 0 -padx 3 -pady 3"
    form_frame $w.2 ridge 3 "1 0 -pady 3"
    foreach {mode text} \
    	{SmoothThomasMiddlecoff "Thomas & Middlecoff" \
    	 SmoothLaplace "Laplace" \
    	 SmoothInterpolation "Interpolation" \
    	 SmoothSor_ThM "Sorenson - Thomas & Middlecoff" \
    	 SmoothSor_Lap "Sorenson - Laplace" \
    	 SmoothHilgenstock_ThM "Hilgenstock - Thomas & Middlecoff" \
    	 SmoothHilgenst "Hilgenstock - Laplace" \
    	 SmoothNone "None" \
    	 SmoothDeformation "Deformation"} {
      form_radiobutton $w.2.$row "$text" etm(varUnselDom) $etmMode($mode) "$row 0" "" ""
      incr row
    }
    form_finish +400+400 1 0
  } 
  if [form_wait .unseldom] {
    foreach item [array names etmMethod] {
      if {$etmMethod($item) == $etm(varUnselDom)} {
        set m $item                                                                       
        break
      } 
    }
    for {set i 0} {$i < [ic_str_num_entities domain]} {incr i} {
      set etmParam(Unselected,$i) $m
    }
  }
  top_destroy .unseldom
}

proc etm_PackWidget { win side list } {
  
  set x 1
  foreach item $list {
    switch $side {
      left {
	pack append $win $win.$item { left fill expand }
      }
      leftNoExpand {
        pack append $win $win.$item { left fill }
      }
      top {
      	pack append $win $win.$item { top fill expand }
      }
      leftLast {
	if { $x == [ llength $list ] } {
	  pack append $win $win.$item { left fill expand }
	} else {
	  pack append $win $win.$item { left fill }
	}
	incr x
      }
      leftFirst {
	if { $x == 1 } {
	  pack append $win $win.$item { left fill expand }
	} else {
	  pack append $win $win.$item { left fill }
	}
	incr x
      }
      topLast {
	if { $x == [ llength $list ] } {
	  pack append $win $win.$item { top fill expand }
        } else {
	  pack append $win $win.$item { top fill }
        }
	incr x
      } 
    }
  }
}

proc etm_SetAllMethods_2D { which } {
global etmParam

  if { [ string match "Hilgenstock *" $which ] || \
       [ string match "Sorenson *" $which ] } {    
    if { [ etm_ShowHybridWin $which 0 2 ] == "cancel" } {
      return
    }
    set which $etmParam(2D,0)
  }

  foreach f [ array names etmParam 2D* ] { 
    set item [ lindex [ split $f , ] 1 ]
    set etmParam(2D,$item) $which
    if [ info exists etmParam(Mix,$item)] { 
      unset etmParam(Mix,$item)
    }
  }
  if [winfo exists .smpara.main.3.2] {
    .smpara.main.3.2 configure -text $which
  }
}

proc etm_SetOneMethod_2D { win } {
global etmParam

 set num [ string range $win [ string last "." $win ] end ]
 regsub ".method" "$num" "" num
 if [ info exists etmParam(Mix,$num) ] {
   unset etmParam(Mix,$num)
 } 
}

proc etm_SetAllMethods_3D { which } {
global etmParam etmMode

  if { [ string match "Hilgenstock *" $which ] || \
       [ string match "Sorenson *" $which ] } {
     if { [ etm_ShowHybridWin $which 0 3 ] == "cancel" } {
       return
     }
     set which $etmParam(3D,0)
  }
  foreach f [ array names etmParam 3D* ] { 
    set item [ lindex [ split $f , ] 1 ]
    set etmParam(3D,$item) $which
  }
  if [winfo exists .smpara.main.3.2] {
    .smpara.main.3.2 configure -text $which
  }
}

proc etm_SetAllFaceMethods_3D { which } {
global etmParam etmMethod

  if {[string match "Hilgenstock *" $which] || \
      [string match "Sorenson *" $which]} {    
    if {[etm_ShowHybridWin $which 0 2] == "cancel"} {
      return
    }
    set which $etmParam(2D,0)
  }
  set m $which
  for {set i 0} {$i < [ic_str_num_entities domain]} {incr i} {
    set etmParam(2D,$i) $which
    set m $etmMethod($etmParam(2D,$i))
    set etmParam(Mix,$i) [list $m $m $m $m $m $m]
  }
  if [winfo exists .smpara.main.4.2] {
    .smpara.main.4.2 configure -text $which
  }
}

proc etm_Settings { what } { 
global env etmSetting file_name

  set etmSetting(Extension) "med"
  set etmSetting(File) "Setting.$etmSetting(Extension)"
  set etmSetting(What) $what
  set etmSetting(Directory) $file_name(mesh_dir)/settings
  set etmSetting(Overwrite) 0
  set etmSetting(Header) "Settings Management for Smoothing and Predefined Mesh: Med"
  if [info exists env(USER)] {
    set etmSetting(User) $env(USER)
  } else {
    set etmSetting(User) Dummy
  }
  if ![file exists $etmSetting(Directory)] {
    file mkdir $etmSetting(Directory)
  }
  if {[file exists $etmSetting(Directory)]  && \
      [file isdirectory $etmSetting(Directory)]} {
    if {$what == "Save"} {
      set use_file $etmSetting(Directory)/$etmSetting(File)
    } else {
      set use_file $etmSetting(Directory)
    } 
  } else {
    if {$what == "Save"} {
      set use_file $file_name(mesh_dir)/$etmSetting(File)
    } else {
      set use_file $file_name(mesh_dir)
    }
    set etmSetting(Directory) $file_name(mesh_dir)
  }
  set file [file_selection -title "$etmSetting(What) Setting" -default $use_file -new_ok 1]
  if {$file == ""} return
  set etmSetting(File) $file
  etm_DoneSettings
}

proc etm_DoneSettings {} {
global etmSetting etm

  if {[string length $etmSetting(File)] == "0"} {
    etm_ShowMessage ERROR "No file name selected.\nSelect a valid file name."
    return
  }
  if {$etmSetting(What) == "Load"} {
    if ![file exists $etmSetting(File)] {
      etm_ShowMessage ERROR "File <$etmSetting(File)> does not \
      	exists.\nSelect another one."
      return
    } 
    if ![file isfile $etmSetting(File)]  {
      etm_ShowMessage ERROR "File <$etmSetting(File)> is not a valid \
      	filename.\nSelect another one."
      return
    }
    set f [open $etmSetting(File) r]
    set line [gets $f]
    close $f
    if ![ string match "$etmSetting(Header)" $line ] {
      etm_ShowMessage ERROR "File <$etmSetting(File)> contains no \
      	settings.\nSelect another one."
      return        
    } else {
      set f [open $etmSetting(File) r]
      etm_LoadSettings $f
      close $f
      if ![info exists etmSetting(error)] {
        mess "Settings loaded from file <$etmSetting(File)>.\n"
        if [info exists etm(Entities)] {
          etm_ListSelectedEntities $etm(Entities)
        }
      } else {
        unset etmSetting(error)
      }
    }
  } elseif { $etmSetting(What) == "Save" } {  
     if [file exists $etmSetting(File)] {
       set etmSetting(Overwrite) [ etm_ShowQuestion WARNING "Overwrite \
       	existing\nfile <$etmSetting(File)> ?" ]
       if !$etmSetting(Overwrite) {
         return
       }
     }
     set f [open $etmSetting(File) w]
     etm_SaveSettings $f
     close $f
     mess "Settings saved as file <$etmSetting(File)>.\n"
  }
}

proc etm_SaveSettings { f } {
global etmSetting etmList etm etmParam etmEdgeGlobalSave etmRelaxZoneSave

  puts $f "$etmSetting(Header)"
  puts $f "Username: $etmSetting(User)"
  puts $f "Filename: $etmSetting(File)"  
  etm_CreateSmoothLists
  etm_CreateDomainList
  etm_CreateMethodLists
  puts $f "SmoothDomain:"
  puts $f "$etmList(SmoothDomain)"
  puts $f "FaceMethods:"
  puts $f "$etmList(FaceMethods)"
  set n 0
  set len [expr [llength $etmList(FaceMethods)] / 6]
  puts $f "Param2D:"
  puts $f $len
  foreach item $etmList(FaceMethods) {
    puts $f "$etmParam(2D,$n)"
    incr n
    if {$n == $len} { break }
  } 
  puts $f "VolumeMethods:"
  puts $f "$etmList(VolumeMethods)" 
  set n 0
  set len [llength $etmList(VolumeMethods)]
  puts $f "Param3D:"
  puts $f $len
  foreach item $etmList(VolumeMethods) {
    puts $f "$etmParam(3D,$n)"
    incr n
  }
  puts $f "EdgeAttr:"
  puts $f "$etmList(etmEdgeAttr)"
  puts $f "RelaxSubface:"
  puts $f "$etmList(etmRelaxSubface)"
  puts $f "LayerExtensionNo:"
  puts $f "$etmList(etmLayerExtensionNo)"
  puts $f "RelaxZone:"
  puts $f "$etmList(etmRelaxZone)"
  puts $f "ViolGeomZone:"
  puts $f "$etmList(etmViolGeomZone)"
  puts $f "LayerExtensionIJK:"
  puts $f "$etmList(etmLayerExtensionIJK)" 
  puts $f "Region:"
  puts $f "$etmList(etmRegion)"
  puts $f "ViolGeomSubface:"
  puts $f "$etmList(etmViolGeomSubface)"
  puts $f "MeshingLawPar:"
  puts $f "$etmList(etmMeshingLawPar)"
  puts $f "$etm(BaseSubfacesNo)"
  puts $f "first_cell_height:"
  puts $f "$etm(first_cell_height)"
  puts $f "last_cell_height:"
  puts $f "$etm(last_cell_height)"
  puts $f "Niter:"
  puts $f $etm(Niter)
  puts $f "Nsteps:"
  puts $f $etm(Nsteps)
  puts $f "Maxlevel:"
  puts $f $etm(Maxlevel)
  puts $f "Sfit:"
  puts $f $etm(Sfit)
  puts $f "Conditional:"
  puts $f $etm(Conditional)
  puts $f "CheckDet:"
  puts $f $etm(CheckDet)
  puts $f "Damping:"
  puts $f $etm(Damping)
  puts $f "VertexFix:"
  puts $f $etm(VertexFix)
  puts $f "EdgeFreeze:"
  puts $f $etm(EdgeFreeze)
  puts $f "WedgeCheck:"
  puts $f $etm(WedgeCheck)
  puts $f "Multigrid2D:"
  puts $f $etm(Multigrid2D)
  puts $f "ReducedEdge:"
  puts $f $etm(ReducedEdge)
  puts $f "FixFam:"
  puts $f $etm(FixFam)
  puts $f "InnVol:"
  puts $f $etm(InnVol)
  puts $f "NsRel:"
  puts $f $etm(NsRel)
  puts $f "AngleFreezeEdges:"
  puts $f $etm(AngleFreezeEdges)
  puts $f "nItera:"
  puts $f $etm(nItera)
  puts $f "ProjLimit:"
  puts $f $etm(ProjLimit)
  puts $f "InterpolateFaces:"
  puts $f $etm(InterpFaces)
  puts $f "InterpolateVolumes:"
  puts $f $etm(InterpVolumes)
  puts $f "ThresholdDet:"
  puts $f $etm(ThresholdDet)
  puts $f "ThresholdAngle:"
  puts $f $etm(ThresholdAngle)
  puts $f "SubfaceExtend:"
  puts $f $etm(SubfaceExtend)
  puts $f "DirectionVector:"
  puts $f $etm(DirectionVector)
  puts $f "BaseSubfacesNo:"
  puts $f "$etm(BaseSubfacesNo)"
  if [ info exists etmList(SmoothDir) ] {
    puts $f "SmoothDir:"
    puts $f "$etmList(SmoothDir)"
    puts $f "PlaneSmooth:"
    puts $f "$etmList(PlaneSmooth)"
  }
  puts $f "relax_weights_2d:"
  puts $f "$etmList(relax_weights_2d)"
  puts $f "relax_weights_3d:"
  puts $f "$etmList(relax_weights_3d)"
  puts $f "relax_weights_3d_surfaces:"
  set sflist ""  
  foreach item [lsort [array names etm sf,*,relaxcoeff]] {
    if $etm($item) {
      set num [lindex [split $item ,] 1]
      append sflist "$num "
    }
  }
  puts $f "$sflist"
  puts $f "relax_weights_inner_2d:"
  puts $f "$etmList(relax_weights_inner_2d)"
  puts $f "relax_weights_inner_3d:"
  puts $f "$etmList(relax_weights_inner_3d)"
  puts $f "SmoothOnFaces:"
  puts $f "$etm(SmoothOnFaces)"
  puts $f "MinResidual:"
  puts $f "$etm(MinResidual)"
  puts $f "StopResidual:"
  puts $f "$etm(StopResidual)" 
  puts $f "UnselectedMethods:"
  puts $f "$etmList(UnselectedMethods)"
  set n 0
  set len [llength $etmList(UnselectedMethods)]
  puts $f "ParamUnselected:"
  puts $f $len
  foreach item $etmList(UnselectedMethods) {
    puts $f "$etmParam(Unselected,$n)"
    incr n
  }
  if [info exists etm(varUnselDom)] {
    puts $f "varUnselDom:"
    puts $f "$etm(varUnselDom)"    
  }
  if [info exists etmList(etmEdgeGlobal)] {
    puts $f "etmEdgeGlobal:"
    puts $f "$etmList(etmEdgeGlobal)"
  }
  puts $f "mesh_type:"
  if ![info exists etm(mesh_type)] {
    if { [ etm_2d_3d "$max" ] != "0" } {
      set etm(mesh_type) 0
    } else {
      set etm(mesh_type) 2
    }
  }
  puts $f "$etm(mesh_type)" 
  puts $f "n_iter_glb:"
  puts $f "$etm(n_iter_glb)"
  puts $f "n_steps_glb:"
  puts $f "$etm(n_steps_glb)"
  if [info exists etmList(etmVertexGlobal)] {
    puts $f "etmVertexGlobal:"
    puts $f "$etmList(etmVertexGlobal)"
  }
  if [info exists etmList(PlaneNumbers)] {
    puts $f "PlaneNumbers:"
    puts $f "$etmList(PlaneNumbers)"
  }
  puts $f "grid_exp_face:"
  puts $f "$etm(grid_exp_face)"
  puts $f "grid_exp_vol:"
  puts $f "$etm(grid_exp_vol)"
  puts $f "ThresholdAngle:"
  puts $f "$etm(ThresholdAngle)"
  puts $f "ThresholdDet:"
  puts $f "$etm(ThresholdDet)"
  puts $f "GroupBadElem:"
  puts $f "$etm(GroupBadElem)"
  puts $f "TypeImprove:"
  puts $f "$etm(TypeImprove)"
  puts $f "TypePostSm:"
  puts $f "$etm(TypePostSm)"
  if [info exists etm(prog_select)] {
    puts $f "prog_select:"
    puts $f "$etm(prog_select)"
  }
  puts $f "abs_dist_bnd:"
  puts $f "$etm(abs_dist_bnd)"
  puts $f "n_points_abs_dist_bnd:"
  puts $f "$etm(n_points_abs_dist_bnd)"
  puts $f "use_pthreads:"
  puts $f "$etm(use_pthreads)"
  puts $f "abs_dist_subf:"
  puts $f "$etmList(abs_dist_subf)"
  puts $f "n_abs_dist_subf:"
  puts $f "$etmList(n_abs_dist_subf)"
  if [info exists etmList(VertexLayer)] {
    puts $f "VertexLayer:"
    puts $f "$etmList(VertexLayer)"
  }
  etm_CreateGlobalSaveList
  if [info exists etmEdgeGlobalSave] {
    set list ""
    puts $f "etmEdgeGlobalSave:"
    foreach item [array names etmEdgeGlobalSave] {
       append list " $etmEdgeGlobalSave($item)"
    }
    puts $f "$list"
  }
  if [info exists etmRelaxZoneSave] {   
    set list ""
    puts $f "etmRelaxZoneSave:"
    foreach item [array names etmRelaxZoneSave] {
      append list  " $etmRelaxZoneSave($item)"
    }
    puts $f "$list"
  }
  puts $f "relaxation_factor:"
  puts $f "$etm(relaxation_factor)"
  puts $f "use_orthog_position:"
  puts $f "$etm(use_orthog_position)"
  puts $f "use_fract_position:"
  puts $f "$etm(use_fract_position)"  
  puts $f "grid_exp_rate_subf_perp:"
  puts $f "$etmList(grid_exp_rate_subf_perp)"
  puts $f "grid_exp_rate_subf_perp_surfaces:"
  set sflist ""
  foreach item [lsort [array names etm sf,*,grid_exp_rate_subf_perp]] {
    set num [lindex [split $item ,] 1]
    append sflist "$num $etm($item) "
  }
  puts $f "$sflist"
  puts $f "grid_exp_rate_subf_1:"
  puts $f "$etmList(grid_exp_rate_subf_1)"
  puts $f "grid_exp_rate_subf_1_surfaces:"
  set sflist ""
  foreach item [lsort [array names etm sf,*,grid_exp_rate_subf_1]] {
    set num [lindex [split $item ,] 1]
    append sflist "$num $etm($item) "
  }
  puts $f "$sflist"
}

proc etm_LoadSettings { f } {
global etmSetting etmList etm etmFlag etmMethod etmParam etmMode etmSmoother 
global etmImageZone etmColors etmTemp etmVar etmRelaxCoeff

  etm_DefaultParameter
  etm_DefaultParameterPost
  etm_UnsetSelectionsArrays

  if ![info exists etm(batch)] {
    foreach item {domain subface edge vertex} {
      if ![info exists etm(overall_visible,$item)] {
         disp_change_overall_visible $item
        set etm(overall_visible,$item) 1
      }
    }
    etm_ClearSelections
  }
  while { ![eof $f] } {
    set line [ gets $f ]
    switch $line {
      SmoothDomain: {
        set etmList(SmoothDomain) [gets $f]
        set i 0
        foreach item $etmList(SmoothDomain) {
          set etmFlag($i) $item
          if ![info exists etm(batch)] {
            set number [expr $i + 1]
            if $etmFlag($i) {
              etm_ShowOneImage domain RelaxationDomain $number 1 $etmColors(RelaxationDomain)
            }
          }
          incr i
        }
        if [info exists etm(batch)] { continue }
        set dom_load [llength [ic_str_list_entities domain]]
        set dom_set [llength $etmList(SmoothDomain)]
        if {$dom_load != $dom_set} {
          mess "Number of domains ($dom_set) in settings file <$etmSetting(File)> \
          is different from number of domains ($dom_load) loaded. \
          Unable to load settings file.\n" red
          set etmSetting(error) 1
          return
        }
      } 
      FaceMethods: {
        set line [gets $f]
        set etmList(FaceMethods) $line
        if [info exists etm(batch)] { continue }
        set i 0
        set n 0
        foreach item $line {
          set itemMix($i) $item
          incr i
          if { $i == "6" } {
            set isMixed 0
            for { set x 0 } { $x < 6 } { incr x } { 
              if { $item == $itemMix($x) } {
                set isMixed 0
              } else {
                set isMixed 1
                break
              }
            }
            if $isMixed {
              for { set x 0 } { $x < 6 } { incr x } {     
                lappend etmParam(Mix,$n) $itemMix($x)
              }     
            }
            incr n
            set i 0
          }
        }
      }
      Param2D:  {
        set len [gets $f]
        for { set i 0 } { $i < $len } { incr i } {
          set etmParam(2D,$i) [gets $f]
        }
      }  
      VolumeMethods:  {
        set line [ gets $f ]
        set etmList(VolumeMethods) $line
      }  
      Param3D:  {
        set len [gets $f]
        for { set i 0 } { $i < $len } { incr i } {
          set etmParam(3D,$i) [gets $f]
        }
      }
      EdgeAttr:  {
        set line [gets $f]
        if [info exists etm(batch)] {
          set etmList(etmEdgeAttr) $line
          continue
        }
        foreach {number mode} $line {
          if {$mode == "1"} { set type EdgeBunching }
          if {$mode == "2"} { set type EdgeFrozen }
          if {$mode == "3"} { set type EdgeBunchingFrozen }
          etm_ShowEdgeAttr $number $type 1
        }      
      } 
      RelaxSubface: {
        set line [gets $f]
        foreach {subface relax} $line {
          if {$relax == "0"} { set type NonRelaxationSubface }
          if {$relax == "1"} { set type RelaxationSubface }
          etm_ShowRelaxSubface $subface $type 1
        }
      } 
      LayerExtensionNo: {
        set line [gets $f]
        if [info exists etm(batch)] {
          set etmList(etmLayerExtensionNo) $line
          continue
        }
        set list {}
        foreach {number mode} $line {
          if {$mode == "0"} { set type SubfaceDefault }
          if {$mode == "1"} { set type SubfaceNeighbor }          
          if {$mode == "2"} { set type SubfaceSymmetric }
          if {$mode == "3"} { set type SubfaceOrthogonal }
          if {$mode == "4"} { set type SubfaceLinear }
          if {$mode == "5"} { set type SubfaceOrtho_Lin }
          if {$mode == "6"} { set type SubfaceSymm_Lin }
          lappend list [list $number $type 1 1]
          set color $etmColors(LayerExtensionSubface)
          etm_ShowOneImage subface LayerExtensionSubface $number 1 $color
        }
        set etmList(TEMP,SubfaceLayers) $list
      } 
      RelaxZone: {
        set line [gets $f]
        foreach {dom imin jmin kmin imax jmax kmax mode} $line {
          set min "$imin $jmin $kmin"
          set max "$imax $jmax $kmax"
          if {$mode == "0"} { set type NonRelaxationZone }
          if {$mode == "1"} { set type RelaxationZone }
          if ![info exists etm(batch)] {
            etm_CreateSubfaceZone $type $dom $min $max
            etm_ConfigureImageZone $etmTemp(Name) 1 $etmColors($type)
          }
          etm_SetRelaxZone 1 $dom $min $max $mode
        }
      } 
      ViolGeomZone: {
        set line [gets $f]
        if [info exists etm(batch)] {
          set etmList(etmViolGeomZone) $line
          continue
        }
        foreach {dom imin jmin kmin imax jmax kmax violate} $line {
          set min "$imin $jmin $kmin"
          set max "$imax $jmax $kmax"
          etm_CreateEdgeZone EdgeViolate $dom $min $max
          etm_ConfigureImageZone $etmTemp(Name) 1 $etmColors(EdgeViolate)
          etm_SetViolGeomZone 1 $dom $min $max $violate
        }
      } 
      LayerExtensionIJK: {
        set etmList(etmLayerExtensionIJK) [gets $f]
      } 
      Region: {
        set etmList(etmRegion) [gets $f]
      } 
      ViolGeomSubface: {
        set etmList(etmViolGeomSubface) [gets $f]
      } 
      MeshingLawPar: {
        set line [gets $f]
        set etmList(etmMeshingLawPar) $line
        set mesh_law [lindex $etmList(etmMeshingLawPar) 0]
        set etmVar(Space1) [lindex $etmList(etmMeshingLawPar) 1]
        set etmVar(Space2) [lindex $etmList(etmMeshingLawPar) 2]
        set etmVar(Space1-2) [lindex $etmList(etmMeshingLawPar) 3]
        set etmVar(Space2-2) [lindex $etmList(etmMeshingLawPar) 4]
        set etmVar(Ratio) [lindex $etmList(etmMeshingLawPar) 5]
        foreach item [array names etmMode MeshLaw*] {
          if {$mesh_law == $etmMode($item)} {
            regsub -all MeshLaw $item "" etmVar(Name,MeshLaw)
            set etmVar(Selected,MeshLaw) $mesh_law
            break
          }
        }        
        if [string match $line ""] {
          continue
        }
        set line [gets $f]
        set etm(BaseSubfacesNo) $line
        if {$etm(BaseSubfacesNo) != ""} {
          set etmVar(SubfaceSelected) 1
        } else {
          set etmVar(SubfaceSelected) 0
        }
        if [info exists etm(batch)] { continue }
        set etmVar(PredefMesh) 1
        set etmList(SubfacePredefMesh) ""
        foreach number $line {
          set col $etmColors(PredefMesh)
          etm_ShowOneImage subface PredefMesh $number 1 $col
          lappend etmList(SubfacePredefMesh) $number
        }
      } 
      first_cell_height: {
        set etm(first_cell_height) [gets $f]
        set etmVar(first_cell_height) $etm(first_cell_height)
      }
      last_cell_height: {
        set etm(last_cell_height) [gets $f]
        set etmVar(last_cell_height) $etm(last_cell_height)
      }      
      Niter: {
        set etm(Niter) [gets $f]
      } 
      Nsteps: {
        set etm(Nsteps) [gets $f]
      } 
      Maxlevel: {
        set etm(Maxlevel) [gets $f]
      } 
      Sfit: {
        set etm(Sfit) [gets $f]
      } 
      Conditional: {
        set etm(Conditional) [gets $f]
      } 
      CheckDet: {
        set etm(CheckDet) [gets $f]
      } 
      Damping: {
        set etm(Damping) [gets $f]
      } 
      VertexFix: {
        set etm(VertexFix) [gets $f]
      } 
      EdgeFreeze: {
        set etm(EdgeFreeze) [gets $f]
      }
      WedgeCheck: {
        set etm(WedgeCheck) [gets $f]
      } 
      Multigrid2D: {
        set etm(Multigrid2D) [gets $f]
      } 
      ReducedEdge: {
        set etm(ReducedEdge) [gets $f]
      } 
      FixFam: {
        set etm(FixFam) [gets $f]
      } 
      InnVol: {
        set etm(InnVol) [gets $f]
      }
      NsRel: {
        set etm(NsRel) [gets $f]
      }
      AngleFreezeEdges: {
        set etm(AngleFreezeEdges) [gets $f]
      }
      nItera: {
        set etm(nItera) [gets $f]
      }
      ProjLimit: {
        set etm(ProjLimit) [gets $f]
      }
      InterpolateFaces: {
        set etm(InterpFaces) [gets $f]
      }
      InterpolateVolumes: {
        set etm(InterpVolumes) [gets $f]
      } 
      ThresholdDet: {
        set etm(ThresholdDet) [gets $f]
      }
      ThresholdAngle: {
        set etm(ThresholdAngle) [gets $f]
      } 
      SubfaceExtend: {
        set etm(SubfaceExtend) [gets $f]
        set etmVar(SubfaceExtend) $etm(SubfaceExtend)
      } 
      DirectionVector: {
        set etm(DirectionVector) [gets $f]
        set etmVar(VectorX) [lindex $etm(DirectionVector) 0]
        set etmVar(VectorY) [lindex $etm(DirectionVector) 1]
        set etmVar(VectorZ) [lindex $etm(DirectionVector) 2]
        if {$etmVar(VectorX) == 0 && $etmVar(VectorY) == 0 && $etmVar(VectorZ) == 0} {
          set etmVar(Vector) 1
        } else {
          set etmVar(Vector) 2
        }
      }
      BaseSubfacesNo: {
        set etm(BaseSubfacesNo) [gets $f]
      }
      SmoothDir: {
        set etmList(SmoothDir) [gets $f]
      }
      PlaneSmooth: {
        set etmList(PlaneSmooth) [gets $f]
      }
      relax_weights_2d: {
        set etmList(relax_weights_2d) [gets $f]
        set i 0
        foreach {aa bb cc dd ee ff} $etmList(relax_weights_2d) {
          if {$aa < 1.0} { set aa 0 }
          if {$bb < 1.0} { set bb 0 }
          if {$cc < 1.0} { set cc 0 }
          if {$dd < 1.0} { set dd 0 }
          if {$ee < 1.0} { set ee 0 }
          if {$ff < 1.0} { set ff 0 }
          set etmList(etmRelaxCoeff,2D,outer,$i) "$aa $bb $cc $dd $ee $ff"
          set etmRelaxCoeff(SET,imin,2D,outer,$i) "$aa"
          set etmRelaxCoeff(SET,imax,2D,outer,$i) "$bb"
          set etmRelaxCoeff(SET,jmin,2D,outer,$i) "$cc"
          set etmRelaxCoeff(SET,jmax,2D,outer,$i) "$dd"
          set etmRelaxCoeff(SET,kmin,2D,outer,$i) "$ee"
          set etmRelaxCoeff(SET,kmax,2D,outer,$i) "$ff"
          incr i
        }
      }
      relax_weights_3d: {
        set etmList(relax_weights_3d) [gets $f]
        set i 0
        foreach {aa bb cc dd ee ff} $etmList(relax_weights_3d) {
          if {$aa < 1.0} { set aa 0 }
          if {$bb < 1.0} { set bb 0 }
          if {$cc < 1.0} { set cc 0 }
          if {$dd < 1.0} { set dd 0 }
          if {$ee < 1.0} { set ee 0 }
          if {$ff < 1.0} { set ff 0 }
          set etmList(etmRelaxCoeff,3D,outer,$i) "$aa $bb $cc $dd $ee $ff"
          set etmRelaxCoeff(SET,imin,3D,outer,$i) "$aa"
          set etmRelaxCoeff(SET,imax,3D,outer,$i) "$bb"
          set etmRelaxCoeff(SET,jmin,3D,outer,$i) "$cc"
          set etmRelaxCoeff(SET,jmax,3D,outer,$i) "$dd"
          set etmRelaxCoeff(SET,kmin,3D,outer,$i) "$ee"
          set etmRelaxCoeff(SET,kmax,3D,outer,$i) "$ff"
          incr i
          if [info exists etm(batch)] { continue }
          foreach item {imin imax jmin jmax kmin kmax} {
            set num [etm_GetSubfaceIJKNumber $i $item]
            if ![info exists tmp(sf,3D,outer,$num)] {
              set etm(sf,$num,relaxcoeff) $etmRelaxCoeff(SET,$item,3D,outer,[expr $i - 1])
              set tmp(sf,3D,outer,$num) 1
            }
          }
        }
      }
      relax_weights_3d_surfaces: {
          if [info exists etm(batch)] { continue }
          set line [gets $f]
          foreach num $line { set etm(sf,$num,relaxcoeff) 1 }
      }
      relax_weights_inner_2d: {
        set etmList(relax_weights_inner_2d) [gets $f]
        set i 0
        foreach {aa bb cc dd ee ff} $etmList(relax_weights_inner_2d) {
          if {$aa < 1.0} { set aa 0 }
          if {$bb < 1.0} { set bb 0 }
          if {$cc < 1.0} { set cc 0 }
          if {$dd < 1.0} { set dd 0 }
          if {$ee < 1.0} { set ee 0 }
          if {$ff < 1.0} { set ff 0 }
          set etmList(etmRelaxCoeff,2D,inner,$i) "$aa $bb $cc $dd $ee $ff"
          set etmRelaxCoeff(SET,imin,2D,inner,$i) "$aa"
          set etmRelaxCoeff(SET,imax,2D,inner,$i) "$bb"
          set etmRelaxCoeff(SET,jmin,2D,inner,$i) "$cc"
          set etmRelaxCoeff(SET,jmax,2D,inner,$i) "$dd"
          set etmRelaxCoeff(SET,kmin,2D,inner,$i) "$ee"
          set etmRelaxCoeff(SET,kmax,2D,inner,$i) "$ff"
          incr i
        }
      }
      relax_weights_inner_3d: {
        set etmList(relax_weights_inner_3d) [gets $f]
        set i 0
        foreach {aa bb cc dd ee ff} $etmList(relax_weights_inner_3d) {
          if {$aa < 1.0} { set aa 0 }
          if {$bb < 1.0} { set bb 0 }
          if {$cc < 1.0} { set cc 0 }
          if {$dd < 1.0} { set dd 0 }
          if {$ee < 1.0} { set ee 0 }
          if {$ff < 1.0} { set ff 0 }
          set etmList(etmRelaxCoeff,3D,inner,$i) "$aa $bb $cc $dd $ee $ff"
          set etmRelaxCoeff(SET,imin,3D,inner,$i) "$aa"
          set etmRelaxCoeff(SET,imax,3D,inner,$i) "$bb"
          set etmRelaxCoeff(SET,jmin,3D,inner,$i) "$cc"
          set etmRelaxCoeff(SET,jmax,3D,inner,$i) "$dd"
          set etmRelaxCoeff(SET,kmin,3D,inner,$i) "$ee"
          set etmRelaxCoeff(SET,kmax,3D,inner,$i) "$ff"
          incr i
        }
      }
      SmoothOnFaces: {
        set etm(SmoothOnFaces) [gets $f]
      }
      MinResidual: {
        set etm(MinResidual) [gets $f]
      }       
      StopResidual: {
        set etm(StopResidual) [gets $f]
      }   
      UnselectedMethods: {
        set etmList(UnselectedMethods) [gets $f]
      }
      ParamUnselected: {
        set len [gets $f]
        for { set i 0 } { $i < $len } { incr i } {
          set etmParam(Unselected,$i) [gets $f]
        }
      }
      varUnselDom:  {
        set etm(varUnselDom) [gets $f]
      }
      etmEdgeGlobal: {
        set line [gets $f]
        foreach number $line {
          etm_ShowEdgeGlobal $number 1
        }
      }
      mesh_type: {
        set etm(mesh_type) [gets $f]
      }
      n_iter_glb: {
        set etm(n_iter_glb) [gets $f]
      }
      n_steps_glb: {
        set etm(n_steps_glb) [gets $f]
      }
      etmVertexGlobal: {
        set line [gets $f]
        foreach number $line {       
          etm_SetVertexGlobal 1 $number vertex
          if ![info exists etm(batch)] {
            etm_ShowOneImage vertex VertexGlobal $number 1 $etmColors(VertexGlobal)
          }
        }
      }
      PlaneNumbers: {
        set etmList(PlaneNumbers) [gets $f]
        if [info exists etm(batch)] { continue }
        if {$etmList(PlaneNumbers) != ""} {
          set len 0
          set diff 0
          for { set dom 0 } { $dom < [llength $etmList(Domains)] } { incr dom } {
            set num [lindex $etmList(PlaneNumbers) $len]
            set start [expr $len + 1]
            set end [expr $len + $num]
            set etm(PlaneNumbers,$dom) [lrange $etmList(PlaneNumbers) $start $end]
            if ![info exists tmp(PlaneNumbers)] {
              set tmp(PlaneNumbers) $etm(PlaneNumbers,$dom)
            } else {
              if {"$tmp(PlaneNumbers)" != "$etm(PlaneNumbers,$dom)"} {
                set diff 1
              }
            }
            set len [expr $end + 1]
          } 
          if !$diff {
            set etm(PlaneNumbers,All) $tmp(PlaneNumbers)
          }      
        }
      } 
      grid_exp_face: {
        set etm(grid_exp_face) [gets $f]
      }
      grid_exp_vol: {
        set etm(grid_exp_vol) [gets $f]
      }  
      ThresholdAngle: {
        set etm(ThresholdAngle) [gets $f]   
      }
      ThresholdDet: {
        set etm(ThresholdDet) [gets $f]
      }
      GroupBadElem: {
        set etm(GroupBadElem) [gets $f]
      }
      TypeImprove: {
        set etm(TypeImprove) [gets $f]
      }
      TypePostSm: {
        set etm(TypePostSm) [gets $f]
      }
      prog_select: {
        set etm(prog_select) [gets $f]
      }
      abs_dist_bnd: {
        set etm(abs_dist_bnd) [gets $f]
      }
      n_points_abs_dist_bnd: {
        set etm(n_points_abs_dist_bnd) [gets $f]
      }
      use_pthreads: {
        set etm(use_pthreads) [gets $f]
      }
      abs_dist_subf: {
        set etmList(abs_dist_subf) [gets $f]
        if [info exists etm(batch)] { continue }
        set pos 0
        for {set i 1} {$i <= [ic_str_num_entities domain]} {incr i} {  
          set diff 0
          foreach item { imin imax jmin jmax kmin kmax } {
            set num [etm_GetSubfaceIJKNumber $i $item]
            set val [lindex $etmList(abs_dist_subf) $pos]
            if ![info exists tmp(abs_dist_subf,$i)] {
              set tmp(abs_dist_subf,$i) $val
            } else {
              if {$tmp(abs_dist_subf,$i) != $val} { set diff 1 }
            }
            set etm(sf,$num,abs_dist_bnd) $val
            incr pos 
          }
          if !$diff { set etm(dom,[expr $i - 1],abs_dist_bnd) $val }
        }
      }
      n_abs_dist_subf: {
        set etmList(n_abs_dist_subf) [gets $f]
        if [info exists etm(batch)] { continue }
        set pos 0
        for {set i 1} {$i <= [ic_str_num_entities domain]} {incr i} {  
          set diff 0
          foreach item { imin imax jmin jmax kmin kmax } {
            set num [etm_GetSubfaceIJKNumber $i $item]
            set val [lindex $etmList(n_abs_dist_subf) $pos]
            if ![info exists tmp(n_abs_dist_subf,$i)] {
              set tmp(n_abs_dist_subf,$i) $val
            } else {
              if {$tmp(n_abs_dist_subf,$i) != $val} { set diff 1 }
            }
            set etm(sf,$num,n_points_abs_dist_bnd) $val
            incr pos 
          }
          if !$diff { set etm(dom,[expr $i - 1],n_points_abs_dist_bnd) $val }
        }
      }
      VertexLayer: {
        set etmList(VertexLayer) [gets $f]
        if [info exists etm(batch)] { continue }
        foreach item $etmList(VertexLayer) {       
          set a [lindex $item 0]
          set etm(vertex_layer_dist) [lindex $item 1]
          set etm(vertex_layer_angle) [lindex $item 2]
          etm_ShowOneImage vertex VertexLayer $a 1 $etmColors(VertexLayer)
        }        
      }
      relaxation_factor: {
        set etm(relaxation_factor) [gets $f] 
      }
      use_orthog_position: {
        set etm(use_orthog_position) [gets $f] 
      }
      use_fract_position: {
        set etm(use_fract_position) [gets $f] 
      }
      grid_exp_rate_subf_perp: {
        set etmList(grid_exp_rate_subf_perp) [gets $f] 
        set i 0
        foreach {aa bb cc dd ee ff} $etmList(grid_exp_rate_subf_perp) {
          set etmRelaxCoeff(GRID,imin,grid_exp_rate_subf_perp,$i) "$aa"
          set etmRelaxCoeff(GRID,imax,grid_exp_rate_subf_perp,$i) "$bb"
          set etmRelaxCoeff(GRID,jmin,grid_exp_rate_subf_perp,$i) "$cc"
          set etmRelaxCoeff(GRID,jmax,grid_exp_rate_subf_perp,$i) "$dd"
          set etmRelaxCoeff(GRID,kmin,grid_exp_rate_subf_perp,$i) "$ee"
          set etmRelaxCoeff(GRID,kmax,grid_exp_rate_subf_perp,$i) "$ff"
          set etmList(grid_exp_rate_subf_perp,$i) "$aa $bb $cc $dd $ee $ff"
          incr i
        }
      }
      grid_exp_rate_subf_perp_surfaces: {
        if [info exists etm(batch)] { continue }
        set line [gets $f]
        foreach {num val} $line { set etm(sf,$num,grid_exp_rate_subf_perp) $val }
      }
      grid_exp_rate_subf_1: {
        set etmList(grid_exp_rate_subf_1) [gets $f]
        set i 0
        foreach {aa bb cc dd ee ff} $etmList(grid_exp_rate_subf_1) {
          set etmRelaxCoeff(GRID,imin,grid_exp_rate_subf_1,$i) "$aa"
          set etmRelaxCoeff(GRID,imax,grid_exp_rate_subf_1,$i) "$bb"
          set etmRelaxCoeff(GRID,jmin,grid_exp_rate_subf_1,$i) "$cc"
          set etmRelaxCoeff(GRID,jmax,grid_exp_rate_subf_1,$i) "$dd"
          set etmRelaxCoeff(GRID,kmin,grid_exp_rate_subf_1,$i) "$ee"
          set etmRelaxCoeff(GRID,kmax,grid_exp_rate_subf_1,$i) "$ff"
          set etmList(grid_exp_rate_subf_1,$i) "$aa $bb $cc $dd $ee $ff"
          incr i
        }
      }
      grid_exp_rate_subf_1_surfaces: {
        if [info exists etm(batch)] { continue }
        set line [gets $f]
        foreach {num val} $line { set etm(sf,$num,grid_exp_rate_subf_1) $val }
      }
    }
  }
  if ![info exists etm(batch)] {
    set etmSmoother(DisplayOn) 1
    disp_set_visible domain 1
  }
}

proc etm_PredefinedMeshParameter {} {
global etmVar
  
  if [winfo exists .predefined] { top_destroy .predefined } 
  etm_ClearView
  etm_SetTypeVisible domain 1
    
  if ![info exists etmVar(PredefMesh)] {
    set etmVar(PredefMesh) 0
  }
  set win .predefined 
  etm_SetParameterPredefined $etmVar(PredefMesh)  
  set buttons {
    {"Apply" "etm_DonePredefined"}
    {"Reset" "etm_ResetPredefined .predefined.main.2"}
    {"Cancel" "etm_CancelPredefined"}
  } 
  set win .predefined
  set w [form_init $win "Predefined mesh parameters" "" $buttons] 
  if { $w != "" } {
    form_frame $w.1 flat 3 "0 0 -pady 3"
    form_label $w.1.1 "Direction vector:" "0 0"
    form_radiobutton $w.1.2 "Normal" etmVar(Vector) 1 "0 1" "" \
    	"etm_SetVectorPredefined $w.2"
    form_radiobutton $w.1.3 "User defined" etmVar(Vector) 2 "0 2" "" \
    	"etm_SetVectorPredefined $w.2"
    form_frame $w.2 flat 3 "1 0 -pady 3"
    form_label $w.2.x "  X " "1 0 -pady 2"
    form_entry $w.2.xx etmVar(VectorX) float "1 1 -pady 2"
    form_label $w.2.y "  Y " "1 2 -pady 2"
    form_entry $w.2.yy etmVar(VectorY) float "1 3 -pady 2"    
    form_label $w.2.z "  Z " "1 4 -pady 2"
    form_entry $w.2.zz etmVar(VectorZ) float "1 5 -pady 2"    
    form_frame $w.3 flat 3 "2 0 -pady 3"
    form_label $w.3.1 "Meshing law: " "0 0 -ipady 2"
    form_menubutton $w.3.2 "$etmVar(Name,MeshLaw)" $w.3.2.m "0 1 -ipady 2"
    $w.3.2 configure -relief raised -bd 3 -indicatoron 1 -width 16
    menu $w.3.2.m -tearoff 0
    set menu $w.3.2
    set proc etm_SetMeshingLawPredefined
    set com "$proc $etmVar(MeshLaw,Default) $menu"
    $w.3.2.m add command -label "Default" -command "$com"
    set com "$proc $etmVar(MeshLaw,Uniform) $menu"
    $w.3.2.m add command -label "Uniform" -command "$com"
    set com "$proc $etmVar(MeshLaw,Hyperbolic) $menu"
    $w.3.2.m add command -label "Hyperbolic" -command "$com"
    set com "$proc $etmVar(MeshLaw,Geometric) $menu"
    $w.3.2.m add command -label "Geometric" -command "$com"
    set com "$proc $etmVar(MeshLaw,Bigeometric) $menu"
    $w.3.2.m add command -label "Bigeometric" -command "$com"
    set com "$proc $etmVar(MeshLaw,Exponential) $menu"
    $w.3.2.m add command -label "Exponential" -command "$com"
    set com "$proc $etmVar(MeshLaw,Biexponential) $menu"
    $w.3.2.m add command -label "Biexponential" -command "$com"
    set com "$proc $etmVar(MeshLaw,Poisson) $menu"
    $w.3.2.m add command -label "Poisson" -command "$com"
    set com "$proc $etmVar(MeshLaw,GLL) $menu"
    $w.3.2.m add command -label "GLL" -command "$com"
    form_frame $w.4 flat 3 "3 0"
    form_label $w.4.1 "Spacing 1    " "0 0 -pady 2"
    form_entry $w.4.1e etmVar(Space1) float "0 1 -pady 2"
    form_label $w.4.2 "Spacing 2    " "0 2 -pady 2"
    form_entry $w.4.2e etmVar(Space2) float "0 3 -pady 2"
    form_label $w.4.3 "Spacing 1-2  " "1 0 -pady 2"
    form_entry $w.4.3e etmVar(Space1-2) float "1 1 -pady 2"
    form_label $w.4.4 "Spacing 2-2  " "1 2 -pady 2"
    form_entry $w.4.4e etmVar(Space2-2) float "1 3 -pady 2"
    form_label $w.4.5 "Ratio        " "2 0 -pady 2"
    form_entry $w.4.5e etmVar(Ratio) float "2 1 -pady 2"
    
    form_frame $w.cell flat 3 "4 0 -pady 3" 
    form_label $w.cell.1 "First hold cell height" "0 0 -pady 2"
    form_entry $w.cell.1e etmVar(first_cell_height) float "0 1 -pady 2"
    form_label $w.cell.2 "Last hold cell height" "1 0 -pady 2"
    form_entry $w.cell.2e etmVar(last_cell_height) float "1 1 -pady 2"    
    form_frame $w.5 flat 3 "5 0 -pady 3"
    form_menubutton $w.5.1 "Base subfaces" $w.5.1.m "0 0 -ipady 2"
    $w.5.1 configure -relief raised -bd 3 -indicatoron 1 -width 16
    menu $w.5.1.m -tearoff 0
    set proc etm_SelectSubfacePredefined
    $w.5.1.m add command -label "Select on screen" -command "$proc Select"
    $w.5.1.m add command -label "By families..." -command "$proc Families"
    form_checkbutton $w.5.2 "Extend base subface" etmVar(SubfaceExtend) \
    	"0 1 -pady 5" "" " etm_ExtendSubfacePredefined"

    etm_SetVectorPredefined $w.2
    if ![string match Windows* [winfo server .]] {
      form_finish -20+20 1 0
    } else {
      form_finish +400+400 1 0
    }
  } 
  catch { wm protocol $win WM_DELETE_WINDOW "etm_CancelPredefined" }  
}

proc etm_SelectSubfacePredefined { what } {
global etm etmList etmVar
  
  if ![info exists etm(overall_visible,subface)] {
    busy 1
    disp_change_overall_visible subface
    set etm(overall_visible,subface) 1
    busy 0
  }
  if {$what ==  "Select"} {
    if $etmVar(SubfaceExtend) {
      mess "Select only one base subface to extend.\n"
    } else {
      if ![ string match "" $etmVar(SubfaceSelected) ] {
        ic_str_scanp_move_zone subface $etmVar(SubfaceSelected) 0 $etmVar(SubfaceExtend)
      }
    }
    etm_SelectObjects subface Select PredefMesh
  } elseif {$what == "Families"} {
    if $etmVar(SubfaceExtend) {
      if ![string match "" $etmVar(SubfaceSelected)] {
        ic_str_scanp_move_zone subface $etmVar(SubfaceSelected) 0 $etmVar(SubfaceExtend)
      }      
    }
    set etmVar(SubfaceExtend) 0
    etm_SelectObjects subface Families PredefMesh
  }
}

proc etm_SubfacePredefMesh { what list } {
global etmVar etmList
  
  set etmList(SubfacePredefMesh) $list  
  if $etmVar(SubfaceExtend) {
    if [ etm_ExtendSubfacePredefined ] {
      return
    }
    foreach item $etmList(SubfacePredefMesh) {
      ic_str_scanp_move_zone subface $item 0 $etmVar(SubfaceExtend)
      break
    }
  }
}

proc etm_ExtendSubfacePredefined {} {
global etmList etmVar
  
  if ![ etm_IsArrayItemOk etmList SubfacePredefMesh ] {
    return
  }
  if { [ llength $etmList(SubfacePredefMesh) ] > 1 && $etmVar(SubfaceExtend) } {
    etm_ShowMessage INFO "You selected more than\none base subface to extend.\n \
      		      Only one base subface is allowed."
    set etmVar(SubfaceExtend) 0
    if ![ string match "" $etmVar(SubfaceSelected) ] {
      ic_str_scanp_move_zone subface $etmVar(SubfaceSelected) 0 $etmVar(SubfaceExtend) 
    }
    return 1
  }
  
  foreach item $etmList(SubfacePredefMesh) {
    ic_str_scanp_move_zone subface $item 0 $etmVar(SubfaceExtend)  
    set etmVar(SubfaceSelected) $item
    return 0
  }
}

proc etm_SetMeshingLawPredefined { what win } {
global etmVar

  foreach item [ array names etmVar MeshLaw,* ] {
    if { $what == $etmVar($item) } {
      set etmVar(Name,MeshLaw) [ lindex [ split $item , ] 1 ]
      set etmVar(Selected,MeshLaw) $what
      $win configure -text $etmVar(Name,MeshLaw)
      break
    }
  }
}

proc etm_DonePredefined {} {
global etmList etmVar etm

  if { ![ info exists etmList(SubfacePredefMesh) ] || \
  	[ llength $etmList(SubfacePredefMesh) ] == 0 } {
    if { ![ etm_ShowQuestion INFO "You selected no base subface(s).\
    		\nPredefined mesh will not work. \
    		\nReally quit parameters ?" ] } {
      return
    }
    catch { unset etmList(SubfacePredefMesh) }
    set etmVar(PredefMesh) 1
    top_destroy .predefined
    return
  }    
  etm_SetMeshingLawPar 1 $etmVar(Selected,MeshLaw) $etmVar(Space1) $etmVar(Space2) \
  		       $etmVar(Space1-2) $etmVar(Space2-2) $etmVar(Ratio)
  set etm(DirectionVector) "$etmVar(VectorX) $etmVar(VectorY) $etmVar(VectorZ)"
  set etm(SubfaceExtend) $etmVar(SubfaceExtend)
  set etm(first_cell_height) $etmVar(first_cell_height)
  set etm(last_cell_height) $etmVar(last_cell_height)
  foreach item $etmList(SubfacePredefMesh) {
    lappend list $item
  }
  set etm(BaseSubfacesNo) $list  
  top_destroy .predefined
  unset etmList(SubfacePredefMesh)
  set etmVar(PredefMesh) 1
}

proc etm_SetVectorPredefined { win } {
global etmVar etmMode

  if { $etmVar(Vector) == "1" } {
    $win.x configure -fg gray
    $win.xx configure -state disabled -fg gray
    $win.y configure -fg gray
    $win.yy configure -state disabled -fg gray
    $win.z configure -fg gray
    $win.zz configure -state disabled -fg gray
    set etmVar(VectorX) $etmMode(VarVectorX)
    set etmVar(VectorY) $etmMode(VarVectorY)
    set etmVar(VectorZ) $etmMode(VarVectorZ)
  } elseif { $etmVar(Vector) == "2" } {
    $win.x configure -fg black 
    $win.xx configure -state normal -fg black  
    $win.y configure -fg black  
    $win.yy configure -state normal -fg black  
    $win.z configure -fg black  
    $win.zz configure -state normal -fg black   
  }
}

proc etm_CancelPredefined {} {
global etmList etm etmColors
  
  if [ info exists etmList(SubfacePredefMesh) ] {
    foreach item $etmList(SubfacePredefMesh) {
      etm_ShowOneImage subface PredefMesh $item 0 $etmColors(PredefMesh)
    }
    unset etmList(SubfacePredefMesh)
  }
  set etm(DirectionVector) ""
  set etm(SubfaceExtend) 0
  set etm(BaseSubfacesNo) ""
  set etm(first_cell_height) -1
  set etm(last_cell_height) -1
  etm_SetMeshingLawPar 0
  top_destroy .predefined
}

proc etm_ResetPredefined { win } {
global etmList etmVar etmColors etm
  
  etm_ClearView
  etm_SetParameterPredefined 0
  set etm(DirectionVector) ""
  set etm(SubfaceExtend) 0
  set etm(BaseSubfacesNo) ""
  etm_SetMeshingLawPar 0
  .predefined.main.3.2 configure -text $etmVar(Name,MeshLaw)
  etm_SetVectorPredefined $win
  if [ info exists etmList(SubfacePredefMesh) ] {
    foreach item $etmList(SubfacePredefMesh) {
      etm_ShowOneImage subface PredefMesh $item 0 $etmColors(PredefMesh)
    }
    unset etmList(SubfacePredefMesh)
  }
}

proc etm_UnsetParameterPredefinedSubface {} {
global etm etmColors
  
  if [info exists etm(BaseSubfacesNo)] {
    foreach item $etm(BaseSubfacesNo) {
      etm_ShowOneImage subface PredefMesh $item 0 $etmColors(PredefMesh)
    }
    set etm(DirectionVector) ""
    set etm(SubfaceExtend) 0
    set etm(BaseSubfacesNo) ""
    set etm(first_cell_height) -1
    set etm(last_cell_height) -1    
    etm_SetMeshingLawPar 0
  }
}

proc etm_SetParameterPredefined { what } {
global etmVar etmMode

  if { $what == 0 } {
    set etmVar(Vector) $etmMode(VarVector)
    set etmVar(VectorX) $etmMode(VarVectorX)
    set etmVar(VectorY) $etmMode(VarVectorY)
    set etmVar(VectorZ) $etmMode(VarVectorZ)
    set etmVar(MeshLaw,Default) $etmMode(MeshLawDefault)
    set etmVar(MeshLaw,Uniform) $etmMode(MeshLawUniform)
    set etmVar(MeshLaw,Hyperbolic) $etmMode(MeshLawHyperbolic)
    set etmVar(MeshLaw,Geometric) $etmMode(MeshLawGeometric)
    set etmVar(MeshLaw,Bigeometric) $etmMode(MeshLawBigeometric)
    set etmVar(MeshLaw,Exponential) $etmMode(MeshLawExponential)
    set etmVar(MeshLaw,Biexponential) $etmMode(MeshLawBiexponential)
    set etmVar(MeshLaw,Poisson) $etmMode(MeshLawPoisson)
    set etmVar(MeshLaw,GLL) $etmMode(MeshLawGLL)
    set etmVar(Selected,MeshLaw) $etmVar(MeshLaw,Default)
    set etmVar(Name,MeshLaw) Default
    set etmVar(Space1) $etmMode(VarSpace1)
    set etmVar(Space2) $etmMode(VarSpace2)
    set etmVar(Space1-2) $etmMode(VarSpace1-2)
    set etmVar(Space2-2) $etmMode(VarSpace2-2)
    set etmVar(Ratio) $etmMode(VarRatio)
    set etmVar(SubfaceExtend) $etmMode(VarSubfaceExtend)
    set etmVar(SubfaceSelected) $etmMode(VarSubfaceSelected) 
    set etmVar(PredefMesh) 0
    set etmVar(first_cell_height) -1
    set etmVar(last_cell_height) -1
  } else {
    set etmVar(MeshLaw,Default) $etmMode(MeshLawDefault)
    set etmVar(MeshLaw,Uniform) $etmMode(MeshLawUniform)
    set etmVar(MeshLaw,Hyperbolic) $etmMode(MeshLawHyperbolic)
    set etmVar(MeshLaw,Geometric) $etmMode(MeshLawGeometric)
    set etmVar(MeshLaw,Bigeometric) $etmMode(MeshLawBigeometric)
    set etmVar(MeshLaw,Exponential) $etmMode(MeshLawExponential)
    set etmVar(MeshLaw,Biexponential) $etmMode(MeshLawBiexponential)
    set etmVar(MeshLaw,Poisson) $etmMode(MeshLawPoisson)
    set etmVar(MeshLaw,GLL) $etmMode(MeshLawGLL)
  }
}

proc etm_StartSmoothing { prog_select } {
global env tool_dir etmMode etmList etm file_name etmSetting etm_undo
    
  if { $prog_select == $etmMode(ProgGlobalSmooth) } {
    set mess "global smoothing"
  } elseif { $prog_select == $etmMode(ProgLocalSmooth) } { 
    set mess "local smoothing"
  } elseif { $prog_select == $etmMode(ProgSingleSmooth) || \
             $prog_select == $etmMode(ProgSingleGlobalPlane) || \
             $prog_select == $etmMode(ProgSingleGlobal) || \
             $prog_select == $etmMode(ProgSingleEdge) || \
             $prog_select == $etmMode(Prog3DGlobal)} {
    set mess "single smoothing"
  } elseif { $prog_select == $etmMode(ProgImprover) } { 
    set mess "post smoothing"
  } elseif { $prog_select == $etmMode(ProgPredefinedMesh) } { 
    set mess "predefined mesh"
  }
  mess "Use interrupt button to cancel $mess.\n"
  mess "Performing $mess...\n"    
  set isChanged [etm_GetArrayChanges Get $prog_select]
  busy 1
  set etm_dir $file_name(mesh_dir)
  set smooth_domain $etmList(SmoothDomain)
  set face_methods $etmList(FaceMethods)
  set volume_methods $etmList(VolumeMethods)
  set niter $etm(Niter)
  set nsteps $etm(Nsteps)
  set maxlevel $etm(Maxlevel)
  set sfit $etm(Sfit)
  set conditional $etm(Conditional)
  set check_det $etm(CheckDet)
  set damping $etm(Damping)
  set vertex_fix $etm(VertexFix)
  set edge_freeze $etm(EdgeFreeze)
  set wedge_check $etm(WedgeCheck)
  set multigrid2d $etm(Multigrid2D)
  set reduced_edge $etm(ReducedEdge)
  set fix_fam $etm(FixFam)
  set inner_vol_sm $etm(InnVol)
  set ns_rel $etm(NsRel)
  set angle_freeze_edge $etm(AngleFreezeEdges)
  set n_iter $etm(nItera)
  set interp_faces $etm(InterpFaces)
  set interp_volumes $etm(InterpVolumes)
  set prog_select $prog_select
  set threshold_det $etm(ThresholdDet)
  set threshold_angle $etm(ThresholdAngle)
  set subface_extensions $etmList(etmLayerExtensionNo)
  set ijk_extensions $etmList(etmLayerExtensionIJK)
  set edge_attrib $etmList(etmEdgeAttr)
  set relax_subfaces $etmList(etmRelaxSubface)
  set relaxation_zones $etmList(etmRelaxZone)
  set viol_geom_zones $etmList(etmViolGeomZone)
  set viol_geom_subfaces $etmList(etmViolGeomSubface)
  set base_subfaces_no $etm(BaseSubfacesNo)
  set meshing_law $etmList(etmMeshingLawPar)
  set subface_extend $etm(SubfaceExtend)
  set direction_vector $etm(DirectionVector)
  set base_regions $etmList(etmRegion)
  set type_improve $etm(TypeImprove)
  set type_postsm $etm(TypePostSm)
  set proj_limit $etm(ProjLimit)
  set group_bad_elem $etm(GroupBadElem)
  set smooth_dir $etmList(SmoothDir)
  set mesh_type $etm(mesh_type)
  set smooth_ngh_method $etmList(UnselectedMethods)
  set surfresolv $etm(SmoothOnFaces)
  set min_mxr $etm(MinResidual)
  set min_res $etm(StopResidual)
  set edge_no_global_smooth $etmList(etmEdgeGlobal)
  set incr_3d_plane_smooth $etmList(PlaneSmooth)
  set relax_weights_2d $etmList(relax_weights_2d)
  set relax_weights_3d $etmList(relax_weights_3d)
  set relax_weights_inner_2d $etmList(relax_weights_inner_2d)
  set relax_weights_inner_3d $etmList(relax_weights_inner_3d)
  set n_iter_glb $etm(n_iter_glb)
  set n_steps_glb $etm(n_steps_glb)
  set global_vertices_opp $etmList(etmRelaxZoneAdd)
  set plane_numbers $etmList(PlaneNumbers)
  set grid_exp_face $etm(grid_exp_face)
  set grid_exp_vol $etm(grid_exp_vol)
  set abs_dist_bnd $etm(abs_dist_bnd)
  set n_points_abs_dist_bnd $etm(n_points_abs_dist_bnd)
  set use_pthreads $etm(use_pthreads)
  set abs_dist_subf $etmList(abs_dist_subf) 
  set n_abs_dist_subf $etmList(n_abs_dist_subf)
  set vertex_attrib $etmList(VertexAttrib)
  set relaxation_factor $etm(relaxation_factor)
  set use_orthog_position $etm(use_orthog_position)
  set use_fract_position $etm(use_fract_position)
  set grid_exp_rate_subf_perp $etmList(grid_exp_rate_subf_perp)
  set grid_exp_rate_subf_1 $etmList(grid_exp_rate_subf_1)
  set first_cell_height $etm(first_cell_height)
  set last_cell_height $etm(last_cell_height)

  ic_undo_suspend
  ic_str_save_previous_nodes   	
  ic_str_smooth_glsm $isChanged $etm_dir \
    	$smooth_domain $face_methods $volume_methods $niter \
    	$nsteps $maxlevel $sfit $conditional $check_det $damping $vertex_fix \
    	$edge_freeze $wedge_check $multigrid2d $reduced_edge $fix_fam \
    	$inner_vol_sm $ns_rel $angle_freeze_edge $n_iter \
    	$interp_faces $interp_volumes $prog_select $threshold_det $threshold_angle \
    	$subface_extensions $ijk_extensions $edge_attrib $relax_subfaces \
    	$relaxation_zones $viol_geom_zones $viol_geom_subfaces $base_subfaces_no \
    	$meshing_law $subface_extend $direction_vector $base_regions \
    	$type_improve $type_postsm $proj_limit $group_bad_elem \
    	$smooth_dir $mesh_type $smooth_ngh_method $surfresolv $min_mxr \
    	$edge_no_global_smooth $incr_3d_plane_smooth $relax_weights_2d \
    	$relax_weights_3d $relax_weights_inner_2d $relax_weights_inner_3d \
    	$n_iter_glb $n_steps_glb $global_vertices_opp $plane_numbers \
    	$grid_exp_face $grid_exp_vol $min_res $abs_dist_bnd $n_points_abs_dist_bnd \
    	$abs_dist_subf $n_abs_dist_subf $vertex_attrib $relaxation_factor \
    	$use_orthog_position $use_fract_position $grid_exp_rate_subf_perp \
    	$grid_exp_rate_subf_1 $first_cell_height $last_cell_height $use_pthreads

  catch { interrupt finish }
  mess "Finish $mess...\n"
  ic_undo_resume
  set etm_undo 1
  etm_GetArrayChanges Set $prog_select
  beep
  .v.view redraw
  if {$prog_select == $etmMode(ProgImprover)} {
    etm_GetValuesPost .postsm.main 1
  }  
  if ![info exists etm(batch)] {
    set etmSetting(Header) "Settings Management for Smoothing and Predefined Mesh: Med"
    if [info exists env(USER)] {
      set etmSetting(User) $env(USER)
    } else {
      set etmSetting(User) Dummy
    }
    set etmSetting(File) "default_settings.med"
    set set_dir $file_name(mesh_dir)/settings 
    if ![file exists $set_dir] { file mkdir $set_dir }
    if {[file exists $set_dir] && [file isdirectory $set_dir]} {
      set set_file $set_dir/$etmSetting(File)
    } else {
      set set_dir $file_name(mesh_dir)
      set set_file $set_dir/$etmSetting(File)
    }
    set f [open $set_file w]
    etm_SaveSettings $f
    close $f
    mess "Current settings saved as file <$set_file>.\n"
  }
  busy 0
}

proc etm_PrepareSmoothing { what } {

  etm_CreateSmoothLists
  etm_CreateDomainList
  etm_CreateMethodLists
  etm_StartSmoothing $what
}

proc etm_Perform { what } {
global etmSmoother etmMode etmColors inside_computation

  if { $what != $etmMode(ProgSingleSmooth) } {
    if ![ etm_IsDomainActive ] {
      etm_ShowMessage Error "Can't do smoothing: no domain is selected."
      return
    }
  }
  if [ info exists inside_computation ] {
    mess "Already performing computation - ignoring second command\n" red
    return
  } 
  set inside_computation 1
  if { $what == $etmMode(ProgGlobalSmooth) } {
    etm_PrepareSmoothing $etmMode(ProgGlobalSmooth)
  } elseif { $what == $etmMode(ProgLocalSmooth) } {
    etm_PrepareSmoothing $etmMode(ProgLocalSmooth)
  } elseif { $what == $etmMode(Prog3DGlobal) } {
    etm_PrepareSmoothing $etmMode(Prog3DGlobal)
  } elseif { $what == $etmMode(ProgSingleSmooth) } {
    set check [etm_CheckSingleSmooth]
    if {$check == "0"} {
      etm_ShowMessage Error "Can't do smoothing: no domain is selected."
      unset inside_computation
      return
    } elseif {$check == "1"} {
      etm_PrepareSmoothing $etmMode(ProgSingleSmooth)
    } elseif {$check == "2"} {
      etm_SingleSmoothWin
    } elseif {$check == "3"} {
      etm_PrepareSmoothing $etmMode(ProgSingleEdge)
    }
  } elseif { $what == $etmMode(ProgImprover) } {
    etm_PostWin
  } elseif { $what == $etmMode(ProgPredefinedMesh) } {
    etm_PerformPredefined
  }  
  unset inside_computation
}

proc etm_CheckSingleSmooth {} {
global etmFlag etmEdgeGlobalSave etmList etmColors

  etm_CreateGlobalSaveList  
  set domains ""
  set edges ""  
  foreach i [array names etmFlag] {
    if $etmFlag($i) { set dom_on($i) 1 }
  }
  foreach i [array names etmEdgeGlobalSave] {
    set edge_on($i) 1
    lappend edges $i
    foreach a [ic_str_get_topo_info edge $i 1] {
      set d [expr [lindex $a 4] -1]
      if [info exists dom_on($d)] {
        set edges_on_dom($d) 1
      }
    }
  } 
  for {set i 0} {$i < [ic_str_num_entities domain]} {incr i} {
    if {[info exists dom_on($i)] && [info exists edges_on_dom($i)]} {
      lappend domains $i
    }
  }    
  if {![info exists dom_on] && ![info exists edge_on]} {
    return 0
  }
  if {[info exists dom_on] && ![info exists edge_on]} {
    return 1
  }  
  if [info exists etmList(SmoothDir)] {
    set list $etmList(SmoothDir)
  } else {
    for {set i 0} {$i < [ic_str_num_entities domain]} {incr i} {
      lappend list 0
    }
  }
  if {![info exists dom_on] && [info exists edge_on]} {
    foreach i [array names etmEdgeGlobalSave] {
      foreach a [ic_str_get_topo_info edge $i 1] {
        set number [lindex $a 4]
        set etmFlag([expr $number - 1]) 1
        etm_ShowOneImage domain RelaxationDomain $number 1 $etmColors(RelaxationDomain)
        if ![info exists add($number)] {
          mess "Added dom$number to selected domains.\n"
          set add($number) 1
        }
      }
    }
    return 3    
  }

  set all_3d 1
  if {[info exists dom_on] && [info exists edge_on]} {
    if {$domains != ""} {
      foreach i $domains {
        if {[lindex $list $i] != "0"} {
          set all_3d 0
          break
        }
      }
      if $all_3d {
        return 3
      } else {
        return 2
      }
    } else {
      foreach im [ic_str_list_blockif_surfs edge] {
        etm_ShowEdgeAttr $im EdgeGlobal 0
      }
      return 1
    }
  }
}

proc etm_SingleSmoothWin {} {
global etmList etmSmoother etmMode etmFlag tmp etmEdgeGlobalSave
  
  etm_CreateSmoothLists
  etm_CreateDomainList
  etm_CreateMethodLists
    
  set single(2D) 0
  set single(win) 0
  set single(plane) 0
  set single(global) 0

  if $etmSmoother(2D) { set single(2D) 1 }
  if {[info exists etmEdgeGlobalSave] && ([array size etmEdgeGlobalSave] != 0)} {
    set single(global) 1
  }
  if {([info exists etmList(SmoothDir)] && $etmList(SmoothDir) != "") && \
      ([info exists etmList(PlaneSmooth)] && $etmList(PlaneSmooth) != "")} {
    set i 0
    foreach item $etmList(SmoothDir) {
      if {$item == "1" || $item == "2" || $item == "3"} {
        if $etmFlag($i) {
          set single(plane) 1
          break
        }
      }
      incr i
    }
  } 
  
  if {$single(global) && ($single(2D) || $single(plane))} {
    set single(win) 1
  }

  if !$single(win) {
    etm_StartSmoothing $etmMode(ProgSingleSmooth)
    return
  }

  set tmp(plane) 1
  set tmp(global) 1

  set buttons {
    {"Apply" "set tmp(done) 1"}
    {"Cancel" "set tmp(done) 0"}
  }
  
  set win .single
  set w [form_init $win "Single smoothing" "" $buttons] 
  if { $w != "" } {
    form_frame $w.1 ridge 3 "0 0 -pady 3"
    form_label $w.1.1 "Select \"single smoothing\" type" "0 0 -padx 3 -pady 3"
    form_frame $w.2 ridge 3 "1 0 -pady 3"
    form_checkbutton $w.2.1 "Plane smoothing" tmp(plane) "0 0 -pady 3" "" \
    	"etm_SingleSmoothSelect $w.2.1"
    form_checkbutton $w.2.2 "Global edge smoothing" tmp(global) "1 0 -pady 3" \
    	"" "etm_SingleSmoothSelect $w.2.2"
    form_finish +400+400 1 0
  }
 
  wm resizable $win 0 0
  grab set $win
  tkwait variable tmp(done)
  grab release $win
  catch { top_destroy $win }

  if $tmp(done) {
    if {$tmp(plane) && $tmp(global)} {
      etm_CreateGlobalList
      etm_StartSmoothing $etmMode(ProgSingleGlobalPlane)
    } elseif $tmp(plane) {
      etm_StartSmoothing $etmMode(ProgSingleSmooth)
    } elseif $tmp(global) {
      etm_CreateGlobalList
      etm_StartSmoothing $etmMode(ProgSingleGlobal)
    }
  }
  unset tmp(plane)
  unset tmp(global)
}

proc etm_SingleSmoothSelect { w } {
global tmp

  if {!$tmp(plane) && !$tmp(global)} {
    $w select
  }
}

proc etm_PerformPredefined {} {
global etmMode

  if ![ etm_IsArrayOk etmMeshingLawPar ] {
    etm_ShowMessage ERROR "No predefined mesh parameters set."
    return
  }
  etm_PrepareSmoothing $etmMode(ProgPredefinedMesh)
}

proc etm_PerformPost {} {
global etm etmPost etmMode inside_computation

  if [ string match "" $etmPost(Threshold) ] {
    etm_ShowMessage INFO "No threshold selected"
    return
  }

  if [ info exists inside_computation ] {
    mess "Already performing computation - ignoring second command\n" red
    return
  }
  set inside_computation 1
  
  if { $etm(TypeImprove) == $etmMode(CriterionOrthogonality) } {
    if { ($etm(TypePostSm) == $etmMode(PostSelectAllExclViol)) || \
     	 ($etm(TypePostSm) == $etmMode(PostSelectAll)) } {
      set etm(ThresholdAngle) [ expr 90 - $etmPost(Threshold) ]
      set etm(ThresholdDet) -110
      mess "Post smoothing: Orthogonality > $etmPost(Threshold)\n"
    } elseif { $etm(TypePostSm) == $etmMode(PostSelectConcentrViol) } {
      set etm(ThresholdAngle) 90.0
      set etm(ThresholdDet) -110
      mess "Post smoothing (Concentrate): Orthogonality > $etm(ThresholdAngle)\n"
    }
  } elseif { $etm(TypeImprove) == $etmMode(CriterionDeterminant) || \
  	     $etm(TypeImprove) == $etmMode(CriterionQuality) || \
  	     $etm(TypeImprove) == $etmMode(CriterionSkewness) } {
    if { ($etm(TypePostSm) == $etmMode(PostSelectAllExclViol)) || \
         ($etm(TypePostSm) == $etmMode(PostSelectAll)) } {
      set etm(ThresholdAngle) 0
      set etm(ThresholdDet) $etmPost(Threshold)
      mess "Post smoothing: Determinant < $etm(ThresholdDet)\n"
    } elseif { $etm(TypePostSm) == $etmMode(PostSelectConcentrViol) } {
      set etm(ThresholdAngle) 0
      set etm(ThresholdDet) 100.0
      mess "Post smoothing (Concentrate): Determinant < $etm(ThresholdDet)\n" 
    }   
  } elseif { $etm(TypeImprove) == $etmMode(CriterionWarp) } {
    if { ($etm(TypePostSm) == $etmMode(PostSelectAllExclViol)) || \
     	 ($etm(TypePostSm) == $etmMode(PostSelectAll)) } {
      set etm(ThresholdAngle) $etmPost(Threshold)
      set etm(ThresholdDet) -110
      mess "Post smoothing: Warp > $etmPost(Threshold)\n"
    } elseif { $etm(TypePostSm) == $etmMode(PostSelectConcentrViol) } {
      set etm(ThresholdAngle) 90.0
      set etm(ThresholdDet) -110
      mess "Post smoothing (Concentrate): Warp > $etm(ThresholdAngle)\n"
    }
  }
  unset inside_computation

  etm_PrepareSmoothing $etmMode(ProgImprover)
}

proc etm_PostWin {} {
global etm etmMode etmPost
  
  if [ winfo exists .postsm ] { top_destroy .postsm }  
  set buttons {
    {"Perform" "etm_PerformPost"} \
    {"Check" "etm_ShowAllBuckets etmPost"} \
    {"Done" "etm_DonePost"}
  }  
  
  set win .postsm
  set w [form_init $win "Post smoothing" "" $buttons]
  if {$w != ""} {
    if {$etm(TypeImprove) == $etmMode(CriterionDeterminant)} {
      set crit "Determinant"
    } elseif {$etm(TypeImprove) == $etmMode(CriterionOrthogonality)} {
      set crit "Orthogonality"
    } elseif {$etm(TypeImprove) == $etmMode(CriterionWarp)} {
      set crit "Warp"
    } elseif {$etm(TypeImprove) == $etmMode(CriterionQuality)} {
      set crit "Quality"
    } elseif {$etm(TypeImprove) == $etmMode(CriterionSkewness)} {
      set crit "Skewness"
    }
    form_frame $w.1 flat 3 "0 0 -pady 3" 
    form_label $w.1.1 "Current criterion:   $crit" "0 0"
    form_frame $w.2 flat 3 "1 0 -pady 3" 
    etm_CreateDomainList
    etm_GetValuesPost $w 1  
    
    if ![string match Windows* [winfo server .]] {
      form_finish -20-20 1 0
    } else {
      form_finish +400+400 1 0
    }
  } 
  catch { wm protocol $win WM_DELETE_WINDOW "etm_DonePost" } 
}

proc etm_GetValuesPost { win destroy } {
global etmPost etmList etmMode etm

  busy 1     
  if  [info exists etmPost(NoIntervall)] {
    for { set i 0 } { $i < $etmPost(NoIntervall) } { incr i } {
      set etmPost(ShowElements,$i) ""
    }
  }    
  ic_str_clear_diagnostics 
  if $destroy {
    set i 0
    catch { unset etmPost(Threshold) }
    catch { top_destroy $win.1.1 }
    set list [ winfo children $win.2 ]
    foreach item $list {
      top_destroy $item
      if [ info exists etmPost(ShowIntervall,$i) ] {
        unset etmPost(ShowIntervall,$i)
      }
      incr i
    }
  }

  if {$etm(TypeImprove) == $etmMode(CriterionDeterminant)} {
    set crit "Determinant"
  } elseif {$etm(TypeImprove) == $etmMode(CriterionOrthogonality)} {
    set crit "Orthogonality"
  } elseif {$etm(TypeImprove) == $etmMode(CriterionWarp)} {
    set crit "Warp"
  } elseif {$etm(TypeImprove) == $etmMode(CriterionQuality)} {
    set crit "Quality"
  } elseif {$etm(TypeImprove) == $etmMode(CriterionSkewness)} {
    set crit "Skewness"
  }
  
  form_label $win.1.1 "Current criterion:   $crit" "0 0"
  form_frame $win.2.t flat 0 "0 0"
  form_label $win.2.t.t1 "Elements" "0 0"
  form_label $win.2.t.t2 "between" "0 1"
  $win.2.t.t2 configure -width 20 -anchor c
  form_label $win.2.t.t3 "Show" "0 2 -padx 15"
  form_label $win.2.t.t4 "Smooth" "0 3"

  if { ($etm(TypeImprove) == $etmMode(CriterionDeterminant)) || \
       ($etm(TypeImprove) == $etmMode(CriterionQuality)) || \
       ($etm(TypeImprove) == $etmMode(CriterionSkewness)) } {
    set etmPost(GetIntervall) 2
  } elseif { ($etm(TypeImprove) == $etmMode(CriterionOrthogonality)) || \
	     ($etm(TypeImprove) == $etmMode(CriterionWarp)) } {
    set etmPost(GetIntervall) 1
  }
  set etmPost(NoIntervall) 20
  set etmPost(Intervall) [ etm_CreateBucketsListPost ]
  
  set opts "-bg white -relief ridge -bd 3 -width 7"
  for { set i 0 } { $i < $etmPost(NoIntervall) } { incr i } {
    set iv [lindex $etmPost(Intervall) $i]
    form_frame $win.2.$i flat 0 "[expr $i + 1] 0"
    set etmPost(ShowElements,$i) [lindex $iv 0]
    form_label $win.2.$i.1 " " "0 0"
    $win.2.$i.1	configure -textvariable etmPost(ShowElements,$i) \
    	-bg white -width 8 -relief ridge
    form_label $win.2.$i.2 " " "0 1"
    $win.2.$i.2 configure -anchor c
    form_label $win.2.$i.3 "[lindex $iv 1]" "0 2"
    $win.2.$i.3 configure -width 5 -anchor c
    form_label $win.2.$i.4 "and" "0 3"
    $win.2.$i.4 configure -anchor c
    form_label $win.2.$i.5 "[lindex $iv 2]" "0 4"
    $win.2.$i.5 configure -width 5 -anchor e
    set etmPost(ShowIntervall,$i) 0
    form_checkbutton $win.2.$i.6 "" etmPost(ShowIntervall,$i) "0 5 -padx 40" \
    	"" "etm_ShowBuckets etmPost"
    form_radiobutton $win.2.$i.7 "" etmPost(Threshold) \
    	[lindex $iv $etmPost(GetIntervall)] "0 6 -padx 5" "" ""
  }
  busy 0  
}


proc etm_CreateBucketsListPost {} {
global etm etmPost etmMode etmList
  
  set list ""
  if { $etm(TypeImprove) == $etmMode(CriterionDeterminant) || \
       $etm(TypeImprove) == $etmMode(CriterionQuality) || \
       $etm(TypeImprove) == $etmMode(CriterionSkewness) } {
    if { $etm(TypeImprove) == $etmMode(CriterionDeterminant) || \
         $etm(TypeImprove) == $etmMode(CriterionQuality) } {
      set max 1.0
      set min -1.0
    } elseif { $etm(TypeImprove) == $etmMode(CriterionSkewness) } {
      set max 1.0
      set min 0.0
    }
    set diff [ expr $max - $min ]
    for { set i 0 } { $i < $etmPost(NoIntervall) } { incr i } {
      set bmin [expr $min + [expr [expr $diff * $i] / $etmPost(NoIntervall)]]
      set bmax [expr $min + [expr [expr $diff * [expr $i + 1]] / $etmPost(NoIntervall)]]
      lappend list [list "" $bmin $bmax]
    }
  } elseif { $etm(TypeImprove) == $etmMode(CriterionOrthogonality) || \
             $etm(TypeImprove) == $etmMode(CriterionWarp) } {
    set max 90.0
    set min 0.0
    set diff [ expr $max - $min ]
    for { set i [ expr $etmPost(NoIntervall) - 1 ] } { $i >= 0 } { incr i -1 } {
      set bmin [expr $min + [expr [expr $diff * $i] / $etmPost(NoIntervall)]]
      set bmax [expr $min + [expr [expr $diff * [expr $i + 1]] / $etmPost(NoIntervall)]]
      lappend list [ list "" $bmin $bmax ]
    }
  } 
  return $list
}

proc etm_DonePost {} {
global etmImageZone
    
  ic_str_clear_diagnostics
  etm_DeleteAllRegionZones EdgeViolate 
  etm_UnsetArray etmPost
  top_destroy .postsm
}

proc etm_ShowAllBuckets { what } {
global $what

  set $what\(VisibleElements) 0
  for { set i 0 } { $i < [ set $what\(NoIntervall) ] } { incr i } {
    set $what\(ShowIntervall,$i) 0
  }
  etm_ShowBuckets $what
  set $what\(VisibleElements) 1
}

proc etm_ShowBuckets { what } {
global $what etm etmList etmMode

  busy 1     
  ic_str_clear_diagnostics
    
  if { $what == "etmPost" } {
    set list ""
    for { set i 0 } { $i < [ llength $etmList(SmoothDomain) ] } { incr i } {
      if { [ lindex $etmList(SmoothDomain) $i ] == 1 } {
        set x $i
        lappend list [ expr $x + 1 ] 
      }   
    }

    if { $etm(TypeImprove) == $etmMode(CriterionDeterminant) } {
      set type Determinant
    } elseif { $etm(TypeImprove) == $etmMode(CriterionOrthogonality) } {
      set type "Max orthogls"
    } elseif { $etm(TypeImprove) == $etmMode(CriterionWarp) } {    
      set type "Max warpgls"
    } elseif { $etm(TypeImprove) == $etmMode(CriterionQuality) } {
      set type Quality
    } elseif { $etm(TypeImprove) == $etmMode(CriterionSkewness) } {
      set type Skew
    }
    if ![ info exists $what\(VisibleElements) ] {
      set show 1
    } else {
      set show [ set $what\(VisibleElements) ]
    }
    ic_str_post_diagnostic $type $list $show
    set item [ set $what\(Intervall) ]
    for { set i 0 } { $i < [ set $what\(NoIntervall) ] } { incr i } {
      if { [ set $what\(ShowIntervall,$i) ] || ($show == 0) } {
        set iv [ lindex $item $i ]
	set n [ic_str_post_add_diagnostic $iv $list]
	set $what\(ShowElements,$i) $n
      }
    }    
  }
  busy 0
}

proc etm_RelaxationCoefficients {type type2 {on 1}} {
global tmp

  set tmp(done) 0
  set win .relaxcoeff
  if $on {
    set title "Hold cell height"
  } else {
    set title "Release cell height"
  }
  set w [form_init $win "$title" "" nobuttons] 
  if { $w != "" } {
    set row 1
    form_frame $w.1 ridge 3 "0 0 -pady 3"
    form_label $w.1.1 "Use \"$title\" method for" "$row 0 -padx 3 -pady 3"
    incr row
    form_frame $w.2 ridge 3 "1 0 -pady 3"
    form_button $w.2.1 "All domains" "set tmp(done) 1" "0 0 -padx 3 -ipadx 3 -ipady 1" ""
    $w.2.1 configure -bg gray -activebackground gray
    form_button $w.2.2 "One domain" "set tmp(done) 2" "0 1 -padx 3 -ipadx 3 -ipady 1" ""
    $w.2.2 configure -bg gray -activebackground gray
    form_button $w.2.3 "Cancel" "set tmp(done) 0" "0 2 -padx 3 -ipadx 3 -ipady 1" ""
    $w.2.3 configure -bg gray -activebackground gray
    form_finish +400+400 1 0
  }
  wm resizable $win 0 0   
  grab set $win
  tkwait variable tmp(done)
  grab release $win
  catch { top_destroy $win }
  if {$tmp(done) == "1"} {
    etm_RelaxationCoefficientsAll $type $type2 $on
  } elseif {$tmp(done) == "2"} {
    etm_RelaxationCoefficientsSingle $type $type2 $on
  }
}

proc etm_RelaxationCoefficientsAll {type type2 on} {
global etmRelaxCoeff

  set win .relaxcoeff
  if [ winfo exists $win ] { etm_CancelMethodsRelaxCoeff } 
  set domain "all domains"
  if $on {
    set title "Hold cell height"
    set buttons {
      {"Apply" "etm_ApplyMethodsRelaxCoeff 1"} \
      {"Cancel" "etm_CancelMethodsRelaxCoeff 1"}
    }
  } else {
    set title "Release cell height"
    set buttons {
      {"Apply" "etm_ApplyMethodsRelaxCoeff 0"} \
      {"Cancel" "etm_CancelMethodsRelaxCoeff 0"}
    }
  }
  set etmRelaxCoeff(CUR) "$type All $type2"  
  set w [form_init $win "$title" "" $buttons] 
  if {$w != ""} {  
    form_frame $w.1 ridge 3 "0 0 -pady 3"
    form_label $w.1.1 "$title for $domain" "0 0 -padx 3 -pady 3"
    form_frame $w.2 ridge 3 "1 0 -pady 3"
    set idx 0
    foreach item {imin imax jmin jmax kmin kmax} {
      set txt "[string index $item 0] [string range $item 1 end]"
      form_label $w.2.${item}txt "$txt" "0 $idx -padx 3 -pady 3"
      if ![info exists etmRelaxCoeff(SET,$item,$type,$type2,All)] {
        if $on {
          set etmRelaxCoeff(SET,$item,$type,$type2,All) 0
          set etmRelaxCoeff(SET,$item,grid_exp_rate_subf_perp,All) 0
          set etmRelaxCoeff(SET,$item,grid_exp_rate_subf_1,All) 0
        } else {
          set etmRelaxCoeff(SET,$item,$type,$type2,All) 1
          set etmRelaxCoeff(SET,$item,grid_exp_rate_subf_perp,All) 1
          set etmRelaxCoeff(SET,$item,grid_exp_rate_subf_1,All) 1
        }
      } else {
        if !$on {
          if !$etmRelaxCoeff(SET,$item,$type,$type2,All) {
            set etmRelaxCoeff(SET,$item,$type,$type2,All) 1
            set etmRelaxCoeff(SET,$item,grid_exp_rate_subf_perp,All) 1
            set etmRelaxCoeff(SET,$item,grid_exp_rate_subf_1,All) 1
          } else {
            set etmRelaxCoeff(SET,$item,$type,$type2,All) 0
            set etmRelaxCoeff(SET,$item,grid_exp_rate_subf_perp,All) 0
            set etmRelaxCoeff(SET,$item,grid_exp_rate_subf_1,All) 0
          }
        }
      }
      form_checkbutton $w.2.$item "" etmRelaxCoeff(SET,$item,$type,$type2,All) \
      	"1 $idx -padx 3 -pady 3" "" ""
      form_checkbutton $w.2.${item}show "Show" etmRelaxCoeff(show,$item) \
        "2 $idx -padx 3 -pady 3" "" "etm_ShowFaceRelaxCoeff $item"
      incr idx
    }
    form_finish +400+400 1 0
  }
}

proc etm_RelaxationCoefficientsSingle {type type2 on} {
global etmRelaxCoeff etmList etmColors

  if [ winfo exists .relaxcoeff ] { etm_CancelMethodsRelaxCoeff } 
  if $on {
    set title "Hold cell height"
    set buttons {
      {"Apply" "etm_ApplyMethodsRelaxCoeff 1"} \
      {"Cancel" "etm_CancelMethodsRelaxCoeff 1"}
    }
  } else {
    set title "Release cell height"
    set buttons {
      {"Apply" "etm_ApplyMethodsRelaxCoeff 0"} \
      {"Cancel" "etm_CancelMethodsRelaxCoeff 0"}
    }
  }
  set etmRelaxCoeff(CUR) "$type Single $type2" 
  set height 20
  set last [ic_str_num_entities domain]
  set list $etmList(Domains)
  etm_SetDefaultsRelaxCoeff $type $type2 $on
  etm_SetDefaultsGridExpansionRate $type $type2
  for {set i 1} {$i <= [ic_str_num_entities subface]} {incr i} {
    if [ic_str_check_blockif_surf subface $i] {
      etm_CoefficientsSubfaceIJK $i 0
    }
  }
  set win .relaxcoeff
  set w [form_init $win "$title" "" $buttons] 
  if {$w != ""} {  
    form_frame $w.1 ridge 3 "0 0 -pady 3"
    form_frame $w.1.1 flat 0 "0 0 -pady 3"
    form_label $w.1.1.dom "Show domain" "0 0"
    $w.1.1.dom configure -width 14
    form_label $w.1.1.imin "i min" "0 1"
    $w.1.1.imin configure -width 8 -fg $etmColors(FACE,imin)
    form_label $w.1.1.imax "i max" "0 2"
    $w.1.1.imax configure -width 8 -fg $etmColors(FACE,imax)
    form_label $w.1.1.jmin "j min" "0 3"
    $w.1.1.jmin configure -width 8 -fg $etmColors(FACE,jmin)
    form_label $w.1.1.jmax "j max" "0 4"
    $w.1.1.jmax configure -width 8 -fg $etmColors(FACE,jmax)
    form_label $w.1.1.kmin "k min" "0 5"
    $w.1.1.kmin configure -width 8 -fg $etmColors(FACE,kmin)
    form_label $w.1.1.kmax "k max" "0 6"
    $w.1.1.kmax configure -width 8 -fg $etmColors(FACE,kmax)
    form_frame $w.1.2 flat 0 "1 0 -pady 3"
    set mc [form_canvas $w.1.2.c 580x100 sunken 3 "0 0" 0 1]
    $w.1.2.c configure -auto none
    for {set i 0} {$i < $last} {incr i} {
      set fr [frame $mc.win$i]
      $mc create window 0 [expr $i * $height] -window $fr -anchor nw
      set name [lindex [lindex $list $i] 1]
      set ii [expr $i + 1]
      form_checkbutton $fr.dom$i "$name" etmRelaxCoeff(show,domain,$i) \
      	"$ii 0" "" "etm_ShowFacesRelaxCoeff $i"
      $fr.dom$i configure -width 11
      set com "etm_SetOneGridExpansionRate imin $type $type2 $i"
      form_checkbutton $fr.imin${i}e "" etmRelaxCoeff(SET,imin,$type,$type2,$i) "$ii 1" "" "$com"
      $fr.imin${i}e configure -width 6
      set com "etm_SetOneGridExpansionRate imax $type $type2 $i"
      form_checkbutton $fr.imax${i}e "" etmRelaxCoeff(SET,imax,$type,$type2,$i) "$ii 2" "" "$com"
      $fr.imax${i}e configure -width 6
      set com "etm_SetOneGridExpansionRate jmin $type $type2 $i"
      form_checkbutton $fr.jmin${i}e "" etmRelaxCoeff(SET,jmin,$type,$type2,$i) "$ii 3" "" "$com"
      $fr.jmin${i}e configure -width 6
      set com "etm_SetOneGridExpansionRate jmax $type $type2 $i"
      form_checkbutton $fr.jmax${i}e "" etmRelaxCoeff(SET,jmax,$type,$type2,$i) "$ii 4" "" "$com" 
      $fr.jmax${i}e configure -width 6
      set com "etm_SetOneGridExpansionRate kmin $type $type2 $i"
      form_checkbutton $fr.kmin${i}e "" etmRelaxCoeff(SET,kmin,$type,$type2,$i) "$ii 5" "" "$com" 
      $fr.kmin${i}e configure -width 6
      set com "etm_SetOneGridExpansionRate kmax $type $type2 $i"
      form_checkbutton $fr.kmax${i}e "" etmRelaxCoeff(SET,kmax,$type,$type2,$i) "$ii 6" "" "$com" 
      $fr.kmax${i}e configure -width 6
    }
  }
  set sh [expr $height * $last]
  set rw [winfo reqwidth $mc]
  $mc configure -scrollregion "0 0 $rw $sh" -width $rw
  if {$sh <= 100} { $mc configure -height [expr $sh - 6] } 
  form_finish +400+400 1 0
}

proc etm_SetOneGridExpansionRate {ijk type type2 dom} {
global etmRelaxCoeff
  set etmRelaxCoeff(SET,$ijk,grid_exp_rate_subf_perp,$dom) $etmRelaxCoeff(SET,$ijk,$type,$type2,$dom)
  set etmRelaxCoeff(SET,$ijk,grid_exp_rate_subf_1,$dom) $etmRelaxCoeff(SET,$ijk,$type,$type2,$dom)
}

proc etm_ShowFacesRelaxCoeff {dom} {
global etmRelaxCoeff etmColors

  set on $etmRelaxCoeff(show,domain,$dom); incr dom
  foreach item { imin imax jmin jmax kmin kmax } {
    etm_ShowFaceIJK $item $dom [string index $item 0] $on $etmColors(FACE,$item)
  }
}

proc etm_ShowFaceRelaxCoeff {which} {
global etmRelaxCoeff

  set on $etmRelaxCoeff(show,$which)
  set what [string index $which 0]
  set end [ic_str_num_entities domain]
  for { set i 1 } { $i <= $end } { incr i } {
    etm_ShowFaceIJK $which $i $what $on
  }
}

proc etm_ShowFaceIJK {which dom what on {color ""}} {

  if {$color == ""} { set color green }
  set subfaces [ic_str_boundaries_of_entity domain $dom]
  foreach number $subfaces {
    set list [ic_str_get_topo_info subface $number 1]
    foreach a $list {
      if {[lindex $a 4] != $dom} { continue }
      set min [lindex $a 5]; set max [lindex $a 6]
      set i_min [lindex $min 0]; set j_min [lindex $min 1]; set k_min [lindex $min 2]
      set i_max [lindex $max 0]; set j_max [lindex $max 1]; set k_max [lindex $max 2]
      if {$which == "imin" || $which == "jmin" || $which == "kmin" } {      
        if {[set ${what}_min] == "1" && [set ${what}_min] == [set ${what}_max]} {
          etm_ShowOneImage subface RelaxCoeff $number $on $color
        }
      } else {
        if {[set ${what}_min] != "1" && [set ${what}_min] == [set ${what}_max]} {
          etm_ShowOneImage subface RelaxCoeff $number $on $color
        }
      }
    }
  }
}

proc etm_CancelMethodsRelaxCoeff {on} {
global etmRelaxCoeff etm
  
  set dom [lindex $etmRelaxCoeff(CUR) 1]
  foreach item [array names etmRelaxCoeff show,*] {
    set etmRelaxCoeff($item) 0    
    if {$dom != "All"} {
      set which [lindex [split $item ,] 2]
      etm_ShowFacesRelaxCoeff $which
    } else {
      set which [lindex [split $item ,] 1]
      etm_ShowFaceRelaxCoeff $which
    }
    unset etmRelaxCoeff($item)
  }  
  top_destroy .relaxcoeff
  if [info exists etm(Entities)] { 
    if {$etm(Entities) == "domain"} {
      etm_ListSelectedEntities domain
    }
  }
}

proc etm_AddGridExpansionRate {} {
global etm etmRelaxCoeff etmList

  set buttons {
    {accept}
  } 
  if [winfo exists .grid_expan] { top_destroy .grid_expan } 
  set w [form_init .grid_expan "Grid expansion rate" "" $buttons] 
  if {$w != ""} {
    form_frame $w.1 ridge 3 "0 0 -pady 3"
    form_label $w.1.1 "Perpendicular direction" "0 0"
    form_entry $w.1.2 etm(grid_exp_rate_subf_perp) float "0 1"
    form_label $w.1.3 "Other direction" "1 0"
    form_entry $w.1.4 etm(grid_exp_rate_subf_1) float "1 1" 
  }   
  form_finish +400+400 1 0
  if [form_wait .grid_expan] {
    set type [lindex $etmRelaxCoeff(CUR) 0]
    set dom [lindex $etmRelaxCoeff(CUR) 1]
    set type2 [lindex $etmRelaxCoeff(CUR) 2]
    if {$dom != "All"} {
      for {set i 0} {$i < [ic_str_num_entities domain]} {incr i} {
        foreach item {imin imax jmin jmax kmin kmax} {
          set ${item}_p $etmRelaxCoeff(SET,$item,grid_exp_rate_subf_perp,$i)
          set ${item}_o $etmRelaxCoeff(SET,$item,grid_exp_rate_subf_1,$i)
        }        
        foreach item {imin imax jmin jmax kmin kmax} {
          if {[set ${item}_p] == 1} {
            set etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_perp,$i) $etm(grid_exp_rate_subf_perp)            
          }
          if {[set ${item}_o] == 1} {
            set etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_1,$i) $etm(grid_exp_rate_subf_1)
          }
        }
      }
    } elseif {$dom == "All"} {
      for {set i 0} {$i < [ic_str_num_entities domain]} {incr i} {
        foreach item {imin imax jmin jmax kmin kmax} {          
          set etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_perp,All) $etm(grid_exp_rate_subf_perp)
          set etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_1,All) $etm(grid_exp_rate_subf_1)
        }
      }
    }
  }
}

proc etm_ApplyMethodsRelaxCoeff {on {explicit ""}} {
global etmRelaxCoeff etmList etm
  
  set type [lindex $etmRelaxCoeff(CUR) 0]
  set dom [lindex $etmRelaxCoeff(CUR) 1]
  set type2 [lindex $etmRelaxCoeff(CUR) 2]
  
  if $on {
    etm_AddGridExpansionRate
  } else {
    for {set i 0} {$i < [ic_str_num_entities domain]} {incr i} {
      foreach item {imin imax jmin jmax kmin kmax} {
        set $item $etmRelaxCoeff(SET,$item,$type,$type2,$i)
        if {[set $item] == 0} {
          set etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_perp,$i) -1
          set etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_1,$i) -1
        }
      }
    }
  }
  if {$dom != "All"} {
    for {set i 0} {$i < [ic_str_num_entities domain]} {incr i} {
      foreach item {imin imax jmin jmax kmin kmax} {
        set $item $etmRelaxCoeff(SET,$item,$type,$type2,$i)
        set ${item}_p $etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_perp,$i)
        set ${item}_o $etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_1,$i)
      }
      if !$on {
        foreach item {imin imax jmin jmax kmin kmax} {
          if {[set $item] == 1} {
            set $item 0
          } else {
            set $item 1
          }
          set etmRelaxCoeff(SET,$item,$type,$type2,$i) [set $item]
          set etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_perp,$i) [set ${item}_p]
          set etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_1,$i) [set ${item}_o]
        }
      } else {
        foreach item {imin imax jmin jmax kmin kmax} {
          set etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_perp,$i) [set ${item}_p] 
          set etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_1,$i) [set ${item}_o]
        }
      }
      set etmList(etmRelaxCoeff,$type,$type2,$i) "$imin $imax $jmin $jmax $kmin $kmax"
      set etmList(grid_exp_rate_subf_perp,$i) "$imin_p $imax_p $jmin_p $jmax_p $kmin_p $kmax_p"
      set etmList(grid_exp_rate_subf_1,$i) "$imin_o $imax_o $jmin_o $jmax_o $kmin_o $kmax_o"
#puts "etmList(grid_exp_rate_subf_perp,$i) == $etmList(grid_exp_rate_subf_perp,$i)"
      if {$explicit != "" || $dom == "Single"} {
        set proc etm_GetSubfaceIJKNumberList
      } else {
        set proc etm_GetSubfaceIJKNumber
      }
      foreach item {imin imax jmin jmax kmin kmax} {
        foreach num [$proc [expr $i + 1] $item] {
          if {[info exists tmp($num)] && $tmp($num)} continue
          if {($explicit != "" && [lsearch $explicit $num] < 0) && $dom != "Single"} continue
          set etm(sf,$num,relaxcoeff) [set $item]
          set etm(sf,$num,grid_exp_rate_subf_perp) [set ${item}_p]
          set etm(sf,$num,grid_exp_rate_subf_1) [set ${item}_o]
          set tmp($num) [set $item]
        }
      } 
    }
  } elseif {$dom == "All"} {
    foreach item {imin imax jmin jmax kmin kmax} {
      set $item $etmRelaxCoeff(SET,$item,$type,$type2,$dom)
      set ${item}_p $etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_perp,$dom)
      set ${item}_o $etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_1,$dom)
    }
    if !$on {
      foreach item {imin imax jmin jmax kmin kmax} {
        if {[set $item] == 1} {
          set $item 0
          set ${item}_p -1
          set ${item}_o -1
        } else {
          set $item 1
          set ${item}_p $etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_perp,$dom)
          set ${item}_o $etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_1,$dom)
        }
        set etmRelaxCoeff(SET,$item,$type,$type2,$dom) [set $item]
        set etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_perp,$dom) [set ${item}_p]
        set etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_1,$dom) [set ${item}_o]
      }
    }
    for {set i 0} {$i < [ic_str_num_entities domain]} {incr i} {
      set etmList(etmRelaxCoeff,$type,$type2,$i) "$imin $imax $jmin $jmax $kmin $kmax"
      set etmList(grid_exp_rate_subf_perp,$i) "$imin_p $imax_p $jmin_p $jmax_p $kmin_p $kmax_p"
      set etmList(grid_exp_rate_subf_1,$i) "$imin_o $imax_o $jmin_o $jmax_o $kmin_o $kmax_o"
      foreach item {imin imax jmin jmax kmin kmax} {
        set etmRelaxCoeff(SET,$item,$type,$type2,$i) [set $item]
        set etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_perp,$i) [set ${item}_p]
        set etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_1,$i) [set ${item}_o]
      }
      foreach item {imin imax jmin jmax kmin kmax} {
        set num [etm_GetSubfaceIJKNumber [expr $i + 1] $item]
        if ![info exists tmp($num)] {
          set etm(sf,$num,relaxcoeff) [set $item]
          set etm(sf,$num,grid_exp_rate_subf_perp) [set ${item}_p]
          set etm(sf,$num,grid_exp_rate_subf_1) [set ${item}_o]
          set tmp($num) 1
        }
      }
    }
  } 
  etm_CancelMethodsRelaxCoeff $on
}

proc etm_CoefficientsSubface {subfaces type on on2 {explicit 0}} {
global etmRelaxCoeff etmList tmp

  if {$type == "CoefficientsSubface2D"} {
    set type "2D"
  } elseif {$type == "CoefficientsSubface3D"} {
    set type "3D"
  }
  set type2 outer
  foreach item $subfaces {
    lappend list [etm_CoefficientsSubfaceIJK $item $on]
  }
  set etmRelaxCoeff(CUR) "$type Domain $type2"
  etm_SetDefaultsRelaxCoeff $type $type2 $on2
  etm_SetDefaultsGridExpansionRate $type $type2
  foreach item $list {
    foreach block $item {
      set dom [expr [lindex $block 0] - 1]
      set ijk [lindex $block 1]
      set etmRelaxCoeff(SET,$ijk,$type,$type2,$dom) $on
      set etmRelaxCoeff(SET,$ijk,grid_exp_rate_subf_perp,$dom) $on
      set etmRelaxCoeff(SET,$ijk,grid_exp_rate_subf_1,$dom) $on
    }
  }
  if $explicit {
      etm_ApplyMethodsRelaxCoeff $on2 $subfaces
  } else {
      etm_ApplyMethodsRelaxCoeff $on2 ""
  }
  foreach item $subfaces { etm_CoefficientsSubfaceIJK $item 0 }
}

proc etm_SetDefaultsRelaxCoeff {type type2 on} { 
  global etmRelaxCoeff

  for {set i 0} {$i < [ic_str_num_entities domain]} {incr i} {
    foreach item {imin imax jmin jmax kmin kmax} {
      if ![info exists etmRelaxCoeff(SET,$item,$type,$type2,$i)] {
        if !$on {
          set etmRelaxCoeff(SET,$item,$type,$type2,$i) 1
        } else {
          set etmRelaxCoeff(SET,$item,$type,$type2,$i) 0
        }
      } else {
        if !$on {
          if $etmRelaxCoeff(SET,$item,$type,$type2,$i) {
            set etmRelaxCoeff(SET,$item,$type,$type2,$i) 0
          } else {
            set etmRelaxCoeff(SET,$item,$type,$type2,$i) 1
          }
        }
      }
    } 
  }
}

proc etm_SetDefaultsGridExpansionRate {type type2} {
global etmRelaxCoeff

  for {set i 0} {$i < [ic_str_num_entities domain]} {incr i} {
    foreach item {imin imax jmin jmax kmin kmax} {
      if ![info exists etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_perp,$i)] {
        set etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_perp,$i) -1
        set etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_1,$i) -1
      }
      set etmRelaxCoeff(SET,$item,grid_exp_rate_subf_perp,$i) 0
      set etmRelaxCoeff(SET,$item,grid_exp_rate_subf_1,$i) 0
    }
  }
}

proc etm_CoefficientsSubfaceIJK { number on } {

  set list ""
  set info [ic_str_get_topo_info subface $number 1]
  foreach a $info {
    set dom [lindex $a 4]; set min [lindex $a 5]; set max [lindex $a 6]
    set i_min [lindex $min 0]; set j_min [lindex $min 1]; set k_min [lindex $min 2]
    set i_max [lindex $max 0]; set j_max [lindex $max 1]; set k_max [lindex $max 2]  
    foreach which { imin imax jmin jmax kmin kmax } {
      set what [string index $which 0]
      if {$which == "imin" || $which == "jmin" || $which == "kmin" } {
        if {[set ${what}_min] == "1" && [set ${what}_min] == [set ${what}_max]} {
          disp_toggle_number_visible subface $number $on
          lappend list "$dom ${what}min"
        }    
      } else {
        if {[set ${what}_min] != "1" && [set ${what}_min] == [set ${what}_max]} {
          disp_toggle_number_visible subface $number $on
          lappend list "$dom ${what}max"
        }
      }      
    }
  }
  return $list
}

proc etm_PlaneSmoothing {dom} {
global etmList etm
 
  if [winfo exists .planesmooth] { top_destroy .planesmooth }
  if {$dom != "All"} { expr $dom - 1 }
  
  for { set i 0 } { $i < [ llength $etmList(Domains) ] } { incr i } {
    if [info exists etmList(SmoothDir)] {
      if {$dom == "All"} {
        set etm(Plane,Var) [lindex $etmList(SmoothDir) $i]
        break
      } else {
        if {$dom == $i} {
          set etm(Plane,Var) [lindex $etmList(SmoothDir) $i]
          break
        }
      }
    } else {
      set etm(Plane,Var) 0
      break
    }
  }
  for { set i 0 } { $i < [ llength $etmList(Domains) ] } { incr i } {
    if [info exists etmList(PlaneSmooth)] {
      if {$dom == "All"} {
        set etm(Plane,Start) [lindex $etmList(PlaneSmooth) [expr $i * 4]]
        set etm(Plane,End) [lindex $etmList(PlaneSmooth) [expr $i * 4 + 1]]
        set etm(Plane,Increment) [lindex $etmList(PlaneSmooth) [expr $i * 4 + 2]]
        set etm(Plane,NSmooth) [lindex $etmList(PlaneSmooth) [expr $i * 4 + 3]]
        break
      } else {
        if {$dom == $i} {
          set etm(Plane,Start) [lindex $etmList(PlaneSmooth) [expr $i * 4]]
          set etm(Plane,End) [lindex $etmList(PlaneSmooth) [expr $i * 4 + 1]]
          set etm(Plane,Increment) [lindex $etmList(PlaneSmooth) [expr $i * 4 + 2]]          
          set etm(Plane,NSmooth) [lindex $etmList(PlaneSmooth) [expr $i * 4 + 3]]          
          break
        }
      }
    }
  }

  set win .planesmooth
  set etm(Plane,Dom) $dom
  set buttons {
    {"Apply" "etm_PlaneSmoothingDone"}
    {"Reset" "etm_PlaneSmoothingReset"}
    {"Planes" "etm_PlaneSmoothingList"}
    {"Cancel" "top_destroy .planesmooth"}
  }
  
  set w [form_init $win "Plane smoothing parameters" "" $buttons] 
  if { $w != "" } {
    form_frame $w.1 ridge 3 "0 0 -pady 3"
    form_label $w.1.1 "Choose \"plane smoothing\" method" "0 0 -padx 3 -pady 3"
    form_frame $w.2 ridge 3 "1 0 -pady 3"
    form_radiobutton $w.2.1 " I  " etm(Plane,Var) 1 "0 0" "" ""
    form_radiobutton $w.2.2 " J  " etm(Plane,Var) 2 "0 1" "" ""
    form_radiobutton $w.2.3 " K  " etm(Plane,Var) 3 "0 2" "" ""
    form_radiobutton $w.2.4 " 3D " etm(Plane,Var) 0 "0 3" "" ""
    form_frame $w.3 ridge 3 "2 0 -pady 3"
    form_label $w.3.1 "Start index   " "0 0 -padx 3 -pady 3"
    form_entry $w.3.1e etm(Plane,Start) float "0 1 -padx 3 -pady 3"
    form_label $w.3.2 "End index     " "1 0 -padx 3 -pady 3"
    form_entry $w.3.2e etm(Plane,End) float "1 1 -padx 3 -pady 3"  
    form_label $w.3.3 "Increment     " "2 0 -padx 3 -pady 3"
    form_entry $w.3.3e etm(Plane,Increment) float "2 1 -padx 3 -pady 3"  
    form_label $w.3.4 "# of vol. iter" "3 0 -padx 3 -pady 3"
    form_entry $w.3.4e etm(Plane,NSmooth) float "3 1 -padx 3 -pady 3"
    if ![string match Windows* [winfo server .]] {
      form_finish -20+20 1 0
    } else {
      form_finish +400+400 1 0
    }
  }
}

proc etm_PlaneSmoothingList {} {
global etm
 
 if [winfo exists .planenumbers] { top_destroy .planenumbers }
  set buttons {
    {"Accept" "etm_PlaneSmoothingListAccept"}
    {cancel}
  }
  if ![info exists etm(PlaneNumbers,$etm(Plane,Dom))] {
    set etm(PlaneNumbers,$etm(Plane,Dom)) ""
  }
  set w [form_init .planenumbers "Plane numbers" "" $buttons] 
  if { $w != "" } {
     form_frame $w.1 ridge 3 "0 0 -pady 3"
     form_text $w.1.1 "Input the plane numbers\nseparated by spaces." \
     	etm(PlaneNumbers,$etm(Plane,Dom)) "0 0" "" 10x20
     form_finish +400+400 1 0
  }
  set etm(PlaneNumbers,win) $w.1.1
}

proc etm_PlaneSmoothingListAccept {} {
global etm etmList

  set data [string trim [form_text_get $etm(PlaneNumbers,win)]]
  set etm(PlaneNumbers,$etm(Plane,Dom)) $data 
  top_destroy .planenumbers
  
  set etmList(PlaneNumbers) ""
  if {$etm(Plane,Dom) == "All"} {
    set len [llength $data]
    if {$len == 0} { return }
    for { set i 0 } { $i < [ llength $etmList(Domains) ] } { incr i } {        
      set numbers "$len "
      foreach item $data {
        append numbers "$item "
      }
      append etmList(PlaneNumbers) "$numbers "
      set etm(PlaneNumbers,$i) $data
    }
  } else {
    for { set i 0 } { $i < [ llength $etmList(Domains) ] } { incr i } {
      foreach item [array names etm PlaneNumbers,$i] {
        set len [llength $etm($item)]
        set numbers "$len "
        foreach num $etm($item) {
          append numbers "$num "
        }
        append etmList(PlaneNumbers) "$numbers "
      }
    }
  }
}

proc etm_PlaneSmoothingDone {} {
global etmList etm
  
  set dom $etm(Plane,Dom)
  if {$etm(Plane,Var) != 0 && ($etm(Plane,Start) < 1 && \
  	$etm(Plane,End) < 1 && $etm(Plane,Increment) < 1)} {
    if {![info exists etmList(PlaneNumbers)] || $etmList(PlaneNumbers) == ""} {
      etm_ShowMessage ERROR "Missing plane numbers."
      return
    }
  } else {
    if {$etm(Plane,Start) < 1 && $etm(Plane,Var) != 0} {
      etm_ShowMessage ERROR "Start index must be greater than 0"
      return
    }
    if {$etm(Plane,End) < $etm(Plane,Start) && $etm(Plane,Var) != 0} {
      etm_ShowMessage ERROR "End index can not be less than start index"
      return   
    }
    if {$etm(Plane,End) < 0 && $etm(Plane,Var) != 0} {
      etm_ShowMessage ERROR "End index must be greater than 0"
      return   
    }
    if {$etm(Plane,Increment) < 1 && $etm(Plane,Var) != 0} {
      etm_ShowMessage ERROR "Increment must be greater than 0"
      return    
    }
  }

  for {set i 0} {$i < [llength $etmList(Domains)]} {incr i} {
    if {$dom == "All"} {
      lappend list $etm(Plane,Var)
      lappend list2 "$etm(Plane,Start) $etm(Plane,End) $etm(Plane,Increment) $etm(Plane,NSmooth)"
    } else {
      if {$dom == $i} {
        lappend list $etm(Plane,Var)
        lappend list2 "$etm(Plane,Start) $etm(Plane,End) $etm(Plane,Increment) $etm(Plane,NSmooth)"
      } else {
        if [info exists etmList(SmoothDir)] {
          lappend list [lindex $etmList(SmoothDir) $i]
          set a [lindex $etmList(PlaneSmooth) [expr $i * 4]]
          set b [lindex $etmList(PlaneSmooth) [expr $i * 4 + 1]]
          set c [lindex $etmList(PlaneSmooth) [expr $i * 4 + 2]]
          set d [lindex $etmList(PlaneSmooth) [expr $i * 4 + 3]]
          lappend list2 "$a $b $c $d"
        } else {
          lappend list 0
          lappend list2 "-1 -1 -1 0"
        }
      }
    }
  }
  set etmList(SmoothDir) $list
  set etmList(PlaneSmooth) $list2
  regsub -all \{ $etmList(PlaneSmooth) "" etmList(PlaneSmooth)
  regsub -all \} $etmList(PlaneSmooth) "" etmList(PlaneSmooth)
  catch { top_destroy .planesmooth }
}


proc etm_PlaneSmoothingReset {} {
global etmList etm
  
  set etm(Plane,Var) 0
  set etm(Plane,Start) -1
  set etm(Plane,End) -1
  set etm(Plane,Increment) -1
  set etm(Plane,NSmooth) 0
  
  for { set i 0 } { $i < [ llength $etmList(Domains) ] } { incr i } {
    lappend list 0
    lappend list2 "$etm(Plane,Start) $etm(Plane,End) $etm(Plane,Increment) $etm(Plane,NSmooth)"
  }
  set etmList(SmoothDir) $list
  set etmList(PlaneSmooth) $list2
  regsub -all \{ $etmList(PlaneSmooth) "" etmList(PlaneSmooth)
  regsub -all \} $etmList(PlaneSmooth) "" etmList(PlaneSmooth)
}

proc etm_done_smooth {} {
global str_type_visible etmSmoother batch_mode etm_runs

  if $batch_mode return
  if ![info exists etm_runs] return
  unset etm_runs
  if ![ic_str_is_loaded] {
    etm_DestroySmootherWindows
    etm_UnsetSelectionsArrays
    etm_UnsetSmootherArrays
    return
  }
  etm_ClearSelections   
  ic_str_glb_sm_init
  set str_type_visible(domain) 1
  disp_change_overall_visible domain
  for {set i 0} {$i < [ic_str_num_entities domain]} {incr i} {
    ic_str_highlight domain [expr $i + 1] 0
  }
  etm_UnsetSmootherArrays
  etm_DestroySmootherWindows
  trace vdelete etmSmoother(DisplayOn) w "etm_SetDisplayOnOff; list"
}

proc etm_UnsetSmootherArrays {} {

  foreach v { etm etmTemp etmFaces etmFlag etmSmoother etmChanges etmVar \
              etmList etmMethod etmParam etmImage etmImageZone etmPost \
              etmRelaxCoeff } {
    etm_UnsetArray $v
  }
}

proc etm_DestroySmootherWindows {} {
  
  if [ winfo exists .methods ] { top_destroy .methods }
  if [ winfo exists .postsm ] { top_destroy .postsm }
  if [ winfo exists .rzm ] { top_destroy .rzm } 
  if [ winfo exists .facem ] { top_destroy .facem } 
  if [ winfo exists .efi ] { top_destroy .efi }  
  if [ winfo exists .slem ] { top_destroy .slem }  
  if [ winfo exists .brs ] { top_destroy .brs }
  if [ winfo exists .predefined ] { top_destroy .predefined }
  if [ winfo exists .smpara ] { top_destroy .smpara }
  if [ winfo exists .planesmooth ] { top_destroy .planesmooth }
  if [ winfo exists .relaxcoeff ] { top_destroy .relaxcoeff }
  if [ winfo exists .planenumbers ] { top_destroy .planenumbers }
  if [ winfo exists .unseldom ] { top_destroy .unseldom }
  if [ winfo exists .smparaexpert ] { top_destroy .smparaexpert }
  if [ winfo exists .postparams ] { top_destroy .postparams }
}

proc etm_ShowMessage { what mess } {
global tmp

  if [winfo exists .etmquest] { top_destroy .etmquest }
  set tmp(ok) 0
  set buttons {
    {"OK" "set tmp(ok) 1"}
  }
  set d [form_init .etmquest "$what" "" $buttons]
  if {$d != ""} {
    form_frame $d.1 ridge 3 "0 0"
    form_label $d.1.1 "$mess" "0 0"
    $d.1.1 configure -bg white
    form_finish +400+400
  }
  tkwait variable tmp(ok)
  form_kill .etmquest
}

proc etm_ShowQuestion { what mess } {
global tmp

  if [winfo exists .etmquest] { top_destroy .etmquest }
  set tmp(ok) 0
  set buttons {
    {"OK" "set tmp(ok) 1"}
    {"Cancel" "set tmp(ok) 0"}
  }
  set d [form_init .etmquest "$what" "" $buttons]
  if {$d != ""} {
    form_frame $d.1 ridge 3 "0 0"
    form_label $d.1.1 "$mess" "0 0"
    $d.1.1 configure -bg white
    form_finish +400+400
  }
  tkwait variable tmp(ok)
  form_kill .etmquest
  return $tmp(ok)
}

proc etm_ShowHybridWin { what number who } {
global etmParam etm tmp

  if { $what == "Hilgenstock Hybrid" } {
    set what "Hilgenstock"
  } elseif { $what == "Sorenson Hybrid" } {
    set what "Sorenson"
  }   
  if ![info exists etm(varHybrid)] {
    set etm(varHybrid) "$what - Thomas & Middlecoff"
  }
  set buttons {
    {"Apply" "set tmp(done) apply"}
    {"Cancel" "set tmp(done) cancel"}
  }
  set win .hybrid
  set w [form_init $win "$what" "" $buttons] 
  if { $w != "" } {
    form_frame $w.1 ridge 3 "0 0 -pady 3"
    form_label $w.1.1 "Choose hybrid method" "0 0 -padx 3 -pady 3"
    form_frame $w.2 ridge 3 "1 0 -pady 3"
    form_radiobutton $w.2.1 "Hybrid Thomas & Middlecoff" etm(varHybrid) \
    	"$what - Thomas & Middlecoff" "0 0" "" ""
    form_radiobutton $w.2.2 "Hybrid Laplace" etm(varHybrid) \
    	"$what - Laplace" "1 0" "" ""
    form_finish +400+400 1 0
  }
  grab set $win
  tkwait variable tmp(done)
  if {$tmp(done) != "cancel"} {
    if { $who == 2 } {
      set etmParam(2D,$number) $etm(varHybrid)
    } elseif { $who == 3 } {
      set etmParam(3D,$number) $etm(varHybrid)
    } elseif { $who == 4 } {
      set etmParam(Unselected,$number) $etm(varHybrid)
    }
  } 
  set value $tmp(done)
  grab release $win
  top_destroy $win
  return $value
}

proc etm_SubfaceLayersWin { what list } {
global etmMode etmList etmColors etm

  if [ winfo exists .slem ] {
    unset etmList(TEMP,SubfaceLayers)
    top_destroy .slem
  }  
  set etmList(TEMP,SubfaceLayers) $list
  if [info exists etmList(APPLY,SubfaceLayers)] {
    foreach item $etmList(APPLY,SubfaceLayers) {
      set i 0
      set found 0
      foreach var $list {
        if [string match [lindex $item 0] [lindex $var 0]] {
          etm_OneSubfaceLayers $i [lindex $item 1]
          set found 1
          break
        }
        incr i
      }
      if !$found {
        lappend etmList(TEMP,SubfaceLayers) [list [lindex $item 0] [lindex $item 1] \
        				    [lindex $item 2 ] 0]
        set number [lindex $item 0]
        etm_ShowOneImage subface LayerExtensionSubface $number 1 $etmColors($what)
      }
    }
  }
  set etmList(TEMP,SubfaceLayers) [lsort $etmList(TEMP,SubfaceLayers)]
  set buttons {
    {"Apply" "etm_ApplySubfaceLayers"}
    {"Reset" "etm_ClearSubfaceLayers"}
    {"Done" "etm_ExitSubfaceLayers"}
  }
  set win .slem
  set w [form_init $win "Layers extension method" "" $buttons] 
  if { $w != "" } {
    form_frame $w.1 ridge 3 "0 0"
    form_label $w.1.1 "Choose type of layer extension method" "0 0"    
    form_frame $w.2 ridge 3 "1 0"
    form_label $w.2.1 "Subface #" "0 0"
    set proc etm_AllSubfaceLayers
    form_button $w.2.2 "Default" "$proc Default" "0 1" ""
    form_button $w.2.3 "Neighbor" "$proc Neighbor" "0 2" ""
    form_button $w.2.4 "Symmetric" "$proc Symmetric" "0 3" ""
    form_button $w.2.5 "Orthogonal" "$proc Orthogonal" "0 4" ""
    form_button $w.2.6 "Linear" "$proc Linear" "0 5" ""
    form_button $w.2.7 "Ortho-Lin" "$proc Ortho_Lin" "0 6" ""
    form_button $w.2.8 "Symm-Lin" "$proc Symm_Lin" "0 7" ""
    foreach i { 1 2 3 4 5 6 7 8 } {
      $w.2.$i configure -width 10
    }
    form_frame $w.3 ridge 3 "2 0"
    set win [form_canvas $w.3.c 800x200 sunken 3 "0 0" 0 1]
    set etm(Layers,Canvas) $win
    set i 0
    set proc etm_OneSubfaceLayers
    set height 20
    set width 8
    foreach var $etmList(TEMP,SubfaceLayers) { 
      frame $win.frame$i -relief flat
      $win create window 0 [expr $i * $height] -window $win.frame$i -anchor nw
      form_label $win.frame$i.label$i [lindex $var 0] "$i 0"
      $win.frame$i.label$i configure -width 15
      form_radiobutton $win.frame$i.a$i "" layerType_$i Default "$i 1" "" "$proc $i Default"
      $win.frame$i.a$i configure -width $width
      form_radiobutton $win.frame$i.b$i "" layerType_$i Neighbor "$i 2" "" "$proc $i Neighbor"
      $win.frame$i.b$i configure -width $width
      if {[lindex $var 2] == 0} {
        $win.frame$i.b$i configure -relief flat -state disabled
      }
      form_radiobutton $win.frame$i.c$i "" layerType_$i Symmetric "$i 3" "" "$proc $i Symmetric"
      $win.frame$i.c$i configure -width $width
      form_radiobutton $win.frame$i.d$i "" layerType_$i Orthogonal "$i 4" "" "$proc $i Orthogonal"
      $win.frame$i.d$i configure -width $width
      form_radiobutton $win.frame$i.e$i "" layerType_$i Linear "$i 5" "" "$proc $i Linear"
      $win.frame$i.e$i configure -width $width
      form_radiobutton $win.frame$i.f$i "" layerType_$i Ortho_Lin "$i 6" "" "$proc $i Ortho_Lin"
      $win.frame$i.f$i configure -width $width
      form_radiobutton $win.frame$i.g$i "" layerType_$i Symm_Lin "$i 7" "" "$proc $i Symm_Lin"
      $win.frame$i.g$i configure -width $width
      if {[lindex $var 1] == "Default"} {
        $win.frame$i.a$i select
      } elseif {[lindex $var 1] == "Neighbor"} {
        $win.frame$i.b$i select
      } elseif {[lindex $var 1] == "Symmetric"} {
        $win.frame$i.c$i select      
      } elseif {[lindex $var 1] == "Orthogonal"} {
        $win.frame$i.d$i select
      } elseif {[lindex $var 1] == "Linear"} {
        $win.frame$i.e$i select      
      } elseif {[lindex $var 1] == "Ortho_Lin"} {
        $win.frame$i.f$i select
      } elseif {[lindex $var 1] == "Symm_Lin"} {
        $win.frame$i.g$i select
      } 
      incr i
    }   
    set rw [winfo reqwidth $win]
    $win configure -scrollregion "0 0 $rw [expr $i * $height]" -width $rw
    form_finish +400+400 1 0
  }
}

proc etm_ApplySubfaceLayers {} {
global etmList etmMode

  foreach item $etmList(TEMP,SubfaceLayers) {
    etm_SetLayerExtensionNo 1 [lindex $item 0] $etmMode(Subface[lindex $item 1]) 1.0
  }
  set etmList(APPLY,SubfaceLayers) $etmList(TEMP,SubfaceLayers)
  etm_ExitSubfaceLayers
}

proc etm_OneSubfaceLayers { i value } {
global etmList

  set var [lindex $etmList(TEMP,SubfaceLayers) $i]
  set newValue [list [lindex $var 0] $value [lindex $var 2] [lindex $var 3]]
  set etmList(TEMP,SubfaceLayers) [lreplace $etmList(TEMP,SubfaceLayers) $i $i $newValue]
}

proc etm_AllSubfaceLayers { what } {
global etmMode etmList etm

  set win $etm(Layers,Canvas)
  set list ""
  for { set i 0 } { $i < [llength $etmList(TEMP,SubfaceLayers)] } { incr i } {
    set var [lindex $etmList(TEMP,SubfaceLayers) $i]
    if { $what == "Default" } {
      $win.frame$i.a$i select
    } elseif { $what == "Neighbor" } {
      if [lindex $var 3] {
        $win.frame$i.b$i select
      } else {
        continue
      }
    } elseif { $what == "Symmetric" } {
      $win.frame$i.c$i select
    } elseif { $what == "Orthogonal" } {
      $win.frame$i.d$i select
    } elseif { $what == "Linear" } {
      $win.frame$i.e$i select
    } elseif { $what == "Ortho_Lin" } {
      $win.frame$i.f$i select
    } elseif { $what == "Symm_Lin" } {
      $win.frame$i.g$i select
    } 
    lappend list [list [lindex $var 0] $what [lindex $var 2] [lindex $var 3]]
  }
  if {[llength $list ] > 0} {
    set etmList(TEMP,SubfaceLayers) $list
  }
}

proc etm_ClearSubfaceLayers {} {
global etmList etmLayerExtensionNo etm

  foreach item [ array name etmLayerExtensionNo ] {
    etm_SetLayerExtensionNo 0 [lindex $etmLayerExtensionNo($item) 0]
  }
  set win $etm(Layers,Canvas)
  for { set i 0 } { $i < [ llength $etmList(TEMP,SubfaceLayers) ] } { incr i } {
    etm_OneSubfaceLayers $i Default
    $win.frame$i.a$i select
  }
  catch { unset etmList(APPLY,SubfaceLayers) }
}

proc etm_ExitSubfaceLayers {} {
global etmList etmColors etmSmoother
  
  foreach item $etmList(TEMP,SubfaceLayers) {
    etm_ShowOneImage subface LayerExtensionSubface [lindex $item 0] 0 gray
  }
  if [ info exists etmList(APPLY,SubfaceLayers) ] {
    foreach item $etmList(APPLY,SubfaceLayers) {
      etm_ShowOneImage subface LayerExtensionSubface [lindex $item 0] \
      	1 $etmColors(LayerExtensionSubface)
    }
  } else {
    foreach item [ array name etmList APPLY,FAM_LayerExtensionSubface,* ] {
      unset etmList($item) 
    }
  }
  
  etm_ClearView 
  unset etmList(TEMP,SubfaceLayers)
  set etmSmoother(DisplayOn) 1
  top_destroy .slem
}

proc etm_IsDomainActive {} {
global etmFlag

  foreach i [ array names etmFlag ] {
    if $etmFlag($i) {
      return 1
    }
  }
  return 0
}

proc etm_SetChildState { win } {
  
  foreach child [ winfo children $win ] {
    foreach child2 [ winfo children $child ] {
      if [ string match [ winfo class $child2 ] "Checkbutton" ] {
        $child2 deselect
      }
      if [ string match [ winfo class $child2 ] "Label" ] {
        $child2 configure -text " "
      }
    }
  }
}

proc etm_SmoothingParameter {} {
global etm guibase_dir etmSmoother etmMethod etmParam

  if [winfo exists .smpara] { top_destroy .smpara } 
  set buttons {
    {"Accept" "etm_AcceptSmoothingParameter"}
    {reset}
    {cancel}
  }  
  set w [form_init .smpara "Smoothing parameters" "" $buttons]
  if { $w != "" } {
    set row 1
    form_frame $w.1 ridge 3 "0 0 -pady 3"
    form_label $w.1.1 "Navier-Stokes Rel." "$row 0 -padx 3 -pady 3"
    form_entry $w.1.1e etm(NsRel) float "$row 1 -padx 3 -pady 3"
    incr row
    form_label $w.1.2 "Projection limit" "$row 0 -padx 3 -pady 3"
    form_entry $w.1.2e etm(ProjLimit) float "$row 1 -padx 3 -pady 3"
    incr row
    form_label $w.1.3 "Angle: fix vertices on freeze edges" "$row 0 -padx 3 -pady 3"
    form_entry $w.1.3e etm(AngleFreezeEdges) float "$row 1 -padx 3 -pady 3"
    incr row
    form_label $w.1.9 "Relaxation factor" "$row 0 -padx 3 -pady 3"
    form_entry $w.1.9e etm(relaxation_factor) float "$row 1 -padx 3 -pady 3"
    incr row
    form_label $w.1.4 "Number of constraint steps" "$row 0 -padx 3 -pady 3"
    form_entry $w.1.4e etm(Nsteps) float "$row 1 -padx 3 -pady 3"
    if !$etmSmoother(2D) {
      incr row
      form_label $w.1.5 "Max. multigrid levels" "$row 0 -padx 3 -pady 3"
      form_entry $w.1.5e etm(Maxlevel) float "$row 1 -padx 3 -pady 3"
    }
    incr row   
    form_label $w.1.6 "Residual factor" "$row 0 -padx 3 -pady 3"
    form_entry $w.1.6e etm(StopResidual) float "$row 1 -padx 3 -pady 3"
    incr row
    form_label $w.1.7 "Grid expansion rate (faces)" "$row 0 -padx 3 -pady 3"
    form_entry $w.1.7e etm(grid_exp_face) float "$row 1 -padx 3 -pady 3"
    incr row
    form_label $w.1.8 "Grid expansion rate (volume)" "$row 0 -padx 3 -pady 3"
    form_entry $w.1.8e etm(grid_exp_vol) float "$row 1 -padx 3 -pady 3"
    
    form_frame $w.2 ridge 3 "1 0 -pady 3"
    form_checkbutton $w.2.1 "Post smoothing (Single)" etm(InnVol) \
    	"1 0 -padx 3 -ipadx 2 -ipady 2" "" "" 
    form_checkbutton $w.2.2 "Surface fitting" etm(Sfit) \
    	"1 1 -padx 3 -ipadx 2 -ipady 2" "" "" 
    form_checkbutton $w.2.3 "Conditional smoothing" etm(Conditional) \
    	"2 0 -padx 3 -ipadx 2 -ipady 2" "" "" 
    form_checkbutton $w.2.4 "Check determinants" etm(CheckDet) \
    	"2 1 -padx 3 -ipadx 2 -ipady 2" "" "" 
###    form_checkbutton $w.2.5 "Check projection at start" etm(FixFam) "3 0 -padx 3 -ipadx 2 -ipady 2" "" "" 
    form_checkbutton $w.2.6 "Use projection" etm(SmoothOnFaces) \
    	"3 0 -padx 3 -ipadx 2 -ipady 2" "" "" 
    $w.2.6 configure -onvalue 0 -offvalue 1
    form_checkbutton $w.2.7 "Use orthogonal positioning" etm(use_orthog_position) \
    	"3 1 -padx 3 -ipadx 2 -ipady 2" "" "" 
    if !$etmSmoother(2D) {
      form_checkbutton $w.2.8 "Use multigrid for 2d" etm(Multigrid2D) \
      	"4 0 -padx 3 -ipadx 2 -ipady 2" "" "" 
    }
    form_checkbutton $w.2.9 "Use fractional positioning" etm(use_fract_position) \
    	"4 1 -padx 3 -ipadx 2 -ipady 2" "" "" 
    	
    if $etmSmoother(2D) {
      set command etm_SetAllMethods_2D
      set methods $etmMethod(2D)
      set type 2D
    } else {
      set command etm_SetAllMethods_3D
      set methods $etmMethod(3D)
      set type 3D
    }
    form_frame $w.3 ridge 3 "2 0 -pady 3"
    form_menubutton $w.3.1 "Volume method" $w.3.1.m "0 0 -padx 3 -ipadx 2 -ipady 2"
    $w.3.1 configure -relief raised -bd 3 -indicatoron 1 -width 13
    menu $w.3.1.m -tearoff 0
    foreach item $methods {
      if {[string match "Sorenson *" $item]} {
        $w.3.1.m add command -label "Sorenson Hybrid..." -command "$command [list $item]"
      } else {
        if {[ string match "Hilgenstock *" $item ]} {
          $w.3.1.m add command -label "Hilgenstock Hybrid..." -command "$command [list $item]"
        } else {
          $w.3.1.m add command -label "$item" -command "$command [list $item]"
        }
      }
    }
    form_label $w.3.2 "" "0 1 -padx 3 -pady 3"
    set text $etmParam($type,0)
    regsub -all \{ $text "" text; regsub -all \} $text "" text
    $w.3.2 configure -width 30 -text "$text" -bg white
    if !$etmSmoother(2D) {
      set command etm_SetAllFaceMethods_3D
      form_frame $w.4 ridge 3 "3 0 -pady 3"
      form_menubutton $w.4.1 "Face method" $w.4.1.m "0 0 -padx 3 -ipadx 2 -ipady 2"
      $w.4.1 configure -relief raised -bd 3 -indicatoron 1 -width 13
      menu $w.4.1.m -tearoff 0    
      foreach item $methods {
        if {[string match "Sorenson *" $item]} {
          $w.4.1.m add command -label "Sorenson Hybrid..." -command "$command [list $item]"
        } else {
          if {[ string match "Hilgenstock *" $item ]} {
            $w.4.1.m add command -label "Hilgenstock Hybrid..." -command "$command [list $item]"
          } else {
            $w.4.1.m add command -label "$item" -command "$command [list $item]"
          }
        }
      }
      form_label $w.4.2 "" "0 1 -padx 3 -pady 3"
      set text $etmParam(2D,0)
      regsub -all \{ $text "" text; regsub -all \} $text "" text
      $w.4.2 configure -width 30 -text "$text" -bg white
    }    
    if ![string match Windows* [winfo server .]] {
      form_finish -20+20 1 0
    } else {
      form_finish +400+400 1 0
    }
  }
  catch { wm resizable $win 0 0 }     
  catch { wm deiconify $win }
}

proc etm_AcceptSmoothingParameter {} {
global etm
  
  if [winfo exists .smpara] { top_destroy .smpara } 
  if [info exists etm(Entities)] {
    etm_ListSelectedEntities $etm(Entities)
  }
}

proc etm_SmoothingParameterExpert {} {
global env etm etmSmoother

  if [winfo exists .smparaexpert] { top_destroy .smparaexpert }  
  set buttons {
    {accept}
    {reset}
    {cancel}
  }   
  set w [form_init .smparaexpert "Expert parameters" "" $buttons]
  if { $w != "" } {
    set row 1
    form_frame $w.1 flat 1 "0 0 -pady 3"
    form_menubutton $w.1.1 "Unselected domains" $w.1.1.m "0 0 -padx 3 -ipadx 3 -ipady 2"
    $w.1.1 configure -relief raised -indicatoron 1 -width 20
    menu $w.1.1.m -tearoff 0
    $w.1.1.m add command -label "All domains" -command "etm_UnselectedDomainsAll"
    $w.1.1.m add command -label "One domain" -command "etm_UnselectedDomainsSingle"
    if {[info exists env(ICEM_LAYER_METHODS)] && !$etmSmoother(2D)} {
      if ![info exists etm(overall_visible,subface)] {
        busy 1
        disp_change_overall_visible subface
        set etm(overall_visible,subface) 1
        busy 0
      }
      form_menubutton $w.1.2 "Layers Methods" $w.1.2.m "0 1 -padx 3 -ipadx 3 -ipady 2"
      $w.1.2 configure -relief raised -indicatoron 1 -width 20
      menu $w.1.2.m -tearoff 0
      set com "etm_SelectObjects subface"
      set type LayerExtensionSubface
      $w.1.2.m add command -label "All Blockinterfaces" -command "$com Blockinterfaces $type"
      $w.1.2.m add command -label "All Boundaries" -command "$com Boundaries $type"
      $w.1.2.m add command -label "None" -command "$com None $type"
      $w.1.2.m add command -label "Select" -command "$com Select $type"
      $w.1.2.m add command -label "By families..." -command "$com Families $type" 
    }
    form_frame $w.2 flat 1 "1 0"
    form_label $w.2.1 "# of iterations in global edge smoothing" "0 0 -padx 3 -pady 3"
    form_entry $w.2.1e etm(n_iter_glb) float "0 1 -padx 3 -pady 3"    
    form_label $w.2.2 "# of steps in global edge-vertex smoothing" "1 0 -padx 3 -pady 3"
    form_entry $w.2.2e etm(n_steps_glb) float "1 1 -padx 3 -pady 3"
    
    form_label $w.2.3 "Absolute distance from blade boundary" "2 0 -padx 3 -pady 3"
    form_entry $w.2.3e etm(abs_dist_bnd) float "2 1 -padx 3 -pady 3"    
    form_label $w.2.4 "Number of nodes in absolute distance" "3 0 -padx 3 -pady 3"
    form_entry $w.2.4e etm(n_points_abs_dist_bnd) int "3 1 -padx 3 -pady 3"
    form_label $w.2.5 "Number of processors to use" "4 0 -padx 3 -pady 3"
    form_entry $w.2.5e etm(use_pthreads) int "4 1 -padx 3 -pady 3"
#   form_checkbutton $w.2.5 "Use parallel processing" etm(use_pthreads) \
#   	"4 0 -padx 3 -pady 3" "" "" 
    
    if ![string match Windows* [winfo server .]] {
      form_finish -20+20 1 0
    } else {
      form_finish +400+400 1 0
    }
  }
  catch { wm resizable $win 0 0 }     
  catch { wm deiconify $win }
}

proc etm_PostParameters {} {
global etm etmMode etmPost etmSmoother
  
  if [ winfo exists .postparams ] { top_destroy .postparams }
  if [ winfo exists .postsm ] { top_destroy .postsm }
  set buttons {
    {accept}
    {reset}
    {cancel}
  }
  set win .postparams
  set w [form_init $win "Post parameters" "" $buttons]
  if {$w != ""} {
    form_frame $w.1 ridge 3 "0 0 -pady 3"
    form_frame $w.1.1 flat 0 "1 0 -pady 3"
    if !$etmSmoother(2D) {
      form_label $w.1.1a "Violate geometry edges" "0 0 -padx 3 -pady 3"
      form_frame $w.1.1.1 flat 1 "0 0 -pady 3"
      form_label $w.1.1.1.1a "Perform" "0 0 -padx 3 -pady 3"
      if {$etm(TypePostSm) == $etmMode(PostSelectAll)} {
        set violate "All include violate"
      } elseif {$etm(TypePostSm) == $etmMode(PostSelectAllExclViol)} {
        set violate "All exclude violate"
      } elseif {$etm(TypePostSm) == $etmMode(PostSelectConcentrViol)} {
        set violate "Concentrate violate"
      }
      form_menubutton $w.1.1.1.1 "$violate" $w.1.1.1.1.m \
      		"0 1 -padx 3 -ipadx 2 -ipady 2"   
      $w.1.1.1.1 configure -relief raised -bd 2 -indicatoron 1 -width 17
      menu $w.1.1.1.1.m -tearoff 0
      set type TypePostSm
      set mode PostSelectAll
      set m $w.1.1.1.1
      $w.1.1.1.1.m add radiobutton -label "All include violate" \
      		-variable etm($type) -value $etmMode($mode) \
      		-command "etm_SetPostLabels $m \"All include violate\""
      set mode PostSelectAllExclViol
      $w.1.1.1.1.m add radiobutton -label "All exclude violate" \
      		-variable etm($type) -value $etmMode($mode) \
      		-command "etm_SetPostLabels $m \"All exclude violate\""
      set mode PostSelectConcentrViol
      $w.1.1.1.1.m add radiobutton -label "Concentrate violate" \
      		-variable etm($type) -value $etmMode($mode) \
      		-command "etm_SetPostLabels $m \"Concentrate violate\""      
      form_label $w.1.1.1.1b "Selected" "1 0 -padx 3 -pady 3"
      form_frame $w.1.1.1.1f flat 0 "1 1"
      form_button $w.1.1.1.1f.1a "Show" "etm_ShowSelectedImagesZones EdgeViolate" \
      		"0 0 -padx 3" ""
      $w.1.1.1.1f.1a configure -bd 2 -width 9
      form_button $w.1.1.1.1f.1b "Clear" "etm_ClearViolateEdge" \
      		"0 1 -padx 3" ""
      $w.1.1.1.1f.1b configure -bd 2 -width 9
    } else {
      form_frame $w.1.1.1 flat 1 "0 0 -pady 3"
      form_label $w.1.1.1.1 "Criterion Determinant" "0 0 -pady 3"
    }
        
    if !$etmSmoother(2D) {
      if {$etm(TypeImprove) == $etmMode(CriterionDeterminant)} {
        set criterion "Determinant"
      } elseif {$etm(TypeImprove) == $etmMode(CriterionOrthogonality)} {
        set criterion "Orthogonality"
      } elseif {$etm(TypeImprove) == $etmMode(CriterionWarp)} {
        set criterion "Warp"
      } elseif {$etm(TypeImprove) == $etmMode(CriterionQuality)} {
        set criterion "Quality"
      } elseif {$etm(TypeImprove) == $etmMode(CriterionSkewness)} {
        set criterion "Skewness"
      }
      form_frame $w.1.1.2 ridge 3 "1 0 -pady 3"
      form_label $w.1.1.2.3a "Criterion" "0 0 -padx 3 -pady 3"
      form_menubutton $w.1.1.2.3 "$criterion" $w.1.1.2.3.m \
      		"0 1 -padx 3 -ipadx 2 -ipady 2 -pady 3"   
      $w.1.1.2.3 configure -relief raised -bd 2 -indicatoron 1 -width 15
      menu $w.1.1.2.3.m -tearoff 0
      set type TypeImprove
      set crit CriterionDeterminant
      set m $w.1.1.2.3
      $w.1.1.2.3.m add radiobutton -label "Determinant" \
      		-variable etm($type) -value $etmMode($crit) \
      		-command "etm_SetPostLabels $m Determinant"
      set crit CriterionOrthogonality
      $w.1.1.2.3.m add radiobutton -label "Orthogonality" \
      		-variable etm($type) -value $etmMode($crit) \
      		-command "etm_SetPostLabels $m Orthogonality"
      set crit CriterionWarp
      $w.1.1.2.3.m add radiobutton -label "Warp" \
      		-variable etm($type) -value $etmMode($crit) \
      		-command "etm_SetPostLabels $m Warp"
      set crit CriterionQuality
      $w.1.1.2.3.m add radiobutton -label "Quality" \
      		-variable etm($type) -value $etmMode($crit) \
      		-command "etm_SetPostLabels $m Quality"
      set crit CriterionSkewness
      $w.1.1.2.3.m add radiobutton -label "Skewness" \
      		-variable etm($type) -value $etmMode($crit) \
      		-command "etm_SetPostLabels $m Skewness"
    }
    form_frame $w.1.1.3 ridge 3 "2 0 -pady 3"
    form_checkbutton $w.1.1.3.1 "Group bad elements" etm(GroupBadElem) \
    		"0 0 -pady 3" "" "" 
    
    if ![string match Windows* [winfo server .]] {
      form_finish -20+20 1 0
    } else {
      form_finish +400+400 1 0
    }
  }
}

proc etm_SetPostLabels {win text} {

  $win configure -text "$text"
  if [winfo exists .postsm] {
    etm_PostWin    
  }
}

proc etm_SetArrow { arrow what var } {
global $what

  switch $arrow {
    Up {
      set $what\($var) [ expr { [ set $what\($var) ] + 1 } ]
    }
    Down {
      set $what\($var) [ expr { [ set $what\($var) ] - 1 } ]
      if { [ set $what\($var) ] < 1 } {
        beep
        set $what\($var) 1
      }
    }
  }
}

proc etm_DefaultParameter {} {
global etm etmParam 

  set etm(Niter) 1
  set etm(Nsteps) 1
  set etm(Maxlevel) 3
  set etm(InnVol) 0
  set etm(Sfit) 1
  set etm(Conditional) 0
  set etm(CheckDet) 0
  set etm(Damping) 1
  set etm(WedgeCheck) 1
  set etm(Multigrid2D) 0
  set etm(ReducedEdge) 0
  set etm(FixFam) 0
  set etm(VertexFix) 1
  set etm(EdgeFreeze) 1
  set etm(NsRel) 0.0
  set etm(AngleFreezeEdges) 5.0
  set etm(nItera) 25
  set etm(ProjLimit) 0.0
  set etm(InterpFaces) 0
  set etm(InterpVolumes) 0
  set etm(BaseSubfacesNo) ""
  set etm(DirectionVector) ""
  set etm(SubfaceExtend) 0
  set etm(SmoothOnFaces) 1
  set etm(MinResidual) 3.0
  set etm(StopResidual) 0.05
  set etm(n_iter_glb) 25
  set etm(n_steps_glb) 25  
  set etm(grid_exp_face) 3.5
  set etm(grid_exp_vol) 4.6
  set etm(abs_dist_bnd) -1.0
  set etm(n_points_abs_dist_bnd) -1
  set etm(use_pthreads) 4
  set etm(vertex_layer_dist) -1
  set etm(vertex_layer_angle) -1
  set etm(relaxation_factor) 0.5
  set etm(use_orthog_position) 0
  set etm(use_fract_position) 0
  set etm(grid_exp_rate_subf_perp) -1
  set etm(grid_exp_rate_subf_1) -1
  set etm(first_cell_height) -1
  set etm(last_cell_height) -1
    
  if ![info exists etm(Plane,Start)] { set etm(Plane,Start) -1 }
  if ![info exists etm(Plane,End)] { set etm(Plane,End) -1 }
  if ![info exists etm(Plane,Increment)] { set etm(Plane,Increment) -1 }
  if ![info exists etm(Plane,NSmooth)] { set etm(Plane,NSmooth) 0 }

  if ![info exists etm(batch)] {
    for {set i 0 } {$i < [ic_str_num_entities domain]} {incr i} {
      set etmParam(2D,$i) "Sorenson - Laplace"
      set etmParam(3D,$i) "Sorenson - Laplace"
    }

    if [winfo exists .smpara.main.3.2] {
      global etmSmoother
      if $etmSmoother(2D) {
        set type 2D
      } else {
        set type 3D
      }
      .smpara.main.3.2 configure -text $etmParam($type,0)
    }
    if [winfo exists .smpara.main.4.2] {
      .smpara.main.4.2 configure -text $etmParam(2D,0)
    }
  }
}

proc etm_DefaultParameterPost {} {
global etm
  
  set etm(ThresholdDet) "30.00000"
  set etm(ThresholdAngle) "80.00000"
  set etm(TypeImprove) 0
  set etm(TypePostSm) 2
  set etm(GroupBadElem) 0
}

proc etm_GetArrayChanges { set what } {
global etmChanges etmList etm

  if { $set == "Set" } {
    set etmChanges(what) $what
  } elseif { $set == "Get" } {
    if ![ info exists etmChanges ] {
      return 1
    }  
    if { $etmChanges(what) != "$what" } {
      return 1
    }
  }  
 
  foreach item { SmoothDomain FaceMethods VolumeMethods etmLayerExtensionNo \
  		 etmLayerExtensionIJK etmEdgeAttr etmEdgeGlobal \
  		 etmRelaxSubface etmRelaxZone etmViolGeomZone  \
  		 etmViolGeomSubface etmMeshingLawPar etmRegion SmoothDir \
  		 PlaneSmooth relax_weights_2d relax_weights_3d \
  		 relax_weights_inner_2d relax_weights_inner_3d etmRelaxZoneAdd \
  		 PlaneNumbers abs_dist_subf n_abs_dist_subf VertexLayer \
  		 grid_exp_rate_subf_perp grid_exp_rate_subf_1} {
    if { $set == "Set" } {
      set etmChanges($item) $etmList($item)
    } elseif { $set == "Get" } {
      if { ($etmChanges($item) != $etmList($item)) } {
        return 1
      }
    }
  }
  
  foreach item { Niter Nsteps Maxlevel Sfit Conditional CheckDet Damping \
                 VertexFix EdgeFreeze WedgeCheck FixFam InnVol SmoothOnFaces \
                 NsRel AngleFreezeEdges nItera InterpFaces InterpVolumes \
  		 ThresholdDet ThresholdAngle BaseSubfacesNo SubfaceExtend \
  		 DirectionVector TypePostSm ProjLimit GroupBadElem \
                 Multigrid2D ReducedEdge n_iter_glb n_steps_glb \
                 grid_exp_face grid_exp_face MinResidual StopResidual \
                 abs_dist_bnd n_points_abs_dist_bnd relaxation_factor \
                 use_orthog_position use_fract_position} {
    if { $set == "Set" } {
      set etmChanges($item) $etm($item)
    } elseif { $set == "Get" } {
      if { ($etmChanges($item) != $etm($item)) } {
        return 1
      }
    }    
  }
  return 0
}

proc etm_SelectObjects { mode what type } {
global etmSmoother

  set etmSmoother(DisplayOn) 1
  switch $type {
    RelaxationZone - NonRelaxationZone {
      etm_ClearView
      etm_ClearAllRegionZones
      etm_SetTypeVisible domain 1
      etm_SelectZones $type
      return
    }
  }
  
  switch $what {
    Families {
      etm_OnAFamily $type $mode
      etm_SetTypeVisible domain 1
      return
    }
  }
  etm_SelectObjectsMed $mode $what $type
  etm_ShowAll
}

proc etm_SelectObjectsMed { mode what type } {
global str_type_visible etmList etmColors etmFlag 
global etmMode etmSmoother etm etmRelaxCoeff
  
  etm_ClearView
  set str_type_visible($mode) 1
  etm_SetTypeVisible domain 1

  switch $what {
    All - Blockinterfaces - Boundaries - Select {
      set on 1
    }
    None - Deselect {
      set on 0
    }
  }

  if {$what == "Select" || $what == "Deselect"} {
     if {$mode != "domain"} {
       disp_set_option $mode
       etm_SetSelectedImagesOff $mode
     }
     etm_ShowAllSelectedImages $mode
  }

  switch $type {
    CoefficientsSubface3D {
      set on2 1
    }
    NonCoefficientsSubface3D {
      set type "CoefficientsSubface3D"
      set on2 0
    }
    NonEdgeBunching - NonRelaxationDomain {
      set on 0
    }
    RelaxationDomain {
      set on 1
    }
  }

  switch $type {
    NonRelaxationSubface - RelaxationSubface - CoefficientsSubface2D -
    CoefficientsSubface3D - LayerExtensionSubface - PredefMesh - BladeBoundary {
      set picked ""
      switch $what {
        Blockinterfaces {
          set picked [ic_str_list_blockif_surfs $mode]
        } 
        Boundaries {
          set picked [ic_str_list_boundary_subfaces]
        }
        Select - Deselect {
          set picked [etm_SelectStructEntities $mode $what $type]
        }
        None {
          foreach item [array name etmList APPLY,FAM_$type,*] {
            unset etmList($item) 
          }
          switch $type {
            NonRelaxationSubface - RelaxationSubface {
              foreach n [ic_str_list_entities $mode] {
                if [etm_IsArrayItemOk etmRelaxSubface $n] {
                  set item [lindex [etm_GetArrayItemValue etmRelaxSubface $n] 1]
                  if {($item == [etm_GetArrayItemValue etmMode $type])} {
                    lappend picked $n
                  }
                }
              }
            }
            LayerExtensionSubface {
              etm_UnsetArray etmLayerExtensionNo
              etm_UnsetList APPLY,SubfaceLayers
              etm_ClearAllImagesLayers
              return              
            }
            CoefficientsSubface2D - CoefficientsSubface3D {
              for {set dom 1 } {$dom <= [ic_str_num_entities domain]} {incr dom} {
                foreach item { imin imax jmin jmax kmin kmax } {
                  set num [etm_GetSubfaceIJKNumber $dom $item]
                  catch { unset etm(sf,$num,relaxcoeff) }
                  catch { unset etm(sf,$num,grid_exp_rate_subf_perp) }
                  catch { unset etm(sf,$num,grid_exp_rate_subf_1) }
                  catch { unset etmRelaxCoeff(SET,$item,3D,outer,[expr $dom - 1]) }
                  catch { unset etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_perp,[expr $dom - 1]) }
                  catch { unset etmRelaxCoeff(GRID,$item,grid_exp_rate_subf_1,[expr $dom - 1]) }
                }
              }
              foreach item {relax_weights_2d relax_weights_3d \
                            relax_weights_inner_2d relax_weights_inner_3d \
                            grid_exp_rate_subf_perp grid_exp_rate_subf_1} {
                etm_UnsetList $item
              }
              for {set dom 0 } {$dom < [ic_str_num_entities domain]} {incr dom} {
                foreach item {2D,outer 3D,outer 2D,inner 3D,inner} {
                  etm_UnsetList etmRelaxCoeff,$item,$dom
                  
                }
              }
              for {set dom 0 } {$dom < [ic_str_num_entities domain]} {incr dom} {
                foreach item {grid_exp_rate_subf_perp grid_exp_rate_subf_1} {
                  etm_UnsetList $item,$dom
                }
              }
            }
            BladeBoundary {
              for {set dom 1 } {$dom <= [ic_str_num_entities domain]} {incr dom} {
                foreach item { imin imax jmin jmax kmin kmax } {
                  set num [etm_GetSubfaceIJKNumber $dom $item]
                  catch { unset etm(sf,$num,abs_dist_bnd) }
                  catch { unset etm(sf,$num,n_points_abs_dist_bnd) }
                }
                set etm(dom,[expr $dom - 1],abs_dist_bnd) -1.0
                set etm(dom,[expr $dom - 1],n_points_abs_dist_bnd) -1
              }
              etm_UnsetList abs_dist_subf
              etm_UnsetList n_abs_dist_subf
            }
          }
        }
      }
      if {$picked == ""} { return }

      switch $type {
        NonRelaxationSubface - RelaxationSubface {
          set zone_picked ""
          if {$type == "NonRelaxationSubface" && $what != "None"} {
              set zone_picked [etm_SetSelectedNonRelaxationSubface $picked]
          } elseif {$type == "NonRelaxationSubface" && ($what == "None" || $what == "Deselect")} {
              global non_relax_smooth fams_attr_local
              etm_ClearRegionZone NonRelaxationSubface
              etm_DeleteAllRegionZones NonRelaxationSubface
              catch { unset non_relax_smooth; unset fams_attr_local }
          }
          foreach n $picked {
            if {$type == "NonRelaxationSubface"} {
              if {[lsearch $zone_picked $n] < 0} {
                etm_ShowRelaxSubface $n $type $on
              }
            } else {
              etm_ShowRelaxSubface $n $type $on
            }
          }
        }
        CoefficientsSubface2D - CoefficientsSubface3D {
          etm_CoefficientsSubface $picked $type $on $on2 1
        }
        BladeBoundary {
          set picked [lsort $picked]
          switch $what {
            Boundaries {
              etm_BladeBoundaryAll $picked
            }
            Select {
              etm_BladeBoundarySelect $picked
            }
          }
        }
        LayerExtensionSubface {
          set list ""
          foreach n $picked {
             if [ic_str_check_blockif_surf $mode $n] {
               set isBlock 1
             } else {
               set isBlock 0
             }
             lappend list [list $n Default $isBlock 1]
             etm_ShowOneImage $mode $type $n 1 $etmColors($type)
          }
          etm_SubfaceLayersWin $type $list
        }
        PredefMesh {
          foreach n $picked {
            etm_ShowOneImage $mode $type $n 1 $etmColors($type)
          }
          etm_SubfacePredefMesh $type $picked
        }
      }
    }

    EdgeBunching - EdgeFrozen - EdgeGlobal - NonEdgeBunching - EdgeViolate {
      set picked ""
      switch $what {
        All - None {
          switch $type {
            EdgeBunching - EdgeFrozen - NonEdgeBunching - EdgeViolate {
              set picked [ic_str_list_entities $mode]
            }
            EdgeGlobal {
              set picked [ic_str_list_blockif_surfs $mode]
            }
          }
        }
        Select - Deselect {
          set picked [etm_SelectStructEntities $mode $what $type]
        }
      } 
      if {$picked == ""} { return }

      switch $type {
        EdgeBunching - EdgeFrozen {
          foreach n $picked {
            if {![etm_IsArrayItemOk etmEdgeAttr $n] && $what == "None"} {
              continue 
            }
            etm_ShowEdgeAttr $n $type $on
          }
        }
        NonEdgeBunching {
          foreach n $picked {
            if {![etm_IsArrayItemOk etmEdgeAttr $n] && $what == "None"} {
              continue 
            }
            etm_ShowEdgeAttr $n EdgeBunching $on
          }          
        }
        EdgeGlobal {
          foreach n $picked {
            if [ic_str_check_blockif_surf $mode $n] {
              if {![etm_IsArrayItemOk etmEdgeGlobal $n] && $what == "None"} {
                continue
              }
              etm_ShowEdgeGlobal $n $on
            }
          }
          if {$what == "None"} {
            etm_UnsetArray etmEdgeGlobal
            etm_UnsetArray etmEdgeGlobalSave
            etm_UnsetArray etmRelaxZoneSave
          } elseif {$what == "Deselect"} {
            if ![etm_IsArrayOk etmEdgeGlobal] {
              etm_UnsetArray etmEdgeGlobal
              etm_UnsetArray etmEdgeGlobalSave
              etm_UnsetArray etmRelaxZoneSave
            }
          }
        }
        EdgeViolate {
          set etmList(EdgeViolate) ""
          foreach n $picked {
            set ijk [ic_str_get_ijk $mode $n]
            set dom [lindex [lindex $ijk 0] 0]; incr dom
            set min [lindex [lindex $ijk 0] 1]
            set max [lindex [lindex $ijk 0] 2]
            lappend etmList(EdgeViolate) [list $dom $n $min $max]
          }
          etm_ClearView
          etm_ClearAllRegionZones
          etm_SelectZones EdgeViolate
          disp_set_visible $mode 1
        }
      }
    }
    NonRelaxationDomain - RelaxationDomain {
      set picked ""
      switch $what {
        All {
          for {set i 0} {$i < [ic_str_num_entities domain]} {incr i} {
            lappend picked [expr $i + 1]
          }
        }
        Select {
          set picked [etm_SelectStructEntities $mode $what $type]
        }
      }
      if {$picked == ""} { return }

      foreach n $picked {
        set etmFlag([expr $n - 1]) $on
        etm_ShowOneImage $mode $type $n $on $etmColors($type)
      }  
      if !$on { disp_change_overall_visible domain }
      etm_SetTypeVisible domain 1
    }
    VertexGlobal - VertexLayer - VertexFixed {
      set picked ""
      switch $what {
        All - None {
          set picked [ic_str_list_entities $mode]
        }
        Select - Deselect {
          set picked [etm_SelectStructEntities $mode $what $type]
        }
      }
      if {$picked == ""} { return }

      switch $type {
        VertexGlobal {
          foreach n $picked {
            if [ic_str_check_blockif_surf $mode $n] {
              etm_SetVertexGlobal $on $n $etmMode($type)
              etm_ShowOneImage vertex $type $n $on $etmColors($type)
            }
          }
        }
        VertexLayer {
          foreach n $picked {
            etm_ShowOneImage vertex $type $n $on $etmColors($type)
          }
          if {$what != "None" && $what != "Deselect"} {
            etm_VertexGlobalLayers [lsort $picked]
          } elseif {$what == "Deselect"} {
            if {[info exists etmList(VertexLayer)] && $etmList(VertexLayer) != ""} {
              set list ""
              foreach item $etmList(VertexLayer) {
                set v [lindex $item 0]
                if {[lsearch $picked $v] == -1} { 
                  lappend list "$v [lindex $item 1] [lindex $item 2]"
                }
              }
              if {$list != ""} {
                set etmList(VertexLayer) $list
              } else {
                catch { unset etmList(VertexLayer) }
                catch { unset etmList(VertexAttrib) }
              }
            }
          } elseif {$what == "None"} {
            catch { unset etmList(VertexLayer) }
            catch { unset etmList(VertexAttrib) }
          }
        }
        VertexFixed {
          foreach n $picked {
            etm_SetVertexFixed $on $n $etmMode($type)
            etm_ShowOneImage vertex $type $n $on $etmColors($type)
          }
        }
      }
    }
  }
}

proc etm_SetSelectedNonRelaxationSubface {picked} {
    global non_relax_smooth fams_attr_local etmColors
    
    if [winfo exists .setnonrelaxsubfaces] { top_destroy .setnonrelaxsubfaces } 
    catch { unset fams_attr_local(all_done) } 
    set buttons {
      {accept}
      {dismiss}
    }
    if ![info exists fams_attr_local(all_at_once)] {
        set fams_attr_local(all_at_once) 0
    }
    set default_value 0
    set type_attr 1
    set type int
    set idx_srf freeze_subfaces
    set text_srf "Freeze subface boundary"
    set text_win "Freeze subface boundary/n layers"
    set list $picked
    set w [form_init .setnonrelaxsubfaces "$text_win" "" $buttons]
    set i 0
    set height 20
    if {$w != ""} {
      form_frame $w.1 ridge 3 "0 0 -pady 3"
      if $fams_attr_local(all_at_once) {
        form_checkbutton $w.1.all "$text_srf" fams_attr_local(all_once,all_items) "1 1" "" \
	        "etm_configure_smooth_parts_form $w.1.all $w.1.value"
	$w.1.all configure -onvalue 0 -offvalue 1
	set filter "fams_attr_local(all_once,all_items) 1"
	form_entry $w.1.value fams_attr_local(all_at_once,value) $type "1 2" $filter
	etm_configure_smooth_parts_form $w.1.all $w.1.value
      } else {
	set mc [form_canvas $w.1.c 300x200 flat 3 "0 0" 0 1]
	foreach item [lsort $list] {
	    form_frame $mc.win$i flat 0 "[expr $i + 1] 0"
	    set fr $mc.win$i
	    $mc create window 0 [expr $i * $height] -window $fr -anchor nw
	    form_label $fr.name$i "$item" "$i 0"; $fr.name$i configure -relief ridge
	    if ![info exists non_relax_smooth($idx_srf,$item)] {
	        set non_relax_smooth($idx_srf,$item) 0
	    }
	    form_checkbutton $fr.part$i "$text_srf" fams_attr_local($idx_srf,$item) "$i 1" "" \
	        "etm_configure_smooth_parts_form $fr.part$i $fr.value$i" 
	    $fr.part$i configure -onvalue 0 -offvalue 1
	    if ![info exists non_relax_smooth(fams_attr,$type_attr,$item)] {
	      set non_relax_smooth(fams_attr,$type_attr,$item) $default_value
	    }
	    set filter "fams_attr_local($idx_srf,$item) $non_relax_smooth(fams_attr,$type_attr,$item)"
	    form_entry $fr.value$i fams_attr_local($type_attr,$item) $type "$i 2" $filter
	    etm_configure_smooth_parts_form $fr.part$i $fr.value$i
	    incr i
	}
      }
      form_checkbutton $w.setall "Set all non-relaxation subface(s) at once" fams_attr_local(all_at_once) \
        "1 0" "" "etm_SetSelectedNonRelaxationSubface [list $list]"
      form_finish +200+200
    } 

    if !$fams_attr_local(all_at_once) {
      set sh [expr $height * $i]
      set rw [winfo reqwidth $mc]
      $mc configure -width 300 -scrollregion "0 0 $rw $sh"
    }
    
    if {[form_wait .setnonrelaxsubfaces] && ![info exists fams_attr_local(all_done)]} {
        set the_subface_list ""
        foreach item $list {
            if !$fams_attr_local(all_at_once) {
              set non_relax_smooth($idx_srf,$item) $fams_attr_local($idx_srf,$item)
            } else {
              set non_relax_smooth($idx_srf,$item) $fams_attr_local(all_once,all_items)
              set fams_attr_local($idx_srf,$item) $fams_attr_local(all_once,all_items)
            }
            if {$non_relax_smooth($idx_srf,$item) == "0"} continue
            append the_subface_list " $item"
            set sfs [ic_str_get_topo_info subface $item 1]
            if {[llength $sfs] > 1} {
                set block 1
             } else {
                set block 0
            }
            if !$fams_attr_local(all_at_once) {
              set value $fams_attr_local($type_attr,$item)
            } else {
              set value $fams_attr_local(all_at_once,value)
            }
            foreach sf $sfs {
              set fam [lindex $sf 2]
              set dom [lindex $sf 4]
              set dom_max [ic_str_get_topo_info domain $dom 1]
              set dom_max [lindex [lindex $dom_max 0] 6]
              set dom_i_max [lindex $dom_max 0]
              set dom_j_max [lindex $dom_max 1]
              set dom_k_max [lindex $dom_max 2]
              set min [lindex $sf 5]
              set max [lindex $sf 6]
              set i_min [lindex $min 0]; set j_min [lindex $min 1]; set k_min [lindex $min 2]
              set i_max [lindex $max 0]; set j_max [lindex $max 1]; set k_max [lindex $max 2] 
              if {$i_min == "1" && $i_min == $i_max} {
                set sf_is imin
              } elseif {$j_min == "1" && $j_min == $j_max} {
                set sf_is jmin
              } elseif {$k_min == "1" && $k_min == $k_max} {
                set sf_is kmin
              } elseif {$i_min == $i_max} {
                set sf_is imax
              } elseif {$j_min == $j_max} {
                set sf_is jmax
              } elseif {$k_min == $k_max} {
                set sf_is kmax
              }
              set ijk_min $min
              set ijk_max $max
              switch $sf_is {
                  imin {
                      set new_value [expr $i_min + $value]
                      if {$new_value > $dom_i_max} { set new_value $dom_i_max }
                      set ijk_max "$new_value $j_max $k_max"
                  }
                  jmin {
                      set new_value [expr $j_min + $value]
                      if {$new_value > $dom_j_max} { set new_value $dom_j_max }
                      set ijk_max "$i_max $new_value $k_max"
                  }
                  kmin {
                      set new_value [expr $k_min + $value]
                      if {$new_value > $dom_k_max} { set new_value $dom_k_max }
                      set ijk_max "$i_max $j_max $new_value"
                  }
                  imax {
                      set new_value [expr $i_max - $value]
                      if {$new_value < 1} { set new_value 1 }
                      set ijk_min "$new_value $j_min $k_min"
                  }
                  jmax {
                      set new_value [expr $j_max - $value]
                      if {$new_value < 1} { set new_value 1 }
                      set ijk_min "$i_min $new_value $k_min"
                  }
                  kmax {                      
                      set new_value [expr $k_max - $value]
                      if {$new_value < 1} { set new_value 1 }
                      set ijk_min "$i_min $j_min $new_value"
                  }  
              }
              etm_SetRelaxZone 1 $dom $ijk_min $ijk_max 0
              etm_CreateSubfaceZone NonRelaxationSubface $dom $ijk_min $ijk_max
              etm_ConfigureImageZone NonRelaxationSubface 1 $etmColors(NonRelaxationSubface)
            }
            if !$fams_attr_local(all_at_once) {
              set non_relax_smooth($idx_srf,$item) $fams_attr_local($idx_srf,$item)
            } else {
              set non_relax_smooth($idx_srf,$item) $fams_attr_local(all_once,all_items)
              set fams_attr_local($idx_srf,$item) $fams_attr_local(all_once,all_items)
            }
            if {$non_relax_smooth($idx_srf,$item) == "1"} {
                if !$fams_attr_local(all_at_once) {
                  set non_relax_smooth(fams_attr,$type_attr,$item) $fams_attr_local($type_attr,$item)
                } else {
                  set non_relax_smooth(fams_attr,$type_attr,$item) $fams_attr_local(all_at_once,value)
                  set fams_attr_local($type_attr,$item) $fams_attr_local(all_at_once,value)
                }
            } else {
                set non_relax_smooth(fams_attr,$type_attr,$item) $default_value
            }
        }
        set fams_attr_local(all_done) 1
        return "$the_subface_list"
    } else {
        return ""
    }
}

proc etm_configure_smooth_parts_form {w1 w2} {
     global fams_attr_local
     set on [$w1 cget -variable]
     if ![set $on] {
         $w1 configure -text "Freeze subface boundary"
         $w2 configure -state disabled
         $w2 configure -foreground gray
     } else {
         $w1 configure -text "Freeze n layers"
         $w2 configure -state normal
         $w2 configure -foreground black
     }
}


proc etm_SelectStructEntities {mode what type} {      
global etmMode

  set picked ""
  set not_these ""
  if {$mode == "subface"} { etm_ConvertSubfaces 1 }
  disp_set_visible $mode 1
  set entities [ic_str_list_entities $mode]
  switch $what {
    Select {
      foreach item $entities {    
        switch $type {
          BladeBoundary {
            if [ic_str_check_blockif_surf $mode $item] {
              append not_these "$item 0 "
            }
          }
          EdgeGlobal {
            if ![ic_str_check_blockif_surf $mode $item] {
              append not_these "$item 0 "
            }
          }
          VertexGlobal {
            if ![ic_str_check_blockif_surf $mode $item] {
              append not_these "$item 0 "
            }
          }
        }
      }
    }
    Deselect {
      foreach item $entities {
        switch $type {
          NonRelaxationSubface - RelaxationSubface {
            if ![etm_IsArrayItemOk etmRelaxSubface $item] {
              append not_these "$item 0 "
            } elseif {[lindex [etm_GetArrayItemValue etmRelaxSubface $item] 1] != $etmMode($type)} {
              append not_these "$item 0 "
            }
          }
          EdgeBunching - EdgeFrozen {
            if ![etm_IsArrayItemOk etmEdgeAttr $item] {
              append not_these "$item 0 "
            } elseif {[lindex [etm_GetArrayItemValue etmEdgeAttr $item] 1] != $etmMode($type) && \
                      [lindex [etm_GetArrayItemValue etmEdgeAttr $item] 1] != $etmMode(EdgeBunchingFrozen)} {
              append not_these "$item 0 "
            }            
          }
          EdgeGlobal {
            if ![etm_IsArrayItemOk etmEdgeGlobal $item] {
              append not_these "$item 0 "
            }
          } 
          VertexGlobal {
            if ![ic_str_check_blockif_surf $mode $item] {
              append not_these "$item 0 "
            }
          }
        }
      }
    }
  }
  if {$not_these != ""} {
    ic_str_set_nums_visible $mode "$not_these"
  }
  set picked [select_struct_surf $mode 0]      
  disp_set_visible $mode 0
  if {$mode == "subface"} { etm_ConvertSubfaces 0 }
  return $picked
}

proc etm_VertexGlobalLayers {vertices} {
global etm etmList

  if {![info exists etmList(SmoothDir)] || $etmList(SmoothDir) == ""} {
    return
  }
  if {[lsearch $etmList(SmoothDir) 0] >= 0} {
    return
  }
  set win .vertexglobal
  if [ winfo exists $win ] { top_destroy .vertexglobal }
  set buttons {
    {accept}
    {cancel}
  }
  set w [form_init $win "Vertex layer" "" $buttons]
  if {$w != ""} {
    form_frame $w.1 ridge 3 "0 0 -pady 3"
    form_label $w.1.1 "First layer distance" "0 0"
    form_entry $w.1.2 etm(vertex_layer_dist) float "0 1"
    form_finish +400+400 1 0
  }
  if [form_wait $win] {
    set dist $etm(vertex_layer_dist)
    set angle $etm(vertex_layer_angle)
    if {[info exists etmList(VertexLayer)] && $etmList(VertexLayer) != ""} {
      foreach item $etmList(VertexLayer) {
        set v [lindex $item 0]
        if {[lsearch $vertices $v] == -1} {
          set tmp($v) "[lindex $item 1] [lindex $item 2]"
        }
      }
    }
    foreach item $vertices {
      lappend list [list $item $dist $angle]
    }
    foreach item [array names tmp] {
      set dist [lindex $tmp($item) 0]
      set angle [lindex $tmp($item) 1]
      lappend list [list $item $dist $angle]
    }
    set etmList(VertexLayer) $list
  }
}

proc etm_BladeBoundaryAll {selected} {
global etmList etm tmp

  if [ winfo exists .bladeboundary ] { top_destroy .bladeboundary }      
  foreach item $selected {
    etm_ShowOneImage subface BladeBoundary $item 1 blue
  }
  set buttons {
    {"Apply" "set tmp(done) 1"}
    {"Cancel" "set tmp(done) 0"}
  }  
  set win .bladeboundary
  set w [form_init $win "Blade boundary" "" $buttons] 
  if {$w != ""} {  
    form_frame $w.1 ridge 3 "0 0 -pady 3"
    form_label $w.1.b1 "Absolute" "0 0"
    $w.1.b1 configure -width 8
    form_label $w.1.b2 "distance" "1 0"
    $w.1.b2 configure -width 8
    form_label $w.1.c1 "Number  " "0 1"
    $w.1.c1 configure -width 8
    form_label $w.1.c2 "of nodes" "1 1"
    $w.1.c2 configure -width 8
    if ![info exists etm(boundary,abs_dist_bnd)] {
      set etm(boundary,abs_dist_bnd) -1.0
    }
    if ![info exists etm(boundary,n_points_abs_dist_bnd)] {
      set etm(boundary,n_points_abs_dist_bnd) -1
    }
    form_entry $w.1.a1 etm(boundary,abs_dist_bnd) float "2 0"
    $w.1.a1 configure -width 8
    form_entry $w.1.a2 etm(boundary,n_points_abs_dist_bnd) int "2 1"
    $w.1.a2 configure -width 8
    form_finish +400+400 1 0
  } 
  tkwait variable tmp(done) 
  form_kill .bladeboundary
  foreach item $selected {
    etm_ShowOneImage subface BladeBoundary $item 0 blue
  }
  if $tmp(done) {
    foreach n $selected {
      set etm(sf,$n,abs_dist_bnd) $etm(boundary,abs_dist_bnd)
      set etm(sf,$n,n_points_abs_dist_bnd) $etm(boundary,n_points_abs_dist_bnd)
    }
    for {set dom 1 } {$dom <= [ic_str_num_entities domain]} {incr dom} {
      foreach item { imin imax jmin jmax kmin kmax } {
        set num [etm_GetSubfaceIJKNumber $dom $item]
        if [info exists etm(sf,$num,abs_dist_bnd)] {
          lappend abs_dist_subf "$etm(sf,$num,abs_dist_bnd)"
        } else {
          lappend abs_dist_subf "-1.0"
        }
        if [info exists etm(sf,$num,n_points_abs_dist_bnd)] {
          lappend n_abs_dist_subf "$etm(sf,$num,n_points_abs_dist_bnd)"
        } else {
          lappend n_abs_dist_subf "-1"
        }
      }
      set etmList(abs_dist_subf) $abs_dist_subf
      set etmList(n_abs_dist_subf) $n_abs_dist_subf
    }
  }
}

proc etm_BladeBoundarySelect {selected} {
global etm etmList tmp
  
  if [winfo exists .bladeboundary] { top_destroy .bladeboundary } 
  set last [llength $selected]
  set height 20; set i 0
  set buttons {
    {"Apply" "set tmp(done) 1"}
    {"Cancel" "set tmp(done) 0"}
  }
  set w [form_init .bladeboundary "Blade boundary" "" $buttons]
  if {$w == ""} { return }
  form_frame $w.f flat 1 "0 0 -pady 3"
  form_label $w.f.n1 "Subface " "0 0"; $w.f.n1 configure -width 7
  form_label $w.f.n2 "number  " "1 0"; $w.f.n2 configure -width 7
  form_label $w.f.a1 "Absolute" "0 1"; $w.f.a1 configure -width 8
  form_label $w.f.a2 "distance" "1 1"; $w.f.a2 configure -width 8
  form_label $w.f.b1 "Number  " "0 2"; $w.f.b1 configure -width 8
  form_label $w.f.b2 "of nodes" "1 2"; $w.f.b2 configure -width 8
  form_frame $w.ff flat 1 "2 0 -pady 3"
  set mc [form_canvas $w.ff.c 200x160 sunken 3 "0 0" 1 1]
  foreach item $selected {
    etm_ShowOneImage subface BladeBoundary $item 1 blue
    form_frame $mc.win$i flat 0 "[expr $i + 1] 0"; set fr $mc.win$i
    $mc create window 0 [expr $i * $height] -window $fr -anchor nw
    set name [lindex $selected $i]
    form_label $fr.name "$name" "$i 0"; $fr.name configure -width 7
    if ![info exists etm(sf,$name,abs_dist_bnd)] {
      set etm(sf,$name,abs_dist_bnd) -1.0
    }
    if ![info exists etm(sf,$name,n_points_abs_dist_bnd)] {
      set etm(sf,$name,n_points_abs_dist_bnd) -1
    }
    form_entry $fr.d etm(sf,$name,abs_dist_bnd) float "$i 1"
    $fr.d configure -width 8
    form_entry $fr.n etm(sf,$name,n_points_abs_dist_bnd) int "$i 2"
    $fr.n configure -width 8
    incr i
  }
  set sh [expr $height * $last]
  set rw [expr [winfo reqwidth $fr.name] + [winfo reqwidth $fr.d] + [winfo reqwidth $fr.n] + 6]
  $mc configure -scrollregion "0 0 $rw $sh" -width $rw
  if {$sh <= 160} { $mc configure -height [expr $sh - 6] } 
  form_finish +400+400 1 0
  tkwait variable tmp(done)  
  form_kill .bladeboundary
  
  foreach item $selected {
    etm_ShowOneImage subface BladeBoundary $item 0 blue
  }

  if $tmp(done) {
    for {set dom 1 } {$dom <= [ic_str_num_entities domain]} {incr dom} {
      foreach item { imin imax jmin jmax kmin kmax } {
        set num [etm_GetSubfaceIJKNumber $dom $item]
        if [info exists etm(sf,$num,abs_dist_bnd)] {
          lappend abs_dist_subf "$etm(sf,$num,abs_dist_bnd)"
        } else {
          lappend abs_dist_subf "-1.0"
        }
        if [info exists etm(sf,$num,n_points_abs_dist_bnd)] {
          lappend n_abs_dist_subf "$etm(sf,$num,n_points_abs_dist_bnd)"
        } else {
          lappend n_abs_dist_subf "-1"
        }
      }
      set etmList(abs_dist_subf) $abs_dist_subf
      set etmList(n_abs_dist_subf) $n_abs_dist_subf
    }
  }
}

proc etm_BladeBoundaryByDomain {} {
global etm etmList tmp

  if [ winfo exists .bladeboundary ] { destroy .bladeboundary }   
  set buttons {
    {"Apply" "set tmp(done) 1"}
    {"Cancel" "set tmp(done) 0"}
  } 
  set height 20
  set last [ic_str_num_entities domain]
  set list $etmList(Domains)
  set win .bladeboundary
  set w [form_init $win "Blade boundary" "" $buttons] 
  if {$w != ""} {  
    form_frame $w.1 ridge 3 "0 0"
    form_frame $w.1.1 flat 0 "0 0 -pady 3"
    form_label $w.1.1.d1 "Domain  " "0 0"
    $w.1.1.d1 configure -width 11
    form_label $w.1.1.d2 "name    " "1 0"
    $w.1.1.d2 configure -width 11
    form_label $w.1.1.b1 "Absolute" "0 2"
    $w.1.1.b1 configure -width 8
    form_label $w.1.1.b2 "distance" "1 2"
    $w.1.1.b2 configure -width 8
    form_label $w.1.1.c1 "Number  " "0 3"
    $w.1.1.c1 configure -width 8
    form_label $w.1.1.c2 "of nodes" "1 3"
    $w.1.1.c2 configure -width 8
    form_frame $w.1.2 flat 0 "1 0"
    set mc [form_canvas $w.1.2.c 200x100 sunken 3 "0 0" 0 1]
    $w.1.2.c configure -auto none
    for {set i 0} {$i < $last} {incr i} {
      set fr [frame $mc.win$i]
      $mc create window 0 [expr $i * $height] -window $fr -anchor nw
      set name [lindex [lindex $list $i] 1]
      form_checkbutton $fr.name "$name" etm(dom,$i,bladeboundary) "$i 0" "" "" 
      $fr.name configure -width 8
      if ![info exists etm(dom,$i,abs_dist_bnd)] {
        set etm(dom,$i,abs_dist_bnd) -1.0
      }
      form_entry $fr.d etm(dom,$i,abs_dist_bnd) float "$i 1"
      $fr.d configure -width 8
      if ![info exists etm(dom,$i,n_points_abs_dist_bnd)] {
        set etm(dom,$i,n_points_abs_dist_bnd) -1
      }
      form_entry $fr.n etm(dom,$i,n_points_abs_dist_bnd) int "$i 2"
      $fr.n configure -width 8
    }
  }
  set sh [expr $height * $last]
  set rw [expr [winfo reqwidth $fr.name] + [winfo reqwidth $fr.d] + [winfo reqwidth $fr.n] + 6]
  $mc configure -scrollregion "0 0 $rw $sh" -width $rw
  if {$sh <= 100} { $mc configure -height [expr $sh - 6] } 
  form_finish +400+400 1 0
  tkwait variable tmp(done) 
  form_kill .bladeboundary
  
  if $tmp(done) {
    for {set i 0} {$i < $last} {incr i} {
      if $etm(dom,$i,bladeboundary) {
        for {set x 1} {$x <= 6} {incr x} {
          lappend abs_dist_subf "$etm(dom,$i,abs_dist_bnd)"
          lappend n_abs_dist_subf "$etm(dom,$i,n_points_abs_dist_bnd)"
        }
        set dom [expr $i + 1]
        foreach item { imin imax jmin jmax kmin kmax } {
          set num [etm_GetSubfaceIJKNumber $dom $item]
          set etm(sf,$num,abs_dist_bnd) "$etm(dom,$i,abs_dist_bnd)"
          set etm(sf,$num,n_points_abs_dist_bnd) "$etm(dom,$i,n_points_abs_dist_bnd)"
        }
      } else {
        lappend abs_dist_subf "-1.0 -1.0 -1.0 -1.0 -1.0 -1.0"
        lappend n_abs_dist_subf "-1 -1 -1 -1 -1 -1"
      }
    }
    set etmList(abs_dist_subf) $abs_dist_subf
    set etmList(n_abs_dist_subf) $n_abs_dist_subf
  }
}

proc etm_GetSubfaceIJKNumber {dom which} {
  
  set what [string index $which 0]
  foreach number [ic_str_boundaries_of_entity domain $dom] {
    set list [ic_str_get_topo_info subface $number 1]
    foreach a $list {
      if {[lindex $a 4] != $dom} { continue }
      set min [lindex $a 5]; set max [lindex $a 6]
      set i_min [lindex $min 0]; set j_min [lindex $min 1]; set k_min [lindex $min 2]
      set i_max [lindex $max 0]; set j_max [lindex $max 1]; set k_max [lindex $max 2]
      if {$which == "imin" || $which == "jmin" || $which == "kmin" } {      
        if {[set ${what}_min] == "1" && [set ${what}_min] == [set ${what}_max]} {
          return [list $number]
        }
      } else {
        if {[set ${what}_min] != "1" && [set ${what}_min] == [set ${what}_max]} {
          return [list $number]
        }
      }
    }
  }
}

proc etm_GetSubfaceIJKNumberList {dom which} {
  
  set what [string index $which 0]
  set ret ""
  foreach number [ic_str_boundaries_of_entity domain $dom] {
    set list [ic_str_get_topo_info subface $number 1]
    foreach a $list {
      if {[lindex $a 4] != $dom} { continue }
      set min [lindex $a 5]; set max [lindex $a 6]
      set i_min [lindex $min 0]; set j_min [lindex $min 1]; set k_min [lindex $min 2]
      set i_max [lindex $max 0]; set j_max [lindex $max 1]; set k_max [lindex $max 2]
      if {$which == "imin" || $which == "jmin" || $which == "kmin" } {      
        if {[set ${what}_min] == "1" && [set ${what}_min] == [set ${what}_max]} {
          lappend ret $number
        }
      } else {
        if {[set ${what}_min] != "1" && [set ${what}_min] == [set ${what}_max]} {
          lappend ret $number
        }
      }
    }
  }
  return $ret
}

proc etm_SelectFamilies {mode what {mess ""}} {
    global etmFamily etmColors
    
    foreach n [ic_str_list_entities $mode] {
      set f [ic_str_get_family $mode $n]
      if {![info exists numbers($f)] && $f != ""} {
        set numbers($f) $n
        lappend found([family_color_for_name $f]) $f
      } elseif {$f != ""} {
        if [info exists numbers($f)] {
          lappend numbers($f) $n
        }
      }
    }
    if ![info exists found] { return "" }   
    set prev [etm_SelectedImages $mode $what]
    catch { unset etmFamily }
    form_kill .etmfamiliesselect
    set d [form_init .etmfamiliesselect "Select families" "" "accept cancel"]
    set n 0
    if {$mess != ""} {
      form_label $d.mess $mess {0 0}
      $d.mess configure -justify l
    }
    catch {unset found(ORFN)}
    set fams ""
    foreach ff [array names found] {
      foreach fn $found($ff) {
	if {$fn != "ORFN"} { lappend fams [list $fn $ff] }
      }
    }
    if [llength $fams] { set sw [form_scroller $d.stuff 300 {1 0}] }
    foreach ff [lsort $fams] {
      set famn [lindex $ff 0]
      set col [lindex $ff 1]
      set full $famn
      if {[string length $famn] > 20} {
        set famn "[string range $famn 0 18]..."
      }
      set etmFamily($full) 0
      set pos "[expr $n / 2] [expr $n % 2]"
      set com "etm_ShowFamilyImage $mode $what \"$numbers($full)\" $full $col"
      form_checkbutton $sw.but$n $famn etmFamily($full) "$pos" "" "$com" 
      $sw.but$n configure -background $col -activebackground $col -width 20
      incr n
    }
    form_finish +400+400 1 0
    if [llength $fams] { form_scroller_hack $d.stuff }
    set ret ""
    if ![form_wait .etmfamiliesselect] {
      foreach ff [array names etmFamily] {
        foreach n $numbers($ff) {
          if {[lsearch $prev $n] == -1} {
            etm_ShowOneImage $mode $what $n 0 ""
          } else {
            etm_ShowOneImage $mode $what $n 1 $etmColors($what)
          }
        }
      }      
    } else {
      foreach ff [array names etmFamily] {
        if $etmFamily($ff) {
          lappend ret [list $ff $numbers($ff)]
          foreach n $numbers($ff) {
            etm_ShowOneImage $mode $what $n 0 ""
          }
        }
      }
    }
    catch { unset etmFamily }
    return $ret
}

proc etm_SelectedImages {mode what} {
global etmImage etmMode

  set ret ""
  foreach item [array names etmImage] {
    if [string match $mode [lindex [split $item ,] 0]] {
      set type [lindex $etmImage($item) 1]
      if {$what == $type} {
        lappend ret [lindex [split $item ,] 1]
      }
    }
  }
  return $ret
}

proc etm_ShowFamilyImage {mode what numbers full color} {
   global etmFamily
   set on $etmFamily($full)
   foreach n $numbers {
     etm_ShowOneImage $mode $what $n $on $color
   }
}

proc etm_SetTypeVisible {what on} {
  global str_type_visible
  set str_type_visible($what) $on
  disp_set_visible $what $on
}

proc etm_OnAFamily {what mode} {
global etmList etmColors etmFlag etm etmMode

  switch $what {
    RelaxationDomain { set title "relaxation domain" }
    NonRelaxationDomain { set title "non-relaxation domain" }
    EdgeBunching { set title "fixed distribution edge" }
    NonEdgeBunching { set title "release distribution edge" }
    EdgeFrozen { set title "fixed edge" }
    EdgeGlobal { set title "global edge" }
    RelaxationSubface { set title "relaxation subface" }
    NonRelaxationSubface { set title "non-relaxation subface" }
    LayerExtensionSubface { set title "layer extension subface" }
    PredefMesh { set title "predefined mesh subface" }
    CoefficientsSubface2D - CoefficientsSubface3D { set title "hold cell height subface" }
    NonCoefficientsSubface3D {
      set title "release cell height subface"
      set what CoefficientsSubface3D
      set old NonCoefficientsSubface3D
    }
    BladeBoundary { set title "blade boundary subface" }
    VertexGlobal { set title "global vertex" }
    VertexLayer { set title "layer vertex" }
  }  
  set color $etmColors($what)
  etm_ClearView  
  etm_SetTypeVisible domain 1
  set fams [etm_SelectFamilies $mode $what "Select the families for $title."]
  etm_ShowAllSelectedImages $mode
  if {$fams == ""} { return }
  
  set zone_picked ""
  if {$what == "NonRelaxationSubface"} {
    set picked ""
    foreach item $fams {
      foreach n [lindex $item 1] {
        append picked "$n "
      }
    }
    set zone_picked [etm_SetSelectedNonRelaxationSubface $picked]
  }
  
  foreach item $fams {
    foreach n [lindex $item 1] {
      switch $what {
        RelaxationDomain {
          set i [expr $n - 1]; set etmFlag($i) 1
          etm_ShowOneImage domain RelaxationDomain $n 1 $color
        }
        NonRelaxationDomain {
          set i [expr $n - 1]; set etmFlag($i) 0
          etm_ShowOneImage domain RelaxationDomain $n 0 $color
        }
        EdgeBunching - EdgeFrozen {
          etm_ShowEdgeAttr $n $what 1
        }
        NonEdgeBunching {
          etm_ShowEdgeAttr $n EdgeBunching 0
        }
        EdgeGlobal {
          etm_ShowEdgeGlobal $n 1
        }
        NonRelaxationSubface - RelaxationSubface {
          if {$what == "NonRelaxationSubface"} {
            if {[lsearch $zone_picked $n] < 0} {
              etm_ShowRelaxSubface $n $what 1
            }
          } else {
            etm_ShowRelaxSubface $n $what 1
          }
        }
        LayerExtensionSubface {
          set isBlock 0
          if [ic_str_check_blockif_surf $mode $n] { set isBlock 1 }
          etm_ShowOneImage $mode $what $n 1 $color
          lappend list [list $n Default $isBlock 1]
        }
        PredefMesh {
          lappend list [list $n]
          etm_ShowOneImage $mode $what $n 1 $color
        }
        CoefficientsSubface2D - CoefficientsSubface3D {
          lappend list [list $n]
        }
        BladeBoundary {
          lappend list [list $n]
        }
        VertexGlobal {
          if [ic_str_check_blockif_surf $mode $n] {
            etm_SetVertexGlobal 1 $n $etmMode(VertexGlobal)
            etm_ShowOneImage vertex VertexGlobal $n 1 $color
          }          
        }
        VertexLayer {
          lappend list [list $n]
          etm_ShowOneImage $mode $what $n 1 $color
        }
      }
    }
  }
  
  switch $what {
    NonRelaxationDomain {
      disp_change_overall_visible domain
    }
    LayerExtensionSubface {
      etm_SubfaceLayersWin $what $list
    }
    PredefMesh {
      etm_SubfacePredefMesh $what $list
    }
    CoefficientsSubface2D - CoefficientsSubface3D {
      if [info exists old] {
        etm_CoefficientsSubface $list $what 1 0 1
      } else {
        etm_CoefficientsSubface $list $what 1 1 1
      }
    }
    BladeBoundary {
      etm_BladeBoundaryAll $list
    }
    VertexLayer {
      etm_VertexGlobalLayers [lsort $list]
    }
  }
  if [info exists etm(Entities)] {
    etm_ListSelectedEntities $etm(Entities)
  }
  etm_ShowAll
}

proc etm_SelectZones { what } {
global etmList etmSmoother etmTemp guibase_dir

  etm_UnsetArray etmTemp
  set etmTemp(Steps) 1
  set etmTemp(Selected) 0
  set etmTemp(SliderOn) 0
  set etmTemp(AllCorners) 0
  set etmTemp(Violate) 0.0
  set etmTemp(What) $what
  
  if [ winfo exists .rzm ] { top_destroy .rzm }    
  set buttons {
    {"Apply" "etm_ApplySelectZones"} \
    {"Clear all" "etm_ClearAllSelectZones"} \
    {"Clear selected" "etm_ClearOneSelectZone"}
    {"Show all" "etm_ShowAllSelectZones"}
    {"Done" "etm_DoneSelectZones"}
  }
  if {$what == "NonRelaxationZone"} {
    set title "Region non-relaxation zones manager"
    set etmTemp(Text) domain
    set list $etmList(Domains)
  } elseif {$what == "RelaxationZone"} {
    set title "Region relaxtion zones manager"
    set etmTemp(Text) domain
    set list $etmList(Domains)
  } elseif {$what == "EdgeViolate"} {
    set title "Violate geometry edges manager"
    set etmTemp(Text) edge
    set list $etmList(EdgeViolate)
  }  
  set etmTemp(Names) "" 
  foreach i [lsort $list] {
    lappend etmTemp(Names) [lindex $i 1]
  }
  set w [form_init .rzm "$title" "" $buttons]
  if {$w != ""} {
    form_frame $w.1 ridge 3 "0 0"
    form_frame $w.1.1 flat 3 "0 0"
    if {$what == "NonRelaxationZone" || $what == "RelaxationZone"} {
      form_listbox $w.1.1.1 "" $etmTemp(Names) "etm_SelectDomainZone" "" 10x8 "0 0"
    } else {
      form_listbox $w.1.1.1 "" $etmTemp(Names) "etm_SelectDomainZone" "" 10x8 "0 0" \
      	"" 0 0 1
    }
    form_frame $w.1.2 flat 3 "0 1"
    form_frame $w.1.2.1 flat 3 "0 0"
    if {$what == "NonRelaxationZone" || $what == "RelaxationZone"} {
      form_label $w.1.2.1.1 "Steps for incrementing/decrementing ijk:" "0 0"
      futil_updown $w.1.2.1.2 etmTemp(Steps) 1 10 "0 1"
      set com "futil_updown_modify etmTemp(Steps) 1; etm_GetIJKSteps $w"
      $w.1.2.1.2.up configure -command $com
      set com "futil_updown_modify etmTemp(Steps) -1; etm_GetIJKSteps $w"
      $w.1.2.1.2.down configure -command $com      
    }
    set is_selected {etmTemp(Selected) 1}
    form_frame $w.1.2.2 flat 3 "1 0"
    form_label $w.1.2.2.i_min "i min" "0 0" $is_selected
    futil_updown $w.1.2.2.i_from etmTemp(i_from) "" "" "0 1" $is_selected
    form_label $w.1.2.2.j_min "j min" "0 2" $is_selected
    futil_updown $w.1.2.2.j_from etmTemp(j_from) "" "" "0 3" $is_selected
    form_label $w.1.2.2.k_min "k min" "0 4" $is_selected
    futil_updown $w.1.2.2.k_from etmTemp(k_from) "" "" "0 5" $is_selected
    form_label $w.1.2.2.i_max "i max" "1 0" $is_selected
    futil_updown $w.1.2.2.i_to etmTemp(i_to) "" "" "1 1" $is_selected
    form_label $w.1.2.2.j_max "j max" "1 2" $is_selected
    futil_updown $w.1.2.2.j_to etmTemp(j_to) "" "" "1 3" $is_selected
    form_label $w.1.2.2.k_max "k max" "1 4" $is_selected
    futil_updown $w.1.2.2.k_to etmTemp(k_to) "" "" "1 5" $is_selected
    foreach m {i_from j_from k_from i_to j_to k_to} {    
      set com "futil_updown_modify etmTemp($m) 1; etm_SetRegionIJK"
      $w.1.2.2.$m.up configure -command $com
      set com "futil_updown_modify etmTemp($m) -1; etm_SetRegionIJK"
      $w.1.2.2.$m.down configure -command $com
    }
    if {$what == "NonRelaxationZone" || $what == "RelaxationZone"} {
      form_frame $w.1.2.3 flat 3 "3 0"
      form_frame $w.1.2.4 flat 3 "2 0"
      if !$etmSmoother(2D) {
        set to 8
      } else {
        set to 4
      }
      form_label $w.1.2.4.ti "Trans i  " "0 0" $is_selected
      form_button_bitmap $w.1.2.4.iup @$guibase_dir/goup.xbm \
      	"etm_TransIJKSteps 1 i 0" "0 1" $is_selected
      form_button_bitmap $w.1.2.4.idown @$guibase_dir/godown.xbm \
      	"etm_TransIJKSteps 0 i 0" "0 2" $is_selected
      form_label $w.1.2.4.tj "     Trans j  " "0 3" $is_selected
      form_button_bitmap $w.1.2.4.jup @$guibase_dir/goup.xbm \
      	"etm_TransIJKSteps 1 j 1" "0 4" $is_selected
      form_button_bitmap $w.1.2.4.jdown @$guibase_dir/godown.xbm \
      	"etm_TransIJKSteps 0 j 1" "0 5" $is_selected
      form_label $w.1.2.4.tk "     Trans k  " "0 6" $is_selected
      form_button_bitmap $w.1.2.4.kup @$guibase_dir/goup.xbm \
      	"etm_TransIJKSteps 1 k 2" "0 7" $is_selected
      form_button_bitmap $w.1.2.4.kdown @$guibase_dir/godown.xbm \
      	"etm_TransIJKSteps 0 k 2" "0 8" $is_selected
      form_checkbutton $w.1.2.3.1 "Show corner vertex" etmTemp(SliderOn) \
    	"0 0" $is_selected "etm_SliderOnOff" 
      set is_vertex_selected {{etmTemp(Selected) 1} {etmTemp(SliderOn) 1}}
      form_checkbutton $w.1.2.3.2 "Select all corner vertices" etmTemp(AllCorners) \
    	"0 1 -padx 15" $is_vertex_selected "etm_SelectAllCornerVertices" 
      set show_corner {{etmTemp(SliderOn) 1} {etmTemp(AllCorners) 0}}
      form_scale $w.1.2.3.3 etmTemp(CornerOn) "etm_ShowCornerVertex" h 1 $to 1 \
      	"1 0 -cols -" $show_corner
    } else {
      form_frame $w.1.2.3 flat 3 "2 0"
      form_label $w.1.2.3.1 "Violate geometry edge value:" "0 0"
      form_entry $w.1.2.3.2 etmTemp(Violate) default "0 1"
      form_button $w.1.2.3.3 "Select all edges" "etm_SelectAllViolateEdges" "1 0"
    }
    form_finish +450+450 1 0
  }
  if {$what == "NonRelaxationZone" || $what == "RelaxationZone"} {
    etm_GetIJKSteps $w
  }
}

proc etm_GetIJKSteps {w} {
global etmTemp
  
  foreach m {i_from j_from k_from i_to j_to k_to} {    
    set com "futil_updown_modify etmTemp($m) $etmTemp(Steps); etm_SetRegionIJK"
    $w.1.2.2.$m.up configure -command $com
    set com "futil_updown_modify etmTemp($m) [expr $etmTemp(Steps) * -1]; etm_SetRegionIJK"
    $w.1.2.2.$m.down configure -command $com
  }
}

proc etm_TransIJKSteps {up trans idx} {
global etmTemp
  
  if $up {
    set from [expr $etmTemp(${trans}_from) + $etmTemp(Steps)]
    set to [expr $etmTemp(${trans}_to) + $etmTemp(Steps)]
  } else {
    set from [expr $etmTemp(${trans}_from) - $etmTemp(Steps)]
    set to [expr $etmTemp(${trans}_to) - $etmTemp(Steps)]
  }
  if {$from < [lindex $etmTemp(Min) $idx] || \
      $from > [lindex $etmTemp(Max) $idx]} {
    set from $etmTemp(${trans}_from)
  }
  if {$to > [lindex $etmTemp(Max) $idx] || \
      $to < [lindex $etmTemp(Min) $idx]} {
    set to $etmTemp(${trans}_to)
  }
  set etmTemp(${trans}_from) $from
  set etmTemp(${trans}_to) $to
  etm_SetRegionIJK
}

proc etm_ApplySelectZones {} {
global etmMode etmTemp etmList etmColors etmImageZone

  if {$etmTemp(What) == "EdgeViolate"} {
    set edges [form_listbox_get_select_index .rzm.main.1.1.1]
    if {[llength $edges] > "1"} {
      foreach item $edges {
        set edge [form_listbox_get .rzm.main.1.1.1 $item]
        foreach i $etmList(EdgeViolate) {
          set number [lindex $i 1]
          if {$number == "$edge"} {
            set dom [lindex $i 0]
            set min [lindex $i 2]; set max [lindex $i 3]
            set color $etmColors(EdgeViolate)
            set name EdgeViolate,$dom.$min.$max
            set etmTemp(APPLY,$name) 1
            etm_ConfigureImageZone $name 1 $color
            etm_SetViolGeomZone 1 $dom $min $max $etmTemp(Violate)
          }
        }
      }
      etm_ShowAllSelectZones
      return
    }
  }
  if [etm_ErrorMessageIJK] { return }
  if {[form_listbox_get_select_index .rzm.main.1.1.1] == ""} { return }
  etm_SetRegionIJK
  set min [list $etmTemp(i_from) $etmTemp(j_from) $etmTemp(k_from)]
  set max [list $etmTemp(i_to) $etmTemp(j_to) $etmTemp(k_to)]
  set number $etmTemp(Domain)
  set name $etmTemp(Name)
  set color $etmColors($etmTemp(What))
  set etmTemp(APPLY,$name) 1
  etm_ConfigureImageZone $name 1 $color
  if {$etmTemp(What) == "NonRelaxationZone" || $etmTemp(What) == "RelaxationZone"} {
    etm_SetRelaxZone 1 $number $min $max $etmMode($etmTemp(What))
  } elseif {$etmTemp(What) == "EdgeViolate"} {
    etm_SetViolGeomZone 1 $number $min $max $etmTemp(Violate)
  }
  etm_ShowAllSelectZones
  etm_ClearMinMax 0
}

proc etm_ShowMinMax { min max } {
global etmTemp

  set etmTemp(i_from) [lindex $min 0]
  set etmTemp(j_from) [lindex $min 1]
  set etmTemp(k_from) [lindex $min 2]
  set etmTemp(i_to) [lindex $max 0]
  set etmTemp(j_to) [lindex $max 1]
  set etmTemp(k_to) [lindex $max 2]
}

proc etm_ClearMinMax {on} {
global etmTemp
  
  set etmTemp(Selected) $on
  set etmTemp(SliderOn) 0
  set etmTemp(AllCorners) 0
  .rzm.main.1.1.1.list selection clear 0 end
  foreach m {i_from j_from k_from i_to j_to k_to} {
    set etmTemp($m) ""
  }
}

proc etm_SelectAllCornerVertices {} {
global etmTemp etmSmoother etmMode etmColors

  if [etm_ErrorMessageIJK] { return }
  if [info exists etmTemp(Name)] { etm_DeleteRegionZone $etmTemp(Name) }
  set what $etmTemp(What)
  set mode $etmMode($what)
  set color $etmColors($what)
  for { set value 1 } { $value <= 8 } { incr value } {  
    etm_SetCornerVertex $value
    etm_SetRegionIJK 1
    set min [list $etmTemp(i_from) $etmTemp(j_from) $etmTemp(k_from)]
    set max [list $etmTemp(i_to) $etmTemp(j_to) $etmTemp(k_to)] 
    set name $etmTemp(Name)
    set number $etmTemp(Domain)
    etm_ConfigureImageZone $name 1 $color
    set etmTemp(APPLY,$name) 1
    etm_SetRelaxZone 1 $number $min $max $mode
  }
  etm_ClearMinMax 0
  etm_ShowAllSelectZones
  if $etmSmoother(2D) {
    mess "Added 4 vertices.\n"
  } else {
    mess "Added 8 vertices.\n"
  }
}

proc etm_SetCornerVertex {value} {   
global etmTemp etmSmoother    
    
    set ijk_from $etmTemp(Min)
    set ijk_to $etmTemp(Max)
    if $etmSmoother(2D) {
      if { $value == 1 } {
        set etmTemp(i_from)  [lindex $ijk_from 0]
        set etmTemp(j_from)  [lindex $ijk_from 1]
        set etmTemp(k_from)  [lindex $ijk_from 2]
        set etmTemp(i_to)    [lindex $ijk_from 0]
        set etmTemp(j_to)    [lindex $ijk_from 1]
        set etmTemp(k_to)    [lindex $ijk_from 2] 
      } elseif { $value == 2 } {    
        set etmTemp(i_from)  [lindex $ijk_to 0]
        set etmTemp(j_from)  [lindex $ijk_from 1]
        set etmTemp(k_from)  [lindex $ijk_from 2]
        set etmTemp(i_to)    [lindex $ijk_to 0]
        set etmTemp(j_to)    [lindex $ijk_from 1]
        set etmTemp(k_to)    [lindex $ijk_from 2] 
      }  elseif { $value == 3 } {
        set etmTemp(i_from)  [lindex $ijk_to 0]
        set etmTemp(j_from)  [lindex $ijk_to 1]
        set etmTemp(k_from)  [lindex $ijk_to 2]
        set etmTemp(i_to)    [lindex $ijk_to 0]
        set etmTemp(j_to)    [lindex $ijk_to 1]
        set etmTemp(k_to)    [lindex $ijk_to 2]
      } elseif { $value == 4 } {
        set etmTemp(i_from)  [lindex $ijk_from 0]
        set etmTemp(j_from)  [lindex $ijk_to 1]
        set etmTemp(k_from)  [lindex $ijk_to 2]
        set etmTemp(i_to)    [lindex $ijk_from 0]
        set etmTemp(j_to)    [lindex $ijk_to 1]
        set etmTemp(k_to)    [lindex $ijk_to 2]
      } 
    } else {
      if { $value == 1 } {
        set etmTemp(i_from)  [lindex $ijk_from 0]
        set etmTemp(j_from)  [lindex $ijk_from 1]
        set etmTemp(k_from)  [lindex $ijk_from 2]
        set etmTemp(i_to)    [lindex $ijk_from 0]
        set etmTemp(j_to)    [lindex $ijk_from 1]
        set etmTemp(k_to)    [lindex $ijk_from 2] 
      } elseif { $value == 2 } {    
        set etmTemp(i_from)  [lindex $ijk_to 0]
        set etmTemp(j_from)  [lindex $ijk_from 1]
        set etmTemp(k_from)  [lindex $ijk_from 2]
        set etmTemp(i_to)    [lindex $ijk_to 0]
        set etmTemp(j_to)    [lindex $ijk_from 1]
        set etmTemp(k_to)    [lindex $ijk_from 2] 
      } elseif { $value == 3 } {
        set etmTemp(i_from)  [lindex $ijk_to 0]
        set etmTemp(j_from)  [lindex $ijk_from 1]
        set etmTemp(k_from)  [lindex $ijk_to 2]
        set etmTemp(i_to)    [lindex $ijk_to 0]
        set etmTemp(j_to)    [lindex $ijk_from 1]
        set etmTemp(k_to)    [lindex $ijk_to 2]
      } elseif { $value == 4 } {
        set etmTemp(i_from)  [lindex $ijk_from 0]
        set etmTemp(j_from)  [lindex $ijk_from 1]
        set etmTemp(k_from)  [lindex $ijk_to 2]
        set etmTemp(i_to)    [lindex $ijk_from 0]
        set etmTemp(j_to)    [lindex $ijk_from 1]
        set etmTemp(k_to)    [lindex $ijk_to 2]
      } elseif { $value == 5 } {
        set etmTemp(i_from)  [lindex $ijk_to 0]
        set etmTemp(j_from)  [lindex $ijk_to 1]
        set etmTemp(k_from)  [lindex $ijk_to 2]
        set etmTemp(i_to)    [lindex $ijk_to 0]
        set etmTemp(j_to)    [lindex $ijk_to 1]
        set etmTemp(k_to)    [lindex $ijk_to 2]
      } elseif { $value == 6 } {
        set etmTemp(i_from)  [lindex $ijk_from 0]
        set etmTemp(j_from)  [lindex $ijk_to 1]
        set etmTemp(k_from)  [lindex $ijk_to 2]
        set etmTemp(i_to)    [lindex $ijk_from 0]
        set etmTemp(j_to)    [lindex $ijk_to 1]
        set etmTemp(k_to)    [lindex $ijk_to 2]
      } elseif { $value == 7 } {    
        set etmTemp(i_from)  [lindex $ijk_from 0]
        set etmTemp(j_from)  [lindex $ijk_to 1]
        set etmTemp(k_from)  [lindex $ijk_from 2]
        set etmTemp(i_to)    [lindex $ijk_from 0]
        set etmTemp(j_to)    [lindex $ijk_to 1]
        set etmTemp(k_to)    [lindex $ijk_from 2] 
      } elseif { $value == 8 } {    
        set etmTemp(i_from)  [lindex $ijk_to 0]
        set etmTemp(j_from)  [lindex $ijk_to 1]
        set etmTemp(k_from)  [lindex $ijk_from 2]
        set etmTemp(i_to)    [lindex $ijk_to 0]
        set etmTemp(j_to)    [lindex $ijk_to 1]
        set etmTemp(k_to)    [lindex $ijk_from 2] 
      }
    }
}

proc etm_SelectAllViolateEdges {} {
global etmTemp etmColors
  
  set i 0
  if [info exist etmTemp(Images)] {
    foreach item $etmTemp(Images) {
      set value [etm_GetArrayItemValue etmTemp "APPLY,$item"]
      if {($value == "0") || ($value == "-1")} {
        etm_DeleteRegionZone $item
      }
    }
    unset etmTemp(Images)
  }
  set edges [form_listbox_get .rzm.main.1.1.1]
  foreach item $edges {
    etm_ShowDomainZone $item
    .rzm.main.1.1.1.list see $i
    .rzm.main.1.1.1.list selection set $i
    incr i
  }
  foreach m {i_from j_from k_from i_to j_to k_to} {    
    set etmTemp($m) ""
  }
  mess "$i edges selected.\n"
}

proc etm_ClearAllSelectZones {} {
global etmTemp

  set what $etmTemp(What)
  etm_DeleteAllRegionZones $what
  switch $what {
    NonRelaxationZone - RelaxationZone {
      etm_UnsetRelaxZone $what
    }
    EdgeViolate {
      etm_UnsetArray etmViolGeomZone
    }
  }
  foreach item [ array names etmTemp APPLY,* ] { unset etmTemp($item) }
  if [info exist etmTemp(Domain)] { unset etmTemp(Domain) }
  if [info exist etmTemp(Name)] { unset etmTemp(Name) }
  etm_ClearMinMax 0
}

proc etm_UnsetRelaxZone {what} {
global etmRelaxZone etmMode   
    
  foreach item [array names etmRelaxZone] {
    set relax [lindex $etmRelaxZone($item) 3]
    if [string match $etmMode($what) $relax] {
      set number [lindex $etmRelaxZone($item) 0]
      set min [lindex $etmRelaxZone($item) 1]
      set max [lindex $etmRelaxZone($item) 2]
      etm_SetRelaxZone 0 $number $min $max $etmMode($what)
    }
  }
}

proc etm_ClearOneSelectZone {} {
global etmRelaxZone etmMode etmTemp etmViolGeomZone etmColors
global etmImageZone

  set what $etmTemp(What)
  if [etm_ErrorMessageIJK] { return }
  if ![info exists etmTemp(Domain)] { return } 
    
  set delNumber $etmTemp(Domain)
  etm_ClearMinMax 0
  if [etm_IsArrayItemOk etmImageZone $etmTemp(Name)] {
    etm_ConfigureImageZone $etmTemp(Name) 0
  }
  if {$what == "NonRelaxationZone" || $what == "RelaxationZone"} {
    foreach item [array names etmRelaxZone] {
      set relax [lindex $etmRelaxZone($item) 3]
      if [string match $etmMode($what) $relax] {
        set number [lindex $etmRelaxZone($item) 0]
        if { $number == $delNumber } {
          set min [lindex $etmRelaxZone($item) 1]
          set max [lindex $etmRelaxZone($item) 2]
          etm_ShowMinMax $min $max
          set name $what,$number.$min.$max
          etm_ConfigureImageZone $name 1 red
          if [etm_ShowQuestion QUESTION "Clear Zone ?"] {
            etm_SetRelaxZone 0 $number $min $max $etmMode($what)
            if [info exists etmTemp(APPLY,$name)] { unset etmTemp(APPLY,$name) }
            etm_DeleteRegionZone $name
          } else {
            etm_ConfigureImageZone $name 1 $etmColors($what)
          }
        }
      }
    }
  } elseif {$what == "EdgeViolate"} {
    foreach item [array names etmViolGeomZone] {
      set number [lindex $etmViolGeomZone($item) 0]
      if {$number == $delNumber} {
        set min [lindex $etmViolGeomZone($item) 1]
        set max [lindex $etmViolGeomZone($item) 2]
        etm_ShowMinMax $min $max
        set name $what,$number.$min.$max
        etm_ConfigureImageZone $name 1 red
        if [etm_ShowQuestion QUESTION "Clear edge ?"] {
          etm_SetViolGeomZone 0 $number $min $max 0
          if [info exists etmTemp(APPLY,$name)] {
            unset etmTemp(APPLY,$name)
          }
          etm_DeleteRegionZone $name
        } else {
          etm_ConfigureImageZone $name 1 $etmColors($what)
        }
      }
    }
  }
  if [ etm_IsArrayItemOk etmImageZone $etmTemp(Name) ] {
    etm_DeleteRegionZone $etmTemp(Name)
  }
  unset etmTemp(Name)
  unset etmTemp(Domain)
  etm_ClearMinMax 1
  etm_ShowAllSelectZones
}

proc etm_ClearViolateEdge {} {
global etmTemp etmViolGeomZone
    
  foreach item [ array names etmTemp APPLY,* ] { unset etmTemp($item) }
  if [info exist etmTemp(Domain)] { unset etmTemp(Domain) }
  if [info exist etmTemp(Name)] { unset etmTemp(Name) }
  etm_DeleteAllRegionZones EdgeViolate  
  foreach item [ array names etmViolGeomZone ] {
    set num [lindex $etmViolGeomZone($item) 0]
    set min [lindex $etmViolGeomZone($item) 1]
    set max [lindex $etmViolGeomZone($item) 2]
    etm_SetViolGeomZone 0 $num $min $max 0
  }
}

proc etm_ShowAllSelectZones {} {
global etmTemp
  
  set what $etmTemp(What)
  if [ info exist etmTemp(Domain) ] {
    catch {$etmTemp(Domain) configure -visible 0}
    unset etmTemp(Domain)
  }
  etm_ClearMinMax 0
  if [ info exist etmTemp(Name) ] {
    set value [ etm_GetArrayItemValue etmTemp "APPLY,$etmTemp(Name)" ] 
    if { ($value == "0") || ($value == "-1") } {
      etm_DeleteRegionZone $etmTemp(Name)
      unset etmTemp(Name)
    } 
  } 
  etm_ShowSelectedImagesZones $etmTemp(What)
}

proc etm_DoneSelectZones {} {
global etmTemp etmImageZone etmSmoother etm
  
  if [info exist etmTemp(Name)] {
    set value [etm_GetArrayItemValue etmTemp "APPLY,$etmTemp(Name)"]
    if {($value == "0") || ($value == "-1")} {
      etm_DeleteRegionZone $etmTemp(Name)
    }
  }
  if {$etmTemp(What) == "EdgeViolate"} {
    if [info exist etmTemp(Images)] {
      foreach item $etmTemp(Images) {
        set value [etm_GetArrayItemValue etmTemp "APPLY,$item"]
        if {($value == "0") || ($value == "-1")} {
          etm_DeleteRegionZone $item
        }
      }
      unset etmTemp(Images)
    }
  }
  etm_ShowAllSelectedImagesZones
  etm_UnsetArray etmTemp
  set etmSmoother(DisplayOn) 1
  if [info exists etm(Entities)] {
    etm_ListSelectedEntities $etm(Entities)
  }
  top_destroy .rzm
}

proc etm_SelectDomainZone {which} {
global etmTemp

    if {$etmTemp(What) == "EdgeViolate"} {
      set w .rzm.main.1.1.1
      set idx [form_listbox_get_select_index $w]
      set len [llength $idx]
      set selected ""
      foreach i $idx {
        lappend selected [form_listbox_get $w $i]
      }
      set n [lsearch $selected $which]
      if {$n == "-1" || $selected == ""} {
        if [info exists etmTemp(Edge,$which)] {
          set name $etmTemp(Edge,$which)
          set etmTemp(APPLY,$name) [etm_GetArrayItemValue etmTemp "APPLY,$name"]
          if {$etmTemp(APPLY,$name) == "0"} {
            etm_DeleteRegionZone "$name"
          } elseif {$etmTemp(APPLY,$name) == "1"} {
            etm_ClearRegionZone $etmTemp(What)
          } elseif {$etmTemp(APPLY,$name) == "-1"} {
            set etmTemp(APPLY,$name) 0
            etm_DeleteRegionZone "$name"
          }
          unset etmTemp(Edge,$which)
          return
        }
      }
      if {$len == "0"} { return }
      etm_ShowDomainZone $which
    } else {
      if [info exist etmTemp(Name)] {
        set name $etmTemp(Name)
        set etmTemp(APPLY,$name) [etm_GetArrayItemValue etmTemp "APPLY,$name"]
        if {$etmTemp(APPLY,$name) == "0"} {
          etm_DeleteRegionZone "$name"
        } elseif {$etmTemp(APPLY,$name) == "1"} {
          etm_ClearRegionZone $etmTemp(What)
        } elseif {$etmTemp(APPLY,$name) == "-1"} {
          set etmTemp(APPLY,$name) 0
          etm_DeleteRegionZone "$name"
        }
      } else {
        etm_ClearAllRegionZones
      }
      etm_ShowDomainZone $which
    }
}

proc etm_ShowDomainZone {which} {
global etmList etmTemp

  if {$etmTemp(What) == "NonRelaxationZone" || \
      $etmTemp(What) == "RelaxationZone"} {
    set list $etmList(Domains)
  } elseif {$etmTemp(What) == "EdgeViolate"} {
    set list $etmList(EdgeViolate)
  }
  for {set i 0} {$i < [llength $list]} {incr i} {
    if {[lindex [lindex $list $i] 1] == $which} {
      set etmTemp(Domain) [lindex [lindex $list $i] 0]
      set etmTemp(Min) [lindex [lindex $list $i] 2]
      set etmTemp(Max) [lindex [lindex $list $i] 3]   
      set etmTemp(i_from) [lindex $etmTemp(Min) 0]
      set etmTemp(j_from) [lindex $etmTemp(Min) 1]
      set etmTemp(k_from) [lindex $etmTemp(Min) 2]
      set etmTemp(i_to) [lindex $etmTemp(Max) 0]
      set etmTemp(j_to) [lindex $etmTemp(Max) 1]
      set etmTemp(k_to) [lindex $etmTemp(Max) 2]
      break
    }
  }  
  if [etm_ErrorMessageIJK] { return }
  futil_updown_reset_minmax etmTemp(i_from) $etmTemp(i_from) $etmTemp(i_to)
  futil_updown_reset_minmax etmTemp(i_to) $etmTemp(i_from) $etmTemp(i_to)
  futil_updown_reset_minmax etmTemp(j_from) $etmTemp(j_from) $etmTemp(j_to)
  futil_updown_reset_minmax etmTemp(j_to) $etmTemp(j_from) $etmTemp(j_to) 
  futil_updown_reset_minmax etmTemp(k_from) $etmTemp(k_from) $etmTemp(k_to)
  futil_updown_reset_minmax etmTemp(k_to) $etmTemp(k_from) $etmTemp(k_to)  
  if {$etmTemp(What) == "NonRelaxationZone" || $etmTemp(What) == "RelaxationZone"} {
    etm_CreateSubfaceZone $etmTemp(What) $etmTemp(Domain) $etmTemp(Min) $etmTemp(Max)
    if $etmTemp(SliderOn) {
      etm_ShowCornerVertex $etmTemp(CornerOn)
    }
  } elseif {$etmTemp(What) == "EdgeViolate"} {
    set etmTemp(Edge,$which) "$etmTemp(What),$etmTemp(Domain).$etmTemp(Min).$etmTemp(Max)"
    etm_CreateEdgeZone $etmTemp(What) $etmTemp(Domain) $etmTemp(Min) $etmTemp(Max)
  }
  set len [llength [form_listbox_get_select_index .rzm.main.1.1.1]]
  if {$len == "0" || $len > "1"} {
    set etmTemp(Selected) 0
  } else {    
    set etmTemp(Selected) 1
  }
}

proc etm_CreateSubfaceZone { what dom min max } {
global etmImageZone etmTemp

  if {$min != $max} {
    set shade wire
    set draw_nodes 0
  } else {
    set shade solid
    set draw_nodes 1
  }  
  set im [ic_str_create_zone white $shade]
  ic_str_clear_ijk_zone $im
  ic_str_add_ijk_zone $im $dom $min $max
  ic_str_configure_zone $im draw_nodes $draw_nodes
  set name $dom.$min.$max
  set etmTemp(Name) $what,$name
  set etmImageZone($etmTemp(Name)) $im
}

proc etm_CreateEdgeZone { what dom min max } {
global etmImageZone etmTemp

  set im [ic_str_create_zone white wire]
  ic_str_clear_ijk_zone $im
  ic_str_add_ijk_zone $im $dom $min $max 
  ic_str_configure_zone $im width 3
  ic_str_configure_zone $im color_type white
  set name $dom.$min.$max
  set etmTemp(Name) $what,$name
  set etmImageZone($etmTemp(Name)) $im
  lappend etmTemp(Images) $etmTemp(Name)
}

proc etm_SetRegionIJK {{on 0}} {
global etmTemp

  if [etm_ErrorMessageIJK] { return }
  set min "$etmTemp(i_from) $etmTemp(j_from) $etmTemp(k_from)"
  set max "$etmTemp(i_to) $etmTemp(j_to) $etmTemp(k_to)"  
  if !$on {
    if [info exist etmTemp(Name)] {
      if ![info exists etmTemp(APPLY,$etmTemp(Name))] {
        etm_DeleteRegionZone $etmTemp(Name)
      } else {
        etm_ConfigureImageZone $etmTemp(Name) 0
      }
    }
  }
  if { ($etmTemp(What) == "NonRelaxationZone") || ($etmTemp(What) == "RelaxationZone") } {
    etm_CreateSubfaceZone $etmTemp(What) $etmTemp(Domain) $min $max
  } elseif { $etmTemp(What) == "EdgeViolate" } {
    etm_CreateEdgeZone $etmTemp(What) $etmTemp(Domain) $min $max
  }
}

proc etm_SliderOnOff {} {
global etmTemp

  if $etmTemp(SliderOn) {
    if [etm_ErrorMessageIJK] { return }
    etm_ClearRegionZone $etmTemp(What)
    etm_ShowCornerVertex $etmTemp(CornerOn)
  } else {
    etm_ClearRegionZone $etmTemp(What)
  }
}

proc etm_ShowCornerVertex { value } {
global etmList etmTemp etmSmoother

  if !$etmTemp(SliderOn) { return }
  if [etm_ErrorMessageIJK] { return }
  etm_SetCornerVertex $value
  etm_SetRegionIJK
}

proc etm_ErrorMessageIJK {} {
global etmTemp

  if {$etmTemp(i_from) == "" || $etmTemp(j_from) == "" || $etmTemp(k_from) == "" || \
      $etmTemp(i_to)   == "" || $etmTemp(j_to)   == "" || $etmTemp(k_to)   == ""} {
    etm_ShowMessage INFO "No $etmTemp(Text) selected or missing ijk value(s)."
    return 1
  }
  if {$etmTemp(i_to) < $etmTemp(i_from) || $etmTemp(j_to) < $etmTemp(j_from) || \
      $etmTemp(k_to) < $etmTemp(k_from)} {
    etm_ShowMessage ERROR "Wrong ijk min or ijk max value(s)."
    return 1
  } 
  return 0
}

proc etm_ConvertSubfaces { on } {
global etmList

  if $on {
    foreach number [ic_str_list_entities subface] {
      set ijk [ic_str_get_ijk subface $number]
      set dom [lindex [lindex $ijk 0] 0]; incr dom
      set min [lindex [lindex $ijk 0] 1]
      set max [lindex [lindex $ijk 0] 2]
      foreach i { 0 1 2 } {
        set p1 [lindex $min $i]
        set p2 [lindex $max $i]
        if { $p1 != $p2 } {
          set inc 2
          set d [expr $p2 - $p1] 
          if { $d < 3 }  { set inc 0 } 
          if { $d <= 5 } { set inc 1 } 		
          if { $d > 5 }  { set inc [expr $d - $d/2 - 2] }
          set min [lreplace $min $i $i [expr $p1 + $inc]]
          set max [lreplace $max $i $i [expr $p2 - $inc]]
        }
      }
      set im [ic_str_get_surf_zone subface $number]
      ic_str_clear_ijk_zone $im
      ic_str_add_ijk_zone $im $dom $min $max
      append etmList(Backup,IJK,$im) $ijk
    }
  } else {
    foreach item [ array names etmList Backup,IJK,* ] {
      set im [lindex [split $item ,] 2]
      set dom [lindex [lindex $etmList($item) 0] 0]; incr dom
      set min [lindex [lindex $etmList($item) 0] 1]
      set max [lindex [lindex $etmList($item) 0] 2]
      ic_str_clear_ijk_zone $im
      ic_str_add_ijk_zone $im $dom $min $max
      unset etmList($item)
    }
  }    
}

proc etm_ShowOneImage { mode type number on color } {
global etmImage
  
  if $on {
    set etmImage($mode,$number) [list $color $type]
  } elseif [info exists etmImage($mode,$number)] {
    unset etmImage($mode,$number)
  }
  catch { ic_str_highlight $mode $number $on $color }
  ic_str_set_nums_visible $mode "$number $on"
  if {$type == "LayerExtensionSubface"} {
    set im [ic_str_get_surf_zone $mode $number]
    ic_str_configure_zone $im draw_name $on  
  }
}

proc etm_SetSelectedImagesOff {mode} {
global etmImage

  foreach item { subface edge vertex } {
    if ![string match $mode $item] {
      set list ""
      foreach i [array names etmImage $item,*] {
        set m [lindex [split $i ,] 0]
        if {$m == $item} {
          set n [lindex [split $i ,] 1]
          append list "$n 0 "
        }
        if {$list != ""} {
          ic_str_set_nums_visible $m "$list"
        }
      }
    }
  }
}

proc etm_SetDisplayOnOff {} {
global etmSmoother
  
  if $etmSmoother(DisplayOn) {
    etm_ShowAll
  } else {
    etm_ClearView
    etm_ClearAllRegionZones
  }  
}

proc etm_ShowAll {} {
global str_type_visible

  foreach item { subface edge domain vertex } {
    if [etm_ShowAllSelectedImages $item] {
      set str_type_visible($item) 1
    } else {
      set str_type_visible($item) 0
    }
  }
  etm_ShowAllSelectedImagesZones
  etm_SetTypeVisible domain 1
}

proc etm_ShowAllSelectedImages { mode } {
global etmImage etmColors etmMode

  set found 0
  foreach item [array names etmImage] {
    if [string match $mode [lindex [split $item ,] 0]] {
      set number [lindex [split $item ,] 1]
      set color [lindex $etmImage($item) 0]
      set type [lindex $etmImage($item) 1]
      etm_ShowOneImage $mode $type $number 1 $color
      set found 1
    }
  }
  return $found
}

proc etm_ShowAllSelectedImagesZones {} {
  foreach item {RelaxationZone NonRelaxationZone EdgeViolate NonRelaxationSubface} {
    etm_ShowSelectedImagesZones $item
  }
}

proc etm_ConfigureImageZone {zone on {color ""}} {
global etmImageZone

  if [info exists etmImageZone($zone)] {
    ic_str_configure_zone $etmImageZone($zone) visible $on
    if ![string match "" $color] {
      ic_str_configure_zone $etmImageZone($zone) color_type $color
    }
  }
}

proc etm_ShowSelectedImagesZones { what } {
global etmImageZone etmColors

  if [etm_IsArrayOk etmRelaxZone] {
    foreach item [array names etmImageZone $what,*] {
      etm_ConfigureImageZone $item 1 $etmColors($what)
    }
  }
  if [etm_IsArrayOk etmViolGeomZone] {
    foreach item [array names etmImageZone $what,*] {
      etm_ConfigureImageZone $item 1 $etmColors($what)
    }
  }
}

proc etm_ClearView {} {
global etmImageZone
    
  foreach item { subface edge domain vertex } {
    etm_SetTypeVisible $item 0
  }
  foreach item [ array names etmImageZone ] {
    etm_ConfigureImageZone $item 0
  }
}

proc etm_ClearAllImages {} {
global etmImage

  foreach item [array names etmImage] {
    set c [lindex $etmImage($item) 0]
    set t [lindex $etmImage($item) 1]
    set m [lindex [split $item ,] 0]
    set i [lindex [split $item ,] 1]
    etm_ShowOneImage $m $t $i 0 $c
  }
}

proc etm_ClearRegionZone { what } {
global etmImageZone
  
  foreach item [ array names etmImageZone $what,* ] {
    etm_ConfigureImageZone $item 0
  }
}

proc etm_ClearAllRegionZones {} {
global etmImageZone
  
  foreach item [ array names etmImageZone ] {
    etm_ConfigureImageZone $item 0
  }
}

proc etm_DeleteRegionZone { item } {
global etmImageZone

  if [info exists etmImageZone($item)] {
    ic_str_delete_zone $etmImageZone($item)
    unset etmImageZone($item)
  }
}

proc etm_DeleteAllRegionZones { what } {
global etmImageZone

  foreach item [array names etmImageZone $what,*] {
    etm_DeleteRegionZone $item
  }
}

proc etm_ClearAllImagesLayers {} {
global etmImage

  foreach item [array names etmImage] {
    set type [lindex $etmImage($item) 1]
    if {$type == "LayerExtensionSubface"} {
      set c [lindex $etmImage($item) 0]
      set m [lindex [split $item ,] 0]
      set n [lindex [split $item ,] 1]
      etm_ShowOneImage $m $type $n 0 $c
    }
  }
}

proc etm_ClearSelections {} {
global etmSmoother etmList
  
  etm_ClearView  
  etm_ClearAllImages
  etm_UnsetSelectionsArrays
  foreach item { subface edge domain vertex } {
    disp_set_option $item
  }
  foreach v [array names etmList APPLY,*] { unset etmList($v) }
  foreach v {RelaxationZone NonRelaxationZone EdgeViolate NonRelaxationSubface} {
    etm_DeleteAllRegionZones $v
  }
  foreach v {SmoothDir PlaneSmooth PlaneNumbers VertexLayer \
             abs_dist_subf n_abs_dist_subf VertexAttrib \
             grid_exp_rate_subf_perp grid_exp_rate_subf_1} {
    if [info exists etmList($v)] { unset etmList($v) }
  }
  ic_str_clear_diagnostics
  set etmSmoother(DisplayOn) 0
}

proc etm_UnsetSelectionsArrays {} {
global etm etmList
  
  foreach v {etmEdgeAttr etmEdgeGlobal etmRelaxSubface etmLayerExtensionNo \
  	     etmRelaxZone etmViolGeomZone etmLayerExtensionIJK \
  	     etmRegion etmViolGeomSubface etmMeshingLawPar etmVertexGlobal \
  	     etmRelaxZoneAdd etmImageZone etmRelaxZoneSave etmEdgeGlobalSave \
  	     etmVertexFixed etmRelaxCoeff} {
    etm_UnsetArray $v
  }
  foreach v {SmoothDir PlaneSmooth PlaneNumbers VertexLayer \
             abs_dist_subf n_abs_dist_subf \
             grid_exp_rate_subf_perp grid_exp_rate_subf_1} {
    if [info exists etmList($v)] { unset etmList($v) }
  }
  foreach v {PlaneNumbers sf} {
    foreach item [array names etm $v,*] {
      if {[lindex [split $item ,] 1] != "win"} {
        unset etm($item)
      }
    }
  }
  foreach v {etmRelaxCoeff grid_exp_rate_subf_perp grid_exp_rate_subf_1} {
    foreach item [array names etmList $v,*] {
      unset etmList($item)
    }
  }
}

proc etm_CreateSmoothLists {} {
global etmList

  foreach v {etmEdgeAttr etmEdgeGlobal etmRelaxSubface etmLayerExtensionNo \
  	     etmRelaxZone etmViolGeomZone etmLayerExtensionIJK \
  	     etmRegion etmViolGeomSubface etmMeshingLawPar etmVertexGlobal \
  	     etmRelaxZoneAdd} {
    if [ etm_IsArrayOk $v ] {
      global $v

      set etmList($v) {}
      foreach item [ array names $v ] {
        lappend etmList($v) [ set $v\($item) ]
      }
      set etmList($v) [ lsort -command etm_SortList $etmList($v) ]
      etm_FormatList $v
    } else {
      etm_UnsetArray $v
      etm_InitList $v
    }
  }
  if ![info exists etmList(PlaneNumbers)] {
    set etmList(PlaneNumbers) ""
  }
}

proc etm_CreateGlobalList {} {
global etmList etmEdgeGlobalSave etmRelaxZoneSave etmRelaxZoneAdd
      
    set etmList(etmEdgeGlobal) {}
    foreach item [ array names etmEdgeGlobalSave ] {
      lappend etmList(etmEdgeGlobal) $etmEdgeGlobalSave($item)
    }
    set etmList(etmEdgeGlobal) [ lsort -command etm_SortList $etmList(etmEdgeGlobal) ]
    etm_FormatList etmEdgeGlobal
    foreach item [ array names etmRelaxZoneSave ] {
      append etmList(etmRelaxZone) " $etmRelaxZoneSave($item)"
    }
    etm_FormatList etmRelaxZone 
    set etmList(etmRelaxZoneAdd) {}
    foreach item [ array names etmRelaxZoneAdd ] {
      append etmList(etmRelaxZoneAdd) "$etmRelaxZoneAdd($item) "
    }
}

proc etm_CreateGlobalSaveList {} {
global etmEdgeGlobal etmVertexGlobal etmRelaxZone 
global etmEdgeGlobalSave etmRelaxZoneSave etmRelaxZoneAdd

  if {[info exists etmEdgeGlobal] && ([array size etmEdgeGlobal] != 0)} {
    catch { unset etmEdgeGlobalSave }
    catch { unset etmRelaxZoneSave }
    catch { unset etmRelaxZoneAdd }
    foreach item [array names etmEdgeGlobal] {
      set etmEdgeGlobalSave($item) $etmEdgeGlobal($item)
      lappend numbers $item
      set tmp($item) 1
    }
    if [info exists numbers] {
      set vertices [ic_str_list_edge_vertices $numbers]
      foreach item $vertices {
        foreach {dom i j k} $item {
          set min "$i $j $k"
          set max $min
          set var "$dom $min $max 0"
          set etmRelaxZoneSave($dom,$min,$max) $var
          set etmRelaxZoneAdd($dom,$min) "$dom $min"
        }
      }
      unset numbers
    }
    if {[info exists etmVertexGlobal] && ([array size etmVertexGlobal] != 0)} {
      foreach item [array names etmVertexGlobal] {
         append numbers "$item "
      }
      if [info exists numbers] {
        set edges [ic_str_list_vertex_edges $numbers]
        foreach item $edges {
          set a [lindex $item 0]
          lappend vertex_global $a
          set b [lindex $item 1]
          foreach c $b {
            set dom [lindex $c 0]
            set i [lindex $c 1]
            set j [lindex $c 2]
            set k [lindex $c 3]
            lappend non_relax "$dom $i $j $k $i $j $k 0"
          }
        }        
        if [info exists vertex_global] {
          foreach item $vertex_global {
            foreach i $item {
              if ![info exists tmp($i)] {
                set etmEdgeGlobalSave($i) $i
              }
            }
          }
        }
        if [info exists tmp] { unset tmp }
        foreach item [array names etmRelaxZone] {
          set etmRelaxZoneSave($item) $etmRelaxZone($item)
          set tmp($etmRelaxZone($item) 1
        }
        if [info exists non_relax] {
          foreach item $non_relax {
            if ![info exists tmp($item)] {
              set dom [lindex $item 0]
              set min "[lindex $item 1] [lindex $item 2] [lindex $item 3]"
              set max "[lindex $item 4] [lindex $item 5] [lindex $item 6]"
              set etmRelaxZoneSave($dom,$min,$max) $item
              set etmRelaxZoneAdd($dom,$min) "$dom $min"
            }
          }
        }
      }
    } else {
      foreach item [array names etmEdgeGlobal] {
        set etmEdgeGlobalSave($item) $etmEdgeGlobal($item)
        lappend numbers $item
        set tmp($item) 1
      }
      if [info exists numbers] {
        set vertices [ic_str_list_edge_vertices $numbers]
        foreach item $vertices {
          foreach {dom i j k} $item {
            set min "$i $j $k"
            set max $min
            set var "$dom $min $max 0"
            set etmRelaxZoneSave($dom,$min,$max) $var
            set etmRelaxZoneAdd($dom,$min) "$dom $min"
          }
        }
      }
    }
  } elseif {[info exists etmVertexGlobal] && ([array size etmVertexGlobal] != 0)} {
    foreach item [array names etmVertexGlobal] {
       append numbers "$item "
    }
    if [info exists numbers] {
      set edges [ic_str_list_vertex_edges $numbers]
      foreach item $edges {
        set a [lindex $item 0]
        lappend vertex_global $a
        set b [lindex $item 1]
        foreach c $b {
          set dom [lindex $c 0]
          set i [lindex $c 1]
          set j [lindex $c 2]
          set k [lindex $c 3]
          lappend non_relax "$dom $i $j $k $i $j $k 0"
        }
      }
      catch { unset etmEdgeGlobalSave }
      if [info exists vertex_global] {
        foreach item $vertex_global {
          foreach i $item {
            if ![info exists tmp($i)] {
              set etmEdgeGlobalSave($i) $i
            }
          }
        }
      }     
      catch { unset etmRelaxZoneSave }
      catch { unset etmRelaxZoneAdd }
      foreach item [array names etmRelaxZone] {
        set etmRelaxZoneSave($item) $etmRelaxZone($item)
        set tmp($etmRelaxZone($item) 1
      }
      if [info exists non_relax] {
        foreach item $non_relax {
          if ![info exists tmp($item)] {
            set dom [lindex $item 0]
            set min "[lindex $item 1] [lindex $item 2] [lindex $item 3]"
            set max "[lindex $item 4] [lindex $item 5] [lindex $item 6]"
            set etmRelaxZoneSave($dom,$min,$max) $item
            set etmRelaxZoneAdd($dom,$min) "$dom $min"
          }
        }
      }
    }
  }
}

proc etm_CreateDomainList {} {
global etmList etmFlag env
  
  for { set i 0 } { $i < [llength $etmList(Domains)] } { incr i } {
    if $etmFlag($i) {
      lappend list 1
    } else {
      lappend list 0
    }
  }
  set etmList(SmoothDomain) $list
  if ![info exists etmList(SmoothDir)] {
    etm_PlaneSmoothingReset
  } elseif {![info exists etmList(PlaneSmooth)] && \
             [info exists etmList(SmoothDir)]} {
    set list ""
    for { set i 0 } { $i < [ llength $etmList(Domains) ] } { incr i } {
      lappend list "-1 -1 -1 0"
    }
    set etmList(PlaneSmooth) $list
    etm_FormatList PlaneSmooth
  }
  if ![info exists etmList(VertexLayer)] {
    set etmList(VertexAttrib) ""
    set etmList(VertexLayer) ""
  } else {
    set etmList(VertexAttrib) $etmList(VertexLayer)
    etm_FormatList VertexAttrib
  }
}

proc etm_CreateMethodLists {} {
global etmParam etmMethod etmList etmSmoother
  
  set etmList(FaceMethods) {}
  set etmList(VolumeMethods) {}
  set etmList(UnselectedMethods) {}
  
  for { set i 0 } { $i < [ llength $etmList(Domains) ] } { incr i } {
    if !$etmSmoother(2D) {
      if [ info exists etmParam(Mix,$i) ] {
        lappend etmList(FaceMethods) $etmParam(Mix,$i)
      } else {
        set list {}
        for { set x 0 } { $x < 6 } { incr x } { 
          lappend list $etmMethod($etmParam(3D,$i))
        }
        lappend etmList(FaceMethods) $list
      } 
    } else {
      set list {}
      for { set x 0 } { $x < 6 } { incr x } { 
        lappend list $etmMethod($etmParam(2D,$i))
      }
      lappend etmList(FaceMethods) $list
    }
  }
  etm_FormatList FaceMethods
  for { set i 0 } { $i < [ llength $etmList(Domains) ] } { incr i } {
    lappend etmList(VolumeMethods) $etmMethod($etmParam(3D,$i))
    lappend etmList(UnselectedMethods) "$etmMethod($etmParam(Unselected,$i))"
  }
  for { set i 0 } { $i < [ llength $etmList(Domains) ] } { incr i } {
    if [info exists etmList(etmRelaxCoeff,2D,outer,$i)] {
      lappend list_2D $etmList(etmRelaxCoeff,2D,outer,$i)
    } else {
      lappend list_2D "0 0 0 0 0 0"
    }
    if [info exists etmList(etmRelaxCoeff,3D,outer,$i)] {
      lappend list_3D $etmList(etmRelaxCoeff,3D,outer,$i)
    } else {
      lappend list_3D "0 0 0 0 0 0"
    }
    if [info exists etmList(etmRelaxCoeff,2D,inner,$i)] {
      lappend list_2D_inner $etmList(etmRelaxCoeff,2D,inner,$i)
    } else {
      lappend list_2D_inner "0 0 0 0 0 0"
    }
    if [info exists etmList(etmRelaxCoeff,3D,inner,$i)] {
      lappend list_3D_inner $etmList(etmRelaxCoeff,3D,inner,$i)
    } else {
      lappend list_3D_inner "0 0 0 0 0 0"
    }
    if [info exists etmList(grid_exp_rate_subf_perp,$i)] {
      lappend list_subf_perp $etmList(grid_exp_rate_subf_perp,$i)
    } else {
      lappend list_subf_perp "-1 -1 -1 -1 -1 -1"
    }
    if [info exists etmList(grid_exp_rate_subf_1,$i)] {
      lappend list_subf_1 $etmList(grid_exp_rate_subf_1,$i)
    } else {
      lappend list_subf_1 "-1 -1 -1 -1 -1 -1"
    }
  }
  set etmList(relax_weights_2d) $list_2D
  set etmList(relax_weights_3d) $list_3D
  set etmList(relax_weights_inner_2d) $list_2D_inner
  set etmList(relax_weights_inner_3d) $list_3D_inner
  set etmList(grid_exp_rate_subf_perp) $list_subf_perp
  set etmList(grid_exp_rate_subf_1) $list_subf_1
  etm_FormatList relax_weights_2d
  etm_FormatList relax_weights_3d
  etm_FormatList relax_weights_inner_2d
  etm_FormatList relax_weights_inner_3d
  etm_FormatList grid_exp_rate_subf_perp
  etm_FormatList grid_exp_rate_subf_1
  if ![info exists etmList(abs_dist_subf)] {
    for { set i 0 } { $i < [ llength $etmList(Domains) ] } { incr i } {
      lappend abs_dist_subf "-1.0 -1.0 -1.0 -1.0 -1.0 -1.0"
    }
    set etmList(abs_dist_subf) $abs_dist_subf
  }
  if ![info exists etmList(n_abs_dist_subf)] {
    for { set i 0 } { $i < [ llength $etmList(Domains) ] } { incr i } {
      lappend n_abs_dist_subf "-1 -1 -1 -1 -1 -1"
    }
    set etmList(n_abs_dist_subf) $n_abs_dist_subf
  } 
  etm_FormatList abs_dist_subf
  etm_FormatList n_abs_dist_subf
}

proc etm_CreateRelaxSubfaceList { do_relax } {
global etmRelaxSubface

  set list ""
  foreach n [ array names etmRelaxSubface ] {
    if { [ lindex $etmRelaxSubface($n) 1 ] == $do_relax } { 
      lappend list $n
    }
  }
  return $list
}

proc etm_CreateLayerExtensionNoList {} {
global etmLayerExtensionNo

  set list ""
  foreach item [ array names etmLayerExtensionNo ] {
    set n [ lindex $etmLayerExtensionNo($item) 0 ]
    lappend list $n
  }
  return $list
}

proc etm_CreatePredefSubfacesList {} {
global etm etmList

  set list ""
  if [ info exists etmList(SubfacePredefMesh) ] {
    foreach item $etmList(SubfacePredefMesh) {
      lappend list $item
    }
  } else {
    foreach item $etm(BaseSubfacesNo) {
      lappend list $item
    }
  }
  return $list
}

proc etm_FormatList {list} {  
  global etmList
  
  regsub -all \{ $etmList($list) "" etmList($list)
  regsub -all \} $etmList($list) "" etmList($list)
}

proc etm_SortList { one two } { 
  return [ expr [ lindex $one 0 ] - [ lindex $two 0 ] ]
}

proc etm_UnsetList { arg } {
global etmList
  if [info exists etmList($arg)] {
    unset etmList($arg)
  }
}

proc etm_InitList { arg } {
global etmList
  set etmList($arg) ""
}

proc etm_UnsetArray { arg } {
global $arg  
  if [info exists $arg] {
    unset $arg
  }
}

proc etm_IsArrayItemOk { what which } {
global $what
  if ![ info exists $what\($which) ] {
    return  0
  }
  if { [ llength [ set $what\($which) ] ] == "0" } {
    return  0
  } 
  return 1
}

proc etm_IsArrayOk { what } {
global $what

  if { ![ info exists $what ] || [ llength $what ] == 0 } {
    return  0
  } 
  return 1
}

proc etm_GetArrayItemValue { what which } {
global $what
  
  if ![ info exists $what\($which) ] {
    return -1
  }
  return [ set $what\($which) ]
}

proc etm_2d_3d { { item "" } } {

  if { [expr [lindex $item 0] - 1] == 0 || \
       [expr [lindex $item 1] - 1] == 0 || \
       [expr [lindex $item 2] - 1] == 0 } {
    return 0
  } else {
    return 1
  }
}

proc etm_LoadStructMesh {} {
global etmList etmSmoother etm str_type_visible

  set etmSmoother(2D) 1
  set etmSmoother(DisplayOn) 0  
  set etmList(Domains) {}  
  if ![info exists etm(batch)] {
    set str_type_visible(domain) 1
    disp_change_overall_visible domain
  }
  set etmList(Domains) ""
  foreach n [ic_str_list_entities domain] {
    foreach a [ic_str_get_topo_info domain 0 0] {
      if {[lindex $a 3] == $n} {
        set min [lindex $a 5]
        set max [lindex $a 6]
        set fam [lindex $a 2]
        break
      }
    }
    lappend etmList(Domains) [list $n DOM$n $min $max $fam $n]
  } 
  if {[etm_2d_3d "$max"] != "0"} {
    set etmSmoother(2D) 0
    set etm(mesh_type) 0
  } else {
    set etm(mesh_type) 2
  }
}

proc etm_ShowLayerExtensionNo { number type mode weight on } {
global etmColors etmMode

  etm_ShowOneImage subface $type $number $on $etmColors($type)
  etm_SetLayerExtensionNo $on $number $etmMode($mode) $weight
} 

proc etm_ShowRelaxSubface { number type on } {
global etmColors etmMode etm
  
  if ![info exists etm(batch)] {
    etm_ShowOneImage subface $type $number $on $etmColors($type)
  }
  etm_SetRelaxSubface $on $number $etmMode($type)
} 

proc etm_ShowEdgeAttr { number type on } {
global etmColors etmMode etmEdgeAttr

  if [info exists etmEdgeAttr($number)] {
    set the_type [lindex $etmEdgeAttr($number) 1]
    if {$type == "EdgeBunching"} {
      if {$the_type == $etmMode(EdgeFrozen) || $the_type == $etmMode(EdgeBunchingFrozen)} {
        if $on {
          set type EdgeBunchingFrozen
        } else {
          set type EdgeFrozen
          set on 1
        }
      } 
    } elseif {$type == "EdgeFrozen"} {
      if {$the_type == $etmMode(EdgeBunching) || $the_type == $etmMode(EdgeBunchingFrozen)} {
        if $on {
          set type EdgeBunchingFrozen
        } else {
          set type EdgeBunching
          set on 1
        }
      }     
    }
  }
  etm_ShowOneImage edge $type $number $on $etmColors($type)
  etm_SetEdgeAttr $on $number $etmMode($type)
  if $on {
    etm_SetEdgeGlobal 0 $number
  }
}

proc etm_ShowEdgeGlobal { number on } {
global etmColors etmMode etm

  if ![info exists etm(batch)] {
    etm_ShowOneImage edge EdgeGlobal $number $on $etmColors(EdgeGlobal)
  }
  etm_SetEdgeGlobal $on $number
  if $on { 
    foreach item {EdgeBunching EdgeFrozen} {
      etm_SetEdgeAttr 0 $number $etmMode($item)
    }
  }
}

proc etm_SetMode {} {
global etmMode

  set etmMode(EdgeFloating) 0
  set etmMode(EdgeBunching) 1
  set etmMode(EdgeFrozen) 2
  set etmMode(EdgeBunchingFrozen) 3
  set etmMode(EdgeGlobal) 4
  
  set etmMode(VertexGlobal) 4
  set etmMode(VertexFixed) 2

  set etmMode(NonRelaxationSubface) 0
  set etmMode(RelaxationSubface) 1
  set etmMode(NonRelaxationZone) 0
  set etmMode(RelaxationZone) 1
  set etmMode(NonRelaxationDomain) 0
  set etmMode(RelaxationDomain) 1
  
  set etmMode(SubfaceDefault) 0
  set etmMode(SubfaceNeighbor) 1
  set etmMode(SubfaceSymmetric) 2
  set etmMode(SubfaceOrthogonal) 3 
  set etmMode(SubfaceLinear) 4
  set etmMode(SubfaceOrtho_Lin) 5
  set etmMode(SubfaceSymm_Lin) 6    

  set etmMode(InterpolateSoni) 0
  set etmMode(InterpolateHermite) 1
  set etmMode(InterpolateOff) 2    

  set etmMode(SmoothSorenson) 0
  set etmMode(SmoothThomasMiddlecoff) 1
  set etmMode(SmoothLaplace) 2
  set etmMode(SmoothHilgenst) 9
  set etmMode(SmoothInterpolation) 4
  set etmMode(SmoothMeshCalculated) 5
  set etmMode(SmoothSor_ThM) 6
  set etmMode(SmoothSor_Lap) 7
  set etmMode(SmoothHilgenstock_ThM) 10
  set etmMode(SmoothFaceMethods) 9
  set etmMode(SmoothNone) -1
  set etmMode(SmoothDeformation) -2
  
  set etmMode(ProgGlobalSmooth) 0
  set etmMode(ProgLocalSmooth) 1
  set etmMode(ProgSingleSmooth) 2
  set etmMode(ProgImprover) 3
  set etmMode(ProgPredefinedMesh) 4
  set etmMode(ProgSingleGlobal) 5
  set etmMode(ProgSingleGlobalPlane) 6
  set etmMode(ProgSingleEdge) 7
  set etmMode(Prog3DGlobal) 5
  
  set etmMode(PostSelectAllExclViol) 0
  set etmMode(PostSelectConcentrViol) 1
  set etmMode(PostSelectAll) 2
  
  set etmMode(PostGroupBadElem) 0

  set etmMode(MeshLawDefault) 0
  set etmMode(MeshLawHyperbolic) 1
  set etmMode(MeshLawBigeometric) 2
  set etmMode(MeshLawGeometric) 3
  set etmMode(MeshLawBiexponential) 4
  set etmMode(MeshLawExponential) 5
  set etmMode(MeshLawPoisson) 6
  set etmMode(MeshLawUniform) 7
  set etmMode(MeshLawGLL) 8  
  set etmMode(VarVector) 1
  set etmMode(VarVectorX) 0.0
  set etmMode(VarVectorY) 0.0
  set etmMode(VarVectorZ) 0.0
  set etmMode(VarSpace1) 0.0
  set etmMode(VarSpace2) 0.0
  set etmMode(VarSpace1-2) 0.0
  set etmMode(VarSpace2-2) 0.0
  set etmMode(VarRatio) 1.1
  set etmMode(VarSubfaceExtend) 0
  set etmMode(VarSubfaceSelected) ""

  set etmMode(CriterionDeterminant) 0
  set etmMode(CriterionOrthogonality) 1
  set etmMode(CriterionWarp) 2
  set etmMode(CriterionQuality) 3
  set etmMode(CriterionSkewness) 4
  set etmMode(CriterionDistortion) 5
  set etmMode(CriterionAspectRatio) 6
  set etmMode(CriterionOppFaceRatio) 7
  set etmMode(CriterionParallelism) 8
}

proc etm_SetRelaxZone { on number imin imax do_relax } {
global etmRelaxZone

  if $on {
    set etmRelaxZone($number,$imin,$imax) [ list $number $imin $imax $do_relax ]
  } else {
    catch { unset etmRelaxZone($number,$imin,$imax) }
  }  
}

proc etm_SetRelaxSubface { on number do_relax } {
global etmRelaxSubface

  if $on {
    set etmRelaxSubface($number) [ list $number $do_relax ]
  } else {
    catch { unset etmRelaxSubface($number) }
  }
}

proc etm_SetEdgeAttr { on number mode } {
global etmEdgeAttr

  if $on {
    set etmEdgeAttr($number) [ list $number $mode ]
  } else {
    catch { unset etmEdgeAttr($number) }
  }
}

proc etm_SetEdgeGlobal { on number } {
global etmEdgeGlobal etmEdgeGlobalSave

  if $on {
    set etmEdgeGlobal($number) [ list $number ]
  } else {
    catch { unset etmEdgeGlobal($number) }
    catch { unset etmEdgeGlobalSave($number) }
  }
}

proc etm_SetVertexGlobal { on number mode } {
global etmVertexGlobal

  if $on {
    set etmVertexGlobal($number) [ list $number ]
  } else {
    catch { unset etmVertexGlobal($number) }
  }
}

proc etm_SetVertexFixed { on number mode } {
global etmVertexFixed

  if $on {
    set etmVertexFixed($number) [ list $number ]
  } else {
    catch { unset etmVertexFixed($number) }
  }
}


proc etm_SetLayerExtensionNo { on { number "" } { mode "" } { weight "" } } {
global etmLayerExtensionNo

  if $on {
    set etmLayerExtensionNo($number) [ list $number $mode $weight ]
  } else {
    catch { unset etmLayerExtensionNo($number) }
  }
}

proc etm_SetLayerExtensionIJK { on number imin imax mode weight } {
global etmLayerExtensionIJK

  if $on {
    set etmLayerExtensionIJK($number,$imin,$imax) [ list $number $imin $imax $mode $weight ]
  } else {
    catch { unset etmLayerExtensionIJK($number,$imin,$imax) }
  }
}

proc etm_SetViolGeomZone { on number imin imax dist } {
global etmViolGeomZone

  if $on {
    set etmViolGeomZone($number,$imin,$imax) [ list $number $imin $imax $dist ]
  } else {
    catch { unset etmViolGeomZone($number,$imin,$imax) }
  }  
}

proc etm_SetViolGeomSubface { on number dist } {
global etmViolGeomSubface

  if $on {
    set etmViolGeomSubface($number) [ list $number $dist ]
  } else {
    catch { unset etmViolGeomSubface($number) }
  }
}

proc etm_SetRegion { on number imin imax } {
global etmRegion

  if $on {
    set etmRegion($number,$imin,$imax) [ list $number $imin $imax ]
  } else {
    catch { unset etmRegion($number,$imin,$imax) }
  }
}

proc etm_SetMeshingLawPar { on { law "" } { s1 "" } { s2 "" } { s3 "" } { s4 "" } { ratio "" } } {
global etmMeshingLawPar

  if $on {
    set etmMeshingLawPar($law) [ list $law $s1 $s2 $s3 $s4 $ratio ]
  } else {
    foreach item [ array names etmMeshingLawPar ] {
      unset etmMeshingLawPar($item)
    }
  }
}

proc etm_SetColors {} {
global etmColors

  set etmColors(EdgeBunching) orange
  set etmColors(NonEdgeBunching) purple
  set etmColors(EdgeFrozen) violet
  set etmColors(EdgeBunchingFrozen) red
  set etmColors(EdgeViolate) darkgreen
  set etmColors(EdgeGlobal) blue
  set etmColors(RelaxationSubface) cyan
  set etmColors(NonRelaxationSubface) purple
  set etmColors(LayerExtensionSubface) green
  set etmColors(RelaxationZone) cyan
  set etmColors(NonRelaxationZone) purple 
  set etmColors(RelaxationDomain) cyan
  set etmColors(NonRelaxationDomain) purple 
  set etmColors(PredefMesh) yellow
  set etmColors(CoefficientsSubface2D) gray
  set etmColors(CoefficientsSubface3D) gray
  set etmColors(VertexGlobal) blue
  set etmColors(VertexLayer) darkgreen
  set etmColors(VertexFixed) violet 
  set etmColors(BladeBoundary) blue
  set etmColors(FACE,imin) #fe0000
  set etmColors(FACE,imax) #fe9898
  set etmColors(FACE,jmin) #00fe00 
  set etmColors(FACE,jmax) #98fe98
  set etmColors(FACE,kmin) #0000fe
  set etmColors(FACE,kmax) #9898fe
  set etmColors(FACE,D) #ffe4c4
}

proc etm_BatchStartSmoothing { project prog_select } {
global etmList etm
  
    set etm_dir $project/mesh
    set smooth_domain $etmList(SmoothDomain)
    set face_methods $etmList(FaceMethods)
    set volume_methods $etmList(VolumeMethods)
    set niter $etm(Niter)
    set nsteps $etm(Nsteps)
    set maxlevel $etm(Maxlevel)
    set sfit $etm(Sfit)
    set conditional $etm(Conditional)
    set check_det $etm(CheckDet)
    set damping $etm(Damping)
    set vertex_fix $etm(VertexFix)
    set edge_freeze $etm(EdgeFreeze)
    set wedge_check $etm(WedgeCheck)
    set multigrid2d $etm(Multigrid2D)
    set reduced_edge $etm(ReducedEdge)
    set fix_fam $etm(FixFam)
    set inner_vol_sm $etm(InnVol)
    set ns_rel $etm(NsRel)
    set angle_freeze_edge $etm(AngleFreezeEdges)
    set n_iter $etm(nItera)
    set interp_faces $etm(InterpFaces)
    set interp_volumes $etm(InterpVolumes)
    set prog_select $prog_select
    set threshold_det $etm(ThresholdDet)
    set threshold_angle $etm(ThresholdAngle)
    set subface_extensions $etmList(etmLayerExtensionNo)
    set ijk_extensions $etmList(etmLayerExtensionIJK)
    set edge_attrib $etmList(etmEdgeAttr)
    set relax_subfaces $etmList(etmRelaxSubface)
    set relaxation_zones $etmList(etmRelaxZone)
    set viol_geom_zones $etmList(etmViolGeomZone)
    set viol_geom_subfaces $etmList(etmViolGeomSubface)
    set base_subfaces_no $etm(BaseSubfacesNo)
    set meshing_law $etmList(etmMeshingLawPar)
    set subface_extend $etm(SubfaceExtend)
    set direction_vector $etm(DirectionVector)
    set base_regions $etmList(etmRegion)
    set type_improve $etm(TypeImprove)
    set type_postsm $etm(TypePostSm)
    set proj_limit $etm(ProjLimit)
    set group_bad_elem $etm(GroupBadElem)
    set smooth_dir $etmList(SmoothDir)
    set mesh_type $etm(mesh_type)
    set smooth_ngh_method $etmList(UnselectedMethods)
    set surfresolv $etm(SmoothOnFaces)
    set min_mxr $etm(MinResidual)
    set min_res $etm(StopResidual)
    set edge_no_global_smooth $etmList(etmEdgeGlobal)
    set incr_3d_plane_smooth $etmList(PlaneSmooth)
    set relax_weights_2d $etmList(relax_weights_2d)
    set relax_weights_3d $etmList(relax_weights_3d)
    set relax_weights_inner_2d $etmList(relax_weights_inner_2d)
    set relax_weights_inner_3d $etmList(relax_weights_inner_3d)
    set n_iter_glb $etm(n_iter_glb)
    set n_steps_glb $etm(n_steps_glb)
    set global_vertices_opp $etmList(etmRelaxZoneAdd)
    set plane_numbers $etmList(PlaneNumbers)
    set grid_exp_face $etm(grid_exp_face)
    set grid_exp_vol $etm(grid_exp_vol)
    set abs_dist_bnd $etm(abs_dist_bnd)
    set n_points_abs_dist_bnd $etm(n_points_abs_dist_bnd)
    set use_pthreads $etm(use_pthreads)
    set abs_dist_subf $etmList(abs_dist_subf) 
    set n_abs_dist_subf $etmList(n_abs_dist_subf)
    set vertex_attrib $etmList(VertexAttrib)
    set relaxation_factor $etm(relaxation_factor)
    set use_orthog_position $etm(use_orthog_position)
    set use_fract_position $etm(use_fract_position)
    set grid_exp_rate_subf_perp $etmList(grid_exp_rate_subf_perp)
    set grid_exp_rate_subf_1 $etmList(grid_exp_rate_subf_1)
    set first_cell_height $etm(first_cell_height)
    set last_cell_height $etm(last_cell_height)
    
    ic_str_smooth_glsm 1 $etm_dir \
    	$smooth_domain $face_methods $volume_methods $niter \
    	$nsteps $maxlevel $sfit $conditional $check_det $damping $vertex_fix \
    	$edge_freeze $wedge_check $multigrid2d $reduced_edge $fix_fam \
    	$inner_vol_sm $ns_rel $angle_freeze_edge $n_iter \
    	$interp_faces $interp_volumes $prog_select $threshold_det $threshold_angle \
    	$subface_extensions $ijk_extensions $edge_attrib $relax_subfaces \
    	$relaxation_zones $viol_geom_zones $viol_geom_subfaces $base_subfaces_no \
    	$meshing_law $subface_extend $direction_vector $base_regions \
    	$type_improve $type_postsm $proj_limit $group_bad_elem \
    	$smooth_dir $mesh_type $smooth_ngh_method $surfresolv $min_mxr \
    	$edge_no_global_smooth $incr_3d_plane_smooth $relax_weights_2d \
    	$relax_weights_3d $relax_weights_inner_2d $relax_weights_inner_3d \
    	$n_iter_glb $n_steps_glb $global_vertices_opp $plane_numbers \
    	$grid_exp_face $grid_exp_vol $min_res $abs_dist_bnd $n_points_abs_dist_bnd \
    	$abs_dist_subf $n_abs_dist_subf $vertex_attrib $relaxation_factor \
    	$use_orthog_position $use_fract_position $grid_exp_rate_subf_perp \
    	$grid_exp_rate_subf_1 $first_cell_height $last_cell_height $use_pthreads
}

proc etm_BatchOpenSettingsFile {setting} {
global env
      
  set f [open $setting r]
  etm_LoadSettings $f
  close $f
}

proc etm_BatchLoadSettings {project what tetin setting} {
global env is_win
     
    if ![info exists is_win] { set is_win [expr ![file exists /etc/passwd]] }
    if {$project == ""} {
      puts "Missing project name."
      exit
    } elseif ![file exists $project] {
      puts "No such project: $project."
      exit
    }
    if {$tetin == ""} {
      puts "Missing tetin file name."
      exit
    } elseif ![file exists $tetin] {
      if ![file exists $project/mesh/$tetin] {
        puts "No such tetin file: $tetin."
        exit
      } else {
        set tetin $project/mesh/$tetin
      }
    }
    if {$setting == ""} {
      puts "Missing smoothing settings file name."
      exit      
    } elseif ![file exists $setting] {
      puts "No such settings file $setting."
      exit
    } else {
      set f [open $setting r]
      set line [ gets $f ]
      set header "Settings Management for Smoothing and Predefined Mesh: Med"
      if ![string match $header $line] {
        puts "\nInvalid settings file: $setting.\n"
        close $f
        exit
      }
      close $f
    }
    if [file exists $project/domains] {
      set domain $project/domains/domain
      set domain_dir $project/domains
    } else {
      set domain $project/domain
      set domain_dir $project
    }
    if [file exists $project/mesh] {
      set mesh_dir $project/mesh
    } else {
      set mesh_dir $project
    }
    if [file exists $mesh_dir/topo_mulcad_out.top] {
      set topo $mesh_dir/topo_mulcad_out.top
    } elseif [file exists $mesh_dir/topo_mulcad_out] {
      set topo $mesh_dir/topo_mulcad_out
    } else {
      puts "File not found: $mesh_dir/topo_mulcad_out or $mesh_dir/topo_mulcad_out.top"
      exit
    }
    if [file exists $mesh_dir/family_topo.fto] {
      set family $mesh_dir/family_topo.fto
    } elseif [file exists $mesh_dir/family_topo] {
      set family $mesh_dir/family_topo
    } else {
      puts "File not found: $mesh_dir/family_topo or $mesh_dir/family_topo.fto."
      exit
    }
    if [file exists $mesh_dir/subface_proj] {
      set subface_proj $mesh_dir/subface_proj
    } else {
      puts "File not found: $mesh_dir/subface_proj."
      exit
    }

    if !$is_win {
      set prog med
    } else {
      set prog "med_batch.exe"
    }
    if {$what == "0"} {
      set using "Global"
    } elseif {$what == "1"} {
      set using "Local"
    } elseif {$what == "2"} {
      set using "Single"
    } elseif {$what == "3"} {
      set using "Post" 
    } elseif {$what == "4"} {
      set using "Predefined mesh"
    } elseif {$what == "5"} {
      set using "Single global"
    } elseif {$what == "6"} {
      set using "Single global plane"
    } elseif {$what == "7"} {
      set using "Single edge"
    }
    puts "Loading project $project..."
    puts "Using tetin file $tetin..."
    puts "Using $topo and $family and $subface_proj..."
    puts "Using smoothing type <$using> to smooth domains."
    set pid [pid]
    set fn ./script.$pid
    set f [open $fn w]
    puts $f "source $env(MED_ROOT)/lib/med_gui/glsm_med.tcl"
    puts $f "ic_load_struct $domain $topo $family $subface_proj"
    puts $f "ic_load_tetin $tetin"
    puts $f "global etm"
    puts $f "set etm(batch) 1"
    puts $f "etm_SetMode"
    puts $f "etm_LoadMethods"
    puts $f "etm_DefaultParameter"
    puts $f "etm_DefaultParameterPost"
    puts $f "puts \"Using smoothing type <$using> to smooth domains.\""
    puts $f "puts \"Loading settings file $setting...\""
    puts $f "etm_BatchOpenSettingsFile $setting"
    puts $f "puts \"Done loading settings file.\""
    puts $f "etm_LoadStructMesh"
    if {$what == "5" || $what == "6"} {
      puts $f "etm_CreateGlobalSaveList"
    }
    puts $f "etm_CreateSmoothLists"
    puts $f "etm_CreateDomainList"
    puts $f "etm_CreateMethodLists"
    if {$what == "5" || $what == "6"} {
      puts $f "etm_CreateGlobalList"
    }
    puts $f "etm_BatchStartSmoothing $project $what"
    puts $f "ic_str_save $domain_dir $topo $family $subface_proj"
    puts $f "exit"
    close $f
    set log logfile.$pid
    puts "Logfile is $log"
    puts "Start smoothing..."
    if !$is_win {
      set cmd "$env(MED_ROOT)/bin/$prog -batch -script $fn"
      eval exec $cmd >& ./$log
    } else {
      set cmd "$env(MED_ROOT)/bin/$prog -script $fn"
      eval exec start /wait $cmd >& ./$log
    }
    puts "Project $project saved."
    puts "Done smoothing."
    exit
}

proc etm_BatchLoadSettingsNew {project what tetin setting} {
global env is_win etm
     
    if ![info exists is_win] { set is_win [expr ![file exists /etc/passwd]] }
    if {$project == ""} {
      puts "Missing project name."
      exit
    } elseif ![file exists $project] {
      puts "No such project: $project."
      exit
    }
    if {$tetin == ""} {
      puts "Missing tetin file name."
      exit
    } elseif ![file exists $tetin] {
      if ![file exists $project/mesh/$tetin] {
        puts "No such tetin file: $tetin."
        exit
      } else {
        set tetin $project/mesh/$tetin
      }
    }
    if {$setting == ""} {
      puts "Missing smoothing settings file name."
      exit      
    } elseif ![file exists $setting] {
      puts "No such settings file $setting."
      exit
    } else {
      set f [open $setting r]
      set line [ gets $f ]
      set header "Settings Management for Smoothing and Predefined Mesh: Med"
      if ![string match $header $line] {
        puts "\nInvalid settings file: $setting.\n"
        close $f
        exit
      }
      close $f
    }
    if [file exists $project/domains] {
      set domain $project/domains/domain
      set domain_dir $project/domains
    } else {
      set domain $project/domain
      set domain_dir $project
    }
    if [file exists $project/mesh] {
      set mesh_dir $project/mesh
    } else {
      set mesh_dir $project
    }
    if [file exists $mesh_dir/topo_mulcad_out.top] {
      set topo $mesh_dir/topo_mulcad_out.top
    } elseif [file exists $mesh_dir/topo_mulcad_out] {
      set topo $mesh_dir/topo_mulcad_out
    } else {
      puts "File not found: $mesh_dir/topo_mulcad_out or $mesh_dir/topo_mulcad_out.top"
      exit
    }
    if [file exists $mesh_dir/family_topo.fto] {
      set family $mesh_dir/family_topo.fto
    } elseif [file exists $mesh_dir/family_topo] {
      set family $mesh_dir/family_topo
    } else {
      puts "File not found: $mesh_dir/family_topo or $mesh_dir/family_topo.fto."
      exit
    }
    if [file exists $mesh_dir/subface_proj] {
      set subface_proj $mesh_dir/subface_proj
    } else {
      puts "File not found: $mesh_dir/subface_proj."
      exit
    }

    if {$what == "0"} {
      set using "Global"
    } elseif {$what == "1"} {
      set using "Local"
    } elseif {$what == "2"} {
      set using "Single"
    } elseif {$what == "3"} {
      set using "Post" 
    } elseif {$what == "4"} {
      set using "Predefined mesh"
    } elseif {$what == "5"} {
      set using "Single global"
    } elseif {$what == "6"} {
      set using "Single global plane"
    } elseif {$what == "7"} {
      set using "Single edge"
    }
    puts "Loading project $project..."
    puts "Using tetin file $tetin..."
    puts "Using $topo and $family and $subface_proj..."
    puts "Using smoothing type <$using> to smooth domains."
    set pid [pid]
    ic_load_struct $domain $topo $family $subface_proj
    ic_load_tetin $tetin
    set etm(batch) 1
    etm_SetMode
    etm_LoadMethods
    etm_DefaultParameter
    etm_DefaultParameterPost
    puts "Using smoothing type <$using> to smooth domains."
    puts "Loading settings file $setting..."
    etm_BatchOpenSettingsFile $setting
    puts "Done loading settings file."
    etm_LoadStructMesh
    if {$what == "5" || $what == "6"} {
      etm_CreateGlobalSaveList
    }
    etm_CreateSmoothLists
    etm_CreateDomainList
    etm_CreateMethodLists
    if {$what == "5" || $what == "6"} {
      etm_CreateGlobalList
    }
    puts "Start smoothing..."
    etm_BatchStartSmoothing $project $what
    ic_str_save $domain_dir $topo $family $subface_proj
    puts "Project $project saved."
    puts "Done smoothing."
}

proc do_glsm_regression_test {project tetin what settings {no_family_topo 0}} {
    global env script_file tcl_platform file_name etm etmList
   
    if ![file exists $settings] {
        mess "Error: Settings file <$settings> not found.\n"
        return 1
    }
    set test_dir [pwd]
    if ![file exists mulcad] {
      set file_name(project_dir) $project
    } else {
      set file_name(project_dir) mulcad/$project
    }
    if ![file exists $file_name(project_dir)] {
        mess "Error: Project <$file_name(project_dir)> not found.\n"
        return 1
    }
    if [file exists $file_name(project_dir)/mesh] {
      set file_name(mesh_dir) $file_name(project_dir)/mesh
    } else {
      set file_name(mesh_dir) $file_name(project_dir)
    }
    if [file exists $file_name(project_dir)/domains] {
      set file_name(domains_dir) $file_name(project_dir)/domains
    } else {
      set file_name(domains_dir) $file_name(project_dir)
    }
    set file_name(tetin) $file_name(mesh_dir)/$tetin
    if ![file exists $file_name(tetin)] {
        mess "Error: Tetin file <$file_name(tetin)> not found.\n"
        return 1
    }
    if !$no_family_topo {
      set file_name(family_topo) $file_name(mesh_dir)/family_topo.fto
      if ![file exists $file_name(family_topo)] {
          set file_name(family_topo) $file_name(mesh_dir)/family_topo
          if ![file exists $file_name(family_topo)] {
            mess "Error: Family topo file <$file_name(family_topo)> not found.\n"
            return 1
          }
      }
    } else {
      set file_name(family_topo) ""
    }
    set file_name(topo_mulcad_out) $file_name(mesh_dir)/topo_mulcad_out.top    
    if ![file exists $file_name(topo_mulcad_out)] {
        set file_name(topo_mulcad_out) $file_name(mesh_dir)/topo_mulcad_out
        if ![file exists $file_name(topo_mulcad_out)] {
          mess "Error: Topology file <$file_name(topo_mulcad_out)> not found.\n"
          return 1
        }
    }
    set file_name(subface_proj) $file_name(mesh_dir)/subface_proj    
    if ![file exists $file_name(subface_proj)] {
        mess "Error: Topology file <$file_name(subface_proj)> not found.\n"
        return 1
    }
    mess "Smoother: Start regression test for project $file_name(project_dir)...\n"

    ic_load_tetin $file_name(tetin)
    ic_load_struct $file_name(domains_dir)/domain $file_name(topo_mulcad_out) $file_name(family_topo) $file_name(subface_proj)
    set etm(batch) 1
    etm_SetMode
    etm_LoadMethods
    etm_DefaultParameter
    etm_DefaultParameterPost    
    mess "Loading settings file $settings...\n"
    etm_BatchOpenSettingsFile $settings
    mess "Done loading settings file.\n"    
    etm_LoadStructMesh    
    if {$what == "5" || $what == "6"} {
      etm_CreateGlobalSaveList
    }
    etm_CreateSmoothLists
    etm_CreateDomainList
    etm_CreateMethodLists
    if {$what == "5" || $what == "6"} {
      etm_CreateGlobalList
    }

    ic_str_clear_diagnostics
    for {set i 0} {$i < [llength $etmList(SmoothDomain)]} {incr i} {
      if {[lindex $etmList(SmoothDomain) $i] == 1} {
        set x $i; lappend dom_list [expr $x + 1] 
      }
    }
    set diag [ic_str_metric Determinant $dom_list]
    set before(Determinant,Num) [lindex $diag 0]
    if {[string index [lindex $diag 3] 0] == "-"} {
        set use_index 5
    } else {
        set use_index 4
    }
    set before(Determinant,Min)  [string range [lindex $diag 3] 0 $use_index]
    set before(Determinant,Max)  [string range [lindex $diag 4] 0 4]
    set before(Determinant,Mean) [string range [expr [lindex $diag 5] / ($before(Determinant,Num) + 0.0)] 0 4]
     
    mess "\nStarting smoothing ...\n"
    switch $what {
      0 { set using "Global" }
      1 { set using "Local" }
      2 { set using "Single" }
      3 { set using "Post" }
      4 { set using "Predefined mesh" }
      5 { set using "Single global" }
      6 { set using "Single global plane" }
      7 { set using "Single edge" }
      default { mess "Unknown smoothing type\n"; return }
    }
    mess "Using smoothing type <$using> to smooth domains.\n"
    etm_BatchStartSmoothing $file_name(project_dir) $what
    mess "Done smoothing.\n"
    
    ic_str_clear_diagnostics
    set diag [ic_str_metric Determinant $dom_list]
    set after(Determinant,Num)  [lindex $diag 0]
    set after(Determinant,Min)  [string range [lindex $diag 3] 0 $use_index]
    set after(Determinant,Max)  [string range [lindex $diag 4] 0 4]
    set after(Determinant,Mean) [string range [expr [lindex $diag 5] / ($after(Determinant,Num) + 0.0)] 0 4]
    
    ic_unload_tetin
    ic_unload_mesh 
    
#    mess "\nTesting: Results (Number of elements $before(Determinant,Num)\)\n"
#    mess "\nDeterminant before smoothing elements: Min: $before(Determinant,Min) Max: $before(Determinant,Max) Mean: $before(Determinant,Mean)"
#    mess "\nDeterminant after smoothing elements : Min: $after(Determinant,Min) Max: $after(Determinant,Max) Mean: $after(Determinant,Mean)"
    set min_diff  [expr $after(Determinant,Min) - $before(Determinant,Min)]
    set max_diff  [expr $after(Determinant,Max) - $before(Determinant,Max)]
    set mean_diff [expr $after(Determinant,Mean) - $before(Determinant,Mean)]
    set min_ok 1; set max_ok 1; set mean_ok 1
    set mess_worse  "Result is worse than before.\n"
    set mess_same   "Result is the same than before.\n"
    set mess_better "Result is better than before.\n"
#    mess "\n\nResults from  current smoothing test: Diff. Min: $min_diff - "
    if {[expr $before(Determinant,Min) > $after(Determinant,Min)]} {
#        mess $mess_worse
        set min_ok 0
    } elseif {[expr $before(Determinant,Min) == $after(Determinant,Min)]} {
#        mess $mess_same
        set min_ok 2
    } else {
#        mess $mess_better
    }
    if {[expr $before(Determinant,Max) > $after(Determinant,Max)]} {
        set max_ok 0
    } elseif {[expr $before(Determinant,Max) == $after(Determinant,Max)]} {
        set max_ok 2
    }
    if {[expr $before(Determinant,Mean) > $after(Determinant,Mean)]} {
        set mean_ok 0
    } elseif {[expr $before(Determinant,Mean) == $after(Determinant,Mean)]} {
        set mean_ok 2
    }   
    set result_differs 0
    set result_better 0
    set os $tcl_platform(os)
    if {$os == "IRIX"} { 
      set arch sgi
    } elseif {$os == "IRIX64"} {
      set arch sgi64
    } elseif {$os == "AIX"} {
      set arch ibm
    } elseif {$os == "SunOS"} {
      set arch sol
    } elseif {$os == "OSF1"} {
      set arch dec
    } elseif {$os == "HP-UX"} {
      set arch hp
    } elseif {$os == "Linux"} {
      set arch linux
    } else {
      set arch win
    }
    if ![file exists mulcad] {
      set proj_name $project
    } else {
      set proj_name [file dirname $project]
    }
    set test_file $test_dir/results/$arch/results.$proj_name
    if [file exists $test_file] {
        set fp [open $test_file r]
        while {![eof $fp]} {
            set line [gets $fp]
            switch $line {
                "Determinant after smoothing elements:" {
                    set result(Min) [lindex [gets $fp] 1]
                    set result(Max) [lindex [gets $fp] 1]
                    set result(Mean) [lindex [gets $fp] 1]
                }
            }
        }
        close $fp
        set mess_worse "Previous result was worse than now.\n"
        set mess_same "Previous result was the same than now.\n"
        set mess_better "Previous result was better than now.\n"
#        mess "Results from previous smoothing test: Min: $result(Min) - "
        if {[expr $result(Min) < $after(Determinant,Min)]} {
#            mess $mess_worse
            set result_differs 1
            set result_better 1
        } elseif {[expr $result(Min) == $after(Determinant,Min)]} {
#            mess $mess_same
        } else {
#            mess $mess_better
            set result_differs 1
        }
    }
    if [info exists env(GLSM_REGRESSION_TEST)] {
      if {(![file exists $test_file] || ($result_better == "1"))} {
        mess "\nWriting results to file $test_file ...\n"
        set fp [open $test_file w]
        puts $fp "# This is a generated file - do not edit."
        puts $fp "Project: $proj_name"
        puts $fp "Testing: Results (Number of elements $before(Determinant,Num)\)"
        puts $fp "Determinant before smoothing elements:"
        puts $fp "Min: $before(Determinant,Min)"
        puts $fp "Max: $before(Determinant,Max)"
        puts $fp "Mean: $before(Determinant,Mean)"
        puts $fp "Determinant after smoothing elements:"
        puts $fp "Min: $after(Determinant,Min)"
        puts $fp "Max: $after(Determinant,Max)"
        puts $fp "Mean: $after(Determinant,Mean)"
        puts $fp "That means:"
        set mess_worse "Result is worse than before."
        set mess_same "Result is the same than before."
        set mess_better "Result is better than before."
        puts -nonewline $fp "Diff. Min: $min_diff - "
        if { $min_ok == "0" } {
            puts $fp $mess_worse
        } elseif { $min_ok == "2" } {
            puts $fp $mess_same
        } else {
            puts $fp $mess_better
        }
        puts -nonewline $fp "Diff. Max: $max_diff - "
        if { $max_ok == "0" } {
           puts $fp $mess_worse
        } elseif { $max_ok == "2" } {
           puts $fp $mess_same
        } else {
           puts $fp $mess_better
        }
        puts -nonewline $fp "Diff. Mean: $mean_diff - "
        if { $mean_ok == "0" } {
           puts $fp $mess_worse
        } elseif { $mean_ok == "2" } {
           puts $fp $mess_same
        } else {
           puts $fp $mess_better
        }
        close $fp
      }
    }
    if {$result_differs == "1" && $result_better != "1"} {
      set ret 1
    } else {
      set ret 0
    }
    mess "\n\n"
    return $ret
}
