proc rmi_GetTriangulationTolerance {{tetin_file ""}} {

  if {$tetin_file == ""} {
    ic_rmi_triangulation_tol ""
    return
  }
  set tri ""
  if {[file exists $tetin_file] && [file isfile $tetin_file]} {
    set f [open $tetin_file r]
    while {![eof $f]} {
      set line [string toupper [gets $f]]
      if [string match "SET_TRIANGULATION_TOLERANCE*" $line] {
        set tri [lindex $line 1]
        break
      }
    }
    close $f  
  }
  ic_rmi_triangulation_tol $tri
}

proc rmi_RenameStationFiles {old new} {
global rmi

  if [file exists $old] {
    cmd_rename $old $new
  }
}

proc rmi_RemoveStationFiles {path} {
global rmi

  if [file exists $path] {
    cmd_rm_r ${path}
  }
}

proc rmi_CheckSurfFamily {file name} {
global rmi
    
  set found 0
  set name [string toupper $name]
  set f [open $file r]
  while {![eof $f]} {
    set line [string toupper [gets $f]]
    if [string match "*DEFINE_SURFACE*" $line] {
      if [string match "*FAMILY*$name*" $line] {
        set found 1
        break
      }
    }
  }
  close $f
  ic_rmi_answer_surf_family $found
}

proc rmi_CreateStationFiles {path} {
global rmi

  if ![file exists $path] {
    cmd_mkdir $path
    rmi_ShowMessage "Directory $path created.\n"
    foreach item { domains mesh import transfer parts } {
      cmd_mkdir ${path}/$item
    }
  } else {
    foreach item { domains mesh import transfer parts } {
      if ![file exists ${path}/$item] { 
        cmd_mkdir ${path}/$item
      }
    }    
  }
}

proc rmi_ic3m_quad {{Volume ""} {Surface ""} {Result ""}} {
  global unstruct_merge cur_uns_map
  global uns_type_visible batch_mode
  ic_unload_mesh 
  foreach par {Volume Surface} {
    set file [subst $[subst $par]]
    if ![llength $file] {
      set $par [tk_getOpenFile -title $par]
      set file [subst $[subst $par]]
    }
    if ![file exists $file] {
      if !$batch_mode {
        tk_messageBox -type ok -message "Cannot read file for $par"
      }
      return
    }
  } 
  ic_load_unstruct $Volume
  set del_fam 0
# delete all COMMON_SURFACE_QUAD
    foreach name [ic_geo_list_families] {
    if {[string match common_surface_qbnd* $name] ||
        [string match COMMON_SURFACE_QBND* $name] ||
        [string match common_surface_quad_* $name] ||
        [string match COMMON_SURFACE_QUAD_* $name] } {
      set del_fam 1
      ic_delete_elements family $name
    }
  }
  if $del_fam {
    ic_save_unstruct $Volume
  }
  ic_unload_mesh 
  ic_load_unstruct $Surface
  ic_change_tri_quad skew 160 warp 20 iters 6 conver 0.25 improvement 0 quadrization 0
  ic_load_unstruct $Volume

  foreach name [ic_geo_list_families] {
    if {$name == "HEAD" ||
        $name == "head" ||
        [string match common_surface_quad_* $name] ||
        [string match COMMON_SURFACE_QUAD_* $name] } {
    }
  }

  set uns_type_visible(QUAD_4) 1
  set uns_type_visible(TRI_3) 1
  ic_uns_subset_create copy_tmp 0 visible
  eval { global uns_cur; [$uns_cur get_map copy_tmp] promote_type 2 }
  # update_uns_visible
# force merge regardless of dimension
  set n [ic_uns_merge_nodes copy_tmp 0.001 "0 0 0" "0 0 0" 0 1 1]
  ic_uns_subset_delete copy_tmp
  if [lindex $n 0] {
    mess "Degenerated elements! Check mesh.\n" red
  }
  if [lindex $n 1] {
    mess "Surface elements became internal.\n" red
  }
  mess "[lindex $n 2] nodes merged.\n" blue

  if ![string length $Result] {
    set Result [tk_getSaveFile -title "Final mesh"]
  }
  if [string length $Result] {
    ic_save_unstruct $Result
  }
}

