TABLE OF CONTENTS


::pwtk::pwi::abc2celldm

SYNOPSIS

proc ::pwtk::pwi::abc2celldm {} {

PURPOSE

Transform the A,B,C,cosAB,cosAC,cosBC cell specification in the SYSTEM namelist into the celldm(1)--celldm(6) specification based on ibrav.

BEWARE

If ibrav==0 & CELL_PARAMETERS are specified in angstrom or bohr units, then celldm(1) is set and CELL_PARAMETERS are transformed to alat units.

If cell is already specified with celldm(i) nothing is done, otherwise A,B,C,cosAB,cosAC,cosBC are unset and celldm(i) are set.

REMARK

This routine is based on the abc2celldm subroutine in QE's Modules/latgen.f90 (if new lattices are introduced to QE, this cmd must be updated).

SOURCE

    set ibrav [ibrav]
    if { $ibrav == "" } {
        ::pwtk::error "ibrav is not defined" 1
    }

    if { $ibrav == 0 } {
        #
        # free lattice: transform CELL_PARAMETERS to alat & set celldm(1)
        #
        set unit [::pwtk::input::cardGetFlags CELL_PARAMETERS trim]
        set cell [::pwtk::input::cardGetContent CELL_PARAMETERS]
        if { $cell == {} } { ::pwtk::error "CELL_PARAMETERS must be specified for ibrav == 0" 1 }
        if { [llength $cell] != 9 } { ::pwtk::error "expected a 3x3 matrix for CELL_PARAMETERS, but got\n$cell" 1 }
        
        if { ! [string match *alat* $unit] } {
            # angstrom || bohr
            set a [::pwtk::norm3 [lrange $cell 0 2]]
            set scale [expr {1.0/$a}]

            if { $unit eq {} } {
                if { [::pwtk::input::namelistGetVarValue SYSTEM celldm(1)] eq {} \
                         && [::pwtk::pwi::aA] } {
                    # from input_pw.html:
                    #   if neither unit nor lattice parameter are specified, 'bohr'
                    #   is assumed - DEPRECATED, will no longer be allowed
                    set unit bohr
                } else {
                    # plain "CELL_PARAMETERS" implies alat units
                    set alat [alat]            
                }
            }
            
            if { [string match *angstrom* $unit] } {
                set alat [expr {$::pwtk::angs2bohr*$a}]
            } elseif { [string match *bohr* $unit] } {
                set alat $a
            }
            SYSTEM " celldm(1) = $alat, A = , a = "
            CELL_PARAMETERS (alat) [::pwtk::scaleVec $scale $cell]
            return
        }
    }
    
    # store A, B, C... & unset them in the SYSTEM namelist
    foreach var {A B C cosAB cosAC cosBC} {
        set varName [::pwtk::input::namelistGetVarNoCase SYSTEM $var]
        set value   [::pwtk::input::namelistGetVarValue SYSTEM $varName]

        SYSTEM " $varName = "

        if { $var == "A" && $value == {} } {
            # not using A, B, C...
            return
        }

        ::pwtk::ifset value 0.0
        set $var $value

        # $value must be a number (or expression)
        if { ! [::pwtk::is_expr $value] } {
            ::pwtk::error "expected a number for lattice parameter $var, but got \"$value\"" 1
        }
    }

    # check lattice-parameters values
    
    if { $A <= 0.0 } { ::pwtk::error "lattice parameter A must be >= 0.0, but got $A" 1 }
    if { $B <  0.0 } { ::pwtk::error "lattice parameter B must be > 0.0, but got $B" 1 }
    if { $C <  0.0 } { ::pwtk::error "lattice parameter C must be > 0.0, but got $C" 1 }
    if { abs($cosAB) > 1.0 } { ::pwtk::error "lattice parameter cosAB must be in \[-1,1\], but got $cosAB" 1 }
    if { abs($cosAC) > 1.0 } { ::pwtk::error "lattice parameter cosAC must be in \[-1,1\], but got $cosAC" 1 }
    if { abs($cosBC) > 1.0 } { ::pwtk::error "lattice parameter cosBC must be in \[-1,1\], but got $cosBC" 1 }
    
    # load celldm() ...
    
    set celldm(1) [expr $A * $::pwtk::angs2bohr]
    set celldm(2) [expr $B / $A]
    set celldm(3) [expr $C / $A]
    set celldm(4) 0.0
    set celldm(5) 0.0
    set celldm(6) 0.0

    if { $ibrav == 14 } {        
        # ... triclinic lattice
        set celldm(4) $cosBC
        set celldm(5) $cosAC
        set celldm(6) $cosAB
        
    } elseif { $ibrav == -12 || $ibrav == -13 } {
        # ... monoclinic P or base centered lattice, unique axis b     
        set celldm(5) $cosAC
        
    } elseif { abs($ibrav) == 5 || $ibrav == 12 || $ibrav == 13 } {
        # ... trigonal and monoclinic lattices, unique axis c     
        set celldm(4) $cosAB
    }
    
    foreach i [seq 1 6] {
        if { $celldm($i) != 0.0 } { SYSTEM " celldm($i) = $celldm($i) " }
    }
}