Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use run schema #8

Merged
merged 14 commits into from
Feb 2, 2024
6 changes: 2 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ readme = "README.md"
authors = [{ name = "The NOMAD Authors" }]
license = { text = "Apache-2.0" }
dependencies = [
"nomad-lab[infrastructure]@git+https://github.com/nomad-coe/nomad.git@develop"
"nomad-lab[infrastructure]@git+https://github.com/nomad-coe/nomad.git@develop",
"nomad-schema-plugin-run@git+https://github.com/nomad-coe/nomad-schema-plugin-run.git@develop",
]

[project.urls]
Expand All @@ -26,9 +27,6 @@ dev = [
]

tests = [
"electronicparsers@git+https://github.com/nomad-coe/electronic-parsers.git@develop",
"atomisticparsers@git+https://github.com/nomad-coe/atomistic-parsers.git@develop",
"workflowparsers@git+https://github.com/nomad-coe/workflow-parsers.git@master"
]

[tool.ruff]
Expand Down
36 changes: 30 additions & 6 deletions simulationworkflowschema/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,42 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
from .general import SimulationWorkflow, SimulationWorkflowMethod, SimulationWorkflowResults
from .general import (
SimulationWorkflow,
SimulationWorkflowMethod,
SimulationWorkflowResults,
)
from .single_point import SinglePoint, SinglePointMethod, SinglePointResults
from .geometry_optimization import GeometryOptimization, GeometryOptimizationMethod, GeometryOptimizationResults
from .molecular_dynamics import MolecularDynamics, MolecularDynamicsMethod, MolecularDynamicsResults
from .geometry_optimization import (
GeometryOptimization,
GeometryOptimizationMethod,
GeometryOptimizationResults,
)
from .molecular_dynamics import (
MolecularDynamics,
MolecularDynamicsMethod,
MolecularDynamicsResults,
)
from .phonon import Phonon, PhononMethod, PhononResults
from .equation_of_state import EquationOfState, EquationOfStateMethod, EquationOfStateResults
from .chemical_reaction import ChemicalReaction, ChemicalReactionMethod, ChemicalReactionResults
from .equation_of_state import (
EquationOfState,
EquationOfStateMethod,
EquationOfStateResults,
)
from .chemical_reaction import (
ChemicalReaction,
ChemicalReactionMethod,
ChemicalReactionResults,
)
from .elastic import Elastic, ElasticMethod, ElasticResults
from .tb import TB, TBMethod, TBResults
from .gw import GW, GWMethod, GWResults
from .xs import XS, XSMethod, XSResults
from .dmft import DMFT, DMFTMethod, DMFTResults
from .max_ent import MaxEnt, MaxEntMethod, MaxEntResults
from .photon_polarization import PhotonPolarization, PhotonPolarizationMethod, PhotonPolarizationResults
from .photon_polarization import (
PhotonPolarization,
PhotonPolarizationMethod,
PhotonPolarizationResults,
)
from .thermodynamics import Thermodynamics, ThermodynamicsMethod, ThermodynamicsResults
86 changes: 52 additions & 34 deletions simulationworkflowschema/chemical_reaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,45 +19,44 @@

from nomad.metainfo import SubSection, Section, Quantity, MEnum
from nomad.datamodel.metainfo.workflow import Task
from nomad.datamodel.metainfo.simulation.calculation import Calculation
from runschema.calculation import Calculation
from .general import (
SimulationWorkflowMethod, SimulationWorkflowResults, SimulationWorkflow
SimulationWorkflowMethod,
SimulationWorkflowResults,
SimulationWorkflow,
)


class ChemicalReactionMethod(SimulationWorkflowMethod):

m_def = Section(validate=False)

reaction_type = Quantity(
type=MEnum('surface_adsorption'),
description='''
type=MEnum("surface_adsorption"),
description="""
The type of the chemical reaction.
'''
""",
)


class ChemicalReactionResults(SimulationWorkflowResults):

reaction_energy = Quantity(
type=np.float64,
unit='joule',
description='''
unit="joule",
description="""
Calculated value of the reaction energy, E_reaction= E_products - E_reactants
'''
""",
)

activation_energy = Quantity(
type=np.float64,
unit='joule',
description='''
unit="joule",
description="""
Calculated value of the activation energy, E_activation = E_transitions - E_reactants
'''
""",
)


class ChemicalReaction(SimulationWorkflow):

