[688] | 1 | #!/bin/sh |
---|
[2415] | 2 | # -*- mode: Tcl -*- |
---|
[1206] | 3 | # ====================================================================== |
---|
| 4 | # AUTHOR: Derrick S. Kearney, Purdue University |
---|
[1214] | 5 | # Copyright (c) 2004-2008 Purdue Research Foundation |
---|
[1206] | 6 | # |
---|
| 7 | # See the file "license.terms" for information on usage and |
---|
| 8 | # redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
---|
| 9 | # ====================================================================== |
---|
[688] | 10 | #\ |
---|
[1986] | 11 | dir=`dirname $0` ; \ |
---|
| 12 | . $dir/rappture.env ; \ |
---|
[2789] | 13 | exec $dir/tclsh "$0" "$@" |
---|
[688] | 14 | |
---|
| 15 | package require Rappture |
---|
| 16 | package require RapptureGUI |
---|
| 17 | |
---|
| 18 | proc defaultHandler {child} { |
---|
| 19 | set childchildList {} |
---|
[693] | 20 | set units [$child get "units"] |
---|
| 21 | # this is for nanowire |
---|
| 22 | if {[string is integer -strict $units]} { |
---|
| 23 | set units "" |
---|
| 24 | } |
---|
| 25 | set defaultVal [$child get "default"] |
---|
| 26 | if {"" != $defaultVal} { |
---|
| 27 | if {"" != $units} { |
---|
| 28 | set defaultVal [Rappture::Units::convert $defaultVal \ |
---|
| 29 | -context $units -to $units -units on] |
---|
[688] | 30 | } |
---|
[693] | 31 | $child put "current" $defaultVal |
---|
[688] | 32 | } else { |
---|
| 33 | if {"components" != [$child element -as type]} { |
---|
| 34 | set childchildList [$child children] |
---|
| 35 | } elseif {"parameters" != [$child element -as type]} { |
---|
| 36 | set childchildList [$child children] |
---|
[693] | 37 | } else { |
---|
| 38 | set childchildList [$child children] |
---|
[688] | 39 | } |
---|
| 40 | } |
---|
| 41 | return $childchildList |
---|
| 42 | } |
---|
| 43 | |
---|
| 44 | proc numberHandler {child} { |
---|
| 45 | set value "" |
---|
| 46 | set units [$child get "units"] |
---|
| 47 | set min [$child get "min"] |
---|
| 48 | set max [$child get "max"] |
---|
| 49 | |
---|
| 50 | if {"" != $min} { |
---|
| 51 | if {"" != $units} { |
---|
[693] | 52 | # check to see if the user added units to their min value |
---|
| 53 | # apps like mosfet need this check. |
---|
| 54 | set min [Rappture::Units::convert $min \ |
---|
| 55 | -context $units -to $units -units off] |
---|
| 56 | if {[string is double -strict $min]} { |
---|
| 57 | # pass |
---|
| 58 | } |
---|
[688] | 59 | } |
---|
| 60 | } |
---|
| 61 | |
---|
| 62 | if {"" != $max} { |
---|
| 63 | if {"" != $units} { |
---|
[693] | 64 | # check to see if the user added units to their min value |
---|
| 65 | # apps like mosfet need this check. |
---|
| 66 | set max [Rappture::Units::convert $max \ |
---|
| 67 | -context $units -to $units -units off] |
---|
| 68 | if {[string is double -strict $max]} { |
---|
| 69 | # pass |
---|
| 70 | } |
---|
[688] | 71 | } |
---|
| 72 | } |
---|
| 73 | |
---|
[693] | 74 | if {"yes" == [$child get "simset"]} { |
---|
| 75 | $child remove "simset" |
---|
[688] | 76 | } else { |
---|
| 77 | if { ("" != $min) && ("" != $max) } { |
---|
| 78 | set value [random $min $max] |
---|
| 79 | $child put current $value$units |
---|
| 80 | } else { |
---|
[693] | 81 | defaultHandler $child |
---|
[688] | 82 | } |
---|
| 83 | } |
---|
| 84 | } |
---|
| 85 | |
---|
| 86 | proc integerHandler {child} { |
---|
| 87 | set value "" |
---|
| 88 | set units [$child get "units"] |
---|
| 89 | set min [$child get "min"] |
---|
| 90 | set max [$child get "max"] |
---|
| 91 | |
---|
[693] | 92 | # nanowire needs this because they set units == 0 and 1 ??? |
---|
| 93 | if {[string is integer -strict $units]} { |
---|
| 94 | set units "" |
---|
| 95 | } |
---|
| 96 | |
---|
[688] | 97 | if {"" != $min} { |
---|
| 98 | if {"" != $units} { |
---|
[693] | 99 | # check to see if the user added units to their min value |
---|
| 100 | # apps like mosfet need this check. |
---|
| 101 | set min [Rappture::Units::convert $min \ |
---|
| 102 | -context $units -to $units -units off] |
---|
| 103 | if {[string is integer -strict $min]} { |
---|
| 104 | # pass |
---|
| 105 | } |
---|
[688] | 106 | } |
---|
| 107 | } |
---|
| 108 | |
---|
| 109 | if {"" != $max} { |
---|
| 110 | if {"" != $units} { |
---|
[693] | 111 | # check to see if the user added units to their min value |
---|
| 112 | # apps like mosfet need this check. |
---|
| 113 | set max [Rappture::Units::convert $max \ |
---|
| 114 | -context $units -to $units -units off] |
---|
| 115 | if {[string is integer -strict $max]} { |
---|
| 116 | # pass |
---|
| 117 | } |
---|
[688] | 118 | } |
---|
| 119 | } |
---|
| 120 | |
---|
[693] | 121 | if {"yes" == [$child get "simset"]} { |
---|
| 122 | $child remove "simset" |
---|
[688] | 123 | } else { |
---|
| 124 | if { ("" != $min) && ("" != $max) } { |
---|
| 125 | set value [randomInt $min $max] |
---|
| 126 | $child put current $value$units |
---|
| 127 | } else { |
---|
[693] | 128 | defaultHandler $child |
---|
[688] | 129 | } |
---|
| 130 | } |
---|
| 131 | |
---|
| 132 | } |
---|
| 133 | |
---|
| 134 | proc booleanHandler {child} { |
---|
[693] | 135 | if {"yes" == [$child get "simset"]} { |
---|
| 136 | $child remove "simset" |
---|
[688] | 137 | } else { |
---|
| 138 | set value [expr {int(rand()*2)}] |
---|
[693] | 139 | if {$value == 1} { |
---|
[688] | 140 | set value "yes" |
---|
| 141 | } else { |
---|
| 142 | set value "no" |
---|
| 143 | } |
---|
| 144 | $child put "current" $value |
---|
| 145 | } |
---|
| 146 | } |
---|
| 147 | |
---|
[693] | 148 | proc loaderHandler {child toolDir} { |
---|
| 149 | |
---|
| 150 | set exDir [file join $toolDir "examples"] |
---|
| 151 | if {! [file isdirectory $exDir]} { |
---|
[1210] | 152 | # in this case we should try to keep processing, not exit |
---|
| 153 | puts "could not find examples directory: $exDir" |
---|
[693] | 154 | exit 0 |
---|
| 155 | } |
---|
| 156 | |
---|
| 157 | set exPathExp [$child get example] |
---|
| 158 | set fpath [file join $exDir $exPathExp] |
---|
| 159 | set exFileList [glob -nocomplain $fpath] |
---|
| 160 | |
---|
| 161 | if {0 == [llength $exFileList]} { |
---|
| 162 | puts "while searching examples directory: $exDir" |
---|
| 163 | puts "could not open find files matching regex: $exPathExp" |
---|
| 164 | set defaultEx [$child get "default"] |
---|
| 165 | if {[file exists [file join $exDir $defaultEx]]} { |
---|
| 166 | lappend exFileList $defaultEx |
---|
| 167 | puts "using default example file" |
---|
| 168 | } else { |
---|
| 169 | puts "default example file does not exists, exiting" |
---|
| 170 | exit 0; |
---|
| 171 | } |
---|
| 172 | } |
---|
| 173 | |
---|
| 174 | set importExFileIdx [expr {int(rand()*[llength $exFileList])}] |
---|
| 175 | set importExFile [lindex $exFileList $importExFileIdx] |
---|
| 176 | |
---|
| 177 | if {! [file exists $importExFile]} { |
---|
| 178 | # importExFile does not exist |
---|
| 179 | } |
---|
| 180 | |
---|
| 181 | set exlib [Rappture::library $importExFile] |
---|
| 182 | |
---|
| 183 | # get the about.label from the file |
---|
| 184 | # if about.label does not exist, use the file name |
---|
| 185 | set importExLabel [$exlib get about.label] |
---|
| 186 | if {"" != $importExLabel} { |
---|
| 187 | set currentVal $importExLabel |
---|
| 188 | } else { |
---|
| 189 | set currentVal [file tail $importExFile] |
---|
| 190 | } |
---|
| 191 | |
---|
| 192 | $child put "current" $currentVal |
---|
| 193 | |
---|
| 194 | set exlibChildList [::Rappture::entities -as object $exlib "input"] |
---|
| 195 | return $exlibChildList |
---|
| 196 | } |
---|
| 197 | |
---|
| 198 | proc groupHandler {child} { |
---|
| 199 | return [$child children -as object] |
---|
| 200 | } |
---|
| 201 | |
---|
[1612] | 202 | proc choiceHandler {valType child} { |
---|
[693] | 203 | if {"yes" == [$child get "simset"]} { |
---|
| 204 | $child remove "simset" |
---|
| 205 | } else { |
---|
| 206 | set optList [$child children -as object -type option] |
---|
[1741] | 207 | set optLib "" |
---|
[1612] | 208 | set value "" |
---|
[1741] | 209 | if {[llength $optList] > 0} { |
---|
| 210 | if {"random" == $valType} { |
---|
| 211 | set optIdx [expr {int(rand()*[llength $optList])}] |
---|
| 212 | set optLib [lindex $optList $optIdx] |
---|
| 213 | set value [$optLib get value] |
---|
| 214 | } elseif {"default" == $valType} { |
---|
| 215 | set defaultVal [$child get default] |
---|
| 216 | foreach optLib $optList { |
---|
| 217 | set label [$optLib get about.label] |
---|
| 218 | set valTag [$optLib get value] |
---|
| 219 | if {($defaultVal == $label) || ($defaultVal == $valTag)} { |
---|
| 220 | set value $valTag |
---|
| 221 | break |
---|
| 222 | } |
---|
[1612] | 223 | } |
---|
| 224 | } |
---|
| 225 | |
---|
[1741] | 226 | if {"" == $value} { |
---|
| 227 | set optLib [lindex $optList 0] |
---|
| 228 | set value [$optLib get value] |
---|
| 229 | if {"" == $value} { |
---|
| 230 | set value [$optLib get about.label] |
---|
| 231 | } |
---|
| 232 | } |
---|
[693] | 233 | } |
---|
| 234 | $child put "current" $value |
---|
| 235 | } |
---|
| 236 | } |
---|
| 237 | |
---|
[1210] | 238 | proc defaultize {xmlobj toolDir} { |
---|
[688] | 239 | set childList [$xmlobj children -as object input] |
---|
[693] | 240 | |
---|
| 241 | while {[llength $childList]} { |
---|
| 242 | set child [lrange $childList 0 0] |
---|
| 243 | set childList [lreplace $childList 0 0] |
---|
| 244 | |
---|
| 245 | switch -- [$child element -as type] { |
---|
| 246 | number { defaultHandler $child } |
---|
| 247 | integer { defaultHandler $child } |
---|
| 248 | boolean { defaultHandler $child } |
---|
| 249 | string { defaultHandler $child } |
---|
[1612] | 250 | choice { choiceHandler default $child } |
---|
[1210] | 251 | loader { loaderHandler $child $toolDir } |
---|
[693] | 252 | structure { defaultHandler $child } |
---|
| 253 | group { set cclist [groupHandler $child] |
---|
| 254 | set childList [concat $childList $cclist] } |
---|
[1612] | 255 | phase { set cclist [groupHandler $child] |
---|
| 256 | set childList [concat $childList $cclist] } |
---|
[693] | 257 | default { defaultHandler $child } |
---|
[688] | 258 | } |
---|
| 259 | } |
---|
| 260 | } |
---|
| 261 | |
---|
[693] | 262 | proc randomize {presetArr xmlobj toolDir} { |
---|
[688] | 263 | upvar $presetArr presets |
---|
| 264 | set childList [$xmlobj children -as object input] |
---|
| 265 | |
---|
[693] | 266 | while {[llength $childList]} { |
---|
[688] | 267 | |
---|
[693] | 268 | set child [lrange $childList 0 0] |
---|
| 269 | set childList [lreplace $childList 0 0] |
---|
[688] | 270 | |
---|
[693] | 271 | set cpath [cleanPath [$child element -as path]] |
---|
| 272 | |
---|
[688] | 273 | set ppath [$child parent -as path] |
---|
| 274 | set cPresets [array get presets $cpath*] |
---|
| 275 | |
---|
| 276 | foreach {cPresetsPath cPresetsVal} $cPresets { |
---|
| 277 | set cutIdx [expr {[string length $cpath] + 1}] |
---|
| 278 | set iPath [string range $cPresetsPath $cutIdx end] |
---|
[693] | 279 | |
---|
| 280 | # apply the preset value and remove from preset array |
---|
[688] | 281 | $child put $iPath $cPresetsVal |
---|
| 282 | unset presets($cPresetsPath) |
---|
[693] | 283 | |
---|
| 284 | # if the value was set on a current node, then set a preset flag |
---|
[1214] | 285 | if {"current" == $iPath} { |
---|
| 286 | $child put simset "yes" |
---|
[693] | 287 | } |
---|
[688] | 288 | } |
---|
| 289 | |
---|
| 290 | switch -- [$child element -as type] { |
---|
[693] | 291 | number { numberHandler $child } |
---|
| 292 | integer { integerHandler $child } |
---|
| 293 | boolean { booleanHandler $child } |
---|
| 294 | string { defaultHandler $child } |
---|
[1612] | 295 | choice { choiceHandler random $child } |
---|
[693] | 296 | loader { |
---|
| 297 | set cpath [$child element -as path] |
---|
| 298 | set ccList [loaderHandler $child $toolDir] |
---|
| 299 | foreach cc $ccList { |
---|
| 300 | set ccpath [$cc element -as path] |
---|
| 301 | # even though the loader might have been returned in ccList |
---|
| 302 | # do not add the loader back to the childList or you might |
---|
| 303 | # get an infinite loop |
---|
| 304 | if {$cpath != $ccpath} { |
---|
| 305 | set ccpath [cleanPath $ccpath] |
---|
| 306 | $xmlobj copy $ccpath from $cc "" |
---|
| 307 | lappend childList [$xmlobj element -as object $ccpath] |
---|
| 308 | } |
---|
| 309 | } |
---|
| 310 | } |
---|
| 311 | structure { defaultHandler $child } |
---|
| 312 | group { |
---|
| 313 | set ccList [groupHandler $child] |
---|
| 314 | set childList [concat $childList $ccList] |
---|
| 315 | } |
---|
[1612] | 316 | phase { |
---|
| 317 | set ccList [groupHandler $child] |
---|
| 318 | set childList [concat $childList $ccList] |
---|
| 319 | } |
---|
[693] | 320 | default { defaultHandler $child } |
---|
[688] | 321 | } |
---|
| 322 | } |
---|
| 323 | } |
---|
| 324 | |
---|
[693] | 325 | proc random {m M} { |
---|
[1612] | 326 | return [expr {$m+(rand()*($M-$m))}] |
---|
[688] | 327 | } |
---|
| 328 | |
---|
[693] | 329 | proc randomInt {m M} { |
---|
[1612] | 330 | return [expr {int(rand()*($M-$m+1)+$m)}] |
---|
[693] | 331 | } |
---|
| 332 | |
---|
| 333 | proc cleanPath { path } { |
---|
| 334 | if {"." == [string index $path 0]} { |
---|
| 335 | # this is because tcl's library module (element -as path) |
---|
| 336 | # returns a crazy dot in the 0th position |
---|
| 337 | set path [string range $path 1 end] |
---|
| 338 | } |
---|
| 339 | return $path |
---|
| 340 | } |
---|
| 341 | |
---|
[688] | 342 | proc parsePathVal {listVar returnVar} { |
---|
| 343 | upvar $listVar params |
---|
| 344 | upvar $returnVar presetArr |
---|
| 345 | catch {unset presetArr} |
---|
| 346 | |
---|
| 347 | # initialize variables |
---|
| 348 | set pathValStr "" |
---|
| 349 | set match "junk" |
---|
| 350 | |
---|
| 351 | while {"" != $match} { |
---|
| 352 | set match "" |
---|
| 353 | set path "" |
---|
| 354 | set val "" |
---|
[693] | 355 | set val2 "" |
---|
| 356 | set val3 "" |
---|
| 357 | set val4 "" |
---|
[688] | 358 | set pathValStr [string trimleft [join $params " "]] |
---|
| 359 | |
---|
| 360 | # search the params for: |
---|
| 361 | # 1) xml path |
---|
| 362 | # 2) followed by = sign |
---|
| 363 | # 3) followed by a starting " sign |
---|
| 364 | # 4) followed by any text (including spaces) |
---|
| 365 | # 5) followed by an ending " sign |
---|
| 366 | # ex: input.number(temperature).current="400K" |
---|
| 367 | # ex: input.number(temperature).current=400K |
---|
| 368 | # ex: input.string(blahh).current="hi momma, i love you!" |
---|
| 369 | # \"([^\"]+)\" |
---|
| 370 | # ((\"([^\"]+)\")|(:([^:]+):)|(\'([^\']+)\')|([^\s]+)) |
---|
| 371 | regexp -expanded { |
---|
| 372 | ( |
---|
[693] | 373 | [a-zA-Z0-9]+(\([a-zA-Z0-9._]+\))? |
---|
| 374 | (\.[a-zA-Z0-9]+(\([a-zA-Z0-9._]+\))?)* |
---|
[688] | 375 | ) |
---|
| 376 | = |
---|
| 377 | ((\"([^\"]+)\")|(\'([^\']+)\')|([^\s]+)) |
---|
[693] | 378 | } $pathValStr match path junk junk junk val junk val2 junk val3 val4 |
---|
| 379 | |
---|
| 380 | |
---|
[688] | 381 | if {"" != $match} { |
---|
| 382 | # remove the matching element from orphaned params list |
---|
| 383 | foreach p [split $match] { |
---|
| 384 | set paramsIdx [lsearch -exact $params $p] |
---|
| 385 | set params [lreplace $params $paramsIdx $paramsIdx] |
---|
| 386 | } |
---|
| 387 | |
---|
[693] | 388 | if {("" != $val2) && ("" == $val3) && ("" == $val4)} { |
---|
| 389 | set val $val2 |
---|
| 390 | } elseif {("" == $val2) && ("" != $val3) && ("" == $val4)} { |
---|
| 391 | set val $val3 |
---|
| 392 | } elseif {("" == $val2) && ("" == $val3) && ("" != $val4)} { |
---|
| 393 | set val $val4 |
---|
| 394 | } |
---|
| 395 | |
---|
[688] | 396 | # add the name and value to our preset array |
---|
| 397 | set presetArr($path) $val |
---|
| 398 | } |
---|
| 399 | } |
---|
| 400 | } |
---|
| 401 | |
---|
| 402 | proc printHelp {} { |
---|
[1214] | 403 | set help { |
---|
| 404 | simsim [OPTIONS] [CONST] |
---|
| 405 | |
---|
| 406 | simulator simulator - simulate simulation |
---|
| 407 | |
---|
| 408 | OPTIONS: |
---|
| 409 | -tool <path> - use the tool.xml file specified at <path> |
---|
[1611] | 410 | -values <valtype> - the type of values used to populate driver file. |
---|
[1214] | 411 | valid <valtype>'s include: |
---|
[1611] | 412 | "default" - replace <current> values with <default>'s, |
---|
| 413 | "current" - use <current> values (ie do nothing), |
---|
| 414 | "random" - generate random values for <current>. |
---|
[1214] | 415 | -driver <path> - write a driver file to <path>. |
---|
| 416 | -compare <path> - compare the results with the run.xml |
---|
| 417 | file at <path>. |
---|
[1986] | 418 | -runfile <path> - move the run file to <path> |
---|
[1214] | 419 | -nosim - no simulation. |
---|
| 420 | -help - print this help menu. |
---|
| 421 | |
---|
| 422 | CONST: |
---|
| 423 | when -values is set to random, constant values can be set for |
---|
| 424 | specific inputs. the general form for constant values is: |
---|
| 425 | |
---|
| 426 | xmlpath(id)=value |
---|
| 427 | |
---|
| 428 | where xmlpath is the path of the element in the xml tree, |
---|
| 429 | id is the id of the xml node and value is the constant value |
---|
| 430 | you want to place in the element. the following the constant |
---|
| 431 | will set input.number(Ef).current to the value "2eV": |
---|
| 432 | |
---|
| 433 | input.number(Ef)=2eV |
---|
| 434 | |
---|
| 435 | EXAMPLES: |
---|
| 436 | simulate using ./tool.xml, default values, no comparisons or driver |
---|
| 437 | simsim |
---|
| 438 | |
---|
| 439 | simulate using ./tool.xml, random values, no comparisons or driver |
---|
| 440 | simsim -values random |
---|
| 441 | |
---|
| 442 | from ./tool.xml, create a driver file named "mydriverfile.xml" |
---|
| 443 | with default values |
---|
| 444 | simsim -nosim -driver mydriverfile.xml |
---|
| 445 | |
---|
| 446 | from ./tool.xml, create a driver file named "mydriverfile.xml" |
---|
| 447 | with random values |
---|
| 448 | simsim -values random -nosim -driver mydriverfile.xml |
---|
| 449 | |
---|
| 450 | from ./tool.xml, simulate with random values but set |
---|
| 451 | input.number(Ef) to "2eV" |
---|
| 452 | simsim -values random input.number(Ef).current=2eV |
---|
| 453 | |
---|
[1611] | 454 | run a simulation using the current values from driver.xml, |
---|
| 455 | "-values current" is only useful if you are asking |
---|
| 456 | simsim to run the simulation and you provide a driver file. |
---|
[1214] | 457 | simsim -tool driver.xml -values current |
---|
| 458 | |
---|
| 459 | compare two xml file, don't do a simulation, don't print a driver.xml |
---|
| 460 | simsim -tool driver.xml -compare previousrun.xml -nosim |
---|
| 461 | |
---|
| 462 | run a simulation and compare the result to previousrun.xml |
---|
| 463 | simsim -compare previousrun.xml |
---|
| 464 | |
---|
| 465 | } |
---|
| 466 | puts $help |
---|
[688] | 467 | exit 0 |
---|
| 468 | } |
---|
| 469 | |
---|
| 470 | proc diffs {xmlobj1 xmlobj2} { |
---|
| 471 | set rlist "" |
---|
| 472 | |
---|
| 473 | # query the values for all entities in both objects |
---|
| 474 | set thisv [concat [Rappture::entities $xmlobj1 "input"] [Rappture::entities $xmlobj1 "output"]] |
---|
| 475 | set otherv [concat [Rappture::entities $xmlobj2 "input"] [Rappture::entities $xmlobj2 "output"]] |
---|
| 476 | |
---|
| 477 | # scan through values for this object and compare against other one |
---|
| 478 | foreach path $thisv { |
---|
| 479 | set i [lsearch -exact $otherv $path] |
---|
| 480 | if {$i < 0} { |
---|
| 481 | foreach {raw norm} [value $xmlobj1 $path] break |
---|
| 482 | lappend rlist - $path $raw "" |
---|
| 483 | } else { |
---|
| 484 | foreach {traw tnorm} [value $xmlobj1 $path] break |
---|
| 485 | foreach {oraw onorm} [value $xmlobj2 $path] break |
---|
| 486 | if {![string equal $tnorm $onorm]} { |
---|
| 487 | lappend rlist c $path $traw $oraw |
---|
| 488 | } |
---|
| 489 | set otherv [lreplace $otherv $i $i] |
---|
| 490 | } |
---|
| 491 | } |
---|
| 492 | |
---|
| 493 | #add any values left over in the other object |
---|
| 494 | foreach path $otherv { |
---|
| 495 | foreach {oraw onorm} [Rappture::LibraryObj::value $xmlobj2 $path] break |
---|
| 496 | lappend rlist + $path "" $oraw |
---|
| 497 | } |
---|
| 498 | return $rlist |
---|
| 499 | } |
---|
| 500 | |
---|
| 501 | proc value {libobj path} { |
---|
| 502 | switch -- [$libobj element -as type $path] { |
---|
| 503 | structure { |
---|
| 504 | set raw $path |
---|
| 505 | # try to find a label to represent the structure |
---|
| 506 | set val [$libobj get $path.about.label] |
---|
| 507 | if {"" == $val} { |
---|
| 508 | set val [$libobj get $path.current.about.label] |
---|
| 509 | } |
---|
| 510 | if {"" == $val} { |
---|
| 511 | if {[$libobj element $path.current] != ""} { |
---|
| 512 | set comps [$libobj children $path.current.components] |
---|
| 513 | set val "<structure> with [llength $comps] components" |
---|
| 514 | } else { |
---|
| 515 | set val "<structure>" |
---|
| 516 | } |
---|
| 517 | } |
---|
| 518 | return [list $raw $val] |
---|
| 519 | } |
---|
| 520 | number { |
---|
| 521 | # get the usual value... |
---|
| 522 | set raw "" |
---|
| 523 | if {"" != [$libobj element $path.current]} { |
---|
| 524 | set raw [$libobj get $path.current] |
---|
| 525 | } elseif {"" != [$libobj element $path.default]} { |
---|
| 526 | set raw [$libobj get $path.default] |
---|
| 527 | } |
---|
| 528 | if {"" != $raw} { |
---|
| 529 | set val $raw |
---|
| 530 | # then normalize to default units |
---|
| 531 | set units [$libobj get $path.units] |
---|
| 532 | if {"" != $units} { |
---|
| 533 | set val [Rappture::Units::convert $val \ |
---|
| 534 | -context $units -to $units -units off] |
---|
| 535 | } |
---|
| 536 | } |
---|
| 537 | return [list $raw $val] |
---|
| 538 | } |
---|
| 539 | curve { |
---|
| 540 | set raw "" |
---|
| 541 | if {"" != [$libobj element $path.component.xy]} { |
---|
| 542 | set raw [$libobj get $path.component.xy] |
---|
| 543 | } |
---|
| 544 | return [list $raw $raw] |
---|
| 545 | } |
---|
| 546 | log { |
---|
| 547 | set raw "" |
---|
| 548 | if {"" != [$libobj element]} { |
---|
| 549 | set raw [$libobj get] |
---|
| 550 | } |
---|
| 551 | return [list $raw $raw] |
---|
| 552 | } |
---|
| 553 | cloud { |
---|
| 554 | set raw "" |
---|
| 555 | if {"" != [$libobj element $path.points]} { |
---|
| 556 | set raw [$libobj get $path.points] |
---|
| 557 | } |
---|
| 558 | return [list $raw $raw] |
---|
| 559 | } |
---|
| 560 | field { |
---|
| 561 | set raw "" |
---|
| 562 | if {"" != [$libobj element $path.component.values]} { |
---|
| 563 | set raw [$libobj get $path.component.values] |
---|
| 564 | } |
---|
| 565 | return [list $raw $raw] |
---|
| 566 | } |
---|
| 567 | |
---|
| 568 | |
---|
| 569 | } |
---|
| 570 | |
---|
| 571 | # for all other types, get the value (current, or maybe default) |
---|
| 572 | set raw "" |
---|
| 573 | if {"" != [$libobj element $path.current]} { |
---|
| 574 | set raw [$libobj get $path.current] |
---|
| 575 | } elseif {"" != [$libobj element $path.default]} { |
---|
| 576 | set raw [$libobj get $path.default] |
---|
| 577 | } |
---|
| 578 | return [list $raw $raw] |
---|
| 579 | } |
---|
| 580 | |
---|
[1206] | 581 | proc compare {orig result} { |
---|
| 582 | if {"" == $orig} { |
---|
| 583 | return |
---|
| 584 | } |
---|
| 585 | if {"" == $result} { |
---|
| 586 | return |
---|
| 587 | } |
---|
[688] | 588 | |
---|
[1206] | 589 | if {![Rappture::library isvalid $orig]} { |
---|
| 590 | set origObj [Rappture::library $orig] |
---|
| 591 | if {![Rappture::library isvalid $origObj]} { |
---|
| 592 | puts "cannot create Rappture library from $orig\n" |
---|
| 593 | return |
---|
| 594 | } |
---|
| 595 | } else { |
---|
| 596 | set origObj $orig |
---|
| 597 | } |
---|
[688] | 598 | |
---|
[1206] | 599 | if {![Rappture::library isvalid $result]} { |
---|
| 600 | set resultObj [Rappture::library $result] |
---|
| 601 | if {![Rappture::library isvalid $resultObj]} { |
---|
| 602 | puts "cannot create Rappture library from $result\n" |
---|
| 603 | return |
---|
| 604 | } |
---|
| 605 | } else { |
---|
| 606 | set resultObj $result |
---|
| 607 | } |
---|
[688] | 608 | |
---|
[1206] | 609 | foreach {op vpath oldval newval} [diffs $origObj $resultObj] { |
---|
| 610 | puts "$op $vpath $oldval $newval" |
---|
| 611 | } |
---|
| 612 | } |
---|
| 613 | |
---|
[1214] | 614 | proc parseOptions {listVar returnVar} { |
---|
| 615 | upvar $listVar argv |
---|
| 616 | upvar $returnVar params |
---|
[1206] | 617 | |
---|
[1214] | 618 | # parse command line arguments |
---|
| 619 | set argc [llength $argv] |
---|
| 620 | for {set i 0} {$i < $argc} {incr i} { |
---|
| 621 | set opt [lindex $argv $i] |
---|
[2658] | 622 | if { ("-t" == $opt) || |
---|
| 623 | ("-tool" == $opt) || |
---|
| 624 | ("--tool" == $opt) } { |
---|
[1214] | 625 | if {[expr {$i + 1}] < $argc} { |
---|
| 626 | incr i |
---|
| 627 | set params(--tool) [lindex $argv $i] |
---|
| 628 | # need to check to see if file exists, if not raise error |
---|
[1206] | 629 | } else { |
---|
| 630 | printHelp |
---|
| 631 | } |
---|
[2658] | 632 | } elseif { ("-tooldir" == $opt) || |
---|
| 633 | ("--tooldir" == $opt) } { |
---|
| 634 | if {[expr {$i + 1}] < $argc} { |
---|
| 635 | incr i |
---|
| 636 | set params(--tooldir) [lindex $argv $i] |
---|
| 637 | # need to check to see if directory exists, if not raise error |
---|
| 638 | } else { |
---|
| 639 | printHelp |
---|
| 640 | } |
---|
[1214] | 641 | } elseif { ("-d" == $opt) || |
---|
| 642 | ("-driver" == $opt) || |
---|
| 643 | ("--driver" == $opt) } { |
---|
| 644 | if {[expr {$i + 1}] < $argc} { |
---|
| 645 | incr i |
---|
| 646 | set params(--driver) [lindex $argv $i] |
---|
| 647 | # need to check to see if file exists, if not raise error |
---|
| 648 | } else { |
---|
| 649 | printHelp |
---|
| 650 | } |
---|
[1986] | 651 | } elseif { ("-r" == $opt) || |
---|
| 652 | ("-runfile" == $opt) || |
---|
| 653 | ("--runfile" == $opt) } { |
---|
| 654 | if {[expr {$i + 1}] < $argc} { |
---|
| 655 | incr i |
---|
| 656 | set params(--runfile) [lindex $argv $i] |
---|
| 657 | } else { |
---|
| 658 | printHelp |
---|
| 659 | } |
---|
[1214] | 660 | } elseif { ("-v" == $opt) || |
---|
| 661 | ("-values" == $opt) || |
---|
| 662 | ("--values" == $opt) } { |
---|
| 663 | if {[expr {$i + 1}] < $argc} { |
---|
| 664 | incr i |
---|
| 665 | set valuesFlag [lindex $argv $i] |
---|
| 666 | if {("default" == $valuesFlag) || |
---|
| 667 | ("current" == $valuesFlag) || |
---|
| 668 | ("random" == $valuesFlag) } { |
---|
| 669 | set params(--values) $valuesFlag |
---|
| 670 | } else { |
---|
| 671 | printHelp |
---|
| 672 | } |
---|
| 673 | } else { |
---|
| 674 | printHelp |
---|
| 675 | } |
---|
| 676 | } elseif { ("-c" == $opt) || |
---|
| 677 | ("-compare" == $opt)|| |
---|
| 678 | ("--compare" == $opt) } { |
---|
| 679 | if {[expr {$i + 1}] < $argc} { |
---|
| 680 | incr i |
---|
| 681 | set params(--compare) [lindex $argv $i] |
---|
| 682 | # need to check to see if file exists, if not raise error |
---|
| 683 | } else { |
---|
| 684 | printHelp |
---|
| 685 | } |
---|
| 686 | } elseif { ("-n" == $opt) || |
---|
| 687 | ("-nosim" == $opt) || |
---|
| 688 | ("--nosim" == $opt) } { |
---|
| 689 | set params(--nosim) true |
---|
| 690 | } elseif { ("-h" == $opt) || |
---|
| 691 | ("-help" == $opt) || |
---|
| 692 | ("--help" == $opt) } { |
---|
[688] | 693 | printHelp |
---|
[1108] | 694 | } else { |
---|
[1214] | 695 | # place all extra params in the params array |
---|
| 696 | lappend params(oParams) $opt |
---|
[1108] | 697 | } |
---|
[688] | 698 | } |
---|
| 699 | } |
---|
| 700 | |
---|
[2607] | 701 | proc storeoutput {data} { |
---|
| 702 | global _d |
---|
| 703 | append _d $data |
---|
| 704 | } |
---|
| 705 | |
---|
[1214] | 706 | proc main {argv} { |
---|
| 707 | # set default values |
---|
| 708 | array set presets [] |
---|
| 709 | set i 0 |
---|
[688] | 710 | |
---|
[1214] | 711 | array set params { |
---|
| 712 | --compare "" |
---|
| 713 | --values default |
---|
| 714 | --nosim false |
---|
| 715 | --driver "" |
---|
[1986] | 716 | --runfile "" |
---|
[1214] | 717 | --tool "./tool.xml" |
---|
[2658] | 718 | --tooldir "" |
---|
[1214] | 719 | oParams {} |
---|
| 720 | } |
---|
[688] | 721 | |
---|
[1214] | 722 | parseOptions argv params |
---|
[688] | 723 | |
---|
[2659] | 724 | # keep the wish window from popping up |
---|
| 725 | catch {wm withdraw .} |
---|
| 726 | |
---|
[1214] | 727 | # parse out path=val combinations from the list of orphaned parameters |
---|
| 728 | parsePathVal params(oParams) presets |
---|
| 729 | if {0 != [llength $params(oParams)]} { |
---|
| 730 | puts "Could not understand the following parameters" |
---|
| 731 | puts "params(oParams) = $params(oParams)" |
---|
| 732 | puts "length params(oParams) = [llength $params(oParams)]" |
---|
[1210] | 733 | } |
---|
[688] | 734 | |
---|
[1214] | 735 | set err "" |
---|
| 736 | if {! [file exists $params(--tool)]} { |
---|
| 737 | append err "\ntool file \"" |
---|
| 738 | append err $params(--tool) |
---|
| 739 | append err "\" does not exist, use -t option\n" |
---|
| 740 | puts $err |
---|
| 741 | printHelp |
---|
| 742 | } |
---|
[1206] | 743 | |
---|
[1214] | 744 | set xmlobj [Rappture::library $params(--tool)] |
---|
[2658] | 745 | if {$params(--tooldir) == ""} { |
---|
| 746 | set installdir [file dirname $params(--tool)] |
---|
| 747 | } else { |
---|
| 748 | set installdir $params(--tooldir) |
---|
| 749 | } |
---|
[1214] | 750 | |
---|
| 751 | # need a better way to do this, |
---|
| 752 | # maybe just take xmldiff functionality out of simsim |
---|
| 753 | if {(!$params(--nosim)) || ("" != $params(--driver))} { |
---|
| 754 | switch -- $params(--values) { |
---|
| 755 | random { randomize presets $xmlobj $installdir } |
---|
| 756 | current { } |
---|
| 757 | default { defaultize $xmlobj $installdir } |
---|
| 758 | } |
---|
[1206] | 759 | } |
---|
[1108] | 760 | |
---|
[1214] | 761 | if {"" != $params(--driver)} { |
---|
| 762 | set fid [open $params(--driver) w] |
---|
| 763 | puts $fid {<?xml version="1.0"?>} |
---|
| 764 | puts $fid [$xmlobj xml] |
---|
| 765 | close $fid |
---|
| 766 | } |
---|
[688] | 767 | |
---|
[1214] | 768 | if {$params(--nosim)} { |
---|
| 769 | if {"" != $params(--compare)} { |
---|
| 770 | compare $xmlobj $params(--compare) |
---|
| 771 | } |
---|
| 772 | exit 0 |
---|
| 773 | } |
---|
[688] | 774 | |
---|
[1986] | 775 | |
---|
| 776 | |
---|
| 777 | |
---|
[1214] | 778 | set tool [Rappture::Tool ::#auto $xmlobj $installdir] |
---|
[688] | 779 | |
---|
[1214] | 780 | # read the run.xml file. |
---|
| 781 | # from analyzer.tcl: |
---|
[688] | 782 | |
---|
[1214] | 783 | set result "" |
---|
| 784 | # execute the job |
---|
[2607] | 785 | foreach {status result} [eval $tool run -output storeoutput] break |
---|
[1214] | 786 | |
---|
[1986] | 787 | # if run was successful, check to see if we should compare |
---|
[1214] | 788 | if {$status == 0 && $result != "ABORT"} { |
---|
[2607] | 789 | global _d |
---|
| 790 | if {[regexp {=RAPPTURE-RUN=>([^\n]+)} $_d match result]} { |
---|
| 791 | if {[string compare "" $params(--runfile)] != 0} { |
---|
[2608] | 792 | if {[catch {file rename -force -- $result $params(--runfile)} out]} { |
---|
[2607] | 793 | puts stderr "while moving $result to $params(--runfile): $out" |
---|
| 794 | } |
---|
| 795 | } |
---|
[1214] | 796 | # do comparison if user chose to compare with other results |
---|
| 797 | if {"" != $params(--compare)} { |
---|
| 798 | compare $params(--compare) $result |
---|
| 799 | } |
---|
| 800 | } else { |
---|
| 801 | set status 1 |
---|
| 802 | puts "Can't find result file in output.\nDid you call Rappture::result in your simulator?" |
---|
[688] | 803 | } |
---|
| 804 | } else { |
---|
[1214] | 805 | puts $result |
---|
[688] | 806 | } |
---|
| 807 | } |
---|
| 808 | |
---|
[1214] | 809 | main $argv |
---|
[688] | 810 | exit 0 |
---|