proc set_abaqus_file {} {
	global file_name abaqus_param_arrays
	global abaqus_Volumes abaqus_Shells abaqus_Bars abaqus_Points
   	if ![info exists abaqus_param_arrays] { set_abaqus_params }
  
	set tmp [writeNastranDEZ get abaqus_file]  
	if {$tmp == ""} {
	if {$file_name(settings) == "" } {
		set base abaqus
		writeNastranDEZ set abaqus_file "abaqus.inp"
	} else {
		set base [file tail [file root $file_name(settings)]]
		writeNastranDEZ set abaqus_file $base.inp
	}
	}

	set tmp [writeNastranDEZ get abaqus_fbc]  
	if {$tmp == ""} {
		writeNastranDEZ set abaqus_fbc $base.abaqus.fbc
	}
  
	set tmp [writeNastranDEZ get abaqus_par]  
	if {$tmp == ""} {
		writeNastranDEZ set abaqus_par $base.abaqus.par
	}
    writeNastranDEZ set abaqus_volumeList {Defined All}
	set tmp [writeNastranDEZ get abaqus_volume]  
	if {$tmp == ""} {
		writeNastranDEZ set abaqus_volume Defined
		set abaqus_Volumes Defined
	}
	 
    writeNastranDEZ set abaqus_shellList {Defined All None}
	set tmp [writeNastranDEZ get abaqus_shell]  
	if {$tmp == ""} {
		writeNastranDEZ set abaqus_shell Defined
		set abaqus_Shells Defined
	}
	 
    writeNastranDEZ set abaqus_barList {Defined All None}
	set tmp [writeNastranDEZ get abaqus_bar]  
	if {$tmp == ""} {
		writeNastranDEZ set abaqus_bar Defined
		set abaqus_Bars Defined
	}
	 
    writeNastranDEZ set abaqus_pointList {Defined All None}
	set tmp [writeNastranDEZ get abaqus_point]  
	if {$tmp == ""} {
		writeNastranDEZ set abaqus_point Defined
		set abaqus_Points Defined
	}
	 
}

proc setup_abaqus_load {} {
	namespace eval ::AIEnv::DEZ::setupNastranRunDEZ {
   		global abaqus_param_arrays
   		if ![info exists abaqus_param_arrays] { set_abaqus_params }
    	foreach {n v} [array get abaqus_param_arrays] {
			array set $n $v
		}

# Structural settings
		set abaqus_Type 0
		set anTypeList {STATIC FREQUENCY}
		set abaqus_anType 0
		set at $analysis(ST/type)
	    foreach t $anTypeList {
			if [string match $at $t] break
			incr abaqus_anType
		}
		
		set abaqus_INC $analysis(INC)
	
		set abaqus_ampList {Stepped Ramped}
		if {$analysis(AMPLITUDE)=="RAMP"} {set abaqus_AMPLITUDE Ramped
		} else {set abaqus_AMPLITUDE Stepped}
		
		set abaqus_nlgList {NO YES}
		set abaqus_NLGEOM $analysis(NLGEOM)
		
		set abaqus_initi $analysis(ST/initi)
		set abaqus_timei $analysis(ST/timei)
		set abaqus_mini $analysis(ST/mini)
		set abaqus_maxi $analysis(ST/maxi)

		set abaqus_modsolvList {LANCZOS SUBSPACE}
		set abaqus_mod_solv $analysis(ST/mod_solv)
		
		set abaqus_mod_n $analysis(ST/mod_n)
		set abaqus_mod_freq1 $analysis(ST/mod_freq1)
		set abaqus_mod_freq2 $analysis(ST/mod_freq2)
		set abaqus_mod_shift $analysis(ST/mod_shift)
		set abaqus_mod_iter $analysis(ST/mod_iter)
	
		set abaqus_normList {"Largest displacement" "Mass matrix"}
		if {$analysis(ST/mod_norm)=="MASS"} {set abaqus_mod_norm "Mass matrix"
		} else {set abaqus_mod_norm "Largest displacement"}
		
	}
}

proc setup_abaqus_apply {} {
    global env abaqus_param_arrays

# get the abaqus settings
    foreach {n v} $abaqus_param_arrays(analysis) { set analysis($n) $v }

# Structural params
	set l {STATIC FREQUENCY}
	set t [setupNastranRunDEZ get abaqus_anType]
	set analysis(ST/type) [lindex $l $t]
	
	set analysis(INC) [setupNastranRunDEZ get abaqus_INC]

	set o STEP
	set t [setupNastranRunDEZ get abaqus_AMPLITUDE]
	if {$t=="Ramped"} {set o RAMP}
	set analysis(AMPLITUDE) $o

	set analysis(NLGEOM) [setupNastranRunDEZ get abaqus_NLGEOM]
		
	set analysis(ST/initi) [setupNastranRunDEZ get abaqus_initi]
	set analysis(ST/timei) [setupNastranRunDEZ get abaqus_timei]
	set analysis(ST/mini) [setupNastranRunDEZ get abaqus_mini]
	set analysis(ST/maxi) [setupNastranRunDEZ get abaqus_maxi]

	set analysis(ST/mod_solv) [setupNastranRunDEZ get abaqus_mod_solv]
		
	set analysis(ST/mod_n) [setupNastranRunDEZ get abaqus_mod_n]
	set analysis(ST/mod_freq1) [setupNastranRunDEZ get abaqus_mod_freq1]
	set analysis(ST/mod_freq2) [setupNastranRunDEZ get abaqus_mod_freq2]
	set analysis(ST/mod_shift) [setupNastranRunDEZ get abaqus_mod_shift]
	set analysis(ST/mod_iter) [setupNastranRunDEZ get abaqus_mod_iter]
	
	set o DISPLACEMENT
	set t [setupNastranRunDEZ get abaqus_mod_norm]
	if {$t=="Mass matrix"} {set o MASS}
	set analysis(ST/mod_norm) $o

# update abaqus_product settings
	set abaqus_param_arrays(analysis) [array get analysis]
}

proc onAbaqusModSolvModify {dez val} {
#	puts "onAbaqusModSolvModify dez=$dez, val=$val"
    if {$val == "SUBSPACE"} {
        ::AIEnv::GUIManagement::ToggleGrey abaqusModF1 1
    } else {
        ::AIEnv::GUIManagement::ToggleGrey abaqusModF1 0
	}
}

proc set_abaqus_params {} {
    global  env solver_setup solver_type
    global abaqus_param_arrays

	array set analysis {
		type ST
		INC 100
		AMPLITUDE STEP
		NLGEOM NO
		ST/type STATIC
		ST/initi 0.1
		ST/timei 1.0
		ST/mini 1e-05
		ST/maxi 1.0
		ST/mod_solv LANCZOS
		ST/mod_n 10
		ST/mod_freq1 0.0
		ST/mod_freq2 1e+08
		ST/mod_shift 1.0
		ST/mod_iter 30
		ST/mod_norm DISPLACEMENT
		TH/trans 0
		TH/END PERIOD
		TH/DELTMX 0
		TH/DELTMX_val 100.0
		TH/initi 0.1
		TH/timei 1.0
		TH/mini 1e-05
		TH/maxi 1.0
		TH/tcr 0.001
	}
	set abaqus_param_arrays(analysis) [array get analysis]

	array set offset {
		node 0
		elem 0
	}
	set abaqus_param_arrays(offset) [array get offset]

	array set transform {
		all 0
		type R
		a ""
		b ""
	}
	set abaqus_param_arrays(transform) [array get transform]
}

proc set_abaqus_solve {} {
# unused...
}

proc solve_abaqus_file {} {
	mess "Sorry, Abaqus solver run not yet implemented.\n"
	return
}

proc set_abaqus_post {} {
    global  env solver_setup solver_type
}

proc post_abaqus_file {} {
    global  env solver_setup solver_type

    set solver_setup 3
}

proc update_abaqus_setup {} {
    global  env solver_setup solver_type

    set solver_setup 3
    	
}

proc aie_generate_abaqus_data {} {
    set afbc [writeNastranDEZ get abaqus_fbc]
    set apar [writeNastranDEZ get abaqus_par]
    
    aie_saveProject 0 1
    mess "Creating the Abaqus attribute & parameter files....\n"
    return [aie_convert_nastran_abaqus_files $afbc $apar]
}

proc abaqus_famboco_edit {} {
    global file_name param_values famboco_data
    
	set saved_atr ""
	if [info exists file_name(attributes)] {
		set saved_atr $file_name(attributes)
	}

	set saved_fbc ""
	if [info exists file_name(family_boco)] {
		set saved_fbc $file_name(family_boco)
		ic_boco_unload
	}

	set saved_par ""
	if [info exists file_name(solver_params)] {
		set saved_par $file_name(solver_params)
	}

    set ft [writeNastranDEZ get abaqus_fbc]
    if [catch {ic_boco_load $ft} res] {
	mess "Error in opening family_boco file; $res\n" red
	if {$saved_atr!=""} {
		set file_name(attributes) $saved_atr
	}
	if {$saved_fbc!=""} {
		set file_name(family_boco) $saved_fbc
		aie_open_attr 0 0
	}
	#refresh icons before returning
	aie_initialize_tree_props_and_icons
	return
    }
	
    set fp [writeNastranDEZ get abaqus_par]
    if [catch {famboco_edit_load_param_values $fp 1} res] {
	mess "Error in opening params file; $res\n" red
	if {$saved_par!=""} {
		set file_name(solver_params) $saved_par
		aie_open_params 0 0
	}
	if {$saved_atr!=""} {
		set file_name(attributes) $saved_atr
	}
	if {$saved_fbc!=""} {
		set file_name(family_boco) $saved_fbc
		aie_open_attr 0 0
	}
	#refresh icons before returning
	aie_initialize_tree_props_and_icons
	return
    }

	set file_name(attributes) ""
	set file_name(attributes_loaded) 0
	set file_name(family_boco) $ft
	set file_name(family_boco_loaded) 1
	set file_name(solver_params) $fp
	set file_name(solver_params_loaded) 1

    aie_famboco_edit ABAQUS
    aie_save_attr

#    catch {unset param_values}
#the following correctly resets param_values in the ic scope of the batch interpreter
	ic_param_set_all ""
    catch {unset famboco_data}
	ic_boco_unload
	if {$saved_par!=""} {
		set file_name(solver_params) $saved_par
		aie_open_params 0 0
	} else {
		set file_name(solver_params) ""
		set file_name(solver_params_loaded) 0
	}
	if {$saved_atr!=""} {
		set file_name(attributes) $saved_atr
		set file_name(attributes_loaded) 1
	} else {
		set file_name(attributes) ""
	}
	if {$saved_fbc!=""} {
		set file_name(family_boco) $saved_fbc
		aie_open_attr 0 0
	} else {
		set file_name(family_boco) ""
		set file_name(family_boco_loaded) 0
	}
	#refresh icons before returning
	aie_initialize_tree_props_and_icons
	return	
}

proc abaqus_params_edit {} {
    global file_name param_values
    
	set saved_par ""
	if [info exists file_name(solver_params)] {
		set saved_par $file_name(solver_params)
	}

	set saved_atr ""
	if [info exists file_name(attributes)] {
		set saved_atr $file_name(attributes)
	}

	set saved_fbc ""
	if [info exists file_name(family_boco)] {
		set saved_fbc $file_name(family_boco)
		ic_boco_unload
	}

    set fp [writeNastranDEZ get abaqus_par]
    if [catch {famboco_edit_load_param_values $fp 1} res] {
	mess "Error in opening params file; $res\n" red
	if {$saved_par!=""} {
    	catch {unset param_values}
		set file_name(solver_params) $saved_par
		aie_open_params 0 0
	}
	if {$saved_atr!=""} {
		set file_name(attributes) $saved_atr
	}
	if {$saved_fbc!=""} {
		set file_name(family_boco) $saved_fbc
		aie_open_attr 0 0
	}
	#refresh icons before returning
	aie_initialize_tree_props_and_icons
	return
	}

    set ft [writeNastranDEZ get abaqus_fbc]
    if [catch {ic_boco_load $ft} res] {
	mess "Error in opening family_boco file; $res\n" red
	if {$saved_par!=""} {
    	catch {unset param_values}
		set file_name(solver_params) $saved_par
		aie_open_params 0 0
	}
	if {$saved_atr!=""} {
		set file_name(attributes) $saved_atr
	}
	if {$saved_fbc!=""} {
		set file_name(family_boco) $saved_fbc
		aie_open_attr 0 0
	}
	#refresh icons before returning
	aie_initialize_tree_props_and_icons
	return
    }

	set file_name(attributes) ""
	set file_name(attributes_loaded) 0
	set file_name(solver_params) $fp
	set file_name(solver_params_loaded) 1
	set file_name(family_boco) $ft
	set file_name(family_boco_loaded) 1

    aie_params_edit ABAQUS
#the following is already achieved by ic_param_save which gets
#called from within famboco_edit_params with reload=2
#	famboco_edit_save_param_values $fp

	ic_boco_unload
#    catch {unset param_values}
#the following correctly resets param_values in the ic scope of the batch interpreter
	ic_param_set_all ""

	if {$saved_par!=""} {
		set file_name(solver_params) $saved_par
		aie_open_params 0 0
	} else {
		set file_name(solver_params) ""
		set file_name(solver_params_loaded) 0
	}
	if {$saved_atr!=""} {
		set file_name(attributes) $saved_atr
		set file_name(attributes_loaded) 1
	} else {
		set file_name(attributes) ""
	}
	if {$saved_fbc!=""} {
		set file_name(family_boco) $saved_fbc
		aie_open_attr 0 0
	} else {
		set file_name(family_boco) ""
		set file_name(family_boco_loaded) 0
	}
	#refresh icons before returning
	aie_initialize_tree_props_and_icons
	return	
}

proc write_abaqus_file {} {
	global env file_name tcl_platform
	global  env solver_setup solver_type

	set solver_setup 3
	aie_saveProject 0 1

    set abaqus_file [writeNastranDEZ get abaqus_file]
    set view_file [writeNastranDEZ get view_file]

#    set afbc [file rootname $file_name(family_boco)].abaqus.fbc
#    set apar [file rootname $file_name(solver_params)].abaqus.par
    set afbc [writeNastranDEZ get abaqus_fbc]
    set apar [writeNastranDEZ get abaqus_par]
    
    if ![writeNastranDEZ get abaqusEditOptionVal] {
        aie_saveProject 0 1
        mess "Creating the Abaqus attribute & parameter files....\n"
        if ![aie_convert_nastran_abaqus_files $afbc $apar] return
    }
    
    mess "Creating the Abaqus Input File.  Please Wait....\n"
    # This runs the translator
    if ![aie_export_abaqus $abaqus_file $file_name(domain) \
	     $afbc $apar] return
    
    if $view_file {
	edit_file $abaqus_file 1
    }
}

# -------------------------------------------------

proc aie_export_abaqus {abaqus_file domain family_boco solver_params} {
    global env bindir tcl_platform
	global abaqus_Volumes abaqus_Shells abaqus_Bars abaqus_Points
    
    set abaqus_exec $env(ICEM_ACN)/icemcfd/output-interfaces/abaqus
    if {$tcl_platform(platform) == "windows"} {
	append abaqus_exec .exe
    }
    
    regsub -all \\\\ $abaqus_exec / abaqus_exec
    
    if ![file executable $abaqus_exec] {
	error "Can't find Converter executable $abaqus_exec"
	return 0
    }
    
	if {[writeNastranDEZ get abaqus_volume]!=$abaqus_Volumes} {
		mess "WARNING: Attribute file out-of-date for volume elements\n" red
	}

	set no_shell 0
	set shl [writeNastranDEZ get abaqus_shell]
	if {$shl=="None"} {
		set no_shell 1
	} else {
		if {$shl!=$abaqus_Shells} {
			mess "WARNING: Attribute file out-of-date for shell elements\n" red
		}
	}

	set no_bar 0
	set br [writeNastranDEZ get abaqus_bar]
	if {$br=="None"} {
		set no_bar 1
	} else {
		if {$br!=$abaqus_Bars} {
			mess "WARNING: Attribute file out-of-date for bar elements\n" red
		}
	}

	set no_node 0
	set nd [writeNastranDEZ get abaqus_point]
	if {$nd=="None"} {
		set no_node 1
	} else {
		if {$nd!=$abaqus_Points} {
			mess "WARNING: Attribute file out-of-date for point elements\n" red
		}
	}

    set abaqus_cmd [list $abaqus_exec -dom $domain -b $family_boco -par $solver_params $abaqus_file]
#    set no_node [writeNastranDEZ get abaqusIgnoreNodeVal]
	if $no_node { lappend abaqus_cmd -ignore_node }
#    set no_bar [writeNastranDEZ get abaqusIgnoreBarVal]
	if $no_bar { lappend abaqus_cmd -ignore_bar }
#    set no_shell [writeNastranDEZ get abaqusIgnoreShellVal]
	if $no_shell { lappend abaqus_cmd -ignore_shell }
    
    mess $abaqus_cmd\n
    
    if {![catch {eval ic_exec $abaqus_cmd} out]} {
	mess "$out\n"
	return 1
    } else {
	mess "Error \n $out\n" red
	return 0
    }
}

