TABLE OF CONTENTS
::pwtk::definePlugin
SYNOPSIS
proc ::pwtk::definePlugin {pluginName flag input QEprograms inputSpecsList {restartScript {}} {scratchScript {}} {exportCmds {}}} {
PURPOSE
Register/define a new plugin for QE so that PWTK knows how to handle its input and run calculations. (This is a (semi)automatic way of adding a new QE plugin to PWTK.)
ARGUMENTS
- pluginName -- plugin name (e.g. environ); the generated commands reside in ::pwtk::$plugin namespace
- flag -- command-line flag to activate the plugin (e.g. -environ)
- input -- name of the input file to activate the plugin (e.g. environ.in)
- QEprograms -- for which QE programs, the plugin is available
- inputSpecsList -- list specifying the structure of the plugin input (this is equivalent to the 'inputSpecsList' argument of ::pwtk::defineInput4Program)
- restartScript -- (optional) the restart PWTK script needed to restart the plugin calculation
- scratchScript -- (optional) the PWTK script needed to switch off the plugin restart calculation (i.e. how to make "from_scratch" plugin calculation)
- exportCmds -- (optional) list of procs in the ::pwtk::${plugin} namespace to export and import into global namespace for convenience (if there are no procs to export, exportCmds should be an empty string)
EXAMPLE
definePlugin oscdft -oscdft oscdft.in pw.x { { namelist OSCDFT {} } { card_wo_flags TARGET_OCCUPATION_NUMBERS {} } { card_wo_flags GAMMA_VAL {} } }
SOURCE
variable plugin #variable auto_inNN_list; # list of auto-defined input namespaces variable runXX_exportList variable exportList variable QE2PWTKname if { $pluginName in $plugin(list) || [namespace exists ::pwtk::$pluginName] } { ::pwtk::error "cannot define the plugin with the '$pluginName' namespace because the namespace ::pwtk::$pluginName already exists" 1 } lappend plugin(list) $pluginName array set plugin [list $pluginName,flag $flag \ $pluginName,input $input \ $pluginName,programs $QEprograms \ $pluginName,restartScript $restartScript] namespace eval ::pwtk::$pluginName { variable plugin; # plugin name (defined for convenience) # arrays: variable PWTK2QEnml variable QE2PWTKnml variable PWTK2QEcard variable QE2PWTKcard variable closingKeyword } set ::pwtk::${pluginName}::plugin $pluginName # inputSpecsList ::pwtk::pluginSpecs_ $pluginName $inputSpecsList # export extra cmds if { $exportCmds ne {} } { lappend ::pwtk::${pluginName}::exportList $exportCmds } # load configuration files ::pwtk::loadConfig_ ::pwtk::$pluginName $pluginName.tcl # define "iron" procs & shortcuts for ::pwtk::${pluginName} proc ::pwtk::${pluginName}_fprint {{file {}}} [concat uplevel ::pwtk::${pluginName}::fprint \$file ] proc ::pwtk::${pluginName}_get {} [list uplevel ::pwtk::${pluginName}::get ] proc ::pwtk::${pluginName}_clear {} [list uplevel ::pwtk::${pluginName}::clear ] proc ::pwtk::${pluginName}::fprint {{file {}}} [concat ::pwtk::input::fprint_ ::pwtk::${pluginName} \$file] proc ::pwtk::${pluginName}::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::${pluginName}::clear {} { variable input_flow_list foreach name $input_flow_list { ::pwtk::input::clear $name } } proc ::pwtk::${pluginName}::save_${input} {file} { variable plugin fprint $::pwtk::plugin($plugin,input) ::pwtk::print "Making a backup copy of $::pwtk::plugin($plugin,input) to $file\n" file copy -force $::pwtk::plugin($plugin,input) $file } proc ::pwtk::${pluginName}::load_${input} {input {clear_existing 1}} { variable plugin 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 "::pwtk::plugin($plugin,input) input" if { [::pwtk::is_true $clear_existing] } { # clear the current pw.x input data ... ::pwtk::${plugin}::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 & handle QE --> PWTK renaming # #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 $plugin input file" 1 } } proc ::pwtk::${pluginName}::${pluginName} {{mode {}}} { variable plugin if { ! [info exists ::pwtk::state($plugin)] } { set ::pwtk::state($plugin) off } set PLUGIN [string toupper $plugin] if { $mode != {} } { if { $::pwtk::plugin($plugin,restartScript) ne {} } { # plugin has a restart mode if { $mode eq "restart" } { ::pwtk::print "$PLUGIN restart mode activated with:\n $::pwtk::plugin($plugin,restartScript)\n" eval $::pwtk::plugin($plugin,restartScript) set mode on } elseif { [regexp scratch $mode] } { ::pwtk::print "$PLUGIN restart disabled with:\n $::pwtk::plugin($plugin,scratchScript)\n" eval $::pwtk::plugin($plugin,scratchScript) set mode on } } if { ! [::pwtk::type::number fboolean $mode] } { pwtk::error "$plugin mode must be boolean, but got mode = $mode" 1 } set postfix {} if { [info exists ::pwtk::RUNopt(POSTFIX)] } { set postfix $::pwtk::RUNopt(POSTFIX) } set ind [lsearch -regexp $postfix ^-+$::pwtk::plugin($plugin,flag)] if { $mode } { ::pwtk::print "$PLUGIN mode is ON\n" set ::pwtk::state($plugin) on # add the plugin's flag to POSTFIX if { $ind < 0 } { lappend ::pwtk::RUNopt(POSTFIX) $::pwtk::plugin($plugin,flag) } } else { ::pwtk::print "$PLUGIN mode is OFF\n" set ::pwtk::state($plugin) off set flag [string trimleft $::pwtk::plugin($plugin,flag) -] set ::pwtk::RUNopt(POSTFIX) [lsearch -inline -all -not -regexp $postfix ^-+$flag] } } return $::pwtk::state($plugin) } # export/import cmds set elist [list ${pluginName}_fprint ${pluginName}_get ${pluginName}_clear] lappend ::pwtk::${pluginName}::exportList $pluginName load_$input save_$input lappend exportList {*}$elist namespace export {*}$elist namespace eval :: namespace import -force {*}[lmap cmd $elist {list ::pwtk::$cmd}] namespace eval ::pwtk::${pluginName} { set ns [namespace current] namespace export {*}$exportList namespace eval :: namespace import -force {*}[lmap cmd $exportList {list ${ns}::$cmd}] } }