# merge the valve and port meshes (Chadice) and create the
# extrusion regions
proc rmi_chad_extrude_base_mesh { merge_file } {
global rmi batch_mode

  ic_undo_stop
  ic_unload_mesh
  rmi_SetMeshParams 1
  set nValves [expr $rmi(intake_number_valve) + $rmi(exhaust_number_valve)]
  set sel ""
  set bocofile ""
  set found 1
  set check_file 1
# chadice base mesh
  set type_outp 11
  for { set i 1 } { $i <= $nValves } { incr i } {
    set check_file 1
    if { $rmi(intake_number_valve) > 0 && \
         $i <= $rmi(intake_number_valve) } {
      set intake_v 1
      set i_v $i
    } else {
      set intake_v 0
      set i_v [expr $i - $rmi(intake_number_valve)]
    }
    if { ($intake_v && \
          !$rmi(intake_motion)) || \
         (!$intake_v && \
          !$rmi(exhaust_motion)) } {
      set check_file 0
    }
    if { $check_file } {
      set file "$rmi(configuration)/static_mesh/domains/domain_port${i}"
      if ![ file exists $file ] { 
        rmi_ShowMessage "No $file found.\n"
      } else {
        lappend sel "$file"
        lappend bocofile $rmi(configuration)/static_mesh/mesh/fam_boco_tvalve${i}
      }
      set file "$rmi(configuration)/static_mesh/domains/domain_valve${i}"
      if ![ file exists $file ] { 
        rmi_ShowMessage "No $file found.\n"
        set found 0
      } else {
        lappend sel "$file"
        lappend bocofile $rmi(configuration)/static_mesh/mesh/fam_boco_hvalve${i}
      }
    }
  }
  if !$found {
    rmi_ShowMessage "Compute mesh before.\n"
    ic_undo_start
    return
  }
      
  busy 1
  set uns 0
  foreach dom $sel {
    if [ file exists $dom ] {
      if !$batch_mode { rmi_ShowMessage "Loading file $dom ..." }
      set uns [ic_load_unstruct [list $dom]]
      if !$batch_mode { rmi_ShowMessage " done.\n" }
    } else {
      rmi_ShowMessage "File $dom does not exist.\n"
    }
  }
  set uns_mesh_ex 0
  if $uns {
    set uns_mesh_ex 1
    ic_save_unstruct $merge_file
    initialize_unstruct_visibility
    disp_new_stuff

# substitute valve shells by vc1 shells
    ic_unload_mesh
    set ret_subst [ic_rmi_substitute_fam "$merge_file" $type_outp $rmi(chadice)]
  }
  ic_unload_mesh
# merge valve meshes and port meshes on S0 families
  rmi_merge_valve_port $merge_file
  ic_undo_start
  busy 0
}

proc rmi_switch_display_to_surf {} {
  switch_to_subset ""
  set types ""
  lappend types "QUAD_4"
  lappend types "TRI_3"
  ic_uns_subset_add_families_and_types visible all $types
# save current map in rmi
  ic_rmi_save_map visible
}

proc rmi_switch_display_all {} {
  switch_to_subset ""
  ic_uns_subset_add_families_and_types visible all all
# save current map in rmi
  ic_rmi_save_map visible
}

proc rmi_chad_set_node_map { node_map numlayers } {
  global n_maps_extrude

  set n_maps 0
  ic_rmi_nodes_storage_init
  set n [ rmi_set_node_map  $node_map $n_maps 1 1 "" \
                            $numlayers 111 0 0  ]
  if { $n < 0 } {
    rmi_ShowMessage "Domain file seems to be corrupt.\n"
    rmi_ShowMessage "Probably the number of layers is different.\n"
    rmi_ShowMessage "Please recreate Domain file.\n"
    return
  }
  if $n {
    incr n_maps
  }
  set n_maps_extrude $n_maps
}

proc rmi_create_display_map { make_cut loaded_display clear_map } {
  switch_to_subset ""
  ic_rmi_create_display_map $make_cut $loaded_display $clear_map
}

proc rmi_merge_conn_families { name_conn_pref } {
  set families ""
  set nameup [string toupper $name_conn_pref]
  set namelow [string tolower $name_conn_pref]
  foreach name [ic_geo_list_families] {
    if {[string match ${nameup}* $name] || [string match ${namelow}* $name]} {
      lappend families $name
    }
  }
  if { $families != "" } {
    ic_merge_meshes $families ""
  }
}

# merge hex and quad mesh together
proc rmi_merge_hex_quad { hex_file quad_file } {

  set n 0
  ic_unload_mesh
  if {[file exists $hex_file] && [file exists $quad_file]} {
    set tol "0.001"
    set n [ic_rmi_merge_hex_quad_mesh $hex_file $quad_file $tol]
    if {$n > 0} {
      ic_save_unstruct $hex_file
    }
  }
  mess "$n merged nodes were eliminated.\n"
  ic_rmi_answer_surf_family $n
  ic_unload_mesh
}

