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

tutorial_DcEnergies #5

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/nomad_parser_vasp/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .parsers.vasp_parser import VASPParser
25 changes: 20 additions & 5 deletions src/nomad_parser_vasp/parsers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,33 @@
from nomad.config.models.plugins import ParserEntryPoint
from pydantic import Field

# class VasprunXMLEntryPoint(ParserEntryPoint):
# parameter: int = Field(0, description='Custom configuration parameter')
#
# def load(self):
# from nomad_parser_vasp.parsers.xml_parser import VasprunXMLParser

class VasprunXMLEntryPoint(ParserEntryPoint):
# return VasprunXMLParser(**self.dict())


# xml_entry_point = VasprunXMLEntryPoint(
# name='VasprunXML Parser',
# description='Parser for VASP output in XML format.',
# mainfile_name_re='.*vasprun\.xml.*',
# )


class VaspEntryPoint(ParserEntryPoint):
parameter: int = Field(0, description='Custom configuration parameter')

def load(self):
from nomad_parser_vasp.parsers.xml_parser import VasprunXMLParser
from nomad_parser_vasp.parsers.vasp_parser import VASPParser

return VasprunXMLParser(**self.dict())
return VASPParser(**self.dict())


xml_entry_point = VasprunXMLEntryPoint(
name='VasprunXML Parser',
xml_entry_point = VaspEntryPoint(
name='VASP Parser',
description='Parser for VASP output in XML format.',
mainfile_name_re='.*vasprun\.xml.*',
)
81 changes: 81 additions & 0 deletions src/nomad_parser_vasp/parsers/vasp_parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from typing import (
TYPE_CHECKING,
)

if TYPE_CHECKING:
from nomad.datamodel.datamodel import (
EntryArchive,
)
from structlog.stdlib import (
BoundLogger,
)

from nomad.config import config
from nomad.parsing.file_parser.xml_parser import XMLParser
from nomad.parsing.parser import MatchingParser
from nomad.units import ureg
from nomad_simulations.schema_packages.general import Simulation

configuration = config.get_plugin_entry_point('nomad_parser_vasp.parsers:myparser')

from .schema import (
HartreeDCEnergy,
Outputs,
TotalEnergy,
XCdcEnergy,
)


class VASPParser(MatchingParser):
def parser(
self,
mainfile: str,
archive: 'EntryArchive',
logger: 'BoundLogger',
child_archives: dict[str, 'EntryArchive'] = None,
) -> None:
logger.info('VASPParser.parse', parameter=configuration.parameter)
xml_reader = XMLParser(mainfile=mainfile) # XPath syntax

def xml_get(path: str, slicer=slice(0, 1), fallback=None):
try:
return xml_reader.parse(path)._results[path][slicer]
except KeyError:
return fallback

# "///separator[@name='electronic exchange-correlation']/i[@name='METAGGA']"
# <separator name="electronic exchange-correlation" >
# <i type="logical" name="LASPH"> F </i>
# <i type="logical" name="LMETAGGA"> F </i>
# </separator>

# "///energy/i[@name='hartreedc']"
# "///energy/i[@name='XCdc']"
# <energy>
# <i name="alphaZ"> 117.79184427 </i>
# <i name="ewald"> -1525.97595329 </i>
# <i name="hartreedc"> -409.06768234 </i>
# <i name="XCdc"> -47.45226295 </i>
# <i name="pawpsdc"> 1356.25396662 </i>
# <i name="pawaedc"> -1245.44542245 </i>
# <i name="eentropy"> -0.00003963 </i>
# <i name="bandstr"> 20.67684976 </i>
# <i name="atom"> 1849.67745644 </i>
# <i name="e_fr_energy"> 116.45875643 </i>
# <i name="e_wo_entrp"> 116.45879606 </i>
# <i name="e_0_energy"> 116.45876964 </i>
# </energy>

total_energy = xml_get("///energy/i[@name='e_fr_energy']")
hartreedc = xml_get("///energy/i[@name='hartreedc']")
xcdc = xml_get("///energy/i[@name='XCdc']")

simulation = Simulation()
output = Outputs()
simulation.outputs.append(output)
output.total_energy.append(TotalEnergy(value=total_energy * ureg.eV))

output.total_energy[0].contributions.append(
HartreeDCEnergy(value=hartreedc * ureg.eV)
)
output.total_energy[0].contributions.append(XCdcEnergy(value=xcdc * ureg.eV))
74 changes: 63 additions & 11 deletions src/nomad_parser_vasp/parsers/xml_parser.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import numpy as np
from nomad.config import config
from nomad.datamodel.datamodel import (
EntryArchive,
)
from nomad.parsing import MatchingParser
from nomad.parsing.file_parser.xml_parser import XMLParser
from nomad_simulations.schema_packages.general import Program, Simulation
from nomad_simulations.schema_packages.model_method import DFT, XCFunctional
from nomad_simulations.schema_packages.model_system import AtomicCell, ModelSystem
from structlog.stdlib import (
BoundLogger,
)

from nomad.config import config
from nomad.parsing import MatchingParser
from nomad.parsing.file_parser.mapping_parser import (
MetainfoParser,
XMLParser,
)
from schema_packages.vasp_package import Simulation

configuration = config.get_plugin_entry_point(
'nomad_parser_vasp.parsers:xml_entry_point'
)


class VasprunXMLParser(MatchingParser):
convert_xc: dict[str, str] = {
'--': 'GGA_XC_PBE',
'PE': 'GGA_XC_PBE',
}

def parse(
self,
mainfile: str,
Expand All @@ -27,6 +31,54 @@ def parse(
child_archives: dict[str, EntryArchive] = None,
) -> None:
logger.info('VasprunXMLParser.parse', parameter=configuration.parameter)
data_parser = MetainfoParser(annotation_key='xml', data_object=Simulation())
XMLParser(filepath=mainfile).convert(data_parser)
archive.data = data_parser.data_object
xml_reader = XMLParser(mainfile=mainfile) # XPath syntax

def xml_get(path: str, slicer=slice(0, 1), fallback=None):
try:
return xml_reader.parse(path)._results[path][slicer]
except KeyError:
return fallback

archive.data = Simulation(
program=Program(
name='VASP',
version=xml_get("//generator/i[@name='version']")[0],
),
model_method=[
DFT(
xc_functionals=[
XCFunctional(
libxc_name=self.convert_xc.get(
xml_get(
"///separator[@name='electronic exchange-correlation']/i[@name='LSDA']"
),
{},
)
.get(
xml_get(
"///separator[@name='electronic exchange-correlation']/i[@name='METAGGA']"
),
{},
)
.get(
xml_get(
"///separator[@name='electronic exchange-correlation']/i[@name='GGA']"
),
'PE',
),
),
],
),
],
)

if (
positions := xml_get(
"structure[@name='finalpos']/./varray[@name='positions']/v",
slice(None),
fallback=np.array([]),
)
).any():
archive.data.model_system.append(
ModelSystem(cell=[AtomicCell(positions=positions)])
)
16 changes: 5 additions & 11 deletions src/nomad_parser_vasp/schema_packages/vasp_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,18 @@
)

if TYPE_CHECKING:
from nomad.datamodel.datamodel import (
EntryArchive,
)
from structlog.stdlib import (
BoundLogger,
)
pass

from nomad.metainfo import SchemaPackage
from nomad.parsing.file_parser.mapping_parser import MappingAnnotationModel
from nomad_simulations.schema_packages.general import Simulation, Program
from nomad_simulations.schema_packages.model_system import (
ModelSystem,
AtomicCell,
)
from nomad_simulations.schema_packages.general import Program, Simulation
from nomad_simulations.schema_packages.model_method import (
DFT,
XCFunctional,
)
from nomad_simulations.schema_packages.model_system import (
AtomicCell,
)
from nomad_simulations.schema_packages.numerical_settings import KMesh

m_package = SchemaPackage()
Expand Down
116 changes: 116 additions & 0 deletions src/nomad_parser_vasp/schema_packages/vasp_package_extended.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
from typing import (
TYPE_CHECKING,
)

if TYPE_CHECKING:
from nomad.datamodel.datamodel import (
EntryArchive,
)
from structlog.stdlib import (
BoundLogger,
)

import numpy as np
from nomad.config import config
from nomad.metainfo import (
MEnum,
Quantity,
SchemaPackage,
)
from nomad_simulations.schema_packages.properties import TotalEnergy
from nomad_simulations.schema_packages.properties.energies import BaseEnergy

configuration = config.get_plugin_entry_point(
'nomad_parser_vasp.schema_packages:mypackage'
)

m_package = SchemaPackage()


# class DoubleCountingCorrection(BaseEnergy): # no extra class, label via type
# value = Quantity(
# type=np.dtype(np.float64),
# unit='eV',
# )
# type # from physical property (like Chema BandGap direct/indirect label)
#
# # Needed?
# def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None:
# super().normalize(archive, logger)
#
# logger.info('MySchema.normalize', parameter=configuration.parameter)
# self.message = f'Hello {self.name}!'


# class HartreeDCEnergy(DoubleCountingCorrection):
# value = DoubleCountingCorrection.value


# class XCdcEnergy(DoubleCountingCorrection):
# value = DoubleCountingCorrection.value


# class Outputs(Outputs):
# m_def = Section(
# validate=False,
# extends_base_section=True,
# )

# # add a new section for the custom output
# hartreedc = SubSection(
# sub_section=HartreeDCEnergy.m_def,
# repeats=True,
# )

# xcdc = SubSection(
# sub_section=XCdcEnergy.m_def,
# repeats=True,
# )


class DoubleCountingEnergy(BaseEnergy):
value = Quantity(
type=np.dtype(np.float64),
unit='eV',
)

type = Quantity(
type=MEnum('double_counting'),
)

def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None:
super().normalize(archive, logger)

if not self.type:
self.type = 'double_counting'


class HartreeDCEnergy(DoubleCountingEnergy):
def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None:
super().normalize(archive, logger)


class XCdcEnergy(DoubleCountingEnergy):
def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None:
super().normalize(archive, logger)


class RestEnergy(BaseEnergy):
def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None:
super().normalize(archive, logger)


class TotalEnergy(TotalEnergy):
def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None:
super().normalize(archive, logger)

if self.total_energy:
for total_energy in self.total_energy:
if total_energy.value and total_energy.contributions:
value = total_energy.value
for contribution in total_energy.contributions:
value -= contribution.value
total_energy.rest_energy.append(RestEnergy(value=value))


m_package.__init_metainfo__()
Loading
Loading