Files
2026-01-08 19:47:32 +03:00

117 lines
4.7 KiB
Python

from monty.re import regrep
import matplotlib.pyplot as plt
from pathlib import Path
from echem.io_data.jdftx import Output
from echem.core.constants import Hartree2eV
import numpy as np
def get_energies_from_logs(folderpath, plot=False, dpi=200):
patterns = {'en': r'(\d+).(\d+)\s+Current Energy:\s+(.\d+\.\d+)', 'iter': r'Now starting iteration (\d+) on\s+\[(.+)\]'}
NEBlogpath = Path(folderpath) / 'logfile_NEB.log'
pylogpath = Path(folderpath) / 'py.log'
matches_neb = regrep(str(NEBlogpath), patterns)
matches_py = regrep(str(pylogpath), patterns)
iterations_number = len(matches_py['iter'])
energies = []
n_images_list = []
for i in range(iterations_number):
energies.append([])
images_list = matches_py['iter'][i][0][1].split(', ')
energies[i] = {key: [] for key in images_list}
n_images = len(images_list)
n_images_list.append(n_images)
for i in range(len(matches_neb['en'])):
iteration = int(matches_neb['en'][i][0][0])
image = matches_neb['en'][i][0][1]
energies[iteration - 1][image].append(float(matches_neb['en'][i][0][2]))
if plot:
max_i = 0
for i in range(len(energies)):
plt.figure(dpi=dpi)
barrier = []
all_images = []
for image in energies[i].keys():
if int(image) > max_i:
max_i = int(image)
plt.scatter([int(image) for _ in range(len(energies[i][image]))], energies[i][image], c=f'C{int(image)}')
if len(energies[i][image]) != 0:
plt.scatter(int(image), energies[i][image][-1], c=f'C{int(image)}')
barrier.append(energies[i][image][-1])
all_images.append(int(image))
plt.plot(all_images, barrier, c='black')
return plt, energies
else:
return energies
def get_energies_from_outs(folderpath, opt_history=False, plot=False, dpi=200):
folderpath /= 'iterations'
neb_barriers_hist = []
neb_barriers = []
for iter, iter_path in enumerate(folderpath.glob('iter_*')):
neb_barriers.append([])
neb_barriers_hist.append([])
for f_path in iter_path.glob('[0-9]'):
out = Output.from_file(f_path / 'output.out')
if opt_history:
neb_barriers_hist[iter].append(out.energy_ionic_hist['G'] * Hartree2eV)
neb_barriers[iter].append(out.energy_ionic_hist['G'][-1] * Hartree2eV)
if plot:
if opt_history:
for i, barrier in enumerate(neb_barriers_hist):
plt.figure(dpi=dpi)
plt.title(f'Iteration {i}')
for i, traj in enumerate(barrier):
plt.plot(traj, label=i)
plt.legend(frameon=False)
plt.figure(dpi=dpi)
for i, barrier in enumerate(neb_barriers):
plt.plot(barrier, label=i)
plt.legend(frameon=False)
return plt, neb_barriers, neb_barriers_hist
else:
plt.figure(dpi=dpi)
for i, barrier in enumerate(neb_barriers):
plt.plot(barrier, label=i)
plt.legend(frameon=False)
return plt, neb_barriers
else:
return neb_barriers
def get_energies_from_pylog(filepath, plot=False, dpi=200):
energies = []
with open(filepath) as f:
data = f.readlines()
for line in data:
if 'Energies after iteration' in line:
energies.append(list(map(float, line.strip().split('[')[1][:-1].split(', '))))
if plot:
plt.figure(dpi=dpi)
for i, e in enumerate(energies):
plt.plot(e, label=i)
plt.legend(frameon=False)
return plt, energies
else:
return energies
def get_energies_from_NEBlog(folderpath, plot=False, dpi=200):
patterns = {'en': r'(\d+)\s+Current Energy:\s+(.\d+\.\d+)', \
'images': r'Successfully initialized JDFTx calculator(.+)/(\d+)'}
NEBlogpath = Path(folderpath) / 'logfile_NEB.log'
matches_neb = regrep(str(NEBlogpath), patterns)
nimages = len(matches_neb['images'])
energies = [[] for i in range(nimages)]
for i in range(len(matches_neb['en'])):
image = int(matches_neb['en'][i][0][0])
energies[image-1].append(float(matches_neb['en'][i][0][1]))
if plot:
plt.figure(dpi=dpi)
barrier = []
all_images = []
for image in range(len(energies)):
plt.scatter([image for _ in range(len(energies[image]))], energies[image], c=f'C{image}')
barrier.append(energies[image][-1])
all_images.append(int(image))
plt.plot(all_images, barrier, c='black')
return plt, energies
else:
return energies