Repository: Quantum-Accelerators/quacc
Pull request #1956 (2024-03-30 14:50:31)

Make espresso outfiles/outdir water tight
## Summary of Changes

Currently, users can still bypass Quacc's intended behavior by using environment variables and other workarounds to obtain output directories outside of Quacc's control. This PR aims to address this issue by enforcing specific keywords to be either deleted or set to certain values at the last moment before writing the input files, ensuring that no tampering can occur.
In addition to this change, I would like to discuss a current problem faced when using Quacc with Espresso for larger systems:

Let's consider a scenario where I want to perform a calculation on a relatively large system (600 atoms), with a wavefunction file size of approximately 1TB. If I want to execute a static job followed by a projwfc job to calculate the projected DOS, I will end up with two folders:

tmp-static: This job will take around 3 hours of compute time and produce 1TB of data.
tmp-projwfc: This job will need to copy the data from tmp-static and run for 5 minutes.

The problem is straightforward: it seems inefficient to copy 1TB of data for a job that will run for only 5 minutes.

As a potential solution, I propose the following (although I suspect it may not be well-received): This solution would require setting GZIP_FILES: False and WORKFLOW_ENGINE: None. When both of these conditions are met, instead of copying files to new jobs, we would set the previous directory inside Espresso's keyword. Espresso will then read from the previous data without the need for copying.

Pros:
- Not intrusive on the code side, requiring only a few additional lines.
- Current working directories are still used, but not for storing already existing data.
- It solves the problem entirely, allowing users with limited scratch space to use Quacc and Espresso.

Cons:

