From 9947ab84b31f8965aa26df2ad4525da27a786c87 Mon Sep 17 00:00:00 2001 From: Marvin Poul Date: Fri, 16 Dec 2022 07:26:51 +0100 Subject: [PATCH 1/3] Add method to add from inspected job --- .../atomistics/job/trainingcontainer.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/pyiron_contrib/atomistics/atomistics/job/trainingcontainer.py b/pyiron_contrib/atomistics/atomistics/job/trainingcontainer.py index c4c45698a..d73efe404 100644 --- a/pyiron_contrib/atomistics/atomistics/job/trainingcontainer.py +++ b/pyiron_contrib/atomistics/atomistics/job/trainingcontainer.py @@ -385,6 +385,53 @@ def to_pandas(self): ] return self._table_cache + def include_jobpath(self, jobpath, iteration_step=-1): + """ + Add structure, energy, forces and pressures from an inspected job. + + Args: + jobpath (:class:`.JobPath`): job path to take structure from + iteration_step (int, optional): if job has multiple steps, this selects which to add + """ + + energy = jobpath["output/generic/energy_pot"][iteration_step] + ff = jobpath["output/generic/forces"] + if ff is not None: + forces = ff[iteration_step] + else: + forces = None + + pp = jobpath["output/generic/stresses"] + if pp is None: + pp = jobpath["output/generic/pressures"] + if pp is not None and len(pp) > 0: + stress = pp[iteration_step] + else: + stress = None + if stress is not None: + stress = np.asarray(stress) + if stress.shape == (3, 3): + stress = np.array( + [ + stress[0, 0], + stress[1, 1], + stress[2, 2], + stress[1, 2], + stress[0, 2], + stress[0, 1], + ] + ) + structure = jobpath["input/structure"].to_object() + structure.positions[:] = jobpath["output/generic/positions"][iteration_step] + structure.cell.array[:] = jobpath["output/generic/cells"][iteration_step] + self.include_structure( + structure, + energy=energy, + forces=forces, + stress=stress, + name=job.name, + ) + def include_job(self, job, iteration_step=-1): """ Add structure, energy and forces from job. From 7c45583e8315d3841b69eb75ae36c771e4078d7b Mon Sep 17 00:00:00 2001 From: Marvin Poul Date: Thu, 5 Jan 2023 10:58:18 +0100 Subject: [PATCH 2/3] Always use the job path interface --- .../atomistics/job/trainingcontainer.py | 100 +++++++----------- 1 file changed, 36 insertions(+), 64 deletions(-) diff --git a/pyiron_contrib/atomistics/atomistics/job/trainingcontainer.py b/pyiron_contrib/atomistics/atomistics/job/trainingcontainer.py index d73efe404..4994431db 100644 --- a/pyiron_contrib/atomistics/atomistics/job/trainingcontainer.py +++ b/pyiron_contrib/atomistics/atomistics/job/trainingcontainer.py @@ -385,31 +385,33 @@ def to_pandas(self): ] return self._table_cache - def include_jobpath(self, jobpath, iteration_step=-1): + def include_job(self, jobpath, iteration_step=-1): """ - Add structure, energy, forces and pressures from an inspected job. + Add structure, energy, forces and pressures from an inspected or loaded job. + + The job must be an atomistic job. + + Forces and stresses are only added if present in the output. Args: - jobpath (:class:`.JobPath`): job path to take structure from + jobpath (:class:`.JobPath`, :class:`.AtomisticGenericJob`): job (path) to take structure from iteration_step (int, optional): if job has multiple steps, this selects which to add """ - energy = jobpath["output/generic/energy_pot"][iteration_step] + kwargs = { + "energy": jobpath["output/generic/energy_pot"][iteration_step], + } ff = jobpath["output/generic/forces"] if ff is not None: - forces = ff[iteration_step] - else: - forces = None + kwargs["forces"] = ff[iteration_step] + # HACK: VASP work-around, current contents of pressures are meaningless, correct values are in + # output/generic/stresses pp = jobpath["output/generic/stresses"] if pp is None: pp = jobpath["output/generic/pressures"] if pp is not None and len(pp) > 0: - stress = pp[iteration_step] - else: - stress = None - if stress is not None: - stress = np.asarray(stress) + stress = np.asarray(pp[iteration_step]) if stress.shape == (3, 3): stress = np.array( [ @@ -421,59 +423,29 @@ def include_jobpath(self, jobpath, iteration_step=-1): stress[0, 1], ] ) - structure = jobpath["input/structure"].to_object() - structure.positions[:] = jobpath["output/generic/positions"][iteration_step] - structure.cell.array[:] = jobpath["output/generic/cells"][iteration_step] - self.include_structure( - structure, - energy=energy, - forces=forces, - stress=stress, - name=job.name, - ) - - def include_job(self, job, iteration_step=-1): - """ - Add structure, energy and forces from job. - - Args: - job (:class:`.AtomisticGenericJob`): job to take structure from - iteration_step (int, optional): if job has multiple steps, this selects which to add - """ - energy = job.output.energy_pot[iteration_step] - ff = job.output.forces - if ff is not None: - forces = ff[iteration_step] + kwargs["stress"] = stress + + indices = jobpath["output/generic/indices"][iteration_step] + cell = jobpath["output/generic/cells"][iteration_step] + positions = jobpath["output/generic/positions"][iteration_step] + if len(indices) == len(jobpath["input/structure/indices"]): + structure = jobpath["input/structure"].to_object() + structure.positions[:] = positions + structure.cell.array[:] = cell + structure.indices[:] = indices else: - forces = None - # HACK: VASP work-around, current contents of pressures are meaningless, correct values are in - # output/generic/stresses - pp = job["output/generic/stresses"] - if pp is None: - pp = job.output.pressures - if pp is not None and len(pp) > 0: - stress = pp[iteration_step] - else: - stress = None - if stress is not None: - stress = np.asarray(stress) - if stress.shape == (3, 3): - stress = np.array( - [ - stress[0, 0], - stress[1, 1], - stress[2, 2], - stress[1, 2], - stress[0, 2], - stress[0, 1], - ] - ) - self.include_structure( - job.get_structure(iteration_step=iteration_step), - energy=energy, - forces=forces, - stress=stress, - name=job.name, + structure = Atoms( + species=jobpath["input/structure/species"], + indices=indices, + positions=positions, + cell=cell, + pbc=jobpath["input/structure/cell/pbc"] + ) + + self.add_structure( + structure, + identifier=job.name, + **kwargs ) @deprecate("Use add_structure instead") From b090aa22b5e497563fd48427d4976d56fe526d4a Mon Sep 17 00:00:00 2001 From: Marvin Poul Date: Thu, 5 Jan 2023 11:07:26 +0100 Subject: [PATCH 3/3] Rename jobpath -> job and do not assume output/indices always exists --- .../atomistics/job/trainingcontainer.py | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/pyiron_contrib/atomistics/atomistics/job/trainingcontainer.py b/pyiron_contrib/atomistics/atomistics/job/trainingcontainer.py index 4994431db..1c898ab95 100644 --- a/pyiron_contrib/atomistics/atomistics/job/trainingcontainer.py +++ b/pyiron_contrib/atomistics/atomistics/job/trainingcontainer.py @@ -385,7 +385,7 @@ def to_pandas(self): ] return self._table_cache - def include_job(self, jobpath, iteration_step=-1): + def include_job(self, job, iteration_step=-1): """ Add structure, energy, forces and pressures from an inspected or loaded job. @@ -394,22 +394,22 @@ def include_job(self, jobpath, iteration_step=-1): Forces and stresses are only added if present in the output. Args: - jobpath (:class:`.JobPath`, :class:`.AtomisticGenericJob`): job (path) to take structure from + job (:class:`.JobPath`, :class:`.AtomisticGenericJob`): job (path) to take structure from iteration_step (int, optional): if job has multiple steps, this selects which to add """ kwargs = { - "energy": jobpath["output/generic/energy_pot"][iteration_step], + "energy": job["output/generic/energy_pot"][iteration_step], } - ff = jobpath["output/generic/forces"] + ff = job["output/generic/forces"] if ff is not None: kwargs["forces"] = ff[iteration_step] # HACK: VASP work-around, current contents of pressures are meaningless, correct values are in # output/generic/stresses - pp = jobpath["output/generic/stresses"] + pp = job["output/generic/stresses"] if pp is None: - pp = jobpath["output/generic/pressures"] + pp = job["output/generic/pressures"] if pp is not None and len(pp) > 0: stress = np.asarray(pp[iteration_step]) if stress.shape == (3, 3): @@ -425,21 +425,25 @@ def include_job(self, jobpath, iteration_step=-1): ) kwargs["stress"] = stress - indices = jobpath["output/generic/indices"][iteration_step] - cell = jobpath["output/generic/cells"][iteration_step] - positions = jobpath["output/generic/positions"][iteration_step] - if len(indices) == len(jobpath["input/structure/indices"]): - structure = jobpath["input/structure"].to_object() + ii = job["output/generic/indices"] + if ii is not None: + indices = ii[iteration_step] + else: + indices = job["input/structure/indices"] + cell = job["output/generic/cells"][iteration_step] + positions = job["output/generic/positions"][iteration_step] + if len(indices) == len(job["input/structure/indices"]): + structure = job["input/structure"].to_object() structure.positions[:] = positions structure.cell.array[:] = cell structure.indices[:] = indices else: structure = Atoms( - species=jobpath["input/structure/species"], + species=job["input/structure/species"], indices=indices, positions=positions, cell=cell, - pbc=jobpath["input/structure/cell/pbc"] + pbc=job["input/structure/cell/pbc"] ) self.add_structure(