TABLE OF CONTENTS
::pwtk::run
SYNOPSIS
proc ::pwtk::run {args} {
USAGE
run [options] program input ?output?
Options are:
-append -serial -prefix -postfix -exec -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
- -append == treat the output file in append mode (default = overwrite)
- -serial == run the calculation in serial mode (default = parallel)
- -prefix == explicitly specify the prefix for parallel execution
- -postfix == explicitly specify the postfix for parallel execution
- -exec == 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 prefix for in/out file)
- output -- [optional] name of file to write the output to (default = $head.out, where $head is the prefix of the input file)
SOURCE
variable state variable run_options variable remote_exec variable remote variable RUNopt variable run # # parse arguments # 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] } set program [lindex $args 0] set input [lindex $args 1] set output [lindex $args 2] 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 } # check for excluding options: (prefix || postfix) vs serial if { $opt(serial) && $opt(prefix) != "" } { ::pwtk::error "cannot specify both -serial and -prefix; the latter is used exclusively for parallel execution" 1 } if { $opt(serial) && $opt(postfix) != "" } { ::pwtk::error "cannot specify both -serial and -postfix; the latter is used exclusively for parallel execution" 1 } # store the name of program, input & output files (they may be queried from other procs) set run(program) $program set run(input) $input set run(output) $output # # determine prefix & postfix # if { ! $opt(serial) } { # parallel run # (beware: do now swap below lines, because order matters !!!) set prefix [::pwtk::getVar_ RUNopt(PREFIX)] set postfix [::pwtk::getVar_ RUNopt(POSTFIX)] if { [remote_mode_] && $remote_exec(rfull) } { set prefix [remote_query_ {::pwtk::getVar_ RUNopt(PREFIX)}] set postfix [remote_query_ {::pwtk::getVar_ RUNopt(POSTFIX)}] } if { $opt(prefix) != "" } { set prefix $opt(prefix) } if { $opt(postfix) != "" } { set postfix $opt(postfix) } } else { # serial run set prefix [::pwtk::getVar_ RUNopt(SERIAL_PREFIX)] set 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 { [remote_mode_] } { remote_execok_ $prog complain } else { if { [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 # (there must be a local copy of input in any case) if { ! [file readable $input] } { ::pwtk::error "file $input does not exist or is not readable" 1 } # redirection and write mode set redirect ">" set mode w if { $opt(append) } { set redirect ">>" set mode a } else { if { [backup_io] } { # make a backup copy of output file_backup $output } } # # RUN: either locally or remotely # set rr [string trim "$prefix [file tail $prog] $postfix"] if { ! [remote_mode_] } { # # run locally # ::pwtk::print "Running: $rr $ihandle $input $redirect $output\n" # check if the output file is writeable if { [catch {set fID [open $output a]}] } { close $fID ::pwtk::error "output file $output is not writable" 1 } close $fID catch { set host_ [exec hostname] } if { $host_ != "" } { # Write to $output on which host the calculation is run ::pwtk::writeFile $output "### Running on host: $host_" $mode set redirect ">>" } ######################################################################## # if { [catch {eval exec $prefix $prog $postfix $ihandle $input $redirect $output} errMsg] } { ::pwtk::writeFile $output.error $errMsg checkForError $output.error $prog $state(stopOnError) } # ######################################################################## checkForError $output $prog $state(stopOnError) } else { # # run remotely # global env ::pwtk::print "Running remotely on $remote_exec(host): $rr $ihandle $input $redirect $output\n" # determine the calculation directory set dir [::fileutil::stripPath $env(HOME) [pwd]] if { $remote_exec(rdir) != "" } { set dir $remote_exec(rdir) } # check if the input & output files are writeable on remote-host remote_writeable_ [file join $dir $input] remote_writeable_ [file join $dir $output] # make a remote shell-script wrapper set scriptFile [remote_scriptName_ sh] writeFile $scriptFile "" if { [info exists env(PATH)] } { writeFile $scriptFile " PATH=$env(PATH) export PATH " a } if { [info exists env(LD_LIBRARY_PATH)] } { writeFile $scriptFile " LD_LIBRARY_PATH=$env(LD_LIBRARY_PATH) export LD_LIBRARY_PATH " a } writeFile $scriptFile " echo \"### Running on host: $remote_exec(host)\" $redirect $output $prefix $prog $postfix $ihandle $input >> $output rm -f $scriptFile " a if { $remote_exec(rfs) } { # running directory is on remote-file system; # copy the input & script files to remote host exec $remote(rcp) $input $remote_exec(host):[file join $dir $input] exec $remote(rcp) $scriptFile $remote_exec(host):[file join $dir $scriptFile] } ######################################################################## # run remotely set head [file rootname $output] catch { eval {exec $remote(rsh)} $remote(rsh_bg_opts) {$remote_exec(host) "cd $dir; $remote(nohup) $remote(shell) $scriptFile $redirect $head.remote.log 2>&1 &"} } # ######################################################################## if { ! $remote_exec(bg) } { # # wait for calculation to finish # (i.e. when calculation finishes the script file is deleted) # set finished 0 while { ! $finished } { after $remote(time_interval) if { $remote_exec(rfs) } { set finished [remote_execTclScript_ " if { \[file exists \[file join $dir $scriptFile]] } { puts 0 } else { puts 1 } "] } else { if { ! [file exists $scriptFile] } { set finished 1 } } } # calculation is finished; copy the output file and check for error if { $remote_exec(rfs) } { exec $remote(rcp) $remote_exec(host):[file join $dir $output] $output } checkForError $output $prog $state(stopOnError) } if { $remote_exec(rfs) } { # the local script file has not yet been deleted # # BEWARE: if remote and local filesystems are identical # then there should be some delay before the script file # is deleted or else it may happen that it will be deleted # before the script is executed on remote host !!! if { $remote_exec(bg) } { # wait for 10 seconds, then delete the file delayed_exec 10000 catch "file delete $scriptFile" } } } }