# This file contains batch processing functions for cart3D
#
# Copyright (c) 1997 Pacific Marketing and Consulting, Inc,
#       and ICEM Systems, GmbH.  All rights reserved.
# Author:  Ganesan HariharaPuthiran, ganesan.hariharaputhiran@ansys.com
# This file contains special comments of the form ## html ... which are
# used to automatically generate documentation

## Cart-3D mesher auto inputs - default bbox refinement etc
## <li> <b>c3dint_file</b> <i>filename</i> (required) : intersected tri file - .i.tri file
## <li> <b>nominal_radius</b> <i>value</i> (optional) : mesh region, default = 1
## <li> <b>num_div</b> <i>ni nj nk</i> (required) : triplet of initial start divisions
## default = "5 5 5"
## <li> <b>symX</b> <i>value</i> (optional) : 1 if model is symmetric in X-dir
## <li> <b>symY</b> <i>value</i> (optional) : 1 if model is symmetric in Y-dir
## <li> <b>symZ</b> <i>value</i> (optional) : 1 if model is symmetric in Z-dir
## <li> <b>density_poly</b> <i>value</i> (optional) : 1 to create density polygons 

proc ic_mesh_cart3d_auto_inputs { c3dint_file args } {
    global projlib batch_mode

    if ![lindex [check_licenses_enabled] 0] {
	error "No med license was obtained"
    }
    
    if ![file exists $c3dint_file] {
	mess "Error: Could not find the Tri File: $c3dint_file\n" red
	mess "Run intersect first to create the cart-3D input Tri file\n" green
	return 0
    }

    set nominal_radius 1
    set num_div   "5 5 5"
    set max_ref   11
    set symX      0
    set symY      0
    set symZ      0
    set density_poly 1

    foreach {n v} $args {
	switch $n {
	    nominal_radius - num_div - max_ref - symX - symY - symZ - density_poly {
		set $n $v 
	    }
	    default {
		mess "Warning: Unknown Option\n"
	    }
	}
    }

    set ndiv_x [lindex $num_div 0]
    set argv [list autoInputs -t $c3dint_file -r $nominal_radius \
		  -nDiv $ndiv_x -maxR $max_ref]
    if $symX {
	lappend argv "-symmX"
    }
    if $symY {
	lappend argv "-symmY"
    }
    if $symZ {
	lappend argv "-symmZ"
    }

    set inputs [eval create_cart3d_inputs $argv]
    if $density_poly {
	# index 0-8 are updated in gui interpreter  
	set npoly [lindex $inputs 9]
	set idx 10;
	set dens_family "DENSITYC3D"
	if { $npoly } {
	    create_empty_tetin_if_needed
	    if !$batch_mode {
		set ta [ tdv_active 0 ]
	    }
	    set objs [geo_lookup density \
			  patterns [list $dens_family*]]
	    #mess "Using Cart-3D density polygons...\n" Blue
	    #ic_delete_geometry density objects $objs
	    if ![llength $objs] {
		for {set i 0} { $i < $npoly} {incr i} {
		    set name "$dens_family.$i"
		    set size [lindex $inputs $idx]; incr idx
		    if {$size < 1} {
			set size 1
		    }
		    set pts {}
		    for {set k 0} {$k < 8} {incr k} {
			set ptx [lindex $inputs [expr $idx]]; incr idx
			set pty [lindex $inputs [expr $idx]]; incr idx
			set ptz [lindex $inputs [expr $idx]]; incr idx
			
			lappend pts "$ptx $pty $ptz"
		    }
		    set rc  [ic_geo_create_density $name $size $pts]
		}
		mess "Created $npoly New Cart-3D density polygons\n" blue
	    }
	    if !$batch_mode {
		tdv_active $ta
	    }
	}
    }
    return $inputs
}

## Runs the Cart-3D mesher
## <li> <b>tetin_file</b> <i>filename</i> (optional) : if specified, runs translator
## to create cart3D triangulation from tetin format.
## <li> <b>c3d_file</b> <i>value</i> (required) : cart3D file prefile / project name
## <li> <b></b> <i>value</i> (required) : cart3D file prefile / project name
## <li> <b>run_intersect</b> <i>0 or 1</i> (optional) : runs intersect components if 1
## <li> <b></b>run_cubes <i>0 or 1</i> (obsolete) : runs mesher
## <li> <b></b>box_min <i>triplet</i> (required) : min xyz limits of the mesh region
## <li> <b></b>box_ax <i>triplet</i> (required) : max xyz limits of the mesh region
## <li> <b></b>start_dim <i>triplet</i> (required) : starting num. of divisiions
## <li> <b></b>box_min <i>triplet</i> (required) : min xyz limits of the mesh region
## <li> <b>symX</b> <i>value</i> (optional) : 1 if model is symmetric in X-dir
## <li> <b>symY</b> <i>value</i> (optional) : 1 if model is symmetric in Y-dir
## <li> <b>symZ</b> <i>value</i> (optional) : 1 if model is symmetric in Z-dir
## <li> <b>aspect_ratio</b> <i>2^n</i> (optional) : anisotrpoic refinement, default = 1
## <li> <b></b>max_ref <i>value</i> (required) : maximum num. of refinement
## <li> <b></b>buff_lay <i>value</i> (optional) : num. of buffer layers, default = 0
## <li> <b></b>max_angle <i>value</i> (optional) : threshold angle for refinement, default = 20
## <li> <b></b>weight_norms <i>0 or 1</i> (optional) :  consider triangle normal weightage
## <li> <b></b>cut_planesX <i>num</i> (optional) : number of cut planes output in X-dir, default = 0
## <li> <b></b>cut_planesY <i>num</i> (optional) : number of cut planes output in Y-dir, default = 0
## <li> <b></b>cut_planesZ <i>num</i> (optional) : number of cut planes output in Z-dir, default = 0
## <li> <b></b>mesh_save <i>0 or 1</i> (required) : 0 - only preview mesh, 1 - save full mesh
## <li> <b></b>mesh_internal<i>0 or 1</i> (optional) : mesh internal volume, default = 0
## <li> <b></b>fix_normals <i>0 or 1</i> (optional) : run fix normal for the geometry translator
## <li> <b></b>load_trifile<i>0 or 1</i> (optional) : load the intersected tri file, default = 0
## <li> <b></b>trifile<i>filename</i> (optional) : cart3d intersected trifile as input
## <li> <b></b>num_mgl<i>num</i> (optional) : if > 1, runs multigrid preprocessor
## <li> <b></b>min_surfref<i>num</i> (optional) : minimum surface refinement, default = -1
## <li> <b></b>sharp_level<i>num</i> (optional) : Num. of additional levels at sharp edges, default = 0

