BASH – vasp2xyz, a script to extract coordinates from VASP

Users of VASP are often familiar with the struggles/hardships to easily visualize the coordinates from the output file [OUTCAR]. To that effect, I wrote the following script [with help at a crucial stage from Pat Krogel, CEC @ MTU]. It expects OUTCAR & POSCAR from a calculation to be in the same folder and when successfully completed, it results in OUTPUT_FILENAME.xyz – containing frame-by-frame [corresponding to each (optimization) step] XYZ co-ordinates of the system.


#! /bin/bash
 
# Script to extract the atomic positions (xyz) from 
# POSCAR & OUTCAR files of VASP and write them to a 
# file, to be used with Jmol, MolDen and such other
# third party programs
 
# First written: Gowtham, Tue, 22 Dec 2009 11:11:12 -0500
# Last modified: Gowtham, Tue, 22 Dec 2009 16:29:36 -0500
 
# Essential VASP Files
# If missing, quit the program
export POSCAR="POSCAR"
export OUTCAR="OUTCAR"
 
if [[ -e $POSCAR || -e $OUTCAR ]];
then
  echo
  echo "  $POSCAR & $OUTCAR found"
else
  echo
  echo "  ERROR : POSCAR &/or OUTCAR missing"
  echo
  exit
fi
 
# Output Filename 
# If missing, quit the program
export OUTPUT=$1
 
