Skip to content

Commit

Permalink
Initial workflow defs
Browse files Browse the repository at this point in the history
  • Loading branch information
ladinesa committed Jan 28, 2025
1 parent 0c0caad commit 0530c27
Show file tree
Hide file tree
Showing 8 changed files with 236 additions and 48 deletions.
54 changes: 54 additions & 0 deletions src/nomad_simulations/schema_packages/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import numpy as np
from nomad.datamodel.data import ArchiveSection
from nomad.datamodel.metainfo.annotations import ELNAnnotation
from nomad.metainfo import Datetime, Quantity


class Time(ArchiveSection):
"""
Contains time-related quantities.
"""

datetime_end = Quantity(
type=Datetime,
description="""
The date and time when this computation ended.
""",
a_eln=ELNAnnotation(component='DateTimeEditQuantity'),
)

cpu1_start = Quantity(
type=np.float64,
unit='second',
description="""
The starting time of the computation on the (first) CPU 1.
""",
a_eln=ELNAnnotation(component='NumberEditQuantity'),
)

cpu1_end = Quantity(
type=np.float64,
unit='second',
description="""
The end time of the computation on the (first) CPU 1.
""",
a_eln=ELNAnnotation(component='NumberEditQuantity'),
)

wall_start = Quantity(
type=np.float64,
unit='second',
description="""
The internal wall-clock time from the starting of the computation.
""",
a_eln=ELNAnnotation(component='NumberEditQuantity'),
)

wall_end = Quantity(
type=np.float64,
unit='second',
description="""
The internal wall-clock time from the end of the computation.
""",
a_eln=ELNAnnotation(component='NumberEditQuantity'),
)
50 changes: 4 additions & 46 deletions src/nomad_simulations/schema_packages/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from nomad.datamodel.data import Schema
from nomad.datamodel.metainfo.annotations import ELNAnnotation
from nomad.datamodel.metainfo.basesections import Activity, Entity
from nomad.metainfo import Datetime, Quantity, SchemaPackage, Section, SubSection
from nomad.metainfo import Quantity, SchemaPackage, Section, SubSection

from nomad_simulations.schema_packages.model_method import ModelMethod
from nomad_simulations.schema_packages.model_system import ModelSystem
Expand All @@ -21,6 +21,8 @@
is_not_representative,
)

from .common import Time

configuration = config.get_plugin_entry_point(
'nomad_simulations.schema_packages:nomad_simulations_plugin'
)
Expand Down Expand Up @@ -121,7 +123,7 @@ def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None:
pass


class BaseSimulation(Activity):
class BaseSimulation(Activity, Time):
"""
A computational simulation that produces output data from a given input model system
and input methodological parameters.
Expand All @@ -135,50 +137,6 @@ class BaseSimulation(Activity):
links=['https://liusemweb.github.io/mdo/core/1.1/index.html#Calculation']
)

datetime_end = Quantity(
type=Datetime,
description="""
The date and time when this computation ended.
""",
a_eln=ELNAnnotation(component='DateTimeEditQuantity'),
)

cpu1_start = Quantity(
type=np.float64,
unit='second',
description="""
The starting time of the computation on the (first) CPU 1.
""",
a_eln=ELNAnnotation(component='NumberEditQuantity'),
)

cpu1_end = Quantity(
type=np.float64,
unit='second',
description="""
The end time of the computation on the (first) CPU 1.
""",
a_eln=ELNAnnotation(component='NumberEditQuantity'),
)

wall_start = Quantity(
type=np.float64,
unit='second',
description="""
The internal wall-clock time from the starting of the computation.
""",
a_eln=ELNAnnotation(component='NumberEditQuantity'),
)

wall_end = Quantity(
type=np.float64,
unit='second',
description="""
The internal wall-clock time from the end of the computation.
""",
a_eln=ELNAnnotation(component='NumberEditQuantity'),
)

program = SubSection(sub_section=Program.m_def, repeats=False)

def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None:
Expand Down
5 changes: 3 additions & 2 deletions src/nomad_simulations/schema_packages/outputs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from typing import TYPE_CHECKING, Optional

import numpy as np
from nomad.datamodel.data import ArchiveSection
from nomad.datamodel.metainfo.annotations import ELNAnnotation
from nomad.metainfo import Quantity, SubSection

Expand Down Expand Up @@ -38,8 +37,10 @@
XASSpectrum,
)

from .common import Time

class Outputs(ArchiveSection):

class Outputs(Time):
"""
Output properties of a simulation. This base class can be used for inheritance in any of the output properties
defined in this schema.
Expand Down
4 changes: 4 additions & 0 deletions src/nomad_simulations/schema_packages/workflow/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .general import SimulationWorkflow
from .geometry_optimization import GeometryOptimization
from .gw import DFTGWWorkflow
from .single_point import SinglePoint
66 changes: 66 additions & 0 deletions src/nomad_simulations/schema_packages/workflow/general.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from nomad.datamodel import EntryArchive
from nomad.datamodel.metainfo.workflow import Link, Task, Workflow
from structlog.stdlib import BoundLogger

