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

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}]
    }
}