proc ic_mesh_cart3d { tetin_file c3d_file args } {
    global uns_uns projlib

    if ![lindex [check_licenses_enabled] 0] {
	error "No med license was obtained"
    }

    if { $c3d_file == "" } {
	mess "No Output Mesh File Selected\n" red
	return 0
    }

    set load_trifile  0
    set c3d_trifile   ""
    set run_intersect 0
    set run_cubes     1
    set box_min       "0 0 0"
    set box_max       "0 0 0"
    set start_dim     "5 5 5"
    set symX	  0
    set symY	  0
    set symZ	  0
    set aspect_ratio  1
    set max_ref       7
    set buff_lay      0
    set max_angle     20
    set weight_norms  0
    set cut_planesX   0
    set cut_planesY   0
    set cut_planesZ   0
    set mesh_save     0
    set mesh_internal 0
    set fix_normals   1
    set num_mgl       5
    set nfams	 0
    set famnums       ""
    set minref	""
    set maxref	""
    set output_history 0
    set stars_method   0
    set min_surfref    -1
    set unload_mesh    1
    set sharp_level    0

    foreach {n v} $args {
	switch $n {
	    run_intersect - run_cubes - box_min - box_max - start_dim \
		- symX - symY - symZ - aspect_ratio - max_ref - buff_lay \
		- max_angle - weight_norms - cut_planesX - cut_planesY - cut_planesZ \
		- mesh_save - mesh_internal - fix_normals - load_trifile \
		- trifile - num_mgl - nfams - famnums - minref - maxref - output_history \
		- stars_method - min_surfref - unload_mesh - sharp_level {
		    set $n $v
	    }
	    default {
		mess "Warning: Unknown Option\n"
	    }
	}
    }

    set startX [lindex $start_dim 0]
    set startY [lindex $start_dim 1]
    set startZ [lindex $start_dim 2]
    if {$startY == ""} {set startY $startX}
    if {$startZ == ""} {set startZ $startX}

    if { $tetin_file == "" && $trifile == ""}  {
	mess "No geometry file selected\n" red
	return 1
    }

   # Get the surfaces in the family
    set nsurfs 0
    if {!$load_trifile} {
	set c3dtri_file  "$c3d_file.a.tri"
    } else {
	set c3dtri_file  "$trifile"
    }
    set c3dint_file  "$c3d_file.i.tri"

    if $run_intersect {
	if { !$load_trifile } {
	    # Convert tris to cart3d tri format
	    cmd_rm $c3dtri_file
	    mess "Converting Triangles to cart3D tri format:\n" blue
	    set status [ic_run_tetin2cart3d $tetin_file $c3dtri_file $fix_normals]
	    if ![file exists $c3dtri_file] {
		mess "Error: Didn't create cart-3D input tri file\n" red
		busy 0
		return 1
	    }
	}

	mess "Running Intersect components...\n" blue
	set status [ic_run_intersect c3dtri_file $c3dtri_file \
		c3dint_file $c3dint_file]
	if ![file exists $c3dint_file] {
	    if !$status {
		mess "Error: Intersect Components Failed\n" red
		busy 0
		return 1
	    } else {
		cmd_cp $c3dtri_file $c3dint_file
	    }
	}
    }

    if $run_cubes {
	# Write Cart-3D input and density cntl files
	set c3dinput_file "$c3d_file.input"
	set c3dcntl_file  "$c3d_file.cntl"
	scan $box_min "%f %f %f" xmin ymin zmin
	scan $box_max "%f %f %f" xmax ymax zmax
	set outer_box "$xmin $xmax $ymin $ymax $zmin $zmax"
	set rc [write_cart3d_input $projlib $c3dinput_file $c3dcntl_file \
		    $c3dint_file $outer_box $startX $startY $startZ $symX $symY $symZ \
		    $aspect_ratio $max_ref $nfams $famnums $minref $maxref $min_surfref]

	# Run cubes - Generate the volume mesh
	set domain_file  "$c3d_file.dom"
	set c3dmesh_file  "$c3d_file.mesh"
	set internal_flag ""
	if $mesh_internal {
	    set internal_flag "-Internal"
	}

	set argv "-i $c3dinput_file -o $c3dmesh_file -ascii \
	      -b $buff_lay -a $max_angle"
	if $weight_norms {
	    append argv " -weight"
	}

	append argv " $internal_flag -pre $c3dcntl_file -no_est "

	# Save only cut planes for pre-view
	if !$mesh_save {
	    append argv "-icem $domain_file -Dcut -Xcut $cut_planesX \
			 -Ycut $cut_planesY -Zcut $cut_planesZ -no_file"
	}
	if $output_history {
	    append argv " -STARS"
	}

	if {$stars_method == 1} {
	    append argv " -lite"
	} elseif {$stars_method == 2} {
	    append argv " -subgrid"
	}

	if $sharp_level {
	    append argv " -maxR $max_ref"
	    append argv " -sf $sharp_level"
	}

	ic_run_cubes $c3d_file $argv

	if !$mesh_save {
	    if ![file exists $domain_file] {
		mess "Error: Cart-3D Did not create pre-view mesh\n" red
	    } else {
		if $unload_mesh {
		    ic_unload_mesh
		}
		ic_load_unstruct $domain_file
	    }
	    busy 0
	    return 0
	}

	if ![file exists $c3dmesh_file] {
	    busy 0
	    mess "Error: Cart3D Mesher Did not create the mesh\n" red
	    return 1
	}

	# reorder mesh
	if $mesh_save {
	    ic_run_reorder mesh_file $c3dmesh_file \
		mesh_info_file "$c3dmesh_file.Info" \
		reorder_file "$c3dmesh_file.R"

	    ic_run_mgPrep num_mgl $num_mgl \
		reorder_file "$c3dmesh_file.R" \
		mesh_info_file "$c3dmesh_file.Info" \
		multgrid_file "$c3dmesh_file.mg"
	}
    }

    busy 0
    return 0
}

## runs tetin to cart3d tri translator
proc ic_run_tetin2cart3d {tetin_file c3dtri_file {fix_normals 1}} {
    set prog icemcfd/output-interfaces/tet2cart3d
    set argv "$tetin_file $c3dtri_file $fix_normals"

    return [run_application_batch $prog TET2CART3D_BIN $argv]
}

## runs intersect components program
## <li> <b></b>c3dtri_file<i>filename</i> (required) : cart3d uninterescted trifile
## <li> <b></b>c3dint_file<i>filename</i> (required) : cart3d intersected trifile

proc ic_run_intersect {args} {
    global env application_running

    set c3dtri_file ""
    set c3dint_file ""

    foreach {n v} $args {
	switch $n {
	    c3dtri_file - c3dint_file {
		set $n $v
	    }
	    default {
		mess "Warning: unknown option \"$n $v\" in ic_run_intersect\n"
	    }
	}
    }

    set argv "-i $c3dtri_file -o $c3dint_file -ascii -v"
    cmd_rm $c3dint_file;
    if [info exists application_running] {
	if [info exists env(INTERSECT_BIN)] {
	    set prog $env(INTERSECT_BIN)
	} else {
	    set prog $env(ICEM_ACN)/icemcfd/intersect
	}
	busy 1
	set status [ic_run_application_exec . "" $prog $argv]
	busy 0
    } else {
	set prog icemcfd/intersect
	set status [run_application_batch $prog INTERSECT_BIN $argv]
    }
    return $status
}

## runs cart3d mesher with given args directly
proc ic_run_cubes {c3d_file argv} {
    global env application_running

    # Store cubes run command tobe run with sixdof
    set fp [open run_cubes.med w]
    puts $fp "ic_run_cubes $c3d_file \"$argv\""
    close $fp

    cmd_rm $c3d_file.mesh; cmd_rm $c3d_file.dom
    if [info exists application_running] {
	if [info exists env(CUBES_BIN)] {
	    set prog $env(CUBES_BIN)
	} else {
	    set prog $env(ICEM_ACN)/icemcfd/cubes
	}
	busy 1
	set status [ic_run_application_exec . "" $prog $argv]
	busy 0
    } else {
	set prog "icemcfd/cubes"
	set status [run_application_batch $prog CUBES_BIN $argv]
    }
    return $status
}

## runs cart3d mesh to domain file translator
proc ic_run_cart3d2df { c3dmesh_file domain_file } {
    global env

    # Convert the c3dmesh file to domain file format.
    set c3dinfo_file "$c3dmesh_file.Info"
    if [info exists env(CART3D2DF_BIN)] {
	set prog $env(CART3D2DF_BIN)
    } else {
	set prog $env(ICEM_ACN)/icemcfd/output-interfaces/cart3d2df
    }
    set argv "-i $c3dmesh_file -info $c3dinfo_file -o $domain_file"

    busy 1
    cmd_rm $domain_file
    set status [ic_run_application_exec . "" $prog $argv]
    if ![file exists $domain_file] {
	mess "Error: Conversion to domain file failed\n" red
	busy 0
	return 1
    }
    busy 0
    return 0
}

## runs cart3d tri to domain file translator
proc ic_run_c3dtri2df { c3dtri_file domain_file {triq 0} {gamma ""} \
                       {comps ""} {family ""} {only_comps 0}} {
    global env

    set argv "-i \"$c3dtri_file\" -o \"$domain_file\""
    set prefix [file root [file root [file tail $c3dtri_file]]]
    set faminfo_file "$prefix.fam"
    if ![file exists $faminfo_file] {
	mess "Error: Could not find cart3d family info file: $faminfo_file\n" red
    } else {
	append argv " -m $faminfo_file"
    }

    if $triq {
	append argv " -triq"
    }
    if {$gamma != ""} {
        append argv " -g $gamma"
    }
    if {$comps != ""} {
        if $only_comps {
            append argv " -c [join $comps ,]"
        } else {
            append argv " -r [join $comps ,]"
            if {$family == ""} {set family COMPONENTS}
        }
        if {$family != ""} {
            append argv " -f $family"
        }
    }

    # Convert the c3dtri file to domain file format.
    if [info exists env(C3DTRI2DF_BIN)] {
	set prog $env(C3DTRI2DF_BIN)
    } else {
	set prog $env(ICEM_ACN)/icemcfd/output-interfaces/c3dtri2df
    }

    busy 1
    cmd_rm $domain_file
    set status [ic_run_application_exec . "" $prog $argv]
    if ![file exists $domain_file] {
	mess "Error: Coversion to domain file Failed\n" red
	busy 0
	return 1
    }
    busy 0
    return 0
}

## runs domain file to cart3d tri translator
proc ic_run_df2cart3d { domain_file c3dtri_prefix {single 0} {nofix_normals 0}} {
    global env

    set argv "-i \"$domain_file\" -o $c3dtri_prefix"
    set c3dtri_file "$c3dtri_prefix.a.tri"
    if $single {
	append argv " -single"
	set c3dtri_file "$c3dtri_prefix.i.tri"
    }
    if $nofix_normals {
	append argv " -nofix_normals"
    }

    # Convert the domain file to cart3d trifile format.
    if [info exists env(DF2CART3D_BIN)] {
	set prog $env(DF2CART3D_BIN)
    } else {
	set prog $env(ICEM_ACN)/icemcfd/output-interfaces/df2cart3d
    }

    busy 1
    cmd_rm $c3dtri_file
    set status [ic_run_application_exec . "" $prog $argv]
    if ![file exists $c3dtri_file] {
	mess "Error: Coversion to Cart3D Tri file Failed\n" red
	busy 0
	return ""
    }
    busy 0
    if $single { # this is same
	cmd_cp  "$c3dtri_prefix.i.tri" "$c3dtri_prefix.a.tri"
    }

    return $c3dtri_file
}

