Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,5 @@ dev/
# Jupytext sync is a tool for writing notebooks in `.ipynb` format, and syncing them to a `.md` file
# https://marketplace.visualstudio.com/items?itemName=caenrigen.jupytext-sync
.jupytext-sync-ipynb

examples
134 changes: 132 additions & 2 deletions src/aiida_epw/tools/parsers.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,87 @@
"""Manual parsing functions for post-processing."""
"""Manual parsing functions for post-processing. These functions can either be used independently or as helper functions of the `EpwParser` class.
It would be good to always have a `parsed_data` dictionary as an output."""

import numpy
import re
import io

Ry2eV = 13.605662285137


### This parse function is used for parsing the `band.eig` and `phband.freq` files.
def parse_epw_bands(file_content):
"""Parse the contents of a band structure file generated by EPW software."""
parsed_data = {}

nbnd, nks = (
int(v)
for v in re.search(r"&plot nbnd=\s+(\d+), nks=\s+(\d+)", file_content).groups()
)
kpt_pattern = re.compile(r"\s([\s-][\d\.]+)" * 3)
band_pattern = re.compile(r"\s+([-\d\.]+)" * nbnd)

kpoints = []
bands = []

for number, line in enumerate(file_content.splitlines()):
match_kpt = re.search(kpt_pattern, line)
if match_kpt and number % 2 == 1:
kpoints.append(list(match_kpt.groups()))

match_band = re.search(band_pattern, line)
if match_band and number % 2 == 0:
bands.append(list(match_band.groups()))

parsed_data["kpoints"] = numpy.array(kpoints, dtype=float)
parsed_data["bands"] = numpy.array(bands, dtype=float)

return parsed_data


def parse_epw_eldos(file_content):
"""Parse the contents of the `.dos` file.
parameters:
file_content: the content of the `.dos` file as a string.
returns:
parsed_data: a dictionary containing the energy, the electronic density of states and the integrated density of states.
"""
parsed_data = {}

dos = numpy.loadtxt(io.StringIO(file_content), dtype=float, comments="#")

parsed_data["energy"] = dos[:, 0]
parsed_data["edos"] = dos[:, 1]
parsed_data["integrated_dos"] = dos[:, 2]
return parsed_data


def parse_epw_phdos(file_content):
"""Parse the contents of the `.phdos` file.
parameters:
file_content: the content of the `.phdos` file as a string.
returns:
parsed_data: a dictionary containing the frequency, the phonon density of states. Note that there are multiple phonon density of states for different smearing.
"""
parsed_data = {}

phdos = numpy.loadtxt(io.StringIO(file_content), dtype=float, skiprows=1)
parsed_data["frequency"] = phdos[:, 0]
parsed_data["phdos"] = phdos[:, 1:]
return parsed_data


def parse_epw_a2f(file_content):
"""Parse the contents of the `.a2f` file.
parameters:
file_content: the content of the `.a2f` file as a string.
returns:
parsed_data: a dictionary containing the frequency, the spectral function for different smearing, and metadata such as electron smearing, Fermi window and summed el-ph coupling strength.
"""
parsed_data = {}

a2f, footer = file_content.split("\n Integrated el-ph coupling")

a2f_array = numpy.array([line.split() for line in a2f.split("\n")], dtype=float)
a2f_array = numpy.array([line.split() for line in a2f.split("\n")[1:]], dtype=float)
parsed_data["frequency"] = a2f_array[:, 0]
parsed_data["a2f"] = a2f_array[:, 1:]

Expand All @@ -31,3 +102,62 @@ def parse_epw_a2f(file_content):
parsed_data[property] = float(line.split()[-1])

return parsed_data


def parse_epw_max_eigenvalue(file_content):
"""Parse the max_eigenvalue part of the `stdout` file when solving the linearized Eliashberg equation."""
parsed_data = {}
re_pattern = re.compile(r"\s+([\d\.]+)\s+([\d\.-]+)\s+\d+\s+[\d\.]+\s+\d+\n")
parsing_block = file_content.split(
"Finish: Solving (isotropic) linearized Eliashberg"
)[0]

parsed_data["max_eigenvalue"] = numpy.array(
re_pattern.findall(parsing_block), dtype=float
)
return parsed_data


def parse_epw_imag_iso(file_contents, prefix="aiida"):
"""Parse the isotropic gap functions from EPW isotropic Eliashberg equation calculation.
parameters:
folder: the folder containing the `imag_iso` files. When serving as a helper function, it can take a `Retrieved` folder from aiida .
When used independently, it can take a local folder.
prefix: the prefix of the `imag_iso` files.
returns:
parsed_data: a dictionary containing the isotropic gap functions of numpy array type and the corresponding temperatures as keys.
"""
parsed_data = {}
pattern_iso = re.compile(rf"^{prefix}\.imag_iso_(\d{{3}}\.\d{{2}})$")

for filename, file_content in file_contents.items():
match = pattern_iso.match(filename)
if match:
T = float(match.group(1))
gap_function = numpy.loadtxt(
io.StringIO(file_content), dtype=float, comments="#", skiprows=1
)
parsed_data[T] = gap_function
return parsed_data


def parse_epw_imag_aniso_gap0(file_contents, prefix="aiida"):
"""Parse the anisotropic gap functions from EPW anisotropic Eliashberg equation calculation.
parameters:
file_contents: a dictionary containing the file contents with filename as keys.
prefix: the prefix of the `imag_aniso_gap0` files.
returns:
parsed_data: a sorted dictionary containing the anisotropic gap functions of numpy array type and the corresponding temperatures as keys.
"""
parsed_data = {}
pattern_aniso_gap0 = re.compile(rf"^{prefix}\.imag_aniso_gap0_(\d{{3}}\.\d{{2}})$")

for filename, file_content in file_contents.items():
match = pattern_aniso_gap0.match(filename)
if match:
T = float(match.group(1))
gap_function = numpy.loadtxt(
io.StringIO(file_content), dtype=float, comments="#", skiprows=1
)
parsed_data[T] = gap_function
return parsed_data
Loading