TABLE OF CONTENTS


::pwtk::difden::DIFDEN

SYNOPSIS

proc ::pwtk::difden::DIFDEN {content} {

PURPOSE

Specify DIFDEN namelist for "difden" calculation (difden acronym stands for difference-density).

An example of "difden" calculation is the calculation of bonding (formation) density (i.e. charge density difference). For example, consider we want to calculate/plot the charge density difference of AB system as:

      \Delta n(r) = n(AB;r) - [n(A;r) + n(B;r)].  

This would involve 3 scf + 3 pp.x (&inputpp namelist) + 1 pp.x (&plot namelist) calculations. The "difden" utility does it automatically. User only needs to define the atomic structural segments (in the example above, there are three segments: AB, A, B).

    

Here is an example of DIFDEN namelist specification.

    DIFDEN {
       segment(1) = "all"
       weight(1)  = 1.0
       name(1)    = "whole_structure"

       segment(2) = "1 3-7"
       weight(2)  = -1.0
       name(2)    = "name_of_segment_2"
       
       segment(3) = "2 8-"
       weight(3)  = -1.0
       name(3)    = "name_of_segment_3"
    }    

ARGUMENTS

     * nsegment -- [OPTIONAL] number of segments; if not specified, 
                   determined from the specification of segment(*) array.

     * segment(i), i=1,nsegment -- [REQUIRED] specify list of atoms belonging to the segment
                                   using the following syntax: "1 3 4-12 17-21"
                                   (also word "all" can be used, which designates all atoms)
                                   Examples: "all"      -- means all atoms
                                             "1-"       -- means all atoms (i.e. from 1 to the end)"
                                             "1 3-5 7-" -- means atoms 1 3 4 5 and from 7 to the end    
                                      
     * weight(i), i=1,nsegment  -- [REQUIRED] weight of the segment

     * name(i), i=1,nsegment -- [OPTIONAL] symbolic name of the segment 
                                (used for naming the corresponding I/O files)

     * restart -- [OPTIONAL] when true, DIFDEN is restarted from
                  previous (interrupted) run (default = false)

SOURCE

    variable difden

    ::pwtk::input::namelist DIFDEN $content 
    
    set segmentL ""
    set weightL  ""

    foreach var [::pwtk::input::namelistVars_ DIFDEN] {
        
        set value [::pwtk::input::namelistGetVarValue DIFDEN $var 1]
        set index [lindex [split $var ()] 1]

        switch -glob -- [string tolower $var] {
            nsegment { 
                set difden(nsegment) $value
            }
            segment(*) {
                set difden(segment,$index)  $value
                lappend segmentL $index         
                # N.B. difden(atomList,$index) needs to be assigned
                # anly just before the calcs are submitted, i.e.,
                # after difden_run is launched                
            }
            weight(*) {
                set difden(weight,$index) $value
                lappend weightL $index  
            }
            name(*) {
                set difden(name,$index) [string trim $value '\"]
            }
            restart {
                set value [string trim $value .]
                # be polite to user, so that she will know what's the problem
                switch -nocase -exact -- $value {
                    1 - t - true - yes {
                        set difden(restart) 1
                    }               
                    0 - fblocked - false - no {
                        set difden(restart) 0
                    }
                    default {
                        error "illegal value of restart variable: $value, must be true or false (or any other variant of these, such as 0, 1, yes, no, ... )"
                    }
                }
            }
            default {
                ::pwtk::error "unknown variable in DIFDEN namelist"
            }
        }
    }

    if { ! [info exists difden(nsegment)] } {
        set difden(nsegment) 1
    }

    # check that segment(*) and weight(*) array elements span a sequence
    
    set sortedSL [lsort -integer $segmentL]    
    set sortedWL [lsort -integer $weightL]    
    if { ! [::tclu::lequal $sortedSL $sortedWL] } {
        ::pwtk::error "elements of segment(*) and wieght(*) arrays do not match"
    }

    set fi [lindex $sortedSL 0]
    set li [lindex $sortedSL end]
    
    if { $fi != 1 } {
        ::pwtk::error "first elements of segment(*) array does not have index of 1"
    }
    
    for {set i 1} {$i<=$li} {incr i} {
        set im [expr {$i - 1}]
        if { [lindex $sortedSL $im] != $i } {
            ::pwtk::error "elements of segment(*) array have not been specified in sequential manner"
        }
    }
    
    if { $li > $difden(nsegment) } {
        set difden(nsegment) $li
    }    
}