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

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:

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