geooptparser.py 8.86 KB
Newer Older
1
from nomadcore.simple_parser import SimpleMatcher as SM
2
from nomadcore.baseclasses import MainHierarchicalParser
3
from commonmatcher import CommonMatcher
4
from cp2kparser.generic.configurationreading import iread
5
from nomadcore.caching_backend import CachingLevel
6
import logging
7
import ase.io
8
9
10
11
12
13
14
15
16
17
18
19
logger = logging.getLogger("nomad")


#===============================================================================
class CP2KGeoOptParser(MainHierarchicalParser):
    """Used to parse the CP2K calculation with run types:
        -GEO_OPT/GEOMETRY_OPTIMIZATION
    """
    def __init__(self, file_path, parser_context):
        """
        """
        super(CP2KGeoOptParser, self).__init__(file_path, parser_context)
20
        self.setup_common_matcher(CommonMatcher(parser_context))
21
        self.traj_iterator = None
22

23
24
        #=======================================================================
        # Cached values
25
26
        self.cache_service.add_cache_object("number_of_frames_in_sequence", 0, single=True, update=True)
        self.cache_service.add_cache_object("frame_sequence_potential_energy", [], single=True, update=True)
27
28
29
30
31

        #=======================================================================
        # Cache levels
        self.caching_level_for_metaname.update({
            'x_cp2k_optimization_energy': CachingLevel.ForwardAndCache,
32
33
            'x_cp2k_optimization_step_size_convergence_limit': CachingLevel.ForwardAndCache,
            'x_cp2k_section_geometry_optimization_information': CachingLevel.ForwardAndCache,
34
35
36
37
        })

        #=======================================================================
        # SimpleMatchers
38
        self.geo_opt = SM(
39
            " ***                     STARTING GEOMETRY OPTIMIZATION                      ***".replace("*", "\*"),
40
            sections=["section_frame_sequence"],
41
            subMatchers=[
42
43
44
45
                SM( " ***                           CONJUGATE GRADIENTS                           ***".replace("*", "\*"),
                    adHoc=self.adHoc_conjugate_gradient()
                ),
                SM( " --------  Informations at step",
46
                    forwardMatch=True,
47
48
49
                    name="geooptstep",
                    repeats=True,
                    sections=["section_single_configuration_calculation", "section_system"],
50
                    subMatchers=[
51
                        SM( " --------  Informations at step",
52
                            sections=["x_cp2k_section_geometry_optimization_information"],
53
                            subMatchers=[
54
55
56
57
58
59
                                SM( "  Optimization Method        =\s+(?P<x_cp2k_optimization_method>{})".format(self.cm.regex_word)),
                                SM( "  Total Energy               =\s+(?P<x_cp2k_optimization_energy__hartree>{})".format(self.cm.regex_f)),
                                SM( "  Real energy change         =\s+(?P<x_cp2k_optimization_energy_change__hartree>{})".format(self.cm.regex_f)),
                                SM( "  Decrease in energy         =\s+(?P<x_cp2k_optimization_energy_decrease>{})".format(self.cm.regex_word)),
                                SM( "  Used time                  =\s+(?P<x_cp2k_optimization_used_time>{})".format(self.cm.regex_f)),
                                SM( "  Max. step size             =\s+(?P<x_cp2k_optimization_max_step_size__bohr>{})".format(self.cm.regex_f)),
60
                                SM( "  Conv. limit for step size  =\s+(?P<x_cp2k_optimization_step_size_convergence_limit__bohr>{})".format(self.cm.regex_f)),
61
62
63
64
                                SM( "  Convergence in step size   =\s+(?P<x_cp2k_optimization_step_size_convergence>{})".format(self.cm.regex_word)),
                                SM( "  RMS step size              =\s+(?P<x_cp2k_optimization_rms_step_size__bohr>{})".format(self.cm.regex_f)),
                                SM( "  Convergence in RMS step    =\s+(?P<x_cp2k_optimization_rms_step_size_convergence>{})".format(self.cm.regex_word)),
                                SM( "  Max. gradient              =\s+(?P<x_cp2k_optimization_max_gradient__bohr_1hartree>{})".format(self.cm.regex_f)),
65
                                SM( "  Conv. limit for gradients  =\s+(?P<x_cp2k_optimization_gradient_convergence_limit__bohr_1hartree>{})".format(self.cm.regex_f)),
66
67
68
69
70
                                SM( "  Conv. for gradients        =\s+(?P<x_cp2k_optimization_max_gradient_convergence>{})".format(self.cm.regex_word)),
                                SM( "  RMS gradient               =\s+(?P<x_cp2k_optimization_rms_gradient__bohr_1hartree>{})".format(self.cm.regex_f)),
                                SM( "  Conv. in RMS gradients     =\s+(?P<x_cp2k_optimization_rms_gradient_convergence>{})".format(self.cm.regex_word)),
                            ],
                            adHoc=self.adHoc_step()
71
72
                        ),
                    ]
73
74
75
76
                ),
                SM( " ***                    GEOMETRY OPTIMIZATION COMPLETED                      ***".replace("*", "\*"),
                    adHoc=self.adHoc_geo_opt_converged())
            ],
77
78
79
80
81
82
83
        )

        # Compose root matcher according to the run type. This way the
        # unnecessary regex parsers will not be compiled and searched. Saves
        # computational time.
        self.root_matcher = SM("",
            forwardMatch=True,
84
            sections=["section_run", "section_sampling_method"],
85
            subMatchers=[
86
87
88
89
90
91
                SM( "",
                    forwardMatch=True,
                    sections=["section_method"],
                    subMatchers=[
                        self.cm.header(),
                        self.cm.quickstep(),
92
                    ],
93
                ),
94
95
96
97
98
                self.geo_opt
            ]
        )

    #===========================================================================