INCORRECT_N_TASKS = 'Incorrect number of tasks found.'


class SimulationWorkflow(Workflow):
"""
Base class for simulation workflows.
"""

def normalize(self, archive: EntryArchive, logger: BoundLogger):
"""
Generate tasks from the archive data outputs.
"""
if not archive.data or not archive.data.outputs:
return

# generate tasks from outputs
if not self.tasks:
# default should to serial execution
times: list[tuple[float, float]] = list(
[
(o.wall_start or n, o.wall_end or n)
for n, o in enumerate(archive.data.outputs)
]
)
times.sort(key=lambda x: x[0])
# current parent task
parent_n = 0
parent_outputs: list[Link] = []
for n, time in enumerate(times):
task = Task(
outputs=[
Link(
name='Output',
section=archive.data.outputs[n],
)
],
)
self.tasks.append(task)
# link tasks based on overlap in execution time
if time[0] >= times[parent_n][1]:
# if no overlap, assign outputs of parent as input to next task
task.inputs = [
Link(name='Input', section=output.section)
for output in parent_outputs or task.outputs
]
# assign first parent outputs as workflow inputs
if not self.inputs:
self.inputs = task.inputs
# assign as new parent
parent_n = n
# reset outputs
parent_outputs = task.outputs
else:
parent_outputs.extend(task.outputs)
# if overlap, assign parent outputs to task inputs
task.inputs = [
Link(name='Input', section=output.section)
for output in self.tasks[parent_n or n].outputs
]
if not self.outputs:
# assign parent outputs as workflow outputs
self.outputs = parent_outputs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from nomad.datamodel import EntryArchive
from nomad.datamodel.metainfo.workflow import Link, Task
from structlog.stdlib import BoundLogger

from .general import SimulationWorkflow


class GeometryOptimization(SimulationWorkflow):
"""
Definitions for geometry optimization workflow.
"""

def normalize(self, archive: EntryArchive, logger: BoundLogger) -> None:
"""
Specify the inputs and outputs of the tasks as the model system.
"""
super().normalize(archive, logger)

def to_system_links(task: Task) -> None:
task.inputs = [
Link(name='Input system', section=link.section.model_system_ref)
for link in task.inputs
if link.section and link.section.model_system_ref
]
task.outputs = [
Link(name='Output system', section=link.section.model_system_ref)
for link in task.inputs
if link.section and link.section.model_system_ref
]

to_system_links(self)
for task in self.tasks:
to_system_links(task)
37 changes: 37 additions & 0 deletions src/nomad_simulations/schema_packages/workflow/gw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from nomad.datamodel import EntryArchive
from structlog.stdlib import BoundLogger

from .general import INCORRECT_N_TASKS, SimulationWorkflow


class DFTGWWorkflow(SimulationWorkflow):
"""
Definitions for GW calculation based on DFT workflow.
"""

def normalize(self, archive: EntryArchive, logger: BoundLogger) -> None:
"""
Link the DFT and GW single point workflows in the DFT-GW workflow.
"""
super().normalize(archive, logger)

if not self.name:
self.name = 'DFT+GW'

if len(self.tasks) != 2:
logger.error(INCORRECT_N_TASKS)
return

if not self.inputs:
# set inputs to inputs of DFT
self.inputs = self.tasks[0].task.inputs

if not self.outputs:
# set ouputs to outputs of GW
self.outputs = self.tasks[1].task.outputs

