Commit 640c7e9a authored by Alvin Noe Ladines's avatar Alvin Noe Ladines
Browse files

Added more quantities to single_point workflow

parent 0d34d12b
Pipeline #98250 passed with stages
in 31 minutes and 22 seconds
......@@ -6847,14 +6847,24 @@ class SinglePoint(MSection):
''',
a_legacy=LegacyDefinition(name='single_point_calculation_method'))
scf_steps = Quantity(
number_of_scf_steps = Quantity(
type=int,
shape=[],
description='''
Number of self-consistent steps for the calculation
Number of self-consistent steps in the calculation
''',
a_legacy=LegacyDefinition(name='number_of_scf_steps'))
final_scf_energy_difference = Quantity(
type=np.dtype(np.float64),
shape=[],
unit='joule',
description='''
The difference in the energy between the last two scf steps.
''',
a_search=Search(),
a_legacy=LegacyDefinition(name='final_scf_energy_difference'))
is_converged = Quantity(
type=bool,
shape=[],
......@@ -6863,6 +6873,46 @@ class SinglePoint(MSection):
''',
a_legacy=LegacyDefinition(name='is_converged'))
with_density_of_states = Quantity(
type=bool,
shape=[],
description='''
Indicates if the calculation contains density of states data
''',
a_legacy=LegacyDefinition(name='with_density_of_states'))
with_bandstructure = Quantity(
type=bool,
shape=[],
description='''
Indicates if the calculation contains bandstructure data
''',
a_legacy=LegacyDefinition(name='with_bandstructure'))
with_eigenvalues = Quantity(
type=bool,
shape=[],
description='''
Indicates if the calculation contains eigenvalue data
''',
a_legacy=LegacyDefinition(name='with_eigenvalues'))
with_volumetric_data = Quantity(
type=bool,
shape=[],
description='''
Indicates if the calculation contains volumetric data
''',
a_legacy=LegacyDefinition(name='with_volumetric_data'))
with_excited_states = Quantity(
type=bool,
shape=[],
description='''
Indicates if the calculation contains excited states data
''',
a_legacy=LegacyDefinition(name='with_excited_states'))
class Workflow(MSection):
'''
......@@ -6878,7 +6928,7 @@ class Workflow(MSection):
shape=[],
description='''
The type of calculation workflow. Can be one of geometry_optimization, elastic,
phonon, molecular_dynamics.
phonon, molecular_dynamics, single_point.
''',
a_search=Search(),
a_legacy=LegacyDefinition(name='workflow_type'))
......@@ -6913,6 +6963,8 @@ class Workflow(MSection):
section_single_point = SubSection(
sub_section=SectionProxy('SinglePoint'),
# TODO determine if there is a need for this to be a repeating section
# such as in the context of fhi-vibes single_point
repeats=False,
categories=[FastAccess],
a_legacy=LegacyDefinition(name='section_single_point'))
......
......@@ -24,6 +24,18 @@ from nomad.datamodel.metainfo.public import Workflow, GeometryOptimization, Phon
MolecularDynamics, SinglePoint
def resolve_energy_difference(energies):
delta_energy = None
energies = [e for e in energies if e is not None]
for n in range(-1, -len(energies), -1):
delta_energy = abs(energies[n] - energies[n - 1])
if delta_energy != 0.0:
break
return delta_energy
class SinglePointNormalizer(Normalizer):
def __init__(self, entry_archive):
super().__init__(entry_archive)
......@@ -40,9 +52,40 @@ class SinglePointNormalizer(Normalizer):
except Exception:
pass
if not self.section.scf_steps:
scc = self.section_run.section_single_configuration_calculation
self.section.scf_steps = len(scc[-1].section_scf_iteration)
scc = self.section_run.section_single_configuration_calculation
if not scc:
return
if not self.section.number_of_scf_steps:
self.section.number_of_scf_steps = len(scc[-1].section_scf_iteration)
energies = [scf.energy_total_scf_iteration for scf in scc[-1].section_scf_iteration]
delta_energy = resolve_energy_difference(energies)
if not self.section.final_scf_energy_difference and delta_energy is not None:
self.section.final_scf_energy_difference = delta_energy
if not self.section.is_converged and delta_energy is not None:
try:
threshold = self.section.section_method[-1].scf_threshold_energy_change
if threshold <= delta_energy:
self.section.is_converged = True
except Exception:
pass
if not self.section.with_density_of_states:
self.section.with_density_of_states = len(scc[-1].section_dos) > 0
if not self.section.with_bandstructure:
self.section.with_bandstructure = len(scc[-1].section_k_band) > 0
if not self.section.with_eigenvalues:
self.section.with_eigenvalues = len(scc[-1].section_eigenvalues) > 0
if not self.section.with_volumetric_data:
self.section.with_volumetric_data = len(scc[-1].section_volumetric_data) > 0
if not self.section.with_excited_states:
self.section.with_excited_states = len(scc[-1].section_excited_states) > 0
class GeometryOptimizationNormalizer(Normalizer):
......@@ -117,17 +160,8 @@ class GeometryOptimizationNormalizer(Normalizer):
if scc.energy_total_T0:
energies.append(scc.energy_total_T0)
delta_energy = None
if len(energies) > 1:
delta_energy = abs(energies[-1] - energies[-2])
if delta_energy == 0.0:
try:
delta_energy = abs(energies[-1] - energies[-3])
except Exception:
pass
if delta_energy:
delta_energy = resolve_energy_difference(energies)
if delta_energy is not None:
self.section.final_energy_difference = delta_energy
if not self.section.final_force_maximum:
......@@ -292,16 +326,20 @@ class WorkflowNormalizer(Normalizer):
self._phonon_programs = ['phonopy']
def _resolve_workflow_type_vasp(self):
try:
ibrion = self.section_run.section_method[0].x_vasp_incarOut_IBRION
except Exception:
ibrion = 1
sec_method = self.section_run.section_method
if not sec_method:
return
incar = self.section_run.section_method[0].x_vasp_incar_out
nsw = incar.get('NSW')
ibrion = -1 if nsw == 0 else incar.get('IBRION', 0)
if ibrion == 0:
workflow_type = "molecular_dynamics"
if ibrion == -1:
return 'single_point'
elif ibrion == 0:
return 'molecular_dynamics'
else:
workflow_type = "geometry_optimization"
return workflow_type
return 'geometry_optimization'
def _resolve_workflow_type(self):
# first get it from section_sampling_method
......@@ -331,6 +369,11 @@ class WorkflowNormalizer(Normalizer):
elif program_name == 'phonopy':
workflow_type = 'phonon'
# resolve if from scc
if not workflow_type:
if len(self.section_run.section_single_configuration_calculation) == 1:
workflow_type = 'single_point'
return workflow_type
def normalize(self, logger=None) -> None:
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -37,6 +37,24 @@ def test_no_workflow(workflow_archive):
assert vasp_archive.section_workflow is None
def test_single_point_workflow(workflow_archive):
vasp_archive = workflow_archive(
'parsers/vasp', 'tests/data/normalizers/workflow/vasp/vasprun.xml.static')
sec_workflow = vasp_archive.section_workflow
assert sec_workflow.workflow_type == 'single_point'
assert sec_workflow.calculations_ref is not None
assert sec_workflow.calculation_result_ref.m_def.name == 'SingleConfigurationCalculation'
assert sec_workflow.section_single_point.single_point_calculation_method == 'DFT'
assert sec_workflow.section_single_point.number_of_scf_steps == 9
assert sec_workflow.section_single_point.final_scf_energy_difference > 0
assert sec_workflow.section_single_point.with_density_of_states
assert not sec_workflow.section_single_point.with_bandstructure
assert sec_workflow.section_single_point.with_eigenvalues
assert not sec_workflow.section_single_point.with_volumetric_data
assert not sec_workflow.section_single_point.with_excited_states
def test_geometry_optimization_workflow(workflow_archive):
vasp_archive = workflow_archive(
'parsers/vasp', 'tests/data/normalizers/workflow/vasp/vasprun.xml')
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment