8
$\begingroup$

There are two files named ‘OUTCAR’ and ‘POSCAR’.

The ‘OUTCAR’ file consists of many lines including the following (Screenshot 1):

(It is noted that, there are data for 48 ions in that OUTCAR file, though the screenshot-1 shows here a portion till 3rd ion)

And the ‘POSCAR’ file consists of many lines including the following (Screenshot 2):

(It is noted that, the screenshot-2 shows a portion of data. But we will be interested to consider up to 48th row of data, after the 'Direct' heading)

What I need is, I need to extract and multiply data from the OUTCAR and POSCAR files in the following way (Screenshot 3):

That is, the result will be,

result = (1_22 * X_13) + (2_22 * X_23) + (3_22 * X_33) + . . . .+ (48_22 * X_483)

For example, according to the screenshot, the result will be:

result  = (1.01531*0.2396715232098912) + (1.01531*0.2396715232098912) + (1.01531*0.2603284767901088) + ..... till 48th

Therefore, I need to get the calculation result for 48 ions, according to the screenshot-3.

Then I need to print and save the "result" and the "list of the individual product" in an excel/text file.

I am requesting how to do this with the help of Python? Any kind of help is greatly appreciated. (Screenshot 1) enter image description here

(Screenshot 2) enter image description here

(Screenshot 3) enter image description here

For convenience, I have uploaded the OUTCAR and POSCAR files in this drive link: Downloadable Link

(Optional: Somehow I could not upload it in the mattermodeling git link, it will be highly appreciated if the two files can be taken to there - in needed)

$\endgroup$

2 Answers 2

5
$\begingroup$

Used pymatgen to parse born matrix

import numpy as np
from pymatgen.io.vasp.outputs import Outcar
vf = Outcar("OUTCAR")
born=vf.born
poscar=np.loadtxt('POSCAR',skiprows=8)[:48,:]
sum=0
for i in range(len(poscar)):
    sum=sum+poscar[i,2]*born[i,1,1]
      
    
print(sum)

$\endgroup$
1
  • $\begingroup$ Pymatgen or ASE will also load the POSCAR as a minor robustness tweak $\endgroup$ Commented Jan 20, 2023 at 21:17
3
$\begingroup$

My version, tested on Python 3.10:

import re
from operator import mul
from itertools import chain

def cars2list(poscar_file, outcar_file):
    """
    Function takes postcar file, outcar file, extracts data and returns a list that can be saved as a
    csv file using ; as a delimiter, following the model given in the question. Note this function is quite
    fragile in the sense the regexps used depend on precise character counts and spacings, at least for
    the poscar, and then rely input files in production are very similar to those given as examples in
    the question. So, if the files depart from the examples given, for example, containing other sections
    with data formated the same way, errors may occur. The only check done it to measure the amount of
    values recovered from both files, to see if the match.
    """
    with open(poscar_file, 'r', newline='') as f:
        poscar_text = f.read()
    with open(outcar_file, 'r', newline='') as f:
        outcar_text = f.read()

    pattern_poscar = re.compile(r"""\s{1,2} -?0\.\d{16}
                                    \s{1,2} -?0\.\d{16}
                                    \s{1,2} (-?0\.\d{16})
                                    \n
                                 """,
                                re.VERBOSE)
    pattern_outcar = re.compile(r"""\s ion \s+ \d+\n
                                    \s+ 1  \s+ -?\d+\.\d+ \s+
                                               -?\d+\.\d+ \s+
                                               -?\d+\.\d+\n
                                    \s+ 2  \s+ -?\d+\.\d+ \s+
                                               (-?\d+\.\d+ \s+)
                                               -?\d+\.\d+\n
                                 """,
                                re.VERBOSE)

    poscar_data = [float(n) for n in pattern_poscar.findall(poscar_text)]
    outcar_data = [float(n) for n in pattern_outcar.findall(outcar_text)]
    assert len(poscar_data) == len(outcar_data), "Problem. Data recovered from POSCAR and OUTCAR are not the same size."
    products = [x * y for x, y in zip(outcar_data, poscar_data)]

    head = [('From OUTCAR', 'From POSCAR', 'Product')]
    body = zip(map(str, outcar_data), map(str, poscar_data), map(str, products))
    tail = [('', 'Sum:', str(sum(products)))]
    return [';'.join((colA, colB, colC + '\n')) for colA, colB, colC in chain(head, body, tail)]

def main():
    L = cars2list('POSCAR', 'OUTCAR')
    with open('results.csv', 'w') as f:
        f.writelines(L)
    print('Done! Look for the file with results in the same folder as the .py file.')

if __name__ == '__main__':
    main()

The results are saved to a CSV file, where data can be further processed, or checked for correctness (note I hid some of the rows, so both begin and end of spreadsheet is visible):

enter image description here

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .