singlepointparser.py 5.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Copyright 2015-2018 Lauri Himanen, Fawzi Mohamed, Ankit Kariryaa
# 
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
# 
#     http://www.apache.org/licenses/LICENSE-2.0
# 
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

15
from __future__ import absolute_import
16
17
from nomadcore.simple_parser import SimpleMatcher as SM
from nomadcore.baseclasses import MainHierarchicalParser
18
from cp2kparser.versions.cp2k262.singlepointforceparser import CP2KSinglePointForceParser
19
from nomadcore.caching_backend import CachingLevel
20
from cp2kparser.versions.cp2k262.commonparser import CP2KCommonParser
21
22
23
24
25
26
27
28
29
import logging
logger = logging.getLogger("nomad")


class CP2KSinglePointParser(MainHierarchicalParser):
    """The main parser class. Used to parse the CP2K calculation with run types:
        -ENERGY
        -ENERGY_FORCE
    """
30
    def __init__(self, parser_context):
31
32
        """
        """
33
        super(CP2KSinglePointParser, self).__init__(parser_context)
34
        self.setup_common_matcher(CP2KCommonParser(parser_context))
35

36
37
        #=======================================================================
        # Cache levels
38
        self.caching_levels.update({
39
40
41
42
43
44
45
            'x_cp2k_energy_total_scf_iteration': CachingLevel.ForwardAndCache,
            'x_cp2k_energy_XC_scf_iteration': CachingLevel.ForwardAndCache,
            'x_cp2k_energy_change_scf_iteration': CachingLevel.ForwardAndCache,
            'x_cp2k_stress_tensor': CachingLevel.ForwardAndCache,
            'x_cp2k_section_stress_tensor': CachingLevel.ForwardAndCache,
        })

46
47
        #=======================================================================
        # SimpleMatchers
48
49
        self.root_matcher = SM("",
            forwardMatch=True,
50
            sections=['section_run', "section_single_configuration_calculation", "section_system", "section_method"],
51
            otherMetaInfo=["atom_forces"],
52
53
            subMatchers=[
                self.cm.header(),
54
55
                self.cm.quickstep_header(),
                self.cm.quickstep_calculation(),
56
                self.cm.footer(),
57
58
59
60
            ]
        )

    #===========================================================================
61
    # onClose triggers
62
63
64
65
66
67
68
69
70
    def onClose_section_single_configuration_calculation(self, backend, gIndex, section):
        """
        """
        # If the force file for a single point calculation is available, and
        # the forces were not parsed fro the output file, parse the separate
        # file
        if section["atom_forces"] is None:
            force_file = self.file_service.get_file_by_id("force_file_single_point")
            if force_file is not None:
71
72
                force_parser = CP2KSinglePointForceParser(self.parser_context)
                force_parser.parse(force_file)
73
74
75
            else:
                logger.warning("The file containing the forces printed by ENERGY_FORCE calculation could not be found.")

76
77
78
        # Only in the single configuration calculations the number of scf
        # iterations is given. E.g. in geometry optimization there are multiple
        # scf calculations so this loses it's meaning sort of.
79
        self.cache_service.addValue("number_of_scf_iterations")
80
81
82
83
84

    def onClose_x_cp2k_section_scf_iteration(self, backend, gIndex, section):
        """Keep track of how many SCF iteration are made."""
        self.cache_service["number_of_scf_iterations"] += 1
        gId = backend.openSection("section_scf_iteration")
85
86
87
        section.add_latest_value("x_cp2k_energy_total_scf_iteration", "energy_total_scf_iteration")
        section.add_latest_value("x_cp2k_energy_XC_scf_iteration", "energy_XC_scf_iteration")
        section.add_latest_value("x_cp2k_energy_change_scf_iteration", "energy_change_scf_iteration")
88
89
90
91
        backend.closeSection("section_scf_iteration", gId)

    def onClose_x_cp2k_section_quickstep_calculation(self, backend, gIndex, section):
        """"""
92
93
94
95
        section.add_latest_value("x_cp2k_energy_total", "energy_total")
        section.add_latest_value("x_cp2k_electronic_kinetic_energy", "electronic_kinetic_energy")
        section.add_latest_value("x_cp2k_quickstep_converged", "single_configuration_calculation_converged")
        section.add_latest_array_values("x_cp2k_atom_forces", "atom_forces")
96
97
98
99

    def onClose_x_cp2k_section_stress_tensor(self, backend, gIndex, section):
        """"""
        gId = backend.openSection("section_stress_tensor")
100
        section.add_latest_array_values("x_cp2k_stress_tensor", "stress_tensor")
101
        backend.closeSection("section_stress_tensor", gId)
102

103
104
105
106
    def onClose_section_system(self, backend, gIndex, section):
        """Stores the index of the section method. Should always be 0, but
        let's get it dynamically just in case there's something wrong.
        """
107
108
        self.cache_service.addArrayValues("atom_positions", unit="angstrom")
        self.cache_service.addArrayValues("simulation_cell", unit="angstrom")
109
        self.cache_service.addArrayValues("lattice_vectors", unit="angstrom")
110

111
    #===========================================================================
112
    # adHoc functions