method = SubSection(sub_section=ChemicalReactionMethod)

results = SubSection(sub_section=ChemicalReactionResults)
Expand All @@ -77,25 +76,29 @@ def normalize(self, archive, logger):
calculation = input.section
if calculation.m_def.section_cls != Calculation or not input.name:
continue
if calculation.m_xpath('energy.total.value') is None:
logger.error('Calculation energy required to calculate adsorption energy.')
if calculation.m_xpath("energy.total.value") is None:
logger.error(
"Calculation energy required to calculate adsorption energy."
)
reactants, products, transitions = [], [], []
break
# TODO resolve reagent type automatically
if 'product' in input.name.lower():
if "product" in input.name.lower():
products.append(calculation)
elif 'transition' in input.name.lower():
elif "transition" in input.name.lower():
transitions.append(calculation)
elif 'reactant' in input.name.lower():
elif "reactant" in input.name.lower():
reactants.append(calculation)

def get_lattices(calculations):
lattices = []
for calculation in calculations:
dimensionality = calculation.m_parent.m_parent.m_xpath('results.material.dimensionality')
if not dimensionality or dimensionality == '0D':
dimensionality = calculation.m_parent.m_parent.m_xpath(
"results.material.dimensionality"
)
if not dimensionality or dimensionality == "0D":
continue
lattice = calculation.m_xpath('system_ref.atoms.lattice_vectors')
lattice = calculation.m_xpath("system_ref.atoms.lattice_vectors")
if lattice is not None:
lattices.append(lattice)
return lattices
Expand All @@ -105,21 +108,25 @@ def get_lattices(calculations):
for reference_lattice in reactant_lattices:
for lattice in get_lattices(products):
array_equal = np.isclose(reference_lattice, lattice, atol=0, rtol=1e-6)
if not array_equal[np.where((reference_lattice != 0) & (lattice != 0))].all():
logger.error('Reactant and product lattices do not match.')
if not array_equal[
np.where((reference_lattice != 0) & (lattice != 0))
].all():
logger.error("Reactant and product lattices do not match.")
reactants, products = [], []
break
for lattice in get_lattices(transitions):
array_equal = np.isclose(reference_lattice, lattice, atol=0, rtol=1e-6)
if not array_equal[np.where((reference_lattice != 0) & (lattice != 0))].all():
logger.error('Reactant and transition state lattices do not match.')
if not array_equal[
np.where((reference_lattice != 0) & (lattice != 0))
].all():
logger.error("Reactant and transition state lattices do not match.")
transitions = []
break

def get_labels(calculations):
atom_labels = []
for calculation in calculations:
labels = calculation.m_xpath('system_ref.atoms.labels')
labels = calculation.m_xpath("system_ref.atoms.labels")
if labels:
atom_labels.extend(labels)
return sorted(atom_labels)
Expand All @@ -128,15 +135,21 @@ def get_labels(calculations):
# products and transition state
reactants_labels = get_labels(reactants)
if reactants_labels != get_labels(products):
logger.error('Inconsistent composition of reactants and products.')
logger.error("Inconsistent composition of reactants and products.")
reactants, products = [], []
if transitions and reactants_labels != get_labels(transitions):
logger.error('Inconsistent composition of reactants and transition states.')
logger.error("Inconsistent composition of reactants and transition states.")
transitions = []

energy_reactants = np.sum([calc.energy.total.value.magnitude for calc in reactants])
energy_products = np.sum([calc.energy.total.value.magnitude for calc in products])
energy_transitions = np.sum([calc.energy.total.value.magnitude for calc in transitions])
energy_reactants = np.sum(
[calc.energy.total.value.magnitude for calc in reactants]
)
energy_products = np.sum(
[calc.energy.total.value.magnitude for calc in products]
)
energy_transitions = np.sum(
[calc.energy.total.value.magnitude for calc in transitions]
)

if reactants and products:
self.results.reaction_energy = energy_products - energy_reactants
Expand All @@ -145,5 +158,10 @@ def get_labels(calculations):
self.results.activation_energy = energy_transitions - energy_reactants

# create task for calculating reaction energy
self.tasks.append(Task(
name='Calculation of reaction energy.', inputs=self.inputs, outputs=self.outputs))
self.tasks.append(
Task(
name="Calculation of reaction energy.",
inputs=self.inputs,
outputs=self.outputs,
)
)
Loading
Loading