From c34fca51302a9daee4d32df2d6c1d2e36d525a1c Mon Sep 17 00:00:00 2001 From: Guido Petretto Date: Mon, 6 Nov 2023 13:47:40 +0100 Subject: [PATCH 1/3] update store_trajectory --- emmet-core/emmet/core/vasp/calculation.py | 30 +++++++++++++++++------ 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/emmet-core/emmet/core/vasp/calculation.py b/emmet-core/emmet/core/vasp/calculation.py index e9f113e862..f95d32890b 100644 --- a/emmet-core/emmet/core/vasp/calculation.py +++ b/emmet-core/emmet/core/vasp/calculation.py @@ -419,7 +419,7 @@ def from_vasp_outputs( contcar: Optional[Poscar], locpot: Optional[Locpot] = None, elph_poscars: Optional[List[Path]] = None, - store_trajectory: bool = False, + store_trajectory: Union[bool, str] = False, ) -> "CalculationOutput": """ Create a VASP output document from VASP outputs. @@ -438,8 +438,10 @@ def from_vasp_outputs( Path to displaced electron-phonon coupling POSCAR files generated using ``PHON_LMC = True``. store_trajectory - Whether to store ionic steps as a pymatgen Trajectory object. If `True`, - the `ionic_steps` field is left as None. + Whether to store ionic steps as a pymatgen Trajectory object. Can be + True, False or "partial", tuning the amount of data from the ionic_steps + stored in the Trajectory. + If not `False`, the `ionic_steps` field is left as None. Returns ------- @@ -613,7 +615,7 @@ def from_vasp_files( strip_bandstructure_projections: bool = False, strip_dos_projections: bool = False, store_volumetric_data: Optional[Tuple[str]] = None, - store_trajectory: bool = False, + store_trajectory: Union[bool, str] = False, vasprun_kwargs: Optional[Dict] = None, ) -> Tuple["Calculation", Dict[VaspObject, Dict]]: """ @@ -670,9 +672,17 @@ def from_vasp_files( store_volumetric_data Which volumetric files to store. store_trajectory - Whether to store the ionic steps in a pymatgen Trajectory object. if `True`, - :obj:'.CalculationOutput.ionic_steps' is set to None to reduce duplicating - information. + Whether to store the ionic steps in a pymatgen Trajectory object and the + amount of data to store from the ionic_steps. Can be: + - True: Store the Trajectory. All the properties from the ionic_steps + are stored in the frame_properties except for the Structure, to + avoid redundancy. + - "partial": Store the Trajectory. All the properties from the ionic_steps + are stored in the frame_properties except from Structure and + ElectronicStep + - False: Trajectory is not Stored. + If not `False`, :obj:'.CalculationOutput.ionic_steps' is set to None + to reduce duplicating information. vasprun_kwargs Additional keyword arguments that will be passed to the Vasprun init. @@ -734,10 +744,14 @@ def from_vasp_files( store_trajectory=store_trajectory, ) if store_trajectory: + exclude_from_trajectory = ["structure"] + if store_trajectory == "partial": + exclude_from_trajectory.append("electronic_steps") traj = Trajectory.from_structures( [d["structure"] for d in vasprun.ionic_steps], frame_properties=[ - IonicStep(**x).model_dump() for x in vasprun.ionic_steps + IonicStep(**x).model_dump(exclude=exclude_from_trajectory) + for x in vasprun.ionic_steps ], constant_lattice=False, ) From 3b012b7c77bb8a79db58acbf55758d28d3f34e09 Mon Sep 17 00:00:00 2001 From: Guido Petretto Date: Mon, 13 Nov 2023 14:24:33 +0100 Subject: [PATCH 2/3] Add temperature to Trajectory --- emmet-core/emmet/core/tasks.py | 2 ++ emmet-core/emmet/core/vasp/calculation.py | 29 +++++++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/emmet-core/emmet/core/tasks.py b/emmet-core/emmet/core/tasks.py index 84599c8e4e..d1ba403f16 100644 --- a/emmet-core/emmet/core/tasks.py +++ b/emmet-core/emmet/core/tasks.py @@ -963,6 +963,8 @@ def _get_task_files(files, suffix=""): vol_files.append(file_no_path) elif file.match(f"*POSCAR.T=*{suffix}*"): elph_poscars.append(file_no_path) + elif file.match(f"*OSZICAR{suffix}*"): + vasp_files["oszicar_file"] = file_no_path if len(vol_files) > 0: # add volumetric files if some were found or other vasp files were found diff --git a/emmet-core/emmet/core/vasp/calculation.py b/emmet-core/emmet/core/vasp/calculation.py index 5e55fb1b31..34b89be970 100644 --- a/emmet-core/emmet/core/vasp/calculation.py +++ b/emmet-core/emmet/core/vasp/calculation.py @@ -21,6 +21,7 @@ BSVasprun, Kpoints, Locpot, + Oszicar, Outcar, Poscar, Potcar, @@ -612,6 +613,7 @@ def from_vasp_files( contcar_file: Union[Path, str], volumetric_files: List[str] = None, elph_poscars: List[Path] = None, + oszicar_file: Optional[Union[Path, str]] = None, parse_dos: Union[str, bool] = False, parse_bandstructure: Union[str, bool] = False, average_locpot: bool = True, @@ -643,6 +645,8 @@ def from_vasp_files( elph_poscars Path to displaced electron-phonon coupling POSCAR files generated using ``PHON_LMC = True``, given relative to dir_name. + oszicar_file + Path to the OSZICAR file, relative to dir_name parse_dos Whether to parse the DOS. Can be: @@ -738,7 +742,9 @@ def from_vasp_files( ddec6 = None if run_ddec6 and VaspObject.CHGCAR in output_file_paths: densities_path = run_ddec6 if isinstance(run_ddec6, (str, Path)) else None - ddec6 = ChargemolAnalysis(path=dir_name, atomic_densities_path=densities_path).summary + ddec6 = ChargemolAnalysis( + path=dir_name, atomic_densities_path=densities_path + ).summary locpot = None if average_locpot: @@ -762,12 +768,25 @@ def from_vasp_files( exclude_from_trajectory = ["structure"] if store_trajectory == "partial": exclude_from_trajectory.append("electronic_steps") + frame_properties = [ + IonicStep(**x).model_dump(exclude=exclude_from_trajectory) + for x in vasprun.ionic_steps + ] + if oszicar_file: + try: + oszicar = Oszicar(oszicar_file) + if "T" in oszicar.ionic_steps[0]: + for frame_property, oszicar_is in zip( + frame_properties, oszicar.ionic_steps + ): + frame_property["temperature"] = oszicar_is.get("T") + except ValueError: + # there can be errors in parsing the floats from OSZICAR + pass + traj = Trajectory.from_structures( [d["structure"] for d in vasprun.ionic_steps], - frame_properties=[ - IonicStep(**x).model_dump(exclude=exclude_from_trajectory) - for x in vasprun.ionic_steps - ], + frame_properties=frame_properties, constant_lattice=False, ) vasp_objects[VaspObject.TRAJECTORY] = traj # type: ignore From 79dd0285357b2c94f3327c293d34af7c995bf8d2 Mon Sep 17 00:00:00 2001 From: Guido Petretto Date: Thu, 16 Nov 2023 00:32:41 +0100 Subject: [PATCH 3/3] Enum to define store_trajectory --- emmet-core/emmet/core/vasp/calculation.py | 34 ++++++++++++++--------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/emmet-core/emmet/core/vasp/calculation.py b/emmet-core/emmet/core/vasp/calculation.py index 34b89be970..230a0f2ad0 100644 --- a/emmet-core/emmet/core/vasp/calculation.py +++ b/emmet-core/emmet/core/vasp/calculation.py @@ -62,6 +62,12 @@ class VaspObject(ValueEnum): PROCAR = "procar" +class StoreTrajectoryOption(ValueEnum): + FULL = "full" + PARTIAL = "partial" + NO = "no" + + class PotcarSpec(BaseModel): """Document defining a VASP POTCAR specification.""" @@ -423,7 +429,7 @@ def from_vasp_outputs( contcar: Optional[Poscar], locpot: Optional[Locpot] = None, elph_poscars: Optional[List[Path]] = None, - store_trajectory: Union[bool, str] = False, + store_trajectory: StoreTrajectoryOption = StoreTrajectoryOption.NO, ) -> "CalculationOutput": """ Create a VASP output document from VASP outputs. @@ -442,10 +448,10 @@ def from_vasp_outputs( Path to displaced electron-phonon coupling POSCAR files generated using ``PHON_LMC = True``. store_trajectory - Whether to store ionic steps as a pymatgen Trajectory object. Can be - True, False or "partial", tuning the amount of data from the ionic_steps + Whether to store ionic steps as a pymatgen Trajectory object. + Different value tune the amount of data from the ionic_steps stored in the Trajectory. - If not `False`, the `ionic_steps` field is left as None. + If not NO, the `ionic_steps` field is left as None. Returns ------- @@ -553,7 +559,9 @@ def from_vasp_outputs( frequency_dependent_dielectric=freq_dependent_diel, elph_displaced_structures=elph_structures, dos_properties=dosprop_dict, - ionic_steps=vasprun.ionic_steps if not store_trajectory else None, + ionic_steps=vasprun.ionic_steps + if store_trajectory == StoreTrajectoryOption.NO + else None, locpot=locpot_avg, outcar=outcar_dict, run_stats=RunStatistics.from_outcar(outcar) if outcar else None, @@ -622,7 +630,7 @@ def from_vasp_files( strip_bandstructure_projections: bool = False, strip_dos_projections: bool = False, store_volumetric_data: Optional[Tuple[str]] = None, - store_trajectory: Union[bool, str] = False, + store_trajectory: StoreTrajectoryOption = StoreTrajectoryOption.NO, vasprun_kwargs: Optional[Dict] = None, ) -> Tuple["Calculation", Dict[VaspObject, Dict]]: """ @@ -688,14 +696,14 @@ def from_vasp_files( store_trajectory Whether to store the ionic steps in a pymatgen Trajectory object and the amount of data to store from the ionic_steps. Can be: - - True: Store the Trajectory. All the properties from the ionic_steps + - FULL: Store the Trajectory. All the properties from the ionic_steps are stored in the frame_properties except for the Structure, to avoid redundancy. - - "partial": Store the Trajectory. All the properties from the ionic_steps + - PARTIAL: Store the Trajectory. All the properties from the ionic_steps are stored in the frame_properties except from Structure and - ElectronicStep - - False: Trajectory is not Stored. - If not `False`, :obj:'.CalculationOutput.ionic_steps' is set to None + ElectronicStep. + - NO: Trajectory is not Stored. + If not NO, :obj:'.CalculationOutput.ionic_steps' is set to None to reduce duplicating information. vasprun_kwargs Additional keyword arguments that will be passed to the Vasprun init. @@ -764,9 +772,9 @@ def from_vasp_files( elph_poscars=elph_poscars, store_trajectory=store_trajectory, ) - if store_trajectory: + if store_trajectory != StoreTrajectoryOption.NO: exclude_from_trajectory = ["structure"] - if store_trajectory == "partial": + if store_trajectory == StoreTrajectoryOption.PARTIAL: exclude_from_trajectory.append("electronic_steps") frame_properties = [ IonicStep(**x).model_dump(exclude=exclude_from_trajectory)