proc params_lsdyna_apply {} {
#    global env lsdyna_param_arrays
    global lsdyna_params_data
	
	set finclude [setupSolverParamDEZ get dyna_include_file]
	if {$finclude==""} return
	if {![info exists lsdyna_params_data(iid)]} {
		set iid 1
		while {[info exists lsdyna_params_data(Include$iid)]} {
			incr iid
		}
	} else {
		set iid $lsdyna_params_data(iid)
		unset lsdyna_params_data(iid)
	}
	set lsdyna_params_data(Include$iid) $finclude
    ::AIEnv::GUIManagement::Tree::PutLsdynaParams Include$iid 0
	setupSolverParamDEZ set dyna_include_file ""
}

proc aie_edit_lsdyna_params {name} {
    global current_lsdyna_params_to_load
    global lsdyna_params_data
    global solver_setup
	
	set solver_setup 2
	
    set current_lsdyna_params_to_load(name) $name
    set current_lsdyna_params_to_load(finclude) $lsdyna_params_data($name)

    setupSolverParamDEZ show
    
    unset current_lsdyna_params_to_load
}

proc aie_delete_lsdyna_params {name} {
    global lsdyna_params_data
    
    catch {unset lsdyna_params_data($name)}
    ::AIEnv::GUIManagement::Tree::DeleteLsdynaParams [list $name]
}

proc aie_rename_lsdyna_params {name} {
	return
    global lsdyna_params_data
    
    set newname [question_box .newname "New name" "New name for paramater $name" $name]
    if {$newname == ""} return

    #if ![aie_valid_name $newname 1] {return}
    #set newname [string toupper $newname]
    set newname [aie_get_valid_name $newname]
   
    set lsdyna_params_data($newname) $lsdyna_params_data($name)
    unset lsdyna_params_data($name)
     ::AIEnv::GUIManagement::Tree::RenameLsdynaParams $name $newname
}

proc aie_tree_load_lsdyna_params {} {
    global lsdyna_params_data env
    
    if [info exists env(AI_ENV_CFX)] return  ;# for now
    
    catch {unset lsdyna_params_data(iid)}
    set lsdyna_params [array names lsdyna_params_data]
#    if $clear { catch {unset lsdyna_params_data} }

    if {[llength $lsdyna_params] != 0} {::AIEnv::GUIManagement::Tree::PutLsdynaParams $lsdyna_params 0}
}

proc params_lsdyna_load {} {
    global lsdyna_params_data current_lsdyna_params_to_load
    if [info exists current_lsdyna_params_to_load(name)] {
		regsub ^Include $current_lsdyna_params_to_load(name) "" iid
		set lsdyna_params_data(iid) $iid
	} else {
		catch {unset lsdyna_params_data(iid) $iid}
	}
    if [info exists current_lsdyna_params_to_load(finclude)] {
		setupSolverParamDEZ set dyna_include_file $current_lsdyna_params_to_load(finclude)
    } else {
		setupSolverParamDEZ set dyna_include_file ""
	}
}

proc set_lsdyna_file {} {
	global file_name lsdyna_param_arrays
	global lsdyna_Volumes lsdyna_Shells lsdyna_Bars lsdyna_Points
    global thickness_defined
   	if ![info exists lsdyna_param_arrays] { set_lsdyna_params }
  
	set tmp [writeNastranDEZ get lsdyna_file]  
	if {$tmp == ""} {
	if {$file_name(settings) == "" } {
		set base lsdyna
		writeNastranDEZ set lsdyna_file "lsdyna.k"
	} else {
		set base [file tail [file root $file_name(settings)]]
		writeNastranDEZ set lsdyna_file $base.k
	}
	}
  
	set tmp [writeNastranDEZ get lsdyna_fbc]  
	if {$tmp == ""} {
		writeNastranDEZ set lsdyna_fbc $base.lsdyna.fbc
	}
  
	set tmp [writeNastranDEZ get lsdyna_par]  
	if {$tmp == ""} {
		writeNastranDEZ set lsdyna_par $base.lsdyna.par
	}
    writeNastranDEZ set lsdyna_volumeList {Defined All}
	set tmp [writeNastranDEZ get lsdyna_volume]  
	if {$tmp == ""} {
		writeNastranDEZ set lsdyna_volume Defined
		set lsdyna_Volumes Defined
	}
	 
    writeNastranDEZ set lsdyna_shellList {Defined All None}
	set tmp [writeNastranDEZ get lsdyna_shell]  
	if {$tmp == ""} {
		writeNastranDEZ set lsdyna_shell Defined
		set lsdyna_Shells Defined
	}
	 
    writeNastranDEZ set lsdyna_barList {Defined All None}
	set tmp [writeNastranDEZ get lsdyna_bar]  
	if {$tmp == ""} {
		writeNastranDEZ set lsdyna_bar Defined
		set lsdyna_Bars Defined
	}
	 
    writeNastranDEZ set lsdyna_pointList {Defined All None}
	set tmp [writeNastranDEZ get lsdyna_point]  
	if {$tmp == ""} {
		writeNastranDEZ set lsdyna_point Defined
		set lsdyna_Points Defined
	}
	 
    aie_check_shell_thicknesses
	if ![info exists thickness_defined] {set thickness_defined 0}
    writeNastranDEZ set lsdyna_thickList {BCDefined Distributed Averaged}
	set tmp [writeNastranDEZ get lsdyna_thick]  
	if {$tmp == ""} {
		if {$thickness_defined == 0} {writeNastranDEZ set lsdyna_thick BCDefined
		} elseif {$thickness_defined == 1} {writeNastranDEZ set lsdyna_thick Distributed
		} elseif {$thickness_defined == 2} {writeNastranDEZ set lsdyna_thick Averaged
		}
	} else {
		if {$thickness_defined == 0 && $tmp != "BCDefined"} {writeNastranDEZ set lsdyna_thick "BCDefined"}
		if {$thickness_defined && $tmp == "BCDefined"} {
			writeNastranDEZ set lsdyna_thick [lindex [writeNastranDEZ get lsdyna_thickList] $thickness_defined]
		}
	}
	 
}

proc setup_lsdyna_load {} {
	namespace eval ::AIEnv::DEZ::setupNastranRunDEZ {
    	global env lsdyna_param_arrays
    	if ![info exists lsdyna_param_arrays] { set_lsdyna_params }
    	foreach {n v} [array get lsdyna_param_arrays] {
			array set $n $v
		}
		
		set lsdyna_title $title(title)
		if {$lsdyna_title==""} { set lsdyna_title "AI*Environment LS-Dyna Project" }
		foreach mat {lsdynaMatSolidVal lsdynaMatShellVal lsdynaMatBeamVal lsdynaFormBeamVal} {
			if { ![info exists $mat] || [set $mat]=="" } {
				set $mat 0
			}
		}
		if {$lsdyna_rho==""} { set lsdyna_rho 0.0 }
		foreach mat {solid_sigy solid_fail shell_sigy shell_fail} {
			if { ![info exists $mat] || [set $mat]=="" } {
				set $mat 0.0
			}
		}
	}
	
}

proc setup_lsdyna_apply {} {
    global env lsdyna_param_arrays

# get the lsdyna params settings..

	set title [setupNastranRunDEZ get lsdyna_title]

# update lsdyna params settings
	set lsdyna_param_arrays(title) [list title $title]

}

proc set_lsdyna_params {} {
    global  env solver_setup solver_type
    global lsdyna_param_arrays

	for {set i 1} {$i<=40} {incr i} {
		set control(Control$i/OPT) 0
	}
# extra settings for lsdyna_control.C, interface to be changed to move this stuff 
# from initParams to readParams.
	set control(Control3/card1p7) 0
	set control(Control18/choice) 0
	
# add secific *CONTROL_s...
	# CONTACT (13) -- too much data, not provided
	# CPU (15, 1 params)
	# ENERGY (17, 4 params)
	# HOURGLASS (18, 2 params)
	# OUTPUT (27, 8 params)
	# PARALLEL (28, 4 params)
	# SHELL (31, 8 params)
	# TERMINATION (35, 5 params)
	# TIMESTEP (39, 8 params)
	
	foreach {n v} {15 1 17 4 18 2 27 8 28 4 31 8 35 5 39 8} {
		set control(Control$n/OPT) 1
		for {set i 1} {$i<=$v} {incr i} {
			set control(Control$n/card1p$i) 0
		}
	}
	
	# ENERGY, HGEN
	set control(Control17/card1p1) 2
	# ENERGY, RWEN
	set control(Control17/card1p2) 2
	# ENERGY, SLNTEN
	set control(Control17/card1p3) 2
	# ENERGY, RYLEN
	set control(Control17/card1p4) 1

	# HOURGLASS, IHQ
	set control(Control18/card1p1) 1
	# HOURGLASS, QH
	set control(Control18/card1p2) 0.1

	# OUTPUT, NPOPT
	set control(Control27/card1p1) 1
	# OUTPUT, NEECHO
	set control(Control27/card1p2) 3
	
	# PARALLEL, NCPU
	set control(Control28/card1p1) 1

	# SHELL, ESORT
	set control(Control31/card1p2) 1
	# SHELL, THEORY
	set control(Control31/card1p5) 2

	# TERMINATION, ENDTIM
	set control(Control35/card1p1) 0.2

	# TIMESTEP, TSSFAC
	set control(Control39/card1p2) 0.9
	# TIMESTEP, DT2MS
#	set control(Control39/card1p5) -6.666E-06

	foreach db { ABSTAT AVSFLT BNDOUT DEFGEO DEFORC ELOUT GCEOUT \
				GLSTAT JNTFORC MATSUM MOVIE MPGS NCFORC NODFOR \
				NODOUT RBDOUT RCFORC RWFORC SBTOUT SECFORC SLEOUT \
				SPCFORC SPHOUT SSSTAT SWFORC TPRINT TRHIST } {
		set dbase(database/$db/OPT) 0
	}
	
	foreach ext { AVS MOVIE MPGS BINARY } {
		set dbase(database_extent/$ext/Opt) 0
	}

	foreach suf { format spring superplastic tracer } {
		set dbase(database_${suf}/DEFINE) 0
	}
		
# add secific *DATABASE_s...
	foreach db { ABSTAT GLSTAT MATSUM RWFORC } {
		set dbase(database/$db/OPT) 1
		set dbase(database/$db/OUT) 1E-03
	}	
	
	set dbase(database_extent/BINARY/Opt) 1
	foreach {n v} {	NEIPH 0 NEIPS 0 MAXINT 0 STRFLG 1 SIGFLG 1 EPSFLG 1 RLTFLG 1  ENGFLG 1 \
					CMPFLG 0 IEVERP 1 BEAMIP 0 DECOMP 0 SHGE 0 STSSZ 0 N3THDT 0 } {
		set dbase(database_extent/BINARY/$n) $v
	}
	
# BINARY_D3PLOT
	set node database_binary:database_binary0
	set dbase($node/OPTION) 5
	set dbase($node/DT) 5E-03
	set dbase($node/LCDT) 0
	set dbase($node/BEAM) 0
	set dbase($node/NPLTC) 0
	
# BINARY_D3THDT
	set node database_binary:database_binary1
	set dbase($node/OPTION) 6
	set dbase($node/DT) 1.0
	set dbase($node/LCDT) 0
	
# BINARY_INTFOR
	set node database_binary:database_binary2
	set dbase($node/OPTION) 7
	set dbase($node/DT) 1.0
	set dbase($node/LCDT) 0
	
	array set def_solid {
		write 0
		formul 0
		mat_def 0
		mat_name ""
		mat0 1
		sec_solid/opt 0
		sec_solid/id -1
		sec_solid/formul 1
		sec_solid/aet 4
		hg_solid/include 0
		EOS_solid/include 0
	}
	for {set i 1} {$i<7} {incr i} {
		for {set j 1} {$j<9} {incr j} {
			set def_solid(card$i/f$j) 0.0
		}
	}
	set def_solid(card1/f1) -1

	array set def_shell {
		write 0
		physics 0
		formul 1
		formul2 12
		mat_def 0
		mat_name ""
		mat0 1
		sec_shell/opt 0
		sec_shell/id -1
		sec_shell/shrf 0.0
		sec_shell/nip 0
		sec_shell/propt 1
		sec_shell/qr 0
		sec_shell/icomp 0
		sec_shell/thk  0.0
		sec_shell/nloc 0
		sec_shell/marea 0.0
		hg_shell/include 0
	}
	for {set i 1} {$i<7} {incr i} {
		for {set j 1} {$j<9} {incr j} {
			set def_shell(card$i/f$j) 0.0
		}
	}
	set def_shell(card1/f1) -1

	array set def_beam {
		write 0
		formul 1
		n3 "0.0 0.0 0.0"
		n3opt 0
		mat_def 0
		mat_name ""
		mat1 1
		rt 0
		rr 0
		cs 2
		sec_beam/id -1
		sec_beam/formul 1
		sec_beam/shrf 1.0
		sec_beam/qr 2
		sec_beam/cst 0
		sec_beam/scoor 0
		sec_beam/nsm 0.0
	}
	for {set i 1} {$i<7} {incr i} {
		for {set j 1} {$j<9} {incr j} {
			set def_beam(card$i/f$j) 0.0
		}
	}
	set def_beam(card1/f1) -1
	for {set i 1} {$i<9} {incr i} {
		set def_beam(sec_beam/f$i) 0.0
	}

	array set def_node {
		write 0
		formul 0
		mass 0.0
	}

	array set def_part {
		adpopt 0
		grav 0
		tmid 0
	}	

	foreach misc { blastload brodeload constraint initial_cfd define \
				contact_rigid contact_interior } {
		set ${misc}(DEFINE) 0
	}
	
	set define(lCurve_feedback/DEFINE) 0

# Add four extremely useful curves...
	set lsdyna_load_curve_id 0
	foreach {name val} {load_curve_null 0.0 load_curve_unity 1.0 load_curve_ramped_load 0.0 dummy_for_contacts 0.0} {
	set node lcurv:$name
	set define($node/name) $name
	incr lsdyna_load_curve_id
	set define($node/id) $lsdyna_load_curve_id
	set define($node/lopt) 0
	set define($node/opt) 0
	set define($node/sfx) 1.0
	set define($node/sfy) 1.0
	set define($node/offx) 0.0
	set define($node/offy) 0.0
	set define($node/type) 0
	set define($node/point:point0/x) 0.0
	set define($node/point:point0/y) $val
	set define($node/point:point1/x) 0.2
	set define($node/point:point1/y) $val
	if {$name=="load_curve_ramped_load"} {
		set define($node/point:point1/x) 0.2
		set define($node/point:point1/y) 1.0
		set define($node/point:point2/x) 1.0
		set define($node/point:point2/y) 1.0 }
	}
 
	set title(title) ""

	foreach arr { control dbase def_solid def_shell def_beam def_node def_part \
				blastload brodeload constraint initial_cfd define title \
				contact_rigid contact_interior } {
    	set lsdyna_param_arrays($arr) [array get $arr]
	}
}

proc set_lsdyna_solve {} {
          global env tcl_platform

	if [catch {solveNastranDEZ get lsdyna_post} exec_tmp] {
	    set exec_tmp ""
	} 
	if {$exec_tmp==""} {
                   if [info exist env(LSDYNA_EXEC_PATH)] {
                       set lsdynaexec $env(LSDYNA_EXEC_PATH)
		     if {$tcl_platform(platform) == "windows" } {
                            regsub -all \\\\ $lsdynaexec / lsdynaexec
		      }
		      solveNastranDEZ set lsdyna_exec $lsdynaexec
                   } else {
                       if [info exist env(ANSYS100_DIR)] {
                          set lsdynaexec $env(ANSYS100_DIR)
		      if {$tcl_platform(platform) == "windows" } {
                            regsub -all \\\\ $lsdynaexec / lsdynaexec
			append lsdynaexec \/bin\/intel\/ls970\.exe
		      } else {
			append lsdynaexec \/bin\/lsdyna100
		      }
		      solveNastranDEZ set lsdyna_exec $lsdynaexec
                      }
                   }
         }

	if {[solveNastranDEZ get lsdyna_in]==""} {
	solveNastranDEZ set lsdyna_in [writeNastranDEZ get lsdyna_file]
	}
	namespace eval ::AIEnv::DEZ::solveNastranDEZ {
		global ansys_product_table
		if {$lsdyna_in==""} {
			set lsdyna_in [writeNastranDEZ get lsdyna_file]
		}
		if {$lsdynaAnsysVal==""} {set lsdynaAnsysVal 0}
		set prod_list ""
		foreach p [lsort [array names ansys_product_table]] {
			if {[regexp ds$ $p] || [regexp dp$ $p] || [regexp ^dyna $p]} {
				lappend prod_list $ansys_product_table($p)
			}
		}
		if {$prod_list==""} {
			mess "No Ansys LS-Dyna product license found.\n"
			return
		} 
		if {$lsdyna_ansys_prod==""} {
			set lsdyna_AnsysList $prod_list
			set lsdyna_ansys_prod [lindex $prod_list 0]
		}
	}
}

proc solve_lsdyna_file {} {
    global  env solver_setup solver_type 
    global  file_name
	global ansys_product_table ansys_directory ansys_vers
    global  is_win

    set solver_setup 2
	
	set exec [solveNastranDEZ get lsdyna_exec]
	if {$exec==""} {
		mess "Error: No LS-Dyna executable specified.\n" red
		return
	}
	if $is_win {
		regsub -all \\\\ $exec / exec
		set exec "start \"$exec\""
	} else {
		regsub -all " " $exec "\\ " exec
	}
	set in [solveNastranDEZ get lsdyna_in]
	if {$in==""} {
		mess "Error: No LS-Dyna input file selected.\n" red
		return
	}
	set work_dir [file dirname $in]
	set inp [file tail $in]
	set cmd "$exec i=[list $inp]"

	set ansys [solveNastranDEZ get lsdynaAnsysVal]
	if {$ansys} {
		set prod [solveNastranDEZ get lsdyna_ansys_prod]
		if {$prod==""} {
			mess "Error: No Ansys LS-Dyna license available.\n" red
			return
		} else {
			set full_name ""
			foreach p [array names ansys_product_table] {
				if {$prod==$ansys_product_table($p)} {
				set full_name $prod
				set prod $p
				break
				}
			}
			set cmd "$cmd pr=$prod &"
		}
	} else {
		set cmd "$cmd &"
	}

	set here [pwd]
	ic_chdir $work_dir
         mess "Starting LS-Dyna run...\n"
	mess "$cmd\n from $work_dir\n"

         if [catch {eval ic_exec $cmd} pid] {
		mess "Error: $pid\n" red
		ic_chdir $here
		return
	}
	mess "$pid\n"
	ic_chdir $here
	return
}

proc set_lsdyna_post {} {
    global  env solver_setup solver_type
    global lsdynainfo
    global file_name
    global env tcl_platform

      set ::lsdynainfo(file) ""
      set ::lsdynainfo(dir_loc) ""
      set ::lsdynainfo(group_by_material) 0

	if [catch {postNastranDEZ get lsdyna_post} exec_tmp] {
	     set exec_tmp ""
	}

	if {$exec_tmp==""} {
                   if [info exist env(LSPOST_EXEC_PATH)] {
                       set lsdynapost $env(LSPOST_EXEC_PATH)
		     if {$tcl_platform(platform) == "windows" } {
                            regsub -all \\\\ $lsdynapost / lsdynapost
		      }

		      catch {postNastranDEZ set lsdyna_post $lsdynapost}
                   } else {
                       if [info exist env(ANSYS100_DIR)] {
                          set lsdynapost $env(ANSYS100_DIR)
		      if {$tcl_platform(platform) == "windows" } {
                            regsub -all \\\\ $lsdynapost / lsdynapost
			append lsdynapost \/bin\/intel\/lspost\.exe
		      } else {
			append lsdynapost \/bin\/lspost100
		      }
		      catch {postNastranDEZ set lsdyna_post $lsdynapost}
                      }
                   }
         }

}

proc post_lsdyna_file {} {
    global  env solver_setup solver_type
    global  is_win

    set solver_setup 2

	if [ catch {postNastranDEZ get lsdyna_post} exec] {
	    set exec ""
	}

	if {$exec==""} {
		mess "Error: No LSPOST executable specified.\n" red
		return
	}
	if $is_win {
		regsub -all \\\\ $exec / exec
		set exec "\"$exec\""
	} else {
		regsub -all " " $exec "\\ " exec
	}

	if [catch {postNastranDEZ get lsdyna_result} in] {
	    set in ""
	}
	if {$in==""} {
		mess "Warning: No LS-Dyna input file selected.\n" red
	}
	set work_dir [file dirname $in]
	set inp [file tail $in]
	set cmd "$exec [list $inp] &"

	set here [pwd]
	ic_chdir $work_dir
    mess "Starting LSPOST run...\n"
	mess "$cmd\n from $work_dir\n"

    if [catch {eval ic_exec $cmd} pid] {
		mess "Error: $pid\n" red
		ic_chdir $here
		return
	}
	mess "$pid\n"
	ic_chdir $here
	return
}

proc post_lsdyna_file_v3 {} {
    global  env solver_setup solver_type
    global lsdynainfo

    set solver_setup 2

    if [catch {postNastranDEZ get lsdyna_result} in] {
       set in ""
    }
    if {$in==""} {
       mess "Warning: No LS-Dyna D3plot file selected.\n" red
       return
    }
   
    set ::lsdynainfo(file) $in
    set ::lsdynainfo(dir_loc) [file dirname $in]

    aie_v3p_startup_cmd -data_format lsdyna

}

proc update_lsdyna_setup {} {
    global  env solver_setup solver_type

    set solver_setup 2
    	
}

proc aie_generate_lsdyna_data {} {
    global thickness_defined
    set afbc [writeNastranDEZ get lsdyna_fbc]
    set apar [writeNastranDEZ get lsdyna_par]
    
    aie_check_shell_thicknesses
    if {$thickness_defined && [writeNastranDEZ get lsdyna_thick] != "BCDefined" && ![ic_uns_thickness_exists_mesh]} {
		mess "Computing thinckness.  Please Wait....\n"
		ic_uns_thickness create
	}
    aie_saveProject 0 1
    mess "Creating the LS-Dyna attribute & parameter files....\n"
    return [aie_convert_nastran_lsdyna_files $afbc $apar]
}

proc lsdyna_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 lsdyna_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 lsdyna_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 LS-DYNA3D
    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 lsdyna_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 lsdyna_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 lsdyna_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 LS-DYNA3D
#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_lsdyna_file {} {
     global env file_name tcl_platform
     global  env solver_setup solver_type
     global thickness_defined

     set solver_setup 2
     aie_saveProject 0 1

    set lsdyna_file [writeNastranDEZ get lsdyna_file]
    set view_file [writeNastranDEZ get view_file]

#    set afbc [file rootname $file_name(family_boco)].lsdyna.fbc
#    set apar [file rootname $file_name(solver_params)].lsdyna.par
    set afbc [writeNastranDEZ get lsdyna_fbc]
    set apar [writeNastranDEZ get lsdyna_par]
    
    if ![writeNastranDEZ get lsdynaEditOptionVal] {
       aie_check_shell_thicknesses
       if {$thickness_defined && [writeNastranDEZ get lsdyna_thick] != "BCDefined" && ![ic_uns_thickness_exists_mesh]} {
		mess "Computing thinckness.  Please Wait....\n"
		ic_uns_thickness create
       }
       aie_saveProject 0 1
       mess "Creating the LS-Dyna attribute & parameter files....\n"
       if ![aie_convert_nastran_lsdyna_files $afbc $apar] return
    }
    
    mess "Creating the LS-Dyna Input File.  Please Wait....\n"
    # This runs the translator
    if ![aie_export_lsdyna $lsdyna_file $file_name(domain) \
	     $afbc $apar] return
    
    if $view_file {
	edit_file $lsdyna_file 1
    }
}

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

proc aie_export_lsdyna {lsdyna_file domain family_boco solver_params} {
    global env bindir tcl_platform
	global lsdyna_Volumes lsdyna_Shells lsdyna_Bars lsdyna_Points
    
    set lsdyna_exec $env(ICEM_ACN)/icemcfd/output-interfaces/ls_dyna3d
    if {$tcl_platform(platform) == "windows"} {
	append lsdyna_exec .exe
    }
    
    regsub -all \\\\ $lsdyna_exec / lsdyna_exec
    
    if ![file executable $lsdyna_exec] {
	error "Can't find Converter executable $lsdyna_exec"
	return 0
    }
    
    set lsdyna_cmd [list $lsdyna_exec -dom $domain -b $family_boco -par $solver_params $lsdyna_file]

	if {[writeNastranDEZ get lsdyna_volume]!=$lsdyna_Volumes} {
		mess "WARNING: Parameter file out-of-date for volume elements\n" red
	}

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

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

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

#    set no_node [writeNastranDEZ get lsdynaIgnoreNodeVal]
	if $no_node { lappend lsdyna_cmd -ignore_node }
#    set no_bar [writeNastranDEZ get lsdynaIgnoreBarVal]
	if $no_bar { lappend lsdyna_cmd -ignore_bar }
#    set no_shell [writeNastranDEZ get lsdynaIgnoreShellVal]
	if $no_shell { lappend lsdyna_cmd -ignore_shell
	} else {
		switch [writeNastranDEZ get lsdyna_thick] {
			BCDefined {set t 0}
			Distributed {set t 1}
			Averaged {set t 2}
			default {set t 0}
		}
		lappend lsdyna_cmd -thickness $t
	}
    
    mess $lsdyna_cmd\n
    
    if {![catch {eval ic_exec $lsdyna_cmd} out]} {
	mess "$out\n"
	return 1
    } else {
	mess "Error \n $out\n" red
	return 0
    }
}

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

# Take the bc's we currently have loaded and convert them into 
# lsdyna bc's and solver parameters.
proc aie_convert_nastran_lsdyna_files {afbc apar} {
	global lsdyna_param_arrays lsdyna_Volumes lsdyna_Shells lsdyna_Bars lsdyna_Points
	global lsdyna_pid_unique
    foreach f [ic_boco_list_unused] { set unused($f) 1 }
#reset all element definitions
	foreach node [array names lsdyna_param_arrays] {
		if [regexp {^elem[0-3]d} $node] { unset lsdyna_param_arrays($node) }
		if [regexp ^set_bc: $node] { unset lsdyna_param_arrays($node) }
	}

#build pid info for uniqueness
    foreach fam [ic_boco_list_families] {
		if [info exists unused($fam)] continue
		#don't ignore families derived from a part
		#if [regexp : $fam] continue
		foreach g [split $fam :] {
		set bcs [ic_boco_get $g]
		  foreach etype {element_prop_0d element_prop_1d element_prop_2d element_prop_3d} {
	    	set data [aie_parse_bcs_$etype $bcs]
	    	if {$data == ""} continue
			catch {unset vals}
    		foreach {n v} $data { set vals($n) $v }
			if ![info exists vals(etype)] continue
			set etype $vals(etype)
			set pid 0
			if [info exists vals(pid)] {
				if {$vals(pid)!=""} {set pid $vals(pid)}
			}
			if !$pid continue
			set lsdyna_pid($pid) 1
			if ![info exists lsdyna_pid_etype($etype)] {
				set lsdyna_pid_etype($etype) $pid
			} else {
				set lsdyna_pid_etype($etype) [lappend lsdyna_pid_etype($etype) $pid]
			}
		  }
		}
	}
	
	catch {unset lsdyna_pid_unique}
	foreach pid [array names lsdyna_pid] {
		set got 0
		set lsdyna_pid_unique($pid) 1
		foreach etype [array names lsdyna_pid_etype] {
			set types $lsdyna_pid_etype($etype)
			if !$got {
				if {[lsearch $types $pid]==-1} continue
				set got 1
			} else {
				if {[lsearch $types $pid]==-1} continue
				set lsdyna_pid_unique($pid) 0
				break
			}
		}
	}
		
    set fp [open $afbc w]
    puts $fp "# family_boco file written for AI*Environment on [cmd_date]"
    puts $fp "# solver LS-DYNA3D"
    foreach fam [ic_boco_list_families] {
	if {$fam=="ORFN"||$fam=="VORFN"} continue
	if [info exists unused($fam)] continue
	set used($fam) 1
	puts $fp "\"$fam\""
	
	foreach g [split $fam :] {
	set bcs [ic_boco_get $g]
	
	# 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 velocity rigidwall constrainednodes} {
	    set data [aie_parse_bcs_$etype $bcs]
	    if {$data == ""} continue
	    
	    aie_write_lsdyna_bc_$etype $fp $fam $data
	}
	}
    }
	#unused__aie_write_lsdyna_bc_contact $fp
	aie_write_lsdyna_bcs_single_contact
	lsdyna_add_multiple_contacts
    close $fp

#LS-Dyna fbc file replay support for regression testing
    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

# LS-Dyna needs that materials are defined alongwith elements.
	lsdyna_add_materials
	
	lsdyna_add_LCS
	
	lsdyna_set_gravity
	
	lsdyna_add_parameters

# reset element type defaults
	foreach e {solid shell beam node} {
		array set def_$e $lsdyna_param_arrays(def_$e)
	}
	
	set lsdyna_Volumes [writeNastranDEZ get lsdyna_volume]
	if {$lsdyna_Volumes == "Defined"} {
		set def_solid(write) 0
	} elseif {$lsdyna_Volumes == "All"} {
		set def_solid(write) 1
	}

	set lsdyna_Shells [writeNastranDEZ get lsdyna_shell]
	if { $lsdyna_Shells== "Defined"} {
		set def_shell(write) 0
	} elseif { $lsdyna_Shells== "All"} {
		set def_shell(write) 1
	}

	set lsdyna_Bars [writeNastranDEZ get lsdyna_bar]
	if {$lsdyna_Bars == "Defined"} {
		set def_beam(write) 0
	} elseif {$lsdyna_Bars == "All"} {
		set def_beam(write) 1
	}

	set lsdyna_Points [writeNastranDEZ get lsdyna_point]
	if { $lsdyna_Points== "Defined"} {
		set def_node(write) 0
	} elseif { $lsdyna_Points== "All"} {
		set def_node(write) 1
	}

	foreach e {solid shell beam node} {
		set lsdyna_param_arrays(def_$e) [array get def_$e] 
	}
	
# add part set of all parts
	if [info exists used] {
		set arr(name) All
		set ctr 0
		foreach p [array names used] {
			set arr(fam:fam$ctr/str) $p
			incr ctr
		}
		set lsdyna_param_arrays(part_set:All) [array get arr]
	}
		
#    set fp [open $apar w]
    lsdyna_params_save_solve_data $apar
#    close $fp

#LS-Dyna 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 lsdyna
# 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_lsdyna_bc_impdisp serves the purpose instead.
proc unused__aie_write_lsdyna_bc_constraint {fp fam data} {
    foreach {n v} $data { set vals($n) $v }
    
    foreach {t dof} {UX 1 UY 2 UZ 3 ROTX 5 ROTY 6 ROTZ 7} {
	if {[info exists vals($t)] && ($vals($t) == 1)} {
	    puts $fp "\"$fam\" \"BOUNDARY\" 1 1 $dof 2 1 1.0 0 1.0E+28 0.0 0.0 0.0"
	}
    }
# don't know how to handle spcSet.
}

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

proc aie_write_lsdyna_bc_impdisp {fp fam data} {
	global lsdyna_param_arrays lcs_data
    foreach {n v} $data { set vals($n) $v }
	if [info exists vals(lsdyna_nsid)] {
		set nsid $vals(lsdyna_nsid)
		if {$nsid=="" || $nsid<0} {
			set nsid 0
		}
	} else {
		set nsid 0
	}
    
	set lcs 0
	if {[info exists vals(LCS)]} {
		if {$vals(LCS)!="Global"} {
			foreach l [array names lcs_data] {
				if {[lindex $lcs_data($l) 0]==$vals(LCS)} {
					set type [lindex $lcs_data($l) 2]
					switch $type {
						Cartesian - R - Rectangular { set type cartesian }
						Cylindrical - C             { set type cylindrical }
						Spherical   - S             { set type spherical }
					}
					if {$type=="cartesian"} {
						set lcs [lindex $lcs_data($l) 0]
					} else {
						mess "Warning: Displacements in $type coordinate system for Part $fam " red
						mess "converted to global coordinate system.\n" red
					}
					break
				}
			}
		}
	}
	
	set fixed 0
    array set fix {1 0 2 0 3 0 5 0 6 0 7 0}
	foreach {t dof} {UX 1 UY 2 UZ 3 ROTX 5 ROTY 6 ROTZ 7} {
	  if {[info exists vals(Check$t)] && ($vals(Check$t) == 1)} {
		if {[expr double($vals($t))]==0.0} {
			set fixed 1
			set fix($dof) 1
		} else {
			if ($lcs){
				mess "Warning: Non-zero displacement $t in $type coordinate system for Part $fam " red
				mess "converted to global coordinate system.\n" red
			} 
			if $nsid {
#	add node set bc...
			  puts $fp "\"$fam\" \"NODE_SET_ID\" $nsid"
			  if ![info exists lsdyna_param_arrays(set_bc:bpid$nsid)] {
#	add parameter set bc
				set sbc(title) "*BOUNDARY_PRESCRIBED_MOTION_SET"
				set sbc(id) $nsid
				set sbc(type) 0
				set sbc(nc) 1
				for {set i 1} {$i<4} {incr i} {
					for {set j 1} {$j<9} {incr j} {
						set sbc(card$i/f$j) ""
					}
				}
				set sbc(card1/f1) $nsid
				set sbc(card1/f2) $dof
				set sbc(card1/f3) 2
				set sbc(card1/f4) 2
				set sbc(card1/f5) $vals($t)
				set sbc(card1/f6) 0
				set sbc(card1/f7) 1.0E+28
				set sbc(card1/f8) 0
				set lsdyna_param_arrays(set_bc:bpid$nsid) [array get sbc]
			  }
			} else {
			puts $fp "\"$fam\" \"BOUNDARY\" 1 1 $dof 2 2 $vals($t) 0 1.0E+28 0.0 0.0 0.0"
			}
		}
	  }
	}
	if $fixed {
	if $nsid {
#	add node set bc...
	  puts $fp "\"$fam\" \"NODE_SET_ID\" $nsid"
	  if ![info exists lsdyna_param_arrays(set_bc:bsid$nsid)] {
#	add parameter set bc
		set sbc(title) "*BOUNDARY_SPC_SET"
		set sbc(id) $nsid
		set sbc(type) 0
		set sbc(nc) 1
		for {set i 1} {$i<4} {incr i} {
			for {set j 1} {$j<9} {incr j} {
				set sbc(card$i/f$j) ""
			}
		}
		set sbc(card1/f1) $nsid
		set sbc(card1/f2) $lcs
		foreach n {1 2 3 5 6 7} f {f3 f4 f5 f6 f7 f8} {
			set sbc(card1/$f) $fix($n)
		}
		set lsdyna_param_arrays(set_bc:bsid$nsid) [array get sbc]
	  }
	} else {
		puts -nonewline $fp "\"$fam\" \"BOUNDARY\" 3 -1 $lcs"
		foreach f [lsort [array names fix]] {
			puts -nonewline $fp " $fix($f)"
		}
		puts $fp ""
	}
    }
# don't know how to handle spcSet.
}

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

proc aie_write_lsdyna_bc_force {fp fam data} {
	global lcs_data lsdyna_param_arrays
    foreach {n v} $data { set vals($n) $v }

	if [info exists vals(lsdyna_nsid)] {
		set nsid $vals(lsdyna_nsid)
		if {$nsid=="" || $nsid<0} {
			set nsid 0
		}
	} else {
		set nsid 0
	}
	
  	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 lcs 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 type [lindex $lcs_data($l) 2]
					switch $type {
						Cartesian - R - Rectangular { set type cartesian }
						Cylindrical - C             { set type cylindrical }
						Spherical   - S             { set type spherical }
					}
					if {$type=="cartesian"} {
						set lcs [lindex $lcs_data($l) 0]
					} else {
						mess "Warning: Forces/Moments in $type coordinate system for Part $fam " red
						mess "converted to global coordinate system.\n" red
					}
					break
				}
			}
		}
	}
	
	set scale 1.0
	if {[info exists vals(scale)]} {
		if {$vals(scale)!=""} {set scale $vals(scale)}
	}

    foreach {t dir} {FX 1 FY 2 FZ 3 MX 5 MY 6 MZ 7} {
	if {[info exists vals($t)]} {
		if {$vals($t)==""} {set vals($t) 0.0}
		if {[expr double($vals($t))]==0.0} continue
		if $nsid {
#	add node set bc...
		  puts $fp "\"$fam\" \"NODE_SET_ID\" $nsid"
		  if ![info exists lsdyna_param_arrays(set_bc:fid$nsid)] {
#	add parameter set bc
			set sbc(title) "*LOAD_NODE_SET"
			set sbc(id) $nsid
			set sbc(type) 0
			set sbc(nc) 1
			for {set i 1} {$i<4} {incr i} {
				for {set j 1} {$j<9} {incr j} {
					set sbc(card$i/f$j) ""
				}
			}
			set sbc(card1/f1) $nsid
			set sbc(card1/f2) $dir
			set sbc(card1/f3) 3
			set sbc(card1/f4) [expr $scale*$vals($t)]
			set sbc(card1/f5) $lcs
			set lsdyna_param_arrays(set_bc:fid$nsid) [array get sbc]
		  }
		} else {
		puts $fp "\"$fam\" \"LOAD\" 6 1 $dir 3 [expr $scale*$vals($t)] $lcs"
		}
    }
	}
# don't know how to handle loadSet.
}

# 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_lsdyna_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 scale 1.0
	if {[info exists vals(scale)]} {
		if {$vals(scale)!=""} {set scale $vals(scale)}
	}

	if {[info exists vals(pres)]} {
		if {$vals(pres)==""} {set vals(pres) 0.0}
		if {[expr double($vals(pres))]==0.0} return
		set etype 2
		if {[writeNastranDEZ get lsdyna_shell]=="Defined"} {
		set bcs [ic_boco_get $fam]
	    set shell_data [aie_parse_bcs_element_prop_2d $bcs]
	    if {$shell_data == ""} {
			set etype 4
		}
		} elseif {[writeNastranDEZ get lsdyna_shell]=="None"} {
			set etype 4
		}
		puts $fp "\"$fam\" \"LOAD\" $etype 1 0.0 2 [expr $scale*$vals(pres)]"
	}

# don't know how to handle loadSet.
}

# Temperature - data can be: loadSet temp lsdyna_nsid

proc aie_write_lsdyna_bc_temperature {fp fam data} {
	global lsdyna_param_arrays
    foreach {n v} $data { set vals($n) $v }
    
	if [info exists vals(lsdyna_nsid)] {
		set nsid $vals(lsdyna_nsid)
		if {$nsid=="" || $nsid<0} {
			set nsid 0
		}
	} else {
		set nsid 0
	}
	
	if {[info exists vals(temp)]} {
	if {$vals(temp)==""} {set vals(temp) 0.0}
	if $nsid {
#	add node set bc...
	  puts $fp "\"$fam\" \"NODE_SET_ID\" $nsid"
	  if ![info exists lsdyna_param_arrays(set_bc:tid$nsid)] {
#	add parameter set bc
		set sbc(title) "*LOAD_THERMAL_CONSTANT"
		set sbc(id) $nsid
		set sbc(type) 0
		set sbc(nc) 2
		for {set i 1} {$i<4} {incr i} {
			for {set j 1} {$j<9} {incr j} {
				set sbc(card$i/f$j) ""
			}
		}
		set sbc(card1/f1) $nsid
		set sbc(card2/f1) $vals(temp)
		set lsdyna_param_arrays(set_bc:tid$nsid) [array get sbc]
	  }
	} else {
	    puts $fp "\"$fam\" \"LOAD\" 8 1 0 0 $vals(temp) 0.0"
	}
	}

# don't know how to handle loadSet.
}

# 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 lsdyna_mat_type lsdyna_beam_type
# "Rigid beam"     indep_dof_cna indep_dof_cnb dep_dof_cna dep_dof_cnb lsdyna_mat_type
#                  beam_type_index dep_dofs weight indep_dofs lsdyna_mat_type
# "Rod connection" pid mat area torsconst torscoeff nsm lsdyna_mat_type
# "Damper connection"	pid force_per_vel component_c1 component_c2 lsdyna_mat_type
# "Spring"         pid stiff damp stress component_c1 component_c2 lsdyna_mat_type
# "Viscous damper" pid damp_ext damp_rot lsdyna_mat_type
# "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 
# "Beam"           pid mat bar_a bar_i1 bar_i2 bar_i12 bar_j lsdyna_mat_type lsdyna_beam_type
#"Beam Cross-Section"	pid mat group beamcs_type beam_type_option nsm_length_a nsm_length_b so_b_option dim dims lsdyna_mat_type lsdyna_beam_type

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

proc aie_write_lsdyna_bc_element_prop {fp fam data} {
	global lsdyna_param_arrays lsdyna_pid_unique
	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"
	}
    
	if ![info exists vals(lsdyna_mat_type)] {
		set lsdyna_mat_type 0
	} else {
		set lsdyna_mat_type $vals(lsdyna_mat_type)
	}

	if ![info exists vals(lsdyna_beam_type)] {
		set lsdyna_beam_type 0
	} else {
		set lsdyna_beam_type $vals(lsdyna_beam_type)
	}

	set pid 0
	if [info exists vals(pid)] {
		if {$vals(pid)!=""} {set pid $vals(pid)}
	}
