115 lines
3.5 KiB
Python
115 lines
3.5 KiB
Python
import numpy as np
|
|
from typing import Union, List, Iterable
|
|
from monty.re import regrep
|
|
import re
|
|
from echem.io_data.ddec import AtomicNetCharges
|
|
|
|
|
|
|
|
|
|
class GasSensor:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@staticmethod
|
|
def read_OUTCAR(filepath) -> float:
|
|
"""
|
|
This function reads your OUTCAR file to get the final Energy of the system.
|
|
"""
|
|
|
|
file = open(filepath, 'r')
|
|
data = file.readlines()
|
|
file.close()
|
|
|
|
patterns = {'energy_ionic': r'free energy\s+TOTEN\s+=\s+(.\d+\.\d+)\s+eV'}
|
|
matches = regrep(filepath, patterns)
|
|
|
|
end_energy = np.array([float(i[0][0]) for i in matches['energy_ionic']])
|
|
|
|
return end_energy[-1]
|
|
|
|
@staticmethod
|
|
def sort_DDEC_output(filepath, k: int) -> list[int]:
|
|
"""
|
|
This function sorts atoms in your system to get atoms related to your molecule
|
|
k - number of atoms consisting in your molecule
|
|
"""
|
|
|
|
z_coords = {}
|
|
|
|
idx = 1
|
|
|
|
with open(filepath, 'r') as file:
|
|
while True:
|
|
line = file.readline()
|
|
if re.search('\sChargemol', line) is not None:
|
|
break
|
|
|
|
list_of_substrings = line.split(' ')
|
|
if re.search('^\s|^j', list_of_substrings[0]) is None:
|
|
z_coords[idx] = list_of_substrings[-2]
|
|
idx += 1
|
|
continue
|
|
|
|
sorted_z_coords = dict(sorted(z_coords.items(), key = lambda item: item[1], reverse = True))
|
|
|
|
result = []
|
|
counter = 0
|
|
for item in sorted_z_coords:
|
|
if counter < k:
|
|
result.append(item)
|
|
counter += 1
|
|
else:
|
|
break
|
|
|
|
return result
|
|
|
|
@staticmethod
|
|
def get_chrg_mol(filepath, k: int or list[int]) -> float:
|
|
"""
|
|
This function can help you to get the molecule charge.
|
|
filepath - DDEC6 output file: DDEC_even_tempered_net_atomic_charges.xyz
|
|
k - the number of atoms, consisting in molecule. Besides, your can write the ordinal number of an atom in your molecule.
|
|
"""
|
|
|
|
atomic_charges = AtomicNetCharges.from_file(filepath)
|
|
net_charges = atomic_charges.net_charges
|
|
|
|
|
|
if type(k) == int:
|
|
chrg_molecule = 0
|
|
targets = GasSensor.sort_DDEC_output(filepath, k)
|
|
for i in targets:
|
|
chrg_molecule += net_charges[i - 1]
|
|
return chrg_molecule
|
|
elif isinstance(k, list):
|
|
targets = k
|
|
chrg_molecule = 0
|
|
for i in targets:
|
|
chrg_molecule += net_charges[i - 1]
|
|
return chrg_molecule
|
|
|
|
@staticmethod
|
|
def get_Ead(filepath, E_surface, E_molecule) -> float:
|
|
"""
|
|
This function can help you to get the adsorption energy, using energy of whole system, energy of the surface and energy of your molecule.
|
|
filepath - your OUTCAR file obtained as a result of VASP optimization.
|
|
"""
|
|
E_system = GasSensor.read_OUTCAR(filepath)
|
|
E_ad = E_system - E_surface - E_molecule
|
|
#print(E_ad)
|
|
return E_ad
|
|
|
|
@staticmethod
|
|
def get_energy_in_meV(filepath):
|
|
"""
|
|
This function can help you to get energies in meV.
|
|
filepath - your .txt file, consisting of energies in eV.
|
|
"""
|
|
X = np.genfromtxt(filepath)
|
|
X_new = []
|
|
for i in X:
|
|
X_new = X * 1000
|
|
return f'Your energies in meV: {X_new}'
|
|
|