## Run reorder mesh for flowCart solver. This reorder the cart3D mesh in Hilbert/Mortan scheme.
## <li> <b>mesh_file</b> <i>filename</i> (required) : the .Mesh file from cart3d mesher
## <li> <b>mesh_info_file</b> <i>filename</i> (required) : the .Mesh.Info file from cart3d mesher
## <li> <b>reorder_file</b> <i>filename</i> (required) : the output reordered mesh file
## <li> <b>scheme</b> <i>type</i> (optional) : H or M (default H)
proc ic_run_reorder {args} {
    global env application_running

    set mesh_file ""
    set mesh_info_file ""
    set reorder_file ""
    set scheme H

    foreach {n v} $args {
	switch $n {
	    mesh_file - mesh_info_file - reorder_file - scheme {
		set $n $v
	    }
	    default {
		mess "Warning: Unknown Option\n"
	    }
	}
    }

    # Store reorder run command tobe run with sixdof
    set fp [open run_cubes.med a]
    puts $fp "ic_run_reorder $args"
    close $fp

    set argv "-i $mesh_file -o $reorder_file \
	    -m $mesh_info_file -sfc $scheme"

    if [info exists application_running] {
	if [info exists env(REORDER_BIN)] {
	    set prog $env(REORDER_BIN)
	} else {
	    set prog $env(ICEM_ACN)/icemcfd/reorder
	}
	busy 1
	set status [ic_run_application_exec . "" $prog $argv]
	busy 0
    } else {
	set prog icemcfd/reorder
	set status [run_application_batch $prog REORDER_BIN $argv]
    }
    return $status
}

## Run MultiGrid preprocessor. for flowCart solver.
## <li> <b>num_mgl</b> <i>value</i> (required) : number of multigrid levels
## <li> <b>reorder_file</b> <i>filename</i> (required) : reordered mesh file
## <li> <b>mesh_info_file</b> <i>filename</i> (required) : .Mesh.Info from cart3D mesher
## <li> <b>multigrid_file</b> <i>filename</i> (required) : output multigrid file
## <li> <b>scheme</b> <i>type</i> (required) : H or M; Should be same scheme as reorder
proc ic_run_mgPrep {args} {
    global env application_running

    set reorder_file ""
    set mesh_info_file ""
    set multgrid_file ""
    set scheme H
    set num_mgl 0

    foreach {n v} $args {
	switch $n {
	    num_mgl - reorder_file - mesh_info_file - multgrid_file - scheme {
		set $n $v
	    }
	    default {
		mess "Warning: Unknown Option\n"
	    }
	}
    }

   if ![file exists $reorder_file] {
	mess "Error: No reordered mesh file: $reorder_file. Please run \
		Reorder Mesh first." red
	return
    }

    # Store mgPrep run command tobe run with sixdof
    set fp [open run_cubes.med a]
    puts $fp "ic_run_mgPrep $args"
    close $fp

    set argv "-n $num_mgl -i $reorder_file -m $mesh_info_file \
	    -o $multgrid_file -sfc $scheme"
    if [info exists application_running] {
	if [info exists env(MGPREP_BIN)] {
	    set prog $env(MGPREP_BIN)
	} else {
	    set prog $env(ICEM_ACN)/icemcfd/mgPrep
	}
	busy 1
	set status [ic_run_application_exec . "" $prog $argv]
	busy 0
    } else {
	set prog icemcfd/mgPrep
	set status [run_application_batch $prog MGPREP_BIN $argv]
    }
    return $status
}

## Create flowCart input cntl file from params file.
## <li> <b>params_file</b> <i>filename</i> (required) : input params file
## <li> <b>cntl_file</b> <i>filename</i> (required) : flowCart input fil
## <li> <b>faminfo_file</b> <i>filename</i> (required) : family info file

proc ic_create_flowCart_input {args} {
    global env

    set params_file ""
    set cntl_file ""
    set faminfo_file ""

    foreach {n v} $args {
	switch $n {
	    params_file - cntl_file - faminfo_file {
		set $n $v
	    }
	    default {
		mess "Warning: unknown option \"$n $v\" in ic_create_flowCart_input\n"
	    }
	}
    }

    if ![file exists $params_file] {
	mess "Error: No flowCart params file: $params_file. Please Edit \
		flowCart params first.\n" red
	return
    }

    if [info exists env(FLOWCARTINPUT_BIN)] {
	set prog $env(FLOWCARTINPUT_BIN)
    } else {
	set prog $env(ICEM_ACN)/icemcfd/output-interfaces/flowCartinput
    }

    set argv "-i $params_file -o $cntl_file -f $faminfo_file"
    ic_run_application_exec . "" $prog $argv

}

## Run flowCart Solver.
## <li> <b>cntl_file</b> <i>filename</i> (required) : flowCart input file
## <li> <b>max_cycles</b> <i>value</i> (required) : number of iterations
## <li> <b>no_fmg</b> <i>value</i> (optional) : flag not to run full multigrid
## <li> <b>freeze_after</b> <i>value</i> (optional) : freeze after n iterations
## <li> <b>restart</b> <i>value</i> (optional) : restart solver from the previous run.
## This assumes that "Restart.file" (link to check point file) is available from the previous run.
## <li> <b>gridseq</b> <i>value</i> (optional) : run grid sequencing instead of multigrid
## <li> <b>dump_fullhex</b> <i>value</i> (optional) : write out full volume result
## <li> <b>Xslices</b> <i>values</i> (optional) : write out specified X-cutplane results
## <li> <b>Yslices</b> <i>values</i> (optional) : write out specified Y-cutplane results
## <li> <b>Zslices</b> <i>values</i> (optional) : write out specified Z-cutplane results
## <li> <b>ncpus</b> <i>value</i> (optional) : run on specified num. of cpus for SMP machines
## <li> <b>yaxis_span</b> <i>value</i> (optional) : 1 if yaxis is spanwise
## <li> <b>run_cmd</b> <i>cmd</i> (optional) : run user specified cmd with flowCart options

proc ic_run_flowCart {args} {
    global env ic_application_output_hook

    set cntl_file ""
    set no_fmg 0
    set gridseq 0
    set restart 0
    set restart_file "Restart.file"
    set max_cycles 0
    set Xslices ""
    set Yslices ""
    set Zslices ""
    set dump_fullhex 0
    set freeze_after 0
    set ncpus 0
    set yaxis_span 0
    set run_cmd ""
    set gui_output ""
    set newargs ""
    foreach {n v} $args {
	switch $n {
	    cntl_file - max_cycles - no_fmg - freeze_after - gridseq \
		    - dump_fullhex - Xslices - Yslices - Zslices - ncpus \
                    - yaxis_span - run_cmd {
		set $n $v
                lappend newargs $n $v
	    }
	    restart - gui_output {
		set $n $v
	    }
	    default {
		mess "$n $v\n" blue
		mess "Warning: Illegal option $n"
	    }
	}
    }

    if ![file exists $cntl_file] {
	mess "Error: No flowCart cntl file: $cntl_file. Please write \
		flowCart input first.\n" red
	return
    }

    set argv "-N $max_cycles -i $cntl_file -clic -his -T -icem"

    if $no_fmg {
	append argv " -no_fmg"
    }
    if $freeze_after {
	append argv " -freezeAfter $freeze_after"
    }

    if $gridseq {
	append argv " -gs $gridseq"
    }

    if $yaxis_span {
	append argv " -y_is_spanwise"
    }

    if $restart {
	if ![file exists $restart_file] {
	    mess "Error: No flowCart Restart file. Could not  \
		    restart computation.\n" red
	    return
	}
	append argv " -restart"
    }

    if $dump_fullhex {
	append argv " -Dfull"
    }

    if {$ncpus && $run_cmd == ""} {
	append argv " -ncpus $ncpus"
    }

    set fpr [open $cntl_file r]
    set fpw [open $cntl_file.tmp w]
    while {[gets $fpr line] >= 0} {
	set str1 [lindex [split $line " "] 0]
	if {$str1 != "Xslices" && $str1 != "Yslices" && \
		$str1 != "Zslices" && $str1 != "\$__Post_Processing:"} {
	    puts $fpw $line
	}
    }

    puts $fpw "\$__Post_Processing:"

    foreach slice {Xslices Yslices Zslices} {
	set sl [set $slice]
	if {$sl != "" } {
	    puts $fpw "$slice $sl"
	}
    }
    close $fpr; close $fpw
    cmd_mv $cntl_file.tmp $cntl_file

    # write flowCart run command for tobe run with sixdof
    set fp [open run_flowCart.med w]
    puts $fp "ic_run_flowCart $newargs"
    close $fp

    if [file exists flowCart.STOP] {
        cmd_rm flowCart.STOP
    }

    if {$gui_output != ""} {
        set ic_application_output_hook "check_flowCart_progress $max_cycles"
        catch {interrupt begin $gui_output \
            initializing $max_cycles application_terminated no_grab}
    }

    if {$run_cmd != ""} {
	set prog [lindex $run_cmd 0]
	set env(FLOWCART_BIN) $prog
	set cmdargs [lrange $run_cmd 1 end]
	set status [run_application_batch $prog FLOWCART_BIN "$cmdargs $argv"]
    } else {
	set prog icemcfd/flowCart
	set status [run_application_batch $prog FLOWCART_BIN $argv]
    }

    catch {unset ic_application_output_hook}
    catch {interrupt finish}
    return $status
}

