Home Science Coding Design Etc. AboutMe

VASP PROCAR split script (밴드구조에서 원자점유 표현하기)

Dec. 3, 2019   /   2 mins read   /  

PROCAR split script

예전에 VASP 계산을 하던 도중, PROCAR 파일에서 데이터를 추출해야 할 필요가 있었습니다.


위 이미지처럼 Band structure에서 각 원자별로 Band structure에 기여를 (Orbital-projected band structure) 나타내려고 했었는데요.

그래서 열심히 스크립트를 짰는데, 결과물은 별로 맘에 안들었고, 코드는 코드대로 엉망이였습니다. 그리고 나중에 보니 이런 게 이미 있었습니다.. 😐

며칠간의 삽질을 통해 깨달은 건, 역시 뭐든지 검색을 잘 하고 주변 고수들에게 많이 물어봐야 한다는 점입니다. 😂

C shell

#!/bin/csh

# Script to split the PROCAR file by each k-points
echo "how many number of atom?"
set ion = $<
echo "how many number of band?(NBANDS)"
set band = $<
set bandlist = `seq 1 $band`

set inputfile = PROCAR

if (-e $inputfile) then
    echo " The" $inputfile "exists, keep going..."
else
    echo $inputfile " file doesn't exist... please check" $inputfile
    exit 0
endif

rm -rf PROCARtemp
mkdir PROCARtemp
cp $inputfile ./PROCARtemp
cd ./PROCARtemp

# split PROCAR file -> each k-point
#####################################################################
set kpoint = `grep "k-point" $inputfile | cut -d " " -f 2`
set kpoint_line = `grep -n "k-point" $inputfile | cut -d ":" -f 1`
    rm -f kpoint_number
    echo $kpoint_line  >> kpoint_number
set kpoint_ini = `awk '{print $2}' kpoint_number`
set kpoint_fin = `awk '{print $3}' kpoint_number`
set kpoint_range = `expr $kpoint_fin - $kpoint_ini`
set no = 0

foreach i ($kpoint_line)
        echo "bandline split... "$no
    set ii = `expr $i + $kpoint_range`
    set ii = `expr $ii - 1`
    rm -f "kpoint"$no
    sed -n $i,${ii}p $inputfile >> "kpoint"$no
    set no = `expr $no + 1`
end
rm -f "kpoint"0
rm -f kpoint_number
#####################################################################

# each k-point files -> split each band
#####################################################################
set kpoint_inputfile = kpoint
set kpointlist = `ls | grep "kpoint" | cut -d 't' -f 2`

foreach kpoint ($kpointlist)
    set kpoint_no = $kpoint
    echo "k-ponit "$kpoint_no "split ing..."
#
# check number of ions
#
    set ion_line = `grep -n "ion" $kpoint_inputfile$kpoint_no | cut -d ":" -f 1`
    rm -f ionnumber
    echo $ion_line | cut -d " " -f 1- >> ionnumber
    set ion_ini = `awk '{print $1}' ionnumber`
    set ion_fin = `awk '{print $2}' ionnumber`
    set ion_range = `expr $ion_ini + $ion`
#####################################################################

# split occupation for each atoms at each bands
#####################################################################
    set b = 1
    set c = 2
    set no_band = `cat ionnumber | wc -w`
    set listofatoms = `seq 1 2 $no_band`

    rm -f ionsplit
        if (-e ionsplit_temp\*) then
        rm -f ionsplit_temp*
        else
    endif
    rm -f ionsplit_fin$kpoint_no

    foreach x ($listofatoms)
        set ion_ini = `awk -v x="$x" '{print $x}' ionnumber`
        #set ion_ini = `expr $ion_ini + 1`
        set y = `expr $x + 1`
        set ion_fin = `awk -v y="$y" '{print $y}' ionnumber`
        set ion_range = `expr $ion_ini + $ion`
        #echo $ion_ini "ini   " $ion_fin "fin    " $ion_range "range     " $i $j
        #set ion_no =
        set noofatom = `seq $ion_ini $ion_range`

            foreach k ($noofatom)
                sed -n ${k}p ${kpoint_inputfile}$kpoint_no >> ionsplit_temp_${kpoint_no}_${k}        # 
            end

        set b = `expr $b + 2`
        set c = `expr $c + 2`
    end
# assemble occupation for each atoms at each bands
#############################################################################
    set b = 1
    set c = 2
    set mergeatoms = `ls -v | grep "ionsplit_temp_${kpoint}" | cut -d '_' -f 3`
echo $mergeatoms

    foreach x ($mergeatoms)
        set ion_ini = `awk -v x="$x" '{print $x}' ionnumber`
        set y = `expr $x + 1`
        set ion_fin = `awk -v y="$y" '{print $y}' ionnumber`
        set ion_range = `expr $ion_ini + $ion`
        set noofatom = `seq $ion_ini $ion_range`

        foreach k ($noofatom)
            set kk = `expr $k + 1`
            if (-e ionsplit_temp_${kpoint_no}_${kk}) then
                cat ionsplit_temp_${kpoint_no}_${kk} >> ionsplit_temp_${kpoint_no}_$ion_ini
                else
            endif
    end

        set b = `expr $b + 2`
        set c = `expr $c + 2`
        cat ionsplit_temp_${kpoint_no}_${ion_ini} >> ionsplit_fin_${kpoint_no}
        #echo ionsplit_temp${ion_ini}
    end
############################################################################
rm -f ionsplit_temp*

cat ionsplit_fin_${kpoint_no} | tr "\n" "\t" | sed 's/\tion/\nion/g' > ../PROCAR_kpoint${kpoint_no}

end

cd ..

set merge_input = PROCAR_kpoint
set mergelist = `ls -v | grep "PROCAR_kpoint" | cut -d 't' -f 2`
set input_linemax = `grep -c '\n' PROCAR_kpoint1`
set input_lineno = `seq 1 $input_linemax`

rm -rf PROCAR_result
foreach m ($mergelist)
        foreach n ($input_lineno)
        echo `sed -n ${n}p $merge_input$m` >> PROCAR_result
        end
        echo "" >> PROCAR_result
end

#rm -rf PROCARtemp
echo "done!"


당시엔 뭐 이런식으로 스크립트를 짰었는데요. 사실 너무 코드가 엉망진창이지만, 기록을 남겨놓아야 같은 실수를 반복하지 않으니.. 하고 올려봅니다.

아참, 혹시라도 PROCAR 를 분석하는 툴이 필요하다면 무료소프트웨어인 p4v를 추천해드립니다.