TABLE OF CONTENTS


::pwtk::pwo::getStructData

SYNOPSIS

proc ::pwtk::pwo::getStructData {what args} {

USAGE

   ::pwtk::pwo::getStructData what [-k] pwoFile [index]

PURPOSE

The master structure retrieval routine for getting the index-th structure (CELL_PARAMETERS, ATOMIC_POSITIONS, ATOMIC_FORCES and their combination) from pw.x output file.

Not meant to be used directly, use the ::pwtk::pwo::getPrimVec, ::pwtk::pwo::getAtmPos, or ::pwtk::pwo::getStruct instead.

ARGUMENTS

Possible values for the 'what' argument: * cell, vectors, CELL_PARAMETERS ==> returns CELL_PARAMETERS * atoms, coordinates, positions, ATOMIC_POSITIONS ==> returns ATOMIC_POSITIONS * atomforce, coorforce, posforce ==> returns ATOMIC_POSITIONS & ATOMIC_FORCES with the following lines "atmSymbol x y z fx fy fz" * both ==> returns CELL_PARAMETERS + ATOMIC_POSITIONS * all ==> implies cell + atomforce

SOURCE

    # parse arguments ...
    
    set options {
        {k "include the keyword line in the result"}
    }
    set usage ":   ::pwtk::pwo::getStructData what \[-k] pwoFile \[index]"

    array set opt [::cmdline::getoptions args $options $usage]

    set narg [llength $args]
    if { $narg < 1 || $narg > 2 } {
        ::pwtk::error "Usage $usage" 1
    }

    set prependKeyword $opt(k)
    set pwoFile [lindex $args 0]
    set index   [expr { $narg == 1 ? "end" : [lindex $args 1] }]    
    
    # do the job ...
    
    set fid    [open $pwoFile r]
    set l_vec  {}
    set l_coor {}
    set l_force {}
    set nat    0
    set l_first_vec  1
    set l_first_coor 1

    if { ! [string is boolean $prependKeyword]  } {
        ::pwtk::error "prependKeyword must be of boolean type; assuming it is true"
        set prependKeyword 1
    }

    while { ! [eof $fid] } {
        #
        gets $fid line
        #
        if { [string match {*number of atoms/cell*} $line] } {
            
            set nat [lindex $line end]
            
        } elseif { [string match {*crystal axes: \(cart. coord. in units of a*} $line] && $l_first_vec } {

            set l_first_vec 0

            if { $prependKeyword} {
                set vec "CELL_PARAMETERS (alat)\n"
            } else {
                set vec ""
            }

            append vec [lrange [string map {( "" ) ""} [gets $fid]] 2 4]\n
            append vec [lrange [string map {( "" ) ""} [gets $fid]] 2 4]\n
            append vec [lrange [string map {( "" ) ""} [gets $fid]] 2 4]\n

            lappend l_vec $vec

        } elseif { [string match CELL_PARAMETERS* $line] } {
            
            if { $prependKeyword} {
                set vec $line\n
            } else {
                set vec ""
            }

            append vec [gets $fid]\n
            append vec [gets $fid]\n
            append vec [gets $fid]\n

            lappend l_vec $vec
        
        } elseif { [string match {*Cartesian axes*} $line] && $l_first_coor } {
            #
            # initial coordinates 
            #
            set l_first_coor 0
            gets $fid line; # empty line
            gets $fid line; # site n.     atom                  positions (a_0 units)
            
            if { $prependKeyword} {
                set key "ATOMIC_POSITIONS (alat)\n"
            } else {
                set key ""
            }

            set coor ""            
            for {set ia 0} {$ia < $nat} {incr ia} {
                set line [gets $fid]
                append coor [concat [lindex $line 1] [lrange [string map {( " " ) " "} $line] 5 7]]\n
            }

            # Try to transform coor to atmPos, but be cautious:
            # perhaps ATOMIC_POSITIONS card is empty or has a
            # different number of atoms; use transformation only if
            # the number-of-atoms matches
            
            set atmPos [::pwtk::pwi::coorToAtmPos $coor]
            if { [::pwtk::getNAtoms $coor] == [::pwtk::getNAtoms $atmPos] } {
                lappend l_coor ${key}$atmPos
            } else {
                lappend l_coor ${key}$coor
            }
        } elseif { [string match ATOMIC_POSITIONS* $line] } {

            if { $prependKeyword} {
                set coor $line\n
            } else {
                set coor ""
            }
            
            for {set ia 0} {$ia < $nat} {incr ia} {
                append coor [gets $fid]\n
            }

            lappend l_coor $coor
        } elseif { [string match {*Forces acting on atoms*} $line] } {

            if { $prependKeyword } {
                set force "ATOMIC_FORCES\n"
            } else {
                set force ""
            }

            gets $fid; # empty line
            for {set ia 0} {$ia < $nat} {incr ia} {
                append force [lrange [gets $fid] end-2 end]\n
            }
            lappend l_force $force
        }
    }
    close $fid

    proc atomforce_ {prependKeyword l_coor l_force index} {
        set coor  [lindex $l_coor $index]
        set force [lindex $l_force $index]
        if { $prependKeyword } {
            # strip the keyword from $l_coor & $l_force
            append result [concat [lindex [split $coor \n] 0] [lindex [split $force \n] 0]]\n
            #
            set coor  [join [lrange [split $coor  \n] 1 end] \n]
            set force [join [lrange [split $force \n] 1 end] \n]
        }
        foreach {a x y z} $coor {fx fy fz} $force {
            append result [format $::pwtk::fmt_coor(7) $a $x $y $z  $fx $fy $fz]
        }
        return $result
    }

    switch -nocase -glob --  $what {    
        cell* -
        vec* {
            # vectors
            set result [lindex $l_vec $index]
        }
        both {
            # vectors + atoms
            set result [lindex $l_vec $index]\n[lindex $l_coor $index]      
        }
        all {
            # vectors + atoms + forces            
            set result [lindex $l_vec $index]\n
            append result [::pwtk::pwo::atomforce_ $prependKeyword $l_coor $l_force $index]
        }
        atomfor* -
        pos*for* -
        coor*for* {
            # atoms + forces
            set result [::pwtk::pwo::atomforce_ $prependKeyword $l_coor $l_force $index]
        }
        atom* -
        pos* -
        coor* {
            # atoms
            set result [lindex $l_coor $index]
        }
        for* {
            # forces
            set result [lindex $l_force $index]
        }
        default {
            ::pwtk::error "wrong type of data requested ($what), must be one of vectors, positions, forces, both, or all" 1
            #set result [lindex $l_coor $index]
        }
    }

    return $result
}