
# Stuff to handle the form-factor code.
#
# Copyright (c) 1993, 1994 Pacific Marketing and Consulting
# Author:  Wayne A. Christopher, wayne@pmac.com
#          Pacific Marketing and Consulting, Berkeley, California
#

proc write_formfactors {} {
    global job_name solver_path grid_mapping ff_ims form_factor
    global grid_mesher_params grid_mesher_null null_unstruct nullr_group
    global domain env autohex_root
    
    set tolerance 0.01
    
    if [info exists ff_ims] { foreach i $ff_ims { $i delete } ; unset ff_ims }
    
    # First re-run the mesher with the null parameters.
    
    grid_clear null
    
    foreach i [array names grid_mesher_params] {
	set save($i) $grid_mesher_params($i)
    }
    catch {unset grid_mesher_params}
    foreach i [array names grid_mesher_null] {
	set grid_mesher_params($i) $grid_mesher_null($i)
    }
    
    set d [directory mesh]
    foreach f {grid_output grid_mapping mesh_timestamp} {
	if [file exists $d/$f] { cmd_mv $d/$f $d/$f.save }
    }
    
    grid_generate null
    reduce_mesh_groups null nullr
    
    foreach f {grid_output grid_mapping mesh_timestamp} {
	catch {cmd_mv $d/$f $d/form_factor.$f}
	if [file exists $d/$f.save] {
	    cmd_mv $d/$f.save $d/$f
	}
    }
    
    catch {unset grid_mesher_params}
    foreach i [array names save] {
	set grid_mesher_params($i) $save($i)
    }

    set win [directory solve]/form.FDVWIN
    set fff [directory solve]/form.FDVWFC
    set grp [directory solve]/form.FDVWIN.groups

    #global sidespec sideface; catch {unset sidespec}; catch {unset sideface}

    set numrad 0; set numnrad 0
    foreach obj [db_list_all] {
	set on_def [$obj getval emis_on 0]
	foreach sh [db_shapes $obj] {
	    
	    if {[$sh get_volume] > 0} {
		set cent [$sh get_centroid]
		switch [$obj getval obtype] {
		    domain  { set out 0 }
		    default { set out 1 }
		}
	    } else {
		set cent [[$domain getval body_shape] get_centroid]
		set out 0
	    }
	    
	    # For certain objects (fluid blocks, etc) this should not be 1 ...
	    foreach side [$sh list_sides $out] {
		set sn [lindex $side 1]
		set on_side [$obj getval ${sn}_emis_on 0]
		if {$on_def || $on_side} { incr numrad } else { incr numnrad }
		
		set nn "nullr_group($grid_mapping($sh) [lindex $side 0])"
		
		if {[info exists $nn] && ([[set $nn] count] > 0)} {
		    # Toss in one object for every mesh element.
#puts "[set $nn] get_oriented_faces $cent $out"
		    set "sidespec($obj $sn)" [[set $nn] get_oriented_faces \
						  $cent $out]
#puts "\t[set "sidespec($obj $sn)"]"
		    set bb [[set $nn] get_bbox]
		    set pt ""
		    foreach i {0 1 2} {
			lappend pt [expr {([lindex [lindex $bb 0] $i] * 3 + [lindex [lindex $bb 1] $i] * 2) / 5.0}]
		    }
		    set "pointon($obj $sn)" $pt
		} else {
		    puts "No group for $nn"
		}
		if 0 {
		    # Just grab the whole side.
		    set "sidespec($obj $sn)" [lindex $side 2]
		}
	    }
	}
    }
    set sidespec_names [lsort [array names sidespec]]
    
    if !$numrad {
	#mess "No view factor computation needed.\n"
	#return
    }
    set nodes ""
    set faces ""
    set nn 1; set ne 1
    
    set gfp [open $grp w]
    puts $gfp [llength $sidespec_names]
    
    if 0 {
	set xxx [open list_map w]
        global junk_ims
	if [info exists junk_ims] {
	    foreach i $junk_ims { $i delete }; unset junk_ims
	}
    }
    puts "SSN $sidespec_names"
    set ident 1
    foreach ss $sidespec_names {
	foreach quad $sidespec($ss) {
	    set q $nn
	    set tx 0; set ty 0; set tz 0
	    foreach i {0 1 2 3} {
		set vv [lindex $quad $i]
		append nodes [format "%5d     %10.3E%10.3E%10.3E\n" $q \
				  [lindex $vv 0] [lindex $vv 1] [lindex $vv 2]]
		incr q
		set tx [expr {$tx + [lindex $vv 0]}]
		set ty [expr {$ty + [lindex $vv 1]}]
		set tz [expr {$tz + [lindex $vv 2]}]
	    }
	    append faces [format "%5d%5d%5d%5d%5d%5d\n" $ne $nn \
			      [incr nn] [incr nn] [incr nn] $ident]
	    lappend sideface($ss) $ne
	    set sideface($ne) $ss
	    set quadarea($ne) 1;#[lindex $quad 4]
	    
	    if 0 {
		puts $xxx "[lindex $quad 6] [expr $ne - 1]"
		set n [lindex $quad 5]
		set p1 "[expr $tx / 4] [expr $ty / 4] [expr $tz / 4]"
		set p2 "[expr $tx / 4 + [lindex $n 0]] [expr $ty / 4 + [lindex $n 1]] [expr $tz / 4 + [lindex $n 2]]"
		lappend junk_ims [.v.view add_image [tdv_arrow_geo -point1 $p1 -point2 $p2]]
		lappend junk_ims [.v.view add_image [tdv_text_im -point $p1 -text $ne]]
		
	    }
	    incr ne; incr nn
	    
	}
	puts $gfp "[[lindex $ss 0] getval name] [lindex $ss 1]"
	incr ident
    }
    incr ne -1; incr nn -1
    close $gfp
    #close $xxx
    
    set fp [open $win w]
    puts $fp "** form factor input for job $job_name"
    puts $fp [format "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d" \
		  3 1 $nn $ne 0 0 0 0 0 0 0 0]
    puts -nonewline $fp $nodes
    puts -nonewline $fp $faces
    close $fp
    
    mess "Starting the form factor program ...\n"
    
    set env(FORM_DIR) $autohex_root/form
    exec $env(FORM_DIR)/form [directory solve] form
    
    mess "All done -- the output file should be $fff.\n"
}

proc ff_invalidate {} {
    global form_factor
    catch {unset form_factor}
}

proc ff_print {} {
    global form_factor domain
    
    foreach ff [array names form_factor] {
	if !$form_factor($ff) continue
	if {([lindex $ff 0] == $domain) || ([lindex $ff 2] == $domain)} continue
	set n1 [[lindex $ff 0] getval name]; set n2 [[lindex $ff 2] getval name]
	puts "From $n1 [lindex $ff 1] to $n2 [lindex $ff 3]: $form_factor($ff)"
    }
}
