From 887719dc3d22755c2343544fa4bac53c62187137 Mon Sep 17 00:00:00 2001 From: Ben Rich Date: Mon, 13 Jan 2025 16:02:40 -0700 Subject: [PATCH] old updates --- src/pymatgen/io/jdftx/jdftxoutfileslice.py | 41 +++++++++++++--------- src/pymatgen/io/jdftx/joutstructure.py | 9 +++-- src/pymatgen/io/jdftx/joutstructures.py | 7 ++++ src/pymatgen/io/jdftx/outputs.py | 20 ++++++++--- 4 files changed, 53 insertions(+), 24 deletions(-) diff --git a/src/pymatgen/io/jdftx/jdftxoutfileslice.py b/src/pymatgen/io/jdftx/jdftxoutfileslice.py index 8a0a9a45eaa..a4307be41f4 100644 --- a/src/pymatgen/io/jdftx/jdftxoutfileslice.py +++ b/src/pymatgen/io/jdftx/jdftxoutfileslice.py @@ -39,6 +39,27 @@ __author__ = "Ben Rich" +_jofs_atr_from_jstrucs = [ + "structure", + "eopt_type", + "elecmindata", + "stress", + "strain", + "forces", + "nstep", + "e", + "grad_k", + "alpha", + "linmin", + "abs_magneticmoment", + "tot_magneticmoment", + "elec_nstep", + "elec_e", + "elec_grad_k", + "elec_alpha", + "elec_linmin", +] + @dataclass class JDFTXOutfileSlice: @@ -265,6 +286,7 @@ class JDFTXOutfileSlice: elecmindata: JElSteps | None = None stress: np.ndarray | None = None strain: np.ndarray | None = None + forces: np.ndarray | None = None nstep: int | None = None e: float | None = None grad_k: float | None = None @@ -842,23 +864,8 @@ def _set_jstrucs(self, text: list[str]) -> None: if self.jstrucs is not None: self._set_trajectory() self.mu = self._get_mu() - self.structure = self.jstrucs[-1].structure - self.eopt_type = self.jstrucs.eopt_type - self.elecmindata = self.jstrucs.elecmindata - self.stress = self.jstrucs.stress - self.strain = self.jstrucs.strain - self.nstep = self.jstrucs.nstep - self.e = self.jstrucs.e - self.grad_k = self.jstrucs.grad_k - self.alpha = self.jstrucs.alpha - self.linmin = self.jstrucs.linmin - self.abs_magneticmoment = self.jstrucs.abs_magneticmoment - self.tot_magneticmoment = self.jstrucs.tot_magneticmoment - self.elec_nstep = self.jstrucs.elec_nstep - self.elec_e = self.jstrucs.elec_e - self.elec_grad_k = self.jstrucs.elec_grad_k - self.elec_alpha = self.jstrucs.elec_alpha - self.elec_linmin = self.jstrucs.elec_linmin + for var in _jofs_atr_from_jstrucs: + setattr(self, var, getattr(self.jstrucs, var)) def _set_backup_vars(self, text: list[str]) -> None: """Set backups for important variables. diff --git a/src/pymatgen/io/jdftx/joutstructure.py b/src/pymatgen/io/jdftx/joutstructure.py index af2bb41e4a1..467ebd9a5a7 100644 --- a/src/pymatgen/io/jdftx/joutstructure.py +++ b/src/pymatgen/io/jdftx/joutstructure.py @@ -76,6 +76,7 @@ class JOutStructure(Structure): elecmindata: JElSteps | None = None stress: np.ndarray | None = None strain: np.ndarray | None = None + forces: np.ndarray | None = None nstep: int | None = None e: float | None = None grad_k: float | None = None @@ -530,7 +531,7 @@ def _parse_ecomp_lines(self, ecomp_lines: list[str]) -> None: key = lsplit[0].strip() val = float(lsplit[1].strip()) self.ecomponents[key] = val * Ha_to_eV - if key is not None and (self.etype is None) and (key in ["F", "G"]): + if key is not None and (self.etype is None) and (key in ["F", "G", "Etot"]): self.etype = key def _parse_lowdin_lines(self, lowdin_lines: list[str]) -> None: @@ -689,7 +690,11 @@ def _collect_generic_line(self, line_text: str, generic_lines: list[str]) -> tup def _init_structure(self) -> None: """Initialize structure attribute.""" self.structure = Structure( - lattice=self.lattice, species=self.species, coords=self.cart_coords, site_properties=self.site_properties + lattice=self.lattice, + species=self.species, + coords=self.cart_coords, + site_properties=self.site_properties, + coords_are_cartesian=True, ) def to_dict(self) -> dict: diff --git a/src/pymatgen/io/jdftx/joutstructures.py b/src/pymatgen/io/jdftx/joutstructures.py index 54b94cc7e7c..3b76016b36d 100644 --- a/src/pymatgen/io/jdftx/joutstructures.py +++ b/src/pymatgen/io/jdftx/joutstructures.py @@ -30,6 +30,7 @@ "elecmindata", "stress", "strain", + "forces", "nstep", "e", "grad_k", @@ -47,6 +48,7 @@ "charges", "magnetic_moments", "selective_dynamics", + "structure", ] @@ -97,6 +99,7 @@ class JOutStructures: charges (np.ndarray[float] | None): The most recent Lowdin-charges. magnetic_moments (np.ndarray[float] | None): The most recent Lowdin-magnetic moments. selective_dynamics (list[int] | None): The selective dynamics flags for the most recent JDFTx call. + structure (Structure | None): Cleaned pymatgen Structure object of final JOutStructure """ out_slice_start_flag = "-------- Electronic minimization -----------" @@ -114,6 +117,7 @@ class JOutStructures: elecmindata: JElSteps = None stress: np.ndarray | None = None strain: np.ndarray | None = None + forces: np.ndarray | None = None nstep: int | None = None e: float | None = None grad_k: float | None = None @@ -131,6 +135,7 @@ class JOutStructures: charges: np.ndarray[float] | None = None magnetic_moments: np.ndarray[float] | None = None selective_dynamics: list[int] | None = None + structure: Structure | None = None @classmethod def _from_out_slice(cls, out_slice: list[str], opt_type: str = "IonicMinimize") -> JOutStructures: @@ -399,6 +404,8 @@ def _get_initial_coords(pre_out_slice: list[str]) -> np.ndarray: coords_type = pre_out_slice[coords_type_lines[0]].strip().split()[1] if coords_type.lower() != "cartesian": coords = np.dot(coords, _get_initial_lattice(pre_out_slice)) + else: + coords *= bohr_to_ang return coords diff --git a/src/pymatgen/io/jdftx/outputs.py b/src/pymatgen/io/jdftx/outputs.py index 8e4e3676094..486c73d122a 100644 --- a/src/pymatgen/io/jdftx/outputs.py +++ b/src/pymatgen/io/jdftx/outputs.py @@ -248,6 +248,7 @@ def _store_eigenvals(self): "elecmindata", "stress", "strain", + "forces", "nstep", "e", "grad_k", @@ -468,6 +469,7 @@ class JDFTXOutfile: elecmindata: JElSteps = field(init=False) stress: np.ndarray = field(init=False) strain: np.ndarray = field(init=False) + forces: np.ndarray = field(init=False) nstep: int = field(init=False) e: float = field(init=False) grad_k: float = field(init=False) @@ -509,7 +511,9 @@ def from_calc_dir( return cls(slices=slices) @classmethod - def from_file(cls, file_path: str | Path, is_bgw: bool = False, none_slice_on_error: bool = False) -> JDFTXOutfile: + def from_file( + cls, file_path: str | Path, is_bgw: bool = False, none_slice_on_error: bool | None = None + ) -> JDFTXOutfile: """ Create a JDFTXOutfile object from a JDFTx out file. @@ -517,16 +521,22 @@ def from_file(cls, file_path: str | Path, is_bgw: bool = False, none_slice_on_er file_path (str | Path): The path to the JDFTx out file. is_bgw (bool): Mark True if data must be usable for BGW calculations. This will change the behavior of the parser to be stricter with certain criteria. - none_slice_on_error (bool): If True, will return None if an error occurs while parsing a slice instead of - halting the parsing process. This can be useful for parsing files with multiple slices where some slices - may be incomplete or corrupted. + none_slice_on_error (bool | None): If True, will return None if an error occurs while parsing a slice + instead of halting the parsing process. This can be useful for parsing files with multiple slices where + some slices may be incomplete or corrupted. If False, all slices may raise errors. If None, only the + final slice can raise an error upon parsing (default behavior) Returns: JDFTXOutfile: The JDFTXOutfile object. """ texts = read_outfile_slices(file_path) + if none_slice_on_error is None: + none_slice_bools = [i != len(texts) - 1 for i in range(len(texts))] + else: + none_slice_bools = [none_slice_on_error for i in range(len(texts))] slices = [ - JDFTXOutfileSlice._from_out_slice(text, is_bgw=is_bgw, none_on_error=none_slice_on_error) for text in texts + JDFTXOutfileSlice._from_out_slice(text, is_bgw=is_bgw, none_on_error=none_slice_bools[i]) + for i, text in enumerate(texts) ] return cls(slices=slices)