proc check_flowCart_progress {maxcycle pid line} {
    if {[lindex $line 0] == "Cycle"} {
	catch {interrupt check [lindex $line 1] $maxcycle running}
    }
    mess "$line\n" blue
    update idletasks
}

## Run flowCart postprocessor (clic) to compute force and moments
## This will create .clic.out file and .LDM file.
## <li> <b>cntl_file</b> <i>filename</i> (required) : input parameters file

proc ic_run_clic {args} {
    global env is_win

    set cntl_file ""

    foreach {n v} $args {
	switch $n {
	    cntl_file {
		set $n $v
	    }
	    default {
		mess "Warning: unknown option \"$n $v\" in ic_run_clic\n"
	    }
	}
    }

#    what if the prefix contains a dot ?
#    set prefix [lindex [split $cntl_file .] 0]
    set prefix [file rootname $cntl_file]
    if {[file extension $prefix] == ".clic"} {
        set prefix [file rootname $prefix]
    }
    set outfile $prefix.clic.out
    set LDMfile $prefix.clic.LDM

    cmd_rm $outfile
    set argv "-i $cntl_file  -ascii -v "
    set prog icemcfd/clic
    set status [run_application_batch $prog CLIC_BIN $argv $outfile]

    if [file exists $outfile] {
	ic_create_flowCart_LDM $outfile
	if 0 {
	    if [ file exists \
		     $env(ICEM_ACN)/icemcfd/output-interfaces/cart3D_LDM.pl] {
		set LDM $env(ICEM_ACN)/icemcfd/output-interfaces/cart3D_LDM.pl
	    } elseif [file exists $env(HOME)/output-interfaces/cart3D_LDM.pl] {
		set LDM $env(HOME)/output-interfaces/cart3D_LDM.pl
	    } else {
		mess "Warning: Could not find cart3D_LDM.pl\n"
		return
	    }
	    if [catch {exec cat $outfile | $LDM |& tee -i $LDMfile} res] {
		mess "$res\n" red
		mess "Error: Did not create *.LDM file\n" red
		mess "Please check perl V5 or greater in path\n" red
		exec perl -v
	    } else {
		mess "Wrote LDM output file: $LDMfile\n"
	    }
	}
    }
    return $status
}

# It puts the info from infile in a tabular format for shipping
# to MS Excel
## <li> <b>infile</b> <i>value</i> (required) : .clic.out file

