TABLE OF CONTENTS


::pwtk::neb_refine_merge

SYNOPSIS

proc ::pwtk::neb_refine_merge {src_prefix ref_prefix iref_IS iref_FS} {

PURPOSE

Merge the original (aka previous-NEB) and refined NEB *.dat, *.int, *.axsf, and *.xyz files. The refined NEB means a NEB calculation on a segment of the original minimum-energy path (MEP), for example, performed by the ::pwtk::neb_refine_auto or ::pwtk::neb_refine command.

The name of the merged files is based on the names of the refined files; if the refined files are named refined.name.*, then the merged files are named merged.name.*

REMARK

This routine is used by ::pwtk::neb_refine and ::pwtk::neb_refine_auto

ARGUMENTS

RETURN VALUE

A dictionary of the merged filenames, where key is the file-type and value the file-name, i.e.:

      dat file.dat   int file.int   axsf file.axsf   xyz file.xyz    

SOURCE

    set exts {.dat .int .crd .axsf .xyz}
    foreach e $exts {
        set ext [string trim $e .]
        # if prefixes are specified 'file.$ext', strip the extension
        set srcFile($ext) [::pwtk::headname $src_prefix $exts].$ext
        set refFile($ext) [::pwtk::headname $ref_prefix $exts].$ext
        ::pwtk::fileMustExist $srcFile($ext) "neb.x $ext file"
        ::pwtk::fileMustExist $refFile($ext) "neb.x $ext file"
    }

    # read *.dat files
    proc read_datfile_ {datfile d_var dE_var err_var N_var} {
        upvar $d_var d $dE_var dE $err_var err $N_var N
        foreach line [split [::pwtk::readFile $datfile] \n] {
            if { [llength $line] == 3 } {
                incr N
                lassign $line d($N) dE($N) err($N)
            }
        }
    }
    read_datfile_ $srcFile(dat) src_d src_dE src_err src_N
    read_datfile_ $refFile(dat) ref_d ref_dE ref_err ref_N

    if { $iref_IS < 1 || $iref_FS > $src_N || $iref_IS >= $iref_FS } {
        ::pwtk::error "iref_IS & iref_FS indices are either out of range or improperly chosen,\nmust be within \[1,$src_N], but got \[$iref_IS,$iref_FS]" 1
    }

    # distance-scale to match "refined" with the "source (aka previous-NEB)
    
    set dsc [expr $src_d($iref_FS) - $src_d($iref_IS)]
    
    # merge *.dat file
     
    set dat_fmt "  %16.10f  %16.10f  %16.10f\n"
    for {set i 1} {$i <= $src_N} {incr i} {        
        if { $i <= $iref_IS || $i >= $iref_FS } {
            append result(dat) [format $dat_fmt $src_d($i) $src_dE($i) $src_err($i)]

            # save coordinates
            incr image
            set coor($image) [::pwtk::formatCoor  [::pwtk::xsf::getPrimCoor $srcFile(axsf) $i] ]
            
            if { $i == $iref_IS } {
                # insert the refined *.dat file from image 2,ref_N-1
                for {set j 2} {$j <= $ref_N-1} {incr j} {
                    set d  [expr $src_d($i) + $dsc*$ref_d($j)]
                    set dE [expr $src_dE($i) + $ref_dE($j)]
                    append result(dat) [format $dat_fmt $d $dE $src_err($i)]

                    incr image
                    set coor($image) [::pwtk::formatCoor  [::pwtk::xsf::getPrimCoor $refFile(axsf) $j] ]
                }
            }
        }
    }
    
    # read *.int files

    proc read_intfile_ {intfile d_var dE_var N_var} {
        upvar $d_var d $dE_var dE $N_var N
        foreach line [split [::pwtk::readFile $intfile] \n] {
            if { [llength $line] == 2 } {
                incr N
                lassign $line d($N) dE($N)
            }
        }
    }
    read_intfile_ $srcFile(int) src_int_d src_int_dE src_int_N
    read_intfile_ $refFile(int) ref_int_d ref_int_dE ref_int_N

    # merge *.int files
    
    set int_fmt "  %16.10f  %16.10f\n"
    
    for {set i 1} {$i <= $src_int_N} {incr i} {        
        if { $src_int_d($i) < $src_d($iref_IS) || $src_int_d($i) > $src_d($iref_FS) } {
            
            append result(int) [format $int_fmt $src_int_d($i) $src_int_dE($i)]

        } else {
            ::pwtk::ifnotexist inserted {
                # insert the refined *.int file
                for {set j 1} {$j <= $ref_int_N} {incr j} {
                    set d  [expr $src_d($iref_IS) + $dsc*$ref_int_d($j)]
                    set dE [expr $src_dE($iref_IS) + $ref_int_dE($j)]
                    append result(int) [format $int_fmt $d $dE]                    
                }
                set inserted 1
            }
        }
    }

    # merge *.axsf & *.xyz files
    
    set nat [::pwtk::xsf::getNAtoms $srcFile(axsf)]
    set result(axsf) "ANIMSTEPS $image
CRYSTAL\nPRIMVEC\n[::pwtk::xsf::getPrimVec $srcFile(axsf)]\n"
    
    for {set i 1} {$i <= $image} {incr i} {
        append result(axsf) "\nPRIMCOORD $i\n$nat 1\n$coor($i)"
        append result(xyz)  "$nat\n\n[::pwtk::formatCoor [::pwtk::atmPosToCoor $coor($i)]]\n"
    }       

    # write the resulting files

    set result_dict [dict create]
    set head merged.[::pwtk::trim_prefix refined [file rootname $refFile(dat)]]
    foreach ext {dat int axsf xyz} {
        set merFile($ext) $head.$ext
        ::pwtk::writeFile $merFile($ext) $result($ext)
        dict append result_dict $ext $merFile($ext)
    }    
    return $result_dict
}