Commit 73829dd2 authored by Lauri Himanen's avatar Lauri Himanen
Browse files

Added the parsing of numeric stress tensor.

parent 9fe74529
......@@ -61,6 +61,9 @@ test/**/*.restart
test/**/*.restart.bak-1
test/**/*.restart.bak-2
test/**/*.restart.bak-3
test/**/*.wfn.bak-1
test/**/*.wfn.bak-2
test/**/*.wfn.bak-3
parser/parser-cp2k/cp2kparser/versions/**/input_data/*.xml
parser/parser-cp2k/cp2kparser/versions/**/input_data/*.html
test/unittests/BASIS_SET
......
......@@ -26,15 +26,15 @@ class CommonMatcher(object):
self.caching_levels = {
'section_XC_functionals': CachingLevel.ForwardAndCache,
'self_interaction_correction_method': CachingLevel.Cache,
'cp2k_section_md_coordinates': CachingLevel.Cache,
'cp2k_section_md_coordinate_atom': CachingLevel.Cache,
'cp2k_md_coordinate_atom_string': CachingLevel.Cache,
'cp2k_md_coordinate_atom_float': CachingLevel.Cache,
'x_cp2k_section_md_coordinates': CachingLevel.Cache,
'x_cp2k_section_md_coordinate_atom': CachingLevel.Cache,
'x_cp2k_md_coordinate_atom_string': CachingLevel.Cache,
'x_cp2k_md_coordinate_atom_float': CachingLevel.Cache,
'cp2k_section_md_forces': CachingLevel.Cache,
'cp2k_section_md_force_atom': CachingLevel.Cache,
'cp2k_md_force_atom_string': CachingLevel.Cache,
'cp2k_md_force_atom_float': CachingLevel.Cache,
'x_cp2k_section_md_forces': CachingLevel.Cache,
'x_cp2k_section_md_force_atom': CachingLevel.Cache,
'x_cp2k_md_force_atom_string': CachingLevel.Cache,
'x_cp2k_md_force_atom_float': CachingLevel.Cache,
}
def adHoc_cp2k_section_cell(self):
......@@ -69,27 +69,27 @@ class CommonMatcher(object):
forwardMatch=True,
subMatchers=[
SM( r" DBCSR\| Multiplication driver",
sections=['cp2k_section_dbcsr'],
sections=['x_cp2k_section_dbcsr'],
),
SM( r" \*\*\*\* \*\*\*\* \*\*\*\*\*\* \*\* PROGRAM STARTED AT\s+(?P<cp2k_run_start_date>\d{4}-\d{2}-\d{2}) (?P<cp2k_run_start_time>\d{2}:\d{2}:\d{2}.\d{3})",
sections=['cp2k_section_startinformation'],
SM( r" \*\*\*\* \*\*\*\* \*\*\*\*\*\* \*\* PROGRAM STARTED AT\s+(?P<x_cp2k_run_start_date>\d{4}-\d{2}-\d{2}) (?P<x_cp2k_run_start_time>\d{2}:\d{2}:\d{2}.\d{3})",
sections=['x_cp2k_section_startinformation'],
),
SM( r" CP2K\|",
sections=['cp2k_section_programinformation'],
sections=['x_cp2k_section_programinformation'],
forwardMatch=True,
subMatchers=[
SM( r" CP2K\| version string:\s+(?P<program_version>[\w\d\W\s]+)"),
SM( r" CP2K\| source code revision number:\s+svn:(?P<cp2k_svn_revision>\d+)"),
SM( r" CP2K\| source code revision number:\s+svn:(?P<x_cp2k_svn_revision>\d+)"),
]
),
SM( r" CP2K\| Input file name\s+(?P<cp2k_input_filename>.+$)",
sections=['cp2k_section_filenames'],
SM( r" CP2K\| Input file name\s+(?P<x_cp2k_input_filename>.+$)",
sections=['x_cp2k_section_filenames'],
subMatchers=[
SM( r" GLOBAL\| Basis set file name\s+(?P<cp2k_basis_set_filename>.+$)"),
SM( r" GLOBAL\| Geminal file name\s+(?P<cp2k_geminal_filename>.+$)"),
SM( r" GLOBAL\| Potential file name\s+(?P<cp2k_potential_filename>.+$)"),
SM( r" GLOBAL\| MM Potential file name\s+(?P<cp2k_mm_potential_filename>.+$)"),
SM( r" GLOBAL\| Coordinate file name\s+(?P<cp2k_coordinate_filename>.+$)"),
SM( r" GLOBAL\| Basis set file name\s+(?P<x_cp2k_basis_set_filename>.+$)"),
SM( r" GLOBAL\| Geminal file name\s+(?P<x_cp2k_geminal_filename>.+$)"),
SM( r" GLOBAL\| Potential file name\s+(?P<x_cp2k_potential_filename>.+$)"),
SM( r" GLOBAL\| MM Potential file name\s+(?P<x_cp2k_mm_potential_filename>.+$)"),
SM( r" GLOBAL\| Coordinate file name\s+(?P<x_cp2k_coordinate_filename>.+$)"),
]
),
SM( " CELL\|",
......@@ -106,10 +106,10 @@ class CommonMatcher(object):
]
),
SM( " TOTAL NUMBERS AND MAXIMUM NUMBERS",
sections=["cp2k_section_total_numbers"],
sections=["x_cp2k_section_total_numbers"],
subMatchers=[
SM( "\s+- Atoms:\s+(?P<number_of_atoms>\d+)"),
SM( "\s+- Shell sets:\s+(?P<cp2k_shell_sets>\d+)")
SM( "\s+- Shell sets:\s+(?P<x_cp2k_shell_sets>\d+)")
]
)
]
......@@ -136,11 +136,11 @@ class CommonMatcher(object):
else:
logger.warning("Unknown self-interaction correction method used.")
def onClose_cp2k_section_filenames(self, backend, gIndex, section):
def onClose_x_cp2k_section_filenames(self, backend, gIndex, section):
"""
"""
# If the input file is available, parse it
input_file = section["cp2k_input_filename"][0]
input_file = section["x_cp2k_input_filename"][0]
filepath = self.file_service.get_absolute_path_to_file(input_file)
if filepath is not None:
input_parser = CP2KInputParser(filepath, self.parser_context)
......
import re
from nomadcore.simple_parser import SimpleMatcher as SM
from nomadcore.caching_backend import CachingLevel
from nomadcore.baseclasses import MainHierarchicalParser
from singlepointforceparser import CP2KSinglePointForceParser
from commonmatcher import CommonMatcher
......@@ -50,11 +49,18 @@ class CP2KSinglePointParser(MainHierarchicalParser):
adHoc=self.adHoc_single_point_not_converged()
),
SM( r" Electronic kinetic energy:\s+(?P<electronic_kinetic_energy__hartree>{})".format(self.cm.regex_f)),
SM( r" **************************** NUMERICAL STRESS ********************************".replace("*", "\*"),
adHoc=self.adHoc_stress_calculation(),
),
SM( r" ENERGY\| Total FORCE_EVAL \( \w+ \) energy \(a\.u\.\):\s+(?P<energy_total__hartree>{0})".format(self.cm.regex_f)),
SM( r" ATOMIC FORCES in \[a\.u\.\]"),
SM( r" # Atom Kind Element X Y Z",
adHoc=self.adHoc_atom_forces()
),
SM( r" NUMERICAL STRESS TENSOR [GPa]"),
SM( r"\s+X\s+Y\s+Z",
adHoc=self.adHoc_stress_tensor()
),
]
)
]
......@@ -73,19 +79,7 @@ class CP2KSinglePointParser(MainHierarchicalParser):
)
#=======================================================================
# The cache settings
self.caching_level_for_metaname = {
'section_XC_functionals': CachingLevel.ForwardAndCache,
'self_interaction_correction_method': CachingLevel.Cache,
'cp2k_section_md_coordinates': CachingLevel.Cache,
'cp2k_section_md_coordinate_atom': CachingLevel.Cache,
'cp2k_md_coordinate_atom_string': CachingLevel.Cache,
'cp2k_md_coordinate_atom_float': CachingLevel.Cache,
'cp2k_section_md_forces': CachingLevel.Cache,
'cp2k_section_md_force_atom': CachingLevel.Cache,
'cp2k_md_force_atom_string': CachingLevel.Cache,
'cp2k_md_force_atom_float': CachingLevel.Cache,
}
self.caching_level_for_metaname = self.cm.caching_levels
#=======================================================================
# The additional onClose trigger functions
......@@ -209,8 +203,8 @@ class CP2KSinglePointParser(MainHierarchicalParser):
return wrapper
def adHoc_atom_forces(self):
"""Used to extract the final atomic forces printed at the end of an
ENERGY_FORCE calculation is the PRINT setting is on.
"""Used to extract the final atomic forces printed at the end of a
calculation.
"""
def wrapper(parser):
......@@ -235,6 +229,21 @@ class CP2KSinglePointParser(MainHierarchicalParser):
return wrapper
def adHoc_stress_tensor(self):
"""Used to extract the stress tensor printed at the end of a
calculation.
"""
def wrapper(parser):
row1 = [float(x) for x in parser.fIn.readline().split()[-3:]]
row2 = [float(x) for x in parser.fIn.readline().split()[-3:]]
row3 = [float(x) for x in parser.fIn.readline().split()[-3:]]
stress_array = np.array([row1, row2, row3])
gid = parser.backend.openSection("section_stress_tensor")
parser.backend.addArrayValues("stress_tensor_value", stress_array, unit="GPa")
parser.backend.closeSection("section_stress_tensor", gid)
return wrapper
def adHoc_single_point_converged(self):
"""Called when the SCF cycle of a single point calculation has converged.
"""
......@@ -249,103 +258,14 @@ class CP2KSinglePointParser(MainHierarchicalParser):
parser.backend.addValue("single_configuration_calculation_converged", False)
return wrapper
# def adHoc_cp2k_section_cell(self):
# """Used to extract the cell information.
# """
# def wrapper(parser):
# # Read the lines containing the cell vectors
# a_line = parser.fIn.readline()
# b_line = parser.fIn.readline()
# c_line = parser.fIn.readline()
# # Define the regex that extracts the components and apply it to the lines
# regex_string = r" CELL\| Vector \w \[angstrom\]:\s+({0})\s+({0})\s+({0})".format(cm.regex_f)
# regex_compiled = re.compile(regex_string)
# a_result = regex_compiled.match(a_line)
# b_result = regex_compiled.match(b_line)
# c_result = regex_compiled.match(c_line)
# # Convert the string results into a 3x3 numpy array
# cell = np.zeros((3, 3))
# cell[0, :] = [float(x) for x in a_result.groups()]
# cell[1, :] = [float(x) for x in b_result.groups()]
# cell[2, :] = [float(x) for x in c_result.groups()]
# # Push the results to the correct section
# parser.backend.addArrayValues("simulation_cell", cell, unit="angstrom")
# return wrapper
# def onClose_cp2k_section_filenames(self, backend, gIndex, section):
# """
# """
# # If the input file is available, parse it
# input_file = section["cp2k_input_filename"][0]
# filepath = self.file_service.get_absolute_path_to_file(input_file)
# if filepath is not None:
# input_parser = CP2KInputParser(filepath, self.parser_context)
# input_parser.parse()
# else:
# logger.warning("The input file of the calculation could not be found.")
# def onClose_cp2k_section_md_coordinate_atom(self, backend, gIndex, section):
# """Given the string with the coordinate components for one atom, make it
# into a numpy array of coordinate components and store for later
# concatenation.
# """
# force_string = section["cp2k_md_coordinate_atom_string"][0]
# components = np.array([float(x) for x in force_string.split()])
# backend.addArrayValues("cp2k_md_coordinate_atom_float", components)
# def onClose_cp2k_section_md_coordinates(self, backend, gIndex, section):
# """When all the coordinates for individual atoms have been gathered,
# concatenate them into one big array and forward to the backend.
# """
# forces = section["cp2k_md_coordinate_atom_float"]
# forces = np.array(forces)
# backend.addArrayValues("cp2k_md_coordinates", forces)
# def onClose_cp2k_section_md_force_atom(self, backend, gIndex, section):
# """Given the string with the force components for one atom, make it
# into a numpy array of force components and store for later
# concatenation.
# """
# force_string = section["cp2k_md_force_atom_string"][0]
# components = np.array([float(x) for x in force_string.split()])
# backend.addArrayValues("cp2k_md_force_atom_float", components)
# def onClose_cp2k_section_md_forces(self, backend, gIndex, section):
# """When all the forces for individual atoms have been gathered,
# concatenate them into one big array and forward to the backend.
# """
# forces = section["cp2k_md_force_atom_float"]
# forces = np.array(forces)
# backend.addArrayValues("cp2k_md_forces", forces, unit="forceAu")
#===========================================================================
# The functions that trigger when sections are closed
# def onClose_section_method(self, backend, gIndex, section):
# """When all the functional definitions have been gathered, matches them
# with the nomad correspondents and combines into one single string which
# is put into the backend.
# """
# # Transform the CP2K self-interaction correction string to the NOMAD
# # correspondent, and push directly to the superBackend to avoid caching
# sic_cp2k = section["self_interaction_correction_method"][0]
# sic_map = {
# "NO": "",
# "AD SIC": "SIC_AD",
# "Explicit Orbital SIC": "SIC_EXPLICIT_ORBITALS",
# "SPZ/MAURI SIC": "SIC_MAURI_SPZ",
# "US/MAURI SIC": "SIC_MAURI_US",
# }
# sic_nomad = sic_map.get(sic_cp2k)
# if sic_nomad is not None:
# backend.superBackend.addValue('self_interaction_correction_method', sic_nomad)
# else:
# logger.warning("Unknown self-interaction correction method used.")
def adHoc_stress_calculation(self):
"""Used to skip over the stress tensor calculation details.
"""
def wrapper(parser):
end_line = " **************************** NUMERICAL STRESS END *****************************\n"
finished = False
while not finished:
line = parser.fIn.readline()
if line == end_line:
finished = True
return wrapper
......@@ -5,6 +5,7 @@
&END GLOBAL
&FORCE_EVAL
METHOD Quickstep
STRESS_TENSOR NUMERICAL
&SUBSYS
&KIND Si
ELEMENT Si
......
......@@ -237,9 +237,9 @@ class TestEnergyForce(unittest.TestCase):
self.assertTrue(np.array_equal(result[0], expected_result))
def test_energy_total(self):
energy_total = self.results["energy_total"]
result = self.results["energy_total"]
expected_result = convert_unit(np.array(-31.297885372811063), "hartree")
self.assertTrue(np.array_equal(energy_total, expected_result))
self.assertTrue(np.array_equal(result, expected_result))
def test_electronic_kinetic_energy(self):
result = self.results["electronic_kinetic_energy"]
......@@ -287,27 +287,27 @@ class TestEnergyForce(unittest.TestCase):
self.assertTrue(np.array_equal(atom_position[-1, :], expected_position))
def test_cp2k_filenames(self):
input_filename = self.results["cp2k_input_filename"]
input_filename = self.results["x_cp2k_input_filename"]
expected_input = "si_bulk8.inp"
self.assertTrue(input_filename, expected_input)
bs_filename = self.results["cp2k_basis_set_filename"]
bs_filename = self.results["x_cp2k_basis_set_filename"]
expected_bs = "../BASIS_SET"
self.assertEqual(bs_filename, expected_bs)
geminal_filename = self.results["cp2k_geminal_filename"]
geminal_filename = self.results["x_cp2k_geminal_filename"]
expected_geminal = "BASIS_GEMINAL"
self.assertEqual(geminal_filename, expected_geminal)
potential_filename = self.results["cp2k_potential_filename"]
potential_filename = self.results["x_cp2k_potential_filename"]
expected_potential = "../GTH_POTENTIALS"
self.assertEqual(potential_filename, expected_potential)
mm_potential_filename = self.results["cp2k_mm_potential_filename"]
mm_potential_filename = self.results["x_cp2k_mm_potential_filename"]
expected_mm_potential = "MM_POTENTIAL"
self.assertEqual(mm_potential_filename, expected_mm_potential)
coordinate_filename = self.results["cp2k_coordinate_filename"]
coordinate_filename = self.results["x_cp2k_coordinate_filename"]
expected_coordinate = "__STD_INPUT__"
self.assertEqual(coordinate_filename, expected_coordinate)
......@@ -335,6 +335,18 @@ class TestEnergyForce(unittest.TestCase):
result = self.results["single_configuration_calculation_to_system_description_ref"]
self.assertEqual(result, 0)
def test_stress_tensor(self):
result = self.results["stress_tensor_value"]
expected_result = convert_unit(
np.array([
[7.77641684, -0.00000106, -0.00000106],
[-0.00000106, 7.77641703, -0.00000106],
[-0.00000106, -0.00000106, 7.77641703],
]),
"GPa"
)
self.assertTrue(np.array_equal(result, expected_result))
#===============================================================================
if __name__ == '__main__':
pass
......
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