99
100
101
102
103
    # onClose triggers
    def onClose_section_frame_sequence(self, backend, gIndex, section):
        self.cache_service.push_value("number_of_frames_in_sequence")
        self.cache_service.push_array_values("frame_sequence_potential_energy")

104
105
106
107
108
109
110
111
112
113
114
115
116
        opt_section = section["x_cp2k_section_geometry_optimization_information"]
        if opt_section is not None:
            opt_section = opt_section[-1]
            geo_limit = opt_section["x_cp2k_optimization_step_size_convergence_limit"]
            if geo_limit is not None:
                self.backend.addValue("geometry_optimization_geometry_change", geo_limit[0])
            force_limit = opt_section["x_cp2k_optimization_gradient_convergence_limit"]
            if force_limit is not None:
                self.backend.addValue("geometry_optimization_threshold_force", force_limit[0])

    def onClose_section_sampling_method(self, backend, gIndex, section):
        self.backend.addValue("sampling_method", "geometry_optimization")

117
118
119
    def onClose_x_cp2k_section_geometry_optimization_information(self, backend, gIndex, section):
        energy = section["x_cp2k_optimization_energy"][0]
        self.cache_service["frame_sequence_potential_energy"].append(energy)
120

121
122
    def onClose_section_method(self, backend, gIndex, section):
        traj_file = self.file_service.get_file_by_id("trajectory")
123
124
125
126
127
128
        if traj_file is not None:
            try:
                self.traj_iterator = iread(traj_file)
            except ValueError:
                # The format was not supported by ase
                pass
129

130
    #===========================================================================
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
    # adHoc functions
    def adHoc_geo_opt_converged(self):
        """Called when the geometry optimization converged.
        """
        def wrapper(parser):
            parser.backend.addValue("geometry_optimization_converged", True)
        return wrapper

    def adHoc_geo_opt_not_converged(self):
        """Called when the geometry optimization did not converge.
        """
        def wrapper(parser):
            parser.backend.addValue("geometry_optimization_converged", False)
        return wrapper

146
147
148
149
150
151
152
    def adHoc_conjugate_gradient(self):
        """Called when conjugate gradient method is used.
        """
        def wrapper(parser):
            parser.backend.addValue("geometry_optimization_method", "conjugate_gradient")
        return wrapper

153
    def adHoc_step(self):
154
155
        """Called when all the step information has been retrieved from the
        output file. Here further information is gathered from external files.
156
157
158
        """
        def wrapper(parser):
            self.cache_service["number_of_frames_in_sequence"] += 1
159
160
161

            # Get the next position from the trajectory file
            if self.traj_iterator is not None:
162
                pos = next(self.traj_iterator)
163
164
165
166
167
168
169
170
171
172
173
174
                self.cache_service["atom_positions"] = pos

        return wrapper

    def adHoc_setup_traj_file(self):
        def wrapper(parser):
            print "HERE"
        return wrapper

    def debug(self):
        def wrapper(parser):
            print "FOUND"
175
        return wrapper