# Python to extract data from two files, and then do a calculation with those data

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)

(Screenshot 2)

(Screenshot 3)

(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)

Used pymatgen to parse born matrix

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

print(sum)


• Pymatgen or ASE will also load the POSCAR as a minor robustness tweak Jan 20 at 21:17

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:
with open(outcar_file, 'r', newline='') as f:

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):