Changeset 5029 for branches/uq/lang
- Timestamp:
- Feb 17, 2015, 5:49:36 PM (10 years ago)
- Location:
- branches/uq/lang/tcl/scripts
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/uq/lang/tcl/scripts/library.tcl
r4180 r5029 215 215 public method remove {{path ""}} 216 216 public method xml {{path ""}} 217 public method uq_make_template {} 217 218 218 219 public method diff {libobj} … … 228 229 private variable _root 0 ;# non-zero => this obj owns document 229 230 private variable _document "" ;# XML DOM tree 230 private variable _node "" ;# node within 231 private variable _node "" ;# node within 231 232 } 232 233 … … 1038 1039 return $rlist 1039 1040 } 1041 1042 1043 # FIXME: get units convert. change varlist to have no units 1044 itcl::body Rappture::LibraryObj::uq_make_template {} { 1045 set varlist "" 1046 set n [$_node selectNodes /run/input//number] 1047 foreach _n $n { 1048 set x [$_n selectNodes current/text()] 1049 set val [$x nodeValue] 1050 if {[string equal -length 8 $val "uniform "] || 1051 [string equal -length 9 $val "gaussian "]} { 1052 set unode [$_n selectNodes units/text()] 1053 if {"" != $unode} { 1054 set units [$unode nodeValue] 1055 set val [Rappture::Units::mconvert $val \ 1056 -context $units -to $units -units off] 1057 } 1058 $x nodeValue @@[$_n getAttribute id] 1059 lappend varlist [list [$_n getAttribute id] $val] 1060 } 1061 } 1062 return $varlist 1063 } -
branches/uq/lang/tcl/scripts/task.tcl
r4514 r5029 1 # -*- mode: tcl; indent-tabs-mode: nil -*- 1 # -*- mode: tcl; indent-tabs-mode: nil -*- 2 2 # ---------------------------------------------------------------------- 3 3 # COMPONENT: task - represents the executable part of a tool … … 57 57 # default method for -jobstats control 58 58 public proc MiddlewareTime {args} 59 60 public method get_params {varlist csvname uq_type args} 59 61 } 60 62 … … 75 77 # ---------------------------------------------------------------------- 76 78 itcl::body Rappture::Task::constructor {xmlobj installdir args} { 79 puts "Task Init" 77 80 if {![Rappture::library isvalid $xmlobj]} { 78 81 error "bad value \"$xmlobj\": should be Rappture::Library" … … 138 141 itcl::body Rappture::Task::run {args} { 139 142 global env errorInfo 140 143 puts "task run $args" 141 144 # 142 145 # Make sure that we save the proper application name. … … 164 167 foreach item {control output error} { set job($item) "" } 165 168 166 # write out the driver.xml file for the tool167 set file "driver[pid].xml"168 set status [catch {169 set fid [open $file w]170 puts $fid "<?xml version=\"1.0\"?>"171 puts $fid [$_xmlobj xml]172 close $fid173 } result]174 175 169 # Set limits for cpu time 176 170 set limit [$_xmlobj get tool.limits.cputime] … … 185 179 set limit 10; # lower bound is 10 seconds. 186 180 } 187 } 188 Rappture::rlimit set cputime $limit 181 } 182 Rappture::rlimit set cputime $limit 183 184 # write out the driver.xml file for the tool 185 set file "driver[pid].xml" 186 set status [catch { 187 set fid [open $file w] 188 puts $fid "<?xml version=\"1.0\"?>" 189 puts $fid [$_xmlobj xml] 190 close $fid 191 } result] 192 193 # This will turn the driver xml into a template 194 # and return a list of the UQ variables and their PDFs. 195 set uq_varlist [$_xmlobj uq_make_template] 196 197 if {$uq_varlist != ""} { 198 # write out the template file for submit 199 set tfile "template[pid].xml" 200 set status [catch { 201 set fid [open $tfile w] 202 puts $fid "<?xml version=\"1.0\"?>" 203 puts $fid [$_xmlobj xml] 204 close $fid 205 } result] 206 } 207 208 189 209 # execute the tool using the path from the tool description 190 210 if {$status == 0} { 191 211 set cmd [$_xmlobj get tool.command] 212 puts "1. cmd=$cmd" 192 213 regsub -all @tool $cmd $_installdir cmd 193 regsub -all @driver $cmd $file cmd 194 regsub -all {\\} $cmd {\\\\} cmd 214 215 if {$uq_varlist == ""} { 216 regsub -all @driver $cmd $file cmd 217 } else { 218 regsub -all @driver $cmd $tfile cmd 219 } 195 220 set cmd [string trimleft $cmd " "] 196 if { $cmd == "" } { 197 puts stderr "cmd is empty" 198 return [list 1 "Command is empty.\n\nThere is no command specified by\n\n <command>\n </command>\n\nin the tool.xml file."] 199 } 200 201 switch -glob -- [resources -jobprotocol] { 202 "submit*" { 203 # if job_protocol is "submit", then use use submit command 204 set cmd "submit --local $cmd" 205 } 206 "mx" { 207 # metachory submission 208 set cmd "mx $cmd" 209 } 210 "exec" { 211 # default -- nothing special 212 } 213 } 221 puts "2. cmd=$cmd" 222 if { $cmd == "" } { 223 puts stderr "cmd is empty" 224 return [list 1 "Command is empty.\n\nThere is no command specified by\n\n <command>\n </command>\n\nin the tool.xml file."] 225 } 226 227 if {$uq_varlist == ""} { 228 switch -glob -- [resources -jobprotocol] { 229 "submit*" { 230 # if job_protocol is "submit", then use use submit command 231 set cmd "submit --local $cmd" 232 } 233 "mx" { 234 # metachory submission 235 set cmd "mx $cmd" 236 } 237 "exec" { 238 # default -- nothing special 239 } 240 } 241 } else { 242 puts "uq_varlist=$uq_varlist" 243 # FIXME. Default to Smolyak level 2, but allow more later. 244 file delete -force puq 245 set params_file [get_params $file $uq_varlist "smolyak" 2] 246 set cmd "submit --runName=puq -l -d $params_file python uq.py $cmd @:$tfile" 247 } 248 214 249 $_xmlobj put tool.execute $cmd 215 250 216 # starting job... 217 _log run started 218 Rappture::rusage mark 219 220 if {0 == [string compare -nocase -length 5 $cmd "ECHO "] } { 221 set status 0; 222 set job(output) [string range $cmd 5 end] 223 } else { 224 set status [catch { 225 set ::Rappture::Task::job(control) "" 226 eval blt::bgexec \ 227 ::Rappture::Task::job(control) \ 228 -keepnewline yes \ 229 -killsignal SIGTERM \ 230 -onoutput [list [itcl::code $this _output]] \ 251 puts "cmd=$cmd" 252 # starting job... 253 _log run started 254 Rappture::rusage mark 255 256 if {0 == [string compare -nocase -length 5 $cmd "ECHO "] } { 257 set status 0; 258 set job(output) [string range $cmd 5 end] 259 } else { 260 set status [catch { 261 set ::Rappture::Task::job(control) "" 262 eval blt::bgexec \ 263 ::Rappture::Task::job(control) \ 264 -keepnewline yes \ 265 -killsignal SIGTERM \ 266 -onoutput [list [itcl::code $this _output]] \ 231 267 -output ::Rappture::Task::job(output) \ 232 268 -error ::Rappture::Task::job(error) \ 233 269 $cmd 234 235 236 237 # We're here because the exec-ed program failed 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 270 } result] 271 272 if { $status != 0 } { 273 # We're here because the exec-ed program failed 274 set logmesg $result 275 if { $::Rappture::Task::job(control) ne "" } { 276 foreach { token pid code mesg } \ 277 $::Rappture::Task::job(control) break 278 if { $token == "EXITED" } { 279 # This means that the program exited normally but 280 # returned a non-zero exitcode. Consider this an 281 # invalid result from the program. Append the stderr 282 # from the program to the message. 283 set logmesg "Program finished: exit code is $code" 284 set result "$logmesg\n\n$::Rappture::Task::job(error)" 285 } elseif { $token == "abort" } { 286 # The user pressed the abort button. 287 set logmesg "Program terminated by user." 288 set result "$logmesg\n\n$::Rappture::Task::job(output)" 289 } else { 290 # Abnormal termination 291 set logmesg "Abnormal program termination: $mesg" 292 set result "$logmesg\n\n$::Rappture::Task::job(output)" 293 } 294 } 295 _log run failed [list $logmesg] 296 return [list $status $result] 297 } 298 } 299 # ...job is finished 300 array set times [Rappture::rusage measure] 301 302 if {[resources -jobprotocol] ne "submit"} { 303 set id [$_xmlobj get tool.id] 304 set vers [$_xmlobj get tool.version.application.revision] 305 set simulation simulation 306 if { $id ne "" && $vers ne "" } { 307 set pid [pid] 308 set simulation ${pid}_${id}_r${vers} 309 } 310 311 # need to save job info? then invoke the callback 312 if {[string length $jobstats] > 0} { 313 uplevel #0 $jobstats [list job [incr jobnum] \ 314 event $simulation start $times(start) \ 315 walltime $times(walltime) cputime $times(cputime) \ 316 status $status] 317 } 318 319 # 320 # Scan through stderr channel and look for statements that 321 # represent grid jobs that were executed. The statements 322 # look like this: 323 # 324 # MiddlewareTime: job=1 event=simulation start=3.001094 ... 325 # 326 set subjobs 0 327 while {[regexp -indices {(^|\n)MiddlewareTime:( +[a-z]+=[^ \n]+)+(\n|$)} $job(error) match]} { 328 foreach {p0 p1} $match break 329 if {[string index $job(error) $p0] == "\n"} { incr p0 } 330 331 catch {unset data} 332 array set data { 333 job 1 334 event simulation 335 start 0 336 walltime 0 337 cputime 0 338 status 0 339 } 304 340 foreach arg [lrange [string range $job(error) $p0 $p1] 1 end] { 305 341 foreach {key val} [split $arg =] break … … 337 373 } 338 374 if {$status == 0} { 339 file delete -force -- $file375 # file delete -force -- $file 340 376 } 341 377 … … 350 386 # a reference to the run.xml file containing results. 351 387 # 388 352 389 if {$status == 0} { 353 390 set result [string trim $job(output)] 391 puts "result=$result" 392 if {$uq_varlist != ""} { 393 file delete -force -- new.xml 394 exec puq_analyze.py puq_[pid].hdf5 395 append result "\n" "=RAPPTURE-RUN=>new.xml" 396 } 354 397 if {[regexp {=RAPPTURE-RUN=>([^\n]+)} $result match file]} { 355 398 set status [catch {Rappture::library $file} result] 399 puts "STATUS=$status" 356 400 if {$status == 0} { 357 401 # add cputime info to run.xml file … … 381 425 if {$status == 0 && $rdir ne ""} { 382 426 catch { 383 file delete -force -- $file427 # file delete -force -- $file 384 428 if {![file exists $rdir]} { 385 429 _mkdir $rdir … … 393 437 } else { 394 438 # don't keep the file 395 file delete -force -- $file439 # file delete -force -- $file 396 440 } 397 441 } else { … … 518 562 puts stderr $line 519 563 } 564 565 566 # 567 # Send the list of parameters to a python program so it can call PUQ 568 # and get a CSV file containing the parameter values to use for the runs. 569 itcl::body Rappture::Task::get_params {dfile varlist uq_type args} { 570 571 # convert tcl list of variables to json so python can read it 572 proc varlist2py {inlist} { 573 set ovar "\[" 574 set first 1 575 foreach a $inlist { 576 foreach {var val} $a break 577 if {$first == 1} { 578 append ovar \[\"$var\", 579 set first 0 580 } else { 581 append ovar \],\[\"$var\", 582 } 583 switch [lindex $val 0] { 584 gaussian { 585 append ovar "\[\"gaussian\",[lindex $val 1],[lindex $val 2]\]" 586 } 587 uniform { 588 append ovar "\[\"uniform\",[lindex $val 1],[lindex $val 2]\]" 589 } 590 default { 591 append ovar $val 592 } 593 } 594 } 595 append ovar "\]\]" 596 return $ovar 597 } 598 599 puts "varlist=$varlist" 600 set varlist [varlist2py $varlist] 601 set pid [pid] 602 exec get_params.py $dfile $pid $varlist $uq_type $args 603 return params[pid].csv 604 } -
branches/uq/lang/tcl/scripts/units.tcl
r3362 r5029 1 # -*- mode: tcl; indent-tabs-mode: nil -*- 1 2 # ---------------------------------------------------------------------- 2 3 # COMPONENT: units - mechanism for converting numbers with units … … 60 61 } 61 62 63 64 # ---------------------------------------------------------------------- 65 # USAGE: mcheck_range value {min ""} {max ""} 66 # 67 # Checks a value or PDF to determine if is is in a required range. 68 # Automatically does unit conversion if necessary. 69 # Returns value if OK. Error if out-of-range 70 # Examples: 71 # [mcheck_range "gaussian 0C 1C" 200K 500K] returns 1 72 # [mcheck_range "uniform 100 200" 150 250] returns 0 73 # [mcheck_range 100 0 200] returns 1 74 # ---------------------------------------------------------------------- 75 76 proc Rappture::Units::_check_range {value min max units} { 77 # make sure the value has units 78 if {$units != ""} { 79 set value [Rappture::Units::convert $value -context $units] 80 # for comparisons, remove units 81 set nv [Rappture::Units::convert $value -units off] 82 # get the units for the value 83 set newunits [Rappture::Units::Search::for $value] 84 } else { 85 set nv $value 86 } 87 88 if {"" != $min} { 89 if {"" != $units} { 90 # compute the minimum in the new units 91 set minv [Rappture::Units::convert $min -to $newunits -units off] 92 # same, but include units for printing 93 set convMinVal [Rappture::Units::convert $min -to $newunits] 94 } else { 95 set minv $min 96 set convMinVal $min 97 } 98 if {$nv < $minv} { 99 error "Minimum value allowed here is $convMinVal" 100 } 101 } 102 if {"" != $max} { 103 if {"" != $units} { 104 # compute the maximum in the new units 105 set maxv [Rappture::Units::convert $max -to $newunits -units off] 106 # same, but include units for printing 107 set convMaxVal [Rappture::Units::convert $max -to $newunits] 108 } else { 109 set maxv $max 110 set convMaxVal $max 111 } 112 if {$nv > $maxv} { 113 error "Maximum value allowed here is $convMaxVal" 114 } 115 } 116 return $value 117 } 118 119 proc Rappture::Units::mcheck_range {value {min ""} {max ""} {units ""}} { 120 puts "mcheck_range $value min=$min max=$max units=$units" 121 122 switch -- [lindex $value 0] { 123 normal - 124 gaussian { 125 # get the mean 126 set mean [_check_range [lindex $value 1] $min $max $units] 127 if {$units == ""} { 128 set dev [lindex $value 2] 129 set ndev $dev 130 } else { 131 set dev [Rappture::Units::convert [lindex $value 2] -context $units] 132 set ndev [Rappture::Units::convert $dev -units off] 133 } 134 if {$ndev <= 0} { 135 error "Deviation must be positive." 136 } 137 return [list gaussian $mean $dev] 138 } 139 uniform { 140 set min [_check_range [lindex $value 1] $min $max $units] 141 set max [_check_range [lindex $value 2] $min $max $units] 142 return [list uniform $min $max] 143 } 144 exact { 145 return [_check_range [lindex $value 1] $min $max $units] 146 } 147 default { 148 return [_check_range [lindex $value 0] $min $max $units] 149 } 150 } 151 } 152 153 # ---------------------------------------------------------------------- 154 # USAGE: mconvert value ?-context units? ?-to units? ?-units on/off? 155 # 156 # This version of convert() converts multiple values. Used when the 157 # value could be a range or probability density function (PDF). 158 # Examples: 159 # gaussian 100k 1k 160 # uniform 0eV 10eV 161 # 42 162 # exact 42 163 # ---------------------------------------------------------------------- 164 165 proc Rappture::Units::mconvert {value args} { 166 puts "mconvert $value : $args" 167 array set opts { 168 -context "" 169 -to "" 170 -units "on" 171 } 172 173 set value [split $value] 174 175 switch [lindex $value 0] { 176 normal - 177 gaussian { 178 set valtype gaussian 179 set vals [lrange $value 1 2] 180 set convtype {0 1} 181 } 182 uniform { 183 set valtype uniform 184 set vals [lrange $value 1 2] 185 set convtype {0 0} 186 } 187 exact { 188 set valtype "" 189 set vals [lindex $value 1] 190 set convtype {0} 191 } 192 default { 193 set valtype "" 194 set vals $value 195 set convtype {0} 196 } 197 } 198 199 foreach {key val} $args { 200 if {![info exists opts($key)]} { 201 error "bad option \"$key\": should be [join [lsort [array names opts]] {, }]" 202 } 203 set opts($key) $val 204 } 205 206 set newval $valtype 207 foreach val $vals ctype $convtype { 208 if {$ctype == 1} { 209 # This code handles unit conversion for deltas (changes). 210 # For example, if we want a standard deviation of 10C converted 211 # to Kelvin, that is 10K, NOT a standard deviation of 283.15K. 212 set units [Rappture::Units::Search::for $val] 213 set base [eval Rappture::Units::convert 0$units $args -units off] 214 set new [eval Rappture::Units::convert $val $args -units off] 215 set delta [expr $new - $base] 216 set val $delta$opts(-to) 217 } 218 # tcl 8.5 allows us to do this: 219 # lappend newval [Rappture::Units::convert $val {*}$args] 220 # but we are using tcl8.4 so we use eval :^( 221 lappend newval [eval Rappture::Units::convert $val $args] 222 } 223 return $newval 224 } 225 62 226 # ---------------------------------------------------------------------- 63 227 # USAGE: convert value ?-context units? ?-to units? ?-units on/off? … … 69 233 # current system. 70 234 # ---------------------------------------------------------------------- 71 proc Rappture::Units::convert {value args} { 72 array set opts { 73 -context "" 74 -to "" 75 -units "on" 76 } 77 foreach {key val} $args { 78 if {![info exists opts($key)]} { 79 error "bad option \"$key\": should be [join [lsort [array names opts]] {, }]" 80 } 81 set opts($key) $val 82 } 83 84 # 85 # Parse the value into the number part and the units part. 86 # 87 set value [string trim $value] 88 if {![regexp {^([-+]?[0-9]+\.?([0-9]+)?([eEdD][-+]?[0-9]+)?) *(/?[a-zA-Z]+[0-9]*)?$} $value match number dummy1 dummy2 units]} { 89 set mesg "bad value \"$value\": should be real number with units" 90 if {$opts(-context) != ""} { 91 append mesg " of [Rappture::Units::description $opts(-context)]" 92 } 93 error $mesg 94 } 95 if {$units == ""} { 96 set units $opts(-context) 97 } 98 99 # 100 # Try to find the object representing the current system of units. 101 # 102 set units [Rappture::Units::System::regularize $units] 103 set oldsys [Rappture::Units::System::for $units] 104 if {$oldsys == ""} { 105 set mesg "value \"$value\" has unrecognized units" 106 if {$opts(-context) != ""} { 107 append mesg ".\nShould be units of [Rappture::Units::description $opts(-context)]" 108 } 109 error $mesg 110 } 111 112 # 113 # Convert the number to the new system of units. 114 # 115 if {$opts(-to) == ""} { 116 # no units -- return the number as is 117 return "$number$units" 118 } 119 return [$oldsys convert "$number$units" $opts(-to) $opts(-units)] 120 } 235 # proc Rappture::Units::convert {value args} {} 236 # Actual implementation is in rappture/lang/tcl/src/RpUnitsTclInterface.cc. 237 121 238 122 239 # ---------------------------------------------------------------------- … … 127 244 # along with a list of all compatible systems. 128 245 # ---------------------------------------------------------------------- 129 proc Rappture::Units::description {units} { 130 set sys [Rappture::Units::System::for $units] 131 if {$sys == ""} { 132 return "" 133 } 134 set mesg [$sys cget -type] 135 set ulist [Rappture::Units::System::all $units] 136 if {"" != $ulist} { 137 append mesg " ([join $ulist {, }])" 138 } 139 return $mesg 140 } 246 # proc Rappture::Units::description {units} {} 247 # Actual implementation is in rappture/lang/tcl/src/RpUnitsTclInterface.cc. 248 141 249 142 250 # ---------------------------------------------------------------------- … … 153 261 private variable _system "" ;# this system of units 154 262 155 public proc for {units} 156 public proc all {units} 263 # These are in rappture/lang/tcl/src/RpUnitsTclInterface.cc. 264 # public proc for {units} 265 # public proc all {units} 266 157 267 public proc regularize {units} 158 268 … … 360 470 # if there is no system that matches the units string. 361 471 # ---------------------------------------------------------------------- 362 itcl::body Rappture::Units::System::for {units} { 363 # 364 # See if the units are a recognized system. If not, then try to 365 # extract any metric prefix and see if what's left is a recognized 366 # system. If all else fails, see if we can find a system without 367 # the exact capitalization. The user might say "25c" instead of 368 # "25C". Try to allow that. 369 # 370 if {[info exists _base($units)]} { 371 return $_base($units) 372 } else { 373 set orig $units 374 if {[regexp {^(/?)[cCmMuUnNpPfFaAkKgGtT](.+)$} $units match slash tail]} { 375 set base "$slash$tail" 376 if {[info exists _base($base)]} { 377 set sys $_base($base) 378 if {[$sys cget -metric]} { 379 return $sys 380 } 381 } 382 383 # check the base part for improper capitalization below... 384 set units $base 385 } 386 387 set matching "" 388 foreach u [array names _base] { 389 if {[string equal -nocase $u $units]} { 390 lappend matching $_base($u) 391 } 392 } 393 if {[llength $matching] == 1} { 394 set sys [lindex $matching 0] 395 # 396 # If we got rid of a metric prefix above, make sure 397 # that the system is metric. If not, then we don't 398 # have a match. 399 # 400 if {[string equal $units $orig] || [$sys cget -metric]} { 401 return $sys 402 } 403 } 404 } 405 return "" 406 } 472 # itcl::body Rappture::Units::System::for {units} {} 473 # Actual implementation is in rappture/lang/tcl/src/RpUnitsTclInterface.cc. 474 407 475 408 476 # ---------------------------------------------------------------------- … … 413 481 # relationships that lead to the same base system. 414 482 # ---------------------------------------------------------------------- 415 itcl::body Rappture::Units::System::all {units} { 416 set sys [Rappture::Units::System::for $units] 417 if {$sys == ""} { 418 return "" 419 } 420 421 if {"" != [$sys cget -basis]} { 422 set basis [lindex [$sys cget -basis] 0] 423 } else { 424 set basis $units 425 } 426 427 set ulist $basis 428 foreach u [array names _base] { 429 set obj $_base($u) 430 set b [lindex [$obj cget -basis] 0] 431 if {$b == $basis} { 432 lappend ulist $u 433 } 434 } 435 return $ulist 436 } 483 # itcl::body Rappture::Units::System::all {units} {} 484 # Actual implementation is in rappture/lang/tcl/src/RpUnitsTclInterface.cc. 485 437 486 438 487 # ----------------------------------------------------------------------
Note: See TracChangeset
for help on using the changeset viewer.