proc rmi_separate_comb_piston { file_comb_piston file_comb file_piston save_csq change_fam } {

  ic_unload_mesh
  if [ic_load_unstruct $file_comb_piston] {
    set tmp_fam ""
    if $save_csq {
      set families ""
      set chk_fam "common_surface_2"
      set pid [ic_uns_lookup_family_pid $chk_fam]
      if { $pid != "" } {
        lappend families $chk_fam
      }
      for { set i 0 } { $i <= 50 } { incr i } {
        set chk_fam "common_surface_quad_$i"
        set pid [ic_uns_lookup_family_pid $chk_fam]
        if { $pid != "" } {
          lappend families $chk_fam
        } else {
          set chk_fam "csq$i"
          set pid [ic_uns_lookup_family_pid $chk_fam]
          if { $pid != "" } {
            lappend families $chk_fam
          }
        }
        set chk_fam "common_surface_qbnd$i"
        set pid [ic_uns_lookup_family_pid $chk_fam]
        if { $pid != "" } {
          lappend families $chk_fam
        } else {
          set chk_fam "csqb$i"
          set pid [ic_uns_lookup_family_pid $chk_fam]
          if { $pid != "" } {
            lappend families $chk_fam
          }
        }
        if { $families != "" } {
          set tmp_fam "tmp_trash"
          ic_rmi_extrude families "$families" dir "0.0 0.0 1.0" \
                      space 1.0 numlayers 1 \
                      volf $tmp_fam sidef $tmp_fam topf $tmp_fam \
                      del_orig 0
        }
      }
    }
    ic_delete_elements family bowl
    set ok [ ic_rmi_diag diag_type standalone fix "1" ]
    if { $save_csq && $tmp_fam != "" } {
      ic_delete_elements family $tmp_fam
      if { $change_fam } {
        set command "ic_change_family_elements"
        foreach fam $families {
          append command " family ${fam}"
        }
        append command " newfam head"
        eval $command
      }
    }
    ic_save_unstruct $file_comb
    ic_unload_mesh
    ic_load_unstruct $file_comb_piston
    ic_delete_elements family hvol
    set ok [ ic_rmi_diag diag_type standalone fix "1" ]
    if { $change_fam } {
      ic_change_family_elements family head newfam cdfp
    }
    ic_save_unstruct $file_piston
    ic_unload_mesh
  }
}