if [ $# != 1 ]
then
  echo
  echo "  ERROR : OUTPUT_FILENAME Missing"
  echo "  Usage : vasp2xyz.sh OUTPUT_FILENAME"
  echo
  exit
fi
 
# Delete scratch files
rm -f Final.tmp.*
rm -f $OUTPUT.xyz
 
# Atoms related information
# Extracted from POSCAR & OUTCAR
 
# Total number of atom types
# Pat Krogel: Tue, 22 Dec 2009 13:13:48 -050
declare -a ATOM_TYPE=(`sed -n '6 p' $POSCAR`)
export ATOM_TYPE_TOTAL=${#ATOM_TYPE[@]}
 
# Total number of atoms
export ATOMS_TOTAL=0
export i=0
while [[ "$i" -lt "$ATOM_TYPE_TOTAL" ]]
do
  export iATOM_TYPE=${ATOM_TYPE[$i]}
  export ATOMS_TOTAL=`expr $ATOMS_TOTAL + $iATOM_TYPE`
  export i=`expr $i + 1`
done
 
# Atom labels
declare -a ATOM_LABEL=(`grep "POTCAR:" $OUTCAR | head -$ATOM_TYPE_TOTAL | awk '{print $3}' | sed -e 's/_.*//g'`)
export ATOM_LABEL_TOTAL=${#ATOM_LABEL[@]}
 
# Print2Screen
if [[ "$ATOM_TYPE_TOTAL" != "$ATOM_LABEL_TOTAL" ]]
then
  echo
  echo "  ERROR : Atom Type Total ($ATOM_TYPE_TOTAL) does NOT"
  echo "          match Atom Label Count ($ATOM_LABEL_COUNT)"
  echo "  Please make sure OUTCAR & POSCAR are from the same"
  echo "  system and calculation"
  echo 
  exit
else
  echo
  echo "  Number of Atom Types   :" $ATOM_TYPE_TOTAL
  echo "  Atom Type              :" ${ATOM_LABEL[@]}
  echo "  Atom Type Count        :" ${ATOM_TYPE[@]}
  echo "  Total Number of Atoms  :" $ATOMS_TOTAL
 
  # ATOM_LABEL_2 is an array of atom labels
  # with each atom label appearing an appropriate
  # number of times, to a total of $ATOMS_TOTAL
  declare -a ATOM_LABEL_2
  export REPEAT=0
  export j=0
 
  while [[ "$j" -lt "$ATOM_TYPE_TOTAL" ]]
  do
    export k=1
 
    while [[ "$k" -le "${ATOM_TYPE[$j]}" ]]
    do
      export REPEAT=`expr $REPEAT + 1`
      export k=`expr $k + 1`
      ATOM_LABEL_2[$REPEAT]=${ATOM_LABEL[$j]}
    done
 
    export j=`expr $j + 1`
  done
# echo ${ATOM_LABEL_2[@]}
# echo ${#ATOM_LABEL_2[@]}
 
  # Record the line numbers where coordinates are written
  # in OUTCAR. Actual coordinates begin 2 lines below
  # the recorded numbers
  grep -n "POSITION" $OUTCAR | sed -e 's/:/ /g' | sed -e 's/POSITION.*//g' > LINE_NUMBERS.tmp
 
  export FRAME_NUMBER=1
  while read START
  do
    export START_HERE=`expr $START + 2`
    export END_HERE=`expr $START_HERE + $ATOMS_TOTAL - 1`
 
    echo "$ATOMS_TOTAL" >> $OUTPUT.xyz
    echo "# Frame Number: $FRAME_NUMBER" >> $OUTPUT.xyz
    sed -n "$START_HERE,$END_HERE p" $OUTCAR | awk '{printf "%12.8f %12.8f %12.8f\n", $1, $2, $3}' > Final.tmp.$FRAME_NUMBER
 
    export l=1
    while read X Y Z
    do
      echo ${ATOM_LABEL_2[$l]} $X $Y $Z > Final.tmp.$FRAME_NUMBER.$l
      awk '{ printf "%-3s %12.8f %12.8f %12.8f\n", $1, $2, $3, $4 }' Final.tmp.$FRAME_NUMBER.$l >> $OUTPUT.xyz
      export l=`expr $l + 1`
    done<Final.tmp.$FRAME_NUMBER
 
    export FRAME_NUMBER=`expr $FRAME_NUMBER + 1`
  done<LINE_NUMBERS.tmp
 
  export FRAMES_TOTAL=`expr $FRAME_NUMBER - 1`
  echo "  Total Number of Frames :" $FRAMES_TOTAL
  echo
fi
 
# Delete scratch files
rm -f LINE_NUMBERS.tmp 
rm -f Final.tmp.*


Test case

If POSCAR and OUTCAR aren’t handily available for testing, one could download the following:

POSCAR | OUTCAR



vasp2xyz

Running vasp2xyz.sh



vasp2xyz

Resulting xyz file



vasp2xyz

xyz file visualized with Jmol



If you have suggestions to make this better/efficient, please do post them as comments.

14 Replies to “BASH – vasp2xyz, a script to extract coordinates from VASP”

  1. Hi….I already save the script with the name vasp2xyz.sh but I have some problem to execute the program….This is what happen when I want to use the program :

    [revival@localhost Program]$ vasp2xyz
    bash: vasp2xyz: command not found

    Could someone give me an answer about this???

    GBU

  2. It is important [and often assumed] that you place these programs/scripts in one of the locations defined by PATH variable. You could check for this by running the command:

    echo $PATH

    One such common location for keeping user’s personal collection of scripts is ‘bin‘ folder within your $HOME directory. Be sure to change the permission of the downloaded script to 755 [or at least 700] by running the command:

    chmod 700 vasp2xyz.sh

    Assuming that you are using the default shell [/bin/bash] for your login, you will need to add the following line to $HOME/.bashrc file:

    export PATH="$HOME/bin:$PATH"

    Save the file and run the command:

    . $HOME/.bashrc

    Once these [customary] steps are completed, you can call vasp2xyz.sh [or any such script stored in your ‘bin‘ folder] from just about any other folder.

    Hope this helps.

  3. Dear Gowtham,,,,thanks so much for your reply and I did like you told me,,,and this is the result :

    I change the mode of vasp2xyz
    [revival@localhost Program]$ chmod 700 vasp2xyz.sh

    I put the bin path into the .bashrc
    [revival@localhost Program]$ vi ~/.bashrc

    #——————————-
    #this is for vasp2xyz.sh

    export PATH=”$HOME/bin:$PATH”

    and then I try again to execute the vasp2xyz.sh and it doesn’t work

    [revival@localhost Program]$ vasp2xyz.sh
    bash: vasp2xyz.sh: command not found

    This is the $PATH

    [revival@localhost Program]$ echo $PATH
    /home/revival/bin:/home/revival/vtstscripts:/home/revival/ase/tools:/home/revival/XCrySDen-1.4.1bin-shared:/home/revival/vtstscripts:/home/revival/ase/tools:/home/revival/XCrySDen-1.4.1bin-shared:/usr/bin:/bin:/usr/local/bin:/usr/X11R6/bin/:/usr/games:/usr/lib/qt4/bin:/home/revival/XCrySDen-1.4.1bin-shared/scripts:/home/revival/XCrySDen-1.4.1bin-shared/util:/home/revival/bin:/home/revival/XCrySDen-1.4.1bin-shared/scripts:/home/revival/XCrySDen-1.4.1bin-shared/util

    Is there anything that I miss to do???? I’m sorry to ask a very basic question like this because I’m still a newbee in linux,,,,this is the first year for me to learn linux but I’m improving much after I read your reply

    Thanks so much Gowtham

    GBU

  4. Dear Gowtham

    This is the result

    [revival@localhost bin]$ $HOME/bin/vasp2xyz.sh
    bash: /home/revival/bin/vasp2xyz.sh: /bin/bash^M: bad interpreter: No such file or directory

    I already put the file vasp2xyz.sh in bin folder,,,,how do you think Gowtham???

    GBU

  5. Ok – I think I know the problem. The error message says /bin/bash^M. ^M indicates invisible Carriage Return character. To get rid of them, do the following:

    1. vi $HOME/bin/vasp2xyz.sh

    2. :g/CTRL+V+M/s///g

    CTRL+V+M means hold down the Control Key along with V & M

    3. :wq

    4. Then try $HOME/bin/vasp2xyz.sh

    And let me know if this works.

  6. Dear Gowtham

    I try like you told me and I find something strange

    [revival@localhost bin]$ vi $HOME/bin/vasp2xyz.sh

    then I type :g/CTRL+V+M/s///g

    Then I press my keyboard

    And it says :

    E486: Pattern not found: CTRL+V+M

    Then I save it :wq

    After that I try again

    [revival@localhost bin]$ vasp2xyz.sh
    bash: /home/revival/bin/vasp2xyz.sh: /bin/bash^M: bad interpreter: No such file or directory

    for information,,,,,I’m using mandriva operating system,,,,I don’t know whether it always happens like this with mandriva

    So Gowtham,,,,how do you think???

    Thanks so much for helping a newbee like me

    GBU

  7. Dear Gowtham

    I try it again

    I type g/CTRL+V+M/s///g

    CTRL+V+M means hold down the Control Key along with V & M
    and then I press Enter on my keyboard….This is the result :

    E486: Pattern not found: ^M

    So I save it again,,,,and then I type in command line

    [revival@localhost ~]$ $HOME/bin/vasp2xyz.sh
    bash: /home/revival/bin/vasp2xyz.sh: /bin/bash^M: bad interpreter: No such file or directory

    How do you think Gowtham???

    GBU

  8. OK – the last trick in my bag is to try the following command:

    dos2unix $HOME/bin/vasp2xyz.sh

    and see if the command works.

    If not, then you are better off literally typing out the script.

  9. Dear gowtham

    I’m sorry to tell you bad result,,,,it’s fail again,,,

    [revival@localhost ~]$ dos2unix $HOME/bin/vasp2xyz.sh
    bash: dos2unix: command not found

    Then I think I will need to type out the script by own,,,,anyway,,,,thanks so much for helping until now,,,,I appreciate all your kindness

    I will tell again the result

    GBU

Comments are closed.