TABLE OF CONTENTS
::pwtk::defineInput4Program
SYNOPSIS
proc ::pwtk::defineInput4Program {prog inNN runCmd inputSpecsList {rerunScript {}} {exportCmds {}}} {
PURPOSE
Register/define an input for a given QE program so that PWTK knows how to handle its input and run calculations. (This is a (semi)automatic way of adding new QE inputs/programs to PWTK.)
ARGUMENTS
- prog -- name of the executable (e.g. pw.x, pp.x, ...)
- inNN -- input namespace name (e.g. pwi, ppi ...; this will map to ::pwtk::pwi, ::pwtk::ppi ...)
- runCmd -- the name of the run command for the $inNN input (e.g. runPW, runPP, ...)
- inputSpecsList -- list specifying the input structure (see below)
- rerunScript -- (optional) if present, the rerunCmd will be generated; it is the PWTK script code needed to perform a restart calculation
- exportCmds -- (optional) list of procs in the ::pwtk::${inNN} namespace to export and import into global namespace for convenience (if there are no procs to export, exportCmds should be an empty string)
The structure of 'inputSpecsList' is the following (? = optional):
{ {type QEname ?PWTKname?} {type QEname ?PWTKname?} ... }
where the list elements follow the sequential structure of the input, and:
- type = type of the input block, i.e.: namelist, namelist.affix, card, card_w_flags, or card_wo_flgs
- QEname = QE name of the namelist or card, i.e.: QEnml, QEnml.ntyp, QEcard, or {QEcard QEclosingKeyword}, where: * QEnml.ntyp = namelist that has 'ntyp' arrays (dimensions) and will undergo var(AtomicSymbol) to var(AtomicIndex) transformation when constructing the input * {QEcard QEclosingKeyword} = "closed" card with the closing keyword (example: {BEGIN_POSITIONS END_POSITIONS})
- PWTKname = PWTKnml or PWTKcard, where these are the correponding PWTK names for QE namelist or card (example for dynmat.x: QEnml = INPUT --> PWTKnml = DYNMAT)
REMARK
For supercards (i.e. QEname == {QEcard QEclosingKeyword}), if the PWTKname is empty, the supercard is ignored in PWTK (example: BEGIN/END in neb.x). The reason is that closed-cards (or supercards) in PWTK are represented by a single name/command (example: POSITIONS {...}). Hence, empty name implies that a supercard is ignored in PWTK.
EXAMPLE
::pwtk::defineInput4Program matdyn.x runMATDYN mdi { { namelist.affix INPUT.ntyp MATDYN } } ::pwtk::defineInput4Program neb.x nebi runNEB { { card {BEGIN END} {} } { card {BEGIN_PATH_INPUT END_PATH_INPUT} {} } { namelist PATH {} } { card_wo_flags CLIMBING_IMAGES {} } { card {BEGIN_ENGINE_INPUT END_ENGINE_INPUT} {} } { card {BEGIN_POSITIONS END_POSITIONS} POSITIONS } }
SOURCE
variable auto_inNN_list; # list of auto-defined input namespaces variable runXX_exportList variable exportList variable prog2runCmd variable prog2inNN variable QE2PWTKname # strip possible ::pwtk:: from $inNN if { [regsub ^::pwtk:: $inNN {}] ne [namespace tail $inNN] } { ::pwtk::error "input namespace \"$inNN\" is not the first descendant of the ::pwtk namescape" 1 } set inNN [namespace tail $inNN] if { $inNN in $auto_inNN_list || [namespace exists ::pwtk::$inNN] } { ::pwtk::error "cannot define the input with the '$inNN' namespace because the namespace ::pwtk::$inNN already exists" 1 } lappend auto_inNN_list $inNN set prog2runCmd($prog) ::pwtk::$runCmd set prog2inNN($prog) ::pwtk::$inNN namespace eval ::pwtk::$inNN { variable inNN variable exeCmd # arrays: variable PWTK2QEnml variable QE2PWTKnml variable PWTK2QEcard variable QE2PWTKcard variable closingKeyword } set ::pwtk::${inNN}::inNN $inNN set ::pwtk::${inNN}::exeCmd $prog # inputSpecsList pwtk::inputSpecs_ $prog $inNN $inputSpecsList # export extra cmds if { $exportCmds ne {} } { lappend ::pwtk::${inNN}::exportList $exportCmds } # load configuration files ::pwtk::loadConfig_ ::pwtk::$inNN $inNN.tcl # define "iron" procs & shortcuts for ::pwtk::${inNN} proc ::pwtk::${inNN}_fprint {{file {}}} [concat uplevel ::pwtk::${inNN}::fprint \$file ] proc ::pwtk::${inNN}_get {} [list uplevel ::pwtk::${inNN}::get ] proc ::pwtk::${inNN}_clear {} [list uplevel ::pwtk::${inNN}::clear ] proc ::pwtk::${inNN}::fprint {{file {}}} [concat ::pwtk::input::fprint_ ::pwtk::${inNN} \$file] proc ::pwtk::${inNN}::get {} { variable input_flow_list_specs variable namelist_flow_list variable card_flow_list variable PWTK2QEnml variable PWTK2QEcard variable closingKeyword if { [info procs loadDefaults_ ] ne {} } { loadDefaults_ } set result "" foreach elem $input_flow_list_specs { lassign $elem type name switch -glob $type { namelist* { set out [::pwtk::input::namelist.affixGet $name] ::pwtk::ifnotempty PWTK2QEnml($name) { # replace PWTKname with QEname set out [regsub -- \\&$name $out \\&$PWTK2QEnml($name)] } append result $out } card* { set out [::pwtk::input::cardGet $name] ::pwtk::ifnotempty PWTK2QEcard($name) { # replace PWTKname with QEname set out [regsub -- "^$name" $out $PWTK2QEcard($name)] } ::pwtk::ifnotempty out { append result [string trimright $out]\n # do we have a closed card? ::pwtk::ifexist closingKeyword($name) { append result $closingKeyword($name)\n } append result \n } } } } return $result } proc ::pwtk::${inNN}::clear {} { variable input_flow_list foreach name $input_flow_list { ::pwtk::input::clear $name } } proc ::pwtk::${inNN}::load_from[string toupper $inNN] {input {clear_existing 1}} { variable inNN variable exeCmd variable namelist_flow_list variable card_flow_list variable input_flow_list_specs variable QEnml_flow_list variable QEcard_flow_list variable QEcard_closing_list variable QE2PWTKcard ::pwtk::fileMustExist $input "$exeCmd input" if { [::pwtk::is_true $clear_existing] } { # clear the current pw.x input data ... ::pwtk::${inNN}::clear } # read namelists & handle QE --> PWTK renaming set output [::pwtk::read_QEinput_ $input \ $QEnml_flow_list $QEcard_flow_list $QEcard_closing_list \ $namelist_flow_list $card_flow_list $input_flow_list_specs \ QE2PWTKcard] #set fid [open $input r] #set output "" # #foreach QEname $QEnml_flow_list PWTKname $namelist_flow_list { # # # find the namelist-type from input_flow_list_specs, which # # contains the {{type PWTKname} {type1 PWTKname1} ...} list # # set ind [lsearch -glob $input_flow_list_specs {* $PWTKname}] # set type [lindex [lindex $input_flow_list_specs $ind] 0] # # seek $fid 0 start # if { $type eq "namelist" } { # append output [::pwtk::readNml $fid $QEname $PWTKname 0 0] # } else { # append output [::pwtk::readNml_w_affix $fid $QEname $PWTKname $QEnml_flow_list [concat $QEcard_flow_list $QEcard_closing_list] 0 0] # } #} #close $fid # ## read cards # #set cardOut [::pwtk::readCards $input $QEcard_flow_list $QEcard_closing_list] # #if { $QEcard_flow_list ne $card_flow_list } { # # replace QEnames with PWTKnames # set out "" # foreach line [split $cardOut \n] { # set word [lindex $line 0] # ::pwtk::ifnotempty QE2PWTKcard($word) { # set line [regsub ^$word [string trim $line] $QE2PWTKcard($word)] # } # append out $line\n # } # set cardOut $out #} # #if { $cardOut ne {} } { append output $cardOut\n } # #eval $output #::pwtk::input::namelists_ityp2atmSymb_ $namelist_flow_list if { $output eq {} } { ::pwtk::error "input file \"$input\" does not appear to be the $exeCmd input file" 1 } } # define the corresponding run command if { [info procs ::pwtk::$runCmd] ne {} } { ::pwtk::error "cannot create ::pwtk::$runCmd command because it already exists" 1 } proc ::pwtk::$runCmd {args} " treat_run_ {*}\$args outdir_create wfcdir_create return \[makeInputAndRun_ ::pwtk::${inNN} $prog {*}\$args] " # build a list of cmds to export set elist [list $runCmd ${inNN}_fprint ${inNN}_get ${inNN}_clear] lappend runXX_exportList $runCmd; # N.B. for ::pwtk::treatrun, which uses ::pwtk::runXX_exportList lappend ::pwtk::${inNN}::exportList load_from[string toupper $inNN] if { $rerunScript ne {} } { proc ::pwtk::re$runCmd {args} " treat_run_ {*}\$args input_pushpop { $rerunScript plugins_restart_ $prog set result \[$runCmd -append {*}\$args] } return \$result " lappend elist re$runCmd lappend runXX_exportList re$runCmd } lappend exportList {*}$elist namespace export {*}$elist namespace eval :: namespace import -force {*}[lmap cmd $elist {list ::pwtk::$cmd}] namespace eval ::pwtk::${inNN} { set ns [namespace current] namespace export {*}$exportList namespace eval :: namespace import -force {*}[lmap cmd $exportList {list ${ns}::$cmd}] } }