proc rmi_set_dynamic_files { what } {
global rmi n_maps_extrude

  set n_maps 0
  set n_maps_extrude 0
  ic_rmi_nodes_storage_init
  set n [ rmi_set_node_map  "map_rmi_ICCH" $n_maps 1 1 "" \
                              $rmi(number_layers_cyl_BDC) 1 0 0  ]
  if { $n < 0 } {
    rmi_ShowMessage "Base mesh file seems to be corrupt.\n"
    rmi_ShowMessage "Probably the number of layers is different.\n"
    rmi_ShowMessage "Please recreate base mesh file.\n"
    return $n
  }
  if $n {
    incr n_maps
  }
  if { $what == "all" } {
    set chk_fam "BOWL"
    set pid [ic_uns_lookup_family_pid $chk_fam]
    if { $pid != "" } {
      set families [ list $chk_fam ]
      set n [ rmi_set_node_map  "" $n_maps 1 1 $families \
                                  -1 2 0 0  ]
      if { $n < 0 } {
        rmi_ShowMessage "Base mesh file seems to be corrupt.\n"
        rmi_ShowMessage "Please recreate base mesh file.\n"
        return $n
      }
      if $n {
        incr n_maps
      }
    }

    set chk_fam "HEAD"
    set pid [ic_uns_lookup_family_pid $chk_fam]
    if { $pid != "" } {
      set families [ list $chk_fam ]
      set n [ rmi_set_node_map  "" $n_maps 1 1 $families \
                                  -1 3 0 0  ]
      if { $n < 0 } {
        rmi_ShowMessage "Base mesh file seems to be corrupt.\n"
        rmi_ShowMessage "Please recreate base mesh file.\n"
        return $n
      }
      if $n {
        incr n_maps
      }
    }
    set families ""
    set chk_fam "HEAD"
    set pid [ic_uns_lookup_family_pid $chk_fam]
    if { $pid != "" } {
      lappend families $chk_fam
    }
    for {set i 1} {$i <= $rmi(intake_number_valve)} {incr i} {
      set chk_fam "BOT1${i}"
      set pid [ic_uns_lookup_family_pid $chk_fam]
      if { $pid != "" } {
        lappend families $chk_fam
      }
    }
    for {set i 1} {$i <= $rmi(exhaust_number_valve)} {incr i} {
      set chk_fam "BOT2${i}"
      set pid [ic_uns_lookup_family_pid $chk_fam]
      if { $pid != "" } {
        lappend families $chk_fam
      }
    }
    if { $families != "" } {
      set n [ rmi_set_node_map  "" $n_maps 0 0 $families \
                                  -1 3 0 0  ]
      if { $n < 0 } {
        rmi_ShowMessage "Base mesh file seems to be corrupt.\n"
        rmi_ShowMessage "Please recreate base mesh file.\n"
        return $n
      }
      if $n {
        incr n_maps
      }
    }
  }

  for {set i 1} {$i <= $rmi(intake_number_valve)} {incr i} {
    set node_map "map_rmi_CV11${i}"
    set n [ rmi_set_node_map  $node_map $n_maps 1 1 "" \
                                $rmi(intake_valve_nlayers) 4 1 $i  ]
    if { $n < 0 } {
      rmi_ShowMessage "Base mesh file seems to be corrupt.\n"
      rmi_ShowMessage "Probably the number of layers is different.\n"
      rmi_ShowMessage "Please recreate base mesh file.\n"
      return $n
    }
    if $n {
      incr n_maps
    }

    set node_map "map_rmi_CBV1${i}"
    set n [ rmi_set_node_map  $node_map $n_maps 1 1 "" \
                                $rmi(number_layers_cyl_BDC) 5 1 $i  ]
    if { $n < 0 } {
      rmi_ShowMessage "Base mesh file seems to be corrupt.\n"
      rmi_ShowMessage "Probably the number of layers is different.\n"
      rmi_ShowMessage "Please recreate base mesh file.\n"
      return $n
    }
    if $n {
      incr n_maps
    }
    if { $what == "all" } {
      set families ""
      set chk_fam "VBK1${i}"
      set pid [ic_uns_lookup_family_pid $chk_fam]
      if { $pid != "" } {
        lappend families $chk_fam
      }
      set chk_fam "VVL1${i}"
      set pid [ic_uns_lookup_family_pid $chk_fam]
      if { $pid != "" } {
        lappend families $chk_fam
      }
      if { $families != "" } {
        set n [ rmi_set_node_map  "" $n_maps 1 1 $families \
                                  -1 6 1 $i  ]
        if { $n < 0 } {
          rmi_ShowMessage "Base mesh file seems to be corrupt.\n"
          rmi_ShowMessage "Please recreate base mesh file.\n"
          return $n
        }
        if $n {
          incr n_maps
        }
      }
    }
  }
  for {set i 1} {$i <= $rmi(exhaust_number_valve)} {incr i} {
    set node_map "map_rmi_CV12${i}"
    set n [ rmi_set_node_map  $node_map $n_maps 1 1 "" \
                                $rmi(exhaust_valve_nlayers) 4 2 $i  ]
    if { $n < 0 } {
      rmi_ShowMessage "Base mesh file seems to be corrupt.\n"
      rmi_ShowMessage "Probably the number of layers is different.\n"
      rmi_ShowMessage "Please recreate base mesh file.\n"
      return $n
    }
    if $n {
      incr n_maps
    }

    set node_map "map_rmi_CBV2${i}"
    set n [ rmi_set_node_map  $node_map $n_maps 1 1 "" \
                                $rmi(number_layers_cyl_BDC) 5 2 $i  ]
    if { $n < 0 } {
      rmi_ShowMessage "Base mesh file seems to be corrupt.\n"
      rmi_ShowMessage "Probably the number of layers is different.\n"
      rmi_ShowMessage "Please recreate base mesh file.\n"
      return $n
    }
    if $n {
      incr n_maps
    }
    if { $what == "all" } {
      set families ""
      set chk_fam "VBK2${i}"
      set pid [ic_uns_lookup_family_pid $chk_fam]
      if { $pid != "" } {
        lappend families $chk_fam
      }
      set chk_fam "VVL2${i}"
      set pid [ic_uns_lookup_family_pid $chk_fam]
      if { $pid != "" } {
        lappend families $chk_fam
      }
      if { $families != "" } {
        set n [ rmi_set_node_map  "" $n_maps 1 1 $families \
                                  -1 6 2 $i  ]
        if { $n < 0 } {
          rmi_ShowMessage "Base mesh file seems to be corrupt.\n"
          rmi_ShowMessage "Please recreate base mesh file.\n"
          return $n
        }
        if $n {
          incr n_maps
        }
      }
    }
  }
  set n_maps_extrude $n_maps
  return 0
}

proc rmi_set_node_map { name_node_map n_maps get_node get_node_number \
                        families n_lay type type_valve number } {
  set n 0
  if {$name_node_map != ""} {
    if [ic_uns_subset_exists $name_node_map] {
      set n [ic_rmi_read_node_map $name_node_map \
     	   1 $n_maps $get_node $get_node_number "" \
           $n_lay $type $type_valve $number]
    }
  } else {
    if [ic_uns_subset_exists visible] {
      ic_uns_subset_add_families_and_types visible $families MIXED
      set n [ic_rmi_read_node_map visible \
             0 $n_maps $get_node $get_node_number "" \
             $n_lay $type $type_valve $number]      
    }
  }
  return $n
}
