# This file contains interface to hexa blocking
# Authors - Ganesan/Jari

proc aie_update_vert_proj {{numbers ""} {move_ogrid 0}} {
    if $move_ogrid {
	    set move_ogrid "move_ogrid_nodes"
    } else {
	    set move_ogrid ""
    }

    if {$numbers == "all"} {
	    hex_command "project_to_surface [range_string] [ic_geo_list_families] $move_ogrid"
    } elseif {$numbers == "active"} {
    	hex_command "project_to_surface [range_string] [family_activename_string] $move_ogrid"
    } else {
	    foreach n $numbers {
	        set ind [ic_hex_vertex_ijk $n]
	        set ijk_min_max ""
	        set i 0
	        foreach i {0 1 2} {
		        set d [lindex $ind $i]
		        lappend ijk_min_max $i:$d,$d
		        incr i
	        }
	        hex_command "project_to_surface $ijk_min_max [family_activename_string] $move_ogrid"
	    }
    }
    hex_update_display vertex edge face block mesh
}

proc aie_get_vert_proj {{numbers ""}} {
    if {$numbers == ""} { return "" }
    set ret ""
    catch { array unset ijk_temp }
	foreach n $numbers {
	    set ind [ic_hex_vertex_ijk $n]
	    set ijk_min_max ""
	    foreach i {0 1 2} {
		    set d [lindex $ind $i]
		    if ![info exists ijk_temp($i:$d,$d)] {
		        lappend ijk_min_max $i:$d,$d
		        set ijk_temp($i:$d,$d) 1
		    }
	    }
	    if {$ijk_min_max != ""} {
	        lappend ret $ijk_min_max
	    }
	}
    return "$ret"
}

proc aie_update_vert_proj_edge {edges} {
    foreach edge $edges {
	    set n1 [lindex $edge 0]
	    set n2 [lindex $edge 1]
	    hex_command "project_to_surface $n1 $n2"
    }
}

proc aie_update_association {{what {}}} {
    global top_current
    hex_command "update_association $top_current $what"
    hex_update_display edge face block mesh
}

proc aie_change_vertproj {type} {
    global display_flag aie_blockVertProj
   
    if $aie_blockVertProj($type) {
        foreach name {proj indices number} {
            set aie_blockVertProj($name) 0
        }
        set aie_blockVertProj($type) 1
        set display_flag(vert_how) $type
    }
    if $display_flag(vert) {
        hex_update_display vert
    }
}

proc aie_change_meshstyle {type} {
    global display_flag aie_blockMeshStyle
   
    if $aie_blockMeshStyle($type) {
        foreach name {1 2} {
            set aie_blockMeshStyle($name) 0
        }
        set aie_blockMeshStyle($type) 1
        set display_flag(mesh_mesh) $type
    }
    if $display_flag(mesh) {
        hex_update_display mesh
    }
}

proc aie_change_meshproj {type} {
    global display_flag aie_blockMeshProj
    global project_type dim_to_mesh
   
    if $aie_blockMeshProj($type) {
        foreach name {-1 0 1 2} {
            set aie_blockMeshProj($name) 0
        }
        set aie_blockMeshProj($type) 1
        set project_type $type
        set dim_to_mesh [ max $dim_to_mesh $project_type ]
    }
    if $display_flag(mesh) {
        hex_update_display mesh
    }
}

proc aie_change_domain_shade {type} {
    global aie_strShade str_option
   
    if $aie_strShade(domain,$type) {
	foreach name {none wire solid flat_wire hidden} {
	    set aie_strShade(domain,$name) 0
	}
	set aie_strShade(domain,$type) 1
	set str_option(domain,shade) $type
    } else {
	set aie_strShade(domain,$type) 1
    }
    disp_set_option domain
}

proc aie_change_subface_shade {type} {
    global aie_strShade str_option
   
    if $aie_strShade(subface,$type) {
        foreach name {wire solid flat_wire hidden} {
            set aie_strShade(subface,$name) 0
        }
        set aie_strShade(subface,$type) 1
        set str_option(subface,shade) $type
    } else {
        set aie_strShade(subface,$type) 1
    }
    disp_set_option subface
}

proc aie_blank_blocks {do} {
    global display_flag use_output_blocks

    set blocks ""
    if {$do == "blank"} {
        set blocks [select_hexa block 0 "blocks to blank"]
    } elseif {$do == "mapped" || $do == "swept" || $do == "free"} {
        if $use_output_blocks {
            set blks [eval ic_hex_get_block_families_and_types [volume_activename_string] output_blocks]
        } else {
            set blks [eval ic_hex_get_block_families_and_types [volume_activename_string]]
        }
        foreach b $blks {
            if {[lindex $b 1] == "ORFN" || [lindex $b 1] == "VORFN"} continue
            if {[lindex $b 2] == "$do"} {
                append blocks "[lindex $b 0] "
            }
        }
    } else {
        hex_command "unblank_blocks"
    }
    if {$blocks != ""} {
        ic_hex_blank_selected_blocks $use_output_blocks $display_flag(use_blanking) $blocks
        set display_flag(use_blanking) 1
    }
    hex_update_display mesh block edge vertex face
}

proc aie_unload_blocking {} {
    global tdv_waiting_for_click tdv_default display_flag
    global hexa_select select_action

    aie_hex_clear_worst_element
    
    # Clear if in selection mode
    set wait 0
    if [info exists hexa_select] {
	    set select_action done
	    catch {unset hexa_select}
	    set wait 1
    }
    if [info exists tdv_waiting_for_click($tdv_default)] {
	    set tdv_waiting_for_click($tdv_default) {2 0 0}
	    set wait 1
    }
    if $wait {
	    mess "Clearing current selection\n" red
	    after 100 { ic_hex_unload_blocking }
    } else {
	    ic_hex_unload_blocking
    }
    banner ""
    foreach type "vert edge face block mesh" {
        set display_flag($type) 0
    }
    hex_update_display
}

proc aie_hex_update_display {} {
    ::AIEnv::GUIManagement::Tree::UpdateBlockingVisibility
    hex_update_display
    get_indices 0
    index_update_all
}

proc aie_hex_index_control {{tearoff 0}} {
    global plot_window index_form hexa_histogram_exist

    if ![ic_hex_blocking_loaded] {
        mess "No Blocking is loaded!\n" red
        return
    }
    get_indices 0
    if {$tearoff || ([info exists hexa_histogram_exist]) || \
	    ([info exists index_form] && [winfo exists $index_form])} {
        if {[winfo children $plot_window] == "$plot_window.indexf"} {
            set w $plot_window
        } else {
            set w ""
        }
    } else {
        set w $plot_window
    }
    setup_index_box $w
}

proc aie_hex_scan_planes {{tearoff 0}} {
    global plot_window index_form
    global hexa_histogram_exist

    if {$tearoff || ([info exists hexa_histogram_exist]) || \
	    ([info exists index_form] && [winfo exists $index_form])} {
        set w ""
    } else {
        set w $plot_window
    }
    mesh_scan_planes $w
}

proc aie_convert_str_to_blocking {} {
    global use_output_blocks file_name
   
    if ![ic_hex_blocking_loaded] {
        msg ERROR "No Blocking Loaded"
        return
    }
    set cmd "read_domains [family_activename_string]"   
    set prefix ""
    if {[info exists file_name(settings)] && $file_name(settings) != ""} {
        set prefix [file tail [file rootname $file_name(settings)]]      
    } elseif {$file_name(domain) != ""} {
        set dfp [file root [file tail $file_name(domain)]]
        if {$dfp != "Multiblock"} {
            set prefix $dfp
        }
    }
    if {$prefix != ""} {
        append cmd " -dom_prefix ${prefix}."
    }

    if { $use_output_blocks } {
        append cmd " -output_blocks"
    }
    hex_command $cmd
    hex_update_display mesh
}

proc aie_convert_uns_to_blocking {} {
    global file_name env

    if ![ic_uns_is_loaded] {
        msg ERROR "No unstruct mesh loaded"
        return
    }

    set uns_file __temp_mesh__.uns
    set blk_file __temp_blocking__.blk

    ic_save_unstruct $uns_file
    if ![file isfile $uns_file] {
        msg ERROR "Could not convert unstruct mesh to blocking"
        return
    }

    mess "Creating blocking from unstruct mesh...\n" blue
    set args "-s $uns_file $blk_file"
    if [catch {ic_run_application_exec . icemcfd mesh2block $args} res] {
        msg ERROR "$res"
        return
    } 

    if ![file isfile $blk_file] {
        msg ERROR "Could not convert unstruct mesh to blocking"
        return
    }
    aie_open_blocking 0 $blk_file
    cmd_rm $uns_file
    cmd_rm $blk_file

    if [aie_hex_sketching_mode] {
        mess "Disassociate vertices, edges and faces..."
        ic_hex_sketch_unset_projections
        mess "Done\n"
    }
    
    mess "Done creating blocking from unstruct mesh\n" blue
    hex_update_display
}

# These were the original functions used for testing at the begining of the
# hexa integration with AI*Env; obsolete now - Ganesan
############################### feature block #####################
proc atest {n} {
    ic_hex_init
    ic_hex_restore_blocking ./hex-test$n.blk
}

proc block_split {} {
    global last_line button_instructions

    hex_command "mark_blocks unmark" 0
    set split_onlymarked 0
  
    set split_edge [select_hexa edge 1 "Please select the edge to split $button_instructions" "new_format"]
    if {$split_edge == ""} return
   
    set split_n1 [lindex $split_edge 0]
    set split_n2 [lindex $split_edge 1]
    banner $button_instructions
    set val [ic_hex_select_value $split_n1 $split_n2 [volume_activename_string] ]
    banner ""
    mess "val: $val\n" blue
    if {$val == ""} return
    ic_hex_split_grid $split_n1 $split_n2 $val m [volume_activename_string]
    ic_hex_display_edge_mesh 2:0,4 m  [volume_activename_string] volume
    hex_update_display edge face block mesh
}

proc block_delete {how} {
    global families family_name family_dims botform_geo use_output_blocks
    global merge_block_numbers display_flag
    global button_instructions
   
    set cmd ""
    switch $how {
	ijk {
	    set nodes [select_node "Please select two vertices $button_instructions" 3 ]
	    if {[llength $nodes] < 2} return
	    set first [lindex $nodes 0]
	    set second [lindex $nodes 1]
	    set cmd "delete_blocks \{ $first \} \{ $second \}"
	}
	sel {
	    hex_command "mark_blocks unmark" 0
	    if ![block_mark_super 1 0 "to Merge" ""] return
	    set cmd "delete_blocks marked"
	}
	two {
	    set nb [get_hexa_nsuperblocks]
	    for {set i 1} {$i <= $nb} {incr i} {
		    set merge_block_numbers($i) 0
	    }
	    set r [form_block_numbers merge_block_numbers 0 "to Delete"]
	   
# If cancelled, stop here
	   
	    if !$r return;
	   
	    set mm ""
	    for {set i 1} {$i <= $nb} {incr i} {
		    if $merge_block_numbers($i) { lappend mm $i }
	    }
	    set cmd "delete_blocks numbers $mm"
	}
	blanked {
	    set mess "Permanently delete blanked blocks?"
	    set ret [tk_dialog .tivc "Confirm" $mess "" 0 Apply Cancel]
        switch -- $ret {
            -1 { if [winfo exists .tivc] { top_destroy .tivc; return } }
            1 {return}
        }
	    set cmd "delete_blocks blanked [volume_activename_string]"
	}
    }
    if $use_output_blocks { append cmd " output_blocks" }
    if $display_flag(use_blanking) { append cmd " -use_blanking" }
   
    hex_command $cmd
    hex_command "remove_unused_grid_lines"
   
    hex_update_display edge face block mesh vertex
    get_indices 0
}

proc block_split_face { how } {
    global last_line button_instructions display_flag
   
   
    if { $how == "corners" } {
    	set nodes [select_node "Select the corners of the face to split $button_instructions" 2]
    	if {[llength $nodes] != 2} return
    	set first [lindex $nodes 0]
    	set second [lindex $nodes 1]
	    set face "\{ $first \} \{ $second \}"
    } elseif { $how == "select" } {
	    set mess "Please select the icon for the face to associated $button_instructions"
	    set cmd "select_super_face node_numbers [range_string] [family_activename_string]"
	    hex_command "$cmd"
	    set nums [string trimright $last_line \n]
	    set face "numbers $nums"
	    if !$display_flag(face) {
	        hex_command "display_super_faces erase"
	    }
	    if { $nums == "" } {
		    return
	    }
    }
# select the split location on the edge
    set edge [select_hexa edge 1 "Please select the edge to split $button_instructions"]
    if {$edge == ""} return
   
    set pos [lindex $edge 0]
    set dim [lindex $edge 1]
   
# select the value on the edge
    banner $button_instructions
    set cmd "select_value \{$pos\} $dim [volume_activename_string] [range_string]"
   
    hex_command $cmd 1 1
    set val [lindex $last_line 0]
    banner ""
    hex_command "select_value erase" 0
    if {$val == ""} return
    foreach split_face $face {
        hex_command "split_face $face \{ $pos \} $dim $val  [volume_activename_string]"
    }

    hex_update_display edge face block mesh
    get_indices 0
    index_update_all
}
###################### End original hexa testing functions ############################

proc aie_topo_extract {{show_tree 1}} {
    global top_current
   
    hex_command "mark_blocks unmark" 0
    set blocks [select_hexa block 0 "Blocks to Extract"]
    if {$blocks == ""} {
	    return
    }
    block_mark_super $blocks
    set top_name [aie_select_unused_topo]
    if {$top_name == ""} {
	    return
    }
    hex_command "extract_blocking $top_name"
    block_unmark
    switch_topology $top_name
    ::AIEnv::GUIManagement::Tree::AddTopo $top_name
    ::AIEnv::GUIManagement::Tree::ToggleTopoVisibility topo $top_name 1
}

proc switch_topology { new_top } {
    global top_current
   
    set top_current $new_top
    hex_command "switch_blocking $top_current"
   
    get_indices 1
    hex_update_display
}

proc aie_rename_topo {name {nname ""}} {
    global top_current

    if {$name == ""} return
   
    if {$nname == ""} {
        set nname [aie_select_unused_topo $name]
        if {$nname == ""} return
    }
   
    hex_command "rename_blocking $name $nname"
    if {$top_current == $name} {
        set top_current $nname
    }
    ::AIEnv::GUIManagement::Tree::RenameGroup topo $name $nname
}

proc aie_delete_topo {name} {
    global top_current
   
    if {$name == ""} return
    if ![info exists top_current] {
        aie_topo_build_defaults
    }
    hex_command "delete_blocking $name"
    ::AIEnv::GUIManagement::Tree::DeleteGroup topo $name 0
    if {$name == $top_current} {
        set top_current ""
        aie_topo_set_default
    }
    hex_update_display
}

proc aie_topo_build_defaults {{reset 1}} {
    global top_current
   
    if $reset {
	    catch {unset top_current}
    }
    set topos [ic_hex_print_topo_tree]
    foreach topo $topos {
	    set name [lindex $topo 0]
	    if ![info exists top_current] {
	        set top_current $name
	    }
	    ::AIEnv::GUIManagement::Tree::AddTopo $name
    }
    aie_topo_set_default
}

proc aie_topo_set_default {} {
    global top_current
   
    if {![info exists top_current] || ($top_current == "")} {
	    set top_current [lindex [lindex [ic_hex_print_topo_tree] 0] 0]
    }
    ::AIEnv::GUIManagement::Tree::ToggleTopoVisibility topo $top_current 1
}


#returns the name of the selected topology
proc aie_topo_select {text { multiple "" } } {
    global top_current last_line topo_selected
   
    set choices ""
    catch { unset topo_selected }
    hex_command "print_topo_tree" 0
    foreach l $last_line {
        set t [lindex $l 0]
	    set topo_selected($t) 0
	    lappend choices $t
    }
    set topo_selected($top_current) 1
   
    if { $multiple != "" } {
	    if { [ check_box_form .top_select $text $choices 10 topo_selected 1 "" "" "" ] == 0 }  {
		    return ""
	    }
	    set ret ""
	    foreach l [ array names topo_selected ] {
		    if { $topo_selected($l) } {
			    lappend ret $l
		    }
	    }
	    return $ret
    } else {
        return [choose_one $text $choices $top_current]
    }
}

proc aie_select_unused_topo {{name ""}} {
   # To avoid leading/trailing spaces in name
    set topos ""
    foreach topo [ic_hex_print_topo_tree] {
	    lappend topos [lindex $topo 0]
    }

    if {$name == ""} {
	    set top_name top0
	    for {set i 0} {[lsearch $topos $top_name] >= 0} {incr i} {
	        set top_name top$i
	    }
    } else {
	    set top_name $name
    }
    while 1 {
	    set top_name [question_box .tname Name "Specify a name for the topology" $top_name]
	    if {$top_name == ""} {
	        return ""
	    }
	    if {[lsearch $topos $top_name] >= 0} {
	        msg ERROR "Subtopology with name: $top_name already exist; specify some other name"
	    } else {
	        break
	    }
    }
    return $top_name
}

proc aie_save_topo {subtopo} {
    global file_name

    set pref [file tail [file rootname $file_name(settings)]]

    set fm [tk_getSaveFile -initialdir [pwd] \
		-initialfile ${pref}_${subtopo}.blk \
		-filetypes {{{Blocking Files} {.blk}} {{All files} *}}]
    if {$fm == ""} return
   
    ic_hex_save_blocking $fm -sub_topo $subtopo
    mess "Blocking file: $fm saved at [cmd_date]\n"
}

proc aie_copy_topo {name} {
    if {$name == ""} return
   
    set nname [aie_select_unused_topo]
    if {$nname == ""} return   
   
    set cmd "copy_blocking $name $nname"
    hex_command $cmd
    ::AIEnv::GUIManagement::Tree::AddTopo $nname 0
}

proc aie_merge_topo {name} {
    global top_current
   
    if {$name == ""} return
   
    set ret [ aie_topo_select "Merge \"$name\" with topology" ]
    if {$ret == ""} return

# get tolerance
    set tol [question_box .mtol "Relative Tolerance" \
		"Specify a relative tolerance for merging the topologies." \
		".1" ]
    if {$tol == ""} return
    hex_command "merge_blocking $name $ret [family_activename_string] \
			-remove_unused_grid_lines -eps $tol \
			-separate_classes -version 110"

    if {$top_current == $name} {
	get_indices 1
	index_reset
	index_update_all
	hex_update_display
    }
}

################################### Create Blocking #########################
proc oncreateBlockDEZLoad {} {
    global env hex_option quad_types env

    set PartList [aie_hex_list_parts 1]
    if {$part_name == ""} {
        set live_pt [lindex [ic_geo_get_objects body] 0]
        if {$live_pt != ""} {
            set part_name [ic_geo_get_family body $live_pt]
        } else {
            set part_name SOLID
        }
    }
    if [info exists env(AI_ENV_IN_WB1)] {
        set part_name "CREATED_MATERIAL"
    }
    if [info exists LongList] { unset LongList }
    
    if {$X == ""} {set X 0}
    if {$Y == ""} {set Y 0}
    if {$Z == ""} {set Z 0}
    if {$angle == ""} {set angle 90}
    if {$ppc == ""} {set ppc 3}
    if {$number == ""} {set number 1}
    set periodicFlag 0
    set collapseFlag 1
    set pointFlag 1
    set curveFlag 1
    set extTwist 0
    set twod2threedEGVal 0
    set applySettings 1
    set inherit_part 0

    if ![info exists env(AI_ENV_LSTC)] {
        if {$minEdgeLen == ""} { set minEdgeLen 0.0 }
        set orientBlk 0
    } else {
        set orientBlk 1
    }
    if ![info exists unsTypeList] {
	    set unsTypeList [array names quad_types]
    }
    if ![info exists unsMethodList] {
	    set unsMethodList [list "ICEM CFD Quad" "Gambit Pave" "Auto"]
	}
    if ![info exists env(AI_ENV_LSTC)] {
	    if {$fillOgridGGVal == ""} { set fillOgridGGVal 0 }
    }
    if [ic_hex_blocking_loaded] {
	    set type [string trimright [ic_hex_unstruct_face_type] \n]
	    set unsType $type
	    set method [string trimright [ic_hex_set_unstruct_face_method] \n]
    } else {
	    set type $hex_option(uns_face_mesh)
	    set method $hex_option(uns_face_mesh_method)
    }
    foreach name [array names quad_types] {
	    if {$type == "$quad_types($name)"} {
	        set unsType $name
	    }
    } 
    if {![info exists unsType] || $unsType == ""} {
        set unsType "Quad w/one Tri"
    }
    if {$method == "uniform_quad"} {
        set unsMethod "ICEM CFD Quad"
    } elseif {$method == "gambit_pave"} {
        set unsMethod "Gambit Pave"
    } elseif {$method == "auto"} {
       set unsMethod "Auto"
    }
    if {![info exists unsMethod] || $unsMethod == ""} {
        set unsMethod "ICEM CFD Quad"
    }
    
    set sweptTypeList [list "Hexa" "Hexa/Prism" "Prism"]
    set sweptType Hexa
    set freeFaceTypeList [list "Tetra" "Tetra/Pyramid" "Hexa Dominant" "Hexa Core"]
    set freeType Tetra
    set freeFaceMethodList [list "Default" "Uniform" "Pave"]
    set freeMethod Default
    set faceMappingList [list "None" "Standard" "Aggressive"]
    set faceMapping Standard
}

proc oncreateBlockDEZAfterLoad {} {
    global env beta_mode

    set greyWidgets {createBlkVertices createBlkExtrude createBlk2Dto3D createBlk3Dto2D}
    if ![ic_hex_blocking_loaded] {
        set off 1
    } else {
        set off 0
    }   
    foreach widgt $greyWidgets {
        ::AIEnv::GUIManagement::ToggleGrey $widgt $off
    }
    if [ic_geo_is_loaded] {
        ::AIEnv::GUIManagement::ToggleGrey createBlkIni 0
    } else {
        ::AIEnv::GUIManagement::ToggleGrey createBlkIni 1
    }
    if ![info exists createBlkVal] { set createBlkVal 0 }
    if {$createBlkVal == ""} { set createBlkVal 0 }

    if ![info exists createBlk2DEEGVal] { set createBlk2DEEGVal 2 }
    if ![info exists createBlkInitVal] { set createBlkInitVal 0 }
    if ![info exists createBlk3DTypeVal] { set createBlk3DTypeVal 0 }
    if ![info exists createBlk2DTypeVal] { set createBlk2DTypeVal 0 }
    if ![info exists createBlk2Dto3DHowVal] { set createBlk2Dto3DHowVal 0 }
    if {[trace vinfo createBlk3DTypeVal] != ""} {
        trace vdelete createBlk3DTypeVal w aie_hex_trace_createblkxdtypeval
    }
    trace variable createBlk3DTypeVal w aie_hex_trace_createblkxdtypeval
    if {[trace vinfo createBlk2DTypeVal] != ""} {
       trace vdelete createBlk2DTypeVal w aie_hex_trace_createblkxdtypeval
    }
    if ![info exists env(AI_ENV_LSTC)] {
	    trace variable createBlk2DTypeVal w aie_hex_trace_createblkxdtypeval
	    if {[trace vinfo createBlkInitVal] != ""} {
	        trace vdelete createBlkInitVal w aie_hex_trace_inherit_part
	    }
	    if {[createBlockDEZ get createBlkVal] == "0" && [createBlockDEZ get createBlkInitVal] == "1"} {
	        set inherit_part 1
	    }
	    trace variable createBlkInitVal w aie_hex_trace_inherit_part
	    aie_hex_trace_inherit_part
    }
    if {[trace vinfo createBlkVal] != ""} {
       trace vdelete createBlkVal w aie_hex_trace_createBlkVal
    }
    trace variable createBlkVal w aie_hex_trace_createBlkVal
    if {[trace vinfo createBlkInitVal] != ""} {
       trace vdelete createBlkInitVal w aie_hex_trace_createBlkVal
    }
    trace variable createBlkInitVal w aie_hex_trace_createBlkVal
    if {[trace vinfo createBlk2Dto3DHowVal] != ""} {
       trace vdelete createBlk2Dto3DHowVal w aie_hex_trace_createBlkVal
    }
    trace variable createBlk2Dto3DHowVal w aie_hex_trace_createBlkVal
    
    if [aie_hex_sketching_mode] {
        set createBlkVal 0
        set createBlkInitVal 2
        ::AIEnv::GUIManagement::ToggleGrey createBlkIni 0
        ::AIEnv::GUIManagement::ToggleGrey createBlkI3D 1
        ::AIEnv::GUIManagement::ToggleGrey createBlkI2D 1
        ::AIEnv::GUIManagement::ToggleGrey createBlkI3DP 1
	}
	if [ic_hex_blocking_loaded] {
	    aie_hex_clear_worst_element
	}
}

proc oncreateBlockDEZUnLoad {} {
    global env

    if {[trace vinfo createBlk3DTypeVal] != ""} {
        trace vdelete createBlk3DTypeVal w aie_hex_trace_createblkxdtypeval
    }
    if {[trace vinfo createBlk2DTypeVal] != ""} {
        trace vdelete createBlk2DTypeVal w aie_hex_trace_createblkxdtypeval
    }
    if ![info exists env(AI_ENV_LSTC)] {
	    if {[trace vinfo createBlkInitVal] != ""} {
	        trace vdelete createBlkInitVal w aie_hex_trace_inherit_part
	    }
    }
    if {[trace vinfo createBlkVal] != ""} {
       trace vdelete createBlkVal w aie_hex_trace_createBlkVal
    }
    if {[trace vinfo createBlkInitVal] != ""} {
       trace vdelete createBlkInitVal w aie_hex_trace_createBlkVal
    }
    if {[trace vinfo createBlk2Dto3DHowVal] != ""} {
       trace vdelete createBlk2Dto3DHowVal w aie_hex_trace_createBlkVal
    }
    if [info exists LongList] { unset LongList }
}

proc aie_hex_trace_createblkxdtypeval {name element op} {
    createBlockDEZ set blockVerts ""
    select_toolbar_delete
    oncreateBlkVerticesLoad
}

proc aie_hex_trace_inherit_part {{name ""} {element ""} {op ""}} {
    global env   
    if [info exists env(AI_ENV_LSTC)] return 
    set inherit [createBlockDEZ get inherit_part]
    set create [createBlockDEZ get createBlkVal]
    set blkini [createBlockDEZ get createBlkInitVal]
    set 2dto3d [createBlockDEZ get createBlk2Dto3DHowVal]
    if {($inherit && $create == 0 && $blkini == 1) || \
        ($inherit && $create == 3 && ($2dto3d == 1 || $2dto3d == 2)) || \
        ($inherit && $create == 2)} {
        ::AIEnv::GUIManagement::ToggleGrey createBlkFam 1
    } else {
        ::AIEnv::GUIManagement::ToggleGrey createBlkFam 0
    }
}

proc aie_hex_trace_createBlkVal {{name ""} {element ""} {op ""}} {
    global env   
    if [info exists env(AI_ENV_LSTC)] return 
    set create [createBlockDEZ get createBlkVal]
    set blkini [createBlockDEZ get createBlkInitVal]
    set 2dto3d [createBlockDEZ get createBlk2Dto3DHowVal]
    if {($create == 0 && ($blkini == 0 || $blkini == 2 || $blkini == 3)) || \
        ($create == 1) || ($create == 3 && ($2dto3d == 0)) || ($create == 4)} {
        ::AIEnv::GUIManagement::ToggleGrey createBlkInherit 1
        createBlockDEZ set inherit_part 0
        ::AIEnv::GUIManagement::ToggleGrey createBlkFam 0
    } else {
        ::AIEnv::GUIManagement::ToggleGrey createBlkInherit 0
    }
}

proc onCreateBlkFamModify {dez val} {
    if {$val == "From screen"} {
        createBlockDEZ set part_name [geo_select_part_from_screen 1]
    }
}

proc oncreateBlkI2DLoad {} {
    set createBlk2DMergeRGVal 0
    set inherit_part 1
    aie_hex_trace_inherit_part
}

proc oncreateBlkIniUnLoad {} {
    ::AIEnv::GUIManagement::ToggleGrey createBlkFam 0
}

proc oncreateBlk3DMultiZoneLoad {} {  
    global env
    
    if ![info exists env(AI_ENV_IN_WB1)] {
        if {[ic_geo_count_solids_without_material] > 1 || [llength [ic_geo_get_objects body]] > 1} {
            set part_name CREATED_MATERIAL_1
        }
    }
}

#-------------------------------------Auto pick procedure for Block Creation----------------------------------
proc oncreateBlkIniLoad {} {
    if ![info exists createBlkInitVal] { set createBlkInitVal 0 ; return }
    if {[createBlockDEZ get createBlkVal] == "0" && [createBlockDEZ get createBlkInitVal] == "1"} {
	    set inherit_part 1
	}
    aie_hex_trace_inherit_part
    switch $createBlkInitVal {
	    0 {
	        if { $auto_pick_mode && [ic_hex_blocking_loaded] } { createBlkPick1 pick }
	    }
    }
}

proc oncreateBlkI3DLoad {} {
    aie_hex_trace_inherit_part
    if {$auto_pick_mode && [ic_hex_blocking_loaded] } {createBlkPick1 pick}
}

proc oncreateBlkI25DLoad {} {
    aie_hex_trace_inherit_part
    if {$auto_pick_mode && [ic_hex_blocking_loaded] } {createBlkPick2 pick}
}

proc oncreateBlkPick1Finish {} {
    if {$pickblkbound != ""} {
        if [info exists LongList] {
            set curlist $LongList
        } else {
            set curlist $pickblkbound
        }
        set picked ""
        set removed 0
        foreach "t e" $curlist {
            if {$t == "density"} {
                incr removed
                continue
            }
            append picked "$t $e "
        }
        if {$removed && $picked != ""} {
            mess "Removed $removed densities from selection\n"
            if [info exists LongList] {
                set LongList $picked
                set len [llength $picked]
                set pickblkbound "[expr $len / 2] entities"
            } else {
                set pickblkbound $picked
            }
        }
    }
    if {($pickblkbound != "") && $auto_pick_mode } {
        createBlockDEZ apply
        switch $createBlkInitVal {
	        0 {createBlkPick1 pick}
	    }
    } else {
        if {$createBlkVal == "0" && $auto_pick_mode} {
            createBlockDEZ setclean
        }
    }
}

proc oncreateBlkExtrudeLoad {} {
    if ![ic_hex_blocking_loaded] return
    set mesh_dim [ic_hex_mesh_dimension]
    if $auto_pick_mode {
	    switch $extrudeBlkEGVal {
		    0 {createBlkFface1  pick}
		    1 {createBlkFface2  pick}
		    2 {createBlkFface3  pick}
	    }
    }
    aie_hex_trace_inherit_part
}

foreach ll {extFaceInter extFaceFixed extBlkCurve} {
proc on$ll\Load {} {    
    if $auto_pick_mode {
	switch $extrudeBlkEGVal {
		0 {createBlkFface1  pick}
		1 {
		    createBlkFface2  pick
		}
		2 {createBlkFface3  pick}
	}
    }
}
}

foreach ll {1 2 3} {
proc oncreateBlkFface$ll\Finish {} {
    if {$face != ""} {
	switch $extrudeBlkEGVal {
	    0 {
		createBlockDEZ apply
		if $auto_pick_mode {
		    createBlkFface1 pick
		}
	    }
	    1 {
	    }
	    2 {
		if $auto_pick_mode {
		    extBlkCurvePick pick
		}
	    }
	}
    }
}
}

proc OncreateBlkFface1Pick {} {
    global use_banner

    set ::use_banner "Select faces with left button and extrude interactively with middle button; cancel = right button"
}

proc onextBlkCurvePickFinish {} {
    if {($face != "") && $auto_pick_mode } {
        extBlkEndptPick pick
    }
}

proc onextBlkEndptPickFinish {} {
    if {($face != "") && $auto_pick_mode } {
        createBlockDEZ apply
        createBlkFface3 pick
    }
}

proc oncreateBlkVerticesLoad {} {
    global auto_pick_mode
    if ![info exists createBlk3DTypeVal] {
        set createBlk3DTypeVal [createBlockDEZ get createBlk3DTypeVal]
    }
    if ![info exists createBlk2DTypeVal] {
        set createBlk2DTypeVal [createBlockDEZ get createBlk2DTypeVal]
    }
    aie_hex_trace_inherit_part
    if [ic_hex_blocking_loaded] {
        set mesh_dim [format %d [ic_hex_mesh_dimension]]
    } else {
        set mesh_dim 3
        return
    }
    switch $mesh_dim {
	    3 {set createBlkDimVal 0}
	    2 {set createBlkDimVal 1}
	    1 {set createBlkDimVal 1}
    }
    if $auto_pick_mode {
	    switch $createBlkDimVal {
	        0 {
		        switch $createBlk3DTypeVal {
		            0 {	
	                    if ![info exists createBlk3DGGVal] {
	                        set createBlk3DGGVal [createBlockDEZ get createBlk3DGGVal]
                        }
			            if $createBlk3DGGVal {
			                createBlkFacesPick pick
			            } else {
			                vertPickV8 pick
			            }
		            }
		            1 { vertPickUns3D pick }
		            2 {	vertPickV6Y pick }
		            3 {	vertPickV6 pick }
		        }
	        }
	        1 {
		        switch $createBlk2DTypeVal {
		            0 {	vertPickV4 pick }
		            1 {	vertPickVUns pick }
		        }
	        }
	    }
    }
}

proc onvertPickV6YFinish {} {
    global button_instructions va_set
    if {$createBlk3DTypeVal != 2} return
    set nverts [llength $blockVerts]
    if {$nverts != 6} {
        if 1 {
	        banner "Select remaining [expr 6 - $nverts] locations from the screen; $button_instructions"
        } else {
	        banner "Select remaining [expr 6 - $nverts] verts from the screen; $button_instructions"
	    }
	    set blockVerts [concat $blockVerts [va_create_xyz auto [expr 6 - $nverts] 0]]
	    banner ""
    }
    if {($blockVerts  != "") && $auto_pick_mode} {
        createBlockDEZ apply
        vertPickV6Y pick
    }
}

proc onvertPickV6Finish {} {
    global button_instructions va_set
    if {$createBlk3DTypeVal != 3} return
    set nverts [llength $blockVerts]
    if {$nverts != 6} {
        if 1 {
            banner "Select remaining [expr 6 - $nverts] locations from the screen; $button_instructions"
        } else {
	        banner "Select remaining [expr 6 - $nverts] verts from the screen; $button_instructions"
	    }
	    set blockVerts [concat $blockVerts [va_create_xyz auto [expr 6 - $nverts] 0]]
	    banner ""
    }
    if {($blockVerts  != "") && $auto_pick_mode } {
	    createBlockDEZ apply
	    vertPickV6 pick
    }
}

proc onvertPickV4Finish {} {
    global button_instructions va_set
    if {$createBlk2DTypeVal != 0} return
    set nverts [llength $blockVerts]
    if {$nverts != 4} {
        if 1 {
            banner "Select remaining [expr 4 - $nverts] locations from the screen; $button_instructions"
        } else {
	        banner "Select remaining [expr 4 - $nverts] verts from the screen; $button_instructions"
	    }
	    #vertPickV4 pick  
	    set blockVerts [concat $blockVerts [va_create_xyz auto [expr 4 - $nverts] 0]]
	    banner ""
    }
    if {($blockVerts  != "") && $auto_pick_mode } {
	    createBlockDEZ apply
	    vertPickV4 pick
    }
}

proc onvertPickV8Finish {} {
    global button_instructions va_set
    if {$createBlk3DTypeVal != 0} return
    set nverts [llength $blockVerts]
    if {$nverts != 8} {
        if 1 {
            banner "Select remaining [expr 8 - $nverts] locations from the screen; $button_instructions"
        } else {
	        banner "Select remaining [expr 8 - $nverts] verts from the screen; $button_instructions"
	    }
	    set blockVerts [concat $blockVerts [va_create_xyz auto [expr 8 - $nverts] 0]]
	    banner ""
    }
    if {($blockVerts  != "") && $auto_pick_mode } {
	    if [ic_hex_blocking_loaded] {
	        createBlockDEZ apply
	        vertPickV8 pick
	    } else {
	        set blockVerts ""
	    }
    }
}

proc onvertPickSheetV4Finish {} {
    global button_instructions va_set
    if {$createBlk3DTypeVal != 4} return
    set nverts [llength $blockVerts]
    if {$nverts != 4} {
	    #set nodes [select_vertex "Please select remaining [expr 4 - $nverts] vertices; $button_instructions" [expr 4 - $nverts] "node_numbers" ]
	    banner "Select remaining [expr 4 - $nverts] locations from the screen; $button_instructions"
	    set nodes [va_create_xyz auto [expr 4 - $nverts] 0]
        set blockVerts [concat $blockVerts $nodes]
        banner ""
    }
    if {($blockVerts != "" && [llength $blockVerts] == "4") && $auto_pick_mode } {
	    if [ic_hex_blocking_loaded] {
	        createBlockDEZ apply
	        vertPickSheetV4 pick
	    } else {
	        set blockVerts ""
	    }
    }
}

proc onvertPickV3YFinish {} {
    global button_instructions va_set
    set nverts [llength $blockVerts]
    if {$nverts != 3} {
        if 1 {
            banner "Select remaining [expr 3 - $nverts] locations from the screen; $button_instructions"
        } else {
            banner "Select remaining [expr 3 - $nverts] verts from the screen; $button_instructions"
        }
        set blockVerts [concat $blockVerts [va_create_xyz auto [expr 3 - $nverts] 0]]
        banner ""
    }

    if {($blockVerts  != "") && $auto_pick_mode } {
        createBlockDEZ apply
        vertPickV3Y pick
    }
}

proc onvertPickVUnsFinish {} {
    if {$createBlk2DTypeVal != 1} return
    set nverts [llength $blockVerts]
    if {$nverts < 3} {
        mess "Select a minimum of 3 vertices for \"Block Type Free\"\n" red
        return
    }
    if {($blockVerts  != "") && $auto_pick_mode } {
        createBlockDEZ apply
        vertPickVUns pick
    }
}

proc onvertPickUns3DFinish {} {
    if {$createBlk3DTypeVal != 1} return
    if {($blockVerts  != "") && $auto_pick_mode } {
        createBlockDEZ apply
        vertPickUns3D pick
    }
}

proc oncreateBlkEdgesUnsPickFinish {} {
    if {$createBlk3DTypeVal != 1} return
    if {($blockEdges != "") && $auto_pick_mode } {
        createBlockDEZ apply
        createBlkEdgesUnsPick pick
    }
}

proc oncreateBlkFacesUnsPickFinish {} {
    if {$createBlk3DTypeVal != 1} return
    if {($blockFaces != "") && $auto_pick_mode } {
        createBlockDEZ apply
        createBlkFacesUnsPick pick
    }
}

proc oncreateBlkFacesPickFinish {} {
    if {($blockFaces  != "") && $auto_pick_mode } {
        createBlockDEZ apply
        createBlkFacesPick pick
    }
}

proc onOgridPartsSelectPick {} {
    aie_clear_ogrid_sel

    if {$ogridParts == ""} {
	    set ogridParts [aie_default_ogrid_parts]
    }
}

proc aie_mark_hexas_for_ogrid { vol_fams face_fams } {
    hex_command "mark_blocks $vol_fams inf_family $face_fams"
    display_elements marked m [volume_activename_string] -solid dead_as_faces
}

proc onOgridPartsSelectFinish {} {
    if {$ogridParts != ""} {
        set ogridFams ""
        foreach p $ogridParts {
            foreach f [ic_geo_list_families_in_part $p] {
                lappend ogridFams $f
            }
        }
        set cmd "mark_blocks on_family $ogridFams"
        hex_command $cmd
        set del_opts "marked m [volume_activename_string] -solid dead_as_faces"
        hex_command "display_elements $del_opts"
        set offset [aie_default_ogrid_offset $ogridParts]
    }
}

proc oncreateBlk2Dto3DLoad {} {
    global env

    if ![createBlockDEZ get fillOgridGGVal] {
        ::AIEnv::GUIManagement::ToggleGrey fillOgridGI 1
    }
    set offset ""
    aie_hex_trace_inherit_part
    if ![info exists env(AI_ENV_LSTC)] {
        if [aie_hex_sketching_mode] {
            createBlockDEZ set createBlk2Dto3DHowVal 1
            ::AIEnv::GUIManagement::ToggleGrey  createBlk2Dto3DM1 1
        } else {
            ::AIEnv::GUIManagement::ToggleGrey  createBlk2Dto3DM1 0
        }
    }
}

proc oncreateBlk2Dto3DUnLoad {} {
    if ![ic_hex_blocking_loaded] return
    aie_clear_ogrid_sel
    set ogridParts ""
}

proc oncreateBlk2Dto3DM1Load {} {
    aie_hex_trace_inherit_part
}

proc aie_default_ogrid_parts {} {
    set fams [aie_list_parts 0]
    set ogrid_parts ""
    foreach ofam $fams {
	    set surfs [ic_geo_get_objects surface $ofam]
	    foreach s $surfs {
	        set params [ic_get_meshing_params surface $s]
	        set pfam_set 0
	        set nlay 0
	        foreach {n v} $params {
		        set $n $v
	        }
	        if { $nlay > 0 } {
		        lappend ogrid_parts $ofam
	        }
	    }
    }
    return $ogrid_parts
}

proc aie_default_ogrid_offset {ogrid_parts} {
    global prism_values cprism_values

    set offset 1.0
    set bbox [ic_geo_model_bounding_box]
    set dist [eval ic_vcalc distance $bbox]
    if {$offset != ""} {
        set offset [format %.1g [expr $dist * 0.1]]
    }
    # for each surfaces find the max layer height
    set height_max 0.0
    set ratio_max 0.0
    set layers_max 0
    set layers 0
    set ratio 0.0
    set height 0.0
    foreach ofam $ogrid_parts {
        set surfs [ic_geo_get_objects surface $ofam]
        foreach s $surfs {
            set params [ic_get_meshing_params surface $s]
            set ehgt 0.0
            set hrat 0.0
            set nlay 0
            foreach {n v} $params {
                set $n $v
            }
            if {($ehgt != "") && ($ehgt > 0.0) && ($ehgt > $height_max)} {
                set height_max $ehgt
            }
            if {($hrat != "") && ($hrat > 0.0) && ($hrat > $ratio_max)} {
                set ratio_max $hrat
            }
            if {($nlay != "") && ($nlay > 0) && ($nlay > $layers_max)} {
                set layers_max $nlay
            }
        }
    }
    if {$layers_max == 0 && ([info exists prism_values(total_height)] && $prism_values(total_height) != "" && \
        $prism_values(total_height) > 0.0)} {
        # check if we can use global prism values
        set offset $prism_values(total_height)
        set height $prism_values(height)
        set ratio $prism_values(ratio)
        set nlay $prism_values(layers)
        foreach ofam $ogrid_parts {
            ic_geo_set_family_params $ofam height $height hrat $ratio nlay $nlay
        }
        mess "Warning: using global prism values for MZone inflation\n"
        return $offset
    }

    set layers $layers_max
    set ratio $ratio_max
    set height $height_max
    
    if {($layers > 0) && ($height > 0.0) && ($ratio > 0.0)} {
        if [catch {prism_compute_params law exponential layers $layers height $height ratio $ratio} param] {
            mess "Error: $param\n" red
        } else {
            set offset [lindex $param 1]
        }
    }
    return $offset
}

proc oncreateBlockDEZOK {} {
    global env last_line replay_recording replay_do_all
    global hex_option index_form index_dims index_min index_max
    global default_bunch_laws use_output_blocks

    set fam [aie_new_part $part_name]
    if {$part_name != $fam} {
        mess "Part name \"$part_name\" is not valid, changed to $fam\n" red
        set part_name $fam
    }
    if {$fam == "" && $createBlkVal != 4} {
        mess "Missing part name for \"Create Block\"\n" red
        return
    }

    set skip 0
    switch $createBlkVal {
        0 {
            set num1_mess -1
            set num2_mess -1
            if {$createBlkInitVal == 0 && [ic_geo_is_loaded]} {
                set is_geom_part 0
                foreach {n v} [ic_geo_get_objects all $fam] {
                    if {$n == "point" || $n == "curve" || $n == "surface"} {
                        set is_geom_part 1
                        break
                    }
                }
                if $is_geom_part {
                    set mess  "Part $fam contains also geometry objects. Do you want to proceed ?"
                    set ret [tk_dialog .partBlk "Part exists" $mess "" -1 Yes No]
                    switch -- $ret {
                        -1 { if [winfo exists .partBlk] { top_destroy .partBlk; return } }
                        1 {return}
                    }
                }
            }
            set blkinit_method $createBlkInitVal
            if [info exists env(AI_ENV_LSTC)] {
                if {$blkinit_method > 0} {
                    incr blkinit_method
                }
            }

            if {$2dBlk == 1 && $blkinit_method == 0} { set blkinit_method 10 }
            switch $blkinit_method {
                0 - 4 - 5 - 10 {
                    if [ic_hex_blocking_loaded] {
                        set mesh_dim [format %d [ic_hex_mesh_dimension]]
                        switch $blkinit_method {
                            0 {
                                if {$mesh_dim == 2} {
                                    set mess  "Current blocking is 2D. Do you want to reinitialize blocking to 3D ?"
                                    set ret [tk_dialog .deleteBlk "Delete current blocking" $mess "" -1 Yes No]
                                    switch -- $ret {
                                        -1 { if [winfo exists .deleteBlk] { top_destroy .deleteBlk; return } }
                                        1 {return}
                                    }
                                    aie_unload_blocking
                                } elseif {$mesh_dim == 3} {
                                    set mess  "A 3D blocking currently exists."
                                    set ret [tk_dialog .deleteBlk "Blocking already exists" $mess "" 1 Merge Replace Cancel]
                                    switch -- $ret {
                                        -1 { if [winfo exists .deleteBlk] { top_destroy .deleteBlk; return } }
                                        2 {return}
                                        1 {aie_unload_blocking}
                                    }
                                }
                            }
                            1 - 4 {
                                set mess  "Keypoint method can not be used with existing blocking. Do you want to reinitialize blocking?"
                                set ret [tk_dialog .deleteBlk "Delete current blocking" $mess "" -1 Yes No] 
                                switch -- $ret {
                                    -1 { if [winfo exists .deleteBlk] { top_destroy .deleteBlk; return } }
                                    1 {return}
                                }
                                aie_unload_blocking
                            }
                            1 - 5 {
                                set mess  "3D Body Wise method can not be used with existing blocking. Do you want to reinitialize blocking?"
                                set ret [tk_dialog .deleteBlk "Delete current blocking" $mess "" -1 Yes No] 
                                switch -- $ret {
                                    -1 { if [winfo exists .deleteBlk] { top_destroy .deleteBlk; return } }
                                    1 {return}
                                }
                                aie_unload_blocking
                            }
                            10 {
                                # Creating a 3D blocking screws this up, so it has to reinitialize
                                set mess  "2D with 3D geometry method can not be used with existing blocking. Do you want to reinitialize blocking?"
                                set ret [tk_dialog .deleteBlk "Delete current blocking" $mess "" -1 Yes No]
                                switch -- $ret {
                                    -1 { if [winfo exists .deleteBlk] { top_destroy .deleteBlk; return } }
                                    1 {return}
                                }
                                aie_unload_blocking
                            }
                        }
                    }
                    switch $blkinit_method {
                        0 - 10 {
                            if [info exists LongList] {
                                set thelist $LongList
                            } else {
                                set thelist $pickblkbound
                            }
                            # Create block
                            set version 101
                            hex_command [list initialize_blocking $thelist $fam $orientBlk $version]
                            set mesh_dim [format %d [ic_hex_mesh_dimension]]
                            if {$mesh_dim == 10} {
                                mess "Warning: created 2D blocking\n" red
                            }
                            set pickblkbound ""
                            if $project {
                                aie_update_parts_in_tree_if_needed
                                hex_command "project_to_surface [volume_activename_string]"
                            }
                            if {$blkinit_method == 10} {
                                set args1 [volume_activename_string]
                                if {[lsearch -exact $args1 $fam] == -1} {
                                    lappend args1 $fam
                                }
                                eval ic_hex_threed_to_twod $args1
                                mess "2D Blocking created\n" blue
                            }
                        }
                        4 {
                            ic_hex_keypoint_blocking $fam
                        }
                        5 {
                            if {[ic_geo_get_objects body] == ""} {
                                set mess "This feature needs bodies."
                                append mess "Do you want to run Create Body?"
                                switch -- [tk_dialog .bodywarn "Initialize 3D Body Wise warning" $mess "" -1 Yes No] {
                                    -1 { if [winfo exists .bodywarn] { top_destroy .bodywarn; return } }
                                    0 {
                                        ic_geo_build_bodies BODY 0 0 0 1 {} 0
                                        if {[ic_geo_get_objects body] != ""} {
                                            mess "Create Body completed\n" blue
                                        } else {
                                            mess "Create Body failed\n" red
                                            return
                                        }
                                    }
                                    1 { return }
                                }
                            }
                            set need_build_topo 1
                            foreach surf [ic_geo_get_objects surface] {
                                if {[ic_geo_boundary surface $surf] != ""} {
                                    set need_build_topo 0
                                    break
                                }
                            }
                            if $need_build_topo {
                                set topotol [aie_default_topo_tolerance]
                                set mess "This feature needs geometry connectivity."
                                append mess "Do you want to run Build Topology with default tolerance = $topotol?"
                                switch -- [tk_dialog .bodywarn "Initialize 3D Body Wise warning" $mess "" -1 Yes No] {
                                    -1 { if [winfo exists .bodywarn] { top_destroy .bodywarn; return } }
                                    0 {
                                        ic_build_topo $topotol -angle 0
                                        mess "Build topology completed\n" blue
                                    }
                                    1 { return }
                                }
                            }
                            set fam2 $fam 
                            if $inherit_part { set fam2 "-inherited" }
                            ic_hex_surface_blocking $fam2 -body_wise
                            ic_hex_twod_to_threed $fam -check_body -swept
                            if ![ic_hex_blocking_loaded] {
                                mess "Initialize blocking failed\n" red
                                return
                            }
                        }
                    }
                }
                1 {
                    if [ic_hex_blocking_loaded] {
                        set mesh_dim [format %d [ic_hex_mesh_dimension]]
                        if {$mesh_dim == 3} {
                            set mess  "Current blocking is 3D. Do you want to reinitialize blocking to 2D ?"
                            set ret [tk_dialog .deleteBlk "Delete current blocking" $mess "" -1 Yes No]
                            switch -- $ret {
                                -1 { if [winfo exists .deleteBlk] { top_destroy .deleteBlk; return } }
                                1 { return }
                            }
                            aie_unload_blocking
                        }
                    }
                    if {$createBlk2DMethodEEGVal == "0"} {
                        if [info exists LongList] {
                            set thelist $LongList
                        } else {
                            set thelist $blockSurfs
                        }
                        set need_build_topo 1
                    } else {
                        if [info exists LongList] {
                            set thelist $LongList
                        } else {
                            set thelist $blockCurves
                        }
                        set need_build_topo 0
                    }                   
                    if $inherit_part { set fam "-inherited" }
                    set before_merge_dormant 0
                    if {$createBlk2DMethodEEGVal == "0"} {
                        set surfs $thelist
                        if {$surfs == ""} {
                            set surfs [ic_geo_get_objects surface]
                        }
                        foreach surf $surfs {
                            if {[ic_geo_boundary surface $surf] != ""} {
                                set need_build_topo 0
                                break
                            }
                        }
                        # if the list of surfaces to block is all surfaces
                        # then make blockSurfs the empty string.
                        if {$thelist != ""} {
                            set is_all 1
                            foreach surf [ic_geo_get_objects surface] {
                                if {[lsearch $thelist $surf] < 0} {
                                    set is_all 0
                                    break
                                }
                            }
                            if $is_all {
                                mess "Blocking Surfs is \"all surfaces\" so making empty\n"
                                set blockSurfs ""
                            }
                        }
                        set topotol [aie_default_topo_tolerance]
                        if $need_build_topo {
                            set mess "This feature needs geometry connectivity."
                            append mess "Do you want to run build topology with default tolerance = $topotol?"
                            switch -- [tk_dialog .bodywarn "Build topology warning" $mess "" -1 Yes No] {
                                -1 { if [winfo exists .bodywarn] { top_destroy .bodywarn; return } }
                                0 {
                                    ic_build_topo $topotol -angle 0
                                    mess "Build topology completed.\n" blue
                                }
                                1 { set blockSurfs ""; return }
                            }
                        }
                        switch $createBlk2DEEGVal {
                            0 { set btype -unstruct; set skip 1 }
                            1 { set btype -mixed; set skip 1 }
                            2 { set btype -mapped; set skip 1 }
                            3 { set btype -swept; set skip 1 }
                        }
                        set args "$fam $btype -min_edge $minEdgeLen"
			            if {$minEdgeLen > 0.0} {
			                append args " -embed_edges"
			            }

                        switch $createBlk2DMergeRGVal {
                            0 {}
                            1 {append args " -respect_non_dormant" }
                            2 {append args " -no_merge"}
                            3 {
                                append args " -merge_dormant"
                                set before_merge_dormant 1
                            }
                        }
                        if {$thelist != ""} {
                            append args " -surfaces $thelist"
                        }
                        if {$sweptSurfs != ""} {
                            append args " -swept_surfaces $sweptSurfs"
                        }
                        if $before_merge_dormant {
                            set points_merge_dormant ""
                            set crvs [ic_geo_get_dormant curve]
                            if {$crvs != ""} {
                                foreach c $crvs {
                                    foreach p [ic_geo_boundary curve $c] {
                                        if {[ic_geo_get_dormant_entity point $p] == 0} {
                                            ic_geo_set_dormant_entity point $p 1
                                            lappend points_merge_dormant $p
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                        switch $createBlk2DCurveEEGVal {
                            0 { set btype -unstruct; set skip 1 }
                            1 { set btype -mixed; set skip 1 }
                            2 { set btype -mapped; set skip 1 }
                            3 { set btype -swept; set skip 1 }
                        }
                        set args "$fam $btype"
                        if {$sweptSurfs != ""} {
                            append args " -swept_surfaces $sweptSurfs"
                        }
                        if {$thelist != ""} {
                            append args " -curves $thelist"
                        }
                    }
                    append args " -show_progress"
                    set res [eval ic_hex_surface_blocking $args]
                    if [ic_hex_blocking_loaded] {
                        if ![llength [eval ic_hex_get_block_families_and_types [volume_activename_string]]] {
                            mess "Initialize blocking failed\n" red
                            aie_close_blocking 0
                            aie_after_close_blocking
                            return
                        }
                    }
                    set blockSurfs ""
                    if $before_merge_dormant {
                        if {$points_merge_dormant != ""} {
                            foreach p $points_merge_dormant {
                                ic_geo_set_dormant_entity point $p 0
                            }
                        }
                        unset points_merge_dormant
                    }
                    #--------------------
                    # 58392 Return if requires topology;
                    # NOTE: TEXT below (please...) GENERATED in C++ module "hex" and may be HUGE
                    set n [string first "please run build_topo" $res]
                    if {$n > 0} {
                        aie_close_blocking 0
                        mess "Please create topology and try again!\n" red
                        return
                    }
                    set type $unsType
                    if [info exists quad_types($type)] {
                        set type $quad_types($type)
                    }
                    hex_command "unstruct_face_type $type"
                    set method "uniform_quad"
                    if {$unsMethod == "ICEM CFD Quad"} {
                        set method "uniform_quad"
                    } elseif {$unsMethod == "Gambit Pave"} {
                        set method "gambit_pave"
                    } elseif {$unsMethod == "Auto"} {
                        set method "auto"
                    }
                    hex_command "set_unstruct_face_method $method"
                    if {$res != "" && [string first "mark_blocks unmark" $res] > 0} {
                        # create subset of failed surfs
                        msg ERROR $res
                        set failed_surfs ""
                        set res [split $res \n]                        
                        #
                        foreach line $res {
                            set s [lindex $line end]
                            if {$s != ""} {
                                if {[ic_geo_check_objects_exist surface $s] != ""} {
                                    lappend failed_surfs "surface $s"
                                }
                            }
                        }
                        set subset [ic_geo_subset_unused_name AUTO_BLOCK_FAILED]
                        if {$failed_surfs != ""} {
                            ic_geo_subset_add_items $subset [join $failed_surfs]
                            ::AIEnv::GUIManagement::Tree::AddGroup geom_subset $subset 1
                            ::AIEnv::GUIManagement::Tree::ToggleGroupVisibility geom_subset $subset same
                            mess "Created subset: $subset for failed surfaces\n"
                        }
                    }
                }
                2 {
                    aie_unload_blocking
                    if [aie_hex_sketching_mode] {
                        aie_hex_sketch_create_blocking_without_geometry $part_name $applySettings
                        return
                    }
                    ic_hex_ensure_is_loaded
                    hex_command "initialize_mesh 2d new_numbering new_blocking $part_name"
                }
                3 {
                    aie_unload_blocking
                    set need_build_topo 1                 
                    if $inherit_part { set fam "-inherited" }
                    set before_merge_dormant 0
                    foreach surf [ic_geo_get_objects surface] {
                        if {[ic_geo_boundary surface $surf] != ""} {
                            set need_build_topo 0
                            break
                        }
                    }
                    if $need_build_topo {
                        set topotol [aie_default_topo_tolerance]
                        set mess "This feature needs geometry connectivity."
                        append mess "Do you want to run build topology with default tolerance = $topotol?"
                        switch -- [tk_dialog .bodywarn "Geometry connectivity" $mess "" -1 Yes No] {
                            -1 { if [winfo exists .bodywarn] { top_destroy .bodywarn; return } }
                             0 {
                                ic_build_topo $topotol -angle 0
                                mess "Build topology completed.\n" blue
                             }
                             1 { return  }
                        }
                    }

                    set skip 1
                    
                    # one_tri/several_tris/all_tris/all_quads

                    catch { unset mtype; unset etyp }
                    switch $sweptType {
                        "Hexa" {
                            set etyp 2 ;# see define of MT_QUADS in mesh_types.h
                            set utyp all_quads
                         }
                         "Hexa/Prism" {
                            set etyp 3 ;# see define of MT_QUADS_AND_TRIS in mesh_types.h
                            set utyp several_tris
                         }
                         "Prism" {
                            set etyp 0; # see define of MT_TRIS in mesh_types.h
                            set utyp all_tris
                        }
                    }
                    switch $freeType {
                        "Tetra" {
                           set mtype 8 ;# see define of UB_TETRA_ALLTRI
                        }
                        "Tetra/Pyramid" {
                           set mtype 5 ;# see define of UB_TGRID
                        }
                        "Hexa Dominant" {
                            set mtype 2 ;# see define of UB_HEX_DOM
                        }
                        "Hexa Core" {
                            set mtype 1 ;# see define of UB_HEXCORE_MESH
                        }
                    }
                    
                    if {$faceMapping == "Standard" || $faceMapping == "Aggressive"} {
                       set mtype 7 ;# see define of UB_NONE                        
                    }
                    
                    set bodies ""
                    if [ic_geo_count_solids_without_material] {
                        set bodies [ic_geo_solids_without_material_names]
                        if {$bodies != ""} {
                            mess "Found [llength $bodies] solid(s)\n"
                            ic_geo_solids_without_material_meshing_params "$bodies" mtype $mtype
                        }
                    } else {
                        set bodies [ic_geo_get_objects body]
                        if {$bodies != ""} {
                           mess "Found [llength $bodies] bodies\n"
                           set bodies2 ""
                           foreach bdy $bodies {
                               set bdyfam [ic_geo_get_part body $bdy]
                               if {"$bdyfam" != "$bdy"} {
                                   ic_geo_set_name body "$bdy" "$bdyfam" 1 0
                                   append bodies2 " $bdyfam"
                                   mess "Changed body name from $bdy to $bdyfam\n"
                                } else {
                                   append bodies2 " $bdyfam"
                                }
                            }
                            set bodies $bodies2
                            ic_set_meshing_params_body "$bodies" mtype $mtype
                        }
                    }
                    if {$bodies == ""} {
                        mess "3D MultiZone requires a body to be created\n" red
                        return
                    }
                    
                    set auto_swept 0
                    switch $faceMapping {
                        "None" { set btype -robust }
                        "Standard" { set btype -swept; set auto_swept 1 }
                        "Aggressive" { set btype -swept }
                    }
                    
                    if {$imprintSurfs != "" || $auto_swept } {
                        set args "-inherited $btype -min_edge $minEdgeLen -automatic_sweep -uface_type $utyp"
                    } else {
                        set args "-inherited $btype -min_edge $minEdgeLen -uface_type $utyp"
                    }

                    switch $createBlkMultiZoneMergeRGVal {
                            0 {}
                            1 { append args " -respect_non_dormant" }
                            2 { append args " -no_merge"}
                            3 {
                                append args " -merge_dormant"
                                set before_merge_dormant 1
                            }
                    }

                    if {$imprintSurfs != ""} {
                        append args " -swept_surfaces $imprintSurfs"
                    }

                    if $before_merge_dormant {
                        set points_merge_dormant ""
                        set crvs [ic_geo_get_dormant curve]
                        if {$crvs != ""} {
                            foreach c $crvs {
                                foreach p [ic_geo_boundary curve $c] {
                                    if {[ic_geo_get_dormant_entity point $p] == 0} {
                                        ic_geo_set_dormant_entity point $p 1
                                        lappend points_merge_dormant $p
                                    }
                                }
                            }
                        }
                    }
                    ic_geo_new_family $fam
                    append args " -save_2d_blocking -show_progress -volfam $fam"
                    set res [eval ic_hex_multizone_blocking $args]
                    if [ic_hex_blocking_loaded] {
                        if {[format %d [ic_hex_mesh_dimension]] != "3"} {
                            set ret 1
                            if {$res != ""} {
                                set num1 [string first "xx1tv" $res]
                                if {$num1 > -1} {
                                    set num1 [expr $num1 + 5]
                                    set num2 [string first "xx2tv" $res]
                                    if {$num2 > $num1} {
                                        set num1_mess $num1
                                        set num2_mess [expr $num2 - 1]
                                        set ret 0
                                    } else {
                                        set num2 [string first "xx2tw" $res]
                                        if {$num2 > $num1} {
                                            set num1_mess $num1
                                            set num2_mess [expr $num2 - 1]
                                        }
                                    }
                                }
                            }
                            if {$ret} {
                                mess "Initialize Blocking failed\n" red
                                aie_unload_blocking
                                aie_after_close_blocking
                                return
                            }
                        }
                    }
                    if $before_merge_dormant {
                        if {$points_merge_dormant != ""} {
                            foreach p $points_merge_dormant {
                                ic_geo_set_dormant_entity point $p 0
                            }
                        }
                        unset points_merge_dormant
                    }
                    set method "auto"
                    if {$freeMethod == "Uniform"} {
                        set method "uniform_quad"
                    } elseif {$freeMethod == "Pave"} {
                        set method "gambit_pave"
                    } elseif {$freeMethod == "Default"} {
                        set method "auto"
                    }
                    hex_command "set_unstruct_face_method $method"
                    if [ic_hex_blocking_loaded] {
                        global top_current
                        if {$top_current != "root"} {
                            aie_rename_topo $top_current root
                        }
                    }
                }
            }
            if ![ic_hex_blocking_loaded] {
                mess "Initialize Blocking failed\n" red
                return
            }
            if $applySettings {
                aie_hex_apply_default_settings $skip
            }
            mess "\nInitialize blocking done\n" blue
            ic_undo_clear
            if {$num1_mess >= 0 && $num2_mess >= 0} {
                mess "Surface blocking instead of volume blocking has been created\n" red
                mess "[string range $res $num1_mess $num2_mess]" red
            }
            createBlockDEZ setclean
        }
        1 {
            if ![ic_hex_blocking_loaded] {
                msg ERROR "No blocking available. Please initialize blocking first"
                return
            }
            switch $createBlkDimVal {
                0 {set Hexa_dimension 3D; set type $createBlk3DTypeVal}
                1 {set Hexa_dimension 2D; set type $createBlk2DTypeVal}
            }
            set mesh_dim [format %d [ic_hex_mesh_dimension]]
            if {$mesh_dim == 2 && $createBlkDimVal == 0} {
                msg ERROR "Current blocking is 2D"
                return
            }
            if {$mesh_dim == 3 && $createBlkDimVal == 1} {
                msg ERROR "Current blocking is 3D"
                return
            }
            set cmd ""
            set best_fit ""
            switch $type {
                0 {
                    set cmd "create_block"
                    if {$createBlk3DGGVal == "1"} {
                        set edges ""
                        foreach e $blockEdges {
                            append edges " [lrange $e 0 1] "
                        }
                        if {$mesh_dim == 3} {
                            set blockVerts $edges
                        }
                    }
                    if {$createBlk3DGGVal == "2"} {
                        set best_fit "best_fit"
                        set blockVerts [join $blockFaces]
                    }
                    if {$mesh_dim == 3 && ([llength $blockVerts]) < 8} {
                        msg ERROR "3D Mapped Block: Number of vertices must be = 8"
                        return
                    }
                    if {$mesh_dim == 2 && ([llength $blockVerts]) < 4} {
                        msg ERROR "2D Mapped Block: Number of vertices must be = 4"
                        return
                    }
                }
                1 {
                    set cmd "create_unstruct_block"
                    if {$createBlkUns3DGGVal == "1"} {
                        set edges ""
                        foreach e $blockEdges {
                            append edges " [lrange $e 0 1] "
                        }
                        if {$mesh_dim == 3} {
                            set blockVerts $edges
                        }
                    }
                    if {$createBlkUns3DGGVal == "2"} {
                        if {$mesh_dim == 3 && ([llength $blockFaces]) < 2} {
                            msg ERROR "3D Swept Block: Number of faces must be = 2"
                            return
                        }
                        set faces ""
                        append faces " [lrange [lindex $blockFaces 0] 0 1] [lrange [lindex $blockFaces 0] 2 3]"
                        append faces " [lrange [lindex $blockFaces 1] 2 3] [lrange [lindex $blockFaces 1] 0 1]"
                        set blockVerts $faces
                    }
                    if {$mesh_dim == 3 && ([llength $blockVerts]) < 6} {
                        msg ERROR "3D Swept Block: Number of vertices must be >= 6"
                        return
                    }
                    if {$mesh_dim == 2 && ([llength $blockVerts]) < 3} {
                        msg ERROR "2D Free Block: Number of vertices must be >= 3"
                        return
                    }
                }
                2 {
                    set cmd "create_yblock"
                    if {$mesh_dim == 3 && ([llength $blockVerts]) < 6} {
                        msg ERROR "3D Quarter-O-Grid Block: Number of vertices must be = 6"
                        return
                    }
                    if {$mesh_dim == 2 && ([llength $blockVerts]) < 3} {
                        msg ERROR "2D Quarter-O-Grid Block: Number of vertices must be = 3"
                        return
                    }
                }
                3 {
                    set cmd "create_degen_block"
                    if {$mesh_dim == 3 && ([llength $blockVerts]) < 6} {
                        msg ERROR "3D Degenerate Block: Number of vertices must be = 6"
                        return
                    }
                }
                4 {
                    set cmd "create_sheet"
                    if {$mesh_dim == 3 && ([llength $blockVerts]) < 4} {
                        msg ERROR "3D Sheet Block: Number of vertices must be = 4"
                        return
                    }
                }
                5 {
                    set cmd "create_unstruct_sheet"
                    if {$blockVerts == ""} {
                        msg ERROR "Free Sheet: No vertices selected"
                        return
                    }
                }
            }
            aie_hex_update_index_form 0
            append cmd " $fam $blockVerts $best_fit [volume_activename_string]"
            hex_command $cmd
            set blockVerts ""
            set blockFaces ""
            get_indices 0
            index_update_all
        }
        2 {
            if ![ic_hex_blocking_loaded] {
                msg ERROR "No blocking available. Please initialize blocking first"
                return
            }
            if {$face == ""} {
                msg ERROR "No face selected for extrusion"
                return
            }
            if {$part_name == "inherited"} {
                set fam inherited
            }
            set ext_type ""
            set cmd "extrude_faces [llength $face] $face"
            switch $extrudeBlkEGVal {
                0 - 1 {
                    switch $extrudeBlkEGVal {
                        0 {
                            set ext_type interactive
                            set distance 1.0e-12
                            set cmd [lreplace $cmd 0 0 extrude_faces_interactive]
                        }
                        1 {
                            set ext_type original
                            if {$distance == ""} {
                                msg ERROR "No distance specified for extrusion"
                                return
                            }
                        }
                    }
                    if $inherit_part {
                        append cmd " inherited $distance -nsub 1"
                    } else {
                        append cmd " $fam $distance -nsub 1"
                    }
                }
                2 {
                    if $orientFlag {
                        set ext_type axial
                    } else {
                        set ext_type normal
                    }
                    if {$extCurve == ""} {
                        msg ERROR "No curve selected for extrusion"
                        return
                    }
                    if {$extEndpt == ""} {
                        msg ERROR "No end point specified for extrusion"
                        return
                    }
                    set extpt $extEndpt
                    if {[llength $extpt] == 1} {
                        set extpt [ic_geo_get_point_location $extEndpt]
                    }
                    if $inherit_part {
                        append cmd " inherited 1.0"
                    } else {
                        append cmd " $fam 1.0"
                    }
                    append cmd " -end $extpt"
                    append cmd " -curve $extCurve"
                    append cmd " -twist $extTwist"
                    append cmd " -nsub $extNumLay"
                    if { $copyProj } {
                        append cmd " -copy_proj"
                    }
                }
            }
            append cmd " -type $ext_type"
            append cmd " [family_activename_string]"
            append cmd " -version 50"
            aie_hex_update_index_form 1
            hex_command $cmd
            # This is for interactive extrusion
            if {($replay_recording) && $ext_type == "interactive"} {
                set d [lindex [string trimright $last_line \n] end]
                set prev_replay_do_all $replay_do_all
                set replay_do_all 1
                if {$d != "" && abs($d) > 1.0e-10} {
                    set rcmd "ic_hex_extrude_faces [llength $face] $face $fam $d -nsub 1"
                    append rcmd " -type original [family_activename_string] -version 50"
                    replay_record_command "replay_put $rcmd"
                }
                set replay_do_all $prev_replay_do_all
            }
            if $hex_option(check_inv) {
                aie_hex_check_fix_inverted
            }
            get_indices 1
            index_update_all
            mess "Extrusion of faces done.\n" blue
        }
        3 {
            if ![ic_hex_blocking_loaded] {
                msg ERROR "No 2D blocking available"
                return
            }
            set mesh_dim [format %d [ic_hex_mesh_dimension]]
            if {$mesh_dim != 2} {
                msg ERROR "Current blocking is already 3D"
                return
            }
            set 2dto3d_method $createBlk2Dto3DHowVal
            if [info exists env(AI_ENV_LSTC)] {
                incr 2dto3d_method
            }
            switch $2dto3d_method {
                0 {
                    hex_command "mark_blocks unmark"
                    set cmd "twod_to_threed $fam -check_body"
                    switch $twod2threedEGVal {
                        0 {append cmd " -basic"}
                        1 {append cmd " -swept"}
                    }
                    hex_command $cmd
                    if $fillOgridGGVal {
                        if {$ogridParts == ""} {
                            msg ERROR "No surface parts selected for Ogrid creation"
                            return
                        }
                        set matfams ""
                        foreach f [ic_hex_list_block_families] {
                            if { $f != "ORFN" && $f != "VORFN" } {
                                lappend matfams $f
                            }
                        }

                        set ogridFams ""
                        foreach p $ogridParts {
                            foreach f [ic_geo_list_families_in_part $p] {
                                lappend ogridFams $f
                            }
                        }
                        set inv_ogridFams ""
                        foreach f [ic_geo_list_families] {
                            if {[lsearch $ogridFams $f] < 0} {
                                # don't put ORFN or VORFN in this list
                                if { $f != "ORFN" && $f != "VORFN" } {
                                    lappend inv_ogridFams $f
                                }
                            }
                        }

			            # for swept inflation faces need to be marked differently
			            if {$twod2threedEGVal == 1} { 
			                hex_command "mark_blocks $matfams inf_family $ogridFams"
			            } else {
			                hex_command "mark_blocks $matfams"
			                hex_command "mark_blocks on_family $inv_ogridFams"
			            }

			            # for uns. blocks absolute is mostly desired
                        set absolute 1
                        if $absolute {set args [list distance $offset var_dist] } else {set args $offset}
                        append args "  m [volume_activename_string] -version 110"		
                       
                        hex_command "ogrid  $args"
                        hex_command "mark_blocks unmark"
                        #hex_command "set_mesh_params fix_boundary -version 110"
                        set ogridParts ""
                    }
                }
                1 {
                    if {$fam == "" && !$inherit_part} return
                    if {$X == ""} {set X 0} ; if {$Y == ""} {set Y 0} ; if {$Z == ""} {set Z 0}
                    if {($X == 0) && ($Y == 0) && ($Z == 0)} {
                        mess "Need to define distance to translate.\n" red
                        return
                    }
                    set args "translate $X $Y $Z"
                    if !$inherit_part {
                        append args " -newfam $fam"
                    }
                    eval ic_hex_extrude_blocks $args
                    if [aie_hex_sketching_mode] {
                        ic_hex_sketch_unset_projections
                    }
                }
                2 {
                    switch $blk2Dto3DRotateBaseEGVal {
                        0 {
                            set base "0 0 0"
                        }
                        1 {
                            if ![va_is_triplet $center] {
                                msg ERROR "No center selected"
                                return
                            }
                            set base $center
                        }
                    }
                    if ![info exists blk2Dto3DRotateAxisEGVal] {
                        msg ERROR "No axis specified for rotation"
                        return
                    }
                    switch $blk2Dto3DRotateAxisEGVal {
                        0 { set vec "1 0 0"}
                        1 { set vec "0 1 0"}
                        2 { set vec "0 0 1"}
                        3 {
                            if {[llength $axis] != 2} {
                                msg ERROR "Need to provide two points for axis"
                                return
                            }
                            foreach i {0 1} {
                                set pt [lindex $axis $i]
                                if {[llength $pt] == 1} {
                                    set pt$i [ic_geo_get_point_location $pt]
                                } else {
                                    set pt$i $pt
                                }
                            }
                            set vec ""
                            foreach i {0 1 2} {
                                lappend vec [expr [lindex $pt1 $i] -  [lindex $pt0 $i]]
                            }
                        }
                    }
                    if {$angle == ""} {set angle 0}
                    if {$angle == 0} {
                        mess "Need to provide an angle\n" red
                        return
                    }
                    set args "rotate $base $vec $angle -ncopies $number -npoints $ppc "
                    if $collapseFlag {lappend args collapse_axis}
                    if $periodicFlag {lappend args set_periodic}
                    if $pointFlag {lappend args -extrude_points}
                    if $curveFlag {lappend args -extrude_curves}
                    if !$inherit_part {
                        lappend args -newfam $fam
                    }
                    hex_command "extrude_blocks $args"
                    if {$pointFlag == 1 || $curveFlag == 1 && ![aie_hex_sketching_mode]} {
                        ic_reinit_geom_objects
                    }
                    if [aie_hex_sketching_mode] {
                        ic_hex_sketch_unset_projections
                    }
                }
            }
            get_indices 1
            index_update_all
            hex_mesh_size 1
            mess "2D -> 3D block conversion is done\n" blue
        }
        4 {
            if ![ic_hex_blocking_loaded] {
                msg ERROR "No blocking loaded"
                return
            }
            eval ic_hex_threed_to_twod [volume_activename_string]
            mess "Blocking successfully converted to 2D\n" blue
            hex_mesh_size 1
        }
    }
    aie_create_vorfn
    aie_update_parts_in_tree_if_needed
    aie_hex_update_display
    aie_hex_update_index_form 0

    if {$createBlkVal == 0} {
        aie_topo_build_defaults 0
    }
    aie_update_icons block
    if {[info exists aie_CurveComposite] && !$aie_CurveComposite} {
        set aie_CurveComposite 1
        ::AIEnv::GUIManagement::Tree::CurveComposite
    }
    if [ic_hex_blocking_loaded] {
        # These don't grey the icons yet, but should be fixed.
        ::AIEnv::GUIManagement::ToggleGrey createBlkVertices 0
        ::AIEnv::GUIManagement::ToggleGrey createBlkExtrude 0
        ::AIEnv::GUIManagement::ToggleGrey createBlk2Dto3D 0
        ::AIEnv::GUIManagement::ToggleGrey createBlk3Dto2D 0
        # band-aid to restore parts visibility after undo/recreate operation
        aie_create_parts_in_tree_if_needed
    }
}

proc aie_hex_sketch_create_blocking_without_geometry {{part SOLID} {apply 0}} {
    global beta_mode fam_visible
    
    if !$beta_mode return
    if [ic_geo_is_loaded] return
    if [ic_hex_blocking_loaded] aie_unload_blocking

    set fam_visible($part) 0
    ic_hex_sketch_create_blocking_without_geometry 2DPlanar 0.001 $part 
    ::AIEnv::GUIManagement::Tree::clear geom
    set fam_visible($part) 1
    
    if $apply { aie_hex_apply_default_settings 2 }
    
    if [ic_hex_blocking_loaded] {
        aie_create_vorfn
        aie_hex_update_display
        aie_update_icons block
        ::AIEnv::GUIManagement::ToggleGrey createBlkVertices 0
        ::AIEnv::GUIManagement::ToggleGrey createBlkExtrude 0
        ::AIEnv::GUIManagement::ToggleGrey createBlk2Dto3D 0
        ::AIEnv::GUIManagement::ToggleGrey createBlk3Dto2D 0
        aie_create_parts_in_tree_if_needed
        aie_update_parts_in_tree_if_needed
        aie_view fitWindow
    }
    mess "\nInitialized 2D Planar blocking (blocking w/o geometry mode)\n" blue
}


proc aie_hex_apply_default_settings {{skip 0}} {
    global hex_option default_bunch_laws

    hex_command "multi_grid_level $hex_option(multigrid_level)"
    hex_command "projection_limit $hex_option(proj_limit)"
    set law $hex_option(default_bunching_law)
    if [info exists default_bunch_laws($law)] {
        set law $default_bunch_laws($law)
        set ratio $hex_option(default_bunching_ratio)
        hex_command "default_bunching_law $law $ratio"
    }
    if $hex_option(floating_grid) {
        hex_command "floating_grid on"
    } else {
        hex_command "floating_grid off"
    }
    hex_command "transfinite_degree $hex_option(trfDeg)"
    if {$skip == 0 || $skip == 2} { hex_command "unstruct_face_type $hex_option(uns_face_mesh)" }
    if {$skip == 0 || $skip == 2} { hex_command "set_unstruct_face_method $hex_option(uns_face_mesh_method)" }
    hex_command "set_n_tetra_smoothing_steps $hex_option(n_tetra_smoothing_steps)"
    if $hex_option(hexa_verbose_mode) {
        hex_command "error_messages on_minor"
    } else {
        hex_command "error_messages off_minor"
    }
}

proc aie_hex_set_default_bunching_on_all_edges {} {
    global hex_option default_bunch_laws use_output_blocks

    set law [string trimright [hex_command "default_bunching_law"] \n]
    set cmd "select_edge no_highlight all max 1 m [join [ic_hex_list_block_families]] new_format selected_bunching volume"
    if $use_output_blocks { append cmd " output_blocks" }
    foreach "edge" [string trimright [hex_command $cmd] \n] {
        set n1 [lindex $edge 0]; set n2 [lindex $edge 1]
        hex_command "set_mesh $n1 $n2 $law"
    }
}

######################## Split Blocking #####################################

proc onsplitBlkDEZLoad {} {

    if {$offset == ""} { set offset 1 }
    if {![info exists splitPar] || ($splitPar == "")} { set splitPar 0.5 }
    if {$splitBlkBlkSel2Val == ""} { set splitBlkBlkSel2Val 0 }
    if {([info exists splitBlkVal]) && $splitBlkVal == 1} { onOgridBlkBlkLoad }
    if {$copy_from_parallel == ""} { set copy_from_parallel 0 }
    if {![info exists nearest_node_split] || ($nearest_node_split == "")} { set nearest_node_split 0 }
    if {$splitExtendGGVal == ""} {
        set splitExtendGGVal 0
        set markedBlock ""
        set markedBlock2 ""
        set Faces ""
        set Edges ""
        set Vertices ""
        set force_ass_vertex 0
        set splitSheets1 ""
        set splitSheets2 ""
        set ublock ""
        set uFace1 ""
        set uFace2 ""
        set convert_side_faces 0
        set iFace ""
        set edgesProj ""
        set vecImprintList ""
        set project 0
        set move_ogrid_nodes 0
        set link_shape 0
    }
}

proc onsplitBlkDEZAfterLoad {} {

    if ![info exists splitBlkAfterInit] {
        aie_reset_picker "" splitBlkEdgeCurvePick image select_curve_loc$icon_size1.gif helptext "Select location on curve"
	    set splitBlkAfterInit 999
    }
    if {[trace vinfo splitExtendGGVal] != ""} {
        trace vdelete splitExtendGGVal w aie_hex_trace_splitExtendGGVal
    }
    trace variable splitExtendGGVal w aie_hex_trace_splitExtendGGVal
    aie_hex_trace_splitExtendGGVal "" "" ""
    if {[format %d [ic_hex_mesh_dimension]] < 3} {
        ::AIEnv::GUIManagement::ToggleGrey ImprintSblockPick 0
        ::AIEnv::GUIManagement::ToggleGrey ImprintSFacePick 1
        ::AIEnv::GUIManagement::ToggleGrey SplitUnsBlk3dCut 1
        ::AIEnv::GUIManagement::ToggleGrey splitFaceFace2 0
        set ImprintMethodVal 0
        set SelectionMethodVal 1
    } else {
        ::AIEnv::GUIManagement::ToggleGrey ImprintSblockPick 1
        ::AIEnv::GUIManagement::ToggleGrey ImprintSFacePick 0
        ::AIEnv::GUIManagement::ToggleGrey SplitUnsBlk3dCut 0
        ::AIEnv::GUIManagement::ToggleGrey splitFaceFace2 1
        set ImprintMethodVal 1
        set SelectionMethodVal 0
    }
    aie_hex_select_split_project
}

proc aie_hex_trace_splitExtendGGVal {name element op} {
    if [splitBlkDEZ get splitExtendGGVal] {
        ::AIEnv::GUIManagement::ToggleGrey ExtEdgePick 1
        after 100 {
            ::AIEnv::GUIManagement::ToggleGrey splitBlkBlkSel2 0
            if [splitBlkDEZ get splitBlkBlkSel2Val] {
                ::AIEnv::GUIManagement::ToggleGrey splitBlkBlkSelSelBlock2 0
            } else {
                ::AIEnv::GUIManagement::ToggleGrey splitBlkBlkSelSelBlock2 1
            }
        }
    } else {
        if [splitBlkDEZ get splitBlkBlkSel2Val] {
            ::AIEnv::GUIManagement::ToggleGrey splitBlkBlkSel2 0
            ::AIEnv::GUIManagement::ToggleGrey splitBlkBlkSelSelBlock2 0
        } else {
            if [splitBlkDEZ get splitExtendGGVal] {
                ::AIEnv::GUIManagement::ToggleGrey splitBlkBlkSel2 0
            }
            ::AIEnv::GUIManagement::ToggleGrey splitBlkBlkSelSelBlock2 1
        }
        ::AIEnv::GUIManagement::ToggleGrey ExtEdgePick 0
    }
}

proc onsplitBlkBlkLoad {} {
    if {$splitBlkBlkSelVal == ""} { set splitBlkBlkSelVal 0 }
    set splitBlkEdgeMethodVal 0
    if $auto_pick_mode {
	    if !$splitBlkBlkSelVal {
	        splitBlkEdgePick pick
	    } else {
	        splitBlkBlkSelSelBlock pick
	    }
    }
}

proc onsplitBlkBlkSelSelBlockFinish {} {
    if {($markedBlock  != "") && $auto_pick_mode } {
	    splitBlkEdgePick pick
    }
}

proc onsplitBlkBlkSelSelBlock2Finish {} {
    if {($markedBlock2  != "") && $auto_pick_mode } {
	    ExtEdgePick pick
    }
}

proc onsplitBlkEdgePickFinish {} {
    global select_action

    if {$splitBlkEdge == "" || (!$auto_pick_mode && $splitBlkEdgeMethodVal)} {
        hex_update_display vert edge
        return
    }
    if !$splitBlkEdgeMethodVal { splitBlkDEZ apply }  
    if !$auto_pick_mode return
	switch $splitBlkEdgeMethodVal {
	    0 {
            if {$select_action == "local_cancel"} return
		    if !$splitBlkBlkSelVal {
		        splitBlkEdgePick pick
		    } else {
		        splitBlkBlkSelSelBlock pick
		    }
	    }
	    1 {
	        set splitPoint ""
	        after 250
		    splitBlkEdgePointPick pick
	    }
	    2  {
	        if {$select_action == "local_cancel"} return
	        if {([string is double $splitPar] || [string is integer $splitPar])} {
		        splitBlkDEZ apply
		    }
	    }
	    
	    4 {
		    splitBlkEdgeCurvePick pick
	    }	   
	}
}

proc onsplitBlkEdgePointPickFinish {} {
    if {($splitPoint != "") && $auto_pick_mode } {
	    splitBlkDEZ apply
	    if !$splitBlkBlkSelVal {
	        splitBlkEdgePick pick
	    } else {
	        splitBlkBlkSelSelBlock pick
	    }
    }
}

proc onsplitBlkEdgeCurvePickFinish {} {
}

proc onsplitBlkExtendLoad {} {
    if {$splitExtendGGVal && $auto_pick_mode} {
	    ExtEdgePick pick
    }
}

proc onExtEdgePickFinish {} {
    if {($ExtendEdge  != "") && $auto_pick_mode } {
        splitBlkDEZ apply
	    splitBlkDEZ onsplitBlkExtendLoad
    }
}


proc onsplitBlkExtendFaceLoad {} {
    if $auto_pick_mode {
        if [splitBlkDEZ get SelectionMethodVal] {
            if {[format %d [ic_hex_mesh_dimension]] == 3} return
            splitFaceFace2 pick
        } else {
            splitFaceFace pick
        }
    }
}

proc onsplitBlkExtendFaceUnLoad {} {
    aie_hex_delete_display_subset
}

proc onsplitFaceFacePick {} {

    aie_hex_delete_display_subset
}

proc onsplitFaceFaceFinish {} {
    global hexa_corners_selected
    
    if {$splitFace != ""} {
        aie_hex_create_display_subset face $splitFace
    }
    if $auto_pick_mode {
	    if {$hexa_corners_selected  != ""} { set splitFace $hexa_corners_selected }
	    splitFaceEdgePick pick
    }
}

proc onsplitFaceEdgePickFinish {} {
    if {$splitFaceEdge == ""} return
    if $auto_pick_mode {
	    splitBlkDEZ apply
	    splitFaceFace pick
    } else {
        splitBlkDEZ apply
    }
}

proc onuncollapseBlkBLoad {} {
    if $auto_pick_mode {
	    uncollapsePickB pick
    }
}

proc onuncollapsePickBFinish {} {
    if {$splitVerts != "" &&  $auto_pick_mode} {
	    splitBlkDEZ apply
	    uncollapsePickB pick
    }
}

proc aie_mark_ogrid {} {
    global hexa_sel

    if {$hexa_sel == "remove"} {
	    set mark_flag unmark
    } else {
	    set mark_flag ""
    }
}

proc aie_clear_ogrid_sel {} {
    hex_command "mark_blocks unmark"
    hex_update_display
}

proc onOBlkBlockPickFinish {} {
    global use_output_blocks hexa_family_selected

    splitBlkDEZ aie_mark_ogrid

    ic_undo_group_begin
    if {$markedBlock != "" && $hexa_family_selected != ""} {
        set cmd "mark_blocks $mark_flag $hexa_family_selected"
        if $use_output_blocks {
            append cmd " output_blocks"
        }
        hex_command $cmd
    } else {
        foreach block $markedBlock {
            set cmd "mark_blocks $mark_flag superblock $block"
            if $use_output_blocks {
                append cmd " output_blocks"
            }
            hex_command $cmd
        }
    }

    ic_undo_group_end
    set del_opts "marked m [volume_activename_string] -solid dead_as_faces"
    hex_command "display_elements $del_opts"
}

proc onOBlkFacePickPick {} {
    global use_output_blocks hexa_family_selected previous_selections
    
    if ![info exists Faces] { set Faces "" }   
    set previous_selections(faces) $Faces
}

proc onOBlkFacePickFinish {} {
    global use_output_blocks hexa_family_selected previous_selections

    splitBlkDEZ aie_mark_ogrid

    ic_undo_group_begin

    set cfaces ""
    set reset_faces ""
    
    if {$previous_selections(faces) != ""} {
       if {$mark_flag == "unmark"} {
           foreach face $previous_selections(faces) {
               if {[lsearch $Faces $face] < 0} {
                   lappend reset_faces $face
               }
           }
       }
    }
    
    foreach face $Faces {
	    if {[lindex $face end] == "u"} {
	        foreach n $face {
		        if [regexp {[0-9]} $n] {
		            set cmd "mark_blocks $mark_flag superblock $n"	   
		            if $use_output_blocks {
			            append cmd " output_blocks"
		            }
		            hex_command $cmd
		        }
	        }
	    } else {
	        lappend cfaces $face
	    }
    }

    if {$cfaces != ""} {
	    set cmd "mark_blocks $mark_flag face_neighbors corners $cfaces"
	    if $use_output_blocks {
	        append cmd " output_blocks"
	    }
	    hex_command $cmd
    }
    if {$reset_faces != "" && $mark_flag == "unmark"} {
	    set cmd "mark_blocks face_neighbors corners $reset_faces"
	    if $use_output_blocks {
	        append cmd " output_blocks"
	    }
	    hex_command $cmd
	    set Faces $reset_faces
    }    
   
    if {$hexa_family_selected != ""} {
	    set cmd "mark_blocks on_family $hexa_family_selected"
	    hex_command $cmd
    }
    ic_undo_group_end
    set del_opts "marked m [volume_activename_string] -solid dead_as_faces"
    hex_command "display_elements $del_opts"
}

proc onOBlkEdgePickFinish {} { 
    global use_output_blocks
 
    splitBlkDEZ aie_mark_ogrid

    ic_undo_group_begin
    foreach edge $Edges {
	set v1 [lindex $edge 0]
	set v2 [lindex $edge 1]

	set cmd "mark_blocks $mark_flag numbers $v1 $v2 edge_neighbors"
	if $use_output_blocks {
	    append cmd " output_blocks"
	}
	hex_command $cmd
    }
    ic_undo_group_end
    set del_opts "marked m [volume_activename_string] -solid dead_as_faces"
    hex_command "display_elements $del_opts"
}

proc onOBlkVertPickFinish {} {
    global use_output_blocks

    splitBlkDEZ aie_mark_ogrid

    ic_undo_group_begin
    foreach v $Vertices {
        set cmd "mark_blocks $mark_flag numbers $v $v vertex_neighbors"
        if $use_output_blocks {
            append cmd " output_blocks"
        }
        hex_command $cmd
    }
    ic_undo_group_end
    set del_opts "marked m [volume_activename_string] -solid dead_as_faces"
    hex_command "display_elements $del_opts"
}

proc onSplitUnsBlk3dFace1Finish {} {
    if {($uFace1 != "") && $auto_pick_mode} {
        SplitUnsBlk3dFace2 pick
    }
}

proc onSplitUnsBlk3dFace2Finish {} {
    if {($uFace2 != "") && $auto_pick_mode} {
        splitBlkDEZ apply
        SplitUnsBlk3dFace1 pick
    }
}

proc onSplitUnsBlk3dPick1Finish {} {
    if {($ublock != "") && $auto_pick_mode} {
	    SplitUnsBlk3dSheets1 pick
    }
}

proc onSplitUnsBlk3dSheets1Finish {} {
    if {($splitSheets1 != "") && $auto_pick_mode} {
        splitBlkDEZ apply
	    SplitUnsBlk3dPick1 pick
    }
}

proc onSplitUnsBlk3dPick2Finish {} {
    if {($ublock != "") && $auto_pick_mode} {
	    SplitUnsBlk3dSheetsLoop3 pick
    }
}

proc onSplitUnsBlk3dSheetsLoop3Finish {} {
    if {($splitSheets1 != "") && $auto_pick_mode} {
	    SplitUnsBlk3dSheetsLoop4 pick
    }
}

proc onSplitUnsBlk3dSheetsLoop4Finish {} {
    if {($splitSheets2 != "") && $auto_pick_mode} {
	    splitBlkDEZ apply
	    SplitUnsBlk3dPick2 pick
    }
}

proc onSplitUnsBlk3dPick4Finish {} {
    if {($ublock != "") && $auto_pick_mode} {
	    SplitUnsBlk3dSheets4 pick
    }
}

proc onSplitUnsBlk3dSheets4Finish {} {
    if {($splitSheets != "") && $auto_pick_mode} {
	    splitBlkDEZ apply
	    SplitUnsBlk3dPick4 pick
    }
}

proc onImprintSblockPickFinish {} {
    if {[format %d [ic_hex_mesh_dimension]] == 3} return
    if {($sblock != "") && $auto_pick_mode} {
	    ImprintUnsBlkEdges pick
    }
}

proc onImprintSFacePickPick {} {

    aie_hex_delete_display_subset
}

proc onImprintSFacePickFinish {} {
    if {[format %d [ic_hex_mesh_dimension]] < 3} return
    if {$iface == ""} return
    aie_hex_create_display_subset face $iface
    if $auto_pick_mode {
	    ImprintUnsBlkEdges pick
    }
}

proc onImprintUnsBlkEdgesFinish {} {
    if !$auto_pick_mode return
    if {$splitVerts == ""} return
    if {($ImprintUnsBlkMethodVal == 0) || ($ImprintUnsBlkMethodVal == 1 && $ImprintUnsBlkEGVal < "3") || \
        ($ImprintUnsBlkMethodVal == 1 && $ImprintUnsBlkEGVal == "3" && ($vecImprintList != "" && [llength $vecImprintList] == 2))} {
	    splitBlkDEZ apply
	    if {[format %d [ic_hex_mesh_dimension]] < 3} {
	        ImprintSblockPick pick
	    } else {
	        ImprintSFacePick pick
	    }
    } elseif {($ImprintUnsBlkEGVal == "3" && ($vecImprintList == "" || [llength $vecImprintList] != 2))} {
        ImprintUnsBlkVector pick
    } 
}

proc onImprintUnsBlkVectorFinish {} {
    if !$auto_pick_mode return
    if {$splitVerts == ""} return
	if {[format %d [ic_hex_mesh_dimension]] < 3} {
	    if {$sblock == ""} return
	} else {
	    if {$iface == ""} return
	}
    if {($vecImprintList != "" && [llength $vecImprintList] == 2)} {
	    splitBlkDEZ apply
	    if {[format %d [ic_hex_mesh_dimension]] < 3} {
	        ImprintSblockPick pick
	    } else {
	        ImprintSFacePick pick
	    }
    }
}

proc onsplitFaceFace2Finish {} {
    if {[format %d [ic_hex_mesh_dimension]] == 3} return
    if !$auto_pick_mode return
    if {$splitFace != ""} {
	    splitBlkDEZ apply
	    splitFaceFace2 pick
    }
}

proc onOgridBlkBlkLoad {} {
    set mesh_dim [ic_hex_mesh_dimension]
    if {$mesh_dim != 3} {
    	::AIEnv::GUIManagement::ToggleGrey OBlkFacePick 1
    	mess "Face selection disabled for 2D blocking \n" blue
    } else {
        ::AIEnv::GUIManagement::ToggleGrey OBlkFacePick 0
    }
    set unmark 0
    set mark_flag ""
    hex_command "mark_blocks unmark"
}

proc onOgridBlkBlkUnLoad {} {
    if ![ic_hex_blocking_loaded] return
    # index_reset
    get_indices 3
    index_update_all
    hex_command "mark_blocks unmark" 0
    set markedBlock ""
    set Faces ""
    set Edges ""
    set Vertices ""
   
    hex_update_display
    set unmark 0
}

proc onsplitBlkDEZUnLoad {} {
    if {[info exists splitBlkVal] && ($splitBlkVal == 1)} {
	    splitBlkDEZ onOgridBlkBlkUnLoad
    }
    if {[trace vinfo splitExtendGGVal] != ""} {
        trace vdelete splitExtendGGVal w aie_hex_trace_splitExtendGGVal
    }
    aie_hex_delete_display_subset
}

proc onsplitUnsBlkLoad {} {
    if $auto_pick_mode {
	    splitUnsBlkVerts pick
    }
}

proc onsplitUnsBlkVertsFinish {} {
    if {$auto_pick_mode && $splitVerts != "" } {
	    splitBlkDEZ apply
	    splitUnsBlkVerts pick
    }
}

proc onSplitUnsBlk3dProjPick1Pick {} {

    aie_hex_delete_display_subset
}

proc onSplitUnsBlk3dProjPick1Finish {} {
    global auto_pick_mode

    set f [splitBlkDEZ get iFace]
    if {$f == ""} return
    aie_hex_create_display_subset face $f 
    if !$auto_pick_mode return
    SplitUnsBlk3dProjPick2 pick
}

proc onSplitUnsBlk3dProjPick2Finish {} {
    global auto_pick_mode

    set f [splitBlkDEZ get edgesProj]
    if {$f == ""} return
    if !$auto_pick_mode return
    splitBlkDEZ apply
    SplitUnsBlk3dProjPick1 pick
}

proc onSplitUnsBlk3dUnLoad {} {
    aie_hex_delete_display_subset
}

proc onImprintUnsBlkUnLoad {} {
    aie_hex_delete_display_subset
}

proc onselectSplitProject {} {

    if $project {
        ::AIEnv::GUIManagement::ToggleGrey splitBlkOgrid 0
        set move_ogrid_nodes 1
    } else {
        ::AIEnv::GUIManagement::ToggleGrey splitBlkOgrid 1
        set move_ogrid_nodes 0
    }
}

proc aie_hex_select_split_project {} {
     splitBlkDEZ onselectSplitProject
}

proc onsplitBlkDEZOK {} {
    global button_instructions last_line use_output_blocks display_flag
    global select_in_dynamics index_min index_max
    global hex_option tdv_picked tdv_click_preset
    global hexa_select select_action beta_mode
    global index_form index_dims bunching_laws 

    catch { unset old_edges }
    catch { unset new_edges }

    switch $splitBlkVal {
        0 {
            set cmd "select_edge no_highlight all max 1 m [volume_activename_string] new_format selected_bunching volume"
            if $use_output_blocks { append cmd " output_blocks" }
            set old_edges [string trimright [hex_command $cmd] \n]
            set old_verts [hex_command "select_nodes 1 all [range_string] m [volume_activename_string] node_numbers"]
            splitBlkDEZ setclean
            set split_edge $splitBlkEdge
            if {$split_edge == ""} return
            set split_n1 [ lindex $split_edge 0 ]
            set split_n2 [ lindex $split_edge 1 ]
            set split_dim [hex_command "edge_node_dim $split_n1 $split_n2"]
            set split_dir [ lindex $split_dim 0 ]
            set split_ind [ lindex $split_dim 1 ]
            switch $splitBlkEdgeMethodVal {
                0 {
                    set ival 0.5
                    if [info exists tdv_picked] {
                        set cmd "ray_x_edge_value $split_n1 $split_n2 $tdv_picked(aloc) $tdv_picked(vec)"
                        hex_command $cmd 1 1
                        set ival [lindex $last_line 0]
                    }
                    banner "Select location on the edge to split; $button_instructions"
                    set ::select_in_dynamics 0
                    tdv_set_key_command F9 select_hexa_toggle_dynamics
                    set ::hexa_select 1
                    if {[lsearch [volume_activename_string] "VORFN"] < 0 && [ic_hex_mesh_dimension] == 2} {
                        set vol_fam_used [volume_activename_string]
                        lappend vol_fam_used VORFN
                    } else {
                        set vol_fam_used [volume_activename_string]
                    }
                    set cmd "select_value $split_n1 $split_n2 -initial $ival $vol_fam_used [range_string]"
                    if $display_flag(use_blanking) {
                        append cmd " -not_blanked"
                    }
                    if {$splitBlkBlkSelVal == 0 && ([info exists index_form] && [winfo exists $index_form])} {
                        set do_it 0
                        set cmd_blk "select_blocks 1 no_highlight all [range_string] m [volume_activename_string] -not_blanked"
                        if $use_output_blocks { append cmd_blk " output_blocks" }
                        if $display_flag(block_super) { append cmd_blk " super" }
                        if {!$display_flag(block_struct)} { append cmd_blk " -hide_struct" }
                        if {!$display_flag(block_unstruct)} { append cmd_blk " -hide_unstruct" }
                        if {!$display_flag(block_swept)} { append cmd_blk " -hide_swept" }
                        append cmd_blk " -keep_unstruct3d"
                        set markedBlockTypes [lsort -unique [hex_command $cmd_blk]]
                        foreach blk $markedBlockTypes {
                            set type [string trimright [ic_hex_print_block_type_info $blk] \n]
                            if {$type == "swept"} {
                                set do_it 1
                                break
                            }                          
                        }
                        if $do_it {
                            set markedBlock $markedBlockTypes
                        } else {
                            unset markedBlockTypes
                        }
                    }
                    hex_command $cmd 1 1
                    set val [lindex $last_line 0]
                    banner ""
                    if ![info exists ::hexa_select] {
                        set select_action "local_cancel"
                        return
                    }
                    mess "Split value: [string trimright $val \n]\n" blue
                    catch {unset ::hexa_select}
                }
                1 {
                    set val $splitPoint
                }
                2 {
                    set val $splitPar
                }
                3 {
                    set val abs:$splitDist
                }
                4 {
                    set val curve:$splitCurve:$splitCurvePar
                }
            }
            if {$val != "" && $val != -1} {
                if {$splitBlkEdgeMethodVal == 0  && ($val <= 0 || $val >= 1)} {
                    msg ERROR "Split value must be between 0.0 and 1.0"
                    catch { unset vol_fam_used }
                    return
                }
                if ![info exists vol_fam_used] {
                    if {[lsearch [volume_activename_string] "VORFN"] < 0 && [ic_hex_mesh_dimension] == 2} {
                        set vol_fam_used [volume_activename_string]
                        lappend vol_fam_used VORFN
                    } else {
                        set vol_fam_used [volume_activename_string]
                    }
                }
                set cmd "$split_n1 $split_n2 $val [range_string] m $vol_fam_used"
                if {$splitBlkBlkSelVal == 1 || ([info exists do_it] && $do_it)} {
                    hex_command "mark_blocks unmark" 0
                    lappend cmd marked
                    block_mark_super $markedBlock
                    if {[info exists do_it] && $do_it} {
                        set splitBlkBlkSelVal 0
                        unset do_it
                    }
                } elseif { $display_flag(use_blanking) } {
                    lappend cmd marked
                    hex_command "mark_blocks unmark" 0
                    hex_command "mark_blocks [volume_activename_string] -not_blanked"
                }
                if $nearest_node_split {
                    lappend cmd mpar
                }
                ic_hex_undo_major_start "split_grid"
                hex_command "split_grid $cmd"                 
                if $project {
                    if {([format %d [ic_hex_mesh_dimension]] == 3) && ([ic_hex_get_block_type_number free] == "1" && [ic_hex_get_block_type_number mapped] == 0 && [ic_hex_get_block_type_number swept] == 0)} {  
                        set new_verts ""
                        catch { array unset tmp_v }
                        foreach v [string trimright [hex_command "select_nodes 1 all [range_string] m [volume_activename_string] node_numbers"] \n] {
                            if {[info exists tmp_v($v)] || [lsearch $old_verts $v] >= 0} continue
                            set tmp_v($v) 1
                            lappend new_verts $v
                        }
                        if {$new_verts != ""} {
                            mess "Projecting [llength $new_verts] vertices..."
                            set new_proj [aie_get_vert_proj "$new_verts"]
                            if $move_ogrid_nodes {
                                ic_hex_project_to_surface $new_proj [volume_activename_string] move_ogrid_nodes only_new
                            } else {
                                ic_hex_project_to_surface $new_proj [volume_activename_string] only_new
                            }
                            mess "done\n"
                        }
                    } else {
                        incr split_ind 
                        set cmd "project_to_surface $split_dir:$split_ind,$split_ind [volume_activename_string]"
                        if $move_ogrid_nodes {
                            append cmd " move_ogrid_nodes"
                        }
                        hex_command $cmd
                    }
                }
                ic_hex_undo_major_end "split_grid"
                if {$split_dir < 3} {
                    if {$split_ind <= $index_max($split_dir)} {
                        incr index_max($split_dir)
                    }
                    if {$split_ind < $index_min($split_dir)} {
                        incr index_min($split_dir)
                    }
                }
            }
            if {$copy_from_parallel && $val != "" && $val != -1} {
                set cmd "select_edge no_highlight all max 1 m [volume_activename_string] new_format selected_bunching volume"
                if $use_output_blocks { append cmd " output_blocks" }
                set new_edges [string trimright [hex_command $cmd] \n]
                catch { unset tmp_e; unset tmp_v }
                foreach e $old_edges { set tmp_e($e) 1 }
                set new_split_edges ""
                catch { unset parallel_edges }
                mess "Copying edge distribution from nearest parallel edge to new split edge(s)"
                set ta [tdv_active 0]
                set i 0
                foreach e $new_edges {
                    if [info exists tmp_e($e)] continue
                    if {[lsearch $old_verts [lindex $e 0]] >= 0} continue
                    if {[lsearch $old_verts [lindex $e 1]] >= 0} continue
                    lappend new_split_edges $e
                    set parallel_edges($e) [aie_hex_parallel_edges $e 1 1]
                    incr i
                    if {[expr $i % 10] == 0} { mess "." }
                }
                mess "\n"
                tdv_active $ta
                if {$new_split_edges != ""} {
                    set i 0
                    foreach to_e $new_split_edges {
                        if ![info exists parallel_edges($to_e)] continue
                        if {$parallel_edges($to_e) == ""} continue
                        set from_e [lindex $parallel_edges($to_e) 0]
                        ic_hex_copy_edge_params $from_e $to_e 1
                        incr i
                    }
                    mess "$i edge distribution(s) copied\n"
                }
            }
            set splitBlkEdge ""
            set markedBlock ""
            set splitPoint ""
            get_indices 3
            hex_update_display vertex edge face block mesh
            catch { unset vol_fam_used }
            mess "Split block done\n" blue
            return
        }

        1 {
            if $around {
                set cmd "select_edge no_highlight all max 1 m [volume_activename_string] new_format volume"
                if $use_output_blocks { append cmd " output_blocks" }
                foreach e [string trimright [hex_command $cmd] \n] {
                    set e1 [lindex $e 0]
                    set e2 [lindex $e 1]
                    set old_edges(params,$e1,$e2) [string trimright [ic_hex_mesh_params $e1 $e2] \n]
                    set old_edges(dim,$e1,$e2) [string trimright [hex_command "edge_node_dim $e1 $e2"] \n]
                }
            }
            
            # Create O-grid
            splitBlkDEZ setclean
            if $absolute {set args [list distance $offset fix_dist] } else { set args $offset }
            if $around {append args " not_marked"}
            if {$beta_mode && $force_ass_vertex == 1 && ([format %d [ic_hex_mesh_dimension]] == 3)} {
                append args " m [volume_activename_string]"
            } else {           
                append args " m [volume_activename_string] -version 50"
            }
            if {[info exists index_form] && [winfo exists $index_form] && [info exists index_dims]} {
                aie_hex_update_index_form 1
            }
            if $link_shape {
                append args " link_shape"
            }
            hex_command "ogrid $args"
            hex_command "mark_blocks unmark" 0
            if $around {
                foreach e [string trimright [hex_command $cmd] \n] {
                    set e1 [lindex $e 0]
                    set e2 [lindex $e 1]
                    if [info exists old_edges(params,$e1,$e2)] continue
                    set new_edges($e1,$e2) [string trimright [hex_command "edge_node_dim $e1 $e2"] \n]
                }
                foreach e [array names new_edges] {
                    set e1 [lindex [split $e ,] 0]
                    set e2 [lindex [split $e ,] 1]
                    set edim $new_edges($e)
                    set dim1 [lindex $edim 0]
                    set idx1 [lindex $edim 1]
                    foreach ee [array names old_edges dim,$e1,*] {
                        set e3 [lindex [split $ee ,] 1]
                        set e4 [lindex [split $ee ,] 2]
                        set edim $old_edges($ee)
                        set dim2 [lindex $edim 0]
                        set idx2 [lindex $edim 1]
                        if {($dim2 != $dim1) && ($idx2 != [expr $idx1 + 1])} continue
                        foreach eee [array names new_edges *,$e4] {
                            set e5 [lindex [split $eee ,] 0]
                            set e6 [lindex [split $eee ,] 1]
                            ic_hex_reset_edge_mesh $old_edges(params,$e3,$e4) $e1 $e2 $e5 $e6
                        }
                    }
                }
                catch { unset old_edges }
                catch { unset new_edges }
            }
             
            if $hex_option(check_inv) {
                aie_hex_check_fix_inverted
            }
            set markedBlock ""
            set Faces ""
            set Edges ""
            set Vertices ""
            hex_update_display
            get_indices 1
            mess "Ogrid block done\n" blue
            return
        }
	    2 {
	        set blocks ""
	        set blank ""
	        if {$splitBlkBlkSel2Val == 1 && $splitExtendGGVal == 0} {
	            foreach b [string trimright [ic_hex_list_blocking_parts] \n] {
	                if {$b == "VORFN"} continue
                    if $use_output_blocks {
                        append blocks "[string trimright [ic_hex_list_block_numbers $b output_blocks] \n] "
                    } else {
                        append blocks "[string trimright [ic_hex_list_block_numbers $b] \n] "
                    }
                }
	            foreach b $blocks {
	                if {[lsearch $markedBlock2 $b] >= 0} continue
	                append blank "$b "
	            }
	            if {$blank != ""} {
	                set display_flag(use_blanking) 1
	                hex_command "mark_blocks unmark"
	                block_mark_super $blank
	                hex_command "blank_blocks marked"
	            }
	        }
	        
	        if $splitExtendGGVal {
                hex_command mark_blocks
                set cmd "decimate_blocks "
                if $use_output_blocks { append cmd " output_blocks" }
                hex_command $cmd
                if $project {
                    hex_command "project_to_surface [volume_activename_string]"
                }
	        } else {
                splitBlkDEZ setclean
                set split_edge $ExtendEdge
                if {$split_edge == ""} return
                set split_n1 [ lindex $split_edge 0 ]
                set split_n2 [ lindex $split_edge 1 ]
                set cmd "index_from_edge $split_n1 $split_n2"
                if $use_output_blocks { append cmd " output_blocks" }
                set indices [hex_command $cmd]
                if {$indices == ""} {
                    mess "Not able to find proper direction\n"
                    return
                }
                set ind1 [lindex $indices 0]
                set ind2 [lindex $indices 1]
				set split_swept 0
				foreach blk $markedBlock2 {
					set type [string trimright [ic_hex_print_block_type_info $blk] \n]
					if {$type == "swept"} {	
						set split_swept 1 
						break
					}
				}
				if { $split_swept == 1 } {
					set cmd "extend_split nodes $split_n1 $split_n2"
				} else {
					set cmd "extend_split $ind1 $ind2 [range_string] m [volume_activename_string]"
					if $use_output_blocks { append cmd " output_blocks" }
					if $display_flag(use_blanking) { append cmd " -not_blanked" }
					if $project { append cmd " proj_split_vert" }
				}
				hex_command $cmd
				if $project {
					hex_command "project_to_surface  $ind1:$ind2,$ind2  [volume_activename_string]"
				}
				if {$blank != ""} {
					hex_command "unblank_blocks"
					set display_flag(use_blanking) 0
				}
	        }
	        get_indices 3
	        mess "Extend split done\n" blue
	        hex_update_display edge face block mesh	   
	        set ExtendEdge ""
	        return
	    }
        3 {
	        splitBlkDEZ setclean
		    if !$SelectionMethodVal {
		        if {$splitFace == ""} {
		            mess "No face to split selected\n" red
		            return
		        }
	            if {$splitFaceEdge == ""} return
	            set pos [lindex $splitFaceEdge 0]
	            set dim [lindex $splitFaceEdge 1]
	            # select the value on the edge
	            banner "Select location on the edge to split; $button_instructions"
	            set ::select_in_dynamics 0
	            tdv_set_key_command F9 select_hexa_toggle_dynamics
	            set cmd "select_value \{$pos\} $dim [volume_activename_string] [range_string]"     
	            if $display_flag(use_blanking) {
                    append cmd " -not_blanked"
	            }
	            append cmd " -face $splitFace"
	            if [catch {hex_command $cmd 1 1} res] {
	                banner ""
	                hex_command "select_value erase" 0 
	                aie_hex_delete_display_subset
	                return
	            }
	            set val [lindex $last_line 0]
	            banner ""
	            hex_command "select_value erase" 0 
	            if {$val != "" && $val != -1} {
                    if {[llength $splitFace] == 2} {
                        set first [ic_hex_vertex_ijk [lindex $splitFace 0]]
                        set second [ic_hex_vertex_ijk [lindex $splitFace 1]]
                        set face "\{ $first \} \{ $second \}"
                    } else {
                        set face "numbers $splitFace"
                    }
                    if [catch {eval ic_hex_split_face $face \{ $pos \} $dim $val [volume_activename_string]} res] {
                        mess "Splitting face \"${splitFace}\" failed: $res\n" red
                        aie_hex_delete_display_subset
                        return
                    }
	            } else {
	                aie_hex_delete_display_subset
	                return
	            }
	            aie_hex_delete_display_subset
	            get_indices 3
	            mess "Split face done\n" blue
		    } else {
		        if {([format %d [ic_hex_mesh_dimension]] == 3)} return
		        set split_enforcement 0.9
		        if {$split_enforcement == "" || $split_enforcement < 0.0 || $split_enforcement > 1.0} {
                    msg ERROR "Split enforcement must be >= 0.0 and <= 1.0"
                    return
		        }
		        set vertex ""
		        set num_faces [ic_hex_count_blocks mapped]
		        mess "Number of mapped faces before splitting: $num_faces\n"
		        ic_hex_undo_major_start "split_face_auto"
		        if {$splitFace == ""} {
                    mess "No face selected, trying to split all mapped faces\n" 
                    if [catch {eval ic_hex_split_face_auto "" $vertex [volume_activename_string] -tol_merge $split_enforcement} res] {
                        mess "Automatic split failed to split all mapped faces\n"
                    }
	                set num_faces2 [ic_hex_count_blocks mapped]
	                if {$num_faces2 > $num_faces} {
	                    mess "Number of mapped faces after splitting: $num_faces2\n"
	                }
	                mess "Automatic split done\n" blue
		        } else {
                    foreach f $splitFace {
                        set face "-numbers \{ $f \}"
                        if [catch {eval ic_hex_split_face_auto $face $vertex [volume_activename_string] -tol_merge $split_enforcement} res] {
                            mess "Automatic split of face \"$f\" failed\n"
                        } else {
	                        mess "Automatic split of face \"$f\" done\n" blue
	                    }
	                }
	                set num_faces2 [ic_hex_count_blocks mapped]
	                if {$num_faces2 > $num_faces} {
	                    mess "Number of mapped faces after splitting: $num_faces2\n"
	                }
                }
	            ic_hex_undo_major_end "split_face_auto"
		    }
	        hex_update_display vert edge face block mesh	
	        set splitFace ""
	        set splitFaceEdge ""
            return
        }
	    4 {
	        if {$splitVerts == ""} {
                msg ERROR "No vertex selected"
                return
	        }
	        foreach vert $splitVerts {
                hex_command "uncollapse_edge $vert"
	        }
	        get_indices 1
	        mess "Split vertices done\n" blue
	        set splitVerts ""
	        return
	    }
	    5 {
            if {$splitVerts == ""} {
                msg ERROR "No free block selected"
                return
            }
            if {([llength $splitVerts] != 2) && ([llength $splitVerts] != 4)} {
                msg ERROR "Please select 2/4 corner vertices of free block"
                return
            }
            ic_hex_undo_major_start "split_unstruct_block"
            if [catch {eval ic_hex_split_unstruct_block $splitVerts} res] {
                if [string match "*two splits*" $res] {
                    set mess "Face split failed because interior holes require two splits. Please select 4 verts to split multi loop free face"
                } else {
                    set mess [hex_trim_error $res]
                }
                msg ERROR $mess
            } else {
                mess "Split free face done\n" blue
            }
            ic_hex_undo_major_end "split_unstruct_block"
            set splitVerts ""
            get_indices 1
            hex_update_display edge face block mesh
            return
	    }
	    6 {
	        switch $ImprintMethodVal {
	            0 {  
	                # 2D Blocking
	                if {$splitVerts == ""} {
		                msg ERROR "No loop edges selected"
		                return
	                }
	                if {$sblock == ""} {
		                msg ERROR "No block selected"
		                return
	                }
	                set cmd "imprint_loop $sblock $splitVerts"
	                if $ImprintUnsBlkMethodVal {
	                    set vec ""
		                switch $ImprintUnsBlkEGVal {
			                0 { set vec "1 0 0"; set vec [list $vec] }
			                1 { set vec "0 1 0"; set vec [list $vec] }
			                2 { set vec "0 0 1"; set vec [list $vec] }
			                3 {
			                    if {$vecImprintList == "" || [llength $vecImprintList] != 2} {
			                        if {[llength $vecImprintList] == 1} {
			                            msg ERROR "Select two points or locations for imprint direction"
			                        } else {
			                            msg ERROR "Missing vector for imprint direction"
			                        }
		                            return
			                    }
			                    set vec "$vecImprintList"
			                }
			            }
			            if {$vec != ""} {
			                append cmd " -vector $vec"
			            }
	                }
	                set ret2 0   
	                ic_hex_undo_major_start "imprint_loop"
	                if [catch {hex_command $cmd} res] {
	                    mess "Error: imprint loop failed: $res\n" red
	                    set ret2 1
	                } else {
	                    mess "Imprint Loop (2D) done\n" blue
                    }
	                ic_hex_undo_major_end "imprint_loop"
	                if $ret2 return
	                set splitVerts ""
	                set sblock ""
	            }
	            1 {
	                # 3D Blocking
	                if {$splitVerts == ""} {
		                msg ERROR "No loop edges selected"
		                return
	                }
	                if {$iface == ""} {
		                msg ERROR "No face selected"
		                return
	                }
                    set cmd "imprint_loop $iface $splitVerts"
	                if $ImprintUnsBlkMethodVal {
	                    set vec ""
		                switch $ImprintUnsBlkEGVal {
			                0 { set vec "1 0 0"; set vec [list $vec] }
			                1 { set vec "0 1 0"; set vec [list $vec] }
			                2 { set vec "0 0 1"; set vec [list $vec] }
			                3 {
			                    if {$vecImprintList == "" || [llength $vecImprintList] != 2} {
			                        if {[llength $vecImprintList] == 1} {
			                            msg ERROR "Select two points or locations for imprint direction"
			                        } else {
			                            msg ERROR "Missing vector for imprint direction"
			                        }
		                            return
			                    }
			                    set vec "$vecImprintList"
			                }
			            }
			            if {$vec != ""} {
			                append cmd " -vector $vec"
			            }
	                }
	                set ret2 0
	                ic_hex_undo_major_start "imprint_loop"
	                if [catch {hex_command $cmd} res] {
	                    mess "Error: imprint failed: $res\n" red
	                    set ret2 1
	                } else {
	                    set num [string first "Warning:" $res]
                        if {$num > -1} {
                            mess "[string range $res $num end]\n" red
                        }
	                    mess "Imprint Loop (3D) done\n" blue
	                }
	                ic_hex_undo_major_end "imprint_loop"
	                if $ret2 return
	                set splitVerts ""
	                set iface ""
	                aie_hex_delete_display_subset
	            }
	        }
	        get_indices 1
	    }
	    7 {
            switch $SplitUnsBlk3dFMVal {
	            0 {
	            	# From edges
		            if {$ublock == ""} {
		                msg ERROR "No free block selected"
		                return
	                }	            
	                if {$splitSheets1 == ""} {
		                msg ERROR "No edges selected"
		                return
	                }
	                ic_hex_undo_major_start "split_unstruct_block3d"
	                if [catch {eval ic_hex_split_unstruct_block3d $ublock loop1 $splitSheets1} res] {
                        mess "ERROR: Split Free Block failed\n" red
	                } else {
	                    mess "Split Free Block done\n" blue 
	                }
	                ic_hex_undo_major_end "split_unstruct_block3d"
	                set splitSheets1 ""
	                set ublock ""
	            }
	            1 {
	                # By imprint
		            if {$iFace == ""} {
		                msg ERROR "No target faces selected"
		                return
	                }
	                if {$edgesProj == ""} {
		                msg ERROR "No edges selected"
		                return
	                }
	                set cmd "imprint_loop $iFace $edgesProj -convert -split"
	                if $SplitUnsBlk3dMethodVal {
	                    set vec ""
		                switch $SplitUnsBlk3dEGVal {
			                0 { set vec "1 0 0"; set vec [list $vec] }
			                1 { set vec "0 1 0"; set vec [list $vec] }
			                2 { set vec "0 0 1"; set vec [list $vec] }
			                3 {
			                    if {$vecImprintList == "" || [llength $vecImprintList] != 2} {
			                    	if {[llength $vecImprintList] == 1} {
			                            msg ERROR "Select two points or locations for imprint direction"
			                        } else {
			                            msg ERROR "Missing vector for imprint direction"
			                        }
		                            return
			                    }
			                    set vec "$vecImprintList"
			                }
			            }
			            if {$vec != ""} {
			                append cmd " -vector $vec"
			            }
			        }
			        set ret2 0
			        ic_hex_undo_major_start "imprint_loop"
	                if [catch {hex_command $cmd} res] {
                        mess "[hex_trim_error $res]\n" red
                        mess "Error: split block by imprint failed\n" red
                        set ret2 1
	                } else {
	                    set num [string first "Warning:" $res]
                        if {$num > -1} {
                            mess "[string range $res $num end]\n" red
                        }
                        mess "Split Free Block by imprint done\n" blue
	                }
	                ic_hex_undo_major_end "imprint_loop"
	                if $ret2 return
	                set iFace ""
	                set edgesProj ""
	                aie_hex_delete_display_subset
	            }
	            2 {
	                # Blend across loops
	                if {$SplitUnsBlk3dOutputVal == 0} {
	                    set dim [format %d [ic_hex_mesh_dimension]]
	                    if {$dim < 3} {
	                        mess "Only available for a 3D blocking\n" red
	                        return
	                    }
	                    set face1 "mapped"; set face2 "mapped"
	                    # Blend across loops (From Faces)
		                if {$uFace1 == ""} {
		                    msg ERROR "No 1st face selected"
		                    return
	                    } else {
                            if {[lindex [lindex $uFace1 0] end] == "u"} {
                                set face1 free
                            }
	                    }
	                    if {$uFace2 == ""} {
		                    msg ERROR "No 2nd face selected"
		                    return
	                    } else {
                            if {[lindex [lindex $uFace2 0] end] == "u"} {
                                set face2 free 
	                        }
	                    }
	                    if {$face1 == "free" && $face2 == "free"} {
	                        set ret2 0
	                        ic_hex_undo_major_start "create_swept_block"
	                        if [catch {eval ic_hex_create_swept_block $uFace1 $uFace2} res] {
                                mess "Error: Split Free Block failed\n" red
                                set ret2 1
	                        } else {
                                mess "Split Free Block done\n" blue
	                        }
	                        ic_hex_undo_major_end "create_swept_block"
	                        if $ret2 return
	                    } elseif {$face1 == "mapped" && $face2 == "mapped"} {
	                        set face_verts "$uFace1 $uFace2"
	                        set face_verts [join $face_verts]
	                        set fam [lindex [ic_hex_list_block_families_without] 0]
	                        set ret2 0
	                        ic_hex_undo_major_start "create_block"
	                        if [catch {eval ic_hex_create_block $fam $face_verts best_fit [volume_activename_string]} res] {
                                mess "Error: Split Free Block failed\n" red
                                set ret2 1
	                        } else {
                                mess "Split Free Block done\n" blue
	                        }
	                        ic_hex_undo_major_end "create_block"
	                        if $ret2 return
	                    } else {
	                        mess "Error: don't mix free and mapped faces to split the free block\n" red
	                        return
	                    }
	                    set uFace1 ""
	                    set uFace2 ""	                    
	                } else {
	                     # Blend across loops (From edges)
		                if {$ublock == ""} {
		                    msg ERROR "No free block selected"
		                    return
	                    }	            
	                    if {$splitSheets1 == ""} {
		                    msg ERROR "No first set of edge loops selected"
		                    return
	                    }
	                    if {$splitSheets2 == ""} {
		                    msg ERROR "No second set of edge loops selected"
		                    return
	                    }
	                    set ret2 0
	                    ic_hex_undo_major_start "split_unstruct_block3d"
	                    if [catch {eval ic_hex_split_unstruct_block3d $ublock loop1 $splitSheets1 loop2 $splitSheets2 -convert} res] {
                            mess "ERROR: Split Free Block failed\n" red
                            set ret2 1
	                    } else {
	                        mess "Split Free Block by edge loops done\n" blue 
	                    }
	                    ic_hex_undo_major_end "split_unstruct_block3d"
	                    if $ret2 return
	                    set splitSheets1 ""
	                    set splitSheets2 ""
	                    set ublock ""	                
	                }
	            }
	            3 {
	                # From sheets
		            if {$ublock == ""} {
		                msg ERROR "No free block selected"
		                return
	                }
	                if {$splitSheets == ""} {
		                msg ERROR "No split sheets selected"
		                return
	                }
	                ic_hex_undo_major_start "split_unstruct_block3d"
	                if [catch {eval ic_hex_split_unstruct_block3d $ublock by_sheets $splitSheets} res] {
                        mess "ERROR: Split Free Block failed\n" red
	                } else {
                        mess "Split Free Block from sheets done\n" blue
	                }
	                ic_hex_undo_major_end "split_unstruct_block3d"
	                set splitSheets ""
	                set ublock ""	            
	            }
	        }
	    }
	    8 {
	        if {$sblock == ""} {
                msg ERROR "No free face selected"
                return
	        }	            
	        if {$conEdges == ""} {
                msg ERROR "No edges selected"
                return
	        }
            ic_hex_undo_major_start "connect_edges"
	        if [catch {eval ic_hex_connect_edges $sblock $conEdges} res] {
                mess "Error: block connections failed: $res\n" red
	        } else {
                mess "Done block connections\n" blue 
	        }
	        ic_hex_undo_major_end "connect_edges"
	        set conEdges ""
	        set sblock ""
        }
    }

    if [aie_hex_sketching_mode] {
        ic_hex_sketch_unset_projections
    }

    get_indices 3
    hex_update_display
    index_update_all
}

proc aie_hex_split_display_edge_bunching {{edge ""}} {

    if ![splitBlkDEZ get copy_from_parallel] return
    if {$edge != ""} {
	    set opts [display_edge_mesh_params]
	    set cmd "display_edge_mesh $opts selected_bunching"
	    append cmd " highlight"
	    append cmd " parallel"
	    append cmd " [lindex $edge 0] [lindex $edge 1]"
	    hex_command $cmd
    } else {
	    hex_update_display edge
    }
}

########################### delete blocking ###########################################

proc ondeleteBlockDEZLoad {} {
    global beta_mode
    
    if ![info exists ::vid_options(DelBlkPerFlag)] {
        set ::vid_options(DelBlkPerFlag) 0
    }
    set delBlocks ""
    if $beta_mode {
        set delEdges ""
        set delVertices ""
        set deleteBlockEGVal 0
    }
}

proc ondeleteBlockDEZAfterLoad {} {
    if $auto_pick_mode { deleteBlkPick pick }
}

proc ondeleteBlkPickFinish {} {
    global auto_pick_mode

    if {$auto_pick_mode && ($delBlocks != "")} {
        deleteBlockDEZ apply
        deleteBlkPick pick
    }
}

proc ondeleteBlockDEZOK {} {
    global use_output_blocks display_flag beta_mode

    if $beta_mode {
        set val $deleteBlockEGVal
    } else {
        set val 0
    }
    switch $val  {
        0 {
            if {$delBlocks == ""} return
            if !$::vid_options(DelBlkPerFlag) {
                aie_hex_update_index_form 1
                aie_change_part_blocks $delBlocks VORFN
                mess "Block(s): $delBlocks moved to VORFN\n" blue
            } else {
                ic_hex_undo_major_start "delete_blocks"
                set cmd "delete_blocks numbers $delBlocks"
                if $use_output_blocks { append cmd " output_blocks" }
                hex_command $cmd    
                mess "Block(s): $delBlocks deleted permanently\n" blue
                ic_hex_undo_major_end "delete_blocks"
            }
            set delBlocks ""
        }
        1 {
            if {$delVertices == ""} return
            set deleted ""
            foreach v $delVertices {
                if [catch {eval ic_hex_delete_node_on_edge $v use_egde_bunching} res] {
                    mess "Skipped vertex $v: $res\n" red
                    continue
                } else {
                    append deleted " $v"
                }
            }
            if {$deleted != ""} {
                mess "Vertices: $deleted vertices deleted\n" blue
                foreach curve [ic_geo_get_objects curve] {
                    ic_redraw_geometry curve $curve
                }
            }
            set delVertices ""
        }
    }
    
    if [aie_hex_sketching_mode] {
        ic_hex_sketch_unset_projections
    }
    get_indices 0
    hex_update_display
    index_update_all
    if !$::vid_options(DelBlkPerFlag) {
        aie_hex_update_index_form 0
    }
    aie_delete_empty_parts
}

########################### modify blocking ###########################################

proc oneditBlockMenuDEZLoad {} {
    global merge_faces icon_size1
    
    if {$periodicBlkMVal == ""} {
        set periodicBlkMVal 0
    }
    if {$joinBlockGGVal == ""} {
        set joinBlockGGVal 0
    }
    if {![info exists editBlockIJKHowVal] || $editBlockIJKHowVal == ""} {
        set editBlockIJKHowVal 0
	    if {[ic_hex_mesh_dimension] == 2} {
	        set convBlockTypeVal 1
	    } else {
	        set convBlockTypeVal 2
	    }
    }
    
    if ![info exists meshTypeList] {
        set meshTypeList {"Tetra-Delaunay" "Tetra-Adv.Front" "Hexa-Core" "Hexa-Dominant" "TGrid"}
    }

    if ![info exists sbmeshTypeList] {
        set sbmeshTypeList [array names quad_types]
    }

    if {![info exists sbmesh_type] || $sbmesh_type == ""} { set sbmesh_type "Quad w/one Tri" }

    set joinBlocks ""
    set transferBlocks ""
    set refDirEdge ""
    set merge_faces ""
    set joinFaceBlocks ""
    set freeBlockFaceFreeTypeMappedMethodVal 0
}

proc oneditBlockMenuDEZUnLoad {} {
    
    aie_hex_delete_display_subset
    aie_hex_display_marked_blocks
    if {[trace vinfo joinBlockGGVal] != ""} {
        trace vdelete joinBlockGGVal w aie_hex_trace_ijk_joinblock
    }
    if {[trace vinfo freeBlockFaceFreeTypeMappedMethodVal] != ""} {
        trace vdelete freeBlockFaceFreeTypeMappedMethodVal w aie_hex_trace_free_block_face
    }
}

proc oneditBlockMenuDEZAfterLoad {} {
    
    if {[trace vinfo joinBlockGGVal] != ""} {
        trace vdelete joinBlockGGVal w aie_hex_trace_ijk_joinblock
    }
    trace variable joinBlockGGVal w aie_hex_trace_ijk_joinblock
    aie_hex_trace_ijk_joinblock "" "" ""
    if {[trace vinfo freeBlockFaceFreeTypeMappedMethodVal] != ""} {
        trace vdelete freeBlockFaceFreeTypeMappedMethodVal w aie_hex_trace_free_block_face
    }
    trace variable freeBlockFaceFreeTypeMappedMethodVal w aie_hex_trace_free_block_face
    aie_hex_trace_free_block_face "" "" ""

}

proc onconvertBlocksLoad {} {
    editBlockMenuDEZ convertBlocksPick
}

proc onconvertBlocksUnLoad {} {
    aie_hex_delete_display_subset
    aie_hex_display_marked_blocks
}

proc convertBlocksPick {} {
    if $auto_pick_mode {
        switch $convBlockTypeVal {
	        0 { convertBlocksPick1 pick }
	        1 { convertBlocksPick2 pick }
	        2 { convertBlocksFacePick pick }
	        3 { convertBlocksPick4 pick }
	        4 { convertBlocksPick5 pick }
        }
    }
}

proc onsetUBlockMeshTypeLoad {} {
    if ![info exists meshTypeList] {
        set meshTypeList {"Tetra-Delaunay" "Tetra-Adv.Front" "Hexa-Core" "Hexa-Dominant" "TGrid"}
    }
    if {$mesh_type == ""} {
        set mesh_type "Tetra-Delaunay"
    }
}

proc onconvertBlocksPick1Finish {} {   
    if {$convBlocks != "" && $auto_pick_mode} {
        editBlockMenuDEZ apply
        editBlockMenuDEZ convertBlocksPick
    }
}

proc onconvertBlocksPick2Finish {} {   
    if {$convBlocks != "" && $auto_pick_mode} {
        editBlockMenuDEZ apply
        editBlockMenuDEZ convertBlocksPick
    }
}

proc onconvertBlocksPick3Finish {} {
    global select_action

    set mesh_dim [format %d [ic_hex_mesh_dimension]]
    if {$mesh_dim != 3} {
        msg ERROR "Can not set block to swept type in 2D"
        return
    }
   
    set convBlocks ""
    while 1 {
	set blk [select_hexa block 1 "Please select block to set type / apply"]
	if { $blk == "" } break
	
	set edge [select_hexa edge 1 "Please select edge for swept direction" new_format]
	if { $edge == "" } break
        lappend convBlocks "$blk [lindex $edge 0] [lindex $edge 1]"
    }
   
    if {$select_action == "done" && $convBlocks != "" && $auto_pick_mode} {
        editBlockMenuDEZ apply
        editBlockMenuDEZ convertBlocksPick
    }
}

proc onconvertBlocksPick4Finish {} {   
    if {$convBlocks != "" && $auto_pick_mode} {
        editBlockMenuDEZ apply
        editBlockMenuDEZ convertBlocksPick
    }
}

proc onconvertBlocksPick5Finish {} {   
    if {$convBlocks != "" && $auto_pick_mode} {
        editBlockMenuDEZ apply
        editBlockMenuDEZ convertBlocksPick
    }
}

proc oneditBlockIJKLoad {} {   
    foreach v {I J K} {
        setBlockIJKMS select "Set $v" $v
    }
    if $auto_pick_mode {
        switch $editBlockIJKHowVal {
            0 {editBlockIJKM1Pick pick}
            1 {editBlockIJKM2Pick pick}
            2 {editBlockIJKM3Pick pick}
            3 {editBlockSetIJKPick pick}
        }
    }   
}

proc oneditBlockIJKM1PickFinish {} {
    if {$blocks != "" && $auto_pick_mode} {
        editBlockMenuDEZ apply
        editBlockIJKM1Pick pick
    }
}

proc oneditBlockIJKM2PickFinish {} {
    if {$blocks != "" && $auto_pick_mode} {
        editBlockVertexPick pick
        if {$vert != ""} {
            editBlockMenuDEZ apply
            editBlockIJKM2Pick pick
        }
    }
}

proc oneditBlockIJKM3PickFinish {} {
    if {$blocks != "" && $auto_pick_mode} {
        editBlockMenuDEZ apply
        editBlockIJKM3Pick pick
    }
}

proc oneditBlockRenumberLoad {} {
    editBlockMenuDEZ setclean
    aie_renumber_blocks
    set editBlkmainVal -1
    editBlockMenuDEZ setclean
}

proc onperiodicBlkBLoad {} {
    if $auto_pick_mode {
        switch $periodicBlkMVal {
            0 { periodicVertsPick pick }
            1 { periodicVertsPick2 pick }
        }
    }
}

proc onperiodicVertsPickFinish {} {
    if {$auto_pick_mode && $perVerts != ""} {
        editBlockMenuDEZ apply
        editBlockMenuDEZ onperiodicBlkBLoad
    }
}

proc onperiodicVertsPick2Finish {} {
    if {$auto_pick_mode && $perVerts != ""} {
        editBlockMenuDEZ apply
        editBlockMenuDEZ onperiodicBlkBLoad
    }
}

proc onjoinBlockMethodLoad {} {
    if {$auto_pick_mode && $joinBlockGGVal == 0} {
        joinBlocksPick pick
    }
}

proc onjoinBlockMethodUnLoad {} {
    hex_update_display
}

proc onjoinBlocksPickFinish {} {
    if {$auto_pick_mode && $joinBlocks != "" && $joinBlockGGVal == 0} {
        editBlockMenuDEZ apply
        joinBlocksPick pick
    }
    if {$auto_pick_mode && $joinBlocks != "" && $joinBlockGGVal == 2} {
        joinBlockDirPick pick
    }
}

proc onjoinBlockFaceLoad {} {
    if $auto_pick_mode {
        joinFacesPick pick
    }
}

proc onjoinFacesPickFinish {} {
    if {$auto_pick_mode && $joinFaceCorners != ""} {
        editBlockMenuDEZ apply
        joinFacesPick pick
    }
}

proc onconvertBlocksFacePickFinish {} {
    if {$auto_pick_mode && $swept_face != ""} {
        editBlockMenuDEZ apply
        convertBlocksFacePick pick
    }
}

proc onconvertFreeBlocksFaceFreePickFinish {} {
    if {$auto_pick_mode && $mapped_face != ""} {
        editBlockMenuDEZ apply
        convertFreeBlocksFaceFreePick pick
    }
}

proc onreverseSBlockPickFinish {} {
    if {$auto_pick_mode && $sblock != ""} {
        editBlockMenuDEZ apply
        reverseSBlockPick pick
    }
}

proc onjoinBlockDirPickPick {} {
    global display_flag unset_display_flag
    
    if !$display_flag(block) {
        set display_flag(block) 1
        set unset_display_flag(block) 1
    }
    
    set display_flag(block_ijk) 1
    hex_update_display block
}

proc onjoinBlockDirPickFinish {} {
    global use_output_blocks merge_faces display_flag unset_display_flag auto_pick_mode

    if [info exists unset_display_flag(block)] {
        set display_flag(block) 0
        unset unset_display_flag(block)
    }
    set display_flag(block_ijk) 0
    hex_update_display block
    if {$refDirEdge == ""} return
    set n1 [lindex $refDirEdge 0]
    set n2 [lindex $refDirEdge 1]
    set edim [string trimright [ic_hex_edge_node_dim $n1 $n2] \n]
    set dim [lindex $edim 0]
    if {$dim < 3 && $dim > -1} {
        mess "Merge blocks direction -> [lindex {I J K} $dim]\n" blue
    } else {
        mess "Select non ogrid edge for merge direction\n" red
        set refDirEdge ""
        return
    }
    if {$joinBlocks == ""} {
        mess "Blocks selection is empty, so selecting all blocks for merging in IJK direction\n"
    }
    mess "Detecting blocks in [lindex {I J K} $dim] direction..."
    busy 1
    if $use_output_blocks {
        set merge_planes [ic_hex_get_super_faces_in_plane output_blocks $n1 $n2]
    } else {
        set merge_planes [ic_hex_get_super_faces_in_plane $n1 $n2]
    }
    set merge_faces ""
    catch { array unset found }
    foreach f $merge_planes {
        if [lindex $f 4] {
            set n1 [lindex $f 0]; set n2 [lindex $f 1]; set n3 [lindex $f 2]; set n4 [lindex $f 3]
            set blocks [string trim [string trimright [ic_hex_get_face_blocks $n1 $n2 $n3 $n4] \n]]
            if {[llength $blocks] != 2} continue
            set b1 [lindex $blocks 0]; set b2 [lindex $blocks 1]
            if {$joinBlocks != ""} {
                if {[lsearch "$joinBlocks" "$b1"] < 0 || [lsearch "$joinBlocks" "$b2"] < 0} continue
            }
            set found($b1) 1
            set found($b2) 1
            if {[lsearch "$merge_faces" " [lrange $f 0 3] "] < 0} {
               lappend merge_faces " [lrange $f 0 3] "
            }
        }
    }
    mess "done\n"
    busy 0
    if ![array size found] {
        mess "Found [array size found] blocks in [lindex {I J K} $dim] direction to merge; select another IJK direction\n" red
        return
    } else {
        mess "Found [array size found] blocks in [lindex {I J K} $dim] direction to merge\n" blue
    }
    if !$auto_pick_mode return
    editBlockMenuDEZ apply
}

proc ontransferBlockMethodLoad {} {
    if {$auto_pick_mode} {
        transferBlocksPick pick
    }
}

proc ontransferBlockMethodUnLoad {} {
    hex_update_display
}

proc ontransferBlocksPickFinish {} {
    if {$auto_pick_mode && $transferBlocks != ""} {
        editBlockMenuDEZ apply
        transferBlocksPick pick
    }
}

proc aie_hex_trace_ijk_joinblock {{name ""} {element ""} {op ""}} {
    if {[editBlockMenuDEZ get joinBlockGGVal] != 2} return
    
     if ![ic_hex_get_block_type_number mapped] {
        mess "The blocking contains no mapped blocks\n" red
        after 100 {
            ::AIEnv::GUIManagement::ToggleGrey joinBlocksPick 1
            ::AIEnv::GUIManagement::ToggleGrey joinBlockDir 1
        } 
        return
    }
    
    if {[format %d [ic_hex_mesh_dimension]] != 3} {
        mess "Can not merge blocks by IJK direction in 2D\n" red
        after 100 {
            ::AIEnv::GUIManagement::ToggleGrey joinBlocksPick 1
            ::AIEnv::GUIManagement::ToggleGrey joinBlockDir 1
        }
    } else {
        after 100 { 
            ::AIEnv::GUIManagement::ToggleGrey joinBlocksPick 0
            ::AIEnv::GUIManagement::ToggleGrey joinBlockDir 0
        } 
    }
}

proc aie_hex_trace_free_block_face {{name ""} {element ""} {op ""}} {
    global icon_size1
    
    if {[editBlockMenuDEZ get convBlockTypeVal] != "5"} return

    if {[format %d [ic_hex_mesh_dimension]] == "2"} {
        aie_reset_picker "" joinFacesPick2 label "2D Block" helptext "Select the blocks" image "select_blocks$icon_size1.gif" 
        if {[editBlockMenuDEZ get freeBlockFaceFreeTypeMappedMethodVal] == 0} {
            aie_reset_picker "" convertFreeBlocksFaceFreeMappedPick label "2D Block(s)" helptext "Select the 2D block(s)" image "select_blocks$icon_size1.gif" 
        } else {
            aie_reset_picker "" convertFreeBlocksFaceFreeMappedPick2 label "2D Block" helptext "Select the 2D block" image "select_blocks$icon_size1.gif" 
        }
    } else {
        aie_reset_picker "" joinFacesPick2 label "Block Faces" helptext "Select the block faces" image "select_face$icon_size1.gif"
        if {[editBlockMenuDEZ get freeBlockFaceFreeTypeMappedMethodVal] == 0} {
            aie_reset_picker "" convertFreeBlocksFaceFreeMappedPick label "Face(s)" helptext "Select the free face(s)" image "select_face$icon_size1.gif"
        } else {
            aie_reset_picker "" convertFreeBlocksFaceFreeMappedPick2 label "Face" helptext "Select the free face" image "select_face$icon_size1.gif"
        }
    }
}

proc onjoinFacesPick2Pick {} {
    global cancel_picker_now

    catch { unset ::cancel_picker_now }
    if {[editBlockMenuDEZ get joinBlockFaceFaceVal] != "1"} return
    if {[format %d [ic_hex_mesh_dimension]] == "3"} return
    editBlockMenuDEZ set joinFaceBlocks [select_hexa block 0 "Select the blocks"]
    set ::cancel_picker_now 1
    onjoinFacesPick2Finish
}

proc onjoinFacesPick2Finish {} {
    global auto_pick_mode
    
    if {[editBlockMenuDEZ get joinBlockFaceFaceVal] != "1"} return
    if {[format %d [ic_hex_mesh_dimension]] != "3"} {   
        if {$auto_pick_mode && [editBlockMenuDEZ get joinFaceBlocks] != ""} {
            editBlockMenuDEZ apply
            joinFacesPick2 pick
        }
        return
    }
    if {$auto_pick_mode && $joinFaceBlocks != ""} {
        editBlockMenuDEZ apply
        joinFacesPick2 pick
    }
}

proc onconvertFreeBlocksFaceFreeMappedPickPick {} {
    global cancel_picker_now auto_pick_mode

    catch { unset ::cancel_picker_now }
    if {[editBlockMenuDEZ get convBlockTypeVal] != "5"} return
    aie_hex_delete_display_subset
    if {[format %d [ic_hex_mesh_dimension]] == "3"} return
    
    aie_hex_display_marked_blocks
    editBlockMenuDEZ set mapped_face [select_hexa block 0 "Select the 2D block(s) to convert" "only_free"]
    set ::cancel_picker_now 1
    set f [editBlockMenuDEZ get mapped_face]
    if {$f == ""} return
    
    aie_hex_display_marked_blocks $f
    set ::cancel_picker_now 1
    if !$auto_pick_mode return
    
    editBlockMenuDEZ apply
    onconvertFreeBlocksFaceFreeMappedPickPick
}

proc onconvertFreeBlocksFaceFreeMappedPick2Pick {} {
    global cancel_picker_now auto_pick_mode 

    catch { unset ::cancel_picker_now }
    if {[editBlockMenuDEZ get convBlockTypeVal] != "5"} return
    aie_hex_delete_display_subset
    if {[format %d [ic_hex_mesh_dimension]] == "3"} return
    
    aie_hex_display_marked_blocks
    editBlockMenuDEZ set mapped_face [select_hexa block 1 "Select the 2D block to convert" "only_free"]
    set ::cancel_picker_now 1
    set f [editBlockMenuDEZ get mapped_face]
    if {$f == ""} return
    set vertsFromBlock ""
    foreach v [string trimright [ic_hex_print_sblock_info $f] \n] {
        if {$v == "loop"} { set skip 1; continue }
        if [info exists skip] { unset skip; continue }
        if [string is integer -strict $v] {
            append vertsFromBlock " $v"
        }
    }
    if {$vertsFromBlock != ""} {
        mess "Please select the 4 corner vertices from vertices \"$vertsFromBlock\"\n"
    } 

    aie_hex_display_marked_blocks $f
    if !$auto_pick_mode return
    
    editBlockMenuDEZ set vertsFree [select_hexa vertex 4 "Select the 4 corner vertices" "node_numbers"]
    set ::cancel_picker_now 1
    if {[editBlockMenuDEZ get vertsFree] == ""} return
    foreach v [editBlockMenuDEZ get vertsFree] {
        if {[lsearch $vertsFromBlock $v] < 0} {
            mess "Error: vertex $v is not a corner vertex of 2D block $f\n" red
            return
        }
    }
    editBlockMenuDEZ apply
    onconvertFreeBlocksFaceFreeMappedPick2Pick
}

proc onconvertFreeBlocksFaceFreeMappedPickFinish {} {
    global auto_pick_mode

    if {[editBlockMenuDEZ get convBlockTypeVal] != "5"} return 
    set f [editBlockMenuDEZ get mapped_face]
    if {$f == ""} return
    
    if {[format %d [ic_hex_mesh_dimension]] != "3"} {
        aie_hex_display_marked_blocks $f
    } else {
        aie_hex_create_display_subset face $f 
    }
    
    if !$auto_pick_mode return
    editBlockMenuDEZ apply
    convertFreeBlocksFaceFreeMappedPick pick
}

proc onconvertFreeBlocksFaceFreeMappedPick2Finish {} {
    global auto_pick_mode

    if {[editBlockMenuDEZ get convBlockTypeVal] != "5"} return   
    set f [editBlockMenuDEZ get mapped_face]
    if {$f == ""} return
    
    if {[format %d [ic_hex_mesh_dimension]] != "3"} {
        aie_hex_display_marked_blocks $f
    } else {
        aie_hex_create_display_subset face $f
    }
    if !$auto_pick_mode return
    convertFreeBlocksNodesMappedPick pick
}

proc onconvertFreeBlocksNodesMappedPickPick {} {
    global auto_pick_mode

    if {[editBlockMenuDEZ get convBlockTypeVal] != "5"} return
    if {[format %d [ic_hex_mesh_dimension]] == "3"} return
    if {$auto_pick_mode && [editBlockMenuDEZ get mapped_face] != ""} {
        
    }
}

proc onconvertFreeBlocksNodesMappedPickFinish {} {
    global auto_pick_mode

    if {[editBlockMenuDEZ get convBlockTypeVal] != "5"} return
    if !$auto_pick_mode return

    if {[editBlockMenuDEZ get mapped_face] != "" && [editBlockMenuDEZ get vertsFree] != ""} {
        editBlockMenuDEZ apply
        convertFreeBlocksFaceFreeMappedPick2 pick
    }
}

proc onjoinBlockFaceUnload {} {
}

proc oneditBlockMenuDEZOK {} {
    global fam_visible use_output_blocks merge_faces index_form beta_mode

    switch $editBlkmainVal {
        0 { # Merge blocks
            if $use_output_blocks {
                set blks_before [eval ic_hex_get_block_families_and_types [volume_activename_string] output_blocks]
            } else {
                set blks_before [eval ic_hex_get_block_families_and_types [volume_activename_string]]
            }
            mess "Number of blocks before merging: [llength $blks_before]\n"
            aie_hex_update_index_form 1
            switch $joinBlockGGVal {
                0 {
                    set mesh_dim [format %d [ic_hex_mesh_dimension]]
                    if {$mesh_dim != 2} {
                        set num_blocks [llength $joinBlocks]
                        if {$num_blocks < 2} {
                            msg ERROR "Please select two or more blocks"
                            return
                        }
                        set free_blocks 0
                        set mapped_blocks 0
                        set swept_blocks 0
                        foreach b $joinBlocks {
                            set btype [aie_hex_get_block_type $b]
                            incr ${btype}_blocks
                        }
                        if {($free_blocks > 0) && ($free_blocks != $num_blocks)} {
                            msg ERROR "Please don't mix free with swept or mapped blocks."
                            return
                        } else {
                            switch $btype {
                                free  {
                                    set cmd "merge_blocks $joinBlocks"
                                    ic_hex_undo_major_start "merge_blocks"
                                    if [catch {hex_command $cmd} res] {
                                        msg ERROR "Merge failed"
                                    }
                                    ic_hex_undo_major_end "merge_blocks"
                                }
                                mapped - swept {
                                    set cmd "merge_blocks $joinBlocks -version 51"
                                    ic_hex_undo_major_start "merge_blocks"
                                    if $use_output_blocks { append cmd " output_blocks" }
                                    if {($mapped_blocks > 0) && ($swept_blocks > 0)} { append cmd " mapped_swept" }
                                    if [catch {hex_command $cmd} res] {
                                        msg ERROR "Merge failed"
                                    }
                                    ic_hex_undo_major_end "merge_blocks"
                                }
                            }
                        }
                    } else {
                        set num_blocks [llength $joinBlocks]
                        if {$num_blocks < 2} {
                            msg ERROR "Please select two or more blocks"
                            return
                        }
                        set cmd "merge_blocks $joinBlocks -version 51"
                        ic_hex_undo_major_start "merge_blocks"
                        if $use_output_blocks { append cmd " output_blocks" }
                        if [catch {hex_command $cmd} res] {
                            msg ERROR "Merge failed"
                        }
                        ic_hex_undo_major_end "merge_blocks"
                    }
                }
                1 {
                    # VORFN reqd to remove face splits - ONYX #34225
                    set vfams [volume_activename_string]
                    if {[lsearch $vfams VORFN] < 0} {
                        lappend vfams VORFN
                    }
                    ic_hex_undo_major_start "auto_merge"
                    set cmd "auto_merge $vfams"
                    if $use_output_blocks { append cmd " output_blocks" }
                    if [catch {hex_command $cmd} res] {
                        msg ERROR "Merge failed" $res"
                    }
                    ic_hex_undo_major_end "auto_merge"
                }
                2 {
                    if {$merge_faces == ""} {
                        mess "No blocks to merge in ijk direction found\n" red
                        return
                    }
                    busy 1
                    set version 51
                    ic_hex_undo_major_start "merge_blocks"
                    foreach f $merge_faces {
                        set n1 [lindex $f 0]; set n2 [lindex $f 1]; set n3 [lindex $f 2]; set n4 [lindex $f 3]
                        set blocks [string trim [string trimright [ic_hex_get_face_blocks $n1 $n2 $n3 $n4] \n]]
                        set ignore 0
                        if {[llength $blocks] == 2} {
                            foreach "b1 b2" $blocks {
                                if {[aie_hex_get_block_type $b1] == "swept" || [aie_hex_get_block_type $b2] == "swept"} {
                                    set ignore 1
                                }
                            }
                            if $ignore continue
                            if $use_output_blocks {
                                if [catch {eval ic_hex_merge_blocks output_blocks "$blocks" -version $version} res] {
                                    msg ERROR "Merge of block [lindex $blocks 0] and block [lindex $blocks 1] failed: $res"
                                }
                            } else {
                                if [catch {eval ic_hex_merge_blocks "$blocks" -version $version} res] {
                                    msg ERROR "Merge of block [lindex $blocks 0] and block [lindex $blocks 1] failed: $res"
                                }
                            }
                        }
                    }
                    ic_hex_undo_major_end "merge_blocks"
                    set refDirEdge ""
                    set merge_faces ""
                    busy 0
                }
            }
            if $use_output_blocks {
                set blks_after [eval ic_hex_get_block_families_and_types [volume_activename_string] output_blocks]
            } else {
                set blks_after [eval ic_hex_get_block_families_and_types [volume_activename_string]]
            }
            mess "Number of blocks after merging: [llength $blks_after]\n"
            if {$blks_before == $blks_after} {
                mess "Merge blocks failed\n" red
            } else {
                mess "Merge blocks done\n" blue
            }
            set joinBlocks ""
        }
        1 {
             if {$joinBlockFaceFaceVal == 0} {
                if {[llength $joinFaceCorners] != 2} {
                    msg ERROR "Please select two block corners"
                    return
                }
                set first [ic_hex_vertex_ijk [lindex $joinFaceCorners 0]]
                set second [ic_hex_vertex_ijk [lindex $joinFaceCorners 1]]
                ic_hex_undo_major_start "merge_face"
                if [catch {hex_command "merge_face \{ $first \} \{ $second \}"} res] {
                    ic_hex_undo_major_end "merge_face"
                    set joinFaceCorners ""
                    return
                }
            } else {
                if {[llength $joinFaceBlocks] <= 1} {
                    if {[format %d [ic_hex_mesh_dimension]] == "2"} {
                        msg ERROR "Please select two or more blocks"
                    } else {
                        msg ERROR "Please select two or more blocks faces"
                    }
                    set joinFaceBlocks ""
                    return
                }
                ic_hex_undo_major_start "merge_face"
                if [catch {hex_command "merge_face -faces $joinFaceBlocks"} res] {
                    ic_hex_undo_major_end "merge_face"
                    msg ERROR "Merge failed"
                    return
                }
            }
            ic_hex_undo_major_end "merge_face"
            set joinFaceCorners ""
            set joinFaceBlocks ""
            mess "Merge faces done\n" blue
        }
        2 { # Rescale Ogrid
            switch $modOgridEGVal {
                0 {
                    if {$OEdge == ""} {
                        msg ERROR "No rescale direction specified"
                        return
                    }
                    if {$distance == ""} {
                        msg ERROR "No rescale value specified"
                        return
                    }
                    foreach i {0 1 2} {
                        set rescale_[lindex {vert dir ind} $i] [lindex $OEdge $i]
                    }
                    set cmd "rescale_ogrid $rescale_dir $rescale_ind $distance"
                    if $rescaleOBlkSelVal {
                        hex_command "mark_blocks unmark"
                        block_mark_super $rescaleBlks
                        append cmd " only_marked"
                    }
                    append cmd " [range_string] m [volume_activename_string]"
                    if $absolute { append cmd " abs" }
                    hex_command $cmd
                }
                1 {
                    if {$resetOgridEdge == ""} {
                        msg ERROR "No edge selected to reset Ogrid orthogonality"
                        return
                    }
                    set t1 [lindex $resetOgridEdge 0]
                    set t2 [lindex $resetOgridEdge 1]
                    set cmd "reset_ogrid_orthogonality $t1 $t2 [range_string] [family_activename_string]"
                    hex_command $cmd
                }
            }
        }
        3 {  # Periodicity
            switch $periodicBlkMVal {
                0 {
                    if {[llength $perVerts] != 2} {
                        msg ERROR "No 2 vertices selected"
                        return
                    }
                    hex_command "make_nodes_periodic \{ [lindex $perVerts 0] \} \{ [lindex $perVerts 1] \}"
                }
                1 {
                    if {[llength $perVerts] == ""} {
                        msg ERROR "No vertices selected"
                        return
                    }
                    hex_command "make_nodes_not_periodic $perVerts"
                }
        2 { # find ptwins auto. based on model periodicity
            hex_command "make_blocking_periodic"
        }
            }
            set perVerts ""
        }
        4 { 
            if {($convBlockTypeVal == 0 || $convBlockTypeVal == 1) && $convBlocks == ""} {
                msg ERROR "No blocks to convert selected"
                return
            } elseif {$convBlockTypeVal == 2 && $swept_face == ""} {
                msg ERROR "No swept face selected"
                return
            } elseif {$convBlockTypeVal == 4 && $mapped_face == ""} {
                msg ERROR "No face selected"
                return
            } elseif {$convBlockTypeVal == 5 && $mapped_face == ""} {
                if {[format %d [ic_hex_mesh_dimension]] == "3"} {
                    msg ERROR "No free 3D block face selected"
                } else {
                    msg ERROR "No free 2D block face selected"
                }
                return
            } elseif {$convBlockTypeVal == 6 && $sblock == ""} {
                msg ERROR "No swept block selected"
                return
            } elseif {$convBlockTypeVal == 7 && ($ublock == "" || $sheet == "")} {
                if {$sheet == ""} {
                    msg ERROR "No sheet block selected"
                }
                if {$ublock == ""} {
                    msg ERROR "No free block selected"
                }
                return
            } elseif {$convBlockTypeVal == 8 && $convBlocks == ""} {
                msg ERROR "No 3D free block selected"
                return
            } elseif {$convBlockTypeVal == 9 && $sblock_faces == ""} {
                msg ERROR "No free face selected"
                return
            }
            switch $convBlockTypeVal {
                0 { # Structured (Mapped)
                    set cmd "ic_hex_convert_to_struct"
                    set sweptDir "-iterative"
                }
                1 { # Unstructured (Free)
                    set cmd "ic_hex_convert_to_unstruct"
                    set sweptDir "" 
                }
                2 { # Swept
                    set mesh_dim [format %d [ic_hex_mesh_dimension]]
                    if {$mesh_dim != 3} {
                        msg ERROR "Can not set block to swept type in 2D"
                        return
                    }
                    set cmd "convert_to_swept $swept_face"
                    if $merge_parallel {
                       append cmd " -merge_parallel"
                    }
                    if [catch {hex_command "$cmd"} res] {
                        msg ERROR "Convert to swept failed"
                    }
                    set swept_face ""
                    get_indices 1
                    hex_update_display
                    mess "Done\n"
                    return
                }
                3 { # convert to Y-block
                    set cmd "ic_hex_convert_degen_to_yblock"
                    set sweptDir ""
                }
                4 { # Convert mapped face to free face
                    set mesh_dim [format %d [ic_hex_mesh_dimension]]
                    if {$mesh_dim != 3} {
                        msg ERROR "Can not set block face to type free in 2D"
                        return
                    }
                    ic_hex_undo_major_start "convert_to_swept"
                    foreach f $mapped_face {
                        if [catch {hex_command "convert_to_swept { $f }"} res] {
                            mess "Failed to convert mapped face \"$f\"\n" red
                            continue
                        } else {
                            mess "Converted mapped face \"$f\" to free\n"
                        }
                    }
                    ic_hex_undo_major_end "convert_to_swept"
                    set mapped_face ""
                    get_indices 1
                    hex_update_display
                    mess "Done\n"
                    return
                }
                5 { # convert free face to mapped face
                    if {$freeBlockFaceFreeTypeMappedMethodVal == 1} {
                        ic_hex_undo_major_start "convert_to_struct_from_nodes"
                        if [catch {hex_command "convert_to_struct_from_nodes -face $mapped_face -v_end [list $vertsFree]" } res] {
                            mess "Failed to convert 2D block $mapped_face using corner vertices $vertsFree\n" red
                        }
                        ic_hex_undo_major_end "convert_to_struct_from_nodes"                    
                    } else {
                        ic_hex_undo_major_start "convert_to_struct"
                        foreach f $mapped_face {
                            if {[format %d [ic_hex_mesh_dimension]] == "3"} {
                                if {[lindex $f end] != "u"} {
                                    mess "Selected face \"$f\" is not type free, skipped\n" red
                                    continue
                                } else {
                                    if [catch {hex_command "convert_to_struct { $f } -propagate"} res] {
                                        mess "Failed to convert free face \"$f\"\n" red
                                    }
                                }
                            } else {
                                if [catch {hex_command "convert_to_struct $f"} res] {
                                    mess "Failed to convert free 2D block \"$f\"\n" red
                                }
                            }
                        }
                        ic_hex_undo_major_end "convert_to_struct"
                    }
                    set mapped_face ""
                    set vertsFree ""
                    get_indices 1
                    aie_hex_delete_display_subset
                    aie_hex_display_marked_blocks
                    hex_update_display
                    if {[format %d [ic_hex_mesh_dimension]] == "3"} {
                        mess "Done convert free 3D block face to mapped\n"
                    } else {
                        mess "Done convert free 2D block to mapped\n"
                    }
                    return
                }
                6 { # reverse sblock direction
                    hex_command "reverse_swept_direction $sblock"
                    hex_update_display
                    set sblock ""
                    mess "Done\n"
                    return
                }
                7 { # merge sheet in unstruct block
                    hex_command "merge_sheet_with_unstruct $ublock $sheet"
                    hex_update_display
                    set sheet ""
                    mess "Done\n"
                    return
                }
                8 { # 3D free block mesh type
                    set type ""
                    if {$mesh_type == "Tetra-Delaunay"} {
                        set type "tet"
                    } elseif {$mesh_type == "Tetra-Adv.Front"} {
                        set type "afmesh"
                    } elseif {$mesh_type == "Hexa-Core"} {
                        set type "hexcore"
                    } elseif {$mesh_type == "Hexa-Dominant"} {
                        set type "hexdom"
                    } elseif {$mesh_type == "TGrid"} {
                        set type "tgrid"
                    } else {
                        msg ERROR "Mesh Type: $mesh_type not supported"
                        return
                    }
                    set mesh_dim [format %d [ic_hex_mesh_dimension]]
                    if {$mesh_dim != 3} {
                        msg ERROR "Can not set block to type \"3D Free Block Mesh Type\" in 2D"
                        return
                    }
                    foreach ub $convBlocks {
                        hex_command "set_ublock_mesh_type $ub $type"
                    }
                    if {([info exists index_form] && [winfo exists $index_form])} {
                        get_indices 3
                    } else {
                        get_indices 1
                    }
                    hex_update_display
                    mess "Done\n"
                    return
                }
                9 { # free face mesh type
                    set type $sbmesh_type
                    if [info exists quad_types($type)] {
                        set type $quad_types($type)
                    }
                    foreach f $sblock_faces {
                        if {[lindex $f end] != "u"} {
                            msg ERROR "Face \"$f\" is not type free"
                            return
                        }
                    }
                    hex_command "set_sblock_mesh_type $type $sblock_faces"
                    hex_update_display
                    mess "Done\n"
                    return
                }
            }
            set multiple [llength $convBlocks]
            set nerr 0
            set cnt 0
            set already_suspended [ic_undo_suspended] 
            
            if {$convBlockTypeVal == "0"} { ic_hex_undo_major_start "convert_to_struct" }
            if {$convBlockTypeVal == "1"} { ic_hex_undo_major_start "convert_to_unstruct" }
            if {$convBlockTypeVal == "3"} { ic_hex_undo_major_start "convert_degen_to_yblock" }
            foreach blk $convBlocks {
                if [catch {eval $cmd $blk $sweptDir} res] {
                    set err [hex_trim_error $res]
                    if {$multiple > 1} {
                        incr nerr
                    } else {
                        msg ERROR $err
                    }
                }
                if {$multiple > 1 && !$cnt && !$already_suspended} {
                    set ta [tdv_active 0] 
                    ic_undo_suspend
                }
                incr cnt
            }
            if {$multiple > 1 && !$already_suspended} {
                tdv_active $ta
                ic_undo_resume
            }
            if {$convBlockTypeVal == "0"} { ic_hex_undo_major_end "convert_to_struct" }
            if {$convBlockTypeVal == "1"} { ic_hex_undo_major_end "convert_to_unstruct" }
            if {$convBlockTypeVal == "3"} { ic_hex_undo_major_end "convert_degen_to_yblock" }
            
            if $nerr { mess "Not all blocks converted: $err\n" red }
            set convBlocks ""
            if {([info exists index_form] && [winfo exists $index_form]) && ($convBlockTypeVal == 0 || $convBlockTypeVal == 1 || $convBlockTypeVal == 2)} {
                get_indices 3
            } else {
                get_indices 1
            }
            hex_update_display
            mess "Done\n"
            return
        }
        5 {
            if {$blocks == ""} {
                msg ERROR "No block selected"
                return
            }
            switch $editBlockIJKHowVal {
                0 {
                    foreach blk $blocks {
                        if $use_output_blocks {
                            hex_command "rotate_super_block $blk output_blocks"
                        } else {
                            hex_command "rotate_super_block $blk"
                        }
                    }
                }
                1 {
                    if {$vert == ""} {
                        msg ERROR "No vertex selected"
                        return
                    }
                    if $use_output_blocks {
                        hex_command "change_origin $blocks $vert output_blocks"
                    } else {
                        hex_command "change_origin $blocks $vert"
                    }
                    set vert ""
                }
                2 {
                    if {$blocks == ""} {
                        msg ERROR "No reference block selected"
                        return
                    }
                    hex_command "align_superblocks $blocks"
                }
                3 {
                    set ijk ""
                    foreach r {I J K} {
                        foreach c {I J K} {
                            if [setBlockIJKMS query "Set $r" $c] {
                                append ijk [string tolower $c]
                            }
                        }
                    }
                    foreach blk $blocks {
                        hex_command "set_super_block_ijk $blk $ijk"
                    }
                }
            }
            set blocks ""
        }
        7 {
            if {$transferBlocks == ""} {
                msg ERROR "No block selected"
                return
            }
            ic_hex_undo_major_start "block_transfer"
            if [catch {hex_command "block_transfer sel $use_output_blocks \"$transferBlocks\""} res] {
                mess "Error: $res\n" red
            } else {
                mess "Done transfer blocks\n" blue
            }
            ic_hex_undo_major_end "block_transfer"
            set transferBlocks ""
        }
    }
    get_indices 0
    index_update_all
    aie_hex_update_index_form 0
    hex_update_display
}

proc onchangeBlockPartDEZLoad {} {
    set PartList [aie_hex_list_parts 1]
    lappend PartList VORFN
}

proc onChangeBlockPartDEZModify {dez val} {
    if {$val == "From screen"} {
        changeBlockPartDEZ set part_name [geo_select_part_from_screen 1]
    }
}

proc onchangeBlockPartDEZOK {} {
    aie_change_part_blocks $changeBlocksList $part_name
}

proc aie_change_part_blocks {blocks part_name {update 1}} {
    if {$blocks == ""} {
        msg ERROR "No block selected"
        return
    }
    if {$part_name == ""} {
        msg ERROR "No partname specified"
        return
    }
    if { $part_name == "VORFN" } {
        set fam VORFN
    } else {
        set fam [aie_new_part $part_name]
    }
    hex_command "mark_blocks unmark"
    block_mark_super $blocks
    hex_command "change_element_id $fam"
    if $update { hex_update_display }
}

proc onmergeBVertexDEZLoad {} {

    if {![info exists mergeBVertexmainVal] || $mergeBVertexmainVal == ""} {
        set mergeBVertexmainVal 0
        set propagate 1
        set merge_ave 0
        set rebuild_orphan 0
        set update_projections 0
        set update_edge_node_count 0
        set force_edge_collapse 0
    }
}

proc onmergeBVertexDEZAfterLoad {} {

    if {[trace vinfo propagate] != ""} {
        trace vdelete propagate w aie_hex_trace_propagate
    }
    trace variable propagate w aie_hex_trace_propagate
    aie_hex_trace_propagate "" "" ""
}

proc aie_hex_trace_propagate {name element op} {
    if [mergeBVertexDEZ get propagate] {
        ::AIEnv::GUIManagement::ToggleGrey collapseEdgeForceMerge 1
        ::AIEnv::GUIManagement::ToggleGrey collapseEdgeOrfn 1
        ::AIEnv::GUIManagement::ToggleGrey collapseEdgeUpdProj 1
        ::AIEnv::GUIManagement::ToggleGrey collapseEdgeUpdBunch 1
    } else {
        ::AIEnv::GUIManagement::ToggleGrey collapseEdgeForceMerge 0
        ::AIEnv::GUIManagement::ToggleGrey collapseEdgeOrfn 0
        ::AIEnv::GUIManagement::ToggleGrey collapseEdgeUpdProj 0
        ::AIEnv::GUIManagement::ToggleGrey collapseEdgeUpdBunch 0
    }
}

proc onmergeBVertexDEZUnLoad {} {

    if {[trace vinfo propagate] != ""} {
        trace vdelete propagate w aie_hex_trace_propagate
    }
}

proc ondeleteBlkStationBLoad {} {
    if $auto_pick_mode {
        if !$merge_multipleEGVal {
            deleteBlkStationPick pick
        } else {
            deleteBlkStaBaseCh pick
        }
    }
}

proc ondeleteBlkStationPickFinish {} {
    if {$auto_pick_mode && $pickblkbound != ""} {
        mergeBVertexDEZ apply
        deleteBlkStationPick pick
    }
}

proc ondeleteBlkStaBaseChFinish {} {
    if {$auto_pick_mode && $pickverbase != ""} {
        deleteBlkStaListCh pick
    }
}

proc ondeleteBlkStaListChFinish {} {
    if {$auto_pick_mode && $pickblkbound != ""} {
		mergeBVertexDEZ apply		
		deleteBlkStaBaseCh pick
    }
}

proc ondeleteBlkStationBTolLoad {} {
    if $auto_pick_mode {
        deleteBlkStationPick2 pick
    }
}

proc ondeleteBlkStationBlkLoad {} {
    if $auto_pick_mode {
        collapseBlkedgePick pick
    }
}

proc onmergeVert2EdgeLoad {} {
    if $auto_pick_mode {
        mergeVertPick pick
    }
}

proc onmergeVertPickFinish {} {
    if {$auto_pick_mode && $mergeVert != ""} {
        mergeEdgePick pick
    }
}

proc onmergeEdgePickFinish {} {
    if {$auto_pick_mode && $splitEdge != "" && $mergeVert != ""} {
        mergeBVertexDEZ apply
        mergeVertPick pick
    }
}

proc ondeleteBlkStationPick2Finish {} {
    if {$auto_pick_mode && $pickblkbound != "" && $tolerance != ""} {
        mergeBVertexDEZ apply
        deleteBlkStationPick2 pick
    }
}

proc oncollapseBlkedgePickFinish {} {
    if {$auto_pick_mode && $collapseBlkEdge != ""} {
        collapseBlkBlkPick pick
    }
}

proc oncollapseBlkBlkPickFinish {} {
    if {$auto_pick_mode && $collapseBlks != ""} {
        mergeBVertexDEZ apply
        collapseBlkedgePick pick
    }
}

proc onmergeBVertexDEZOK {} {
    global env index_form

    switch $mergeBVertexmainVal {
        0 {
            if {$pickblkbound == ""} {
                msg ERROR "No vertex selected for merging"
                return
            }
            if $merge_multipleEGVal {
                # Multiple Vertices
                if [catch "format %d $pickverbase"] return
                ic_undo_group_begin
                foreach v $pickblkbound {
                    ic_hex_collapse_edge $pickverbase $v join -version 101 fix_first keep_first
                }
                ic_undo_group_end
                # End Multiple Certices	
            } else {    
                # 1 Vertex
                if {[llength $pickblkbound] == 1} {
                    if [catch {eval ic_hex_delete_node_on_edge $pickblkbound use_egde_bunching} res] {
                        msg ERROR "Skipped vertex $pickblkbound: $res"
                        return
                    } else {
                        mess "Vertex $pickblkbound deleted\n" blue
                        foreach curve [ic_geo_get_objects curve] {
                            ic_redraw_geometry curve $curve
                        }
                    }
                    set pickblkbound ""
                    hex_update_display edge face block
                    return
                }
                # 2 Vertices
                if {[llength $pickblkbound] != 2} {
                     msg ERROR "Selected vertices are unique"
                     return
                }
                if !$propagate {
                    set cmd  "collapse_edge $pickblkbound join keep_first -version 101"
                    if !$merge_ave {
                        append cmd " fix_first"
                    }
                    if $rebuild_orphan {
                        append cmd " -rebuild_orphan"
                    }
                    if $update_projections {
                        append cmd " update_projections"
                    }
                    if $update_edge_node_count {
                        append cmd " update_edge_node_count"
                    }
                    if $force_edge_collapse {
                        append cmd " allow_convert_mapped_faces"
                    }
                    if [catch {hex_command $cmd} res] {
                        mess "Error: $res\n" red
                        return
                    }
                    if $update_projections {
                        foreach curve [ic_geo_get_objects curve] {
                            ic_redraw_geometry curve $curve
                        }
                    }
                } else {
                    # first will be kept
                    set second [ic_hex_vertex_ijk [lindex $pickblkbound 0]]
                    set first [ic_hex_vertex_ijk [lindex $pickblkbound 1]]	
                    if {0} { # forgot know why I did this
                        # second will be kept
                        set cmd "delete_station -nodes $first $second"
                    }
                    set dir [del_dim $first $second]
                    if {$dir == ""} return
                    set ind1 [node_index $first $dir]
                    set ind2 [node_index $second $dir]
                    if {($ind1 == "") || ($ind2 == "")} return
                    set mess "Confirm delete station:\ndirection = $dir\n\index range = \[$ind1 - $ind2\]"
                    set ret [tk_dialog .delete "Delete station" $mess "" 0 Confirm Cancel]
                    switch -- $ret {
                        -1 { if [winfo exists .delete] { top_destroy .delete; return } }
                        0 {
                            set cmd "delete_station $dir $ind1 $ind2"
                            if $merge_ave {
                                append cmd " set_ave_loc"
                            }
                            if [catch {hex_command $cmd} res] {
                                mess "Error: $res\n" red
                                return
                            }
                        }
                    }
                }
            }
            set pickblkbound ""
            mess "Done \"Merge Vertices\"\n" blue
        }
        1 {
            if {$pickblkbound == ""} {
                msg ERROR "No vertex selected for merging"
                return
            }
            if {$tolerance == ""} {
                msg ERROR "No tolerance specified for merging"
                return
            }
            set cmd "merge_vertices $tolerance [llength $pickblkbound] $pickblkbound"
            if $update_projections {
                append cmd " update_projections"
            }
            hex_command  $cmd
            if $update_projections {
                foreach curve [ic_geo_get_objects curve] {
                    ic_redraw_geometry curve $curve
                }
            }
            set pickblkbound ""
            # Recreate VORFN
            hex_command "mark_blocks unmark"
            hex_command "mark_blocks VORFN"
            hex_command "delete_blocks marked"
            mess "Done \"Merge Vertices\"\n" blue
        }
        2 {
            if {$collapseBlkEdge == ""} {
                msg ERROR "Collapse direction not specified"
                return
            }
            if {$collapseBlks == ""} {
                msg ERROR "No blocks selected to collapse"
                return
            }
            hex_command "mark_blocks unmark" 0
            block_mark_super $collapseBlks
            set collapse_dir [lindex $collapseBlkEdge 1]
            hex_command "collapse_blocks $collapse_dir version 410"
            set collapseBlkEdge ""
            set collapseBlk ""
            mess "Done \"Collapse Blocks\"\n" blue
        }
        3 {
            if {$mergeVert == ""} {
                msg ERROR "No vertex selected for merging"
                return
            }
            if {$splitEdge == ""} {
                msg ERROR "No Edge selected for splitting"
                return
            }
            hex_command "vertex_to_edge $mergeVert  [lindex $splitEdge 0] [lindex $splitEdge 1]"
            set mergeVert ""
            set splitEdge ""
            mess "Done \"Merge Vertex to Edge\"\n" blue
        }
    }  
    # fix inverted blocks created sometimes
    if [info exists env(HEXA_TOYOTA)] {
        ic_hex_mark_blocks unmark
        ic_hex_mark_blocks inverted
        ic_hex_invert_super_block marked
    }
    if {[info exists index_form] && [winfo exists $index_form]} {
        get_indices 3
    } else {
        get_indices 1
        index_update_all
    }
    hex_update_display edge face block
}

########################### Edit edges ###########################################

proc aie_blocking_menu_unload {{mess ""}} {
    global hexa_select tdv_waiting_for_click tdv_default
    global auto_pick_mode
   
    select_toolbar_delete
    catch { unset hexa_select }
    if [info exists tdv_waiting_for_click($tdv_default)] {
        set tdv_waiting_for_click($tdv_default) {2 0 0}
    }
    banner ""; hex_update_display
}

proc oneditEdgeMenuDEZLoad {} {
    set tan_factor1 0.33
    set tan_factor2 0.33
    set factor 1.0
    set auto_linear_all 0
    if {$link == ""} {set link all}
}

proc aie_blocking_factor1 {num {dez ""}} {}

proc aie_blocking_factor2 {num {dez ""}} {}

proc oneditEdgeMenuDEZAfterLoad {} {

    if {[trace vinfo auto_linear_all] != ""} {
        trace vdelete auto_linear_all w aie_hex_trace_auto_linear_all
    }
    trace variable auto_linear_all w aie_hex_trace_auto_linear_all
    aie_hex_trace_auto_linear_all "" "" ""
    
    if [info exists editEdgemainVal] {
	    switch $editEdgemainVal {
	        0 {
		        editEdgeMenuDEZ oneditEdgeSplitLoad
	        }
	        1 {
		        editEdgeMenuDEZ oneditEdgeUnSplitLoad
	        }
	        2 {
		        editEdgeMenuDEZ oneditEdgeLinkLoad
	        }
	        3 {
		        editEdgeMenuDEZ oneditEdgeUnLinkLoad
	        }
	    }
    }
}

proc oneditEdgeMenuDEZUnLoad {} {

    if {[trace vinfo auto_linear_all] != ""} {
        trace vdelete auto_linear_all w aie_hex_trace_auto_linear_all
    }
}

proc aie_hex_trace_auto_linear_all {name element op} {
    if [editEdgeMenuDEZ get auto_linear_all] {
        ::AIEnv::GUIManagement::ToggleGrey editEdgeSplitEdge3 1
        ::AIEnv::GUIManagement::ToggleGrey editEdgeSplitEdge6 1
    } else {
        ::AIEnv::GUIManagement::ToggleGrey editEdgeSplitEdge3 0
        ::AIEnv::GUIManagement::ToggleGrey editEdgeSplitEdge6 0
    }
}

proc oneditEdgeSplitLoad {} {
    global auto_pick_mode wait_for_confirm
    global select_action hexa_select
    
    # to avoid multiple clicking on the select split edge icon (the split edge is different, edge selection will be done in C++ code)
    if {[info exists ::hexa_select] && $editEdgeSplitEdgeHowVal == 0} return
    
    if $auto_pick_mode {
	    switch $editEdgeSplitEdgeHowVal {
	        0 { editEdgeSplitEdge0 pick }
	        1 { editEdgeSplitEdge1 pick }
	        2 { editEdgeSplitEdge2 pick }
	        3 { editEdgeSplitEdge3 pick }
	        4 { editEdgeSplitEdge4 pick }
	        5 { editEdgeSplitEdge5 pick }
	        default {}
	    }
    }
}

proc oneditEdgeSplitUnLoad {} {
    aie_blocking_menu_unload editEdgeSplit
}

proc onedgeSplitSplineLoad {} {
    if $auto_pick_mode {
        editEdgeSplitEdge0 pick
    }
}

proc onedgeSplitLinearLoad {} {
    if $auto_pick_mode {
        editEdgeSplitEdge1 pick
    }
}

proc onedgeSplitCPLoad {} {
    if $auto_pick_mode {
        editEdgeSplitEdge2 pick
    }
}

proc onedgeSplitALinearLoad {} {
    if $auto_pick_mode {
        editEdgeSplitEdge3 pick
    }
}

proc onedgeSplitASplineLoad {} {
    if $auto_pick_mode {
        editEdgeSplitEdge6 pick
    }
}

proc onedgeSplitTanLoad {} {
    if $auto_pick_mode {
        editEdgeSplitEdge4 pick
    }
}

proc oneditEdgeSplitEdgeTan2Load {} {
    if $auto_pick_mode {
        editEdgeSplitEdge4 pick
    }
}

proc onedgeSplitAtVertexLoad {} {
    if $auto_pick_mode {
        editEdgeSplitEdge5 pick
    }
}

proc editEdgeUnSplitPick {} {
    if $auto_pick_mode {
	    switch $edgeUnSplitVal {
	        0 {editEdgeUnSplitEdge pick}
	        1 {editEdgeUnSplitVertex pick}
	        default {}
	    }
    }
}

proc oneditEdgeUnSplitLoad {} {
    if $auto_pick_mode {
        editEdgeMenuDEZ editEdgeUnSplitPick
    }
}

proc oneditEdgeUnSplitEdgeFinish {} {
    if {$edgeUnSplits != "" && $auto_pick_mode} {
        editEdgeMenuDEZ apply
        editEdgeMenuDEZ editEdgeUnSplitPick
    }
}

proc oneditEdgeUnSplitVertexFinish {} {
    if {$edgeUnSplits != "" && $auto_pick_mode} {
        editEdgeMenuDEZ apply
        editEdgeMenuDEZ editEdgeUnSplitPick
    }
}

proc oneditEdgeUnSplitUnLoad {} {
    aie_blocking_menu_unload editEdgeUnSplit
}

proc oneditEdgeLinkLoad {} {
    if ![info exists editEdgeLinkDirGGVal] { set editEdgeLinkDirGGVal 0 }
    if $editEdgeLinkDirGGVal {
        ::AIEnv::GUIManagement::ToggleGrey editEdgeLinkDirPick 0
    } else { 
        ::AIEnv::GUIManagement::ToggleGrey editEdgeLinkDirPick 1
    }
    if ![info exists editEdgeLinkDirGG2Val] { set editEdgeLinkDirGG2Val 0 }
    if $editEdgeLinkDirGG2Val {
        ::AIEnv::GUIManagement::ToggleGrey editEdgeLinkDirPick2 0
    } else {
        ::AIEnv::GUIManagement::ToggleGrey editEdgeLinkDirPick2 1
    }
    set dir_vector ""
    if $auto_pick_mode {
	    switch $editEdgeLinkEGVal {
	        0 {
		        editEdgeLinkSEdge pick
	        }
	        1 {
		        linkEdgeDimPick pick
	        }
	    }
    }
}

proc oneditEdgeLinkUnLoad {} {
    aie_blocking_menu_unload editEdgeLink
}

proc onlinkEdgeDimPickFinish {} {
    if {$editEdgemainVal != 2} {
        return
    }
    if {$auto_pick_mode && $edgeLinkDim != ""} {
        linkEdgeSourceIndex pick
    }
}

proc onlinkEdgeSourceIndexFinish {} {
    if {$editEdgemainVal != 2} return
    if {$auto_pick_mode && $edgeLinkSrcIndex != ""} {
        linkEdgeTargetIndex pick
    }
}

proc onlinkEdgeTargetIndexFinish {} {
    if {$editEdgemainVal != 2} return
    if {$auto_pick_mode && $edgeLinkTargIndex != ""} {
        editEdgeMenuDEZ apply
        editEdgeMenuDEZ oneditEdgeLinkLoad
    }
}

proc oneditEdgeUnLinkLoad {} {
    if $auto_pick_mode {editEdgeUnLinkEdge pick}
}

proc oneditEdgeUnLinkUnLoad {} {
    aie_blocking_menu_unload editEdgeUnLink
}

proc oneditEdgeMenuDEZUnLoad {} {
    aie_blocking_menu_unload editEdgeMenuDEZ
}

foreach ll {0 1 2 3 4 5 6} {
proc oneditEdgeSplitEdge$ll\Finish {} {
    global display_flag button_instructions
    global last_line replay_recording replay_do_all 
    global select_action hexa_select use_output_blocks hexa_sketching_select
   
    # to avoid multiple clicking on the select edge icon
    if [info exists ::hexa_select] {
        mess "Already in select mode\n"
        return
    }
    switch $editEdgeSplitEdgeHowVal {
        0 {
	        # Spline
	        set smooth_opt " -interpolate "
	    }
	    1 {
	        # Linear
	        set smooth_opt ""
	    }
	    2 {
	        # Control Point
	        set smooth_opt " -smooth "
	    }
	    3 {
	        # Automatic Linear
	        if {$auto_pick_mode && ($AutoedgeSplits != "" || $auto_linear_all)} {
		        editEdgeMenuDEZ apply
		        if !$auto_linear_all {
		            editEdgeSplitEdge3 pick
		        }
	        }
	        return
	    }
	    4 {
	        # Automatic Spline
	        if {$auto_pick_mode && ($AutoedgeSplits != "" || $auto_linear_all)} {
		        editEdgeMenuDEZ apply
		        if !$auto_linear_all {
		            editEdgeSplitEdge6 pick
		        }
	        }
	        return
	    }
	    5 {
	        # Tangent
	        return
	    }
	    6 {
	        # At Vertex smooth
	        if {$auto_pick_mode && $vertexSplits != ""} {
		        editEdgeMenuDEZ apply
	        }
	        return
	    }
	    default {
	        mess "Invalid edge splitting method\n"
	        return
	    }
    }

    editEdgeMenuDEZ setclean

    if [aie_hex_sketching_mode] {
        if ![info exists ::hexa_sketching_select] {
            set ::hexa_sketching_select 1
        }
        banner "Select a location on the edge to split and move; left button = select, right = cancel"
    } else {
        banner "Select a location on the edge to split and move"
    }
    
    set cmd "ic_hex_split_edge [range_string] [family_activename_string]"
    
    if $display_flag(edge_proj) { append cmd " proj" }
    if $display_flag(edge_shape) { append cmd " edge_shape" }
    if $display_flag(edge_nodes) { append cmd " nodes" }
    if $display_flag(edge_shape_source) { append cmd " shape_source" }
    if !$display_flag(edge_vol) { append cmd " -no_volume" }
    if $display_flag(use_blanking) { append cmd " -not_blanked" }
    if $use_output_blocks { append cmd " output_blocks" }
    append cmd $smooth_opt
    set ::hexa_select 1
    set confirm_edge_split [eval $cmd]
    catch { unset ::hexa_select }
    catch { array unset edges2 }
    if {[string trimright $confirm_edge_split \n] != "" && $smooth_opt == ""} {
        set e1 [lindex $confirm_edge_split 0]; set e2 [lindex $confirm_edge_split 1]
        if {[lindex [ic_hex_mesh_params $e1 $e2] 7]== "from_edge_pnts"} {
            set nseg [ic_hex_get_edge_segment_number $e1 $e2]
            set cmd "set_mesh $e1 $e2 n [expr $nseg + 1] from_edge_pnts"
            hex_command $cmd
            set edges2($e1,$e2) "ic_hex_set_mesh $e1 $e2 n [expr $nseg + 1] from_edge_pnts"
        }
    }
    hex_update_display block edge face mesh
    banner ""  
   
    if $replay_recording {
	    set prev_replay_do_all $replay_do_all
	    set replay_do_all 1
	    set e [string trimright $confirm_edge_split \n]
	    if {$e != ""} {
	        replay_record_command "replay_put ic_hex_split_edge $e"
	        set e1 [lindex $e 0]; set e2 [lindex $e 1]
	        if {$editEdgeSplitEdgeHowVal == 0} {
	            replay_record_command "replay_put ic_hex_make_edge_curve_type $e1 $e2 spline"
	        } elseif {$editEdgeSplitEdgeHowVal == 2} {
	            replay_record_command "replay_put ic_hex_make_edge_curve_type $e1 $e2 control_point"
	        }
	        if [info exists edges2($e1,$e2)] {
	            replay_record_command "replay_put $edges2($e1,$e2)"
	        }
	    }
	    set replay_do_all $prev_replay_do_all
    }

    if {$confirm_edge_split != ""} {
	    switch $editEdgeSplitEdgeHowVal {
	        0 {editEdgeSplitEdge0 pick}
	        1 {editEdgeSplitEdge1 pick}
	        2 {editEdgeSplitEdge2 pick}
	        default {}
	    }
    } else { 
        if [aie_hex_sketching_mode] {
            catch { unset ::hexa_sketching_select }
        }
    }
}
}

proc oneditEdgeUnSplitEdgeFinish {} {
    if {$editEdgemainVal != 1} return
    if {$edgeUnSplitVal == 0 && $auto_pick_mode && $edgeUnSplits != ""} {
        editEdgeMenuDEZ apply
        editEdgeUnSplitEdge pick
    }
}

proc oneditEdgeUnSplitVertexFinish {} {
    global button_instructions
    global last_line replay_recording replay_do_all

    if {$editEdgemainVal != 1} return
    editEdgeMenuDEZ setclean    
    switch $edgeUnSplitVal {
    	1 {
            banner "Please select the edge vertex to remove $button_instructions"
            set edges [eval ic_hex_remove_edge_point [range_string] [volume_activename_string]]
            catch { array unset edges2 }
            foreach e [split $edges \n] {
                if {$e == ""} break
                set n1 [lindex $e 0]; set n2 [lindex $e 1]
                if {[string is integer -strict $n1] && [string is integer -strict $n2]} {
                    if {[lindex [ic_hex_mesh_params $n1 $n2] 7] == "from_edge_pnts"} {
                        set nseg [ic_hex_get_edge_segment_number $n1 $n2]
                        if {$nseg >= 2} {
                            ic_hex_set_mesh $n1 $n2 n [expr $nseg + 1] from_edge_pnts
                            set edges2($n1,$n2) "ic_hex_set_mesh $n1 $n2 n [expr $nseg + 1] from_edge_pnts"
                        }
                    }
                }
            }
            banner ""
            hex_update_display block edge face mesh
            if $replay_recording {
                set prev_replay_do_all $replay_do_all
                set replay_do_all 1
                foreach e [split $edges \n] {
                    if {$e == ""} break
                    replay_record_command "replay_put ic_hex_remove_edge_point $e"
                }
                foreach e [array names edges2] {
                    replay_record_command "replay_put $edges2($e)"
                }
                set replay_do_all $prev_replay_do_all
            }
        }
    }
}

proc oneditEdgeLinkSEdgeFinish {} {
    if {$editEdgemainVal != 2} return
    if {$auto_pick_mode && $edgeSLink != ""} {
	    if $editEdgeLinkEGVal {
	        linkEdgeDimPick pick
	    } else {
	        editEdgeLinkTEdge pick
	    }
    }
}

proc oneditEdgeLinkSEdge2Finish {} {
    if {$editEdgemainVal != 2} return
    if {$auto_pick_mode && $edgeSLink != ""} {
	     editEdgeLinkTEdge2 pick
    }
}

proc oneditEdgeUnLinkEdgeFinish {} {
    if {$editEdgemainVal != 3} return
    if {$auto_pick_mode && $edgeUnLink != ""} {
        editEdgeMenuDEZ apply
        editEdgeUnLinkEdge pick
    }
}

proc oneditEdgeLinkTEdgeFinish {} {
    if {$editEdgemainVal != 2} return
    if {$auto_pick_mode && $edgeTLinks != ""} {
        editEdgeMenuDEZ apply
        editEdgeMenuDEZ oneditEdgeLinkLoad
    }
}

proc oneditEdgeLinkTEdge2Finish {} {
    if {$editEdgemainVal != 2} return
    if {[llength $edgeTLinks] == 1} {
        set e [lindex $edgeTLinks 0]
        set f [ic_hex_get_edge_shape_factor [lindex $e 0] [lindex $e 1]]
        if {$f != "-1" && ([string is integer $f] || [string is double $f])} {
            set factor $f
        }
    }
}

proc oneditEdgeLinkDirPickFinish {} {
    if {[llength $dir_vector] == 2} {
        set n1 [lindex $dir_vector 0]
        set n2 [lindex $dir_vector 1]
        set dir_vector [aie_get_edge_vec $n1 $n2]
    } else {
        mess "Need 2 vertices for \"Link direction\"\n" red
    }
}

proc oneditEdgeLinkDirPick2Finish {} {
    if {[llength $dir_vector] == 2} {
        set n1 [lindex $dir_vector 0]
        set n2 [lindex $dir_vector 1]
        set dir_vector [aie_get_edge_vec $n1 $n2]
    } else {
        mess "Need 2 vertices for \"Link direction\"\n" red
    }
}

proc oneditEdgeMenuDEZOK {} {
    global display_flag button_instructions select_type
           
    switch $editEdgemainVal {
        0 {
            switch $editEdgeSplitEdgeHowVal {
                3 - 4 {
                    set spline ""
                    if {$editEdgeSplitEdgeHowVal == 4} {
                        set spline "-spline"
                    }
                    ic_hex_undo_major_start "auto_edge_split"
                    if !$auto_linear_all {
                        # Automatic edge splits
                        foreach edge $AutoedgeSplits {
                            set reset_from_edge_pnts 0
                            set t1 [lindex $edge 0]
                            set t2 [lindex $edge 1]
                            if {[string is integer -strict $t1] && [string is integer -strict $t2]} {
                                if {[lindex [ic_hex_mesh_params $t1 $t2] 7] == "from_edge_pnts"} {
                                    set reset_from_edge_pnts 1
                                }
                            }
                            hex_command "auto_split_edge $spline $t1 $t2" 1 1
                            if $reset_from_edge_pnts {
                                set nseg [ic_hex_get_edge_segment_number $t1 $t2]
                                if {$nseg >= 2} {
                                    ic_hex_set_mesh $t1 $t2 n [expr $nseg + 1] from_edge_pnts
                                }
                            }
                        }
                    } else {
                        set cmd "auto_split_edge $spline -all"
                        hex_command $cmd
                        set cmd "select_edge no_highlight all [range_string] max 1 m [volume_activename_string] new_format volume"
                        if $use_output_blocks { append cmd " output_blocks" }
                        foreach "t1 t2" [string trimright [hex_command $cmd] \n] {
                            if {[string is integer -strict $t1] && [string is integer -strict $t2]} {
                                if {[lindex [ic_hex_mesh_params $t1 $t2] 7] == "from_edge_pnts"} {
                                    ic_hex_set_mesh $t1 $t2 n [expr [ic_hex_get_edge_segment_number $t1 $t2] + 1] from_edge_pnts
                                }
                            }
                        }
                    }
                    ic_hex_undo_major_end "auto_edge_split"
                    hex_update_display edge
                    foreach curve [ic_geo_get_objects curve] {
                        ic_redraw_geometry curve $curve
                    }
                    set AutoedgeSplits ""
                }
                5 {
                    if {$edges == ""} {
                        msg ERROR "No edge selected"
                        return
                    }
                    ic_hex_undo_major_start "split_tangent_edges"
                    set args ""
                    switch $editEdgeSplitEdgeTan1Val {
                        0 {
                            if ![va_is_int_or_real $tan_factor1] {
                                mess "Warning: Factor for Vertex 1 is missing or invalid. Defaulting to 0.33\n" red
                                set tan_factor1 0.33
                            }
                            set args [concat $args tan1 ortho fac1 $tan_factor1]
                        }
                        1 {
                            if ![va_is_int_or_real $tan_factor1] {
                                mess "Warning: Factor for Vertex 1 is missing or invalid. Defaulting to 0.33\n" red
                                set tan_factor1 0.33
                            }
                            if ![va_is_triplet $tan_point1] {
                                msg ERROR "Please select or enter a valid tangency point for Vertex 1"
                                return
                            }
                            set args [concat $args tan1 $tan_point1 fac1 $tan_factor1]
                        }
                        2 {
                        }
                    }
                    switch $editEdgeSplitEdgeTan2Val {
                        0 {
                            if ![va_is_int_or_real $tan_factor2] {
                                mess "Warning: Factor for Vertex 2 is missing or invalid. Defaulting to 0.33\n" red
                                set tan_factor2 0.33
                            }
                            set args [concat $args tan2 ortho fac2 $tan_factor2]
                        }
                        1 {
                            if ![va_is_int_or_real $tan_factor2] {
                                mess "Warning: Factor for Vertex 2 is missing or invalid. Defaulting to 0.33\n" red
                                set tan_factor2 0.33
                            }
                            if ![va_is_triplet $tan_point2] {
                                msg ERROR "Please select or enter a valid tangency point for Vertex 2"
                                return
                            }
                            set args [concat $args tan2 $tan_point2 fac2 $tan_factor2]
                        }
                        2 {
                        }
                    }
                    if {$select_type == "visible"} {
                        eval ic_hex_set_edge_tangents all $args
                    } else {
                        foreach edge $edges {
                            set n1 [lindex $edge 0]
                            set n2 [lindex $edge 1]
                            eval ic_hex_set_edge_tangents $n1 $n2 $args
                        }
                    }
                    ic_hex_undo_major_end "split_tangent_edges"
                    hex_update_display edge
                }
                6 {
                    if {$vertexSplits == ""} {
                        msg ERROR "No vertex selected"
                        return
                    }
                    ic_hex_undo_major_start "split_edges_at_vertex"
                    if {$select_type == "visible"} {
                        eval ic_hex_smooth_edges_at_vertex [volume_activename_string]
                    } else {
                        foreach v $vertexSplits {
                            eval ic_hex_smooth_edges_at_vertex $v [volume_activename_string]
                        }
                    }
                    ic_hex_undo_major_end "split_edges_at_vertex"
                    set vertexSplits ""
                    hex_update_display edge
                }
                7 {
                    ic_hex_undo_major_start "split_edges_at_vertex"
                    set cmd "smooth_edges_at_vertex"
                    hex_command $cmd
                    ic_hex_undo_major_end "split_edges_at_vertex"
                    hex_update_display edge
                }
                default {
                }
            }
            mess "Done split edge\n" blue
        }
        1 {
            switch $edgeUnSplitVal {
                0 {
                    if {$edgeUnSplits == ""} {
                        msg ERROR "No edge selected to remove split"
                    }
                    foreach edge $edgeUnSplits {
                        set n1 [ lindex $edge 0 ]
                        set n2 [ lindex $edge 1 ]
                        set cmd "remove_edge_points $n1 $n2"
                        hex_command $cmd
                    }
                    hex_update_display block edge face mesh
                    set editEdgeUnSplitEdge ""
                }    
            }
            mess "Done unsplit edge\n" blue
        }
        2 {      
            switch $editEdgeLinkEGVal {
                0 - 1 {
                    if {$edgeSLink == ""} {
                        msg ERROR "No source edge selected to link shape"
                        return
                    }
                    set s1 [ lindex $edgeSLink 0 ]
                    set s2 [ lindex $edgeSLink 1 ]
                    if {$edgeTLinks == ""} {
                        msg ERROR "No target edge selected to link shape"
                        return
                    }
                    if {$factor == ""} {
                        msg ERROR "No factor specified to link shape"
                        return
                    }
                    foreach t $edgeTLinks {
                        set t1 [ lindex $t 0 ]
                        set t2 [ lindex $t 1 ]
                        set cmd "link_shape $t1 $t2 $s1 $s2 $factor"
                        if {$editEdgeLinkEGVal == 0} {
                            if $editEdgeLinkDirGGVal {
                                append cmd " $dir_vector"
                             }
                        } else {
                            if $editEdgeLinkDirGG2Val {
                                append cmd " $dir_vector"
                             } 
                        }
                        hex_command $cmd
                    }           
                }
                2 {
                    if {$edgeLinkDim == ""} {
                        msg ERROR "No dimension specified to link shape"
                        return
                    }
                    if {$edgeLinkSrcIndex == ""} {
                        msg ERROR "No source index specified for link edges in dimension"
                        return
                    }
                    if {$edgeLinkTargIndex == ""} {
                        msg ERROR "No target index specified for link edges in dimension"
                        return
                    }
                    foreach i {0 1 2} {
                        set [lindex {vert dim ind} $i] [lindex $edgeLinkDim $i]
                    }
                    set cmd "link_shape_dimension $dim $edgeLinkSrcIndex $edgeLinkTargIndex $factor"
                    if {$link == "visible"} {
                        append cmd " [range_string] m [family_activename_string]"
                    }
                    hex_command $cmd
                }
            }
            hex_update_display block edge face mesh       
            set edgeSLink ""
            set edgeTLinks ""
            set edgeLinkDim ""
            mess "Done link edge\n" blue
        }
        3 {               
            if {$edgeUnLink == ""} {
                msg ERROR "No edge selected to unlink shape"
                return
            }
            foreach edge $edgeUnLink {
                set t1 [ lindex $edge 0 ]
                set t2 [ lindex $edge 1 ]
                set cmd "link_shape $t1 $t2"
                hex_command $cmd
            }
            hex_update_display block edge face mesh
            set edgeUnLink ""
            mess "Done unlink edge\n" blue
        }
        4 {
            switch $editEdgeOptionsEdgeVal {
                0 {
                    set what spline
                }
                1 {
                    set what control_point
                }
                2 {
                    set what linear
                }
            }
            foreach e $edgesSplitType {
                set t1 [lindex $e 0]
                set t2 [lindex $e 1]
                ic_hex_make_edge_curve_type $t1 $t2 $what
            }
            hex_update_display block edge face mesh
            mess "Done change edge split type\n" blue
        }
    }
}

#######################################################################################

proc aie_hex_proj_active_surfs {} {
    global active_surface_var
    
    catch { unset active_surface_var }
    foreach "part proj" [string trimright [ic_hex_list_family_projection] \n] {
        set active_surface_var($part) $proj
    }
    set surfs ""
    set form_families ""
    foreach f [aie_hex_list_parts 0] {
        if {$f == "VORFN" || $f == "ORFN"} continue
        lappend fams $f
    }
    set fams [lsort $fams]
    foreach "part dim" [ic_hex_list_families dims] {
        set part_dims($part) $dim
    }
    set surfs ""
    foreach n $fams {
        if {[info exists part_dims($n)] && $part_dims($n) != 3} {
            lappend surfs [list $n -text $n ]
            lappend form_families $n
        }
    }
    if [check_box_form .act_surfs "Active surfaces parts" $surfs 8 active_surface_var] {
        hex_command "undo_major_start active_families -no_save"
        foreach f $form_families {
            ic_hex_set_family_projection $f $active_surface_var($f)
        }
        hex_command "undo_major_end active_families"
        catch { unset active_surface_var }
    }
}


########################### Move Edge vertex ###########################################

proc onmoveBVertexDEZLoad {} {

    if ![ic_hex_blocking_loaded] return
    
    set MoveVertexOptions {Single Multiple}
    if ![info exists MVHow] {set MVHow Single}
    if {$MVHow == ""} {set MVHow Single}
    set SetPostitionOptions {"Set Position" "Increment Position"}
    if ![info exists SLHow] {set SLHow "Set Position"}
    if {$SLHow == ""} {set SLHow "Set Position"}
    
    set dim [format %d [ic_hex_mesh_dimension]]
    if {$dim == 3} {
    	::AIEnv::GUIManagement::ToggleGrey moveBVertexControlN 0
    } else {
   	    ::AIEnv::GUIManagement::ToggleGrey moveBVertexControlN 1
    }
    if ![info exists AlignVertCsysVal] {
        set AlignVertCsysVal 0
    }
    if ![info exists edgeLenGGVal] {
        set edgeLenGGVal 0
    }
    set AlignVertexPlaneMethod 1
}

proc onmoveBVertexDEZAfterLoad {} { 
    if ![ic_hex_blocking_loaded] {
        aie_update_icons
        moveBVertexDEZ unload
        return
    }
    if [aie_wb2_is_running] {
        after 100 { aie_wb2_wb_parameter_input_blocking_move_vertices [moveBVertexDEZ get vertices] }
    }
}

proc onmoveBVertexMLoad {} {
    if $auto_pick_mode {moveVertPick pick}
}

proc onmoveBVertexMUnLoad {} {
    aie_blocking_menu_unload moveBVertexM
}


proc onmoveVertsDirPickFinish {} {
    if {$dirEdge != ""} {
        set n1 [lindex $dirEdge 0]
        set n2 [lindex $dirEdge 1]
        set dirEdge [aie_get_edge_vec $n1 $n2]
    }
}

proc onmoveVertPickFinish {} {
    global display_flag button_instructions not_finished
    global last_line replay_recording replay_do_all use_output_blocks

    if {$mv_fixx && $mv_fixy && $mv_fixz} {
        msg ERROR "too many constraints"
        return
    }

    if [info exists not_finished] return
    set not_finished 1
    moveBVertexDEZ setclean       
    switch $MVHow {
	    Single {
	        banner "Please select and move the edge vertex $button_instructions"
	        set cmd "ic_hex_place_node [range_string] [family_activename_string] -node_numbers"
	    }
        Multiple {
	        set nodes ""
	        banner "Please select and move the selected vertices $button_instructions"	   
	        set cmd "ic_hex_place_nodes [range_string] [family_activename_string] -node_numbers $nodes"
        }
    }
   
    if $display_flag(edge_vol) { append cmd " volume" }
    if $display_flag(use_blanking) { append cmd " -not_blanked" }
    if $display_flag(edge_shape) { append cmd " -edge_shape" }
    if $display_flag(edge_shape_source) { append cmd " -shape_source" }
#    if $display_flag(edge_nodes) { append cmd " -nodes" }
    if $use_output_blocks { append cmd " output_blocks" }

    if $mv_fixx { append cmd " -fixx" }
    if $mv_fixy { append cmd " -fixy" }
    if $mv_fixz { append cmd " -fixz" }
    if $mv_normal { append cmd " -normal" }
    if $mv_depend { append cmd " move_dependent" }
    if $moveVertsDirGGVal {
        if {$dirEdge == ""}	{
	        msg ERROR "No fixed direction specified"
	        banner ""
	        catch {unset not_finished}
	        return
	    }
	    append cmd " -vec $dirEdge"
    }

    if [catch {set places [eval $cmd]} res] {
	    msg ERROR [hex_trim_error $res]	
    }
    catch {unset not_finished}
    banner ""
    hex_update_display vert edge face block mesh
    if {$moveBVertexmainVal != 0} return
    # record place_node as a series of commands
    set places [string trimright $places \n]
    if $replay_recording {
	    set prev_replay_do_all $replay_do_all
	    set replay_do_all 1
	    foreach pl [split $places \n] {
	        if { [ string match "undo*" $pl ] } continue
	        replay_record_command "ic_hex_place_node $pl"
	    }
        set replay_do_all $prev_replay_do_all
    }
    if {$MVHow == "Multiple" && $places != "" && $auto_pick_mode} {
        moveVertPick pick
    }
}

proc onmoveBlkNodesOnLineLoad {} {
    if $auto_pick_mode {
        alignVertsDirPick pick
    }
}

proc onedgeLenBBLoad {} {
    if $auto_pick_mode {
        setEdgeLengthPick pick
    }
}

proc onedgeLenBBUnLoad {} {
    aie_blocking_menu_unload edgeLenBB
}

proc onsetEdgeLengthPickFinish {} {
    global last_line

    set length ""
    foreach e $edgeList {
	    hex_command "mesh_params [lindex $e 0] [lindex $e 1]"
	    set el [lindex $last_line 5]
	    if {$length == ""} {
	        set length $el
	    } elseif {$el != $length} {
	        set length ""
	        break
	    }
    }
}

proc onedgeLenGGPick2Finish {} {
    foreach e $edgeList {
        set n1 [lindex $e 0]
        set n2 [lindex $e 1]
        set v1 [lsearch $vertex $n1]
        set v2 [lsearch $vertex $n2]
        if {$v1 >= 0 && $v2 >= 0} {
            msg ERROR "Both ends of edge \"[lrange $e 0 1]\" are frozen by vertices [lindex $vertex $v1] and [lindex $vertex $v2]"
            return
        }
    }
}

proc aie_get_edge_vec {n1 n2} {
    set loc1 [ic_hex_get_node_location $n1]
    set loc2 [ic_hex_get_node_location $n2]
    set mag 0
    foreach i {0 1 2} {
	    set dvec($i) [expr [lindex $loc1 $i] -  [lindex $loc2 $i]]
	    set mag [expr $mag + ($dvec($i) * $dvec($i))]
    }
    foreach i {0 1 2} {
	    set dvec($i) [format %.3g [expr $dvec($i) / sqrt($mag)]]
    }

    set evec "$dvec(0) $dvec(1) $dvec(2)"
    return $evec
}

proc onSelLocBMLoad {} {
    set csys_name [ic_csystem_get_current]
    set csys_type [lindex [ic_csystem_get $csys_name] 0]
    switch $csys_type {
	    cartesian { set SetLocCsysVal 0 }
	    cylindrical { set SetLocCsysVal 1 }
    }	   
    if {$auto_pick_mode && $SLHow == "Set Position"} {
	    moveBVertexDEZ OnSetLoRefLocPick
    }
}

proc OnSetLoRefLocPick {} {
    SetLoRefLoc${refLocTypeVal} pick
}

proc onSelLocBMUnLoad {} {
    aie_blocking_menu_unload SelLocBM
}

proc onSLtypeModify {dez val} {
    if {$val == "Increment Position"} {
	    ::AIEnv::GUIManagement::ToggleGrey refLocType 1
	    ::AIEnv::GUIManagement::ToggleGrey refLocType 1
    } else {
	    ::AIEnv::GUIManagement::ToggleGrey refLocType 0
	    ::AIEnv::GUIManagement::ToggleGrey refLocType 0
    }
}

proc onAlignVerBBLoad {} {
    set csys_name [ic_csystem_get_current]
    set csys_type [lindex [ic_csystem_get $csys_name] 0]
    switch $csys_type {
	    cartesian { set AlignVertCsysVal 0 }
	    cylindrical { set AlignVertCsysVal 1 }
    }	   
    if $auto_pick_mode {
	    AlignVertexEdge pick
    }
}

proc onAlignVerBBUnLoad {} {
    aie_blocking_menu_unload AlignVerBB
}

proc onAlignVertexPlane3PtLocPick {} {
    after 1 {
        set banner "Select 3 locations on the plane with the left button, right = cancel"
        banner $banner
    }
}

proc onAlignVertexPlane3PtLocFinish {} {
    if {$AlignVertexPlaneMethod == 1} {
        set p1 [ic_coords_into_local [ic_geo_get_point_location [lindex $Plane 0]]]
        set p2 [ic_coords_into_local [ic_geo_get_point_location [lindex $Plane 1]]]
        set p3 [ic_coords_into_local [ic_geo_get_point_location [lindex $Plane 2]]]
        set Plane [get_plane_normal $p1 $p2 $p3]
    }
}

proc onAlignVertexEdgeFinish {} {
    global last_line
    
    if {$edge != ""} {
	    set n1 [lindex $edge 0]
	    set n2 [lindex $edge 1]
	    hex_command "edge_node_dim $n1 $n2"	
	    set dim [lindex $last_line 0]
	    switch $AlignVertCsysVal {
	        0 {
		        set csys_name [ic_csystem_get_current]
		        set csys [ic_csystem_get $csys_name]
		        if {$dim >= 3} {
		            set AlignVertexGGVal 3
		            ::AIEnv::GUIManagement::ToggleGrey AlignVertexVert4P 0		  
		            # Set Normalized edge vec
		            if {$AlignVertexPlaneMethod == 0} {
		                set Plane [aie_get_edge_vec $n1 $n2]
		                if {$csys_name != "global"} {
			                set Plane [ic_coords_into_local $Plane $csys_name]
			            }
		            }
		        } else {
		            if {$csys_name != "global"} {
			            # Get best aligned local axis
			            set Plane [aie_get_edge_vec $n1 $n2]
			            set dmax -1.0
			            foreach i {0 1 2} {
			                set axis [lindex $csys [expr $i+2]]
			                set d [expr abs([vec_dot $Plane $axis])]
			                if {$d > $dmax} {
				                set dir $i
				                set dmax $d
			                }
			            }
			            set AlignVertexGGVal $dir
		            } else {
			            set AlignVertexGGVal $dim
		            }
		            ::AIEnv::GUIManagement::ToggleGrey AlignVertexVert4P 1
		        }
	        }
	        1 {}
	    }

	    if $auto_pick_mode {
	        AlignVertexVert pick
	    }
    }
}

proc onmoveFaceNodesLoad {} {
    if $auto_pick_mode {
        moveFacesPick pick
    }
}

proc onmoveFaceNodesUnLoad {} {
    hex_command "display_super_faces [range_string] [family_activename_string] erase_icon -not_blanked"
    aie_blocking_menu_unload moveFaceNodes
}

proc onalignVertsDirPickFinish {} {
    if {$auto_pick_mode && $alignDir != ""} {
        alignVertsPick pick
    }
}

proc onalignVertsPickFinish {} {
    if {$auto_pick_mode && $vertList != ""} {
        moveBVertexDEZ apply
        alignVertsDirPick pick
    }
}

proc onmoveBVertexDEZOK {} {   
    global select_type
    global _tempx _tempy _tempz
    global last_line replay_recording replay_do_all

    switch $moveBVertexmainVal {
        0 {
            msg ERROR "Please select the vertex and move interactively"
            return
        }
        1 {
        if {$vertices == "" } {
            mess "No vertices selected\n" red
            return
        }
        set args ""
        switch $SetLocCsysVal {
            0 {
                set xval $SetLocBVertexXVal
                set yval $SetLocBVertexYVal
                set zval $SetLocBVertexZVal
                set nval $SetLocBVertexNVal
            }
            1 {
                set xval $SetLocCylRVal
                set yval $SetLocCylTVal
                set zval $SetLocCylZVal
                set nval 0
            }
        } 
        set val(xval) $X; set val(yval) $Y; set val(zval) $Z;
        set val(nval) $Normal
        foreach p {xval yval zval nval} {
            if [set $p] {
                if {$val($p) == ""} {
                    msg ERROR "No value specified for $p"
                    return
                }
            }
        }
        switch $SLHow {
            "Set Position" {
                if $xval {lappend args x \{$X\}}
                if $yval {lappend args y \{$Y\}}
                if $zval {lappend args z \{$Z\}}
                if $nval {lappend args norm $Normal}
            }
            "Increment Position" {
                if $xval {lappend args dx $X}
                if $yval {lappend args dy $Y}
                if $zval {lappend args dz $Z}
                if $nval {lappend args dnorm $Normal}
            }
        }
        set csys_name [ic_csystem_get_current]
        lappend args -csys $csys_name
        if {[info exists select_type] && $select_type == "visible"} {
            lappend args [range_string] [volume_activename_string]
        } else {
            lappend args node_numbers [list $vertices]
        }
        eval ic_hex_set_node_location [join $args]
        hex_update_display vertex edge face block mesh
        mess "Done \"Set Location\"\n" blue
        moveBVertexDEZ setdirty
    }
	2 {
	    #Align Vertices
	    set vec ""
	    set csys_name [ic_csystem_get_current]
	    set csys [ic_csystem_get $csys_name]
	    if {$edge == ""} {
		    msg ERROR "No edge selected for alignment dimension"
		    return
	    }
	    if {$vertex == ""} {
		    msg ERROR "No vertex selected for reference index"
		    return
	    }
	    if {$dim < 3} {
		    set index [lindex [ic_hex_vertex_ijk $vertex] $dim]
	    } else {
		    set index ""
		    # ijk indices may be "0 1 2 5:1"
		    set ogrids [lrange [ic_hex_vertex_ijk $vertex] 3 end]
		    foreach ogrid $ogrids {
		        set ogrid [split $ogrid :]
		        set ogridnum [lindex $ogrid 0]
		        if {$ogridnum == $dim} {
			        set index [lindex $ogrid 1]
			        break
		        }
		    }
		    if {$index == ""} {
		        set index 0
		    }
	    }	  
	    set cmd "align_vertices $dim $index"
	    switch $AlignVertCsysVal {
		0 { #cartesian
		    if {[lindex $csys 0] != "cartesian"} {
			    msg ERROR "Current active coord. system is [lindex $csys 0]"
			    return
		    }
		    switch $AlignVertexGGVal {
			    0 { set vec "1 0 0" }
			    1 { set vec "0 1 0" }
			    2 { set vec "0 0 1" }
			    3 { set vec $Plane }
		    }
		    append  cmd " $vec"
		}
		1 { #Cylinderical
		    if {[lindex $csys 0] != "cylindrical"} {
			    msg ERROR "Current active coord. system is [lindex $csys 0]"
			    return
		    }		    
		    set vec [lindex $csys 4]
		    append cmd " $vec"
		    switch $AlignVertCylParVal {
			    0 { append cmd " -par r"}
			    1 { append cmd " -par t"}
			    2 { append cmd " -par z"}
		    }
		}
	    }

	    if {$vec == ""} {
		    msg ERROR "No plane specified for alignment"
		    return
	    }	   
	   
	    append cmd " -csys $csys_name [range_string] [volume_activename_string]"
	    hex_command $cmd
	    mess "Done \"Align Vertices\"\n" blue
	    hex_update_display vertex edge face block mesh
	}
	3 { # align vertices in-line
	    if {$alignDir == ""} {
		    msg ERROR "No direction specified for align vertices"
		    return
	    }
	    hex_command "align_vertices2 $alignDir -nodes $vertList"
	    mess "Done \"Align Vertices in-line\"\n" blue
	    hex_update_display
	}
	4 {
	    # set edge Length
	    if {$edgeList == ""} {
		    msg ERROR "No edge selected to set Length"
		    return
	    }
	    if {$length == ""} {
		    msg ERROR "No Length specified"
		    return
	    }
	    foreach e $edgeList {
		    set cmd "set_edge_length [lindex $e 0] [lindex $e 1] $length"
		    if {$edgeLenGGVal == 1} {
			    set n1 [lindex $e 0]
			    set n2 [lindex $e 1]
			    set v1 [lsearch $vertex $n1]
			    set v2 [lsearch $vertex $n2]
			    if {$v1 >= 0 && $v2 >= 0} {
			        msg ERROR "Both ends of edge \"[lrange $e 0 1]\" are frozen by vertices [lindex $vertex $v1] and [lindex $vertex $v2]"
			        return
			    }
			    set v -1
			    if {$v1 >= 0} {
			        set v $v1
			    } elseif {$v2 >= 0} {
			        set v $v2
			    }
			    if {$v >= 0} {
			        lappend cmd fix [lindex $vertex $v]
			    }
		    }
		    hex_command $cmd
	    }
	    mess "Done \"Set Edge Length\"\n" blue
	    set edgeList ""
	    hex_update_display	
	}
	5 {
	    switch $moveFacesEGVal {
		0 {
		    if {$faceList == ""} {
			msg ERROR "No face selected"
			return
		    }
	   
		    set cmd ""
		    switch $moveFaceGGVal {
			0 {
			    if {$vector == ""} {
				msg ERROR "No move direction specified"
				return
			    }
			    append cmd " vector $vector"
			}
			1 {
			    if {[llength $vecList] != 2} {
				msg ERROR "No move direction specified"
				return
			    }
			   
			    set i 0
			    foreach pt $vecList {
				if {[llength $pt] == 1} {
				    set pt$i [ic_geo_get_point_location $pt]
				} else {
				    set pt$i $pt
				}
				incr i
			    }
			    append cmd " points $pt0 $pt1"
			}
		    }
		    foreach face $faceList {
			hex_command "move_face [lindex $face 0] [lindex $face 3] $cmd"
		    }
		    hex_update_display
		}
		1 {
		    if {$vertList == ""} {
			msg ERROR "No vertex selected"
			return
		    }
		    if {$angle == ""} {
			msg ERROR "No angle specified"
			return
		    }
		    if {$center == ""} {
			msg ERROR "No center selected"
			return
		    }
		    set base [join $center]
		   
		    switch $moveVertsGGVal {
			0 {
			    if {$vector == ""} {
				msg ERROR "No axis specified for rotation"
				return
			    }
			    set axis $vector
			}
			1 {
			    if {[llength $vecList] != 2} {
				msg ERROR "No axis specified for rotation"
				return
			    }
			   
			    set i 0
			    foreach pt $vecList {
				if {[llength $pt] == 1} {
				    set pt$i [ic_geo_get_point_location $pt]
				} else {
				    set pt$i $pt
				}
				incr i
			    }
			    set axis ""
			    foreach i {0 1 2} {
				lappend axis [expr [lindex $pt1 $i] - [lindex $pt0 $i]]
			    }
			}
		    }
		    hex_command "rotate_nodes $angle $base $axis $vertList"
		    hex_update_display		   
		}
	    }
	}
    }
}

proc onmoveBVertexDEZUnload {} {
    if {$moveBVertexmainVal == 4} {
        hex_command "display_super_faces [range_string] [family_activename_string] erase_icon  -not_blanked"
    }
    aie_blocking_menu_unload moveBVertexDEZ
}

foreach i {0 1} {
    proc onSetLoRefLoc${i}Finish {} {	
	global replay_recording

	if {$refLocTypeVal == 0} {
	    if {$ref_vertex  != ""} {
		ic_hex_get_node_location $ref_vertex _tempx _tempy _tempz
		set X "\$_tempx"
		set Y "\$_tempy"
		set Z "\$_tempz"
		if $replay_recording {
		    replay_record_command "replay_put ic_hex_get_node_location $ref_vertex _tempx _tempy _tempz"
		}
	    }
	} else {
	    set xyz  [va_check_data_set_point $ref_point xyz]
	    set X [lindex $xyz 0]
	    set Y [lindex $xyz 1]
	    set Z [lindex $xyz 2]
	}
    }
}

proc onSetLocBVertexSelEdgeFinish {} {

    set verts ""
    catch { array unset temp } 
    foreach v [moveBVertexDEZ get vertices] {
        if {[llength $v] == 3} {
            # an edge was selected
            foreach i "0 1" {
                set vv " [lindex $v $i] "
                if [info exists temp($vv)] continue
                set temp($vv) 1
                lappend verts $vv
            }
            continue
        }
        set v " [lindex $v 0] "
        if [info exists temp($v)] continue
        set temp($v) 1
        lappend verts $v
    }
    if {$verts == ""} {
        if [aie_wb2_is_running] {
            aie_wb2_wb_parameter_reset_input "Set Location" moveBVertexDEZ
        }
        return
    }
    moveBVertexDEZ set vertices [lsort -dictionary $verts]

    if [aie_wb2_is_running] {
        aie_wb2_wb_parameter_input_blocking_move_vertices [moveBVertexDEZ get vertices]
    }
}

##################### Projection stuff #############

proc oneditProjDEZLoad {} {

    if {$FaceKeepMeshEGVal == ""} { set FaceKeepMeshEGVal 0 }
    if {$updateVert == ""} {
	    set updateVert 1; set updateEdge 1; set updateFace 1;
    }
    if {$projFacBlkseVal == ""} { set projFacBlkseVal 2 }
    if {$assocVertEGVal == ""} { set assocVertEGVal 1 }
    if {$resetVert == ""} {
        set resetVert 1; set resetEdge 1; set resetFace 1
    }
    set updateBlocking 0;
    if {$v_reset_method == ""} { set v_reset_method "all" }
    if {$e_reset_method == ""} { set e_reset_method "all" }
    if {$f_reset_method == ""} { set f_reset_method "all" }
    if {$update_method == ""} { set update_method "parametric" }
    set auto_proj 1
    set curve_refmesh 0
}

proc oneditProjDEZAfterLoad {} {

    if {$resetEdge == "1"} {
        ::AIEnv::GUIManagement::ToggleGrey resetAssocEdgeAllRG 0
    } else {
        ::AIEnv::GUIManagement::ToggleGrey resetAssocEdgeAllRG 1
    }
    if {[trace vinfo resetEdge] != ""} {
        trace vdelete resetEdge w aie_trace_reset_edge_ass
    }
    trace variable resetEdge w aie_trace_reset_edge_ass
}

proc onProjFacBlkFamModify {dez val} {
    if {$val == "From screen"} {
	    editProjDEZ set part_name [geo_select_part_from_screen 1]
    }
}

#-------------------------------------Auto pick procedure for associations ----------------------------------

proc onassocVertLoad {} {
    if {[info exists assocVertEGVal] && ($auto_pick_mode)} {
        switch $assocVertEGVal {
            0 { assocVertPick1 pick }
            1 { assocVertPick2 pick }
            2 { assocVertPick3 pick }
            3 { assocVertPick4 pick }
        }
    }
}

proc onassocVertPick1Finish {} {
    if {$verts != "" && $auto_pick_mode} {
	    assocVertPart pick
    }
}

proc onassocVertPartFinish {} {
    if {$verts != "" && $part_name != "" && $auto_pick_mode} {
	    editProjDEZ apply
        editProjDEZ onassocVertLoad
    }
}

proc onassocVertPick2Finish {} {
    if {$verts != "" && $auto_pick_mode} {
        assocVertPointPick pick
    }
}

proc onassocVertPick3Finish {} {
    if {$verts != "" && $auto_pick_mode} {
        assocVertCurvePick pick
    }
}

proc onassocVertPick4Finish {} {
    if {$verts != "" && $auto_pick_mode} {
        editProjDEZ apply
        assocVertPick4 pick
    }
}

proc onassocVertPointPickFinish {} {
    if {$point != "" && $auto_pick_mode} {
	editProjDEZ apply
	editProjDEZ onassocVertLoad
    }
}

proc onassocVertCurvePickFinish {} {
    if {$curves != "" && $auto_pick_mode} {
        editProjDEZ apply
        editProjDEZ onassocVertLoad
    }
}

proc onassocEdgeLoad {} {
    if $auto_pick_mode {
        assocEdgePick pick
    }
}

proc onassocEdgePickFinish {} {
    if {$edges != "" && $auto_pick_mode} {
        assocEdgeCurvePick pick
    }
}

proc onassocEdgeCurvePickFinish {} {
    if {$curves != "" && $auto_pick_mode} {
        editProjDEZ apply
        editProjDEZ onassocEdgeLoad
    }
}

proc onassocFacSurfLoad {} {
    if {[info exists projFacBlkseVal] && ($auto_pick_mode)} {
        switch $projFacBlkseVal {
            0 { projFaceSurfE1 pick }
            1 { projFaceSurfE2 pick }
            2 { projFaceSurfE3 pick }
            3 { }
        }
    }
}

proc onprojFaceSurfE1Finish {} {
    if {$faces != "" && $auto_pick_mode} {
        editProjDEZ apply
        editProjDEZ onassocFacSurfLoad
    }
}

proc onprojFaceSurfE2Finish {} {
    if {$faces != "" && $auto_pick_mode} {
        editProjDEZ apply
        editProjDEZ onassocFacSurfLoad
    }
}

proc onprojFaceSurfE3Finish {} {
    if {$faces != "" && $auto_pick_mode} {
        projFacePart pick
    }
}

proc onprojFacePartFinish {} {
    if {$faces != "" && $part_name != "" && $auto_pick_mode} {
        editProjDEZ apply
        editProjDEZ onassocFacSurfLoad
    }
}

proc onprojSWPartsFinish {} {
    if {$solids != "" && $auto_pick_mode} {
        if $projFaceSharedGGVal {
            editProjDEZ apply
        } else {
            projSWSurf pick
        }
    }
}

proc onprojSWSurfFinish {} {
    if {$solids != "" && $surface != "" && $auto_pick_mode} {
        editProjDEZ apply
        editProjDEZ onassocFacSurfLoad
    }
}

proc onprojFaceSurfE2Finish {} {
    if {$faces != "" && $auto_pick_mode} {
        editProjDEZ apply
        editProjDEZ onassocFacSurfEGLoad
    }
}

proc onprojFaceSurfE2Finish {} {
    if {$faces != "" && $auto_pick_mode} {
        editProjDEZ apply
        editProjDEZ onassocFacSurfLoad
    }
}

proc onprojFaceSurfE4Finish {} {
    if {$faces != "" && $auto_pick_mode} {
        editProjDEZ apply
        editProjDEZ onassocFacSurfLoad
    }
}

proc onprojFaceSurfsPickFinish {} {
    if {$faces != "" && $face_surface != "" && $auto_pick_mode} {
        editProjDEZ apply
    }
}

proc ongroupEGILoad {} {
    if $auto_pick_mode {
	    groupCurvesPick pick
    }
}

proc ongroupCurvesPickFinish {} {
    if {$groupCurvesList != "" && $auto_pick_mode} {
	    editProjDEZ apply
	    groupCurvesPick pick
    }
}

proc onungroupEGILoad {} {
    if $auto_pick_mode {
	    ungroupCurvesPick pick
    }
}

proc onungroupCurvesPickFinish {} {
    if {$groupCurvesList != "" && $auto_pick_mode} {
	    editProjDEZ apply
	    ungroupCurvesPick pick
    }
}

proc onprojUpdateVisVertFinish {} {
    if {$projVerts != "" && $auto_pick_mode} {
        editProjDEZ apply
        projUpdateVisVert pick
    }
}

proc onprojVUpdateLoad {} {
    if $auto_pick_mode {
        projUpdateVisVert pick
    }
}

proc onassocEdgeSurfLoad {} {
    if $auto_pick_mode {
        assocEdgeSurfPick pick
    }
}

proc onassocEdgeSurfPickFinish {} {
    if {$edges != "" && $auto_pick_mode} {
        editProjDEZ apply
        assocEdgeSurfPick pick
    }
}

proc onunsetAssocVertPickFinish {} {
    if {$verts != "" && $auto_pick_mode} {
        editProjDEZ apply
        unsetAssocVertPick pick
    }
}

proc onunsetAssocEdgePickFinish {} {
    if {$edges != "" && $auto_pick_mode} {
        editProjDEZ apply
        unsetAssocEdgePick pick
    }
}

proc onunsetAssocFacePickFinish {} {
    if {$faces != "" && $auto_pick_mode} {
        if {$unsetAssocFaceKeepMeshVal && $FaceKeepMeshEGVal == 1} {
            FaceKeepMeshPart pick
            return
        }
        editProjDEZ apply
        unsetAssocFacePick pick
    }
}

proc onFaceKeepMeshPartFinish {} {
    if {$part_name != "" && $auto_pick_mode} {
        editProjDEZ apply
        unsetAssocFacePick pick
    }
}

proc onUnsFaceAssocSelFinish {} {
    if {$faces != "" && $auto_pick_mode} {
        editProjDEZ apply
        UnsFaceAssocSel pick
    }
}

proc onassocFacSurfLoad {} {
    if $auto_pick_mode {
        switch $projFacBlkseVal {
            0 { projFaceSurfE1 pick }
            1 { projFaceSurfE2 pick }
            2 { projFaceSurfE3 pick }
            3 { projSWParts pick }
        }
    }
}

proc onprojFacBlkSharedWallLoad {} {
    aie_hex_show_shared_wall_info
}

proc aie_hex_show_shared_wall_info {{verbose 1}} {
    set shwalls [ic_hex_list_shared_walls]
    if {$shwalls == ""} {
	    if $verbose { mess "\nThere are no shared walls currently defined\n" }
    } else {
	    mess "\nCurrently defined shared walls:\n"
	    mess "\tVolume 1\t\tVolume 2\t\tSurface\n"
	    set nn 1
	    foreach "w1 w2 w3" $shwalls {
	        mess "$nn.\t$w1\t\t$w2\t\t$w3\n"
	        incr nn
	    }
    }
}

proc onUnsFaceAssocLoad {} {
    set mesh_dim [ic_hex_mesh_dimension]
    if {$mesh_dim != 3} {
        #msg ERROR "Uns. Face mesh association is available only for 3D Swept Blocks"
        #set editAssocEGVal -1
        #return
    }
}

proc oneditProjDEZOK {} {
    global use_output_blocks
    
    # Group selected curves
    if {$editAssocEGVal == 0 || $editAssocEGVal == 1} {
	    if {[llength $curves] > 1} {
	        set projcurves ""
	        foreach compcurve $curves {
		        hex_command "get_proj_curves $compcurve"
		        foreach c $last_line {
		            lappend projcurves $c
		        }
	        }
	        ic_hex_create_composite $curves
	        foreach curve $projcurves {
		        ic_redraw_geometry curve $curve
	        }
	        mess "Grouped curves: $curves\n"
	    }
    }

    switch $editAssocEGVal {
        0 { # vertex -> point/curve
	        if {$verts == ""} {
		        msg ERROR "No vertex selected for association"
		        return
	        }
	        switch $assocVertEGVal {
		        0 {
		            if {$part_name == ""} {
			            msg ERROR "No part name specified vertex association"
			            return
		            }
		            set ptfam [aie_new_part $part_name]
		            foreach v $verts {
			            # create geom point at the vertex loc
			            set pt [string trimright [ic_hex_get_node_location $v] \n]
			            set ptname [ic_geo_create_point_location $ptfam $pt]
			            set name [ic_geo_new_name point $ptfam.]
			            ic_geo_set_name point $ptname $name
			            mess "New point: $name created at the vertex: \#$v location\n"
			            hex_command "move_node $v $name"
		            }
		        }
		        1 {
		            if {$point == ""} {
			            msg ERROR "No point selected for association"
			            return
		            }
		            foreach v $verts {
			            hex_command "move_node $v $point"
		            }
		        }
		        2 {
		            if {$curves== ""} {
			            msg ERROR "No curves selected for association"
			            return
		            }
		            set to_what [lindex $curves 0]
		            foreach v $verts {
			            hex_command "set_node_projection $v $to_what"
		            }
		        }
		        3 {
		            foreach v $verts {
			            hex_command "set_node_projection $v"
		            }
		        }
	        }
	        hex_update_display edge face block mesh
	        set verts ""
	        set point ""
	        set curves ""
	        mess "Done "; mess "\"Vertex -> " blue
	        switch $assocVertEGVal {
	            0 { mess "Self\" " blue }
	            1 { mess "Point\" " blue }
	            2 { mess "Curve\" " blue }
	            3 { mess "Surface\" " blue }
	        }
	        mess "association\n"
	        hex_update_display vertex edge face block mesh 
	    }
	    1 { # edge -> curve   
	        if {$edges == ""} {
		        msg ERROR "No edge selected for association"
		        return
	        }
	        if {$curves== ""} {
		        msg ERROR "No curve selected for association"
		        return
	        }
	        foreach projedge $edges {
		        set n1 [lindex $projedge 0]
		        set n2 [lindex $projedge 1]
		        set seg [lindex $projedge 2]
		        set args "$n1 $n2 $seg 1 [lindex $curves 0]"
		        if $intersection {
		            append args " intersection"
		        }
		        if $curve_intersection {
		            append args " curve_intersection"
		        }
		        if $curve_refmesh {
			        if ![ic_hex_ref_mesh_set] {
			            set stat [aie_hex_ref_uns_mesh]
			            if $stat return
			        }
			        append args " -from_mesh"
		        }
		        eval ic_hex_set_edge_projection $args
		        if $update {
		            aie_update_vert_proj_edge [list $projedge]
		        }
	        }
	        hex_update_display vertex edge face block mesh
            if {[info exists aie_CurveComposite] && !$aie_CurveComposite} {
                #set aie_CurveComposite 1
                #::AIEnv::GUIManagement::Tree::CurveComposite
            }
	        set edges ""
	        set curves ""
	        mess "Done "; mess "\"Edge -> Curve\" " blue; mess "association\n"
	    }
	    2 { # edge -> surface
	        if {$edges == ""} {
		        msg ERROR "No edge selected for association"
		        return
	        }
	        foreach projedge $edges {
		        set n1 [lindex $projedge 0]
		        set n2 [lindex $projedge 1]
		        set seg [lindex $projedge 2]
		        ic_hex_set_edge_projection $n1 $n2 $seg 2 0
	        }
	        hex_update_display edge face block mesh
	        set edges ""
	        mess "Done "; mess "\"Edge -> Surface\" " blue; mess "association\n"
	    }
        3 { # face -> surface
	        switch $projFacBlkseVal {
		        0 { set what any }
		        1 { set what do_not_project }
		        2 { set what [aie_new_part $part_name] }
		        3 {
		            if {$solids == ""} {
			            msg ERROR "No volume parts selected"
			            return
		            }
		            switch $projFaceSharedGGVal {
			            0 {
			                if {$surface == ""} {
			                    msg ERROR "No surface part selected"
				                return
			                }
			                set shared_surf $surface
			                set cmd define_shared_wall
			            }
			            1 {
			                set shared_surf ""
			                set surface ""
			                set cmd remove_shared_wall
			            }
			            2 {
			                if {$projFaceSharedGGVal == 2} {
				                set shared_surf "ORFN"
				                set surface ""
				                set cmd define_shared_wall
			                }
			            }
		            }
                    set sparts [ic_geo_list_families]
		            foreach p [concat $solids $surface] {
			            if {[lsearch $sparts $p] == -1} {
			                msg ERROR  "Part with name: $p does not exist"
			                return
			            }
		            }
		            hex_command "$cmd $solids $shared_surf"
		            hex_update_display edge face block mesh
		            set solids ""
		            set surface ""
		            return
		        }
		        4 { set what -link }
		        5 {
		            if ![ic_hex_ref_mesh_set] {
			            set stat [aie_hex_ref_uns_mesh]
			            if $stat return
		            }
		            set what -from_mesh 
		        }
		        6 { # face -> explicit surface
		            if { $face_surface == "" } {
			            msg ERROR "No surface selected for face association"
			            return
		            }
		            set what "-to_surface $face_surface" 
		        }
	        }
	        if {$faces == ""} {
		        msg ERROR "No face selected for association"
		        return
	        }
	        hex_command "project_face node_numbers $faces $what"
	        hex_update_display edge face block mesh
	        set faces ""
	        set part_name ""
	        mess "Done "; mess "\"Face -> Surface\" " blue; mess "association\n"
	    }	
	    4 { # vertex/edge/face -> none
	        foreach v $verts {
		        hex_command "set_node_projection $v to_none"
	        }
	        foreach projedge $edges {
		        set n1 [lindex $projedge 0]
		        set n2 [lindex $projedge 1]
		        set seg [lindex $projedge 2]
		        ic_hex_set_edge_projection $n1 $n2 $seg 3 0
	        }
	        # create empty part if necessary
	        if {[llength $faces] && ($unsetAssocFaceKeepMeshVal)} {
		        switch $FaceKeepMeshEGVal {
		            0 {		
			            set proj_part do_not_project
		            }
		            1 {
			            if {$part_name == ""} {
			                msg ERROR "No part name selected surface mesh"
			                return
			            }
			            if [llength [ic_geo_get_objects surface $part_name]] {
			                msg ERROR "Only parts with no surfaces can be assigned"
			                return
			            }						
			            set proj_part [aie_new_part $part_name]
		            }
		        }
	        }
	        foreach f $faces {
		        if {[llength $f] != 4} continue
		        if $unsetAssocFaceKeepMeshVal {
		            hex_command "project_face node_numbers \{ $f \} $proj_part"
		        } else {
		            hex_command "unproject_face node_numbers \{ $f \}"
		        }
	        }
	        hex_update_display vertex edge face block mesh
	        set verts ""
	        set edges ""
	        set faces ""
	        mess "Done "; mess "\"Vertex/Edge/Face -> None\" " blue; mess "association\n"
	    }
        5 { # renew association
	        global top_current

	        if $updateAssocBlockGGVal {
		        switch $update_method {
		            parametric { hex_command  "update_node_locations" }
		            morph { hex_command  "morph_blocking_to_geometry" }
		        }
	        }
	        set only_dormant ""
	        if $updateDormant {
		        set only_dormant "-only_dormant"
	        }
	        if {($updateVert) && ($updateEdge) && ($updateFace)} {
		        hex_command "update_association $top_current $only_dormant"
	        } else {
		        if $updateVert {
		            hex_command "update_association $top_current vertices $only_dormant"
		        }
		        if $updateEdge {
		            hex_command "update_association $top_current edges $only_dormant"
		        }
		        if $updateFace {
		            hex_command "update_association $top_current faces"
		        }
	        }
	        hex_update_display vertex edge face block mesh
			foreach curve [ic_geo_get_objects curve] {
				ic_redraw_geometry curve $curve
			}
	        mess "Done "; mess "update " blue; mess "associations\n"
	    }
	    6 { # reset association
	        global top_current last_line

	        if {($resetVert && $v_reset_method == "all") && ($resetEdge && $e_reset_method == "all") && \
	            ($resetFace && $f_reset_method == "all")} {
		        hex_command "clear_association $top_current"
	        } else {
		        if $resetVert {
		            if {$v_reset_method == "all"} {
		                hex_command "clear_association $top_current vertices"
		            } else {
		                if ![::AIEnv::GUIManagement::Tree::NodeVisibility block_vertNode] {
		                    mess "Vertices are not turned on in the tree panel\n" red
		                } else {
                            set cmd "select_nodes 1 all [range_string] m [volume_activename_string] node_numbers"
                            if $use_output_blocks { append cmd " output_blocks" }
                            hex_command $cmd
                            set clear_verts ""
                            foreach e "[string trimright $last_line \n]" {
                                set v1 [lindex $e 0]; set v2 [lindex $e 1]
                                if {[lsearch $clear_verts $v1] < 0} { append clear_verts "$v1 " }
                                if {[lsearch $clear_verts $v2] < 0} { append clear_verts "$v2 " }
                            }
                            if {$clear_verts != ""} {
                                hex_command "undo_major_start clear_association_vertices"
                                foreach v $clear_verts {
                                    hex_command "set_node_projection $v"
                                }
                                hex_command "update_association $top_current vertices"
                                hex_command "undo_major_end clear_association_vertices"
                            }
		                }
		            }
		        }
		        if $resetEdge {
		            if {$e_reset_method == "all"} {
		                hex_command "clear_association $top_current edges"
		            } else {
		                if ![::AIEnv::GUIManagement::Tree::NodeVisibility block_edgeNode] {
		                    mess "Edges are not turned on in the tree panel\n" red
		                } else {
                            set cmd "select_edge [list no_highlight all] [range_string] max 1 m [volume_activename_string] new_format edge_segment"
                            if $use_output_blocks { append cmd " output_blocks" }
                            hex_command $cmd
                            set clear_edges "[string trimright $last_line \n]"
                            if {$clear_edges != ""} {
                                hex_command "undo_major_start clear_association_edges"
                                foreach e $clear_edges {
                                    set cmd "set_edge_projection"
                                    append cmd " [lindex $e 0] [lindex $e 1] [lindex $e 2] 2 0"
                                    hex_command $cmd
                                }
                                hex_command "undo_major_end clear_association_edges"
                            }
		                }
		            }
		        }
		        if $resetFace {
		            if {$f_reset_method == "all"} {
		                hex_command "clear_association $top_current faces"
		            } else {
		                if ![::AIEnv::GUIManagement::Tree::NodeVisibility block_faceNode] {
		                    mess "Faces are not turned on in the tree panel\n" red
		                } else {
		                    if {[format %d [ic_hex_mesh_dimension]] != "2"} {
		                        set cmd "select_super_faces all max 1 icon [range_string] [family_activename_string]"
		                        if $use_output_blocks { append cmd " output_blocks" }
                                hex_command $cmd
                                set clear_faces "[string trimright $last_line \n]"
                                if {$clear_faces != ""} {
                                    hex_command "undo_major_start clear_association_faces"
                                    foreach f $clear_faces {
                                        set proj [string trimright [eval ic_hex_query_face_proj $f] \n]
                                        if {$proj != "DEFAULT"} {
                                            if {[string match "SELECTED SURFACE -*" $proj]} {
                                                hex_command "unproject_face node_numbers \{ $f \}"
                                            } elseif {[string match "INTERPOLATE" $proj]} {
                                                hex_command "unproject_face node_numbers \{ $f \}"
                                            } elseif {[string match "SURFACE PART -*" $proj]} {
                                                hex_command "project_face node_numbers \{ $f \} any"
                                            } elseif {$proj == ""}  {
                                                hex_command "unproject_face node_numbers \{ $f \}"
                                            }
                                        }
                                    }
                                    hex_command "undo_major_end clear_association_faces"
                                }
                            }
                        }
		            }
		        }
	        }
	        hex_update_display vertex edge face block mesh
	        mess "Done "; mess "reset " blue; mess "association\n"
	    }
        7 { # project verts
	        if $projVUpdateGGVal {
		        aie_update_vert_proj $projVerts $move_ogrid
		        set projVerts ""
	        } else {
		        aie_update_vert_proj active $move_ogrid
	        }
	        mess "Done project vertices\n"
	    }
        8 {
	        if ![ic_hex_blocking_loaded] {
		        msg ERROR "Composite Curve Grouping is available only with blocking loaded"
		        return
	        }
	        switch $groupEGVal {
		        0 {
		            switch $groupTypeVal {
			            0 {
			                if {$groupCurvesList == ""} {
				                msg ERROR "No curve selected for grouping"
				                return
			                }
			                # We have to do a trick here because we can't include in the list
			                # curves that are "owned" by another composite, or the creation command
			                # will not work.
			                catch {unset dont_use}
			                set projcurves ""
			                foreach compcurve $groupCurvesList {
				                hex_command "get_proj_curves $compcurve"
				                foreach c [lrange $last_line 1 end] {
				                    set dont_use($c) 1
				                }
				                foreach c $last_line {
				                    lappend projcurves $c
				                }
			                }
			                set groupcurves ""
			                foreach c $projcurves {
				                if ![info exists dont_use($c)] {
				                    set dont_use($c) 1
				                    lappend groupcurves $c
				                }
			                }
			                ic_hex_create_composite $groupcurves
			                foreach curve $projcurves {
				                ic_redraw_geometry curve $curve
			                }
			                mess "Grouped curves: $groupcurves\n"
			            }
			            1 {
			                # Check build topo exists
			                set surfs [ic_geo_get_objects surface]
			                set need_build_topo 1
			                foreach surf $surfs {
				                if {[ic_geo_boundary surface $surf] != ""} {
				                    set need_build_topo 0
				                    break
				                }
			                }
			                if $need_build_topo {
				                set mess "This feature needs geometry connectivity. Do you want to run build topology?"
				                switch -- [tk_dialog .bodywarn "Group curve warning" $mess "" -1 Yes No] {
                                    -1 { if [winfo exists .bodywarn] { top_destroy .bodywarn; return } }
				                    0 {
					                    set topotol [aie_default_topo_tolerance]
					                    ic_build_topo $topotol -angle 0
				                    }
				                    1 { return }
				                }	
			                }
			                ic_hex_composite_curve tangential_curves
			                mess "Grouped all tangential curves\n"
			                # Kind of over kill, but have to refine curves
			                foreach curve [ic_geo_get_objects curve] {
				                ic_redraw_geometry curve $curve
			                }
			            }
			            2 {
			                ic_hex_composite_curve by_family
			                foreach curve [ic_geo_get_objects curve] {
				                ic_redraw_geometry curve $curve
			                }
#			                foreach part $groupPartList { ic_hex_composite_curve family $part }
			            }
		            }
		        }
		        1 {
		            if {$groupCurvesList == ""} {
			            msg ERROR "No curve selected for ungrouping"
			            return
		            }
		            foreach compcurve $groupCurvesList {
			            hex_command "get_proj_curves $compcurve"
			            set curves $last_line
			            hex_command "delete_composite $compcurve"
			            foreach curve $curves {
			                ic_redraw_geometry curve $curve
			            }
		            }
		            mess "Ungrouped curves: $groupCurvesList\n"
		        }
	        }
	        hex_update_display edge
	        set groupCurvesList ""
	        mess "Done group/ungroup curves\n"
	    }
	    9 { # Auto association	   
	        set surfs [ic_geo_get_objects surface]
	        set need_build_topo 0
	        foreach surf $surfs {
		        if {[ic_geo_boundary surface $surf] == ""} {
		            set need_build_topo 1
		        }
	        }
	        if $need_build_topo {
		        set mess "This feature needs geometry connectivity. Do you want to run build topology?"
		        switch -- [tk_dialog .auto_assoc_warn "Auto association warning" $mess "" -1 Yes No] {
		            -1 { if [winfo exists .auto_assoc_warn] { top_destroy .auto_assoc_warn; return } }
		            0 {
			            aie_apply_other_dez repairGeomDEZ repairSurfaceEGVal 0
		            }
		            1 { return }
		        }
	        }
	        ic_hex_auto_associate_geometry
	        ic_geo_reset_data_structures
	        if $auto_proj {
		        aie_update_vert_proj all 1
	        }
	        hex_update_display
	        mess "Done auto association\n"
	    }
    }
}

proc aie_topo_create_temp_visible {} {
    global top_current last_line use_output_blocks display_flag
   
    set top_current_save $top_current 
    hex_command "mark_blocks unmark" 0
    set cmd "select_blocks 1 [list no_highlight all] [range_string] m [volume_activename_string] -not_blanked"
    if $use_output_blocks { append cmd " output_blocks" }
    if $display_flag(block_ijk) { append cmd " orientation" }
    if $display_flag(block_super) { append cmd " super" }
    if $display_flag(block_solid) { append cmd " -solid" }
    if !$display_flag(block_struct) { append cmd " -hide_struct" }
    if !$display_flag(block_unstruct) { append cmd " -hide_unstruct" }
    if !$display_flag(block_swept) { append cmd " -hide_swept" }
    hex_command $cmd
    set blocks "[string trimright $last_line \n]"
    if {$blocks == ""} { return "" }
    block_mark_super $blocks
    set topos ""
    foreach topo [ic_hex_print_topo_tree] {
	    lappend topos [lindex $topo 0]
    }
    set top_name temp_topo_[pid]_
    for {set i 0} {[lsearch $topos $top_name] >= 0} {incr i} {
	    set top_name $top_name$i
	}
    if {$top_name == ""} { return "" }
    hex_command "extract_blocking $top_name"
    block_unmark
    hex_command "switch_blocking $top_name"
    return $top_name
}

proc aie_topo_delete_temp_visible {name} {
   
    if {$name == ""} return
    hex_command "delete_blocking $name"
}

proc oneditProjDEZCancel {} {
     if {[trace vinfo resetEdge] != ""} {
        trace vdelete resetEdge w aie_trace_reset_edge_ass
    }
}

proc aie_trace_reset_edge_ass {name element op} {
    if {[editProjDEZ get resetEdge] == "1"} {
        ::AIEnv::GUIManagement::ToggleGrey resetAssocEdgeAllRG 0
    } else {
        ::AIEnv::GUIManagement::ToggleGrey resetAssocEdgeAllRG 1
    }
}

##################### Mesh sizing stuff #############

proc aie_hex_update_mesh_params {} {
    global hex_option

    set fix [mParamsDEZ get blockParamSelVal]
    set arg "[volume_activename_string]"
    if {$fix == 2} {append arg " fix_counts"}
    if {$fix == 1} {append arg " fix_laws"}
    if {$fix == 3} {append arg " curve_bunching"}
    hex_command "set_mesh_params $arg -version 110"
    hex_mesh_size
}

proc onmParamsDEZLoad {} {
    global bunching_laws hex_option supported_laws_hex beta_mode
    
    if {$blockParamSelVal == ""} { set blockParamSelVal 0 }
    if {$factor == ""} { set factor 1 }
    mParamsDEZ setdirty

    set i 0
    catch { array unset ::supported_laws_hex }
    foreach item [lsort [array names bunching_laws]] {
        switch $item {
            UserDefined { if !$beta_mode continue }
        }
        lappend ::supported_laws_hex($i) $item 
        incr i
    }
    set eparamMeshLawVal 0
    
    if {$edgeRefDimGGVal == ""} { set edgeRefDimGGVal 0 } 
    if ![info exists eparamCopyVal] { set eparamCopyVal 0 }
    set eparam_np ""
    if ![info exists matchEdgeVal] { set matchEdgeVal 0 }
    if ![info exists edgeParamsEditVal] { set edgeParamsEditVal 0 }
    if ![info exists matchEdgesDimGGVal] { set matchEdgesDimGGVal 0 }
    if ![info exists edgeParamsCopyTo2Val] { set edgeParamsCopyTo2Val 0 }
    set SpacingTypes [list Minimum Maximum Average]
    if {$spacing == ""} { set spacing Minimum }
    set edge ""
    set curves ""
    set copy_absolute 0
    set copy_no_nodes 0
    set check_blck 0
    set length ""
    set n 2
    set lockNodes 0
    if [info exists hex_option(check_blck)] {
        set check_blck $hex_option(check_blck)
    }
}

proc onmParamsDEZAfterLoad {} {

    if {[trace vinfo eparamCopyVal] != ""} {
        trace vdelete eparamCopyVal w trace_display_edge_bunching
    }
    trace variable eparamCopyVal w trace_display_edge_bunching
    if {[trace vinfo copyFlag] != ""} {
        trace vdelete copyFlag w aie_hex_trace_copyFlag
    }
    trace variable copyFlag w aie_hex_trace_copyFlag   
    foreach i "link_sp1 link_sp2" {
        if {[trace vinfo $i] != ""} {
            trace vdelete $i w aie_hex_trace_link_spacing
        }
        trace variable $i w aie_hex_trace_link_spacing
    }
    aie_hex_lock_edge_nodes
    
    if [aie_wb2_is_running] {
        aie_wb2_wb_parameter_input_blocking_edge [lrange [mParamsDEZ get edge] 0 1]
    }
}

proc onmParamsDEZUnLoad {} {
    global hex_option

    if $hex_option(old_eparams) return

    if {[trace vinfo eparamCopyVal] != ""} {
        trace vdelete eparamCopyVal w trace_display_edge_bunching
    }
    if {[trace vinfo n] != ""} {
        trace vdelete n w trace_change_edge_bunching
    }
    if {[trace vinfo copyFlag] != ""} {
        trace vdelete copyFlag w aie_hex_trace_copyFlag
    }
    foreach i "link_sp1 link_sp2" {
        if {[trace vinfo $i] != ""} {
            trace vdelete $i w aie_hex_trace_link_spacing
        }
    }
    mParamsDEZ hexMeshParamsUpdate
    mParamsDEZ display_edge_bunching reset
}

foreach iiii {2 3 4 5} {
    proc oneparamCopy${iiii}Load {} {
	    if $auto_pick_mode {
	        if {$eparamCopyVal >= 2} {
		        eparamCopyPick${eparamCopyVal} pick
	        }
	    }
    }
}

# copy to edges
foreach iiii {2 3} {
    proc oneparamCopyPick${iiii}Finish {} {
        if {$copyEdge != ""} {
	        if {[trace vinfo n] != ""} {
	            trace vdelete n w trace_change_edge_bunching
	        }
    	    set cur_edge $edge
	        if {$eparamCopyVal == 3} {
	            mParamsDEZ aie_hex_reverse_params 0
	        }
	        foreach edge $copyEdge {
	            set emparams [ic_hex_mesh_params [lindex $edge 0] [lindex $edge 1]]
		        set lw [lindex $emparams 0]
		        if {$lw == "linear" || $lw == "spline" || $lw == "userdefined" } {
			        set nodes_locked ""
			        set params_locked 0
		        } else {
			        set nodes_locked [lindex $emparams 14]
			        set params_locked [lindex $emparams 6]
		        }
	            if {$nodes_locked == "n_locked"} {
		            mess "Error in copy; nodes locked for edge: [lindex $edge 0]-[lindex $edge 1]\n" red
	            } elseif {$params_locked == "1"} {
		            mess "Error in copy; mesh params locked for edge: [lindex $edge 0]-[lindex $edge 1]\n" red
	            } else {
		            mParamsDEZ aie_hex_apply_mparams
	            }
	        }
	        set copyEdge ""
	        set edge $cur_edge
	        mParamsDEZ display_edge_bunching
	        trace variable n w trace_change_edge_bunching
        }
    }
}

# copy from edges
foreach iiii {4 5} {
    proc oneparamCopyPick${iiii}Finish {} {
        if {$copyEdge != ""} {
	        if {[trace vinfo n] != ""} {
	            trace vdelete n w trace_change_edge_bunching
	        }
	        set emparams [ic_hex_mesh_params [lindex $edge 0]  [lindex $edge 1]]
	        set lw [lindex $emparams 0]
	        if {$lw == "linear" || $lw == "spline" || $lw == "userdefined" } {
		        set nodes_locked ""
		        set params_locked 0
	        } else {
		        set nodes_locked [lindex $emparams 14]
		        set params_locked [lindex $emparams 6]
	        }
	        if {$nodes_locked == "n_locked"} {
	            mess "Error in copy; nodes locked for edge: [lindex $edge 0]-[lindex $edge 1]\n" red
	            return
	        } elseif {$params_locked == "1"} {
	            mess "Error in copy; mesh params locked for edge: [lindex $edge 0]-[lindex $edge 1]\n" red
	            return
	        }
	        mParamsDEZ hexMeshParamsUpdate 1 "" $copyEdge
	        if {$eparamCopyVal == 5} {
	            mParamsDEZ aie_hex_reverse_params
	        } else {
	            mParamsDEZ aie_hex_apply_mparams
	        }
	        set copyEdge ""
	        trace variable n w trace_change_edge_bunching
        }
    }
}

proc aie_hex_set_law {law} {
    global supported_laws_hex
    
    if {[mParamsDEZ get eparamMeshLawVal] < 0} {
        return
    }
    foreach l [array names ::supported_laws_hex] {
        if {$::supported_laws_hex($l) == "$law"} {
             mParamsDEZ set eparamMeshLawVal $l
             break
        }
    }
}

proc hexMeshParamsUpdate {{update_all 1} {params ""} {tedge ""}} {
    global bunching_laws beta_mode
    global eparam_sp1 eparam_sp2 eparam_spmax eparam_rat1 eparam_rat2
    global eparam_save eparam_density eparam_length eparam_func
    global eparam_edge eparam_np last_line eparam_locked eparam_nlocked
    global eparam_law eparam_highlight_dep display_linked_to
    global eparam_linked eparam_linkedijk
    global eparam_actual display_flag edge_meshc_done
    global edge_meshc_params edge_meshc_points mesh_eparam_editcv
    global mesh_eparam_editspc sp1_linked sp2_linked
    global eparam_nlocked eparam_rel
    
    if $update_all {
        set n 0
    }
    if {$tedge == ""} {
        set tedge $edge
    }

    set length ""
    set h1 ""
    set h1act ""
    set h2 ""
    set h2act ""
    set r1 ""
    set r1act ""
    set r2 ""
    set r2act ""
    set lmax ""
    set lmaxact ""

    set lockNodes 0

    if {$tedge == ""} return
      
    if {$params == ""} {
        set edge_mparams [string trimright [ic_hex_mesh_params [lindex $tedge 0] [lindex $tedge 1]] \n]
    } else {
        set edge_mparams $params
    }
    set law [lindex $edge_mparams 0]

    if {![string compare $law "linear"] || ![string compare $law "spline"]} {
        set islinear 1
    } else {
        set islinear 0
    }
    if {[lindex [lindex $edge_mparams 0] 0 ] == "userdefined" && $beta_mode} {
	    global eparam_family
	    set eparam_law [lindex [lindex $edge_mparams 0] 0 ] 
        aie_hex_set_law [mesh_law_names $eparam_law]
	    set eparam_family [lindex [lindex $edge_mparams 1] 0 ]
	    set law_part_name $eparam_family
	    set eparam_np [lindex [lindex $edge_mparams 2] 0]
	    set n $eparam_np
    } elseif ![string compare [lindex $edge_mparams 0] "linked"] {
        if {[lindex $edge_mparams 2] == "locked"} {
            set lockParams 1
            set n [lindex $edge_mparams 3]
        } else {
            set lockParams 0
            set n [lindex $edge_mparams 2]
        }
        set linkFlag 1
	    set linkEdge [lindex $edge_mparams 1]
        set nprev $n
        set law ""
    } else {
	if $islinear {
	    # extract the law name and the # of points
	    set eparam_law [mesh_law_names [lindex $edge_mparams 0]]
	    set eparam_func $eparam_law
	    set eparam_np [lindex $edge_mparams 1]
	    if $update_all {
		    set n $eparam_np
		    set nprev $n
	    }
	    set np [lindex $edge_mparams 2]

	    set mesh_eparam_editcv 1
	    set mesh_eparam_editspc 0
	   
	    # can get into update 2 ways: 1) after an apply
	    # as a selection (ie requires initialization)
	    # do this first because both setcurvetype and
	    # setnpoints will initialize things in case
	    # the form is not initialized
	   
	    set isinit [info exists edge_meshc_params(formup)]
	   
	    edge_meshc_setcurvetype $eparam_law
	    edge_meshc_setnpoints $eparam_np
	    if [info exists eparam_length] {
		    edge_meshc_setlength $eparam_length
	    }
	    # if form is already up, don't want to do this
	   
	    if !$isinit {		   
		set density ""
		set firstx 0.0
		set lastx 0.0
		
		for {set i 0} {$i < $np} {incr i} {
		    set x [lindex $edge_mparams [expr 2*$i+3]]
		    set y [lindex $edge_mparams [expr 2*$i+4]]
		    append density "$x $y "
		   
		    if {$i == 0} {
			set firstx $x
		    } elseif {$i == $np-1} {
			set lastx [expr 1.0 - $x]
		    }
		}
		
		# is the length on the line?

		set ll [llength $edge_mparams]
		if {$ll == 2*$np + 4} {
		    set eparam_length [expr [lindex $edge_mparams [expr 2*$np + 3]] * 1.0]
		} else {
		    set eparam_length 1.0
		}
		set length $eparam_length
		edge_meshc_setlength $eparam_length
		
		edge_meshc_setcallback eparam_density_callback mesh_law_names edge_meshc_filebrowser
		   
		# if we have no density, use default density
		# ((0, 1) to (1, 1))
		
		if {$density == ""} {
		   
		    mesh_eparam_initedgepoints
		    edge_meshc_setinitpoints
		   
		    set eparam_density [edge_meshc_screentocoord $edge_meshc_points(0)]
		} else {

		    # use given density set on the points
		   
		    edge_meshc_setinitpoints $density
		    set eparam_density $density
		   
		    if {$firstx == 0.0} {
			set edge_meshc_params(edgepointsactive) 0
			set lastx 0.0
		    } else {
			set edge_meshc_params(edgepointsactive) 1
			
			# set the current actual spacings
			
			set eparam_actual(sp1) $edge_meshc_params(asp1)
			set eparam_actual(sp2) $edge_meshc_params(asp2)
		    }
		    set edge_meshc_params(fe) $firstx
		    set edge_meshc_params(sp1) $firstx
		    set edge_meshc_params(asp1) [expr $firstx*$eparam_length]
			
		    set edge_meshc_params(le) $lastx
		    set edge_meshc_params(sp2) $lastx
		    set edge_meshc_params(asp2) [expr $lastx*$eparam_length]
		   
		    set edge_meshc_params(clength) [expr 1.0-$firstx-$lastx]
			edge_meshc_edgeminmax
		}
	    } else {
		    catch {edge_meshc_update 1}
		    set eparam_density [edge_meshc_screentocoord $edge_meshc_points(0)]
	    }
	    set eparam_linked 0
	    set eparam_linkedijk ""
	    foreach name [array names bunching_laws] {
		    if {$law == $bunching_laws($name)} {
		        aie_hex_set_law $name
		        break
		    }
	    }
	} else {
	    # get standard spacing + bunching law
	    if {[llength $edge_mparams] < 9} {
		    mess "Expecting 9 params from mesh_params\n" red
		    return
	    }
	    if $update_all {
		    set n [lindex $edge_mparams 0]
		    set nprev $n
	    }
	    set h1 [lindex $edge_mparams 1]
        if {$eparam_rel && [lindex $h1 0] != "linked"} { 
            set h1 [expr ($h1 + .0) / [lindex $edge_mparams 5]]
        }
	    set r1 [lindex $edge_mparams 2]
	    set h2 [lindex $edge_mparams 3]
        if {$eparam_rel && [lindex $h2 0] != "linked"} {
            set h2 [expr ($h2 + .0) / [lindex $edge_mparams 5]]
        }
	    set r2 [lindex $edge_mparams 4]
	    set length [expr [lindex $edge_mparams 5] * 1.0]
	    set lockParams [lindex $edge_mparams 6]
	    set tlaw [lindex $edge_mparams 7]
	    set lmax [lindex $edge_mparams 8]
	    set h1act [lindex $edge_mparams 9]
	    set r1act [lindex $edge_mparams 10]
	    set h2act [lindex $edge_mparams 11]
	    set r2act [lindex $edge_mparams 12]
	    set lmaxact [lindex $edge_mparams 13]
	    foreach name [array names bunching_laws] {
		    if {$tlaw == $bunching_laws($name)} {
		        aie_hex_set_law $name
		        break
		    }
	    }
	    set linkFlag 0
	    set linkEdge ""	
		if {[lindex $h1 0] == "linked"} {
		    set link_sp1 1
		} else {
		    set link_sp1 0
		}
		if {[lindex $h2 0] == "linked"} {
		    set link_sp2 1
		} else {
		    set link_sp2 0
		}
	    # check for number of nodes locked
            if {[ llength $edge_mparams ] >= 15 && [lindex $edge_mparams 14 ] == "n_locked"}  {
                set lockNodes 1
		        aie_hex_lock_edge_nodes 
            } else {
		        set lockNodes 0
		        aie_hex_lock_edge_nodes
	        }
	    }
    }
}

proc aie_hex_lock_edge_nodes {} {
    mParamsDEZ lock_edge_nodes
}

proc lock_edge_nodes {} {
    set reset_n [mParamsDEZ get n]
    if $lockNodes {
        ::AIEnv::GUIManagement::ToggleGrey editEdgeParamNum 1
    } else {
        ::AIEnv::GUIManagement::ToggleGrey editEdgeParamNum 0
    }
    mParamsDEZ set n $reset_n
}

proc aie_hex_eparam_sellink { var_name } {

    set link_edge [select_hexa edge 1 "Please select the edge to link to" "new_format selected_bunching"]
    if {$link_edge == ""} return
    mParamsDEZ set $var_name "linked [lrange $link_edge 0 1]"
    mParamsDEZ set lockParams 1
    mParamsDEZ display_edge_bunching
}

proc aie_hex_eparam_revlink { var_name } {
    global $var_name

    set var [mParamsDEZ get $var_name]
    if {![string compare [lindex $var 0] "linked"]} {
        set e1 [lindex $var 1]
        set e2 [lindex $var 2]
        mParamsDEZ set $var_name "linked $e2 $e1"
    } else {
        if {[llength $var] == 2} {
            set e1 [lindex $var 0]
            set e2 [lindex $var 1]
            mParamsDEZ set $var_name "$e2 $e1"
        }
    }
}

proc oneditEdgeParamEdgeFinish {} {
    if {[trace vinfo n] != ""} {
        trace vdelete n w trace_change_edge_bunching
    }
    if {$edge != ""} {
        mParamsDEZ hexMeshParamsUpdate	
        mParamsDEZ display_edge_bunching
        mParamsDEZ aie_hex_apply_mparams 0
        trace variable n w trace_change_edge_bunching
        set cur_params [ic_hex_mesh_params [lindex $edge 0]  [lindex $edge 1]]
        lappend prev_medges $edge
        lappend prev_mparams $cur_params
        if {[lsearch $cur_params linked] > -1} {
            ::AIEnv::GUIManagement::ToggleGrey editEdgeLinkGI 0
        } else {
            ::AIEnv::GUIManagement::ToggleGrey editEdgeLinkGI 1
        }
    }
    if [aie_wb2_is_running] {
        aie_wb2_wb_parameter_input_blocking_edge [lrange [mParamsDEZ get edge] 0 1]
    }
}

proc trace_change_edge_bunching {name element op} {
    global edge_bunching_after_id 
    if {[mParamsDEZ get $name] < 2} return
    if {$name == "n"} {
        if ![info exists edge_bunching_after_id] {
            trace_change_edge_bunching_apply $name
        }
    } else {
        if [info exists edge_bunching_after_id] {
            after cancel trace_change_edge_bunching_apply $name
        }
        set edge_bunching_after_id [after 500 trace_change_edge_bunching_apply $name]
    }
}

proc aie_hex_trace_copyFlag {name element op} {

    if [mParamsDEZ get copyFlag] {
        ::AIEnv::GUIManagement::ToggleGrey eparamCopy 0
        ::AIEnv::GUIManagement::ToggleGrey editEdgeParamAbs 0
    } else {
        ::AIEnv::GUIManagement::ToggleGrey eparamCopy 1
        ::AIEnv::GUIManagement::ToggleGrey editEdgeParamAbs 1
    }
}

proc aie_hex_trace_link_spacing {name element op} {
    set var [lindex [split $name :] end]
    switch $var {
        link_sp1 { set sp [mParamsDEZ get h1] }
        link_sp2 { set sp [mParamsDEZ get h2] }
        default { return }
    }
    if {[lindex $sp 0] != "linked"} {
        return
    }
    set on [mParamsDEZ get $var]
    if !$on {
        switch $var {
            link_sp1 {
                mParamsDEZ set h1 1e+010
            }
            link_sp2 {
                mParamsDEZ set h2 1e+010
            }
        }
    }
}

proc trace_change_edge_bunching_apply {name} {
    if {[mParamsDEZ get $name] > 1} {
        if {$name == "n"} {
            set on 0
        } else {
            set on 1
        }
        mParamsDEZ mparams_noreset $on
        mParamsDEZ apply
    }
}

proc mparams_noreset {{on 1}} {
    if $on {
        set no_reset 1
    } elseif [info exists no_reset] {
        unset no_reset
    }
}

proc trace_display_edge_bunching {name element op} {
    mParamsDEZ display_edge_bunching
    if [aie_wb2_is_running] {
        aie_wb2_wb_parameter_input_blocking_edge [lrange [mParamsDEZ get edge] 0 1]
    }
}

proc oneditEdgeLinkPickFinish {} {
    if {$linkEdge != ""} {
        set linkEdge "linked [lindex $linkEdge 0] [lindex $linkEdge 1]"
        set lockParams 1
    }
}

proc aie_hex_scale_linkfactor {num {dez ""}} {
    global scale_linkfactor
    
    if [info exists scale_linkfactor] return
    set scale_linkfactor 1
    set factor [editEdgeMenuDEZ get factor]
    set edgeSLink [editEdgeMenuDEZ get edgeSLink]
    if {$edgeSLink == ""} {
        unset scale_linkfactor
        return
    }
    set s1 [lindex $edgeSLink 0]
    set s2 [lindex $edgeSLink 1]
    set edgeTLinks [editEdgeMenuDEZ get edgeTLinks]
    if {$edgeTLinks == ""} {
        unset scale_linkfactor
        return
    }
    foreach t $edgeTLinks {
        set t1 [lindex $t 0]
        set t2 [lindex $t 1]
        set cmd "link_shape $t1 $t2 $s1 $s2 $factor"
        hex_command $cmd
   }
   hex_update_display
   unset scale_linkfactor
}

proc aie_hex_reverse_link {} {
    set ledge [mParamsDEZ get linkEdge]
    if {![string compare [lindex $ledge 0] "linked"]} {
        set e1 [lindex $ledge 1]
        set e2 [lindex $ledge 2]
        mParamsDEZ set linkEdge "linked $e2 $e1"
    } else {
        if {[llength $ledge] == 2} {
            set e1 [lindex $ledge 0]
            set e2 [lindex $ledge 1]
            mParamsDEZ set linkEdge "$e2 $e1"
        }
    }
}

proc display_edge_bunching {{action ""}} {
    if {$action == "reset"} {
	    hex_update_display edge
	    return
    }
    if {$edge != ""} {
	    set opts [display_edge_mesh_params ]
	    set cmd "display_edge_mesh $opts selected_bunching"
	    if { $hlAttached } {
	        append cmd " -faces"
	    }

	    if { $hlMaster && $linkEdge != "" } {
	        append cmd " color:yellow $linkEdge"
        }

	    append cmd " highlight"
	    if {$copyFlag && ($eparamCopyVal == 0 || $eparamCopyVal == 1)} {
	        append cmd " parallel"
	    } elseif { $hlDependent } {
	        append cmd " linked"
	    }
	    append cmd " [lindex $edge 0] [lindex $edge 1]"
	    hex_command $cmd
    }
}

proc aie_hex_update_h1h2 {} {
    mParamsDEZ onedgeParamS_update_h1h2
}

proc onedgeParamS_update_h1h2 {} {
    foreach val "h1 h2 length" {
        if {[set $val] == ""} return
    }
    if { $eparam_rel } {
        set h1 [expr $h1 / ($length * 1.0)]
        set h2 [expr $h2 / ($length * 1.0)]
    } else {
        set h1 [expr $h1 * ($length * 1.0)]
        set h2 [expr $h2 * ($length * 1.0)]
    }
}

proc onedgeRefDimPickFinish {} {
    if {$ref_dim != ""} {
        set ref_dim [lindex $ref_dim 1]
    }
}

proc aie_hex_reverse_law { lname } {
    switch $lname {
	geo1 {
	    return geo2
	}
	"Geometric1" {
	    return "Geometric2"
	}
	geo2 {
	    return geo1
	}
	"Geometric2" {
	    return "Geometric1"
	}
	"Exponential1" {
	    return "Exponential2"
	}
	"Exponential2" {
	    return "Exponential1"
	}
	exp1 {
	    return exp2
	}
	exp2 {
	    return exp1
	}
	"HalfCosinus1" {
	    return "HalfCosinus2"
	}
	"HalfCosinus2" {
	    return "HalfCosinus1"
	}
	hcosinus1 {
	    return hcosinus2
	}
	hcosinus2 {
	    return hcosinus1
	}
	default {
	    return $lname
	}
    }
}

proc aie_hex_reverse_params {{apply 1}} {
    global bunching_laws 
    global eparam_edgelist eparam_sp1 eparam_sp2 eparam_spmax
    global eparam_rat1 eparam_rat2 eparam_law eparam_density eparam_length
    global eparam_np eparam_locked eparam_parallel eparam_parallelv
    global display_flag eparam_linked eparam_linkedijk eparam_scale
    global edge_meshc_params edge_meshc_points mesh_eparam_editcv
    global mesh_eparam_editspc eparam_curedgelist eparam_func
    global eparam_nlocked eparam_rel eparam_family supported_laws_hex

    if {$edge == ""} {
	    msg ERROR "No edge selected for setting params"
	    return
    }
    
    set law $::supported_laws_hex([mParamsDEZ get eparamMeshLawVal])
    if {$law == "Spline" || $law == "Linear"} {
	    edge_meshc_reverse x $graphformup
	    set eparam_density [edge_meshc_screentocoord $edge_meshc_points(0)]
    } else {
	    set th1 $h1; set h1 $h2; set h2 $th1
	    set tr1 $r1; set r1 $r2; set r2 $tr1

	    if [info exists bunching_laws($law)] {
	        set lname [aie_hex_reverse_law $bunching_laws($law)]
	        foreach name [array names bunching_laws] {
		        if {$lname == $bunching_laws($name)} {
		            aie_hex_set_law $name
		            break
		        }
	        }
	    }
    }
    if $apply {
	    mParamsDEZ apply
    }
}

proc aie_hex_screen_params {} {
    global display_flag button_instructions
    global select_in_dynamics

    if {$edge == ""} {
        msg ERROR "No edge selected for setting params"
        return
    }
    banner "Modify the edge meshing $button_instructions"
    set ::select_in_dynamics 0
    tdv_set_key_command F9 select_hexa_toggle_dynamics
    set cmd "dynamic_edge_mesh [lindex $edge 0] [lindex $edge 1] [range_string] m [volume_activename_string]"
    if $display_flag(edge_vol) { append cmd " volume" }
    hex_command $cmd
    banner ""
    mess "Done\n"

    mParamsDEZ hexMeshParamsUpdate 0
    mParamsDEZ display_edge_bunching
}

proc aie_hex_mesh_law_modified {{a ""} {b ""}} {
    global bunching_laws supported_laws_hex

    if {[mParamsDEZ get eparamMeshLawVal] < 0} return
    set law $::supported_laws_hex([mParamsDEZ get eparamMeshLawVal])

    if {$law == "On-Screen"} {
	    mParamsDEZ aie_hex_screen_params
    } elseif {$law == "Linear" || $law == "Spline"} {
	    mParamsDEZ aie_hex_graph_params $law
    } elseif {$law == "From-Graphs"} {
	    mParamsDEZ aie_hex_graph_params
    } elseif {$law == "FromEdgeSplits"} {
        set e [mParamsDEZ get edge]
        if {$e != ""} {
            set nseg [ic_hex_get_edge_segment_number [lindex $e 0] [lindex $e 1]]
            if  {$nseg < 2} {
                mess "Mesh law \"FromEdgeSplits\" can only be applied to edges that have edge splits, resetting law to \"BiGeometric\"\n" red
                mParamsDEZ set eparamMeshLawVal 0
            } else {
                mess "Setting number of nodes to [expr $nseg + 1] for Mesh law \"FromEdgeSplits\"\n"
                mParamsDEZ set n [expr $nseg + 1]
            }
        }
    } elseif {$law == "ReferenceMesh"} {
        if ![ic_uns_is_loaded] {
           mess "No mesh loaded, resetting law to \"BiGeometric\"\n" red
           mParamsDEZ set eparamMeshLawVal 0
           return
        }
    } else {
    
    }
}

proc onedgeParamSLoad {} {
    global hex_option
    
    set hex_option(old_eparams) 0
    if $hex_option(old_eparams) {
	    editBlockMenuDEZ setclean
	    after 1 aie_hex_edge_meshing
	    set blockParamVal -1
	    mParamsDEZ setclean
	    return
    }

    set edge ""
    mParamsDEZ hexMeshParamsUpdate
    mParamsDEZ display_edge_bunching

    set prev_mparams ""
    set prev_medges ""

    editEdgeParamEdge pick
}

proc onedgeParamSUnLoad {} {

    if $hex_option(old_eparams) return
    set edge ""
    display_edge_bunching reset
    if {[trace vinfo n] != ""} {
	    trace vdelete n w trace_change_edge_bunching
    }
    set prev_mparams ""
    set prev_medges ""
}

proc aie_hex_apply_mparams {{apply 1}} {
    global hex_option bunching_laws 
    global eparam_edgelist eparam_sp1 eparam_sp2 eparam_spmax
    global eparam_rat1 eparam_rat2 eparam_law eparam_density eparam_length
    global eparam_np eparam_locked eparam_parallel eparam_parallelv
    global display_flag eparam_linked eparam_linkedijk eparam_scale
    global edge_meshc_params edge_meshc_points mesh_eparam_editcv
    global mesh_eparam_editspc eparam_curedgelist eparam_func
    global eparam_nlocked eparam_rel eparam_family beta_mode
    global supported_laws_hex last_line

    set stuff ""
    set copy_to_parallel 0
    set linked1 0
    set linked2 0

    set valid [mParamsDEZ get n]
    if {![string is integer $valid] && [string index $valid 0] != "\$"} {
        mess "Invalid input for number of \"Nodes\": $n\n" red
        return
    }
    
    set law $::supported_laws_hex([mParamsDEZ get eparamMeshLawVal])
    
    if $linkFlag {
        if {$linkEdge == ""} {
	        msg ERROR "No edge selected to link bunching"
	        return
	    }
	    set cmd "set_mesh [lindex $edge 0] [lindex $edge 1]"
	    if {[lindex $linkEdge 0] != "linked"} {
	        append cmd " linked $linkEdge"
        } else {
            append cmd " $linkEdge"
        }
        
    } else {
    	if {$law == "UserDefined" && $beta_mode} {
		    if {$law_part_name == ""} {
		        mess "Missing law part name\n" red
		        return
		    }
		    set eparam_family $law_part_name
		    set eparam_np $n
		    set stuff "userdefined $eparam_family n $eparam_np"
        } elseif {$law == "FromEdgeSplits"} {
            set nseg [ic_hex_get_edge_segment_number [lindex $edge 0] [lindex $edge 1]]
            if  {$nseg < 2} {
                mess "Mesh law \"FromEdgeSplits\" can only be applied to edges that have edge splits, resetting law to \"BiGeometric\"\n" red
                mParamsDEZ set eparamMeshLawVal 0
                return
            } else {
                if {[ic_hex_get_edge_curve_type [lindex $edge 0] [lindex $edge 1]] != "0"} {
                    mess "Mesh law \"FromEdgeSplits\" can only be applied to edges that have edge splits created using method \"Linear\", resetting law to \"BiGeometric\"\n" red
                    mParamsDEZ set eparamMeshLawVal 0
                    return
                }
                if {$nseg != [expr $n - 1]} {
                    mess "Mesh law \"FromEdgeSplits\" requires that the number of nodes must match the number of edge splits + 2,\
                        resetting number of nodes to [expr $nseg + 1]\n" red
                    set n [expr $nseg + 1]
                }
            }
            set nprev $n
            if [info exists bunching_laws($law)] {
                set law_exp $bunching_laws($law)
            } else {
                mess "Bunching Law: $law not supported\n" red
                return
            }
            set stuff "n $n $law_exp"
            set cmd "set_mesh [lindex $edge 0] [lindex $edge 1] $stuff"
        } elseif {$law == "ReferenceMesh"} {
            set nprev $n
            if {$apply == 0} return
            if ![ic_uns_is_loaded] {
                mess "No mesh loaded, resetting to previous mesh law\n" red
                return
            }
            if {$curves == ""} {
                mess "Missing curve name(s), resetting to previous mesh law\n" red   
                return
            }
            set nelems 0
            foreach c $curves {
                set s [ic_uns_get_attached_elements curve [lindex $c 0]]
                incr nelems [ic_uns_subset_count_elements $s]
                ic_uns_subset_delete $s
            }
            if !$nelems {
                mess "Unable to set mesh law \"ReferenceMesh\" for edge [lindex $edge 0] [lindex $edge 1], resetting to previous mesh law\n" red
                return
            }
            if {[llength $curves] > 1} {
	            set projcurves ""
	            foreach compcurve $curves {
		            hex_command "get_proj_curves $compcurve"
		            foreach c $last_line {
		                lappend projcurves $c
		            }
	            }
	            ic_hex_create_composite $curves
	            foreach curve $projcurves {
		            ic_redraw_geometry curve $curve
	            }
	            mess "Grouped curves: $curves\n" blue
	        }
		    set cmd "set_edge_projection [lindex $edge 0] [lindex $edge 1] [lindex $edge 2] 1 [lindex $curves 0] -from_mesh"
			if ![ic_hex_ref_mesh_set] {
			     set stat [aie_hex_ref_uns_mesh]
			     if $stat return
			} else {
			    aie_hex_ref_uns_mesh
			}
			hex_command $cmd
			set n [lindex [ic_hex_mesh_params [lindex $edge 0] [lindex $edge 1]] 0] 
			set curves ""
			mParamsDEZ display_edge_bunching
			return
        } elseif {$law == "Spline" || $law == "Linear"} {
            # spline stuff.
            set eparam_law $law
            set mesh_eparam_editcv 1
            set mesh_eparam_editspc 0
            set eparam_func $eparam_law  
            # If this is an intialization -- set defaults
            set graphformup [info exists edge_meshc_params(formup)]
            if $graphformup {		
                # implicit apply of current parameters on form
                # if we apply with the form up IFF commitform
                # parameter is 1
                if $commitform {
                    set eparam_density [edge_meshc_screentocoord $edge_meshc_points(0)]
                }
            }
            if {$eparam_density == ""} {		
                edge_meshc_setcallback eparam_density_callback mesh_law_names edge_meshc_filebrowser
                edge_meshc_setcurvetype $eparam_law
                edge_meshc_setnpoints $eparam_np
                edge_meshc_setlength $eparam_length
                # set the initial edge spacings and control points
                mesh_eparam_initedgepoints
                edge_meshc_setinitpoints
                # set the initial point list
                set eparam_density [edge_meshc_screentocoord $edge_meshc_points(0)]
            } else {
                set len [llength $eparam_density]
                set firstx [lindex $eparam_density 0]
                if {$firstx == 0.0} {
                    set edge_meshc_params(edgepointsactive) 0
                } else {
                    set edge_meshc_params(edgepointsactive) 1
                }
            }
            set key ""
            if $edge_meshc_params(edgepointsactive) {
                set key "end_spacing"
            }
            set np [expr [llength $eparam_density]/2]
            set stuff "n $n [mesh_law_names $eparam_law] $np $eparam_density $key"
        } else {
            set nmgl $hex_option(multigrid_level)
            set delta [expr int(pow(2,$nmgl))]
            set np $n
            if {[info exists nprev]} {
                if {$n > $nprev} {	   
                    set np [expr $np - 1 + $delta]
                } elseif {$n < $nprev} {
                    if {$n > [expr (1 + $delta)]} {
                        set np [expr $np + 1 - $delta]
                    }
                }
            }
            if {$np < [expr (1 + $delta)]} {
                if {$apply && $nmgl > 0} {
                    mess "Current \"Multigrid level\" of $nmgl requires minimum number of nodes of [expr (1 + $delta)]\n"
                    set n [expr (1 + $delta)]
                }
                return
            }
            set n $np
            set nprev $n
            set params "n $np"
            if  {$h1 != "" && [lsearch $h1 linked] < 0} { set h1 [expr $h1 * 1.0] }
            if  {$h2 != "" && [lsearch $h2 linked] < 0} { set h2 [expr $h2 * 1.0] }
            if {$eparam_rel} {
                if  {$h1 != ""} {append params " h1rel $h1"}
                if  {$h2 != ""} {append params " h2rel $h2"}
            } elseif {!$absolute && $copyFlag} {
                if {$h1 != ""} {
                    if {[lsearch $h1 linked] > -1} {
                        set linked1 1
                        append params " h1rel $h1"
                    } else {
                        append params " h1rel [expr ($h1 + .0)/$length]"
                    }
                }
                if  {$h2 != ""} {
                    if {[lsearch $h2 linked] > -1} {
                        set linked2 1
                        append params " h2rel $h2"
                    } else {
                        append params " h2rel [expr ($h2 + .0)/$length]"
                    }
                }
            } else {
                if  {$h1 != ""} {append params " h1 $h1"}
                if  {$h2 != ""} {append params " h2 $h2"}
            }
            if  {$r1 != ""} {append params " r1 $r1"}
            if  {$r2 != ""} {append params " r2 $r2"}
            if  {$lmax != ""} {append params " lmax $lmax"}
            if [info exists bunching_laws($law)] {
                set law_exp $bunching_laws($law)
            } else {
                if {!$linkFlag && $linkEdge != "" && $law == ""} {
                    mess "Unlink edge [lindex $edge 0] [lindex $edge 1] from edge $linkEdge\n"
                    set law_exp default
	            } else {
                    msg ERROR "Bunching Law: $law not supported"
                    return
                }
            }
            append params " $law_exp"
            set stuff $params
        }
        set cmd "set_mesh [lindex $edge 0] [lindex $edge 1] $stuff"
    }
    
    if {$copyFlag && ($eparamCopyVal == 0 || $eparamCopyVal == 1)} {
	    append cmd " copy_to_parallel"
	    set copy_to_parallel 1
        if {$eparamCopyVal == 1} {
            append cmd " [range_string] m [family_activename_string]"
        }
        if $absolute {
            append cmd " no_scale"
        }
    }
    if {$lockParams == 1} {
        append cmd " locked"
    } else {
        append cmd " unlocked"
    }

    if $lockNodes {
        append cmd " nlocked"
    }

    if $apply {
        if {$copy_to_parallel && ($linked1 || $linked2)} {
            if $linked1 {
                if [aie_hex_is_linked_edge_parallel $h1 $edge] {
                    msg ERROR "Circular link is not allowed!"
                    return
                }
            }
            if $linked2 {
                if [aie_hex_is_linked_edge_parallel $h2 $edge] {
                    msg ERROR "Circular link is not allowed!"
                    return
                }
            }
        } else {
            if $link_sp1 {
                if {[lsearch $h1 linked] < 0} {
                    msg ERROR "No edge selected to link \"Spacing 1\""
                    return
                } else {
                    if {[lrange $h1 1 2] == [lrange $edge 0 1]} {
                        msg ERROR "\"Spacing 1\": don't link an edge to itself"
                        return
                    }
                }
            } 
            if $link_sp2 {
                if {[lsearch $h2 linked] < 0} {
                    msg ERROR "No edge selected to link \"Spacing 2\""
                    return
                } else {
                    if {[lrange $h2 1 2] == [lrange $edge 0 1]} {
                        msg ERROR "\"Spacing 2\": don't link an edge to itself"
                        return
                    }
                }
            }
        }
	    hex_command $cmd
        # Display the changed bunching
        mParamsDEZ display_edge_bunching
        if {$hex_option(multigrid_level) > 0} {       
            set cur_n [lindex [ic_hex_mesh_params [lindex $edge 0] [lindex $edge 1]] 0]
            if {[string is integer -strict $cur_n] && $n != $cur_n} {
                set n $cur_n
            }
        }
    }
}

proc aie_hex_is_linked_edge_parallel {h edge} {

    set mparam [ic_hex_mesh_params [lindex $h 1] [lindex $h 2]]
    set linked [lindex $mparam 1]
    if {[lindex $linked 0] == "linked"} {
        set const1 [string trimright [ic_hex_list_edge_constraints [lindex $edge 0] [lindex $edge 1]] \n]
        set const2 [string trimright [ic_hex_list_edge_constraints [lindex $linked 1] [lindex $linked 2]] \n]
        set edim [ic_hex_edge_node_dim [lindex $edge 0] [lindex $edge 1]]
        set dim1 [lindex $edim 0]
        set idx1 [lindex $edim 1]
        set edim [ic_hex_edge_node_dim [lindex $linked 1] [lindex $linked 2]]
        set dim2 [lindex $edim 0]
        set idx2 [lindex $edim 1]
        if {"$const1" == "$const2" && "$idx1" == "$idx2" && "$dim1" == "$dim2"} {
            return 1
        }
    }
    return 0
}

proc aie_hex_parallel_edges {edge {only_visible 0} {nearest 0}} {
    global use_output_blocks mess_frame
    
    set parallel ""
    set const1 [lindex [string trimright [ic_hex_list_edge_constraints [lindex $edge 0] [lindex $edge 1]] \n] end]
    set edim [string trimright [ic_hex_edge_node_dim [lindex $edge 0] [lindex $edge 1]] \n]
    set dim1 [lindex $edim 0]
    set idx1 [lindex $edim 1]
    if $only_visible {
        set fam_used [string trimright [volume_activename_string] \n]
        set range [string trimright [range_string] \n]
    } else {
        set fam_used [join [string trimright [ic_hex_list_block_families] \n]]
        set range ""
    }
    set cmd "select_edge no_highlight all $range max 1 m $fam_used new_format selected_bunching volume"
    if $use_output_blocks { append cmd " output_blocks" }
    # avoid line feeds
    if [winfo exists $mess_frame.text] {
        $mess_frame.text configure -state disabled
    }
    set p_edges [string trimright [hex_command $cmd] \n]
    foreach "e" $p_edges {
        set const2 [lindex [string trimright [ic_hex_list_edge_constraints [lindex $e 0] [lindex $e 1]] \n] end]
        set edim [string trimright [ic_hex_edge_node_dim [lindex $e 0] [lindex $e 1]] \n]
        set dim2 [lindex $edim 0]
        set idx2 [lindex $edim 1]
        if {"$const1" == "$const2" && "$idx1" == "$idx2" && "$dim1" == "$dim2"} {
            if {[lindex $edge 0] != [lindex $e 0] && [lindex $edge 1] != [lindex $e 1]} {
                lappend parallel $e
            }
        }
    }
    if [winfo exists $mess_frame.text] {
        $mess_frame.text configure -state normal
    }
    if $nearest {
        set ne1 ""
        set ne2 ""
        set n1 [lindex $edge 0]
        set n2 [lindex $edge 1]
        set loc1 [string trimright [ic_hex_get_node_location $n1] \n]
        set loc2 [string trimright [ic_hex_get_node_location $n2] \n]
        foreach e $parallel {
            set n3 [lindex $e 0]
            set n4 [lindex $e 1]
            set tmp_e($n3,$n4) 1
            set loc3 [string trimright [ic_hex_get_node_location $n3] \n]
            set loc4 [string trimright [ic_hex_get_node_location $n4] \n]
            set dist1 [ic_vcalc distance $loc1 $loc3]
            set dist2 [ic_vcalc distance $loc1 $loc4]
            if {$dist1 < $dist2} {
                set dist $dist1
                set ne1 $n3
            } else {
                set dist $dist2
                set ne1 $n4
            }
            if ![info exists distance1] {
                set distance1 $dist
                set near1 $ne1
            } else {
                if {$dist < $distance1} {
                    set distance1 $dist
                    set near1 $ne1
                }
            }
            if {![info exists tmp_e($near1,$n3)] && ![info exists tmp_e($near1,$n4)]} continue
            set dist1 [ic_vcalc distance $loc2 $loc3]
            set dist2 [ic_vcalc distance $loc2 $loc4]
            if {$dist1 < $dist2} {
                set dist $dist1
                set ne2 $n3
            } else {
                set dist $dist2
                set ne2 $n4
            }
            if ![info exists distance2] {
                set distance2 $dist
                set near2 $ne2
            } else {
                if {$dist < $distance2} {
                    set distance2 $dist
                    set near2 $ne2
                }
            }
        }
        if {[info exists near1] && [info exists near2]} {
            if [info exists tmp_e($near1,$near2)] {
                set parallel "\{ $near1 $near2 -1 \}"
            }
        }
    }
    return $parallel
}

proc onedgeParamMatchEdgeLoad {} {
    if {($auto_pick_mode) && ($matchEdgeVal == 0)} {
        edgeParamRef pick
    }
    set link_edge 0
}

proc onedgeParamRefFinish {} {
    if {$ref_edge != ""} {
        set edge $ref_edge
        mParamsDEZ hexMeshParamsUpdate
        mParamsDEZ display_edge_bunching
        if $auto_pick_mode {
            switch $edgeParamsEditVal {
                0 {edgeParamTarget pick}
                1 {edgeParamCopyToPick pick}
            }
        }
    }
}

proc onedgeParamTargetFinish {} {
    if {$target_edges != "" && $auto_pick_mode} {
        mParamsDEZ apply
        mParamsDEZ onedgeParamMatchEdgeLoad
    }
}

proc onedgeParamCopyToPickFinish {} {
    if {$to_edge != "" && $auto_pick_mode} {
        mParamsDEZ apply
        mParamsDEZ onedgeParamMatchEdgeLoad
    }
}

proc onedgeParamRefinementLoad {} {
    if $auto_pick_mode {
        edgeParamRefinementBlks pick
    }
}

proc onmParamsDEZOK {} {
    global bunching_laws edge_bunching_after_id
    global hex_option default_bunch_laws use_output_blocks

    switch $blockParamVal {
	    0 {
	        if $check_blck { hex_command "renew" }
	        set arg "[volume_activename_string]"
	        if {$blockParamSelVal == 2} {append arg " fix_counts"}
	        if {$blockParamSelVal == 1} {append arg " fix_laws"}
	        if {$blockParamSelVal == 3} {append arg " curve_bunching"}
	        hex_command "set_mesh_params $arg -version 110"
	        mess "Done recalculate\n"
	        hex_mesh_size
	    }
	    1 {
	        if {$factor == "" || $factor == 1.0 || $factor == 0.0} {
	            mess "Invalid \"Factor\"\n" red
	            return
	        }
	        if {[regexp {\/} $factor]} {
	            set ii [split $factor /]
	            set factor [expr double([lindex $ii 0])/double([lindex $ii 1])]
	        } else {
                set factor [expr $factor]
            }
	        hex_command "undo_major_start scale_mesh_size"
	        if $scale_spacings {
	            if {$factor == 0.0} return
                set cmd "select_edge no_highlight all [range_string] max 1 m [volume_activename_string] new_format volume"
                if $use_output_blocks { append cmd " output_blocks" }
                set edges [string trimright [hex_command $cmd] \n]
                ic_hex_scale_mesh_size_with_spacings $factor $edges
	        } else {
	            hex_command "scale_mesh_size $factor"
	        }
	        hex_command "undo_major_end scale_mesh_size"
	        mess "Done scaling\n"
	        hex_mesh_size
	    }
	    2 {
	        if {$edge == ""} {
		        mess "No edge selected\n" red
		        return
	        }
	        if [info exists in_onmParamsDEZOK] {
		        return
	        }
	        set in_onmParamsDEZOK 1

	        mParamsDEZ aie_hex_apply_mparams
	        mParamsDEZ hexMeshParamsUpdate 0
	        if [info exists no_reset] {
		        unset no_reset
	        } else {
		        set prev_mparams ""
		        set prev_medges ""
	        }
	        set copyEdge ""
	        catch { unset edge_bunching_after_id }
	        unset in_onmParamsDEZOK
	    }
	    3 {	  
	        switch $matchEdgeVal {
		        0 {
		            if {$ref_edge == ""} {
			            msg ERROR "No reference edge selected"
			            return
		            }
		            if {$target_edges == ""} {
			            msg ERROR "No target edge selected"
			            return
		            }
		            set done 0
		            set renodes "[lindex $ref_edge 0] [lindex $ref_edge 1]"
		            if !$link_edge {
		                foreach edge $target_edges {
			                if [catch {eval ic_hex_match_edges $renodes [lindex $edge 0] [lindex $edge 1]} res] {
			                    mess "Warning: edges \{$ref_edge\} and \{$edge\} don't match\n" red
			                    continue
			                } else {
			                    set done 1
			                }
			            }
		            } else {
		                foreach edge $target_edges {
			                if [catch {eval ic_hex_match_and_link_edges [lindex $ref_edge 0] [lindex $ref_edge 1] [lindex $edge 0] [lindex $edge 1]} res] {
			                    mess "Warning: unable to match/link edges \{$ref_edge\} and \{$edge\}\n" red
			                    continue
			                } else {
			                    set done 1
			                }
			            }
		            }
		            set target_edges ""
		            if $done {
		                if !$link_edge {
		                    mess "Done match edges\n"
		                } else {
		                    mess "Done match/link edges\n"
		                }
		            }
		        }
		        1 { # automatic
		            if {$matchEdgesDimGGVal == 0 && $refEdges == ""} {
			            msg ERROR "No reference edge(s) selected"
			            return
		            }
		            mess "Matching edge spacing at verts $verts...\n"
		            set cmd "match_edges_auto"

		            set nverts [llength $verts]
		            append cmd " nverts $nverts $verts"

		            set space min
		            if {$spacing == "Maximum"} { 
			            set space max
		            } elseif {$spacing == "Average"} { 
			            set space ave
		            }
		            append cmd " spacing $space"

		            set dims ""
		            if {$matchEdgesDimGGVal == 0} {
		                foreach e $refEdges {
			                set n1 [lindex $e 0]
			                set n2 [lindex $e 1]
			                set edim  [ic_hex_edge_node_dim $n1 $n2] 
			                set dim [lindex $edim 0]
			                lappend dims $dim
		                }
		            }
		    
		            if {$dims != ""} {
			            append cmd " dims $dims"
		            }
		    
		            hex_command "$cmd"
		            mess "Done match automatic\n"
		        }
		        2 {
		            if {$edgeParamsCopyTo2Val == 0 && $to_edge == ""} {
			            msg ERROR "No edge selected to copy to"
			            return
		            }
		            set use_absolut 0
		            set use_edges $to_edge
		            set use_copy_no_nodes 0
		            if {$edgeParamsCopyTo2Val == 1} {
		                set use_absolut $copy_absolute
		                set use_edges copy_to_parallel
		            } else {
		                set use_copy_no_nodes $copy_no_nodes
		            }
		            foreach edge $use_edges {
			            ic_hex_copy_edge_params $ref_edge2 $edge $use_absolut $use_copy_no_nodes
		            }
		            set to_edge ""
		            mess "Done copy bunching\n"
		        }
	        }
	        hex_update_display edge
	    }
	    4 {
	        if {$blocks == ""} {
		        msg ERROR "No blocks selected for refinement"
		        return
	        }

	        if $edgeRefDimGGVal {
		        if {$ref_dim == ""} {
		            msg ERROR "No dimension specified for refinement"
		            return
		        }
		        set dim $ref_dim
	        } else {
		        set dim -1
	        }

	        hex_command "mark_blocks unmark"
	        block_mark_super $blocks
	        hex_command "set_refinement $dim $factor"
	        mess "Done refinement\n"
	    }
    }

    if {!($blockParamVal == 2 || $blockParamVal == 3)} {
	    hex_update_display edge face block mesh
    }       
    mParamsDEZ setdirty
}

proc aie_hex_graph_params {{law ""}} {
    global eparam_law 

    if {$edge == ""} {
        msg ERROR "Please select the edge first"
        return
    }
    if [winfo exists .eparam] { form_kill .eparam }
    mesh_eparams $edge 1    
    if {$law != ""} { set eparam_law $law }
    mesh_eparam_editc ""
}

# this reverts back to original edge params
proc onmParamsDEZCancel {} {
    global hex_option

    if $hex_option(old_eparams) return
    if {[trace vinfo n] != ""} {
	    trace vdelete n w trace_change_edge_bunching
    }
    set prev_mparams ""
    set prev_medges ""
}

##################### Check block stuff #############

proc onCheckBlockDEZLoad {} {
    if ![info exists blockCheckVal] {set blockCheckVal 0}
    if {$blockCheckVal == ""} {set blockCheckVal 0}
    checkBlockDEZ setdirty
}


proc onCheckBlockDEZApply {} {
    switch $blockCheckVal {
	    0 {
	        hex_command "renew"
	        mess "Done check/fix\n" blue
	    }
	    1 {
	        hex_command "mark_blocks unmark"
	        hex_command "mark_blocks inverted"
	        hex_command "invert_super_block marked"	
	        mess "Done fix inverted blocks\n" blue 
	    }
	    2 {
	        if {$Blocks == ""} {
		        msg ERROR "No blocks selected"
		        return
	        }
	        hex_command "mark_blocks unmark"
	        block_mark_super $Blocks
	        hex_command "invert_super_block marked"	 
	        set Blocks ""
	        mess "Done invert selected blocks\n" blue
	    }
	    3 {
	        ic_hex_pack_superblocks
	        mess "Done pack block numbers\n" blue
        }
    }
    hex_update_display
}

proc aie_hex_check_fix_inverted {} {
    global display_flag

    if [catch {eval ic_hex_worst_hex [volume_activename_string]} res] {
        return
    }
    set res [lindex [split $res \n] 0]
    set worst_det [lindex $res end]
    if {$worst_det > 0} {
        return
    }
    mess "Worst block determinant = $worst_det\n" red
    if !$display_flag(block_worst) {
	    hex_command "worst_hex erase"
    }
    set mess "There are blocks with negative determinant. Do you want to invert them?\n"
    set ret [tk_dialog .tivc "Confirm" $mess "" 0 Yes No]
    switch -- $ret {
        -1 { if [winfo exists .tivc] { top_destroy .tivc; return } }
        1 { return }
    }
    hex_command "mark_blocks unmark"
    hex_command "mark_blocks inverted"
    hex_command "invert_super_block marked"
}

proc onfindWorstElemsDEZLoad {} {
    global hex_diagnostic_3d hex_diagnostic_2d hex_diagnostic_1d
    
	if [ic_hex_blocking_loaded] {
	    set mesh_dim [format %d [ic_hex_mesh_dimension]]
	} else {
	    set mesh_dim 3
	}
	
	switch $mesh_dim {
	    3 {
            set qualityDDList [lsort [array names hex_diagnostic_3d]]
	    }
	    2 {
            set qualityDDList [lsort [array names hex_diagnostic_2d]]
	    }
	    1 {
            set qualityDDList [lsort [array names hex_diagnostic_1d]]
	    }
	}
}

proc onfindWorstElemsDEZAfterLoad {} {
    global hex_option
    
    if {$worse_criterion == "" } {
        if [info exists hex_option(worse_criterion)] {
            set worse_criterion $hex_option(worse_criterion)
        } else {
            set worse_criterion "Quality"
            set hex_option(worse_criterion) $worse_criterion
        }
    }
    ::AIEnv::GUIManagement::ToggleGrey findWorstElemsQualityPrevious 0
    ::AIEnv::GUIManagement::ToggleGrey findWorstElemsQualityNext 0
}

proc onfindWorstElemsDEZApply {} {
    global hex_option

    ::AIEnv::GUIManagement::ToggleGrey findWorstElemsQualityPrevious 0
    ::AIEnv::GUIManagement::ToggleGrey findWorstElemsQualityNext 0
    set hex_option(worse_criterion) $worse_criterion
    aie_hex_find_worst_element
}

proc aie_hex_find_worst_element {} {
    global display_flag project_type plot_window hex_option 
    global hex_diagnostic_2d hex_diagnostic_3d project_type dim_to_mesh tdv_default 
    global worse_elements cur_worse_element worse_scale_to_box num_worse_elements

	if ![ic_hex_blocking_loaded] return

    if [info exists hex_option(worse_criterion)] {
        set worseCrit $hex_option(worse_criterion)
    } else {
        set worseCrit "Quality"
    }
    aie_hex_clear_worst_element
    
    if {[info exists plot_window] && [winfo exists $plot_window.graph]} {
        mess "The \"Find worst elements\" option is only available if the histogram is closed\n" 
        return
    }
    if {[hex_mesh_up_to_date 1 1] == 0} {
        msg ERROR "No Pre-Mesh available"
        return
    }

    if {$worseCrit == "Constant Radius"} {
        mess "The criterion \"Constant Radius\" is not supported\n" 
        return
    }
    
    set dim [format %d [ic_hex_mesh_dimension]]
    if {$dim == "3"} {
        set crit [lindex $hex_diagnostic_3d($worseCrit) 0]
        set minCrit [lindex $hex_diagnostic_3d($worseCrit) 1]
        set maxCrit [lindex $hex_diagnostic_3d($worseCrit) 2]
    } else {
        if [info exists hex_diagnostic_2d($worseCrit)] {
            set crit [lindex $hex_diagnostic_2d($worseCrit) 0]
            set minCrit [lindex $hex_diagnostic_2d($worseCrit) 1]
            set maxCrit [lindex $hex_diagnostic_2d($worseCrit) 2]
        } else {
            mess "The criterion \"$worseCrit\" is not supported for 2D blocking\n" 
            return
        }
    }
    
    if {$worseCrit == "Volume change"} {
        ic_uns_diag_reset_degen_min_max
    }
        
    set elems [eval ic_hex_write_file "" [volume_activename_string] no_file $project_type dim_to_mesh $dim_to_mesh no_boco]
    set nn 0; set nb 0; set nt 0; set nq 0
    set nh 0; set np 0; set npy 0; set ntt 0
    foreach i {0 1 2 3 4 5 6 7} {
        set [lindex {nn nb nt nq nh np npy ntt} $i] [lindex $elems $i]
    }
    # NODE nn
    # LINE_2 nb
    # TRI_3 nt
    # QUAD_4 nq
    # TETRA_4 ntt
    # HEXA_8 nh
    # PENTA_6 np
    # PYRA_5 npy
    
    set number_elems [expr $nt + $nq + $ntt + $nh + $np + $npy]
    set number_elems2d [expr $nt + $nq ]
    set number_elems3d [expr $ntt + $nh + $np + $npy]
    
    if {$dim == "2" && $number_elems2d == "0"} {
        mess "2D blocking: the pre-mesh contains no shell elements\n" red
        return
    }
    if {$dim == "3" && $number_elems3d == "0"} {
        mess "3D blocking: the pre-mesh contains no volume elements\n" red
        return
    }
    
    set full [ic_hex_ratio_check_minquality $crit "[volume_activename_string]" "" $project_type 1]
    if {$worseCrit == "Volume change"} {
        set min [lindex $full 1]
        set max [lindex $full 0]
    } else {
        set min [lindex $full 0]
        set max [lindex $full 1]
    }

    if {$worseCrit == "Angle"} {
        set min [expr $min * 90.0]
        set max [expr $max * 90.0]
    } else {
        if {$min == 0.0} {
            set min -0.001
        } else {
            set min [expr $min - (abs($min/100.0))]
        }
    }

    if {($min > 0.0 && $min < 0.0001) && ($worseCrit == "Max sector volume" || $worseCrit == "Min sector volume" || $worseCrit == "Max warp" || \
         $worseCrit == "Max warp 4.3v" || $worseCrit == "Warpage")} {                  
        set min 0.0
    }
    set stop 0
    set too_much 0
    set bars 10000
    while 1 {
        set ret [eval ic_hex_ratio_histogram $bars [volume_activename_string] proj $project_type minval $min -type \"$crit\" maxval $max new_format -location]
        set i 0
        set ii 0
        set hi 0
        set low 0
        set ntotal 0
        foreach {n low hi per} [lrange $ret 2 end] {
            if $n {
                incr i
            }
            incr ii
            incr ntotal $n
            if {$i >= 1 && $ntotal >= 500} { set too_much 1 }
            if {$i == 1 && $ntotal > 5} { set stop 1; break }
            if {$i > 1 && $ntotal >= 5} { set stop 1; break }
            if {$i > 5 && $ntotal >= 5} { set stop 1; break }
       }
       if {$ii >= $bars} { set stop 1 }
       if $stop break
    }
    if {$ntotal == 0} {
         if $too_much {
            set ntotal 500
         } else {
            mess "Criterion $worseCrit : no elements found; skipped display of worst elements\n" red
            return
         }
    }
    if {$ntotal >= 500} {
        mess "Criterion $worseCrit : found too much elements within the same range; skipped display of worst elements\n" red
        return
    }
    if {$worseCrit == "Angle"} {
        #set min [expr $min * 89.0]
        #set hi [expr $hi * 90.0]
    }
    tdv_active 0
    if {$i == 1} { set min $low }
    set locs [eval ic_hex_ratio_range $min $hi [volume_activename_string] proj $project_type -type \"$crit\" -solid -location]
    tdv_active 1
    if {$locs == "too much elements" || [llength $locs] >= 500} {
        mess "Criterion $worseCrit : found too much elements within the same range; skipped display of worst elements\n" red
        return
    }
    findWorstElemsDEZ set num_worse_elements [llength $locs]
    set ii 0
    catch { array unset worse_scale_to_box }
    catch { array unset worse_elements }   
    set locs [lsort -command aie_hexa_compare_ratio $locs]
    foreach "elem" $locs {
        set p1 [lindex $elem 2]; set p2 [lindex $elem 3]; ; set p3 [lindex $elem 4]; 
        set p4 [lindex $elem 5]; set p5 [lindex $elem 6]; ; set p6 [lindex $elem 7];
        set bb "{$p1 $p2 $p3} {$p4 $p5 $p6}"
        set worse_scale_to_box($ii) "[list [lindex $bb 0]] [list [lindex $bb 1]]"
        set ratio [lindex $elem 0]
        set type [lindex $elem 1]
        if {$worseCrit == "Angle"} {
            set ratio [expr $ratio * 90.0]
        }
        set worse_elements($ii) "$ratio $type"
        incr ii
    }
    if ![array exists worse_elements] {
        mess "Criterion $worseCrit : no elements found; skipped display of worst elements\n" red
        return      
    }
    set low [lindex $worse_elements(0) 0]
    set hi [lindex $worse_elements([expr [array size worse_elements] - 1]) 0]
    mess "Criterion $worseCrit : found [llength $locs] worst element(s) between $low and $hi\n"
    set cur_worse_element 0
    if {$ii > 1} {
        ::AIEnv::GUIManagement::ToggleGrey findWorstElemsQualityNext 0
        ::AIEnv::GUIManagement::ToggleGrey findWorstElemsQualityPrevious 0
    } else {
        ::AIEnv::GUIManagement::ToggleGrey findWorstElemsQualityNext 1
        ::AIEnv::GUIManagement::ToggleGrey findWorstElemsQualityPrevious 1
    }
    aie_hex_next_worst_element 1
}

proc aie_hex_clear_worst_element {} {
    global bad_marker_images
    
    if ![ic_hex_blocking_loaded] return
    hex_command "ratio_range erase"
    if [info exists ::bad_marker_images] {
        foreach im $::bad_marker_images { $im delete }
        unset ::bad_marker_images
    }
    if [findWorstElemsDEZ isbuilt] {
        findWorstElemsDEZ set num_worse_elements 0
        findWorstElemsDEZ set cur_worse_elements ""
        findWorstElemsDEZ set ratio_worse_elements ""
        findWorstElemsDEZ set type_worse_elements ""
        ::AIEnv::GUIManagement::ToggleGrey findWorstElemsQualityNext 1
        ::AIEnv::GUIManagement::ToggleGrey findWorstElemsQualityPrevious 1
    }
}

proc aie_hex_next_worst_element {up} {
    global worse_elements cur_worse_element worse_scale_to_box tdv_default
    global bad_marker_images num_worse_elements
    
    set num_worse_elements [findWorstElemsDEZ get num_worse_elements]   
    if ![info exists cur_worse_element] {
        set cur_worse_element 0
    } else {
        if $up {
            ::AIEnv::GUIManagement::ToggleGrey findWorstElemsQualityPrevious 0
            if {$cur_worse_element < $num_worse_elements} {
                incr cur_worse_element 1
            }
            if {$cur_worse_element == $num_worse_elements} {
                ::AIEnv::GUIManagement::ToggleGrey findWorstElemsQualityNext 1
            }
            if {$cur_worse_element == 1} {
                ::AIEnv::GUIManagement::ToggleGrey findWorstElemsQualityPrevious 1
            }
        } else {
            ::AIEnv::GUIManagement::ToggleGrey findWorstElemsQualityNext 0
            if {$cur_worse_element > 1} {
                incr cur_worse_element -1
            }
            if {$cur_worse_element == 1} {
                ::AIEnv::GUIManagement::ToggleGrey findWorstElemsQualityPrevious 1
            }
        }
    }
    set idx [expr $cur_worse_element - 1]
    if {![info exists worse_scale_to_box($idx)]} { 
        return
    }
    if [info exists ::bad_marker_images] {
        foreach im $::bad_marker_images { $im delete }
        unset ::bad_marker_images
    }
    findWorstElemsDEZ set cur_worse_elements $cur_worse_element
    set bb $worse_scale_to_box($idx)
    tdv_scale_to_box $tdv_default [lindex $bb 0] [lindex $bb 1] 1.2
    set centroid {}
    foreach coord {0 1 2} {
        lappend centroid [expr {([lindex [lindex $bb 0] $coord] + [lindex [lindex $bb 1] $coord]) / 2.0}]
    }
    set im [tdv_point_im -point "$centroid" -size 10 -color white]
    $tdv_default add_image $im
    lappend ::bad_marker_images $im
    findWorstElemsDEZ set ratio_worse_elements [lindex $worse_elements($idx) 0]
    switch -- [lindex $worse_elements($idx) 1] {
        4 { set type TETRA_4 }
        6 { set type HEXA_8 }
        8 { set type TRI_3 }
        12 { set type PENTA_6 }
        14 { set type QUAD_4 }
        18 { set type PYRA_5 }
        default { set type "" }
    }
    findWorstElemsDEZ set type_worse_elements $type
}

proc aie_hexa_compare_ratio {a b} {
    set a0 [lindex $a 0]
    set b0 [lindex $b 0]
    if {$a0 < $b0} {
        return -1
    } elseif {$a0 > $b0} {
        return 1
    }
    return [string compare [lindex $a 1] [lindex $b 1]]
}

####################### File I/O functions ###########################################

proc aie_convert_hexa_mesh {type} {
    global file_name env cancel_was_pressed is_win

    if ![ic_hex_blocking_loaded] {
        msg ERROR "No blocking loaded\n"
        return
    }

    set file_name(domains_dir) .
    
    set prefix ""
    if {$type == "multiblock"} {
        set prefix [aie_convert_hex2_${type}]
        if {$prefix == "" && [info exists cancel_was_pressed]} {
            mess "Convert to multi block canceled by user\n" red
            unset cancel_was_pressed
            return
        }
    } else {
        set mfile [aie_convert_hex2_${type} ""]
        if $is_win {
            set mfile [win_shortname $mfile]
        }
    }

    if [info exists env(AI_ENV_LSTC)] {
        mess "Done writing unstructured domain file: hex.uns\n" blue
        return
    }

    if {$type == "multiblock"} {
	    if {$prefix != ""} {
	        set mfile ${prefix}Multiblock
	    } else {
	        set mfile Multiblock
	    }
    }
    
    if {$type == "multiblock"} {
        if {$file_name(project_dir) != "." && $file_name(project_dir) != ""} {
            if [file exists $file_name(project_dir)/$mfile] {
                set file_name(domain) $file_name(project_dir)/$mfile
                aie_open_Mesh 0
                aie_afterStuffLoaded 0
            }
        } else {
            set file_name(domain) $mfile
            aie_open_Mesh 0
            aie_afterStuffLoaded 0
        }
    } else { 
        if [file exists "$mfile"] {
            if [ic_uns_is_loaded] {
                set opt [tk_dialog .unsOverwrite "Mesh Exists" "Mesh Already Exists" "" 1 "Merge" "Replace" "Cancel" ]
                switch -- $opt {
                    -1 {
                        if [winfo exists .unsOverwrite] { destroy .unsOverwrite }
                        return
                    }
                    0 { }
                    1 { aie_close_Mesh 0; mess "   --- Unloading existing mesh\n" }
                    2 { return }
                }
            }
            set ok [ic_uns_load [list $mfile] 3 0 "" 1]
            if !$ok {
	            mess "Error: opening mesh file\n" red
                busy reset
                ic_unload_mesh
                return
            }
	        aie_after_open_mesh 0 0
	        aie_afterStuffLoaded 0
            if [aie_wb2_is_running] {
                cmd_rm $mfile
                set mfile [aie_get_global wb_initProjName]
                if {$mfile != "___NA___"} {
                    set file_name(domain) $mfile.uns
                }
            } else {
                set file_name(domain) [file tail $mfile]
            }
	    }  else {
            mess "Error: file \"$mfile\" not found\n" red
        }
    }
}

proc aie_hex_write_global_cart {} {
    global file_name is_win

    if ![ic_hex_blocking_loaded] {
        msg ERROR "No blocking loaded"
        return
    }
    if {[info exists file_name(settings)] && $file_name(settings) != ""} {
        set prefix [file tail [file rootname $file_name(settings)]]
    } else {
        set prefix blocking
    }
    set fname $prefix.crt
    set path [pwd]/$fname
    if $is_win {
        set path [list [win_shortname $path]]
    }
    set cmd "write_cart_file $path"
    hex_command $cmd
}

proc aie_write_super_domain {} {
    global file_name

    if ![ic_hex_blocking_loaded] {
        msg ERROR "No blocking loaded"
        return
    }
   
    set prefix [aie_convert_hex2_multiblock 0]
    mess "including all domain.* with prefix $prefix\n"
    if {$prefix == ""} {
        set sel [glob domain.*]
    } else {
        set sel [glob ${prefix}domain.*]
    }

    set numbers ""
    foreach d $sel {
        lappend numbers [string range [file extension $d] 1 end]
    }
    set supername [file join . super_domain.1]
    set listname  [file join . sup_domain_list]
    set topofile topo_mulcad_out.top

    ic_convert_struct_to_super . $numbers $topofile $supername $listname
}

proc aie_convert_hex2_multiblock {{type ""}} {
    global last_line use_output_blocks file_name
    global project_type cancel_was_pressed

    hex_mesh_up_to_date 0
    hex_command mesh_dimension
    set only_sub ""
    
    catch { unset cancel_was_pressed }
    
    if {$type != ""} {
	    set res $type
    } else {
	    set res 0
	    if { $last_line == "3" } {
	        # for volume meshes check if only surface is wanted
	        set res [tk_dialog .only_sub "Multiblock" "Convert which kind of domains?" "" -1 Volume Surface Cancel]
            if {$res == -1} { if [winfo exists .only_sub] { top_destroy .only_sub; return "" } }       
	        if {$res == 2} { return "" }
	    }
    }

    set cmd "multi_block [family_activename_string] proj $project_type"
    if $res { append cmd " only_subfaces" }
    if $use_output_blocks { append cmd " output_blocks" }
    set prefix ""
    if {[info exists file_name(settings)] && $file_name(settings) != ""} {
        set prefix [file tail [file rootname $file_name(settings)]]
        if {$prefix != ""} {
            lappend cmd -family_topo ${prefix}.fto -topo_mulcad_out ${prefix}.top -subface_proj ${prefix}.spr -dom_prefix ${prefix}.
        } else {        
            lappend cmd -family_topo family_topo.fto -topo_mulcad_out topo_mulcad_out.top -subface_proj subface_proj
        }
    } else {
        set mess "Warning: Multi block domains will be saved in current working directory without any prefix. \
                  Do you want to continue saving?"
        switch -- [tk_dialog .missing_project "Missing project name" "$mess" "" -1 Yes No "Save as project"] {
            -1 {
                if [winfo exists .missing_project] {
                    top_destroy .missing_project
                    set cancel_was_pressed 1
                    return ""
                }
            }
            0 {}
            1 {
                set cancel_was_pressed 1
                return ""
            }
            2 {
               mess "Multi block domains will be saved in a project directory.\n"
               aie_newProject "" 1
               if {$file_name(project_dir) == "." || $file_name(project_dir) == ""} {
                   set cancel_was_pressed 1
                   return "" 
               } else {
                   set new_project_created 1
               }
            }
	}
	if [info exists new_project_created] {
	    unset new_project_created
	    set prefix [file tail [file rootname $file_name(settings)]]
	    lappend cmd -family_topo ${prefix}.fto -topo_mulcad_out ${prefix}.top -subface_proj ${prefix}.spr -dom_prefix ${prefix}.
	} else {
            lappend cmd -family_topo family_topo.fto -topo_mulcad_out topo_mulcad_out.top -subface_proj subface_proj
        }
    }
    set cur_pwd [pwd]
    if {$file_name(project_dir) != "." && $file_name(project_dir) != "" && $prefix != ""} {
        cd $file_name(project_dir)
        mess "Saving Multi block domains in directory $file_name(project_dir)\n"
    } else {
        mess "Saving Multi block domains in current working directory $cur_pwd\n"
    }
    hex_command $cmd    
    if {$prefix != ""} { 
	set prefix $prefix. 
    }    
    aie_create_multiblock_file $prefix
    cd $cur_pwd
    mess "Done writing Multi block domains\n" blue
    return $prefix
}

proc aie_convert_hex2_uns {{file ""}} {
    global project_type dim_to_mesh hex_option file_name is_win

    hex_mesh_up_to_date 0
    if {$file == ""} {
        if {$file_name(project_dir) != "." && $file_name(project_dir) != "" && [file exists $file_name(project_dir)]} {
            set file $file_name(project_dir)/hex.uns
        } else {
            set file ./hex.uns
        }
        if [file exists $file] {
            cmd_rm $file
        }
    }
    if $is_win { set file [win_shortname $file] }
    set cmd "write_file [list $file] [volume_activename_string] proj $project_type dim_to_mesh $dim_to_mesh no_boco"
    if $hex_option(wr_hexa7) { append cmd " conv_hexa7" }
    mess "Converting to unstruct mesh...\n"
    hex_command $cmd
    return $file
}


proc aie_hex_mesh_size {{recalculate 1} {block_info 0}} {
    global project_type dim_to_mesh hex_option 
    global last_line is_win

    if ![ic_hex_blocking_loaded] {
        mess "No blocking is loaded\n" red
        return
    }
    if {([ic_hex_count_unstruct_blocks 2d] || [ic_hex_count_unstruct_blocks 3d])} {
        set filename " "
        set cmd "write_file $filename [volume_activename_string] no_file proj $project_type dim_to_mesh $dim_to_mesh no_boco"
        if $hex_option(wr_hexa7) { append cmd " conv_hexa7" }
        busy 1
        hex_command $cmd
        busy 0
        set nn 0
        set nb 0
        set nt 0
        set nq 0
        set nh 0
        set np 0
        set npy 0
        set ntt 0
        foreach i {0 1 2 3 4 5 6 7} {
            set [lindex {nn nb nt nq nh np npy ntt} $i] [lindex $last_line $i]
        }
        if $block_info { hex_number_of_blocks_info }
        mess "\nMesh size:\n"
        if {$nn > 0}  { mess "        NODE : $nn\n" }
        if {$nb > 0}  { mess "        LINE_2 : $nb\n" }
        if {$nt > 0}  { mess "        TRI_3 : $nt\n" }
        if {$nq > 0}  { mess "        QUAD_4 : $nq\n" }
        if {$ntt > 0} { mess "        TETRA_4 : $ntt\n" }
        if {$nh > 0}  { mess "        HEXA_8 : $nh\n" }
        if {$np > 0}  { mess "        PENTA_6 : $np\n" }
        if {$npy > 0} { mess "        PYRA_5 : $npy\n" }
    } else {
        hex_mesh_size $block_info 0
    }
}

proc aie_create_multiblock_file {{prefix ""}} {

    set name "${prefix}Multiblock"
    if [file isdirectory $name] {
        mess "Unable to save file $name; file is directory\n" red
    }
    set fp [open $name w]
    puts $fp "This is just a dummy file to load all the domains of multiblock."
    set doms "${prefix}domain.*"
    puts $fp "domain files: $doms"
    close $fp
}

proc aie_strdisp_shrink {type} {
    global str_option

    disp_shrink_ijk $type !$str_option($type,shrink)
}


proc aie_edit_composite_curve {} {
    if ![ic_hex_blocking_loaded] {
        msg ERROR "Composite Curve Grouping is available only with Blocking Loaded"
        return
    }
    editCompositeCurveDEZ show
}

proc aie_create_vorfn {{force 0}} {
    global vorfn_exist fam_visible

    if {![info exists vorfn_exist] || ($force)} {
	    set fam_visible(VORFN) 0
	    ::AIEnv::GUIManagement::Tree::AddGroup part VORFN 0
	    set vorfn_exist 1
    } else {
        if {[info exists fam_visible(VORFN)] && [lsearch [ic_hex_list_block_families] "VORFN"] >= 0} {
            ::AIEnv::GUIManagement::Tree::AddGroup part VORFN $fam_visible(VORFN)
        }
    }
}

proc aie_delete_vorfn {} {   
    global vorfn_exist fam_visible

    if [info exists vorfn_exist] {
        ::AIEnv::GUIManagement::Tree::DeleteGroup part VORFN 0
        catch { unset fam_visible(VORFN) }
        unset vorfn_exist
    }
}

proc aie_hex_list_parts {fn} {
    global vorfn_exist
   
    set parts [aie_list_parts $fn]
    if {[info exists vorfn_exist] && [lsearch $parts VORFN] < 0} {
        lappend parts VORFN
    }
    return $parts
}

proc aie_after_blocking_loaded {{force 0} {after_replay 0}}  {
    global Hexa_dimension dim_to_mesh str_option aie_CurveComposite cut_info_backup

    if ![ic_hex_blocking_loaded] return
    catch { array unset cut_info_backup }
    InitBlockDisplaySettings $after_replay
    ::AIEnv::GUIManagement::Tree::UpdateBlockingVisibility
    aie_hex_check_families 1
    set str_option(curve,show_composite) 1
    set aie_CurveComposite 1
    update_geom_visible curve p
    aie_topo_build_defaults
    ic_hex_is_modified 0
    set dim [format %d [ic_hex_mesh_dimension]]
    set dim_to_mesh [format %g [ic_hex_dim_to_mesh]]
    switch $dim {
        2 { set Hexa_dimension 2D }
        3 { set Hexa_dimension 3D }
        default { mess "Warning: Hexa dimension not set\n" red }
    }
    if !$after_replay { hex_command "unblank_blocks" }
    aie_hex_load_settings
    aie_update_icons block
    get_indices 0
    index_reset
    aie_init_hex_subsets
    if {$force == "1"} { hex_mesh_size 1 1 }
}

proc aie_after_rename_blocking {{rename ""}} {
    global top_current
    
    if ![ic_hex_blocking_loaded] return
    if {$rename == ""} return
    set rename_exists 0
    foreach topo [ic_hex_print_topo_tree] {
	    set name [lindex $topo 0]
        if {"$rename" == "$name"} {
            set rename_exists 1
            break
        }
    }
    if !$rename_exists {
        catch { ::AIEnv::GUIManagement::Tree::DeleteGroup topo $rename 0 }
    }
}

proc aie_hex_load_settings {} {
    if ![hexMeshOptsDEZ isbuilt] { 
        hexMeshOptsDEZ build
    }
}

proc aie_hex_check_families {{force 1}} {
    global fam_visible

    if ![ic_hex_blocking_loaded] return
    aie_create_vorfn
    if $force {
    	aie_create_initial_assemblies
    }
}

########################## Block Quality ##########################################

proc onhexQualityDEZLoad {} {
    global hex_diagnostic_3d hex_diagnostic_2d hex_diagnostic_1d
   
	if [ic_hex_blocking_loaded] {
	    set mesh_dim [format %d [ic_hex_mesh_dimension]]
	} else {
	    set mesh_dim 3
	}
	
	switch $mesh_dim {
	    3 {
            set qualityDDList [lsort [array names hex_diagnostic_3d]]
	    }
	    2 {
            set qualityDDList [lsort [array names hex_diagnostic_2d]]
	    }
	    1 {
            set qualityDDList [lsort [array names hex_diagnostic_1d]]
	    }
	}
    if {$qualitydde == "" } {
        hexQualityDDE setvalue @4
        if {$minv == ""} { set minv 0 }
        if {$maxv == ""} { set maxv 1 }
    } else {
        switch $mesh_dim {
            3 {
                set minv [lindex $hex_diagnostic_3d($qualitydde) 1]
                set maxv [lindex $hex_diagnostic_3d($qualitydde) 2]
	        }
	        2 {
                set minv [lindex $hex_diagnostic_2d($qualitydde) 1]
                set maxv [lindex $hex_diagnostic_2d($qualitydde) 2]
	        }
	        1 {
                set minv [lindex $hex_diagnostic_1d($qualitydde) 1]
                set maxv [lindex $hex_diagnostic_1d($qualitydde) 2]
	        }
	    }
    }

    if {$nbars == 0} { set nbars 20 }
    set AllowActiveReload 1
    set activePartsOnly 0
}

proc onhexQualityDEZAfterLoad {} {

    if ![ic_hex_blocking_loaded] {
        msg ERROR "No Blocking available"
        hexQualityDEZ hide
        return
    }
    if {[hex_mesh_up_to_date 1] == 0} {
        msg ERROR "No Pre-Mesh available"
        hexQualityDEZ hide
        return
    }
    hexQualityDEZ setdirty
    set sparts [volume_activename_string]
    foreach fam [join [ic_hex_list_families]] {
        if {$fam == "ORFN" || $fam == "VORFN"} continue
        if {[lsearch $sparts $fam] < 0} {
            set activePartsOnly 1
            break
        }
    }
    ::AIEnv::GUIManagement::ToggleGrey HEXQualityonlyVisibleChk 0
    ::AIEnv::GUIManagement::ToggleGrey HEXQualityactivePartsChk 0
    status_message ""
}

proc onHexQualityDDEModify {dez val} {
    global histo_minv histo_maxv hexa_histogram_title histo_replot
    global hex_diagnostic_3d hex_diagnostic_2d hex_diagnostic_1d

    status_message ""
    set qualitydde [hexQualityDEZ get qualitydde]
    if {[info exists hexa_histogram_title] && "$hexa_histogram_title" == "$qualitydde"} {
        set histo_minv [hexQualityDEZ get minv]
        set histo_maxv [hexQualityDEZ get maxv]
        set histo_ylim [hexQualityDEZ get ylim]
        set histo_nbars [hexQualityDEZ get nbars]
    } else {
	    if [ic_hex_blocking_loaded] {
	        set mesh_dim [format %d [ic_hex_mesh_dimension]]
	    } else {
	        set mesh_dim 3
	    }
        switch $mesh_dim {
            3 {
                set histo_minv [lindex $hex_diagnostic_3d($qualitydde) 1]
                set histo_maxv [lindex $hex_diagnostic_3d($qualitydde) 2]
	        }
	        2 {
                set histo_minv [lindex $hex_diagnostic_2d($qualitydde) 1]
                set histo_maxv [lindex $hex_diagnostic_2d($qualitydde) 2]
	        }
	        1 {
                set histo_minv [lindex $hex_diagnostic_1d($qualitydde) 1]
                set histo_maxv [lindex $hex_diagnostic_1d($qualitydde) 2]
	        }
	    }
        set histo_ylim 20
        set histo_nbars 20
    }
    set hexa_histogram_title $qualitydde
    if {$qualitydde == "Constant Radius"} {
        ::AIEnv::GUIManagement::ToggleGrey hexQualityHistoMinX 1
        ::AIEnv::GUIManagement::ToggleGrey hexQualityHistoMaxX 1
        ::AIEnv::GUIManagement::ToggleGrey hexQualityHistoMaxY 1
        ::AIEnv::GUIManagement::ToggleGrey hexQualityHistoNbars 1
        aie_hex_clear_histogram
        ::AIEnv::GUIManagement::ConfigureConsoleZone 0; update
        mess "\nThe criterion \"Constant Radius\" does not have an associated histogram\n" blue
    } else {
        ::AIEnv::GUIManagement::ToggleGrey hexQualityHistoMinX 0
        ::AIEnv::GUIManagement::ToggleGrey hexQualityHistoMaxX 0
        ::AIEnv::GUIManagement::ToggleGrey hexQualityHistoMaxY 0
        ::AIEnv::GUIManagement::ToggleGrey hexQualityHistoNbars 0
    }
     
    if {[info exists hexa_histogram_title] && $qualitydde != "Constant Radius"} {
        if [info exists histo_replot($hexa_histogram_title,minv)] {
            set histo_minv $histo_replot($hexa_histogram_title,minv)
            set histo_maxv $histo_replot($hexa_histogram_title,maxv)
            set histo_ylim $histo_replot($hexa_histogram_title,ylim)
            set histo_nbars $histo_replot($hexa_histogram_title,nbars)
        }
    }

    foreach p {minv maxv ylim nbars} {
        hexQualityDEZ set $p [set histo_$p]
    }
}

proc aie_hex_check_const_radius {} {
    set face [select_hexa face 1 "Please select the the face to check"]
    if {$face != ""} {
        hexQualityDEZ setdirty
        mess "Face vertices [join $face]\n" blue
        set mess [hex_command "check_face_radii [join $face]"]
        mess "$mess\n" blue
    }
}
proc onhexQualityDEZOK {} {    
    if {$qualitydde == "Constant Radius"} {
        aie_hex_check_const_radius
        return
    }
    if {$qualitydde != ""} {
        aie_hex_update_histogram $qualitydde $nbars $minv $maxv $ylim $activePartsOnly $onlyVisible "user"
    }
    ::AIEnv::GUIManagement::ToggleGrey HEXQualityonlyVisibleChk 0
    ::AIEnv::GUIManagement::ToggleGrey HEXQualityactivePartsChk 0
}


proc aie_hex_show_min_quality {} {
    global hex_diagnostic_3d hex_diagnostic_2d hex_diagnostic_1d project_type
    
    set dim [format %d [ic_hex_mesh_dimension]]
    if $activePartsOnly {
        set parts [volume_activename_string]
    } else {
        set parts ""
    }
    if $onlyVisible {
        set range [range_string]
    } else {
        set range ""
    }
    busy 1
    set ta [tdv_active 0]
    mess "Quick min overview:\n"
    ic_undo_suspend
    foreach item $qualityDDList {
        if {$item == "Constant Radius" || $item == "Custom quality"} continue
        mess "Minimum quality for \"$item\": "
        switch $dim {
            3 { set m [ic_hex_ratio_check_minquality [lindex $hex_diagnostic_3d($item) 0] $parts $range $project_type] }
            2 { set m [ic_hex_ratio_check_minquality [lindex $hex_diagnostic_2d($item) 0] $parts $range $project_type] }
            1 { set m [ic_hex_ratio_check_minquality [lindex $hex_diagnostic_1d($item) 0] $parts $range $project_type] }
        }
        if {$item == "Angle"} {	set m [expr $m * 90.0] }
        if {$item == "Volume change"} {
            mess "$m (max quality)\n"
        } else {
            mess "$m\n"
        }
        update
    }
    ic_undo_resume
    tdv_active $ta
    busy 0
}

proc aie_hex_update_histogram {{title ""} {nbars ""} {min ""} {max ""} {ylim ""} {only_active 1} {only_visible 0} {arguments ""}} {
    global histo_width histo_height colorBand
    global histo_minv histo_maxv histo_minv_limit histo_maxv_limit
    global histo_solid histo_color_by_quality histo_nbars histo_ylim
    global dim_to_mesh project_type hex_diagnostic_3d hex_diagnostic_2d
    global hex_diagnostic_1d diag_which hexa_histogram_exist
    global index_form scan_form histo_show options 
    global histo_only_active histo_only_visible hexa_histogram_title histo_replot
    global hex_diagnostic_calculate_3d hex_diagnostic_calculate_2d hex_diagnostic_calculate_1d

    aie_hex_clear_worst_element
    aie_hex_clear_histogram
    status_message ""
    ::AIEnv::GUIManagement::ConfigureConsoleZone 1
    if [ic_hex_blocking_loaded] {
        set mesh_dim [format %d [ic_hex_mesh_dimension]]
    } else {
        set mesh_dim 3
    }
    
    set active_dez [aie_active_dez]
    switch $mesh_dim {
	    3 {
	        if {![info exists hex_diagnostic_3d($title)] && ($active_dez == "hexQualityDEZ" || $active_dez == "hexSmoothDEZ")} {
	            set title [$active_dez get qualitydde]
	        }
	        set diag_which [lindex $hex_diagnostic_3d($title) 0]
	    }
	    2 {
	        if {![info exists hex_diagnostic_2d($title)] && ($active_dez == "hexQualityDEZ" || $active_dez == "hexSmoothDEZ")} {
	            set title [$active_dez get qualitydde]
	        }
	        set diag_which [lindex $hex_diagnostic_2d($title) 0]
	    }
	    1 {
	        if {![info exists hex_diagnostic_1d($title)] && ($active_dez == "hexQualityDEZ" || $active_dez == "hexSmoothDEZ")} {
	            set title [$active_dez get qualitydde]
	        }
	        set diag_which [lindex $hex_diagnostic_1d($title) 0]
	    }
    }
    if {$nbars == ""} {
        if [info exists histo_nbars] {
            set nbars $histo_nbars
        } else {
            set nbars 20
            set histo_nbars $nbars
        }
    } else {
         if [string is integer $nbars] {
            set histo_nbars $nbars
         }
    }
    if {$ylim == ""} {
	    if [info exists histo_ylim] {
	        set ylim $histo_ylim
	    } else {
	        set ylim 0
	        set histo_ylim $ylim
	    }
    } else {
        if [string is integer $ylim] {
            set histo_ylim $ylim
        }
    }
    set histo_solid 0
    set histo_color_by_quality 0
    if {($nbars < 1) || ($nbars > 500)} {
        mess "Num. bars not in valid range {1,500}; resetting the histogram values to defaults\n" red
        set histo_nbars 20; set nbars 20
    }   
    set xvals ""
    set yvals ""
    set ymax 0
    busy 1
    if {[hex_mesh_up_to_date 1] == 2} {
        set min ""
        set max ""
    }
    
    set min_set 1
    set max_set 1
    set hexa_histogram_title $title
    
    if {$min == ""} {
        switch $mesh_dim {
            3 {
                set min [lindex $hex_diagnostic_3d($title) 1]
	        }
	        2 {
                set min [lindex $hex_diagnostic_2d($title) 1]
	        }
	        1 {
                set min [lindex $hex_diagnostic_1d($title) 1]
	        }
	    }
        if {[aie_active_dez] == "hexQualityDEZ"} {
            hexQualityDEZ set minv $min
            set hexa_histogram_title $title
        }
	    set min_set 0
    }
    set add_cmd ""
    if {[aie_active_dez] == "hexQualityDEZ"} {
        set only_active [hexQualityDEZ get activePartsOnly]
        set histo_only_active $only_active
    } else {
        if [info exists histo_only_active] {
            set only_active $histo_only_active
        }
    }
    if {$only_active == "1"} {
        append add_cmd " [volume_activename_string]"
    } else {
        foreach f [join [ic_hex_list_families]] {
            if {$f == "VORFN" || $f == "ORFN"} continue
            append add_cmd " $f"
        }
    }
    if {$add_cmd == " "} {
        mess "No parts found\n" red
        busy 0
        return
    }
    if {[aie_active_dez] == "hexQualityDEZ"} {
        set only_visible [hexQualityDEZ get onlyVisible]
        set histo_only_visible $only_visible
    } else {
        if [info exists histo_only_visible] {
            set only_visible $histo_only_visible
        }
    }
    if {$only_visible == "1"} {
        append add_cmd " [range_string]"
    }
    
    if {$max == "" || $min >= $max} {
         if {$max != "" && $min >= $max} {
            mess "Max value can not be less or equal than min value; resetting the histogram min/max values to defaults\n" red
            set reset_min 1
         }
	     switch $mesh_dim {
            3 {
                if [info exists reset_min] { set min [lindex $hex_diagnostic_3d($title) 1] }
                set max [lindex $hex_diagnostic_3d($title) 2]
            }
            2 {
                if [info exists reset_min] { set min [lindex $hex_diagnostic_2d($title) 1] }
                set max [lindex $hex_diagnostic_2d($title) 2]
            }
            1 {
                if [info exists reset_min] { set min [lindex $hex_diagnostic_1d($title) 1] }
                set max [lindex $hex_diagnostic_1d($title) 2]
            }
        }
        if {[aie_active_dez] == "hexQualityDEZ"} {
            if [info exists reset_min] { hexQualityDEZ set minv $min }
            hexQualityDEZ set maxv $max
        }
        catch { unset reset_min }
        set max_set 0
    }
    
    set recalculate -1
    set ret [eval ic_hex_ratio_histogram $nbars $add_cmd proj $project_type minval $min -type \"$diag_which\" maxval $max new_format]
    switch $mesh_dim {
        3 {
            set recalculate [lsearch $hex_diagnostic_calculate_3d $title]
	    }
	    2 {
            set recalculate [lsearch $hex_diagnostic_calculate_2d $title]
	    }
	    1 {
            set recalculate [lsearch $hex_diagnostic_calculate_1d $title]
	    }
	}
	set ntotal 0
	if {$recalculate >= 0} {
	    foreach {n low hi per} [lrange $ret 2 end] {
            incr ntotal $n
        }
    }
    if {($recalculate >= 0 && $ntotal == 0)} {
        mess "Note: the current \"Max-X\" value is too small to represent the pre-mesh quality\n" red
    }
    # get the full range if -ve
    if {!$min_set && ([lindex $ret 0] < 0.0)} {
        set min [lindex $ret 0]
        set ret [eval ic_hex_ratio_histogram $nbars $add_cmd proj $project_type minval $min -type \"$diag_which\" maxval $max new_format]
    }
    if {$title == "Angle"} {	
        set actual_min [expr [lindex $ret 0] * 90.0]
        set actual_max [expr [lindex $ret 1] * 90.0]
    } else {
        set actual_min [lindex $ret 0]
        set actual_max [lindex $ret 1]
    }
    set no_range [expr {$min == $max}]
   
    set xvals ""
    set yvals ""
    set ymax 0
    set hi 0
    set low 0
    set ntotal 0
    foreach {n low hi per} [lrange $ret 2 end] {
        incr ntotal $n
    }

    set warn_no_elems 0
    if {$ntotal == 0} {
        set ntotal 1
        set warn_no_elems 1
    }
    mess "\nCriterion: $title\n\n" blue
    foreach {n low hi per} [lrange $ret 2 end] {
        if {(($low >= $min) && ($hi <= $max))} {
            lappend xvals $low
            lappend yvals $n
            if {$n > $ymax} {
                set ymax $n
            }
        }
        set percent [format %.3f [expr $n*100.0/$ntotal]]
        if !$warn_no_elems { mess "$low -> $hi : $n ($percent%)\n" blue }
    }
    if ![info exists hi] return
   
    lappend xvals $hi

    set histo_minv_limit $actual_min
    set histo_maxv_limit $actual_max

    if {$histo_minv_limit == $histo_maxv_limit} {
        set histo_minv_limit 0
    }

    if $min_set {
        set histo_min $min
    } else {
        set histo_min $actual_min
    }

    if $max_set {
        set histo_max $max
    } else {
        set histo_max $actual_max
    }
   
    # save the formating from the input
    if {$min == $histo_min} {
        set histo_min $min
    }
    if {$max == $histo_max} {
        set histo_max $max
    }
   
    set labels [list "Min $actual_min" "Max $actual_max"]
    set extra_buts [list [list done "Done" aie_hex_clear_histogram]]
    set hexa_histogram_exist 1
    
    if {![info exists histo_replot($hexa_histogram_title,minv)] || $arguments == "user"} {
        set histo_replot($hexa_histogram_title,minv) $min
        set histo_replot($hexa_histogram_title,maxv) $max
        set histo_replot($hexa_histogram_title,ylim) $ylim
        set histo_replot($hexa_histogram_title,nbars) $nbars
    }
    
    status_message "Pre-Mesh quality criterion: $hexa_histogram_title (Min $actual_min Max $actual_max)"
    if [info exists colorBand] { unset colorBand }
    if $warn_no_elems {
        mess "\nWarning: no element(s) found in the current min/max range\n" red
    }
    aie_make_histogram $title $xvals $yvals $ylim $labels aie_hex_update_histogram hex_select_histo {} $extra_buts 2 12 9 1 0 0 0 0 -1
    # tearoff scan/index form if exists
    if {([info exists index_form]) && !([winfo exists $index_form])} {
        aie_hex_index_control 1
    }
    if {([info exists scan_form]) && !([winfo exists $scan_form])} {
        aie_hex_scan_planes 1
    }
    busy 0
    if [info exists options(histo_show_default)] {
        if {!$histo_show && $options(histo_show_default) == "0"} {
            mess "\nNote: Histogram default \"Show\" is set to off\n"
        }
    }
}

proc aie_hex_clear_histogram {{del 1}} {
    global histo_minv histo_maxv histo_ylim histo_nbars
    global hexa_histogram_exist 

    set histo_minv ""
    set histo_maxv ""
    set histo_ylim 0
    set histo_nbars 20
    status_message ""
    if ![ic_hex_blocking_loaded] return
    hex_command "ratio_range erase"
    if $del {
        hex_command "ratio_range erase_unstruct"
        aie_delete_histogram
        ::AIEnv::GUIManagement::ConfigureConsoleZone 0
    }

    catch { unset hexa_histogram_exist }
}

proc hex_select_histo {w intervals arguments solid show color_by_quality} {
    global project_type diag_which hexa_histogram_exist 
    
    if {$intervals == "" || (!$show)} {
	    hex_command "ratio_range erase"
	    return
    }
    set hexa_histogram_exist 1
    set max [lindex [lindex $intervals 0] 0]
    set min [lindex [lindex $intervals 0] 1]
    foreach i $intervals {
	    set low [lindex $i 0]
	    set hi [lindex $i 1]
	    if {$low < $min} {
	        set min $low
	    }
	    if {$hi > $max} {
	        set max $hi
	    }
    }
    set rmin [ lindex $arguments 0 ]
    set rmax [ lindex $arguments 1 ]
    if {$min == $rmin } {
	    set min -1.0e10
    }
    if { $max == $rmax } {
	    set max 1.0e10
    }
    if {$min < $max} {
	    set dtype $diag_which
	    set sol ""; if $solid { set sol "-solid" }
        # now display all contiguous
	    set new_intervals ""
	    set last_low [ lindex [ lindex $intervals 0 ] 0 ]
	    set last_hi $last_low
	    foreach i $intervals {
		    set low [lindex $i 0]
        	set hi [lindex $i 1]
		    if { $low == $last_hi } {
                # extend an interval
			    set last_hi $hi
		    } else {
                # output new interval
			    lappend new_intervals " $last_low $last_hi "
			    set last_low $low
			    set last_hi $hi
		    }
	    }
	    if { $last_hi != "" } {
		    lappend new_intervals " $last_low $last_hi "
	    }
	    set intervals $new_intervals
	    set min [lindex [lindex $intervals 0] 0]
    	set max [lindex [lindex $intervals 0] 1]
    	set activename [volume_activename_string]
        if {$activename == "" && "$dtype" == "Volume change"} {
            set activename [ic_hex_list_block_families_without]
        }
	    set cmd "ratio_range $min $max $activename proj $project_type -type \"$dtype\" $sol"
	    set intervals [ lrange $intervals 1 end ]
	    foreach i $intervals {
		    append cmd " -interval [ lindex $i 0 ] [ lindex $i 1 ]"
	    }
	    hex_command "$cmd"
    } else {
	    hex_command "ratio_range erase"
    }
}

proc aie_hex_subset_histogram {} {
    msg ERROR "Not implemented yet"
}

proc onhexQualityDEZUnLoad {} {
    global histo_showit histo_replot hexa_histogram_title
    
    catch { unset histo_showit }
    catch { unset histo_replot; unset hexa_histogram_title }
}

################################ Transformation ######################

proc ontransformBlocksToolsDEZLoad {} {
    set x 0
    set y 0
    set z 0
    set xF 1; set yF 1; set zF 1   
	set moveBlocksEGVal 0
	set RotateBlkCenterEGVal 0
	set blkRotateAxisOptionEGVal 0
	set rot_angle 90
	set ReflectBlocksCenterEGVal 0
	set BlocksMirrorAxisOptionEGVal 0
	set ScaleBlocksCenterEGVal 0
	set also_whole_geom 0
	set transBlocksEGVal 0
	set rotateBlocksList ""
}

proc ontransformBlocksToolsDEZAfterLoad {} {

    if {[trace vinfo BlkList] != ""} {
	    trace vdelete BlkList w aie_hex_trace_BlkList
    }
    trace variable BlkList w aie_hex_trace_BlkList
    aie_hex_trace_BlkList
}

proc onrotateBlocksFromLcsLoad {} {
    if {$transfrmBlocksEGVal == 5 && $transBlocksEGVal == 2} {
        if ![llength [ic_image get global]] {
            ic_image csys_im cartesian
        }
    }
}

proc onrotateBlocksFromLcsUnLoad {} {
   if [llength [ic_image get global]] {
       ic_image delete csys_im
    }
}

proc ontransBlocksEGILoad {} {
    if {$transfrmBlocksEGVal == 5 && $transBlocksEGVal == 2} {
        if ![llength [ic_image get global]] {
            ic_image csys_im cartesian
        }
    }
}

proc ontransBlocksEGIUnLoad {} {
   if [llength [ic_image get global]] {
       ic_image delete csys_im
    }
}

proc ontransformBlocksToolsDEZUnLoad {} {
    if {[trace vinfo BlkList] != ""} {
	    trace vdelete BlkList w aie_hex_trace_BlkList
    }
    if [llength [ic_image get global]] {
        ic_image delete csys_im
    }
}

proc aie_hex_trace_BlkList {{name ""} {element ""} {op ""}} {
    if {[transformBlocksToolsDEZ get BlkList] == "" && [ic_geo_is_loaded]} {
        ::AIEnv::GUIManagement::ToggleGrey transMoveBlocksGeom1 0
        ::AIEnv::GUIManagement::ToggleGrey transMoveBlocksGeom2 0
        ::AIEnv::GUIManagement::ToggleGrey transMoveBlocksGeom3 0
        ::AIEnv::GUIManagement::ToggleGrey transMoveBlocksGeom4 0
    } else {
        ::AIEnv::GUIManagement::ToggleGrey transMoveBlocksGeom1 1
        ::AIEnv::GUIManagement::ToggleGrey transMoveBlocksGeom2 1
        ::AIEnv::GUIManagement::ToggleGrey transMoveBlocksGeom3 1
        ::AIEnv::GUIManagement::ToggleGrey transMoveBlocksGeom4 1
        transformBlocksToolsDEZ set also_whole_geom 0
    }
}

proc ontransformBlocksToolsDEZOK {} {
    global top_current fam_visible use_output_blocks
    global replay_recording

    # periodic copy
    if {$transfrmBlocksEGVal == 4} {
        catch { unset parts_to_inc_before; unset parts_to_inc_after; unset inc_i }
	    set cmd "copy_blocking_periodic -ncopies $ncopies"
	    if {$inc_parts != ""} {
	        append cmd " -incr_fams $inc_parts"
	        foreach p $inc_parts {
	            if $use_output_blocks {
                    set blks [eval ic_hex_get_block_families_and_types $p output_blocks]
                } else {
                    set blks [eval ic_hex_get_block_families_and_types $p]
                }
	            foreach pp [lsort -dictionary $blks] {
	               lappend parts_to_inc_before($p) [lindex $pp 0]
	            }
	        }
	    }
	    hex_command $cmd
	    if {$inc_parts != ""} {
	        foreach p $inc_parts {
	            if $use_output_blocks {
                    set blks [eval ic_hex_get_block_families_and_types $p output_blocks]
                } else {
                    set blks [eval ic_hex_get_block_families_and_types $p]
                }
	            foreach pp [lsort -dictionary $blks] {
	                if {[lsearch $parts_to_inc_before($p) [lindex $pp 0]] < 0} {
	                    lappend parts_to_inc_after($p) [lindex $pp 0]
	                }
	            }
	            set i 0
	            if [info exists parts_to_inc_after($p)] {
	                set len_after($p) [llength $parts_to_inc_after($p)]
	                if ![info exists inc_i($p)] { set inc_i($p) 1 }
	                set inc_new ${p}_COPY$inc_i($p)
	                ic_geo_new_family $inc_new
                    ic_boco_set_part_color $inc_new
	                foreach pp $parts_to_inc_after($p) {
                        ic_hex_mark_blocks unmark
                        ic_hex_mark_blocks superblock $pp
                        ic_hex_change_element_id $inc_new
	                    ic_hex_mark_blocks unmark
	                    incr i
	                    if {[expr $len_after($p) / $ncopies] == $i} {
	                        incr inc_i($p)
	                        set inc_new ${p}_COPY$inc_i($p)
	                        ic_geo_new_family $inc_new
	                        ic_boco_set_part_color $inc_new
	                        set i 0
	                    }
	                }
	            }
	        }
	        aie_create_parts_in_tree_if_needed
	    }
	    hex_update_display
	    mess "Done \"Copy Periodic Blocking\"\n"
	    return
    }
    set blks $BlkList
    set blks2 ""
    if {$blks == ""} {
	    mess "Selecting all blocks to transform\n"
	    set blks [string trimright [ic_hex_select_blocks 1 no_highlight all] \n]
	    #set blks [string trimright [ic_hex_select_blocks 1 no_highlight all -keep_unstruct3d] \n]
    } else {
        foreach part [ic_hex_list_block_families_without] {
            foreach b [ic_hex_get_block_families_and_types $part] {
                append blks2 " [lindex $b 0]"
            }
        }
        set blks [lsort -integer $blks]
        set blks2 [lsort -integer $blks2]
        if {"$blks" == "$blks2"} {
            set blks [string trimright [ic_hex_select_blocks 1 no_highlight all] \n]
        }
    }

    # Create a subset of selected blocks
    set subset __TEMP_BLOCK_SUBSET__

    ic_geo_new_family $subset
    set hex_subnum [ic_hex_create_subset display $subset]
    if {$hex_subnum < 0} {
	    ic_geo_delete_family $subset
	    mess "Subset $subset creation failed\n" red	
	    return
    }
    
    eval ic_hex_subset_add_items $subset block [llength $blks] $blks
    if $replay_recording {
	    replay_record_command "replay_put ic_hex_create_subset display $subset"
	    replay_record_command "replay_put ic_hex_subset_add_items $subset block [llength $blks] $blks"
    }

    set mpoint ""
    set norm ""
    set move_about ""

    set move_do_translate 0
    set move_do_rotate 0
    set move_do_mirror 0
    set move_do_scale 0
    set move_translate "0 0 0"

    aie_hex_update_index_form 1
    switch $transfrmBlocksEGVal {
	    0 { 
	        set move_do_translate 1
	        switch $moveBlocksEGVal {
		        0 {
		            set move_translate "$x $y $z"
		        }
		        1 {
			        set move_translate [ic_vcalc diff [lindex $pointList2 0] [lindex $pointList2 1]]
		            if {$move_translate == ""} {
			            msg ERROR "No points selected for offset vector"
			            return
		            }
		        }
	        }
	        set copyGGVal $copyGGVal1
	    }
	    1 {
	        set move_do_rotate 1
	        set move_about $RotateBlkCenterEGVal
	        switch $blkRotateAxisOptionEGVal {
		        0 { set rot_norm {1 0 0} }
		        1 { set rot_norm {0 1 0} }
		        2 { set rot_norm {0 0 1} }
		        3 {
		            set rot_norm [ic_vcalc dir [lindex $axisList 0] [lindex $axisList 1]]
			        if {$rot_norm == ""} {
				        msg ERROR "No points selected for offset vector"
				        return
		            }
		        }
	        }
	        set copyGGVal $copyGGVal2
	    }
	    2 {
	        set move_do_mirror 1
	        set move_about $ReflectBlocksCenterEGVal
	        switch $BlocksMirrorAxisOptionEGVal {
		        0 { set mirror_norm {1 0 0} }
		        1 { set mirror_norm {0 1 0} }
		        2 { set mirror_norm {0 0 1} }
		        3 {
		            set mirror_norm [ic_vcalc dir [lindex $normPointList 0] [lindex $normPointList 1]]
			        if {$mirror_norm == ""} {
				        msg ERROR "No points selected for offset vector"
				        return
		            }
		        }
	        }
    	    set ncopies 1
	        set copyGGVal $copyGGVal3
	    }
	    3 {
	        set move_do_scale 1
	        set move_about $ScaleBlocksCenterEGVal
	        set ncopies 1
	        set copyGGVal $copyGGVal4
	    }
	    5 {
	        set move_do_translate 1
	        set move_do_rotate 1 
	        if $copyGGVal5 {
	            set move_how copy
            } else {
	            set move_how move
            }
            switch $transBlocksEGVal {
                0 {
                    if {[llength $rotateBlocksList] != 6} {
                        ic_mess "Select 6 locations\n" red
                        return
                    }
                    foreach "p00 p01 p02 p10 p11 p12" $rotateBlocksList ""
                    if {[ic_csystem_get_current] != "global"} {
                        foreach p "p00 p01 p02 p10 p11 p12" {
                            set $p [ic_coords_into_global [set $p]]
                        }
                    }
                    set from [list $p00 $p01 $p02]
                    set to [list $p10 $p11 $p12]					
                }
                1 {
                    if {[llength $rotateBlocksList] != 2} {
                        mess "Select two curves\n" red
                        return
                    }
                    foreach i "0 1" {
                        set crv [lindex $rotateBlocksList $i]
                        if ![llength [ic_geo_check_objects_exist curve $crv]] {
                            mess "Select two curves!\n" red
                            return
                        }
                        set p${i}0 [lindex [ic_geo_get_crv_pos 0 $crv] 0]
                        set p${i}1 [lindex [ic_geo_get_crv_pos 0.5 $crv] 0]
                        set p${i}2 [lindex [ic_geo_get_crv_pos 1 $crv] 0]
                    }
                    set from [list $p00 $p01 $p02]
                    set to [list $p10 $p11 $p12]
                }
                2 {
                   # From LCS to LCS
                    set from $fromLCS
                    set to $toLCS
                }
            }
            hex_command "undo_major_start transform_blocking"
            ic_hex_move_lcs_lcs $from $to $top_current $move_how $subset
            hex_command "undo_major_end transform_blocking"
            ic_hex_delete_subset $subset
            ic_geo_delete_family $subset
            hex_update_display
            if $replay_recording {
	            replay_record_command "replay_put ic_hex_delete_subset $subset"
            }
            switch $move_how {
	            copy { aie_hex_check_blocks }
            }
            mess "Done transform\n"
            return
	    }
    }

    switch $move_about {
	    0 { set mpoint "0 0 0" }
	    1 { set mpoint "centroid" }
	    2 { set mpoint [join $center_point] }
    }
   
    set cmd ""
    if $copyGGVal {
	    set move_how copy
    } else {
	    set move_how move
    }
   
    set top_transform_name $top_current
    hex_command "undo_major_start transform_blocking"
    
    switch $move_how {
	    copy {
	        set top_copy_name "__temp__"
	        set last_transform_name $top_transform_name
	        set last_copy_name $top_copy_name
	        for {set i 0} {$i < $ncopies} {incr i} {
		        if { $i == 0 } {
		            set cmd "copy_blocking $last_transform_name $last_copy_name"
		            append cmd " m $subset "
		            hex_command $cmd
		        }
		        set cmd "transform_blocking $last_copy_name "
		        if $move_do_translate {
		            append cmd "translate $move_translate "
		        }
		        if $move_do_rotate {
		            append cmd "rotate $mpoint $rot_norm $rot_angle "
		        }
		        if $move_do_mirror {	
		            append cmd "mirror $mpoint $mirror_norm "
		        }
		        if $move_do_scale {
		            set sc "$xF $yF $zF"
		            append cmd "scale $mpoint $sc "
		        }
		        hex_command $cmd
                # now merge it in
		        set cmd "merge_blocking $top_transform_name $last_copy_name"
		        append cmd " -remove_unused_grid_lines"
		        append cmd " -separate_classes -version 110"
		        hex_command $cmd
		        set last_transform_name $last_copy_name
	        }
	        hex_command "delete_blocking __temp__"
	        set copy_name ""
	    }
	    move {
	        set cmd "transform_blocking $top_transform_name "
	        if $move_do_translate {
		        append cmd "translate $move_translate "
            }
	        if $move_do_rotate {
		        append cmd "rotate $mpoint $rot_norm $rot_angle "
	        }	  
	        if $move_do_mirror {	
		        append cmd "mirror $mpoint $mirror_norm "
	        }
	        if $move_do_scale {
		        set sc "$xF $yF $zF"
		        append cmd "scale $mpoint $sc "
	        }
	        append cmd " m $subset "
	        hex_command $cmd
	    }
    }
    hex_command "undo_major_end transform_blocking"

    # delete the extracted subset
    ic_hex_delete_subset $subset
    ic_geo_delete_family $subset
    catch {unset fam_visible($subset)}

    if {$also_whole_geom && [ic_geo_is_loaded]} {
        mess "Selecting all geometry to transform\n"
        if ![transformSurfsToolsDEZ isbuilt] {
	        transformSurfsToolsDEZ build
        }
        transformSurfsToolsDEZ set transfrmSurfsEGVal $transfrmBlocksEGVal
        set ents [ic_geo_get_objects all "" 1]
        regsub -all "\{" $ents "" ents
        regsub -all "\}" $ents "" ents
        transformSurfsToolsDEZ set surfaceList $ents
        if $move_do_translate {
            transformSurfsToolsDEZ set copyTranslateGGVal $copyGGVal1
            transformSurfsToolsDEZ set moveSurfsEGVal $moveBlocksEGVal
            transformSurfsToolsDEZ set numCopies $ncopies
            switch $moveBlocksEGVal {
		        0 {
                    transformSurfsToolsDEZ set x $x
                    transformSurfsToolsDEZ set y $y
                    transformSurfsToolsDEZ set z $z
                }
                1 {
                    set points $pointList2
                    set movedistance [ic_vcalc distance [lindex $pointList2 0] [lindex $pointList2 1]]
                    transformSurfsToolsDEZ set pointList2 $points
                    transformSurfsToolsDEZ set movedistance $movedistance
                }
            }
        }
        if $move_do_rotate {
            transformSurfsToolsDEZ set copyRotateGGVal $copyGGVal2
            transformSurfsToolsDEZ set RotateGeomCenterEGVal $RotateBlkCenterEGVal
            transformSurfsToolsDEZ set rotateCenterPnt $mpoint
            transformSurfsToolsDEZ set geomRotateAxisOptionEGVal $blkRotateAxisOptionEGVal
            transformSurfsToolsDEZ set axisSurfList $axisList
            transformSurfsToolsDEZ set rot_angle $rot_angle
        }	  
        if $move_do_mirror {
            transformSurfsToolsDEZ set copyMirrorGGVal $copyGGVal3
            transformSurfsToolsDEZ set ReflectGeomCenterEGVal $ReflectBlocksCenterEGVal
            transformSurfsToolsDEZ set geomMirrorAxisOptionEGVal $BlocksMirrorAxisOptionEGVal
            transformSurfsToolsDEZ set normPointList $normPointList
            transformSurfsToolsDEZ set reflectCenterPnt $center_point
        }
	    if $move_do_scale {
	        transformSurfsToolsDEZ set copyScaleGGVal $copyGGVal4
	        transformSurfsToolsDEZ set xF $xF
	        transformSurfsToolsDEZ set yF $yF
	        transformSurfsToolsDEZ set zF $zF
	        transformSurfsToolsDEZ set ScaleGeomCenterEGVal $ScaleBlocksCenterEGVal
	        transformSurfsToolsDEZ set scaleCenterPnt $center_point
        }
        transformSurfsToolsDEZ apply
	}
   
    get_indices 1
    hex_update_display
    aie_hex_update_index_form 0
    transformBlocksToolsDEZ setdirty
#    set BlkList ""
    if $replay_recording {
	    replay_record_command "replay_put ic_hex_delete_subset $subset"
    }
    switch $move_how {
	    copy {
            aie_hex_check_blocks
        }
    }
    mess "Done transform\n"
}

proc aie_hex_check_blocks {} {
    global use_output_blocks

    set fams ""
    foreach f [ic_hex_list_block_families] {
        lappend fams $f
    }

    if $use_output_blocks {
        set blks [eval ic_hex_get_block_families_and_types $fams output_blocks]
    } else {
        set blks [eval ic_hex_get_block_families_and_types $fams]
    }
    catch { unset dup }
    foreach blk $blks {
        set n [lindex $blk 0]
        set t [lindex $blk 2]
        if ![info exists dup($t,$n)] {
            set dup($t,$n) 1
        } else {
            incr dup($t,$n)
        }
    }
    foreach n [lsort [array names dup]] {
        if {$dup($n) > 1} {
             mess "Found $dup($n) blocks with number [lindex [split $n ,] 1]; run \"Check/Fix\"\n" red
        }
    }
}

proc aie_rotate_blocks {} {
    set blocks [select_hexa block 0 "blocks to rotate IJK"]
    foreach blk $blocks {
	    hex_command "rotate_super_block $blk"
    }
    hex_update_display block
}

proc aie_init_output_blocks {} {
    global use_output_blocks
    if ![ic_hex_blocking_loaded] {
        mess "No Blocking is loaded!\n" red
        return
    }
    hex_command init_output_blocks
    if {$use_output_blocks == 1} {
    	hex_update_display block edge
    }
    mess "Output blocks initialized\n"
}

proc aie_hex_recompute_mesh {} {
    global project_type last_line hex_option dim_to_mesh
    global options plot_window display_flag
    global histo_title histo_nbars histo_minv histo_maxv histo_ylim

    if ![ic_hex_blocking_loaded] {
        mess "No blocking file is loaded\n" red
        return
    }

    set fams [volume_activename_string]
    set fams2 ""
    set blk_fams [ic_hex_non_empty_families]
    set geo_fams [ic_geo_non_empty_families]
    foreach f $fams {
        if {[lsearch $blk_fams $f] > -1 || [lsearch $geo_fams $f] > -1} {
            lappend fams2 $f
        }
    }
    set fams $fams2
    if {$fams == ""} return
    # to avoid recomputing when only part VORFN is on
    if {$fams == "VORFN"} {
        mess "Will not compute Pre-mesh for part VORFN region only\n" red
        return
    }
    set ptype $project_type
    if ![info exists hex_option(project_bspline)] {
        set hex_option(project_bspline) 0
    }
    if {$ptype == 2  && ($hex_option(project_bspline))} {
        set ptype 3
    }
    set freeze_fams ""
    set cmd "create_mesh $fams proj $ptype dim_to_mesh $dim_to_mesh"
    if {$freeze_fams != ""} {
        append cmd " -freeze $freeze_fams"
    }
    set part_disabled ""
    foreach "part proj" [string trimright [ic_hex_list_family_projection] \n] {
       if !$proj { lappend part_disabled $part }
    }
    if {$part_disabled != ""} {
        mess "Projection to part(s) $part_disabled has been disabled\n" red
    }
    mess "Number of processors  =  $options(n_processors)\n" 
    if { $options(n_processors) != 1 } {
        append cmd " nproc $options(n_processors)"
    }
    busy 1
    if [ic_wb2_is_running] {
        aie_set_global wb2_icemcfd_running 1
    }
    mess "Recompute pre-mesh...\n"
    aie_hex_clear_worst_element
    set update_display "vert edge face block mesh"

    set res [hex_command $cmd]
    if {$res != ""} {
        set num [string first "Error:" $res]
        if {$num > -1} {
            mess "[string range $res $num end]" red
            if {[ic_hex_count_unstruct_blocks 3d] > 0} {
                set tmp_files [glob -nocomplain "[ic_temp_dir]/temp_cmd*.[pid].*.log"]
                foreach f $tmp_files {
                    if [file isfile $f] {
	                    set fp [open $f r]
	                    set data [read $fp]
	                    close $fp
	                    catch { file delete $f }
	                    set num [string first "ERR " $data]
	                    if {$num > -1} {
	                        mess "[string range $data $num end]" red
	                    }
	                }
                }
            }
        } else {
            set num [string first "Note:" $res]
            if {$num > -1} {
                set num2 [string first "\n" $res $num]
                if {$num2 > -1} { mess "[string range $res $num $num2]" }
            }
        }
    }
    mess "Done recompute pre-mesh\n"
	if [ic_wb2_is_running] {
	    aie_unset_global wb2_icemcfd_running
	}
    busy 0
    if {[info exists plot_window] && [winfo exists $plot_window.graph]} {
        if ![hexQualityDEZ isbuilt] {
            hexQualityDEZ build
            hexQualityDEZ apply
        } else {
            if [info exists histo_title] { 
                aie_hex_update_histogram "$histo_title" $histo_nbars $histo_minv $histo_maxv $histo_ylim
            }
        }
    }
    foreach type $update_display {
        if $display_flag($type) {
            hex_update_display $type
        }
    }
    hex_update_display scan
}

proc aie_renumber_blocks {} {
    global last_line display_flag use_output_blocks
    global renumber_pos renumber_at renumber_tag

    catch {form_kill .renum}
    catch {unset renumber_at}
    catch {unset renumber_pos}

    set cmd pack_superblocks
    if $use_output_blocks { append cmd " output_blocks" }
    append cmd " [volume_activename_string]"
    hex_command $cmd

    set ndom $last_line
    if !$ndom {
        mess "Error: can't renumber blocks -- no superblocks found\n" red
        return
    }
    #set ndom 300

# save off old values
    set db $display_flag(block)
    set ds $display_flag(block_super)
# turn on super block display
    set display_flag(block) 1
    set display_flag(block_super) 1
    hex_update_display block

    set d [form_init .renum "Blocks renumbering" mesh "accept cancel"]

    set can [form_canvas $d.c 400x200 sunken 2 {0 0 -fill y} 0 1]

    set its ""
    for {set i 1} {$i <= $ndom} {incr i} {
        set r [expr {($i - 1) / 10}]
        set c [expr {($i - 1) % 10}]
        set renumber_pos($i) "$r $c"

        set it2 [$can create rectangle 0 0 0 0 -fill [.renum cget -background]\
                     -width 1 -outline black]
        set it [$can create text 0 0 -fill black -text $i]

        #frame $can.fr$i -width 28 -height 18 -relief raised -borderwidth 2
        #label $can.fr$i.l -text $i
        #pack $can.fr$i.l -fill both -anchor c
        #pack propagate $can.fr$i 0
        #set it [$can create window 0 0 -window $can.fr$i -anchor c]
        set renumber_tag($i) "$it $it2"
        renumber_putrc $i

        foreach x "$it $it2" {
            $can bind $x <ButtonPress-1> "$can raise $it2; $can raise $it"
            $can bind $x <Button1-Motion> \
                "renumber_move $i \[renum_p %W x %x\] \[renum_p %W y %y\]"
            $can bind $x <ButtonRelease-1> \
                "renumber_putrc $i \[renum_p %W x %x\] \[renum_p %W y %y\]"
        }

        lappend its $it $it2
    }
   
    set bb [eval $can bbox $its]
    set v0 [lindex $bb 0]
    set v1 [lindex $bb 1]
    set v2 [lindex $bb 2]
    set v3 [lindex $bb 3]
    $can configure -scrollregion "$v0 $v1 $v2 [expr $v3 + 40]"
    if {[winfo screenwidth .] > 2048} {
        form_finish +[expr [winfo rootx .] + 50]+300
    } else {
        form_finish +300+300
    }

    if [form_wait .renum] {
        set cmd "change_superblocks"
        if $use_output_blocks { append cmd " output_blocks" }

        # Now grab all the data.
        foreach rc [lsort -command renumber_cmp [array names renumber_at]] {
            lappend cmd $renumber_at($rc)
        }
        hex_command $cmd
    }

# restore old values
    set display_flag(block) $db
    set display_flag(block_super) $ds

    hex_update_display edge face block
}

proc renum_p {w x v} {
    return [expr int([$w canvas$x $v])]
}

proc renumber_cmp {v1 v2} {
    if {[lindex $v1 0] == [lindex $v2 0]} {
        return [expr {[lindex $v1 1] - [lindex $v2 1]}]
    } else {
        return [expr {[lindex $v1 0] - [lindex $v2 0]}]
    }
}

proc renumber_putrc {i {xpos ""} {ypos ""}} {
    global renumber_pos renumber_at renumber_tag


    set can .renum.main.c.c
    set r [lindex $renumber_pos($i) 0]
    set c [lindex $renumber_pos($i) 1]
    if {$xpos != ""} { set c [expr $xpos / 40] }
    if {$ypos != ""} { set r [expr $ypos / 20] }
    set xpos [expr {$c * 40}]
    set ypos [expr {$r * 20}]
    renumber_setpos $i $xpos $ypos

    catch {unset renumber_at($renumber_pos($i))}

    # Now move the others out of the way.
    renumber_moveup $r $c

    set "renumber_at($r $c)" $i
    set renumber_pos($i) "$r $c"
}

proc renumber_setpos {i x y} {
    global renumber_tag

    set can .renum.main.c.c
    $can coords [lindex $renumber_tag($i) 0] \
        [expr $x + 20] [expr $y + 10]
    $can coords [lindex $renumber_tag($i) 1] \
        [expr $x + 1] [expr $y + 1] [expr $x + 39] [expr $y + 19]
}

proc renumber_moveup {r c} {
    global renumber_at


    if [info exists "renumber_at($r $c)"] {
        set nr $r; set nc [expr $c + 1]
        if {$nc == 10} { set nc 0; incr nr }
        renumber_moveup $nr $nc
        renumber_putrc [set "renumber_at($r $c)"] \
            [expr $nc * 40] [expr $nr * 20]
    }
}

proc renumber_move {i xpos ypos} {
    renumber_setpos $i [expr $xpos - 20] [expr $ypos - 10]
}


######################## Block Primitives ###########################

proc oncreateBlockPrimDEZLoad {} {
    set PartList [aie_hex_list_parts 1]
    if {$part_name == ""} { set part_name SOLID }
    if ![ic_hex_blocking_loaded] {
        ic_hex_initialize_mesh
	    mess "Blocking initialized\n" blue
    }
}

proc oncreateBlockPrimDEZOK {} {
    set fam [aie_new_part $part_name]
    switch $createBlkPrimVal {
	0 {
	    if {$curve1 == ""} {
            msg ERROR "No Curve-A selected"
		    return
	    }
	    if {$curve2 == ""} {
		    msg ERROR "No Curve-B selected"
		    return
	    }
	    if {$point1 == ""} {
		    msg ERROR "No Point-A selected"
		    return
	    }
	    if {$point2 == ""} {
		    msg ERROR "No Point-B selected"
		    return
	    }
	    if {$d1 == ""} {
		    msg ERROR "No Block-A size specified"
		    return
	    }
	    if {$d2 == ""} {
		    msg ERROR "No Block-B size specified"
		    return
	    }
	    foreach i {1 2} {
		    set pt [lindex [set point$i] 0]
		    if {[llength $pt] == 1} {
		        set pt$i [ic_geo_get_point_location $pt]
		    } else {
		        set pt$i $pt
		    }
	    }	
	    set cmd "create_block_primitive T $fam $curve1 $curve2 $pt1 $pt2 $d1 $d2 -version 51"
	    hex_command $cmd
	}
	1 {
	     if {$curve1 == ""} {
		    msg ERROR "No Curve-A selected"
		    return
	    }
	    if {$curve2 == ""} {
		    msg ERROR "No Curve-B selected"
		    return
	    }
	    if {$curve3 == ""} {
		    msg ERROR "No curve-C selected"
		    return
	    }
	    if {$point1 == ""} {
		    msg ERROR "No Point-A selected"
		    return
	    }
	    if {$point2 == ""} {
		    msg ERROR "No Point-B selected"
		    return
	    }
	    if {$point3 == ""} {
		    msg ERROR "No Point-C selected"
		    return
	    }
	    if {$d1 == ""} {
		    msg ERROR "No Block-A size specified"
		    return
	    }
	    if {$d2 == ""} {
		    msg ERROR "No Block-B size specified"
		    return
	    }
	    if {$d3 == ""} {
		    msg ERROR "No Block-C size specified"
		    return
	    }
	    foreach i {1 2 3} {
		    set pt [lindex [set point$i] 0]
		    if {[llength $pt] == 1} {
		        set pt$i [ic_geo_get_point_location $pt]
		    } else {
		        set pt$i $pt
		    }
	    }	
	    set cmd "create_block_primitive Y $fam $curve1 $curve2 $curve3 $pt1 $pt2 $pt3 $d1 $d2 $d3 -version 51"
	    hex_command $cmd
	}
	2 {
	    if {$curve1 == ""} {
		    msg ERROR "No center curve selected"
		    return
	    }
	    if {$point1 == ""} {
		    msg ERROR "No Point-A selected"
		    return
	    }
	    if {$point2 == ""} {
		    msg ERROR "No Point-B selected"
		    return
	    }
	    if {$d1 == ""} {
		    msg ERROR "No Block size specified"
		    return
	    }
	    foreach i {1 2} {
		    set pt [lindex [set point$i] 0]
		    if {[llength $pt] == 1} {
		        set cpt$i [ic_geo_get_point_location $pt]
		    } else {
		        set cpt$i $pt
		    }
	    }	
	   
	    set vec ""
	    if {[llength $vecList] != 2} {
		    msg ERROR "No points selected for side face direction"
		    return
	    }
		   
	    set i 0
	    foreach pt $vecList {
		    if {[llength $pt] == 1} {
		        set pt$i [ic_geo_get_point_location $pt]
		    } else {
		        set pt$i $pt
		    }
		    incr i
	    }
	    foreach i {0 1 2} {
		    lappend vec [expr [lindex $pt1 $i] - [lindex $pt0 $i]]
	    }

	    set cmd "create_block_primitive BF $fam $curve1 $curve1 $cpt1 $cpt2 $d1 0 $vec -version 51"
	    hex_command $cmd
	}
	3 {
	    if {$curve1 == ""} {
		    msg ERROR "No center curve selected for extrusion"
		    return
	    }
	    if {$startFace== ""} {
		    msg ERROR "No start face selected"
		    return
	    }
	    if {$endFace== ""} {
		    msg ERROR "No end face selected"
		    return
	    }
	    if {[llength $startVerts] != 2} {
		    msg ERROR "No start edge vertices selected"
		    return
	    }
	    if {[llength $endVerts] != 2} {
		    msg ERROR "No end edge vertices selected"
		    return
	    }
	    set sface [lindex $startFace 0]
	    set eface [lindex $endFace 0]
	   
	    set cmd "extrude_faces 4 \{ [lindex $sface 0] [lindex $sface 3] \}"
	    append cmd " \{ [lindex $eface 0] [lindex $eface 3] \}"
	    append cmd " \{ $startVerts \} \{ $endVerts \}"
	    append cmd " $fam 1.0 -curve $curve1 -nsub $numLay -type 3 [family_activename_string] -version 50"
	    hex_command $cmd
	}
    }
   
    get_indices 1
    index_update_all
    hex_update_display   
}

proc oncreateBlockPrimDEZUnLoad {} {
    hex_update_display vertex
}

proc oncreateBlkStartVertsPickFinish {} {
    aie_hex_disp_ext_verts
}

proc oncreateBlkEndVertsPickFinish {} {
    aie_hex_disp_ext_verts
}

proc aie_hex_disp_ext_verts {} {
    set sverts [createBlockPrimDEZ get startVerts]
    set everts [createBlockPrimDEZ get endVerts]
    set nodes [concat $sverts $everts]
    if {$nodes != ""} {
        hex_command "display_nodes [range_string] [family_activename_string] number [join $nodes] numbers"
    }
}

proc aie_hex_show_inverted {} {
    hex_command "mark_blocks unmark"
    hex_command "mark_blocks inverted"
    set opts "marked m [volume_activename_string] -solid"
    hex_command "display_elements $opts"
    hex_command "mark_blocks unmark"
}

#########################################################################

proc onhexMeshOptsDEZLoad {} {
    global default_bunch_laws quad_types dim_to_mesh hex_option beta_mode
    global hex_diagnostic_3d

    if ![info exists lawList] {
	    set lawList [array names default_bunch_laws]
    }
    if ![info exists unsTypeList] {
	    set unsTypeList [array names quad_types]
    }
    if ![info exists unsMethodList] {
	    set unsMethodList [list "ICEM CFD Quad" "Gambit Pave" "Auto"]
    }
    set check_blck 0
    set mgLevel 0
    set projLimit 0
    set floatGrid 0
    set smoothOgrid 0
    set proj 0
    set trfDeg 1
    set refTopo ""
    set meshLaw BiGeometric
    if {![info exists unsType] || $unsType == ""} {
    	set unsType "Quad w/one Tri"
    }
    if {![info exists unsMethod] || $unsMethod == ""} {
    	set unsMethod "Uniform Quad"
    }
    set ratio 2.0
    set old_eparams 0
    set wr_hexa7 0
    set quad_debug -1
    if ![info exists hexEntTypes] {
	    set hexEntTypes {"Vertices" "Edges" "Faces" "Struct. & Swept Blocks" "All Blocks"}
    }
    set what_to_mesh "All Blocks"
    set nTetSmooth 20
    set hexa_verbose_mode 0
    set hexa_update_mode 1
    set find_worst 1-3

    set hex_option(old_eparams) 0
    if [info exists hex_option(check_blck)] {
        set check_blck $hex_option(check_blck)
    }
    if [info exists hex_option(check_inv)] {
        set check_inv $hex_option(check_inv)
    }
    if [info exists hex_option(old_eparams)] {
        set old_eparams $hex_option(old_eparams)
    }
    if [info exists hex_option(wr_hexa7)] {
        set wr_hexa7 $hex_option(wr_hexa7)
    }
    if [info exists hex_option(uns_face_mesh)] {
        set unsType $hex_option(uns_face_mesh)
        foreach name [array names quad_types] {
            if {$unsType == "$quad_types($name)"} {
                set unsType $name
            }
        }
    }
    if [info exists hex_option(uns_face_mesh_method)] {
        set method $hex_option(uns_face_mesh_method)
        if {$method == "uniform_quad"} {
            set unsMethod "ICEM CFD Quad"
        } elseif {$method == "gambit_pave"} {
            set unsMethod "Gambit Pave"
        } elseif {$method == "auto"} {
           set unsMethod "Auto"
        }
    }
    if [info exists hex_option(default_bunching_law)] {
        set meshLaw $hex_option(default_bunching_law)
    }
    if [info exists hex_option(default_bunching_ratio)] {
        set ratio $hex_option(default_bunching_ratio)
    }  
    if [info exists hex_option(floating_grid)] {
        set floatGrid $hex_option(floating_grid)
    }
    if [info exists hex_option(smooth_ogrid)] {
        set smoothOgrid $hex_option(smooth_ogrid)
    }
    if [info exists hex_option(proj_limit)] {
        set projLimit $hex_option(proj_limit)
    }
    if [info exists hex_option(multigrid_level)] {
        set mgLevel $hex_option(multigrid_level)
    }
    if [info exists hex_option(n_tetra_smoothing_steps)] {
        set nTetSmooth $hex_option(n_tetra_smoothing_steps)
    }
    if [info exists hex_option(project_bspline)] {
        set proj $hex_option(project_bspline)
    }
    if [info exists hex_option(trfDeg)] {
        set trfDeg $hex_option(trfDeg)
    }
    if [info exists hex_option(hexa_verbose_mode)] {
        set hexa_verbose_mode $hex_option(hexa_verbose_mode)
    }
    if [info exists hex_option(hexa_update_mode)] {
        set hexa_update_mode $hex_option(hexa_update_mode)
    }
    if [info exists hex_option(find_worst)] {
        set find_worst $hex_option(find_worst)
    }
    if [info exists hex_option(project_to_topo)] {
        set project_to_topo $hex_option(project_to_topo)
    }
    
    set hexa_sketching_mode 0
    if $beta_mode {
        if [info exists hex_option(sketching_mode)] {
            set hexa_sketching_mode $hex_option(sketching_mode)
        }
    }
}

proc onhexMeshOptsDEZAfterLoad {} {
    global default_bunch_laws quad_types beta_mode
    global hex_option dim_to_mesh do_not_save_hexa_settings
    
    if {[ic_hex_blocking_loaded] && $hexa_update_mode} {
        mess "\nUpdating Hexa Meshing Options from current blocking..." blue
        after 500 {
            hexMeshOptsDEZ set mgLevel [string trimright [ic_hex_multi_grid_level] \n]
            set hex_option(multigrid_level) [hexMeshOptsDEZ get mgLevel]
            hexMeshOptsDEZ set projLimit [string trimright [ic_hex_projection_limit] \n]
            set hex_option(proj_limit) [hexMeshOptsDEZ get projLimit]
            hexMeshOptsDEZ set nTetSmooth [string trimright [ic_hex_set_n_tetra_smoothing_steps] \n]
            set hex_option(n_tetra_smoothing_steps) [hexMeshOptsDEZ get nTetSmooth]
            set law_ratio [string trimright [ic_hex_default_bunching_law new_format] \n]
            set law [lindex $law_ratio 0]
            hexMeshOptsDEZ set ratio [lindex $law_ratio 1]
            set hex_option(default_bunching_ratio) [hexMeshOptsDEZ get ratio]
            set meshLaw $law
            foreach name [array names default_bunch_laws] {
                if {$law == $default_bunch_laws($name)} {
                    hexMeshOptsDEZ set meshLaw $name
                    set hex_option(default_bunching_law) [hexMeshOptsDEZ get meshLaw]
                    break
                }
            }
            hexMeshOptsDEZ set floatGrid [string trimright [ic_hex_floating_grid] \n]
            set hex_option(floating_grid) [hexMeshOptsDEZ get floatGrid]
            hexMeshOptsDEZ set smoothOgrid [string trimright [ic_hex_ogrid_smooth_transition] \n]
            set hex_option(smooth_ogrid) [hexMeshOptsDEZ get smoothOgrid]
            hexMeshOptsDEZ set trfDeg [string trimright  [ic_hex_transfinite_degree] \n]
            set hex_option(trfDeg) [hexMeshOptsDEZ get trfDeg]
            hexMeshOptsDEZ set refTopo [string trimright [ic_hex_reference_blocking] \n]
            set type [string trimright [ic_hex_unstruct_face_type] \n]
            set unsType $type
            foreach name [array names quad_types] {
                if {$type == "$quad_types($name)"} {
                    hexMeshOptsDEZ set unsType $name
                    set hex_option(uns_face_mesh) $type
                    break
                }
            }
            set name ""
            set method [string trimright [ic_hex_set_unstruct_face_method] \n]
            set unsMethod $method
            if {$method == "uniform_quad"} {
                set name "ICEM CFD Quad"
            } elseif {$method == "gambit_pave"} {
                set name "Gambit Pave"
            } elseif {$method == "auto"} {
                set name "Auto"
            }
            if {$name != ""} {
                hexMeshOptsDEZ set unsMethod $name
                set hex_option(uns_face_mesh_method) $method
            }
            set dim_to_mesh [format %g [ic_hex_dim_to_mesh]]
            switch $dim_to_mesh {
                0 { hexMeshOptsDEZ set what_to_mesh "Vertices" }
                1 { hexMeshOptsDEZ set what_to_mesh "Edges" }
                2 { hexMeshOptsDEZ set what_to_mesh "Faces" }
                2.5 { hexMeshOptsDEZ set what_to_mesh "Struct. & Swept Blocks" }
                default { hexMeshOptsDEZ set what_to_mesh "All Blocks" }
            }
            hexMeshOptsDEZ set project_to_topo [string trimright [ic_hex_project_to_topo] \n]
            set do_not_save_hexa_settings 1
            hexMeshOptsDEZ apply
            unset do_not_save_hexa_settings
        }
        mess "done\n" blue
    }
    if [ic_hex_blocking_loaded] {
        set displayLevel 0
        if {[trace vinfo mgLevel] != ""} {
            trace vdelete mgLevel w aie_hex_trace_mgLevel
        }
        trace variable mgLevel w aie_hex_trace_mgLevel
    }
}

proc onhexMeshOptsDEZUnLoad {} { 
    if [ic_hex_blocking_loaded] {
        if {[trace vinfo mgLevel] != ""} {
            trace vdelete mgLevel w aie_hex_trace_mgLevel
        }
    }
    set displayLevel 0
    aie_hex_check_multigrid_level
}

proc onhexMeshOptsDEZOK {} {
    global quad_types hex_option default_bunch_laws
    global dim_to_mesh do_not_save_hexa_settings beta_mode

    set hex_option(project_bspline) $proj
    set hex_option(multigrid_level) $mgLevel
    set hex_option(check_blck) $check_blck
    set hex_option(check_inv) $check_inv
    set hex_option(old_eparams) 0
    set hex_option(wr_hexa7) $wr_hexa7
    set type $unsType
    if [info exists quad_types($type)] {
        set type $quad_types($type)
        set hex_option(uns_face_mesh) $type
    }
    set hex_option(uns_face_mesh_method) "uniform_quad"
    if {$unsMethod == "Gambit Pave"} {
        set hex_option(uns_face_mesh_method) "gambit_pave"
    } elseif {$unsMethod == "Auto"} {
       set hex_option(uns_face_mesh_method) "auto"
    }
    set method $hex_option(uns_face_mesh_method)
    set hex_option(default_bunching_law) $meshLaw
    set hex_option(default_bunching_ratio) $ratio
    set hex_option(floating_grid) $floatGrid
    set hex_option(smooth_ogrid) $smoothOgrid
    set hex_option(proj_limit) $projLimit
    set hex_option(n_tetra_smoothing_steps) $nTetSmooth
    set hex_option(trfDeg) $trfDeg
    set hex_option(hexa_verbose_mode) $hexa_verbose_mode
    set hex_option(hexa_update_mode) $hexa_update_mode
    if {$find_worst == ""} { set find_worst 1-3 }
    set hex_option(find_worst) $find_worst
    set hex_option(project_to_topo) $project_to_topo

    aie_hex_clear_worst_element

    if $beta_mode {
        set hex_option(sketching_mode) $hexa_sketching_mode
    }
    
    if ![info exists do_not_save_hexa_settings] {
        # save settings to ~/.aienv_options
        aie_set_options
    } else {
        return
    }
    if ![ic_hex_blocking_loaded] return

    mess "Updating current blocking from Hexa Meshing Options\n" blue
    switch $what_to_mesh {
	    "Vertices"  {set dim_to_mesh 0}
	    "Edges" {set dim_to_mesh 1}
	    "Faces" {set dim_to_mesh 2}
	    "Struct. & Swept Blocks" {set dim_to_mesh 2.5}
	    "All Blocks" {set dim_to_mesh 3}
    }
    hex_command "multi_grid_level $mgLevel"
    hex_command "projection_limit $projLimit"
    set law $meshLaw
    if [info exists default_bunch_laws($law)] {
        set law $default_bunch_laws($law)
    }
    hex_command "default_bunching_law $law $ratio"
    if $floatGrid {
        hex_command "floating_grid on"
    } else {
        hex_command "floating_grid off"
    }
    if $smoothOgrid {
        hex_command "ogrid_smooth_transition on"
    } else {
        hex_command "ogrid_smooth_transition off"
    }
    hex_command "transfinite_degree $trfDeg"
    hex_command "reference_blocking $refTopo"
    hex_command "unstruct_face_type $type"
    hex_command "set_unstruct_face_method $method"
    hex_command "dim_to_mesh $dim_to_mesh"
    hex_command "set_n_tetra_smoothing_steps $nTetSmooth"
    if $hex_option(hexa_verbose_mode) {
        hex_command "error_messages on_minor"
    } else {
        hex_command "error_messages off_minor"
    }
    if $project_to_topo {
        hex_command "project_to_topo on"
    } else {
        hex_command "project_to_topo off"
    }
    ic_quad_debug $quad_debug 
    hex_update_display
}

proc aie_hex_opts_restore_defaults {} {
    set check_blck 0
    set mgLevel 0
    set projLimit 0
    set floatGrid 0
    set smoothOgrid 0
    set proj 0
    set trfDeg 1
    set refTopo ""
    set meshLaw BiGeometric
    set unsType "Quad w/one Tri"
    set unsMethod "ICEM CFD Quad"
    set ratio 2.0
    set wr_hexa7 0
    set quad_debug -1
    set what_to_mesh "All Blocks"
    set nTetSmooth 20
    set hexa_verbose_mode 0
    set hexa_update_mode 1
    set find_worst 1-3
    set project_to_topo 0
    hexMeshOptsDEZ apply
}

proc aie_hex_trace_mgLevel {{name ""} {element ""} {op ""}} {
     aie_hex_check_multigrid_level
}

proc aie_hex_check_multigrid_level {} {
    global hex_option multigrid_level_subset

    if ![ic_hex_blocking_loaded] return
    busy reset
    set level [hexMeshOptsDEZ get mgLevel]
    set check [hexMeshOptsDEZ get displayLevel]
    if [info exists multigrid_level_subset] {
        ic_hex_delete_subset number $multigrid_level_subset
        hex_update_display edge
        unset multigrid_level_subset
    }
    if {$check == 0} return
    set picked [join [ic_hex_multi_grid_level_check $level]]
    if {[llength $picked] == 0} return
    set subset [format %d [ic_hex_create_subset selection]]
    hex_command "subset_add_items number $subset edge [llength $picked] [join $picked]"
    set opts [display_edge_mesh_params]
    eval ic_hex_display_subset number $subset edge $opts
    set multigrid_level_subset $subset
}

proc aie_hex_find_worse {} {
    global display_flag hex_option use_output_blocks

    set find_worst $hex_option(find_worst)
    if $display_flag(block_worst) {
        set blocks ""
        set find_worst [split $find_worst -]
        set from [lindex $find_worst 0]
		set to [lindex $find_worst end]
		if {$from < 1} { set from 1 }
		if {$to < 1} { set to 1 }
        if $use_output_blocks {
            set worse [eval ic_hex_worst_hex -do_10_worst [expr $from - 1] [expr $to - 1] output_blocks [volume_activename_string]]
        } else {
		    set worse [eval ic_hex_worst_hex -do_10_worst [expr $from - 1] [expr $to - 1] [volume_activename_string]]
		}
		set blocks ""
		if {[llength $worse] > 0} {
            mess "\nRange of displaying worst blocks: $from - $to\n"
		    mess "\nBlock\t\t\tWorst hex determinant\n"
		    foreach n $worse {
		        set a [lindex $n 0]
		        set b [lindex $n 1]
		        append blocks "$a "
		        mess "$a\t\t\t$b\n"
		    }
            if $display_flag(block) {
                set opts "m [volume_activename_string]"
                if $use_output_blocks { append opts " output_blocks" }
                if $display_flag(block_super) { append opts " super" }
                if $display_flag(block_solid) { append opts " -solid" }
                if $display_flag(block_ijk) { append opts " orientation" }
                if $display_flag(block_noshrink) { append opts " no_shrink" }
                if !$display_flag(block_struct) { append opts " -hide_struct" }
                if !$display_flag(block_unstruct) { append opts " -hide_unstruct" }
                if !$display_flag(block_swept) { append opts " -hide_swept" }
                append opts " highlight $blocks "
                hex_command "display_elements $opts"
            }
        }
    } else {
        hex_command "worst_hex erase"
    }
}

############################ Unstruct smoother ####################

proc onhexSmoothDEZLoad {} {

    if {$quality == ""} {
        set quality 0.2
    }
    if ![info exists qualityDDList] {
	set smoothPremeshVal 0
	set qualityDDList {"Determinant 3x3x3" Angle}
	set qualitydde "Determinant 3x3x3"
	set itersSurf 10
	set itersVol 5
	set expansionSurf 0.0
	set expansionVol 0.0
	set stabilizeSurf 1.0
	set stabilizeVol 2.0
	set numLayersFix 0
	set niterPost 3
	set limitPost 0.2
	set rebunchEdges 0
	set treatUnstruct 0
	set SrfFitFlag 1
	set KperGeomFlag 1
	HEXsmoothTypeSOEMS select "Faces" "Orthogonality"
	HEXsmoothTypeSOEMS select "Volume" "Orthogonality"
	set useorthoDistSurf 0
	set useorthoDistVol 0
        set RelaxBlocks ""
        set NonRelaxFaces ""
        set HoldCellHeightFaces ""
        set GlobalVertices ""
        set LayerVertices ""
        set VolumeList [list "Laplace" "Sorenson - Laplace" "Sorenson - Thomas & Middlecoff" \
                     "Thomas & Middlecoff" "Interpolation" "Hilgenstock - Thomas & Middlecoff" \
                     "Hilgenstock - Laplace"]
        set FaceList [list "Laplace" "Sorenson - Laplace" "Sorenson - Thomas & Middlecoff" \
                     "Thomas & Middlecoff" "Interpolation" "Hilgenstock - Thomas & Middlecoff" \
                     "Hilgenstock - Laplace"]
        set refEdge ""
        set refEdgeDir ""
        set startIndex 1
        set endIndex 1
        set incrIndex 1
        set iterIndex 0
        set planeNums ""
        set itersEdges 25
        set itersVertices 25
        set parameterPrjLim 0.0
        set parameterRelFac 0.5
        set parameterResFac 0.05
        set parameterUseProj 1
        set parameterFaceFit 1
        set parameterUseOrt 1
        set parameterUseFra 0
        set volume_method "Sorenson - Laplace"
        set face_method "Sorenson - Laplace"
        set gridexpansionVol 4.6
        set gridexpansionFace 3.5
        set smoothFilterNonRelax 0
        set smoothFilterHoldCellHeight 0
        set smoothFaceOptionsVal 0
        set smoothVertexEntitiesVal 0
        set smoothAdvancedVal 1
        set HEXsmoothDirVal 1
        set NonRelaxRemove 1
        set HoldCellHeightRemove 1
        set HEXsmoothMBSVal 0
        set mbs_setting_load ""
        set mbs_setting_save ""
        set mbs_setting_seq_1 ""
        set mbs_setting_seq_2 ""
        set mbs_setting_seq_3 ""
        set mbs_setting_seq_4 ""
        set mbs_setting_seq_5 ""
        set mbs_setting_old ""
        set mbs_setting_new ""
        set display_blocks_off 0
        set display_faces_off 0
        set display_vertices_off 1
        set display_faces_icons 0
    }
    mess "Updating histogram...\n"
    aie_hex_update_histogram $qualitydde
    hexSmoothDEZ setdirty
}

proc onHEXchooseQualityDDEModify {dez val} {
    aie_hex_update_histogram $val
}

proc onhexSmoothDEZAfterLoad {} {
    global smooth_multi_block use_output_blocks is_output_blocks test_smooth

    # Orthogonality smoother start   
    aie_hex_rebunch_edge_active 0
    aie_hex_treat_unstruct_active 0
    set freezeCriterion 1
    # Orthogonality smoother end
    
    set is_output_blocks $use_output_blocks
    if ![info exists smooth_multi_block(topology_information)] {
        if {$smoothPremeshVal == 2} {
            onHEXsmoothPremeshbyMultiblockLoad
        }
    }
    if {[trace vinfo smoothPremeshVal] != ""} {
        trace vdelete smoothPremeshVal w onHEXsmoothPremeshbyMultiblockLoad
    }
    trace variable smoothPremeshVal w onHEXsmoothPremeshbyMultiblockLoad

    if {[trace vinfo partFixList] != ""} {
        trace vdelete partFixList w aie_hex_trace_partFixList
    }
    trace variable partFixList w aie_hex_trace_partFixList
    if {[trace vinfo partFirstList] != ""} {
        trace vdelete partFirstList w aie_hex_trace_partFirstList
    }
    trace variable partFirstList w aie_hex_trace_partFirstList

    # 1000 should be enough time to get the DEZ settings from the project file and to set the test_smooth array
    after 1000 {
        catch { unset test_smooth }
        set test_smooth(loaded) 1
        set test1 [hexSmoothDEZ get fix_layers_settings]
        set test2 [hexSmoothDEZ get layer_distance_settings]
        if {$test1 != ""} {
            foreach item $test1 {
                set var [lindex $item 0]
                set val [lindex $item 1]
                set test_smooth($var) $val
            }
        }
        if {$test2 != ""} {
            foreach item $test2 {
                set var [lindex $item 0]
                set val [lindex $item 1]
                set test_smooth($var) $val
            }
        }
    }
}

proc onhexSmoothDEZUnLoad {} {
    global smooth_multi_block

    aie_hex_clear_histogram
    if [info exists smooth_multi_block(topology_information)] {
        onHEXsmoothPremeshbyMultiblockUnLoad
    }
    if {[trace vinfo partFixList] != ""} {
        trace vdelete partFixList w aie_hex_trace_partFixList
    }
    if {[trace vinfo partFirstList] != ""} {
        trace vdelete partFirstList w aie_hex_trace_partFirstList
    }
    ic_hex_gls_init glsm
    hex_update_display block edge vertex face
}

proc aie_hex_trace_partFixList {{name ""} {element ""} {op ""}} {
    global test_smooth
    if {[hexSmoothDEZ get partFixList] == ""} {
        foreach item [array names test_smooth freeze_surfaces,*] {
            unset test_smooth($item)
        }
        foreach item [array names test_smooth fams_attr,1,*] { 
            unset test_smooth($item)
        }
        hexSmoothDEZ set fix_layers_settings ""
    }
}

proc aie_hex_trace_partFirstList {{name ""} {element ""} {op ""}} {
    global test_smooth
    if {[hexSmoothDEZ get partFirstList] == ""} {
        foreach item [array names test_smooth release_ortho,*] {
            unset test_smooth($item)
        }
        foreach item [array names test_smooth fams_attr,0,*] { 
            unset test_smooth($item)
        }
        hexSmoothDEZ set layer_distance_settings ""
    }
}

proc onHEXsmoothPremeshbyMultiblockLoad {{name ""} {element ""} {op ""}} {
    global smooth_multi_block use_output_blocks display_flag is_output_blocks
    global options

    if ![ic_hex_blocking_loaded] return
    if [info exists smooth_multi_block(topology_information)] return
    if {[hexSmoothDEZ get smoothPremeshVal] != 2} return
    
    hex_command "display_super_faces [range_string] [family_activename_string] erase_icon"
    hex_command "display_nodes erase"
    hex_command "mark_blocks unmark"
    hex_command "unblank_blocks"
    hex_update_display block edge vertex face
      
    ::AIEnv::GUIManagement::ToggleGrey HEXsmoothPremeshbyMultiblock 1
    
    if ![info exists is_output_blocks] {
        set force_update 1
    } else {
        if {$use_output_blocks != $is_output_blocks} {
            set force_update 1
        } else {
            set force_update 0
        }
    }
    
    aie_hex_prepare_smooth_multi_block $force_update
    
    if $smooth_multi_block(feature_is_disabled) {
        mess "Warning: Smooth Method \"Multiblock\" disabled.\n" red
        return
    }  
    set fams [family_activename_string]
    if {$fams == ""} {
        set fams [join [ic_hex_list_families]]
    }   
    hex_command "display_super_faces [range_string] $fams erase_icon"
    hex_command "display_nodes erase"
    hex_command "mark_blocks unmark"
    hex_command "unblank_blocks"
   
    set smooth_multi_block(SelectedBlocks) ""
    set blocks ""
    for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
        append blocks "$i "
    }
    set smooth_multi_block(UnselectedBlocks) $blocks
    set smooth_multi_block(RelaxBlocks,save) ""
    set smooth_multi_block(ijkBlock) ""
    set smooth_multi_block(smoothDirection) 0
    set smooth_multi_block(use_output_blocks) $use_output_blocks
    set smooth_multi_block(LayerVertices,save) ""
    set smooth_multi_block(LayerVertices) ""
    set smooth_multi_block(GlobalVertices,save) ""
    set smooth_multi_block(GlobalVertices) ""
   
    if $use_output_blocks {
        set smooth_multi_block(PeriodicFaces) [lindex [ic_hex_display_periodic_faces get_faces output_blocks] 0]
    } else {
        set smooth_multi_block(PeriodicFaces) [lindex [ic_hex_display_periodic_faces get_faces] 0]
    }
    set smooth_multi_block(NonRelaxFaces,save) ""
    set smooth_multi_block(HoldCellHeightFaces,save) ""
    foreach idx {0 1 2} {
        set smooth_multi_block(NonRelaxFaces,$idx) ""
        set smooth_multi_block(NonRelaxFaces,topo_nums,$idx) ""
        set smooth_multi_block(HoldCellHeightFaces,$idx) ""
        set smooth_multi_block(HoldCellHeightFaces,topo_nums,$idx) ""
    }
    set smooth_multi_block(mesh_dim) [format %d [ic_hex_mesh_dimension]]
    if {[info exists options(n_processors)] && $options(n_processors) > 1} {
        set smooth_multi_block(n_processors) $options(n_processors)
    } else {
        set smooth_multi_block(n_processors) 1
    }

    if {[trace vinfo HEXsmoothDirVal] != ""} {
        trace vdelete HEXsmoothDirVal w aie_hex_trace_choose_direction
    }
    trace variable HEXsmoothDirVal w aie_hex_trace_choose_direction
    if {[trace vinfo planeNums] != ""} {
        trace vdelete planeNums w aie_hex_trace_smooth_dir_params
    }
    trace variable planeNums w aie_hex_trace_smooth_dir_params
    if {[trace vinfo smoothPremeshVal] != ""} {
        trace vdelete smoothPremeshVal w aie_hex_trace_premesh_val
    }
    trace variable smoothPremeshVal w aie_hex_trace_premesh_val  
    aie_hex_trace_premesh_val "" "" ""

    if {[trace vinfo use_output_blocks] != ""} {
        trace vdelete use_output_blocks w aie_hex_trace_use_output_blocks
    }
    trace variable use_output_blocks w aie_hex_trace_use_output_blocks
          
    if $use_output_blocks {
        smoothNonRelaxFacePick set -key selectOptions "output_blocks super_face"
        smoothHoldCellHeightFacePick set -key selectOptions "output_blocks super_face"
    } else {
        smoothNonRelaxFacePick set -key selectOptions "super_face"
        smoothHoldCellHeightFacePick set -key selectOptions "super_face"
    }

    if {[trace vinfo HEXsmoothMBSVal] != ""} {
        trace vdelete HEXsmoothMBSVal w aie_hex_trace_multiblock_settings
    }
    trace variable HEXsmoothMBSVal w aie_hex_trace_multiblock_settings
    foreach n {block_solid block_super} {
        if {[trace vinfo display_flag($n)] != ""} {
            trace vdelete display_flag($n) w aie_hex_trace_multiblock_display
        }
        trace variable display_flag($n) w aie_hex_trace_multiblock_display
    }
    aie_hex_relaxblocks_update

    set smooth_multi_block(entry_load) [lindex [hexSmoothDEZ pathIgnoreErrors HEXsmoothMBSLoadFile] 1]
    set smooth_multi_block(entry_save) [lindex [hexSmoothDEZ pathIgnoreErrors HEXsmoothMBSSaveFile] 1]
    $smooth_multi_block(entry_load) configure -state readonly -readonlybackground grey
    $smooth_multi_block(entry_save) configure -state readonly -readonlybackground grey
    set button [hexSmoothDEZ pathIgnoreErrors HEXparameterUseProj]
    $button configure -onvalue 0 -offvalue 1
      
    mess "\n"
    if ![info exists smooth_multi_block(topology_information)] {
        if $use_output_blocks { mess "Using pre-mesh option \"Output blocks\"\n" }
        mess "Number of blocks:   $smooth_multi_block(nBlocks)\n"
        mess "Number of faces:    $smooth_multi_block(nFaces)\n"
        mess "Number of edges:    $smooth_multi_block(nEdges)\n"
        mess "Number of vertices: $smooth_multi_block(nVert)\n"
        set smooth_multi_block(topology_information) 1
    }
}

proc onHEXsmoothPremeshbyMultiblockUnLoad {} {
    global smooth_multi_block use_output_blocks select_premesh_families display_flag
    global is_output_blocks

    if {[trace vinfo planeNums] != ""} {
        trace vdelete planeNums w aie_hex_trace_smooth_dir_params
    }
    if {[trace vinfo smoothPremeshVal] != ""} {
        trace vdelete smoothPremeshVal w aie_hex_trace_premesh_val
    }
    if {[trace vinfo HEXsmoothDirVal] != ""} {
        trace vdelete HEXsmoothDirVal w aie_hex_trace_choose_direction
    }
    if {[trace vinfo use_output_blocks] != ""} {
        trace vdelete use_output_blocks w aie_hex_trace_use_output_blocks
    }
    if {[trace vinfo HEXsmoothMBSVal] != ""} {
        trace vdelete HEXsmoothMBSVal w aie_hex_trace_multiblock_settings
    }
    if {[trace vinfo smoothPremeshVal] != ""} {
        trace vdelete smoothPremeshVal w onHEXsmoothPremeshbyMultiblockLoad
    }
    foreach n {block_solid block_super} {
        if {[trace vinfo display_flag($n)] != ""} {
            trace vdelete display_flag($n) w aie_hex_trace_multiblock_display
        }
    }    
    if [info exists select_premesh_families] { unset select_premesh_families }
    if [info exists is_output_blocks] { unset is_output_blocks }
    if [info exists smooth_multi_block] { unset smooth_multi_block }
    
    if ![ic_hex_blocking_loaded] return    
    hex_command "display_super_faces [range_string] [family_activename_string] erase_icon"
    hex_command "display_nodes erase"
    hex_command "mark_blocks unmark"
    hex_command "unblank_blocks"
    hex_update_display block edge vertex face
}

proc aie_hex_rebunch_edge_active {{rebunch empty}} {
    if {$rebunch != "empty"} { set rebunchEdges $rebunch }
    if {$rebunchEdges != 2} {
        ::AIEnv::GUIManagement::ToggleGrey HEXselectEdges2SOE 1
    } else {
        ::AIEnv::GUIManagement::ToggleGrey HEXselectEdges2SOE 0
    }
}

proc aie_hex_treat_unstruct_active {{treat empty}} {
    if {$treat != "empty"} { set treatUnstruct $treat }
}

proc onhexSmoothDEZOK {} {
    global test_smooth project_type file_name smooth_multi_block use_output_blocks
   
    hexSmoothDEZ setdirty
   
    switch $smoothPremeshVal {
	0 { # Quality based smoother
	    set cmd "smooth $iters"
	    if $activePartsOnly {
		    append cmd " [volume_activename_string]"
	    } else {
		    append cmd " [join [ic_hex_list_families]]"
	    }
	   
	    if $onlyVisible {
		    append cmd " [range_string]"
	    }

	    if $laplaceFlag {
		    append cmd " laplace"		
	    } elseif {$qualitydde == "Angle"} {
		    set criteria angle
		    append cmd " angle"
	    }
	    append cmd " sm_param $quality"
	}
	
	1 { # Orthogonality smoother
	    set fams ""
        if $activePartsOnly {
            set fams [volume_activename_string]
        } else {
            set fams [join [ic_hex_list_families]]
        }
	    set cmd "smooth $itersVol $fams elliptic"	   

	    append cmd " iter_srf $itersSurf iter_vol $itersVol"
	    append cmd " exp_srf $expansionSurf exp_vol $expansionVol"
	    append cmd " niter_post $niterPost limit_post $limitPost"

	    set smtype_srf [expr [HEXsmoothTypeSOEMS query "Faces" "Laplace"] + 2]
	    set smtype_vol [expr [HEXsmoothTypeSOEMS query "Volume" "Laplace"] + 2]
	    set smooth_type [expr $smtype_srf + 100 * $smtype_vol]
	    append cmd " smooth_type $smooth_type"

	    set nfix_layers $numLayersFix
	    if {$freezeCriterion == 0} {
		    if {$nfix_layers < 0} {
		        set nfix_layers -1
		    }
	    } elseif {$freezeCriterion == 1 || $freezeCriterion == 2} {
	        set nfix_layers -1
	    }
	    append cmd " nfix_layers $nfix_layers"
	   
            set fams_attr ""
            set info_0 0; set info_1 0
            if {$partFirstList != ""} {     
                foreach item [array names test_smooth fams_attr,0,*] {
                  set info_0 1
                  break          
                }
            }
            if {$partFixList != ""} {
                foreach item [array names test_smooth fams_attr,1,*] {
                  set info_1 1
                  break          
                }
            }
            for {set i 0} {$i <= 1} {incr i} {
                if {($i == 0 && $info_0 == 1) || \
                    ($i == 1 && $info_1 == 1) } {
                    foreach item [array names test_smooth fams_attr,$i,*] {
                        set part [lindex [split $item ,] 2]
                        set val $test_smooth(fams_attr,$i,$part)
                        if {$i == "1"} {
                            set idx_srf freeze_surfaces
                            if {$freezeCriterion != 1 && $freezeCriterion != 2} continue
                            if {[lsearch $partFixList $part] < 0}  continue
                        } else {
                            set idx_srf release_ortho
                            if {[lsearch $partFirstList $part] < 0} continue
                        }
                        if !$test_smooth($idx_srf,$part) {
                            set val 0
                        } else {
                            if { $val <= 0 } {
                                set val -1
                            }
                        }
                        append fams_attr " $part $i $val"
                    }
                } else {
                    switch $i {
                        0 {
                            foreach part $partFirstList {
                                 append fams_attr " $part 0 -1"
                            }
                        }
                        1 {
                            foreach part $partFixList {
                                 if {$freezeCriterion != 1 && $freezeCriterion != 2} continue
                                 append fams_attr " $part 1 -1"
                            }
                        }
                    }
                }
            }
            if {$fams_attr != ""} {
                append cmd " fams_attr [list $fams_attr]"
            }
            if {$rebunchEdges == 1} {
                append cmd " rebunch_edges 1"
            } else {
                append cmd " rebunch_edges 0"
            }
           
            if {$treatUnstruct != ""} {
                append cmd " treat_unstruct $treatUnstruct"
            }
            if {$partBorderList != ""} {
                append cmd " parts_edges [list $partBorderList]"
	    }
	    set rebunch_list ""
	    if {$edgesRebunchList != ""} {
	        foreach item $edgesRebunchList {
	            append rebunch_list " [lindex $item 0] [lindex $item 1]"
	        }
	        append cmd " selected_rebunch_edges [list $rebunch_list]"
	    }
	    append cmd " stabilize_srf $stabilizeSurf"
	    append cmd " stabilize_vol $stabilizeVol"
	    append cmd " ortho_distance_srf $useorthoDistSurf"
	    append cmd " ortho_distance_vol $useorthoDistVol"
	    append cmd " surface_fitting $SrfFitFlag"
	    append cmd " keep_per_geom $KperGeomFlag"
	}
	2 { # Multiblock smoother
            if $smooth_multi_block(feature_is_disabled) {
                mess "Warning: Smooth Method \"Multiblock\" disabled.\n" red
                return
            }
            if {$smooth_multi_block(smoothDirection) != 0 && $planeNums == ""} {
                if {$startIndex < 1} {
                    mess "Start layer must be greater than 0.\n" red
                    return
                }
                if {$endIndex < $startIndex} {
                    mess "End layer can not be less than start layer.\n" red
                    return  
                }
                if {$endIndex < 0} {
                    mess "End layer must be greater than 0.\n" red
                    return  
                }
                if {$incrIndex < 1} {
                    mess "Increment must be greater than 0.\n" red
                    return   
                }
            }
           
            mess "Running Multiblock smoother...\n" blue

            set the_face_methods ""
            for {set i 0} {$i < 6} {incr i} {
                append the_face_methods "$smooth_multi_block($face_method) "
            }
            set smooth_domain ""
            set face_methods ""
            set volume_methods ""
            set smooth_dir ""
            set incr_3d_plane_smooth ""
            set relax_weights_2d ""
            set relax_weights_3d ""
            set relax_weights_inner_2d ""
            set relax_weights_inner_3d "" 
            set smooth_ngh_method ""      
            set abs_dist_subf ""
            set n_abs_dist_subf ""
            set grid_exp_rate_subf_perp ""
            set grid_exp_rate_subf_1 ""
           
            set relax_faces ""
            set relaxation_zones ""
            set edge_no_global_smooth ""
            set global_vertices_opp ""
            set vertex_attrib ""
            set mesh_type 0
           
            set the_volume_method $smooth_multi_block($volume_method)
           
            set plane_numbers ""
            if {$smooth_multi_block(smoothDirection) == 0} {
                set the_incr_3d_plane_smooth "-1 -1 -1 0"
            } else {
                if {$planeNums != ""} {
                     set plane_len [llength $planeNums]
                     for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
                         set numbers "$plane_len "
                         foreach item $planeNums {
                             append numbers "$item "
                         }
                         append plane_numbers "$numbers "
                     }
                     set the_incr_3d_plane_smooth "-1 -1 -1 $iterIndex"
                } else {
                    set the_incr_3d_plane_smooth "$startIndex $endIndex $incrIndex $iterIndex"
                }
            }
           
            for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
                append smooth_domain "[aie_hex_is_seleced_block $i] "
                append face_methods "$the_face_methods "
                append volume_methods "$the_volume_method "
                append smooth_dir "$smooth_multi_block(smoothDirection) "
                append incr_3d_plane_smooth "$the_incr_3d_plane_smooth "
                append relax_weights_2d "0 0 0 0 0 0 "
                append relax_weights_inner_2d "0 0 0 0 0 0 "
                append relax_weights_inner_3d "0 0 0 0 0 0 " 
                append smooth_ngh_method "-2 "      
                append abs_dist_subf "-1.0 -1.0 -1.0 -1.0 -1.0 -1.0 "
                append n_abs_dist_subf "-1 -1 -1 -1 -1 -1 "
                append grid_exp_rate_subf_perp "-1 -1 -1 -1 -1 -1 "
                append grid_exp_rate_subf_1 "-1 -1 -1 -1 -1 -1 "
            }
           
            set used_parts ""
            set unused_parts ""
            for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
                set part [string trimright [ic_hex_get_block_family $i]\n]
                if [aie_hex_is_seleced_block $i] {
                    if {[lsearch $used_parts $part] < 0} {
                        append used_parts "$part "
                    }
                }
            }
            for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
                set part [string trimright [ic_hex_get_block_family $i]\n]
                if ![aie_hex_is_seleced_block $i] {
                    if {[lsearch $unused_parts $part] < 0 && [lsearch $used_parts $part] < 0} {
                        append unused_parts "$part "
                    }
                }
            }

            if {([info exists smooth_multi_block(NonRelaxFaces,topo_nums,$smoothFilterNonRelax)] && \
                $smooth_multi_block(NonRelaxFaces,topo_nums,$smoothFilterNonRelax) != "")} {
                foreach n $smooth_multi_block(NonRelaxFaces,topo_nums,$smoothFilterNonRelax) {
                    if {$n != -1} { append relax_faces "$n 0 " }
                }
            }

            catch { unset tmp }
            for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
                set tmp(set,imin,$i) 0; set tmp(set,imax,$i) 0
                set tmp(set,jmin,$i) 0; set tmp(set,jmax,$i) 0
                set tmp(set,kmin,$i) 0; set tmp(set,kmax,$i) 0
            }
           
            set topo_nums ""
            if {([info exists smooth_multi_block(HoldCellHeightFaces,topo_nums,$smoothFilterHoldCellHeight)] && \
                $smooth_multi_block(HoldCellHeightFaces,topo_nums,$smoothFilterHoldCellHeight) != "")} {
                foreach n $smooth_multi_block(HoldCellHeightFaces,topo_nums,$smoothFilterHoldCellHeight) {
                    if {$n != -1} { append topo_nums "$n " }
                }
            }

            for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
                foreach item $smooth_multi_block(facesBlocks,$i) {
                    set face_no [lindex $item 0]
                    foreach n $topo_nums {
                        if {$n == $face_no} {
                            set ijk [lindex $item 1]
                            set tmp(set,$ijk,$i) 1
                            break
                        }
                    }
                }
            }          
            for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
               set imin $tmp(set,imin,$i); set imax $tmp(set,imax,$i)
               set jmin $tmp(set,jmin,$i); set jmax $tmp(set,jmax,$i)
               set kmin $tmp(set,kmin,$i); set kmax $tmp(set,kmax,$i)
               append relax_weights_3d "$imin $imax $jmin $jmax $kmin $kmax "
            }
            if {$smooth_multi_block(GlobalVertices) != ""} {
                set topo_nums ""
                foreach n $smooth_multi_block(GlobalVertices) {
                    set num [string trimright [ic_hex_topo_vertex_number $n] \n]
                    if {[lsearch $topo_nums $num] < 0} {
                        append topo_nums "$num "
                    }
                }

                foreach item [ic_hex_list_vertex_edges [lsort -dictionary $topo_nums]] {
                    foreach e [lindex $item 0] {
                        append edge_no_global_smooth "$e "
                    }
                    foreach v [lindex $item 1] {
                        set block_no [lindex $v 0]
                        set i [lindex $v 1]
                        set j [lindex $v 2]
                        set k [lindex $v 3]
                        set min "[lindex $v 1] [lindex $v 2] [lindex $v 3]"
                        append relaxation_zones "$block_no $i $j $k $i $j $k 0 "
                        append global_vertices_opp "$block_no $min "
                    }
                }
            }
            foreach n $smooth_multi_block(LayerVertices) {
                set layerDist -1
                set num [string trimright [ic_hex_topo_vertex_number $n] \n]
                if {$num == "" || $num == "-1"} continue
                if [info exists smooth_multi_block(layer_distance,$n)] {
                    set layerDist $smooth_multi_block(layer_distance,$n)
                }
                if {$layerDist == "" || $layerDist < 0} { set layerDist -1 }

                append vertex_attrib "$num $layerDist -1 "
            }
           
            if {$smooth_multi_block(smoothDirection) == 0 || $smooth_multi_block(GlobalVertices) == "" || \
                [llength $smooth_multi_block(SelectedBlocks)] == 1} {
                set use_smooth_prog_type 2
            } else {
                set use_smooth_prog_type 5
            }
    
            set niter 1
            set nsteps 1
            set maxlevel 3
            set sfit $parameterFaceFit
            set conditional 0
            set check_det 0
            set damping 1
            set vertex_fix 1
            set edge_freeze 1
            set wedge_check 1
            set fix_fam 0
            set multigrid2d 0
            set reduced_edge 0
            set inner_vol_sm 0
            set ns_rel 0.0
            set angle_freeze_edge 5.0
            set n_iter $itersEdges
            set interp_faces 0
            set interp_volumes 0
            set threshold_det 30.0
            set threshold_angle 80.0
            set subface_extensions ""
            set ijk_extensions ""
            set edge_attrib ""
            set relax_subfaces $relax_faces
            set relaxation_zones $relaxation_zones
            set viol_geom_zones ""
            set viol_geom_subfaces ""
            set base_subfaces_no ""
            set meshing_law ""
            set subface_extend 0
            set direction_vector ""
            set base_regions ""
            set type_improve 0
            set type_postsm 2
            set proj_limit $parameterPrjLim
            set group_bad_elem 0
            set mesh_type 0
            set surfresolv $parameterUseProj
            set min_mxr 3.0
            set edge_no_global_smooth $edge_no_global_smooth
            set n_iter_glb $itersEdges
            set n_steps_glb $itersVertices
            set global_vertices_opp $global_vertices_opp
            set grid_exp_face $gridexpansionFace
            set grid_exp_vol $gridexpansionVol
            set min_res $parameterResFac
            set abs_dist_bnd -1
            set n_points_abs_dist_bnd -1
            set vertex_attrib $vertex_attrib
            set relaxation_factor $parameterRelFac
            set use_orthog_position $parameterUseOrt
            set use_fract_position $parameterUseFra
            set first_cell_height -1
            set last_cell_height -1
            set use_pthreads $smooth_multi_block(n_processors)
           
            set active_parts ""
            foreach f [family_activename_string] {
                if {[lsearch $unused_parts $f] < 0} {
                    append active_parts "$f "
                }
            }
            if $use_output_blocks {
                set cmd "global_smooth families \"$active_parts\" output_blocks proj $project_type"
            } else {
                set cmd "global_smooth families \"$active_parts\" proj $project_type"
            }
            append cmd " sm_param"
            append cmd " 1 \"$file_name(mesh_dir)\""
            append cmd " smooth_domain \"$smooth_domain\""
            append cmd " face_methods \"$face_methods\""
            append cmd " volume_methods \"$volume_methods\""
            append cmd " niter $niter"
            append cmd " nsteps $nsteps"
            append cmd " maxlevel $maxlevel"
            append cmd " sfit $sfit"
            append cmd " conditional $conditional"
            append cmd " check_det $check_det"
            append cmd " damping $damping"
            append cmd " vertex_fix $vertex_fix"
            append cmd " edge_freeze $edge_freeze"
            append cmd " wedge_check $wedge_check"
            append cmd " fix_fam $fix_fam"
            append cmd " multigrid2d $multigrid2d"
            append cmd " reduced_edge $reduced_edge"
            append cmd " inner_vol_sm $inner_vol_sm"
            append cmd " ns_rel $ns_rel"
            append cmd " angle_freeze_edge $angle_freeze_edge"
            append cmd " n_iter $n_iter"
            append cmd " interp_faces $interp_faces"
            append cmd " interp_volumes $interp_volumes"
            append cmd " prog_select $use_smooth_prog_type"
            append cmd " threshold_det $threshold_det"
            append cmd " threshold_angle $threshold_angle"
            append cmd " subface_extensions \"$subface_extensions\""
            append cmd " ijk_extensions \"$ijk_extensions\""
            append cmd " edge_attrib \"$edge_attrib\""
            append cmd " relax_subfaces \"$relax_subfaces\""
            append cmd " relaxation_zones \"$relaxation_zones\""
            append cmd " viol_geom_zones \"$viol_geom_zones\""
            append cmd " viol_geom_subfaces \"$viol_geom_subfaces\""
            append cmd " base_subfaces_no \"$base_subfaces_no\""
            append cmd " meshing_law \"$meshing_law\""
            append cmd " subface_extend $subface_extend"
            append cmd " direction_vector \"$direction_vector\""
            append cmd " base_regions \"$base_regions\""
            append cmd " type_improve $type_improve"
            append cmd " type_postsm $type_postsm"
            append cmd " proj_limit $proj_limit"
            append cmd " group_bad_elem $group_bad_elem"
            append cmd " smooth_dir \"$smooth_dir\""
            append cmd " mesh_type $mesh_type"
            append cmd " smooth_ngh_method \"$smooth_ngh_method\""
            append cmd " surfresolv \"$surfresolv\""
            append cmd " min_mxr $min_mxr"
            append cmd " edge_no_global_smooth \"$edge_no_global_smooth\""
            append cmd " incr_3d_plane_smooth \"$incr_3d_plane_smooth\""
            append cmd " relax_weights_2d \"$relax_weights_2d\""
            append cmd " relax_weights_3d \"$relax_weights_3d\""
            append cmd " relax_weights_inner_2d \"$relax_weights_inner_2d\""
            append cmd " relax_weights_inner_3d \"$relax_weights_inner_3d\""
            append cmd " n_iter_glb $n_iter_glb"
            append cmd " n_steps_glb $n_steps_glb"
            append cmd " global_vertices_opp \"$global_vertices_opp\""
            append cmd " plane_nos \"$plane_numbers\""
            append cmd " grid_exp_face $grid_exp_face"
            append cmd " grid_exp_vol $grid_exp_vol"
            append cmd " min_res $min_res"
            append cmd " abs_dist_bnd \"$abs_dist_bnd\""
            append cmd " n_points_abs_dist_bnd \"$n_points_abs_dist_bnd\""
            append cmd " abs_dist_subf \"$abs_dist_subf\""
            append cmd " n_abs_dist_subf \"$n_abs_dist_subf\""
            append cmd " vertex_attrib \"$vertex_attrib\""
            append cmd " relaxation_factor $relaxation_factor"
            append cmd " use_orthog_position $use_orthog_position"
            append cmd " use_fract_position $use_fract_position"
            append cmd " grid_exp_rate_subf_perp \"$grid_exp_rate_subf_perp\""
            append cmd " grid_exp_rate_subf_1 \"$grid_exp_rate_subf_1\""
            append cmd " first_cell_height $first_cell_height"
            append cmd " last_cell_height $last_cell_height"
            append cmd " use_pthreads $use_pthreads"
	}
    }
   
    if {$smoothPremeshVal == 2} { ic_hex_undo_major_start "global_smooth" }
    mess "Start smoothing...\n"
    hex_command $cmd
    if {$smoothPremeshVal == 2} { ic_hex_undo_major_end "global_smooth" }
    catch { interrupt finish }
    mess "Updating histogram...\n"
    aie_hex_update_histogram $qualitydde
    if {$smoothPremeshVal == 2} {
        aie_hex_multiblock_display_selections
    } else {
        hex_update_display
    }
}

proc aie_hex_save_multiblock_settings {{name ""} {element ""} {op ""}} {
    global smooth_multi_block file_name use_output_blocks project_type env

    if [info exists smooth_multi_block(sequence_run)] return
    set file [hexSmoothDEZ get mbs_setting_save]
    if {$file == ""} return
   
    set planeNums [hexSmoothDEZ get planeNums]
    set startIndex [hexSmoothDEZ get startIndex]
    set endIndex [hexSmoothDEZ get endIndex]
    set incrIndex [hexSmoothDEZ get incrIndex]
    set iterIndex [hexSmoothDEZ get iterIndex]
    set face_method [hexSmoothDEZ get face_method]
    set volume_method [hexSmoothDEZ get volume_method]
    set smoothFilterNonRelax [hexSmoothDEZ get smoothFilterNonRelax]
    set smoothFilterHoldCellHeight [hexSmoothDEZ get smoothFilterHoldCellHeight]
    set parameterFaceFit [hexSmoothDEZ get parameterFaceFit]
    set parameterPrjLim [hexSmoothDEZ get parameterPrjLim]
    set parameterUseProj [hexSmoothDEZ get parameterUseProj]
    set itersEdges [hexSmoothDEZ get itersEdges]
    set itersVertices [hexSmoothDEZ get itersVertices]
    set gridexpansionFace [hexSmoothDEZ get gridexpansionFace]
    set gridexpansionVol [hexSmoothDEZ get gridexpansionVol]
    set parameterResFac [hexSmoothDEZ get parameterResFac]
    set parameterRelFac [hexSmoothDEZ get parameterRelFac]
    set parameterUseOrt [hexSmoothDEZ get parameterUseOrt]
    set parameterUseFra [hexSmoothDEZ get parameterUseFra]

    if {$smooth_multi_block(smoothDirection) != 0 && $planeNums == ""} {
        if {$startIndex < 1} {
            mess "Start layer must be greater than 0.\n" red
            return
        }
        if {$endIndex < $startIndex} {
            mess "End layer can not be less than start layer.\n" red
            return  
        }
        if {$endIndex < 0} {
            mess "End layer must be greater than 0.\n" red
            return  
        }
        if {$incrIndex < 1} {
            mess "Increment must be greater than 0.\n" red
            return   
        }
    }

    busy 1
   
    set the_face_methods ""
    for {set i 0} {$i < 6} {incr i} {
        append the_face_methods "$smooth_multi_block($face_method) "
    }

    set smooth_domain ""
    set face_methods ""
    set volume_methods ""
    set smooth_dir ""
    set incr_3d_plane_smooth ""
    set relax_weights_2d ""
    set relax_weights_3d ""
    set relax_weights_inner_2d ""
    set relax_weights_inner_3d "" 
    set smooth_ngh_method ""      
    set abs_dist_subf ""
    set n_abs_dist_subf ""
    set grid_exp_rate_subf_perp ""
    set grid_exp_rate_subf_1 ""

    set relax_faces ""
    set relaxation_zones ""
    set edge_no_global_smooth ""
    set global_vertices_opp ""
    set vertex_attrib ""
    set vertex_attrib_gui ""
    set mesh_type 0

    set the_volume_method $smooth_multi_block($volume_method)

    set plane_numbers ""
    if {$smooth_multi_block(smoothDirection) == 0} {
        set the_incr_3d_plane_smooth "-1 -1 -1 0"
    } else {
        if {$planeNums != ""} {
             set plane_len [llength $planeNums]
             for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
                 set numbers "$plane_len "
                 foreach item $planeNums {
                     append numbers "$item "
                 }
                 append plane_numbers "$numbers "
             }
             set the_incr_3d_plane_smooth "-1 -1 -1 $iterIndex"
        } else {
            set the_incr_3d_plane_smooth "$startIndex $endIndex $incrIndex $iterIndex"
        }
    }
   
    for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
        append smooth_domain "[aie_hex_is_seleced_block $i] "
        append face_methods "$the_face_methods "
        append volume_methods "$the_volume_method "
        append smooth_dir "$smooth_multi_block(smoothDirection) "
        append incr_3d_plane_smooth "$the_incr_3d_plane_smooth "
        append relax_weights_2d "0 0 0 0 0 0 "
        append relax_weights_inner_2d "0 0 0 0 0 0 "
        append relax_weights_inner_3d "0 0 0 0 0 0 " 
        append smooth_ngh_method "-2 "      
        append abs_dist_subf "-1.0 -1.0 -1.0 -1.0 -1.0 -1.0 "
        append n_abs_dist_subf "-1 -1 -1 -1 -1 -1 "
        append grid_exp_rate_subf_perp "-1 -1 -1 -1 -1 -1 "
        append grid_exp_rate_subf_1 "-1 -1 -1 -1 -1 -1 "
    }

    set used_parts ""
    set unused_parts ""
    for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
        set part [string trimright [ic_hex_get_block_family $i]\n]
        if [aie_hex_is_seleced_block $i] {
            if {[lsearch $used_parts $part] < 0} {
                append used_parts "$part "
            }
        }
    }
    for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
        set part [string trimright [ic_hex_get_block_family $i]\n]
        if ![aie_hex_is_seleced_block $i] {
            if {[lsearch $unused_parts $part] < 0 && [lsearch $used_parts $part] < 0} {
                append unused_parts "$part "
            }
        }
    }

    if {([info exists smooth_multi_block(NonRelaxFaces,topo_nums,$smoothFilterNonRelax)] && \
        $smooth_multi_block(NonRelaxFaces,topo_nums,$smoothFilterNonRelax) != "")} {
        foreach n $smooth_multi_block(NonRelaxFaces,topo_nums,$smoothFilterNonRelax) {
            if {$n != -1} { append relax_faces "$n 0 " }
        }
    }
   
    catch { unset tmp }
    for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
        set tmp(set,imin,$i) 0; set tmp(set,imax,$i) 0
        set tmp(set,jmin,$i) 0; set tmp(set,jmax,$i) 0
        set tmp(set,kmin,$i) 0; set tmp(set,kmax,$i) 0
    }
   
    set topo_nums ""
    if {([info exists smooth_multi_block(HoldCellHeightFaces,topo_nums,$smoothFilterHoldCellHeight)] && \
        $smooth_multi_block(HoldCellHeightFaces,topo_nums,$smoothFilterHoldCellHeight) != "")} {
        foreach n $smooth_multi_block(HoldCellHeightFaces,topo_nums,$smoothFilterHoldCellHeight) {
            if {$n != -1} { append topo_nums "$n " }
        }
    }

    for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
        foreach item $smooth_multi_block(facesBlocks,$i) {
            set face_no [lindex $item 0]
            foreach n $topo_nums {
                if {$n == $face_no} {
                    set ijk [lindex $item 1]
                    set tmp(set,$ijk,$i) 1
                    break
                }
            }
        }
    }
                       
    for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
       set imin $tmp(set,imin,$i); set imax $tmp(set,imax,$i)
       set jmin $tmp(set,jmin,$i); set jmax $tmp(set,jmax,$i)
       set kmin $tmp(set,kmin,$i); set kmax $tmp(set,kmax,$i)
       append relax_weights_3d "$imin $imax $jmin $jmax $kmin $kmax "
    }

    if {$smooth_multi_block(GlobalVertices) != ""} {
        set topo_nums ""
        foreach n $smooth_multi_block(GlobalVertices) {
            set num [string trimright [ic_hex_topo_vertex_number $n] \n]
            if {[lsearch $topo_nums $num] < 0} {
                append topo_nums "$num "
            }
        }
        foreach item [ic_hex_list_vertex_edges $topo_nums] {
            foreach e [lindex $item 0] {
                append edge_no_global_smooth "$e "
            }
            foreach v [lindex $item 1] {
                set block_no [lindex $v 0]
                set i [lindex $v 1]
                set j [lindex $v 2]
                set k [lindex $v 3]
                set min "[lindex $v 1] [lindex $v 2] [lindex $v 3]"
                append relaxation_zones "$block_no $i $j $k $i $j $k 0 "
                append global_vertices_opp "$block_no $min "
            }
        }
    }

    foreach n $smooth_multi_block(LayerVertices) {
        set layerDist -1
        set num [string trimright [ic_hex_topo_vertex_number $n] \n]
        if {$num == "" || $num == "-1"} continue
        if [info exists smooth_multi_block(layer_distance,$n)] {
            set layerDist $smooth_multi_block(layer_distance,$n)
        }
        if {$layerDist == "" || $layerDist < 0} { set layerDist -1 }
        append vertex_attrib "$num $layerDist -1 "
        append vertex_attrib_gui "$n $layerDist "
    }

    if {$smooth_multi_block(smoothDirection) == 0 || $smooth_multi_block(GlobalVertices) == "" || \
        [llength $smooth_multi_block(SelectedBlocks)] == 1} {
        set use_smooth_prog_type 2
    } else {
        set use_smooth_prog_type 5
    }

    set niter 1
    set nsteps 1
    set maxlevel 3
    set sfit $parameterFaceFit
    set conditional 0
    set check_det 0
    set damping 1
    set vertex_fix 1
    set edge_freeze 1
    set wedge_check 1
    set fix_fam 0
    set multigrid2d 0
    set reduced_edge 0
    set inner_vol_sm 0
    set ns_rel 0.0
    set angle_freeze_edge 5.0
    set n_iter $itersEdges
    set interp_faces 0
    set interp_volumes 0
    set threshold_det 30.0
    set threshold_angle 80.0
    set subface_extensions ""
    set ijk_extensions ""
    set edge_attrib ""
    set relax_subfaces $relax_faces
    set relaxation_zones $relaxation_zones
    set viol_geom_zones ""
    set viol_geom_subfaces ""
    set base_subfaces_no ""
    set meshing_law ""
    set subface_extend 0
    set direction_vector ""
    set base_regions ""
    set type_improve 0
    set type_postsm 2
    set proj_limit $parameterPrjLim
    set group_bad_elem 0
    set mesh_type 0
    set surfresolv $parameterUseProj
    set min_mxr 3.0
    set edge_no_global_smooth $edge_no_global_smooth
    set n_iter_glb $itersEdges
    set n_steps_glb $itersVertices
    set global_vertices_opp $global_vertices_opp
    set grid_exp_face $gridexpansionFace
    set grid_exp_vol $gridexpansionVol
    set min_res $parameterResFac
    set abs_dist_bnd -1
    set n_points_abs_dist_bnd -1
    set vertex_attrib $vertex_attrib
    set relaxation_factor $parameterRelFac
    set use_orthog_position $parameterUseOrt
    set use_fract_position $parameterUseFra
    set first_cell_height -1
    set last_cell_height -1
    set use_pthreads $smooth_multi_block(n_processors)

    set active_parts ""
    foreach f [family_activename_string] {
        if {[lsearch $unused_parts $f] < 0} {
            append active_parts "$f "
        }
    }

    set batch_params "families \"$active_parts\""
    if $use_output_blocks {
        append batch_params " output_blocks"
    }
    append batch_params " proj $project_type"
    append batch_params " sm_param 1"
    append batch_params " \"$file_name(mesh_dir)\""
    append batch_params " smooth_domain \"$smooth_domain\""
    append batch_params " face_methods \"$face_methods\""
    append batch_params " volume_methods \"$volume_methods\""
    append batch_params " niter $niter"
    append batch_params " nsteps $nsteps"
    append batch_params " maxlevel $maxlevel"
    append batch_params " sfit $sfit"
    append batch_params " conditional $conditional"
    append batch_params " check_det $check_det"
    append batch_params " damping $damping"
    append batch_params " vertex_fix $vertex_fix"
    append batch_params " edge_freeze $edge_freeze"
    append batch_params " wedge_check $wedge_check"
    append batch_params " fix_fam $fix_fam"
    append batch_params " multigrid2d $multigrid2d"
    append batch_params " reduced_edge $reduced_edge"
    append batch_params " inner_vol_sm $inner_vol_sm"
    append batch_params " ns_rel $ns_rel"
    append batch_params " angle_freeze_edge $angle_freeze_edge"
    append batch_params " n_iter $n_iter"
    append batch_params " interp_faces $interp_faces"
    append batch_params " interp_volumes $interp_volumes"
    append batch_params " prog_select $use_smooth_prog_type"
    append batch_params " threshold_det $threshold_det"
    append batch_params " threshold_angle $threshold_angle"
    append batch_params " subface_extensions \"$subface_extensions\""
    append batch_params " ijk_extensions \"$ijk_extensions\""
    append batch_params " edge_attrib \"$edge_attrib\""
    append batch_params " relax_subfaces \"$relax_subfaces\""
    append batch_params " relaxation_zones \"$relaxation_zones\""
    append batch_params " viol_geom_zones \"$viol_geom_zones\""
    append batch_params " viol_geom_subfaces \"$viol_geom_subfaces\""
    append batch_params " base_subfaces_no \"$base_subfaces_no\""
    append batch_params " meshing_law \"$meshing_law\""
    append batch_params " subface_extend $subface_extend"
    append batch_params " direction_vector \"$direction_vector\""
    append batch_params " base_regions \"$base_regions\""
    append batch_params " type_improve $type_improve"
    append batch_params " type_postsm $type_postsm"
    append batch_params " proj_limit $proj_limit"
    append batch_params " group_bad_elem $group_bad_elem"
    append batch_params " smooth_dir \"$smooth_dir\""
    append batch_params " mesh_type $mesh_type"
    append batch_params " smooth_ngh_method \"$smooth_ngh_method\""
    append batch_params " surfresolv \"$surfresolv\""
    append batch_params " min_mxr $min_mxr"
    append batch_params " edge_no_global_smooth \"$edge_no_global_smooth\""
    append batch_params " incr_3d_plane_smooth \"$incr_3d_plane_smooth\""
    append batch_params " relax_weights_2d \"$relax_weights_2d\""
    append batch_params " relax_weights_3d \"$relax_weights_3d\""
    append batch_params " relax_weights_inner_2d \"$relax_weights_inner_2d\""
    append batch_params " relax_weights_inner_3d \"$relax_weights_inner_3d\""
    append batch_params " n_iter_glb $n_iter_glb"
    append batch_params " n_steps_glb $n_steps_glb"
    append batch_params " global_vertices_opp \"$global_vertices_opp\""
    append batch_params " plane_nos \"$plane_numbers\""
    append batch_params " grid_exp_face $grid_exp_face"
    append batch_params " grid_exp_vol $grid_exp_vol"
    append batch_params " min_res $min_res"
    append batch_params " abs_dist_bnd \"$abs_dist_bnd\""
    append batch_params " n_points_abs_dist_bnd \"$n_points_abs_dist_bnd\""
    append batch_params " abs_dist_subf \"$abs_dist_subf\""
    append batch_params " n_abs_dist_subf \"$n_abs_dist_subf\""
    append batch_params " vertex_attrib \"$vertex_attrib\""
    append batch_params " relaxation_factor $relaxation_factor"
    append batch_params " use_orthog_position $use_orthog_position"
    append batch_params " use_fract_position $use_fract_position"
    append batch_params " grid_exp_rate_subf_perp \"$grid_exp_rate_subf_perp\""
    append batch_params " grid_exp_rate_subf_1 \"$grid_exp_rate_subf_1\""
    append batch_params " first_cell_height $first_cell_height"
    append batch_params " last_cell_height $last_cell_height"
    append batch_params " use_pthreads $use_pthreads"
   
    set gui_params ""
    foreach n [::AIEnv::GUIManagement::GetLocalVariables hexSmoothDEZ] {
        if ![catch {hexSmoothDEZ get $n} v] {
            append gui_params "[list $n $v] "
        }
    }
    append gui_params "[list vertex_attrib_gui $vertex_attrib_gui] "
    append gui_params "[list ijkBlock $smooth_multi_block(ijkBlock)] "
    append gui_params "[list smoothDirection $smooth_multi_block(smoothDirection)] "
    append gui_params "[list n_processors $use_pthreads] "

    set f [open $file w]
    puts $f "# Multiblock Settings File"
    puts $f "# This is a generated file! Do not edit."
    puts $f "#"
    puts $f "# Full Range of Multiblock Smoothing Parameters for Batch"
    puts $f "#"
    puts $f "batch_params"
    puts $f "$batch_params"
    puts $f ""
    puts $f "#"
    puts $f "# Full Range of Multiblock Smoothing Parameters for Gui"
    puts $f "#"
    puts $f "gui_params"
    puts $f "$gui_params"
    puts $f ""
    close $f
    mess "Multiblock settings file $file saved.\n" blue

    set use_ge_settings 0
    set parts(All) "[ic_str_list_families] [ic_geo_list_families 0 1]"
    if {([lsearch $parts(All) R_0.AF.*_0] >= 0) || ([lsearch $parts(All) R_0.AFT.*_0] >= 0) || ([lsearch $parts(All) R_0.AFH.*_0] >= 0)} {
        set use_ge_settings 1
    }
    
    if [info exists env(USE_GE_43_SETTINGS)] {
        set use_ge_settings 1
    }
    
    if !$use_ge_settings {
        $smooth_multi_block(entry_save) configure -state readonly -readonlybackground grey
        busy 0
        return
    }  

    switch -- [tk_dialog .saveold Save "Saving file also as settings file 4.3 version?"  "" -1 Yes No] {
        -1 { if [winfo exists .saveold] { top_destroy .saveold; return } }
        0 { }
        1 { return  }
    }

    set title "Settings file 4.3 version"
    set name setttings.version43.med
    set file [tk_getSaveFile -initialdir $file_name(project_dir) -initialfile $name -title $title -filetypes {{{All Files} *}}]
    if {$file == ""} {
        $smooth_multi_block(entry_save) configure -state readonly -readonlybackground grey
        busy 0
        return
    }
 
    set f [open $file w]
    if [info exists env(USER)] {
        set user $env(USER)
    } else {
        set user Dummy
    }
    puts $f "Settings Management for Smoothing and Predefined Mesh: Med"
    puts $f "Username: $user"
    puts $f "Filename: $file"
    puts $f "SmoothDomain:"
    puts $f "$smooth_domain"
    puts $f "FaceMethods:"
    puts $f "$face_methods"
    puts $f "VolumeMethods:"
    puts $f "$volume_methods" 
    puts $f "RelaxSubface:"
    puts $f "$relax_subfaces"
    puts $f "RelaxZone:"
    puts $f "$relaxation_zones"
    puts $f "ViolGeomZone:"
    puts $f "$viol_geom_zones"
    puts $f "LayerExtensionIJK:"
    puts $f "$ijk_extensions" 
    puts $f "Region:"
    puts $f "$base_regions"
    puts $f "ViolGeomSubface:"
    puts $f "$viol_geom_subfaces"
    puts $f "first_cell_height:"
    puts $f "$first_cell_height"
    puts $f "last_cell_height:"
    puts $f "$last_cell_height"
    puts $f "Niter:"
    puts $f $niter
    puts $f "Nsteps:"
    puts $f $nsteps
    puts $f "Maxlevel:"
    puts $f $maxlevel
    puts $f "Sfit:"
    puts $f $sfit
    puts $f "Conditional:"
    puts $f $conditional
    puts $f "CheckDet:"
    puts $f $check_det
    puts $f "Damping:"
    puts $f $damping
    puts $f "VertexFix:"
    puts $f $vertex_fix
    puts $f "EdgeFreeze:"
    puts $f $edge_freeze
    puts $f "WedgeCheck:"
    puts $f $wedge_check
    puts $f "Multigrid2D:"
    puts $f $multigrid2d
    puts $f "ReducedEdge:"
    puts $f $reduced_edge
    puts $f "FixFam:"
    puts $f $fix_fam
    puts $f "InnVol:"
    puts $f $inner_vol_sm
    puts $f "NsRel:"
    puts $f $ns_rel
    puts $f "AngleFreezeEdges:"
    puts $f $angle_freeze_edge
    puts $f "nItera:"
    puts $f $n_iter
    puts $f "ProjLimit:"
    puts $f $proj_limit
    puts $f "InterpolateFaces:"
    puts $f $interp_faces
    puts $f "InterpolateVolumes:"
    puts $f $interp_volumes
    puts $f "ThresholdDet:"
    puts $f $threshold_det
    puts $f "ThresholdAngle:"
    puts $f $threshold_angle
    puts $f "SubfaceExtend:"
    puts $f $subface_extensions
    puts $f "DirectionVector:"
    puts $f $direction_vector
    puts $f "SmoothDir:"
    puts $f "$smooth_dir"
    puts $f "PlaneSmooth:"
    puts $f "$incr_3d_plane_smooth"
    puts $f "relax_weights_2d:"
    puts $f "$relax_weights_2d"
    puts $f "relax_weights_3d:"
    puts $f "$relax_weights_3d"
    puts $f "relax_weights_inner_2d:"
    puts $f "$relax_weights_inner_2d"
    puts $f "relax_weights_inner_3d:"
    puts $f "$relax_weights_inner_3d"
    puts $f "SmoothOnFaces:"
    puts $f "$surfresolv"
    puts $f "MinResidual:"
    puts $f "$min_mxr"
    puts $f "StopResidual:"
    puts $f "$min_res" 
    puts $f "UnselectedMethods:"
    puts $f "$smooth_ngh_method"
    puts $f "mesh_type:"
    puts $f "$mesh_type" 
    puts $f "n_iter_glb:"
    puts $f "$n_iter_glb"
    puts $f "n_steps_glb:"
    puts $f "$n_steps_glb"
    puts $f "etmVertexGlobal:"
    puts $f "$global_vertices_opp"
    puts $f "PlaneNumbers:"
    puts $f "$plane_numbers"
    puts $f "grid_exp_face:"
    puts $f "$grid_exp_face"
    puts $f "grid_exp_vol:"
    puts $f "$grid_exp_vol"
    puts $f "ThresholdAngle:"
    puts $f "$threshold_angle"
    puts $f "ThresholdDet:"
    puts $f "$threshold_det"
    puts $f "GroupBadElem:"
    puts $f "$group_bad_elem"
    puts $f "TypeImprove:"
    puts $f "$type_improve"
    puts $f "TypePostSm:"
    puts $f "$type_postsm"
    puts $f "prog_select:"
    puts $f "$use_smooth_prog_type"
    puts $f "abs_dist_bnd:"
    puts $f "$abs_dist_bnd"
    puts $f "n_points_abs_dist_bnd:"
    puts $f "$n_points_abs_dist_bnd"
    puts $f "use_pthreads:"
    puts $f "$use_pthreads"
    puts $f "abs_dist_subf:"
    puts $f "$abs_dist_subf"
    puts $f "n_abs_dist_subf:"
    puts $f "$n_abs_dist_subf"
    puts $f "VertexLayer:"
    puts $f "$vertex_attrib"
    puts $f "etmEdgeGlobalSave:"
    puts $f "$edge_no_global_smooth"
    puts $f "relaxation_factor:"
    puts $f "$relaxation_factor"
    puts $f "use_orthog_position:"
    puts $f "$use_orthog_position"
    puts $f "use_fract_position:"
    puts $f "$use_fract_position"  
    puts $f "grid_exp_rate_subf_perp:"
    puts $f "$grid_exp_rate_subf_perp"
    puts $f "grid_exp_rate_subf_1:"
    puts $f "$grid_exp_rate_subf_1"
    close $f
        
    mess "Multiblock settings file (4.3 format) $file saved.\n" blue
    $smooth_multi_block(entry_save) configure -state readonly -readonlybackground grey
    busy 0
}

proc aie_hex_load_multiblock_settings {{file ""} {sequence ""} {op ""}} {
    global smooth_multi_block batch_mode use_output_blocks

    if !$batch_mode {
        if {$sequence != ""} {
            set file [hexSmoothDEZ get mbs_setting_seq_$sequence]
        } else {
            set file [hexSmoothDEZ get mbs_setting_load]
        }
    } else {
        if ![file exists $file] {
            mess "Missing settings file $file\n" red
            return
        }
    }
    if {$file == ""} return
    set f [open $file r]
    set line [string trim [gets $f]]
    close $f
    if {$line != "# Multiblock Settings File"} {
        if [string match "Settings Management for Smoothing and Predefined Mesh: Med" $line] {
            mess "Loading old setting $file.\n" blue
            hexSmoothDEZ set mbs_setting_old $file
            set tmp_file [cmd_tempfile $file .tmp]
            hexSmoothDEZ set mbs_setting_new $tmp_file
            aie_hex_convert_multiblock_settings 1
            hexSmoothDEZ set mbs_setting_old ""
            hexSmoothDEZ set mbs_setting_new ""
            return 
        } else {
            mess "File $file is not a \"Multiblock Settings File\".\n" red
            return ""
        }
    }
   
    catch { unset batch_params; unset gui_params }  
    set f [open $file r]
    while {![eof $f]} {
      set line [string trim [gets $f]]
      if {$line == ""} continue
      if [string match \#* $line] continue
      if [string match batch_params $line] {
          set batch_params [string trim [gets $f]]
      }
      if [string match gui_params $line] {
          set gui_params [string trim [gets $f]]
      }
    }
    close $f
   
    if {![info exists batch_params] || ![info exists gui_params]} {
        mess "Unable to read \"Multiblock\" settings from file $file.\n" red
        return ""
    }

    if !$batch_mode {
        set smooth_multi_block(loading) 1
        hex_command "display_super_faces [range_string] [family_activename_string] erase_icon"
        hex_command "display_nodes erase"
        hex_command "mark_blocks unmark"
        hex_command "unblank_blocks"
        aie_hex_init_multiblock_selections
        busy 1
        set numblocks 0
        set idx [lsearch $batch_params smooth_domain]
        if {$idx != -1} {
            set numblocks [llength [lindex $batch_params [expr $idx + 1]]]
        }
        foreach {n v} $gui_params {
            if {$n == "vertex_attrib_gui"} {
                foreach {num val} $v {
                     set smooth_multi_block(layer_distance,$num) $val
                }
            } elseif {$n == "ijkBlock"} {
                 set smooth_multi_block(ijkBlock) $v
            } elseif {$n == "smoothDirection"} {
                 set smooth_multi_block(smoothDirection) $v
            } elseif {$n == "n_processors"} {
                 set smooth_multi_block(n_processors) $v
            } elseif {$n == "HEXsmoothMBSVal" || $n == "mbs_setting_load" || \
                      $n == "mbs_setting_save"} {
                 continue
            } elseif {($n == "mbs_setting_seq_1" || $n == "mbs_setting_seq_2" || \
                       $n == "mbs_setting_seq_3" || $n == "mbs_setting_seq_4" || \
                       $n == "mbs_setting_seq_5") && $sequence != ""} {
                 continue
            } else {
                catch { hexSmoothDEZ set $n $v }
            }
        }
        if {$smooth_multi_block(nBlocks) != $numblocks} {
            mess "The number of blocks is different from the settings file. You may wish\
                  to clear block, face and/or vertex selection and reselect them.\n" red
        }
        set smooth_multi_block(SelectedBlocks) [hexSmoothDEZ get RelaxBlocks]
        set blocks ""
        for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
            if {[lsearch $smooth_multi_block(SelectedBlocks) $i] < 0} {
                append blocks "$i "
            }
        }
        set smooth_multi_block(UnselectedBlocks) $blocks
        if $use_output_blocks {
            set faces [ic_hex_get_super_faces_topo output_blocks]
        } else {
            set faces [ic_hex_get_super_faces_topo]
        }
        foreach f $faces {
            set face " [lrange $f 0 3] "
            set smooth_multi_block(TopoFaceNum,$face) [lindex $f 4]
        }
        aie_hex_face_picking_finished_all [hexSmoothDEZ get NonRelaxFaces] NonRelaxFaces 1
        aie_hex_face_picking_finished_all [hexSmoothDEZ get HoldCellHeightFaces] HoldCellHeightFaces 1
        foreach type "GlobalVertices LayerVertices" {
            set smooth_multi_block($type) [hexSmoothDEZ get $type]
        }
        set idx [hexSmoothDEZ get incrIndex]
        aie_hex_relaxblocks_update
        hexSmoothDEZ set incrIndex $idx
        aie_hex_multiblock_display_selections
        $smooth_multi_block(entry_load) configure -state readonly -readonlybackground grey
        mess "Multiblock settings file $file loaded.\n" blue
        busy 0
        unset smooth_multi_block(loading)
        return ""
    } else {
        mess "Multiblock settings file $file loaded.\n" blue
        return "$batch_params"
    }
}

proc aie_hex_run_multiblock_settings {} {
    global smooth_multi_block
   
    foreach run "1 2 3 4 5" {
        set mbs_file [hexSmoothDEZ get mbs_setting_seq_$run]
        if {$mbs_file == ""} break
        if [file exists $mbs_file] {
            set smooth_multi_block(sequence_run) $run
            aie_hex_load_multiblock_settings "$mbs_file" $run ""
            mess "Sequence $run: Running settings file $mbs_file\n" blue
            hexSmoothDEZ apply
            unset smooth_multi_block(sequence_run)         
            mess "Sequence $run: Done\n" blue
        } else {
            mess "Error sequence $run: Settings file not found: $mbs_file\n" red
            break
        }
    }
}

proc aie_hex_run_auto_setup {} {
    global smooth_multi_block use_output_blocks

    if {$refEdge == "" && $smooth_multi_block(mesh_dim) == 3} {
        mess "Select reference edge before using \"Auto Setup\"\n" red
        return
    }
    if {$smooth_multi_block(mesh_dim) != 3} {
        mess "Not implemented for mesh dimension $smooth_multi_block(mesh_dim) yet\n" red
        return
    }
     
    busy 1
   
    mess "Running auto setup...\n" blue
    catch { unset autosetup }
    hex_command "display_super_faces [range_string] [family_activename_string] erase_icon"
    hex_command "display_nodes erase"
   
    if {$smooth_multi_block(mesh_dim) == 3} {
        set n1 [lindex $refEdge 0]
        set n2 [lindex $refEdge 1]
        set node_dim [string trimright [ic_hex_edge_node_dim $n1 $n2] \n]
        set dim [lindex {I J K} [lindex $node_dim 0]]
        mess "Detecting blocks in $dim direction...\n"
        if $use_output_blocks {
            set autosetup(Planes) [ic_hex_get_super_faces_in_plane output_blocks check_subface_num $n1 $n2]
        } else {
            set autosetup(Planes) [ic_hex_get_super_faces_in_plane check_subface_num $n1 $n2]
        }
    }
   
    set merge_blocks_before 0
    foreach f $autosetup(Planes) {
        if [lindex $f 4] {
            set n1 [lindex $f 0]; set n2 [lindex $f 1]; set n3 [lindex $f 2]; set n4 [lindex $f 3]
            if $use_output_blocks {
                 set n $smooth_multi_block(TopoFaceNum, [lrange $f 0 3] )
                 set blocks $smooth_multi_block(blockFaces,$n)
            } else {
                set blocks [string trim [string trimright [ic_hex_get_face_blocks $n1 $n2 $n3 $n4] \n]]
            }
            if {[llength $blocks] != 2} continue
            set b1 [lindex $blocks 0]; set b2 [lindex $blocks 1]
            if {[lsearch "$smooth_multi_block(SelectedBlocks)" "$b1"] >= 0 && \
                [lsearch "$smooth_multi_block(SelectedBlocks)" "$b2"] >= 0} {       
               set merge_blocks_before 1
               break
            }
        }
    }
    if $merge_blocks_before {
        mess "Error: you need to merge blocks in $dim direction before using \"Auto setup\" \
                     or you need to set pre-mesh option \"Output Blocks\" before creating the pre-mesh\n" red
        busy 0
        return
    }
   
    set autosetup(InPlane) ""
    set autosetup(NotInPlane) ""
    foreach f $autosetup(Planes) {
        set face [lrange $f 0 3]
        set in_plane [lindex $f 4]
        if $in_plane {
            lappend autosetup(InPlane) " $face "
        } else {
            lappend autosetup(NotInPlane) " $face "
        }
    }
    set autosetup(UseSelected) $autosetup(NotInPlane)

    catch { unset not_these }
    set not_these(isBlock) ""
    set not_these(isBound) ""  
    
    mess "Selecting non-relax faces...\n"
    set autosetup(NonRelaxFaces) ""
    hexSmoothDEZ set NonRelaxRemove 1
    set on(NonRelaxFaces) [hexSmoothDEZ get NonRelaxRemove]
    foreach f $autosetup(UseSelected) {
        if {[lsearch "$smooth_multi_block(PeriodicFaces)" "$f"] >= 0} continue
        set n1 [lindex $f 0]; set n2 [lindex $f 1]; set n3 [lindex $f 2]; set n4 [lindex $f 3]
        if ![info exists smooth_multi_block(TopoFaceNum,$f)] {
            if $use_output_blocks {
                set n [string trimright [ic_hex_topo_face_number output_blocks $n1 $n4] \n]
            } else {
                set n [string trimright [ic_hex_topo_face_number $n1 $n4] \n]
            }
            set smooth_multi_block(TopoFaceNum,$f) $n
        }
        if $use_output_blocks {
             set n $smooth_multi_block(TopoFaceNum,$f)
             set blocks $smooth_multi_block(blockFaces,$n)
        } else {
            set blocks [string trim [string trimright [ic_hex_get_face_blocks $n1 $n2 $n3 $n4] \n]]
        }
        if {[lsearch "$smooth_multi_block(isBound)" $smooth_multi_block(TopoFaceNum,$f)] >= 0} {
            if {[llength $blocks] == 1 && ([lsearch "$smooth_multi_block(SelectedBlocks)" "$blocks"] >= 0)} {
                set skip_face 0
                foreach p $not_these(isBound) {
                    if ![info exists smooth_multi_block(faceFamily,$p)] continue
                    set n $smooth_multi_block(TopoFaceNum,$f)
                    if {[lsearch "$smooth_multi_block(faceFamily,$p)" "$n"] >= 0} {
                        set skip_face 1
                    }
                }
                if $skip_face continue
                lappend autosetup(NonRelaxFaces) $f
            }
        } elseif {[lsearch "$smooth_multi_block(isBlock)" $smooth_multi_block(TopoFaceNum,$f)] >= 0} {
            if {[llength $blocks] != 2} continue
            set skip_face 0
            foreach p $not_these(isBlock) {
                if ![info exists smooth_multi_block(faceFamily,$p)] continue
                set n $smooth_multi_block(TopoFaceNum,$f)
                if {[lsearch "$smooth_multi_block(faceFamily,$p)" "$n"] >= 0} {
                    set skip_face 1
                }
            }
            if $skip_face continue
            foreach {b1 b2} $blocks {
                if {([lsearch "$smooth_multi_block(SelectedBlocks)" "$b1"] < 0 && \
                     [lsearch "$smooth_multi_block(SelectedBlocks)" "$b2"] >= 0) || \
                    ([lsearch "$smooth_multi_block(SelectedBlocks)" "$b2"] < 0 && \
                     [lsearch "$smooth_multi_block(SelectedBlocks)" "$b1"] >= 0)} {
                    lappend autosetup(NonRelaxFaces) $f
                }
            }
        }
    }
   
    mess "Selecting hold cell height faces...\n"
    set autosetup(HoldCellHeightFaces) ""
    hexSmoothDEZ set HoldCellHeightRemove 1
    set on(HoldCellHeightFaces) [hexSmoothDEZ get HoldCellHeightRemove]
    set autosetup(HoldCellHeightFaces) $autosetup(NonRelaxFaces)

    hexSmoothDEZ set smoothFilterNonRelax 0
    hexSmoothDEZ set smoothFilterHoldCellHeight 0
    foreach type {NonRelaxFaces HoldCellHeightFaces} {
        aie_hex_face_picking_finished_all $autosetup($type) $type 1
        hexSmoothDEZ set $type $smooth_multi_block($type,0)
    }

    set parts ""
    foreach p [array names smooth_multi_block faceFamily,*] {
        set part [lindex [split $p ,] 1]
        lappend parts $part
    }
    set part_used ""
    foreach p $parts {
        set faces $smooth_multi_block(faceFamily,$p)
        foreach f $autosetup(NonRelaxFaces) {
            set n $smooth_multi_block(TopoFaceNum,$f)
            if {[lsearch "$faces" "$n"] >= 0} {
                append part_used "$p "
                break
            }
        }
    }
   
    set existing_verts [hex_command "select_nodes 1 all [range_string] m [volume_activename_string] node_numbers"]
    
    mess "Selecting global vertices...\n"
    set vertices ""; set skip ""
    foreach n $existing_verts {
        if {[lsearch "$vertices" "$n"] >= 0} continue
        if $use_output_blocks {
            set blocks [string trimright [ic_hex_get_vertex_blocks $n output_blocks] \n]
        } else {
            set blocks [string trimright [ic_hex_get_vertex_blocks $n] \n]
        }
        foreach b $blocks {
            if {[lsearch "$smooth_multi_block(SelectedBlocks)" "$b"] >= 0} {
                if {[info exists smooth_multi_block(vertexBlock,$n)] && $smooth_multi_block(vertexBlock,$n)} {
                    if {[lsearch "$vertices" "$n"] < 0} {
                        append vertices "$n "
                    }
                }
            } else {
                append skip "$n "
            }
        }
    }   
    set global_vertices ""
    foreach n $vertices {
        if {[lsearch "$skip" "$n"] < 0} {
            append global_vertices "$n "
        }
    }

    if {$global_vertices == "" && [llength $smooth_multi_block(SelectedBlocks)] > 1} {
        set global_vertices [lsort -integer $existing_verts]
    }
    hexSmoothDEZ set GlobalVertices [lsort -integer $global_vertices]
    set smooth_multi_block(GlobalVertices) $GlobalVertices
 
    mess "Selecting layer vertices...\n"
    set vertices ""; set skip ""
    foreach n $existing_verts {
        if {[lsearch "$vertices" "$n"] >= 0} continue
        if $use_output_blocks {
            set blocks [string trimright [ic_hex_get_vertex_blocks $n output_blocks] \n]
        } else {
            set blocks [string trimright [ic_hex_get_vertex_blocks $n] \n]
        }
        foreach b $blocks {
            if {[lsearch "$smooth_multi_block(SelectedBlocks)" "$b"] >= 0} {
                if {[lsearch "$vertices" "$n"] < 0} {
                    append vertices "$n "
                }
            } else {
                append skip "$n "
            }
        }
    }   
    set layer_vertices ""
    foreach n $vertices {
        if {[lsearch "$skip" "$n"] < 0} {
            append layer_vertices "$n "
        }
    }
    if {$layer_vertices == "" && [llength $smooth_multi_block(SelectedBlocks)] > 1} {
        set layer_vertices [lsort -integer $existing_verts]
    }
    hexSmoothDEZ set LayerVertices [lsort -integer $layer_vertices]
    set smooth_multi_block(LayerVertices) $LayerVertices
    foreach i $layer_vertices {
        set smooth_multi_block(layer_distance,$i) -1
    }
   
    if {$part_used != ""} {
        mess "Parts used for non-relax and hold cell height faces: $part_used\n"
    }
    aie_hex_multiblock_display_selections
    mess "Done auto setup\n" blue
    busy 0
}

proc aie_hex_trace_choose_direction {{name ""} {element ""} {op ""}} {
    global smooth_multi_block

    if [info exists smooth_multi_block(sequence_run)] return
    if ![info exists smooth_multi_block(SelectedBlocks)] return

    if {$smooth_multi_block(mesh_dim) == "2"} {
        ::AIEnv::GUIManagement::ToggleGrey smoothEdgeDirPick 1
    }

    if {[hexSmoothDEZ get HEXsmoothDirVal] == 0 || [hexSmoothDEZ get RelaxBlocks] == ""} {
        set smooth_multi_block(smoothDirection) 0
    } else {
        if {$smooth_multi_block(mesh_dim) == "2"} {
            set min 1
            set max 1
            set smooth_multi_block(smoothDirection) 3
            hexSmoothDEZ set refEdgeDir K
        } else {
            set min [lindex $smooth_multi_block(ijkBlock) 0]
            set max [lindex $smooth_multi_block(ijkBlock) 1]
            switch [hexSmoothDEZ get refEdgeDir] {
                I { set smooth_multi_block(smoothDirection) 1 }
                J { set smooth_multi_block(smoothDirection) 2 }
                K { set smooth_multi_block(smoothDirection) 3 }
                default { set smooth_multi_block(smoothDirection) 0 }
            }
        }
    }
    switch $smooth_multi_block(smoothDirection) {
        0 {
            hexSmoothDEZ set startIndex 1
            hexSmoothDEZ set endIndex 1
            hexSmoothDEZ set incrIndex 1
            hexSmoothDEZ set planeNums ""
            ::AIEnv::GUIManagement::ToggleGrey smoothLayerframe 1
        }
        1 - 2 - 3 {
            ::AIEnv::GUIManagement::ToggleGrey smoothLayerframe 0
            if {$min == "" && $max == ""} return
            if {$smooth_multi_block(mesh_dim) == "2"} {
                hexSmoothDEZ set startIndex 1
                hexSmoothDEZ set endIndex 1
                ::AIEnv::GUIManagement::ToggleGrey HEXincr 1
                ::AIEnv::GUIManagement::ToggleGrey HEXsmoothPlanesNums 1
                return
            } else {
                set idx [expr $smooth_multi_block(smoothDirection) - 1]
                hexSmoothDEZ set startIndex [lindex $min $idx]
                hexSmoothDEZ set endIndex [lindex $max $idx]
                hexSmoothDEZ set incrIndex [expr [hexSmoothDEZ get endIndex ] - 1]
            }     
            aie_hex_trace_smooth_dir_params
        }
    }
}

proc aie_hex_trace_smooth_dir_params {{name ""} {element ""} {op ""}} {
    global smooth_multi_block

    if [info exists smooth_multi_block(sequence_run)] return   
    if {[hexSmoothDEZ get HEXsmoothDirVal] == 0} return
    if {[hexSmoothDEZ get planeNums] != ""} {
        ::AIEnv::GUIManagement::ToggleGrey HEXstartIndex 1
        ::AIEnv::GUIManagement::ToggleGrey HEXendIndex 1
        ::AIEnv::GUIManagement::ToggleGrey HEXincr 1
    } else {
        ::AIEnv::GUIManagement::ToggleGrey HEXstartIndex 0
        ::AIEnv::GUIManagement::ToggleGrey HEXendIndex 0
        ::AIEnv::GUIManagement::ToggleGrey HEXincr 0
    }
}

proc aie_hex_trace_premesh_val {name element op} {
    global smooth_multi_block select_premesh_families

    if [info exists smooth_multi_block(sequence_run)] return
    if {[hexSmoothDEZ get smoothPremeshVal] == 2} {
        if ![ic_geo_is_loaded] {
            mess "Geometry not loaded. Load geometry file before using \"Multiblock\".\n" red
            if [info exists select_premesh_families] { unset select_premesh_families }
            ::AIEnv::GUIManagement::ToggleGrey HEXsmoothPremeshbyMultiblock 1
            return
        } else {
            ::AIEnv::GUIManagement::ToggleGrey HEXsmoothPremeshbyMultiblock 0
            set select_premesh_families 1
            # this is for loading settings from a project file
            if ![info exists smooth_multi_block(loading)] {
                after 500 {
                    busy 1
                    # ignore the settings from the project file
                    # user should use the settings file instead
                    aie_hex_settings_reset
                    aie_hex_relaxblocks_update
                    aie_hex_multiblock_display_selections
                    busy reset
                }
            }
        }
    } else {
        if [info exists select_premesh_families] { unset select_premesh_families }
        onHEXsmoothPremeshbyMultiblockUnLoad
        ::AIEnv::GUIManagement::ToggleGrey HEXsmoothPremeshbyMultiblock 0
    }
}

proc aie_hex_trace_use_output_blocks {name element op} {
    global smooth_multi_block use_output_blocks
   
    if {[TreeStack peek] != "hexSmoothDEZ_Tree"} return
    if {[hexSmoothDEZ get smoothPremeshVal] != 2} return
    if {$smooth_multi_block(use_output_blocks) != $use_output_blocks} {
        if $use_output_blocks {
            mess "Warning: You switched \"Output Blocks\" to on.  Please reset to off again\n" red
        } else {
            mess "Warning: You switched \"Output Blocks\" to off.  Please reset to on again\n" red
        }
    }
}

proc aie_hex_trace_multiblock_settings {name element op} {
    global smooth_multi_block
    if ![info exists smooth_multi_block(entry_save)] return
    $smooth_multi_block(entry_save) configure -state readonly -readonlybackground grey
    $smooth_multi_block(entry_load) configure -state readonly -readonlybackground grey
}

proc aie_hex_trace_multiblock_display {name element op} {
    global smooth_multi_block
    if ![info exists smooth_multi_block(SelectedBlocks)] return
    if {$smooth_multi_block(SelectedBlocks) == ""} return
    if [info exists smooth_multi_block(display_selections)] return
    set smooth_multi_block(display_selections) 1
    after 1 {
        aie_hex_multiblock_display_selections
        unset smooth_multi_block(display_selections)
    }
}

proc aie_hex_clear_all_selections {} {
    busy 1
    aie_hex_settings_reset
    aie_hex_relaxblocks_update
    aie_hex_multiblock_display_selections
    busy reset   
}

proc aie_hex_settings_reset {} {
    global smooth_multi_block use_output_blocks

    hexSmoothDEZ set RelaxBlocks ""
    hexSmoothDEZ set NonRelaxFaces ""
    hexSmoothDEZ set HoldCellHeightFaces ""
    hexSmoothDEZ set GlobalVertices ""
    hexSmoothDEZ set LayerVertices ""
    hexSmoothDEZ set refEdge ""
    hexSmoothDEZ set refEdgeDir ""
    hexSmoothDEZ set startIndex 1
    hexSmoothDEZ set endIndex 1
    hexSmoothDEZ set incrIndex 1
    hexSmoothDEZ set iterIndex 0
    hexSmoothDEZ set planeNums ""
    hexSmoothDEZ set itersEdges 25
    hexSmoothDEZ set itersVertices 25
    hexSmoothDEZ set parameterPrjLim 0.0
    hexSmoothDEZ set parameterRelFac 0.5
    hexSmoothDEZ set parameterResFac 0.05
    hexSmoothDEZ set parameterUseProj 1
    hexSmoothDEZ set parameterFaceFit 1
    hexSmoothDEZ set parameterUseOrt 1
    hexSmoothDEZ set parameterUseFra 0
    hexSmoothDEZ set volume_method "Sorenson - Laplace"
    hexSmoothDEZ set face_method "Sorenson - Laplace"
    hexSmoothDEZ set gridexpansionVol 4.6
    hexSmoothDEZ set gridexpansionFace 3.5
    hexSmoothDEZ set smoothFilterNonRelax 0
    hexSmoothDEZ set smoothFilterHoldCellHeight 0
    hexSmoothDEZ set smoothFaceOptionsVal 0
    hexSmoothDEZ set smoothVertexEntitiesVal 0
    hexSmoothDEZ set smoothAdvancedVal 1
    hexSmoothDEZ set HEXsmoothDirVal 1
    hexSmoothDEZ set NonRelaxRemove 1
    hexSmoothDEZ set HoldCellHeightRemove 1
    hexSmoothDEZ set HEXsmoothMBSVal 0
    hexSmoothDEZ set mbs_setting_load ""
    hexSmoothDEZ set mbs_setting_save ""
    hexSmoothDEZ set mbs_setting_seq_1 ""
    hexSmoothDEZ set mbs_setting_seq_2 ""
    hexSmoothDEZ set mbs_setting_seq_3 ""
    hexSmoothDEZ set mbs_setting_seq_4 ""
    hexSmoothDEZ set mbs_setting_seq_5 ""
    hexSmoothDEZ set mbs_setting_old ""
    hexSmoothDEZ set mbs_setting_new ""
    set smooth_multi_block(SelectedBlocks) ""
    set blocks ""
    for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
        append blocks "$i "
    }
    set smooth_multi_block(UnselectedBlocks) $blocks
    set smooth_multi_block(RelaxBlocks,save) ""
    set smooth_multi_block(ijkBlock) ""
    set smooth_multi_block(smoothDirection) 0
    set smooth_multi_block(use_output_blocks) $use_output_blocks
    set smooth_multi_block(LayerVertices,save) ""
    set smooth_multi_block(LayerVertices) ""
    set smooth_multi_block(GlobalVertices,save) ""
    set smooth_multi_block(GlobalVertices) ""
   
    if $use_output_blocks {
        set smooth_multi_block(PeriodicFaces) [lindex [ic_hex_display_periodic_faces get_faces output_blocks] 0]
    } else {
        set smooth_multi_block(PeriodicFaces) [lindex [ic_hex_display_periodic_faces get_faces] 0]
    }
    set smooth_multi_block(NonRelaxFaces,save) ""
    set smooth_multi_block(HoldCellHeightFaces,save) ""
    foreach idx {0 1 2} {
        set smooth_multi_block(NonRelaxFaces,$idx) ""
        set smooth_multi_block(NonRelaxFaces,topo_nums,$idx) ""
        set smooth_multi_block(HoldCellHeightFaces,$idx) ""
        set smooth_multi_block(HoldCellHeightFaces,topo_nums,$idx) ""
    }
}

proc aie_hex_relaxblocks_update {} {
    global smooth_multi_block

    if [info exists smooth_multi_block(sequence_run)] return
    if ![info exists smooth_multi_block(SelectedBlocks)] return
    if {$smooth_multi_block(SelectedBlocks) == ""} {
        ::AIEnv::GUIManagement::ToggleGrey HEXsmoothDir 1
        ::AIEnv::GUIManagement::ToggleGrey smoothLayerframe 1
        ::AIEnv::GUIManagement::ToggleGrey smoothFaceOptions 1
        ::AIEnv::GUIManagement::ToggleGrey smoothVertexEntities 1
        hexSmoothDEZ set smoothAdvancedVal 4
    } else {
        ::AIEnv::GUIManagement::ToggleGrey HEXsmoothDir 0
        ::AIEnv::GUIManagement::ToggleGrey smoothFaceOptions 0
        ::AIEnv::GUIManagement::ToggleGrey smoothVertexEntities 0
        aie_hex_trace_choose_direction
    }
}

proc onsmoothHEXSetSelectedParts {what {part_list ""} {reset 0}} {
    global test_smooth fams_attr_local
   
    if [winfo exists .test_smooth_set_part] { form_delete .test_smooth_set_part }  
    set buttons {
      {accept}
      {dismiss}
    }
    if {$what == "layer_distance"} {
      if {$part_list != ""} {
          set partFirstList $part_list
      } else {
          set partFirstList [hexSmoothDEZ get partFirstList]
      }
      if {$partFirstList == ""} {
          mess "No part(s) selected.\n"
          return ""
      }
      set default_value -1
      set type_attr 0
      set type float
      set idx_srf release_ortho
      set text_srf "Release orthogonality"
      set text_win "Release orthogonality/Initial Height"
      set list $partFirstList
    } else {
      if {$part_list != ""} {
          set partFixList $part_list
      } else {
          set partFixList [hexSmoothDEZ get partFixList]
      }
      if {$partFixList == ""} {
          mess "No part(s) selected.\n"
          return ""
      }
      set default_value 0
      set type_attr 1
      set type int
      set idx_srf freeze_surfaces
      set text_srf "Freeze surface boundary"
      set text_win "Freeze surface boundary + n layers"
      set list $partFixList
    }
    set w [form_init .test_smooth_set_part "$text_win by part(s)" "" $buttons]

    set i 0
    if {$w != ""} {
	    foreach item $list {
	        form_label $w.name$i "$item" "$i 0"; $w.name$i configure -relief ridge
	        if ![info exists test_smooth($idx_srf,$item)] {
	            set test_smooth($idx_srf,$item) 0
	        }
            if {$what == "fix_layers"} {
	        form_checkbutton $w.part$i "$text_srf" fams_attr_local($idx_srf,$item) "$i 1" "" \
	            "aie_hex_configure_smooth_parts_form $w.part$i $w.value$i $type_attr $w.layers$i" "nonbool"
            } else {
	        form_checkbutton $w.part$i "$text_srf" fams_attr_local($idx_srf,$item) "$i 1" "" \
	            "aie_hex_configure_smooth_parts_form $w.part$i $w.value$i $type_attr" "nonbool"
            }
	        $w.part$i configure -onvalue 0 -offvalue 1
	        if {![info exists test_smooth(fams_attr,$type_attr,$item)] || \
		        $test_smooth(fams_attr,$type_attr,$item) == ""} {
	            set test_smooth(fams_attr,$type_attr,$item) $default_value
	        }
	        set filter "fams_attr_local($idx_srf,$item) $test_smooth(fams_attr,$type_attr,$item)"
	        set fams_attr_local($type_attr,$item) $test_smooth(fams_attr,$type_attr,$item)
	        form_entry $w.value$i fams_attr_local($type_attr,$item) $type "$i 2" $filter
            if {$what == "fix_layers"} {
                form_label $w.layers$i "Layers" "$i 4"
	            aie_hex_configure_smooth_parts_form $w.part$i $w.value$i $type_attr $w.layers$i
            } else {
	            aie_hex_configure_smooth_parts_form $w.part$i $w.value$i $type_attr
            }
	        incr i
	    }
	form_finish +200+200
    }
    if [form_wait .test_smooth_set_part] {
        foreach item $list {
            set test_smooth($idx_srf,$item) $fams_attr_local($idx_srf,$item)
            if {$fams_attr_local($idx_srf,$item) == "1"} {
                set test_smooth(fams_attr,$type_attr,$item) $fams_attr_local($type_attr,$item)
            } else {
                set test_smooth(fams_attr,$type_attr,$item) $default_value
            }
        }
        set the_part_list1 ""
        foreach item [array names test_smooth $idx_srf,*] {
            lappend the_part_list1 "$item $test_smooth($item)"
        }
        set the_part_list2 ""
        foreach item [array names test_smooth fams_attr,$type_attr,*] {
            lappend the_part_list2 "$item $test_smooth($item)"
        }
        if $reset {
            if {$what == "layer_distance"} {
                onHEXfirstLayerSOESelFinish "$the_part_list1 $the_part_list2"
            } elseif {$what == "fix_layers"} {
                onHEXfreezeLayersSOESelFinish "$the_part_list1 $the_part_list2"
            }
        } else {
            return "$the_part_list1 $the_part_list2"
        }
    } else {
        return ""
    }
}

proc aie_hex_configure_smooth_parts_form {w1 w2 type {w3 ""}} {
     global fams_attr_local
     set on [$w1 cget -variable]
     if ![set $on] {
         if {$type == 0} {
             $w1 configure -text "Release orthogonality"
         } elseif {$type == 1} {
             $w1 configure -text "Surface boundary"
             if {$w3 != ""} {
                 $w3 configure -text "      "
             }
         }
         $w2 configure -state disabled
         $w2 configure -foreground gray
     } else {
         if {$type == 0} {
             $w1 configure -text "Initial Height"
         } elseif {$type == 1} {
             $w1 configure -text "Surface boundary + "
             if {$w3 != ""} {
                 $w3 configure -text "Layers"
             }
         }
         $w2 configure -state normal
         $w2 configure -foreground black
     }
}

proc onHEXfreezeLayersSOESelFinish {{attr ""}} {
    global test_smooth

    if {$attr == ""} {
        set attr [onsmoothHEXSetSelectedParts fix_layers $partFixList]
    }
    set attr2 ""
    if {$attr != ""} {
        set list [hexSmoothDEZ get partFixList]
        set attr2 ""
        foreach item $attr {
            set var [lindex $item 0]
            set what [lindex [split $var ,] 0]
            if {$what == "freeze_surfaces"} {
                set part [lindex [split $var ,] 1]
            } elseif {$what == "fams_attr"} {
                set part [lindex [split $var ,] 2]
            } else {
                continue
            }
            if {[lsearch $list $part] < 0} continue
            lappend attr2 $item
        }
    }
    set attr $attr2
    if {$attr != ""} {
        foreach item [array names test_smooth freeze_surfaces,*] {
            unset test_smooth($item)
        }
        foreach item [array names test_smooth fams_attr,1,*] { 
            unset test_smooth($item)
        }
        foreach item $attr {
            set var [lindex $item 0]
            set val [lindex $item 1]
            set test_smooth($var) $val
        }
        hexSmoothDEZ set fix_layers_settings $attr
    }
}

proc onHEXfirstLayerSOESelFinish {{attr ""}} {
    global test_smooth
    
    if {$attr == ""} {
        set attr [onsmoothHEXSetSelectedParts layer_distance $partFirstList]
    }
    set attr2 ""
    if {$attr != ""} {
        set list [hexSmoothDEZ get partFirstList]
        set attr2 ""
        foreach item $attr {
            set var [lindex $item 0]
            set what [lindex [split $var ,] 0]
            if {$what == "release_ortho"} {
                set part [lindex [split $var ,] 1]
            } elseif {$what == "fams_attr"} {
                set part [lindex [split $var ,] 2]
            } else {
                continue
            }
            if {[lsearch $list $part] < 0} continue
            lappend attr2 $item
        }
    }
    set attr $attr2
    if {$attr != ""} {
        foreach item [array names test_smooth release_ortho,*] {
            unset test_smooth($item)
        }
        foreach item [array names test_smooth fams_attr,0,*] { 
            unset test_smooth($item)
        }
        foreach item $attr {
            set var [lindex $item 0]
            set val [lindex $item 1]
            set test_smooth($var) $val
        }
        hexSmoothDEZ set layer_distance_settings $attr
    }
}

proc aie_hex_add_or_remove {} {
    global hexa_sel
    if {$hexa_sel == "remove"} {
        return remove
    } else {
        return add
    }
}

proc aie_hex_init_multiblock_selections {} {
    global smooth_multi_block
   
    hexSmoothDEZ set refEdge ""
    hexSmoothDEZ set refEdgeDir ""
    set smooth_multi_block(ijkBlock) ""
    hexSmoothDEZ set NonRelaxFaces ""
    set smooth_multi_block(NonRelaxFaces,save) ""
    hexSmoothDEZ set HoldCellHeightFaces ""
    set smooth_multi_block(HoldCellHeightFaces,save) ""
    foreach type {NonRelaxFaces HoldCellHeightFaces} {       
        aie_hex_face_picking_finished_all "" $type
        hexSmoothDEZ set $type $smooth_multi_block($type,0)
    }
    hexSmoothDEZ set GlobalVertices ""
    hexSmoothDEZ set LayerVertices ""
    set smooth_multi_block(GlobalVertices) ""
    set smooth_multi_block(GlobalVertices,save) ""
    set smooth_multi_block(LayerVertices) ""
    set smooth_multi_block(LayerVertices,save) ""
    foreach item [array names smooth_multi_block layer_distance,*] {
        unset smooth_multi_block($item)
    }
}

proc onsmoothRelaxBlockPickPick {} {
    global smooth_multi_block

    set smooth_multi_block(RelaxBlocks,save) $smooth_multi_block(SelectedBlocks)
    hex_command "unblank_blocks"
    after 1 {
        if {[aie_hex_add_or_remove] == "remove"} {
            set ::use_banner "Unselect Relaxation blocks with the left button, middle = done,\
                              right = back up/cancel, '?' = list options."
            if {$smooth_multi_block(UnselectedBlocks) != ""} {
                hex_command "mark_blocks unmark"               
                block_mark_super $smooth_multi_block(UnselectedBlocks)
                hex_command "blank_blocks marked"
            }
            if {$smooth_multi_block(SelectedBlocks) != ""} {
                aie_hex_multiblock_display_blocks 1
            }
        }
    }
}

proc onsmoothRelaxBlockPickFinish {} {
    global smooth_multi_block use_output_blocks

    if {$RelaxBlocks == ""} {
        set smooth_multi_block(SelectedBlocks) $smooth_multi_block(RelaxBlocks,save)
        set RelaxBlocks $smooth_multi_block(SelectedBlocks)
        aie_hex_relaxblocks_update
        aie_hex_multiblock_display_selections
        return
    }
    if {[aie_hex_add_or_remove] == "add"} {
        set relax $smooth_multi_block(RelaxBlocks,save)
        foreach b $RelaxBlocks {
            if {[lsearch "$smooth_multi_block(RelaxBlocks,save)" $b] == -1} {
               lappend relax $b
            }
        }
    } else {
        set relax ""
        foreach b $smooth_multi_block(RelaxBlocks,save) {
            if {[lsearch "$RelaxBlocks" $b] == -1} {
               lappend relax $b
            }
        }
    }
   
    set smooth_multi_block(SelectedBlocks) [lsort -dictionary $relax]
    set RelaxBlocks $smooth_multi_block(SelectedBlocks)
   
    set non_relax ""
    for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
        if {[lsearch $smooth_multi_block(SelectedBlocks) $i] < 0} {
            lappend non_relax $i
        }
    }
    set smooth_multi_block(UnselectedBlocks) [lsort -dictionary $non_relax]
    if {$smooth_multi_block(SelectedBlocks) == ""} {
        aie_hex_init_multiblock_selections
    }
    aie_hex_relaxblocks_update
    aie_hex_multiblock_display_selections
}

proc onsmoothEdgeDirPickPick {} {
    global smooth_multi_block use_output_blocks
   
    if {$smooth_multi_block(SelectedBlocks) == ""} return

    hex_command "unblank_blocks"
    hexSmoothDEZ set display_faces_off 1
    aie_hex_multiblock_display_faces
    after 1 {
        if {$smooth_multi_block(SelectedBlocks) != ""} {
            set blocks [lrange $smooth_multi_block(SelectedBlocks) 1 end]
            append blocks " $smooth_multi_block(UnselectedBlocks)"
            hex_command "mark_blocks unmark"
            block_mark_super $blocks
            hex_command "blank_blocks marked"
            aie_hex_multiblock_display_blocks 1 1
        }
    }
}

proc onsmoothEdgeDirPickFinish {} {
    global smooth_multi_block use_output_blocks

    hex_command "unblank_blocks"
    hex_command "mark_blocks unmark"
    hexSmoothDEZ set display_faces_off 0
    aie_hex_multiblock_display_faces
    hex_update_display
    aie_hex_multiblock_display_selections
    if {$refEdge == "" || $RelaxBlocks == ""} {
        set refEdgeDir ""
        set smooth_multi_block(ijkBlock) ""
        ::AIEnv::GUIManagement::ToggleGrey smoothLayerframe 1
        return
    }
    set n1 [lindex $refEdge 0]
    set n2 [lindex $refEdge 1]
    if $use_output_blocks {
      set te [string trimright [ic_hex_topo_edge_number output_blocks $n1 $n2]\n]
    } else {
      set te [string trimright [ic_hex_topo_edge_number $n1 $n2]\n]
    }
    set block_num [lindex $smooth_multi_block(SelectedBlocks) end]
    catch { unset min; unset max }
    foreach ijk [string trimright [ic_hex_edge_ijk $te]\n] {
        set use_block [lindex $ijk 0]
        if {[lsearch $smooth_multi_block(SelectedBlocks) $use_block] < 0} continue
        set use_min [lrange $ijk 1 3]
        set use_max [lrange $ijk 4 6]
        if {$use_block <= $block_num} {
            set block_num $use_block
            set min $use_min
            set max $use_max
        }
    }

    if {![info exists min] || $block_num != [lindex $smooth_multi_block(SelectedBlocks) 0]} {
        mess "Unable to get the smoothing direction. Please select an edge which belongs to the\
              highlighted block\n" red
        set refEdge ""
        set refEdgeDir ""
        set smooth_multi_block(ijkBlock) ""
        ::AIEnv::GUIManagement::ToggleGrey smoothLayerframe 1
        return
    }
    set min_i [lindex $min 0]; set max_i [lindex $max 0]
    set min_j [lindex $min 1]; set max_j [lindex $max 1]
    set min_k [lindex $min 2]; set max_k [lindex $max 2]
    if {$min_i != $max_i && $min_j == $max_j && $min_k == $max_k} {
        set refEdgeDir I
    } elseif {$min_i == $max_i && $min_j != $max_j && $min_k == $max_k} {
        set refEdgeDir J
    } elseif {$min_i == $max_i && $min_j == $max_j && $min_k != $max_k} {
        set refEdgeDir K
    } else {
       mess "Unable to get the smoothing direction\n" red
       set refEdge ""
       set refEdgeDir ""
       set smooth_multi_block(ijkBlock) ""
       ::AIEnv::GUIManagement::ToggleGrey smoothLayerframe 1
       return
    }
    ::AIEnv::GUIManagement::ToggleGrey smoothLayerframe 0
    set smooth_multi_block(ijkBlock) [list $min $max]
    mess "Smoothing direction: $refEdgeDir\n" blue
    aie_hex_trace_choose_direction
}

proc onsmoothNonRelaxFacePickPick {} {
    global smooth_multi_block
    aie_hex_multiblock_display_faces 1
    set smooth_multi_block(NonRelaxFaces,save) $NonRelaxFaces
    aie_hex_multiblock_display_blocks 0
    after 1 {
        if {[aie_hex_add_or_remove] == "remove"} {
            set ::use_banner "Unselect Non-Relaxtion faces with the left button, middle = done,\
                              right = back up/cancel, '?' = list options."
        }
    }
}

proc onsmoothNonRelaxFacePickFinish {} {
    global smooth_multi_block

    if ![info exists NonRelaxFaces] {
        set NonRelaxFaces [hexSmoothDEZ get NonRelaxFaces]
        set smoothFilterNonRelax [hexSmoothDEZ get smoothFilterNonRelax]
        set smooth_multi_block(NonRelaxFaces,save) $NonRelaxFaces
    }
    if {$NonRelaxFaces == ""} {
        set NonRelaxFaces $smooth_multi_block(NonRelaxFaces,save)       
        aie_hex_multiblock_display_selections
        return
    }
    set periodic ""
    if {[aie_hex_add_or_remove] == "add"} {
        set non_relax $smooth_multi_block(NonRelaxFaces,save)
        foreach f $NonRelaxFaces {
            if {[lsearch "$smooth_multi_block(NonRelaxFaces,save)" $f] == -1} {
               if {[lsearch "$smooth_multi_block(PeriodicFaces)" $f] >= 0 && $NonRelaxRemove} {
                   lappend periodic $f
               } else {
                   lappend non_relax $f
               }
            }
        }
    } else {
        set non_relax ""
        foreach f $smooth_multi_block(NonRelaxFaces,save) {
            if {[lsearch "$NonRelaxFaces" $f] == -1} {
               lappend non_relax $f
            }
        }
    }
    if {$periodic != ""} {
        mess "Removed [llength $periodic] periodic faces from selection\n"
    }   
    set NonRelaxFaces $non_relax
    if ![hexSmoothDEZ get smoothFilterNonRelax] {
        set skip 1
    } else {
        set skip 0
    }   
    aie_hex_face_picking_finished_all $NonRelaxFaces NonRelaxFaces $skip
    set NonRelaxFaces $smooth_multi_block(NonRelaxFaces,0)
    aie_hex_multiblock_display_selections
}

proc onsmoothNonRelaxFacePickFilter {} {
    aie_hex_multiblock_display_selections
}

proc onsmoothHoldCellHeightFacePickPick {} {
    global smooth_multi_block
    aie_hex_multiblock_display_faces 1
    set smooth_multi_block(HoldCellHeightFaces,save) $HoldCellHeightFaces
    aie_hex_multiblock_display_blocks 0
    after 1 {
        if {[aie_hex_add_or_remove] == "remove"} {
            set ::use_banner "Unselect Hold Cell Height faces with the left button, middle = done,\
                              right = back up/cancel, '?' = list options."
        }
    }
}

proc onsmoothHoldCellHeightFacePickFinish {} {
    global smooth_multi_block

    if ![info exists HoldCellHeightFaces] {
        set HoldCellHeightFaces [hexSmoothDEZ get HoldCellHeightFaces]
        set smoothFilterHoldCellHeight [hexSmoothDEZ get smoothFilterHoldCellHeight]
        set smooth_multi_block(HoldCellHeightFaces,save) $HoldCellHeightFaces
    }
    if {$HoldCellHeightFaces == ""} {
        set HoldCellHeightFaces $smooth_multi_block(HoldCellHeightFaces,save)
        aie_hex_multiblock_display_selections
        return
    }
    set periodic ""
    if {[aie_hex_add_or_remove] == "add"} {
        set hold $smooth_multi_block(HoldCellHeightFaces,save)
        foreach f $HoldCellHeightFaces {
            if {[lsearch "$smooth_multi_block(HoldCellHeightFaces,save)" $f] == -1} {
               if {[lsearch "$smooth_multi_block(PeriodicFaces)" $f] >= 0 && $HoldCellHeightRemove} {
                   lappend periodic $f
               } else {
                   lappend hold $f
               }
            }
        }
    } else {   
        set hold ""
        foreach f $smooth_multi_block(HoldCellHeightFaces,save) {
            if {[lsearch "$HoldCellHeightFaces" $f] == -1} {
               lappend hold $f
            }
        }
    }
    if {$periodic != ""} {
        mess "Removed [llength $periodic] periodic faces from selection\n"
    }
    set HoldCellHeightFaces $hold
    if ![hexSmoothDEZ get smoothFilterHoldCellHeight] {
        set skip 1
    } else {
        set skip 0
    }
    aie_hex_face_picking_finished_all $HoldCellHeightFaces HoldCellHeightFaces $skip
    set HoldCellHeightFaces $smooth_multi_block(HoldCellHeightFaces,0)
    aie_hex_multiblock_display_selections
}

proc onsmoothHoldCellHeightFacePickFilter {} {
    aie_hex_multiblock_display_selections
}

proc onsmoothGlobalVertPickPick {} {
    global smooth_multi_block
    set smooth_multi_block(GlobalVertices,save) $GlobalVertices
    aie_hex_multiblock_display_blocks 0
    after 1 {
        if {[aie_hex_add_or_remove] == "remove"} {
            set ::use_banner "Unselect global vertices with the left button, middle = done,\
                              right = back up/cancel, '?' = list options."
        }
    }
}

proc onsmoothGlobalVertPickFinish {} {
    global smooth_multi_block
   
    if {$GlobalVertices == ""} {
        set GlobalVertices $smooth_multi_block(GlobalVertices,save)
        aie_hex_multiblock_display_selections
        return
    }
    set vertices ""; set non_block ""
    if {[aie_hex_add_or_remove] == "add"} {
        foreach n $GlobalVertices {
            if {[lsearch "$smooth_multi_block(GlobalVertices,save)" $n] == -1} {
                if {[info exists smooth_multi_block(vertexBlock,$n)] && $smooth_multi_block(vertexBlock,$n)} {
                    append vertices "$n "
                } else {
                    append non_block "$n "
                }
            }
        }
        foreach n $smooth_multi_block(GlobalVertices,save) {
            if {[lsearch "$vertices" $n] >= 0} continue
            append vertices "$n "
        }
    } else {
        foreach n $smooth_multi_block(GlobalVertices,save) {
            if {[lsearch "$GlobalVertices" $n] >= 0} continue
            append vertices "$n "
        }
    }
   
    set GlobalVertices [lsort -integer $vertices]
    set smooth_multi_block(GlobalVertices) $GlobalVertices
    if {$non_block != ""} {
        mess "Removed [llength $non_block] non-blockinterfaces vert(s) from selection\n"
    }
    aie_hex_multiblock_display_selections
}

proc onsmoothLayerVertPickPick {} {
    global smooth_multi_block
    set smooth_multi_block(LayerVertices,save) $LayerVertices
    aie_hex_multiblock_display_blocks 0
    after 1 {
        if {[aie_hex_add_or_remove] == "remove"} {
            set ::use_banner "Unselect layer vertices with the left button, middle = done,\
                              right = back up/cancel, '?' = list options."
        }
    }
}

proc onsmoothLayerVertPickFinish {} {   
     global smooth_multi_block
    
    set vertices ""
    if {$LayerVertices == ""} {
        set LayerVertices $smooth_multi_block(LayerVertices,save)
        aie_hex_multiblock_display_selections
        return
    }
   
    if {[aie_hex_add_or_remove] == "add"} {
        foreach n $LayerVertices {
            if {[lsearch "$smooth_multi_block(LayerVertices,save)" $n] == -1} {
                append vertices "$n "
            }
        }
        foreach n $smooth_multi_block(LayerVertices,save) {
            if {[lsearch "$vertices" $n] >= 0} continue
            append vertices "$n "
        }
    } else {
        foreach n $smooth_multi_block(LayerVertices,save) {
            if {[lsearch "$LayerVertices" $n] >= 0} continue
            append vertices "$n "
        }
    }
   
    set LayerVertices [lsort -integer $vertices]
    set smooth_multi_block(LayerVertices) $LayerVertices
   
    if {[aie_hex_add_or_remove] == "add" && $LayerVertices != ""}  {
        set value [aie_hex_set_selected_first_layer_distance $LayerVertices]
        foreach item $LayerVertices {
            set smooth_multi_block(layer_distance,$item) $value
        }
    } elseif {[aie_hex_add_or_remove] == "remove" && $LayerVertices != ""} {
        foreach item [array names smooth_multi_block layer_distance,*] {
            set n [lindex [split $item ,] 1]
            if {[lsearch "$LayerVertices" $n] < 0} {
                unset smooth_multi_block(layer_distance,$n)
            }
        }
    }
    aie_hex_multiblock_display_selections  
}

proc aie_hex_face_picking_finished_all {picked type {skip 0}} {
    global smooth_multi_block use_output_blocks
  
    if {$picked == ""} {
        foreach idx {0 1 2} {
            set smooth_multi_block($type,$idx) ""
            set smooth_multi_block($type,topo_nums,$idx) ""
        }
        return
    }
    busy 1
    if !$skip {
        set active_faces ""
        foreach face $picked {
            set n1 [lindex $face 0]; set n2 [lindex $face 1]; set n3 [lindex $face 2]; set n4 [lindex $face 3]
            if $use_output_blocks {
                 if ![info exists smooth_multi_block(TopoFaceNum,$face)] {
                     set blocks [string trimright [ic_hex_get_face_blocks output_blocks $n1 $n2 $n3 $n4] \n]
                 } else {
                     set n $smooth_multi_block(TopoFaceNum,$face)
                     set blocks $smooth_multi_block(blockFaces,$n)
                 }
            } else {
                set blocks [string trimright [ic_hex_get_face_blocks $n1 $n2 $n3 $n4] \n]
            }
            foreach b $blocks {
                if {[lsearch "$smooth_multi_block(SelectedBlocks)" "$b"] >= 0} {
                    if {[lsearch "$active_faces" "$face"] < 0} {
                        lappend active_faces $face
                    }
                }
            }
        }
        set picked $active_faces
    }

    set ret_all ""
    set ret_isBlock ""
    set ret_isBound ""
    set topo_nums_all ""
    set topo_nums_isBlock ""
    set topo_nums_isBound ""
    set faces ""; set used ""
    foreach n $picked {
        if [info exists smooth_multi_block(TopoFaceNum,$n)] {
            lappend ret_all $n
            lappend topo_nums_all $smooth_multi_block(TopoFaceNum,$n)
            if {[lsearch "$smooth_multi_block(isBlock)" $smooth_multi_block(TopoFaceNum,$n)] >= 0} {
                lappend ret_isBlock $n
                lappend topo_nums_isBlock $smooth_multi_block(TopoFaceNum,$n)
            } elseif {[lsearch "$smooth_multi_block(isBound)" $smooth_multi_block(TopoFaceNum,$n)] >= 0} {
                lappend ret_isBound $n
                lappend topo_nums_isBound $smooth_multi_block(TopoFaceNum,$n)
            }
            continue
        }    
        set n1 [lindex $n 0]
        set n2 [lindex $n end]
        append faces "$n1 $n2 "
        lappend used $n
    }

    set topo_numbers ""
    if {$faces != ""} {
        if $use_output_blocks {
            set topo_numbers [string trimright [ic_hex_topo_face_number_list output_blocks "$faces"] \n]
        } else {
            set topo_numbers [string trimright [ic_hex_topo_face_number_list "$faces"] \n]
        }
    }
    set idx 0
    foreach topo_num [lindex $topo_numbers 0] {
        lappend ret_all [lindex $used $idx]
        lappend topo_nums_all $topo_num
        set smooth_multi_block(TopoFaceNum,[lindex $used $idx]) $topo_num
        if {[lsearch "$smooth_multi_block(isBlock)" $topo_num] >= 0} {
            lappend ret_isBlock [lindex $used $idx]
            lappend topo_nums_isBlock $topo_num
        } elseif {[lsearch "$smooth_multi_block(isBound)" $topo_num] >= 0} {
            lappend ret_isBound [lindex $used $idx]
            lappend topo_nums_isBound $topo_num
        }
        incr idx
    }
    set smooth_multi_block($type,0) $ret_all
    set smooth_multi_block($type,topo_nums,0) [lsort -dictionary $topo_nums_all]
    set smooth_multi_block($type,1) $ret_isBlock
    set smooth_multi_block($type,topo_nums,1) [lsort -dictionary $topo_nums_isBlock]
    set smooth_multi_block($type,2) $ret_isBound
    set smooth_multi_block($type,topo_nums,2) [lsort -dictionary $topo_nums_isBound]
    busy 0
}

proc aie_hex_set_first_layer_distance {} {
    global smooth_multi_block
   
    if [winfo exists .multiblock_layer_distance] { form_delete .multiblock_layer_distance }  
    set buttons {
      {accept}
      {cancel}
    }
    set LayerVertices [hexSmoothDEZ get LayerVertices]
    if {$LayerVertices == ""} {
        mess "No vert(s) selected.\n"
        return ""
    }
    set i 0
    set w [form_init .multiblock_layer_distance "Initial Height" "" $buttons]
    if {$w != ""} {
	form_label $w.name " Vertex #  /  Layer Distance" "$i 0"
	set sw [form_scroller $w.stuff 300 "1 0"]
	foreach item $LayerVertices {
	    form_label $sw.name$i "$item" "$i 0"; $sw.name$i configure -width 8
	    form_entry $sw.value$i smooth_multi_block(layer_distance,$item) float "$i 1" ""
	    if ![info exists smooth_multi_block(layer_distance,$item)] {
	        set smooth_multi_block(layer_distance,$item) -1
	    }
	    incr i
	}
	form_finish +200+200
    }
    form_scroller_hack $w.stuff
    if [form_wait .multiblock_layer_distance] {
        set layer_distance ""
        foreach item $LayerVertices {
            append layer_distance "$item $smooth_multi_block(layer_distance,$item) "
        }
        return $layer_distance
    } else {
        return ""
    }
}

proc aie_hex_set_selected_first_layer_distance {selected} {
    global smooth_multi_block
   
    if [winfo exists .multiblock_layer_distance] { form_delete .multiblock_layer_distance }  
    set buttons {
      {accept}
      {cancel}
    }
    if {$selected == ""} {
        mess "No vert(s) selected.\n"
        return ""
    }
    set w [form_init .multiblock_layer_distance "Initial Height" "" $buttons]
    if {$w != ""} {
	form_label $w.name "Layer Distance" "0 0"
	form_entry $w.value smooth_multi_block(selected_layer_distance) float "0 1" ""
	if ![info exists smooth_multi_block(selected_layer_distance)] {
	    set smooth_multi_block(selected_layer_distance) -1
	}
	form_finish +200+200
    }
    if [form_wait .multiblock_layer_distance] {
        return $smooth_multi_block(selected_layer_distance)
    } else {
        return -1
    }
}

proc aie_hex_multiblock_display_faces {{show_only_icons 0}} {
    global smooth_multi_block use_output_blocks

    if ![ic_hex_blocking_loaded] return
   
    set non_relax ""; set hold_cell ""; set both ""
    set cmd "display_super_faces [range_string] [family_activename_string] erase_icon"
    hex_command "$cmd"
    if [hexSmoothDEZ get display_faces_off] return
    
    set idx [hexSmoothDEZ get smoothFilterNonRelax]
    if {[info exists smooth_multi_block(NonRelaxFaces,topo_nums,$idx)] && \
        $smooth_multi_block(NonRelaxFaces,topo_nums,$idx) != ""} {
        set non_relax $smooth_multi_block(NonRelaxFaces,topo_nums,$idx)
    }
    set idx [hexSmoothDEZ get smoothFilterHoldCellHeight]
    if {[info exists smooth_multi_block(HoldCellHeightFaces,topo_nums,$idx)] && \
        $smooth_multi_block(HoldCellHeightFaces,topo_nums,$idx) != ""} {
        set hold_cell $smooth_multi_block(HoldCellHeightFaces,topo_nums,$idx)
    }   
    set len_non_relax [llength $non_relax]
    set len_hold_cell [llength $hold_cell)]
    if {!$len_non_relax && !$len_hold_cell} return

    if {[hexSmoothDEZ get display_faces_icons] || $show_only_icons} {
         set use_face_display only_icons
    } else {
         set use_face_display show_full
    }
    
    if $len_non_relax {
        set topo_nums ""
        set color [aie_hex_multiblock_color_to_RGB $smooth_multi_block(Color,NonRelaxFaces)]
        foreach n $non_relax {
            if {[lsearch "$hold_cell" $n] >= 0} {
                append both "$n "
            } else {
                append topo_nums "$n "
            }
        }
        set len_topo_nums [llength $topo_nums]
        if $use_output_blocks {
            hex_command "display_super_faces [range_string] [family_activename_string] output_blocks \
                     color $color preselected_faces $len_topo_nums $topo_nums only_listed $use_face_display displ_num"
        } else {
            hex_command "display_super_faces [range_string] [family_activename_string] \
                     color $color preselected_faces $len_topo_nums $topo_nums only_listed $use_face_display displ_num"
        }
    }
    if $len_hold_cell {
        set topo_nums ""
        set color [aie_hex_multiblock_color_to_RGB $smooth_multi_block(Color,HoldCellHeightFaces)]  
        foreach n $hold_cell {
            if {[lsearch "$non_relax" $n] == -1} { append topo_nums "$n " }
        }
        set len_topo_nums [llength $topo_nums]
        if $use_output_blocks {
            hex_command "display_super_faces [range_string] [family_activename_string] output_blocks \
                     color $color preselected_faces $len_topo_nums $topo_nums only_listed $use_face_display displ_num"
        } else {
            hex_command "display_super_faces [range_string] [family_activename_string] \
                     color $color preselected_faces $len_topo_nums $topo_nums only_listed $use_face_display displ_num"
        }
    }

    if {$both != ""} {
        set len_both [llength $both]
        set color [aie_hex_multiblock_color_to_RGB $smooth_multi_block(Color,BothFaces)]
        if $use_output_blocks {
            hex_command "display_super_faces [range_string] [family_activename_string] output_blocks \
                     color $color preselected_faces $len_both $both only_listed $use_face_display displ_num" 
        } else {
            hex_command "display_super_faces [range_string] [family_activename_string] \
                     color $color preselected_faces $len_both $both only_listed $use_face_display displ_num"
        }
    }
}

proc aie_hex_multiblock_display_blocks {{solid 1} {ijk 0}} {
    global smooth_multi_block use_output_blocks display_flag

    if ![ic_hex_blocking_loaded] return
    if {[hexSmoothDEZ get display_blocks_off] && !$ijk} {
        hex_command "display_elements erase"
        return
    }
    hex_command "mark_blocks unmark"
    if {$smooth_multi_block(SelectedBlocks) != ""} {
        foreach block $smooth_multi_block(SelectedBlocks) {
	    set cmd "mark_blocks superblock $block"
	    if $use_output_blocks { append cmd " output_blocks" }
	    hex_command $cmd
        }
    }
    set opts "marked m [volume_activename_string] -not_blanked super_nums"
    if $use_output_blocks { append opts " output_blocks" }
    if $ijk { append opts " orientation" }
    if {$solid && ($display_flag(block_solid) || $ijk)} { append opts " -solid" }
    if $display_flag(block_super) { append opts " super" }
    hex_command "display_elements $opts"
}

proc aie_hex_multiblock_display_nodes {} {
    global smooth_multi_block aie_blockVertProj
   
    if ![ic_hex_blocking_loaded] return
    hex_command "display_nodes erase"
    if [hexSmoothDEZ get display_vertices_off] return
    
    set len_global [llength $smooth_multi_block(GlobalVertices)]
    set len_layer [llength $smooth_multi_block(LayerVertices)]
    if {!$len_global && !$len_layer} return
    
    catch { unset tmp }
    set nums ""
    if $len_global {
        foreach n $smooth_multi_block(GlobalVertices) {
            if ![info exists tmp($n)] {
                append nums "$n "
                set tmp($n) 1
            }
        }
    }
    if $len_layer {
        foreach n $smooth_multi_block(LayerVertices) {
            if ![info exists tmp($n)] {
                append nums "$n "
                set tmp($n) 1
            }
        }
    }
    if $aie_blockVertProj(number) {
        if {$nums != ""} {
            hex_command "display_nodes [range_string] [family_activename_string] number [join $nums]"
        }
    } else {
         hex_command "display_nodes [range_string] [family_activename_string]"
    }
}

proc aie_hex_multiblock_display_selections {} {   
    if ![ic_hex_blocking_loaded] return
    aie_hex_multiblock_display_nodes
    aie_hex_multiblock_display_faces
    aie_hex_multiblock_display_blocks
    hex_update_display mesh
}

proc aie_hex_multiblock_color_to_RGB {color} { 
  set display_color $color 
  if {[scan $display_color \#%2x%2x%2x r g b] == 3} {
    set display_color [format 0X%2.2x%2.2x%2.2x $b $g $r]
  }
  return $display_color
}

proc aie_hex_is_seleced_block {block} {
    global smooth_multi_block   
    if ![info exists smooth_multi_block(SelectedBlocks)] {
        return 0
    }  
    if {[lsearch "$smooth_multi_block(SelectedBlocks)" $block] >= 0} {
        return 1
    } else {
        return 0
    }
}

proc aie_hex_prepare_smooth_multi_block {{force_update 0}} {
    global smooth_multi_block use_output_blocks last_line
   
    if [info exists smooth_multi_block] { unset smooth_multi_block }
      
    set "smooth_multi_block(Thomas & Middlecoff)" 1
    set "smooth_multi_block(Laplace)" 2
    set "smooth_multi_block(Interpolation)" 4
    set "smooth_multi_block(Sorenson - Thomas & Middlecoff)" 6
    set "smooth_multi_block(Sorenson - Laplace)" 7
    set "smooth_multi_block(Hilgenstock - Laplace)" 9
    set "smooth_multi_block(Hilgenstock - Thomas & Middlecoff)" 10
    set smooth_multi_block(Color,NonRelaxFaces) yellow
    set smooth_multi_block(Color,HoldCellHeightFaces) blue
    set smooth_multi_block(Color,BothFaces) green
   
    busy 1; set res [aie_hex_prepare_get_inf $force_update]; busy 0
    if {$res == "" } {
        set smooth_multi_block(feature_is_disabled) 1
        return
    } else {
        set smooth_multi_block(feature_is_disabled) 0
    }
    set smooth_multi_block(nBlocks) [lindex $res 0]
    set smooth_multi_block(nFaces)  [lindex $res 1]
    set smooth_multi_block(nEdges)  [lindex $res 2]
    set smooth_multi_block(nVert)   [lindex $res 3]
    set smooth_multi_block(nTwin)   [lindex $res 4]
    set smooth_multi_block(isBound) [lindex $res 5]
    set smooth_multi_block(isBlock) [lindex $res 6]
    set smooth_multi_block(fFaces)  [lindex $res 7]
    set smooth_multi_block(fEdges)  [lindex $res 8]
    set ijkBlock [lindex $res 9]
    set x 0; set y 1; set z 2; set min [list 1 1 1]
   
    set smooth_multi_block(ijkBlock) ""
    for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
        set max [list [lindex $ijkBlock $x] [lindex $ijkBlock $y] [lindex $ijkBlock $z]]
        set smooth_multi_block(ijkBlock,$i) [list $min $max]
        incr x 3; incr y 3; incr z 3
    }
    set facesBlocks [lindex $res 10]
    for {set i 0} {$i < $smooth_multi_block(nBlocks)} {incr i} {
        set block_no [expr $i + 1]
        set faces_no [lindex $facesBlocks $i]
        set smooth_multi_block(facesBlocks,$block_no) ""
        foreach {num dim} $faces_no {
            switch $dim {
                1 { set ijk imin }
                3 { set ijk jmin }
                5 { set ijk kmin }
                2 { set ijk imax }
                4 { set ijk jmax }
                6 { set ijk kmax }
            }
            lappend smooth_multi_block(facesBlocks,$block_no) [list $num $ijk]
            lappend smooth_multi_block(blockFaces,$num) $block_no
        }
    }
    set vertexEdges [lindex $res 11]  
    for {set i 0} {$i < [llength $vertexEdges]} {incr i} {
        set vertex_no [lindex [lindex $vertexEdges $i] 0]
        set is_block [lindex [lindex $vertexEdges $i] 1]
        set edges_no [lindex [lindex $vertexEdges $i] 2]
        set smooth_multi_block(vertexEdges,$vertex_no) $edges_no
        set smooth_multi_block(vertexBlock,$vertex_no) $is_block
    }
    foreach i [array names smooth_multi_block vertexEdges,*] {
        set vertex_no [lindex [split $i ,] 1]
        set edges_no $smooth_multi_block($i)
        foreach e $edges_no {
            if [info exists smooth_multi_block(vertexConnected,$e)] {
                if {[lsearch "$smooth_multi_block(vertexConnected,$e)" $vertex_no] == -1} {
                    append smooth_multi_block(vertexConnected,$e) "$vertex_no "
                }
            } else {
                set smooth_multi_block(vertexConnected,$e) "$vertex_no "
            }
        }
    }
   
    set faceFams [lindex $res 12]
    set smooth_multi_block(nameFamily,0) ORFN
    for {set i 0} {$i < [llength $faceFams]} {incr i} {
        set fam [lindex [lindex $faceFams $i] 0]
        set num [lindex [lindex $faceFams $i] 1]
        set smooth_multi_block(nameFamily,$num) $fam
    }
    for {set i 0} {$i < [llength $smooth_multi_block(fFaces)]} {incr i} {
        set num [lindex $smooth_multi_block(fFaces) $i]
        if ![info exists smooth_multi_block(nameFamily,$num)] continue
        set fam $smooth_multi_block(nameFamily,$num)
        set face_no [expr $i + 1]
        append smooth_multi_block(faceFamily,$fam) "$face_no "
    }
    
    foreach {fam dim} [hex_command "list_families dims"] {
        set smooth_multi_block(dimFamily,$fam) $dim
    }
    if $use_output_blocks {
        set faces [ic_hex_get_super_faces_topo output_blocks]
    } else {
        set faces [ic_hex_get_super_faces_topo]
    }
    foreach f $faces {
        set face " [lrange $f 0 3] "
        set smooth_multi_block(TopoFaceNum,$face) [lindex $f 4]
    } 
    for {set i 1} {$i <= $smooth_multi_block(nBlocks)} {incr i} {
        if $use_output_blocks {
            set p [string trimright [ic_hex_get_block_family $i output_blocks] \n]
        } else {
            set p [string trimright [ic_hex_get_block_family $i] \n]
        }
        lappend smooth_multi_block(VolumeBlockParts,$p) $i
    }  
    return 1
}

proc aie_hex_prepare_get_inf {{force_update 0}} {
    global project_type use_output_blocks is_output_blocks

#    set fams [family_activename_string]
#    if {$fams == ""} { set fams [join [ic_hex_list_families]] }
    set fams [join [ic_hex_list_families]]
    if $use_output_blocks {
        set args "families \"$fams\" output_blocks proj $project_type"
    } else {
        set args "families \"$fams\" proj $project_type"
    }
    append args " prepare"
    if {$force_update} { append args " force_update" }
    if [catch {eval ic_hex_global_smooth $args} res] { return "" }
    set args "get_inf"
    if $use_output_blocks { append args " output_blocks" }
    if [catch {eval ic_hex_global_smooth $args} res] { return "" }
    set nBlocks [lindex $res 0]
    set nFaces  [lindex $res 1]
    set nEdges  [lindex $res 2]
    set nVert   [lindex $res 3]
    set nTwin   [lindex $res 4]
    set isBound [lindex $res 5]
    set isBlock [lindex $res 6]
    set fFaces  [lindex $res 7]
    set fEdges  [lindex $res 8]
    set ijkBlock [lindex $res 9]
    set facesBlocks [lindex $res 10]
    set vertexEdges [lindex $res 11]
    set faceFams [lindex $res 12]
    return [list $nBlocks $nFaces $nEdges $nVert $nTwin $isBound $isBlock \
                 $fFaces $fEdges $ijkBlock $facesBlocks $vertexEdges $faceFams]
}


proc aie_hex_convert_multiblock_settings {{only_temp 0}} {
    global smooth_multi_block use_output_blocks

    set load_file [hexSmoothDEZ get mbs_setting_old]
    if {$load_file == ""} return
    set save_file [hexSmoothDEZ get mbs_setting_new]
    if {$save_file == ""} return
   
    foreach n [array names convert_multi_block] { unset convert_multi_block($n) }
    foreach n [array names convert_multi_block2] { unset convert_multi_block2($n) } 
      
    hex_command "display_super_faces [range_string] [family_activename_string] erase_icon"
    hex_command "display_nodes erase"
    hex_command "mark_blocks unmark"
    hex_command "unblank_blocks"
   
    busy 1
    set f [open $load_file r]
    while {![eof $f]} {
        set line [gets $f]
        switch $line {
            SmoothDomain: {
                set smooth_multi_block(SelectedBlocks) ""
                set smooth_multi_block(UnselectedBlocks) ""
                set blocks [gets $f]
                if {[llength $blocks] > $smooth_multi_block(nBlocks)} {
                    mess "Error: The number of blocks from the settings file is different from the\
                          number of blocks from the blocking file.  Maybe you must set the pre-mesh option\
                          \"Output Blocks\" before you use this converter\n" red
                    busy reset
                    close $f
                    return
                }
                set smooth_multi_block(nBlocks) [llength $blocks]
                for {set i 0} {$i < $smooth_multi_block(nBlocks)} {incr i} {
                    set n [expr $i + 1]
                    if [lindex $blocks $i] {
                        append smooth_multi_block(SelectedBlocks) "$n "
                    } else {
                        append smooth_multi_block(UnselectedBlocks) "$n "
                    }
                }
                set smooth_multi_block(RelaxBlocks,save) $smooth_multi_block(SelectedBlocks)
                set convert_multi_block(RelaxBlocks) $smooth_multi_block(SelectedBlocks)
            }
            FaceMethods: {
                set line [gets $f]
                set convert_multi_block(face_method) ""
                switch [lindex $line 0] {
                    1 { set face_method "Thomas & Middlecoff" }
                    2 { set face_method "Laplace" }
                    4 { set face_method "Interpolation" }
                    6 { set face_method "Sorenson - Thomas & Middlecoff" }
                    7 { set face_method "Sorenson - Laplace" }
                    9 { set face_method "Hilgenstock - Laplace" }
                    10 { set face_method "Hilgenstock - Thomas & Middlecoff" }
                    default { set face_method "Sorenson - Laplace" }
                }
                set convert_multi_block(face_method) $face_method
            }
            Param2D:  {
                set len [gets $f]
                for {set i 0} {$i < $len} {incr i} {
                    set dummy [gets $f]
                }
            } 
            VolumeMethods:  {
                set line [gets $f]
                set convert_multi_block(volume_method) ""
                switch [lindex $line 0] {
                    1 { set volume_method "Thomas & Middlecoff" }
                    2 { set volume_method "Laplace" }
                    4 { set volume_method "Interpolation" }
                    6 { set volume_method "Sorenson - Thomas & Middlecoff" }
                    7 { set volume_method "Sorenson - Laplace" }
                    9 { set volume_method "Hilgenstock - Laplace" }
                    10 { set volume_method "Hilgenstock - Thomas & Middlecoff" }
                    default { set volume_method "Sorenson - Laplace" }
                }
                set convert_multi_block(volume_method) $volume_method
            } 
            Param3D:  {
                set len [gets $f]
                for {set i 0} {$i < $len} {incr i} {
                    set dummy [gets $f]
                }
            }
            EdgeAttr:  {
                set dummy [gets $f]
            }
            RelaxSubface: {
                set line [gets $f]
                set smooth_multi_block(NonRelaxFaces,topo_nums,0) ""
                foreach {num relax} $line {
                    if !$relax {
                       append smooth_multi_block(NonRelaxFaces,topo_nums,0) "$num "
                    }
                }
            }
            LayerExtensionNo: {
                set dummy [gets $f]
            }
            RelaxZone: {
                set dummy_later [gets $f]
            }
            ViolGeomZone: {
                set dummy [gets $f]
            }
            LayerExtensionIJK: {
                set dummy [gets $f]
            }
            Region: {
                set dummy [gets $f]
            }
            ViolGeomSubface: {
                set dummy [gets $f]
            }
            MeshingLawPar: {
                set dummy [gets $f]
                set dummy [gets $f]
            }
            first_cell_height: {
               set dummy [gets $f]
            }
            last_cell_height: {
                set dummy [gets $f]
            }     
            Niter: {
                set dummy [gets $f]
            }
            Nsteps: {
                set dummy [gets $f]
            }
            Maxlevel: {
                set dummy [gets $f]
            }
            Sfit: {
                set convert_multi_block(parameterFaceFit) [gets $f]
            }
            Conditional: {
                set dummy [gets $f]
            }
            CheckDet: {
                set dummy [gets $f]
            }
            Damping: {
               set dummy [gets $f]
            }
            VertexFix: {
                set dummy [gets $f]
            }
            EdgeFreeze: {
                set dummy [gets $f]
            }
            WedgeCheck: {
                set dummy [gets $f]
            }
            Multigrid2D: {
                set dummy [gets $f]
            }
            ReducedEdge: {
                set dummy [gets $f]
            }
            FixFam: {
                set dummy [gets $f]
            }
            InnVol: {
                set dummy [gets $f]
            }
            NsRel: {
                set dummy [gets $f]
            }
            AngleFreezeEdges: {
                set dummy [gets $f]
            }
            nItera: {
                set convert_multi_block(itersEdges) [gets $f]
            }
            ProjLimit: {
                set convert_multi_block(parameterPrjLim) [gets $f]
            }
            InterpolateFaces: {
                set dummy [gets $f]
            }
            InterpolateVolumes: {
                set dummy [gets $f]
            }
            ThresholdDet: {
                set dummy [gets $f]
            }
            ThresholdAngle: {
                set dummy [gets $f]
            }
            SubfaceExtend: {
                set dummy [gets $f]
            }
            DirectionVector: {
                set dummy [gets $f]
            }
            BaseSubfacesNo: {
                set dummy [gets $f]
            }
            SmoothDir: {
                set smooth_multi_block(smoothDirection) [lindex [gets $f] 0]
            }
            PlaneSmooth: {
                set dummy_later [gets $f]
            }
            relax_weights_2d: {
                set dummy [gets $f]
            }
            relax_weights_3d: {
                set relax_weights_3d [gets $f]
                set topo_nums ""
                catch {unset faces_inf}
                set i 0
                foreach {aa bb cc dd ee ff} $relax_weights_3d {
                    set block_num [expr $i + 1]
                    foreach n {imin imax jmin jmax kmin kmax} {
                        set faces_inf($n) ""
                    }   
                    foreach n $smooth_multi_block(facesBlocks,$block_num) {
                        set num [lindex $n 0]
                        set ijk [lindex $n 1]
                        if {[lsearch "$smooth_multi_block(isBlock)" $num] >= 0} {
                            lappend faces_inf($ijk) $n
                        }
                    }
                    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 }
                    if {$aa >= 1.0} {
                        foreach n $faces_inf(imin) {
                            set num [lindex $n 0]
                            if {[lsearch "$topo_nums" $num] == -1} {
                               append topo_nums "$num "
                            }
                        }
                    }
                    if {$bb >= 1.0} {
                        foreach n $faces_inf(imax) {
                            set num [lindex $n 0]
                            if {[lsearch "$topo_nums" $num] == -1} {
                                append topo_nums "$num "
                            }
                        }                      
                    }
                    if {$cc >= 1.0} {
                        foreach n $faces_inf(jmin) {
                            set num [lindex $n 0]
                            if {[lsearch "$topo_nums" $num] == -1} {
                                append topo_nums "$num "
                            }
                        }
                    }
                    if {$dd >= 1.0} {
                        foreach n $faces_inf(jmax) {
                            set num [lindex $n 0]
                            if {[lsearch "$topo_nums" $num] == -1} {
                                append topo_nums "$num "
                            }
                        }
                    }
                    if {$ee >= 1.0} {
                        foreach n $faces_inf(kmin) {
                            set num [lindex $n 0]
                            if {[lsearch "$topo_nums" $num] == -1} {
                                append topo_nums "$num "
                            }
                        }
                    }
                    if {$ff >= 1.0} {
                        foreach n $faces_inf(kmax) {
                            set num [lindex $n 0]
                            if {[lsearch "$topo_nums" $num] == -1} {
                                append topo_nums "$num "
                            }
                        }
                    }
                    incr i
                }
                set hold_cell ""
                foreach n $topo_nums {
                    if {[lsearch "$smooth_multi_block(NonRelaxFaces,topo_nums,0)" $n] >= 0} {
                        append hold_cell "$n "
                    }
                }
                set smooth_multi_block(HoldCellHeightFaces,topo_nums,0) [lsort -integer $hold_cell]
            }
            relax_weights_3d_surfaces: {
                set line [gets $f]
                if {$line != ""} {
                    set smooth_multi_block(HoldCellHeightFaces,topo_nums,0) [lsort -integer $line]
                }
            }         
            relax_weights_inner_2d: {
                set dummy [gets $f]
            }
            relax_weights_inner_3d: {
                set dummy [gets $f]
            }
            SmoothOnFaces: {
                set convert_multi_block(parameterUseProj) [gets $f]
            }
            MinResidual: {
                set dummy [gets $f]
            }      
            StopResidual: {
                set convert_multi_block(parameterResFac) [gets $f]
            }  
            UnselectedMethods: {
                set dummy [gets $f]
            }
            ParamUnselected: {
                set dummy [gets $f]
            }
            varUnselDom:  {
                set dummy [gets $f]
            }
            etmEdgeGlobal: {
                set dummy_later [gets $f]
            }
            mesh_type: {
                set dummy_later [gets $f]
            }
            n_iter_glb: {
                set convert_multi_block(itersEdges) [gets $f]
            }
            n_steps_glb: {
                set convert_multi_block(itersVertices) [gets $f]
            }
            etmVertexGlobal: {
                set convert_multi_block2(GlobalVertices) [gets $f]
            }
            PlaneNumbers: {
                set line [gets $f]
                set num [lindex $line 0]
                for {set i 1} {$i <= $num} {incr i} {
                    append convert_multi_block(planeNums) "[lindex $line $i] "
                }
            }
            grid_exp_face: {
                set convert_multi_block(gridexpansionFace) [gets $f]
            }
            grid_exp_vol: {
                set convert_multi_block(gridexpansionVol) [gets $f]
            }
            GroupBadElem: {
                set dummy [gets $f]
            }
            TypeImprove: {
                set dummy [gets $f]
            }
            TypePostSm: {
                set dummy [gets $f]
            }
            prog_select: {
                set dummy [gets $f]
            }
            abs_dist_bnd: {
                set dummy [gets $f]
            }
            n_points_abs_dist_bnd: {
                set dummy [gets $f]
            }
            abs_dist_subf: {
                set dummy_later [gets $f]
            }
            n_abs_dist_subf: {
                set dummy_later [gets $f]
            }
            VertexLayer: {
                set line [gets $f]
                foreach n $line {
                    append convert_multi_block2(LayerVertices) "[lindex $n 0] "
                    set convert_multi_block2(layer_distance,[lindex $n 0]) [lindex $n 1]
                }
            }
            etmEdgeGlobalSave: {
                set convert_multi_block2(EdgeGlobal) [gets $f]
            }
            relaxation_factor: {
                set convert_multi_block(parameterRelFac) [gets $f]
            }
            use_orthog_position: {
                set convert_multi_block(parameterUseOrt) [gets $f]
            }
            use_fract_position: {
                set convert_multi_block(parameterUseFra) [gets $f]
            }
            grid_exp_rate_subf_perp: {
                set dummy_later [gets $f]
            }
            grid_exp_rate_subf_perp_surfaces: {         
                set dummy [gets $f]
            }
            grid_exp_rate_subf_1: {
                set dummy [gets $f]
            }
            grid_exp_rate_subf_1_surfaces: {
                set dummy [gets $f]
            }
        }
    }
    close $f
   
    foreach n [array names convert_multi_block] {
        hexSmoothDEZ set $n $convert_multi_block($n)
    }
   
    set all_existing [lsort -integer [hex_command "select_nodes 1 all [range_string] m [volume_activename_string] node_numbers"]]
    
    set vertices ""
    if [info exists convert_multi_block2(GlobalVertices)] {
        foreach i $all_existing {
            set num [string trimright [ic_hex_topo_vertex_number $i] \n]
            if {[lsearch "$convert_multi_block2(GlobalVertices)" $num] >= 0} {
                if {[lsearch $vertices $i] < 0} {
                    append vertices "$i "
                }
            }
        }
    }

    set smooth_multi_block(GlobalVertices) [lsort -integer $vertices]
    hexSmoothDEZ set GlobalVertices $smooth_multi_block(GlobalVertices)
   
    set vertices ""    
    foreach n [array names smooth_multi_block layer_distance,*] { unset smooth_multi_block($n) }
    if [info exists convert_multi_block2(LayerVertices)] {
        foreach i $all_existing {
            set num [string trimright [ic_hex_topo_vertex_number $i] \n]
            if {[lsearch "$convert_multi_block2(LayerVertices)" $num] >= 0} {
                append vertices "$i "
                set smooth_multi_block(layer_distance,$i) $convert_multi_block2(layer_distance,$num)
            }
        }
    }


    set smooth_multi_block(LayerVertices) [lsort -integer $vertices]
    hexSmoothDEZ set LayerVertices $smooth_multi_block(LayerVertices)
 
    hexSmoothDEZ set refEdge ""
    hexSmoothDEZ set refEdgeDir ""
    set smooth_multi_block(ijkBlock) ""
    if {$smooth_multi_block(smoothDirection) != 0} {
        hexSmoothDEZ set refEdgeDir [lindex {I J K } [expr $smooth_multi_block(smoothDirection) - 1]]
        set n [lindex [lsort -dictionary [hexSmoothDEZ get RelaxBlocks]] 0]
        set stop 0
        catch { unset min; unset max }
        if $use_output_blocks {
            set vertices [string trimright [ic_hex_get_block_vertices $n output_blocks] \n]
        } else {
            set vertices [string trimright [ic_hex_get_block_vertices $n] \n]
        }
        foreach v $vertices {
            if $stop break
            foreach e [ic_hex_get_vertex_edges $v] {
                if $stop break
                set n1 [lindex $e 0]
                set n2 [lindex $e 1]
                set dim [lindex {I J K} [lindex [string trimright [ic_hex_edge_node_dim $n1 $n2] \n] 0]]
                if {$dim == [hexSmoothDEZ get refEdgeDir]} {
                    hexSmoothDEZ set refEdge "$e -1"
                    if $use_output_blocks {
                        set te [string trimright [ic_hex_topo_edge_number output_blocks $n1 $n2]\n]
                    } else {
                        set te [string trimright [ic_hex_topo_edge_number $n1 $n2]\n]
                    }
                    foreach ijk [string trimright [ic_hex_edge_ijk $te]\n] {
                        set use_block [lindex $ijk 0]
                        if {[lsearch $smooth_multi_block(SelectedBlocks) $use_block] < 0} continue
                        set use_min [lrange $ijk 1 3]
                        set use_max [lrange $ijk 4 6]       
                        if {$use_block <= $n} {
                            set block_num $use_block
                            set min $use_min
                            set max $use_max
                        }
                    }
                    if [info exists min] {
                        set smooth_multi_block(ijkBlock) [list $min $max]
                        set stop 1
                        break
                    }
                }
            }
        }
    }
    aie_hex_trace_choose_direction
   
    set non_relax ""
    set hold_cell ""
    foreach n [array names smooth_multi_block TopoFaceNum,*] {
        set face [lindex [split $n ,] 1]
        set num $smooth_multi_block(TopoFaceNum,$face)
        if {[lsearch "$smooth_multi_block(NonRelaxFaces,topo_nums,0)" "$num"] >= 0} {
            lappend non_relax $face
        }
        if {[lsearch "$smooth_multi_block(HoldCellHeightFaces,topo_nums,0)" "$num"] >= 0} {
            lappend hold_cell $face
        }
    }
    hexSmoothDEZ set NonRelaxFaces $non_relax
    hexSmoothDEZ set HoldCellHeightFaces $hold_cell
    aie_hex_face_picking_finished_all [hexSmoothDEZ get NonRelaxFaces] NonRelaxFaces 1
    aie_hex_face_picking_finished_all [hexSmoothDEZ get HoldCellHeightFaces] HoldCellHeightFaces 1
   
    aie_hex_relaxblocks_update
    aie_hex_multiblock_display_selections
    hexSmoothDEZ set mbs_setting_save "$save_file"
    if !$only_temp {
        aie_hex_save_multiblock_settings "$save_file" "" ""
    }
    hexSmoothDEZ set mbs_setting_save ""
    mess "File $load_file converted\n" blue
    busy 0
}

proc aie_hex_line_width {} {
    global hex_line_width
    if ![ic_hex_blocking_loaded] {
          mess "No Blocking is loaded!\n" red
	return
    }
    set ww [question_box .linew "Line width" " Enter line width." $hex_line_width]
    if {$ww != ""} {
        set hex_line_width $ww
        hex_command "set_linewidth $ww"
        hex_update_display
    }
}

proc aie_hex_edge_meshing {} {
    mesh_eparams
}

#------------------------------ Str Mesh Edit stuff --------------------

proc oneditStrMeshIJKPickFinish {} {
    if {$domains != "" && $auto_pick_mode}  {
	reorientStrMeshDEZ apply
	editStrMeshIJKPick pick
    }
}

proc onreorientStrMeshDEZOK {} {
    if {$domains == ""} {
	msg ERROR "No domain selected"
	return
    }

    array set new {I 0 J 0 K 0}
    array set index { I 0 J 1 K 2 }
    foreach r {I J K} {
	foreach c {I J K} {
	    if [setStrMeshIJKMS query "Set $r" $c] {
		set new($r) $index($c)
	    }
	}
    }

   

    catch {array unset ok}
    foreach i {I J K} {
	if ![info exists new($i)] {
	    msg ERROR "You must specify a correct permutation of IJK"
	    return
	}
	set ok($new($i)) 1
    }

    foreach i {0 1 2} {
	if ![info exists ok($i)] {
	    msg ERROR "You must specify a correct permutation of IJK"
	    return
	}
    }
	   
    busy 1
    foreach dom $domains {
	ic_str_move_domain $dom \
	    flip_ijk [list $flipI $flipJ $flipK] \
	    permute_ijk [list $new(I) $new(J) $new(K)]
    }
    ic_str_update_surfs
    busy 0
}


proc onmoveStrNodesDEZLoad {} {
    if ![ic_geo_is_loaded] {
	::AIEnv::GUIManagement::ToggleGrey moveStrNodeWP 1
    } else {
	::AIEnv::GUIManagement::ToggleGrey moveStrNodeWP 0
    }
}

proc onmoveStrNodesInterLoad {} {
    if ![info exists moveNodesTypeVal] {
	set project_geom 1
    }
    if $auto_pick_mode {
        moveStrNodesDynamic pick
    }
}

proc onmoveStrNodesDynamicFinish {} {
    if {$moveStrNodesGGVal != 0 || $nodeList == ""} {
	return
    }
    moveStrNodesDEZ setclean          
    while 1 {
	if {$nodeList == ""} {
	    ic_newop
	    set ss [select_struct_node 0 "" 0 "" 1 1]
	    set sel_surf [lindex $ss 0]
	    set xypos [lindex $ss 1]
	} else {
	    set sel_surf [lindex $nodeList 0]
	    set xypos [lindex $nodeList 1]
        }
        if {$sel_surf == ""} return
	select_move_str_surf 1 $xypos $project_geom
	ic_str_clear_selection_subset
	set nodeList ""
    }
}

proc onmoveStrNodesRefLocFinish {} {
    set xyz  [va_check_data_set_point  $ref_point xyz]
    set xpos [lindex $xyz 0]
    set ypos [lindex $xyz 1]
    set zpos [lindex $xyz 2]
}

proc onmoveStrNodesDEZOK {} {
    if {$moveStrNodesGGVal != 1 } {
	return
    }

    if {$faceList == ""} {
	msg ERROR "No subfaces selected"
	return
    }
   
    set doit ""
    set val ""
    if $moveStrNodesExactRGVal {
	if $moveStrNodesExactPosXVal {
	    lappend doit 1
	    lappend val $xpos
	} else {
	    lappend doit 0
	    lappend val 0
	}
	if $moveStrNodesExactPosYVal {
	    lappend doit 1
	    lappend val $ypos
	} else {
	    lappend doit 0
	    lappend val 0
	}
	if $moveStrNodesExactPosZVal {
	    lappend doit 1
	    lappend val $zpos
	} else {
	    lappend doit 0
	    lappend val 0
	}
    } else {
	if $moveStrNodesExactOffXVal {
	    lappend doit 1
	    lappend val $x
	} else {
	    lappend doit 0
	    lappend val 0
	}
	if $moveStrNodesExactOffYVal {
	    lappend doit 1
	    lappend val $y
	} else {
	    lappend doit 0
	    lappend val 0
	}
	if $moveStrNodesExactOffZVal {
	    lappend doit 1
	    lappend val $z
	} else {
	    lappend doit 0
	    lappend val 0
	}
    }
   
    set val [ic_coords_dir_into_global $val]

    foreach s $faceList {
	set amt [ic_str_move_nodes_exact subface $s $moveStrNodesExactRGVal \
		     [lindex $doit 0] [lindex $doit 1] [lindex $doit 2] \
		     [lindex $val 0] [lindex $val 1] [lindex $val 2]]
	if [info exists val_ret] {
	    if {[lindex $amt 0] < $val_ret(min)} { set val_ret(min) [lindex $amt 0] }
	    if {[lindex $amt 1] > $val_ret(max)} { set val_ret(max) [lindex $amt 1] }
	    set val_ret(tot) [expr $val_ret(tot) + [lindex $amt 2]]
	    incr val_ret(num) [lindex $amt 3]
	} else {
	    set val_ret(min) [lindex $amt 0]
	    set val_ret(max) [lindex $amt 1]
	    set val_ret(tot) [lindex $amt 2]
	    set val_ret(num) [lindex $amt 3]
	}
    }
    if $val_ret(num) {
	mess "$val_ret(num) nodes moved, min $val_ret(min), max $val_ret(max),\
		mean [expr {$val_ret(tot) / ($val_ret(num) + 0.0)}]\n"
    } else {
	mess "0 nodes moved\n"
    }
}

proc ontransformStrMeshDEZLoad {} {
    if ![info exists transformStrMeshInit] {
        set transformStrMeshInit 1
        set transformDomsEG  0
        set translateDomsEG 0
        set DomRotateAxisOptionEGVal 0
        set DomMirrorAxisOptionEGVal 0
        set x 0; set y 0; set z 0
        set xF 1; set yF 1; set zF 1
        set rot_angle 0
        set moveDomsCopyGGVal 0
        set moveDomsCopyGGVal2 0
        set RotateDomCenterEGVal 0
        set ReflectDomCenterEGVal 0
        set ScaleDomCentEGVal 0
        set moveElemesCopyGGVal 0
    }
}

proc ontransformStrMeshDEZAfterLoad {} {
    if ![ic_str_is_loaded] {
        msg ERROR "No Struct. mesh available"
        transformStrMeshDEZ hide
        return
    }
}

proc ontransformStrMeshDEZOK {} {
    global dir
   
    if {$domList == ""} {
        msg ERROR "No domain selected"
        return
    }
   
    if {$transformDomsEGVal == 2 && $flipIndexGGVal != 1} {
        set mess "You have selected a mirror and not an IJK flip - this may\
		result in left-handed domains.  Continue?"
        switch -- [tk_dialog .copymove_check "Mirror without IJK flip" $mess "" -1 Continue Cancel] {        
            -1 { if [winfo exists .copymove_check] { top_destroy .copymove_check; return } }
            1 { return }
        }
    }

    catch {unset needs_topo_recompute}
    set numdoms [llength $domList]

    set make_copy 0
    switch $transformDomsEGVal {
        0 { if $moveDomsCopyGGVal { set make_copy 1 } }
        1 { if $moveDomsCopyGG2Val { set make_copy 1 } }
        default { if $moveElemesCopyGGVal { set make_copy 1 } }
    }
    set ncount 1
    if {$transformDomsEGVal == 0 || $transformDomsEGVal == 1} {
        if $make_copy {
            set ncount $numCopies
        }
    }
    if {$make_copy || ($numdoms != [ic_str_num_entities domain])} {
        ic_str_assign_subface_families
        set needs_topo_recompute 1
    }
    catch {unset off_set}
    catch {unset transfCenter}
    set argList ""
    set new_domList $domList
    for {set i 0} {$i < $ncount } {incr i} {
	    if $make_copy {
	        set new_domList ""
	        foreach dom $domList {
                lappend new_domList [ic_str_copy_domain $dom]
	        }
	    }
        switch $transformDomsEGVal {
	        0 {
                # TRANSLATION
                if ![info exists off_set] {
                    switch $translateDomsEGVal {
                        0 {
                            set off_set [list $x $y $z]
                            mess "Translation Components:$off_set\n"
                        }
			            1 {
                            set pt1 [ic_geo_get_point_location [lindex $pointList2 0]]
                            set pt2 [ic_geo_get_point_location [lindex $pointList2 1]]
                            set x [expr [lindex $pt2 0] -  [lindex $pt1 0]]
                            set y [expr [lindex $pt2 1] -  [lindex $pt1 1]]
                            set z [expr [lindex $pt2 2] -  [lindex $pt1 2]]
                            set off_set [list $x $y $z]
                        }
                    }
                }
                set tt ""
                foreach j {0 1 2} {
                    lappend tt [expr {($i+1) * [lindex $off_set $j]}]
                }
                lappend argList translate $tt
            }
	        1 {
                if ![info exists transfCenter] {
                    # in Rotation-----------
                    switch $DomRotateAxisOptionEGVal {
                        0 {set rot_axis {1 0 0} }
                        1 {set rot_axis {0 1 0} }
                        2 {set rot_axis {0 0 1} }
                        3 {
                            set pt1 [ic_geo_get_point_location [lindex $axisElemList 1]]
                            set pt2 [ic_geo_get_point_location [lindex $axisElemList 0]]
                            set x [expr [lindex $pt2 0] -  [lindex $pt1 0]]
                            set y [expr [lindex $pt2 1] -  [lindex $pt1 1]]
                            set z [expr [lindex $pt2 2] -  [lindex $pt1 2]]
                            set rot_axis [list $x $y $z]
                        }
                    }
                    if {$rot_axis ==""} { 
                        mess "\n rotation axis was not specified" red
                        return
                    }
                    mess "\nAngle: $rot_angle\n"
                    if {$rot_angle==0} {
                        mess "\n!!Angle was not specified!" red
                        return
                    }
                    # take care of center of rotation----- 
                    switch $RotateDomCenterEGVal {
                        0 { set transfCenter {0 0 0} }	
                        1 { set transfCenter [ic_str_domain_centroid [lindex $new_domList 0]]}
                        2 {
                            if {$rotateCenterPnt == ""} {
                                mess "Error: Rotation center point not selected\n" red
                                return
                            }
                            set transfCenter [ic_geo_get_point_location $rotateCenterPnt]
                        }
                    }
                }
                set rot [expr (($i+1) * $rot_angle)]
#set rot [expr $rot * -1.0]
                lappend argList rotate $rot rotate_axis $rot_axis
                lappend argList cent $transfCenter
            }
	        2 {
                # IN MIRROR
                switch $DomMirrorAxisOptionEGVal {
                    0 {set mirror_norm {1 0 0} }
                    1 {set mirror_norm {0 1 0} }
                    2 {set mirror_norm {0 0 1} }
                    3 {
                        set pt1 [ic_geo_get_point_location [lindex $normPointList 1]]
                        set pt2 [ic_geo_get_point_location [lindex $normPointList 0]]
                        set x [expr [lindex $pt2 0] -  [lindex $pt1 0]]
                        set y [expr [lindex $pt2 1] -  [lindex $pt1 1]]
                        set z [expr [lindex $pt2 2] -  [lindex $pt1 2]]
                        set mirror_norm [list $x $y $z]
                    }
                }
                lappend argList mirror $mirror_norm
                switch $ReflectDomCenterEGVal {
                    0 { set transfCenter {0 0 0} }
                    1 { set transfCenter  [ic_str_domain_centroid [lindex $new_domList 0]]}
                    2 {
                        if {$reflectCenterPnt == ""} {
                            mess "Error: Reflection center point not selected\n" red
                            return
                        }
                        set transfCenter [ic_geo_get_point_location $reflectCenterPnt]
                    }	   
                }
                lappend argList cent $transfCenter
                if $flipIndexGGVal {
                    lappend argList flip_ijk $flipIndex
                }
            }
            3 {
                # IN SCALE
                set scaleFactor [list $xF $yF $zF]
                lappend argList scale $scaleFactor
                # now fix the center of Reflection-----
                switch $ScaleDomCentEGVal {
                    0 { set transfCenter {0 0 0} }
                    1 { set transfCenter "centroid"}
                    2 {
                        if {$scaleCenterPnt == ""} {
                            mess "Error: Scale center point not selected\n" red
                            return
                        }
                        set transfCenter [ic_geo_get_point_location $scaleCenterPnt]
                    }
                }
                lappend argList cent $transfCenter
            }
        }
	
	    #----evaluate
        foreach dom $new_domList {
            eval ic_str_move_domain $dom $argList
        }
    }

    if [info exists needs_topo_recompute] {
        struct_comptopo 0
        unset needs_topo_recompute
        catch {unset type_nums}
        foreach type {edge vertex} {
            foreach n [ic_str_list_entities $type] {
                set info [ic_str_get_topo_info $type $n 0]
                set part [lindex [lindex $info 0] 2]
                if ![llength $part] {
                    lappend type_nums($type) $n
                }
            }
        }
        foreach type [array names type_nums] {
            #ic_str_change_family $type "$type_nums($type)" DEFAULT_[string toupper $type]
        }
    }

    mess "Updating domain lists...\n"
    ic_str_update_surfs
    initialize_struct_visibility
    foreach type {domain subface edge vertex} {
        disp_change_overall_visible $type 
    }
    mess "Done.\n"

    transformStrMeshDEZ setdirty
}

proc onsplitStrMeshDEZLoad {} {
    global str_type_visible
    set subfaceList ""
    set partList ""
    splitStrMeshDEZ setclean
    set str_type_visible(subface) 1
    ::AIEnv::GUIManagement::Tree::UpdateStrMeshVisibility
    disp_change_overall_visible subface
}

proc onsplitStrMeshSubfaceSelFinish {} {
    set partList ""
    if {$subfaceList == ""} return
    str_select_highlight subface "$subfaceList" ""
    if $auto_pick_mode {
        splitStrMeshDEZ apply
        splitStrMeshDEZ setclean
        splitStrMeshSubfaceSel pick
     }
}

proc onsplitStrMeshSubfacePartFinish {} {
    set subfaceList ""
    if {$partList == ""} return
    ic_str_topo_make_surfs subface 0
    set stuff [ic_str_list_in_families subface "$partList"]
    if {$stuff == ""} {
        mess "Part(s) $partList contains no subfaces\n" red
        set partList ""
        return
    } else {
        str_select_highlight subface "$stuff" ""
    }
    set nstuff [llength $stuff]
    mess "Selected $nstuff subface(s) in part(s): $partList\n"
    set partList $stuff
    if $auto_pick_mode {
        splitStrMeshDEZ apply
        splitStrMeshDEZ setclean
#        splitStrMeshSubfacePart pick
     }
}

proc onsplitStrMeshDEZOK {} {
    if {$subfaceList == "" && $partList == ""} {
        mess "Nothing selected\n"
        return
    }
    busy 1
    set subfaces ""
    if {$subfaceList != ""} {
        set subfaces $subfaceList
    } elseif {$partList != ""} {
        set subfaces $partList
    }
    foreach s $subfaces {
	set new [ic_str_split_subface $s]
	if {$new != ""} {
	    mess "Split subface $s -> $new\n"
	}
    }
    update_struct_visibility
    str_select_unhighlight subface "" ""
    busy 0
    set subfaceList ""
    set partList ""
    splitStrMeshDEZ setclean
}

proc onsplitStrMeshDEZUnLoad {} {
    if {$subfaceList != "" || $partList != ""} {
        str_select_unhighlight subface "" ""
    }
}

############### Struct mesh smoother ##########################################################

proc onsmoothStrMeshDEZLoad {} {

    set RelaxDomains ""
    set NonRelaxFaces ""
    set HoldCellHeightFaces ""
    set FixedEdges ""
    set FixedDistributionEdges ""
    set GlobalVertices ""
    set LayerVertices ""
    set direction_list [list I J K 3D]
    set refEdgeDir 3D
    set VolumeList [list "Laplace" "Sorenson - Laplace" "Sorenson - Thomas & Middlecoff" \
         "Thomas & Middlecoff" "Interpolation" "Hilgenstock - Thomas & Middlecoff" \
         "Hilgenstock - Laplace"]
    set FaceList [list "Laplace" "Sorenson - Laplace" "Sorenson - Thomas & Middlecoff" \
         "Thomas & Middlecoff" "Interpolation" "Hilgenstock - Thomas & Middlecoff" \
         "Hilgenstock - Laplace"]
    set startIndex 1
    set endIndex 1
    set incrIndex 1
    set iterIndex 0
    set planeNums ""
    set itersEdges 25
    set itersVertices 25
    set parameterPrjLim 0.0
    set parameterRelFac 0.5
    set parameterResFac 0.05
    set parameterUseProj 1
    set parameterFaceFit 1
    set parameterUseOrt 1
    set parameterUseFra 0
    set volume_method "Sorenson - Laplace"
    set face_method "Sorenson - Laplace"
    set gridexpansionVol 4.6
    set gridexpansionFace 3.5
    set smoothStrFaceOptionsVal 0
    set smoothStrVertOptionsVal 0
    set smoothStrAdvancedVal 1
    set smoothStrMBSFileVal 0
    set numProcs 0
    set waitTimeout 30
    set mbs_setting_load ""
    set mbs_setting_save ""
    set mbs_setting_seq_1 ""
    set mbs_setting_seq_2 ""
    set mbs_setting_seq_3 ""
    set mbs_setting_seq_4 ""
    set mbs_setting_seq_5 ""
    set version43Flag 0
}

proc onsmoothStrMeshDEZAfterLoad {} {
    global smooth_str_domains options str_type_visible
    global select_struct_families

    catch { unset smooth_str_domains }

    set button [smoothStrMeshDEZ pathIgnoreErrors smoothStrParameterUseProj]
    $button configure -onvalue 0 -offvalue 1

    foreach n [ic_str_list_entities domain] {
        set smooth_str_domains(DomainInfo,$n) ""
        foreach nn [ic_str_get_topo_info domain 0 0] {
            if {[lindex $nn 3] == $n} {
                set min [lindex $nn 5]
                set max [lindex $nn 6]
                set part [lindex $nn 2]
                break
            }
        }
        set smooth_str_domains(DomainInfo,$n) [list $min $max $part]
    }
    busy 1
    foreach type {domain subface edge vertex} {
        if ![info exists smooth_str_domains(overall_visible,$type)] {
            disp_change_overall_visible $type
            set smooth_str_domains(overall_visible,$type) 1
        }
    }
    busy 0
    set smooth_str_domains(RelaxDomains,save) ""
    set smooth_str_domains(NonRelaxFaces,save) ""
    set smooth_str_domains(HoldCellHeightFaces,save) ""
    set smooth_str_domains(FixedEdges,save) ""
    set smooth_str_domains(FixedDistributionEdges,save) ""
    set smooth_str_domains(GlobalVertices,save) ""
    set smooth_str_domains(LayerVertices,save) ""
    set smooth_str_domains(layer_distance) -1
    set smooth_str_domains(BlockInterFaces) [ic_str_list_blockif_subfaces]
    set smooth_str_domains(BoundaryFaces) [ic_str_list_boundary_subfaces]

    if {[info exists options(n_processors)] && $options(n_processors) > 1} {
        set smooth_str_domains(n_processors) $options(n_processors)
    } else {
        set smooth_str_domains(n_processors) 1
    }
    set smooth_str_domains(hostfile) [aie_hosts_hostfile glsm]
    set numProcs [aie_hosts_nprocs $smooth_str_domains(hostfile)]
    if {[info exists smoothStrGridDistributedVal] && !$numProcs} {
        ::AIEnv::GUIManagement::ToggleGrey smoothStrGridDistributed 1
    }

    set "smooth_str_domains(Thomas & Middlecoff)" 1
    set "smooth_str_domains(Laplace)" 2
    set "smooth_str_domains(Interpolation)" 4
    set "smooth_str_domains(Sorenson - Thomas & Middlecoff)" 6
    set "smooth_str_domains(Sorenson - Laplace)" 7
    set "smooth_str_domains(Hilgenstock - Laplace)" 9
    set "smooth_str_domains(Hilgenstock - Thomas & Middlecoff)" 10

    if {[trace vinfo refEdgeDir] != ""} {
        trace vdelete refEdgeDir w aie_str_trace_refEdgeDir
    }
    trace variable refEdgeDir w aie_str_trace_refEdgeDir
    aie_str_trace_refEdgeDir
    if {[trace vinfo planeNums] != ""} {
        trace vdelete planeNums w aie_str_trace_planeNums
    }
    trace variable planeNums w aie_str_trace_planeNums
    aie_str_trace_planeNums
    
    set ::select_struct_families 1

#    mess "Updating histogram...\n"
#    aie_str_do_histo
}

proc onsmoothStrMeshDEZUnLoad {} {
    global smooth_str_domains struct_diag
    global select_struct_families

    if [info exists smooth_str_domains] {
        unset smooth_str_domains
    }
    if [ic_str_is_loaded] {
        aie_str_clear_all_selections
        ic_str_glb_sm_init
    }
    ic_str_unset_temp_highlight_array
#    aie_str_clear_histogram
    if [info exists struct_diag(is_done)] {
        unset struct_diag(is_done)
    }

    if {[trace vinfo refEdgeDir] != ""} {
        trace vdelete refEdgeDir w aie_str_trace_refEdgeDir
    }
    if {[trace vinfo planeNums] != ""} {
        trace vdelete planeNums w aie_str_trace_planeNums
    }
    unset ::select_struct_families
}

proc aie_str_trace_refEdgeDir {{name ""} {element ""} {op ""}} {

    if {[smoothStrMeshDEZ get refEdgeDir] == "3D" || [smoothStrMeshDEZ get RelaxDomains] == ""} {
        smoothStrMeshDEZ set startIndex 1
        smoothStrMeshDEZ set endIndex 1
        smoothStrMeshDEZ set incrIndex 1
        smoothStrMeshDEZ set planeNums ""
        ::AIEnv::GUIManagement::ToggleGrey smoothStrLayerFrame 1
        return
    }
    set n [lindex [smoothStrMeshDEZ get RelaxDomains] 0]
    set min "1 1 1"
    set max "[ic_str_ijk_limits $n]"
    if {$min == "" || $max == ""} return
    ::AIEnv::GUIManagement::ToggleGrey smoothStrLayerFrame 0
    switch [smoothStrMeshDEZ get refEdgeDir] {
        I  { set smoothDirection 1 }
        J  { set smoothDirection 2 }
        K  { set smoothDirection 3 }
    }
    set idx [expr $smoothDirection - 1]
    smoothStrMeshDEZ set startIndex [lindex $min $idx]
    smoothStrMeshDEZ set endIndex [lindex $max $idx]
    smoothStrMeshDEZ set incrIndex [expr [smoothStrMeshDEZ get endIndex ] - 1]
}

proc aie_str_trace_planeNums {{name ""} {element ""} {op ""}} {
    if {[smoothStrMeshDEZ get planeNums] != "" && [smoothStrMeshDEZ get refEdgeDir] != "3D"} {
        ::AIEnv::GUIManagement::ToggleGrey smoothStrStartIndex 1
        ::AIEnv::GUIManagement::ToggleGrey smoothStrEndIndex 1
        ::AIEnv::GUIManagement::ToggleGrey smoothStrIncr 1
    } else {
        if {[smoothStrMeshDEZ get refEdgeDir] != "3D"} {
            ::AIEnv::GUIManagement::ToggleGrey smoothStrStartIndex 0
            ::AIEnv::GUIManagement::ToggleGrey smoothStrEndIndex 0
            ::AIEnv::GUIManagement::ToggleGrey smoothStrIncr 0
        }
    }
}

proc aie_str_get_smooth_method_number {type} {
    switch $type {
        volume {
            set method [smoothStrMeshDEZ get volume_method]
        }
        subface {
            set method [smoothStrMeshDEZ get face_method]
        }
    }
    switch $method {
        "Thomas & Middlecoff" { return 1 }
        "Laplace" { return 2 }
        "Interpolation" { return 4 }
        "Sorenson - Thomas & Middlecoff)" { return 6 }
        "Sorenson - Laplace" { return 7 }
        "Hilgenstock - Laplace" { return 9 }
        "Hilgenstock - Thomas & Middlecoff" { return 10 }
        default { return 7 }
    }
}

proc aie_str_get_smooth_method_name {number} {
    switch $number {
        1 { return "Thomas & Middlecoff" }
        2 { return "Laplace" }
        4 { return "Interpolation" }
        6 { return "Sorenson - Thomas & Middlecoff)" }
        7 { return "Sorenson - Laplace" }
        9 { return "Hilgenstock - Laplace" }
        10 { return "Hilgenstock - Thomas & Middlecoff" }
        deafult { return "Sorenson - Laplace" }
    }
}

proc aie_str_add_or_remove {} {
    global struct_sel
    if {$struct_sel == "remove"} {
        return remove
    } else {
        return add
    }
}

proc onsmoothStrRelaxDomainPickPick {} {
    global smooth_str_domains

    set smooth_str_domains(RelaxDomains,save) [smoothStrMeshDEZ get RelaxDomains]
    after 1 {
        if {[aie_str_add_or_remove] == "remove"} {
            if {[smoothStrMeshDEZ get RelaxDomains] == ""} {
                banner ""
                mess "No relaxation domain(s) selected\n"
            } else {
                set banner "Unselect Relaxation domains with the left button, middle = done,\
                        right = back up/cancel, '?' = list options."
                banner $banner
            }
        }
    }
}

proc onsmoothStrRelaxDomainPickFinish {} {
    global smooth_str_domains

    if {$RelaxDomains == "" || ![string compare $RelaxDomains "*cancel*"]} {
        set RelaxDomains $smooth_str_domains(RelaxDomains,save)
        aie_str_display_domains
        return
    }
    if {[aie_str_add_or_remove] == "add"} {
        set relax $smooth_str_domains(RelaxDomains,save)
        foreach b $RelaxDomains {
            if {[lsearch "$smooth_str_domains(RelaxDomains,save)" $b] == -1} {
               lappend relax $b
            }
        }
    } else {
        set relax ""
        foreach b $smooth_str_domains(RelaxDomains,save) {
            if {[lsearch "$RelaxDomains" $b] == -1} {
               lappend relax $b
            }
        }
    }
    set RelaxDomains [lsort -dictionary $relax]
    aie_str_display_domains
    aie_str_trace_refEdgeDir
}

proc onsmoothStrNonRelaxFacePickPick {} {
    global smooth_str_domains
    set smooth_str_domains(NonRelaxFaces,save) $NonRelaxFaces
    after 1 {
        if {[aie_str_add_or_remove] == "remove"} {
            if {[smoothStrMeshDEZ get NonRelaxFaces] == ""} {
                banner ""
                mess "No Non-Relaxtion faces(s) selected\n"
            } else {
                set banner "Unselect Non-Relaxtion faces with the left button, middle = done,\
                        right = back up/cancel, '?' = list options."
                banner $banner
            }
        }
    }
}

proc onsmoothStrNonRelaxFacePickFinish {} {
    global smooth_str_domains

    if {$NonRelaxFaces == "" || ![string compare $NonRelaxFaces "*cancel*"]} {
        set NonRelaxFaces $smooth_str_domains(NonRelaxFaces,save)
        aie_str_display_subfaces
        return
    }
    if {[aie_str_add_or_remove] == "add"} {
        set non_relax $smooth_str_domains(NonRelaxFaces,save)
        foreach f $NonRelaxFaces {
            if {[lsearch "$smooth_str_domains(NonRelaxFaces,save)" $f] == -1} {
               lappend non_relax $f
            }
        }
    } else {
        set non_relax ""
        foreach f $smooth_str_domains(NonRelaxFaces,save) {
            if {[lsearch "$NonRelaxFaces" $f] == -1} {
               lappend non_relax $f
            }
        }
    }
    set NonRelaxFaces $non_relax
    aie_str_display_subfaces
}

proc onsmoothStrHoldCellHeightFacePickPick {} {
    global smooth_str_domains
    set smooth_str_domains(HoldCellHeightFaces,save) $HoldCellHeightFaces
    after 1 {
        if {[aie_str_add_or_remove] == "remove"} {
            if {[smoothStrMeshDEZ get HoldCellHeightFaces] == ""} {
                banner ""
                mess "No Hold Cell Height faces(s) selected\n"
            } else {
                set banner "Unselect Hold Cell Height faces with the left button, middle = done,\
                        right = back up/cancel, '?' = list options."
                banner $banner
            }
        }
    }
}

proc onsmoothStrHoldCellHeightFacePickFinish {} {
    global smooth_str_domains

    if {$HoldCellHeightFaces == "" || ![string compare $HoldCellHeightFaces "*cancel*"]} {
        set HoldCellHeightFaces $smooth_str_domains(HoldCellHeightFaces,save)
        aie_str_display_subfaces
        return
    }
    if {[aie_str_add_or_remove] == "add"} {
        set non_relax $smooth_str_domains(HoldCellHeightFaces,save)
        foreach f $HoldCellHeightFaces {
            if {[lsearch "$smooth_str_domains(HoldCellHeightFaces,save)" $f] == -1} {
               lappend non_relax $f
            }
        }
    } else {
        set non_relax ""
        foreach f $smooth_str_domains(HoldCellHeightFaces,save) {
            if {[lsearch "$HoldCellHeightFaces" $f] == -1} {
               lappend non_relax $f
            }
        }
    }
    set HoldCellHeightFaces $non_relax
    aie_str_display_subfaces
}

proc onsmoothStrFixedEdgesPickPick {} {
    global smooth_str_domains
    set smooth_str_domains(FixedEdges,save) $FixedEdges
    after 1 {
        if {[aie_str_add_or_remove] == "remove"} {
            if {[smoothStrMeshDEZ get FixedEdges] == ""} {
                banner ""
                mess "No edge(s) selected\n"
            } else {
                set banner "Unselect fixed edges with the left button, middle = done,\
                            right = back up/cancel, '?' = list options."
                banner $banner
            }
        }
    }
}

proc onsmoothStrFixedEdgesPickFinish {} {
    global smooth_str_domains

    if {$FixedEdges == "" || ![string compare $FixedEdges "*cancel*"]} {
        set FixedEdges $smooth_str_domains(FixedEdges,save)
        return
    }
    set edges ""
    if {[aie_str_add_or_remove] == "add"} {
        foreach n $FixedEdges {
            if {[lsearch "$smooth_str_domains(FixedEdges,save)" $n] == -1} {
                append edges "$n "
            }
        }
        foreach n $smooth_str_domains(FixedEdges,save) {
            if {[lsearch "$edges" $n] >= 0} continue
            append edges "$n "
        }
    } else {
        foreach n $smooth_str_domains(FixedEdges,save) {
            if {[lsearch "$FixedEdges" $n] >= 0} continue
            append edges "$n "
        }
    }

    set FixedEdges [lsort -integer $edges]
    aie_str_display_edges
}

proc onsmoothStrFixedDistributionEdgesPickPick {} {
    global smooth_str_domains
    set smooth_str_domains(FixedDistributionEdges,save) $FixedDistributionEdges
    after 1 {
        if {[aie_str_add_or_remove] == "remove"} {
            if {[smoothStrMeshDEZ get FixedDistributionEdges] == ""} {
                banner ""
                mess "No edge(s) selected\n"
            } else {
                set banner "Unselect fixed distribution edges with the left button, middle = done,\
                            right = back up/cancel, '?' = list options."
                banner $banner
            }
        }
    }
}

proc onsmoothStrFixedDistributionEdgesPickFinish {} {
    global smooth_str_domains

    if {$FixedDistributionEdges == "" || ![string compare $FixedDistributionEdges "*cancel*"]} {
        set FixedDistributionEdges $smooth_str_domains(FixedDistributionEdges,save)
        return
    }
    set edges ""
    if {[aie_str_add_or_remove] == "add"} {
        foreach n $FixedDistributionEdges {
            if {[lsearch "$smooth_str_domains(FixedDistributionEdges,save)" $n] == -1} {
                append edges "$n "
            }
        }
        foreach n $smooth_str_domains(FixedDistributionEdges,save) {
            if {[lsearch "$edges" $n] >= 0} continue
            append edges "$n "
        }
    } else {
        foreach n $smooth_str_domains(FixedDistributionEdges,save) {
            if {[lsearch "$FixedDistributionEdges" $n] >= 0} continue
            append edges "$n "
        }
    }

    set FixedDistributionEdges [lsort -integer $edges]
    aie_str_display_edges
}

proc onsmoothStrGlobalVertPickPick {} {
    global smooth_str_domains
    set smooth_str_domains(GlobalVertices,save) $GlobalVertices
    after 1 {
        if {[aie_str_add_or_remove] == "remove"} {
            if {[smoothStrMeshDEZ get GlobalVertices] == ""} {
                banner ""
                mess "No vert(s) selected\n"
            } else {
                set banner "Unselect global vertices with the left button, middle = done,\
                            right = back up/cancel, '?' = list options."
                banner $banner
            }
        }
    }
}

proc onsmoothStrGlobalVertPickFinish {} {
    global smooth_str_domains

    if {$GlobalVertices == "" || ![string compare $GlobalVertices "*cancel*"]} {
        set GlobalVertices $smooth_str_domains(GlobalVertices,save)
        return
    }
    set vertices ""
    if {[aie_str_add_or_remove] == "add"} {
        foreach n $GlobalVertices {
            if {[lsearch "$smooth_str_domains(GlobalVertices,save)" $n] == -1} {
                append vertices "$n "
            }
        }
        foreach n $smooth_str_domains(GlobalVertices,save) {
            if {[lsearch "$vertices" $n] >= 0} continue
            append vertices "$n "
        }
    } else {
        foreach n $smooth_str_domains(GlobalVertices,save) {
            if {[lsearch "$GlobalVertices" $n] >= 0} continue
            append vertices "$n "
        }
    }

    set GlobalVertices [lsort -integer $vertices]
}

proc onsmoothStrLayerVertPickPick {} {
    global smooth_str_domains
    set smooth_str_domains(LayerVertices,save) $LayerVertices
    after 1 {
        if {[aie_str_add_or_remove] == "remove"} {
            if {[smoothStrMeshDEZ get LayerVertices] == ""} {
                banner ""
                mess "No vert(s) selected\n"
            } else {
                set banner "Unselect layer vertices with the left button, middle = done,\
                            right = back up/cancel, '?' = list options."
                banner $banner
            }
        }
    }
}

proc onsmoothStrLayerVertPickFinish {} {
     global smooth_str_domains

    set vertices ""
    if {$LayerVertices == "" || ![string compare $LayerVertices "*cancel*"]} {
        set LayerVertices $smooth_str_domains(LayerVertices,save)
        return
    }
    if {[aie_str_add_or_remove] == "add"} {
        foreach n $LayerVertices {
            if {[lsearch "$smooth_str_domains(LayerVertices,save)" $n] == -1} {
                append vertices "$n "
            }
        }
        foreach n $smooth_str_domains(LayerVertices,save) {
            if {[lsearch "$vertices" $n] >= 0} continue
            append vertices "$n "
        }
    } else {
        foreach n $smooth_str_domains(LayerVertices,save) {
            if {[lsearch "$LayerVertices" $n] >= 0} continue
            append vertices "$n "
        }
    }
    set vertices [lsort -integer $vertices]
    if {[aie_str_add_or_remove] == "add" && $vertices != ""}  {
        smoothStrMeshDEZ aie_str_set_selected_first_layer_distance $vertices
    } elseif {[aie_str_add_or_remove] == "remove" && $vertices != ""} {
        foreach i [array names smooth_str_domains layer_distance,*] {
            set n [lindex [split $i ,] 1]
            if {[lsearch "$vertices" $n] < 0} {
                unset smooth_str_domains(layer_distance,$n)
            }
        }
    }
    set LayerVertices [lsort -integer $vertices]
}

proc aie_str_set_first_layer_distance {} {
    global smooth_str_domains

    if [winfo exists .layer_distance] { form_delete .layer_distance }
    set buttons { {accept} {cancel} }
    set LayerVertices [smoothStrMeshDEZ get LayerVertices]
    if {$LayerVertices == ""} {
        mess "No vert(s) selected.\n"
        return ""
    }
    set i 0
    set w [form_init .layer_distance "Initial Height" "" $buttons]
    if {$w != ""} {
	form_label $w.name " Vertex #  /  Layer Distance" "$i 0"
	set sw [form_scroller $w.stuff 300 "1 0"]
	foreach item $LayerVertices {
	    form_label $sw.name$i "$item" "$i 0"; $sw.name$i configure -width 8
	    form_entry $sw.value$i distence($item) float "$i 1" ""
	    if [info exists smooth_str_domains(layer_distance,$item)] {
	        set distence($item) $smooth_str_domains(layer_distance,$item)
	    } else {
	        set distence($item) -1
	    }
	    incr i
	}
	form_scroller_hack $w.stuff
	form_finish +200+200
    }
    if [form_wait .layer_distance] {
        foreach i $LayerVertices {
            if {$distence($i) == "" || $distence($i) < 0} { set distence($i) -1 }
            set smooth_str_domains(layer_distance,$i) $distence($i)
            smoothStrMeshDEZ set ::smooth_str_domains(layer_distance,$i) $distence($i)
        }
    }
    catch { unset distence }
}

proc aie_str_set_selected_first_layer_distance {selected} {
    global smooth_str_domains

    if [winfo exists .set_layer_distance] { form_delete .set_layer_distance }
    set buttons { {accept} {cancel} }
    if {$selected == ""} {
        mess "No vert(s) selected.\n"
        return ""
    }
    set w [form_init .set_layer_distance "Initial Height" "" $buttons]
    if {$w != ""} {
	form_label $w.name "Layer Distance" "0 0"
	form_entry $w.value layer_distance float "0 1" ""
	set layer_distance $smooth_str_domains(layer_distance)
	form_finish +200+200
    }
    if [form_wait .set_layer_distance] {
        set smooth_str_domains(layer_distance) $layer_distance
        foreach i [smoothStrMeshDEZ get LayerVertices] {
            if {[lsearch $selected $i] < 0} continue
            set smooth_str_domains(layer_distance,$i) $layer_distance
            smoothStrMeshDEZ set ::smooth_str_domains(layer_distance,$i) $layer_distance
        }
    }
    catch { unset layer_distance }
}

proc aie_str_display_domains {} {
    global batch_mode

    if $batch_mode return
    str_select_unhighlight domain "" ""
    foreach n [smoothStrMeshDEZ get RelaxDomains] {
        ic_str_highlight domain $n 1 cyan
        ic_str_set_nums_visible domain "$n 1"
    }
}

proc aie_str_display_subfaces {} {
    global str_option batch_mode

    if $batch_mode return
    str_select_unhighlight subface "" ""
    set nonrelax [smoothStrMeshDEZ get NonRelaxFaces]
    set holdcell [smoothStrMeshDEZ get HoldCellHeightFaces]
    set nums_nonrelax ""
    set nums_holdcell ""
    set nums_both ""
    foreach n $nonrelax {
       if {[lsearch $holdcell $n] >= 0} {
           lappend nums_both $n
       } else {
           lappend nums_nonrelax $n
       }
    }
    foreach n $holdcell {
       if {[lsearch $nonrelax $n] == -1} {
           lappend nums_holdcell $n
       }
    }
    set shrink 0
    foreach n $nums_nonrelax {
        ic_str_highlight subface $n 1 yellow
        ic_str_set_nums_visible subface "$n 1"
        set shrink 1
    }
    foreach n $nums_holdcell {
        ic_str_highlight subface $n 1 blue
        ic_str_set_nums_visible subface "$n 1"
        set shrink 1
    }
    foreach n $nums_both {
        ic_str_highlight subface $n 1 green
        ic_str_set_nums_visible subface "$n 1"
        set shrink 1
    }
    if !$str_option(subface,shrink) {
        set str_option(subface,shrink) $shrink
        disp_shrink_ijk subface !$str_option(subface,shrink)
    } else {
        if !$shrink {
            set str_option(subface,shrink) 0
            disp_shrink_ijk subface 1
        }
    }
}

proc aie_str_display_edges {} {
    global batch_mode

    if $batch_mode return
    str_select_unhighlight edge "" ""
    set fixed [smoothStrMeshDEZ get FixedEdges]
    set fixed_dist [smoothStrMeshDEZ get FixedDistributionEdges]
    set nums_fixed ""; set nums_fixed_dist ""; set nums_both ""
    foreach n $fixed {
       if {[lsearch $fixed_dist $n] >= 0} {
           lappend nums_both $n
       } else {
           lappend nums_fixed $n
       }
    }
    foreach n $fixed_dist {
       if {[lsearch $fixed $n] == -1} {
           lappend nums_fixed_dist $n
       }
    }
    foreach n $nums_fixed {
        ic_str_highlight edge $n 1 violet
        ic_str_set_nums_visible edge "$n 1"
    }
    foreach n $nums_fixed_dist {
        ic_str_highlight edge $n 1 orange
        ic_str_set_nums_visible edge "$n 1"
    }
    foreach n $nums_both {
        ic_str_highlight edge $n 1 red
        ic_str_set_nums_visible edge "$n 1"
    }

}

proc aie_str_clear_all_selections {} {
    global batch_mode smooth_str_domains str_type_visible

    if $batch_mode return
    smoothStrMeshDEZ set RelaxDomains ""
    smoothStrMeshDEZ set NonRelaxFaces ""
    smoothStrMeshDEZ set HoldCellHeightFaces ""
    smoothStrMeshDEZ set FixedEdges ""
    smoothStrMeshDEZ set FixedDistributionEdges ""
    smoothStrMeshDEZ set GlobalVertices ""
    smoothStrMeshDEZ set LayerVertices ""
    foreach n [array names smooth_str_domains layer_distance,*] {
        unset smooth_str_domains($n)
    }
    if ![ic_str_is_loaded] return
    foreach t "domain subface edge" {
        if {$t != "domain"} {
            foreach n [ic_str_list_entities_visible $t 1] {
                catch { ic_str_set_nums_visible $t "$n 0" }
            }
        }
        catch { str_select_unhighlight $t "" "" }
        catch { set str_option($t,shrink) 0 }
        catch { disp_shrink_ijk $t !$str_option($t,shrink) }
    }
}

proc aie_str_dist_hosts {} {
    global smooth_str_domains
    aie_hosts_setup $smooth_str_domains(hostfile) aie_str_dist_update 1
}

proc aie_str_dist_update {hostfile} {
    smoothStrMeshDEZ set numProcs [aie_hosts_nprocs $hostfile]
    smoothStrMeshDEZ setdirty
}

proc aie_str_dist_reset {} {
    global smooth_str_domains
    if {$smooth_str_domains(hostfile) == ""} {
        set smooth_str_domains(hostfile) [aie_hosts_hostfile glsm]
    }
    if {[info exists smoothStrGridDistributedGGVal]} {
        set numProcs [aie_hosts_nprocs $smooth_str_domains(hostfile)]
        if {$numProcs > 0 && $smoothStrGridDistributedGGVal} {
            ::AIEnv::GUIManagement::ToggleGrey smoothStrGridDistributed 0
        } else {
            ::AIEnv::GUIManagement::ToggleGrey smoothStrGridDistributed 1
        }
    }
}

proc onsmoothStrMeshDEZOK {} {
    global file_name smooth_str_domains

    switch $refEdgeDir {
        3D { set smoothDirection 0 }
        I  { set smoothDirection 1 }
        J  { set smoothDirection 2 }
        K  { set smoothDirection 3 }
    }

    if {$smoothDirection != 0 && $planeNums == ""} {
        if {$startIndex < 1} {
            mess "Start layer must be greater than 0.\n" red
            return
        }
        if {$endIndex < $startIndex} {
            mess "End layer can not be less than start layer.\n" red
            return
        }
        if {$endIndex < 0} {
            mess "End layer must be greater than 0.\n" red
            return
        }
        if {$incrIndex < 1} {
            mess "Increment must be greater than 0.\n" red
            return
        }
    }
    
    if {[smoothStrMeshDEZ get RelaxDomains] == ""} {
        mess "No relaxation domain selected\n" red
        return
    } else {
        mess "Running smoother...\n" blue
    }

    set the_face_methods ""
    for {set i 0} {$i < 6} {incr i} {
        append the_face_methods "[aie_str_get_smooth_method_number subface] "
    }
    set smooth_domain ""
    set face_methods ""
    set volume_methods ""
    set smooth_dir ""
    set incr_3d_plane_smooth ""
    set relax_weights_2d ""
    set relax_weights_3d ""
    set relax_weights_inner_2d ""
    set relax_weights_inner_3d ""
    set smooth_ngh_method ""
    set abs_dist_subf ""
    set n_abs_dist_subf ""
    set grid_exp_rate_subf_perp ""
    set grid_exp_rate_subf_1 ""

    set relax_faces ""
    set relaxation_zones ""
    set edge_no_global_smooth ""
    set global_vertices_opp ""
    set vertex_attrib ""
    set mesh_type 0

    set the_volume_method [aie_str_get_smooth_method_number volume]

    set plane_numbers ""
    if {$smoothDirection == 0} {
        set the_incr_3d_plane_smooth "-1 -1 -1 0"
    } else {
        if {$planeNums != ""} {
           set plane_len [llength $planeNums]
           for {set i 1} {$i <= [ic_str_num_entities domain]} {incr i} {
               set numbers "$plane_len "
               foreach item $planeNums {
                   append numbers "$item "
               }
               append plane_numbers "$numbers "
           }
           set the_incr_3d_plane_smooth "-1 -1 -1 $iterIndex"
        } else {
           set the_incr_3d_plane_smooth "$startIndex $endIndex $incrIndex $iterIndex"
        }
    }

    for {set i 1} {$i <= [ic_str_num_entities domain]} {incr i} {
        append smooth_domain "[aie_str_is_seleced_domain $i] "
        append face_methods "$the_face_methods "
        append volume_methods "$the_volume_method "
        append smooth_dir "$smoothDirection "
        append incr_3d_plane_smooth "$the_incr_3d_plane_smooth "
        append relax_weights_2d "0 0 0 0 0 0 "
        append relax_weights_inner_2d "0 0 0 0 0 0 "
        append relax_weights_inner_3d "0 0 0 0 0 0 "
        append smooth_ngh_method "-2 "
        append abs_dist_subf "-1.0 -1.0 -1.0 -1.0 -1.0 -1.0 "
        append n_abs_dist_subf "-1 -1 -1 -1 -1 -1 "
        append grid_exp_rate_subf_perp "-1 -1 -1 -1 -1 -1 "
        append grid_exp_rate_subf_1 "-1 -1 -1 -1 -1 -1 "
    }

    foreach n [smoothStrMeshDEZ get NonRelaxFaces] {
        append relax_faces "$n 0 "
    }

    catch { unset tmp }
    for {set i 1} {$i <= [ic_str_num_entities domain]} {incr i} {
        set tmp(set,imin,$i) 0; set tmp(set,imax,$i) 0
        set tmp(set,jmin,$i) 0; set tmp(set,jmax,$i) 0
        set tmp(set,kmin,$i) 0; set tmp(set,kmax,$i) 0
    }

    set topo_nums ""
    foreach n [smoothStrMeshDEZ get HoldCellHeightFaces] {
        append topo_nums "$n "
    }
    for {set i 1} {$i <= [ic_str_num_entities domain]} {incr i} {
        foreach n "imin imax jmin jmax kmin kmax" {
            foreach face_no [aie_str_get_subface_ijk $i $n] {
                if {[lsearch $topo_nums $face_no] >= 0} {
                    set tmp(set,$n,$i) 1
                }
            }
        }
    }
    for {set i 1} {$i <= [ic_str_num_entities domain]} {incr i} {
       set imin $tmp(set,imin,$i); set imax $tmp(set,imax,$i)
       set jmin $tmp(set,jmin,$i); set jmax $tmp(set,jmax,$i)
       set kmin $tmp(set,kmin,$i); set kmax $tmp(set,kmax,$i)
       append relax_weights_3d "$imin $imax $jmin $jmax $kmin $kmax "
    }

    set edge_attrib ""
    set fixed [smoothStrMeshDEZ get FixedEdges]
    set fixed_dist [smoothStrMeshDEZ get FixedDistributionEdges]
    foreach n $fixed {
       if {[lsearch $fixed_dist $n] >= 0} {
           lappend edge_attrib $n 3
       } else {
           lappend edge_attrib $n 2
       }
    }
    foreach n $fixed_dist {
       if {[lsearch $fixed $n] == -1} {
           lappend edge_attrib $n 1
       }
    }

    foreach n [ic_str_list_vertex_edges [smoothStrMeshDEZ get GlobalVertices]] {
        foreach e [lindex $n 0] {
            append edge_no_global_smooth "$e "
        }
        foreach v [lindex $n 1] {
            set num [lindex $v 0]
            set i [lindex $v 1]
            set j [lindex $v 2]
            set k [lindex $v 3]
            set min "[lindex $v 1] [lindex $v 2] [lindex $v 3]"
            append relaxation_zones "$num $i $j $k $i $j $k 0 "
            append global_vertices_opp "$num $min "
        }
    }

    foreach n [smoothStrMeshDEZ get LayerVertices] {
        set dist -1
        if [info exists smooth_str_domains(layer_distance,$n)] {
            set dist $smooth_str_domains(layer_distance,$n)
        }
        if {$dist == "" || $dist < 0} { set dist -1 }
        append vertex_attrib "$n $dist -1 "
    }

    if {$smoothDirection == 0 || [smoothStrMeshDEZ get GlobalVertices] == "" || \
        [smoothStrMeshDEZ get RelaxDomains] == 1} {
        set prog_select 2
    } else {
        set prog_select 5
    }

    set niter 1
    set nsteps 1
    set maxlevel 3
    set sfit $parameterFaceFit
    set conditional 0
    set check_det 0
    set damping 1
    set vertex_fix 1
    set edge_freeze 1
    set wedge_check 1
    set fix_fam 0
    set multigrid2d 0
    set reduced_edge 0
    set inner_vol_sm 0
    set ns_rel 0.0
    set angle_freeze_edge 5.0
    set n_iter $itersEdges
    set interp_faces 0
    set interp_volumes 0
    set threshold_det 30.0
    set threshold_angle 80.0
    set subface_extensions ""
    set ijk_extensions ""
    set relax_subfaces $relax_faces
    set relaxation_zones $relaxation_zones
    set viol_geom_zones ""
    set viol_geom_subfaces ""
    set base_subfaces_no ""
    set meshing_law ""
    set subface_extend 0
    set direction_vector ""
    set base_regions ""
    set type_improve 0
    set type_postsm 2
    set proj_limit $parameterPrjLim
    set group_bad_elem 0
    set mesh_type 0
    set surfresolv $parameterUseProj
    set min_mxr 3.0
    set edge_no_global_smooth $edge_no_global_smooth
    set n_iter_glb $itersEdges
    set n_steps_glb $itersVertices
    set global_vertices_opp $global_vertices_opp
    set grid_exp_face $gridexpansionFace
    set grid_exp_vol $gridexpansionVol
    set min_res $parameterResFac
    set abs_dist_bnd -1
    set n_points_abs_dist_bnd -1
    set vertex_attrib $vertex_attrib
    set relaxation_factor $parameterRelFac
    set use_orthog_position $parameterUseOrt
    set use_fract_position $parameterUseFra
    set first_cell_height -1
    set last_cell_height -1
    set use_pthreads $smooth_str_domains(n_processors)

    set num_procs 0
    set hostfile ""
    set timeout 0
    set verbose 0
    if {[info exists smoothStrGridDistributedGGVal] &&
        $smoothStrGridDistributedGGVal && $numProcs > 0} {
        set num_procs $numProcs
        set hostfile $smooth_str_domains(hostfile)
        if {$waitTimeout != "" && $waitTimeout > 0} {
            set timeout $waitTimeout
        }
        if {[info exists distVerbose]} {
            set verbose $distVerbose
        }
    }
    ic_undo_suspend
    ic_str_save_previous_nodes
    set isChanged 1
    busy 0
    ic_str_smooth_glsm $isChanged $file_name(mesh_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 $num_procs $hostfile $timeout $verbose

    catch { interrupt finish }
    mess "Done running smoother\n" blue
    ic_undo_resume
}

proc aie_str_is_seleced_domain {n} {
    if {[lsearch "[smoothStrMeshDEZ get RelaxDomains]" $n] >= 0} {
        return 1
    }
    return 0
}

proc aie_str_get_subface_ijk {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 aie_str_selections_pressed_button {b type i} {
    $b configure -fg red
    ic_str_highlight $type $i 1 red
    ic_str_set_nums_visible $type "$i 1"
    ic_str_configure_one_attribute $type $i width 5
    if {$type == "vertex"} {
        ic_str_configure_one_attribute $type $i node_size 9
    }
}

proc aie_str_selections_released_button {b type i col} {
    $b configure -fg black
    ic_str_highlight $type $i 0 $col
    ic_str_set_nums_visible $type "$i 1"
    ic_str_configure_one_attribute $type $i width 2
    if {$type == "vertex"} {
        ic_str_configure_one_attribute $type $i node_size 3
    }
}

proc aie_str_show_all_selections {} {
    global smooth_str_domains

    if [winfo exists .list_selected] { destroy .list_selected }

    set nDomains [ic_str_num_entities domain]
    set nSubfaces [ic_str_num_entities subface]
    set nEdges [ic_str_num_entities edge]
    set nVertices [ic_str_num_entities vertex]

    set w .list_selected
    set buttons [list dismiss] 
    set ww [form_init $w "Selected entities" "" $buttons]
    if {$ww == ""} return
    set ii 0
    set c [form_scroller $ww.fr 400 {1 0}]
    $c configure -relief sunken -bd 4
    form_label $c.dom "Relaxation domains" "0 0 -fill both"
    $c.dom configure -background white
    for {set i 1} {$i <= $nDomains} {incr i} {
        if [aie_str_is_seleced_domain $i] {
            incr ii
            form_label $c.dom$ii "DOM$i " "$ii 0 -fill both"
            bind $c.dom$ii <ButtonPress-1> "aie_str_selections_pressed_button $c.dom$ii domain $i"
            bind $c.dom$ii <ButtonRelease-1> "aie_str_selections_released_button $c.dom$ii domain $i cyan"
        }
    }
    set rfaces [smoothStrMeshDEZ get NonRelaxFaces]
    set hfaces [smoothStrMeshDEZ get HoldCellHeightFaces]
    if {$rfaces != "" || $hfaces != ""} {
        incr ii
        form_label $c.face "Subfaces" "$ii 0 -fill both"
        $c.face configure -background white
        form_label $c.rela "Relaxation" "$ii 1 -fill both"
        $c.rela configure -background white
        form_label $c.hold "Hold Cell Height" "$ii 2 -fill both"
        $c.hold configure -background white
        for {set i 1} {$i <= $nSubfaces} {incr i} {
            if {[lsearch $rfaces $i] > -1 || [lsearch $hfaces $i] > -1} {
                incr ii
                form_label $c.f$ii "$i" "$ii 0 -fill both"
                set rf 0; set hf 0
                if {[lsearch $rfaces $i] > -1} {
                    form_label $c.rf$ii "x" "$ii 1 -fill both"
                    set rf 1
                }
                if {[lsearch $hfaces $i] > -1} {
                    form_label $c.hf$ii "x" "$ii 2 -fill both"
                    set hf 1
                }
                if {$rf && $hf} {
                    set col green
                } elseif {$rf} {
                    set col yellow
                } else {
                    set col blue
                }
                bind $c.f$ii <ButtonPress-1> "aie_str_selections_pressed_button $c.f$ii subface $i"
                bind $c.f$ii <ButtonRelease-1> "aie_str_selections_released_button $c.f$ii subface $i $col"
            }
        }
    }
    set fixed [smoothStrMeshDEZ get FixedEdges]
    set distr [smoothStrMeshDEZ get FixedDistributionEdges]
    if {$fixed != "" || $distr != ""} {
        incr ii
        form_label $c.edge "Edges" "$ii 0 -fill both"
        $c.edge configure -background white
        form_label $c.fixe "Fixed" "$ii 1 -fill both"
        $c.fixe configure -background white
        form_label $c.dist "Fixed Distribution" "$ii 2 -fill both"
        $c.dist configure -background white
        for {set i 1} {$i <= $nEdges} {incr i} {
            if {[lsearch $fixed $i] > -1 || [lsearch $distr $i] > -1} {
                incr ii
                form_label $c.e$ii "$i" "$ii 0 -fill both"
                set fe 0; set de 0
                if {[lsearch $fixed $i] > -1} {
                    form_label $c.fe$ii "x" "$ii 1 -fill both"
                    set fe 1
                }
                if {[lsearch $distr $i] > -1} {
                    form_label $c.de$ii "x" "$ii 2 -fill both"
                    set de 1
                }
                if {$fe && $de} {
                    set col violet
                } elseif {$fe} {
                    set col orange
                } else {
                    set col red
                }
                bind $c.e$ii <ButtonPress-1> "aie_str_selections_pressed_button $c.e$ii edge $i"
                bind $c.e$ii <ButtonRelease-1> "aie_str_selections_released_button $c.e$ii edge $i $col"
            }
        }
    }
    set layer [smoothStrMeshDEZ get LayerVertices]
    set globa [smoothStrMeshDEZ get GlobalVertices]
    if {$layer != "" || $globa != ""} {
        incr ii
        form_label $c.vertex "Vertices" "$ii 0 -fill both"
        $c.vertex configure -background white
        form_label $c.layer "Global" "$ii 1 -fill both"
        $c.layer configure -background white
        form_label $c.globa "Layer" "$ii 2 -fill both"
        $c.globa configure -background white
        form_label $c.dista "Distance" "$ii 3 -fill both"
        $c.dista configure -background white
        for {set i 1} {$i <= $nVertices} {incr i} {
            if {[lsearch $layer $i] > -1 || [lsearch $globa $i] > -1} {
                incr ii
                form_label $c.lv$ii "$i" "$ii 0 -fill both"
                if {[lsearch $globa $i] > -1} {
                    form_label $c.gv$ii "x" "$ii 1 -fill both"
                }
                if {[lsearch $layer $i] > -1 && ([info exists smooth_str_domains(layer_distance,$i)] && \
                                                 $smooth_str_domains(layer_distance,$i) != -1)} {
                    form_label $c.fe$ii "x" "$ii 2 -fill both"
                    if [info exists smooth_str_domains(layer_distance,$i)] {
                        set n $smooth_str_domains(layer_distance,$i)
                        form_label $c.ld$ii "$n" "$ii 3 -fill both"
                    }
                }
                set col [family_color_for_name [ic_str_get_family vertex $i]]
                bind $c.lv$ii <ButtonPress-1> "aie_str_selections_pressed_button $c.lv$ii vertex $i"
                bind $c.lv$ii <ButtonRelease-1> "aie_str_selections_released_button $c.lv$ii vertex $i $col"
            }
        }
    }
    form_finish +100+300
    aie_str_display_domains
    aie_str_display_subfaces
    aie_str_display_edges
}

proc aie_str_save_settings {{name ""} {element ""} {op ""}} {
    global smooth_str_domains file_name options beta_mode

    if [info exists ::smooth_str_domains(sequence_run)] return
    set file [smoothStrMeshDEZ get mbs_setting_save]
    if {$file == ""} {
        mess "Missing settings file name\n" red
        return
    }
    set RelaxDomains [smoothStrMeshDEZ get RelaxDomains]
    set refEdgeDir [smoothStrMeshDEZ get refEdgeDir]
    set planeNums [smoothStrMeshDEZ get planeNums]
    set startIndex [smoothStrMeshDEZ get startIndex]
    set endIndex [smoothStrMeshDEZ get endIndex]
    set incrIndex [smoothStrMeshDEZ get incrIndex]
    set iterIndex [smoothStrMeshDEZ get iterIndex]
    set face_method [smoothStrMeshDEZ get face_method]
    set volume_method [smoothStrMeshDEZ get volume_method]
    set parameterFaceFit [smoothStrMeshDEZ get parameterFaceFit]
    set parameterPrjLim [smoothStrMeshDEZ get parameterPrjLim]
    set parameterUseProj [smoothStrMeshDEZ get parameterUseProj]
    set itersEdges [smoothStrMeshDEZ get itersEdges]
    set itersVertices [smoothStrMeshDEZ get itersVertices]
    set gridexpansionFace [smoothStrMeshDEZ get gridexpansionFace]
    set gridexpansionVol [smoothStrMeshDEZ get gridexpansionVol]
    set parameterResFac [smoothStrMeshDEZ get parameterResFac]
    set parameterRelFac [smoothStrMeshDEZ get parameterRelFac]
    set parameterUseOrt [smoothStrMeshDEZ get parameterUseOrt]
    set parameterUseFra [smoothStrMeshDEZ get parameterUseFra]
    set version43Flag [smoothStrMeshDEZ get version43Flag]
    
    switch $refEdgeDir {
        3D { set smoothDirection 0 }
        I  { set smoothDirection 1 }
        J  { set smoothDirection 2 }
        K  { set smoothDirection 3 }
    }

    if {$smoothDirection != 0 && $planeNums == ""} {
        if {$startIndex < 1} {
            mess "Start layer must be greater than 0.\n" red
            return
        }
        if {$endIndex < $startIndex} {
            mess "End layer can not be less than start layer.\n" red
            return  
        }
        if {$endIndex < 0} {
            mess "End layer must be greater than 0.\n" red
            return  
        }
        if {$incrIndex < 1} {
            mess "Increment must be greater than 0.\n" red
            return
        }
    }           

    set the_face_methods ""
    for {set i 0} {$i < 6} {incr i} {
        append the_face_methods "[aie_str_get_smooth_method_number subface] "
    }
    set smooth_domain ""
    set face_methods ""
    set volume_methods ""
    set smooth_dir ""
    set incr_3d_plane_smooth ""
    set relax_weights_2d ""
    set relax_weights_3d ""
    set relax_weights_inner_2d ""
    set relax_weights_inner_3d "" 
    set smooth_ngh_method ""      
    set abs_dist_subf ""
    set n_abs_dist_subf ""
    set grid_exp_rate_subf_perp ""
    set grid_exp_rate_subf_1 ""
           
    set relax_faces ""
    set relaxation_zones ""
    set edge_no_global_smooth ""
    set global_vertices_opp ""
    set vertex_attrib ""
    set mesh_type 0

    set the_volume_method [aie_str_get_smooth_method_number volume]
    set nDomains [ic_str_num_entities domain]
    
    set plane_numbers ""
    if {$smoothDirection == 0} {
        set the_incr_3d_plane_smooth "-1 -1 -1 0"
    } else {
        if {$planeNums != ""} {
           set plane_len [llength $planeNums]
           for {set i 1} {$i <= $nDomains} {incr i} {
               set numbers "$plane_len "
               foreach item $planeNums {
                   append numbers "$item "
               }
               append plane_numbers "$numbers "
           }
           set the_incr_3d_plane_smooth "-1 -1 -1 $iterIndex"
        } else {
           set the_incr_3d_plane_smooth "$startIndex $endIndex $incrIndex $iterIndex"
        }
    }
           
    for {set i 1} {$i <= $nDomains} {incr i} {
        append smooth_domain "[aie_str_is_seleced_domain $i] "
        append face_methods "$the_face_methods "
        append volume_methods "$the_volume_method "
        append smooth_dir "$smoothDirection "
        append incr_3d_plane_smooth "$the_incr_3d_plane_smooth "
        append relax_weights_2d "0 0 0 0 0 0 "
        append relax_weights_inner_2d "0 0 0 0 0 0 "
        append relax_weights_inner_3d "0 0 0 0 0 0 " 
        append smooth_ngh_method "-2 "      
        append abs_dist_subf "-1.0 -1.0 -1.0 -1.0 -1.0 -1.0 "
        append n_abs_dist_subf "-1 -1 -1 -1 -1 -1 "
        append grid_exp_rate_subf_perp "-1 -1 -1 -1 -1 -1 "
        append grid_exp_rate_subf_1 "-1 -1 -1 -1 -1 -1 "
    }

    foreach n [smoothStrMeshDEZ get NonRelaxFaces] {
        append relax_faces "$n 0 "
    }

    catch { unset tmp }
    for {set i 1} {$i <= $nDomains} {incr i} {
        set tmp(set,imin,$i) 0; set tmp(set,imax,$i) 0
        set tmp(set,jmin,$i) 0; set tmp(set,jmax,$i) 0
        set tmp(set,kmin,$i) 0; set tmp(set,kmax,$i) 0
    }
           
    set topo_nums ""
    foreach n [smoothStrMeshDEZ get HoldCellHeightFaces] {
        append topo_nums "$n "
    }
    for {set i 1} {$i <= $nDomains} {incr i} {
        foreach n "imin imax jmin jmax kmin kmax" {
            foreach face_no [aie_str_get_subface_ijk $i $n] {
                if {[lsearch $topo_nums $face_no] >= 0} {
                    set tmp(set,$n,$i) 1
                }
            }
        }
    }            
    for {set i 1} {$i <= $nDomains} {incr i} {
       set imin $tmp(set,imin,$i); set imax $tmp(set,imax,$i)
       set jmin $tmp(set,jmin,$i); set jmax $tmp(set,jmax,$i)
       set kmin $tmp(set,kmin,$i); set kmax $tmp(set,kmax,$i)
       append relax_weights_3d "$imin $imax $jmin $jmax $kmin $kmax "
    }

    set edge_attrib ""
    set fixed [smoothStrMeshDEZ get FixedEdges]
    set fixed_dist [smoothStrMeshDEZ get FixedDistributionEdges]   
    foreach n $fixed {
       if {[lsearch $fixed_dist $n] >= 0} {
           lappend edge_attrib $n 3
       } else {
           lappend edge_attrib $n 2
       }
    }
    foreach n $fixed_dist {
       if {[lsearch $fixed $n] == -1} {
           lappend edge_attrib $n 1
       }
    }

    foreach n [ic_str_list_vertex_edges [smoothStrMeshDEZ get GlobalVertices]] {
        foreach e [lindex $n 0] {
            append edge_no_global_smooth "$e "
        }
        foreach v [lindex $n 1] {
            set num [lindex $v 0]
            set i [lindex $v 1]
            set j [lindex $v 2]
            set k [lindex $v 3]
            set min "[lindex $v 1] [lindex $v 2] [lindex $v 3]"
            append relaxation_zones "$num $i $j $k $i $j $k 0 "
            append global_vertices_opp "$num $min "
        }
    }

    set vertex_attrib_gui ""
    foreach n [smoothStrMeshDEZ get LayerVertices] {
        set dist -1
        if [info exists smooth_str_domains(layer_distance,$n)] {
            set dist $smooth_str_domains(layer_distance,$n)
        }
        if {$dist == "" || $dist < 0} { set dist -1 }
        append vertex_attrib "$n $dist -1 "
        append vertex_attrib_gui "$n $dist "
    }
           
    if {$smoothDirection == 0 || [smoothStrMeshDEZ get GlobalVertices] == "" || \
        [smoothStrMeshDEZ get RelaxDomains] == 1} {
        set prog_select 2
    } else {
        set prog_select 5
    }
    
    set niter 1
    set nsteps 1
    set maxlevel 3
    set sfit $parameterFaceFit
    set conditional 0
    set check_det 0
    set damping 1
    set vertex_fix 1
    set edge_freeze 1
    set wedge_check 1
    set fix_fam 0
    set multigrid2d 0
    set reduced_edge 0
    set inner_vol_sm 0
    set ns_rel 0.0
    set angle_freeze_edge 5.0
    set n_iter $itersEdges
    set interp_faces 0
    set interp_volumes 0
    set threshold_det 30.0
    set threshold_angle 80.0
    set subface_extensions ""
    set ijk_extensions ""
    set relax_subfaces $relax_faces
    set relaxation_zones $relaxation_zones
    set viol_geom_zones ""
    set viol_geom_subfaces ""
    set base_subfaces_no ""
    set meshing_law ""
    set subface_extend 0
    set direction_vector ""
    set base_regions ""
    set type_improve 0
    set type_postsm 2
    set proj_limit $parameterPrjLim
    set group_bad_elem 0
    set mesh_type 0
    set surfresolv $parameterUseProj
    set min_mxr 3.0
    set edge_no_global_smooth $edge_no_global_smooth
    set n_iter_glb $itersEdges
    set n_steps_glb $itersVertices
    set global_vertices_opp $global_vertices_opp
    set grid_exp_face $gridexpansionFace
    set grid_exp_vol $gridexpansionVol
    set min_res $parameterResFac
    set abs_dist_bnd -1
    set n_points_abs_dist_bnd -1
    set vertex_attrib $vertex_attrib
    set relaxation_factor $parameterRelFac
    set use_orthog_position $parameterUseOrt
    set use_fract_position $parameterUseFra
    set first_cell_height -1
    set last_cell_height -1
    set use_pthreads $options(n_processors)
    set isChanged 1
    set batch_params "$isChanged $file_name(mesh_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"
   
    set gui_params ""
    foreach n [::AIEnv::GUIManagement::GetLocalVariables smoothStrMeshDEZ] {
        if ![catch {smoothStrMeshDEZ get $n} v] {
            if {$n == "smoothStrMBSFileVal" || $n == "mbs_setting_load" || $n == "mbs_setting_save" || [string match mbs_setting_seq_* $n]} continue
            if {$n == "version43Flag"} continue
            append gui_params "[list $n $v] "
        }
    }
    append gui_params "[list vertex_attrib_gui $vertex_attrib_gui] "

    busy 0
    if {$version43Flag == 0} {
        set f [open $file w]
        puts $f "# Structured Multiblock Domains Setting File"
        puts $f "# This is a generated file! Do not edit."
        puts $f "#"
        puts $f "# Full Range of Structured Multiblock Domains Smoothing Parameters for Batch"
        puts $f "#"
        puts $f "batch_params"
        puts $f "$batch_params"
        puts $f ""
        puts $f "#"
        puts $f "# Full Range of Structured Multiblock Domains Smoothing Parameters for Gui"
        puts $f "#"
        puts $f "gui_params"
        puts $f "$gui_params"
        puts $f ""
        close $f
        mess "Structured Multiblock Domains setting file [lindex [file split $file] end] saved.\n" 
        return
    }

    set f [open $file w]
    if [info exists env(USER)] {
        set user $env(USER)
    } else {
        set user Dummy
    }
    puts $f "Settings Management for Smoothing and Predefined Mesh: Med"
    puts $f "Username: $user"
    puts $f "Filename: $file"
    puts $f "SmoothDomain:"
    puts $f "$smooth_domain"
    puts $f "FaceMethods:"
    puts $f "$face_methods"
    puts $f "VolumeMethods:"
    puts $f "$volume_methods" 
    puts $f "RelaxSubface:"
    puts $f "$relax_subfaces"
    puts $f "RelaxZone:"
    puts $f "$relaxation_zones"
    puts $f "ViolGeomZone:"
    puts $f "$viol_geom_zones"
    puts $f "LayerExtensionIJK:"
    puts $f "$ijk_extensions" 
    puts $f "Region:"
    puts $f "$base_regions"
    puts $f "ViolGeomSubface:"
    puts $f "$viol_geom_subfaces"
    puts $f "first_cell_height:"
    puts $f "$first_cell_height"
    puts $f "last_cell_height:"
    puts $f "$last_cell_height"
    puts $f "Niter:"
    puts $f $niter
    puts $f "Nsteps:"
    puts $f $nsteps
    puts $f "Maxlevel:"
    puts $f $maxlevel
    puts $f "Sfit:"
    puts $f $sfit
    puts $f "Conditional:"
    puts $f $conditional
    puts $f "CheckDet:"
    puts $f $check_det
    puts $f "Damping:"
    puts $f $damping
    puts $f "VertexFix:"
    puts $f $vertex_fix
    puts $f "EdgeFreeze:"
    puts $f $edge_freeze
    puts $f "WedgeCheck:"
    puts $f $wedge_check
    puts $f "Multigrid2D:"
    puts $f $multigrid2d
    puts $f "ReducedEdge:"
    puts $f $reduced_edge
    puts $f "FixFam:"
    puts $f $fix_fam
    puts $f "InnVol:"
    puts $f $inner_vol_sm
    puts $f "NsRel:"
    puts $f $ns_rel
    puts $f "AngleFreezeEdges:"
    puts $f $angle_freeze_edge
    puts $f "nItera:"
    puts $f $n_iter
    puts $f "ProjLimit:"
    puts $f $proj_limit
    puts $f "InterpolateFaces:"
    puts $f $interp_faces
    puts $f "InterpolateVolumes:"
    puts $f $interp_volumes
    puts $f "ThresholdDet:"
    puts $f $threshold_det
    puts $f "ThresholdAngle:"
    puts $f $threshold_angle
    puts $f "SubfaceExtend:"
    puts $f $subface_extensions
    puts $f "DirectionVector:"
    puts $f $direction_vector
    puts $f "SmoothDir:"
    puts $f "$smooth_dir"
    puts $f "PlaneSmooth:"
    puts $f "$incr_3d_plane_smooth"
    puts $f "relax_weights_2d:"
    puts $f "$relax_weights_2d"
    puts $f "relax_weights_3d:"
    puts $f "$relax_weights_3d"
    puts $f "relax_weights_inner_2d:"
    puts $f "$relax_weights_inner_2d"
    puts $f "relax_weights_inner_3d:"
    puts $f "$relax_weights_inner_3d"
    puts $f "SmoothOnFaces:"
    puts $f "$surfresolv"
    puts $f "MinResidual:"
    puts $f "$min_mxr"
    puts $f "StopResidual:"
    puts $f "$min_res" 
    puts $f "UnselectedMethods:"
    puts $f "$smooth_ngh_method"
    puts $f "mesh_type:"
    puts $f "$mesh_type" 
    puts $f "n_iter_glb:"
    puts $f "$n_iter_glb"
    puts $f "n_steps_glb:"
    puts $f "$n_steps_glb"
    puts $f "etmVertexGlobal:"
    puts $f "$global_vertices_opp"
    puts $f "PlaneNumbers:"
    puts $f "$plane_numbers"
    puts $f "grid_exp_face:"
    puts $f "$grid_exp_face"
    puts $f "grid_exp_vol:"
    puts $f "$grid_exp_vol"
    puts $f "ThresholdAngle:"
    puts $f "$threshold_angle"
    puts $f "ThresholdDet:"
    puts $f "$threshold_det"
    puts $f "GroupBadElem:"
    puts $f "$group_bad_elem"
    puts $f "TypeImprove:"
    puts $f "$type_improve"
    puts $f "TypePostSm:"
    puts $f "$type_postsm"
    puts $f "prog_select:"
    puts $f "$prog_select"
    puts $f "abs_dist_bnd:"
    puts $f "$abs_dist_bnd"
    puts $f "n_points_abs_dist_bnd:"
    puts $f "$n_points_abs_dist_bnd"
    puts $f "use_pthreads:"
    puts $f "$use_pthreads"
    puts $f "abs_dist_subf:"
    puts $f "$abs_dist_subf"
    puts $f "n_abs_dist_subf:"
    puts $f "$n_abs_dist_subf"
    puts $f "VertexLayer:"
    puts $f "$vertex_attrib"
    puts $f "etmEdgeGlobalSave:"
    puts $f "$edge_no_global_smooth"
    puts $f "relaxation_factor:"
    puts $f "$relaxation_factor"
    puts $f "use_orthog_position:"
    puts $f "$use_orthog_position"
    puts $f "use_fract_position:"
    puts $f "$use_fract_position"  
    puts $f "grid_exp_rate_subf_perp:"
    puts $f "$grid_exp_rate_subf_perp"
    puts $f "grid_exp_rate_subf_1:"
    puts $f "$grid_exp_rate_subf_1"
    close $f

    mess "Structured Multiblock Domains settings file [lindex [file split $file] end] saved (old 4.3 format)\n" 
    busy 0
}

proc aie_str_load_settings {{file ""} {sequence ""} {op ""}} {
    global smooth_str_domains file_name options batch_mode
    if !$batch_mode {
        if {$sequence != ""} {
            set file [smoothStrMeshDEZ get mbs_setting_seq_$sequence]
        } else {
            set file [smoothStrMeshDEZ get mbs_setting_load]
        }
    } else {
        if ![file exists $file] {
            mess "Not found: settings file $file\n" red
            return
        }
    }
    if {$file == ""} return
    set f [open $file r]
    set line [gets $f]
    close $f
    if [string match "Settings Management for Smoothing and Predefined Mesh: Med" $line] {
        if !$batch_mode {
            if {$sequence == ""} {
                smoothStrMeshDEZ aie_str_load_old_settings $file
            } else {
                mess "Unable to run setting file $file in old 4.3 format in sequence\n" red
                catch { unset ::smooth_str_domains(sequence_run) }
                return
            }
        }
    } elseif {[string match "# Structured Multiblock Domains Setting File" $line]} {
        if !$batch_mode {
            smoothStrMeshDEZ aie_str_load_new_settings $file
        } else {
            set settings [aie_str_load_new_settings $file]
            return $settings
        }
    } else {
        mess "File $file is not a \"Structured Multiblock Settings File\".\n" red
        catch { unset ::smooth_str_domains(sequence_run) }
        return
    }
    if !$batch_mode {
        aie_str_display_domains
        aie_str_display_subfaces
        # strange - display subfaces must be called twice
        aie_str_display_subfaces
        aie_str_display_edges
        smoothStrMeshDEZ aie_str_dist_reset
    }
}

proc aie_str_load_old_settings {load_file} {
    global smooth_str_domains

    if {$load_file == ""} return
    foreach n [array names convert_str_domains] { unset convert_str_domains($n) }
    foreach n [array names convert_str_domains2] { unset convert_str_domains2($n) }     
    aie_str_clear_all_selections

    busy 1
    set f [open $load_file r]
    while {![eof $f]} {
        set line [gets $f]
        switch $line {
            SmoothDomain: {
                set blocks [gets $f]
                if {[llength $blocks] > [ic_str_num_entities domain] || \
                    [llength $blocks] < [ic_str_num_entities domain]} {
                    mess "Error: The number of domains from the settings file is different from the\
                          number of domains loaded.\n" red
                    busy reset
                    close $f
                    return
                }
                set selected ""
                for {set i 0} {$i < [ic_str_num_entities domain]} {incr i} {
                    set n [expr $i + 1]
                    if [lindex $blocks $i] {
                        append selected "$n "
                    }
                }
                set smooth_str_domains(RelaxDomains,save) $selected
                smoothStrMeshDEZ set RelaxDomains $smooth_str_domains(RelaxDomains,save)
            }
            FaceMethods: {
                set line [gets $f]
                set convert_str_domains(face_method) [aie_str_get_smooth_method_name [lindex $line 0]]
            }
            Param2D:  {
                set len [gets $f]
                for {set i 0} {$i < $len} {incr i} {
                    set dummy [gets $f]
                }
            } 
            VolumeMethods:  {
                set line [gets $f]
                set convert_str_domains(volume_method) [aie_str_get_smooth_method_name [lindex $line 0]]
            } 
            Param3D:  {
                set len [gets $f]
                for {set i 0} {$i < $len} {incr i} {
                    set dummy [gets $f]
                }
            }
            EdgeAttr:  {
                set line [gets $f]
                set fixed ""; set fixed_dist ""
                foreach {n m} $line {
                    if {$m == "1"} { lappend convert_str_domains(FixedEdges) $n }
                    if {$m == "2"} { lappend convert_str_domains(FixedDistributionEdges) $n }
                    if {$m == "3"} {
                        lappend convert_str_domains(FixedEdges) $n
                        lappend convert_str_domains(FixedDistributionEdges) $n
                    } 
                }               
            }
            RelaxSubface: {
                set line [gets $f]
                set convert_str_domains(NonRelaxFaces) ""
                foreach {num relax} $line {
                    if !$relax {
                       append convert_str_domains(NonRelaxFaces) "$num "
                    }
                }
            }
            LayerExtensionNo: {
                set dummy [gets $f]
            }
            RelaxZone: {
                set dummy_later [gets $f]
            }
            ViolGeomZone: {
                set dummy [gets $f]
            }
            LayerExtensionIJK: {
                set dummy [gets $f]
            }
            Region: {
                set dummy [gets $f]
            }
            ViolGeomSubface: {
                set dummy [gets $f]
            }
            MeshingLawPar: {
                set dummy [gets $f]
                set dummy [gets $f]
            }
            first_cell_height: {
               set dummy [gets $f]
            }
            last_cell_height: {
                set dummy [gets $f]
            }     
            Niter: {
                set dummy [gets $f]
            }
            Nsteps: {
                set dummy [gets $f]
            }
            Maxlevel: {
                set dummy [gets $f]
            }
            Sfit: {
                set convert_str_domains(parameterFaceFit) [gets $f]
            }
            Conditional: {
                set dummy [gets $f]
            }
            CheckDet: {
                set dummy [gets $f]
            }
            Damping: {
               set dummy [gets $f]
            }
            VertexFix: {
                set dummy [gets $f]
            }
            EdgeFreeze: {
                set dummy [gets $f]
            }
            WedgeCheck: {
                set dummy [gets $f]
            }
            Multigrid2D: {
                set dummy [gets $f]
            }
            ReducedEdge: {
                set dummy [gets $f]
            }
            FixFam: {
                set dummy [gets $f]
            }
            InnVol: {
                set dummy [gets $f]
            }
            NsRel: {
                set dummy [gets $f]
            }
            AngleFreezeEdges: {
                set dummy [gets $f]
            }
            nItera: {
                set convert_str_domains(itersEdges) [gets $f]
            }
            ProjLimit: {
                set convert_str_domains(parameterPrjLim) [gets $f]
            }
            InterpolateFaces: {
                set dummy [gets $f]
            }
            InterpolateVolumes: {
                set dummy [gets $f]
            }
            ThresholdDet: {
                set dummy [gets $f]
            }
            ThresholdAngle: {
                set dummy [gets $f]
            }
            SubfaceExtend: {
                set dummy [gets $f]
            }
            DirectionVector: {
                set dummy [gets $f]
            }
            BaseSubfacesNo: {
                set dummy [gets $f]
            }
            SmoothDir: {
                set convert_str_domains2(refEdgeDir) [lindex [gets $f] 0]
            }
            PlaneSmooth: {
                set dummy_later [gets $f]
            }
            relax_weights_2d: {
                set dummy [gets $f]
            }
            relax_weights_3d: {
                set line [gets $f]
                set i 0
                catch { unset convert_str_domains(HoldCellHeightFaces) }
                catch { unset tmp }
                foreach {aa bb cc dd ee ff} $line {
                    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 convert_str_domains2(imin,$i) "$aa"
                    set convert_str_domains2(imax,$i) "$bb"
                    set convert_str_domains2(jmin,$i) "$cc"
                    set convert_str_domains2(jmax,$i) "$dd"
                    set convert_str_domains2(kmin,$i) "$ee"
                    set convert_str_domains2(kmax,$i) "$ff"
                    incr i
                    foreach item {imin imax jmin jmax kmin kmax} {
                        set numbers [aie_str_get_subface_ijk $i $item]
                        set ii [expr $i - 1]
                        foreach num $numbers {
                            if [info exists tmp($num)] continue
                            if $convert_str_domains2($item,$ii) {
                                lappend convert_str_domains(HoldCellHeightFaces) $num
                                set tmp($num) 1
                            }
                        }
                    }
                }
                set convert_str_domains(HoldCellHeightFaces) [lsort -integer $convert_str_domains(HoldCellHeightFaces)]
            }
            relax_weights_3d_surfaces: {
                set line [gets $f]
                if {$line != ""} {
                    set convert_str_domains(HoldCellHeightFaces) [lsort -integer $line]
                }
            }
            relax_weights_inner_2d: {
                set dummy [gets $f]
            }
            relax_weights_inner_3d: {
                set dummy [gets $f]
            }
            SmoothOnFaces: {
                set convert_str_domains(parameterUseProj) [gets $f]
            }
            MinResidual: {
                set dummy [gets $f]
            }
            StopResidual: {
                set convert_str_domains(parameterResFac) [gets $f]
            }
            UnselectedMethods: {
                set dummy [gets $f]
            }
            ParamUnselected: {
                set dummy [gets $f]
            }
            varUnselDom:  {
                set dummy [gets $f]
            }
            etmEdgeGlobal: {
                set dummy_later [gets $f]
            }
            mesh_type: {
                set dummy_later [gets $f]
            }
            n_iter_glb: {
                set convert_str_domains(itersEdges) [gets $f]
            }
            n_steps_glb: {
                set convert_str_domains(itersVertices) [gets $f]
            }
            etmVertexGlobal: {
                set convert_str_domains(GlobalVertices) [gets $f]
            }
            PlaneNumbers: {
                set line [gets $f]
                set num [lindex $line 0]
                for {set i 1} {$i <= $num} {incr i} {
                    append convert_str_domains(planeNums) "[lindex $line $i] "
                }
            }
            grid_exp_face: {
                set convert_str_domains(gridexpansionFace) [gets $f]
            }
            grid_exp_vol: {
                set convert_str_domains(gridexpansionVol) [gets $f]
            }
            GroupBadElem: {
                set dummy [gets $f]
            }
            TypeImprove: {
                set dummy [gets $f]
            }
            TypePostSm: {
                set dummy [gets $f]
            }
            prog_select: {
                set dummy [gets $f]
            }
            abs_dist_bnd: {
                set dummy [gets $f]
            }
            n_points_abs_dist_bnd: {
                set dummy [gets $f]
            }
            abs_dist_subf: {
                set dummy_later [gets $f]
            }
            n_abs_dist_subf: {
                set dummy_later [gets $f]
            }
            VertexLayer: {
                set line [gets $f]
                foreach n $line {
                    append convert_str_domains(LayerVertices) "[lindex $n 0] "
                    set convert_str_domains2(layer_distance,[lindex $n 0]) [lindex $n 1]
                }
            }
            etmEdgeGlobalSave: {
                set convert_str_domains2(EdgeGlobal) [gets $f]
            }
            relaxation_factor: {
                set convert_str_domains(parameterRelFac) [gets $f]
            }
            use_orthog_position: {
                set convert_str_domains(parameterUseOrt) [gets $f]
            }
            use_fract_position: {
                set convert_str_domains(parameterUseFra) [gets $f]
            }
            grid_exp_rate_subf_perp: {
                set dummy_later [gets $f]
            }
            grid_exp_rate_subf_perp_surfaces: {
                set dummy [gets $f]
            }
            grid_exp_rate_subf_1: {
                set dummy [gets $f]
            }
            grid_exp_rate_subf_1_surfaces: {
                set dummy [gets $f]
            }
        }
    }
    close $f

    foreach n [array names convert_str_domains] {
        smoothStrMeshDEZ set $n $convert_str_domains($n)
    }

    switch $convert_str_domains2(refEdgeDir) {
        0 { smoothStrMeshDEZ set refEdgeDir 3D }
        1 { smoothStrMeshDEZ set refEdgeDir I }
        2 { smoothStrMeshDEZ set refEdgeDir J }
        3 { smoothStrMeshDEZ set refEdgeDir K }
    }

    foreach n [array names smooth_str_domains layer_distance,*] { unset smooth_str_domains($n) }
    foreach n [smoothStrMeshDEZ get LayerVertices] {
        set smooth_str_domains(layer_distance,$n) $convert_str_domains2(layer_distance,$n)
        smoothStrMeshDEZ set ::smooth_str_domains(layer_distance,$n) $convert_str_domains2(layer_distance,$n)
    }
    mess "Structured Multiblock setting file [lindex [file split $load_file] end] loaded (old 4.3 format)\n" 
    busy 0
    
    set use_ge_settings 0
    set parts(All) "[ic_str_list_families] [ic_geo_list_families 0 1]"
    if {([lsearch $parts(All) R_0.AF.*_0] >= 0) || ([lsearch $parts(All) R_0.AFT.*_0] >= 0) || ([lsearch $parts(All) R_0.AFH.*_0] >= 0)} {
        set use_ge_settings 1
    }
    
    if !$use_ge_settings return

    mess "User defined settings for GE...\n" 
    
    if [winfo exists .ge_settings] { form_delete .ge_settings }
    set buttons { {accept} {cancel} }
    if {[string match *FC_HC_BASE* $load_file] || [string match *FC_QC_BASE* $load_file]} {
        set ::ge_setting_type CuspTE
    } elseif {[string match *FC_HO_BASE* $load_file] || [string match *FC_QO_BASE* $load_file]} {
        set ::ge_setting_type RoundTE
    } else {
        if {([lsearch $parts(All) R_0.CTIP_AF.P0.SUR_0] >= 0) && \
            ([lsearch $parts(All) R_0.CTIP_AF.N0.SUR_0] >= 0)} {
            set ::ge_setting_type CuspTE
        } else {
            set ::ge_setting_type RoundTE
        }
    }
    if {[string match *settings1* $load_file]} {
        set ::ge_setting_file Setting1
    } elseif {[string match *settings2* $load_file]} {
        set ::ge_setting_file Setting2
    } elseif {[string match *settings3* $load_file]} {
        set ::ge_setting_file Setting3
    } else {
        set ::ge_setting_file Setting1
    }
    set w [form_init .ge_settings "GE user defined" "" $buttons]
    if {$w != ""} {
        form_frame $w.1 ridge 3 "0 0 -cols -"
        form_label $w.1.1 "Airfoil Class" "0 0"
        form_radiobutton $w.1.2 "RoundTE" ::ge_setting_type RoundTE "1 0" "" ""
        form_radiobutton $w.1.3 "CuspTE" ::ge_setting_type CuspTE "2 0" "" ""
        form_radiobutton $w.1.4 "Other" ::ge_setting_type Other "3 0" "" ""
        form_frame $w.2 ridge 3 "1 0 -pady 3"
        form_label $w.2.1 "Setting file #" "0 0"
        form_frame $w.2.2 flat 0 "1 0 -pady 3"
        form_radiobutton $w.2.2.1 "1" ::ge_setting_file Setting1 "1 0" "" ""
        form_radiobutton $w.2.2.2 "2" ::ge_setting_file Setting2 "1 1" "" ""
        form_radiobutton $w.2.2.3 "3" ::ge_setting_file Setting3 "1 2" "" ""
	    form_finish +200+200
    }
    if ![form_wait .ge_settings] return
    if {$::ge_setting_type == "Other"} return
 
    set parts(RoundTE,Setting1,Both) "R_0.AF.UNTR.LPER.SUR_0 R_0.AF.UNTR.UPER.SUR_0 \
        R_0.AFT.UNTR.LPER.SUR_0 R_0.AFT.UNTR.UPER.SUR_0 R_0.AFH.UNTR.LPER.SUR_0 \
        R_0.AFH.UNTR.UPER.SUR_0"
    set parts(RoundTE,Setting1,NonRelax) ""
    set parts(RoundTE,Setting2,Both) "R_0.AFT.UNTR.LPER.SUR_0 R_0.AFT.UNTR.UPER.SUR_0"
    set parts(RoundTE,Setting2,NonRelax) ""
    set parts(RoundTE,Setting3,Both) "R_0.AFH.UNTR.LPER.SUR_0 R_0.AFH.UNTR.UPER.SUR_0"
    set parts(RoundTE,Setting3,NonRelax) ""

    set parts(CuspTE,Setting1,Both) "R_0.AF.UNTR.LPER.SUR_0 R_0.AF.UNTR.UPER.SUR_0 \
        R_0.AFT.UNTR.LPER.SUR_0 R_0.AFT.UNTR.UPER.SUR_0 R_0.AFH.UNTR.LPER.SUR_0 \
        R_0.AFH.UNTR.UPER.SUR_0 R_0.CUSP_N0.SUR_0 R_0.CUSPH_N0.SUR_0 R_0.CUSPT_N0.SUR_0 \
        R_0.CUSP_P0.SUR_0 R_0.CUSPH_P0.SUR_0 R_0.CUSPT_P0.SUR_0 R_0.CTIP_AF.P0.SUR_0 \
        R_0.CTIP_AF.N0.SUR_0 R_0.CHB_AF.P0.SUR_0 R_0.CHB_AF.N0.SUR_0"
    set parts(CuspTE,Setting1,NonRelax) ""
    set parts(CuspTE,Setting2,Both) "R_0.AFT.UNTR.LPER.SUR_0 R_0.AFT.UNTR.UPER.SUR_0"
    set parts(CuspTE,Setting2,NonRelax) "R_0.CTIP_WEDGE.N0.SUR_0 R_0.CTIP_WEDGE.P0.SUR_0"
    set parts(CuspTE,Setting3,Both) "R_0.AFH.UNTR.LPER.SUR_0 R_0.AFH.UNTR.UPER.SUR_0"
    set parts(CuspTE,Setting3,NonRelax) "R_0.CHB_WEDGE.N0.SUR_0 R_0.CHB_WEDGE.P0.SUR_0"

    smoothStrMeshDEZ set NonRelaxFaces ""
    smoothStrMeshDEZ set HoldCellHeightFaces ""
    set nonrelax ""
    set holdcell ""
    foreach p [ic_str_list_families] {
        if {[lsearch $parts($::ge_setting_type,$::ge_setting_file,Both) $p] >= 0} {
            foreach sf [ic_str_list_in_families subface $p] {
                if {[lsearch $nonrelax $sf] < 0} { lappend nonrelax $sf }
                if {[lsearch $holdcell $sf] < 0} { lappend holdcell $sf }
                continue
            }
        }
        if {[lsearch $parts($::ge_setting_type,$::ge_setting_file,NonRelax) $p] >= 0} {
            foreach sf [ic_str_list_in_families subface $p] {
                if {[lsearch $nonrelax $sf] < 0} {
                    lappend nonrelax $sf
                    continue
                }
            }
        }
    }
    
    if {$::ge_setting_file == "Setting1"} {
        set a [lsort $convert_str_domains(NonRelaxFaces)]
        set b [lsort $nonrelax]
        set s [ic_str_list_entities subface]
        foreach c $a {
            if {[lsearch $b $c] < 0  && [lsearch $s $c] >= 0} {
                set p [ic_str_get_family subface $c]       
                if {$p == "DEFAULT_SUBFACE" || $p == ""} {
                    foreach i [ic_str_get_topo_info subface $c 1] {
                        set d [lindex $i 4]
                        if {[lsearch $smooth_str_domains(RelaxDomains,save) $d] >= 0} {
                            if {[lsearch $nonrelax $c] < 0} { lappend nonrelax $c }
                            if {[lsearch $holdcell $c] < 0} { lappend holdcell $c }
                        }
                    }
                }
           }
        }
    }
    
    smoothStrMeshDEZ set NonRelaxFaces $nonrelax
    smoothStrMeshDEZ set HoldCellHeightFaces $holdcell
}

proc aie_str_load_new_settings {{file ""}} {
    global smooth_str_domains batch_mode

    if {$file == ""} return
    if $batch_mode {
        if ![file exists $file] {
            mess "Missing \"Structured Multiblock settings file\" $file\n" red
            return
        }
    }
    set f [open $file r]
    set line [string trim [gets $f]]
    close $f
    if {$line != "# Structured Multiblock Domains Setting File"} {
        mess "File $file is not a \"Structured Multiblock settings file\".\n" red
        return ""
    }
    catch { unset batch_params; unset gui_params }
    set f [open $file r]
    while {![eof $f]} {
      set line [string trim [gets $f]]
      if {$line == ""} continue
      if [string match \#* $line] continue
      if [string match batch_params $line] {
          set batch_params [string trim [gets $f]]
      }
      if [string match gui_params $line] {
          set gui_params [string trim [gets $f]]
      }
    }
    close $f

    if {![info exists batch_params] || ![info exists gui_params]} {
        mess "Unable to read \"Structured Multiblock\" settings from file $file.\n" red
        return ""
    }

    if !$batch_mode {
        busy 1
        aie_str_clear_all_selections
        foreach {n v} $gui_params {
            if {$n == "vertex_attrib_gui"} {
                foreach {num val} $v {
                     set smooth_str_domains(layer_distance,$num) $val
                     smoothStrMeshDEZ set ::smooth_str_domains(layer_distance,$num) $val
                }
            } elseif {$n == "smoothStrMBSFileVal" || $n == "mbs_setting_load" || $n == "mbs_setting_save" || \
                [string match mbs_setting_seq_* $n] || $n == "version43Flag"}  {
                continue
            } else {
                catch { smoothStrMeshDEZ set $n $v }
            }
        }
        mess "Structured Multiblock settings file [lindex [file split $file] end] loaded.\n" 
        busy 0
        return ""
    } else {
        mess "Structured Multiblock settings file [lindex [file split $file] end] loaded.\n" 
        return "$batch_params"
    }
}

proc aie_str_run_multiblock_settings {} {
    global smooth_str_domains

    foreach run "1 2 3 4 5" {
        set mbs_file [smoothStrMeshDEZ get mbs_setting_seq_$run]
        if {$mbs_file == ""} break
        if [file exists $mbs_file] {
            set ::smooth_str_domains(sequence_run) $run
            aie_str_load_settings "$mbs_file" $run ""
            if ![info exists ::smooth_str_domains(sequence_run)] return
            mess "Sequence $run: Running settings file $mbs_file\n" 
            smoothStrMeshDEZ apply
            unset ::smooth_str_domains(sequence_run)
            mess "Sequence $run: Done\n" 
        } else {
            mess "Error sequence $run: Settings file not found: $mbs_file\n" red
            break
        }
    }
}

proc aie_str_do_diag {} {
    global struct_diag

    if ![ic_str_is_loaded] return
    ic_str_clear_diagnostics

    set doms ""
    foreach d [ic_str_list_entities domain] {
        if ![info exists struct_diag($d)] {
            set struct_diag($d) 1
        }
	if $struct_diag($d) {
	    lappend doms $d
	}
    }
    set struct_diag(domlist) $doms

    busy 1
    set st [ic_str_metric $struct_diag(which) $struct_diag(domlist)]
    busy 0

    set nok [lindex $st 0]
    set nundef [lindex $st 1]
    set nbad [lindex $st 2]
    set min [lindex $st 3]
    set max [lindex $st 4]
    set totval [lindex $st 5]

    ic_str_create_diagnostic_subset

    if $nok {
	mess "Criterion = $struct_diag(which)\n"
	mess "Min = $min, max = $max, mean = [expr $totval / ($nok + 0.0)]\n"
	mess "Num = $nok, undefined = $nundef, bad = $nbad\n"
    } else {
	mess "Warning: $struct_diag(which) is not defined for any elements\n" red
	set min ""; set max ""
    }
    set struct_diag(minv) $min
    set struct_diag(maxv) $max
    set struct_diag(is_done) 1
}


proc aie_str_do_histo {{title ""} {nbars ""} {min ""} {max ""}
		      {ylim 100} {arguments ""}} {
    global struct_diag plot_window histo_width histo_height colorBand
    global histo_bad_elements histo_show histo_solid

    if ![ic_str_is_loaded] return
    if ![info exists struct_diag(is_done)] { aie_str_do_diag }

    if {$struct_diag(minv) == ""} {
	mess "Not plotting histogram\n" red
	return
    }
    ::AIEnv::GUIManagement::ConfigureConsoleZone 1; update
    if {$min == ""} { set min $struct_diag(minv) }
    if {$max == ""} { set max $struct_diag(maxv) }
    if {$title != ""} { set title $struct_diag(which) }
    if {$nbars == ""} { set nbars 20 }

    for {set i 0} {$i < $nbars} {incr i} { set histo($i) 0 }

    set numt 0
    set hist [ic_str_histogram $min $max $nbars $struct_diag(domlist)]
    for {set i 0} {$i < $nbars} {incr i} {
	set n [lindex $hist [expr $i + 1]]
	incr histo($i) $n
	incr numt $n
    }

    incr histo(0) [lindex $hist 0]
    incr histo([expr $nbars - 1]) [lindex $hist [expr $nbars + 1]]

    set diff [expr {$max - $min}]
    set vstep [expr {$diff / ($nbars + 0.0)}]

    set xvalues {}
    set yvalues {}
    set total 0
    for {set i 0} {$i < $nbars} {incr i} {
	set x [expr {$min + $i * $vstep}]
	set y $histo($i)	
	lappend xvalues $x
	lappend yvalues $y
	incr total $y
    }
    lappend xvalues $max
    
    if !$total {
	warningmsg "No values fell within the specified range ($min - $max)"
	return
    }

    catch { unset colorBand }
    catch { unset histo_bad_elements }
    set histo_width [winfo width $plot_window]
    set histo_height [expr [winfo height $plot_window] - 25]
    set histo_show 1
    set histo_solid 1
    set extra_buts [list [list done "Done" aie_str_clear_histogram]]
    make_histogram $plot_window $title $xvalues $yvalues $ylim \
	[list "Num = $total" "Min = $min" "Max = $max"] \
	aie_str_do_histo aie_str_plot_histo "" "$extra_buts" 2 12 9 1 0 0 0 0 -1
}

proc aie_str_plot_histo {w intervals args solid show} {
    global struct_diag
 
    if ![ic_str_is_loaded] return
    if ![info exists struct_diag(is_done)] { aie_str_do_diag }
    
    if $solid {
	ic_str_configure_diagnostic_subset -shade flat_wire
    } else {
	ic_str_configure_diagnostic_subset -shade wire
    }
    ic_str_configure_diagnostic_subset -visible $show 
    set tot [ic_str_set_with_diagnostic $intervals $struct_diag(domlist)]
    mess "$tot elements\n"
}

proc aie_str_clear_histogram {} {
    global histo_minv histo_maxv histo_ylim histo_nbars struct_diag
    global histogram_args  

    if [info exists struct_diag(is_done)] {
        unset struct_diag(is_done)
    }
    if [info exists histogram_args] {
        unset histogram_args
    }
    ::AIEnv::GUIManagement::ConfigureConsoleZone 0
    if ![ic_str_is_loaded] return
    ic_str_clear_diagnostics
    aie_clear_plot_window
}

proc onqualityStrMeshDEZLoad {} {    
    if ![ic_str_is_loaded] return
    ic_str_clear_diagnostics
    set qualityDomains ""
}

proc onqualityStrMeshDEZAfterLoad {} {
    global struct_diag
    set diags ""
    foreach d [lsort -dictionary [diagnostic_info]] {
        append diags "[list [lindex $d 0]] "
    }
    set qualityStrList $diags
    set quality_str Quality
    if {[trace vinfo quality_str] != ""} {
        trace vdelete quality_str w aie_str_trace_quality
    }
    trace variable quality_str w aie_str_trace_quality
    set quality_str Quality
}

proc onqualityStrMeshDEZUnLoad {} {    
    if ![ic_str_is_loaded] return
    if {[trace vinfo quality_str] != ""} {
        trace vdelete quality_str w aie_str_trace_quality
    }     
    aie_str_clear_histogram 
}

proc onqualityStrMeshDEZOK {} {
    global str_type_visible struct_diag

    if ![ic_str_is_loaded] return
    aie_str_clear_histogram
    
    set doms ""
    foreach d [ic_str_list_entities domain] {
        if {[lsearch $qualityDomains $d] >= 0} {
            set struct_diag($d) 1
        } else {
            set struct_diag($d) 0
        }
    }
    aie_str_do_histo
}

proc aie_str_trace_quality {name element op} {
    global struct_diag    
    set struct_diag(which) [qualityStrMeshDEZ get quality_str]  
}

proc aie_delete_blanked_blocks {} {
    set mess "Permanently delete blanked blocks?"
    switch -- [tk_dialog .tivc "Confirm" $mess "" 0 Yes No] {
        -1 { if [winfo exists .tivc] { top_destroy .tivc; return } }
        1 { return }
    }
    set cmd "delete_blocks blanked [volume_activename_string]"
    hex_command $cmd
}

########## Cut-Plane ########################

proc aie_hex_cutplane_update_mesh {{cur ""}} {
    global cut_info cut_saved_fam_visible cut_saved_type_visible dim_to_mesh
   
    if ![ic_hex_blocking_loaded] return
    if {[aie_active_dez] != "hexcutPlaneDEZ"} return
   
    if {$cur == "cur"} { set cur $cut_info(cur) }
   
    set ptnorm [$cur get_ptnorm]
    set args "-point [lrange $ptnorm 0 2] -norm [lrange $ptnorm 3 5]"
    append args " proj $dim_to_mesh" 
    if $cut_info(solid) {append args " -solid"}
    if $cut_info(shrink) {append args " -shrink"}
    append args " [volume_activename_string]"
    hex_command "cut_plane $args"
}

proc onhexcutPlaneDEZApply {} {
    global dynamic_info cut_info
   
    set which [::AIEnv::GUIManagement::ExclusiveGroup::GetCurrentGroupName hexcutPlaneM]
   
    set what ""; set abcd ""
    switch -- $which {
	    hexcutPlaneCf {
	        set abcd [list a b c d]
	        set what coeffs
	    }
	    hexcutPlanePn {
	        foreach v $cut_info(xyz) s {px py pz} { set cut_info($s) $v }
            set abcd [list px py pz nx ny nz]
            set what ptnorm
        }
	    hexcutPlaneCp {
	        set abcd [list pt1 pt2 pt3]
	        set what corner
	        foreach p $abcd {
		        if {[llength $cut_info($p)] == 1} {
		            set cut_info($p) [lindex $cut_info($p) 0]
		        }
	        }
	    }
    }

    if {$abcd != ""} {
	set rr [aie_cutplane_get $what]
	if {$rr == ""} {return ""}
	set did 0
	foreach v $rr s $abcd {
	    if {$s == ""} continue
	    foreach k $cut_info($s) {
		    if ![string is double -strict $k] {return ""}
	    }
	    if {$v != $cut_info($s)} {incr did}
	}
	if {$did} {
	    set pp ""
	    foreach s $abcd {eval lappend pp $cut_info($s)}
	        eval aie_cutplane_set $what $pp
	    }
    }
}

proc onhexcutPlaneDEZLoad {} {
    global cut_info dynamic_info tdv_default cut_info_backup
    variable cutPlaneMethod

    if {[hex_mesh_up_to_date 1] == 0} {
        mess "Warning: Current cut plane is out of date\n" red
    }

    if [info exists cut_info(unstr_mesh)] {
        unset cut_info(unstr_mesh)
        aie_cutplane_clear 1
    }

    set cut_info(hexa) 1
    set cut_info(solid) 1
    set cut_info(shrink) 0
    set cut_info(active) 1

    if ![info exist cut_info(cur)] {
	    # need to initialize a few variables
	    set dynamic_info(an_val) 0.5
	    set cut_info(whole) 1
	    aie_cutplane_create -cmd aie_hex_cutplane_update_mesh
    } else {
        if ![eval ic_hex_subset_exist number $cut_info(cur)] {
            set ta [tdv_active 0]
            aie_cutplane_create -cmd aie_hex_cutplane_update_mesh
            if [array exists cut_info_backup] {
                foreach n [array names cut_info_backup] {
                    set cut_info($n) $cut_info_backup($n)
                }
            } else {
                set dynamic_info(an_val) 0.5
            }
            aie_update_cutplane_scan -1
            tdv_active $ta
        }
    }

    if {![info exist cutPlaneMethod] || ($cutPlaneMethod == "")} { set cutPlaneMethod 1 }
    set cut_info(display_color) [$cut_info(cur) get -color]
    set display_type [$cut_info(cur) get -display_type]
    set cut_info(display) [expr $display_type ? 1 : 0]
    set cut_info(display_n) [expr $display_type & 0x4]
    set cut_info(display_bd) [expr $display_type & 0x1]
    set cut_info(display_tsh) [expr $display_type & 0x2]
    if {($cut_info(display_transp) < 0.999) && ($cut_info(display_tsh) > 0)} {
        set cut_info(display_tsh) 0.5
    }
   
    set w $tdv_default
    foreach {i v} {<Button-4> 50 <Button-5> -50} {
        set cut_info(binding,$w,$i) [list bind $w $i [eval bind $w $i]]
        bind $w $i "aie_update_cutplane_wheelzoom $w $v"
    }
    foreach m [list . $w] {
        set cut_info(binding,$m,<MouseWheel>) [list bind $m <MouseWheel> [eval bind $m <MouseWheel>]]
        bind $m <MouseWheel> "aie_update_cutplane_wheelzoom $w %D %X %Y"
    }
}

proc aie_hex_cut_plane_clear {{clear 0}} {
    global tdv_default cut_info cut_info_backup
   
    foreach {n v} [array get cut_info binding,*] {
        eval $v
        unset cut_info($n)
    }
    foreach {n v} [array get cut_info] {
        set cut_info_backup($n) $cut_info($n)
    }
    aie_cutplane_clear $clear
    if [ic_hex_blocking_loaded] { hex_command "cut_plane erase" }
}

proc onhexcutPlaneDEZUnLoad {} {
    aie_hex_cut_plane_clear
}

proc onhexcutPlaneITLoad {} {
   aie_cutplane_set pick

   hexcutPlaneDEZ set cutPlaneMethod 1
}

proc onhexcutPlane3PLoad {} {
   aie_cutplane_set 3pts

   hexcutPlaneDEZ set cutPlaneMethod 1
}

proc onhexcutPlaneSYLoad {} {
   aie_cutplane_set preset 1

   hexcutPlaneDEZ set cutPlaneMethod 1
}

proc onhexcutPlaneSZLoad {} {
   aie_cutplane_set preset 2

   hexcutPlaneDEZ set cutPlaneMethod 1
}

proc onhexcutPlaneSXLoad {} {
   aie_cutplane_set preset 0

   hexcutPlaneDEZ set cutPlaneMethod 1
}

############################################

proc aie_hex_ref_uns_mesh {} {
    global file_name
    
    if ![ic_hex_blocking_loaded] { return 1 }
    if ![ic_uns_is_loaded] {
        msg ERROR "No unstruct mesh loaded"
        return 1
    }
    mess "Updating Reference Mesh..."
    hex_command "update_ref_uns_mesh"
    mess "done\n"
    return 0
}

proc aie_hex_update_index_form {set_min_max {reset_min_max 0}} {
    global plot_window index_form index_min index_max index_dims
    global index_control_min_backup index_control_max_backup

    if {![info exists index_form] || ![winfo exists $index_form]} {
        catch { unset index_control_max_backup; unset index_control_min_backup }
        return
    }
    if $set_min_max {
        catch { unset index_control_max_backup; unset index_control_min_backup }
        foreach i [array names index_min] {
            set index_control_min_backup($i) $index_min($i)
        }
        foreach i [array names index_max] {
            set index_control_max_backup($i) $index_max($i)
        }
        return
    }
    if {![info exists index_control_min_backup] || ![info exists index_control_max_backup]} return

    if [info exists index_dims] {
        foreach i [array names index_control_min_backup] {
            set index_min($i) $index_control_min_backup($i)
        }
        foreach i [array names index_control_max_backup] {
            if [info exists index_max($i)] {
                if {$index_max($i) != $index_control_max_backup($i)} {
                    if $reset_min_max { set index_control_max_backup($i) $index_max($i) }
                }
            }
            set index_max($i) $index_control_max_backup($i)
       }
       unset index_control_min_backup; unset index_control_max_backup
       hex_update_display
    }
}

proc aie_hex_sketching_mode {} {
    global beta_mode hex_option

    if {$beta_mode && ![ic_geo_is_loaded]} {
        if {[info exists hex_option(sketching_mode)] && $hex_option(sketching_mode) == "1"} {
            return 1
        }
    }
    return 0
}

proc aie_hex_sketch_display_faces {on} {
    global last_line display_flag dim_to_mesh
    
    hex_command "n_nodes_edge"
    set solid ""
    set ndim [llength $last_line]
    if $on {
        set erase ""
        if {$display_flag(mesh_mesh) == 2} { set solid solid }
    } else {
        set erase erase
    }
    for {set d 0} {$d < $ndim} {incr d} {
        hex_command "scan_plane \" $d 0 0 \" $erase proj $dim_to_mesh $solid m [family_activename_string]"
    }
}

proc aie_hex_display_marked_blocks {{blocks ""}} {
    global display_flag

    if {$blocks == ""}  {
        hex_command "display_elements erase"
        if $display_flag(block) { hex_update_display block }
        return
    }
    hex_command "mark_blocks unmark" 0
    foreach b $blocks {
        hex_command "mark_blocks superblock $b"
    }
    set del_opts "marked m [volume_activename_string] -solid super no_shrink"
    hex_command "display_elements $del_opts"
    hex_command "mark_blocks unmark" 0
}

proc aie_hex_create_display_subset {type {ents ""}} {
    global hex_display_subset beta_mode
    
    if ![ic_hex_blocking_loaded] return
    if {$ents == ""} return 
    aie_hex_delete_display_subset
    set sub [format %d [ic_hex_create_subset selection]]
    if {$type == "edge"} {
        foreach f $ents {
            change_subset number $sub $type add select new_format [list $f]
        }
    } else {
        foreach f $ents {
            change_subset number $sub $type add select "" [list $f]
        }
    }
    set disp_opts ""
    switch $type {
        vertex {
            set disp_opts " numbers"
        }
	    edge {
	        set disp_opts "[range_string] m [volume_activename_string] -not_blanked"
	    }
	    face {
	         set disp_opts ""
	    }
	    block {	   
	        set disp_opts "display_elements [range_string] m [volume_activename_string] super -not_blanked"
	    }
    }
    if {[format %d [ic_hex_mesh_dimension]] == 3 && $type == "face"} {
        ic_hex_set_linewidth2 2
    }
    eval ic_hex_display_subset number $sub $type $disp_opts
    if {[format %d [ic_hex_mesh_dimension]] == 3 && $type == "face"} {
        ic_hex_set_linewidth2 1
    }
    set hex_display_subset $sub
}

proc aie_hex_delete_display_subset {} {
    global hex_display_subset beta_mode
    
    if ![ic_hex_blocking_loaded] return
    if {![info exists hex_display_subset] || $hex_display_subset == ""} return 
    if ![eval ic_hex_subset_exist number $hex_display_subset] return
    ic_hex_delete_subset number $hex_display_subset
    set hex_display_subset ""
}

proc aie_hex_split_block3d_absolute {edge num_splits} {

    if ![ic_hex_blocking_loaded] return
    if {[format %d [ic_hex_mesh_dimension]] != 3} {
        mess "Can not split block in 2D\n" red
        return
    }
    if ![llength [ic_hex_get_edge_blocks [lindex $edge 0] [lindex $edge 1]]] {
        mess "Selected edge $edge must be an edge of a mapped or swept block\n" red
        return
    }

    ic_hex_undo_major_start "split_mapped_block3d_absolute"
    ic_hex_split_block3d_absolute $edge $num_splits
    ic_hex_undo_major_end "split_mapped_block3d_absolute"
    hex_update_display
}

proc aie_hex_get_block_type {block} {
    global use_output_blocks

    if $use_output_blocks {
        return "[string trimright [ic_hex_print_block_type_info $block output_blocks] \n]"             
    } else {
        return "[string trimright [ic_hex_print_block_type_info $block] \n]"
    }
}

proc aie_hex_show_piping_dez {} {

    aie_closeProject 1
    if [ic_geo_is_loaded] { mess "Unloading geometry\n"; ic_unload_tetin }
    if [ic_hex_blocking_loaded] { mess "Unloading blocking\n"; ic_hex_unload_blocking }

    pipesFromFileDEZ show
}

proc onpipesFromFileDEZLoad {} {

    if ![ic_hex_blocking_loaded] { 
        set param_init_height ""
        set param_ogrid_height ""
        set param_height_ratio ""
        set param_max_length ""
        set param_l_axial ""
        set param_n_across ""
        set param_target_size ""
        set pipe_input_file ""
        set single 1
   }
}

proc onpipesFromFileDEZAfterLoad {} {

}

proc onpipesFromFilenameFinish {} {
    global is_win
   
    set param_init_height ""
    set param_ogrid_height ""
    set param_height_ratio ""
    set param_max_length ""
    set param_l_axial ""
    set param_n_across ""
    set param_target_size ""
    
    if {$pipe_input_file == ""} return
    
    if $is_win {
        set pipe_input_file [win_shortname $pipe_input_file]
    }
    
    aie_hex_display_pipe_params
}

proc aie_hex_display_pipe_params {} {
    global tdv_default pipe_marker_images
    
    set pipe_input_file [pipesFromFileDEZ get pipe_input_file]
    if {$pipe_input_file == ""} return
    
    set fp [open $pipe_input_file r]
    while {[gets $fp line] > 0} {
        if {[string match "param *" $line ]} {
            set type [lindex $line 1]
            set value [lindex $line 2]
            pipesFromFileDEZ set param_$type $value
        }
    }
    close $fp
}

proc aie_hex_display_pipe_markers {} {
    global tdv_default pipe_marker_images
    
    set pipe_input_file [pipesFromFileDEZ get pipe_input_file]
    if {$pipe_input_file == ""} return
    
    if ![pipesFromFileDEZ get marker] aie_hex_clear_pipe_markers
    
    set fp [open $pipe_input_file r]
    while {[gets $fp line] > 0} {
        if [pipesFromFileDEZ get marker] {
            if {[string match "point *" $line ]} {
                set centroid [lrange $line 2 4]
                set im [tdv_point_im -point "$centroid" -size 3 -color white]
                $tdv_default add_image $im
                lappend ::pipe_marker_images $im
                set im [tdv_text_im -point "$centroid" -text [lindex $line 1] -color white]
                $tdv_default add_image $im
                lappend ::pipe_marker_images $im
            }
        }
    }
    close $fp
}

proc onpipesFromFileDEZUnLoad {} {
    aie_hex_clear_pipe_markers
}

proc onpipesFromFileDEZApply {} {
    if {$pipe_input_file == ""} {
        mess "Missing pipe blocking input file\n" red
        return
    }
    
    aie_hex_clear_pipe_markers
    aie_hex_display_pipe_params
    pipesFromFileDEZ aie_hex_create_piping_network
    aie_hex_display_pipe_markers
    pipesFromFileDEZ show
    pipesFromFileDEZ setdirty
}

proc aie_hex_create_piping_network {} {
    
    if [ic_geo_is_loaded] { mess "Unloading geometry\n"; ic_unload_tetin }
    if [ic_hex_blocking_loaded] { mess "Unloading blocking\n"; ic_hex_unload_blocking }

    set here [pwd]

    set temp_dir "[ic_temp_dir]/__pipe__temp__[pid]__"
    aie_hex_rm_temp_dir $temp_dir
    ic_mkdir $temp_dir 
    ic_chdir $temp_dir
    
    set error 0
    
    if [catch { ic_run_application_exec . icemcfd pipes "\"$pipe_input_file\" -b \"pipe.blk\" -t \"pipe.tin\" -r \"pipe.rpl\" -f \"pipe.fbc\" -o -trans -nomesh" } res] {
        mess "Error: $res\n" red
        ic_chdir $here
        aie_hex_rm_temp_dir $temp_dir
        return
    } 
    
    if ![file exists pipe.tin] { set error 1; mess "Error: failed to create pipe geometry file\n" red }
    if ![file exists pipe.rpl] { set error 1; mess "Error: failed to create pipe replay file\n" red }

    if $error {
        ic_chdir $here
        aie_hex_rm_temp_dir $temp_dir
        return  
    }
    
    if [file exists pipe.tin] {
        mess "Loading geometry file...\n"
        ic_load_tetin pipe.tin
    }
    if [file exists pipe.rpl] {
        mess "Running replay file...\n"
        source pipe.rpl
    }
    
    if [ic_hex_blocking_loaded] {
        if $single {
            ic_hex_unload_blocking
            aie_after_close_blocking
            ic_hex_restore_blocking "$temp_dir/pipe.blk"
        } else {
            set topo [lindex [ic_hex_print_topo_tree] end]
            regsub -all " " $topo "" topo
            ::AIEnv::GUIManagement::Tree::ToggleTopoVisibility topo $topo 1
        }
        mess "Creating pre-mesh...\n" 
        eval ic_hex_create_mesh [ic_geo_list_parts "" 1] proj 2 dim_to_mesh 3
    } else {
        mess "Error: failed to create pipe blocking\n" red 
        set error 1
    }
    
    if $error {
        ic_chdir $here
        aie_hex_rm_temp_dir $temp_dir
        return  
    }
    
    aie_afterStuffLoaded
    
    ic_chdir $here
    aie_hex_rm_temp_dir $temp_dir
    
    if [ic_geo_is_loaded] {
        aie_viewInfo geometry
    }
    if [ic_hex_blocking_loaded] {
        mess "\n--- Blocking Info ---"
	    hex_number_of_blocks_info
	    aie_hex_mesh_size
    }
}

proc aie_hex_rm_temp_dir {temp} {
    if {[file exists $temp] && [file isdirectory $temp]} { 
        ic_rm_r $temp
    }
}

proc aie_hex_clear_pipe_markers {} {
    global pipe_marker_images
    
    if [info exists ::pipe_marker_images] {
        foreach im $::pipe_marker_images { $im delete }
        unset ::pipe_marker_images
    }
}