proc ic_create_flowCart_LDM {infile} {

    set fp [open $infile r]
    set comps ""
    set comps1 ""
    foreach par {CL CD Cy CY CN roll roll pitch yaw CmaX CmaY CmaZ} {
	array set $par {}
    }

    while {[gets $fp line] >= 0} {
        set line [string trim $line]
        if {$line == ""} continue
	if {[lindex $line 1] == "Component"} {
	    set comp [lindex $line 2]
	    set comp [string trim $comp \']
            continue
	}
	if {[lindex $line 1] == "Forces"} {
	    if {[lsearch $comps $comp] < 0} {
		#puts "force comp: $comp"
		lappend comps $comp
	    }
            continue
	}
	if {[lindex $line 1] == "Moment"} {
	    if {[lsearch $comps1 $comp] < 0} {
		#puts "mom comp: $comp"
		lappend comps1 $comp
	    }
            continue
	}
        if {[string index $line 0] == "("} {
 	    foreach par {CL CD Cy CA CY CN roll pitch yaw} {
	        if {[lsearch $line *$par*] >= 0} {
		    set [set par]($comp) [lindex $line end]
		    #puts "set [set par]($comp) [lindex $line end]"
                    break
	        }
            }
            continue
	}
        if {[string range $line 0 3] == "Cma\["} {
            set par Cma[string index $line 4]
            set [set par]($comp) [lindex $line end]
        }
    }
    close $fp

    set width 9
    foreach comp $comps {
        set len [string length $comp]
        if {$width < $len} {set width $len}
    }

    set outfile "[file root $infile].LDM"
    set fp [open $outfile w]

    set str "Force coefficients:"
    puts $fp $str; mess "$str\n"
    set str [format "%-*s\t%9s\t%9s\t%9s\t%9s\t%9s\t%9s" $width \
        "Component" "CL" "CD" "Cy" "CX" "CY" "CZ"]
    puts $fp $str; mess "$str\n"
    foreach comp $comps {
	if ![info exists CL($comp)] {continue}
	set str [format "%-*s\t%9.5f\t%9.5f\t%9.5f\t%9.5f\t%9.5f\t%9.5f" \
            $width $comp $CL($comp) $CD($comp) $Cy($comp) \
            $CA($comp) $CY($comp) $CN($comp)]
	puts $fp $str
	mess "$str\n"
    }
    set str "\nMoment coefficients:"
    puts $fp $str; mess "$str\n"
    set str [format "%-*s\t%9s\t%9s\t%9s\t%9s\t%9s\t%9s" $width \
        "Component" "roll" "pitch" "yaw" "CmX" "CmY" "CmZ"]
    puts $fp $str; mess "$str\n"
    foreach comp1 $comps1 {
	if ![info exists roll($comp1)] {continue}
	set str [format "%-*s\t%9.5f\t%9.5f\t%9.5f\t%9.5f\t%9.5f\t%9.5f" \
            $width $comp1 $roll($comp1) $pitch($comp1) $yaw($comp1) \
            $CmaX($comp1) $CmaY($comp1) $CmaZ($comp1)]
	puts $fp $str
	mess "$str\n"
    }
    close $fp
    mess "Wrote LDM output file: $outfile\n"
}

## This runs cart3D mesher, flowCart solver with sixDOF in cycle.
## Uses lot of file name conventions and parsing formats.
## see sixDOF.html and sixDOF.pdf for more information
proc ic_run_sixdof_multiple {args} {
    global env

    set tri_file ""
    set output_dir sixDOF
    set time_start 0.0
    set time_step 0.0
    set time_end 0.0
    set model_scale 1.0
    set dynamic_pressure ""
    set store_cycle 1
    set multi_6dof 0
    set show_progress 0

    foreach {n v} $args {
	switch $n {
	    tri_file - output_dir - move_comp - time_start - time_step \
		    - time_end - store_cycle - model_scale \
                    - dynamic_pressure - show_progress {
		set $n $v
	    }
	    default {
		mess "Warning: unknown option \"$n $v\" in ic_run_sixdof_multiple\n"
	    }
	}
    }

    if {$tri_file == "" || ![file exists $tri_file]} {
	mess "Error: could not find input tri file: $tri_file\n" red
	return
    }

    if [expr $time_start < 0.0] {
        mess "Error: start time must be >= 0\n" red
        return
    }
    if [expr $time_step <= 0.0] {
        mess "Error: time step must be > 0\n" red
        return
    }

    set prefix [file rootname [file rootname $tri_file]]

    set tri_file_initial $tri_file.initial
    if [file exists $tri_file.initial] {
        cmd_cp $tri_file_initial $tri_file
    } else {
        cmd_cp $tri_file $tri_file_initial
    }

    set intsect_file $prefix.i.tri
    set cubes_input_file $prefix.input
    set cubes_prespec_file $prefix.cntl
    set mesh_file $prefix.mesh
    set multi_grid_file $prefix.mesh.mg
    set mesh_info_file $prefix.mesh.Info
    set flowCart_file flowCart.cntl
    set clic_file $prefix.clic.cntl
    set clic_LDMfile $prefix.clic.LDM
    set result_file $prefix.i.triq
    set run_cubes run_cubes.med
    set run_flowCart run_flowCart.med
    set aerofm_log_file aeroForces.log
    set moving_comp_file 6DOF_Moving_Comp.dat
    set slice_planes_file slicePlanes.dom
    set force_file forces.dat
    set history_file history.dat

    foreach name $move_comp {
        regsub -all / $name . prefix
        set comp_file($name) $prefix.6dof
    }

    set store_files [list $clic_file $clic_LDMfile $result_file \
        $slice_planes_file $force_file $history_file]

    if ![file exists $run_cubes] {
	mess "Error: could not find cubes run script file: \
		$run_cubes\n" red
	return
    }
    set run_cubes_cmd ""
    set fp [open $run_cubes r]
    while {[gets $fp cmd] > 0} {
        lappend run_cubes_cmd $cmd
    }
    close $fp

    if ![file exists $run_flowCart] {
	mess "Error: could not find flowCart run script file: \
		$run_flowCart\n" red
	return
    }
    set fp [open $run_flowCart r]
    set run_flowCart_cmd [gets $fp]
    close $fp

    # get RefArea, RefLength and Model axis transformation from clic file
    # Also check that the moving components are defined
    # and get component numbers

    foreach i {0 1 2} {
	set trf($i) $i; set sign($i) 1;
    }
    set fp [open $clic_file r]
    while {[gets $fp line] >= 0} {
        set nvals [llength $line]
        if {$nvals < 2} {continue}
        set key [lindex $line 0]
        set name [lindex $line end]
        if {$nvals == 2} {
            if {$key == "\$_Model_X_axis_is"} {
		set trf(0) [get_sixdof_axis_trf $name sign(0)]
            } elseif {$key == "\$_Model_Y_axis_is"} {
		set trf(1) [get_sixdof_axis_trf $name sign(1)]
	    } elseif {$key == "\$_Model_Z_axis_is"} {
		set trf(2) [get_sixdof_axis_trf $name sign(2)]
	    } elseif {$key == "\$_Force" &&
                      [lsearch $move_comp $name] >= 0} {
                set found_force($name) 1
            } else { }
        } elseif {$nvals == 3} {
            set val [lindex $line 1]
            if {$name == "entire" || [lsearch $move_comp $name] >= 0} {
	        if {$key == "\$_Reference_Area"} {
		    set refarea($name) [format "%f" $val]
                } elseif {$key == "\$_Reference_Length"} {
		    set reflength($name) [format "%f" $val]
                } elseif {$key == "\$_ComponentName"} {
		    set compnum($name) $val
                } else { }
            }
        } elseif {$nvals == 5 && $key == "\$_Moment_Point" &&
                  [lsearch $move_comp $val] >= 0} {
            set found_moment($name) 1
        } else { }
    }
    close $fp

    set need_write 0
    foreach name $move_comp {
	if {![info exists refarea($name)]} {
            if {[info exists refarea(entire)]} {
                set refarea($name) $refarea(entire)
            } else {
	        mess "Error: couldn't find refarea for $name\n" red
                return
            }
	}
	if {![info exists reflength($name)]} {
            if {[info exists reflength(entire)]} {
                set reflength($name) $reflength(entire)
            } else {
	        mess "Error: couldn't find reflength for $name\n" red
                return
            }
	}
	mess "refarea($name): $refarea($name), reflength($name): $reflength($name)\n" blue
        if {![info exists found_force($name)] ||
            ![info exists found_moment($name)]} {incr need_write}
    }

    if $need_write {
        set fp [open $clic_file a]
        foreach name $move_comp {
            if {![info exists found_force($name)]} {
                puts $fp "\$_Force $name"
            }
            if {![info exists found_force($name)]} {
                puts $fp "\$_Moment_Point 0.0 0.0 0.0 $name"
            }
        }
        close $fp
    }

    mess "Model frame transformation: (Xmodel, Ymodel, Zmodel) <=> \
	    ($sign(0)*$trf(0), $sign(1)*$trf(1), $sign(2)*$trf(2))\n" blue

    # freestream dynamic pressure

    if {$dynamic_pressure == "" || [expr $dynamic_pressure <= 0.0]} {
        # get Mach Number from flowCart.cntl file
        set mach_num ""
        set rho_inf 1.0
        set a_inf 1.0
        set fp [open $flowCart_file r]
        while {[gets $fp line] >= 0} {
            if { [string range $line 0 3] == "Mach" } {
                scan $line "%s %f" key mach_num
            }
            if { [string range $line 0 6] == "Rho_inf" } {
                scan $line "%s %f" key rho_inf
            }
            if { [string range $line 0 4] == "a_inf" } {
                scan $line "%s %f" key a_inf
            }
        }
        close $fp
        if {$mach_num == ""} {
            mess "Error: couldn't read Mach Number from params file\n" red
            return
        }
        set v_inf [expr $mach_num * $a_inf]
        mess "Mach = $mach_num, rho_inf = $rho_inf, a_inf = $a_inf, v_inf = $v_inf\n" blue
        set q_inf [expr 0.5 * $rho_inf * $v_inf * $v_inf]
        set l_scal 1.0
    } else {
        set rho_inf 1.0
        set a_inf 1.0
        set q_inf $dynamic_pressure
        set l_scal $model_scale
    }

    set time [format "%g" $time_start]

    if {$time == 0} {
        # truncate the component log files
        # probably dont need this, since they should have been
        # written out from flowCart_sixdof_apply
if 0 {
        foreach name $move_comp {
            set logfile $comp_file($name).log
            if [file exists $logfile] {
                set in [open $logfile r]
                set out [open $logfile.temp w]
                while {[gets $in line] >= 0} {
                    set line [string trim $line]
                    if {[string index $line 0] != "\#" &&
                        [expr [lindex $line 0] > $time]} break
                    puts $out $line
                }
                close $in
                close $out
                cmd_cp $logfile.temp $logfile
                cmd_rm $logfile.temp
            }
        }
}
        if [file exists $aerofm_log_file] {
            cmd_rm $aerofm_log_file
        }
        set do_run 1
    } else {
        if {![file exists "time_$time/$clic_LDMfile"]} {
            mess "Error: solution file at time=$time does not exist\n" red
            return
        }
        cmd_cp "time_$time/$clic_LDMfile" $clic_LDMfile
        # copy the component log files
        foreach name $move_comp {
            set logfile $comp_file($name).log
            if [file exists "time_$time/$logfile"] {
                cmd_cp "time_$time/$logfile" $logfile
            }
        }
        # truncate the aero force log file if needed
        if [file exists $aerofm_log_file] {
            set in [open $aerofm_log_file r]
            set out [open $aerofm_log_file.temp w]
            while {[gets $in line] >= 0} {
                if [expr [lindex $line 0] == $time] break
                puts $out $line
            }
            close $in
            close $out
            cmd_cp $aerofm_log_file.temp $aerofm_log_file
            cmd_rm $aerofm_log_file.temp
        }
        set do_run 0
    }

    # create the component log files if they dont exist

    foreach name $move_comp {
        set logfile $comp_file($name).log
        if {![file exists $logfile]} {
            if ![info exists compnum($name)] {
                mess "Error: couldn't get component number for $name\n" red
                return
            }
            set in [open $moving_comp_file r]
            while {[gets $in line] >= 0} {
                if {[lindex $line 0] == $name} {
                    set out [open $logfile w]
                    set mcen [lindex $line 2]
                    set data [lrange $line 4 end]
                    regsub -all "\{" $data "\(" data
                    regsub -all "\}" $data "\)" data
                    puts $out "\#time icomp x_cm u_cm omega euler"
                    puts $out "$time $compnum($name) \($mcen\) $data"
                    close $out
                    break
                }
            }
            close $in
            if ![file exists $logfile] {
                mess "Error: component $name not found in $moving_comp_file\n" red
                return
            }
        }
    }

    set ncycle 0

    while {1} {
	mess "time = $time\n" blue

        if $do_run {

            # run intersect

            if ![ic_run_intersect c3dtri_file $tri_file \
                 c3dint_file $intsect_file] return
            if ![file exists $intsect_file] {
                # no need to run intersect
                cmd_cp $tri_file $intsect_file
            }

            # run cubes

            foreach cmd $run_cubes_cmd {
                if ![eval $cmd] return
            }

            # get center of mass
            array set c0 {}
            array set c1 {}
            array set c2 {}
            foreach name $move_comp {
                set fp [open "$comp_file($name).log" r]
                while {[gets $fp line] >= 0} {
                    set endline $line
                }
                scan $endline "%f %d (%f %f %f)" t id c0($name) c1($name) c2($name)
                close $fp
                mess "center of mass for $name: $c0($name) $c1($name) $c2($name)\n" blue
            }

            # Append c.m for zSlices
            set infile $flowCart_file
            set outfile $infile.tmp
            set in [open $infile r]
            set out [open $outfile w]
            while {[gets $in line] >= 0} {
                if { [string range $line 0 6] == "Zslices" } {
                    set cmz ""
                    foreach name $move_comp {
                        lappend cmz "$c2($name)"
                    }
                    set line "Zslices $cmz"
                }
                puts $out "$line"
            }
            close $in; close $out;
            cmd_mv $outfile $infile

            set cmd $run_flowCart_cmd
            if $show_progress {
                lappend cmd gui_output "sixDOF Simulation - time = $time"
            }
            if ![eval $cmd] return

            # Append c.m for point moment
            set infile $clic_file
            set outfile $infile.tmp
            set in [open $infile r]
            set out [open $outfile w]
            while {[gets $in line] >= 0} {
                set name [lindex $line end]
                if {[lsearch $move_comp $name] >= 0 &&
                    [lindex $line 0] == "\$_Moment_Point"} {
                    set line "\$_Moment_Point $c0($name) $c1($name) $c2($name) $name"
                }
                puts $out "$line"
            }
            close $in; close $out;
            cmd_mv $outfile $infile

            if ![ic_run_clic cntl_file $clic_file] return

            # store files at this time step separately
            if { [expr $ncycle % $store_cycle] == 0 } {
                set tf time_$time
                set dir "$output_dir/$tf"
                cmd_mkdir $dir
                foreach f $store_files {
                    if [file exists $f] {
                        cmd_cp $f $dir
                    }
                }
                # save log files for a restart
                foreach name $move_comp {
                    if [file exists "$comp_file($name).log"] {
                        cmd_cp "$comp_file($name).log" $dir
                    }
                }
            }
        }

        if [expr $time >= $time_end] break

	# run 6DOF for each moving component
	cmd_cp $tri_file_initial $tri_file
	foreach name $move_comp {
	    # get Force/Moments
	    set fp [open $clic_LDMfile r]
	    set force_read 0
	    while {[gets $fp line] >= 0} {
		if { [lindex $line 0] == "$name" } {
		    if !$force_read {
			scan $line "%s %f %f %f %f %f %f" \
			    n  Cfa(0) Cfa(1) Cfa(2) Cfb(0) Cfb(1) Cfb(2)
			set force_read 1
		    } else {
			scan $line "%s %f %f %f %f %f %f" \
			    n Cma(0) Cma(1) Cma(2) Cmb(0) Cmb(1) Cmb(2)
		    }
		}
	    }

	    #mess "Forces in body frame: $Cfb(0) $Cfb(1) $Cfb(2)\n" blue
	    #mess "Moments in body frame:  $Cmb(0) $Cmb(1) $Cmb(2)\n" blue

	    # CA and CN have opposite sense in body frame in clic
	    set Cfb(0) -$Cfb(0)
	    set Cfb(2) -$Cfb(2)

	    foreach dir {0 1 2} {
		set F($dir) [expr $sign($dir) * $Cfb($trf($dir)) \
				 * $q_inf * $refarea($name)]
		set M($dir) [expr $sign($dir) * $Cmb($trf($dir)) \
				 * $q_inf * $refarea($name) * \
                                 $reflength($name)]
	    }

	    # Non-dimensionalize
	    foreach dir {0 1 2} {
		set F($dir) [expr $F($dir) * $l_scal * $l_scal / \
                    ($rho_inf * $a_inf * $a_inf)]
		set M($dir) [expr $M($dir) * $l_scal * $l_scal * $l_scal / \
                    ($rho_inf * $a_inf * $a_inf)]
	    }

	    mess "Forces in model frame: $F(0) $F(1) $F(2)\n" blue
	    mess "Moments in model frame:  $M(0) $M(1) $M(2)\n" blue

	    set aerofm [open $aerofm_log_file a]
	    puts $aerofm "$time $name ($F(0) $F(1) $F(2)) \
		($M(0) $M(1) $M(2))"
	    close $aerofm

	    # run sixDOF
	    # for mutiple comps

	    set prog icemcfd/sixDOF
	    set argv "-dt $time_step -len $l_scal -force $F(0) $F(1) $F(2) \
		-moment $M(0) $M(1) $M(2) -log $comp_file($name).log \
		-cntl $comp_file($name).cntl -info $mesh_info_file"
            if [file exists $comp_file($name).efm] {
                append argv " -external $comp_file($name).efm"
            }
            if [file exists $comp_file($name).bfm] {
                append argv " -body $comp_file($name).bfm"
            }
	    busy 1
	    set status [run_application_batch $prog SIXDOF_BIN $argv]
	    busy 0
            if !$status return

	    set files [glob $tri_file.*]
	    set trifile_time [file mtime $tri_file]
	    set new_tri_file ""
	    foreach f $files {
		if {$new_tri_file == "" || [file mtime $f] > [file mtime $new_tri_file]} {
		    set new_tri_file $f
		}
	    }

	    cmd_cp $new_tri_file $tri_file
	    cmd_rm $new_tri_file
            incr do_run
	}
	incr ncycle
	set time [format "%g" [expr $time + $time_step]]
    }
    cmd_cp $tri_file_initial $tri_file
    cmd_rm $tri_file_initial
}

## obsolete - This is there for backward compatiblity
## use ic_run_sixdof_multiple
proc ic_run_sixdof {args} {
    global env

    set tri_file ""
    set output_dir sixDOF
    set time_start 0.0
    set time_step 0.0
    set time_end 0.0
    set dynamic_pressure ""
    set model_scale 1.0
    set store_cycle 1

    foreach {n v} $args {
	switch $n {
	    tri_file - output_dir - move_comp - time_start - time_step \
		    - time_end - store_cycle - model_scale \
                    - dynamic_pressure {
		set $n $v
	    }
	    default {
		mess "Warning: unknown option \"$n $v\" in ic_run_sixdof\n"
	    }
	}
    }

    if {$tri_file == "" || ![file exists $tri_file]} {
	mess "Error: could not find input tri file: $tri_file\n" red
	return
    }

    set prefix [lindex [split $tri_file .] 0]

    set tri_file_initial $tri_file.initial
    cmd_cp $tri_file $tri_file_initial

    set intsect_file $prefix.i.tri
    set cubes_input_file $prefix.input
    set cubes_prespec_file $prefix.cntl
    set mesh_file $prefix.mesh
    set multi_grid_file $prefix.mesh.mg
    set mesh_info_file $prefix.mesh.Info
    set flowCart_file flowCart.cntl
    set clic_file $prefix.clic.cntl
    set clic_LDMfile $prefix.clic.LDM
    set result_file $prefix.i.triq
    set sixdof_log_file $prefix.6dof.log
    set sixdof_cntl_file $prefix.6dof.cntl
    set sixdof_efm_file $prefix.6dof.efm
    set run_cubes run_cubes.med
    set run_flowCart run_flowCart.med
    set aerofm_log_file aeroForces.log
    set slice_planes_file slicePlanes.dom
    set force_file forces.dat
    set history_file history.dat

    set store_files [list $clic_file $result_file $slice_planes_file $force_file $history_file]

    if ![file exists $run_cubes] {
	mess "Error: could not find cubes run script file: \
		$run_cubes\n" red
	return
    }

    if ![file exists $run_flowCart] {
	mess "Error: could not find flowCart run script file: \
		$run_flowCart\n" red
	return
    }

    # get RefArea, RefLength and Model axis transformation from clic file
    foreach i {0 1 2} {
	set trf($i) $i; set sign($i) 1;
    }
    set fp [open $clic_file r]
    while {[gets $fp line] >= 0} {
	if {[scan $line "%s %s %s" key val name ] == 3} {
	    if {$key == "\$_Reference_Area" && \
		    $name == "$move_comp"} {
		set refarea [format "%f" $val]
	    }
	}
	if {[scan $line "%s %s %s" key val name ] == 3} {
	    if {$key == "\$_Reference_Length" && \
		    $name == "$move_comp"} {
		set reflength [format "%f" $val]
	    }
	}
	if {[scan $line "%s %s" key val] == 2} {
	    if {$key == "\$_Model_X_axis_is"} {
		set trf(0) [get_sixdof_axis_trf $val sign(0)]
	    }
	    if {$key == "\$_Model_Y_axis_is"} {
		set trf(1) [get_sixdof_axis_trf $val sign(1)]
	    }
	    if {$key == "\$_Model_Z_axis_is"} {
		set trf(2) [get_sixdof_axis_trf $val sign(2)]
	    }
	}
    }
    close $fp;

    if {![info exists refarea] && ![info exists reflength]} {
	mess "Error: couldn't find refarea/reflength for $move_comp\n" red
	return
    }
    mess "refarea: $refarea, reflength: $reflength\n" blue
    mess "Model frame transformation: (Xmodel, Ymodel, Zmodel) <=> \
	    ($sign(0)*$trf(0), $sign(1)*$trf(1), $sign(2)*$trf(2))\n" blue

    # freestream dynamic pressure

    if {$dynamic_pressure == ""} {
        # get Mach Number from flowCart.cntl file
        set mach_num ""
        set rho_inf 1.0
        set a_inf 1.0
        set fp [open $flowCart_file r]
        while {[gets $fp line] >= 0} {
            if { [string range $line 0 3] == "Mach" } {
                scan $line "%s %f" key mach_num
            }
            if { [string range $line 0 6] == "Rho_inf" } {
                scan $line "%s %f" key rho_inf
            }
            if { [string range $line 0 4] == "a_inf" } {
                scan $line "%s %f" key a_inf
            }
        }
        close $fp
        if {$mach_num == ""} {
            mess "Error: couldn't read Mach Number from params file\n" red
            return
        }
        set v_inf [expr $mach_num * $a_inf]
        mess "Mach = $mach_num, rho_inf = $rho_inf, a_inf = $a_inf, v_inf = $v_inf\n" blue
        set q_inf [expr 0.5 * $rho_inf * $v_inf * $v_inf]
    } else {
        set rho_inf 1.0
        set a_inf 1.0
        set q_inf $dynamic_pressure
    }

    set time $time_start
    set end_movcomp [expr [string length $move_comp] - 1]
    set ncycle 0
    while {$time <= $time_end} {
	mess "time = $time\n" blue
	ic_run_intersect c3dtri_file $tri_file c3dint_file $intsect_file
	if ![file exists $intsect_file] {
	    # no need to run intersect
	    cmd_cp $tri_file $intsect_file
	}
	source $run_cubes

	# get center of mass
	set fp [open $sixdof_log_file r]
	while {[gets $fp line] >= 0} {
	    set endline $line
	}
	scan $endline "%f \t %d \t (%f %f %f)" t id c0 c1 c2
	close $fp
	mess "center of mass: $c0 $c1 $c2\n" blue

	# Append c.m for zSlices
	set infile $flowCart_file
	set outfile $infile.tmp
	set in [open $infile r]
	set out [open $outfile w]
	while {[gets $in line] >= 0} {
	    if { [string range $line 0 6] == "Zslices" } {
		set line "Zslices $c2"
	    }
	    puts $out "$line"
	}
	close $in; close $out;
	cmd_mv $outfile $infile

	source $run_flowCart

	# Append c.m for point moment
	set infile $clic_file
	set outfile $infile.tmp
	set in [open $infile r]
	set out [open $outfile w]
	while {[gets $in line] >= 0} {
	    if { [string range $line 0 13] == "\$_Moment_Point" } {
		set line "\$_Moment_Point $c0 $c1 $c2 $move_comp"
	    }
	    puts $out "$line"
	}
	close $in; close $out;
	cmd_mv $outfile $infile

	ic_run_clic cntl_file $clic_file

	# get Force/Moments
	set fp [open $clic_LDMfile r]
	set force_read 0
	while {[gets $fp line] >= 0} {
	    if { [string range $line 0 $end_movcomp] == "$move_comp" } {
		if !$force_read {
		    scan $line "%s %f %f %f %f %f %f" \
			    n  Cfa(0) Cfa(1) Cfa(2) Cfb(0) Cfb(1) Cfb(2)
		    set force_read 1
		} else {
		    scan $line "%s %f %f %f %f %f %f" \
			    n Cma(0) Cma(1) Cma(2) Cmb(0) Cmb(1) Cmb(2)
		}
	    }
	}
	#mess "Forces in body frame: $Cfb(0) $Cfb(1) $Cfb(2)\n" blue
	#mess "Moments in body frame:  $Cmb(0) $Cmb(1) $Cmb(2)\n" blue

	# CA and CN have opposite sense in body frame in clic
	set Cfb(0) -$Cfb(0)
	set Cfb(2) -$Cfb(2)

	foreach dir {0 1 2} {
	    set F($dir) [expr $sign($dir) * $Cfb($trf($dir)) \
		    * $q_inf * $refarea]
	    set M($dir) [expr $sign($dir) * $Cmb($trf($dir)) \
		    * $q_inf * $refarea * $reflength]
	}

	# Non-dimensionalize
	foreach dir {0 1 2} {
	    set F($dir) [expr $F($dir) / ($rho_inf * $a_inf * $a_inf * $model_scale * $model_scale)]
	    set M($dir) [expr $M($dir) / ($rho_inf * $a_inf * $a_inf * $model_scale * $model_scale * $model_scale)]
	}

	mess "Forces in model frame: $F(0) $F(1) $F(2)\n" blue
	mess "Moments in model frame:  $M(0) $M(1) $M(2)\n" blue

	set aerofm [open $aerofm_log_file a]
	puts $aerofm "$time $move_comp ($F(0) $F(1) $F(2)) \
		($M(0) $M(1) $M(2))"
	close $aerofm

	# store files at this time step separately
	if { [expr $ncycle % $store_cycle] == 0 } {
	    set tf time_$time
	    set dir "$output_dir/$tf"
	    cmd_mkdir $dir
	    foreach f $store_files {
		if [file exists $f] {
		    cmd_cp $f $dir
		}
	    }
	    #cd storeSep
	    #exec tar -cvf $tf.tar $tf
	    #exec gzip $tf.tar
	    #cmd_rm $tf.tar; cmd_rm $tf
	    #cd ..
	}

	# run sixDOF
	cmd_cp $tri_file_initial $tri_file

	set prog icemcfd/sixDOF
	set argv "-dt $time_step -force $F(0) $F(1) $F(2) \
		-moment $M(0) $M(1) $M(2) -log $sixdof_log_file \
		-cntl $sixdof_cntl_file -info $mesh_info_file \
		-external $sixdof_efm_file"
	busy 1
	set status [run_application_batch $prog SIXDOF_BIN $argv]
	busy 0

	set files [glob $tri_file.*]
	set trifile_time [file mtime $tri_file]
	set new_tri_file ""
	foreach f $files {
	    if {$new_tri_file == "" || [file mtime $f] > [file mtime $new_tri_file]} {
		set new_tri_file $f
	    }
	}

	incr ncycle
	set time [expr $time + $time_step]
	cmd_cp $new_tri_file $tri_file
	cmd_rm $new_tri_file
    }
    cmd_cp $tri_file_initial $tri_file
}


proc get_sixdof_axis_trf {val var} {
    upvar $var sign

    if {$val == "Xb"} { set axis 0; set sign 1}
    if {$val == "-Xb"} { set axis 0; set sign -1}
    if {$val == "Yb"} { set axis 1; set sign 1}
    if {$val == "-Yb"} { set axis 1; set sign -1}
    if {$val == "Zb"} { set axis 2; set sign 1}
    if {$val == "-Zb"} { set axis 2; set sign -1}

    return $axis
}

## Send ctrl-C signal to interrupt the flowCart solver process.
## Solver will stop with writing a check-point file. Then, it can be
## restarted from the left iteration level.

proc ic_cart3d_solver_stop {} {
    global application_pid application_running application_batch_done
    global application_is_remote is_win

    if ![info exists application_pid] {
	mess "Can't terminate process: PID is not known (yet).\n" red
	catch {unset application_running}
	return
    }

    if [tk_dialog .really_stop "Stop Solver" " WARNING: Retstart may not work for some cases; \
        Really Stop the Solver?" "" -1 Yes No] return
    
    if $application_is_remote {
	if [catch {application_exec "kill -s 2 $application_pid" "" 1} res] {
	    mess "$res\n" red
	}
    } elseif $is_win {
        if ![file exists flowCart.STOP] {
            set fp [open flowCart.STOP w]
            puts $fp ""
            close $fp
        }
    } else {
	if [catch {cmd_kill $application_pid 2} res] {
	    mess "$res\n" red
	}
    }
    
    mess "Job Interrupted.\n"
    #set application_batch_done 0
}
set dont_record_command(ic_cart3d_solver_stop) 1

## Convert check pt. status file to full domain result file
## <li> <b>ckpt_file</b> <i>filename</i> (required) : the check. file from cart3d solver
## <li> <b>domain_file</b> <i>filename</i> (optional) : the output domain file
## <li> <b>mesh_file</b> <i>filename</i> (optional) : the .mg file from cart3d mesher
## <li> <b>mesh_info_file</b> <i>filename</i> (required) : the .Mesh.Info file from cart3d mesher
## <li> <b>cntl_file</b> <i>filename</i> (required) : the flowCart input cntl fil
## <li> <b>tri_file</b> <i>filename</i> (required) : the surface mesh tri file
proc ic_run_c3dvis {args} {
    global env

    set ckpt_file ""
    set mesh_file ""
    set mesh_info_file ""
    set cntl_file ""
    set tri_file ""
    set domain_file ""

    foreach {n v} $args {
	switch $n {
	    ckpt_file - mesh_file - mesh_info_file - cntl_file - tri_file - domain_file {
		set $n $v
	    }
	    default {
		mess "Warning: Unknown Option $n\n" red
	    }
	}
    }

    set argv "-t $tri_file"
    if {$mesh_file != ""} {
	append argv " -i $mesh_file"
    }
    if {$domain_file != ""} {
	append argv " -o $domain_file"
    }

    append argv " -v -cntl $cntl_file -info $mesh_info_file -ckpt $ckpt_file -icem -T"

    busy 1
    cmd_rm $domain_file
    set prog icemcfd/output-interfaces/c3dvis
    set status [run_application_batch $prog C3DVIS_BIN $argv]

    if ![file exists $domain_file] {
	mess "Error: Coversion to domain file Failed\n" red
	busy 0
	return 1
    }
    busy 0
    return 0
}

## Write out clic input cntl file
## <li> <b>clic_file</b> <i>clic input file</i> (required) : clic cntl file
## <li> <b>args</b> <i>name value</i> (required) : variables
proc ic_cart3d_write_clic_cntl_file {clic_file args} {
    global is_win

    array set flowCart {}
    foreach {n v} $args {
	set flowCart($n) $v
    }

    # get the actual alpha and beta with which the solver was run
    if [file exists $flowCart(cntl_file)] {
	set fp [open $flowCart(cntl_file) r]
	while {[gets $fp line] >= 0} {
	    if {[lindex $line 0] == "alpha"} {
		set flowCart(alpha) [lindex $line 1]
	    }
	    if {[lindex $line 0] == "beta"} {
		set flowCart(beta) [lindex $line 1]
	    }
	}
	close $fp
    } else {
	mess "Error: $flowCart(cntl_file) does not exist; could not set alpha and beta for the clic computation\n" red
    }

    set fp [open $clic_file w]

    set resfile [file tail $flowCart(result_file)]
    set outdir  [file tail $flowCart(clic_outdir)]
    puts $fp "\$_ClicFileName $resfile"
    puts $fp "\$_Output_Directory $outdir"

    # clic system cmd fails
    if $is_win {
	cmd_mkdir $outdir
    }

    # component name and group
    puts $fp ""
    foreach f $flowCart(families) {
	set surfs $flowCart(surface,$f)
	foreach s $surfs {
	    puts $fp "\$_ComponentName $flowCart(num,$s) $s"
	}
	if {[llength $surfs] > 1} {
	    puts $fp "\$_ComponentGroup $f $surfs"
	}
    }

    # Refarea and Reflength
    set label(area) "\$_Reference_Area"
    set label(length) "\$_Reference_Length"
    foreach param {area length} {
	if [info exists flowCart(set,all,$param)] {
	    set val [format %f $flowCart(set,all,$param)]
	    append ref$param "$label($param) $val entire\n"
	}
	foreach f $flowCart(families) {
	    if [info exists flowCart(set,family,$param,$f)] {
		set val [format %f $flowCart(set,family,$param,$f)]
		append ref$param "$label($param) $val $f\n"
	    }
	    if {[llength $flowCart(surface,$f)] > 1 } {
		foreach s $flowCart(surface,$f) {
		    if [info exists flowCart(set,surface,$param,$s)] {
			set val [format %f $flowCart(set,surface,$param,$s)]
			append ref$param "$label($param) $val $s\n"
		    }
		}
	    }
	}
    }

    if { ![info exists refarea] && ![info exists reflength]} {
	mess "Error: Reference Area and Length must be specified for \
		the components\n" red
	return failure
    }

    puts $fp ""
    puts $fp "$refarea"
    puts $fp "$reflength"

    set alpha [format %f $flowCart(alpha)]
    set beta [format %f $flowCart(beta)]

    puts $fp "\$_Incidence_Angle $alpha"
    puts $fp "\$_Sideslip_Angle $beta\n"

    puts $fp "\$_Model_X_axis_is $flowCart(model_Xaxis)"
    puts $fp "\$_Model_Y_axis_is $flowCart(model_Yaxis)"
    puts $fp "\$_Model_Z_axis_is $flowCart(model_Zaxis)\n"

    # Force-Moment for Entire config.
    if {[info exists flowCart(set,all,force) ] && \
	    $flowCart(set,all,force)} {
	puts $fp "\$_Force entire"
    }

    if {[info exists flowCart(set,all,moment) ] && \
	    $flowCart(set,all,moment)} {
	if {[info exists flowCart(set,all,point_moment)] && \
		[llength $flowCart(set,all,point_moment)] == 3} {
	    puts $fp [format "\$_Moment_Point %f %f %f entire" \
                [lindex $flowCart(set,all,point_moment) 0] \
                [lindex $flowCart(set,all,point_moment) 1] \
                [lindex $flowCart(set,all,point_moment) 2]]
	}
	if {[info exists flowCart(set,all,line_moment_pt1)] && \
		[info exists flowCart(set,all,line_moment_pt2)] && \
		[llength $flowCart(set,all,line_moment_pt1)] == 3 && \
		[llength $flowCart(set,all,line_moment_pt2)] == 3 } {
	    puts $fp [format "\$_Moment_Line %f %f %f %f %f %f entire" \
                [lindex $flowCart(set,all,line_moment_pt1) 0] \
                [lindex $flowCart(set,all,line_moment_pt1) 1] \
                [lindex $flowCart(set,all,line_moment_pt1) 2] \
                [lindex $flowCart(set,all,line_moment_pt2) 0] \
                [lindex $flowCart(set,all,line_moment_pt2) 1] \
                [lindex $flowCart(set,all,line_moment_pt2) 2]]
	}
    }

    # Force-Moment for Families
    foreach f $flowCart(families) {
	if {[info exists flowCart(set,family,force,$f) ] && \
		$flowCart(set,family,force,$f)} {
	    puts $fp "\$_Force $f"
	}
	if {[info exists flowCart(set,family,moment,$f) ] && \
		$flowCart(set,family,moment,$f)} {
	    if {[info exists flowCart(set,family,point_moment,$f)] && \
		    [llength $flowCart(set,family,point_moment,$f)] == 3} {
		puts $fp [format "\$_Moment_Point %f %f %f %s" \
			[lindex $flowCart(set,family,point_moment,$f) 0] \
			[lindex $flowCart(set,family,point_moment,$f) 1] \
			[lindex $flowCart(set,family,point_moment,$f) 2] $f ]
	    }
	    if {[info exists flowCart(set,family,line_moment_pt1,$f)] && \
		    [info exists flowCart(set,family,line_moment_pt2,$f)] && \
		    [llength $flowCart(set,family,line_moment_pt1,$f)] == 3 && \
		    [llength $flowCart(set,family,line_moment_pt2,$f)] == 3} {
		puts $fp [format "\$_Moment_Line %f %f %f %f %f %f %s" \
			[lindex $flowCart(set,family,line_moment_pt1,$f) 0] \
			[lindex $flowCart(set,family,line_moment_pt1,$f) 1] \
			[lindex $flowCart(set,family,line_moment_pt1,$f) 2] \
			[lindex $flowCart(set,family,line_moment_pt2,$f) 0] \
			[lindex $flowCart(set,family,line_moment_pt2,$f) 1] \
			[lindex $flowCart(set,family,line_moment_pt2,$f) 2] $f ]
	    }
	}
    }

    # Force-Moment for Surfaces - Not required for now
    if (0) {
    foreach f $flowCart(families) {
	foreach s $flowCart(surface,$f) {
	    if {[info exists flowCart(set,surface,force,$s) ] && \
		    $flowCart(set,surface,force,$s)} {
		puts $fp "\$_Force $s"
	    }
	    if {[info exists flowCart(set,surface,moment,$s) ] && \
		    $flowCart(set,surface,moment,$s)} {
		if {[info exists flowCart(set,surface,point_moment,$s)] && \
			[llength $flowCart(set,surface,point_moment,$s)] == 3} {
		    puts $fp [format "\$_Moment_Point %f %f %f %s" \
			    [lindex $flowCart(set,surface,point_moment,$s) 0] \
			    [lindex $flowCart(set,surface,point_moment,$s) 1] \
			    [lindex $flowCart(set,surface,point_moment,$s) 2] $s ]
		}
		if {[info exists flowCart(set,surface,line_moment_pt1,$s)] && \
			[info exists \
			flowCart(set,surface,line_moment_pt2,$s)] && \
			[llength $flowCart(set,surface,line_moment_pt1,$s)] == 3 && \
			[llength $flowCart(set,surface,line_moment_pt2,$s)] == 3} {
		    puts $fp [format "\$_Moment_Line %f %f %f %f %f %f %s" \
			    [lindex $flowCart(set,surface,line_moment_pt1,$s) 0] \
			    [lindex $flowCart(set,surface,line_moment_pt1,$s) 1] \
			    [lindex $flowCart(set,surface,line_moment_pt1,$s) 2] \
			    [lindex $flowCart(set,surface,line_moment_pt2,$s) 0] \
			    [lindex $flowCart(set,surface,line_moment_pt2,$s) 1] \
			    [lindex $flowCart(set,surface,line_moment_pt2,$s) 2] $s ]
		}
	    }
	}
    }
    }

    # Cp distribution
    puts $fp ""
    for {set p 1} {$p <= $flowCart(clic_cpdists)} {incr p}  {
	if {[info exists flowCart(set,plane$p,comps)] && \
		[llength $flowCart(plane$p,pt1)] == 3 && \
		[llength $flowCart(plane$p,pt2)] == 3 && \
		[llength $flowCart(plane$p,pt3)] == 3} {
	    puts $fp [format "\$_Distribution %f %f %f %f %f %f %f %f %f %s" \
		    [lindex $flowCart(plane$p,pt1) 0] \
		    [lindex $flowCart(plane$p,pt1) 1] \
		    [lindex $flowCart(plane$p,pt1) 2] \
		    [lindex $flowCart(plane$p,pt2) 0] \
		    [lindex $flowCart(plane$p,pt2) 1] \
		    [lindex $flowCart(plane$p,pt2) 2] \
		    [lindex $flowCart(plane$p,pt3) 0] \
		    [lindex $flowCart(plane$p,pt3) 1] \
		    [lindex $flowCart(plane$p,pt3) 2] \
		    $flowCart(set,plane$p,comps) ]
	}
    }

    close $fp
    mess "wrote clic input file: $clic_file\n"

    return success
}
