Commit 671ce31b authored by Lauri Himanen's avatar Lauri Himanen
Browse files

Added couple tests to see how the unittest package works.

parent 0622015a
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from collections import defaultdict
from cp2kparser.generics.util import *
......@@ -54,6 +56,19 @@ class CP2KInputEngine(object):
def get_subsection(self, path, index=0):
return self.root_section.get_subsection(path, index)
def get_keyword(self, path, index=0):
split = path.rsplit('/', 1)
section_path = split[0]
keyword = split[1]
section = self.root_section.get_subsection(section_path, index)
if section is not None:
return section.get_keyword(keyword)
def get_parameter(self, path, index=0):
section = self.root_section.get_subsection(path, index)
if section is not None:
return section.get_parameter()
#===============================================================================
class InputSection(object):
......@@ -140,4 +155,6 @@ class InputSection(object):
return result
def get_parameter(self):
if self.params is None:
print_debug("The section '{}' has no parameters set".format(self.name))
return self.params
......@@ -5,6 +5,7 @@ import os
import time
from abc import ABCMeta, abstractmethod
from cp2kparser.generics.util import *
from pint import UnitRegistry
#===============================================================================
......@@ -130,6 +131,8 @@ class NomadParser(object):
else:
print_debug("Using cached result.")
# Do the conversion to SI units based on the given units
stop = time.clock()
print_debug("Elapsed time: {} ms".format((stop-start)*1000))
return result
......@@ -149,7 +152,10 @@ class NomadParser(object):
@abstractmethod
def parse_quantity(self, name):
"""Parse a quantity from the given files."""
"""Parse a quantity from the given files. Should return a tuple
containing the result object (numeric results preferably as numpy
arrays) and the unit of the result (None if no unit is needed)
"""
pass
@abstractmethod
......
import logging
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import os
import json
from cp2kparser.implementation.parser import CP2KParser
......@@ -18,7 +19,7 @@ def scan_path_for_files(path):
extension = os.path.splitext(filename)[1]
if extension in extensions:
file_object = {
"path": filename,
"path": os.path.join(path, filename),
"file_id": "",
}
files.append(file_object)
......@@ -26,9 +27,8 @@ def scan_path_for_files(path):
#===============================================================================
def extract(path):
def get_parser(path):
files = scan_path_for_files(path)
logging.basicConfig(format='%(message)s', level=logging.DEBUG)
json_input = {
"version": "nomadparsein.json 1.0",
"tmpDir": "/home/lauri",
......@@ -37,8 +37,4 @@ def extract(path):
"files": files
}
parser = CP2KParser(json.dumps(json_input))
print parser.get_quantity("energy_total")
print parser.get_quantity("XC_functional")
print parser.get_quantity("particle_forces")
# n = len(parser.get_quantity("particle_forces"))
# print "Number of force configurations found: {}".format(n)
return parser
......@@ -15,6 +15,10 @@ from cp2kparser.engines.cp2kinputengine import CP2KInputEngine
class CP2KParser(NomadParser):
"""The interface for a NoMaD CP2K parser. All parsing actions will go
through this class.
The CP2K version 2.6.2 was used as a reference for this basic
implementation. For other versions there should be classes that extend from
this.
"""
def __init__(self, input_json_string):
......@@ -92,8 +96,8 @@ class CP2KParser(NomadParser):
# Now check from input what the other files are called
self.inputengine.parse_input()
force_path = self.inputengine.get_subsection("FORCE_EVAL/PRINT/FORCES").get_keyword("FILENAME")
if force_path and force_path != "__STD_OUT__":
force_path = self.inputengine.get_keyword("FORCE_EVAL/PRINT/FORCES/FILENAME")
if force_path is not None and force_path != "__STD_OUT__":
force_path = os.path.basename(force_path) + "-1_0"
# Check against the given files
......@@ -157,23 +161,68 @@ class CP2KImplementation(object):
return self.regexengine.parse(self.regexs.energy_total, self.parser.get_file_handle("output"))
def XC_functional(self):
"""Returns the type of the XC functional based on the value of the
extractor xc_shortcut
"""Returns the type of the XC functional.
Can currently only determine version if they are declared as parameters
for XC_FUNCTIONAL or via activating subsections of XC_FUNCTIONAL.
Returns:
A string containing the final result that should
belong to the list defined in NoMaD wiki.
"""
# xc_shortcut = self.regexengine.parse(self.regexs.XC_functional, self.parser.get_file_handle("input"))
# First try to look at the shortcut
xc_shortcut = self.inputengine.get_subsection("FORCE_EVAL/DFT/XC/XC_FUNCTIONAL").get_parameter()
if xc_shortcut is not None and xc_shortcut != "NONE" and xc_shortcut != "NO_SHORTCUT":
print_debug("Shortcut defined for XC_FUNCTIONAL")
# If PBE, check version
if xc_shortcut == "PBE":
pbe_version = self.inputengine.get_subsection("FORCE_EVAL/DFT/XC/XC_FUNCTIONAL/PBE").get_keyword("PARAMETRIZATION")
return {
'ORIG': "GGA_X_PBE",
'PBESOL': "GGA_X_PBE_SOL",
'REVPBE': "GGA_X_PBE_R",
}.get(pbe_version, "GGA_X_PBE")
return {
'B3LYP': "HYB_GGA_XC_B3LYP",
'BEEFVDW': "",
'BLYP': "",
'BEEFVDW': None,
'BLYP': "GGA_C_LYP_GGA_X_B88",
'BP': None,
'HCTH120': None,
'OLYP': None,
'LDA': "LDA_XC_TETER93",
'PADE': "LDA_XC_TETER93",
'PBE': "GGA_X_PBE",
'PBE0': None,
'TPSS': None,
}.get(xc_shortcut, None)
else:
print_debug("No shortcut defined for XC_FUNCTIONAL. Looking into subsections.")
# Look at the subsections and determine what part have been activated
# Becke88
xc_components = []
becke_88 = self.inputengine.get_subsection("FORCE_EVAL/DFT/XC/XC_FUNCTIONAL/BECKE88").get_parameter()
if becke_88 == "TRUE":
xc_components.append("GGA_X_B88")
# Becke 97
becke_97 = self.inputengine.get_parameter("FORCE_EVAL/DFT/XC/XC_FUNCTIONAL/BECKE97")
if becke_97 == "TRUE":
becke_97_param = self.inputengine.get_keyword("FORCE_EVAL/DFT/XC/XC_FUNCTIONAL/BECKE97/PARAMETRIZATION")
becke_97_result = {
'B97GRIMME': None,
'B97_GRIMME': None,
'ORIG': "GGA_XC_B97",
'WB97X-V': None,
}.get(becke_97_param, None)
if becke_97_result is not None:
xc_components.append(becke_97_result)
# Return an alphabetically sorted and joined list of the xc components
return "_".join(sorted(xc_components))
def particle_forces(self):
"""Return all the forces for every step found.
......@@ -199,6 +248,6 @@ class CP2KImplementation(object):
#===============================================================================
class CP2K_240_Implementation(CP2KImplementation):
class CP2K_262_Implementation(CP2KImplementation):
def __init__(self, parser):
CP2KImplementation.__init__(self, parser)
&GLOBAL
RUN_TYPE ENERGY_FORCE
PROJECT_NAME si_bulk
PRINT_LEVEL LOW
&END GLOBAL
&FORCE_EVAL
METHOD Quickstep
&DFT
POTENTIAL_FILE_NAME /home/lauri/GTH_POTENTIALS
BASIS_SET_FILE_NAME /home/lauri/BASIS_SET
&QS
EPS_DEFAULT 1e-3
&END QS
&SCF
MAX_SCF 100
EPS_SCF 1e-03
SCF_GUESS ATOMIC
&PRINT
&RESTART OFF
BACKUP_COPIES 0
&END RESTART
&END PRINT
&END SCF
&XC
&XC_FUNCTIONAL
&BECKE88 TRUE
&END BECKE88
&END XC_FUNCTIONAL
&END XC
&MGRID
CUTOFF 50
NGRIDS 2
REL_CUTOFF 25
&END MGRID
&END DFT
&SUBSYS
&COORD
Si 0.0 0.0 0.0
&END COORD
&CELL
A 5.4306975 0.0 0.0
C 0.0 0.0 5.4306975
B 0.0 5.4306975 0.0
PERIODIC XYZ
&END CELL
&KIND Si
POTENTIAL GTH-PADE-q4
BASIS_SET DZVP-GTH-PADE
&END KIND
&END SUBSYS
&END FORCE_EVAL
&GLOBAL
RUN_TYPE ENERGY_FORCE
PROJECT_NAME si_bulk
PRINT_LEVEL LOW
&END GLOBAL
&FORCE_EVAL
METHOD Quickstep
&DFT
POTENTIAL_FILE_NAME /home/lauri/GTH_POTENTIALS
BASIS_SET_FILE_NAME /home/lauri/BASIS_SET
&QS
EPS_DEFAULT 1e-3
&END QS
&SCF
MAX_SCF 100
EPS_SCF 1e-03
SCF_GUESS ATOMIC
&PRINT
&RESTART OFF
BACKUP_COPIES 0
&END RESTART
&END PRINT
&END SCF
&XC
&XC_FUNCTIONAL BLYP
&END XC_FUNCTIONAL
&END XC
&MGRID
CUTOFF 50
NGRIDS 2
REL_CUTOFF 25
&END MGRID
&END DFT
&SUBSYS
&COORD
Si 0.0 0.0 0.0
&END COORD
&CELL
A 5.4306975 0.0 0.0
C 0.0 0.0 5.4306975
B 0.0 5.4306975 0.0
PERIODIC XYZ
&END CELL
&KIND Si
POTENTIAL GTH-PADE-q4
BASIS_SET DZVP-GTH-PADE
&END KIND
&END SUBSYS
&END FORCE_EVAL
This diff is collapsed.
&GLOBAL
RUN_TYPE ENERGY_FORCE
PROJECT_NAME si_bulk
PRINT_LEVEL LOW
&END GLOBAL
&FORCE_EVAL
METHOD Quickstep
&DFT
POTENTIAL_FILE_NAME /home/lauri/GTH_POTENTIALS
BASIS_SET_FILE_NAME /home/lauri/BASIS_SET
&QS
EPS_DEFAULT 1e-3
&END QS
&SCF
MAX_SCF 100
EPS_SCF 1e-03
SCF_GUESS ATOMIC
&PRINT
&RESTART OFF
BACKUP_COPIES 0
&END RESTART
&END PRINT
&END SCF
&XC
&XC_FUNCTIONAL LDA
&END XC_FUNCTIONAL
&END XC
&MGRID
CUTOFF 50
NGRIDS 2
REL_CUTOFF 25
&END MGRID
&END DFT
&SUBSYS
&COORD
Si 0.0 0.0 0.0
&END COORD
&CELL
A 5.4306975 0.0 0.0
C 0.0 0.0 5.4306975
B 0.0 5.4306975 0.0
PERIODIC XYZ
&END CELL
&KIND Si
POTENTIAL GTH-PADE-q4
BASIS_SET DZVP-GTH-PADE
&END KIND
&END SUBSYS
&END FORCE_EVAL
This diff is collapsed.
......@@ -9,46 +9,31 @@
POTENTIAL_FILE_NAME /home/lauri/GTH_POTENTIALS
BASIS_SET_FILE_NAME /home/lauri/BASIS_SET
&QS
EPS_DEFAULT 1e-10
EPS_DEFAULT 1e-3
&END QS
&SCF
MAX_SCF 300
EPS_SCF 1e-07
MAX_SCF 100
EPS_SCF 1e-03
SCF_GUESS ATOMIC
&DIAGONALIZATION ON
ALGORITHM STANDARD
&END DIAGONALIZATION
&MIXING TRUE
NBUFFER 8
ALPHA 0.4
METHOD BROYDEN_MIXING
&END MIXING
&PRINT
&RESTART OFF
BACKUP_COPIES 0
&END RESTART
&END PRINT
&END SCF
&XC
&XC_FUNCTIONAL PADE
&END XC_FUNCTIONAL
&END XC
&MGRID
CUTOFF 300
NGRIDS 4
REL_CUTOFF 60
CUTOFF 50
NGRIDS 2
REL_CUTOFF 25
&END MGRID
&END DFT
&PRINT
&FORCES ON
FILENAME /home/lauri/forces
&END FORCES
&END PRINT
&SUBSYS
&COORD
Si 0.0 0.0 0.0
Si 1.357674375 1.357674375 1.357674375
Si 2.71534875 2.71534875 0.0
Si 4.073023125 4.073023125 1.357674375
Si 2.71534875 0.0 2.71534875
Si 4.073023125 1.357674375 4.073023125
Si 0.0 2.71534875 2.71534875
Si 1.357674375 4.073023125 4.073023125
&END COORD
&CELL
A 5.4306975 0.0 0.0
......
This diff is collapsed.
import unittest
import os
from cp2kparser.implementation.autoparser import get_parser
from cp2kparser.generics.util import *
# import logging
# logging.basicConfig(level=logging.DEBUG)
#===============================================================================
class TestFunctionals(unittest.TestCase):
def getxc(self, folder, result):
path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "functionals", folder)
parser = get_parser(path)
xc = parser.get_quantity("XC_functional")
self.assertEqual(xc, result)
def test_pade(self):
self.getxc("pade", "LDA_XC_TETER93")
def test_lda(self):
self.getxc("lda", "LDA_XC_TETER93")
def test_becke88(self):
self.getxc("becke88", "GGA_X_B88")
def test_blyp(self):
self.getxc("blyp", "GGA_C_LYP_GGA_X_B88")
if __name__ == '__main__':
unittest.main()
This diff is collapsed.
from cp2kparser.implementation.extract import extract
import os
if __name__ == "__main__":
path = os.path.dirname(os.path.realpath("__file__"))
extract(path)
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