Commit fe0d9f5c authored by Lauri Himanen's avatar Lauri Himanen
Browse files

Added more testing tools, updated stress tensor parsing.

parent db713caa
......@@ -64,6 +64,7 @@ test/**/*.restart.bak-3
test/**/*.wfn.bak-1
test/**/*.wfn.bak-2
test/**/*.wfn.bak-3
test/**/*.png
parser/parser-cp2k/cp2kparser/versions/**/input_data/*.xml
parser/parser-cp2k/cp2kparser/versions/**/input_data/*.html
test/unittests/BASIS_SET
......
......@@ -37,31 +37,8 @@ class CommonMatcher(object):
'x_cp2k_md_force_atom_float': CachingLevel.Cache,
}
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(self.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
#===========================================================================
# SimpleMatcher trees
# SimpleMatcher for the header that is common to all run types
def header(self):
......@@ -84,6 +61,7 @@ class CommonMatcher(object):
),
SM( r" CP2K\| Input file name\s+(?P<x_cp2k_input_filename>.+$)",
sections=['x_cp2k_section_filenames'],
otherMetaInfo=['section_XC_functionals', 'XC_functional_name', 'XC_functional_weight', 'XC_functional', 'configuration_periodic_dimensions', "stress_tensor_method"],
subMatchers=[
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>.+$)"),
......@@ -115,6 +93,8 @@ class CommonMatcher(object):
]
)
#===========================================================================
# Section close triggers
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
......@@ -122,19 +102,22 @@ class CommonMatcher(object):
"""
# 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.")
try:
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.")
except:
pass
def onClose_x_cp2k_section_filenames(self, backend, gIndex, section):
"""
......@@ -148,6 +131,34 @@ class CommonMatcher(object):
else:
logger.warning("The input file of the calculation could not be found.")
#===========================================================================
# Ad hoc parsing
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(self.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 getOnCloseTriggers(self):
"""
Returns:
......
......@@ -125,6 +125,20 @@ class CP2KInputParser(BasicParser):
force_file_path = self.normalize_cp2k_path(force_file, "xyz")
self.file_service.set_file_id(force_file_path, "force_file_single_point")
#=======================================================================
# Stress tensor calculation method
stress_tensor_method = self.input_tree.get_keyword("FORCE_EVAL/STRESS_TENSOR")
if stress_tensor_method != "NONE":
mapping = {
"NUMERICAL": "Numerical",
"ANALYTICAL": "Analytical",
"DIAGONAL_ANALYTICAL": "Diagonal analytical",
"DIAGONAL_NUMERICAL": "Diagonal numerical",
}
stress_tensor_method = mapping.get(stress_tensor_method)
if stress_tensor_method is not None:
self.backend.addValue("stress_tensor_method", stress_tensor_method)
def normalize_cp2k_path(self, path, extension, name=""):
"""The paths in CP2K input can be given in many ways. This function
tries to normalize these forms into a valid path.
......
......@@ -43,9 +43,11 @@ class CP2KSinglePointParser(MainHierarchicalParser):
]
),
SM( r" \*\*\* SCF run converged in\s+(\d+) steps \*\*\*",
otherMetaInfo=["single_configuration_calculation_converged"],
adHoc=self.adHoc_single_point_converged()
),
SM( r" \*\*\* SCF run NOT converged \*\*\*",
otherMetaInfo=["single_configuration_calculation_converged"],
adHoc=self.adHoc_single_point_not_converged()
),
SM( r" Electronic kinetic energy:\s+(?P<electronic_kinetic_energy__hartree>{})".format(self.cm.regex_f)),
......@@ -55,12 +57,22 @@ class CP2KSinglePointParser(MainHierarchicalParser):
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()
adHoc=self.adHoc_atom_forces(),
otherMetaInfo=["atom_forces"],
),
SM( r" (?:NUMERICAL )?STRESS TENSOR \[GPa\]",
sections=["section_stress_tensor"],
otherMetaInfo=["stress_tensor"],
subMatchers=[
SM( r"\s+X\s+Y\s+Z",
adHoc=self.adHoc_stress_tensor()
),
SM( " 1/3 Trace\(stress tensor\):\s+(?P<x_cp2k_stress_tensor_one_third_of_trace__GPa>{})".format(self.cm.regex_f)),
SM( " Det\(stress tensor\)\s+:\s+(?P<x_cp2k_stress_tensor_determinant__GPa3>{})".format(self.cm.regex_f)),
SM( " EIGENVECTORS AND EIGENVALUES OF THE STRESS TENSOR",
adHoc=self.adHoc_stress_tensor_eigenpairs()),
]
)
]
)
]
......@@ -72,6 +84,7 @@ class CP2KSinglePointParser(MainHierarchicalParser):
self.root_matcher = SM("",
forwardMatch=True,
sections=['section_run', "section_single_configuration_calculation", "section_system", "section_method"],
otherMetaInfo=["atom_forces"],
subMatchers=[
self.cm.header(),
self.energy_force
......@@ -238,10 +251,23 @@ class CP2KSinglePointParser(MainHierarchicalParser):
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)
parser.backend.addArrayValues("stress_tensor", stress_array, unit="GPa")
return wrapper
def adHoc_stress_tensor_eigenpairs(self):
"""Parses the stress tensor eigenpairs.
"""
def wrapper(parser):
parser.fIn.readline()
eigenvalues = np.array([float(x) for x in parser.fIn.readline().split()][::-1])
parser.fIn.readline()
row1 = [float(x) for x in parser.fIn.readline().split()]
row2 = [float(x) for x in parser.fIn.readline().split()]
row3 = [float(x) for x in parser.fIn.readline().split()]
eigenvectors = np.fliplr(np.array([row1, row2, row3]))
parser.backend.addArrayValues("x_cp2k_stress_tensor_eigenvalues", eigenvalues, unit="GPa")
parser.backend.addArrayValues("x_cp2k_stress_tensor_eigenvectors", eigenvectors)
return wrapper
def adHoc_single_point_converged(self):
......
......@@ -170,6 +170,39 @@ class TestSelfInteractionCorrectionMethod(unittest.TestCase):
self.assertEqual(sic, "SIC_MAURI_US")
#===============================================================================
class TestStressTensorMethods(unittest.TestCase):
"""Tests that the stress tensor can be properly parsed for different
calculation methods.
"""
def test_none(self):
get_results("stress_tensor/none", "section_stress_tensor")
def test_analytical(self):
results = get_results("stress_tensor/analytical", ["stress_tensor_method", "stress_tensor"])
method = results["stress_tensor_method"]
results["stress_tensor"]
self.assertEqual(method, "Analytical")
def test_numerical(self):
results = get_results("stress_tensor/numerical", ["stress_tensor_method", "stress_tensor"])
method = results["stress_tensor_method"]
results["stress_tensor"]
self.assertEqual(method, "Numerical")
def test_diagonal_analytical(self):
results = get_results("stress_tensor/diagonal_analytical", ["stress_tensor_method", "stress_tensor"])
method = results["stress_tensor_method"]
results["stress_tensor"]
self.assertEqual(method, "Diagonal analytical")
def test_diagonal_numerical(self):
results = get_results("stress_tensor/diagonal_numerical", ["stress_tensor_method", "stress_tensor"])
method = results["stress_tensor_method"]
results["stress_tensor"]
self.assertEqual(method, "Diagonal numerical")
#===============================================================================
class TestConfigurationPeriodicDimensions(unittest.TestCase):
"""Tests that the self-interaction correction can be properly parsed.
......@@ -336,7 +369,7 @@ class TestEnergyForce(unittest.TestCase):
self.assertEqual(result, 0)
def test_stress_tensor(self):
result = self.results["stress_tensor_value"]
result = self.results["stress_tensor"]
expected_result = convert_unit(
np.array([
[7.77641684, -0.00000106, -0.00000106],
......@@ -347,6 +380,30 @@ class TestEnergyForce(unittest.TestCase):
)
self.assertTrue(np.array_equal(result, expected_result))
def test_stress_tensor_eigenvalues(self):
result = self.results["x_cp2k_stress_tensor_eigenvalues"]
expected_result = convert_unit(np.array([7.77641809, 7.77641797, 7.77641485]), "GPa")
self.assertTrue(np.array_equal(result, expected_result))
def test_stress_tensor_eigenvectors(self):
result = self.results["x_cp2k_stress_tensor_eigenvectors"]
expected_result = np.array([
[0.00094549, -0.79967815, 0.60042815],
[-0.70749682, 0.42379757, 0.56554741],
[0.70671590, 0.42533573, 0.56536905],
])
self.assertTrue(np.array_equal(result, expected_result))
def test_stress_tensor_determinant(self):
result = self.results["x_cp2k_stress_tensor_determinant"]
expected_result = convert_unit(4.70260626E+02, "GPa^3")
self.assertTrue(np.array_equal(result, expected_result))
def test_stress_tensor_one_third_of_trace(self):
result = self.results["x_cp2k_stress_tensor_one_third_of_trace"]
expected_result = convert_unit(7.77641697E+00, "GPa")
self.assertTrue(np.array_equal(result, expected_result))
#===============================================================================
if __name__ == '__main__':
pass
......@@ -357,6 +414,7 @@ if __name__ == '__main__':
suites.append(unittest.TestLoader().loadTestsFromTestCase(TestErrors))
suites.append(unittest.TestLoader().loadTestsFromTestCase(TestXCFunctional))
suites.append(unittest.TestLoader().loadTestsFromTestCase(TestEnergyForce))
suites.append(unittest.TestLoader().loadTestsFromTestCase(TestStressTensorMethods))
suites.append(unittest.TestLoader().loadTestsFromTestCase(TestSelfInteractionCorrectionMethod))
suites.append(unittest.TestLoader().loadTestsFromTestCase(TestConfigurationPeriodicDimensions))
suites.append(unittest.TestLoader().loadTestsFromTestCase(TestSCFConvergence))
......
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