import os
import subprocess
import tempfile
from io import StringIO
from aiida_fleur.data.fleurinp import FleurinpData
from ase import Atoms
from ase.io import write as ase_write
[docs]
class Fleur_setup:
"""Class to prepare input for inpgen."""
def __init__(self, ase_obj):
self.ase_obj = ase_obj
[docs]
def validate(self):
self.xml_input = self.ase_to_fleur_xml(self.ase_obj)
if not self.xml_input:
return "Fleur inpgen misconfiguration occured"
return None
[docs]
def ase_to_fleur_xml(self, ase_obj: Atoms):
"""
Skipping the textual Fleur input generation
in order to simplify our provenance persistence layers
"""
buff = StringIO()
ase_write(
buff,
ase_obj,
format="fleur-inpgen",
parameters={
"title": "%ABSDX_%",
},
)
buff.seek(0)
txt_input = buff.getvalue()
with tempfile.TemporaryDirectory(prefix="fleur_inpgen_") as tmp_dir:
input_path = os.path.join(tmp_dir, "fleur.inp")
with open(input_path, "w") as f:
f.write(txt_input)
opts = ["-f", "fleur.inp", "-inc", "+all", "-noco"]
inpgen_path = os.environ.get("FLEUR_INPGEN_PATH", "/data/inpgen")
if not inpgen_path or not os.path.exists(inpgen_path):
raise FileNotFoundError("FLEUR_INPGEN_PATH is not set or does not exist")
p = subprocess.Popen(
[inpgen_path] + opts,
cwd=tmp_dir,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
_, stderr = p.communicate()
if p.returncode != 0:
error_msg = stderr.decode() if stderr else "inpgen failed with unknown error"
raise RuntimeError(f"inpgen failed: {error_msg}")
xml_path = os.path.join(tmp_dir, "inp.xml")
if not os.path.exists(xml_path):
error_msg = stderr.decode() if stderr else "inpgen produced no result"
raise RuntimeError(f"inpgen produced no result: {error_msg}")
with open(xml_path, "r") as f:
xml_input = f.read()
return xml_input
[docs]
def convert_xml_to_FleurInpData(xml_input: str):
"""
Takes the content of an inp.xml file as a string, saves it to a temporary folder
as 'inp.xml', and converts it to a FleurinpData object.
Args:
xml_input (str): Content of inp.xml as a string.
Returns:
FleurinpData: The FleurinpData object created from the XML input.
"""
with tempfile.TemporaryDirectory() as tmp_dir:
xml_path = os.path.join(tmp_dir, "inp.xml")
with open(xml_path, "w") as f:
f.write(xml_input)
fleur_inp_data = FleurinpData(files=[xml_path])
return fleur_inp_data