# -------------------------------------------------

proc aie_convert_nastran_abaqus_files {afbc apar} {
	global abaqus_Volumes abaqus_Shells abaqus_Bars abaqus_Points
	global gasket_has_abaqus_mp
	catch {unset gasket_has_abaqus_mp}
    foreach f [ic_boco_list_unused] { set unused($f) 1 }
    set fp [open $afbc w]
    puts $fp "# family_boco file written for AI*Environment on [cmd_date]"
    puts $fp "# solver Abaqus"

# transform reset moved up as the transforms are created alongwith lcs...
	abaqus_reset_transforms
	abaqus_add_LCS
#material data translation moved upstream for reading off applicable gasket properties
	abaqus_add_materials
	
	set famlist [ic_boco_list_families]
    foreach fam $famlist {
	if {$fam=="ORFN"||$fam=="VORFN"} continue
	if [info exists unused($fam)] continue
	set bcs [ic_boco_get $fam]
	
	puts $fp "\"$fam\""
	
	# Each type of bc has a aie_parse_bcs_ function.  This returns a list
	# of name / value pairs that have the data for that type of bc.
# full list for etypes as follows; only 1 provided, for the time being...
# foreach etype {constraint impdisp force pressure temperature element_prop} 
	foreach etype {impdisp force pressure temperature \
					element_prop_0d element_prop_1d element_prop_2d element_prop_3d } {
             	foreach g [split $fam :] {
	        set bcs [ic_boco_get $g]
	        set data [aie_parse_bcs_$etype $bcs]
	        if {$data == ""} continue
	    
	        aie_write_abaqus_bc_$etype $fp $fam $data
             	}
	}
    }
    puts $fp ""
    close $fp

	abaqus_add_contacts

#	abaqus_add_materials

#	abaqus_add_LCS
	
#set family dimension info
	ic_boco_reset_fam_dim
#	catch {unset fam_dim}
   	foreach fam $famlist {
		set dims [ic_boco_fam_dim $fam 1]
#puts "$fam dims=$dims"
		foreach dim $dims {
			regsub -all {[a-zA-Z]} $dim "" dim
			switch -exact $dim {
				0 - 1 - 2 - 3 {
					if ![info exists fam_dim($fam)] {
						set fam_dim($fam) $dim
					} elseif {$dim>$fam_dim($fam)} {
						set fam_dim($fam) $dim
					}
				}
			}
		}
	}
#puts "fam_dim: [array get fam_dim]"

# add element type bcs for mesh dump
    set fp [open $afbc a]

	set abaqus_Volumes [writeNastranDEZ get abaqus_volume]
	if {$abaqus_Volumes == "All"} {
    	foreach fam $famlist {
		if {![info exists fam_dim($fam)] || $fam_dim($fam)!=3} continue
		if {$fam=="ORFN"||$fam=="VORFN"} continue
		if [info exists unused($fam)] continue
		set bcs [ic_boco_get $fam]
	    set data [aie_parse_bcs_element_prop_3d $bcs]
	    if {$data != ""} continue
	    puts $fp "\"$fam\" \"SOLID3D\" 0 0"
		}
	}
	
	set abaqus_Shells [writeNastranDEZ get abaqus_shell]
	if {$abaqus_Shells == "All"} {
    	foreach fam $famlist {
		if {![info exists fam_dim($fam)] || $fam_dim($fam)!=2} continue
		if {$fam=="ORFN"||$fam=="VORFN"} continue
		if [info exists unused($fam)] continue
		set bcs [ic_boco_get $fam]
	    set data [aie_parse_bcs_element_prop_2d $bcs]
	    if {$data != ""} continue
	    puts $fp "\"$fam\" \"SHELL\" 0 0 0 0"
		}
	}
	
	set abaqus_Bars [writeNastranDEZ get abaqus_bar]
	if {$abaqus_Bars == "All"} {
    	foreach fam $famlist {
		if {![info exists fam_dim($fam)] || $fam_dim($fam)!=1} continue
		if {$fam=="ORFN"||$fam=="VORFN"} continue
		if [info exists unused($fam)] continue
		set bcs [ic_boco_get $fam]
	    set data [aie_parse_bcs_element_prop_1d $bcs]
	    if {$data != ""} continue
	    puts $fp "\"$fam\" \"BEAM\" 0 0 0 0"
		}
	}
	
	set abaqus_Points [writeNastranDEZ get abaqus_point]
	if {$abaqus_Points == "All"} {
    	foreach fam $famlist {
		if {![info exists fam_dim($fam)] || $fam_dim($fam)!=0} continue
		if {$fam=="ORFN"||$fam=="VORFN"} continue
		if [info exists unused($fam)] continue
		set bcs [ic_boco_get $fam]
	    set data [aie_parse_bcs_element_prop_0d $bcs]
	    if {$data != ""} continue
	    puts $fp "\"$fam\" \"MASS\" 0.0"
		}
	}
    close $fp
    
    # Abaqus fbc file replay support
    set fp [open $afbc r]
	set afbc_contents ""
    while {![eof $fp]} {
		set line [gets $fp]
		append afbc_contents $line \\n
	}
    close $fp
	ic_write_file $afbc $afbc_contents 
   

#    set fp [open $apar w]
    abaqus_params_save_solve_data $apar
#    close $fp

#Abaqus par file replay support for regression testing
    set fp [open $apar r]
	set apar_contents ""
    while {![eof $fp]} {
		set line [gets $fp]
		append apar_contents $line \\n
	}
    close $fp
	ic_write_file $apar $apar_contents
	
	
	return 1
}

# For each type of data this will translate the "generic" data into the abaqus
# data and write it to the fbc file.  The data argument is a list of name /
# value pairs.

# Single-point constraints - data may be: spcSet UX UY UZ ROTX ROTY ROTZ

#Following proc is unused; aie_write_abaqus_bc_impdisp serves the purpose instead.
proc unused__aie_write_abaqus_bc_constraint {fp fam data} {
    foreach {n v} $data { set vals($n) $v }
    
    foreach {t dof} {UX 1 UY 2 UZ 3 ROTX 4 ROTY 5 ROTZ 6} {
	if {[info exists vals($t)] && ($vals($t) == 1)} {
	    puts $fp "\"$fam\" \"BOUNDARY\" $vals(spcSet) $dof 0.0"
	}
    }
}

proc aie_get_abaqus_step_for_spcset {sid} {
	if {$sid==""} {return 1}
	foreach id [aie_list_subcases] {
		array set opts [ic_param_get_values :Subcase/$id]
		if {[info exists opts(ACTIVE)] && $opts(ACTIVE)==0} continue
		if {[info exists opts(SPC)] && $opts(SPC)!="" && $opts(SPC)==$sid} {
			return $id
		}
	}
	return 1
}

# Imposed displacements - data names can be: spcSet CheckUX CheckUY CheckUZ 
# UX UY UZ CheckROTX CheckROTY CheckROTZ ROTX ROTY ROTZ LCS

proc aie_write_abaqus_bc_impdisp {fp fam data} {
	global lcs_data abaqus_param_arrays
    foreach {n v} $data { set vals($n) $v }
	set spcSet [aie_get_abaqus_step_for_spcset $vals(spcSet)]

    foreach {t dof} {UX 1 UY 2 UZ 3 ROTX 4 ROTY 5 ROTZ 6} {
	if {[info exists vals(Check$t)] && ($vals(Check$t) == 1)} {
		puts $fp "\"$fam\" \"BOUNDARY\" $spcSet $dof $vals($t)"
	}
    }
	
	if {[info exists vals(LCS)]} {
		if {$vals(LCS)!=0} {
			set lcs ""
			foreach l [array names lcs_data] {
				if {[lindex $lcs_data($l) 0]==$vals(LCS)} {
					set lcs [lindex $lcs_data($l) 1]
					break
				}
			}
			if {$lcs==""} return
			array set transform $abaqus_param_arrays(transform)
			set trans Transform_$lcs
			set node specific:$trans
#puts "impdisp transformation $node"
			if ![info exists transform($node/name)] {
				set transform($node/name) $trans
				array set define $abaqus_param_arrays(orient:$lcs)
				set transform($node/type) [string index $define(type) 0]
				set transform($node/a) $define(a)
				set transform($node/b) $define(b)
				set abaqus_param_arrays(transform) [array get transform]
			}
			puts $fp "\"$fam\" \"TRANSFORM\" \"$trans\""
		}
	}
}

proc aie_get_abaqus_step_for_loadset {lid} {
	if {$lid==""} {return 1}
	foreach id [aie_list_subcases] {
		array set opts [ic_param_get_values :Subcase/$id]
		if {[info exists opts(ACTIVE)] && $opts(ACTIVE)==0} continue
		if {[info exists opts(LOAD)] && $opts(LOAD)!="" && $opts(LOAD)==$lid} {
			return $id
		}
	}
	return 1
}

# Forces and moments - data can be: loadSet LCS scale FX FY FZ MX MY MZ force_type

proc aie_write_abaqus_bc_force {fp fam data} {
	global lcs_data abaqus_param_arrays
    foreach {n v} $data { set vals($n) $v }
  	set force_type 0
	if {[info exists vals(force_type)] && $vals(force_type)!=""} {
		set force_type $vals(force_type)
	}
	if $force_type {
		mess "Warning: \"Total\" option not yet supported for forces (Part $fam)\n" red
		return
	}
    
	set loadSet [aie_get_abaqus_step_for_loadset $vals(loadSet)]
    
	set scale 1.0
	if {[info exists vals(scale)]} {
		if {$vals(scale)!=""} {set scale $vals(scale)}
	}

    foreach t {FX FY FZ MX MY MZ} {
	if {[info exists vals($t)]} {
		if {$vals($t)==""} {set vals($t) 0.0}
	} else {
		set vals($t) 0.0
	}
	set vals($t) [expr $scale*$vals($t)]
	}
	puts $fp "\"$fam\" \"CLOAD\" $loadSet $vals(FX) $vals(FY) $vals(FZ) $vals(MX) $vals(MY) $vals(MZ)"
	
	if {[info exists vals(LCS)]} {
		if {$vals(LCS)!="Global"} {
			set lcs ""
			foreach l [array names lcs_data] {
				if {[lindex $lcs_data($l) 1]==$vals(LCS)} {
					set lcs [lindex $lcs_data($l) 1]
					break
				}
			}
			if {$lcs==""} return
			array set transform $abaqus_param_arrays(transform)
			set trans Transform_$lcs
			set node specific:$trans
#puts "force transformation $node"
			if ![info exists transform($node/name)] {
				set transform($node/name) $trans
				array set define $abaqus_param_arrays(orient:$lcs)
				set transform($node/type) [string index $define(type) 0]
				set transform($node/a) $define(a)
				set transform($node/b) $define(b)
				set abaqus_param_arrays(transform) [array get transform]
			}
			puts $fp "\"$fam\" \"TRANSFORM\" \"$trans\""
		}
	}
}

# Pressure - data can be: loadSet pres vol for PLOAD2
# Pressure - data can be: loadSet LCS vect1 vect2 vect3 pres pres2 pres3 pres4 for PLOAD4

proc aie_write_abaqus_bc_pressure {fp fam data} {
    foreach {n v} $data { set vals($n) $v }
	if [info exists vals(LCS)] {
		mess "Conversion of general pressure load not supported.\n"
		return
	}
	set loadSet [aie_get_abaqus_step_for_loadset $vals(loadSet)]
    
	if {[info exists vals(pres)]} {
		if {$vals(pres)==""} {set vals(pres) 0.0}
		if {[expr double($vals(pres))]==0.0} return
		set shells 1
		if {[writeNastranDEZ get abaqus_shell]=="Defined"} {
		set bcs [ic_boco_get $fam]
	    set shell_data [aie_parse_bcs_element_prop_2d $bcs]
	    if {$shell_data == ""} {
			set shells 0
		}
		} elseif {[writeNastranDEZ get abaqus_shell]=="None"} {
			set shells 0
		}
		puts $fp "\"$fam\" \"DLOAD\" $loadSet 8 $vals(pres) 0.0 0.0 0.0 0.0 0.0 0.0 0 0 $shells 0 0"
	}
}

proc aie_get_abaqus_step_for_tempset {tid} {
	if {$tid==""} {return 1}
	foreach id [aie_list_subcases] {
		array set opts [ic_param_get_values :Subcase/$id]
		if {[info exists opts(ACTIVE)] && $opts(ACTIVE)==0} continue
		if {[info exists opts(TEMP)] && $opts(TEMP)!="" && $opts(TEMP)==$tid} {
			return $id
		}
	}
	return 1
}

# Temperature - data can be: loadSet temp

proc aie_write_abaqus_bc_temperature {fp fam data} {
    foreach {n v} $data { set vals($n) $v }
	set loadSet [aie_get_abaqus_step_for_tempset $vals(loadSet)]
    
	if {[info exists vals(temp)]} {
		if {$vals(temp)==""} {set vals(temp) 0.0}
	    puts $fp "\"$fam\" \"TEMPERATURE\" $loadSet $vals(temp)"
	}
}

# Element types - one of the data elements can be etype which is the
# type of element, and the other data depend on that one.
# Etype            Other data
# -----            ----------
# "Mass point"     pid mass
# "Bar"            pid mat bar_a bar_i1 bar_i2 bar_j bar_x1 bar_x2 bar_x3
# "Rigid beam"     indep_dof_cna indep_dof_cnb dep_dof_cna dep_dof_cnb
#                  beam_type_index dep_dofs weight indep_dofs
# "Rod connection" mat area torsconst torscoeff nsm
# "Damper connection"	pid force_per_vel component_c1 component_c2
# "Spring"         pid stiff damp stress stress component_c1 component_c2
# "Viscous damper" pid damp_ext damp_rot
# "Shell"          pid mat mat_b mat_t nsm mat_c m_thick b_stiff t_stiff
# "Shear"          pid mat thick nsm
# "Volume"         mat LCS pid gasket gasket_gap_data gasket_loading_data gasket_unloading_data gasket_tss_data
# "Beam"           pid mat bar_a bar_i1 bar_i2 bar_i12 bar_j
#"Beam Cross-Section"	pid mat group beamcs_type beam_type_option nsm_length_a nsm_length_b so_b_option dim dims

# Temporary ...  -Wayne
foreach i {0 1 2 3} {
    proc aie_write_abaqus_bc_element_prop_${i}d {fp fam data} {
	return [aie_write_abaqus_bc_element_prop $fp $fam $data]
    }
}

proc aie_write_abaqus_bc_element_prop {fp fam data} {
	global abaqus_param_arrays material_data lcs_data
	global gasket_has_abaqus_mp
	regsub -all : $fam _ spbug
	regsub -all / $spbug __ spbug
    foreach {n v} $data { set vals($n) $v }
	#reset all -999999's to ""
	foreach p [array names vals] {
		if {$vals($p)==-999999} { set vals($p) "" }
	}
	
	if ![info exists vals(mat)] {
		set vals(mat) ""
	} else {
#		mess "fam= $fam, vals(mat) = $vals(mat)\n"
	}
    
# get WTMASS parameter from Nastran.
	set wtmass [setupNastranRunDEZ get wtmass]
	if {$wtmass==""} {set wtmass 1.0}

	if [info exists vals(etype)] {
#mess "family: $fam\n"
#mess "vals: [array get vals]\n"
		switch $vals(etype) {
		Volume {
			set lcs ""
			set lcs_flag 0 
			if {[info exists vals(LCS)]} {
				if {$vals(LCS)!="Global"} {
					foreach l [array names lcs_data] {
						if {[lindex $lcs_data($l) 1]==$vals(LCS)} {
							set lcs [lindex $lcs_data($l) 1]
							break
						}
					}
					if {$lcs!=""} {
						if {$vals(gasket)} {
							mess "Warning: Skipping LCS for gasket elements\n"
							set lcs ""
						} else {
							set lcs_flag 1
						}
					}
				}
			}
			if {[info exists vals(gasket)]} {

					set mat_gasket None
					set gap 0.0
					if {[info exists vals(mat)] && $vals(mat)!=""} {
						set alp ""
						set mb ""
						array set tb { \
							opt None opt0 0 \
							exp0 0 exp1 0 exp2 0 exp3 0 \
							opt1 0 Crp 0 \
						}
						set mat $vals(mat)
						if {![info exists gasket_has_abaqus_mp($mat)]} {
							if {[info exists abaqus_param_arrays(mat:$mat)]} {
								catch {unset abaqus_mat}
								array set abaqus_mat $abaqus_param_arrays(mat:$mat)
#thermal expansion coefficients
								set alp_type ""
								if $abaqus_mat(EXPANSION/define) {
								  switch $abaqus_mat(EXPANSION/type) {
									0 {
										set alp_type ISO
									}
									1 {
										set alp_type ORTHO
									}
									2 {
										set alp_type ANISO
									}
								  }
								}
								if {$alp_type!=""} {
									if [info exists abaqus_mat(EXPANSION/$alp_type/line:line1/c0)] {
										mess "Warning: Tempearture variation ignored for ${alp_type}TROPIC gasket expansion\n"
									}
									switch $abaqus_mat(EXPANSION/type) {
										0 {
											set alp $abaqus_mat(EXPANSION/$alp_type/line:line0/c0)
										}
										1 {
											set alp [list $abaqus_mat(EXPANSION/$alp_type/line:line0/c0) \
														$abaqus_mat(EXPANSION/$alp_type/line:line0/c1) \
														$abaqus_mat(EXPANSION/$alp_type/line:line0/c2)]
										}
										2 {
											mess "Warning: ANISOTROPIC gasket expansion converted to ORTHOTROPIC\n"
											set alp [list $abaqus_mat(EXPANSION/$alp_type/line:line0/c0) \
														$abaqus_mat(EXPANSION/$alp_type/line:line0/c2) \
														$abaqus_mat(EXPANSION/$alp_type/line:line0/c5)]
										}
									}
								}
#membrane properties
								set mb_type ""
								if $abaqus_mat(ELASTIC/define) {
								  switch $abaqus_mat(ELASTIC/type) {
									0 {
										set mb_type ISOTROPIC
									}
									default {
										mess "Warning: Non-isotropic membrane properties ignored for gasket\n"
									}
								  }
								}
								if {$mb_type!=""} {
									catch {unset membrane}
									foreach node [array names abaqus_mat] {
										if [regsub ^ELASTIC/$mb_type/line:line $node "" lnum] {
											regsub /c\[0-9\]+$ $lnum "" id
											switch [string index $lnum end] {
												0 {set membrane(E,$id) $abaqus_mat($node)}
												1 {set membrane(nu,$id) $abaqus_mat($node)}
												2 {set membrane(T,$id) $abaqus_mat($node)}
											}
										}
									}
									foreach prop [array names membrane] {
										lappend mb "$prop $membrane($prop)"
									}
										
								}
							}
						} else {
							set alp [lindex $gasket_has_abaqus_mp($mat) 0]
							set mb [lindex $gasket_has_abaqus_mp($mat) 1]
						}
						set mat_gasket Gasket_Behavior_$spbug
						set gasket_node gmat:$mat_gasket
						set gasket_behavior(name) $mat_gasket
						if {$alp!=""} {
							switch [llength $alp] {
								1 {
									set tb(opt0) 1
									set tb(exp0) $alp
								}
								3 {
									set tb(opt0) 2
									foreach dir {0 1 2} {
										set dd [expr $dir + 1]
										set tb(exp$dd) [lindex $alp $dir]
									}
								}
							}
							foreach node [array names tb] {
#								set gasket_behavior(tb/$node) $tb($node)
							}
						}
						if {$mb!=""} {
							set gasket_behavior(GaskElst/MB/opt2) 1
							set gasket_behavior(GaskElst/MB/E) 0.0
							set gasket_behavior(GaskElst/MB/nu) 0.0
							foreach pair $mb {
								set node [split [lindex $pair 0] ,]
								set prop [lindex $node 0]
								set id [lindex $node 1]
								set gasket_behavior(GaskElst/MB/T-mdata:T-mdata$id/$prop) [lindex $pair 1]
							}
						}
						set gasket_has_abaqus_mp($mat) [list $alp $mb]
#intial gap
						if [lindex $vals(gasket_gap_data) 0] {
							if {[lindex $vals(gasket_gap_data) 1]!=""} {
								set gap [lindex $vals(gasket_gap_data) 1]
							}
						}
#compression loading
						if {[lindex $vals(gasket_loading_data) 2]!=""} {

							set tb(opt) DMG
							set tb(DMG/opt3) 0
							set tb(DMG/opt4) 0
							set tb(DMG/lcrv/opt1) 0
							set tb(DMG/lcrv/tsf) 0.0
							set opt2 [lindex $vals(gasket_loading_data) 1]
							set tb(DMG/lcrv/opt2) $opt2

							if $opt2 {
							  set ntemp [llength [lindex $vals(gasket_loading_data) 2]]
							  set tb(DMG/lcrv/opt2) 1
							  set k 0
							  for {set i 0} {$i<$ntemp} {incr i} {
								set params [lindex [lindex $vals(gasket_loading_data) 2] $i]
								set temp [lindex $params 0]
								catch {unset comp}
								set j 0
								foreach {x y} [lrange $params 1 end] {
									set comp($j) [list $x $y]
									incr j
								}
								foreach point [lsort -increasing [array names comp]] {
									set pair $comp($point)
									set pres [lindex $pair 0]
									set closure [lindex $pair 1]
									set tb(DMG/lcrv/T-Lpt:T-Lpt$k/F) $pres
									set tb(DMG/lcrv/T-Lpt:T-Lpt$k/CL) $closure
									set tb(DMG/lcrv/T-Lpt:T-Lpt$k/T) $temp
									incr k
								}
							  }
							} else {
								set params [lindex [lindex $vals(gasket_loading_data) 2] 0]
								set temp [lindex $params 0]
								catch {unset comp}
								set j 0
								foreach {x y} [lrange $params 1 end] {
									set comp($j) [list $x $y]
									incr j
								}
								set j 0
								foreach point [lsort -increasing [array names comp]] {
									set pair $comp($point)
									set pres [lindex $pair 0]
									set closure [lindex $pair 1]
									set tb(DMG/lcrv/Lpt:Lpt$j/F) $pres
									set tb(DMG/lcrv/Lpt:Lpt$j/CL) $closure
									incr j
								}
							}

						}
#unloading (optional)
						if [lindex $vals(gasket_unloading_data) 0] {
							if {[lindex $vals(gasket_unloading_data) 2]!=""} {

								if {$tb(opt)!="DMG"} {
									mess "Warning: No gasket loading data specified for part $fam\n"
									mess "Unloading gasket data ignored.\n"
								} else {
									set opt2 [lindex $vals(gasket_unloading_data) 1]
									set tb(DMG/ucrv:ucrv0/opt2) $opt2

									if $opt2 {
									set ntemp [llength [lindex $vals(gasket_unloading_data) 2]]
							  		set tb(DMG/ucrv:ucrv0/opt2) 1
							  		set k 0
							  		  for {set i 0} {$i<$ntemp} {incr i} {
										set params [lindex [lindex $vals(gasket_unloading_data) 2] $i]
										set temp [lindex $params 0]
										catch {unset uncomp}
										set j 0
										foreach {x y} [lrange $params 1 end] {
											set uncomp($j) [list $x $y]
											incr j
										}
										foreach point [lsort -increasing [array names uncomp]] {
											set pair $uncomp($point)
											set pres [lindex $pair 0]
											set closure [lindex $pair 1]
											set pcl 0.0
											set tb(DMG/ucrv:ucrv0/T-Upt:T-Upt$k/F) $pres
											set tb(DMG/ucrv:ucrv0/T-Upt:T-Upt$k/CL) $closure
											set tb(DMG/ucrv:ucrv0/T-Upt:T-Upt$k/PCL) $pcl
											set tb(DMG/ucrv:ucrv0/T-Upt:T-Upt$k/T) $temp
											incr k
										}
							  		  }
									} else {
										set params [lindex [lindex $vals(gasket_unloading_data) 2] 0]
										set temp [lindex $params 0]
										catch {unset uncomp}
										set j 0
										foreach {x y} [lrange $params 1 end] {
											set uncomp($j) [list $x $y]
											incr j
										}
										set j 0
										foreach point [lsort -increasing [array names uncomp]] {
											set pair $comp($point)
											set pres [lindex $pair 0]
											set closure [lindex $pair 1]
											set pcl 0.0
											set tb(DMG/ucrv:ucrv0/Upt:Upt$j/F) $pres
											set tb(DMG/ucrv:ucrv0/Upt:Upt$j/CL) $closure
											set tb(DMG/ucrv:ucrv0/Upt:Upt$j/PCL) $pcl
											incr j
										}
									}
								}

							}
						}
#transverse (optional)
						if {[lindex $vals(gasket_tss_data) 0]==1} {
							set gasket_behavior(GaskElst/TS/opt2) 0
							set gasket_behavior(GaskElst/TS/Ss) [lindex $vals(gasket_tss_data) 1]
						} elseif {[lindex $vals(gasket_tss_data) 0]==2} {
							if {[lindex $vals(gasket_tss_data) 1]!=""} {
								set gasket_behavior(GaskElst/TS/opt2) 1
								set params [lindex $vals(gasket_tss_data) 1]
								set params [lrange [lindex $params 0] 1 end]
								catch {unset tss}
								set j 0
								foreach {temp t} $params {
									set tss($j) [list $temp $t]
									incr j
								}
								set j 0
								foreach point [lsort -increasing [array names tss]] {
									set pair $tss($point)
									set gasket_behavior(GaskElst/TS/T-tdata:T-tdata$j/T) [lindex $pair 0]
									set gasket_behavior(GaskElst/TS/T-tdata:T-tdata$j/Ss) [lindex $pair 1]
									incr j
								}
							}
						}

						foreach node [array names tb] {
							set gasket_behavior(tb/$node) $tb($node)
						}
								
						set abaqus_param_arrays($gasket_node) [array get gasket_behavior] 
						
					}

			puts $fp "\"$fam\" \"GK_AR\" \"$mat_gasket\" 0 0 0 $gap 0.0 -1 0 0 0 0 0 0"
			} else {
			puts $fp "\"$fam\" \"SOLID3D\" 0 0"
			puts $fp "\"$fam\" \"SOLID_SECTION\" \"$vals(mat)\" \"$lcs\" $lcs_flag"
			}
    	}
		Shell {
			mess "Only thickness paramter supported for Shell elements.\n"
			puts $fp "\"$fam\" \"SHELL\" 0 0 0 0"

			set tflag 0
			set thk 0.0
			if {[info exists vals(m_thick)] && $vals(m_thick)!=""} {
				if {[expr double($vals(m_thick))]!=0.0} {
					set thk $vals(m_thick)
				}
			}
			if {[expr double($thk)]!=0.0} {
				set tflag 1
			}
			puts $fp "\"$fam\" \"SHELL_GEN_SECTION\" \"$vals(mat)\" \"\" 1 $tflag $thk 0"
		}
		Shear {
#created a separate case for shear elements; these probably map better to Abaqus membranes.
#save for later...
			mess "Only thickness paramter supported for Shear elements.\n"
			puts $fp "\"$fam\" \"SHELL\" 0 0 0 0"

			set tflag 0
			set thk 0.0
			if {[info exists vals(thick)] && $vals(thick)!=""} {
				if {[expr double($vals(thick))]!=0.0} {
					set thk $vals(thick)
				}
			}
			if {[expr double($thk)]!=0.0} {
				set tflag 1
			}
			puts $fp "\"$fam\" \"SHELL_GEN_SECTION\" \"$vals(mat)\" \"\" 1 $tflag $thk 0"
		}
		"Beam Cross-Section" {
			
			set a 0.0
			set i1 0.0
			set i2 0.0
			set i3 0.0
			set j 0.0
			set x1 0.0
			set x2 0.0
			set x3 0.0
			set start 0
			set dims $vals(dims)
			for {set e 0} {$e<[llength $dims]} {incr e} {
				if {[lindex $dims $e]==""} {set dims [lreplace $dims $e $e 0.0]}
			}
			if $vals(beamcs_type) {
				mess "calculating average beam c/s properties.\n"
			}
			set ends [expr $vals(beamcs_type)+1]
			for {set e 0} {$e<$ends} {incr e} {
			catch {unset cs}
# Area, Ix & Iy values copied from vpost/vpbeamcross.C
			switch -exact $vals(beam_type_option) {
				I {
					for {set ee 0} {$ee<6} {incr ee} {
						set cs($ee) [lindex $dims $start]
						incr start
					}
					set a [expr $a + $cs(0) * $cs(3) + ($cs(1) - $cs(3)) * $cs(4) \
								+ ($cs(2) - $cs(3)) * $cs(5)]
					set i1 [expr $i1 + $cs(3)*$cs(3)*$cs(3) * ($cs(0) - $cs(4) - $cs(5))/12.0 \
								+ $cs(1)*$cs(1)*$cs(1) * $cs(4)/12.0 + $cs(2)*$cs(2)*$cs(2) * $cs(5)/12.0]
					set i2 [expr $i2 + $cs(0)*$cs(0)*$cs(0) * $cs(3)/12.0 \
								+ ($cs(1) - $cs(3)) * $cs(4) * ($cs(4)*$cs(4)/3.0 \
								+ ($cs(0) - $cs(4))*($cs(0) - $cs(4)))/4.0 \
								+ ($cs(2) - $cs(3)) * $cs(5) * ($cs(5)*$cs(5)/3.0 \
								+ ($cs(0) - $cs(5))*($cs(0) - $cs(5)))/4.0]
				}
				T {
					for {set ee 0} {$ee<4} {incr ee} {
						set cs($ee) [lindex $dims $start]
						incr start
					}
					set a [expr $a + $cs(0)*$cs(2) + $cs(3)*($cs(1)-$cs(2))]
					set i1 [expr $i1 + $cs(0)*$cs(0)*$cs(0)*$cs(2)/12.0 \
									+ $cs(3)*$cs(3)*$cs(3)*($cs(1)-$cs(2))/12.0 \
						] 
					set i2 [expr $i2 + $cs(1)*$cs(1)*$cs(1)*$cs(3)/12.0 \
									+ ($cs(0)-$cs(3))*$cs(2)*(($cs(2)*$cs(2)/3.0 + ($cs(1)-$cs(2))*($cs(1)-$cs(2))))/4.0 \
						] 
				}
				L {
					for {set ee 0} {$ee<4} {incr ee} {
						set cs($ee) [lindex $dims $start]
						incr start
					}
					set a [expr $a + $cs(0) * $cs(2) + $cs(3) * ($cs(1) - $cs(2))]
					set i1 [expr $i1 + $cs(0)*$cs(0)*$cs(0) * $cs(2)/12.0 \
									+ ($cs(1) - $cs(2)) * $cs(3) * ($cs(3)*$cs(3)/3.0 \
									+ ($cs(0) - $cs(3))*($cs(0) - $cs(3)))/4.0] 
					set i2 [expr $i2 + $cs(1)*$cs(1)*$cs(1) * $cs(3)/12.0 \
									+ ($cs(0) - $cs(3)) * $cs(2) * ($cs(2)*$cs(2)/3.0 \
									+ ($cs(1) - $cs(2))*($cs(1) - $cs(2)))/4.0]
				}
				H {
					for {set ee 0} {$ee<4} {incr ee} {
						set cs($ee) [lindex $dims $start]
						incr start
					}
					set a [expr $a + 2*$cs(1)*$cs(2) + $cs(0)*$cs(3)]
					set i1 [expr $i1 + $cs(0)*$cs(0)*$cs(0) * $cs(3)/12.0 \
									+ $cs(2) * $cs(1) * ($cs(1)*$cs(1)/3.0 \
									+ ($cs(0) + $cs(1))*($cs(0) + $cs(1)))/2.0] 
					set i2 [expr $i2 + $cs(1) * $cs(2)*$cs(2)*$cs(2)/6.0 \
									+ $cs(0) * $cs(3)*$cs(3)*$cs(3)/12.0]
				}
				BOX {
					for {set ee 0} {$ee<2} {incr ee} {
						set cs($ee) [lindex $dims $start]
						incr start
					}
					set a [expr $a + $cs(0)*$cs(1)]
					set i1 [expr $i1 + $cs(0)*$cs(0)*$cs(0)*$cs(1)/12.0] 
					set i2 [expr $i2 + $cs(0)*$cs(1)*$cs(1)*$cs(1)/12.0] 
				}
				BAR {
					for {set ee 0} {$ee<4} {incr ee} {
						set cs($ee) [lindex $dims $start]
						incr start
					}
					set a [expr $a + $cs(0)*$cs(1) - ($cs(0) - 2*$cs(3))*($cs(1) - 2*$cs(2))]
					set i1 [expr $i1 + $cs(0)*$cs(0)*$cs(0)*$cs(2)/6.0 \
									+ ($cs(1)/2.0 - $cs(2))*$cs(3)*($cs(3)*$cs(3)/3.0 + ($cs(0)-$cs(3))*($cs(0)-$cs(3))) \
							] 
					set i2 [expr $i2 + + $cs(1)*$cs(1)*$cs(1)*$cs(3)/6.0 \
									+ ($cs(0)/2.0 - $cs(3))*$cs(2)*($cs(2)*$cs(2)/3.0 + ($cs(1)-$cs(2))*($cs(1)-$cs(2))) \
							] 
				} 
				ROD {
					for {set ee 0} {$ee<1} {incr ee} {
						set cs($ee) [lindex $dims $start]
						incr start
					}
					set a [expr $a + $cs(0)*$cs(0)*3.1416]
					set i1 [expr $i1 + $cs(0)*$cs(0)*$cs(0)*$cs(0)*3.1416/4.0] 
					set i2 $i1 
				}
				TUBE {
					for {set ee 0} {$ee<2} {incr ee} {
						set cs($ee) [lindex $dims $start]
						incr start
					}
					set a [expr $a + ($cs(0) * $cs(0) - $cs(1) * $cs(1)) * 3.1416]
					set i1 [expr $i1 + ($cs(0)*$cs(0)*$cs(0)*$cs(0) \
									- $cs(1)*$cs(1)*$cs(1)*$cs(1)) * 3.1416/4.0] 
					set i2 $i1
				}
				HAT {
					for {set ee 0} {$ee<4} {incr ee} {
						set cs($ee) [lindex $dims $start]
						incr start
					}
					set a [expr $a + $cs(1)*(2*$cs(3)+$cs(2)+ 2*($cs(0) - $cs(1)))]
					set i1 [expr $i1 + $cs(2)*$cs(2)*$cs(2) * $cs(1)/12.0 \
									+ $cs(1) * $cs(3) * ($cs(3)*$cs(3)/3.0 \
									+ ($cs(2) + $cs(3))*($cs(2) + $cs(3)))/2.0 \
									+ ($cs(0) - $cs(2)) * $cs(1) * ($cs(1)*$cs(1)/3.0 \
									+ ($cs(2) - $cs(1))*($cs(2) - $cs(1)))/2.0] 
					set i2 [expr $i2 + $cs(0)*$cs(0)*$cs(0) * $cs(1)/6.0 \
									+ ($cs(2)/2.0 - $cs(1) + $cs(3)) * $cs(1) * ($cs(1)*$cs(1)/3.0 \
									+ ($cs(0) - $cs(1))*($cs(0) - $cs(1)))/2.0]
				}
				CHAN {
					for {set ee 0} {$ee<4} {incr ee} {
						set cs($ee) [lindex $dims $start]
						incr start
					}
					set a [expr $a + 2*$cs(0)*$cs(3) + $cs(2)*($cs(1) - 2*$cs(3)]
					set i1 [expr $i1 + $cs(0)*$cs(0)*$cs(0) * $cs(3)/6.0 \
									+ ($cs(1)/2.0 - $cs(3)) * $cs(2) * ($cs(2)*$cs(2)/3.0 \
									+ ($cs(0) - $cs(2))*($cs(0) - $cs(2)))/2.0] 
					set i2 [expr $i2 + $cs(1)*$cs(1)*$cs(1) * $cs(2)/12.0 \
									+ ($cs(0) - $cs(2)) * $cs(3) * ($cs(3)*$cs(3)/3.0 \
									+ ($cs(1) - $cs(3))*($cs(1) - $cs(3)))/2.0]
				}  
			}
			}

			if {[info exists vals(bar_x1)] && $vals(bar_x1)!=""} {
				set x1 $vals(bar_x1)
			}
			if {[info exists vals(bar_x2)] && $vals(bar_x2)!=""} {
				set x2 $vals(bar_x2)
			}
			if {[info exists vals(bar_x3)] && $vals(bar_x3)!=""} {
				set x3 $vals(bar_x3)
			}

#support for non-structural mass to be added later...

			set mat $vals(mat)
			if {$mat==""} {
				mess "Warning: Material not specified for bar elements for family $fam\n"
			}

		    array set mat_def {
			name ""
			den 0.0
			pois 0.0
			zero 0.0
			E 0.0
			G 0.0
			K 0.0
			}
			set mat_def(name) $mat

			foreach n [abaqus_material_property_order] v $material_data($mat) {
				if {$v==""} continue
# code for temperature dependence / non-linearity
				switch -regexp [lindex $v 1] {
					^temp$ {
						mess "temperature dependant properties not yet supported.\n"
						mess "skipping property variation \"$n\" for material $mat...\n"
						continue
					}
					nonlinear {
						mess "nonlinear properties not yet supported.\n"
						mess "skipping property variation \"$n\" for material $mat...\n"
						continue
					}
				}

				switch $n {
					ID { continue }
					E {
						set mat_def(E) $v
					}
					G {
						set mat_def(G) $v
					}
					NU {
						set mat_def(pois) $v
					}
					DENSITY {
						set mat_def(den) [expr $v*$wtmass]
					}
					EXPANSION_ISO_c0 {
						set mat_def(K) $v
					}
					REFT {
						set mat_def(zero) $v
					}
				}
			}
			
			foreach p {den pois zero E G K} {
				if { $mat_def($p) == "" } {set mat_def($p) 0.0}
			}

			set abaqus_param_arrays(beam_prop:$mat) [array get mat_def]
			puts $fp "\"$fam\" \"BEAM_GEN_SECTION\" \"$mat\" 0 $a $i1 $i3 $i2 $j \"$x1 $x2 $x3\""
		}
		Beam -
		Bar {
			puts $fp "\"$fam\" \"BEAM\" 0 0 0 0"

			set a 0.0
			set mi1 0.0
			set mi2 0.0
			set mi3 0.0
			set j 0.0
			set x1 0.0
			set x2 0.0
			set x3 0.0
			
			if {[info exists vals(bar_a)] && $vals(bar_a)!=""} {
				set a $vals(bar_a)
			}

			if {[info exists vals(bar_i1)] && $vals(bar_i1)!=""} {
				set mi1 $vals(bar_i1)
			}

			if {[info exists vals(bar_i2)] && $vals(bar_i2)!=""} {
				set mi3 $vals(bar_i2)
			}

			if {[info exists vals(bar_j)] && $vals(bar_j)!=""} {
				set j $vals(bar_j)
			}

			if {$vals(etype)=="Beam"} {
				mess "Conversion of I12 for Beam elements not supported.\n"
			}

			if {[info exists vals(bar_x1)] && $vals(bar_x1)!=""} {
				set x1 $vals(bar_x1)
			}
			if {[info exists vals(bar_x2)] && $vals(bar_x2)!=""} {
				set x2 $vals(bar_x2)
			}
			if {[info exists vals(bar_x3)] && $vals(bar_x3)!=""} {
				set x3 $vals(bar_x3)
			}

			set mat $vals(mat)
			if {$mat==""} {
				mess "Warning: Material not specified for bar elements for family $fam\n"
			}

		    array set mat_def {
			name ""
			den 0.0
			pois 0.0
			zero 0.0
			E 0.0
			G 0.0
			K 0.0
			}
			set mat_def(name) $mat

			foreach n [abaqus_material_property_order] v $material_data($mat) {
				if {$v==""} continue
# code for temperature dependence / non-linearity
				switch -regexp [lindex $v 1] {
					^temp$ {
						mess "temperature dependant properties not yet supported.\n"
						mess "skipping property variation \"$n\" for material $mat...\n"
						continue
					}
					nonlinear {
						mess "nonlinear properties not yet supported.\n"
						mess "skipping property variation \"$n\" for material $mat...\n"
						continue
					}
				}

				switch $n {
					ID { continue }
					E {
						set mat_def(E) $v
					}
					G {
						set mat_def(G) $v
					}
					NU {
						set mat_def(pois) $v
					}
					DENSITY {
						set mat_def(den) [expr $v*$wtmass]
					}
					EXPANSION_ISO_c0 {
						set mat_def(K) $v
					}
					REFT {
						set mat_def(zero) $v
					}
				}
			}
			
			foreach p {den pois zero E G K} {
				if { $mat_def($p) == "" } {set mat_def($p) 0.0}
			}

			set abaqus_param_arrays(beam_prop:$mat) [array get mat_def]
			puts $fp "\"$fam\" \"BEAM_GEN_SECTION\" \"$mat\" 0 $a $mi1 $mi2 $mi3 $j \"$x1 $x2 $x3\""

		}
		"Rigid beam" {
			switch $vals(beam_type_index) {
			0 - 2 { mess "Conversion of rigid beam type $vals(beam_type_index) not yet supported.\n" }
			1 {
				puts $fp "\"$fam\" \"RIGID\" 0 0.0"
			}
			default { mess "Error: unrecognized rigid beam type $vals(beam_type_index)\n" }
			}
			
		}
		Spring {
			set stiff 0.0
			set freq 0.0
			set dof1 0
			set dof2 0
			if {[info exists vals(stiff)] && $vals(stiff)!=""} {
				set stiff $vals(stiff)
			}
			if {[info exists vals(component_c1)] && $vals(component_c1)!=""} {
				set dof1 $vals(component_c1)
			}
			if {[info exists vals(component_c2)] && $vals(component_c2)!=""} {
				set dof2 $vals(component_c2)
			}
			puts $fp "\"$fam\" \"SPRING\" 2 $dof1 $dof2 $stiff $freq"
		}
		"Damper connection" {
			set coeff 0.0
			set freq 0.0
			set dof1 0
			set dof2 0
			if {[info exists vals(force_per_vel)] && $vals(force_per_vel)!=""} {
				set coeff $vals(force_per_vel)
			}
			if {[info exists vals(component_c1)] && $vals(component_c1)!=""} {
				set dof1 $vals(component_c1)
			}
			if {[info exists vals(component_c2)] && $vals(component_c2)!=""} {
				set dof2 $vals(component_c2)
			}
			puts $fp "\"$fam\" \"DASHPOT\" 2 $dof1 $dof2 $coeff $freq"
    	}
		"Mass point" {
			puts $fp "\"$fam\" \"MASS\" $vals(mass)"
    	}
		default { 
			mess "Conversion of element type $vals(etype) not yet supported.\n" 
		}
		}
	}
}

proc abaqus_add_materials {} {
	global material_data abaqus_param_arrays
	global material_dpnd_data material_tbl_type material_tbl_data material_type

# get WTMASS parameter from Nastran.
	set wtmass [setupNastranRunDEZ get wtmass]
	if {$wtmass==""} {set wtmass 1.0}

#reset all material property data
	foreach node [array names abaqus_param_arrays] {
		if [regexp ^mat: $node] {unset abaqus_param_arrays($node)}
	}
	
	foreach mat [array names material_data] {

	set mt [lindex $material_type($mat) 0]

	catch {unset mat_def}
    array set mat_def {
	ELASTIC/define 0
	ELASTIC/type 0
	ELASTIC/ISOTROPIC/line:line0/c0 0.0
	ELASTIC/ISOTROPIC/line:line0/c1 0.0
	ELASTIC/ISOTROPIC/line:line0/c2 ""
	ELASTIC/LAMINA/line:line0/c0 0.0
	ELASTIC/LAMINA/line:line0/c1 0.0
	ELASTIC/LAMINA/line:line0/c2 0.0
	ELASTIC/LAMINA/line:line0/c3 0.0
	ELASTIC/LAMINA/line:line0/c4 0.0
	ELASTIC/LAMINA/line:line0/c5 0.0
	ELASTIC/LAMINA/line:line0/c6 ""
	ELASTIC/ANISOTROPIC/line:line0/c0 0.0
	ELASTIC/ANISOTROPIC/line:line0/c1 0.0
	ELASTIC/ANISOTROPIC/line:line0/c2 0.0
	ELASTIC/ANISOTROPIC/line:line0/c3 0.0
	ELASTIC/ANISOTROPIC/line:line0/c4 0.0
	ELASTIC/ANISOTROPIC/line:line0/c5 0.0
	ELASTIC/ANISOTROPIC/line:line0/c6 0.0
	ELASTIC/ANISOTROPIC/line:line0/c7 0.0
	ELASTIC/ANISOTROPIC/line:line0/c8 0.0
	ELASTIC/ANISOTROPIC/line:line0/c9 0.0
	ELASTIC/ANISOTROPIC/line:line0/c10 0.0
	ELASTIC/ANISOTROPIC/line:line0/c11 0.0
	ELASTIC/ANISOTROPIC/line:line0/c12 0.0
	ELASTIC/ANISOTROPIC/line:line0/c13 0.0
	ELASTIC/ANISOTROPIC/line:line0/c14 0.0
	ELASTIC/ANISOTROPIC/line:line0/c15 0.0
	ELASTIC/ANISOTROPIC/line:line0/c16 0.0
	ELASTIC/ANISOTROPIC/line:line0/c17 0.0
	ELASTIC/ANISOTROPIC/line:line0/c18 0.0
	ELASTIC/ANISOTROPIC/line:line0/c19 0.0
	ELASTIC/ANISOTROPIC/line:line0/c20 0.0
	ELASTIC/ANISOTROPIC/line:line0/c21 ""
	PLASTIC/define 0
	PLASTIC/harden 0
	DENSITY/define 0
	DAMPING/define 0
	DAMPING/c0 0.0
	DAMPING/c1 0.0
	EXPANSION/define 0
	EXPANSION/type 0
	EXPANSION/ORTHO/line:line0/c0 0.0
	EXPANSION/ORTHO/line:line0/c1 0.0
	EXPANSION/ORTHO/line:line0/c2 0.0
	EXPANSION/ORTHO/line:line0/c3 ""
	EXPANSION/ANISO/line:line0/c0 0.0
	EXPANSION/ANISO/line:line0/c1 0.0
	EXPANSION/ANISO/line:line0/c2 0.0
	EXPANSION/ANISO/line:line0/c3 0.0
	EXPANSION/ANISO/line:line0/c4 0.0
	EXPANSION/ANISO/line:line0/c5 0.0
	EXPANSION/ANISO/line:line0/c6 ""
	CONDUCTIVITY/define 0
	CONDUCTIVITY/type 0
	SPECIFIC/define 0
	}
	set mat_def(name) $mat

#puts "material $mat, type $mt"

	catch {unset mptemp}
	foreach n [abaqus_material_property_order $mt] v $material_data($mat) d $material_dpnd_data($mat) {
		if {$n==""} break
		if {$n=="dummy"} continue
		if {$n=="ID"} continue
		set tvar 0
		set data ""
		if {$d!=""} {
			set t $material_tbl_type($d)
			if $t {
				if {$t>2} {
					mess "Table type $t not supported for property \"$n\".\n"
					continue
				}
				if {$n=="E"} {
					set mat_def(PLASTIC/define) 1
					set typ [lindex [lindex $material_tbl_data($d) 2] 0]
					set vlist [lindex [lindex $material_tbl_data($d) 2] 1]
puts "$typ table data: $vlist"
					if {$typ=="nonlinear"} {
					set i 0
					foreach {x y} [lrange $vlist 1 end] {
#Nastran strain-stress sequence reversed for Abaqus..
						set mat_def(PLASTIC/line:line$i/c0) $y
						set mat_def(PLASTIC/line:line$i/c1) $x
						set mat_def(PLASTIC/line:line$i/c2) ""
						incr i
					}
					} elseif {$typ=="temp_nonlinear"} {
						set i 0
						foreach {temp tid} [lrange $vlist 1 end] {
							set tname [aie_material_tbl_name_from_number $tid]
							if {$tname==""} {
								mess "Table id $tid not found for material data\n"
							continue
							}
							if {$material_tbl_type($tname)!=1} {
								mess "Reference table id $tid should be Nonlinear for base table [lindex $data 0]\n"
								continue
							}
							set tdata $material_tbl_data($tname)
							set tlst [lindex [lindex $tdata 2] 1]
							foreach {x y} [lrange $tlst 1 end] {
#Nastran strain-stress sequence reversed for Abaqus..
								set mat_def(PLASTIC/line:line$i/c0) $y
								set mat_def(PLASTIC/line:line$i/c1) $x
								set mat_def(PLASTIC/line:line$i/c2) $temp
								incr i
							}
						}
					} else {
						mess "Unsupported table type $typ for material data\n"
						continue
					}
				} else {
					mess "Nonlinear variation not supported for property \"$n\".\n"
					continue
				}
			} else {
				set tvar 1
				set data $material_tbl_data($d)
			}
		}

#puts "material property $n"
		switch -regexp $n {
			ID { continue }
			^EXPANSION_I {
				if $tvar {
					set vlist [lindex [lindex $data 8] 1]
					set mptemp(EXPANSION) $vlist
				} else {
					if {$v==""} continue
					set mat_def(EXPANSION/ISO/line:line0/c0) $v
					set mat_def(EXPANSION/ISO/line:line0/c1) ""
				}
				set mat_def(EXPANSION/define) 1
			}
			^EX {
				if $tvar {
					mess "Temperature variation not supported for property \"$n\".\n"
					continue
				}
				if {$v==""} continue
				set elst [split $n _]
				set ext 0
				switch [lindex $elst 1] {
					ORTHO {set ext 1}
					ANISO {set ext 2}
					default {
						mess "Type [lindex $elst 1] not supported for property \"[lindex $elst 0]\".\n"
						continue
					}
				}
				set mat_def(EXPANSION/define) 1
				set mat_def(EXPANSION/type) $ext
				set mat_def(EXPANSION/[lindex $elst 1]/line:line0/[lindex $elst 2]) $v
			}
			^EL {
				if $tvar {
					mess "Temperature variation not supported for property \"$n\".\n"
					continue
				}
				if {$v==""} continue
				set elst [split $n _]
				set ext 0
				switch [lindex $elst 1] {
					LAMINA {set ext 2}
					ANISOTROPIC {set ext 4}
					default {
						mess "Type [lindex $elst 1] not supported for property \"[lindex $elst 0]\".\n"
						continue
					}
				}
				set mat_def(ELASTIC/define) 1
				set mat_def(ELASTIC/type) $ext
				set mat_def(ELASTIC/[lindex $elst 1]/line:line0/[lindex $elst 2]) $v
			}
			^E {
				if $tvar {
					set vlist [lindex [lindex $data 8] 1]
					set mptemp(ELASTIC,1) $vlist
				} else {
					if {$v==""} continue
					set mat_def(ELASTIC/ISOTROPIC/line:line0/c0) $v
				}
				set mat_def(ELASTIC/define) 1
			}
			^NU {
				if $tvar {
					set vlist [lindex [lindex $data 8] 1]
					set mptemp(ELASTIC,2) $vlist
				} else {
					if {$v==""} continue
					set mat_def(ELASTIC/ISOTROPIC/line:line0/c1) $v
				}
				set mat_def(ELASTIC/define) 1
			}
			^DE {
				if $tvar {
					set vlist [lindex [lindex $data 8] 1]
					set j [llength $vlist]
					for {set i 1} {$i<$j} {incr i 2} {
						set vlist [lreplace $vlist $i $i [expr [lindex $vlist $i]*$wtmass]]
					}
					set mptemp(DENSITY) $vlist
				} else {
					if {$v==""} continue
					set mat_def(DENSITY/line:line0/c0) [expr $v*$wtmass]
					set mat_def(DENSITY/line:line0/c1) ""
				}
				set mat_def(DENSITY/define) 1
			}
			^R {
				if $tvar {
					mess "property \"$n\" not supported.\n"
					continue
				}
				if {$v==""} continue
				mess "property \"$n\" not supported.\n"
				mess "skipping for material $mat...\n"
				continue
			}
			^DA {
				if $tvar {
					mess "Temperature dependence not supported for property \"$n\".\n"
					continue
				}
				if {$v==""} continue
				set mat_def(DAMPING/define) 1
				set mat_def(DAMPING/c0) $v
			}
		}
	}

	set eflag 0
	if [info exists mptemp] {
		foreach p [array names mptemp] {
			switch -regexp $p {
				^EX {set pnode $p/ISO}
				default {set pnode $p}
			}
			
			switch -regexp $p {
				^EL {
					if [regexp 1$ $p] {
						set eflag [expr $eflag|1]
					} else {
						set eflag [expr $eflag|2]
					}
				}
				default {
					set n 0
					foreach {x y1} [lrange $mptemp($p) 1 end] {
						if {$x==""} continue
						if {$y1==""} {set y1 0.0}
						set mat_def($pnode/line:line$n/c1) $x
						set mat_def($pnode/line:line$n/c0) $y1
						incr n
					}
				}
			}

		}
	}

#special for combined Young's Modulus & Poisson's Ratio...
	set n 0
	set pnode ELASTIC/ISOTROPIC
	switch $eflag {
		0 {}
		1 {
			foreach {x y1} [lrange $mptemp(ELASTIC,1) 1 end] {
				if {$x==""} continue
				if {$y1==""} {set y1 0.0}
				set mat_def($pnode/line:line$n/c2) $x
				set mat_def($pnode/line:line$n/c0) $y1
				set mat_def($pnode/line:line$n/c1) $mat_def($pnode/line:line0/c1)
				incr n
			}
		}
		2 {
			foreach {x y2} [lrange $mptemp(ELASTIC,2) 1 end] {
				if {$x==""} continue
				if {$y2==""} {set y2 0.0}
				set mat_def($pnode/line:line$n/c2) $x
				set mat_def($pnode/line:line$n/c0) $mat_def($pnode/line:line0/c0)
				set mat_def($pnode/line:line$n/c1) $y2
				incr n
			}
		}
		3 {
			mess "Warning: Couldn't translate combined temperature dependence for\n"
			mess "Young's Modulus & Poisson's Ratio. Setting zero property values.\n"
		}
	}
			
	set abaqus_param_arrays(mat:$mat) [array get mat_def]
	}
}

proc abaqus_material_property_order {{type 0}} {
    if {$type==0} {
		return {ID E G NU DENSITY EXPANSION_ISO_c0 REFT DAMPING}
    } elseif {$type==3} {
#MAT8 (Shell Orthotropic) entries
		return {ID ELASTICITY_LAMINA_c0 ELASTICITY_LAMINA_c1 ELASTICITY_LAMINA_c2 \
					ELASTICITY_LAMINA_c3 ELASTICITY_LAMINA_c4 ELASTICITY_LAMINA_c5 \
					DENSITY EXPANSION_ORTHO_c0 EXPANSION_ORTHO_c1 REFT dummy dummy dummy dummy dummy DAMPING}
	} elseif {$type==2} {
#MAT9 (Solid Anisotropic) entries
#Nastran matrix order corrected for Abaqus..
		return {ID ELASTICITY_ANISOTROPIC_c0 ELASTICITY_ANISOTROPIC_c1 ELASTICITY_ANISOTROPIC_c3 ELASTICITY_ANISOTROPIC_c6 \
					ELASTICITY_ANISOTROPIC_c10 ELASTICITY_ANISOTROPIC_c15 ELASTICITY_ANISOTROPIC_c2 ELASTICITY_ANISOTROPIC_c4 \
					ELASTICITY_ANISOTROPIC_c7 ELASTICITY_ANISOTROPIC_c11 ELASTICITY_ANISOTROPIC_c16 ELASTICITY_ANISOTROPIC_c5 \
					ELASTICITY_ANISOTROPIC_c8 ELASTICITY_ANISOTROPIC_c12 ELASTICITY_ANISOTROPIC_c17 ELASTICITY_ANISOTROPIC_c9 \
					ELASTICITY_ANISOTROPIC_c13 ELASTICITY_ANISOTROPIC_c18 ELASTICITY_ANISOTROPIC_c14 ELASTICITY_ANISOTROPIC_c19 \
					ELASTICITY_ANISOTROPIC_c20 \
					DENSITY \
					EXPANSION_ANISO_c0 EXPANSION_ANISO_c1 EXPANSION_ANISO_c2 EXPANSION_ANISO_c3 EXPANSION_ANISO_c4 EXPANSION_ANISO_c5 \
					REFT DAMPING}
	} elseif {$type==1} {
#MAT2 (Shell Anisotropic) entries
#Nastran matrix order corrected for Abaqus..
		return {ID ELASTICITY_ANISOTROPIC_c0 ELASTICITY_ANISOTROPIC_c1 ELASTICITY_ANISOTROPIC_c3 ELASTICITY_ANISOTROPIC_c6 \
					ELASTICITY_ANISOTROPIC_c10 ELASTICITY_ANISOTROPIC_c9 \
					DENSITY \
					EXPANSION_ORTHO_c0 EXPANSION_ORTHO_c1 EXPANSION_ORTHO_c2 \
					REFT DAMP}
	}
	return ""
}

proc abaqus_add_LCS {} {
	global lcs_data abaqus_param_arrays

    foreach n [array names lcs_data] {
	if {$n == "Global"} continue
	
	foreach i {number name type dby x1 y1 z1 x2 y2 z2 x3 y3 z3 ref scale what_is_this} v $lcs_data($n) {
	    set $i $v
	}
	
	set t ""
	switch $type {
	    Cartesian   - R - Rectangular { set t RECTANGULAR }
	    Cylindrical - C               { set t CYLINDRICAL }
	    Spherical   - S               { set t SPHERICAL }
		default { mess "Warning: Can't refer system type $t LCS \"$name\"\n"; continue }
	}
	if {!($ref == "" || $ref=="Global" || $ref == 0)} {
	    mess "Warning: Can't refer $ref system for LCS \"$name\"\n"
	}

	set define(name) $name
	set define(type) $t
# Nastran to Abaqus LCS conversion
	set zvec [list [expr $x2-$x1] [expr $y2-$y1] [expr $z2-$z1]]
	if {$t=="RECTANGULAR"} {
	set xzvec [list [expr $x3-$x1] [expr $y3-$y1] [expr $z3-$z1]]
	set yvec [vec_cross $zvec [vec_normalize $xzvec]]
# xzvec above is normalised to keep the value comparable to zvec
	set xvec [vec_cross [vec_normalize $yvec] $zvec]
# yvec is normalised above to keep the values comparable to zvec
	set xypt [vec_add $xvec $yvec]
	set define(a) $xvec
#	set define(b) $xypt
	set define(b) $yvec
	} else {
# define polar axis specified by Nastran origin & zvec
	set define(a) "$x1 $y1 $z1"
	set define(b) $zvec
	}
   	set abaqus_param_arrays(orient:$name) [array get define]

#add tranforms for all lcs
	array set transform $abaqus_param_arrays(transform)
	set trans Transform_$name
	set node specific:$trans
	set transform($node/name) $trans
	set transform($node/type) [string index $t 0]
	set transform($node/a) $define(a)
	set transform($node/b) $define(b)
	set abaqus_param_arrays(transform) [array get transform]
	}
}

proc abaqus_reset_transforms {} {
	global abaqus_param_arrays
	array set transform {
		all 0
		type R
		a ""
		b ""
	}
	set abaqus_param_arrays(transform) [array get transform]
}

# new Contact implementation in secondary domains
proc abaqus_add_contacts {} {
	global abaqus_param_arrays
#delete all existing contact data
	foreach name [array names abaqus_param_arrays] {
		if [regexp ^contact: $name] {
			unset abaqus_param_arrays($name)
		}
	}
#refresh
	foreach c [ic_param_list_children :contact] {
		array set cdata [ic_param_get_values $c]
#for backward compatibility
		if ![info exists cdata(sfaces)] {set cdata(sfaces) 0}
		if ![info exists cdata(mfaces)] {set cdata(mfaces) 0}
		set name ""
		regsub ^:contact/ $c "" name
		set arr contact:$name
		set ${arr}(name) $name
		set ${arr}(by_elements) 1
		set ${arr}(vol_master) $cdata(mfaces)
		set ${arr}(vol_slave) $cdata(sfaces)
		set ${arr}(mface) SPOS
		set ${arr}(sface) SPOS
		set ${arr}(adj_flag) 0
		set ${arr}(adj) 0.0
		set ${arr}(tied) 0
		set ${arr}(ez_flag) 0
		set ${arr}(ez) 0.1
		set ${arr}(sld) 0
		set ${arr}(sld_type) 0
		set ${arr}(smth_flag) 0
		set ${arr}(smth) 0.2
		set ${arr}(nrml) 0
		set ${arr}(poc) 0
		set ${arr}(s0) 1.0
		set ${arr}(c0) 0.0
		set ${arr}(p0) 0.0
		set ${arr}(sep) 1
		set ${arr}(tgt) 1
		set ${arr}(fm) 0
		set ${arr}(mue) $cdata(mue)
		set ${arr}(slip) 0.0
		set abaqus_param_arrays($arr) [array get $arr]
	}
}

# Surface-based contacts - data names can be: name mue mued 
proc unused__aie_write_abaqus_bc_contact {fp fam data} {
	global abaqus_param_arrays
    foreach f [ic_boco_list_unused] { set unused($f) 1 }
    foreach {n v} $data { set vals($n) $v }
    
	set name ""
	if {[info exists vals(name)]} {set name $vals(name)}

    foreach t {mue mued} {
	if {[info exists vals($t)] && $vals($t)!=""} {
	    set $t $vals($t)
	} else {
		set $t 0.0
	}
    }

    array set targets [ic_boco_classify_by_bctype TARGET_FOR_CONTACT]
    if [info exists targets($name)] {
	foreach t $targets($name) {
		if [info exists unused($t)] continue
	    puts $fp "\"$t\" \"SURFACE\" \"${t}_CONTACT_MASTER_SURFACE\" \"SPOS\" 2 0"
	    puts $fp "\"$fam\" \"CONTACT\" \"$name\" \"${t}_CONTACT_MASTER_SURFACE\""
	}
	set arr contact:$name
	set ${arr}(name) $name
	set ${arr}(mue) $mue
	foreach {n v} {
		adj_flag 0
		adj 0
		tied 0
		ez_flag 1
		ez 0.1
		sld 1
		sld_type 1
		smth_flag 1
		smth 0.2
		nrml 1
		poc 1
		s0 1.0
		c0 0.0
		p0 0.0
		sep 1
		tgt 1
		fm 0
		slip 0.0
	} { set ${arr}($n) $v }
	set abaqus_param_arrays($arr) [array get $arr]
    } else {
	mess "Warning: No masters found for contact \"$name\"" red
    }
}

#------------------------------------------------------------------------------
# Abaqus params file stuff
# Ref: ai_env/scripts/aie_ansys.tcl

proc abaqus_params_load_solve_data {file} {
	global abaqus_param_arrays
	catch {unset abaqus_param_arrays}
	
    if ![file exists $file] { set_abaqus_params; return }

    set fp [open $file r]
	set inner 0
#	set abaqus_param_arrays ""
    while {![eof $fp]} {
	set line [string trim [gets $fp]]
#	puts "line: $line"
	if {[string match \#* $line] || ($line == "")} continue
	if {[lindex $line 0] == "begin"} {
	    set nname [lindex $line 1]
	    set ninst [lindex $line 2]
		if {!$inner} {
			set array $nname
			if {$ninst != ""} {
			append array ":$ninst"
	    	}
#			puts "setting array $array..."
#			global $array
    		set path ""
			set inner 1
			if {[lsearch [array names abaqus_param_arrays] $array]==-1} {
#				lappend emax_param_arrays $array
			} else {
				mess "merging duplicate Abaqus solver data ($array)\n"
			}
		} else {
	    	if {$ninst != ""} {
			append path "$nname:$ninst/"
	    	} else {
			append path "$nname/"
	    	}
		}
	} elseif {[lindex $line 0] == "end"} {
		if {$path==""} {
			if ![info exists array] { error "bad params file" }
			set inner 0
#			puts "unsetting array $array. empty path..."
			set abaqus_param_arrays($array) [array get $array]
			unset array
		} else {
	    	set par [lindex $line 1]
	    	set ninst [lindex $line 2]
			if {$ninst != ""} {
			append par ":$ninst"
	    	}
			set colon [string last / $path]
			if {$colon!=-1} { # This must be multiple param at root level
				incr colon -1
				set last [string range $path 0 $colon]
				if {![regexp $par$ $last]} {
				error "$line doesn't match $last"
	    		}
				set loc [expr [string length $last] - [string length $par] - 1]
				set path [string range $last 0 $loc] 
			} else {
#				puts "unsetting array $array. multiple param at root level..."
				set path ""
				set inner 0
				set abaqus_param_arrays($array) [array get $array]
				unset array
			}
		}
	} else {
		if ![info exists array] { error "bad params file" }
		set var "${path}[lindex $line 0]"
#		puts ", var: $var"
		set ${array}($var) [lindex $line 1]
	}
    }

    mess "Loaded AI*Env solver data for Abaqus...\n"
    close $fp
}

proc abaqus_params_save_solve_data {file} {
	global abaqus_saved_params_data abaqus_param_arrays
    
    set fp [open $file w]
    puts $fp "# solver params file written for AI*Env on [cmd_date]"
    puts $fp "# solver: Abaqus"

	if ![info exists abaqus_param_arrays] { set_abaqus_params }
	catch {unset abaqus_saved_params_data}

    foreach array [array names abaqus_param_arrays] {
#		global $array
		foreach {n v} $abaqus_param_arrays($array) { set ${array}($n) $v }
		set last ""
		foreach key [lsort [array names $array]] {
			set abaqus_saved_params_data($array,$key) 0
		}
		set key_list [lsort [array names $array]]
#mess "array: $array\n"
#mess "key_list: $key_list\n"
		abaqus_params_save_solve_array $fp $array $last $key_list
    }
    close $fp
    mess "Saved AI*Env solver data for Abaqus...\n"
}

proc abaqus_params_save_solve_array {fp arr {last0 ""} {list0 ""}} {
	global abaqus_saved_params_data
#    upvar #0 $arr array
	
	if { $list0=="" } return
	if { $last0=="" } {
		set outlist ""
		set fwdlist ""
		foreach key $list0 {
			if {$abaqus_saved_params_data($arr,$key)} continue
			if {![regexp ^${last0} $key]} continue
			if [is_solve_level_end $key $last0] {
				set abaqus_saved_params_data($arr,$key) 1
				lappend outlist $key
			} 
		}
		foreach key $list0 {
			if {$abaqus_saved_params_data($arr,$key)} continue
			lappend fwdlist $key
		}
		abaqus_params_begin_level $fp $arr $last0 $outlist
		abaqus_params_save_solve_array $fp $arr [get_new_last_list $fwdlist $last0] $fwdlist
		abaqus_params_end_level $fp $arr $last0
	} else {
	foreach last $last0 {
		set outlist ""
		set fwdlist ""
		foreach key $list0 {
			if {$abaqus_saved_params_data($arr,$key)} continue
			if {![regexp ^${last} $key]} continue
			if [is_solve_level_end $key $last] {
				set abaqus_saved_params_data($arr,$key) 1
				lappend outlist $key
			} else {
				lappend fwdlist $key
			}
		}
		abaqus_params_begin_level $fp $arr $last $outlist
		abaqus_params_save_solve_array $fp $arr [get_new_last_list $fwdlist $last] $fwdlist
		abaqus_params_end_level $fp $arr $last
	}
	}
		
}

proc get_new_last_list {keys llast} {
	set ret ""
	if { $llast==""} {
		foreach key $keys {
			set last [get_next_level_key $key]
			if {$last==""} continue
			if {$ret==""} {
				lappend ret "$last"
			} else {
				set found 0
				foreach node $ret {
					if {$node==$last} {set found 1;break}
				}
				if {!$found} {
					lappend ret "$last"
				}
			}
		}
	} else {
		foreach prev $llast {
		foreach key $keys {
			if {![regsub ^${prev} $key "" tmp]} continue
			set last [get_next_level_key $tmp]
			if {$last==""} continue
			if {$ret==""} {
				lappend ret "$prev$last"
			} else {
				set found 0
				foreach node $ret {
					if {$node=="$prev$last"} {set found 1;break}
				}
				if {!$found} {
					lappend ret "$prev$last"
				}
			}
		}
		}
	}
	return $ret
}				
			
proc is_solve_level_end {key last} {
	regsub ^${last} $key "" tmp
	if { ![regexp (/|:)+ $tmp] } {
		return 1
	}
	return 0
}
					
proc abaqus_params_begin_level {fp arr last outlist} {
	global abaqus_param_arrays
#    upvar #0 $arr array
	foreach {n v} $abaqus_param_arrays($arr) { set array($n) $v }
	
	set level [count_solve_level $last]
#	incr level
	set tabs ""
	for {set i 0} {$i<$level} {incr i} {
		append tabs "    "
	}
	
	set wspec 0
	if {$last==""} {
		set nodename $arr
	} else {
		set nodename [get_solve_node_name $last]
	}

	if [regexp : $nodename] {
		set mark [string first : $nodename]
		set nodename1 [string range $nodename 0 [expr $mark-1]]
		set nodename2 [string range $nodename [expr $mark+1] end]
		if [regexp " " $nodename2] {
			set wspec 1
		} else {
			regsub : $nodename " " nodename
		}
	}

	if {!$level} { puts $fp "" }
	if {!$wspec} {
		puts $fp "${tabs}begin $nodename"
	} else {
		puts $fp "${tabs}begin $nodename1 \"$nodename2\""
	}
		
	foreach key $outlist {
		regsub ^${last} $key "" par
		set val $array($key)
		if {$val==""} { 
			set val "\{\}" 
		} elseif { [regexp " " $val] } {
			set val "\{$val\}"
		}
		puts $fp "${tabs}    $par $val"
	}
}

proc abaqus_params_end_level {fp arr last} {
	set level [count_solve_level $last]
#	incr level
	set tabs ""
	for {set i 0} {$i<$level} {incr i} {
		append tabs "    "
	}
	
	set wspec 0
	if {$last==""} {
		set nodename $arr
	} else {
		set nodename [get_solve_node_name $last]
	}

	if [regexp : $nodename] {
		set mark [string first : $nodename]
		set nodename1 [string range $nodename 0 [expr $mark-1]]
		set nodename2 [string range $nodename [expr $mark+1] end]
		if [regexp " " $nodename2] {
			set wspec 1
		} else {
			regsub : $nodename " " nodename
		}
	}

	if {!$wspec} {
		puts $fp "${tabs}end $nodename"
	} else {
		puts $fp "${tabs}end $nodename1 \"$nodename2\""
	}
}

proc get_next_level_key {key} {
	if {$key==""} { return "" }

	set last ""
	set multi [string first / $key]
	if {$multi!=-1} {
		set last [string range $key 0 $multi]
	}
	return $last
}

proc get_solve_node_name {key} {
	if {$key==""} { return "" }

	regsub /$ $key "" key
	
	set last ""
	set multi [string last / $key]
	if {$multi==-1} {
			return $key
	} else {
		incr multi
		set last [string range $key $multi end]
		regsub : $last " " last
	}
	return $last
}

proc count_solve_level {str} {
	if {$str==""} {return 0}
# now look for /s...
	set level [regsub -all / $str / dummy]
	return $level 
}

#------------------------------------------------------------------------------
# Abaqus import...

proc aie_import_abaqus {{file ""} {do_load 1}} {
    global file_name env bindir tcl_platform
    global  solver_setup solver_setup_global
    
    if ![file isdirectory $file_name(project_dir)] {
	set file_name(project_dir) .
    }
    if {$file == ""} {
	set types {{{Abaqus input files} *.inp} {{All files} *}}
	set file [tk_getOpenFile -initialdir $file_name(project_dir) \
		      -filetypes $types]
	if {$file == ""} { return "" }
    }
    
    set conv $env(ICEM_ACN)/icemcfd/output-interfaces/abaqus2icem
    if {![file exists $conv] && ![file exists $conv.exe]} {
	set conv $bindir/abaqus2icem
    }
    
    set pname [aie_unused_project_name]
    
    mess "$conv -dom ${pname}.abaqus.import.uns -b ${pname}.abaqus.import.fbc \
			-par ${pname}.abaqus.import.par -inp $file\n"
    busy 1

    if [catch {eval exec [list $conv -dom ${pname}.abaqus.import.uns -b ${pname}.abaqus.import.fbc \
							-par ${pname}.abaqus.import.par -inp $file]} pid] {
		mess "Error: $pid\n" red
		busy 0
		return
    }
	mess "$pid\n"
    
    if ![file exists ${pname}.abaqus.import.uns] {
		mess "Error: Can't find imported Abaqus mesh file.\n" red
		busy 0
		return
	}

	file copy ${pname}.abaqus.import.uns $pname.uns
	aie_nastran_to_abaqus ${pname}.abaqus.import $pname

    if $do_load {
         set solver_setup 3

	set file_name(domain) ${pname}.uns
	aie_open_Mesh 0
	
	set file_name(solver_params) ${pname}.par
	set file_name(solver_params_loaded) 1
	aie_open_params 0 0
	
	set file_name(family_boco) ${pname}.fbc
	set file_name(family_boco_loaded) 1
	aie_open_attr 0 0
	
	set file_name(settings) ${pname}.prj
	aie_afterStuffLoaded
	aie_initial_unsmesh_visibility	
    }
    
    busy 0
    return $pname
}

proc aie_nastran_to_abaqus {abaqus proj} {
	global abaqus_param_arrays
	set par ${abaqus}.par
	set bc ${abaqus}.fbc
	abaqus_params_load_solve_data $par
#puts "abaqus_param_arrays: [array names abaqus_param_arrays]"

# materials
	set tid 1
	set mid 0
	set ELASTIC {ISOTROPIC ENGINEERING LAMINA ORTHOTROPIC ANISOTROPIC}
	set EXPANSION {ISO ORTHO ANISO}
	foreach node [array names abaqus_param_arrays] {
#puts "node: $node"
		if ![regexp ^mat: $node] continue
		incr mid
		catch {unset material}
		array set material $abaqus_param_arrays($node)
mess "material $material(name)\n"
		set matid($material(name)) $mid
		set ntype 0
		set nlin 0
		for {set i 1} {$i<6} {incr i} {
			set mval($i) 0.0
			set mtemp($i) 0
		}

		foreach {t i} {ELASTIC 1 EXPANSION 3 DENSITY 4 DAMPING 5} {
			set ntemp 0
			if {[info exists material($t/define)] && $material($t/define)} {
				set sub ""
				switch -regexp $t {
					^E {
						set type $material($t/type)
						if $type {
							mess "Property *$t type [lindex [set $t] $type] not yet supported\n" red
							continue
						}
						set sub [lindex [set $t] $type]
						set sub /$sub
					}
				}
				switch -regexp $t {
					^E - ^DE {
						if [info exists material($t$sub/line:line1/c0)] {
							set ntemp 1
						}
					}
				}
				if $ntemp {
					set mtemp($i) 1
					set xy 0
					for {set j 0} {1} {incr j} {
						if [info exists material($t$sub/line:line$j/c0)] {
							set temp 0.0
							if [info exists material($t$sub/line:line$j/c2)] {
								set temp $material($t$sub/line:line$j/c2)
							}
							lappend xy $temp $material($t$sub/line:line$j/c0)
							continue
						}
						break
					}
					if $j {
					set table Material_Property_Table:TABLE$tid
					set ${table}(Table_ID) $tid
					set ${table}(Length) $j
					set ${table}(Table)	[list temp $xy]	
					set nastran_param_arrays($table) [array get $table]
					set mval($i) $tid
					incr tid
					}
					if {$t=="ELASTIC"} {
						incr i
						set mtemp($i) 1
						set xy 0
						for {set j 0} {1} {incr j} {
							if [info exists material($t$sub/line:line$j/c1)] {
								set temp 0.0
								if [info exists material($t$sub/line:line$j/c2)] {
									set temp $material($t$sub/line:line$j/c2)
								}
								lappend xy $temp $material($t$sub/line:line$j/c1)
								continue
							}
							break
						}
						if $j {
						set table Material_Property_Table:TABLE$tid
						set ${table}(Table_ID) $tid
						set ${table}(Length) $j
						set ${table}(Table)	[list temp $xy]	
						set nastran_param_arrays($table) [array get $table]
						set mval($i) $tid
						incr tid
						}
					}
				} else {
					if [info exists material($t$sub/line:line0/c0)] {
						set mval($i) $material($t$sub/line:line0/c0)
					}
					if {$t=="ELASTIC"} {
						if [info exists material($t$sub/line:line0/c1)] {
							incr i
							set mval($i) $material($t$sub/line:line0/c1)
						}
					}
				}
			}
		}
		
		if {[info exists material(PLASTIC/define)] && $material(PLASTIC/define)} {
			set type 0
			if [info exists material(ELASTIC/type)] {
				set type $material(ELASTIC/type)
			}
			if $type {
				mess "Property *PLASTIC not supported for *ELASTIC type [lindex $ELASTIC $type]"
			} else {
#determine number of temperatures...
				catch {unset temps}
				for {set j 0} {1} {incr j} {
					if [info exists material(PLASTIC/line:line$j/c2)] {
						set temp $material(PLASTIC/line:line$j/c2)
						if ![info exists temps($temp)] {
							set temps($temp) $j
						} else {
							set temps($temp) "$temps($temp) $j"
						}
						continue
					}
					break
				}
				if $j {
					if {[llength [array names temps]]==1} {
						set table Stress_Dependent_Material_Property_Table:TABLE$tid
						set ${table}(Table_ID) $tid
						set temp [array names temps]
						set ${table}(Length) [llength $temps($temp)]
						set xy $temp
						foreach jj $temps($temp) {
							lappend xy $material(PLASTIC/line:line$jj/c1) $material(PLASTIC/line:line$jj/c0)
						}
						set ${table}(Table)	[list nonlinear $xy]	
						set nastran_param_arrays($table) [array get $table]
						set pdata Stress_Dependent_Material:$material(name)
						foreach p {Hardening_Rule Initial_Yield_Point Internal_Friction_Angle_Degrees \
									Work_Hardening_Slope Yield_Function_criterion} {
							set ${pdata}($p) ""
						}
						set ${pdata}(Nonlinearity_type) NELAST
						set ${pdata}(Material_ID) $mid
						set ${pdata}(Stress_Dependent_Table_ID) $tid
						incr tid
						set nastran_param_arrays($pdata) [array get $pdata]
						set adel Isotropic_Material_Temperature_Dependence:$material(name)
						set ${adel}(Isotropic_Material_ID) $mid
						set nastran_param_arrays($adel) [array get $adel]
					} else {
						set table Nonlinear_Material_Temp_Dependence_Tables:TABLE$tid
						set ${table}(Table_ID) $tid
						set ${table}(Length) [array names temps]
						set xy 0
						set jj 0
						foreach temp [array names temps] {
							incr jj
							set ttid [expr $tid+$jj]
							lappend xy $temp $ttid
						}
						set ${table}(Table)	[list temp_nonlinear $xy]	
						set nastran_param_arrays($table) [array get $table]
						set pdata Stress_Dependent_Material:$material(name)
						foreach p {Hardening_Rule Initial_Yield_Point Internal_Friction_Angle_Degrees \
									Work_Hardening_Slope Yield_Function_criterion} {
							set ${pdata}($p) ""
						}
						set ${pdata}(Nonlinearity_type) NELAST
						set ${pdata}(Material_ID) $mid
						set ${pdata}(Stress_Dependent_Table_ID) $tid
						set nastran_param_arrays($pdata) [array get $pdata]
						incr tid
						
						foreach temp [array names temps] {
							set table Stress_Dependent_Material_Property_Table:TABLE$tid
							set ${table}(Table_ID) $tid
							set ${table}(Length) [llength $temps($temp)]
							set xy $temp
							foreach jj $temps($temp) {
								lappend xy $material(PLASTIC/line:line$jj/c1) $material(PLASTIC/line:line$jj/c0)
							}
							set ${table}(Table)	[list nonlinear $xy]	
							set nastran_param_arrays($table) [array get $table]
							incr tid
						}
						set adel Isotropic_Material_Temperature_Dependence:$material(name)
						set ${adel}(Isotropic_Material_ID) $mid
						set nastran_param_arrays($adel) [array get $adel]
					}
				}
			}
		}
						
		set mdata1 Isotropic_Material:$material(name)
		set i 1
		foreach p {Youngs_Modulus Poissons_Ratio Thermal_Expansion_Coefficient \
					Mass_Density Structural_Damping_Coefficient} {
			set ${mdata1}($p) ""
			if {!$mtemp($i) && $mval($i)} {
				set ${mdata1}($p) $mval($i)
			}
			incr i
		}
		set ${mdata1}(Material_ID) $mid
		set nastran_param_arrays($mdata1) [array get $mdata1]

		set mdata2 Isotropic_Material_Temperature_Dependence:$material(name)
		set i 1
		foreach p {Youngs_Modulus Poissons_Ratio Thermal_Expansion_Coefficient \
					Mass_Density Structural_Damping_Coefficient} {
			if $mtemp($i) {
				set ${mdata2}(Temperature_Dependent_$p) $mval($i)
			}
			incr i
		}
		if [info exists $mdata2] {
			set ${mdata2}(Isotropic_Material_ID) $mid
			foreach p {Youngs_Modulus Poissons_Ratio Thermal_Expansion_Coefficient \
						Mass_Density Structural_Damping_Coefficient} {
				if ![info exists ${mdata2}(Temperature_Dependent_$p)] {
					set ${mdata2}(Temperature_Dependent_$p) ""
				}
			}
			set nastran_param_arrays($mdata2) [array get $mdata2]
		}
	}

# beam materials
	set abaqus_beam_props {E G pois K den "" zero}
	set nastran_material_props { 
		Youngs_Modulus Shear_Modulus Poissons_Ratio Thermal_Expansion_Coefficient \
		Mass_Density Structural_Damping_Coefficient Reference_Temperature \
	}
	foreach node [array names abaqus_param_arrays] {
#puts "node: $node"
		if ![regexp ^beam_prop: $node] continue
		incr mid
		regsub ^beam_prop: $node "" name
		catch {unset material}
		array set material $abaqus_param_arrays($node)
mess "beam material $material(name)\n"
		set matid($name) $mid
		set mdata4 Isotropic_Material:$name
		set ${mdata4}(Material_ID) $mid
		set i 0
		foreach nst $nastran_material_props {
			set ${mdata4}($nst) ""
			set abq [lindex $abaqus_beam_props $i]
			incr i
			if {$abq==""} continue
			if {[info exists material($abq)] && $material($abq)} {
				set ${mdata4}($nst) $material($abq)
			}
		}
		set nastran_param_arrays($mdata4) [array get $mdata4]
	}

# transforms
	if [info exists abaqus_param_arrays(transform)] {
	array set xdata $abaqus_param_arrays(transform)
	foreach node [array names xdata] {
		if ![regexp ^specific: $node] continue
		regsub ^specific: $node "" trail
		regsub /.*$ $trail "" name
		regsub ^.*/ $trail "" param
		if ![info exists xform($name)] {
			set xform($name) ""
puts "set transform($name)"
		}
		lappend xform($name) "$param [list $xdata($node)]"
	}
	}
	
	if [info exists xform] {
		set id 1
		foreach x [array names xform] {
#puts "xform($x) = $xform($x)"
			catch {unset trans}
			foreach pair $xform($x) {
				set trans([lindex $pair 0]) [lindex $pair 1]
			}
			switch $trans(type) {
			 	R {
					set type Rectangular
					set origin "0 0 0"
					set xvec $trans(a)
					set yvec $trans(b)
					set zvec [vec_cross $xvec $yvec]
					set xzvec $xvec
				}
			 	C - S {
					set type Cylindrical
					if  {$trans(type)=="S"} {set type Spherical}
					set origin $trans(a)
					set o1 [lindex $origin 0]
					set o2 [lindex $origin 1]
					set o3 [lindex $origin 2]
					set zvec [vec_sub $trans(b) $trans(a)]
#find an arbitrary orthogonal vector to Z axis, such that x1y1+x2y2+x3y3=0
					set x1 [lindex $zvec 0]
					set x2 [lindex $zvec 1]
					set x3 [lindex $zvec 2]
					set len [vec_mag $zvec]
					set y1 [expr $x1 - $len]
					set y2 [expr $x2 - $len]
					set y3 [expr $x3 - $len]
					if $x3 {
						set y3 [expr -1.0*($x1*$y1+$x2*$y2)/$x3]
					} elseif $x2 {
						set y2 [expr -1.0*($x1*$y1+$x3*$y3)/$x2]
					} elseif $x1 {
						set y1 [expr -1.0*($x2*$y2+$x3*$y3)/$x1]
					} else {
						mess "ERROR: zero vector found in transform $trans(name)\n" red
						continue
					}
					#vector xzec is picked as xvec
					set xzvec "[expr $y1+$o1] [expr $y2+$o2] [expr $y3+$o3]"
				}
			 	default {
					mess "Warning: Unknown type $type for transform $trans(name)\n"
					continue
				}
			}
			set name $trans(name)
			set arr Local_Coordinates:Transform_$name
			set ${arr}(Type) $type
			set ${arr}(Create) 1
			set ${arr}(Coordinate_System_ID) $id
			incr id
			set ${arr}(Reference_Coordinate_System) 0
			set ${arr}(Scale) 1.0
			set ${arr}(Pt1_1) [lindex $origin 0]
			set ${arr}(Pt1_2) [lindex $origin 1]
			set ${arr}(Pt1_3) [lindex $origin 2]
			set ${arr}(Pt2_1) [lindex $zvec 0]
			set ${arr}(Pt2_2) [lindex $zvec 1]
			set ${arr}(Pt2_3) [lindex $zvec 2]
			set ${arr}(Pt3_1) [lindex $xzvec 0]
			set ${arr}(Pt3_2) [lindex $xzvec 1]
			set ${arr}(Pt3_3) [lindex $xzvec 2]
			set nastran_param_arrays($arr) [array get $arr]
		}
	}

# dummy material
	incr mid
	set matid(unspecified_abaqus_material) $mid
# step data
	set nsteps ""
	set allstepsdata ""

	if [file exists $bc] {
		if [catch {ic_boco_load $bc} res] {
			mess "Error in opening Abaqus family_boco file; $res\n" red
		} else {
			set fp [open ${proj}.fbc w]
# parts
			foreach fam [ic_boco_list_families] {
#				if {$fam==""} continue
				if [regexp ORFN$ $fam] continue
				if {![info exists added($fam)]} {
					puts $fp "\"$fam\""
					set added($fam) 1
					set esys($fam) ""
					set mat4fam($fam) ""
					set thick($fam) ""
					set beam_prop($fam) ""
				}
				set boc [ic_boco_get $fam]
				foreach b $boc {
# use materials loop for lcs..
					if {[lindex $b 1]=="SOLID_SECTION"} {
						if {[lindex $b 2]==""} {
							if {$mat4fam($fam)==""} {
								set mat4fam($fam) unspecified_abaqus_material
							}
						} else {
							if {$mat4fam($fam)==""} {
								set mat4fam($fam) [lindex $b 2]
							} else {
								mess "Warning: Ignoring duplicate material for part $fam\n" red
							}
						}
						if {[lindex $b 4]==1} {
							mess "Warning: Ignoring lcs [index $b 3] for part $fam\n" red
							continue
							if {$esys($fam)==""} {
# handle esystems in the next update...
#								set esys($fam) [lindex $b 3]
							} else {
								mess "Warning: Ignoring duplicate lcs for part $fam\n" red
							}
						}
					} elseif {[lindex $b 1]=="SHELL_GEN_SECTION"} {
						if {[lindex $b 4]} {
							if {[lindex $b 2]==""} {
								if {$mat4fam($fam)==""} {
									set mat4fam($fam) unspecified_abaqus_material
								}
							} else {
								if {$mat4fam($fam)==""} {
									set mat4fam($fam) [lindex $b 2]
								} else {
									mess "Warning: Ignoring duplicate material for part $fam\n" red
								}
							}
						} else {
							if {$mat4fam($fam)==""} {
								set mat4fam($fam) unspecified_abaqus_material
							}
						}
						if {[lindex $b 5]} {
							if {$thick($fam)==""} {
								set thick($fam) [lindex $b 6]
							} else {
								mess "Warning: Ignoring duplicate thickness value for part $fam\n" red
							}
						}
					} elseif {[lindex $b 1]=="BEAM_GEN_SECTION"} {
						set beamat [lindex $b 2]
						if {$beamat!=""} {
							if ![info exists nastran_param_arrays(Isotropic_Material:$beamat)] {
								mess "Warning: Material $beamat not found for part $fam\n" red
								set mat4fam($fam) unspecified_abaqus_material
							} else {
								if {$mat4fam($fam)==""} {
									set mat4fam($fam) $beamat
								} else {
									mess "Warning: Ignoring duplicate material for part $fam\n" red
								}
							}
						} else {
							if {$mat4fam($fam)==""} {
								set mat4fam($fam) unspecified_abaqus_material
							}
						}
						set beam_prop($fam) $b
#puts "beam_prop($fam) $beam_prop($fam)"
					} elseif {[lindex $b 1]=="TRANSFORM"} {
# associate transforms
						if [info exists transformed($fam)] {
							mess "Warning: Ignoring duplicate transformation [lindex $b 2] on part $fam\n" red
						} else {
							set transformed($fam) [lindex $b 2]
						}
					}
				}
			}

# element types
			set pid 1
			foreach fam [ic_boco_list_families] {
				set boc [ic_boco_get $fam]
#puts [list $fam $boc]
				foreach b $boc {
					switch [lindex $b 1] {
						SOLID3D {
							if {![info exists mat4fam($fam)] || $mat4fam($fam)==""} {
								mess "Warning: Material not found for volume part $fam\nSkipping part...\n" red
							} elseif ![info exists matid($mat4fam($fam))] {
								mess "Warning: Material $mat4fam($fam) not found for volume part $fam\nSkipping part...\n" red
							} else {
#ignore esys for now
#								puts $fp "\"$fam\" \"IVOL\" $mat4fam($fam) \"$esys($fam)\" 0 $pid"
								puts $fp "\"$fam\" \"IVOL\" $matid($mat4fam($fam)) 0 0 $pid"
								incr pid
							}
						}
						SOLID2D - AXSYM_SOLID - MEMBRANE - SHELL {
							if {![info exists mat4fam($fam)] || $mat4fam($fam)==""} {
								mess "Warning: Material not found for shell part $fam\nSkipping part...\n" red
							} elseif ![info exists matid($mat4fam($fam))] {
								mess "Warning: Material $mat4fam($fam) not found for shell part $fam\nSkipping part...\n" red
							} else {
								set m_thick ""
								if [info exists thick($fam)] {set m_thick $thick($fam)}
								puts $fp "\"$fam\" \"ISHE\" $pid $matid($mat4fam($fam)) \"\" \"\" \"\" \"\" $m_thick \"\" \"\""
								incr pid
							}
						}
						SOLID1D - AXSYM_MEMBRANE - TRUSS - BEAM - FRAME - ELBOW - AXSYM_SHELL {
							if {![info exists mat4fam($fam)] || $mat4fam($fam)==""} {
								mess "Warning: Material not found for beam part $fam\nSkipping part...\n" red
							} elseif ![info exists matid($mat4fam($fam))] {
								mess "Warning: Material $mat4fam($fam) not found for beam part $fam\nSkipping part...\n" red
							} else {
#								set a 0; set i1 0; set i2 0; set j 0; set or ""
								set bp [list 1 fam beam_prop 0 0 0 0 0 0 ""]
								if {[info exists beam_prop($fam)] && $beam_prop($fam)!=""} {
									set bp $beam_prop($fam)
								} else {
									mess "No section information found beam part $fam\n"
								}
								puts $fp "\"$fam\" \"PBAR\" $pid $matid($mat4fam($fam)) [lindex $bp 4] [lindex $bp 5] [lindex $bp 7] [lindex $bp 8]" 
								puts $fp "\"$fam\" \"OR\" $pid [lindex $bp 9]" 
								incr pid
							}
						}
						SPRING {
							puts $fp "\"$fam\" \"PELAS\" $pid [lindex $b 5] 0.0 0.0"
							if [lindex $b 2] {
								puts -nonewline $fp "\"$fam\" \"CMP\" $pid "
								if [lindex $b 3] {
									puts -nonewline $fp "[lindex $b 3] "
								} else {
									puts -nonewline $fp "\"\""
								}
								incr pid
								if [lindex $b 4] {
									puts -nonewline $fp "[lindex $b 4] "
								} else {
									puts -nonewline $fp "\"\""
								}
								puts $fp ""
							} else {
								puts $fp "\"$fam\" \"CMP\" $pid \"\" \"\""
							}
						}
						DASHPOT {
							puts $fp "\"$fam\" \"PDAMP\" $pid [lindex $b 5] 0.0"
							if [lindex $b 2] {
								puts -nonewline $fp "\"$fam\" \"CMP\" $pid "
								if [lindex $b 3] {
									puts -nonewline $fp "[lindex $b 3] "
								} else {
									puts -nonewline $fp "\"\" "
								}
								incr pid
								if [lindex $b 4] {
									puts -nonewline $fp "[lindex $b 4]"
								} else {
									puts -nonewline $fp "\"\""
								}
								puts $fp ""
								incr pid
							} else {
								puts $fp "\"$fam\" \"CMP\" $pid \"\" \"\""
							}
						}
						RIGID {
							puts $fp "\"$fam\" \"RBE2\" 1 0 \"\""
						}
						MASS {
							puts $fp "\"$fam\" \"CONM1\" 0 [lindex $b 2]"
						}
						CONNECTOR - SPRING1 - DASHPOT1 - ROTARY {
							mess "warning: Abaqus element type [lindex $b 1] not supported\n"
						}
						BOUNDARY {
							set lcs 0
							if [info exists transformed($fam)] {
								set lcsname Transform_$transformed($fam)
								if [info exists nastran_param_arrays(Local_Coordinates:$lcsname)] {
									array set lcsarr $nastran_param_arrays(Local_Coordinates:$lcsname)
									set lcs $lcsarr(Coordinate_System_ID)
								} else {
									mess "Warning: Ignoring transformation $transformed($fam) for BOUNDARY on part $fam\n" red
								}
							}
							set val 0
							set spcset [lindex $b 2]
							set step_bound($spcset) 1
							if $spcset {
							  if {[lsearch $nsteps $spcset]==-1} {
								  lappend nsteps $spcset
							  }
							  switch [lindex $b 3] {
								1 - 2 - 3 - 4 - 5 - 6 {
									set val [lindex $b 4]
									puts $fp "\"$fam\" \"ISPC\" $spcset [lindex $b 3] $val $lcs"
								}
								7 {
									puts $fp "\"$fam\" \"ISPC\" $spcset 1 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 2 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 3 $val $lcs"
								}
								8 {
									puts $fp "\"$fam\" \"ISPC\" $spcset 1 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 2 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 3 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 4 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 5 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 6 $val $lcs"
								}
								9 {
									puts $fp "\"$fam\" \"ISPC\" $spcset 1 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 5 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 6 $val $lcs"
								}
								10 {
									puts $fp "\"$fam\" \"ISPC\" $spcset 2 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 4 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 6 $val $lcs"
								}
								11 {
									puts $fp "\"$fam\" \"ISPC\" $spcset 3 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 4 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 5 $val $lcs"
								}
								12 {
									puts $fp "\"$fam\" \"ISPC\" $spcset 2 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 3 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 4 $val $lcs"
								}
								13 {
									puts $fp "\"$fam\" \"ISPC\" $spcset 1 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 3 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 5 $val $lcs"
								}
								14 {
									puts $fp "\"$fam\" \"ISPC\" $spcset 1 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 2 $val $lcs"
									puts $fp "\"$fam\" \"ISPC\" $spcset 6 $val $lcs"
								}
							  }
							} else {
							  switch [lindex $b 3] {
								1 - 2 - 3 - 4 - 5 - 6 {
									set val [lindex $b 4]
									lappend allstepsdata "$fam ISPC [lindex $b 3] $val $lcs"
								}
								7 {
									lappend allstepsdata "$fam ISPC 1 $val $lcs"
									lappend allstepsdata "$fam ISPC 2 $val $lcs"
									lappend allstepsdata "$fam ISPC 3 $val $lcs"
								}
								8 {
									lappend allstepsdata "$fam ISPC 1 $val $lcs"
									lappend allstepsdata "$fam ISPC 2 $val $lcs"
									lappend allstepsdata "$fam ISPC 3 $val $lcs"
									lappend allstepsdata "$fam ISPC 4 $val $lcs"
									lappend allstepsdata "$fam ISPC 5 $val $lcs"
									lappend allstepsdata "$fam ISPC 6 $val $lcs"
								}
								9 {
									lappend allstepsdata "$fam ISPC 1 $val $lcs"
									lappend allstepsdata "$fam ISPC 5 $val $lcs"
									lappend allstepsdata "$fam ISPC 6 $val $lcs"
								}
								10 {
									lappend allstepsdata "$fam ISPC 2 $val $lcs"
									lappend allstepsdata "$fam ISPC 4 $val $lcs"
									lappend allstepsdata "$fam ISPC 6 $val $lcs"
								}
								11 {
									lappend allstepsdata "$fam ISPC 3 $val $lcs"
									lappend allstepsdata "$fam ISPC 4 $val $lcs"
									lappend allstepsdata "$fam ISPC 5 $val $lcs"
								}
								12 {
									lappend allstepsdata "$fam ISPC 2 $val $lcs"
									lappend allstepsdata "$fam ISPC 3 $val $lcs"
									lappend allstepsdata "$fam ISPC 4 $val $lcs"
								}
								13 {
									lappend allstepsdata "$fam ISPC 1 $val $lcs"
									lappend allstepsdata "$fam ISPC 3 $val $lcs"
									lappend allstepsdata "$fam ISPC 5 $val $lcs"
								}
								14 {
									lappend allstepsdata "$fam ISPC 1 $val $lcs"
									lappend allstepsdata "$fam ISPC 2 $val $lcs"
									lappend allstepsdata "$fam ISPC 6 $val $lcs"
								}
							  }
							}
						}
						CLOAD {
							set lcs 0
							if [info exists transformed($fam)] {
								set lcsname Transform_$transformed($fam)
								if [info exists nastran_param_arrays(Local_Coordinates:$lcsname)] {
									array set lcsarr $nastran_param_arrays(Local_Coordinates:$lcsname)
									set lcs $lcsarr(Coordinate_System_ID)
								} else {
									mess "Warning: Ignoring transformation $transformed($fam) for CLOAD on part $fam\n" red
								}
							}
							set spcset [lindex $b 2]
							set step_load($spcset) 1
							if $spcset {
							  if {[lsearch $nsteps $spcset]==-1} {
								  lappend nsteps $spcset
							  }
							puts $fp "\"$fam\" \"FORCE\" $spcset $lcs 1.0 [lindex $b 3] [lindex $b 4] [lindex $b 5] 0"
							puts $fp "\"$fam\" \"MOMENT\" $spcset $lcs 1.0 [lindex $b 6] [lindex $b 7] [lindex $b 8] 0"
							} else {
								lappend allstepsdata "$fam FORCE $lcs 1.0 [lindex $b 3] [lindex $b 4] [lindex $b 5] 0"
								lappend allstepsdata "$fam MOMENT $lcs 1.0 [lindex $b 6] [lindex $b 7] [lindex $b 8] 0"
							}
						}
					}
				}
			}

			if {$allstepsdata!=""} {
				if {$nsteps==""} {set nsteps 1}
				foreach stp $nsteps {
					foreach cbc $allstepsdata {
						puts $fp "\"[lindex $cbc 0]\" \"[lindex $cbc 1]\" $stp [lrange $cbc 2 end]"
					}
				}
			}

			close $fp
			ic_boco_delete_unused 1
			ic_boco_unload
		}
	}
	
#write steps as subcases
	foreach stp $nsteps {
		catch {unset subcase}
		set subcase(ACTIVE) 1
		set subcase(TITLE) "Step $stp"
		if {[info exists step_bound(0)] || [info exists step_bound($stp)]} {
			set subcase(SPC) $stp
		}
		if {[info exists step_load(0)] || [info exists step_load($stp)]} {
			set subcase(LOAD) $stp
		}
		set nastran_param_arrays(Subcase:$stp) [array get subcase]
	}

#Add dummy material
	set mats ""
	foreach fm [array names mat4fam] {lappend mats $mat4fam($fm)}
	if {[lsearch $mats unspecified_abaqus_material]!=-1} {
		set mdata3 Isotropic_Material:unspecified_abaqus_material
		set i 1
		foreach p {Youngs_Modulus Poissons_Ratio Thermal_Expansion_Coefficient \
					Mass_Density Structural_Damping_Coefficient} {
			set ${mdata3}($p) ""
			incr i
		}
		set ${mdata3}(Material_ID) $matid(unspecified_abaqus_material)
		set nastran_param_arrays($mdata3) [array get $mdata3]
	}

	catch {unset abaqus_param_arrays}
	if ![info exists nastran_param_arrays] {
    	set fp [open ${proj}.par w]
    	close $fp
		return
	}
		
# for Nastran params file...
#puts "nastran_param_arrays: [array names nastran_param_arrays]"
	foreach n [array names nastran_param_arrays] {
		set abaqus_param_arrays($n) $nastran_param_arrays($n)
	}
	abaqus_params_save_solve_data ${proj}.par
	catch {unset abaqus_param_arrays}
}


#------------------------------------------------------------------------------
# Abaqus params file stuff
# Ref: ai_env/scripts/aie_lsdyna.tcl

proc abaqus_params_load_solve_data {file} {
	global abaqus_param_arrays
	catch {unset abaqus_param_arrays}
	
    if {![file exists $file] || [file size $file]==0 } { set_abaqus_params; return }

    set fp [open $file r]
	set inner 0
#	set abaqus_param_arrays ""
    while {![eof $fp]} {
	set line [string trim [gets $fp]]
#	puts "line: $line"
	if {[string match \#* $line] || ($line == "")} continue
	if {[lindex $line 0] == "begin"} {
	    set nname [lindex $line 1]
	    set ninst [lindex $line 2]
		if {!$inner} {
			set array $nname
			if {$ninst != ""} {
			append array ":$ninst"
	    	}
#			puts "setting array $array..."
#			global $array
    		set path ""
			set inner 1
			if {[lsearch [array names abaqus_param_arrays] $array]==-1} {
#				lappend emax_param_arrays $array
			} else {
				mess "merging duplicate Abaqus solver data ($array)\n"
			}
		} else {
	    	if {$ninst != ""} {
			append path "$nname:$ninst/"
	    	} else {
			append path "$nname/"
	    	}
		}
	} elseif {[lindex $line 0] == "end"} {
		if {$path==""} {
			if ![info exists array] { error "bad params file" }
			set inner 0
#			puts "unsetting array $array. empty path..."
			set abaqus_param_arrays($array) [array get $array]
			unset array
		} else {
	    	set par [lindex $line 1]
	    	set ninst [lindex $line 2]
			if {$ninst != ""} {
			append par ":$ninst"
	    	}
			set colon [string last / $path]
			if {$colon!=-1} { # This must be multiple param at root level
				incr colon -1
				set last [string range $path 0 $colon]
				if {![regexp $par$ $last]} {
				error "$line doesn't match $last"
	    		}
				set loc [expr [string length $last] - [string length $par] - 1]
				set path [string range $last 0 $loc] 
			} else {
#				puts "unsetting array $array. multiple param at root level..."
				set path ""
				set inner 0
				set abaqus_param_arrays($array) [array get $array]
				unset array
			}
		}
	} else {
		if ![info exists array] { error "bad params file" }
		set var "${path}[lindex $line 0]"
#		puts ", var: $var"
		set ${array}($var) [lindex $line 1]
	}
    }

    mess "Loaded AI*Env solver data for Abaqus...\n"
    close $fp
}

proc abaqus_params_save_solve_data {file} {
	global abaqus_saved_params_data abaqus_param_arrays
    
    set fp [open $file w]
    puts $fp "# solver params file written for AI*Environment on [cmd_date]"
    puts $fp "## solver ABAQUS"

	if ![info exists abaqus_param_arrays] { set_abaqus_params }
	catch {unset abaqus_saved_params_data}

    foreach array [array names abaqus_param_arrays] {
#		global $array
		foreach {n v} $abaqus_param_arrays($array) { set ${array}($n) $v }
		set last ""
		foreach key [lsort [array names $array]] {
			set abaqus_saved_params_data($array,$key) 0
		}
		set key_list [lsort [array names $array]]
#mess "array: $array\n"
#mess "key_list: $key_list\n"
		abaqus_params_save_solve_array $fp $array $last $key_list
    }
    close $fp
    mess "Saved AI*Env solver data for Abaqus...\n"
}

proc abaqus_params_save_solve_array {fp arr {last0 ""} {list0 ""}} {
	global abaqus_saved_params_data
#    upvar #0 $arr array
	
	if { $list0=="" } return
	if { $last0=="" } {
		set outlist ""
		set fwdlist ""
		foreach key $list0 {
			if {$abaqus_saved_params_data($arr,$key)} continue
			if {![regexp ^${last0} $key]} continue
			if [is_solve_level_end $key $last0] {
				set abaqus_saved_params_data($arr,$key) 1
				lappend outlist $key
			} 
		}
		foreach key $list0 {
			if {$abaqus_saved_params_data($arr,$key)} continue
			lappend fwdlist $key
		}
		abaqus_params_begin_level $fp $arr $last0 $outlist
		abaqus_params_save_solve_array $fp $arr [get_new_last_list $fwdlist $last0] $fwdlist
		abaqus_params_end_level $fp $arr $last0
	} else {
	foreach last $last0 {
		set outlist ""
		set fwdlist ""
		foreach key $list0 {
			if {$abaqus_saved_params_data($arr,$key)} continue
			if {![regexp ^${last} $key]} continue
			if [is_solve_level_end $key $last] {
				set abaqus_saved_params_data($arr,$key) 1
				lappend outlist $key
			} else {
				lappend fwdlist $key
			}
		}
		abaqus_params_begin_level $fp $arr $last $outlist
		abaqus_params_save_solve_array $fp $arr [get_new_last_list $fwdlist $last] $fwdlist
		abaqus_params_end_level $fp $arr $last
	}
	}
		
}

proc get_new_last_list {keys llast} {
	set ret ""
	if { $llast==""} {
		foreach key $keys {
			set last [get_next_level_key $key]
			if {$last==""} continue
			if {$ret==""} {
				lappend ret "$last"
			} else {
				set found 0
				foreach node $ret {
					if {$node==$last} {set found 1;break}
				}
				if {!$found} {
					lappend ret "$last"
				}
			}
		}
	} else {
		foreach prev $llast {
		foreach key $keys {
			if {![regsub ^${prev} $key "" tmp]} continue
			set last [get_next_level_key $tmp]
			if {$last==""} continue
			if {$ret==""} {
				lappend ret "$prev$last"
			} else {
				set found 0
				foreach node $ret {
					if {$node=="$prev$last"} {set found 1;break}
				}
				if {!$found} {
					lappend ret "$prev$last"
				}
			}
		}
		}
	}
	return $ret
}				
			
proc is_solve_level_end {key last} {
	regsub ^${last} $key "" tmp
	if { ![regexp (/|:)+ $tmp] } {
		return 1
	}
	return 0
}
					
proc abaqus_params_begin_level {fp arr last outlist} {
	global abaqus_param_arrays
#    upvar #0 $arr array
	foreach {n v} $abaqus_param_arrays($arr) { set array($n) $v }
	
	set level [count_solve_level $last]
#	incr level
	set tabs ""
	for {set i 0} {$i<$level} {incr i} {
		append tabs "    "
	}
	
	set wspec 0
	if {$last==""} {
		set nodename $arr
	} else {
		set nodename [get_solve_node_name $last]
	}

	if [regexp : $nodename] {
		set mark [string first : $nodename]
		set nodename1 [string range $nodename 0 [expr $mark-1]]
		set nodename2 [string range $nodename [expr $mark+1] end]
		if [regexp " " $nodename2] {
			set wspec 1
		} else {
			regsub : $nodename " " nodename
		}
	}

	if {!$level} { puts $fp "" }
	if {!$wspec} {
		puts $fp "${tabs}begin $nodename"
	} else {
		puts $fp "${tabs}begin $nodename1 \"$nodename2\""
	}
		
	foreach key $outlist {
		regsub ^${last} $key "" par
		set val $array($key)
		if {$val==""} { 
			set val "\{\}" 
		} elseif { [regexp " " $val] } {
			set val "\{$val\}"
		}
		puts $fp "${tabs}    $par $val"
	}
}

proc abaqus_params_end_level {fp arr last} {
	set level [count_solve_level $last]
#	incr level
	set tabs ""
	for {set i 0} {$i<$level} {incr i} {
		append tabs "    "
	}
	
	set wspec 0
	if {$last==""} {
		set nodename $arr
	} else {
		set nodename [get_solve_node_name $last]
	}

	if [regexp : $nodename] {
		set mark [string first : $nodename]
		set nodename1 [string range $nodename 0 [expr $mark-1]]
		set nodename2 [string range $nodename [expr $mark+1] end]
		if [regexp " " $nodename2] {
			set wspec 1
		} else {
			regsub : $nodename " " nodename
		}
	}

	if {!$wspec} {
		puts $fp "${tabs}end $nodename"
	} else {
		puts $fp "${tabs}end $nodename1 \"$nodename2\""
	}
}

proc get_next_level_key {key} {
	if {$key==""} { return "" }

	set last ""
	set multi [string first / $key]
	if {$multi!=-1} {
		set last [string range $key 0 $multi]
	}
	return $last
}

proc get_solve_node_name {key} {
	if {$key==""} { return "" }

	regsub /$ $key "" key
	
	set last ""
	set multi [string last / $key]
	if {$multi==-1} {
			return $key
	} else {
		incr multi
		set last [string range $key $multi end]
		regsub : $last " " last
	}
	return $last
}

proc count_solve_level {str} {
	if {$str==""} {return 0}
# now look for /s...
	set level [regsub -all / $str / dummy]
	return $level 
}

#------------------------------------------------------------------------------







