TABLE OF CONTENTS
::pwtk::run
SYNOPSIS
proc ::pwtk::run {args} {
USAGE
run [OPTIONS] PROGRAM INPUT ?OUTPUT? ?&? Options are: -bg -append -serial -prefix PREFIX -postfix POSTFIX -exec EXECUTABLE -ihandle VALUE
PURPOSE
Run a given Quantum-ESPRESSO (QE) program. It is implicitly assumed that QE program reads from stdin and writes to stdout, that is, it is assumed that the standard usage from the terminal or shell-script is:
PROGRAM < INPUT > OUTPUT
The equivalent PWTK statement is:
run PROGRAM INPUT ?OUTPUT?
where INPUT is the name of the input file and OUTPUT is the name of the output file. Note that the OUTPUT argument is optional; if it is not specified it is automatically constructed from the input file name. For example, if the INPUT is "file.in" then the OUTPUT is "file.out", but if the input filename does not have .in or .inp extension, then the name of the output is simply file.out, where "file" is the input filename.
See the ::pwtk::findExecutable for how the executable is located.
OPTIONS
- -bg --- run calculation in background (synonymous with "&" as the last argument)
- -append --- treat the output file in append mode (default = overwrite)
- -serial --- run the calculation in serial mode (default = parallel)
- -prefix PREFIX --- explicitly specify the prefix for parallel execution
- -postfix POSTFIX --- explicitly specify the postfix for parallel execution
- -exec EXECUTABLE --- explicitly specify the executable
- -ihandle VALUE --- explicitly set the input handle (for the description of input handle, see ::pwtk::input_handle)
ARGUMENTS
- PROGRAM -- name of executable
- INPUT -- input file (or the rootname for the I/O files)
- OUTPUT -- [optional] name of file to write the output to (default = $head.out, where $head is the prefix of the input file)
- & -- [optional] run calculation in background (synonymous with the -bg option)
RETURN VALUE
The name of the output file, unless the -bg option was specified in which case the ID of the backhound job is returned, which can be used for ::pwtk::run_wait.
SOURCE
variable state variable run_options variable RUNopt variable run variable makeInputAndRun_ # for prerun & remedy a recursive call to run is made, store how to call it set args_orig $args set run_cmd { ifexist makeInputAndRun_ { #set result [eval makeInputAndRun_ $makeInputAndRun_] set result [makeInputAndRun_ {*}$makeInputAndRun_] } else { #set result [eval run $args_orig] set result [run {*}$args_orig] } concat $result } # # parse arguments # set bg 0 set lastarg [lindex $args end] if { $lastarg eq "&" } { set bg 1 set args [lrange $args 0 end-1] } set usage "\n\nUsage: ::pwtk::run ?OPTIONS? PROGRAM INPUT ?OUTPUT? ?&?\n\nOptions are:" array set opt [::cmdline::getoptions args $run_options $usage] if { [llength $args] < 2 || [llength $args] > 3 } { error [::cmdline::usage $run_options $usage] 1 } # &" is synonymous with -bg if { $bg } { set opt(bg) 1 } lassign $args program input output set ihandle $RUNopt(input_handle) if { $output == "" } { set output [outputName_ $input] } if { $opt(ihandle) != {} } { set ihandle $opt(ihandle) } # if in restart-mode & job is already done, do not run it again if { $state(restart) && [::pwtk::job_done $output] } { ::pwtk::print "The $program job \"$output\" already done.\n" return $output } # check for excluding options: (prefix || postfix) vs serial if { $opt(serial) && $opt(prefix) != "" } { ::pwtk::error "exclusive -serial and -prefix options were specified" 1 } if { $opt(serial) && $opt(postfix) != "" } { ::pwtk::error "exclusive -serial and -postfix options were specified" 1 } # store the name of program, input & output files (they may be queried from other procs) array set run [list program $program input $input output $output] set pname [file tail $program] # handle "prerun" set preruns [::pwtk::preruns_ $pname] if { $preruns ne {} } { ::pwtk::input::pushpop { foreach name $preruns { #::pwtk::print "Evaluating the prerun script:\n$state($name)" eval $state($name) unset state($name) } eval $run_cmd } return [varvalue result] } # # determine prefix & postfix # if { ! $opt(serial) } { # parallel run # (beware: do not swap the below lines, because order matters !!!) set prefix [list {*}[::pwtk::getVar_ RUNopt(NICE_CMD)] {*}[::pwtk::getVar_ RUNopt(CONTAINER_EXEC)] {*}[::pwtk::getVar_ RUNopt(PREFIX)]] set postfix [::pwtk::getVar_ RUNopt(POSTFIX)] if { $opt(prefix) != "" } { set prefix $opt(prefix) } if { $opt(postfix) != "" } { set postfix $opt(postfix) } } else { # serial run set prefix [list {*}[::pwtk::getVar_ RUNopt(NICE_CMD)] {*}[::pwtk::getVar_ RUNopt(CONTAINER_EXEC)] {*}[::pwtk::getVar_ RUNopt(SERIAL_PREFIX)]] set postfix [::pwtk::getVar_ RUNopt(SERIAL_POSTFIX)] } # # find the executable # if { $opt(exec) == "" } { set prog [findExecutable $program] } else { # executable was explicitly specified (check if it is OK) set prog $opt(exec) if { $state(bin_query) && [auto_execok $prog] == "" } { ::pwtk::error "explicitly specified program '$prog' is not executable" 1 } } ::pwtk::print "Executable: $prog" # check if the input file exists and is readable if { ! [file readable $input] } { ::pwtk::error "file '$input' does not exist or is not readable" 1 } # redirection and write mode set mode w set redirect ">" if { $opt(append) } { set mode a set redirect ">>" } else { if { [backup_io] } { # make a backup copy of output file_backup $output } } # check if the output file is writeable try { close [open $output a] } on error errVar { ::pwtk::error "output file '$output' is not writable\n\n$errVar" 1 } # write to output the hostname where calculation is run set redirect_orig $redirect set host_ [info hostname] if { $host_ != "" } { ::pwtk::writeFile $output "### Running on host: $host_" $mode set redirect ">>" } # remove the error file if { [file exists $output.error] } { file delete $output.error } #### run the calculation ############################################### # set rr [string trim "$prefix [file tail $prog] $postfix"] try { if { ! $opt(bg) } { # foreground ::pwtk::print "Running: $rr $ihandle $input $redirect_orig $output\n" eval exec $prefix $prog $postfix $ihandle $input $redirect $output } else { # background; # make a push to prevent stack-level == 0, for which ::pwtk::input::peek returns an empty string ::pwtk::input::pushpop { ::pwtk::print "Running in background: $rr $ihandle $input $redirect_orig $output 2> $output.error &" set id [incr run(bg.ID)] set pid [eval exec $prefix $prog $postfix $ihandle $input $redirect $output 2> $output.error &] ::pwtk::print "PID of the background process = $pid\n" # tk array set run [list bg.prog,$id $prog \ bg.pname,$id $pname \ bg.output,$id $output \ bg.PID,$id $pid \ bg.peek,$id [::pwtk::input::peek] \ bg.run_cmd,$id $run_cmd] # tk_end } return $id } } on error errMsg { ::pwtk::writeFile $output.error $errMsg } # ######################################################################## # handle "remedy" if { [remedy $pname] } { if { [checkForError $output $prog 0] } { set remedy [remedy $pname get] ::pwtk::infoMsg "Trying to remedy the $pname error by using the remedy script:\n$remedy" ::pwtk::input::pushpop { remedy $pname clear eval $remedy eval $run_cmd } return [varvalue result] } } else { checkForError $output $prog $state(stopOnError) } # handle "postrun" set postruns [::pwtk::postruns_ $pname] if { $postruns ne {} } { foreach name $postruns { # should a postrun be done inside pushpop? NO! #::pwtk::print "Evaluating the postrun script:\n$state($name)" eval $state($name) } } return [varvalue output] }