#puts "Family: $fam, PID=$pid"

	if [info exists vals(etype)] {
#mess "family: $fam\n"
#mess "vals: [array get vals]\n"
		switch $vals(etype) {
		Volume {
			if !$pid {
				set ename $spbug
			} else {
				set ename $vals(etype)_PID_$pid
			}
			
#			puts $fp "\"$fam\" \"ELEMENT3D\" \"$spbug\""
			puts $fp "\"$fam\" \"ELEMENT3D\" \"$ename\""
			if [info exists lsdyna_param_arrays(elem3d:$ename)] return

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

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

			set upid 0
			if {[info exists lsdyna_pid_unique($pid)] && $lsdyna_pid_unique($pid)} {set upid $pid}
			lsdyna_add_element_solid $fam $vals(mat) $ename $upid
    	}
		Shell -
		Shear {
			if !$pid {
				set ename $spbug
			} else {
				set ename $vals(etype)_PID_$pid
			}
			
#			puts $fp "\"$fam\" \"ELEMENT2D\" \"$spbug\""
			puts $fp "\"$fam\" \"ELEMENT2D\" \"$ename\""
			if [info exists lsdyna_param_arrays(elem2d:$ename)] return
			array set section {
				thk 0.0
				marea 0.0
				shrf 0.0
			}

			if {[info exists vals(thick)] && $vals(thick)!=""} {
				set section(thk) $vals(thick)
			} elseif {[info exists vals(m_thick)] && $vals(m_thick)!=""} {
				set section(thk) $vals(m_thick)
			}

			if {[info exists vals(nsm)] && $vals(nsm)!=""} {
				set section(marea) $vals(nsm)
			}

			if {[info exists vals(b_stiff)] && $vals(b_stiff)!=""} {
				if {[expr double($vals(b_stiff))]!=1.0} {
					mess "ignoring bending thickness ratio for LS-Dyna shell element.\n"
				}
			}

			if {[info exists vals(t_stiff)] && $vals(t_stiff)!=""} {
				set section(shrf) $vals(t_stiff)
			}

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

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

			set upid 0
			if {[info exists lsdyna_pid_unique($pid)] && $lsdyna_pid_unique($pid)} {set upid $pid}
			lsdyna_add_element_shell $fam $vals(mat) section $ename $upid
		}
		"Beam Cross-Section" {
			set formul 1
			set formul [expr $lsdyna_beam_type+1]
			if {$formul==6} {
# seatbelts
				set formul 11
			}
			if {$formul!=3 && $formul!=11} {
				puts $fp "\"$fam\" \"BORIENT\" $vals(bar_x1) $vals(bar_x2) $vals(bar_x3) 0"
			}

			if !$pid {
				set ename $spbug
			} else {
				regsub -all " " $vals(etype) _ vet
				set ename ${vet}_PID_$pid
			}
			
			puts $fp "\"$fam\" \"ELEMENT1D\" \"$ename\""
			if [info exists lsdyna_param_arrays(elem1d:$ename)] return
			array set sec_beam {
				scoor 0
				f1 0.0
				f2 0.0
				f3 0.0
				f4 0.0
			}
			set sec_beam(formul) $formul
			set nsm 0.0
			if {[info exists vals(nsm_length_a)] && $vals(nsm_length_a)!=""} {
				set nsm $vals(nsm_length_a)
			}
			if [info exists vals(nsm_length_b)] {
			if {$vals(nsm_length_b)!=""} {
				set nsm [expr ($nsm+$vals(nsm_length_b))/2.0]
			} else {
				set nsm [expr $nsm/2.0]
			}
			}
			set sec_beam(nsm) $nsm
			
			set area 0.0
			set i1 0.0
			set i2 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 area [expr $area + $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 area [expr $area + $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 area [expr $area + $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 area [expr $area + 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 area [expr $area + $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 area [expr $area + $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 area [expr $area + $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 area [expr $area + ($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 area [expr $area + $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 area [expr $area + 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]
				}  
			}
			}

			switch $formul {
			2 - 3 { 
				set sec_beam(f1) $area
				set sec_beam(f2) $i1
				set sec_beam(f3) $i2
			}
			1 - 4 - 5 {
				set h 0.0
				set b 0.0
				if $area {set h [expr sqrt($i1*12.0/$area)]}
				if $area {set b [expr sqrt($i2*12.0/$area)]}
				set sec_beam(f1) $h
				set sec_beam(f2) $h
				set sec_beam(f3) $b
				set sec_beam(f4) $b
				mess "converting to type $formul rectangular beam with given area.\n"
# non-uniform & non-rectangular sections to be supported later...
			}
			}
			
			set arr elem1d:$ename
			set ${arr}(name) $ename
			set upid 0
			if {[info exists lsdyna_pid_unique($pid)] && $lsdyna_pid_unique($pid)} {set upid $pid}
			set ${arr}(pid) $upid
			set ${arr}(rt) 0
			set ${arr}(rr) 0
			set ${arr}(rt1) 0
			set ${arr}(rr1) 0
			
			lsdyna_add_element_beam $fam $vals(mat) sec_beam $arr $lsdyna_mat_type
		}
		Beam -
		Bar {
# set beam formulation & write orientations to fbc if formulation is other than truss
#			set form_list_id [setupNastranRunDEZ get lsdynaFormBeamVal]
#			if {$form_list_id==""} { set form_list_id 0 }
			set formul 1
#			switch $form_list_id {
#				0 { set formul 1 } 1 { set formul 2 } 2 { set formul 3 }
#				default { set form_list_id 0 }
#			}
# new switch for partwise formulation
			set formul [expr $lsdyna_beam_type+1]
			if {$formul==6} {
# seatbelts
				set formul 11
			}
			if {$formul!=3 && $formul!=11} {
			    set put_it 0
			    foreach v "bar_wa1 bar_wa2 bar_wa3 bar_wb1 bar_wb2 bar_wb3" {
			        if {$vals($v) != 0} {
			            set put_it 1
			            break
			        }
			    }
			    if $put_it {
			        puts $fp "\"$fam\" \"BORIENT\" $vals(bar_x1) $vals(bar_x2) $vals(bar_x3) 0 1 $vals(bar_wa1) $vals(bar_wa2) $vals(bar_wa3) $vals(bar_wb1) $vals(bar_wb2) $vals(bar_wb3)"
			    } else {
				    puts $fp "\"$fam\" \"BORIENT\" $vals(bar_x1) $vals(bar_x2) $vals(bar_x3) 0"
				}
			}

			if !$pid {
				set ename $spbug
			} else {
				set ename $vals(etype)_PID_$pid
			}
			
#			puts $fp "\"$fam\" \"ELEMENT1D\" \"$spbug\""
			puts $fp "\"$fam\" \"ELEMENT1D\" \"$ename\""
			if [info exists lsdyna_param_arrays(elem1d:$ename)] return
			array set sec_beam {
				scoor 0
				nsm 0.0
				f1 0.0
				f2 0.0
				f3 0.0
				f4 0.0
			}
			set sec_beam(formul) $formul

			set area 0.0
			set i1 0.0
			set i2 0.0
			if {[info exists vals(bar_a)] && $vals(bar_a)!=""} {
				set area $vals(bar_a)
			}
			if {[info exists vals(bar_i1)] && $vals(bar_i1)!=""} {
				set i1 $vals(bar_i1)
			}
			if {[info exists vals(bar_i2)] && $vals(bar_i2)!=""} {
				set i2 $vals(bar_i2)
			}

			switch $formul {
			2 - 3 { 
				set sec_beam(f1) $area
				set sec_beam(f2) $i1
				set sec_beam(f3) $i2
			}
			1 - 4 - 5 {
				set h 0.0
				set b 0.0
				set area 
				if $area {set h [expr sqrt($i1*12.0/$area)]}
				if $area {set b [expr sqrt($i2*12.0/$area)]}
				set sec_beam(f1) $h
				set sec_beam(f2) $h
				set sec_beam(f3) $b
				set sec_beam(f4) $b
				mess "converting to type $formul rectangular beam with given area.\n"
			}
			}
			
			if {[info exists vals(bar_j)] && $vals(bar_j)!=""} {
				mess "ignoring torsional constant for LS-Dyna beam element.\n"
			}

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

#			set arr elem1d:$spbug
#			set ${arr}(name) $spbug
			set arr elem1d:$ename
			set ${arr}(name) $ename
			set upid 0
			if {[info exists lsdyna_pid_unique($pid)] && $lsdyna_pid_unique($pid)} {set upid $pid}
			set ${arr}(pid) $upid
#			set ${arr}(n3) "$vals(bar_x1) $vals(bar_x2) $vals(bar_x3)"
			set ${arr}(rt) 0
			set ${arr}(rr) 0
			set ${arr}(rt1) 0
			set ${arr}(rr1) 0
			
			lsdyna_add_element_beam $fam $vals(mat) sec_beam $arr $lsdyna_mat_type
		}
		"Rigid beam" {
			switch $vals(beam_type_index) {
			0 { mess "Conversion of rigid beam type RBAR not yet supported.\n" }
			3 {
# the case for beam_type_index=3 is really meant for RBARs(beam_type_index=0).
# to be enabled later in AI*1.1 after fixing lsdyna interface for RBARs..
				set dof1 0
				if {[info exists vals(dep_dof_cna)] && $vals(dep_dof_cna)!=""} {
					set dof1 [lsdyna_get_DOF $vals(dep_dof_cna)]
				}
				set dof2 0
				if {[info exists vals(dep_dof_cnb)] && $vals(dep_dof_cnb)!=""} {
					set dof2 [lsdyna_get_DOF $vals(dep_dof_cnb)]
				}
				set dof 0
				if {!($dof1 || $dof2)} {
					mess "Deriving dependant DOF's for RBAR element for part $fam...\n"
					set dof3 0
					if {[info exists vals(indep_dof_cna)] && $vals(indep_dof_cna)!=""} {
						set dof3 [lsdyna_get_DOF $vals(indep_dof_cna)]
					}
					set dof4 0
					if {[info exists vals(indep_dof_cnb)] && $vals(indep_dof_cnb)!=""} {
						set dof4 [lsdyna_get_DOF $vals(indep_dof_cnb)]
					}
					set dof5 [lsdyna_combine_DOF $dof3 $dof4]
					switch $dof5 {
						# invert...
						1 {set dof 5}
						2 {set dof 6}
						3 {set dof 4}
						4 {set dof 3}
						5 {set dof 1}
						6 {set dof 2}
					}
				} else {
					set dof [lsdyna_combine_DOF $dof1 $dof2]
				}

				if !$dof {
					mess "No valid dependant DOF's found for RBAR element for part $fam.\n\
							Skipping conversion.\n"
					return
				}
			
				puts $fp "\"$fam\" \"CONSTRAINED\" 2 \"\" $dof 1.0E+20 0 0 1 0 0 0 0 0 0 0 0 0 0"
			}
			1 {
				set dof ""
				if {[info exists vals(dep_dofs)] && $vals(dep_dofs)!=""} {
					set dof [lsdyna_get_DOF $vals(dep_dofs)]
				}
				if {$dof==""} {
					mess "Warning: No valid dependant DOF's found for RBE2 element for part $fam.\n" red
					set dof "0 0"
				}
			
#redefined conversion to constrained nodal rigid body
				puts $fp "\"$fam\" \"CONSTRAINED\" 11 0 0 0 -[lindex $dof 0] -[lindex $dof 1]"

			}
			2 { 
				set dof1 0
				if {[info exists vals(dep_dofs)] && $vals(dep_dofs)!=""} {
					set dof1 $vals(dep_dofs)
				}
				set dof2 0
				if {[info exists vals(indep_dofs)] && $vals(indep_dofs)!=""} {
					set dof2 $vals(indep_dofs)
				}
				if {[info exists vals(weight)] && $vals(weight)!=1} {
					mess "Warning: Using default unity weights for RBE3 element for part $fam...\n" red
				}
				puts $fp "\"$fam\" \"CONSTRAINED\" 13 \"\" $dof1 $dof2 0 0 1 0 0 0 0 0 0 0 0 0 0"
			}
			default { mess "Error: unrecognized rigid beam type $vals(beam_type_index)\n" }
			}
			
		}
		Spring -
		"Damper connection" -
		"Viscous damper" {
			if !$pid {
				set ename $spbug
			} else {
				regsub -all " " $vals(etype) _ vet
				set ename ${vet}_PID_$pid
			}
			
#			puts $fp "\"$fam\" \"ELEMENT1D\" \"$spbug\""
			puts $fp "\"$fam\" \"ELEMENT1D\" \"$ename\""
			if [info exists lsdyna_param_arrays(elem1d:$ename)] return
			array set sec_beam {
				formul 6
				scoor 2
				nsm 0.0
				f1 1.0
				f2 1.0
				f3 0.0
				f4 0.0
			}

#			set arr elem1d:$spbug
#			set ${arr}(name) $spbug
			set arr elem1d:$ename
			set ${arr}(name) $ename
			set upid 0
			if {[info exists lsdyna_pid_unique($pid)] && $lsdyna_pid_unique($pid)} {set upid $pid}
			set ${arr}(pid) $upid
			set ${arr}(rt) 7
			set ${arr}(rr) 7
			set ${arr}(rt1) 7
			set ${arr}(rr1) 7
			
			switch $lsdyna_mat_type {
				1 { set damp card1/f5 }
				0 -
				default { set damp card2/f1 }
			}

			if {[info exists vals(stiff)] && $vals(stiff)!=""} {
				set ${arr}(card1/f3) $vals(stiff)
			}

			if {[info exists vals(damp)] && $vals(damp)!=""} {
				set ${arr}($damp) $vals(damp)
			} elseif {[info exists vals(damp_ext)] && $vals(damp_ext)!=""} {
				set ${arr}($damp) $vals(damp_ext)
			} elseif {[info exists vals(force_per_vel)] && $vals(force_per_vel)!=""} {
				set ${arr}($damp) $vals(force_per_vel)
			}

			if !$lsdyna_mat_type {
			if {[info exists vals(damp_rot)] && $vals(damp_rot)!=""} {
				set ${arr}(card2/f4) $vals(damp_rot)
			}
			}

			if {[info exists vals(stress)] && $vals(stress)!=""} {
				mess "ignoring stress coefficient for LS-Dyna discrete beam element.\n"
			}

# set material defaults for card2.
			for {set n 1} {$n<=8} {incr n} {
				if ![info exists ${arr}(card2/f$n)] { set ${arr}(card2/f$n) 0.0 }
			}

			lsdyna_add_element_beam $fam $vals(mat) sec_beam $arr $lsdyna_mat_type
    	}
		"Mass point" {
			puts $fp "\"$fam\" \"ELEMENT0D\" \"$spbug\""
			lsdyna_add_element_mass $fam $vals(mass)
    	}
		default { 
			mess "Conversion of element type $vals(etype) not yet supported.\n" 
		}
		}
	}
}


proc lsdyna_get_DOF {dof} {
	regsub -all " " $dof "" dof
	if {$dof==""} {return ""}
# parameter dof is Nastran-style series of numbers from 1-6.
	if ![regexp {^[1-6]+} $dof] { 
		mess "Error: Incorrect Nastran DOF format \"$dof\"\n"
		return ""
	}
	
	set len [string length $dof]
	set x 0; set y 0; set z 0; set rx 0; set ry 0; set rz 0
	for {set n 0} {$n<$len} {incr n} {
		set d [string index $dof $n]
		switch $d {
			1 {set x 1}
			2 {set y 2}
			3 {set z 4}
			4 {set rx 1}
			5 {set ry 2}
			6 {set rz 4}
			" " {}
		}
	}
	array set or2l { 1 1 2 2 3 4 4 3 5 6 6 5 7 7 }
	set ret1 [expr $x|$y|$z]
	if $ret1 {
		set ret1 $or2l($ret1)
	}
	set ret2 [expr $rx|$ry|$rz]
	if $ret2 {
		set ret2 $or2l($ret2)
	}
	return "$ret1 $ret2"
}


proc lsdyna_combine_DOF {dof1 dof2} {
	array set l2or { 1 1 2 2 3 4 4 3 5 6 6 5 7 7 }
	
	set bit1 {0 0 0}
	if {!($dof1<1 || $dof1>7)} {
		set bit1 [lsdyna_get_xyz_bits $l2or($dof1)]
	}
	
	set bit2 {0 0 0}
	if {!($dof2<1 || $dof2>7)} {
		set bit2 [lsdyna_get_xyz_bits $l2or($dof2)]
	}
	
	set dof 0
	foreach b1 $bit1 b2 $bit2 {
		set dof [expr $dof|$b1|$b2]
	}
	
	if $dof {set dof $l2or($dof)}
	return $dof
}

proc lsdyna_get_xyz_bits {b} {
	set ret ""
	foreach xyz {1 2 4} {
		lappend ret [expr $xyz & $b]
	}
	return $ret
}
		
proc lsdyna_add_element_solid {fam mat ename pid} {
	global lsdyna_param_arrays
	if {$fam==""} return
	if {$mat==""} {
		mess "Error: Please specify material for volume family $fam\n" red
		return
	}
# mess "fam= $fam, mat=$mat\n"

	regsub -all : $fam _ spbug
	regsub -all / $spbug __ spbug
#	set arr elem3d:$spbug
	set arr elem3d:$ename

#	set ${arr}(name) $spbug
	set ${arr}(name) $ename
# Only Solid element formulation
	set ${arr}(pid) $pid
	set ${arr}(formul) 0
#	set ${arr}(mat_def) 0
	set ${arr}(mat_def) 1
	set ${arr}(mat_name) $mat

# set default section data
	set ${arr}(sec_solid/id) -1
	set ${arr}(sec_solid/opt) 0
	set ${arr}(sec_solid/formul) 1
	set ${arr}(sec_solid/aet) 4
	
# mess "volume element $arr: [array get $arr]\n"
   	set lsdyna_param_arrays($arr) [array get $arr]
}

proc lsdyna_add_element_shell {fam mat section ename pid} {
	global lsdyna_param_arrays
	if {$fam==""} return
	if {$mat==""} {
		mess "Error: Please specify material for surface family $fam\n" red
		return
	}
#mess "adding shell element for family $fam, material=$mat\n"
	upvar $section sec

	regsub -all : $fam _ spbug
	regsub -all / $spbug __ spbug
#	set arr elem2d:$spbug
	set arr elem2d:$ename
	
#	set ${arr}(name) $spbug
	set ${arr}(name) $ename
# Only Shell element formulation
	set ${arr}(pid) $pid
	set ${arr}(physics) 0
	set ${arr}(formul) 1
	set ${arr}(formul2) 12
#	set ${arr}(mat_def) 0
	set ${arr}(mat_def) 1
	set ${arr}(mat_name) $mat

# set default section data
	set ${arr}(sec_shell/id) -1
	set ${arr}(sec_shell/opt) 0
#	set ${arr}(sec_shell/formul) 0
	set ${arr}(sec_shell/nip) 0
	set ${arr}(sec_shell/propt) 1
	set ${arr}(sec_shell/qr) 0
	set ${arr}(sec_shell/icomp) 0
	set ${arr}(sec_shell/nloc) 0
	
# set user-specified section data
	foreach p [array names sec] {
		set ${arr}(sec_shell/$p) $sec($p)
	}
	
#mess "shell element $arr: [array get $arr]\n"
   	set lsdyna_param_arrays($arr) [array get $arr]
}

proc lsdyna_add_element_beam {fam mat section element_node mat_list_id} {
	global lsdyna_param_arrays
	if {$fam==""} return
	if {$mat==""} {
		mess "Warning: Material not specified for line family $fam\n" red
# user warned, rather than returning giving error. needed for springs & dampers.
#		return
	}
# mess "adding beam element for family $fam, material=$mat\n"
	upvar $element_node arr
	upvar $section sec
	set formul $sec(formul)

#	regsub -all : $fam _ spbug
#	set arr elem1d:$spbug
	
#	set ${arr}(name) $fam
	set arr(formul) $formul
	set arr(mat_def) 0

#	set ${arr}(rt) 0
#	set ${arr}(rr) 0
	set arr(cs) 2
# following are needed for Springs & Dampers, but still needed for write_Elements.C
	set arr(sf) 1.0
	set arr(pf) 0
	set arr(of) 0.0
	set arr(slen) 0.0

# Currently only Type 66 material - *MAT_LINEAR_ELASTIC_DISCRETE_BEAM for discretes; more options later
	switch $formul {
		1 - 2 - 3 - 4 - 5 - 11 { 
			set arr(mat_def) 1
			set arr(mat_name) $mat
		}
		6 { 
			set mat_type 66
			switch $mat_list_id {
				0 { set mat_type 66 } 1 { set mat_type 74 }
			}
			set arr(mat6) $mat_type 
			lsdyna_add_material $mat_type $mat arr
		}
	}
	
# set default section data
	set arr(sec_beam/id) -1
#	set ${arr}(sec_beam/formul) 1
	set arr(sec_beam/shrf) 1.0
	set arr(sec_beam/qr) 2
	set arr(sec_beam/cst) 0
#	set ${arr}(sec_beam/scoor) 0
	for {set n 5} {$n<=8} {incr n} {
		set arr(sec_beam/f$n) 0.0
	}
	
# set user-specified section data
	foreach p [array names sec] {
		set arr(sec_beam/$p) $sec($p)
	}
	
# mess "beam element $arr: [array get $arr]\n"
   	set lsdyna_param_arrays($element_node) [array get arr]
}

	
proc lsdyna_add_element_mass {fam mass} {
	global lsdyna_param_arrays
	if {$fam==""} return
# mess "fam= $fam\n"

	regsub -all : $fam _ spbug
	regsub -all / $spbug __ spbug
	set arr elem0d:$spbug

	set ${arr}(name) $spbug
# Only Lumped mass element formulation
	set ${arr}(formul) 0
	set ${arr}(mat_def) 0
	set ${arr}(mass) $mass
# following are needed for Inertia & SPH particles, but still needed for write_Elements.C
	set ${arr}(csid) 0
	set ${arr}(ixx) 0.0
	set ${arr}(ixy) 0.0
	set ${arr}(ixz) 0.0
	set ${arr}(iyy) 0.0
	set ${arr}(iyz) 0.0
	set ${arr}(izz) 0.0
	
# mess "mass element $arr: [array get $arr]\n"
   	set lsdyna_param_arrays($arr) [array get $arr]
}

proc lsdyna_get_material_card_data { type } {
# aie material_data_order = { ID    E    G    PR   RO    ALPHA REF_TEMP DAMP }
	set ret ""
	switch -exact $type {
		1 { lappend ret "1,1 1,3 0,0 1,4 1,2  0,0  0,0    0,0" }
	}
	return $ret
}

proc lsdyna_get_material_property_names {} {
    return {
	"Material ID" "Young's Modulus" "Shear Modulus" "Poisson's Ratio" "Density" \
	"Thermal Expansion Coefficient" "Reference Temperature" "Damping Coefficient"
    }
}

proc lsdyna_add_material {type mat element_node} {
	global material_data material_dpnd_data material_tbl_type material_tbl_data material_type
	upvar $element_node arr

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

# aie material_data_order = { ID E G PR RO ALPHA REFT DAMP }
	set card1_sequence ""
	set mdata ""
	set dpnd ""
	set mt 0
	if {$mat!=""} {
		set mdata $material_data($mat)
		set dpnd $material_dpnd_data($mat)
		set mt [lindex $material_type($mat) 0]
	}

	if $mt {
		if {$mt==3} {
#			mess "Orthotropic material properties not yet supported($mat).\n"
		} else {
#			mess "Anisotropic material properties not yet supported($mat).\n"
		}
	}
			
	switch $type {
		 1 - 201 -  3 - 18 - 19 -  20 -  24 -  28 - 30 -
		52 -  64 - 81 - 96 - 112 - 123 - 124 { set card1_sequence "1 3 0 4 2 0 0 0" }
		63 { set card1_sequence "1 3 0 4 2 0 0 7" }
		5 - 7 - 10 - 210 - 12 - 14 { set card1_sequence "1 0 3 0 2 0 0 0" }
		6 { set card1_sequence "1 0 0 0 2 0 0 0" }
		8 { set card1_sequence "1 0 7 0 2 0 0 0" }
		9 { set card1_sequence "1 7 0 8 2 0 0 0" }
		15 { set card1_sequence "1 4 3 5 2 0 0 0" }
		27 - 31 { set card1_sequence "1 0 0 3 2 0 0 0" }
		53 { set card1_sequence "1 3 0 0 2 0 0 0" }
		57 { set card1_sequence "1 3 8 0 2 0 0 0" }
		66 - 74 { set card1_sequence "1 9 9 9 2 9 9 9" }
	}
#mess "$element_node - type: $type, card1_sequence: $card1_sequence\n" red
	foreach n $card1_sequence v $mdata d $dpnd p [lsdyna_get_material_property_names] {
		if {$n==""} break
		if $mt {
			set arr(card1/f$n) 0.0
			continue
		}
		set val 0.0
		if {$v==""} { 
			if {$n==2} {
#				mess "assuming small value for unspecified density.\n"
#				set val 1.0E-29
				set val [setupNastranRunDEZ get lsdyna_rho]
				if {$val==""} {set val 0.0}
			}
		} else {
			set val $v
		}
		if {$n==2} { set val [expr $val*$wtmass] }
		if !$n {
#			if {$v!=""&&$v!=0.0} {mess "Material $mat: Property $p not yet supported.\n"}
		} elseif {$n>1} {
			if {$n==3} {
				if [info exists arr(mat0)] {
					if {$d!=""} {
						set t $material_tbl_type($d)
						if {$t==1} {
							switch -exact $type {
								24 - 81 - 112 - 123 {}
								default {set arr(mat0) 24}
							}
							for {set i 1} {$i<9} {incr i} {
								set arr(card3/f$i) 0.0
								set arr(card4/f$i) 0.0
							}
							set data $material_tbl_data($d)
							set ctr [lindex $data 1]
							set xy [lindex [lindex $data 2] 1]
							set xy [lrange $xy 1 end]
							set i 1
							foreach {x y} $xy {
								set arr(card3/f$i) $x
								set arr(card4/f$i) $y
								incr i
								if {$i>8} break
							}
						} else {
#							mess "Temperature dependence not supported for $p\n"
						}
					}
				}
			} elseif {$n<9} {
				if {$d!=""} {
#					mess "Only constant values supported for $p\n"
				}
			}
		}
# added checks for temperature dependence and nonlinear properties.
		set arr(card1/f$n) $val
	}
# unset null setting
	catch { unset arr(card1/f0) }
# unset dummy setting for f9
	catch { unset arr(card1/f9) }
# set auto-mid
	set arr(card1/f1) -1
if 0 {
# set SIGY & FAIL parameters for material type 24
	if {$type==24} {
		if [regexp ^elem3d $element_node] {
			set arr(card1/f5) [setupNastranRunDEZ get solid_sigy]
			set arr(card1/f7) [setupNastranRunDEZ get solid_fail]
		} elseif [regexp ^elem2d $element_node] {
			set arr(card1/f5) [setupNastranRunDEZ get shell_sigy]
			set arr(card1/f7) [setupNastranRunDEZ get shell_fail]
		}
	}
}
# set material defaults for card1.
	for {set n 1} {$n<=8} {incr n} {
		if { ![info exists arr(card1/f$n)] || $arr(card1/f$n)=="" } { 
			set arr(card1/f$n) 0.0 
		}
	}

	if {$type==24} {
	if {[lsearch -regexp [array names arr] card3]==-1} {
#	mess "setting steel properties for cards 3 & 4 for material type 24.\n"
# add card 3/4 defaults for steel for type 24..
	array set card3 {f1 0.0 f2 0.004 f3 0.03 f4 0.15 f5 0.3 f6 0.4 f7 10 f8 0.0}
	array set card4 {f1 0.0 f2 215 f3 300 f4 390 f5 440 f6 460 f7 400 f8 0.0}
	foreach f [array names card3] { set arr(card3/$f) $card3($f) }
	foreach f [array names card4] { set arr(card4/$f) $card4($f) }
	}
	}
	return
}
	

proc lsdyna_add_materials {} {
	global material_data lsdyna_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}

	foreach mat [array names material_data] {
	
	catch {unset mat_data}
	set mat_data(name) $mat
	set mid [lindex $material_data($mat) 0]
	set mat_data(id) $mid
	set mat_data(type) 1
	for {set c 1} {$c<3} {incr c} {
		for {set i 1} {$i<9} {incr i} {
			set mat_data(card$c/f$i) 0.0
		}
	}

	set mt [lindex $material_type($mat) 0]
	if $mt {
		if {$mt==3} {
			set type 2
			set tropic Orthotropic_Shell
			set seq [list 7 1 2 3 4 5 6]
		} elseif {$mt==2} {
			set type 202
			set tropic Anisotropic_Solid
			set seq [list 22 1 2 7 3 8 12 4 9 13 16 5 10 14 17 19 6 11 15 18 20 21]
		} elseif {$mt==1} {
			set type 202
			set tropic Anisotropic_Shell
			set seq [list 7 1 2 4 -1 -1 -1 3 5 -1 6 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1]
		} else {
			mess "Nastran material type $mt not yet supported($mat).\n"
			mess "Assigning LS-Dyna material type 1...\n"
			for {set c 3} {$c<7} {incr c} {
				for {set i 1} {$i<9} {incr i} {
					set mat_data(card$c/f$i) 0.0
				}
			}
			set mat_data(card1/f1) -1
			set lsdyna_param_arrays(mat_data:$mat) [array get mat_data]
			continue
		}
	} else {
		set mlist [list 1 201 3 5 6 7 8 9 10 210 12 14 15 18 19 20 24 27 28 30 31 38 52 53 57 63 64 73 81 96 112 123 124 140 401]
		set lid [lindex $material_data($mat) 12]
		if {$lid==""} {set lid 0}
		set type [lindex $mlist $lid]
		if {$type==""} {set type 1}
		set tropic Isotropic
		set seq [list 4 1 3 5 2 7]
	}
	
#puts "material type $type, Tropic $tropic, sequence $seq"
	set mat_data(type) $type

	switch -exact $type {
		 1 - 201 -  3 - 18 - 19 -  20 -  24 -  28 - 30 - 
		52 -  63 - 64 - 81 - 96 - 112 - 123 - 124
		{set cards {1/f2 1/f3 1/f4}}
		 5 - 6 - 7 - 8 - 10 - 210 - 12 - 14 - 38
		{set cards {1/f2 "" ""}}
		9 {set cards {1/f2 1/f7 1/f8}}
		15 {set cards {1/f2 1/f4 1/f5 "" 1/f3}}
		27 - 31 {set cards {1/f2 "" 1/f3}}
		53 - 57 - 73 {set cards {1/f2 1/f3 ""}}
		140 {set cards ""}
		2 {set cards {1/f2 1/f3 1/f4 1/f6 2/f1 2/f2 2/f3}}
		202 {set cards {
				1/f2 1/f3 1/f4 1/f5 1/f6 1/f7 1/f8 \
				2/f1 2/f2 2/f3 2/f4 2/f5 2/f6 2/f7 2/f8 \
				3/f1 3/f2 3/f3 3/f4 3/f5 3/f6 3/f7 \
				}
			}
		401 {set cards ""}
	}
	switch -exact $type {
		63 {lappend cards "" "" 1/f7}
		5 - 7 - 10 - 210 - 12 - 14 - 38 {lappend cards "" 1/f3}
		8 {lappend cards "" 1/f7}
		57 - 73 {lappend cards "" "" 1/f8}
	}
	
	set dpnd $material_dpnd_data($mat)
	foreach c $cards pos $seq {
		if {$pos==-1} continue
		set v [lindex $material_data($mat) $pos]
		set p [lindex [aie_material_property_order ${tropic}_Material] $pos]
		set d [lindex $dpnd $pos]
		if {$c==""} {
			if {$v!=""&&$v!=0.0} {mess "Property $p not supported for material id $mid (type $type).\n"}
			continue
		}
		set val 0.0
		if {$v!=""} {
			set val $v
		}
		set mat_data(card$c) $val
		if {$pos==4} { set mat_data(card$c) [expr $val*$wtmass] }
		if {$d!=""} {
			if {$pos==1} {
				set t $material_tbl_type($d)
				if {$t==1} {
					switch -exact $type {
						24 - 81 - 112 - 123 {}
						default {
							mess "Changing Material id $mid type from $type to 24.\n"
							set mat_data(type) 24
						}
					}
					for {set i 1} {$i<9} {incr i} {
						set mat_data(card3/f$i) 0.0
						set mat_data(card4/f$i) 0.0
					}
					set data $material_tbl_data($d)
					set ctr [lindex $data 1]
					set xy [lindex [lindex $data 2] 1]
					set xy [lrange $xy 1 end]
					set i 1
					foreach {x y} $xy {
						set mat_data(card3/f$i) $x
						set mat_data(card4/f$i) $y
						incr i
						if {$i>8} break
					}
				} else {
					mess "Temperature dependence not supported for $p\n"
				}
			} else {
				mess "Only constant values supported for $p\n"
			}
		}
	}
	set mat_data(card1/f1) -1

	if {$type==24} {
	set mat_data(card1/f5) [lindex $material_data($mat) 13]
	set mat_data(card1/f7) [lindex $material_data($mat) 14]
	if {[lsearch -regexp [array names mat_data] card3]==-1} {
	mess "setting steel properties for cards 3 & 4 for material id $mid.\n"
# add card 3/4 defaults for steel for type 24..
	array set card3 {f1 0.0 f2 0.004 f3 0.03 f4 0.15 f5 0.3 f6 0.4 f7 10 f8 0.0}
	array set card4 {f1 0.0 f2 215 f3 300 f4 390 f5 440 f6 460 f7 400 f8 0.0}
	foreach f [array names card3] { set mat_data(card3/$f) $card3($f) }
	foreach f [array names card4] { set mat_data(card4/$f) $card4($f) }
	}
	} elseif {$type==2} {
		if {$mat_data(card1/f3)!=0.0} {
			set mat_data(card1/f6) [expr $mat_data(card1/f6)*$mat_data(card1/f4)/$mat_data(card1/f3)]
		} else {
			mess "Can't calculate minor Poisson's ratio for zero longitudinal Young's Modulus.\n"
			mess "Using major Poisson's ratio for material id $mid (type $type).)\n"
		}
	}
	
	for {set c 3} {$c<7} {incr c} {
		for {set i 1} {$i<9} {incr i} {
			if ![info exists mat_data(card$c/f$i)] {
				set mat_data(card$c/f$i) 0.0
			}
		}
	}

	set lsdyna_param_arrays(mat_data:$mat) [array get mat_data]
	}
}


proc lsdyna_material_property_order {} {
    return {
	ID E G NU
	DENS ALP REFT 
	DAMP SLT SLC SLS MCSID
	TYPE_LIST_ID
    }
}


proc lsdyna_add_LCS {} {
	global lcs_data lsdyna_param_arrays
	array set define $lsdyna_param_arrays(define)
	set id 0
    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 cartesian }
	    Cylindrical - C               { set t cylindrical }
	    Spherical   - S               { set t spherical }
	}
	if {$t!="cartesian"} {
		mess "Warning: $t coordinate system not supported by the solver.\nSkipping $name\n" red
		continue
	}
	if {!($ref == "" || $ref=="Global" || $ref == 0)} {
	    mess "Warning: Can't refer $ref system for LCS \"$name\"\n" red
	}

	set node coord:$name
	set define($node/name) $name
	incr id
	set define($node/id) $number
	set define($node/opt) 0
# Nastran to LS-Dyna LCS conversion
	set define($node/xo) $x1
	set define($node/yo) $y1
	set define($node/zo) $z1
	set zvec [list [expr $x2-$x1] [expr $y2-$y1] [expr $z2-$z1]]
	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($node/xl) [lindex $xvec 0]
	set define($node/yl) [lindex $xvec 1]
	set define($node/zl) [lindex $xvec 2]
#	set define($node/xp) [lindex $xypt 0]
#	set define($node/yp) [lindex $xypt 1]
#	set define($node/zp) [lindex $xypt 2]
	set define($node/xp) [lindex $yvec 0]
	set define($node/yp) [lindex $yvec 1]
	set define($node/zp) [lindex $yvec 2]
	}
   	set lsdyna_param_arrays(define) [array get define]
}

proc lsdyna_set_gravity {} {
	global lsdyna_param_arrays
	set gls [ic_param_list_children :Gravity_Load]
    set ch [lindex $gls 0]
	if {$ch==""} return
	if {[llength $gls]>1} {
		mess "Warning: multiple gravity definitions found. Only gravity [lindex [split $ch /] 1] will be used.\n" red
	}
    array set vals [ic_param_get_values $ch]
	set on 0; set x 0.0; set y 0.0; set z 0.0; set scale 1.0; set cid 0; set sid "" ; set bds -1
    foreach {n1 n2} {
	Create on
	Acceleration_Vector_Component_1 x
	Acceleration_Vector_Component_2 y
	Acceleration_Vector_Component_3 z
	CID cid
	SID sid
	Acceleration_Vector_Scale scale
    } {
	if [info exists vals($n1)] { set $n2 $vals($n1) }
    }
	
	if !$on return

	foreach i {x y z} {
	    set $i [expr [set $i] * $scale]
	}
    
	set n 0
	foreach {i j} {x 1 y 2 z 3} {
		if {[expr double([set $i])]==0.0} continue
		set arr bodyload:bodyload$n
		incr n
		set ${arr}(OPTION1) $j
		set ${arr}(LCID) 2
		set ${arr}(SF) [set $i]
		set ${arr}(LCIDDR) 0
		set ${arr}(XC) 0.0
		set ${arr}(YC) 0.0
		set ${arr}(ZC) 0.0
		set lsdyna_param_arrays($arr) [array get $arr]
	}

	return
}


proc lsdyna_add_parameters {} {
	global lsdyna_params_data lsdyna_param_arrays
	if [info exists lsdyna_params_data] {
		set iid 0
		foreach f [array names lsdyna_params_data] {
			set includes(F1:F1$iid/title) "*INCLUDE"
			set includes(F1:F1$iid/str1) $lsdyna_params_data($f)
			incr iid
		}
   		set lsdyna_param_arrays(custom) [array get includes]
	}
}

#------------------------------------------------------------------------------
# LS-Dyna Contacts...

# Surface-to-Surface contacts - data names can be: name mue mued 
proc unused__aie_write_lsdyna_bc_contact {fp} {
	global lsdyna_param_arrays
	set i 0
	foreach o {1 2 3 5 6 7 8 9 10 11 12 13 14 \
			   15 16 21 22 23 26 27 28 29 31 32} {
		set copt($i) $o
		incr i
	}

    array set slaves [ic_boco_classify_by_bctype CONTACT]
	foreach name [array names slaves] {
	array set masters [ic_boco_classify_by_bctype TARGET_FOR_CONTACT]
	if [info exists masters($name)] {
		set arr1 part_set:${name}_slaves
		set ${arr1}(name) ${name}_slaves
		set i 1
		foreach s $slaves($name) {
			set ${arr1}(fam:fam$i/str) $s
			incr i
		}
		set data [aie_parse_bcs_contact [ic_boco_get $s]]
		if {$data == ""} continue
		set mue 0.3
		set mued 0.1
		set ctype 0
		set auto 0
		set tie 0
		foreach {n v} $data { set $n $v }
		if [info exists copt($ctype)] {
			set ctype $copt($ctype)
		} else {
			mess "Warning: skipping invalid contact type $ctype\n" red
			continue
		}
		set arr2 part_set:${name}_masters
		set ${arr2}(name) ${name}_masters
		set i 1
		foreach m $masters($name) {
			set ${arr2}(fam:fam$i/str) $m
			incr i
		}
	   	set lsdyna_param_arrays($arr1) [array get $arr1]
	   	set lsdyna_param_arrays($arr2) [array get $arr2]
		
		set arr contact:$name
#		set ${arr}(opt) 1
#		set ${arr}(opt1) 5
#		set ${arr}(opt2) 0
		set ${arr}(opt) $ctype
		set ${arr}(opt1) $auto
		set ${arr}(opt2) $tie
		set ${arr}(ssidopt) 1
		set ${arr}(ssid1) 0
		set ${arr}(ssid2) ${name}_slaves
		set ${arr}(msidopt) 1
		set ${arr}(msid1) 0
		set ${arr}(msid2) ${name}_masters
		set ${arr}(sstype) 2
		set ${arr}(mstype) 2
		set ${arr}(sboxid) 0
		set ${arr}(mboxid) 0
		set ${arr}(spr) 1
		set ${arr}(mpr) 1
		set ${arr}(fs) $mue
		set ${arr}(fd) $mued
		set ${arr}(dc) 0.0
		set ${arr}(vc) 0.0
		set ${arr}(vdc) 0.0
		set ${arr}(penchk) 0
		set ${arr}(bt) 0.0
		set ${arr}(dt) 0.0
		set ${arr}(sfs) 1.0
		set ${arr}(sfm) 1.0
		set ${arr}(sst) 1.0
		set ${arr}(mst) 1.0
		set ${arr}(sfst) 1.0
		set ${arr}(sfmt) 1.0
		set ${arr}(fsf) 1.0
		set ${arr}(vsf) 1.0
		set ${arr}(option) 1
		set ${arr}(nfls) 0.0
		set ${arr}(sfls) 0.0
		set ${arr}(ccrit) 0.0
		set ${arr}(kpf) 0.0
		set ${arr}(isym) 0
		set ${arr}(erosop) 0
		set ${arr}(iadj) 0
		set ${arr}(lcid1) 1001
		set ${arr}(lcid2) 1001
		set ${arr}(lcid) 1001
		set ${arr}(fcm) 1
		set ${arr}(us) 0.0
		set ${arr}(nflf) 0.0
		set ${arr}(sflf) 0.0
		set ${arr}(nen) 0.0
		set ${arr}(mes) 0.0
		set ${arr}(nfls1) 0.0
		set ${arr}(sfls1) 0.0
		set ${arr}(tblcid1) 1001
#		set ${arr}() 
	   	set lsdyna_param_arrays($arr) [array get $arr]
		
	} else {
		mess "Warning: No masters found for contact \"$name\"" red
	}
	}
}

# Surface-to-Surface contacts
# Removed single surface types 6,21 & subtype 5 of automatic contact.
# Added types 17,18,19.
proc lsdyna_add_multiple_contacts {} {
	global lsdyna_param_arrays
#delete existing surface-to-surface contacts
	foreach name [array names lsdyna_param_arrays] {
		if [regexp ^contact: $name] {
			array set ctmp $lsdyna_param_arrays($name)
			#spare single surface contacts...
			if !$ctmp(by_elements) continue
#puts "unsetting old surface-to-surface contact node $name"
			unset lsdyna_param_arrays($name)
		}
	}

	set i 0
	foreach o {1 2 3 5 7 8 9 10 11 12 13 14 15 16 \
			   17 18 19 22 23 26 27 28 29 31 32} {
		set copt($i) $o
		incr i
	}

	set i 0
	foreach o {0 1 2 3 4 6 7} {
		set autopt($i) $o
		incr i
	}

#refresh contact data
	foreach c [ic_param_list_children :contact] {
		set name ""
		regsub ^:contact/ $c "" name
		set arr contact:$name
		set ${arr}(name) $name
		set ${arr}(by_elements) 1
		set mue 0.3
		set mued 0.1
		set ctype 0
		set auto -1
		set tie 0
		set sfaces 1
		set mfaces 1
		foreach {n v} [ic_param_get_values $c] { set $n $v }
		if [info exists copt($ctype)] {
			set ctype $copt($ctype)
			if ($ctype==1) {
				if [info exists autopt($auto)] {
					set auto $autopt($auto)
				} else {
					mess "Warning: skipping invalid automatic contact type $auto\n" red
					continue
				}
			}
		} else {
			mess "Warning: skipping invalid contact type $ctype\n" red
			continue
		}

		set ${arr}(opt) $ctype
		set ${arr}(opt1) $auto
		set ${arr}(opt2) $tie
		set ${arr}(fs) $mue
		set ${arr}(fd) $mued
		set ${arr}(ssidopt) 1
		set ${arr}(ssid1) 0
		set ${arr}(ssid2) ""
		set ${arr}(msidopt) 1
		set ${arr}(msid1) 0
		set ${arr}(msid2) ""
		set ${arr}(sstype) 0
		set ${arr}(seg_slave) $sfaces
		switch -exact $ctype {
			1 {
				switch -exact $auto {
					2 {set ${arr}(sstype) 4}
				}
			}
			28 {
				switch -exact $tie {
					0 - 1 {set ${arr}(sstype) 4}
				}
			}
			2 - 5 - 10 - 13 - 14 - 17 - 29 {set ${arr}(sstype) 4}
		}
		set ${arr}(mstype) 0
		set ${arr}(seg_master) $mfaces
		set ${arr}(sboxid) 0
		set ${arr}(mboxid) 0
		set ${arr}(spr) 1
		set ${arr}(mpr) 1
		set ${arr}(dc) 0.0
		set ${arr}(vc) 0.0
		set ${arr}(vdc) 0.0
		set ${arr}(penchk) 0
		set ${arr}(bt) 0.0
		set ${arr}(dt) 0.0
		set ${arr}(sfs) 1.0
		set ${arr}(sfm) 1.0
		set ${arr}(sst) 1.0
		set ${arr}(mst) 1.0
		set ${arr}(sfst) 1.0
		set ${arr}(sfmt) 1.0
		set ${arr}(fsf) 1.0
		set ${arr}(vsf) 1.0
		set ${arr}(option) 1
		set ${arr}(nfls) 0.0
		set ${arr}(sfls) 0.0
		set ${arr}(ccrit) 0.0
		set ${arr}(kpf) 0.0
		set ${arr}(isym) 0
		set ${arr}(erosop) 0
		set ${arr}(iadj) 0
		set ${arr}(lcid1) 4
		set ${arr}(lcid2) 4
		set ${arr}(lcid) 4
		set ${arr}(fcm) 1
		set ${arr}(us) 0.0
		set ${arr}(nflf) 0.0
		set ${arr}(sflf) 0.0
		set ${arr}(nen) 0.0
		set ${arr}(mes) 0.0
		set ${arr}(nfls1) 0.0
		set ${arr}(sfls1) 0.0
		set ${arr}(tblcid1) 4
	   	set lsdyna_param_arrays($arr) [array get $arr]
	}
}

# Single surface contacts
proc aie_write_lsdyna_bcs_single_contact {} {
	global lsdyna_param_arrays
#delete existing single surface contacts
	foreach name [array names lsdyna_param_arrays] {
		if [regexp ^contact: $name] {
			array set ctmp $lsdyna_param_arrays($name)
			#spare multiple surface contacts...
			if $ctmp(by_elements) continue
#puts "unsetting old single surface contact node $name"
			unset lsdyna_param_arrays($name)
		}
	}

    array set slaves [ic_boco_classify_by_bctype CONTACT_SINGLE]
	foreach name [array names slaves] {
		set arr1 part_set:${name}_slaves
		set ${arr1}(name) ${name}_slaves
		set i 1
		foreach s $slaves($name) {
			set ${arr1}(fam:fam$i/str) $s
			incr i
		}
#puts "lastfam $s"
		set data [aie_parse_bcs_singlecontact [ic_boco_get $s]]
#puts "singlecontact $name data: $data"
		if {$data == ""} continue
		set mue 0.3
		set mued 0.1
		set ctype 0
		foreach {n v} $data { set $n $v }
		switch -exact $ctype {
			0 { set opt 1; set opt1 5 }
			1 { set opt 21; set opt1 0 }
			2 { set opt 6; set opt1 0 }
			default {
				mess "Warning: skipping invalid contact type $ctype\n" red
				continue
			}
		}

	   	set lsdyna_param_arrays($arr1) [array get $arr1]
		
		set arr contact:$name
		set ${arr}(name) $name
		set ${arr}(by_elements) 0
		set ${arr}(opt) $opt
		set ${arr}(opt1) $opt1
		set ${arr}(opt2) 0
		set ${arr}(ssidopt) 1
		set ${arr}(ssid1) 0
		set ${arr}(ssid2) ${name}_slaves
		set ${arr}(msidopt) 0
		set ${arr}(msid1) 0
		set ${arr}(msid2) ""
		set ${arr}(sstype) 2
		set ${arr}(mstype) 2
		set ${arr}(sboxid) 0
		set ${arr}(mboxid) 0
		set ${arr}(spr) 1
		set ${arr}(mpr) 1
		set ${arr}(fs) $mue
		set ${arr}(fd) $mued
		set ${arr}(dc) 0.0
		set ${arr}(vc) 0.0
		set ${arr}(vdc) 0.0
		set ${arr}(penchk) 0
		set ${arr}(bt) 0.0
		set ${arr}(dt) 0.0
		set ${arr}(sfs) 1.0
		set ${arr}(sfm) 1.0
		set ${arr}(sst) 1.0
		set ${arr}(mst) 1.0
		set ${arr}(sfst) 1.0
		set ${arr}(sfmt) 1.0
		set ${arr}(fsf) 1.0
		set ${arr}(vsf) 1.0
		set ${arr}(option) 1
		set ${arr}(nfls) 0.0
		set ${arr}(sfls) 0.0
		set ${arr}(ccrit) 0.0
		set ${arr}(kpf) 0.0
		set ${arr}(isym) 0
		set ${arr}(erosop) 0
		set ${arr}(iadj) 0
		set ${arr}(lcid1) 4
		set ${arr}(lcid2) 4
		set ${arr}(lcid) 4
		set ${arr}(fcm) 1
		set ${arr}(us) 0.0
		set ${arr}(nflf) 0.0
		set ${arr}(sflf) 0.0
		set ${arr}(nen) 0.0
		set ${arr}(mes) 0.0
		set ${arr}(nfls1) 0.0
		set ${arr}(sfls1) 0.0
		set ${arr}(tblcid1) 4
#		set ${arr}() 
	   	set lsdyna_param_arrays($arr) [array get $arr]
		
	}
}

#------------------------------------------------------------------------------
# Single surface contacts...

foreach i { "" Existing } {
proc oncreate${i}SingleContactDEZLoad {} {
	global current_singlecontact_to_load
	global solver_setup solver_setup_global
	set AllowActiveReload 1
    
    select_reset_parts_and_subsets
    
	if {$solver_setup != "-1"} {
	   set solve_format $solver_setup
	} else {
	   set solve_format $solver_setup_global
	}

	foreach {n v} {
		name "" mue 0.3 mued 0.1 ctype 0
	} {
		if [info exists current_singlecontact_to_load($n)] {
		    set $n $current_singlecontact_to_load($n)
		} else {
		    set $n $v
		}
	}
	set ContactType $ctype

}

proc oncreate${i}SingleContactDEZApply {} {
	if ![info exists singleContactList] {set singleContactList {}}
	
	set ctype $ContactType
	foreach {n v} [applySingleContact $mue $mued $ctype unsmap $singleContactList $name] {
		set $n $v
	}

	set singleContactList {}
}
}

set ::aie_bctypes_used(singlecontact) CONTACT_SINGLE
set ::aie_prop_subtype(singlecontact) singlecontact

set ::aie_tree_nodes(singlecontact) "Single Surface Contacts"

proc applySingleContact {mue mued ctype type objects name} {
    set bcs [list [list 1 CONTACT_SINGLE $name $mue $mued $ctype]]
    aie_apply_attribute singlecontact $bcs SCON $name $type $objects [select_get_parts_and_subsets]
}

proc aie_edit_singlecontact {name} {
     aie_edit_attribute $name singlecontact SingleContact
}

proc aie_apply_icons_singlecontact {fam obtype vis lvis} {
    foreach {n v} {name "" mue 0.3 mued 0.1 ctype 0} {
	set $n $v
    }
#    set name ""
    set bcs [ic_boco_get $fam]
    if {$bcs == ""} { return 0 }
    set parsed [aie_parse_bcs_singlecontact $bcs]

    if {$parsed == ""} { return 0 }
    foreach {n v} $parsed { set $n $v }
    ic_boco_apply_generic_icon_to_group $fam singlecontact [list $name $mue $mued $ctype] $vis
    return 1
}

proc aie_parse_bcs_singlecontact {bcs} {
#puts "singlecontact bcs: $bcs"
    set ret ""
    set got_it 0
    foreach bc $bcs {
	switch [lindex $bc 1] {
	    CONTACT_SINGLE {
		foreach n {name mue mued ctype} v [lrange $bc 2 end] {
		    lappend ret $n $v
		}
		set got_it 1
	    }
	}
    }
    if $got_it {
	return $ret
    } else {
	return ""
    }
}

#------------------------------------------------------------------------------
# Initial velocities...

foreach i { "" Existing } {
    proc oncreate${i}VelocityDEZLoad {} {
	global current_velocity_to_load
	global  solver_setup solver_setup_global
	set AllowActiveReload 1
    
	select_reset_parts_and_subsets
    
	if {$solver_setup != "-1"} {
	   set solve_format $solver_setup
	} else {
	   set solve_format $solver_setup_global
	}

	foreach {n v} {
		name "" vx 0.0 vy 0.0 vz 0.0 vxr 0.0 vyr 0.0 vzr 0.0 lsdyna_nsid ""
	} {
		if [info exists current_velocity_to_load($n)] {
		set $n $current_velocity_to_load($n)
		} else {
		set $n $v
		}
	}

}

proc oncreate${i}VelocityDEZApply {} {
	if ![info exists objList] {set objList {}}
	if {$lsdyna_nsid == "" || $lsdyna_nsid <= 0} {
		user_error "Please enter a valid Node Set ID"
		set objList {}
		return
	}
	
	foreach {n v} [applyVelocity $vx $vy $vz $vxr $vyr $vzr $lsdyna_nsid point $objList $name] {
		set $n $v
	}

	set objList {}
}
}

set ::aie_bctypes_used(velocity) {VELOCITY LSDYNA_VID}
set ::aie_prop_subtype(velocity) velocity

set ::aie_tree_nodes(velocity) Velocities

proc applyVelocity {vx vy vz vxr vyr vzr lsdyna_nsid type objects name} {
    set bcs [list [list 1 VELOCITY $vx $vy $vz $vxr $vyr $vzr] [list 1 LSDYNA_VID $lsdyna_nsid]]
    aie_apply_attribute velocity $bcs VEL $name $type $objects \
	[select_get_parts_and_subsets]
}

proc aie_edit_velocity {name} {
     aie_edit_attribute $name velocity Velocity
}

proc aie_apply_icons_velocity {fam obtype vis lvis} {
	foreach n {vx vy vz vxr vyr vzr} {
		set $n 0.0
	}
	set name ""
	set bcs [ic_boco_get $fam]
	if {$bcs == ""} { return 0 }
	set parsed [aie_parse_bcs_velocity $bcs]
	if {$parsed == ""} { return 0 }
	foreach {n v} $parsed { set $n $v }
	ic_boco_apply_generic_icon_to_group $fam velocity [list $vx $vy $vz $vxr $vyr $vzr] $vis
	return 1
}

proc aie_parse_bcs_velocity {bcs} {
#puts "velocity bcs: $bcs"
    set ret ""
    set got_it 0
    foreach bc $bcs {
	switch [lindex $bc 1] {
	    VELOCITY {
		foreach n {vx vy vz vxr vyr vzr} v [lrange $bc 2 end] {
		    lappend ret $n $v
		}
		set got_it 1
	    }
	    LSDYNA_VID {
			lappend ret lsdyna_nsid [lindex $bc 2]
			set got_it 1
	    }
	}
    }
    if $got_it {
	return $ret
    } else {
	return ""
    }
}

# *INITIAL_VELOCITY - data names can be: name vx vy vz vxr vyr vzr lsdyna_nsid

proc aie_write_lsdyna_bc_velocity {fp fam data} {
	global lsdyna_param_arrays
    foreach n {vx vy vz vxr vyr vzr} { set vals($n) 0.0 }
    foreach {n v} $data { 
		set vals($n) $v
		if {$vals($n)==""} {set vals($n) 0.0} 
	}

	if [info exists vals(lsdyna_nsid)] {
		set nsid $vals(lsdyna_nsid)
		if {$nsid=="" || $nsid<0} {
			set nsid 0
		}
	} else {
		set nsid 0
	}
	
	if $nsid {
#	add node set bc...
	  puts $fp "\"$fam\" \"NODE_SET_ID\" $nsid"
	  if ![info exists lsdyna_param_arrays(set_bc:vid$nsid)] {
#	add parameter set bc
		set sbc(title) "*INITIAL_VELOCITY"
		set sbc(id) $nsid
		set sbc(type) 0
		set sbc(nc) 2
		for {set i 1} {$i<4} {incr i} {
			for {set j 1} {$j<9} {incr j} {
				set sbc(card$i/f$j) ""
			}
		}
		set sbc(card1/f1) $nsid
		foreach n {vx vy vz vxr vyr vzr} f {f1 f2 f3 f4 f5 f6} {
			set sbc(card2/$f) $vals($n)
		}
		set lsdyna_param_arrays(set_bc:vid$nsid) [array get sbc]
	  }
	} else {
	puts $fp "\"$fam\" \"INITIAL\" 8 \"\" 0 $vals(vx) $vals(vy) $vals(vz) \
				$vals(vxr) $vals(vyr) $vals(vzr) 0.0 0.0 0.0 0.0 0.0 0.0"
	}
}

#------------------------------------------------------------------------------
# Planar rigid walls...

foreach i { "" Existing } {
    proc oncreate${i}RigidwallDEZLoad {} {
	global current_rigidwall_to_load
	global  solver_setup solver_setup_global
	set AllowActiveReload 1

	select_reset_parts_and_subsets
	
	if {$solver_setup != "-1"} {
	   set solve_format $solver_setup
	} else {
	   set solve_format $solver_setup_global
	}

	foreach {n v} {
		name "" o 0.0 xt 0.0 yt 0.0 zt 0.0 xh 0.0 yh 0.0 zh 0.0 fr 0.0 wv 0.0 lsdyna_nsid ""
	} {
		if [info exists current_rigidwall_to_load($n)] {
		set $n $current_rigidwall_to_load($n)
		} else {
		set $n $v
		}
	}

}

proc oncreate${i}RigidwallDEZApply {} {
	if ![info exists objList] {set objList {}}
	if {$lsdyna_nsid == "" || $lsdyna_nsid <= 0} {
		user_error "Please enter a valid Node Set ID"
		set objList {}
		return
	}
	
	foreach {n v} [applyRigidwall $o $xt $yt $zt $xh $yh $zh $fr $wv $lsdyna_nsid point $objList $name] {
		set $n $v
	}

	set objList {}
}
}

set ::aie_bctypes_used(rigidwall) {RIGIDWALL LSDYNA_RID}
set ::aie_prop_subtype(rigidwall) rigidwall

set ::aie_tree_nodes(rigidwall) "Rigid walls"

proc applyRigidwall {o xt yt zt xh yh zh fr wv lsdyna_nsid type objects name} {
    set bcs [list [list 1 RIGIDWALL $o $xt $yt $zt $xh $yh $zh $fr $wv] [list 1 LSDYNA_RID $lsdyna_nsid]]
    aie_apply_attribute rigidwall $bcs RWALL $name $type $objects [select_get_parts_and_subsets]
}

proc aie_edit_rigidwall {name} {
    aie_edit_attribute $name rigidwall Rigidwall
}

proc aie_apply_icons_rigidwall {fam obtype vis lvis} {
    foreach n {o xt yt zt xh yh zh fr wv} {
	set $n 0.0
    }
    set name ""
    set bcs [ic_boco_get $fam]
    if {$bcs == ""} { return 0 }
    set parsed [aie_parse_bcs_rigidwall $bcs]
    if {$parsed == ""} { return 0 }
    foreach {n v} $parsed { set $n $v }
    ic_boco_apply_generic_icon_to_group $fam rigidwall [list $o $xt $yt $zt $xh $yh $zh $fr $wv] $vis
    return 1
}

proc aie_parse_bcs_rigidwall {bcs} {
#puts "rigidwall bcs: $bcs"
    set ret ""
    set got_it 0
    foreach bc $bcs {
	switch [lindex $bc 1] {
	    RIGIDWALL {
		foreach n {o xt yt zt xh yh zh fr wv} v [lrange $bc 2 end] {
		    lappend ret $n $v
		}
		set got_it 1
	    }
	    LSDYNA_RID {
			lappend ret lsdyna_nsid [lindex $bc 2]
			set got_it 1
	    }
	}
    }
    if $got_it {
	return $ret
    } else {
	return ""
    }
}

# *RIGIDWALL_PLANAR - data names can be: name o xt yt zt xh yh zh fr wv lsdyna_nsid

proc aie_write_lsdyna_bc_rigidwall {fp fam data} {
	global lsdyna_param_arrays
    foreach n {o xt yt zt xh yh zh fr wv lsdyna_nsid} { set $n 0 }
    foreach {n v} $data { 
		set $n $v
		if {$v==""} {set $n 0.0} 
	}

	if [info exists lsdyna_nsid] {
		set nsid $lsdyna_nsid
		if {$nsid=="" || $nsid<0} {
			set nsid 0
		}
	} else {
		set nsid 0
	}
	
	if $nsid {
#	add node set bc...
	  puts $fp "\"$fam\" \"NODE_SET_ID\" $nsid"
	  if ![info exists lsdyna_param_arrays(set_bc:rid$nsid)] {
#	add parameter set bc
		set sbc(title) "*RIGIDWALL_PLANAR"
		set sbc(id) $nsid
		set sbc(type) 0
		set sbc(nc) 2
		for {set i 1} {$i<4} {incr i} {
			for {set j 1} {$j<9} {incr j} {
				set sbc(card$i/f$j) ""
			}
		}
		set sbc(card1/f1) $nsid
		set sbc(card1/f3) 0
		set sbc(card1/f4) $o
		foreach n {xt yt zt xh yh zh fr wv} f {f1 f2 f3 f4 f5 f6 f7 f8} {
			set sbc(card2/$f) [set $n]
		}
		set lsdyna_param_arrays(set_bc:rid$nsid) [array get sbc]
	  }
	} else {
	puts $fp "\"$fam\" \"RIGIDWALL\" 5 0 0 \"\" 0 $o $xt $yt $zt $xh $yh $zh $fr $wv \
				0 0 0 0 0 0 0 0 0 0"
	}
}

#------------------------------------------------------------------------------
# *CONSTRAINED cards...

foreach i { "" Existing } {
    proc oncreate${i}ConstrainedNodesDEZLoad {} {
	global current_constrainednodes_to_load
	global  solver_setup solver_setup_global
	set AllowActiveReload 1

	select_reset_parts_and_subsets
	
	if {$solver_setup != "-1"} {
	   set solve_format $solver_setup
	} else {
	   set solve_format $solver_setup_global
	}

	set NodeSetDOFList {
		"x translational" "y translational" "z translational" \
		"x and y translational" "y and z translational" "x and z translational" \
		"x,y,and z translational" \
	}

# Constrained Nodal Rigid Bodies mapped to RBE2's
if 0 {
	set DRflagList {
		"off for rigid body behavior" \
		"release along X in local system" \
		"release along Y in local system" \
		"release along Z in local system" \
		"release along X,Y in local system" \
		"release along Y,Z in local system" \
		"release along Z,X in local system" \
		"release along X,Y,Z in local system" \
		"release along X in global system" \
		"release along Y in global system" \
		"release along Z in global system" \
		"release along X,Y in global system" \
		"release along Y,Z in global system" \
		"release along Z,X in global system" \
		"release along X,Y,Z in global system" \
	}
	set RRflagList $DRflagList
}

	set WeldList {Spot Fillet Butt}

	foreach {n v} {
		name "" lsdyna_nsid "" type 0 \
		dof 0 tf 1.0E+20 weld 0 cid2 0 npr 0 tfail 0.0 epsf 0.0
	} {
		if [info exists current_constrainednodes_to_load($n)] {
		set $n $current_constrainednodes_to_load($n)
#puts "current_constrainednodes_to_load($n) $current_constrainednodes_to_load($n)"
		} else {
		set $n $v
		}
	}
	
	set dof [lindex $NodeSetDOFList $dof]
#	set drflag [lindex $DRflagList $drflag]
#	set rrflag [lindex $RRflagList $rrflag]
	set weld [lindex $WeldList $weld]

}

proc oncreate${i}ConstrainedNodesDEZApply {} {
	if ![info exists objList] {set objList {}}
	if {$lsdyna_nsid == "" || $lsdyna_nsid <= 0} {
		user_error "Please enter a valid Node Set ID"
		set objList {}
		return
	}
	
	set dof1 [lsearch $NodeSetDOFList $dof]
	if {$dof1==-1} {set dof1 0}
	
#	set drflag1 [lsearch $DRflagList $drflag]
#	if {$drflag1==-1} {set drflag1 0}
	
#	set rrflag1 [lsearch $RRflagList $rrflag]
#	if {$rrflag1==-1} {set rrflag1 0}
	
	set weld1 [lsearch $WeldList $weld]
	if {$weld1==-1} {set weld1 0}
	

	foreach {n v} [applyConstrainedNodes $type $dof1 $tf $weld1 $cid2 $npr \
					$tfail $epsf $lsdyna_nsid point $objList $name] {
		set $n $v
	}

	set objList {}
}
}

set ::aie_bctypes_used(constrainednodes) {CONSTRAINED_NODES LSDYNA_CNID}
set ::aie_prop_subtype(constrainednodes) constrainednodes

set ::aie_tree_nodes(constrainednodes) "Constrained nodes"

proc applyConstrainedNodes {type dof tf weld cid2 npr tfail epsf lsdyna_nsid ent objects name} {
    set bcs [list [list 1 CONSTRAINED_NODES $type $dof $tf $weld $cid2 $npr $tfail $epsf] \
			[list 1 LSDYNA_CNID $lsdyna_nsid]]
    aie_apply_attribute constrainednodes $bcs CONSTRN $name $ent $objects [select_get_parts_and_subsets]
}

proc aie_edit_constrainednodes {name} {
     aie_edit_attribute $name constrainednodes ConstrainedNodes
}

proc aie_apply_icons_constrainednodes {fam obtype vis lvis} {
    foreach n {type dof tf cid1 pnode drflag rrflag weld cid2 npr tfail epsf} {
	set $n 0.0
    }
    set name ""
    set bcs [ic_boco_get $fam]
    if {$bcs == ""} { return 0 }
    set parsed [aie_parse_bcs_constrainednodes $bcs]
    if {$parsed == ""} { return 0 }
    foreach {n v} $parsed { set $n $v }
    ic_boco_apply_generic_icon_to_group $fam constrainednodes [list $type $dof $tf $cid1 $pnode $drflag $rrflag $weld $cid2 $npr $tfail $epsf] $vis
    return 1
}

proc aie_parse_bcs_constrainednodes {bcs} {
#puts "constrainednodes bcs: $bcs"
    set ret ""
    set got_it 0
    foreach bc $bcs {
	switch [lindex $bc 1] {
	    CONSTRAINED_NODES {
		foreach n {type dof tf weld cid2 npr tfail epsf} v [lrange $bc 2 end] {
		    lappend ret $n $v
		}
		set got_it 1
	    }
	    LSDYNA_CNID {
			lappend ret lsdyna_nsid [lindex $bc 2]
			set got_it 1
	    }
	}
    }
    if $got_it {
	return $ret
    } else {
	return ""
    }
}

# Constrained Nodal Rigid Bodies mapped to RBE2's
# *CONSTRAINED - data names can be: name type dof tf weld cid2 npr tfail epsf lsdyna_nsid

proc aie_write_lsdyna_bc_constrainednodes {fp fam data} {
	global lsdyna_param_arrays
    foreach n {type dof tf weld cid2 npr tfail epsf lsdyna_nsid} { set $n 0 }
    foreach {n v} $data { 
		set $n $v
		if {$v==""} {set $n 0} 
	}

	if [info exists lsdyna_nsid] {
		set nsid $lsdyna_nsid
		if {$nsid=="" || $nsid<0} {
			set nsid 0
		}
	} else {
		set nsid 0
	}
	
	if $nsid {
#	add node set bc...
	  puts $fp "\"$fam\" \"NODE_SET_ID\" $nsid"
	  if ![info exists lsdyna_param_arrays(set_bc:cnid$type$weld$nsid)] {
#	add parameter set bc
		for {set i 1} {$i<4} {incr i} {
			for {set j 1} {$j<9} {incr j} {
				set sbc(card$i/f$j) ""
			}
		}
		switch $type {
			0 {
				set sbc(title) "*CONSTRAINED_NODE_SET"
				set sbc(nc) 1
				set sbc(card1/f1) $nsid
				set sbc(card1/f2) [expr $dof + 1]
				set sbc(card1/f3) $tf
			}
			2 {
				#this was type 1 earlier; obsolete after being remapped to RBE2's
				set sbc(title) "*CONSTRAINED_NODAL_RIGID_BODY"
				set sbc(nc) 1
				set sbc(card1/f1) $nsid
				set sbc(card1/f2) $cid1
				set sbc(card1/f3) 0
				set sbc(card1/f4) $pnode
				set sbc(card1/f5) 0
				if {$drflag>7} {set drflag [expr -1*($drflag - 7)]}
				set sbc(card1/f6) $drflag
				if {$rrflag>7} {set rrflag [expr -1*($rrflag - 7)]}
				set sbc(card1/f7) $rrflag
			}
			1 {
				#this was type 2 earlier; moved up after removing previous type 2 from the list
				switch $weld {
					0 {
						set sbc(title) "*CONSTRAINED_GENERALIZED_WELD_SPOT"
					}
					1 {
						set sbc(title) "*CONSTRAINED_GENERALIZED_WELD_FILLET"
					}
					2 {
						set sbc(title) "*CONSTRAINED_GENERALIZED_WELD_BUTT"
					}
					default {
						return
					}
				}
				set sbc(nc) 2
				set sbc(card1/f1) $nsid
				set sbc(card1/f2) $cid2
				set sbc(card1/f3) 0
				set sbc(card1/f4) 0
				set sbc(card1/f5) $npr
				set sbc(card1/f6) 0
				set sbc(card2/f1) $tfail
				set sbc(card2/f2) $epsf
			}
			default {
				return
			}
		}
		set sbc(id) $nsid
		set sbc(type) 0
		set lsdyna_param_arrays(set_bc:cnid$type$weld$nsid) [array get sbc]
	  }
	} else {
		for {set i 1} {$i<23} {incr i} {
			set pos$i 0
		}
		switch $type {
			0 {
				set pos1 2
				set pos3 [expr $dof + 1]
				set pos4 $tf
				set pos 4
			}
			2 {
				#this was type 1 earlier; obsolete now
				set pos1 11
				set pos2 $cid1
				set pos3 $pnode
				set pos4 0
				if {$drflag>7} {set drflag [expr -1*($drflag - 7)]}
				set pos5 $drflag
				if {$rrflag>7} {set rrflag [expr -1*($rrflag - 7)]}
				set pos6 $rrflag
				set pos 6
			}
			1 {
				#this was type 2 earlier; moved up
				switch $weld {
					0 {
						set pos1 8
						set pos11 $tfail
						set pos12 $epsf
						set pos 12
					}
					1 {
						set pos1 9
						set pos7 $tfail
						set pos8 $epsf
						set pos 14
						
					}
					2 {
						set pos1 10
						set pos7 $tfail
						set pos8 $epsf
						set pos 12
					}
					default {
						return
					}
				}
				set pos2 $cid2
				set pos3 0
				set pos4 0
				set pos5 $npr
				set pos6 0
			}
			default {
				return
			}
		}
		puts -nonewline $fp "\"$fam\" \"CONSTRAINED\""
		for {set i 1} {$i<=$pos} {incr i} {
			puts -nonewline $fp " [set pos$i]"
		}
		puts $fp ""
	}
}

#------------------------------------------------------------------------------
# LS-Dyna import...

proc aie_import_lsdyna_new {} {
	importLsdynaDEZ show
}

proc aie_import_lsdyna {{file ""} {do_load 1} {include 0}} {
    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 {{{LS-Dyna keyword files} *.k} {{All files} *}}
	set file [tk_getOpenFile -initialdir $file_name(project_dir) \
		      -filetypes $types]
	if {$file == ""} { return "" }
    }
    
    set conv $env(ICEM_ACN)/icemcfd/output-interfaces/lsdyna2icem
    if {![file exists $conv] && ![file exists $conv.exe]} {
	set conv $bindir/lsdyna2icem
    }
    
    set pname [aie_unused_project_name]
    
    mess "$conv -dom ${pname}.lsdyna.import.uns -b ${pname}.lsdyna.import.fbc \
			-par ${pname}.lsdyna.import.par -k $file -include $include\n"
    busy 1

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

	file copy ${pname}.lsdyna.import.uns $pname.uns
	aie_nastran_to_lsdyna ${pname}.lsdyna.import $pname

    if $do_load {
         set solver_setup 2

	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
	aie_tree_load_lsdyna_params
	
	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_lsdyna {lsdyna proj} {
	global lsdyna_param_arrays
	set par ${lsdyna}.par
	set bc ${lsdyna}.fbc
	lsdyna_params_load_solve_data $par
#puts "lsdyna_param_arrays: [array names lsdyna_param_arrays]"

	if [file exists $bc] {
		if [catch {ic_boco_load $bc} res] {
			mess "Error in opening LS-Dyna family_boco file; $res\n" red
		} else {
			set fp [open ${proj}.fbc w]
# parts
			foreach fam [ic_boco_list_families] {
				if [regexp ORFN$ $fam] continue
				if {![info exists added($fam)]} {
					puts $fp "\"$fam\""
#					puts $fp "\"$fam\" \"PART_NAME\" \"$fam\""
					set added($fam) 1
				}
# read node sets bcs
				set boc [ic_boco_get $fam]
				foreach b $boc {
					if {[lindex $b 1]=="NODE_SET_ID"} {
						set nsid [lindex $b 2]
						if [info exists NODE_SET_ID($nsid)] {
							lappend NODE_SET_ID($nsid) $fam
						} else {
							set NODE_SET_ID($nsid) $fam
						}
					}
				}
			}

			set dispid 1
			set loadid 1
			set velid 1
			set rwid 1
#			set Table_ID 1
			foreach fam [ic_boco_list_families] {
				catch {unset elem}
				catch {unset $elem}
				catch {unset mat_data}
				catch {unset $mat_data}
				set boc [ic_boco_get $fam]
#puts [list $fam $boc]
				foreach b $boc {
					set bctype [lindex $b 1]
# elements,materials,sections,hourglasses...
					if {[regexp ^ELEMENT $bctype]} {
#						regsub -nocase FAM $fam "" pid
						set skip [string last _ $fam]
						incr skip
						set pid [string range $fam $skip end]
						set dim -1
						switch -regexp [lindex $b 1] {
							0D$ {set dim 0}
							1D$ {set dim 1}
							2D$ {set dim 2}
							3D$ {set dim 3}
							default {continue}
						}
						set elemname [lindex $b 2]
						set elemnode elem${dim}d:$elemname
						if ![info exists lsdyna_param_arrays($elemnode)] {
							mess "Warning: element definition $elemname not found for part $fam\n" red
							continue
						}
						catch {unset elem}
						array set elem $lsdyna_param_arrays($elemnode)
# pid's redefined!
						set pid 0
						if [info exists elem(pid)] {set pid $elem(pid)}
						set formul $elem(formul)
#puts "element dimension $dim; element formulation $formul"

# old code for material data within element bc
						if 0 {
						if ![info exists elem(mat$formul)] {
							mess "error: material definition not found for part $fam\n" red
							continue
						}
						set mat $elem(mat$formul)
						}
#						if {![info exists elem(mat_def)] || $elem(mat_def)==0} {
#							mess "error: no material defined for part $fam\n" red
#							continue
#						}
						#exclude node families from material check
						if $dim {
						if {![info exists elem(mat_name)] || $elem(mat_name)==""} {
							mess "error: invalid material name for part $fam\n" red
							continue
						}
						set mat_name $elem(mat_name)
						if ![info exists lsdyna_param_arrays(mat_data:$mat_name)] {
							mess "error: material named $mat_name not found for part $fam\n" red
							continue
						}
						array set mat_data $lsdyna_param_arrays(mat_data:$mat_name)
						set mid $mat_data(id)
						set mat $mat_data(type)
						}
						
						switch $dim {
							0 {
								set mass 0.0
								if {$formul==2} {mess "Lumped Inertia elements not supported in Nastran\n"
								} else {
								if [info exists elem(mass)] {set mass $elem(mass)}
								}
								puts $fp "\"$fam\" \"CONM1\" 0 $mass"
							}
							1 {
								switch -exact $formul {
									2 - 3 {
										foreach n {f1 f2 f3 f4} p {A I1 I2 J} {
											set $n 0.0
											if [info exists elem(sec_beam/$n)] {set $n $elem(sec_beam/$n)} \
											else { mess "Warning: assuming zero section property $p for beams for part $fam\n" red }
										}
#										puts $fp "\"$fam\" \"PBAR\" $pid $pid $f1 $f2 $f3 0.0" 
										puts $fp "\"$fam\" \"PBAR\" $pid $mid $f1 $f2 $f3 $f4" 
#										puts $fp "\"$fam\" \"OR\" $pid 0.0 0.0 1.0"
# orientation to be obtained from BORIENT bcs
										set orflag 0
										foreach btmp [ic_boco_get $fam] {
											switch [lindex $btmp 1] {
												BORIENT {
													puts $fp "\"$fam\" \"OR\" $pid [lrange $btmp 2 4]"
													set orflag 1
													break
												}
											}
										}
										if !$orflag {puts $fp "\"$fam\" \"OR\" $pid 0.0 0.0 1.0"}
										puts $fp "\"$fam\" \"LSDYNA_BEAM_FORM\" [expr $formul-1]"
									} 1 - 4 - 5 {
										set cst 0
										if [info exists elem(sec_beam/cst)] {set cst $elem(sec_beam/cst)} \
										else { mess "Warning: assuming rectangular beams for part $fam\n" red}
										foreach n {f1 f2 f3 f4} p {TS1 TS2 TT1 TT2} {
											set $n 0.0
											if [info exists elem(sec_beam/$n)] {set $n $elem(sec_beam/$n)} \
											else { mess "Warning: assuming zero section property $p for beams for part $fam\n" red }
										}
# MI calculations later...
											if !$cst {
												mess "calculating average area for rectangular c/s\n"
												set a [expr ($f1+$f2)*($f3+$f4)/4.0]
											} else {
												mess "calculating average area for circular c/s\n"
												set od [expr ($f1+$f2)/2.0]
												set id [expr ($f3+$f4)/2.0]
												set a [expr 3.1416*($od*$od-$id*$id)/4.0]
											}
#										puts $fp "\"$fam\" \"PBAR\" $pid $pid $f1 $f2 $f3 0.0" 
										puts $fp "\"$fam\" \"PBAR\" $pid $mid $a 0.0 0.0 0.0" 
#										puts $fp "\"$fam\" \"OR\" $pid 0.0 0.0 1.0"
# orientation to be obtained from BORIENT bcs
										set orflag 0
										foreach btmp [ic_boco_get $fam] {
											switch [lindex $btmp 1] {
												BORIENT {
													puts $fp "\"$fam\" \"OR\" $pid [lrange $btmp 2 4]"
													set orflag 1
													break
												}
											}
										}
										if !$orflag {puts $fp "\"$fam\" \"OR\" $pid 0.0 0.0 1.0"}
										puts $fp "\"$fam\" \"LSDYNA_BEAM_FORM\" [expr $formul-1]"
									} 6 {
										#set stiff 0.0
										catch {unset stiff}
										set damp 0.0
										switch -exact $mat {
											66 - 68 {
												set stiff $elem(card1/f3)
												set damp $elem(card2/f1)
											}
											67 - 71 - 93 - 95 {set stiff 0.0}
											69 {set damp $elem(card1/f7)}
											74 - 94 {
												set stiff $elem(card1/f3)
												set damp $elem(card1/f5)
											}
										}
										if [info exists stiff] {
											puts $fp "\"$fam\" \"PELAS\" $pid $stiff $damp 0.0"
										} else {
											puts $fp "\"$fam\" \"PDAMP\" $pid $damp"
										}
										puts $fp "\"$fam\" \"CMP\" $pid \"\" \"\""
									} 10 {
										switch -exact $mat {
											301 - 303 - 304 - 306 - 307 - 308 - 313 - 314 - 315 {
												puts $fp "\"$fam\" \"PELAS\" $pid 0.0 0.0 0.0" 
												puts $fp "\"$fam\" \"CMP\" $pid \"\" \"\""
											}
											302 - 305 {
												puts $fp "\"$fam\" \"PVISC\" $pid 0.0 0.0"
											}
										}
									} 11 {
										puts $fp "\"$fam\" \"PBAR\" $pid $mid 0.0 0.0 0.0 0.0" 
										puts $fp "\"$fam\" \"OR\" $pid 0.0 0.0 1.0"
										puts $fp "\"$fam\" \"LSDYNA_BEAM_FORM\" 5"
										if {$mat!=401} {
											mess "Warning: correcting material for seatbelt elements for part $fam\n" red
										}
									} default {
										mess "Warning: skipping formulation $formul beam elements for part $fam\n" red
										continue
									}
								}
								set aiemat 0
								if {$formul==6||$formul==10} {
								set defmat 66
								switch -exact $mat {
									66 {}
									74 {set aiemat 1}
									default { mess "Warning: converting material id $mid to type $defmat for part $fam\n" red }
								}
								}
								puts $fp "\"$fam\" \"LSDYNA_MATERIAL_BEAM\" $aiemat"
							}
							2 {
								foreach n {marea thk shrf} {
									set $n 0.0
									if [info exists elem(sec_shell/$n)] {set $n $elem(sec_shell/$n)} \
else {puts "error: can't find section property $n for shells for part $fam"}
								}
#								puts $fp "\"$fam\" \"ISHE\" $pid $pid \"\" \"\" $marea \"\" $thk 1.0 $shrf"
								puts $fp "\"$fam\" \"ISHE\" $pid $mid \"\" \"\" $marea \"\" $thk 1.0 $shrf"
#								set sigy 0.0
#								set fail 0.0
#								puts $fp "\"$fam\" \"LSDYNA_MATERIAL_SHELL\" $aiemat $sigy $fail"
							}
							3 {
#								puts $fp "\"$fam\" \"IVOL\" $pid 0 0 $pid"
								puts $fp "\"$fam\" \"IVOL\" $mid 0 0 $pid"
#								set sigy 0.0
#								set fail 0.0
#								puts $fp "\"$fam\" \"LSDYNA_MATERIAL_SOLID\" $aiemat $sigy $fail"
							}
						}
					} elseif {$bctype=="BOUNDARY"} {
# displacements
						if {[lindex $b 2]==1} {
							#disabled boundary_prescribed_motion_rigid since it is applied to part, besides
							#it doesn't correctly map to the Nastran imposed displacements/constraints
							if {[lindex $b 3]==2} continue
							if {[lindex $b 5]!=2} continue
							set dof ""
							switch [lindex $b 4] {
								1 - 2 - 3 {
									set dof [lindex $b 4]
								}
								5 - 6 - 7 {
									set dof [expr [lindex $b 4]-1]
								}
							}
							if {$dof!=""} {
								set cnval 0.0
								set val [get_max_load_curve_value [lindex $b 6]]
								if {$val==""} {
									mess "error reading load curve id [lindex $b 6]\n\
											for imposed displacement for part $fam\n"
								} else {
									set cnval [expr [lindex $b 7]*$val]
								}
								puts $fp "\"$fam\" \"ISPC\" 1 $dof $cnval"
								puts $fp "\"$fam\" \"IMPDISP_NAME\" \"Constraint$dispid\""
								incr dispid
							}
# constraints
						} elseif {[lindex $b 2]==3} {
							set dof ""
							for {set i 5} {$i<=10} {incr i} {
								if {[lindex $b $i]!="" && [lindex $b $i]} {
									set dof ${dof}[expr $i-4]
								}
							}
							if {$dof!=""} {
								puts $fp "\"$fam\" \"ISPC\" 1 $dof 0"
								puts $fp "\"$fam\" \"CONSTRAINT_NAME\" \"Constraint$dispid\""
								incr dispid
							}
						}
					} elseif {$bctype=="LOAD"} {
						switch [lindex $b 2] {
							2 - 4 {
# pressures
								set frval 0.0
								set val [get_max_load_curve_value [lindex $b 5]]
								if {$val==""} {
									mess "error reading load curve id [lindex $b 5]\n\
											for pressure load for part $fam\n" red
								} else {
									set frval [expr [lindex $b 6]*$val]
								}
								puts $fp "\"$fam\" \"PLOAD2\" 1 $frval"
								puts $fp "\"$fam\" \"PRESSURE_NAME\" \"Load$loadid\""
								incr loadid
							}
							6 - 7 {
# forces, moments
								set frval 0.0
								set val [get_max_load_curve_value [lindex $b 5]]
								if {$val==""} {
									mess "error reading load curve id [lindex $b 5]\n\
											for force/moment load for part $fam\n"
								} else {
									set frval [expr [lindex $b 6]*$val]
								}
								set force([lindex $b 4]) $frval
							}
							8 {
# temperatures
								if {[lindex $b 3]==1} {
									puts $fp "\"$fam\" \"TEMP\" 1 [lindex $b 6]"
									puts $fp "\"$fam\" \"TEMPERATURE_NAME\" \"Load$loadid\""
									incr loadid
								} elseif  {[lindex $b 3]==2} {
									set frval 0.0
									set val [get_max_load_curve_value [lindex $b 4]]
									if {$val==""} {
										mess "error reading load curve id [lindex $b 4]\n\
												for thermal load for part $fam\n"
									} else {
										set frval $val
									}
									puts $fp "\"$fam\" \"TEMP\" 1 $frval"
									puts $fp "\"$fam\" \"TEMPERATURE_NAME\" \"Load$loadid\""
									incr loadid
								}
							}
						}
					} elseif {$bctype=="INITIAL"} {
# initial velocities
					  switch [lindex $b 2] {
						8 {
							puts -nonewline $fp "\"$fam\" \"VELOCITY\""
							for {set i 5} {$i<=10} {incr i} {
								if {[lindex $b $i]!=""} {
									set vel [lindex $b $i]
								} else {
									set vel 0.0
								}
								puts -nonewline $fp " $vel"
							}
							puts $fp ""
							puts $fp "\"$fam\" \"VELOCITY_NAME\" \"Velocity$velid\""
							incr velid
						}
						9 {
							#disabled initial_velocity_generation for now since it can applied to part set, part or node set
							continue
							if {!([lindex $b 3]==2 || [lindex $b 3]==3)} continue
							puts -nonewline $fp "\"$fam\" \"VELOCITY\""
							for {set i 5} {$i<=7} {incr i} {
								if {[lindex $b $i]!=""} {
									set vel [lindex $b $i]
								} else {
									set vel 0.0
								}
								puts -nonewline $fp " $vel"
							}
							set omega 0.0
							if {[lindex $b 4]!=""} {set omega [lindex $b 4]}
							for {set i 11} {$i<=13} {incr i} {
								set j [expr $i-10]
								if {[lindex $b $i]!=""} {
									set dc$j [lindex $b $i]
								} else {
									set dc$j 0.0
								}
								puts -nonewline $fp " [expr $omega*[set dc$j]]"
							}
							puts $fp ""
							puts $fp "\"$fam\" \"VELOCITY_NAME\" \"Velocity$velid\""
							incr velid
						}
					  }
					} elseif {$bctype=="RIGIDWALL"} {
						if {[lindex $b 2]==5} {
# planar rigidwalls
							puts -nonewline $fp "\"$fam\" \"RIGIDWALL\""
							for {set i 7} {$i<=15} {incr i} {
								if {[lindex $b $i]!=""} {
									set rw [lindex $b $i]
								} else {
									set rw 0.0
								}
								puts -nonewline $fp " $rw"
							}
							puts $fp ""
							puts $fp "\"$fam\" \"RIGIDWALL_NAME\" \"Rigidwall$rwid\""
							incr rwid
						}
					} elseif {$bctype=="CONSTRAINED"} {
						if {[lindex $b 2]==11} {
# nodal rigid body cards
							puts -nonewline $fp "\"$fam\" \"RBE2\" 1 0"
							set cid [lindex $b 3]
							set pnode [lindex $b 4]
							set iprt [lindex $b 5]
							set dr [lindex $b 6]
							if {$dr<0} {set dr [expr -1 * $dr]}
							set rr [lindex $b 7]
							if {$rr<0} {set rr [expr -1 * $rr]}
							if {$cid} {
								mess "Warning: ignoring rigid body local system id $cid for part $fam\n" red
							}
							if {$pnode} {
								mess "Warning: ignoring rigid body nodal point $pnode for part $fam\n" red
							}
							if {$iprt} {
								mess "Warning: ignoring rigid body print flag $iprt for part $fam\n" red
							}
							array set nas_disp {1 1 2 2 3 4 4 12 5 23 6 13 7 123}
							array set nas_rotn {1 4 2 5 3 6 4 45 5 56 6 46 7 456}
							if ![info exists nas_disp($dr)] {
								set disp ""
							} else {
								set disp $nas_disp($dr)
							}
							if ![info exists nas_rotn($rr)] {
								set rotn ""
							} else {
								set rotn $nas_rotn($rr)
							}
							puts $fp " $disp$rotn"
						}
					}
				}
				if [info exists force] {
					puts -nonewline $fp "\"$fam\" \"FORCE\" 1 0 1.0"
					foreach i {1 2 3} dir {FX FY FZ} {
						if [info exists force($i)] {
							puts -nonewline $fp " $force($i)"
						} else {
							puts -nonewline $fp " 0.0"
						}
					}
					puts $fp ""
					puts -nonewline $fp "\"$fam\" \"MOMENT\" 1 0 1.0"
					foreach i {5 6 7} dir {MX MY MZ} {
						if [info exists force($i)] {
							puts -nonewline $fp " $force($i)"
						} else {
							puts -nonewline $fp " 0.0"
						}
					}
					puts $fp ""
					puts $fp "\"$fam\" \"FORCE_NAME\" \"Load$loadid\""
					incr loadid
					unset force
				}
			}
#			close $fp
			ic_boco_delete_unused 1
			ic_boco_unload
		}
	}
	

# materials
	set Table_ID 1
	foreach node [array names lsdyna_param_arrays] {
#puts "node: $node"
		if ![regexp ^mat_data: $node] continue
		catch {unset material}
		array set material $lsdyna_param_arrays($node)
		set mid $material(id)
		set mat $material(type)

		set cards ""
		switch -exact $mat {
			 1 -  201 -  3 - 17 - 18 - 19 - 20 - 24 - 26 - 28 - 30 - 33 - 
			35 -   36 - 37 - 39 - 51 - 52 - 64 - 81 - 89 - 96 - 98 -
			100 - 101 - 102 - 103 - 104 - 105 - 112 - 114 - 115 -
			120 - 123 - 124 - 126 - 191 - 192 - 194 - 195 -
			 29 -  63 - 139 - 106
				{set cards {1/f2 1/f3 1/f4}}
			 2 -  4 -  5 -  6 -  7 -  8 - 10 - 210 - 11 - 12 - 13 - 14 - 21 - 22 - 23 - 25 - 
			32 - 34 - 38 - 40 - 41 - 42 - 43 - 44 - 45 - 46 - 47 - 48 - 49 - 50 - 54 -
			55 - 58 - 59 - 60 - 61 - 65 - 76 - 78 - 79 - 80 - 86 - 88 - 90 - 91 -
			110 - 111 - 116 - 117 - 118 - 127 - 128 - 129 - 130 - 161 -
			66 - 67 - 68 - 69 - 70 - 71 - 74 - 93 - 94 - 95
				{set cards {1/f2 "" ""}}
			9 {set cards {1/f2 1/f7 1/f8}}
			15 {set cards {1/f2 1/f4 1/f5 "" 1/f3}}
			16 - 193 {set cards {1/f2 "" 1/f4 "" 1/f3}}
			27 - 31 - 72 - 77 - 84 - 85 - 87 {set cards {1/f2 "" 1/f3}}
			53 - 57 - 73 - 75 {set cards {1/f2 1/f3 ""}}
			62 {set cards {1/f2 "" 1/f8}}
			301 - 302 - 303 - 304 - 305 - 306 - 307 - 308 -
			401 -
			501 - 502 - 503
			{}
			default {
				mess "Warning: property conversion unsupported material type $mat\n" red
			}
		}
		switch -exact $mat {
			29 - 139 {lappend cards "" "" 1/f5}
			63 {lappend cards "" "" 1/f7}
			5 - 7 - 10 - 11 - 12 - 13 - 14 - 38 - 65 - 78 - 110 - 111 {lappend cards "" 1/f3}
			8 {lappend cards "" 1/f7}
			25 - 127 {lappend cards "" 1/f4}
			34 {lappend cards "" "" 2/f8}
			40 {lappend cards 2/f6 "" 3/f5}
			57 - 73 {lappend cards "" "" 1/f8}
			75 {lappend cards "" "" 1/f6}
			79 {lappend cards "" "" 2/f1}
			88 {lappend cards "" 3/f1}
			90 {lappend cards "" "" 1/f4}
			106 {lappend cards 1/f6}
		}
						
		for {set i 1} {$i<7} {incr i} {
			set mval($i) 0.0
		}

		set i 1
		foreach c $cards {
			if {$c!=""} {
				set loc card$c
			 	if [info exists material($loc)] {
					set mval($i) $material($loc)
				} else {
					mess "Warning: error reading $loc for material type $mat (id=$mid)\n" red
				}
			}
			incr i
		}
							
		if {$mat==7} {set mval(3) 0.463}
		if {$mat==38} {set mval(3) 0.25}
						
		set mdata Isotropic_Material:IsotropicMat$mid
		set ${mdata}(Material_ID) $mid

		set i 1
		foreach p {Mass_Density Youngs_Modulus Poissons_Ratio Thermal_Expansion_Coefficient \
					Shear_Modulus Structural_Damping_Coefficient} {
			set ${mdata}($p) $mval($i)
			incr i
		}
		if {$cards==""} {
			mess "Warning: assigning zero property values to material id $mid\n" red
		}
							
		set mlist [list 1 201 3 5 6 7 8 9 10 210 12 14 15 18 19 20 24 27 28 30 31 38 52 53 57 63 64 73 81 96 112 123 124 140 401]
		set lid [lsearch $mlist $mat]
		if {$lid==-1} {
			mess "Warning: converting unsupported material $mid to type 1\n" red
			set lid 0
		}
		set ${mdata}(LSDyna_Material_Type) $lid
		
		set nastran_param_arrays($mdata) [array get $mdata]

		set nonlinear 0
		set nlc1 3
		set nlc2 4
		switch -exact $mat {
			24 - 81 - 112 - 123 {set nonlinear 1}
			10 {set nonlinear 1; set nlc1 "2 4"; set nlc2 "3 5"}
			210 {set nonlinear 1; set nlc1 "3 5"; set nlc2 "4 6"}
		}

		if {$nonlinear} {
#			if [info exists elem(card1/f5)] { set sigy $elem(card1/f5) }
#			if [info exists elem(card1/f7)] { set fail $elem(card1/f7) }
			array set stress_mat [ list Material_ID $mid Stress_Dependent_Table_ID $Table_ID \
				Nonlinearity_type NLELAST \
				Work_Hardening_Slope {} \
				Yield_Function_criterion {} \
				Hardening_Rule {} \
				Initial_Yield_Point {} \
				Internal_Friction_Angle_Degrees {}]
			set stress_table(Length) 8
			set stress_table(Table_ID) $Table_ID
			set vals 0
			foreach c1 $nlc1 c2 $nlc2 {
			for {set i 1} {$i<=8} {incr i} {
				set vals "$vals $material(card$c1/f$i) $material(card$c2/f$i)"
			}
			}
			set stress_table(Table) [list nonlinear $vals]
			set nastran_param_arrays(Stress_Dependent_Material:IsotropicMat$mid) [array get stress_mat]
			set nastran_param_arrays(Stress_Dependent_Material_Property_Table:TABLE$Table_ID) [array get stress_table]
			set nastran_param_arrays(Isotropic_Material_Temperature_Dependence:IsotropicMat$mid) \
				[list Isotropic_Material_ID $mid \
					Temperature_Dependent_Youngs_Modulus {} \
					Temperature_Dependent_Shear_Modulus {} \
					Temperature_Dependent_Poissons_Ratio {} \
					Temperature_Dependent_Mass_Density {} \
					Temperature_Dependent_Thermal_Expansion_Coefficient {} \
					Temperature_Dependent_Structural_Damping_Coefficient{} \
					Temperature_Dependent_Tension_Limit {} \
					Temperature_Dependent_Compression_Limit {} \
					Temperature_Dependent_Shear_Limit {}]
			incr Table_ID
		}
	}


if 0 {
# contacts disabled
	set cnid 1
	set i 0
	foreach o {1 2 3 5 6 7 8 9 10 11 12 13 14 \
			   15 16 21 22 23 26 27 28 29 31 32} {
		set copt($o) $i
		incr i
	}
	foreach node [array names lsdyna_param_arrays] {
#puts "node: $node"
		if ![regexp ^contact: $node] continue
		catch {unset contact}
		array set contact $lsdyna_param_arrays($node)
		set ctype $contact(opt)
		#skip unsupported contact types
		if ![info exists copt($ctype)] continue
		set ctype $copt($ctype)
		set auto $contact(opt1)
		set tie $contact(opt2)
		set mue $contact(fs)
		set mued $contact(fd)

# slaves
		set sset $contact(ssidopt)
		set cfams ""
		if $sset {
			set cnode $contact(ssid2)
			if ![info exists lsdyna_param_arrays(part_set:$cnode)] {
				mess "error: could not find Slave Part Set $cnode for $node\n" red
				continue
			}
			catch {unset pset}
			array set pset $lsdyna_param_arrays(part_set:$cnode)
			foreach p [array names pset] {
				if [regexp ^fam: $p] {lappend cfams $pset($p)}
			}
		} else {
			set cfams $contact(ssid1)
		}
		
		foreach cfam $cfams {
			puts $fp  "\"$cfam\" \"CONTACT\" \"Contact$cnid\" $mue $mued $ctype $auto $tie"
		}

# masters
		set mset $contact(msidopt)
		set tfams ""
		if $mset {
			set cnode $contact(msid2)
#puts "master: $cnode"
			if {$cnode==""} {
				# copy over slaves for single surface contact
				set tfams $cfams
			} else {
				if ![info exists lsdyna_param_arrays(part_set:$cnode)] {
					mess "error: could not find Master Part Set $cnode for $node\n" red
					continue
				}
				catch {unset pset}
				array set pset $lsdyna_param_arrays(part_set:$cnode)
				foreach p [array names pset] {
					if [regexp ^fam: $p] {lappend tfams $pset($p)}
				}
			}
		} else {
			set tfams $contact(msid1)
		}
		
		foreach tfam $tfams {
			puts $fp "\"$tfam\" \"TARGET_FOR_CONTACT_NAME\" \"Contact$cnid\""
		}

		incr cnid
	}
}

# param node set bs
	foreach node [array names lsdyna_param_arrays] {
#puts "node: $node"
		if ![regexp ^set_bc: $node] continue
		catch {unset sbc}
		array set sbc $lsdyna_param_arrays($node)
		if {$sbc(type)} continue
		if {!$sbc(id)} continue
		set sid $sbc(id)
		if ![info exists NODE_SET_ID($sid)] continue
		for {set i 1} {$i<4} {incr i} {
			for {set j 1} {$j<9} {incr j} {
				if {$sbc(card$i/f$j)==""} {set sbc(card$i/f$j) 0}
			}
		}
		catch {unset force}
		catch {unset moment}
		foreach sfam $NODE_SET_ID($sid) {
			switch -exact $sbc(title) {
				"*BOUNDARY_SPC_SET" {
					set dofs ""
					for {set j 3} {$j<9} {incr j} {
						if {$sbc(card1/f$j)} {set dofs "${dofs}[expr $j-2]"}
					}
					if {$dofs==""} break
					puts $fp "\"$sfam\" \"LSDYNA_NSID\" $sid"
					if {$sbc(card1/f2)} {
						mess "Warning: Ignored CID for $sbc(title) on nsid $sid\n" red
					}
					puts $fp "\"$sfam\" \"ISPC\" 1 $dofs 0 0 1"
				}
				"*BOUNDARY_PRESCRIBED_MOTION_SET" {
					if {$sbc(card1/f3)!=2} {
						mess "Warning: VAD $sbc(card1/f3) not supported for $sbc(title) on nsid $sid\n" red
						break
					}
					catch {unset dofs}
					array set dofs {1 1 2 2 3 3 5 4 6 5 7 6}
					set dof $sbc(card1/f2)
					if ![info exists dofs($dof)] break
					set dof $dofs($dof)
					set val [get_max_load_curve_value $sbc(card1/f4)]
					if {$val==""} {
						mess "Error reading load curve id $sbc(card1/f4)\n\
								for $sbc(title) on nsid $sid\n" red
						break
					} else {
						set val [expr $sbc(card1/f5)*$val]
					}
					if {$sbc(card1/f6)} {
						mess "Warning: Ignored VID for $sbc(title) on nsid $sid\n" red
					}
					puts $fp "\"$sfam\" \"LSDYNA_NSID\" $sid"
					puts $fp "\"$sfam\" \"ISPC\" 1 $dof $val 0 1"
				}
				"*LOAD_NODE_SET" {
					set val [get_max_load_curve_value $sbc(card1/f3)]
					if {$val==""} {
						mess "error reading load curve id $sbc(card1/f3)\n\
								for $sbc(title) on nsid $sid\n" red
					} else {
						set val [expr $val*$sbc(card1/f4)]
						set dof $sbc(card1/f2)
						switch $dof {
							1 - 2 - 3 { set force($dof) $val}
							5 - 6 - 7 { set moment($dof) $val}
							default {
								mess "Warning: Ignored DOF for $sbc(title) on nsid $sid\n" red
							}
						}
					}
				}
				"*LOAD_THERMAL_CONSTANT" {
					if {$sbc(card1/f2)} {
						mess "Warning: Ignored NSEXID for $sbc(title) on nsid $sid\n" red
					}
					if {$sbc(card1/f3)} {
						mess "Warning: Ignored BOXID for $sbc(title) on nsid $sid\n" red
					}
					puts $fp "\"$sfam\" \"LSDYNA_TID\" $sid"
					puts $fp "\"$sfam\" \"TEMP\" 1 $sbc(card2/f1)"
				}
				"*INITIAL_VELOCITY" {
					if {$sbc(card1/f2)} {
						mess "Warning: Ignored NSEXID for $sbc(title) on nsid $sid\n" red
					}
					if {$sbc(card1/f3)} {
						mess "Warning: Ignored BOXID for $sbc(title) on nsid $sid\n" red
					}
					if {$sbc(card1/f4)} {
						mess "Warning: Ignored BOXID for $sbc(title) on nsid $sid\n" red
					}
					puts $fp "\"$sfam\" \"LSDYNA_VID\" $sid"
					puts -nonewline $fp "\"$sfam\" \"VELOCITY\""
					for {set i 1} {$i<=6} {incr i} {
						puts -nonewline $fp " $sbc(card2/f$i)"
					}
					puts $fp ""
				}
				"*RIGIDWALL_PLANAR" - 
				"*RIGIDWALL_PLANAR_FINITE" - 
				"*RIGIDWALL_PLANAR_MOVING" {
					if {$sbc(card1/f2)} {
						mess "Warning: Ignored NSEXID for $sbc(title) on nsid $sid\n" red 
					}
					if {$sbc(card1/f3)} {
						mess "Warning: Ignored BOXID for $sbc(title) on nsid $sid\n" red
					}
					puts $fp "\"$sfam\" \"LSDYNA_RID\" $sid"
					puts -nonewline $fp "\"$sfam\" \"RIGIDWALL\" $sbc(card1/f4)"
					for {set i 1} {$i<=8} {incr i} {
						puts -nonewline $fp " $sbc(card2/f$i)"
					}
					puts $fp ""
				}
				"*CONSTRAINED_NODE_SET" {
					puts $fp "\"$sfam\" \"LSDYNA_CNID\" $sid"
    				foreach n {type dof tf weld cid2 npr tfail epsf} {
						set $n 0
    				}
					set dof [expr $sbc(card1/f2) - 1]
					set tf $sbc(card1/f3)
					if {$tf==0} {set tf 1.0E+20}
					puts $fp "\"$sfam\" \"CONSTRAINED_NODES\" $type $dof $tf $weld $cid2 $npr $tfail $epsf"
				}
#the following bc is remapped to RBE2's as CONSTRAINED family bc and is no longer a set bc
				"*CONSTRAINED_NODAL_RIGID_BODY_UNMAPPED" {
					puts $fp "\"$sfam\" \"LSDYNA_CNID\" $sid"
    				foreach n {type dof tf cid1 pnode drflag rrflag weld cid2 npr tfail epsf} {
						set $n 0
    				}
					set type 1
					set cid1 $sbc(card1/f2)
					set pnode $sbc(card1/f3)
					if {$sbc(card1/f4)!="" && $sbc(card1/f4)} {
						mess "Warning: Ignored IPRT for $sbc(title) on nsid $sid\n" red
					}
					set drflag $sbc(card1/f5)
					if {$drflag<0} {set drflag [expr (-1*$drflag) + 7]}
					set rrflag $sbc(card1/f6)
					if {$rrflag<0} {set rrflag [expr (-1*$rrflag) + 7]}
					puts $fp "\"$sfam\" \"CONSTRAINED_NODES\" $type $dof $tf $cid1 $pnode $drflag $rrflag $weld $cid2 $npr $tfail $epsf"
				}
			}
		}

		foreach sfam $NODE_SET_ID($sid) {
			if [info exists force] {
				puts $fp "\"$sfam\" \"LSDYNA_FID\" $sid"
				puts -nonewline $fp "\"$sfam\" \"FORCE\" 1 0 1.0"
				foreach i {1 2 3} {
					if [info exists force($i)] {
						puts -nonewline $fp " $force($i)"
					} else {
						puts -nonewline $fp " 0.0"
					}
				}
				puts $fp ""
			}
			if [info exists moment] {
				puts $fp "\"$sfam\" \"LSDYNA_FID\" $sid"
				puts -nonewline $fp "\"$sfam\" \"MOMENT\" 1 0 1.0"
				foreach i {5 6 7} {
					if [info exists moment($i)] {
						puts -nonewline $fp " $moment($i)"
					} else {
						puts -nonewline $fp " 0.0"
					}
				}
				puts $fp ""
			}
		}
	}

	close $fp

# local coord systems
  if [info exists lsdyna_param_arrays(define)] {
	array set define $lsdyna_param_arrays(define)
	foreach node [array names define] {
#puts "node: $node, val: $define($node)"
		if ![regexp ^coord: $node] continue
		if ![regexp /opt$ $node] continue
		if $define($node) continue
		set lnode [file dirname $node]
		set lcsnode($lnode) 1
	}

	foreach node [array names lcsnode] {
		foreach n {name id x0 y0 z0 xp yp zp xl yl zl} {
			set lcs($n) $define($node/$n)
		}
		#set name $lcs(name)
		set nastran Local_Coordinates:LocalCoordinateSystem$lcs(id)
		set ${nastran}(Create) 1
		#set ${nastran}(name) $name
		#set ${nastran}(number) $lcs(id)
		set ${nastran}(Coordinate_System_ID) $lcs(id)
		#set ${nastran}(type) Cartesian
		set ${nastran}(Type) Rectangular
		#set ${nastran}(dby) 3
		#set ${nastran}(ref) Global
		set ${nastran}(Reference_Coordinate_System) 0
		#set ${nastran}(scale) 1.0
		set ${nastran}(Scale) 1.0
		set ${nastran}(Pt1_1) $lcs(x0)
		set ${nastran}(Pt1_2) $lcs(y0)
		set ${nastran}(Pt1_3) $lcs(z0)
		set zvec [vec_cross [list $lcs(xl) $lcs(yl) $lcs(zl)] [list $lcs(xp) $lcs(yp) $lcs(zp)]]
		#set zvec [vec_normalize $zvec]
		set ${nastran}(Pt2_1) [lindex $zvec 0]
		set ${nastran}(Pt2_2) [lindex $zvec 1]
		set ${nastran}(Pt2_3) [lindex $zvec 2]
		set ${nastran}(Pt3_1) $lcs(xl)
		set ${nastran}(Pt3_2) $lcs(yl)
		set ${nastran}(Pt3_3) $lcs(zl)
		set nastran_param_arrays($nastran) [array get $nastran]
	}
  }

# gravity
	set gravity 0
	set g1 0.0
	set g2 0.0
	set g3 0.0
	foreach node [array names lsdyna_param_arrays] {
#puts "node: $node"
		if ![regexp ^bodyload: $node] continue
		catch {unset grav}
		array set grav $lsdyna_param_arrays($node)
		set opt $grav(OPTION1)
#puts "opt: $opt"
		switch $opt {
			1 - 2 - 3 {
				set gravity 1
#puts "LCID: $grav(LCID)"
#puts "SF: $grav(SF)"
				set val [get_max_load_curve_value $grav(LCID)]
				if {$val!=""} {set g$opt [expr $val*$grav(SF)]}
			}
		}
	}
	if $gravity {
		set nastran_param_arrays(Gravity_Load) [list \
			SID "" CID 0 Create 1 Bulk_Data_Section -1 Acceleration_Vector_Scale 1.0 \
			Acceleration_Vector_Component_1 $g1 \
			Acceleration_Vector_Component_2 $g2 \
			Acceleration_Vector_Component_3 $g3 \
		]
	}
		
#Title
	if [info exists lsdyna_param_arrays(title)] {
		array set title $lsdyna_param_arrays(title)
#this doesn't seem to work before loading a project
#		setupNastranRunDEZ set lsdyna_title $title(title)
	}

# include files
	if [info exists lsdyna_param_arrays(custom)] {
		global lsdyna_params_data
		array set includes $lsdyna_param_arrays(custom)
		set iid 1
		foreach node [array names includes] {
#puts "node: $node"
			if ![regexp ^F1:F1 $node] continue
			if [regexp /str1$ $node] {
				set lsdyna_params_data(Include$iid) $includes($node)
				incr iid
			}
		}
	}

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

proc get_max_load_curve_value {id} {
	global lsdyna_param_arrays
	if ![info exists lsdyna_param_arrays] {return ""}
	if ![info exists lsdyna_param_arrays(define)] {return ""}
	array set define $lsdyna_param_arrays(define)
	set got 0
	foreach node [array names define] {
#puts "node: $node, val: $define($node)"
		if ![regexp ^lcurv: $node] continue
		if ![regexp /id$ $node] continue
		if {$define($node)!=$id} continue
		set got 1
		break
	}
#puts "node: $node, got: $got"
	if {!$got} { return ""}
	set lcurv [file dirname $node]
#puts "lcurv: $lcurv"
	set max ""
	foreach node [array names define] {
		if ![regexp ^${lcurv}/ $node] continue
		if ![regexp /point:point $node] continue
		if ![regexp /y$ $node] continue
		if {$max==""} {set max $define($node)}
		if {$max<$define($node)} {set max $define($node)}
	}
	return $max
}	
	 

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

proc lsdyna_params_load_solve_data {file} {
	global lsdyna_param_arrays
	catch {unset lsdyna_param_arrays}
	
    if ![file exists $file] { set_lsdyna_params; return }

    set fp [open $file r]
	set inner 0
#	set lsdyna_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 lsdyna_param_arrays] $array]==-1} {
#				lappend emax_param_arrays $array
			} else {
				mess "merging duplicate LS-Dyna 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 lsdyna_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 lsdyna_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 LS-Dyna...\n"
    close $fp
}

proc lsdyna_params_save_solve_data {file} {
	global lsdyna_saved_params_data lsdyna_param_arrays
    
    set fp [open $file w]
    puts $fp "# solver params file written for AI*Environment on [cmd_date]"
    puts $fp "## solver LS-DYNA3D"

	if ![info exists lsdyna_param_arrays] { set_lsdyna_params }
	catch {unset lsdyna_saved_params_data}

    foreach array [array names lsdyna_param_arrays] {
#		global $array
		foreach {n v} $lsdyna_param_arrays($array) { set ${array}($n) $v }
		set last ""
		foreach key [lsort [array names $array]] {
			set lsdyna_saved_params_data($array,$key) 0
		}
		set key_list [lsort [array names $array]]
#mess "array: $array\n"
#mess "key_list: $key_list\n"
		lsdyna_params_save_solve_array $fp $array $last $key_list
    }
    close $fp
    mess "Saved AI*Env solver data for LS-Dyna...\n"
}

proc lsdyna_params_save_solve_array {fp arr {last0 ""} {list0 ""}} {
	global lsdyna_saved_params_data
#    upvar #0 $arr array
	
	if { $list0=="" } return
	if { $last0=="" } {
		set outlist ""
		set fwdlist ""
		foreach key $list0 {
			if {$lsdyna_saved_params_data($arr,$key)} continue
			if {![regexp ^${last0} $key]} continue
			if [is_solve_level_end $key $last0] {
				set lsdyna_saved_params_data($arr,$key) 1
				lappend outlist $key
			} 
		}
		foreach key $list0 {
			if {$lsdyna_saved_params_data($arr,$key)} continue
			lappend fwdlist $key
		}
		lsdyna_params_begin_level $fp $arr $last0 $outlist
		lsdyna_params_save_solve_array $fp $arr [get_new_last_list $fwdlist $last0] $fwdlist
		lsdyna_params_end_level $fp $arr $last0
	} else {
	foreach last $last0 {
		set outlist ""
		set fwdlist ""
		foreach key $list0 {
			if {$lsdyna_saved_params_data($arr,$key)} continue
			if {![regexp ^${last} $key]} continue
			if [is_solve_level_end $key $last] {
				set lsdyna_saved_params_data($arr,$key) 1
				lappend outlist $key
			} else {
				lappend fwdlist $key
			}
		}
		lsdyna_params_begin_level $fp $arr $last $outlist
		lsdyna_params_save_solve_array $fp $arr [get_new_last_list $fwdlist $last] $fwdlist
		lsdyna_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 lsdyna_params_begin_level {fp arr last outlist} {
	global lsdyna_param_arrays
#    upvar #0 $arr array
	foreach {n v} $lsdyna_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 lsdyna_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 
}

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