# link dft and gw workflows
self.tasks[0].inputs = self.inputs
self.tasks[0].outputs = self.tasks[0].task.outputs
self.tasks[1].inputs = self.tasks[0].outputs
self.tasks[1].outputs = self.outputs
35 changes: 35 additions & 0 deletions src/nomad_simulations/schema_packages/workflow/single_point.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from nomad.datamodel import EntryArchive
from nomad.datamodel.metainfo.workflow import Link
from structlog.stdlib import BoundLogger

from .general import INCORRECT_N_TASKS, SimulationWorkflow


class SinglePoint(SimulationWorkflow):
"""
Definitions for single point workflow.
"""

def normalize(self, archive: EntryArchive, logger: BoundLogger) -> None:
"""
Specify the method and system as inputs.
"""
super().normalize(archive, logger)
if len(self.tasks) != 1:
logger.error(INCORRECT_N_TASKS)
return

if not self.inputs:
self.inputs = self.tasks[0].inputs

inps: list[Link] = []
for inp in self.inputs:
if inp.section and inp.section.model_system_ref:
inps.append(
Link(name='Input system', section=inp.section.model_system_ref)
)
if inp.section and inp.section.model_method_ref:
inps.append(
Link(name='Input method', section=inp.section.model_method_ref)
)
self.inputs = inps

1 comment on commit 0530c27

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCoverMissing
src/nomad_simulations
   __init__.py4250%3–4
   _version.py11282%5–6
src/nomad_simulations/schema_packages
   __init__.py15287%39–41
   atoms_state.py1902189%13–15, 201–204, 228, 283–284, 352–353, 355, 537, 549–550, 611–615, 630–634, 641
   basis_set.py2402888%8–9, 122–133, 172–185, 208, 391–395, 417–418, 462–465, 584, 615, 617
   general.py85891%4–7, 123, 143, 253–254, 264
   model_method.py2697871%10–12, 171–174, 177–184, 276–277, 297, 318–339, 355–381, 384–401, 587, 780, 791, 833–840, 878, 897, 977, 1034, 1109, 1223
   model_system.py3483789%45–51, 235, 254, 258, 261, 264, 290, 376–377, 454–455, 472–473, 686–689, 736–743, 917–918, 1140–1144, 1150–1151, 1159–1160, 1165, 1188
   numerical_settings.py2596176%12–14, 217, 219–220, 223–226, 230–231, 238–241, 250–253, 257–260, 262–265, 270–273, 279–282, 469–496, 571, 606–609, 633, 636, 681, 683–686, 690, 694, 741, 745–766, 821–822, 889
   outputs.py1201092%8–9, 253–256, 296–299, 324, 326, 363, 382
   physical_property.py102793%20–22, 202, 331–333
   variables.py861286%8–10, 98, 121, 145, 167, 189, 211, 233, 256, 276
src/nomad_simulations/schema_packages/properties
   band_gap.py51590%8–10, 135–136
   band_structure.py1232580%9–11, 232–265, 278, 285, 321–322, 325, 372–373, 378
   energies.py42979%7–9, 36, 57, 82, 103, 119, 134
   fermi_surface.py17476%7–9, 40
   forces.py22673%7–9, 36, 56, 79
   greens_function.py991387%7–9, 210–211, 214, 235–236, 239, 260–261, 264, 400
   hopping_matrix.py29583%7–9, 58, 94
   permittivity.py48883%7–9, 97–105
   spectral_profile.py26012851%9–11, 57–60, 95–98, 199–300, 356–368, 393–396, 416, 421–424, 466–502, 526, 573–576, 592–593, 598–604
   thermodynamics.py752764%7–9, 35, 56, 72, 81, 90, 101, 110, 137, 147, 157, 172–174, 177, 193, 213–215, 218, 234, 254–256, 259
src/nomad_simulations/schema_packages/utils
   utils.py791680%8–11, 65–74, 83–84, 89, 92, 169–170
src/nomad_simulations/schema_packages/workflow
   __init__.py440%1–4
   general.py26260%1–66
   geometry_optimization.py13130%1–33
   gw.py19190%1–37
   single_point.py19190%1–35
TOTAL267659578% 

Tests Skipped Failures Errors Time
402 0 💤 0 ❌ 0 🔥 6.568s ⏱️

Please sign in to comment.