- This mode requires setting unrelated settings, such as GZIP_FILES: False (because QE cannot read gzipped files) and WORKFLOW_ENGINE: None (because I'm unsure of the behavior if multiple QE instances try to read the same files).
- It may go against Quacc's design philosophy to some extent.
-
It's worth noting that this problem is somewhat niche, and Espresso's extreme modularity is defintely the problem here.

### Checklist

- [ ] I have read the ["Guidelines" section](https://quantum-accelerators.github.io/quacc/dev/contributing.html#guidelines) of the contributing guide. Don't lie! 😉
- [ ] My PR is on a custom branch and is _not_ named `main`.
- [ ] I have added relevant, comprehensive [unit tests](https://quantum-accelerators.github.io/quacc/dev/contributing.html#unit-tests).

### Notes

- Your PR will likely not be merged without proper and thorough tests.
- If you are an external contributor, you will see a comment from [@buildbot-princeton](https://github.com/buildbot-princeton). This is solely for the maintainers.
- When your code is ready for review, ping one of the [active maintainers](https://quantum-accelerators.github.io/quacc/about/contributors.html#active-maintainers).


buildbot-princeton: Can one of the admins verify this patch?
Andrew-S-Rosen: Regarding the first part (file handling), all efforts are appreciated here. Espresso is especially tricky because most other codes don't give the user an option on where to write things --- it just dumps everything in the current working directory. Espresso's significant flexibility here is a blessing and a curse, mostly the latter in the context of a workflow engine. I'll trust your approach on this. If it's not too painful, you could consider logging a warning if the user sets one of these parameters in Espresso, but I anticipate that there are so many of them that this might not be a worthwhile effort.

As for the second topic about space, it is an interesting point to consider. These kinds of scales are just not possible with other codes. For VASP, I've run 500+ atom calculations and the wavefunctions are never more than a few GBs (1 TB would be absolutely wild). For VASP, there's also no way to avoid file copying because VASP has no knowledge of how to deal with files that aren't in the current working directory, and you'd overwrite the original output files if you ran in the same directory. That's true for most other codes as well, although Espresso is flexible here --- that's the blessing rather than the curse.

I think it is worth finding a mechanism to do this cleanly in Espresso given that it supports this kind of thing. Now for some implementation brainstorming:
- I think there might be a way to avoid hard-coding the `GZIP_FILES = False` behavior. Presumably, in the Espresso calculator, we could check to see if the `previous_directory` parameter (or whatever that setting is called in Espresso --- sorry, I don't know) is set and if it is, automatically gunzip everything there. That might be a robust approach.
- Regarding the workflow engine business, that might be one scenario worth trying to find out. Concurrent read operations really shouldn't be a problem. Concurrent read operations are only generally an issue when you have some locking mechanism, which Espresso has no reason to implement. So, perhaps one would not need to play with this.
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/Quantum-Accelerators/quacc/pull/1956?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Quantum-Accelerators) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 99.29%. Comparing base [(`ee3d9e7`)](https://app.codecov.io/gh/Quantum-Accelerators/quacc/commit/ee3d9e79bdff93250929a0192f703e42de078399?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Quantum-Accelerators) to head [(`f49f042`)](https://app.codecov.io/gh/Quantum-Accelerators/quacc/pull/1956?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Quantum-Accelerators).
> Report is 5 commits behind head on main.


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #1956      +/-   ##
==========================================
- Coverage   99.29%   99.29%   -0.01%     
==========================================
  Files          81       81              
  Lines        3270     3254      -16     
==========================================
- Hits         3247     3231      -16     
  Misses         23       23              
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/Quantum-Accelerators/quacc/pull/1956?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Quantum-Accelerators).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Quantum-Accelerators).

tomdemeyere: @Andrew-S-Rosen 

Some further details:

- I agree for GZIP_FILES, it should not be that hard to get around.
- Good news: It seems that it does not matter how many instances are reading files. 
- Bad news: some post-processing binary still write files to the "outdir" (xml files), meaning that potentially multiple instances will be writing to the same file.

I think that you actually found the solution: adding a kwargs to the concerned post processing jobs (they don't have many kwargs anyway) like "in_place", or "prev_outdir" giving the choice to the users about how to do things. If they are concerned about disk space then they should use it. With proper documentation and a warning about the potential writing conflict that should be ok.

This PR is good to go if you are ok with it.
Andrew-S-Rosen: @tomdemeyere: Thanks! I'm setting this to auto-merge. I fixed an issue with a docstring, but the rest is fine.

Agreed regarding the file copying approach. If there is a case of file clashing, we need to ensure that users have the option to avoid that. Giving users the option here seems like the most logical approach to me. I don't think that would be too much of a challenge. 

Patch:
diff --git a/src/quacc/calculators/espresso/espresso.py b/src/quacc/calculators/espresso/espresso.py
index 40081209..c9507024 100644
--- a/src/quacc/calculators/espresso/espresso.py
+++ b/src/quacc/calculators/espresso/espresso.py
@@ -23,7 +23,10 @@ from ase.io.espresso import (
 from ase.io.espresso_namelist.keys import ALL_KEYS
 
 from quacc import SETTINGS
-from quacc.calculators.espresso.utils import get_pseudopotential_info
+from quacc.calculators.espresso.utils import (
+    espresso_prepare_dir,
+    get_pseudopotential_info,
+)
 from quacc.utils.dicts import recursive_dict_merge
 from quacc.utils.files import load_yaml_calc
 
@@ -68,21 +71,6 @@ class EspressoTemplate(EspressoTemplate_):
 
         self.binary = binary
 
-        self.outdirs = {
-            "outdir": os.environ.get("ESPRESSO_TMPDIR", "."),
-            "wfcdir": os.environ.get("ESPRESSO_TMPDIR", "."),
-        }
-
-        self.outfiles = {
-            "fildos": "pwscf.dos",
-            "filpdos": "pwscf.pdos_tot",
-            "flfrc": "q2r.fc",
-            "fldos": "matdyn.dos",
-            "flfrq": "matdyn.freq",
-            "flvec": "matdyn.modes",
-            "fleig": "matdyn.eig",
-        }
-
         self.test_run = test_run
 
         self.nruns = 0
@@ -218,31 +206,29 @@ class EspressoTemplate(EspressoTemplate_):
             with Path.open(directory / self.outputname, "r") as fd:
                 results = read_espresso_ph(fd)
         elif self.binary == "dos":
-            fildos = self.outfiles["fildos"]
-            with fildos.open("r") as fd:
+            with Path.open(directory / "pwscf.dos", "r") as fd:
                 lines = fd.readlines()
                 fermi = float(re.search(r"-?\d+\.?\d*", lines[0])[0])
                 dos = np.loadtxt(lines[1:])
-            results = {fildos.name.replace(".", "_"): {"dos": dos, "fermi": fermi}}
+            results = {"dos_results": {"dos": dos, "fermi": fermi}}
         elif self.binary == "projwfc":
-            filpdos = self.outfiles["filpdos"]
-            with filpdos.open("r") as fd:
+            with Path.open(directory / "pwscf.pdos_tot", "r") as fd:
                 lines = np.loadtxt(fd.readlines())
                 energy = lines[1:, 0]
                 dos = lines[1:, 1]
                 pdos = lines[1:, 2]
             results = {
-                filpdos.name.replace(".", "_"): {
+                "projwfc_results": {
                     "energy": energy,
                     "dos": dos,
                     "pdos": pdos,
                 }
             }
         elif self.binary == "matdyn":
-            fldos = self.outfiles["fldos"]
+            fldos = Path(directory, "matdyn.dos")
             if fldos.exists():
                 phonon_dos = np.loadtxt(fldos)
-                results = {fldos.name.replace(".", "_"): {"phonon_dos": phonon_dos}}
+                results = {"matdyn_results": {"phonon_dos": phonon_dos}}
 
         if "energy" not in results:
             results["energy"] = None
@@ -250,13 +236,14 @@ class EspressoTemplate(EspressoTemplate_):
         return results
 
     def _output_handler(
-        self, parameters: dict[str, Any], directory: Path
+        self, parameters: dict[str, Any], directory: Path | str
     ) -> dict[str, Any]:
         """
-        Function that handles the various output of espresso binaries. If they are
-        relative, they are resolved against `directory`. In any other case the
-        function will raise a ValueError. This is to avoid the user to use absolute
-        paths that might lead to unexpected behaviour when using Quacc.
+        Function that handles the various output of espresso binaries. It will force the
+        output directory and other output files to be set or deleted if needed.
+
+        It will also prevent the user from setting environment variables that change the
+        output directories.
 
         Parameters
         ----------
@@ -270,35 +257,16 @@ class EspressoTemplate(EspressoTemplate_):
         dict[str, Any]
             The merged kwargs
         """
-        input_data = parameters.get("input_data", {})
 
-        all_out = {**self.outdirs, **self.outfiles}
-        working_dir = Path(directory).expanduser().resolve()
-
-        for key in all_out:
-            path = Path(working_dir, all_out[key])
-
-            for section in input_data:
-                if key in input_data[section]:
-                    path = Path(input_data[section][key])
-                    if path.is_absolute():
-                        raise ValueError(
-                            f"Cannot use {key}={path} because it is an absolute path. When using Quacc please provide relative paths."
-                        )
-                    path = (working_dir / path).resolve()
-                    input_data[section][key] = path
-
-            try:
-                path.relative_to(working_dir)
-            except ValueError as e:
-                raise ValueError(
-                    f"Cannot use {key}={path} because it is not a subpath of {working_dir}. When using Quacc please provide subpaths relative to the working directory."
-                ) from e
-            if key in self.outdirs:
-                path.mkdir(parents=True, exist_ok=True)
-                self.outdirs[key] = path
-            elif key in self.outfiles:
-                self.outfiles[key] = path
+        os.environ.pop("ESPRESSO_TMPDIR", None)
+        os.environ.pop("ESPRESSO_FILDVSCF_DIR", None)
+        os.environ.pop("ESPRESSO_FILDRHO_DIR", None)
+
+        espresso_outdir = Path(directory).expanduser().resolve()
+        outkeys = espresso_prepare_dir(espresso_outdir, self.binary)
+
+        input_data = parameters.get("input_data", {})
+        input_data = recursive_dict_merge(input_data, outkeys)
 
         parameters["input_data"] = input_data
 
@@ -335,7 +303,7 @@ class EspressoTemplate(EspressoTemplate_):
             # Temporary patch for https://gitlab.com/QEF/q-e/-/issues/644
             if qplot and lqdir and recover and is_grid:
                 prefix = input_ph.get("prefix", "pwscf")
-                outdir = self.outdirs["outdir"]
+                outdir = input_ph.get("outdir", ".")
 
                 Path(outdir, "_ph0", f"{prefix}.q_1").mkdir(parents=True, exist_ok=True)
             if not (ldisp or qplot):
diff --git a/src/quacc/calculators/espresso/utils.py b/src/quacc/calculators/espresso/utils.py
index 60c2c291..452a9731 100644
--- a/src/quacc/calculators/espresso/utils.py
+++ b/src/quacc/calculators/espresso/utils.py
@@ -7,6 +7,8 @@ from typing import TYPE_CHECKING
 import numpy as np
 from ase.io.espresso import Namelist
 
+from quacc.utils.dicts import Remove
+
 if TYPE_CHECKING:
     from typing import Any
 
@@ -86,24 +88,19 @@ def pw_copy_files(
     prefix = control.get("prefix", "pwscf")
     restart_mode = control.get("restart_mode", "from_scratch")
 
-    outdir = control.get("outdir", ".")
-    wfcdir = control.get("wfcdir", outdir)
-
     files_to_copy = {prev_dir: []}
 
     basics_to_copy = ["charge-density.*", "data-file-schema.*", "paw.*"]
 
     if restart_mode == "restart":
-        files_to_copy[prev_dir].append(Path(wfcdir, f"{prefix}.wfc*"))
-        files_to_copy[prev_dir].append(Path(wfcdir, f"{prefix}.mix*"))
-        files_to_copy[prev_dir].append(Path(wfcdir, f"{prefix}.restart_k*"))
-        files_to_copy[prev_dir].append(Path(wfcdir, f"{prefix}.restart_scf*"))
+        files_to_copy[prev_dir].append(Path(f"{prefix}.wfc*"))
+        files_to_copy[prev_dir].append(Path(f"{prefix}.mix*"))
+        files_to_copy[prev_dir].append(Path(f"{prefix}.restart_k*"))
+        files_to_copy[prev_dir].append(Path(f"{prefix}.restart_scf*"))
     elif include_wfc:
         basics_to_copy.append("wfc*.*")
 
-    files_to_copy[prev_dir].extend(
-        [Path(outdir, f"{prefix}.save", i) for i in basics_to_copy]
-    )
+    files_to_copy[prev_dir].extend([Path(f"{prefix}.save", i) for i in basics_to_copy])
 
     return files_to_copy
 
@@ -193,3 +190,51 @@ def grid_prepare_repr(patterns: dict[str, Any], nblocks: int) -> list:
     this_block = nblocks if nblocks > 0 else len(patterns)
     repr_to_do = [rep for rep in patterns if not patterns[rep]["done"]]
     return np.array_split(repr_to_do, np.ceil(len(repr_to_do) / this_block))
+
+
+def espresso_prepare_dir(outdir: str | Path, binary: str = "pw") -> dict[str, Any]:
+    """
+    Function that prepares the espresso dictionary for the calculation.
+
+    Parameters
+    ----------
+    outdir
+        The output to be used for the espresso calculation
+    binary
+        The binary to be used for the espresso calculation
+
+    Returns
+    -------
+    dict
+        Input data for the espresso calculation
+    """
+
+    outkeys = {
+        "pw": {"control": {"outdir": outdir, "wfcdir": Remove}},
+        "ph": {
+            "inputph": {
+                "fildyn": "matdyn",
+                "outdir": outdir,
+                "ahc_dir": Remove,
+                "wpot_dir": Remove,
+                "dvscf_star%dir": Remove,
+                "drho_star%dir": Remove,
+            }
+        },
+        "pp": {"inputpp": {"filplot": "tmp.pp", "outdir": outdir}},
+        "dos": {"dos": {"fildos": "pwscf.dos", "outdir": outdir}},
+        "projwfc": {"projwfc": {"filpdos": "pwscf", "outdir": outdir}},
+        "matdyn": {
+            "input": {
+                "fldos": "matdyn.dos",
+                "flfrq": "matdyn.freq",
+                "flvec": "matdyn.modes",
+                "fleig": "matdyn.eig",
+            }
+        },
+        "q2r": {"input": {"flfrc": "q2r.fc"}},
+        "bands": {"bands": {"filband": "bands.out", "outdir": outdir}},
+        "fs": {"fermi": {"file_fs": "fermi_surface.bxsf", "outdir": outdir}},
+    }
+
+    return outkeys.get(binary, {})


Test patch:
diff --git a/tests/core/calculators/espresso/test_espresso.py b/tests/core/calculators/espresso/test_espresso.py
index a3dc65a5..77d088b3 100644
--- a/tests/core/calculators/espresso/test_espresso.py
+++ b/tests/core/calculators/espresso/test_espresso.py
@@ -147,28 +147,21 @@ def test_espresso_kpts():
 def test_output_handler(tmp_path, monkeypatch):
     monkeypatch.chdir(tmp_path)
 
-    parameters = {"input_data": {"system": {"outdir": "../test3/test2/test1"}}}
+    parameters = {"input_data": {"control": {"outdir": "../test3/test2/test1"}}}
 
     test_path = "../test3/test2/test1"
     fake_template = EspressoTemplate()
-    with pytest.raises(ValueError, match="because it is"):
-        new_parameters = fake_template._output_handler(parameters, Path())
+    new_parameters = fake_template._output_handler(parameters, Path())
+
+    assert str(new_parameters["input_data"]["control"]["outdir"]) != test_path
 
     test_path = "/test3/test2/test1"
-    parameters["input_data"]["system"]["outdir"] = test_path
+    parameters["input_data"]["control"]["outdir"] = test_path
     fake_template = EspressoTemplate()
-    with pytest.raises(ValueError, match="because it is"):
-        new_parameters = fake_template._output_handler(parameters, Path())
 
-    test_path = Path("test3/test2/test1")
-    parameters["input_data"]["system"]["outdir"] = test_path
-    fake_template = EspressoTemplate()
     new_parameters = fake_template._output_handler(parameters, Path())
-    assert (
-        new_parameters["input_data"]["system"]["outdir"]
-        == test_path.expanduser().resolve()
-    )
-    assert Path(tmp_path, "test3/test2/test1").exists()
+
+    assert str(new_parameters["input_data"]["control"]["outdir"]) != test_path
 
 
 def test_bad_calculator_params():
diff --git a/tests/core/calculators/espresso/test_io.py b/tests/core/calculators/espresso/test_io.py
index 7731ee9e..5d5d1aa7 100644
--- a/tests/core/calculators/espresso/test_io.py
+++ b/tests/core/calculators/espresso/test_io.py
@@ -45,6 +45,5 @@ def test_read_espresso_ph_1():
 def test_dos_output(tmp_path, monkeypatch):
     monkeypatch.chdir(tmp_path)
     template = EspressoTemplate(binary="dos")
-    template.outfiles = {"fildos": Path(RUN_PATH, "test.dos")}
-    results = template.read_results(directory=".")
-    assert results["test_dos"]["fermi"] == pytest.approx(5.98)
+    results = template.read_results(directory=Path(RUN_PATH))
+    assert results["dos_results"]["fermi"] == pytest.approx(5.98)
diff --git a/tests/core/calculators/espresso/test_runs/test.dos b/tests/core/calculators/espresso/test_runs/pwscf.dos
similarity index 100%
rename from tests/core/calculators/espresso/test_runs/test.dos
rename to tests/core/calculators/espresso/test_runs/pwscf.dos
diff --git a/tests/core/recipes/espresso_recipes/test_core.py b/tests/core/recipes/espresso_recipes/test_core.py
index dc1bac97..3d4ef2e1 100644
--- a/tests/core/recipes/espresso_recipes/test_core.py
+++ b/tests/core/recipes/espresso_recipes/test_core.py
@@ -166,18 +166,25 @@ def test_static_job_outdir_abs(tmp_path, monkeypatch, ESPRESSO_PARALLEL_INFO):
         "control": {
             "pseudo_dir": tmp_path,
             "outdir": Path(tmp_path, "test2").resolve(),
+            "wfcdir": Path(tmp_path, "test1").resolve(),
         },
     }
     pseudopotentials = {"Si": "Si.upf"}
 
-    with pytest.raises(ValueError):
-        static_job(
-            atoms,
-            input_data=input_data,
-            pseudopotentials=pseudopotentials,
-            kpts=None,
-            parallel_info=ESPRESSO_PARALLEL_INFO,
-        )
+    results = static_job(
+        atoms,
+        input_data=input_data,
+        pseudopotentials=pseudopotentials,
+        kpts=None,
+        parallel_info=ESPRESSO_PARALLEL_INFO,
+    )
+
+    assert (
+        str(Path(tmp_path, "test2").resolve())
+        != results["parameters"]["input_data"]["control"]["outdir"]
+    )
+
+    assert results["parameters"]["input_data"]["control"].get("wfcdir") is None
 
 
 def test_static_job_dir_fail(tmp_path, monkeypatch):
diff --git a/tests/core/recipes/espresso_recipes/test_dos.py b/tests/core/recipes/espresso_recipes/test_dos.py
index 30b88b60..a6558e55 100644
--- a/tests/core/recipes/espresso_recipes/test_dos.py
+++ b/tests/core/recipes/espresso_recipes/test_dos.py
@@ -25,7 +25,7 @@ def test_dos_job(tmp_path, monkeypatch, ESPRESSO_PARALLEL_INFO):
     copy_decompress_files(DATA_DIR, ["Si.upf.gz"], tmp_path)
     output = dos_job(tmp_path, parallel_info=ESPRESSO_PARALLEL_INFO)
 
-    assert output["results"]["pwscf_dos"]["fermi"] == pytest.approx(7.199)
+    assert output["results"]["dos_results"]["fermi"] == pytest.approx(7.199)
 
 
 def test_projwfc_job(tmp_path, monkeypatch, ESPRESSO_PARALLEL_INFO):
@@ -37,7 +37,7 @@ def test_projwfc_job(tmp_path, monkeypatch, ESPRESSO_PARALLEL_INFO):
     output = projwfc_job(tmp_path, parallel_info=ESPRESSO_PARALLEL_INFO)
 
     assert output["name"] == "projwfc.x Projects-wavefunctions"
-    assert output["parameters"]["input_data"]["projwfc"] == {}
+    assert output["parameters"]["input_data"]["projwfc"]["filpdos"]
 
 
 def test_dos_flow(tmp_path, monkeypatch, ESPRESSO_PARALLEL_INFO):
@@ -96,7 +96,7 @@ def test_dos_flow(tmp_path, monkeypatch, ESPRESSO_PARALLEL_INFO):
     assert output["non_scf_job"]["results"]["nbands"] == 8
     assert output["non_scf_job"]["results"]["nspins"] == 1
 
-    assert output["dos_job"]["results"]["pwscf_dos"]["fermi"] == pytest.approx(6.772)
+    assert output["dos_job"]["results"]["dos_results"]["fermi"] == pytest.approx(6.772)
 
 
 def test_projwfc_flow(tmp_path, monkeypatch, ESPRESSO_PARALLEL_INFO):
diff --git a/tests/core/recipes/espresso_recipes/test_phonons.py b/tests/core/recipes/espresso_recipes/test_phonons.py
index c3d8b560..0a9cf0be 100644
--- a/tests/core/recipes/espresso_recipes/test_phonons.py
+++ b/tests/core/recipes/espresso_recipes/test_phonons.py
@@ -187,7 +187,7 @@ def test_q2r_job(tmp_path, monkeypatch, ESPRESSO_PARALLEL_INFO):
     with Path(q2r_results["dir_name"], "q2r.in").open() as f:
         recycled_input = read_fortran_namelist(f)
 
-    assert Path(recycled_input[0]["input"].pop("flfrc")).is_absolute()
+    assert recycled_input[0]["input"].pop("flfrc") == "q2r.fc"
 
     assert recycled_input[0]["input"] == {"fildyn": "matdyn"}
     assert recycled_input[1] == [*additional_cards, "EOF"]
@@ -208,16 +208,19 @@ def test_matdyn_job(tmp_path, monkeypatch, ESPRESSO_PARALLEL_INFO):
     assert Path(matdyn_results["dir_name"], "matdyn.dos.gz").exists()
     assert Path(matdyn_results["dir_name"], "matdyn.freq.gz").exists()
     assert Path(matdyn_results["dir_name"], "matdyn.modes.gz").exists()
-    assert matdyn_results["results"]["matdyn_dos"]["phonon_dos"].shape == (561, 3)
+    assert matdyn_results["results"]["matdyn_results"]["phonon_dos"].shape == (561, 3)
 
     decompress_file(Path(matdyn_results["dir_name"], "matdyn.in.gz"))
 
     with Path(matdyn_results["dir_name"], "matdyn.in").open() as f:
         recycled_input = read_fortran_namelist(f)
 
-    assert Path(recycled_input[0]["input"].pop("flfrc")).is_absolute()
+    assert recycled_input[0]["input"].pop("flfrc") == "q2r.fc"
 
-    assert recycled_input[0]["input"] == input_data["input"]
+    assert recycled_input[0]["input"]["fldos"] == "matdyn.dos"
+    assert recycled_input[0]["input"]["flfrq"] == "matdyn.freq"
+    assert recycled_input[0]["input"]["flvec"] == "matdyn.modes"
+    assert recycled_input[0]["input"]["fleig"] == "matdyn.eig"
 
 
 def test_phonon_dos_flow(tmp_path, monkeypatch, ESPRESSO_PARALLEL_INFO):